Compare commits

..

2 commits

Author SHA1 Message Date
Anton Thomasson
84aed94614 Add two-stage create/send print job support 2022-07-10 19:15:46 +02:00
Anton Thomasson
46e101f016 Don't use chunked encoding when there is no document 2022-07-10 17:05:58 +02:00
43 changed files with 1848 additions and 2842 deletions

View file

@ -20,7 +20,7 @@ For PDFs, your printer needs to support one of the following formats:
For Postscript, your printer needs to support Postscript natively. (SeaPrint just sends it as-is)
For Plaintext, SeaPrint can render it to PDF internally and then the requirements follow those of PDF.
You can also send Plaintext to supporting printers and leave the rendering up to the printer (SeaPrint will strip leading and trailing Form Feed characters and ensure CR+LF newlines, but not do any reflow or similar). Since rendering will differ between printers, this has lowest priority for automatic format selection.
You can also send Plaintext to supporting printers and leave the rendering up to the printer (SeaPrint will strip leading and trailing Form Feed characters and ensure CR-NL newlines, but not do any reflow or similar). Since rendering will differ between printers, this has lowest priority for automatic format selection.
For printing "Office" files, like .doc(x) and odt, you need to install
`calligraconverter` (from the `calligra` package in Sailfish OS 4.2 onwards).
@ -41,12 +41,6 @@ For printing JPEG images, transferring them as JPEG has highest priority.
JPEGs are then (losslessly) re-encoded to the baseline encoding profile to work with all printers (since SeaPrint 1.1).
For other image formats JPEG has lowest priority as transfer format since it is lossy.
![Format flowchart](doc/pipeline.svg)
Flowchart made with [GoAT](https://github.com/blampe/goat).
pdf2printable, ppm2pwg and baselinify were made especially for SeaPrint and can be found [here](https://github.com/attah/ppm2pwg).
Printers with any of these IPP certifications and derivative standards should likely be supported:
* IPP Everywhere

View file

@ -1,27 +0,0 @@
Normal flow:
.---------------.
PDF -------------------------------------------->| +----------------------> PDF 1.5
.-----------------. | |
Plaintext ---->| QTextDocument +------------------>| pdf2printable +----------------------> Postscript 2
'-----------------' | |
DOC/PPT .-------------------. | (Poppler+Cairo) | .---------.
ODT/ODP ---->| Calligraconverter +---------------->| | | |
| (optional) | | +---->| +----> PWG-Raster
'-------------------' .--------. | | | ppm2pwg |
Images --------------------------->| +---->| | | +----> URF-Raster
| | '---------------' | |
| QImage +---------------------------->| |
.--------------. | | '---------'
SVG ---->| QSvgRenderer +---->| +----------------------------------------------> PNG, JPEG,
'--------------' '--------' Reverse BMP
If target format is the same:
Postscript --------------------------------------------------------------------------------------> Postscript
.-----------------------.
Plaintext ---->| ensure CR+LF newlines +------------------------------------------------------> Plaintext
'-----------------------'
PNG --------------------------------------------------------------------------------------> PNG
.------------.
JPEG ---->| baselinify +-----------------------------------------------------------------> JPEG
'------------' (Baseline profile)

View file

@ -1,444 +0,0 @@
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='441' width='976' font-family='Menlo,Lucida Console,monospace'>
<style type="text/css">
svg {
color: #000000;
}
@media (prefers-color-scheme: dark) {
svg {
color: #FFFFFF;
}
}
</style>
<g transform='translate(8,16)'>
<path d='M 496,16 L 608,16' fill='none' stroke='currentColor'></path>
<path d='M 120,32 L 472,32' fill='none' stroke='currentColor'></path>
<path d='M 624,32 L 808,32' fill='none' stroke='currentColor'></path>
<path d='M 176,48 L 304,48' fill='none' stroke='currentColor'></path>
<path d='M 120,64 L 152,64' fill='none' stroke='currentColor'></path>
<path d='M 320,64 L 472,64' fill='none' stroke='currentColor'></path>
<path d='M 624,64 L 808,64' fill='none' stroke='currentColor'></path>
<path d='M 176,80 L 304,80' fill='none' stroke='currentColor'></path>
<path d='M 176,96 L 320,96' fill='none' stroke='currentColor'></path>
<path d='M 688,96 L 752,96' fill='none' stroke='currentColor'></path>
<path d='M 120,112 L 152,112' fill='none' stroke='currentColor'></path>
<path d='M 336,112 L 472,112' fill='none' stroke='currentColor'></path>
<path d='M 624,128 L 664,128' fill='none' stroke='currentColor'></path>
<path d='M 768,128 L 808,128' fill='none' stroke='currentColor'></path>
<path d='M 176,144 L 320,144' fill='none' stroke='currentColor'></path>
<path d='M 360,144 L 416,144' fill='none' stroke='currentColor'></path>
<path d='M 120,160 L 336,160' fill='none' stroke='currentColor'></path>
<path d='M 432,160 L 472,160' fill='none' stroke='currentColor'></path>
<path d='M 768,160 L 808,160' fill='none' stroke='currentColor'></path>
<path d='M 496,176 L 608,176' fill='none' stroke='currentColor'></path>
<path d='M 432,192 L 664,192' fill='none' stroke='currentColor'></path>
<path d='M 176,208 L 280,208' fill='none' stroke='currentColor'></path>
<path d='M 688,208 L 752,208' fill='none' stroke='currentColor'></path>
<path d='M 120,224 L 152,224' fill='none' stroke='currentColor'></path>
<path d='M 296,224 L 336,224' fill='none' stroke='currentColor'></path>
<path d='M 432,224 L 808,224' fill='none' stroke='currentColor'></path>
<path d='M 176,240 L 280,240' fill='none' stroke='currentColor'></path>
<path d='M 360,240 L 416,240' fill='none' stroke='currentColor'></path>
<path d='M 120,304 L 808,304' fill='none' stroke='currentColor'></path>
<path d='M 176,320 L 352,320' fill='none' stroke='currentColor'></path>
<path d='M 120,336 L 152,336' fill='none' stroke='currentColor'></path>
<path d='M 368,336 L 808,336' fill='none' stroke='currentColor'></path>
<path d='M 176,352 L 352,352' fill='none' stroke='currentColor'></path>
<path d='M 120,368 L 808,368' fill='none' stroke='currentColor'></path>
<path d='M 176,384 L 264,384' fill='none' stroke='currentColor'></path>
<path d='M 120,400 L 152,400' fill='none' stroke='currentColor'></path>
<path d='M 280,400 L 808,400' fill='none' stroke='currentColor'></path>
<path d='M 176,416 L 264,416' fill='none' stroke='currentColor'></path>
<path d='M 160,112 L 160,128' fill='none' stroke='currentColor'></path>
<path d='M 336,112 L 336,128' fill='none' stroke='currentColor'></path>
<path d='M 344,160 L 344,224' fill='none' stroke='currentColor'></path>
<path d='M 432,160 L 432,192' fill='none' stroke='currentColor'></path>
<path d='M 432,192 L 432,224' fill='none' stroke='currentColor'></path>
<path d='M 480,32 L 480,160' fill='none' stroke='currentColor'></path>
<path d='M 624,32 L 624,64' fill='none' stroke='currentColor'></path>
<path d='M 624,64 L 624,128' fill='none' stroke='currentColor'></path>
<path d='M 624,128 L 624,160' fill='none' stroke='currentColor'></path>
<path d='M 672,112 L 672,192' fill='none' stroke='currentColor'></path>
<path d='M 768,112 L 768,128' fill='none' stroke='currentColor'></path>
<path d='M 768,128 L 768,160' fill='none' stroke='currentColor'></path>
<path d='M 768,160 L 768,192' fill='none' stroke='currentColor'></path>
<polygon points='160.000000,64.000000 148.000000,58.400002 148.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 152.000000, 64.000000)'></polygon>
<polygon points='160.000000,112.000000 148.000000,106.400002 148.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 152.000000, 112.000000)'></polygon>
<polygon points='160.000000,224.000000 148.000000,218.399994 148.000000,229.600006' fill='currentColor' transform='rotate(0.000000, 152.000000, 224.000000)'></polygon>
<polygon points='160.000000,336.000000 148.000000,330.399994 148.000000,341.600006' fill='currentColor' transform='rotate(0.000000, 152.000000, 336.000000)'></polygon>
<polygon points='160.000000,400.000000 148.000000,394.399994 148.000000,405.600006' fill='currentColor' transform='rotate(0.000000, 152.000000, 400.000000)'></polygon>
<polygon points='344.000000,160.000000 332.000000,154.399994 332.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 336.000000, 160.000000)'></polygon>
<polygon points='344.000000,224.000000 332.000000,218.399994 332.000000,229.600006' fill='currentColor' transform='rotate(0.000000, 336.000000, 224.000000)'></polygon>
<polygon points='480.000000,32.000000 468.000000,26.400000 468.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 472.000000, 32.000000)'></polygon>
<polygon points='480.000000,64.000000 468.000000,58.400002 468.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 472.000000, 64.000000)'></polygon>
<polygon points='480.000000,112.000000 468.000000,106.400002 468.000000,117.599998' fill='currentColor' transform='rotate(0.000000, 472.000000, 112.000000)'></polygon>
<polygon points='480.000000,160.000000 468.000000,154.399994 468.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 472.000000, 160.000000)'></polygon>
<polygon points='672.000000,128.000000 660.000000,122.400002 660.000000,133.600006' fill='currentColor' transform='rotate(0.000000, 664.000000, 128.000000)'></polygon>
<polygon points='672.000000,192.000000 660.000000,186.399994 660.000000,197.600006' fill='currentColor' transform='rotate(0.000000, 664.000000, 192.000000)'></polygon>
<polygon points='816.000000,32.000000 804.000000,26.400000 804.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 808.000000, 32.000000)'></polygon>
<polygon points='816.000000,64.000000 804.000000,58.400002 804.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 808.000000, 64.000000)'></polygon>
<polygon points='816.000000,128.000000 804.000000,122.400002 804.000000,133.600006' fill='currentColor' transform='rotate(0.000000, 808.000000, 128.000000)'></polygon>
<polygon points='816.000000,160.000000 804.000000,154.399994 804.000000,165.600006' fill='currentColor' transform='rotate(0.000000, 808.000000, 160.000000)'></polygon>
<polygon points='816.000000,224.000000 804.000000,218.399994 804.000000,229.600006' fill='currentColor' transform='rotate(0.000000, 808.000000, 224.000000)'></polygon>
<polygon points='816.000000,304.000000 804.000000,298.399994 804.000000,309.600006' fill='currentColor' transform='rotate(0.000000, 808.000000, 304.000000)'></polygon>
<polygon points='816.000000,336.000000 804.000000,330.399994 804.000000,341.600006' fill='currentColor' transform='rotate(0.000000, 808.000000, 336.000000)'></polygon>
<polygon points='816.000000,368.000000 804.000000,362.399994 804.000000,373.600006' fill='currentColor' transform='rotate(0.000000, 808.000000, 368.000000)'></polygon>
<polygon points='816.000000,400.000000 804.000000,394.399994 804.000000,405.600006' fill='currentColor' transform='rotate(0.000000, 808.000000, 400.000000)'></polygon>
<path d='M 496,16 A 16,16 0 0,0 480,32' fill='none' stroke='currentColor'></path>
<path d='M 608,16 A 16,16 0 0,1 624,32' fill='none' stroke='currentColor'></path>
<path d='M 176,48 A 16,16 0 0,0 160,64' fill='none' stroke='currentColor'></path>
<path d='M 304,48 A 16,16 0 0,1 320,64' fill='none' stroke='currentColor'></path>
<path d='M 160,64 A 16,16 0 0,0 176,80' fill='none' stroke='currentColor'></path>
<path d='M 320,64 A 16,16 0 0,1 304,80' fill='none' stroke='currentColor'></path>
<path d='M 176,96 A 16,16 0 0,0 160,112' fill='none' stroke='currentColor'></path>
<path d='M 320,96 A 16,16 0 0,1 336,112' fill='none' stroke='currentColor'></path>
<path d='M 688,96 A 16,16 0 0,0 672,112' fill='none' stroke='currentColor'></path>
<path d='M 752,96 A 16,16 0 0,1 768,112' fill='none' stroke='currentColor'></path>
<path d='M 160,128 A 16,16 0 0,0 176,144' fill='none' stroke='currentColor'></path>
<path d='M 336,128 A 16,16 0 0,1 320,144' fill='none' stroke='currentColor'></path>
<path d='M 360,144 A 16,16 0 0,0 344,160' fill='none' stroke='currentColor'></path>
<path d='M 416,144 A 16,16 0 0,1 432,160' fill='none' stroke='currentColor'></path>
<path d='M 480,160 A 16,16 0 0,0 496,176' fill='none' stroke='currentColor'></path>
<path d='M 624,160 A 16,16 0 0,1 608,176' fill='none' stroke='currentColor'></path>
<path d='M 176,208 A 16,16 0 0,0 160,224' fill='none' stroke='currentColor'></path>
<path d='M 280,208 A 16,16 0 0,1 296,224' fill='none' stroke='currentColor'></path>
<path d='M 672,192 A 16,16 0 0,0 688,208' fill='none' stroke='currentColor'></path>
<path d='M 768,192 A 16,16 0 0,1 752,208' fill='none' stroke='currentColor'></path>
<path d='M 160,224 A 16,16 0 0,0 176,240' fill='none' stroke='currentColor'></path>
<path d='M 296,224 A 16,16 0 0,1 280,240' fill='none' stroke='currentColor'></path>
<path d='M 344,224 A 16,16 0 0,0 360,240' fill='none' stroke='currentColor'></path>
<path d='M 432,224 A 16,16 0 0,1 416,240' fill='none' stroke='currentColor'></path>
<path d='M 176,320 A 16,16 0 0,0 160,336' fill='none' stroke='currentColor'></path>
<path d='M 352,320 A 16,16 0 0,1 368,336' fill='none' stroke='currentColor'></path>
<path d='M 160,336 A 16,16 0 0,0 176,352' fill='none' stroke='currentColor'></path>
<path d='M 368,336 A 16,16 0 0,1 352,352' fill='none' stroke='currentColor'></path>
<path d='M 176,384 A 16,16 0 0,0 160,400' fill='none' stroke='currentColor'></path>
<path d='M 264,384 A 16,16 0 0,1 280,400' fill='none' stroke='currentColor'></path>
<path d='M 160,400 A 16,16 0 0,0 176,416' fill='none' stroke='currentColor'></path>
<path d='M 280,400 A 16,16 0 0,1 264,416' fill='none' stroke='currentColor'></path>
<style>
text {
text-anchor: middle;
font-family: "Menlo","Lucida Console","monospace";
fill: currentColor;
font-size: 1em;
}
</style>
<text x='16' y='4'>N</text>
<text x='24' y='4'>o</text>
<text x='32' y='4'>r</text>
<text x='40' y='4'>m</text>
<text x='48' y='4'>a</text>
<text x='56' y='4'>l</text>
<text x='72' y='4'>f</text>
<text x='80' y='4'>l</text>
<text x='88' y='4'>o</text>
<text x='96' y='4'>w</text>
<text x='104' y='4'>:</text>
<text x='32' y='36'>P</text>
<text x='40' y='36'>D</text>
<text x='48' y='36'>F</text>
<text x='824' y='36'>P</text>
<text x='832' y='36'>D</text>
<text x='840' y='36'>F</text>
<text x='856' y='36'>1</text>
<text x='864' y='36'>.</text>
<text x='872' y='36'>5</text>
<text x='32' y='68'>P</text>
<text x='40' y='68'>l</text>
<text x='48' y='68'>a</text>
<text x='56' y='68'>i</text>
<text x='64' y='68'>n</text>
<text x='72' y='68'>t</text>
<text x='80' y='68'>e</text>
<text x='88' y='68'>x</text>
<text x='96' y='68'>t</text>
<text x='192' y='68'>Q</text>
<text x='200' y='68'>T</text>
<text x='208' y='68'>e</text>
<text x='216' y='68'>x</text>
<text x='224' y='68'>t</text>
<text x='232' y='68'>D</text>
<text x='240' y='68'>o</text>
<text x='248' y='68'>c</text>
<text x='256' y='68'>u</text>
<text x='264' y='68'>m</text>
<text x='272' y='68'>e</text>
<text x='280' y='68'>n</text>
<text x='288' y='68'>t</text>
<text x='504' y='68'>p</text>
<text x='512' y='68'>d</text>
<text x='520' y='68'>f</text>
<text x='528' y='68'>2</text>
<text x='536' y='68'>p</text>
<text x='544' y='68'>r</text>
<text x='552' y='68'>i</text>
<text x='560' y='68'>n</text>
<text x='568' y='68'>t</text>
<text x='576' y='68'>a</text>
<text x='584' y='68'>b</text>
<text x='592' y='68'>l</text>
<text x='600' y='68'>e</text>
<text x='824' y='68'>P</text>
<text x='832' y='68'>o</text>
<text x='840' y='68'>s</text>
<text x='848' y='68'>t</text>
<text x='856' y='68'>s</text>
<text x='864' y='68'>c</text>
<text x='872' y='68'>r</text>
<text x='880' y='68'>i</text>
<text x='888' y='68'>p</text>
<text x='896' y='68'>t</text>
<text x='912' y='68'>2</text>
<text x='32' y='100'>D</text>
<text x='40' y='100'>O</text>
<text x='48' y='100'>C</text>
<text x='56' y='100'>/</text>
<text x='64' y='100'>P</text>
<text x='72' y='100'>P</text>
<text x='80' y='100'>T</text>
<text x='496' y='100'>(</text>
<text x='504' y='100'>P</text>
<text x='512' y='100'>o</text>
<text x='520' y='100'>p</text>
<text x='528' y='100'>p</text>
<text x='536' y='100'>l</text>
<text x='544' y='100'>e</text>
<text x='552' y='100'>r</text>
<text x='560' y='100'>+</text>
<text x='568' y='100'>C</text>
<text x='576' y='100'>a</text>
<text x='584' y='100'>i</text>
<text x='592' y='100'>r</text>
<text x='600' y='100'>o</text>
<text x='608' y='100'>)</text>
<text x='32' y='116'>O</text>
<text x='40' y='116'>D</text>
<text x='48' y='116'>T</text>
<text x='56' y='116'>/</text>
<text x='64' y='116'>O</text>
<text x='72' y='116'>D</text>
<text x='80' y='116'>P</text>
<text x='184' y='116'>C</text>
<text x='192' y='116'>a</text>
<text x='200' y='116'>l</text>
<text x='208' y='116'>l</text>
<text x='216' y='116'>i</text>
<text x='224' y='116'>g</text>
<text x='232' y='116'>r</text>
<text x='240' y='116'>a</text>
<text x='248' y='116'>c</text>
<text x='256' y='116'>o</text>
<text x='264' y='116'>n</text>
<text x='272' y='116'>v</text>
<text x='280' y='116'>e</text>
<text x='288' y='116'>r</text>
<text x='296' y='116'>t</text>
<text x='304' y='116'>e</text>
<text x='312' y='116'>r</text>
<text x='208' y='132'>(</text>
<text x='216' y='132'>o</text>
<text x='224' y='132'>p</text>
<text x='232' y='132'>t</text>
<text x='240' y='132'>i</text>
<text x='248' y='132'>o</text>
<text x='256' y='132'>n</text>
<text x='264' y='132'>a</text>
<text x='272' y='132'>l</text>
<text x='280' y='132'>)</text>
<text x='824' y='132'>P</text>
<text x='832' y='132'>W</text>
<text x='840' y='132'>G</text>
<text x='848' y='132'>-</text>
<text x='856' y='132'>R</text>
<text x='864' y='132'>a</text>
<text x='872' y='132'>s</text>
<text x='880' y='132'>t</text>
<text x='888' y='132'>e</text>
<text x='896' y='132'>r</text>
<text x='696' y='148'>p</text>
<text x='704' y='148'>p</text>
<text x='712' y='148'>m</text>
<text x='720' y='148'>2</text>
<text x='728' y='148'>p</text>
<text x='736' y='148'>w</text>
<text x='744' y='148'>g</text>
<text x='32' y='164'>I</text>
<text x='40' y='164'>m</text>
<text x='48' y='164'>a</text>
<text x='56' y='164'>g</text>
<text x='64' y='164'>e</text>
<text x='72' y='164'>s</text>
<text x='824' y='164'>U</text>
<text x='832' y='164'>R</text>
<text x='840' y='164'>F</text>
<text x='848' y='164'>-</text>
<text x='856' y='164'>R</text>
<text x='864' y='164'>a</text>
<text x='872' y='164'>s</text>
<text x='880' y='164'>t</text>
<text x='888' y='164'>e</text>
<text x='896' y='164'>r</text>
<text x='368' y='196'>Q</text>
<text x='376' y='196'>I</text>
<text x='384' y='196'>m</text>
<text x='392' y='196'>a</text>
<text x='400' y='196'>g</text>
<text x='408' y='196'>e</text>
<text x='32' y='228'>S</text>
<text x='40' y='228'>V</text>
<text x='48' y='228'>G</text>
<text x='184' y='228'>Q</text>
<text x='192' y='228'>S</text>
<text x='200' y='228'>v</text>
<text x='208' y='228'>g</text>
<text x='216' y='228'>R</text>
<text x='224' y='228'>e</text>
<text x='232' y='228'>n</text>
<text x='240' y='228'>d</text>
<text x='248' y='228'>e</text>
<text x='256' y='228'>r</text>
<text x='264' y='228'>e</text>
<text x='272' y='228'>r</text>
<text x='824' y='228'>P</text>
<text x='832' y='228'>N</text>
<text x='840' y='228'>G</text>
<text x='848' y='228'>,</text>
<text x='864' y='228'>J</text>
<text x='872' y='228'>P</text>
<text x='880' y='228'>E</text>
<text x='888' y='228'>G</text>
<text x='896' y='228'>,</text>
<text x='824' y='244'>R</text>
<text x='832' y='244'>e</text>
<text x='840' y='244'>v</text>
<text x='848' y='244'>e</text>
<text x='856' y='244'>r</text>
<text x='864' y='244'>s</text>
<text x='872' y='244'>e</text>
<text x='888' y='244'>B</text>
<text x='896' y='244'>M</text>
<text x='904' y='244'>P</text>
<text x='16' y='276'>I</text>
<text x='24' y='276'>f</text>
<text x='40' y='276'>t</text>
<text x='48' y='276'>a</text>
<text x='56' y='276'>r</text>
<text x='64' y='276'>g</text>
<text x='72' y='276'>e</text>
<text x='80' y='276'>t</text>
<text x='96' y='276'>f</text>
<text x='104' y='276'>o</text>
<text x='112' y='276'>r</text>
<text x='120' y='276'>m</text>
<text x='128' y='276'>a</text>
<text x='136' y='276'>t</text>
<text x='152' y='276'>i</text>
<text x='160' y='276'>s</text>
<text x='176' y='276'>t</text>
<text x='184' y='276'>h</text>
<text x='192' y='276'>e</text>
<text x='208' y='276'>s</text>
<text x='216' y='276'>a</text>
<text x='224' y='276'>m</text>
<text x='232' y='276'>e</text>
<text x='240' y='276'>:</text>
<text x='32' y='308'>P</text>
<text x='40' y='308'>o</text>
<text x='48' y='308'>s</text>
<text x='56' y='308'>t</text>
<text x='64' y='308'>s</text>
<text x='72' y='308'>c</text>
<text x='80' y='308'>r</text>
<text x='88' y='308'>i</text>
<text x='96' y='308'>p</text>
<text x='104' y='308'>t</text>
<text x='824' y='308'>P</text>
<text x='832' y='308'>o</text>
<text x='840' y='308'>s</text>
<text x='848' y='308'>t</text>
<text x='856' y='308'>s</text>
<text x='864' y='308'>c</text>
<text x='872' y='308'>r</text>
<text x='880' y='308'>i</text>
<text x='888' y='308'>p</text>
<text x='896' y='308'>t</text>
<text x='32' y='340'>P</text>
<text x='40' y='340'>l</text>
<text x='48' y='340'>a</text>
<text x='56' y='340'>i</text>
<text x='64' y='340'>n</text>
<text x='72' y='340'>t</text>
<text x='80' y='340'>e</text>
<text x='88' y='340'>x</text>
<text x='96' y='340'>t</text>
<text x='184' y='340'>e</text>
<text x='192' y='340'>n</text>
<text x='200' y='340'>s</text>
<text x='208' y='340'>u</text>
<text x='216' y='340'>r</text>
<text x='224' y='340'>e</text>
<text x='240' y='340'>C</text>
<text x='248' y='340'>R</text>
<text x='256' y='340'>+</text>
<text x='264' y='340'>L</text>
<text x='272' y='340'>F</text>
<text x='288' y='340'>n</text>
<text x='296' y='340'>e</text>
<text x='304' y='340'>w</text>
<text x='312' y='340'>l</text>
<text x='320' y='340'>i</text>
<text x='328' y='340'>n</text>
<text x='336' y='340'>e</text>
<text x='344' y='340'>s</text>
<text x='824' y='340'>P</text>
<text x='832' y='340'>l</text>
<text x='840' y='340'>a</text>
<text x='848' y='340'>i</text>
<text x='856' y='340'>n</text>
<text x='864' y='340'>t</text>
<text x='872' y='340'>e</text>
<text x='880' y='340'>x</text>
<text x='888' y='340'>t</text>
<text x='32' y='372'>P</text>
<text x='40' y='372'>N</text>
<text x='48' y='372'>G</text>
<text x='824' y='372'>P</text>
<text x='832' y='372'>N</text>
<text x='840' y='372'>G</text>
<text x='32' y='404'>J</text>
<text x='40' y='404'>P</text>
<text x='48' y='404'>E</text>
<text x='56' y='404'>G</text>
<text x='184' y='404'>b</text>
<text x='192' y='404'>a</text>
<text x='200' y='404'>s</text>
<text x='208' y='404'>e</text>
<text x='216' y='404'>l</text>
<text x='224' y='404'>i</text>
<text x='232' y='404'>n</text>
<text x='240' y='404'>i</text>
<text x='248' y='404'>f</text>
<text x='256' y='404'>y</text>
<text x='824' y='404'>J</text>
<text x='832' y='404'>P</text>
<text x='840' y='404'>E</text>
<text x='848' y='404'>G</text>
<text x='824' y='420'>(</text>
<text x='832' y='420'>B</text>
<text x='840' y='420'>a</text>
<text x='848' y='420'>s</text>
<text x='856' y='420'>e</text>
<text x='864' y='420'>l</text>
<text x='872' y='420'>i</text>
<text x='880' y='420'>n</text>
<text x='888' y='420'>e</text>
<text x='904' y='420'>p</text>
<text x='912' y='420'>r</text>
<text x='920' y='420'>o</text>
<text x='928' y='420'>f</text>
<text x='936' y='420'>i</text>
<text x='944' y='420'>l</text>
<text x='952' y='420'>e</text>
<text x='960' y='420'>)</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

View file

@ -3,10 +3,9 @@ Type=Application
Icon=harbour-seaprint
X-Nemo-Application-Type=silica-qt5
Exec=harbour-seaprint
X-DBusActivatable=true
Name=SeaPrint
[X-Sailjail]
Permissions=Internet;Pictures;Documents;Downloads;RemovableMedia;MediaIndexing;Compatibility
OrganizationName=net.attah
ApplicationName=seaprint
ExecDBus=harbour-seaprint --prestart

View file

@ -26,18 +26,14 @@ INSTALLS += i18n
system(lrelease $$PWD/translations/*.ts)
CONFIG += sailfishapp
QT += svg dbus
PKGCONFIG += mlite5 libcurl glib-2.0
INCLUDEPATH += $$system(pkg-config --cflags-only-I poppler-glib | sed 's/-I//g')
QT += svg
PKGCONFIG += mlite5 libcurl poppler glib-2.0 cairo libjpeg
LIBS += -lcurl -lglib-2.0 -lgobject-2.0 -ldl
DEFINES += MADNESS=1
DEFINES += PDF_CREATOR='\\"SeaPrint\ $$VERSION\\"'
DEFINES += SEAPRINT_VERSION='\\"$$VERSION\\"'
SOURCES += src/harbour-seaprint.cpp \
src/dbusadaptorbase.cpp \
src/freedesktopdbusadaptor.cpp \
src/rangelistchecker.cpp \
src/convertchecker.cpp \
src/curlrequester.cpp \
src/imageitem.cpp \
@ -45,17 +41,16 @@ SOURCES += src/harbour-seaprint.cpp \
src/ippmsg.cpp \
src/ippprinter.cpp \
src/mimer.cpp \
ppm2pwg/printparameters.cpp \
ppm2pwg/ppm2pwg.cpp \
ppm2pwg/pdf2printable.cpp \
ppm2pwg/baselinify.cpp \
ppm2pwg/bytestream/bytestream.cpp \
src/overrider.cpp \
src/printerworker.cpp \
src/seaprintdbusadaptor.cpp \
src/settings.cpp
DISTFILES += qml/harbour-seaprint.qml \
qml/components/DependentOn.qml \
qml/cover/CoverPage.qml \
qml/components/*qml \
qml/pages/*.qml \
@ -86,9 +81,6 @@ TRANSLATIONS += translations/harbour-seaprint-de.ts \
translations/harbour-seaprint-pl.ts
HEADERS += \
src/dbusadaptorbase.h \
src/freedesktopdbusadaptor.h \
src/rangelistchecker.h \
src/convertchecker.h \
src/curlrequester.h \
src/imageitem.h \
@ -107,11 +99,9 @@ HEADERS += \
ppm2pwg/UrfPgHdr.codable \
ppm2pwg/bytestream/bytestream.h \
ppm2pwg/bytestream/codable.h \
ppm2pwg/argget.h \
src/overrider.h \
src/papersizes.h \
src/printerworker.h \
src/seaprintdbusadaptor.h \
src/settings.h
INCLUDEPATH += ppm2pwg \

@ -1 +1 @@
Subproject commit acc32f3769c3b18bd6b94c55b882c7b7b778854c
Subproject commit ba8d015e911991d20dc1433292d7188e5e7ab8f9

View file

@ -7,7 +7,7 @@ Setting {
property var preferred_choices: []
property string preferred_choice_suffix: ""
property var actual_choices: Utils.fixupChoices(name, choices, parent.selectedFileType, parent.printer)
property var actual_choices: Utils.fixupChoices(name, choices, parent.selectedFileType)
property int num_large_choices: 8

View file

@ -20,9 +20,10 @@ Dialog {
id: valueField
validator: IntValidator{bottom: min; top: max;}
width: parent.width
placeholderText: ""+min+"-"+(max == 65535 ? "..." : max)
placeholderText: ""+min+"-"+max
label: title
focus: true
labelVisible: true
inputMethodHints: Qt.ImhDigitsOnly
}

View file

@ -2,21 +2,8 @@ import QtQuick 2.6
import Sailfish.Silica 1.0
Setting {
property int minimum_high: 0
property int low: _valid ? parent.printer.attrs[name+"-supported"].value.low : (minimum_high != 0) ? 1 : 0
property int high: _valid ? ensure_minimum(parent.printer.attrs[name+"-supported"].value.high) : minimum_high
function ensure_minimum(orig)
{
if(orig < minimum_high)
{
return minimum_high;
}
else
{
return orig;
}
}
property int low: valid ? parent.printer.attrs[name+"-supported"].value.low : 0
property int high: valid ? parent.printer.attrs[name+"-supported"].value.high : 0
property bool suppressChange: false
@ -53,7 +40,7 @@ Setting {
anchors.right: parent.right
icon.source: "image://theme/icon-s-edit"
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
{title: prettyName,
{value: choice, title: prettyName,
min: low, max: high});
dialog.accepted.connect(function() {
choice = dialog.value;

View file

@ -1,30 +0,0 @@
import QtQuick 2.6
import Sailfish.Silica 1.0
import seaprint.rangelistchecker 1.0
Dialog {
id: dialog
allowedOrientations: Orientation.All
property string title
property var value
canAccept: valueField.acceptableInput
Column {
width: parent.width
DialogHeader { }
TextField {
id: valueField
acceptableInput: Object.keys(value).length !== 0
width: parent.width
placeholderText: "1,2,17-42"
label: title
focus: true
labelVisible: true
onTextChanged: { dialog.value = RangeListChecker.parse(text) }
}
}
}

View file

@ -5,7 +5,6 @@ Setting {
property int high
property int choice_low: 1
property int choice_high: 0
property bool acceptRangeList: false
property bool suppressChange: false
@ -42,7 +41,7 @@ Setting {
}
onChoiceChanged: {
if(choice == undefined || choice.constructor.name !== "Object")
if(choice == undefined)
{
suppressChange = true;
low_slider.value = low_slider.minimumValue;
@ -51,39 +50,7 @@ Setting {
}
}
displayValue: prettify(choice)
function prettify(choice)
{
if(choice == undefined)
{
return qsTr("all");
}
else if(choice.constructor.name === "Object")
{
return (""+choice.low+" - "+choice.high)
}
else
{
var ret = "";
for(var i = 0; i < choice.length; i++)
{
if(i!=0)
{
ret = ret+","
}
if(choice[i].low == choice[i].high)
{
ret=ret+choice[i].low
}
else
{
ret=ret+choice[i].low+"-"+choice[i].high
}
}
return ret
}
}
displayValue: choice == undefined ? qsTr("all") : ""+choice.low+" - "+choice.high
menu: ContextMenu {
MenuItem {
@ -104,7 +71,7 @@ Setting {
anchors.right: parent.right
icon.source: "image://theme/icon-s-edit"
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
{title: prettyName + " (" + qsTr("Low") + ")",
{value: choice, title: prettyName,
min: 1, max: high});
dialog.accepted.connect(function() {
choice_low = dialog.value;
@ -132,7 +99,7 @@ Setting {
anchors.right: parent.right
icon.source: "image://theme/icon-s-edit"
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
{title: prettyName + " (" + qsTr("High") + ")",
{value: choice, title: prettyName,
min: 1, max: high});
dialog.accepted.connect(function() {
choice_high = dialog.value;
@ -142,17 +109,6 @@ Setting {
}
MenuItem {
visible: acceptRangeList
text: qsTr("Advanced")
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("RangeListInputDialog.qml"),
{title: prettyName});
dialog.accepted.connect(function() {
choice = dialog.value;
})
}
}
}

View file

@ -13,37 +13,9 @@ ApplicationWindow
{
id: appWin
property Page _mainPage
property bool expectCalligra: true
function openFile(file) {
selectedFile = file
selectedFileType = Mimer.get_type(selectedFile);
if(selectedFileType == "")
{
selectedFile = ""
notifier.notify(qsTr("Unsupported document format"))
}
if(pageStack.currentPage.busyPage)
{
notifier.notify(qsTr("New file selected"))
}
else
{
pageStack.pop(appWin._mainPage, PageStackAction.Immediate)
}
}
property string selectedFile: ""
property string selectedFileType
initialPage: Component {
FirstPage {
Component.onCompleted: appWin._mainPage = this
}
}
initialPage: Component { FirstPage { selectedFile: Qt.application.arguments[1] ? Qt.application.arguments[1] : "" } }
cover: Qt.resolvedUrl("cover/CoverPage.qml")
allowedOrientations: Orientation.All

View file

@ -62,7 +62,7 @@ Page {
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
color: Theme.primaryColor
text: "© 2019-2023 Anton Thomasson et al."
text: "© 2019-2022 Anton Thomasson et al."
}
@ -101,7 +101,7 @@ Page {
qsTr("Dutch")+" - JSEHV, Rudi Timmermans\n"+
qsTr("French")+" - ensag-dev, pherjung, phklrz, Quentí\n"+
qsTr("German")+" - black-sheep-dev, cnlpete, wheelseal\n"+
qsTr("Polish")+" - atlochowski, karolkurek\n"+
qsTr("Polish")+" - atlochowski\n"+
qsTr("Spanish")+" - carmenfdezb, JSEHV"
}

View file

@ -3,8 +3,6 @@ import Sailfish.Silica 1.0
import "utils.js" as Utils
Page {
property bool busyPage: true
allowedOrientations: Orientation.All
Component.onCompleted: {

View file

@ -13,7 +13,6 @@ Page {
contentHeight: col.height
PullDownMenu {
visible: identifyLabel.visible
MenuItem {
id: identifyLabel

View file

@ -12,6 +12,9 @@ Page {
id: page
allowedOrientations: Orientation.All
property string selectedFile: ""
property string selectedFileType
Connections {
target: wifi
onConnectedChanged: {
@ -57,6 +60,11 @@ Page {
Component.onCompleted: {
IppDiscovery.discover();
if(selectedFile != "")
{
var type = Mimer.get_type(selectedFile);
selectedFileType = type;
}
}
property bool nagged: false
@ -135,7 +143,7 @@ Page {
property string name: Utils.unknownForEmptyString(printer.attrs["printer-name"].value)
property var supported_formats: Utils.supported_formats(printer, considerAdditionalFormatsSetting.value)
property bool canPrint: supported_formats.mimetypes.indexOf(appWin.selectedFileType) != -1
property bool canPrint: supported_formats.mimetypes.indexOf(selectedFileType) != -1
Connections {
target: printer
@ -174,7 +182,7 @@ Page {
{
if(printer.attrs.hasOwnProperty("printer-uuid"))
{
return JSON.parse(db.getJobSettings(printer.attrs["printer-uuid"].value, appWin.selectedFileType));
return JSON.parse(db.getJobSettings(printer.attrs["printer-uuid"].value, selectedFileType));
}
else
{
@ -191,7 +199,7 @@ Page {
return;
}
debugCountReset.restart();
if(appWin.selectedFile == "")
if(selectedFile == "")
{
noFileSelected();
}
@ -201,7 +209,7 @@ Page {
}
else
{
pageStack.push(Qt.resolvedUrl("PrinterPage.qml"), {printer: printer, selectedFile: appWin.selectedFile, jobParams: maybeGetParams()})
pageStack.push(Qt.resolvedUrl("PrinterPage.qml"), {printer: printer, selectedFile: selectedFile, jobParams: maybeGetParams()})
}
}
@ -242,13 +250,13 @@ Page {
Label {
id: name_label
color: canPrint || appWin.selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
color: canPrint || selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
text: name
}
Label {
id: mm_label
color: canPrint || appWin.selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
color: canPrint || selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
font.pixelSize: Theme.fontSizeExtraSmall
text: Utils.unknownForEmptyString(printer.attrs["printer-make-and-model"].value)
+ (Utils.existsAndNotEmpty("printer-location", printer) ? " • "+printer.attrs["printer-location"].value : "")
@ -256,7 +264,7 @@ Page {
Label {
id: uri_label
color: canPrint || appWin.selectedFile == "" ? Theme.highlightColor : Theme.secondaryColor
color: canPrint || selectedFile == "" ? Theme.highlightColor : Theme.secondaryColor
font.pixelSize: Theme.fontSizeTiny
text: printer.url
}
@ -277,7 +285,7 @@ Page {
width: Theme.itemSizeExtraSmall/2
visible: supported_formats.pdf
highlightColor: "red"
highlighted: !(appWin.selectedFile == "" || canPrint)
highlighted: !(selectedFile == "" || canPrint)
source: "image://theme/icon-m-file-pdf"
}
HighlightImage {
@ -285,7 +293,7 @@ Page {
width: Theme.itemSizeExtraSmall/2
visible: supported_formats.postscript
highlightColor: "red"
highlighted: !(appWin.selectedFile == "" || canPrint)
highlighted: !(selectedFile == "" || canPrint)
source: "image://theme/icon-m-file-other"
}
@ -294,7 +302,7 @@ Page {
width: Theme.itemSizeExtraSmall/2
visible: supported_formats.plaintext
highlightColor: "red"
highlighted: !(appWin.selectedFile == "" || canPrint)
highlighted: !(selectedFile == "" || canPrint)
source: "image://theme/icon-m-file-document"
}
HighlightImage {
@ -302,7 +310,7 @@ Page {
width: Theme.itemSizeExtraSmall/2
visible: supported_formats.office
highlightColor: "red"
highlighted: !(appWin.selectedFile == "" || canPrint)
highlighted: !(selectedFile == "" || canPrint)
source: "image://theme/icon-m-file-formatted"
}
HighlightImage {
@ -310,7 +318,7 @@ Page {
width: Theme.itemSizeExtraSmall/2
visible: supported_formats.office
highlightColor: "red"
highlighted: !(appWin.selectedFile == "" || canPrint)
highlighted: !(selectedFile == "" || canPrint)
source: "image://theme/icon-m-file-presentation"
}
HighlightImage {
@ -318,7 +326,7 @@ Page {
width: Theme.itemSizeExtraSmall/2
visible: supported_formats.images
highlightColor: "red"
highlighted: !(appWin.selectedFile == "" || canPrint)
highlighted: !(selectedFile == "" || canPrint)
source: "image://theme/icon-m-file-image"
}
}
@ -373,7 +381,7 @@ Page {
Row {
id: warningRow
anchors.horizontalCenter: parent.horizontalCenter
visible: Mimer.isOffice(appWin.selectedFileType)
visible: Mimer.isOffice(page.selectedFileType)
HighlightImage {
source: "image://theme/icon-s-warning"
@ -396,7 +404,7 @@ Page {
horizontalAlignment: contentWidth > width ? Text.AlignRight : Text.AlignHCenter
truncationMode: TruncationMode.Fade
text: appWin.selectedFile != "" ? appWin.selectedFile : qsTr("No file selected")
text: selectedFile != "" ? selectedFile : qsTr("No file selected")
SequentialAnimation {
id: noFileSelectedAnimation
@ -449,7 +457,18 @@ Page {
title: qsTr("Choose file")
onSelectedContentPropertiesChanged: {
appWin.openFile(selectedContentProperties.filePath);
var mimeType = Mimer.get_type(selectedContentProperties.filePath)
if(mimeType == Mimer.PDF || mimeType == Mimer.Postscript || mimeType == Mimer.Plaintext || Mimer.isOffice(mimeType))
{
page.selectedFile = selectedContentProperties.filePath
page.selectedFileType = mimeType
}
else
{
notifier.notify(qsTr("Unsupported document format"))
page.selectedFile = ""
page.selectedFileType = ""
}
}
}
}
@ -459,7 +478,8 @@ Page {
allowedOrientations: Orientation.All
onSelectedContentPropertiesChanged: {
appWin.openFile(selectedContentProperties.filePath);
page.selectedFile = selectedContentProperties.filePath
page.selectedFileType = Mimer.get_type(selectedContentProperties.filePath)
}
}
}

View file

@ -104,8 +104,6 @@ Page {
tag: IppMsg.Integer
name: "copies"
prettyName: qsTr("Copies")
valid: _valid || Utils.supports_raster(printer)
minimum_high: 99
}
ChoiceSetting {
tag: IppMsg.Keyword
@ -120,7 +118,6 @@ Page {
property var pdfpages: ConvertChecker.pdfPages(selectedFile)
high: pdfpages == 0 ? 65535 : pdfpages
acceptRangeList: true
}
ChoiceSetting {
tag: IppMsg.Integer

View file

@ -63,16 +63,6 @@ function supported_formats(printer, considerAdditionalFormats)
return {pdf: pdf, postscript: postscript, plaintext: plaintext, office: office, images: images, mimetypes: mimetypes};
}
function supports_raster(printer)
{
var formats = printer.attrs["document-format-supported"].value;
if(considerAdditionalFormats)
{
formats=formats+printer.additionalDocumentFormats;
}
return (has(formats, Mimer.Mimer.PWG) || has(formats, Mimer.Mimer.URF));
}
function has(arrayish, what)
{
return arrayish.indexOf(what) != -1;
@ -445,7 +435,7 @@ function knownPaperSize(mediaName)
}
function fixupChoices(name, choices, mimeType, printer)
function fixupChoices(name, choices, mimeType)
{
switch(name) {
case "document-format":
@ -497,18 +487,7 @@ function fixupChoices(name, choices, mimeType, printer)
return choices;
}
case "media":
if(printer.attrs.hasOwnProperty("media-ready"))
{
for(var m in printer.attrs["media-ready"].value)
{
var value = printer.attrs["media-ready"].value[m];
if(!has(choices, value))
{
choices.push(value);
}
}
}
return choices;
return choices.filter(knownPaperSize);
default:
return choices;
}

View file

@ -4,8 +4,8 @@ Summary: SeaPrint
Version: 0
Release: 1
Group: Qt/Qt
License: GPLv3
URL: https://github.com/attah/harbour-seaprint
License: LICENSE
URL: http://example.org/
Source0: %{name}-%{version}.tar.bz2
Requires: sailfishsilica-qt5 >= 0.10.9
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
@ -21,9 +21,6 @@ BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(cairo)
BuildRequires: pkgconfig(libjpeg)
%define _source_payload w6T.xzdio
%define _binary_payload w6T.xzdio
%description
Network printing for Sailfish OS
@ -47,7 +44,7 @@ desktop-file-install --delete-original \
%files
%defattr(-,root,root,-)
%{_bindir}/%{name}
%{_bindir}
%{_datadir}/%{name}
%{_datadir}/applications/%{name}.desktop
%{_datadir}/icons/hicolor/*/apps/%{name}.png

View file

@ -1,25 +0,0 @@
#include "dbusadaptorbase.h"
#include <QtQuick>
void DBusAdaptorBase::doActivate()
{
QMetaObject::invokeMethod(_view->rootObject(), "activate");
}
void DBusAdaptorBase::doOpen(const QString& fileName)
{
QMetaObject::invokeMethod(_view->rootObject(), "openFile", Q_ARG(QVariant, fileName));
doActivate();
}
void DBusAdaptorBase::doCreateFileAndOpen(const QString& fileContents, const QString& name)
{
QTemporaryFile tmpfile(QDir::tempPath() + "/" + name);
tmpfile.setAutoRemove(false);
tmpfile.open();
tmpfile.write(fileContents.toUtf8());
tmpfile.close();
QMetaObject::invokeMethod(_view->rootObject(), "openFile", Q_ARG(QVariant, tmpfile.fileName()));
doActivate();
}

View file

@ -1,24 +0,0 @@
#ifndef DBUSADAPTORBASE_H
#define DBUSADAPTORBASE_H
#include <QObject>
#include <QtDBus/QDBusAbstractAdaptor>
#include <QQuickView>
class DBusAdaptorBase
{
public:
DBusAdaptorBase(QQuickView* view)
: _view(view)
{}
void doActivate();
void doOpen(const QString& fileName);
void doCreateFileAndOpen(const QString& fileContents, const QString& name);
protected:
QQuickView* _view;
};
#endif // DBUSADAPTORBASE_H

View file

@ -1,31 +0,0 @@
#include "freedesktopdbusadaptor.h"
#include <QtQuick>
FreedesktopDBusAdaptor::FreedesktopDBusAdaptor(QQuickView *view)
: QDBusAbstractAdaptor(view)
, DBusAdaptorBase(view)
{
}
FreedesktopDBusAdaptor::~FreedesktopDBusAdaptor()
{
}
void FreedesktopDBusAdaptor::Open(const QStringList& uris, const QVariantMap& platformData)
{
qDebug() << platformData;
if (!uris.isEmpty() && uris[0] != "") {
doOpen(uris.at(0));
}
else if(platformData.contains("data"))
{
doCreateFileAndOpen(platformData["data"].toString(),
(platformData.contains("name") ? platformData["name"].toString() : "seaprint"));
}
}
void FreedesktopDBusAdaptor::Activate(const QVariantMap&)
{
QMetaObject::invokeMethod(_view->rootObject(), "activate");
}

View file

@ -1,21 +0,0 @@
#ifndef FREEDESKTOPDBUSADAPTOR_H
#define FREEDESKTOPDBUSADAPTOR_H
#include "dbusadaptorbase.h"
class FreedesktopDBusAdaptor : public QDBusAbstractAdaptor, public DBusAdaptorBase
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Application")
public:
FreedesktopDBusAdaptor(QQuickView *view);
~FreedesktopDBusAdaptor();
public Q_SLOTS:
Q_NOREPLY void Open(const QStringList& uris, const QVariantMap& platformData);
Q_NOREPLY void Activate(const QVariantMap& platformData);
};
#endif // FREEDESKTOPDBUSADAPTOR_H

View file

@ -1,6 +1,4 @@
#include <QtQuick>
#include <QVariant>
#include <QDBusConnection>
#include <sailfishapp.h>
#include <src/ippdiscovery.h>
@ -9,11 +7,6 @@
#include <src/mimer.h>
#include <src/convertchecker.h>
#include <src/settings.h>
#include <src/rangelistchecker.h>
#include <src/freedesktopdbusadaptor.h>
#include <src/seaprintdbusadaptor.h>
#include "argget.h"
#include <iostream>
Q_DECLARE_METATYPE(CURLcode)
Q_DECLARE_METATYPE(Bytestream)
@ -32,17 +25,6 @@ static QObject* singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngi
int main(int argc, char *argv[])
{
bool prestart = false;
std::string FileName;
SwitchArg<bool> pretsartOpt(prestart, {"--prestart"}, "Run prestart");
PosArg fileArg(FileName, "File to print", true);
ArgGet args({&pretsartOpt}, {&fileArg});
if(!args.get_args(argc, argv))
{
return 1;
}
qRegisterMetaType<CURLcode>();
qRegisterMetaType<Bytestream>();
qRegisterMetaType<PrintParameters>();
@ -59,9 +41,7 @@ int main(int argc, char *argv[])
qmlRegisterSingletonType<IppDiscovery>("seaprint.ippdiscovery", 1, 0, "IppDiscovery", singletontype_provider<IppDiscovery>);
qmlRegisterSingletonType<Mimer>("seaprint.mimer", 1, 0, "Mimer", singletontype_provider<Mimer>);
qmlRegisterSingletonType<ConvertChecker>("seaprint.convertchecker", 1, 0, "ConvertChecker", singletontype_provider<ConvertChecker>);
qmlRegisterSingletonType<Settings>("seaprint.settings", 1, 0, "SeaPrintSettings", singletontype_provider<Settings>);
qmlRegisterSingletonType<RangeListChecker>("seaprint.rangelistchecker", 1, 0, "RangeListChecker", singletontype_provider<RangeListChecker>);
qmlRegisterSingletonType<ConvertChecker>("seaprint.settings", 1, 0, "SeaPrintSettings", singletontype_provider<Settings>);
qmlRegisterType<IppPrinter>("seaprint.ippprinter", 1, 0, "IppPrinter");
qmlRegisterType<ImageItem>("seaprint.imageitem", 1, 0, "ImageItem");
qmlRegisterUncreatableType<IppMsg>("seaprint.ippmsg", 1, 0, "IppMsg", "Only used to supply an enum type");
@ -69,26 +49,8 @@ int main(int argc, char *argv[])
QQuickView* view = SailfishApp::createView();
view->engine()->addImportPath(SailfishApp::pathTo("qml/pages").toString());
view->setSource(SailfishApp::pathToMainQml());
FreedesktopDBusAdaptor freedesktopDbus(view);
SeaPrintDBusAdaptor seaprintDbus(view);
if (!QDBusConnection::sessionBus().registerObject("/net/attah/seaprint", view))
qWarning() << "Could not register /net/attah/seaprint D-Bus object.";
if (!QDBusConnection::sessionBus().registerService("net.attah.seaprint"))
qWarning() << "Could not register net.attah.seaprint D-Bus service.";
if(!FileName.empty())
{
qDebug() << "Opening" << FileName.c_str();
QVariant fileNameVariant(FileName.c_str());
QMetaObject::invokeMethod(view->rootObject(), "openFile", Q_ARG(QVariant, fileNameVariant));
}
if(!prestart)
{
view->show();
}
view->show();
return app->exec();
}

View file

@ -288,7 +288,6 @@ QString IppMsg::consume_attribute(QJsonObject& attrs, Bytestream& data)
|| name.startsWith("printer-firmware")
|| name.endsWith("-supported")
|| name == "printer-icons"
|| name == "media-ready"
|| name.endsWith("-reasons")));
if(!unnamed.empty() || forceArray)
@ -320,15 +319,11 @@ Bytestream IppMsg::encode()
QStringList InitialAttrs = {"attributes-charset",
"attributes-natural-language",
"printer-uri",
"job-id",
"requesting-user-name"};
for(QString key : InitialAttrs)
{
if(_opAttrs.find(key) != _opAttrs.end())
{
QJsonObject val = _opAttrs.take(key).toObject();
encode_attr(ipp, val["tag"].toInt(), key, val["value"]);
}
QJsonObject val = _opAttrs.take(key).toObject();
encode_attr(ipp, val["tag"].toInt(), key, val["value"]);
}
for(QJsonObject::iterator it = _opAttrs.begin(); it != _opAttrs.end(); it++)
{ // encode any remaining op-attrs
@ -362,25 +357,7 @@ void IppMsg::encode_attr(Bytestream& msg, quint8 tag, QString name, QJsonValue v
name = "";
}
msg << tag << quint16(name.length()) << name.toStdString();
if(value.isArray())
{
QJsonArray array = value.toArray();
value = array.takeAt(0);
encode_value(msg, tag, value);
for(QJsonValue v : array)
{
msg << tag << quint16(0);
encode_value(msg, tag, v);
}
}
else
{
encode_value(msg, tag, value);
}
}
void IppMsg::encode_value(Bytestream& msg, quint8 tag, QJsonValue value)
{
switch (tag) {
case OpAttrs:
@ -424,11 +401,19 @@ void IppMsg::encode_value(Bytestream& msg, quint8 tag, QJsonValue value)
case BeginCollection:
{
msg << (quint16)0; // length of value
QJsonObject collection = value.toObject();
for(QString key : collection.keys())
if(value.isObject())
{
encode_attr(msg, collection[key].toObject()["tag"].toInt(), key,
collection[key].toObject()["value"], true);
QJsonObject collection = value.toObject();
for(QString key : collection.keys())
{
encode_attr(msg, collection[key].toObject()["tag"].toInt(), key,
collection[key].toObject()["value"], true);
}
}
else
{
// TODO add support for 1-setOf in collections
Q_ASSERT("FIXME-array");
}
msg << (quint8)EndCollection << (quint16)0 << (quint16)0;
break;

View file

@ -88,7 +88,6 @@ private:
QJsonValue collect_attributes(QJsonArray& attrs);
QString consume_attribute(QJsonObject& attrs, Bytestream& data);
void encode_attr(Bytestream& msg, quint8 tag, QString name, QJsonValue value, bool subCollection=false);
void encode_value(Bytestream& msg, quint8 tag, QJsonValue value);
Operation _operation;

View file

@ -1,7 +1,6 @@
#include "ippprinter.h"
#include "ippdiscovery.h"
#include "mimer.h"
#include "convertchecker.h"
#include "papersizes.h"
#include "overrider.h"
#include "settings.h"
@ -10,32 +9,35 @@
Q_DECLARE_METATYPE(QMargins)
Q_DECLARE_METATYPE(IppMsg)
IppPrinter::IppPrinter()
IppPrinter::IppPrinter() : _worker(this)
{
_worker = new PrinterWorker(this);
QObject::connect(this, &IppPrinter::urlChanged, this, &IppPrinter::onUrlChanged);
qRegisterMetaType<QTemporaryFile*>("QTemporaryFile*");
connect(this, &IppPrinter::doDoGetPrinterAttributes, _worker, &PrinterWorker::getPrinterAttributes);
connect(this, &IppPrinter::doGetJobs, _worker, &PrinterWorker::getJobs);
connect(this, &IppPrinter::doCancelJob, _worker, &PrinterWorker::cancelJob);
connect(this, &IppPrinter::doIdentify, _worker, &PrinterWorker::identify);
connect(this, &IppPrinter::doPrint, _worker, &PrinterWorker::print);
connect(this, &IppPrinter::doPrint2, _worker, &PrinterWorker::print2);
_worker.moveToThread(&_workerThread);
connect(this, &IppPrinter::doGetStrings, _worker, &PrinterWorker::getStrings);
connect(this, &IppPrinter::doGetImage, _worker, &PrinterWorker::getImage);
connect(this, &IppPrinter::doDoGetPrinterAttributes, &_worker, &PrinterWorker::getPrinterAttributes);
connect(this, &IppPrinter::doGetJobs, &_worker, &PrinterWorker::getJobs);
connect(this, &IppPrinter::doCancelJob, &_worker, &PrinterWorker::cancelJob);
connect(this, &IppPrinter::doIdentify, &_worker, &PrinterWorker::identify);
connect(this, &IppPrinter::doPrint, &_worker, &PrinterWorker::print);
connect(this, &IppPrinter::doPrint2, &_worker, &PrinterWorker::print2);
connect(_worker, &PrinterWorker::progress, this, &IppPrinter::setProgress);
connect(_worker, &PrinterWorker::busyMessage, this, &IppPrinter::setBusyMessage);
connect(_worker, &PrinterWorker::failed, this, &IppPrinter::convertFailed);
connect(this, &IppPrinter::doGetStrings, &_worker, &PrinterWorker::getStrings);
connect(this, &IppPrinter::doGetImage, &_worker, &PrinterWorker::getImage);
connect(&_worker, &PrinterWorker::progress, this, &IppPrinter::setProgress);
connect(&_worker, &PrinterWorker::busyMessage, this, &IppPrinter::setBusyMessage);
connect(&_worker, &PrinterWorker::failed, this, &IppPrinter::convertFailed);
qRegisterMetaType<QMargins>();
qRegisterMetaType<IppMsg>();
_workerThread.start();
}
IppPrinter::~IppPrinter() {
}
QJsonObject IppPrinter::opAttrs() {
@ -83,7 +85,6 @@ void IppPrinter::setUrl(QString url_s)
void IppPrinter::onUrlChanged()
{
QMetaObject::invokeMethod(_worker, "urlChanged", Q_ARG(QUrl, httpUrl()));
refresh();
}
@ -419,16 +420,16 @@ QString targetFormatIfAuto(QString documentFormat, QString mimeType, QJsonArray
return documentFormat;
}
void IppPrinter::adjustRasterSettings(QString filename, QString mimeType, QJsonObject& jobAttrs, PrintParameters& Params)
void IppPrinter::adjustRasterSettings(QString documentFormat, QJsonObject& jobAttrs, PrintParameters& Params)
{
if(Params.format != PrintParameters::PWG && Params.format != PrintParameters::URF)
if(documentFormat != Mimer::PWG && documentFormat != Mimer::URF)
{
return;
}
jobAttrs.remove("printer-resolution");
//TODO? jobAttrs.remove("printer-resolution");
if(Params.format == PrintParameters::PWG)
if(documentFormat == Mimer::PWG)
{
quint32 diff = std::numeric_limits<quint32>::max();
quint32 AdjustedHwResX = Params.hwResW;
@ -451,8 +452,9 @@ void IppPrinter::adjustRasterSettings(QString filename, QString mimeType, QJsonO
Params.hwResW = AdjustedHwResX;
Params.hwResH = AdjustedHwResY;
}
else if(Params.format == PrintParameters::URF)
{ // Ensure Params.format resolution for URF
if(documentFormat == Mimer::URF)
{ // Ensure symmetric resolution for URF
Params.hwResW = Params.hwResH = std::min(Params.hwResW, Params.hwResH);
quint32 diff = std::numeric_limits<quint32>::max();
@ -485,7 +487,7 @@ void IppPrinter::adjustRasterSettings(QString filename, QString mimeType, QJsonO
if(Sides != "" && Sides != "one-sided")
{
if(Params.format == PrintParameters::PWG)
if(documentFormat == Mimer::PWG)
{
QString DocumentSheetBack = _attrs["pwg-raster-document-sheet-back"].toObject()["value"].toString();
if(Sides=="two-sided-long-edge")
@ -513,7 +515,7 @@ void IppPrinter::adjustRasterSettings(QString filename, QString mimeType, QJsonO
}
}
}
else if(Params.format == PrintParameters::URF)
else if(documentFormat == Mimer::URF)
{
QJsonArray URfSupported = _attrs["urf-supported"].toObject()["value"].toArray();
if(Sides=="two-sided-long-edge")
@ -543,47 +545,6 @@ void IppPrinter::adjustRasterSettings(QString filename, QString mimeType, QJsonO
}
}
int copies_requested = getAttrOrDefault(jobAttrs, "copies").toInt(1);
QJsonArray varying_attributes = _attrs["document-format-varying-attributes"].toObject()["value"].toArray();
bool supports_copies = _attrs.contains("copies-supported")
&& _attrs["copies-supported"].toObject()["value"].toObject()["high"].toInt(1) != 1
// assume raster formats causes the variation in supported copies
&& !(varying_attributes.contains("copies-supported") || varying_attributes.contains("copies"));
if(copies_requested > 1 && !supports_copies)
{
QString copyMode = getAttrOrDefault(jobAttrs, "multiple-document-handling").toString();
qDebug() << "Doing local copies" << copyMode << copies_requested;
if(copyMode == "separate-documents-uncollated-copies")
{ // Only do silly copies if explicitly requested
Params.pageCopies = copies_requested;
}
else
{
Params.documentCopies = copies_requested;
}
jobAttrs.remove("copies");
if(Sides != "one-sided")
{
bool singlePageRange = false;
if(Params.pageRangeList.size() == 1)
{
size_t fromPage = Params.pageRangeList.begin()->first;
size_t toPage = Params.pageRangeList.begin()->second;
singlePageRange = fromPage != 0 && fromPage == toPage;
}
bool singlePageDocument = (Mimer::instance()->isImage(mimeType) ||
(mimeType == Mimer::PDF && ConvertChecker::instance()->pdfPages(filename) == 1));
if(singlePageDocument || singlePageRange)
{
jobAttrs.insert("sides", QJsonObject {{"tag", IppMsg::Keyword}, {"value", "one-sided"}});
qDebug() << "Optimizing one-page document to one-sided";
}
}
}
}
void IppPrinter::print(QJsonObject jobAttrs, QString filename)
@ -614,11 +575,7 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
qDebug() << supportedMimeTypes << supportedMimeTypes.contains(mimeType);
if(!Params.setPaperSize(getAttrOrDefault(jobAttrs, "media").toString(Params.paperSizeName.c_str()).toStdString()))
{
emit convertFailed(tr("Unsupported paper size"));
return;
}
Params.paperSizeName = getAttrOrDefault(jobAttrs, "media").toString(Params.paperSizeName.c_str()).toStdString();
QString targetFormat = getAttrOrDefault(jobAttrs, "document-format").toString();
qDebug() << "target format:" << targetFormat;
@ -653,9 +610,14 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
if(jobAttrs.contains("media-col") && jobAttrs.contains("media"))
{
qDebug() << "moving media to media-col" << Params.paperSizeName.c_str();
if(!PaperSizes.contains(Params.paperSizeName.c_str()))
{
emit convertFailed(tr("Unsupported paper size"));
return;
}
int x = Params.getPaperSizeWInMillimeters()*100;
int y = Params.getPaperSizeHInMillimeters()*100;
int x = PaperSizes[Params.paperSizeName.c_str()].width()*100;
int y = PaperSizes[Params.paperSizeName.c_str()].height()*100;
QJsonObject Dimensions =
{{"tag", IppMsg::BeginCollection},
@ -709,33 +671,35 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
Params.format = PrintParameters::Invalid;
}
QSizeF size = PaperSizes[Params.paperSizeName.c_str()];
Params.paperSizeUnits = PrintParameters::Millimeters;
Params.paperSizeW = size.width();
Params.paperSizeH = size.height();
qDebug() << "Printing job" << jobOpAttrs << jobAttrs;
QJsonValue PrinterResolutionRef = getAttrOrDefault(jobAttrs, "printer-resolution");
Params.hwResW = PrinterResolutionRef.toObject()["x"].toInt(Params.hwResW);
Params.hwResH = PrinterResolutionRef.toObject()["y"].toInt(Params.hwResH);
// Effected locally, unless it is Postscript which we cant't render
if(jobAttrs.contains("page-ranges") && mimeType != Mimer::Postscript)
{
QJsonArray tmp;
QJsonValue pageRanges = getAttrOrDefault(jobAttrs, "page-ranges");
if(pageRanges.isArray())
{
tmp = pageRanges.toArray();
}
else if(pageRanges.isObject())
{
tmp = {pageRanges.toObject()};
}
for(QJsonValueRef ref : tmp)
{
Params.pageRangeList.push_back({ref.toObject()["low"].toInt(), ref.toObject()["high"].toInt()});
}
jobAttrs.remove("page-ranges");
}
adjustRasterSettings(targetFormat, jobAttrs, Params);
adjustRasterSettings(filename, mimeType, jobAttrs, Params);
Params.quality = getAttrOrDefault(jobAttrs, "print-quality").toInt();
QString PrintColorMode = getAttrOrDefault(jobAttrs, "print-color-mode").toString();
Params.colors = PrintColorMode.contains("color") ? 3 : PrintColorMode.contains("monochrome") ? 1 : Params.colors;
if(jobAttrs.contains("page-ranges"))
{
QJsonObject PageRanges = getAttrOrDefault(jobAttrs, "page-ranges").toObject();
Params.fromPage = PageRanges["low"].toInt();
Params.toPage = PageRanges["high"].toInt();
// Effected locally, unless it is Postscript which we cant't render
if(targetFormat != Mimer::Postscript)
{
jobAttrs.remove("page-ranges");
}
}
QString Sides = getAttrOrDefault(jobAttrs, "sides").toString();
@ -749,11 +713,6 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
Params.tumble = true;
}
Params.quality = getAttrOrDefault(jobAttrs, "print-quality").toInt();
QString PrintColorMode = getAttrOrDefault(jobAttrs, "print-color-mode").toString();
Params.colors = PrintColorMode.contains("color") ? 3 : PrintColorMode.contains("monochrome") ? 1 : Params.colors;
QJsonArray supportedOperations = _attrs["operations-supported"].toObject()["value"].toArray();
if(supportedOperations.contains(IppMsg::CreateJob) && supportedOperations.contains(IppMsg::SendDocument))

View file

@ -107,7 +107,7 @@ private:
QJsonObject opAttrs();
void adjustRasterSettings(QString filename, QString mimeType, QJsonObject& jobAttrs, PrintParameters& Params);
void adjustRasterSettings(QString documentFormat, QJsonObject& jobAttrs, PrintParameters& Params);
void setBusyMessage(QString msg);
void setProgress(qint64 sent, qint64 total);
@ -130,7 +130,8 @@ private:
QString _busyMessage;
QString _progress;
PrinterWorker* _worker;
QThread _workerThread;
PrinterWorker _worker;
bool _iconRetried = false;
};

View file

@ -55,12 +55,5 @@ Mimer* Mimer::instance()
QString Mimer::get_type(QString filename) {
QString type = _db.mimeTypeForFile(filename).name();
qDebug() << "MimeType:" << type;
if(type == PDF || type == Postscript || type == Plaintext || isImage(type) || isOffice(type))
{
return type;
}
else
{
return "";
}
return type;
}

View file

@ -3,6 +3,208 @@
#include <QMap>
#include <QSizeF>
static QMap<QString, QSizeF> PaperSizes =
{{"asme_f_28x40in", {711.20, 1016.00}},
{"iso_2a0_1189x1682mm", {1189.00, 1682.00}},
{"iso_a0_841x1189mm", {841.00, 1189.00}},
{"iso_a0x3_1189x2523mm", {1189.00, 2523.00}},
{"iso_a10_26x37mm", {26.00, 37.00}},
{"iso_a1_594x841mm", {594.00, 841.00}},
{"iso_a1x3_841x1783mm", {841.00, 1783.00}},
{"iso_a1x4_841x2378mm", {841.00, 2378.00}},
{"iso_a2_420x594mm", {420.00, 594.00}},
{"iso_a2x3_594x1261mm", {594.00, 1261.00}},
{"iso_a2x4_594x1682mm", {594.00, 1682.00}},
{"iso_a2x5_594x2102mm", {594.00, 2102.00}},
{"iso_a3-extra_322x445mm", {322.00, 445.00}},
{"iso_a3_297x420mm", {297.00, 420.00}},
{"iso_a3x3_420x891mm", {420.00, 891.00}},
{"iso_a3x4_420x1189mm", {420.00, 1189.00}},
{"iso_a3x5_420x1486mm", {420.00, 1486.00}},
{"iso_a3x6_420x1783mm", {420.00, 1783.00}},
{"iso_a3x7_420x2080mm", {420.00, 2080.00}},
{"iso_a4-extra_235.5x322.3m", {235.50, 322.30}},
{"iso_a4-tab_225x297mm", {225.00, 297.00}},
{"iso_a4_210x297mm", {210.00, 297.00}},
{"iso_a4x3_297x630mm", {297.00, 630.00}},
{"iso_a4x4_297x841mm", {297.00, 841.00}},
{"iso_a4x5_297x1051mm", {297.00, 1051.00}},
{"iso_a4x6_297x1261mm", {297.00, 1261.00}},
{"iso_a4x7_297x1471mm", {297.00, 1471.00}},
{"iso_a4x8_297x1682mm", {297.00, 1682.00}},
{"iso_a4x9_297x1892mm", {297.00, 1892.00}},
{"iso_a5-extra_174x235mm", {174.00, 235.00}},
{"iso_a5_148x210mm", {148.00, 210.00}},
{"iso_a6_105x148mm", {105.00, 148.00}},
{"iso_a7_74x105mm", {74.00, 105.00}},
{"iso_a8_52x74mm", {52.00, 74.00}},
{"iso_a9_37x52mm", {37.00, 52.00}},
{"iso_b0_1000x1414mm", {1000.00, 1414.00}},
{"iso_b10_31x44mm", {31.00, 44.00}},
{"iso_b1_707x1000mm", {707.00, 1000.00}},
{"iso_b2_500x707mm", {500.00, 707.00}},
{"iso_b3_353x500mm", {353.00, 500.00}},
{"iso_b4_250x353mm", {250.00, 353.00}},
{"iso_b5-extra_201x276mm", {201.00, 276.00}},
{"iso_b5_176x250mm", {176.00, 250.00}},
{"iso_b6_125x176mm", {125.00, 176.00}},
{"iso_b6c4_125x324mm", {125.00, 324.00}},
{"iso_b7_88x125mm", {88.00, 125.00}},
{"iso_b8_62x88mm", {62.00, 88.00}},
{"iso_b9_44x62mm", {44.00, 62.00}},
{"iso_c0_917x1297mm", {917.00, 1297.00}},
{"iso_c10_28x40mm", {28.00, 40.00}},
{"iso_c1_648x917mm", {648.00, 917.00}},
{"iso_c2_458x648mm", {458.00, 648.00}},
{"iso_c3_324x458mm", {324.00, 458.00}},
{"iso_c4_229x324mm", {229.00, 324.00}},
{"iso_c5_162x229mm", {162.00, 229.00}},
{"iso_c6_114x162mm", {114.00, 162.00}},
{"iso_c6c5_114x229mm", {114.00, 229.00}},
{"iso_c7_81x114mm", {81.00, 114.00}},
{"iso_c7c6_81x162mm", {81.00, 162.00}},
{"iso_c8_57x81mm", {57.00, 81.00}},
{"iso_c9_40x57mm", {40.00, 57.00}},
{"iso_dl_110x220mm", {110.00, 220.00}},
{"iso_id-1_53.98x85.6mm", {53.98, 85.60}},
{"iso_id-3_88x125mm", {88.00, 125.00}},
{"iso_ra0_860x1220mm", {860.00, 1220.00}},
{"iso_ra1_610x860mm", {610.00, 860.00}},
{"iso_ra2_430x610mm", {430.00, 610.00}},
{"iso_ra3_305x430mm", {305.00, 430.00}},
{"iso_ra4_215x305mm", {215.00, 305.00}},
{"iso_sra0_900x1280mm", {900.00, 1280.00}},
{"iso_sra1_640x900mm", {640.00, 900.00}},
{"iso_sra2_450x640mm", {450.00, 640.00}},
{"iso_sra3_320x450mm", {320.00, 450.00}},
{"iso_sra4_225x320mm", {225.00, 320.00}},
{"jis_b0_1030x1456mm", {1030.00, 1456.00}},
{"jis_b10_32x45mm", {32.00, 45.00}},
{"jis_b1_728x1030mm", {728.00, 1030.00}},
{"jis_b2_515x728mm", {515.00, 728.00}},
{"jis_b3_364x515mm", {364.00, 515.00}},
{"jis_b4_257x364mm", {257.00, 364.00}},
{"jis_b5_182x257mm", {182.00, 257.00}},
{"jis_b6_128x182mm", {128.00, 182.00}},
{"jis_b7_91x128mm", {91.00, 128.00}},
{"jis_b8_64x91mm", {64.00, 91.00}},
{"jis_b9_45x64mm", {45.00, 64.00}},
{"jis_exec_216x330mm", {216.00, 330.00}},
{"jpn_chou2_111.1x146mm", {111.10, 146.00}},
{"jpn_chou3_120x235mm", {120.00, 235.00}},
{"jpn_chou40_90x225mm", {90.00, 225.00}},
{"jpn_chou4_90x205mm", {90.00, 205.00}},
{"jpn_hagaki_100x148mm", {100.00, 148.00}},
{"jpn_kahu_240x322.1mm", {240.00, 322.10}},
{"jpn_kaku1_270x382mm", {270.00, 382.00}},
{"jpn_kaku2_240x332mm", {240.00, 332.00}},
{"jpn_kaku3_216x277mm", {216.00, 277.00}},
{"jpn_kaku4_197x267mm", {197.00, 267.00}},
{"jpn_kaku5_190x240mm", {190.00, 240.00}},
{"jpn_kaku7_142x205mm", {142.00, 205.00}},
{"jpn_kaku8_119x197mm", {119.00, 197.00}},
{"jpn_oufuku_148x200mm", {148.00, 200.00}},
{"jpn_you4_105x235mm", {105.00, 235.00}},
{"na_10x11_10x11in", {254.00, 279.40}},
{"na_10x13_10x13in", {254.00, 330.20}},
{"na_10x14_10x14in", {254.00, 355.60}},
{"na_10x15_10x15in", {254.00, 381.00}},
{"na_11x12_11x12in", {279.40, 304.80}},
{"na_11x15_11x15in", {279.40, 381.00}},
{"na_12x19_12x19in", {304.80, 482.60}},
{"na_5x7_5x7in", {127.00, 177.80}},
{"na_6x9_6x9in", {152.40, 228.60}},
{"na_7x9_7x9in", {177.80, 228.60}},
{"na_9x11_9x11in", {228.60, 279.40}},
{"na_a2_4.375x5.75in", {111.12, 146.05}},
{"na_arch-a_9x12in", {228.60, 304.80}},
{"na_arch-b_12x18in", {304.80, 457.20}},
{"na_arch-c_18x24in", {457.20, 609.60}},
{"na_arch-d_24x36in", {609.60, 914.40}},
{"na_arch-e2_26x38in", {660.40, 965.20}},
{"na_arch-e3_27x39in", {685.80, 990.60}},
{"na_arch-e_36x48in", {914.40, 1219.20}},
{"na_b-plus_12x19.17in", {304.80, 486.92}},
{"na_c5_6.5x9.5in", {165.10, 241.30}},
{"na_c_17x22in", {431.80, 558.80}},
{"na_d_22x34in", {558.80, 863.60}},
{"na_e_34x44in", {863.60, 1117.60}},
{"na_edp_11x14in", {279.40, 355.60}},
{"na_eur-edp_12x14in", {304.80, 355.60}},
{"na_executive_7.25x10.5in", {184.15, 266.70}},
{"na_f_44x68in", {1117.60, 1727.20}},
{"na_fanfold-eur_8.5x12in", {215.90, 304.80}},
{"na_fanfold-us_11x14.875in", {279.40, 377.82}},
{"na_foolscap_8.5x13in", {215.90, 330.20}},
{"na_govt-legal_8x13in", {203.20, 330.20}},
{"na_govt-letter_8x10in", {203.20, 254.00}},
{"na_index-3x5_3x5in", {76.20, 127.00}},
{"na_index-4x6-ext_6x8in", {152.40, 203.20}},
{"na_index-4x6_4x6in", {101.60, 152.40}},
{"na_index-5x8_5x8in", {127.00, 203.20}},
{"na_invoice_5.5x8.5in", {139.70, 215.90}},
{"na_ledger_11x17in", {279.40, 431.80}},
{"na_legal-extra_9.5x15in", {241.30, 381.00}},
{"na_legal_8.5x14in", {215.90, 355.60}},
{"na_letter-extra_9.5x12in", {241.30, 304.80}},
{"na_letter-plus_8.5x12.69in", {215.90, 322.33}},
{"na_letter_8.5x11in", {215.90, 279.40}},
{"na_monarch_3.875x7.5in", {98.42, 190.50}},
{"na_number-10_4.125x9.5in", {104.77, 241.30}},
{"na_number-11_4.5x10.375in", {114.30, 263.52}},
{"na_number-12_4.75x11in", {120.65, 279.40}},
{"na_number-14_5x11.5in", {127.00, 292.10}},
{"na_number-9_3.875x8.875in", {98.42, 225.42}},
{"na_oficio_8.5x13.4in", {215.90, 340.36}},
{"na_personal_3.625x6.5in", {92.07, 165.10}},
{"na_quarto_8.5x10.83in", {215.90, 275.08}},
{"na_super-a_8.94x14in", {227.08, 355.60}},
{"na_super-b_13x19in", {330.20, 482.60}},
{"na_wide-format_30x42in", {762.00, 1066.80}},
{"oe_12x16_12x16in", {304.80, 406.40}},
{"oe_14x17_14x17in", {355.60, 431.80}},
{"oe_18x22_18x22in", {457.20, 558.80}},
{"oe_a2plus_17x24in", {431.80, 609.60}},
{"oe_business-card_2x3.5in", {50.80, 88.90}},
{"oe_photo-10r_10x12in", {254.00, 304.80}},
{"oe_photo-20r_20x24in", {508.00, 609.60}},
{"oe_photo-l_3.5x5in", {88.90, 127.00}},
{"oe_photo-s10r_10x15in", {254.00, 381.00}},
{"oe_square-photo_4x4in", {101.60, 101.60}},
{"oe_square-photo_5x5in", {127.00, 127.00}},
{"om_16k_184x260mm", {184.00, 260.00}},
{"om_16k_195x270mm", {195.00, 270.00}},
{"om_business-card_55x85mm", {55.00, 85.00}},
{"om_business-card_55x91mm", {55.00, 91.00}},
{"om_card_54x86mm", {54.00, 86.00}},
{"om_dai-pa-kai_275x395mm", {275.00, 395.00}},
{"om_dsc-photo_89x119mm", {89.00, 119.00}},
{"om_folio-sp_215x315mm", {215.00, 315.00}},
{"om_folio_210x330mm", {210.00, 330.00}},
{"om_invite_220x220mm", {220.00, 220.00}},
{"om_italian_110x230mm", {110.00, 230.00}},
{"om_juuro-ku-kai_198x275mm", {198.00, 275.00}},
{"om_large-photo_200x300", {200.00, 300.00}},
{"om_medium-photo_130x180mm", {130.00, 180.00}},
{"om_pa-kai_267x389mm", {267.00, 389.00}},
{"om_postfix_114x229mm", {114.00, 229.00}},
{"om_small-photo_100x150mm", {100.00, 150.00}},
{"om_square-photo_89x89mm", {89.00, 89.00}},
{"om_wide-photo_100x200mm", {100.00, 200.00}},
{"prc_10_324x458mm", {324.00, 458.00}},
{"prc_16k_146x215mm", {146.00, 215.00}},
{"prc_1_102x165mm", {102.00, 165.00}},
{"prc_2_102x176mm", {102.00, 176.00}},
{"prc_32k_97x151mm", {97.00, 151.00}},
{"prc_3_125x176mm", {125.00, 176.00}},
{"prc_4_110x208mm", {110.00, 208.00}},
{"prc_5_110x220mm", {110.00, 220.00}},
{"prc_6_120x320mm", {120.00, 320.00}},
{"prc_7_160x230mm", {160.00, 230.00}},
{"prc_8_120x309mm", {120.00, 309.00}},
{"roc_16k_7.75x10.75in", {196.85, 273.05}},
{"roc_8k_10.75x15.5in", {273.05, 393.70}}};
static QMap<QString, QString> CalligraPaperSizes =
{{"iso_a0_841x1189mm", "A0"},
{"iso_a1_594x841mm", "A1"},

View file

@ -21,26 +21,6 @@
PrinterWorker::PrinterWorker(IppPrinter* parent)
{
_printer = parent;
_url = parent->httpUrl();
_thread.reset(new QThread);
moveToThread(_thread.get());
_thread->start();
}
PrinterWorker::~PrinterWorker()
{
QMetaObject::invokeMethod(this, "cleanup");
_thread->wait();
}
void PrinterWorker::cleanup()
{
_thread->quit();
}
void PrinterWorker::urlChanged(QUrl url)
{
_url = url;
}
void PrinterWorker::getStrings(QUrl url)
@ -58,25 +38,25 @@ void PrinterWorker::getImage(QUrl url)
void PrinterWorker::getPrinterAttributes(Bytestream msg)
{
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
CurlRequester cr(_printer->httpUrl(), CurlRequester::IppRequest, &msg);
awaitResult(cr, "getPrinterAttributesFinished");
}
void PrinterWorker::getJobs(Bytestream msg)
{
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
CurlRequester cr(_printer->httpUrl(), CurlRequester::IppRequest, &msg);
awaitResult(cr, "getJobsRequestFinished");
}
void PrinterWorker::cancelJob(Bytestream msg)
{
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
CurlRequester cr(_printer->httpUrl(), CurlRequester::IppRequest, &msg);
awaitResult(cr, "cancelJobFinished");
}
void PrinterWorker::identify(Bytestream msg)
{
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
CurlRequester cr(_printer->httpUrl(), CurlRequester::IppRequest, &msg);
awaitResult(cr, "identifyFinished");
}
@ -86,7 +66,7 @@ void PrinterWorker::print2(QString filename, QString mimeType, QString targetFor
Bytestream header = createJob.encode();
CurlRequester cr(_url, CurlRequester::IppRequest, &header);
CurlRequester cr(_printer->httpUrl(), CurlRequester::IppRequest, &header);
Bytestream resData;
CURLcode res = cr.await(&resData);
@ -106,7 +86,6 @@ void PrinterWorker::print2(QString filename, QString mimeType, QString targetFor
}
else
{
resData.setPos(0);
QMetaObject::invokeMethod(_printer, "printRequestFinished", Qt::QueuedConnection,
Q_ARG(CURLcode, res),
Q_ARG(Bytestream, resData));
@ -150,14 +129,7 @@ void PrinterWorker::print(QString filename, QString mimeType, QString targetForm
}
else if(mimeType == Mimer::Plaintext)
{
if(Params.paperSizeH == 0 && Params.getPaperSizeWInMillimeters() < 26)
{
convertPlaintextLabel(filename, contents, Params);
}
else
{
convertPlaintext(filename, contents, Params);
}
convertPlaintext(filename, contents, Params);
}
else if(Mimer::isImage(mimeType))
{
@ -189,7 +161,7 @@ void PrinterWorker::justUpload(QString filename, Bytestream header)
{
emit busyMessage(tr("Printing"));
CurlRequester cr(_url);
CurlRequester cr(_printer->httpUrl());
QFile file(filename);
file.open(QFile::ReadOnly);
@ -208,6 +180,8 @@ void PrinterWorker::printImageAsImage(QString filename, Bytestream header, QStri
QStringList supportedImageFormats = {Mimer::JPEG, Mimer::PNG};
qDebug() << ((IppPrinter*)parent())->_attrs;
if(targetFormat == Mimer::RBMP)
{
// ok
@ -224,7 +198,7 @@ void PrinterWorker::printImageAsImage(QString filename, Bytestream header, QStri
QString mimeType = Mimer::instance()->get_type(filename);
Bytestream OutBts;
CurlRequester cr(_url);
CurlRequester cr(_printer->httpUrl());
if(mimeType == Mimer::JPEG && targetFormat == Mimer::JPEG)
{
@ -294,7 +268,7 @@ void PrinterWorker::printImageAsImage(QString filename, Bytestream header, QStri
void PrinterWorker::fixupPlaintext(QString filename, Bytestream header)
{
CurlRequester cr(_url);
CurlRequester cr(_printer->httpUrl());
QFile inFile(filename);
if(!inFile.open(QIODevice::ReadOnly))
@ -336,7 +310,7 @@ void PrinterWorker::convertPdf(QString filename, Bytestream header, PrintParamet
{
emit busyMessage(tr("Printing"));
CurlRequester cr(_url);
CurlRequester cr(_printer->httpUrl());
OK(cr.write((char*)header.raw(), header.size()));
@ -461,14 +435,6 @@ void PrinterWorker::convertImage(QString filename, Bytestream header, PrintParam
}
else
{
size_t total_pages = Params.documentCopies*Params.pageCopies;
if(total_pages > 1 && Params.duplex)
{ // Images are one page by definition - if we need to do client-side copies, they must be one-sided or we'd have to insert backsides
qDebug() << "Inconsistent duplex setting";
throw ConvertFailedException(tr("Inconsistent duplex setting"));
}
QImage outImage = QImage(Params.getPaperSizeWInPixels(), Params.getPaperSizeHInPixels(), inImage.format());
outImage.fill(Qt::white);
QPainter painter(&outImage);
@ -479,7 +445,7 @@ void PrinterWorker::convertImage(QString filename, Bytestream header, PrintParam
QBuffer buf;
buf.open(QIODevice::ReadWrite);
Bytestream fileHdr, outBts;
Bytestream outBts;
if(inImage.allGray())
@ -504,23 +470,18 @@ void PrinterWorker::convertImage(QString filename, Bytestream header, PrintParam
buf.read((char*)(inBts.raw()), inBts.size());
fileHdr << (Params.format == PrintParameters::URF ? make_urf_file_hdr(1) : make_pwg_file_hdr());
outBts << (Params.format == PrintParameters::URF ? make_urf_file_hdr(1) : make_pwg_file_hdr());
bool verbose = QLoggingCategory::defaultCategory()->isDebugEnabled();
bmp_to_pwg(inBts, outBts, 1, Params, verbose);
CurlRequester cr(_url);
CurlRequester cr(_printer->httpUrl());
emit busyMessage(tr("Printing"));
OK(cr.write((char*)header.raw(), header.size()));
OK(cr.write((char*)fileHdr.raw(), fileHdr.size()));
for(size_t c = 0; c < total_pages; c++)
{
OK(cr.write((char*)(outBts.raw()), outBts.size()));
emit progress(c+1, total_pages);
}
OK(cr.write((char*)(outBts.raw()), outBts.size()));
awaitResult(cr, "printRequestFinished");
}
@ -587,22 +548,12 @@ void PrinterWorker::convertOfficeDocument(QString filename, Bytestream header, P
void PrinterWorker::convertPlaintext(QString filename, Bytestream header, PrintParameters Params)
{
QPageSize pageSize;
if(Params.paperSizeUnits == PrintParameters::Millimeters)
{
pageSize = QPageSize(QSizeF {Params.paperSizeW, Params.paperSizeH}, QPageSize::Millimeter);
}
else if(Params.paperSizeUnits == PrintParameters::Inches)
{
pageSize = QPageSize(QSizeF {Params.paperSizeW, Params.paperSizeH}, QPageSize::Inch);
}
else
if(!PaperSizes.contains(Params.paperSizeName.c_str()))
{
qDebug() << "Unsupported paper size" << Params.paperSizeName.c_str();
throw ConvertFailedException(tr("Unsupported paper size"));
}
QSizeF size = PaperSizes[Params.paperSizeName.c_str()];
QFile inFile(filename);
if(!inFile.open(QIODevice::ReadOnly))
@ -617,7 +568,7 @@ void PrinterWorker::convertPlaintext(QString filename, Bytestream header, PrintP
QPdfWriter pdfWriter(tmpPdfFile.fileName());
pdfWriter.setCreator("SeaPrint " SEAPRINT_VERSION);
QPageSize pageSize(size, QPageSize::Millimeter);
pdfWriter.setPageSize(pageSize);
pdfWriter.setResolution(resolution);
@ -656,6 +607,7 @@ void PrinterWorker::convertPlaintext(QString filename, Bytestream header, PrintP
doc.setDefaultFont(font);
(void)doc.documentLayout(); // wat
// Needs to be before painter
pdfWriter.setMargins({mmMargin, mmMargin, mmMargin, mmMargin});
@ -738,70 +690,6 @@ void PrinterWorker::convertPlaintext(QString filename, Bytestream header, PrintP
qDebug() << "posted";
}
void PrinterWorker::convertPlaintextLabel(QString filename, Bytestream header, PrintParameters Params)
{
QFile inFile(filename);
if(!inFile.open(QIODevice::ReadOnly))
{
throw ConvertFailedException(tr("Failed to open file"));
}
QString allText = inFile.readAll();
while(allText.endsWith('\n'))
{
allText.chop(1);
}
if(allText.contains('\n') || allText.contains('\f'))
{
throw ConvertFailedException(tr("Multiline label not supported"));
}
QTemporaryFile tmpPdfFile;
tmpPdfFile.open();
// NB: running with rotated format - pdf2printable will sort that out
int pixelHeight = Params.getPaperSizeWInPixels();
QFont font = QFont("Arial");
font.setPixelSize(pixelHeight);
QFontMetrics fm(font);
QString bigText = "AXgjqÈÅÄÖþ";
QRect rect = fm.boundingRect(bigText);
while(rect.height() > pixelHeight*(8.0/10.0))
{
font.setPixelSize(font.pixelSize()-1);
fm = QFontMetrics(font);
rect = fm.boundingRect(bigText);
}
rect = fm.boundingRect(allText);
int pixelWidth = rect.width() + pixelHeight/2;
float ratio = pixelWidth*1.0/pixelHeight;
Params.paperSizeH = Params.paperSizeW * ratio;
QPdfWriter pdfWriter(tmpPdfFile.fileName());
pdfWriter.setCreator("SeaPrint " SEAPRINT_VERSION);
QPageSize pageSize({Params.getPaperSizeHInPoints(), Params.getPaperSizeWInPoints()}, QPageSize::Point);
pdfWriter.setPageSize(pageSize);
pdfWriter.setMargins({0,0,0,0});
pdfWriter.setResolution(Params.hwResH);
QPainter painter(&pdfWriter);
int xOffset = -rect.x() + pixelHeight/4;
int yOffset = -rect.y() + pixelHeight/10;
painter.setFont(font);
painter.drawText(xOffset, yOffset, allText);
painter.end();
convertPdf(tmpPdfFile.fileName(), header, Params);
qDebug() << "Finished";
qDebug() << "posted";
}
void PrinterWorker::awaitResult(CurlRequester& cr, QString callback)
{
Bytestream resMsg;

View file

@ -1,7 +1,6 @@
#ifndef PRINTERWORKER_H
#define PRINTERWORKER_H
#include <QObject>
#include <memory>
#include "curlrequester.h"
#include "ippmsg.h"
#include "ppm2pwg/printparameters.h"
@ -28,13 +27,11 @@ class PrinterWorker : public QObject
public:
PrinterWorker(IppPrinter* parent);
~PrinterWorker();
private:
PrinterWorker();
public slots:
void urlChanged(QUrl url);
void getStrings(QUrl url);
void getImage(QUrl url);
void getPrinterAttributes(Bytestream msg);
@ -44,9 +41,6 @@ public slots:
void print(QString filename, QString mimeType, QString targetFormat, IppMsg job, PrintParameters Params, QMargins margins);
void print2(QString filename, QString mimeType, QString targetFormat, IppMsg createJob, IppMsg sendDocument, PrintParameters Params, QMargins margins);
private slots:
void cleanup();
signals:
void progress(qint64 done, qint64 pages);
void busyMessage(QString msg);
@ -60,13 +54,11 @@ private:
void convertImage(QString filename, Bytestream header, PrintParameters Params, QMargins margins);
void convertOfficeDocument(QString filename, Bytestream header, PrintParameters Params);
void convertPlaintext(QString filename, Bytestream header, PrintParameters Params);
void convertPlaintextLabel(QString filename, Bytestream header, PrintParameters Params);
void awaitResult(CurlRequester& cr, QString callback);
std::unique_ptr<QThread> _thread;
QPointer<IppPrinter> _printer;
QUrl _url;
IppPrinter* _printer;
};
#endif // PRINTERWORKER_H

View file

@ -1,47 +0,0 @@
#include "rangelistchecker.h"
RangeListChecker::RangeListChecker()
{
}
RangeListChecker::~RangeListChecker()
{
}
RangeListChecker* RangeListChecker::m_Instance = 0;
RangeListChecker* RangeListChecker::instance()
{
static QMutex mutex;
if (!m_Instance)
{
mutex.lock();
if (!m_Instance)
m_Instance = new RangeListChecker;
mutex.unlock();
}
return m_Instance;
}
QJsonArray RangeListChecker::parse(QString str) const
{
PrintParameters params;
params.setPageRange(str.toStdString());
QJsonArray ret;
size_t previous = 0;
for(const std::pair<size_t, size_t>& p : params.pageRangeList)
{
if(p.first <= previous)
{
return {};
}
ret.append(QJsonObject {{"low", int(p.first)}, {"high", int(p.second)}});
previous = p.second;
}
return ret;
}

View file

@ -1,29 +0,0 @@
#ifndef RANGELISTCHECKER_H
#define RANGELISTCHECKER_H
#include <QValidator>
#include <QMutex>
#include <QJsonArray>
#include <QJsonObject>
#include "printparameters.h"
class RangeListChecker : public QObject
{
Q_OBJECT
public:
static RangeListChecker* instance();
Q_INVOKABLE QJsonArray parse(QString str) const;
private:
static RangeListChecker* m_Instance;
RangeListChecker();
~RangeListChecker();
RangeListChecker(const RangeListChecker &);
RangeListChecker& operator=(const RangeListChecker &);
};
#endif // RANGELISTCHECKER_H

View file

@ -1,21 +0,0 @@
#include "seaprintdbusadaptor.h"
#include <QtQuick>
SeaPrintDBusAdaptor::SeaPrintDBusAdaptor(QQuickView *view)
: QDBusAbstractAdaptor(view)
, DBusAdaptorBase(view)
{
}
SeaPrintDBusAdaptor::~SeaPrintDBusAdaptor()
{
}
void SeaPrintDBusAdaptor::Open(const QString& fileName)
{
doOpen(fileName);
}
void SeaPrintDBusAdaptor::OpenPlaintext(const QString& fileContents, const QString& name)
{
doCreateFileAndOpen(fileContents, name);
}

View file

@ -1,21 +0,0 @@
#ifndef SEAPRINTDBUSADAPTOR_H
#define SEAPRINTDBUSADAPTOR_H
#include "dbusadaptorbase.h"
class SeaPrintDBusAdaptor : public QDBusAbstractAdaptor, public DBusAdaptorBase
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "net.attah.seaprint")
public:
SeaPrintDBusAdaptor(QQuickView *view);
~SeaPrintDBusAdaptor();
public Q_SLOTS:
Q_NOREPLY void Open(const QString& fileName);
Q_NOREPLY void OpenPlaintext(const QString& fileContents, const QString& name);
};
#endif // SEAPRINTDBUSADAPTOR_H

File diff suppressed because it is too large Load diff

View file

@ -276,6 +276,10 @@
<source>Not on WiFi</source>
<translation>No hay WiFi</translation>
</message>
<message>
<source>Unsupported document format</source>
<translation>Formato de documento no soportado</translation>
</message>
<message>
<source>This format may not render correctly</source>
<translation>Este formato puede no renderizarse correctamente</translation>
@ -515,14 +519,6 @@
<source>Print error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Inconsistent duplex setting</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Multiline label not supported</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>
@ -530,18 +526,6 @@
<source>all</source>
<translation>todos</translation>
</message>
<message>
<source>Advanced</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Low</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>High</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Setting</name>
@ -626,14 +610,6 @@
<source>SVGs</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported document format</source>
<translation>Formato de documento no soportado</translation>
</message>
<message>
<source>New file selected</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>strings</name>
@ -5192,6 +5168,10 @@
</context>
<context>
<name>utils</name>
<message>
<source></source>
<translation></translation>
</message>
<message>
<source>pending</source>
<translation type="unfinished"></translation>

View file

@ -276,6 +276,10 @@
<source>Not on WiFi</source>
<translation>Pas en WiFi</translation>
</message>
<message>
<source>Unsupported document format</source>
<translation>Format de document non supporté</translation>
</message>
<message>
<source>This format may not render correctly</source>
<translation>Ce format peut ne pas être rendu correctement</translation>
@ -502,7 +506,7 @@ sur cette imprimante</translation>
</message>
<message>
<source>Unknown target format</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Preparing</source>
@ -516,14 +520,6 @@ sur cette imprimante</translation>
<source>Print error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Inconsistent duplex setting</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Multiline label not supported</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>
@ -531,18 +527,6 @@ sur cette imprimante</translation>
<source>all</source>
<translation>tout</translation>
</message>
<message>
<source>Advanced</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Low</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>High</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Setting</name>
@ -627,14 +611,6 @@ sur cette imprimante</translation>
<source>SVGs</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported document format</source>
<translation>Format de document non supporté</translation>
</message>
<message>
<source>New file selected</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>strings</name>
@ -5193,6 +5169,10 @@ sur cette imprimante</translation>
</context>
<context>
<name>utils</name>
<message>
<source></source>
<translation></translation>
</message>
<message>
<source>pending</source>
<translation type="unfinished"></translation>

View file

@ -276,6 +276,10 @@
<source>Not on WiFi</source>
<translation>Niet met WiFi netwerk verbonden</translation>
</message>
<message>
<source>Unsupported document format</source>
<translation>Niet-ondersteunde documentindeling</translation>
</message>
<message>
<source>This format may not render correctly</source>
<translation>Dit formaat wordt mogelijk niet correct weergegeven</translation>
@ -515,14 +519,6 @@
<source>Print error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Inconsistent duplex setting</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Multiline label not supported</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>
@ -530,18 +526,6 @@
<source>all</source>
<translation>alles</translation>
</message>
<message>
<source>Advanced</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Low</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>High</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Setting</name>
@ -626,14 +610,6 @@
<source>SVGs</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported document format</source>
<translation>Niet-ondersteunde documentindeling</translation>
</message>
<message>
<source>New file selected</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>strings</name>
@ -5192,6 +5168,10 @@
</context>
<context>
<name>utils</name>
<message>
<source></source>
<translation></translation>
</message>
<message>
<source>pending</source>
<translation type="unfinished"></translation>

File diff suppressed because it is too large Load diff

View file

@ -276,6 +276,10 @@
<source>Not on WiFi</source>
<translation>WiFi</translation>
</message>
<message>
<source>Unsupported document format</source>
<translation></translation>
</message>
<message>
<source>This format may not render correctly</source>
<translation></translation>
@ -515,14 +519,6 @@
<source>Print error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Inconsistent duplex setting</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Multiline label not supported</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>
@ -530,18 +526,6 @@
<source>all</source>
<translation></translation>
</message>
<message>
<source>Advanced</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Low</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>High</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Setting</name>
@ -626,14 +610,6 @@
<source>SVGs</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported document format</source>
<translation></translation>
</message>
<message>
<source>New file selected</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>strings</name>
@ -5192,6 +5168,10 @@
</context>
<context>
<name>utils</name>
<message>
<source></source>
<translation></translation>
</message>
<message>
<source>pending</source>
<translation type="unfinished"></translation>

View file

@ -276,6 +276,10 @@
<source>Not on WiFi</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported document format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This format may not render correctly</source>
<translation type="unfinished"></translation>
@ -515,14 +519,6 @@
<source>Unknown target format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Inconsistent duplex setting</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Multiline label not supported</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RangeSetting</name>
@ -530,18 +526,6 @@
<source>all</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Advanced</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Low</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>High</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Setting</name>
@ -626,14 +610,6 @@
<source>plaintext</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported document format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New file selected</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>strings</name>