Compare commits
97 commits
1.0.4-rele
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
38975d1f64 | ||
|
53f458d71a | ||
|
f138f0b89d | ||
|
1d71f3477a | ||
|
2d0d61f3e5 | ||
|
1905cec933 | ||
|
912bc36dad | ||
|
317a864ff6 | ||
|
d473d23d55 | ||
|
29c5bbf62b | ||
|
e4038db1b0 | ||
|
fce00048ef | ||
|
62bcecccbe | ||
|
d3bc294f0a | ||
|
5d5e86dc6b | ||
|
3045244c71 | ||
|
3aad66c714 | ||
|
31bfd08fae | ||
|
6f4d602456 | ||
|
3d8ade0bef | ||
|
7a144471e3 | ||
|
5433d81764 | ||
|
a51061df7c | ||
|
741bdd7724 | ||
|
f9b740c94b | ||
|
371c06b430 | ||
|
38d5a95982 | ||
|
ac84fe079e | ||
|
53ca370f92 | ||
|
3abd1e103f | ||
|
8712ee6eea | ||
|
9287da53aa | ||
|
6a06fa5ffd | ||
|
b7aeb097a3 | ||
|
b70be18897 | ||
|
15cae28413 | ||
|
5f71f2dd64 | ||
|
51c90e6443 | ||
|
d037600d0f | ||
|
d094db4d89 | ||
|
515d3944e7 | ||
|
31cdaf0939 | ||
|
2cd0bb2812 | ||
|
445cc19b10 | ||
|
56395707fa | ||
|
aaae57b113 | ||
|
da923e3a32 | ||
|
071c39b6f3 | ||
|
04830863ab | ||
|
95ef563230 | ||
|
8ea54769c5 | ||
|
f6ec27b423 | ||
|
0874122bda | ||
|
813e1edb6a | ||
|
c30e7d3548 | ||
|
fb40a89858 | ||
|
64a7b0120f | ||
|
8c6344eef8 | ||
|
9ff8775fab | ||
|
6c7e09fdb5 | ||
|
1e6be94965 | ||
|
342a1a82f0 | ||
|
58619bd63a | ||
|
a7d181a867 | ||
|
18f0c66dba | ||
|
ab96dc547f | ||
|
6ba065b4b1 | ||
|
ba2a826b56 | ||
|
21b3819a86 | ||
|
08b66ed711 | ||
|
ff2eae04cf | ||
|
b4aaa85a2d | ||
|
f30f40683e | ||
|
f84d05e514 | ||
|
dd19333c81 | ||
|
b1cd524b4c | ||
|
0dd09a2707 | ||
|
6e2ded84e2 | ||
|
5799985c92 | ||
|
cecc038a6d | ||
|
993eb75cf7 | ||
|
ea39f0285b | ||
|
438628598f | ||
|
09ceb4f0ec | ||
|
e16bfbe7c6 | ||
|
ef3b53abdb | ||
|
bb6fa7926d | ||
|
40da0790e2 | ||
|
0312a367f4 | ||
|
71b2986a37 | ||
|
3be30e58e6 | ||
|
444cf09ae0 | ||
|
0efd96c072 | ||
|
d8267db9fe | ||
|
4537f32005 | ||
|
9ba3f2daf1 | ||
|
4f06a8e85e |
60 changed files with 37292 additions and 3714 deletions
19
README.md
19
README.md
|
@ -11,7 +11,7 @@ A minority of printers support only PCL and/or their own proprietary formats, th
|
||||||
|
|
||||||
## Format support
|
## Format support
|
||||||
|
|
||||||
For PDFs or plaintext, your printer needs to support one of the following formats:
|
For PDFs, your printer needs to support one of the following formats:
|
||||||
* PDF
|
* PDF
|
||||||
* Postscript
|
* Postscript
|
||||||
* PWG-raster
|
* PWG-raster
|
||||||
|
@ -19,6 +19,9 @@ For PDFs or plaintext, your printer needs to support one of the following format
|
||||||
|
|
||||||
For Postscript, your printer needs to support Postscript natively. (SeaPrint just sends it as-is)
|
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.
|
||||||
|
|
||||||
For printing "Office" files, like .doc(x) and odt, you need to install
|
For printing "Office" files, like .doc(x) and odt, you need to install
|
||||||
`calligraconverter` (from the `calligra` package in Sailfish OS 4.2 onwards).
|
`calligraconverter` (from the `calligra` package in Sailfish OS 4.2 onwards).
|
||||||
Then the printer support follows that of PDF.
|
Then the printer support follows that of PDF.
|
||||||
|
@ -31,8 +34,18 @@ For images, your printer needs to support one of the following formats:
|
||||||
* PDF
|
* PDF
|
||||||
* Postscript
|
* Postscript
|
||||||
|
|
||||||
For printing JPEG images, transferring the unaltered image has priority and the printer does the scaling.
|
When printing images the result may depend on how they are transferred.
|
||||||
Other image formats are lossless and SeaPrint does scale-and-rotate to fit, so JPEG has lowest prio there.
|
If a document-oriented format like PDF/Postscript/PWG/URF is used SeaPrint does scale-and-rotate to fit, otherwise (when transferred as PNG or JPEG) that is left up to the printer. Only when printing images *as images* can the scaling setting be used.
|
||||||
|
|
||||||
|
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:
|
Printers with any of these IPP certifications and derivative standards should likely be supported:
|
||||||
|
|
||||||
|
|
27
doc/pipeline.goat
Normal file
27
doc/pipeline.goat
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
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)
|
444
doc/pipeline.svg
Normal file
444
doc/pipeline.svg
Normal file
|
@ -0,0 +1,444 @@
|
||||||
|
<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>
|
After Width: | Height: | Size: 20 KiB |
|
@ -3,9 +3,10 @@ Type=Application
|
||||||
Icon=harbour-seaprint
|
Icon=harbour-seaprint
|
||||||
X-Nemo-Application-Type=silica-qt5
|
X-Nemo-Application-Type=silica-qt5
|
||||||
Exec=harbour-seaprint
|
Exec=harbour-seaprint
|
||||||
|
X-DBusActivatable=true
|
||||||
Name=SeaPrint
|
Name=SeaPrint
|
||||||
[X-Sailjail]
|
[X-Sailjail]
|
||||||
Permissions=Internet;Pictures;Documents;Downloads;MediaIndexing;Compatibility
|
Permissions=Internet;Pictures;Documents;Downloads;RemovableMedia;MediaIndexing;Compatibility
|
||||||
OrganizationName=net.attah
|
OrganizationName=net.attah
|
||||||
ApplicationName=seaprint
|
ApplicationName=seaprint
|
||||||
|
ExecDBus=harbour-seaprint --prestart
|
||||||
|
|
|
@ -26,30 +26,36 @@ INSTALLS += i18n
|
||||||
system(lrelease $$PWD/translations/*.ts)
|
system(lrelease $$PWD/translations/*.ts)
|
||||||
|
|
||||||
CONFIG += sailfishapp
|
CONFIG += sailfishapp
|
||||||
QT += svg
|
QT += svg dbus
|
||||||
PKGCONFIG += mlite5 libcurl poppler glib-2.0 cairo
|
PKGCONFIG += mlite5 libcurl glib-2.0
|
||||||
|
INCLUDEPATH += $$system(pkg-config --cflags-only-I poppler-glib | sed 's/-I//g')
|
||||||
LIBS += -lcurl -lglib-2.0 -lgobject-2.0 -ldl
|
LIBS += -lcurl -lglib-2.0 -lgobject-2.0 -ldl
|
||||||
DEFINES += MADNESS=1
|
DEFINES += MADNESS=1
|
||||||
DEFINES += PDF_CREATOR='\\"SeaPrint\ $$VERSION\\"'
|
DEFINES += PDF_CREATOR='\\"SeaPrint\ $$VERSION\\"'
|
||||||
DEFINES += SEAPRINT_VERSION='\\"$$VERSION\\"'
|
DEFINES += SEAPRINT_VERSION='\\"$$VERSION\\"'
|
||||||
|
|
||||||
SOURCES += src/harbour-seaprint.cpp \
|
SOURCES += src/harbour-seaprint.cpp \
|
||||||
|
src/dbusadaptorbase.cpp \
|
||||||
|
src/freedesktopdbusadaptor.cpp \
|
||||||
|
src/rangelistchecker.cpp \
|
||||||
src/convertchecker.cpp \
|
src/convertchecker.cpp \
|
||||||
src/curlrequester.cpp \
|
src/curlrequester.cpp \
|
||||||
|
src/imageitem.cpp \
|
||||||
src/ippdiscovery.cpp \
|
src/ippdiscovery.cpp \
|
||||||
src/ippmsg.cpp \
|
src/ippmsg.cpp \
|
||||||
src/ippprinter.cpp \
|
src/ippprinter.cpp \
|
||||||
src/mimer.cpp \
|
src/mimer.cpp \
|
||||||
|
ppm2pwg/printparameters.cpp \
|
||||||
ppm2pwg/ppm2pwg.cpp \
|
ppm2pwg/ppm2pwg.cpp \
|
||||||
ppm2pwg/pdf2printable.cpp \
|
ppm2pwg/pdf2printable.cpp \
|
||||||
|
ppm2pwg/baselinify.cpp \
|
||||||
ppm2pwg/bytestream/bytestream.cpp \
|
ppm2pwg/bytestream/bytestream.cpp \
|
||||||
src/overrider.cpp \
|
src/overrider.cpp \
|
||||||
src/printerworker.cpp \
|
src/printerworker.cpp \
|
||||||
src/settings.cpp \
|
src/seaprintdbusadaptor.cpp \
|
||||||
src/svgprovider.cpp
|
src/settings.cpp
|
||||||
|
|
||||||
DISTFILES += qml/harbour-seaprint.qml \
|
DISTFILES += qml/harbour-seaprint.qml \
|
||||||
qml/components/DependentOn.qml \
|
|
||||||
qml/cover/CoverPage.qml \
|
qml/cover/CoverPage.qml \
|
||||||
qml/components/*qml \
|
qml/components/*qml \
|
||||||
qml/pages/*.qml \
|
qml/pages/*.qml \
|
||||||
|
@ -80,26 +86,33 @@ TRANSLATIONS += translations/harbour-seaprint-de.ts \
|
||||||
translations/harbour-seaprint-pl.ts
|
translations/harbour-seaprint-pl.ts
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
src/dbusadaptorbase.h \
|
||||||
|
src/freedesktopdbusadaptor.h \
|
||||||
|
src/rangelistchecker.h \
|
||||||
src/convertchecker.h \
|
src/convertchecker.h \
|
||||||
src/curlrequester.h \
|
src/curlrequester.h \
|
||||||
|
src/imageitem.h \
|
||||||
src/ippdiscovery.h \
|
src/ippdiscovery.h \
|
||||||
src/ippmsg.h \
|
src/ippmsg.h \
|
||||||
src/ippprinter.h \
|
src/ippprinter.h \
|
||||||
src/mimer.h \
|
src/mimer.h \
|
||||||
ppm2pwg/ppm2pwg.h \
|
ppm2pwg/ppm2pwg.h \
|
||||||
ppm2pwg/pdf2printable.h \
|
ppm2pwg/pdf2printable.h \
|
||||||
|
ppm2pwg/baselinify.h \
|
||||||
ppm2pwg/madness.h \
|
ppm2pwg/madness.h \
|
||||||
|
ppm2pwg/printparameters.h \
|
||||||
ppm2pwg/PwgPgHdr.h \
|
ppm2pwg/PwgPgHdr.h \
|
||||||
ppm2pwg/PwgPgHdr.codable \
|
ppm2pwg/PwgPgHdr.codable \
|
||||||
ppm2pwg/UrfPgHdr.h \
|
ppm2pwg/UrfPgHdr.h \
|
||||||
ppm2pwg/UrfPgHdr.codable \
|
ppm2pwg/UrfPgHdr.codable \
|
||||||
ppm2pwg/bytestream/bytestream.h \
|
ppm2pwg/bytestream/bytestream.h \
|
||||||
ppm2pwg/bytestream/codable.h \
|
ppm2pwg/bytestream/codable.h \
|
||||||
|
ppm2pwg/argget.h \
|
||||||
src/overrider.h \
|
src/overrider.h \
|
||||||
src/papersizes.h \
|
src/papersizes.h \
|
||||||
src/printerworker.h \
|
src/printerworker.h \
|
||||||
src/settings.h \
|
src/seaprintdbusadaptor.h \
|
||||||
src/svgprovider.h
|
src/settings.h
|
||||||
|
|
||||||
INCLUDEPATH += ppm2pwg \
|
INCLUDEPATH += ppm2pwg \
|
||||||
ppm2pwg/bytestream
|
ppm2pwg/bytestream
|
||||||
|
|
2
ppm2pwg
2
ppm2pwg
|
@ -1 +1 @@
|
||||||
Subproject commit 9cb1d1524c1779edff6f6ac7eae6c1b43507164b
|
Subproject commit acc32f3769c3b18bd6b94c55b882c7b7b778854c
|
|
@ -7,14 +7,18 @@ Setting {
|
||||||
property var preferred_choices: []
|
property var preferred_choices: []
|
||||||
property string preferred_choice_suffix: ""
|
property string preferred_choice_suffix: ""
|
||||||
|
|
||||||
property var actual_choices: Utils.fixupChoices(name, choices, parent.selectedFileType)
|
property var actual_choices: Utils.fixupChoices(name, choices, parent.selectedFileType, parent.printer)
|
||||||
|
|
||||||
property int num_large_choices: 8
|
property int num_large_choices: 8
|
||||||
|
|
||||||
displayValue: Utils.ippName(name, choice != undefined ? choice : default_choice, strings)
|
displayValue: Utils.ippName(name, choice != undefined ? choice : default_choice, strings)
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if(actual_choices.length>num_large_choices)
|
if(hasMenu)
|
||||||
|
{
|
||||||
|
menu.open(this)
|
||||||
|
}
|
||||||
|
else if(actual_choices.length != 0)
|
||||||
{
|
{
|
||||||
var dialog = pageStack.push("LargeChoiceDialog.qml",
|
var dialog = pageStack.push("LargeChoiceDialog.qml",
|
||||||
{name:name, choice: choice != undefined ? choice : default_choice, choices: actual_choices,
|
{name:name, choice: choice != undefined ? choice : default_choice, choices: actual_choices,
|
||||||
|
@ -24,10 +28,6 @@ Setting {
|
||||||
choice = dialog.choice
|
choice = dialog.choice
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
menu.open(this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menu: ContextMenu {
|
menu: ContextMenu {
|
||||||
|
@ -45,7 +45,5 @@ Setting {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasMenu: !actual_choices.length>num_large_choices
|
hasMenu: actual_choices.length != 0 && (actual_choices.length <= num_large_choices)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,9 @@ Dialog {
|
||||||
id: valueField
|
id: valueField
|
||||||
validator: IntValidator{bottom: min; top: max;}
|
validator: IntValidator{bottom: min; top: max;}
|
||||||
width: parent.width
|
width: parent.width
|
||||||
placeholderText: ""+min+"-"+max
|
placeholderText: ""+min+"-"+(max == 65535 ? "..." : max)
|
||||||
label: title
|
label: title
|
||||||
focus: true
|
focus: true
|
||||||
labelVisible: true
|
|
||||||
inputMethodHints: Qt.ImhDigitsOnly
|
inputMethodHints: Qt.ImhDigitsOnly
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,21 @@ import QtQuick 2.6
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
|
|
||||||
Setting {
|
Setting {
|
||||||
property int low: valid ? parent.printer.attrs[name+"-supported"].value.low : 0
|
property int minimum_high: 0
|
||||||
property int high: valid ? parent.printer.attrs[name+"-supported"].value.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 bool suppressChange: false
|
property bool suppressChange: false
|
||||||
|
|
||||||
|
@ -40,7 +53,7 @@ Setting {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
icon.source: "image://theme/icon-s-edit"
|
icon.source: "image://theme/icon-s-edit"
|
||||||
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
|
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
|
||||||
{value: choice, title: prettyName,
|
{title: prettyName,
|
||||||
min: low, max: high});
|
min: low, max: high});
|
||||||
dialog.accepted.connect(function() {
|
dialog.accepted.connect(function() {
|
||||||
choice = dialog.value;
|
choice = dialog.value;
|
||||||
|
|
30
qml/components/RangeListInputDialog.qml
Normal file
30
qml/components/RangeListInputDialog.qml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ Setting {
|
||||||
property int high
|
property int high
|
||||||
property int choice_low: 1
|
property int choice_low: 1
|
||||||
property int choice_high: 0
|
property int choice_high: 0
|
||||||
|
property bool acceptRangeList: false
|
||||||
|
|
||||||
property bool suppressChange: false
|
property bool suppressChange: false
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ Setting {
|
||||||
}
|
}
|
||||||
|
|
||||||
onChoiceChanged: {
|
onChoiceChanged: {
|
||||||
if(choice == undefined)
|
if(choice == undefined || choice.constructor.name !== "Object")
|
||||||
{
|
{
|
||||||
suppressChange = true;
|
suppressChange = true;
|
||||||
low_slider.value = low_slider.minimumValue;
|
low_slider.value = low_slider.minimumValue;
|
||||||
|
@ -50,7 +51,39 @@ Setting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
displayValue: choice == undefined ? qsTr("all") : ""+choice.low+" - "+choice.high
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
menu: ContextMenu {
|
menu: ContextMenu {
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
@ -71,7 +104,7 @@ Setting {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
icon.source: "image://theme/icon-s-edit"
|
icon.source: "image://theme/icon-s-edit"
|
||||||
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
|
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
|
||||||
{value: choice, title: prettyName,
|
{title: prettyName + " (" + qsTr("Low") + ")",
|
||||||
min: 1, max: high});
|
min: 1, max: high});
|
||||||
dialog.accepted.connect(function() {
|
dialog.accepted.connect(function() {
|
||||||
choice_low = dialog.value;
|
choice_low = dialog.value;
|
||||||
|
@ -99,7 +132,7 @@ Setting {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
icon.source: "image://theme/icon-s-edit"
|
icon.source: "image://theme/icon-s-edit"
|
||||||
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
|
onClicked: {var dialog = pageStack.push(Qt.resolvedUrl("IntegerInputDialog.qml"),
|
||||||
{value: choice, title: prettyName,
|
{title: prettyName + " (" + qsTr("High") + ")",
|
||||||
min: 1, max: high});
|
min: 1, max: high});
|
||||||
dialog.accepted.connect(function() {
|
dialog.accepted.connect(function() {
|
||||||
choice_high = dialog.value;
|
choice_high = dialog.value;
|
||||||
|
@ -109,6 +142,17 @@ 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;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import "../components"
|
||||||
property int low_level: 10
|
property int low_level: 10
|
||||||
property string name: ""
|
property string name: ""
|
||||||
property string type: ""
|
property string type: ""
|
||||||
|
property real value_fraction: level/(high_level == 0 ? 100 : high_level)
|
||||||
|
|
||||||
spacing: Theme.paddingMedium
|
spacing: Theme.paddingMedium
|
||||||
bottomPadding: Theme.paddingMedium
|
bottomPadding: Theme.paddingMedium
|
||||||
|
@ -19,13 +20,13 @@ import "../components"
|
||||||
{
|
{
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
color: parent.color
|
color: parent.color
|
||||||
value: (level/high_level)
|
value: value_fraction
|
||||||
}
|
}
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
width: Theme.itemSizeExtraSmall
|
width: Theme.itemSizeExtraSmall
|
||||||
text: ""+(100*level/high_level)+"%"
|
text: ""+Math.round(100*value_fraction)+"%"
|
||||||
color: level <= low_level ? "red" : Theme.highlightColor
|
color: level <= low_level ? "red" : Theme.highlightColor
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,37 @@ ApplicationWindow
|
||||||
{
|
{
|
||||||
id: appWin
|
id: appWin
|
||||||
|
|
||||||
|
property Page _mainPage
|
||||||
|
|
||||||
property bool expectCalligra: true
|
property bool expectCalligra: true
|
||||||
|
|
||||||
initialPage: Component { FirstPage { selectedFile: Qt.application.arguments[1] ? Qt.application.arguments[1] : "" } }
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: Orientation.All
|
||||||
|
|
||||||
|
@ -75,10 +103,18 @@ ApplicationWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
function simplifyType(mimetype) {
|
function simplifyType(mimetype) {
|
||||||
if(Mimer.isImage(mimetype))
|
if(mimetype == Mimer.SVG)
|
||||||
|
{
|
||||||
|
return {simple: "svg", translatable: qsTr("SVGs")};
|
||||||
|
}
|
||||||
|
else if(Mimer.isImage(mimetype))
|
||||||
{
|
{
|
||||||
return {simple: "image", translatable: qsTr("images")};
|
return {simple: "image", translatable: qsTr("images")};
|
||||||
}
|
}
|
||||||
|
else if(mimetype == Mimer.Plaintext)
|
||||||
|
{
|
||||||
|
return {simple: "plaintext", translatable: qsTr("plaintext")};
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return {simple: "document", translatable: qsTr("documents")};
|
return {simple: "document", translatable: qsTr("documents")};
|
||||||
|
@ -156,5 +192,12 @@ ApplicationWindow
|
||||||
defaultValue: SeaPrintSettings.debugLogDefault
|
defaultValue: SeaPrintSettings.debugLogDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConfigurationValue
|
||||||
|
{
|
||||||
|
id: allowExternalConnectionsSetting
|
||||||
|
key: SeaPrintSettings.allowExternalConnectionsPath
|
||||||
|
defaultValue: SeaPrintSettings.allowExternalConnectionsDefault
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ Page {
|
||||||
AboutLabel {
|
AboutLabel {
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.primaryColor
|
color: Theme.primaryColor
|
||||||
text: "© 2019-2022 Anton Thomasson et al."
|
text: "© 2019-2023 Anton Thomasson et al."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,9 +99,9 @@ Page {
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
text: qsTr("Chinese")+" - dashinfantry\n"+
|
text: qsTr("Chinese")+" - dashinfantry\n"+
|
||||||
qsTr("Dutch")+" - JSEHV, Rudi Timmermans\n"+
|
qsTr("Dutch")+" - JSEHV, Rudi Timmermans\n"+
|
||||||
qsTr("French")+" - ensag-dev, phklrz, Quentí\n"+
|
qsTr("French")+" - ensag-dev, pherjung, phklrz, Quentí\n"+
|
||||||
qsTr("German")+" - black-sheep-dev, cnlpete, wheelseal\n"+
|
qsTr("German")+" - black-sheep-dev, cnlpete, wheelseal\n"+
|
||||||
qsTr("Polish")+" - atlochowski\n"+
|
qsTr("Polish")+" - atlochowski, karolkurek\n"+
|
||||||
qsTr("Spanish")+" - carmenfdezb, JSEHV"
|
qsTr("Spanish")+" - carmenfdezb, JSEHV"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ import Sailfish.Silica 1.0
|
||||||
import "utils.js" as Utils
|
import "utils.js" as Utils
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
|
property bool busyPage: true
|
||||||
|
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: Orientation.All
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
|
|
@ -12,6 +12,18 @@ Page {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
contentHeight: col.height
|
contentHeight: col.height
|
||||||
|
|
||||||
|
PullDownMenu {
|
||||||
|
visible: identifyLabel.visible
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
id: identifyLabel
|
||||||
|
text: qsTr("Identify printer")
|
||||||
|
visible: printer.attrs.hasOwnProperty("identify-actions-supported")
|
||||||
|
onClicked: printer.identify()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Sailfish.Pickers 1.0
|
||||||
import seaprint.ippdiscovery 1.0
|
import seaprint.ippdiscovery 1.0
|
||||||
import seaprint.convertchecker 1.0
|
import seaprint.convertchecker 1.0
|
||||||
import seaprint.ippprinter 1.0
|
import seaprint.ippprinter 1.0
|
||||||
|
import seaprint.imageitem 1.0
|
||||||
import seaprint.mimer 1.0
|
import seaprint.mimer 1.0
|
||||||
import "utils.js" as Utils
|
import "utils.js" as Utils
|
||||||
|
|
||||||
|
@ -11,9 +12,6 @@ Page {
|
||||||
id: page
|
id: page
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: Orientation.All
|
||||||
|
|
||||||
property string selectedFile: ""
|
|
||||||
property string selectedFileType
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: wifi
|
target: wifi
|
||||||
onConnectedChanged: {
|
onConnectedChanged: {
|
||||||
|
@ -59,11 +57,6 @@ Page {
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
IppDiscovery.discover();
|
IppDiscovery.discover();
|
||||||
if(selectedFile != "")
|
|
||||||
{
|
|
||||||
var type = Mimer.get_type(selectedFile);
|
|
||||||
selectedFileType = type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool nagged: false
|
property bool nagged: false
|
||||||
|
@ -142,7 +135,7 @@ Page {
|
||||||
|
|
||||||
property string name: Utils.unknownForEmptyString(printer.attrs["printer-name"].value)
|
property string name: Utils.unknownForEmptyString(printer.attrs["printer-name"].value)
|
||||||
property var supported_formats: Utils.supported_formats(printer, considerAdditionalFormatsSetting.value)
|
property var supported_formats: Utils.supported_formats(printer, considerAdditionalFormatsSetting.value)
|
||||||
property bool canPrint: supported_formats.mimetypes.indexOf(selectedFileType) != -1
|
property bool canPrint: supported_formats.mimetypes.indexOf(appWin.selectedFileType) != -1
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: printer
|
target: printer
|
||||||
|
@ -181,7 +174,7 @@ Page {
|
||||||
{
|
{
|
||||||
if(printer.attrs.hasOwnProperty("printer-uuid"))
|
if(printer.attrs.hasOwnProperty("printer-uuid"))
|
||||||
{
|
{
|
||||||
return JSON.parse(db.getJobSettings(printer.attrs["printer-uuid"].value, selectedFileType));
|
return JSON.parse(db.getJobSettings(printer.attrs["printer-uuid"].value, appWin.selectedFileType));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -198,7 +191,7 @@ Page {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debugCountReset.restart();
|
debugCountReset.restart();
|
||||||
if(selectedFile == "")
|
if(appWin.selectedFile == "")
|
||||||
{
|
{
|
||||||
noFileSelected();
|
noFileSelected();
|
||||||
}
|
}
|
||||||
|
@ -208,11 +201,11 @@ Page {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pageStack.push(Qt.resolvedUrl("PrinterPage.qml"), {printer: printer, selectedFile: selectedFile, jobParams: maybeGetParams()})
|
pageStack.push(Qt.resolvedUrl("PrinterPage.qml"), {printer: printer, selectedFile: appWin.selectedFile, jobParams: maybeGetParams()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
ImageItem {
|
||||||
id: icon
|
id: icon
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -221,13 +214,17 @@ Page {
|
||||||
|
|
||||||
height: Theme.itemSizeLarge
|
height: Theme.itemSizeLarge
|
||||||
width: Theme.itemSizeLarge
|
width: Theme.itemSizeLarge
|
||||||
|
image: printer.icon
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: placeholder
|
||||||
|
anchors.fill: parent
|
||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
source: printer.attrs["printer-icons"] ? "image://ippdiscovery/"+Utils.selectIcon(printer.attrs["printer-icons"].value)
|
|
||||||
: "image://svg/qml/pages/icon-seaprint-nobg.svg"
|
|
||||||
// Some printers serve their icons over https with invalid certs...
|
|
||||||
onStatusChanged: if (status == Image.Error) source = "image://svg/qml/pages/icon-seaprint-nobg.svg"
|
|
||||||
|
|
||||||
|
visible: !parent.valid
|
||||||
|
source: "icon-seaprint-nobg.svg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
@ -245,13 +242,13 @@ Page {
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: name_label
|
id: name_label
|
||||||
color: canPrint || selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
|
color: canPrint || appWin.selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
|
||||||
text: name
|
text: name
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: mm_label
|
id: mm_label
|
||||||
color: canPrint || selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
|
color: canPrint || appWin.selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||||||
text: Utils.unknownForEmptyString(printer.attrs["printer-make-and-model"].value)
|
text: Utils.unknownForEmptyString(printer.attrs["printer-make-and-model"].value)
|
||||||
+ (Utils.existsAndNotEmpty("printer-location", printer) ? " • "+printer.attrs["printer-location"].value : "")
|
+ (Utils.existsAndNotEmpty("printer-location", printer) ? " • "+printer.attrs["printer-location"].value : "")
|
||||||
|
@ -259,7 +256,7 @@ Page {
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: uri_label
|
id: uri_label
|
||||||
color: canPrint || selectedFile == "" ? Theme.highlightColor : Theme.secondaryColor
|
color: canPrint || appWin.selectedFile == "" ? Theme.highlightColor : Theme.secondaryColor
|
||||||
font.pixelSize: Theme.fontSizeTiny
|
font.pixelSize: Theme.fontSizeTiny
|
||||||
text: printer.url
|
text: printer.url
|
||||||
}
|
}
|
||||||
|
@ -280,7 +277,7 @@ Page {
|
||||||
width: Theme.itemSizeExtraSmall/2
|
width: Theme.itemSizeExtraSmall/2
|
||||||
visible: supported_formats.pdf
|
visible: supported_formats.pdf
|
||||||
highlightColor: "red"
|
highlightColor: "red"
|
||||||
highlighted: !(selectedFile == "" || canPrint)
|
highlighted: !(appWin.selectedFile == "" || canPrint)
|
||||||
source: "image://theme/icon-m-file-pdf"
|
source: "image://theme/icon-m-file-pdf"
|
||||||
}
|
}
|
||||||
HighlightImage {
|
HighlightImage {
|
||||||
|
@ -288,7 +285,7 @@ Page {
|
||||||
width: Theme.itemSizeExtraSmall/2
|
width: Theme.itemSizeExtraSmall/2
|
||||||
visible: supported_formats.postscript
|
visible: supported_formats.postscript
|
||||||
highlightColor: "red"
|
highlightColor: "red"
|
||||||
highlighted: !(selectedFile == "" || canPrint)
|
highlighted: !(appWin.selectedFile == "" || canPrint)
|
||||||
source: "image://theme/icon-m-file-other"
|
source: "image://theme/icon-m-file-other"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -297,7 +294,7 @@ Page {
|
||||||
width: Theme.itemSizeExtraSmall/2
|
width: Theme.itemSizeExtraSmall/2
|
||||||
visible: supported_formats.plaintext
|
visible: supported_formats.plaintext
|
||||||
highlightColor: "red"
|
highlightColor: "red"
|
||||||
highlighted: !(selectedFile == "" || canPrint)
|
highlighted: !(appWin.selectedFile == "" || canPrint)
|
||||||
source: "image://theme/icon-m-file-document"
|
source: "image://theme/icon-m-file-document"
|
||||||
}
|
}
|
||||||
HighlightImage {
|
HighlightImage {
|
||||||
|
@ -305,7 +302,7 @@ Page {
|
||||||
width: Theme.itemSizeExtraSmall/2
|
width: Theme.itemSizeExtraSmall/2
|
||||||
visible: supported_formats.office
|
visible: supported_formats.office
|
||||||
highlightColor: "red"
|
highlightColor: "red"
|
||||||
highlighted: !(selectedFile == "" || canPrint)
|
highlighted: !(appWin.selectedFile == "" || canPrint)
|
||||||
source: "image://theme/icon-m-file-formatted"
|
source: "image://theme/icon-m-file-formatted"
|
||||||
}
|
}
|
||||||
HighlightImage {
|
HighlightImage {
|
||||||
|
@ -313,7 +310,7 @@ Page {
|
||||||
width: Theme.itemSizeExtraSmall/2
|
width: Theme.itemSizeExtraSmall/2
|
||||||
visible: supported_formats.office
|
visible: supported_formats.office
|
||||||
highlightColor: "red"
|
highlightColor: "red"
|
||||||
highlighted: !(selectedFile == "" || canPrint)
|
highlighted: !(appWin.selectedFile == "" || canPrint)
|
||||||
source: "image://theme/icon-m-file-presentation"
|
source: "image://theme/icon-m-file-presentation"
|
||||||
}
|
}
|
||||||
HighlightImage {
|
HighlightImage {
|
||||||
|
@ -321,7 +318,7 @@ Page {
|
||||||
width: Theme.itemSizeExtraSmall/2
|
width: Theme.itemSizeExtraSmall/2
|
||||||
visible: supported_formats.images
|
visible: supported_formats.images
|
||||||
highlightColor: "red"
|
highlightColor: "red"
|
||||||
highlighted: !(selectedFile == "" || canPrint)
|
highlighted: !(appWin.selectedFile == "" || canPrint)
|
||||||
source: "image://theme/icon-m-file-image"
|
source: "image://theme/icon-m-file-image"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,12 +352,16 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DockedPanel {
|
Rectangle {
|
||||||
id: fileDock
|
id: fileDock
|
||||||
open: true
|
|
||||||
height: panelColumn.implicitHeight
|
height: panelColumn.implicitHeight
|
||||||
width: parent.width
|
width: parent.width
|
||||||
dock: Dock.Bottom
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop { position: 0.0; color: Theme.rgba(Theme.highlightBackgroundColor, 0.15) }
|
||||||
|
GradientStop { position: 1.0; color: Theme.rgba(Theme.highlightBackgroundColor, 0.3) }
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: panelColumn
|
id: panelColumn
|
||||||
|
@ -372,7 +373,7 @@ Page {
|
||||||
Row {
|
Row {
|
||||||
id: warningRow
|
id: warningRow
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
visible: Mimer.isOffice(page.selectedFileType)
|
visible: Mimer.isOffice(appWin.selectedFileType)
|
||||||
|
|
||||||
HighlightImage {
|
HighlightImage {
|
||||||
source: "image://theme/icon-s-warning"
|
source: "image://theme/icon-s-warning"
|
||||||
|
@ -395,7 +396,7 @@ Page {
|
||||||
|
|
||||||
horizontalAlignment: contentWidth > width ? Text.AlignRight : Text.AlignHCenter
|
horizontalAlignment: contentWidth > width ? Text.AlignRight : Text.AlignHCenter
|
||||||
truncationMode: TruncationMode.Fade
|
truncationMode: TruncationMode.Fade
|
||||||
text: selectedFile != "" ? selectedFile : qsTr("No file selected")
|
text: appWin.selectedFile != "" ? appWin.selectedFile : qsTr("No file selected")
|
||||||
|
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
id: noFileSelectedAnimation
|
id: noFileSelectedAnimation
|
||||||
|
@ -448,18 +449,7 @@ Page {
|
||||||
title: qsTr("Choose file")
|
title: qsTr("Choose file")
|
||||||
|
|
||||||
onSelectedContentPropertiesChanged: {
|
onSelectedContentPropertiesChanged: {
|
||||||
var mimeType = Mimer.get_type(selectedContentProperties.filePath)
|
appWin.openFile(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 = ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,8 +459,7 @@ Page {
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: Orientation.All
|
||||||
|
|
||||||
onSelectedContentPropertiesChanged: {
|
onSelectedContentPropertiesChanged: {
|
||||||
page.selectedFile = selectedContentProperties.filePath
|
appWin.openFile(selectedContentProperties.filePath);
|
||||||
page.selectedFileType = Mimer.get_type(selectedContentProperties.filePath)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ Page {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
text: qsTr("Install calligra:") + " " + (ConvertChecker.calligra ? qsTr("(done)") : "")
|
text: qsTr("Install Calligra:") + " " + (ConvertChecker.calligra ? qsTr("(done)") : "")
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
@ -78,6 +78,16 @@ Page {
|
||||||
Clipper {}
|
Clipper {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
visible: appWin.expectCalligra
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
|
text: qsTr("If you are still seeing this message despite installing Calligra, that can be because of SailJail "+
|
||||||
|
"in Sailfish OS 4.x before the compatibility permission in 4.4. " +
|
||||||
|
"You can either upgrade to 4.4 or edit out the SailJail section in /usr/share/applications/harbour-seaprint.desktop")
|
||||||
|
}
|
||||||
|
|
||||||
Item{
|
Item{
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: Theme.itemSizeMedium
|
height: Theme.itemSizeMedium
|
||||||
|
|
|
@ -104,6 +104,8 @@ Page {
|
||||||
tag: IppMsg.Integer
|
tag: IppMsg.Integer
|
||||||
name: "copies"
|
name: "copies"
|
||||||
prettyName: qsTr("Copies")
|
prettyName: qsTr("Copies")
|
||||||
|
valid: _valid || Utils.supports_raster(printer)
|
||||||
|
minimum_high: 99
|
||||||
}
|
}
|
||||||
ChoiceSetting {
|
ChoiceSetting {
|
||||||
tag: IppMsg.Keyword
|
tag: IppMsg.Keyword
|
||||||
|
@ -118,6 +120,7 @@ Page {
|
||||||
|
|
||||||
property var pdfpages: ConvertChecker.pdfPages(selectedFile)
|
property var pdfpages: ConvertChecker.pdfPages(selectedFile)
|
||||||
high: pdfpages == 0 ? 65535 : pdfpages
|
high: pdfpages == 0 ? 65535 : pdfpages
|
||||||
|
acceptRangeList: true
|
||||||
}
|
}
|
||||||
ChoiceSetting {
|
ChoiceSetting {
|
||||||
tag: IppMsg.Integer
|
tag: IppMsg.Integer
|
||||||
|
@ -148,10 +151,10 @@ Page {
|
||||||
tag: IppMsg.Keyword
|
tag: IppMsg.Keyword
|
||||||
name: "print-scaling"
|
name: "print-scaling"
|
||||||
prettyName: qsTr("Scaling")
|
prettyName: qsTr("Scaling")
|
||||||
valid: _valid && selectedFileType == Mimer.JPEG
|
valid: _valid && Mimer.isImage(selectedFileType) && selectedFileType != Mimer.SVG
|
||||||
DependentOn {
|
DependentOn {
|
||||||
target: transferFormatSetting
|
target: transferFormatSetting
|
||||||
values: [Mimer.JPEG]
|
values: [Mimer.JPEG, Mimer.PNG]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChoiceSetting {
|
ChoiceSetting {
|
||||||
|
@ -196,6 +199,7 @@ Page {
|
||||||
name: "media-top-margin"
|
name: "media-top-margin"
|
||||||
subkey: "media-col"
|
subkey: "media-col"
|
||||||
prettyName: qsTr("Top")
|
prettyName: qsTr("Top")
|
||||||
|
valid: _valid && Mimer.isImage(selectedFileType)
|
||||||
}
|
}
|
||||||
ChoiceSetting {
|
ChoiceSetting {
|
||||||
visible: marginsButton.active
|
visible: marginsButton.active
|
||||||
|
@ -203,6 +207,7 @@ Page {
|
||||||
name: "media-bottom-margin"
|
name: "media-bottom-margin"
|
||||||
subkey: "media-col"
|
subkey: "media-col"
|
||||||
prettyName: qsTr("Bottom")
|
prettyName: qsTr("Bottom")
|
||||||
|
valid: _valid && Mimer.isImage(selectedFileType)
|
||||||
}
|
}
|
||||||
ChoiceSetting {
|
ChoiceSetting {
|
||||||
visible: marginsButton.active
|
visible: marginsButton.active
|
||||||
|
@ -210,6 +215,7 @@ Page {
|
||||||
name: "media-left-margin"
|
name: "media-left-margin"
|
||||||
subkey: "media-col"
|
subkey: "media-col"
|
||||||
prettyName: qsTr("Left")
|
prettyName: qsTr("Left")
|
||||||
|
valid: _valid && Mimer.isImage(selectedFileType)
|
||||||
}
|
}
|
||||||
ChoiceSetting {
|
ChoiceSetting {
|
||||||
visible: marginsButton.active
|
visible: marginsButton.active
|
||||||
|
@ -217,6 +223,7 @@ Page {
|
||||||
name: "media-right-margin"
|
name: "media-right-margin"
|
||||||
subkey: "media-col"
|
subkey: "media-col"
|
||||||
prettyName: qsTr("Right")
|
prettyName: qsTr("Right")
|
||||||
|
valid: _valid && Mimer.isImage(selectedFileType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,14 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextSwitch {
|
||||||
|
text: qsTr("Allow external connections")
|
||||||
|
description: qsTr("Allow SeaPrint to fetch recources like icons and option name dictionaries from addresses that are not the printer itself. Some printer makers store icons on their website as opposed to locally on the printer.")
|
||||||
|
checked: allowExternalConnectionsSetting.value
|
||||||
|
onCheckedChanged: {
|
||||||
|
allowExternalConnectionsSetting.value = checked
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1148
qml/pages/strings.js
Normal file
1148
qml/pages/strings.js
Normal file
File diff suppressed because it is too large
Load diff
1276
qml/pages/utils.js
1276
qml/pages/utils.js
File diff suppressed because it is too large
Load diff
|
@ -4,15 +4,14 @@ Summary: SeaPrint
|
||||||
Version: 0
|
Version: 0
|
||||||
Release: 1
|
Release: 1
|
||||||
Group: Qt/Qt
|
Group: Qt/Qt
|
||||||
License: LICENSE
|
License: GPLv3
|
||||||
URL: http://example.org/
|
URL: https://github.com/attah/harbour-seaprint
|
||||||
Source0: %{name}-%{version}.tar.bz2
|
Source0: %{name}-%{version}.tar.bz2
|
||||||
Requires: sailfishsilica-qt5 >= 0.10.9
|
Requires: sailfishsilica-qt5 >= 0.10.9
|
||||||
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
|
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
|
||||||
BuildRequires: pkgconfig(Qt5Core)
|
BuildRequires: pkgconfig(Qt5Core)
|
||||||
BuildRequires: pkgconfig(Qt5Qml)
|
BuildRequires: pkgconfig(Qt5Qml)
|
||||||
BuildRequires: pkgconfig(Qt5Quick)
|
BuildRequires: pkgconfig(Qt5Quick)
|
||||||
BuildRequires: pkgconfig(Qt5Svg)
|
|
||||||
BuildRequires: pkgconfig(mlite5)
|
BuildRequires: pkgconfig(mlite5)
|
||||||
BuildRequires: desktop-file-utils
|
BuildRequires: desktop-file-utils
|
||||||
BuildRequires: pkgconfig(libcurl)
|
BuildRequires: pkgconfig(libcurl)
|
||||||
|
@ -20,6 +19,10 @@ BuildRequires: pkgconfig(poppler)
|
||||||
BuildRequires: pkgconfig(poppler-glib)
|
BuildRequires: pkgconfig(poppler-glib)
|
||||||
BuildRequires: pkgconfig(glib-2.0)
|
BuildRequires: pkgconfig(glib-2.0)
|
||||||
BuildRequires: pkgconfig(cairo)
|
BuildRequires: pkgconfig(cairo)
|
||||||
|
BuildRequires: pkgconfig(libjpeg)
|
||||||
|
|
||||||
|
%define _source_payload w6T.xzdio
|
||||||
|
%define _binary_payload w6T.xzdio
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Network printing for Sailfish OS
|
Network printing for Sailfish OS
|
||||||
|
@ -44,7 +47,7 @@ desktop-file-install --delete-original \
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%{_bindir}
|
%{_bindir}/%{name}
|
||||||
%{_datadir}/%{name}
|
%{_datadir}/%{name}
|
||||||
%{_datadir}/applications/%{name}.desktop
|
%{_datadir}/applications/%{name}.desktop
|
||||||
%{_datadir}/icons/hicolor/*/apps/%{name}.png
|
%{_datadir}/icons/hicolor/*/apps/%{name}.png
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "convertchecker.h"
|
#include "convertchecker.h"
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
#include "mimer.h"
|
|
||||||
|
|
||||||
ConvertChecker::ConvertChecker() : poppler("libpoppler-glib.so.8")
|
ConvertChecker::ConvertChecker() : poppler("libpoppler-glib.so.8")
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,7 @@ static size_t trampoline(char* dest, size_t size, size_t nmemb, void* userp)
|
||||||
return cid->requestWrite(dest, size*nmemb);
|
return cid->requestWrite(dest, size*nmemb);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurlRequester::CurlRequester(QUrl addr, Role role)
|
CurlRequester::CurlRequester(QUrl addr, Role role, Bytestream* singleData)
|
||||||
: _addr(addr), _canWrite(1), _canRead(), _reading(false), _done(false), _dest(nullptr), _size(0), _offset(0), _curl(curl_easy_init())
|
: _addr(addr), _canWrite(1), _canRead(), _reading(false), _done(false), _dest(nullptr), _size(0), _offset(0), _curl(curl_easy_init())
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -36,7 +36,15 @@ CurlRequester::CurlRequester(QUrl addr, Role role)
|
||||||
curl_easy_setopt(_curl, CURLOPT_READDATA, this);
|
curl_easy_setopt(_curl, CURLOPT_READDATA, this);
|
||||||
|
|
||||||
_opts = curl_slist_append(_opts, "Expect:");
|
_opts = curl_slist_append(_opts, "Expect:");
|
||||||
|
if(singleData != nullptr)
|
||||||
|
{
|
||||||
|
curl_easy_setopt(_curl, CURLOPT_POSTFIELDSIZE, singleData->size());
|
||||||
|
write((char*)(singleData->raw()), singleData->size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_opts = curl_slist_append(_opts, "Transfer-Encoding: chunked");
|
_opts = curl_slist_append(_opts, "Transfer-Encoding: chunked");
|
||||||
|
}
|
||||||
_opts = curl_slist_append(_opts, "Content-Type: application/ipp");
|
_opts = curl_slist_append(_opts, "Content-Type: application/ipp");
|
||||||
_opts = curl_slist_append(_opts, "Accept-Encoding: identity");
|
_opts = curl_slist_append(_opts, "Accept-Encoding: identity");
|
||||||
break;
|
break;
|
||||||
|
@ -59,22 +67,14 @@ CurlRequester::CurlRequester(QUrl addr, Role role)
|
||||||
if(res != CURLE_OK)
|
if(res != CURLE_OK)
|
||||||
qDebug() << "curl_easy_perform() failed: " << curl_easy_strerror(res);
|
qDebug() << "curl_easy_perform() failed: " << curl_easy_strerror(res);
|
||||||
|
|
||||||
emit done(res, buf);
|
_result = res;
|
||||||
|
_resultMsg = buf;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CurlRequester::~CurlRequester()
|
CurlRequester::~CurlRequester()
|
||||||
{
|
{
|
||||||
while(!_canWrite.tryAcquire(1, 500))
|
await();
|
||||||
{
|
|
||||||
if(!_worker.isRunning())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_done = true;
|
|
||||||
_canRead.release();
|
|
||||||
_worker.waitForFinished();
|
|
||||||
|
|
||||||
if(_dest != nullptr)
|
if(_dest != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +85,22 @@ CurlRequester::~CurlRequester()
|
||||||
curl_easy_cleanup(_curl);
|
curl_easy_cleanup(_curl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CURLcode CurlRequester::await(Bytestream* data)
|
||||||
|
{
|
||||||
|
while(_worker.isRunning() && !_canWrite.tryAcquire(1, 500))
|
||||||
|
{}
|
||||||
|
|
||||||
|
_done = true;
|
||||||
|
_canRead.release();
|
||||||
|
_worker.waitForFinished();
|
||||||
|
|
||||||
|
if(data != nullptr)
|
||||||
|
{
|
||||||
|
(*data) = _resultMsg;
|
||||||
|
}
|
||||||
|
return _result;
|
||||||
|
}
|
||||||
|
|
||||||
bool CurlRequester::write(const char *data, size_t size)
|
bool CurlRequester::write(const char *data, size_t size)
|
||||||
{
|
{
|
||||||
qDebug() << "write " << size;
|
qDebug() << "write " << size;
|
||||||
|
@ -113,7 +129,7 @@ size_t CurlRequester::requestWrite(char* dest, size_t size)
|
||||||
if(!_reading)
|
if(!_reading)
|
||||||
{
|
{
|
||||||
_canRead.acquire();
|
_canRead.acquire();
|
||||||
if(_done) // Can only have been set by write() - only relevant to check if strating to write
|
if(_done) // Can only have been set by await() - only relevant to check if strating to write
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QSemaphore>
|
#include <QSemaphore>
|
||||||
#include <QMetaMethod>
|
|
||||||
#include <QtConcurrent/QtConcurrent>
|
#include <QtConcurrent/QtConcurrent>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <bytestream.h>
|
#include <bytestream.h>
|
||||||
|
@ -20,9 +19,11 @@ public:
|
||||||
HttpGetRequest
|
HttpGetRequest
|
||||||
};
|
};
|
||||||
|
|
||||||
CurlRequester(QUrl addr, Role role = IppRequest);
|
CurlRequester(QUrl addr, Role role = IppRequest, Bytestream* = nullptr);
|
||||||
~CurlRequester();
|
~CurlRequester();
|
||||||
|
|
||||||
|
CURLcode await(Bytestream* = nullptr);
|
||||||
|
|
||||||
bool write(const char *data, size_t size);
|
bool write(const char *data, size_t size);
|
||||||
size_t requestWrite(char* dest, size_t size);
|
size_t requestWrite(char* dest, size_t size);
|
||||||
|
|
||||||
|
@ -33,9 +34,6 @@ public:
|
||||||
return bytes_to_write;
|
return bytes_to_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
signals:
|
|
||||||
void done(CURLcode, Bytestream);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CurlRequester();
|
CurlRequester();
|
||||||
|
|
||||||
|
@ -62,6 +60,9 @@ private:
|
||||||
bool _reading;
|
bool _reading;
|
||||||
bool _done;
|
bool _done;
|
||||||
|
|
||||||
|
CURLcode _result;
|
||||||
|
Bytestream _resultMsg;
|
||||||
|
|
||||||
char* _dest;
|
char* _dest;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
size_t _offset;
|
size_t _offset;
|
||||||
|
|
25
src/dbusadaptorbase.cpp
Normal file
25
src/dbusadaptorbase.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#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();
|
||||||
|
}
|
24
src/dbusadaptorbase.h
Normal file
24
src/dbusadaptorbase.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#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
|
31
src/freedesktopdbusadaptor.cpp
Normal file
31
src/freedesktopdbusadaptor.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#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");
|
||||||
|
}
|
21
src/freedesktopdbusadaptor.h
Normal file
21
src/freedesktopdbusadaptor.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#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
|
|
@ -1,15 +1,23 @@
|
||||||
#include <QtQuick>
|
#include <QtQuick>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
|
||||||
#include <sailfishapp.h>
|
#include <sailfishapp.h>
|
||||||
#include <src/ippdiscovery.h>
|
#include <src/ippdiscovery.h>
|
||||||
#include <src/ippprinter.h>
|
#include <src/ippprinter.h>
|
||||||
|
#include <src/imageitem.h>
|
||||||
#include <src/mimer.h>
|
#include <src/mimer.h>
|
||||||
#include <src/convertchecker.h>
|
#include <src/convertchecker.h>
|
||||||
#include <src/svgprovider.h>
|
|
||||||
#include <src/settings.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(CURLcode)
|
||||||
Q_DECLARE_METATYPE(Bytestream)
|
Q_DECLARE_METATYPE(Bytestream)
|
||||||
|
Q_DECLARE_METATYPE(PrintParameters)
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
static QObject* singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
|
static QObject* singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
|
||||||
|
@ -24,8 +32,20 @@ static QObject* singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngi
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
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<CURLcode>();
|
||||||
qRegisterMetaType<Bytestream>();
|
qRegisterMetaType<Bytestream>();
|
||||||
|
qRegisterMetaType<PrintParameters>();
|
||||||
|
|
||||||
// Turn on/off logging according to setting
|
// Turn on/off logging according to setting
|
||||||
QLoggingCategory::defaultCategory()->setEnabled(QtMsgType::QtDebugMsg, Settings::instance()->debugLog());
|
QLoggingCategory::defaultCategory()->setEnabled(QtMsgType::QtDebugMsg, Settings::instance()->debugLog());
|
||||||
|
@ -39,17 +59,36 @@ int main(int argc, char *argv[])
|
||||||
qmlRegisterSingletonType<IppDiscovery>("seaprint.ippdiscovery", 1, 0, "IppDiscovery", singletontype_provider<IppDiscovery>);
|
qmlRegisterSingletonType<IppDiscovery>("seaprint.ippdiscovery", 1, 0, "IppDiscovery", singletontype_provider<IppDiscovery>);
|
||||||
qmlRegisterSingletonType<Mimer>("seaprint.mimer", 1, 0, "Mimer", singletontype_provider<Mimer>);
|
qmlRegisterSingletonType<Mimer>("seaprint.mimer", 1, 0, "Mimer", singletontype_provider<Mimer>);
|
||||||
qmlRegisterSingletonType<ConvertChecker>("seaprint.convertchecker", 1, 0, "ConvertChecker", singletontype_provider<ConvertChecker>);
|
qmlRegisterSingletonType<ConvertChecker>("seaprint.convertchecker", 1, 0, "ConvertChecker", singletontype_provider<ConvertChecker>);
|
||||||
qmlRegisterSingletonType<ConvertChecker>("seaprint.settings", 1, 0, "SeaPrintSettings", singletontype_provider<Settings>);
|
qmlRegisterSingletonType<Settings>("seaprint.settings", 1, 0, "SeaPrintSettings", singletontype_provider<Settings>);
|
||||||
|
qmlRegisterSingletonType<RangeListChecker>("seaprint.rangelistchecker", 1, 0, "RangeListChecker", singletontype_provider<RangeListChecker>);
|
||||||
|
|
||||||
qmlRegisterType<IppPrinter>("seaprint.ippprinter", 1, 0, "IppPrinter");
|
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");
|
qmlRegisterUncreatableType<IppMsg>("seaprint.ippmsg", 1, 0, "IppMsg", "Only used to supply an enum type");
|
||||||
|
|
||||||
QQuickView* view = SailfishApp::createView();
|
QQuickView* view = SailfishApp::createView();
|
||||||
|
|
||||||
view->engine()->addImportPath(SailfishApp::pathTo("qml/pages").toString());
|
view->engine()->addImportPath(SailfishApp::pathTo("qml/pages").toString());
|
||||||
view->engine()->addImageProvider(QLatin1String("ippdiscovery"), IppDiscovery::instance());
|
|
||||||
view->engine()->addImageProvider(QLatin1String("svg"), SvgProvider::instance());
|
|
||||||
|
|
||||||
view->setSource(SailfishApp::pathToMainQml());
|
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();
|
return app->exec();
|
||||||
}
|
}
|
||||||
|
|
29
src/imageitem.cpp
Normal file
29
src/imageitem.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include "imageitem.h"
|
||||||
|
|
||||||
|
ImageItem::ImageItem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageItem::paint(QPainter *painter)
|
||||||
|
{
|
||||||
|
QImage scaled = _image.scaledToHeight(boundingRect().height(), Qt::SmoothTransformation);
|
||||||
|
painter->drawImage(QPoint {0, 0}, scaled);
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage ImageItem::getImage() const
|
||||||
|
{
|
||||||
|
return _image;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageItem::setImage(const QImage &image)
|
||||||
|
{
|
||||||
|
_image = image;
|
||||||
|
emit imageChanged();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImageItem::isValid() const
|
||||||
|
{
|
||||||
|
return !_image.isNull();
|
||||||
|
}
|
31
src/imageitem.h
Normal file
31
src/imageitem.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef IMAGEITEM_H
|
||||||
|
#define IMAGEITEM_H
|
||||||
|
|
||||||
|
#include <QQuickPaintedItem>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
class ImageItem : public QQuickPaintedItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QImage image READ getImage WRITE setImage NOTIFY imageChanged)
|
||||||
|
Q_PROPERTY(bool valid READ isValid NOTIFY imageChanged)
|
||||||
|
public:
|
||||||
|
ImageItem();
|
||||||
|
|
||||||
|
void paint(QPainter *painter);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void imageChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QImage getImage() const;
|
||||||
|
void setImage(const QImage &image);
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
QImage _image;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IMAGEITEM_H
|
|
@ -37,7 +37,7 @@ QStringList get_addr(Bytestream& bts)
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IppDiscovery::IppDiscovery() : QStringListModel(), QQuickImageProvider(QQuickImageProvider::Image, ForceAsynchronousImageLoading)
|
IppDiscovery::IppDiscovery() : QStringListModel()
|
||||||
{
|
{
|
||||||
socket = new QUdpSocket(this);
|
socket = new QUdpSocket(this);
|
||||||
connect(socket, &QUdpSocket::readyRead, this, &IppDiscovery::readPendingDatagrams);
|
connect(socket, &QUdpSocket::readyRead, this, &IppDiscovery::readPendingDatagrams);
|
||||||
|
@ -93,15 +93,15 @@ void IppDiscovery::sendQuery(quint16 qtype, QStringList addrs) {
|
||||||
QTime now = QTime::currentTime();
|
QTime now = QTime::currentTime();
|
||||||
QTime aWhileAgo = now.addSecs(-1);
|
QTime aWhileAgo = now.addSecs(-1);
|
||||||
|
|
||||||
foreach(QString oq, _outstandingQueries.keys())
|
for(QPair<quint16, QString> oq : _outstandingQueries.keys())
|
||||||
{
|
{
|
||||||
if(_outstandingQueries[oq] < aWhileAgo)
|
if(_outstandingQueries[oq] < aWhileAgo)
|
||||||
{ // Housekeeping for _outstandingQueries
|
{ // Housekeeping for _outstandingQueries
|
||||||
_outstandingQueries.remove(oq);
|
_outstandingQueries.remove(oq);
|
||||||
}
|
}
|
||||||
else if(addrs.contains(oq))
|
else if(oq.first == qtype && addrs.contains(oq.second))
|
||||||
{ // we recently asked about this, remove it
|
{ // we recently asked about this, remove it
|
||||||
addrs.removeOne(oq);
|
addrs.removeOne(oq.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,9 +121,9 @@ void IppDiscovery::sendQuery(quint16 qtype, QStringList addrs) {
|
||||||
|
|
||||||
query << _transactionid++ << flags << questions << (quint16)0 << (quint16)0 << (quint16)0;
|
query << _transactionid++ << flags << questions << (quint16)0 << (quint16)0 << (quint16)0;
|
||||||
|
|
||||||
foreach(QString addr, addrs)
|
for(QString addr : addrs)
|
||||||
{
|
{
|
||||||
_outstandingQueries.insert(addr, now);
|
_outstandingQueries.insert({qtype, addr}, now);
|
||||||
|
|
||||||
QStringList addrParts = addr.split(".");
|
QStringList addrParts = addr.split(".");
|
||||||
QString addrPart, restAddr;
|
QString addrPart, restAddr;
|
||||||
|
@ -153,9 +153,7 @@ void IppDiscovery::sendQuery(quint16 qtype, QStringList addrs) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray bytes((char*)(query.raw()), query.size());
|
socket->writeDatagram((char*)(query.raw()), query.size(), QHostAddress("224.0.0.251"), 5353);
|
||||||
socket->writeDatagram(bytes, QHostAddress("224.0.0.251"), 5353);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString make_addr(QString proto, int defaultPort, quint16 port, QString ip, QString rp)
|
QString make_addr(QString proto, int defaultPort, quint16 port, QString ip, QString rp)
|
||||||
|
@ -187,11 +185,15 @@ void IppDiscovery::update()
|
||||||
QList<QPair<QString,QString>> ippsIpRps;
|
QList<QPair<QString,QString>> ippsIpRps;
|
||||||
QString target, rp;
|
QString target, rp;
|
||||||
|
|
||||||
foreach(QString it, _ipps)
|
for(QString it : _ipps)
|
||||||
{
|
{
|
||||||
quint16 port = _ports[it];
|
if(!_targets.contains(it) || !_ports.contains(it) || !_rps.contains(it))
|
||||||
target = _targets[it];
|
continue;
|
||||||
rp = _rps[it];
|
|
||||||
|
quint16 port = _ports.value(it);
|
||||||
|
target = _targets.value(it);
|
||||||
|
rp = _rps.value(it);
|
||||||
|
|
||||||
|
|
||||||
for(QMultiMap<QString,QString>::Iterator ait = _AAs.begin(); ait != _AAs.end(); ait++)
|
for(QMultiMap<QString,QString>::Iterator ait = _AAs.begin(); ait != _AAs.end(); ait++)
|
||||||
{
|
{
|
||||||
|
@ -208,11 +210,14 @@ void IppDiscovery::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(QString it, _ipp)
|
for(QString it : _ipp)
|
||||||
{
|
{
|
||||||
quint16 port = _ports[it];
|
if(!_targets.contains(it) || !_ports.contains(it) || !_rps.contains(it))
|
||||||
target = _targets[it];
|
continue;
|
||||||
rp = _rps[it];
|
|
||||||
|
quint16 port = _ports.value(it);
|
||||||
|
target = _targets.value(it);
|
||||||
|
rp = _rps.value(it);
|
||||||
|
|
||||||
for(QMultiMap<QString,QString>::Iterator ait = _AAs.begin(); ait != _AAs.end(); ait++)
|
for(QMultiMap<QString,QString>::Iterator ait = _AAs.begin(); ait != _AAs.end(); ait++)
|
||||||
{
|
{
|
||||||
|
@ -234,9 +239,9 @@ void IppDiscovery::update()
|
||||||
|
|
||||||
// Counting on that _ipp duplicates doesn't resolve fully any erlier than their _ipps counterpart
|
// Counting on that _ipp duplicates doesn't resolve fully any erlier than their _ipps counterpart
|
||||||
|
|
||||||
// TODO?: replace this with some logica that can bpoth add and remove
|
// TODO?: replace this with some logic that can bpoth add and remove
|
||||||
// and it can consider _favourites, so we can drop cleanUpdate
|
// and it can consider _favourites, so we can drop cleanUpdate
|
||||||
foreach(QString f, found)
|
for(QString f : found)
|
||||||
{
|
{
|
||||||
if(!this->stringList().contains(f))
|
if(!this->stringList().contains(f))
|
||||||
{
|
{
|
||||||
|
@ -252,16 +257,23 @@ void IppDiscovery::update()
|
||||||
void IppDiscovery::updateAndQueryPtrs(QStringList& ptrs, QStringList new_ptrs)
|
void IppDiscovery::updateAndQueryPtrs(QStringList& ptrs, QStringList new_ptrs)
|
||||||
{
|
{
|
||||||
new_ptrs.removeDuplicates();
|
new_ptrs.removeDuplicates();
|
||||||
foreach(QString ptr, new_ptrs)
|
for(QString ptr : new_ptrs)
|
||||||
{
|
{
|
||||||
if(!ptrs.contains(ptr))
|
if(!ptrs.contains(ptr))
|
||||||
{
|
{
|
||||||
ptrs.append(ptr);
|
ptrs.append(ptr);
|
||||||
}
|
}
|
||||||
// If pointer does not resolve to a target or is missing information, query about it
|
// If pointer does not resolve to a target or is missing information, query about it
|
||||||
if(!_targets.contains(ptr) || !_ports.contains(ptr) || !_rps.contains(ptr))
|
if(!_rps.contains(ptr))
|
||||||
{ // if the PTR doesn't already resolve, ask for everything about it
|
{
|
||||||
sendQuery(ALL, {ptr});
|
// Avahi *really* hates sending TXT to anything else than a TXT query
|
||||||
|
qDebug() << "querying txt " << ptr;
|
||||||
|
sendQuery(TXT, {ptr});
|
||||||
|
}
|
||||||
|
if(!_targets.contains(ptr) || !_ports.contains(ptr))
|
||||||
|
{
|
||||||
|
qDebug() << "querying srv " << ptr;
|
||||||
|
sendQuery(SRV, {ptr});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,6 +340,7 @@ void IppDiscovery::readPendingDatagrams()
|
||||||
{
|
{
|
||||||
std::string tmprp;
|
std::string tmprp;
|
||||||
tmp/tmp.remaining() >> tmprp;
|
tmp/tmp.remaining() >> tmprp;
|
||||||
|
qDebug() << "tmprp" << aaddr << tmprp.c_str();
|
||||||
_rps[aaddr] = tmprp.c_str();
|
_rps[aaddr] = tmprp.c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +383,7 @@ void IppDiscovery::readPendingDatagrams()
|
||||||
qDebug() << "new ipp ptrs" << new_ipp_ptrs;
|
qDebug() << "new ipp ptrs" << new_ipp_ptrs;
|
||||||
qDebug() << "new ipps ptrs" << new_ipps_ptrs;
|
qDebug() << "new ipps ptrs" << new_ipps_ptrs;
|
||||||
qDebug() << "ipp ptrs" << _ipp;
|
qDebug() << "ipp ptrs" << _ipp;
|
||||||
qDebug() << "ipp ptrs" << _ipps;
|
qDebug() << "ipps ptrs" << _ipps;
|
||||||
qDebug() << "rps" << _rps;
|
qDebug() << "rps" << _rps;
|
||||||
qDebug() << "ports" << _ports;
|
qDebug() << "ports" << _ports;
|
||||||
qDebug() << "new targets" << new_targets;
|
qDebug() << "new targets" << new_targets;
|
||||||
|
@ -380,12 +393,12 @@ void IppDiscovery::readPendingDatagrams()
|
||||||
|
|
||||||
// These will send one query per unique new ptr.
|
// These will send one query per unique new ptr.
|
||||||
// some responders doesn't give TXT records for more than one thing at at time :(
|
// some responders doesn't give TXT records for more than one thing at at time :(
|
||||||
updateAndQueryPtrs(_ipp, new_ipp_ptrs);
|
|
||||||
updateAndQueryPtrs(_ipps, new_ipps_ptrs);
|
updateAndQueryPtrs(_ipps, new_ipps_ptrs);
|
||||||
|
updateAndQueryPtrs(_ipp, new_ipp_ptrs);
|
||||||
|
|
||||||
QStringList unresolvedAddrs;
|
QStringList unresolvedAddrs;
|
||||||
|
|
||||||
foreach(QString t, new_targets)
|
for(QString t : new_targets)
|
||||||
{
|
{
|
||||||
// If target does not resolve to an address, query about it
|
// If target does not resolve to an address, query about it
|
||||||
if(!_AAs.contains(t))
|
if(!_AAs.contains(t))
|
||||||
|
@ -404,7 +417,7 @@ void IppDiscovery::readPendingDatagrams()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IppDiscovery::resolve(QUrl& url)
|
bool IppDiscovery::resolve(QUrl& url)
|
||||||
{
|
{
|
||||||
QString host = url.host();
|
QString host = url.host();
|
||||||
|
|
||||||
|
@ -417,39 +430,7 @@ void IppDiscovery::resolve(QUrl& url)
|
||||||
if(_AAs.contains(host))
|
if(_AAs.contains(host))
|
||||||
{ // TODO: retry potential other IPs
|
{ // TODO: retry potential other IPs
|
||||||
url.setHost(_AAs.value(host));
|
url.setHost(_AAs.value(host));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
|
||||||
QImage IppDiscovery::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
|
|
||||||
{ //TODO: consider caching images (doesn't appear to be needed currently)
|
|
||||||
Q_UNUSED(requestedSize);
|
|
||||||
qDebug() << "requesting image" << id;
|
|
||||||
|
|
||||||
QImage img;
|
|
||||||
|
|
||||||
QNetworkAccessManager* nam = new QNetworkAccessManager();
|
|
||||||
QUrl url(id);
|
|
||||||
|
|
||||||
resolve(url);
|
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
|
||||||
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
|
|
||||||
connect(nam, &QNetworkAccessManager::sslErrors, &IppPrinter::ignoreSslErrors);
|
|
||||||
|
|
||||||
QNetworkReply* reply = nam->get(request);
|
|
||||||
|
|
||||||
QEventLoop loop;
|
|
||||||
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
|
||||||
loop.exec();
|
|
||||||
|
|
||||||
if (reply->error() == QNetworkReply::NoError)
|
|
||||||
{
|
|
||||||
QImageReader imageReader(reply);
|
|
||||||
img = imageReader.read();
|
|
||||||
}
|
|
||||||
|
|
||||||
*size = img.size();
|
|
||||||
delete nam;
|
|
||||||
return img;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
#ifndef IPPDISCOVERY_H
|
#ifndef IPPDISCOVERY_H
|
||||||
#define IPPDISCOVERY_H
|
#define IPPDISCOVERY_H
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QQuickImageProvider>
|
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QImageReader>
|
|
||||||
#include <QtNetwork>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QEventLoop>
|
|
||||||
#include "bytestream.h"
|
#include "bytestream.h"
|
||||||
|
|
||||||
class IppDiscovery : public QStringListModel, public QQuickImageProvider
|
class IppDiscovery : public QStringListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -21,7 +16,7 @@ public:
|
||||||
Q_INVOKABLE void discover();
|
Q_INVOKABLE void discover();
|
||||||
Q_INVOKABLE void reset();
|
Q_INVOKABLE void reset();
|
||||||
|
|
||||||
void resolve(QUrl& url);
|
bool resolve(QUrl& url);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void favouritesChanged();
|
void favouritesChanged();
|
||||||
|
@ -49,9 +44,6 @@ private:
|
||||||
|
|
||||||
void updateAndQueryPtrs(QStringList& ptrs, QStringList new_ptrs);
|
void updateAndQueryPtrs(QStringList& ptrs, QStringList new_ptrs);
|
||||||
|
|
||||||
|
|
||||||
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
|
|
||||||
|
|
||||||
QStringList _ipp;
|
QStringList _ipp;
|
||||||
QStringList _ipps;
|
QStringList _ipps;
|
||||||
QMap<QString,QString> _rps;
|
QMap<QString,QString> _rps;
|
||||||
|
@ -61,7 +53,7 @@ private:
|
||||||
QMultiMap<QString,QString> _AAs;
|
QMultiMap<QString,QString> _AAs;
|
||||||
QMultiMap<QString,QString> _AAAAs;
|
QMultiMap<QString,QString> _AAAAs;
|
||||||
|
|
||||||
QMap<QString, QTime> _outstandingQueries;
|
QMap<QPair<quint16, QString>, QTime> _outstandingQueries;
|
||||||
|
|
||||||
QStringList _favourites;
|
QStringList _favourites;
|
||||||
QUdpSocket* socket;
|
QUdpSocket* socket;
|
||||||
|
|
|
@ -6,8 +6,9 @@ IppMsg::IppMsg()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IppMsg::IppMsg(QJsonObject opAttrs, QJsonObject jobAttrs, quint8 majVsn, quint8 minVsn)
|
IppMsg::IppMsg(Operation operation, QJsonObject opAttrs, QJsonObject jobAttrs, quint8 majVsn, quint8 minVsn)
|
||||||
{
|
{
|
||||||
|
_operation = operation;
|
||||||
_majVsn = majVsn;
|
_majVsn = majVsn;
|
||||||
_minVsn = minVsn;
|
_minVsn = minVsn;
|
||||||
_opAttrs = opAttrs;
|
_opAttrs = opAttrs;
|
||||||
|
@ -76,40 +77,63 @@ QJsonValue IppMsg::consume_value(quint8 tag, Bytestream& data)
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
case Integer:
|
case Integer:
|
||||||
case Enum:
|
case Enum:
|
||||||
quint32 tmp_u32;
|
{
|
||||||
data >> tmp_len >> tmp_u32;
|
quint32 tmp_u32=0;
|
||||||
|
if(!(data >>= (quint16)0))
|
||||||
|
{
|
||||||
|
data >> (quint16)4 >> tmp_u32;
|
||||||
|
}
|
||||||
value = (int)tmp_u32;
|
value = (int)tmp_u32;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Boolean:
|
case Boolean:
|
||||||
quint8 tmp_bool;
|
{
|
||||||
data >> tmp_len >> tmp_bool;
|
quint8 tmp_bool=0;
|
||||||
|
if(!(data >>= (quint16)0))
|
||||||
|
{
|
||||||
|
data >> (quint16)1 >> tmp_bool;
|
||||||
|
}
|
||||||
value = (bool)tmp_bool;
|
value = (bool)tmp_bool;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case DateTime:
|
case DateTime:
|
||||||
|
{
|
||||||
|
QDateTime tmp_datetime;
|
||||||
|
if(!(data >>= (quint16)0))
|
||||||
{
|
{
|
||||||
quint16 year;
|
quint16 year;
|
||||||
quint8 month, day, hour, minutes, seconds, deci_seconds,
|
quint8 month, day, hour, minutes, seconds, deci_seconds,
|
||||||
plus_minus, utc_h_offset, utc_m_offset;
|
plus_minus, utc_h_offset, utc_m_offset;
|
||||||
data >> tmp_len >> year >> month >> day >> hour >> minutes >> seconds >> deci_seconds
|
data >> (quint16)11 >> year >> month >> day >> hour >> minutes >> seconds >> deci_seconds
|
||||||
>> plus_minus >> utc_h_offset >> utc_m_offset;
|
>> plus_minus >> utc_h_offset >> utc_m_offset;
|
||||||
QDate date(year, month, day);
|
QDate date(year, month, day);
|
||||||
QTime time(hour, minutes, seconds, deci_seconds*100);
|
QTime time(hour, minutes, seconds, deci_seconds*100);
|
||||||
int offset_seconds = (plus_minus == '+' ? 1 : -1)*(utc_h_offset*60*60+utc_m_offset*60);
|
int offset_seconds = (plus_minus == '+' ? 1 : -1)*(utc_h_offset*60*60+utc_m_offset*60);
|
||||||
value = QDateTime(date, time, Qt::OffsetFromUTC, offset_seconds).toString(Qt::ISODate);
|
tmp_datetime = QDateTime(date, time, Qt::OffsetFromUTC, offset_seconds);
|
||||||
|
}
|
||||||
|
value = tmp_datetime.toString(Qt::ISODate);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Resolution:
|
case Resolution:
|
||||||
{
|
{
|
||||||
qint32 x, y;
|
qint32 x=0;
|
||||||
qint8 units;
|
qint32 y=0;
|
||||||
data >> tmp_len >> x >> y >> units;
|
qint8 units=0;
|
||||||
|
if(!(data >>= (quint16)0))
|
||||||
|
{
|
||||||
|
data >> (quint16)9 >> x >> y >> units;
|
||||||
|
}
|
||||||
value = QJsonObject {{"x", x}, {"y", y}, {"units", units}};
|
value = QJsonObject {{"x", x}, {"y", y}, {"units", units}};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IntegerRange:
|
case IntegerRange:
|
||||||
{
|
{
|
||||||
qint32 low, high;
|
qint32 low=0;
|
||||||
data >> tmp_len >> low >> high;
|
qint32 high=0;
|
||||||
|
if(!(data >>= (quint16)0))
|
||||||
|
{
|
||||||
|
data >> (quint16)8 >> low >> high;
|
||||||
|
}
|
||||||
value = QJsonObject {{"low", low}, {"high", high}};
|
value = QJsonObject {{"low", low}, {"high", high}};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +183,7 @@ QJsonArray IppMsg::get_unnamed_attributes(Bytestream& data)
|
||||||
QJsonArray untag_values(QJsonArray taggedValues)
|
QJsonArray untag_values(QJsonArray taggedValues)
|
||||||
{
|
{
|
||||||
QJsonArray res;
|
QJsonArray res;
|
||||||
foreach(QJsonValue it, taggedValues)
|
for(QJsonValue it : taggedValues)
|
||||||
{
|
{
|
||||||
res.append(it.toObject()["value"]);
|
res.append(it.toObject()["value"]);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +275,6 @@ QString IppMsg::consume_attribute(QJsonObject& attrs, Bytestream& data)
|
||||||
name = tmp_str.c_str();
|
name = tmp_str.c_str();
|
||||||
|
|
||||||
taggedValue = consume_value(tag, data);
|
taggedValue = consume_value(tag, data);
|
||||||
|
|
||||||
QJsonArray unnamed = get_unnamed_attributes(data);
|
QJsonArray unnamed = get_unnamed_attributes(data);
|
||||||
|
|
||||||
if(tag == BeginCollection)
|
if(tag == BeginCollection)
|
||||||
|
@ -265,6 +288,7 @@ QString IppMsg::consume_attribute(QJsonObject& attrs, Bytestream& data)
|
||||||
|| name.startsWith("printer-firmware")
|
|| name.startsWith("printer-firmware")
|
||||||
|| name.endsWith("-supported")
|
|| name.endsWith("-supported")
|
||||||
|| name == "printer-icons"
|
|| name == "printer-icons"
|
||||||
|
|| name == "media-ready"
|
||||||
|| name.endsWith("-reasons")));
|
|| name.endsWith("-reasons")));
|
||||||
|
|
||||||
if(!unnamed.empty() || forceArray)
|
if(!unnamed.empty() || forceArray)
|
||||||
|
@ -280,13 +304,13 @@ QString IppMsg::consume_attribute(QJsonObject& attrs, Bytestream& data)
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bytestream IppMsg::encode(Operation op)
|
Bytestream IppMsg::encode()
|
||||||
{
|
{
|
||||||
Bytestream ipp;
|
Bytestream ipp;
|
||||||
|
|
||||||
ipp << _majVsn << _minVsn;
|
ipp << _majVsn << _minVsn;
|
||||||
|
|
||||||
ipp << quint16(op);
|
ipp << quint16(_operation);
|
||||||
ipp << _reqid++;
|
ipp << _reqid++;
|
||||||
|
|
||||||
|
|
||||||
|
@ -296,12 +320,16 @@ Bytestream IppMsg::encode(Operation op)
|
||||||
QStringList InitialAttrs = {"attributes-charset",
|
QStringList InitialAttrs = {"attributes-charset",
|
||||||
"attributes-natural-language",
|
"attributes-natural-language",
|
||||||
"printer-uri",
|
"printer-uri",
|
||||||
|
"job-id",
|
||||||
"requesting-user-name"};
|
"requesting-user-name"};
|
||||||
foreach(QString key, InitialAttrs)
|
for(QString key : InitialAttrs)
|
||||||
|
{
|
||||||
|
if(_opAttrs.find(key) != _opAttrs.end())
|
||||||
{
|
{
|
||||||
QJsonObject val = _opAttrs.take(key).toObject();
|
QJsonObject val = _opAttrs.take(key).toObject();
|
||||||
encode_attr(ipp, val["tag"].toInt(), key, val["value"]);
|
encode_attr(ipp, val["tag"].toInt(), key, val["value"]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for(QJsonObject::iterator it = _opAttrs.begin(); it != _opAttrs.end(); it++)
|
for(QJsonObject::iterator it = _opAttrs.begin(); it != _opAttrs.end(); it++)
|
||||||
{ // encode any remaining op-attrs
|
{ // encode any remaining op-attrs
|
||||||
QJsonObject val = it.value().toObject();
|
QJsonObject val = it.value().toObject();
|
||||||
|
@ -334,7 +362,25 @@ void IppMsg::encode_attr(Bytestream& msg, quint8 tag, QString name, QJsonValue v
|
||||||
name = "";
|
name = "";
|
||||||
}
|
}
|
||||||
msg << tag << quint16(name.length()) << name.toStdString();
|
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) {
|
switch (tag) {
|
||||||
case OpAttrs:
|
case OpAttrs:
|
||||||
|
@ -351,7 +397,7 @@ void IppMsg::encode_attr(Bytestream& msg, quint8 tag, QString name, QJsonValue v
|
||||||
}
|
}
|
||||||
case Boolean:
|
case Boolean:
|
||||||
{
|
{
|
||||||
quint32 tmp_u8 = value.toBool();
|
quint8 tmp_u8 = value.toBool();
|
||||||
msg << (quint16)1 << tmp_u8;
|
msg << (quint16)1 << tmp_u8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -378,20 +424,12 @@ void IppMsg::encode_attr(Bytestream& msg, quint8 tag, QString name, QJsonValue v
|
||||||
case BeginCollection:
|
case BeginCollection:
|
||||||
{
|
{
|
||||||
msg << (quint16)0; // length of value
|
msg << (quint16)0; // length of value
|
||||||
if(value.isObject())
|
|
||||||
{
|
|
||||||
QJsonObject collection = value.toObject();
|
QJsonObject collection = value.toObject();
|
||||||
foreach(QString key, collection.keys())
|
for(QString key : collection.keys())
|
||||||
{
|
{
|
||||||
encode_attr(msg, collection[key].toObject()["tag"].toInt(), key,
|
encode_attr(msg, collection[key].toObject()["tag"].toInt(), key,
|
||||||
collection[key].toObject()["value"], true);
|
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;
|
msg << (quint8)EndCollection << (quint16)0 << (quint16)0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -418,3 +456,8 @@ void IppMsg::encode_attr(Bytestream& msg, quint8 tag, QString name, QJsonValue v
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IppMsg::setOpAttr(QString name, IppMsg::IppTag type, QJsonValue value)
|
||||||
|
{
|
||||||
|
_opAttrs.insert(name, QJsonObject {{"tag", type}, {"value", value}});
|
||||||
|
}
|
||||||
|
|
20
src/ippmsg.h
20
src/ippmsg.h
|
@ -4,11 +4,11 @@
|
||||||
#include "bytestream.h"
|
#include "bytestream.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QDate>
|
||||||
|
#include <QTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QUrl>
|
|
||||||
#include <QtNetwork>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QIODevice>
|
|
||||||
|
|
||||||
class IppMsg
|
class IppMsg
|
||||||
{
|
{
|
||||||
|
@ -61,20 +61,23 @@ public:
|
||||||
RestartJob = 0x000E,
|
RestartJob = 0x000E,
|
||||||
PausePrinter = 0x0010,
|
PausePrinter = 0x0010,
|
||||||
ResumePrinter = 0x0011,
|
ResumePrinter = 0x0011,
|
||||||
PurgeJobs = 0x0012
|
PurgeJobs = 0x0012,
|
||||||
|
IdentifyPrinter = 0x003C
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit IppMsg();
|
explicit IppMsg();
|
||||||
explicit IppMsg(Bytestream& resp);
|
explicit IppMsg(Bytestream& resp);
|
||||||
IppMsg(QJsonObject opAttrs, QJsonObject jobAttrs=QJsonObject(), quint8 majVsn=1, quint8 minVsn=1);
|
IppMsg(Operation operation, QJsonObject opAttrs, QJsonObject jobAttrs=QJsonObject(), quint8 majVsn=1, quint8 minVsn=1);
|
||||||
IppMsg(const IppMsg& other) = default;
|
IppMsg(const IppMsg& other) = default;
|
||||||
~IppMsg();
|
~IppMsg();
|
||||||
|
|
||||||
Bytestream encode(Operation op);
|
Bytestream encode();
|
||||||
QJsonObject getPrinterAttrs() {return _printerAttrs;}
|
QJsonObject getPrinterAttrs() {return _printerAttrs;}
|
||||||
QJsonArray getJobAttrs() {return _jobAttrs;}
|
QJsonArray getJobAttrs() {return _jobAttrs;}
|
||||||
QJsonObject getOpAttrs() {return _opAttrs;}
|
QJsonObject getOpAttrs() {return _opAttrs;}
|
||||||
|
|
||||||
|
void setOpAttr(QString name, IppMsg::IppTag type, QJsonValue value);
|
||||||
|
|
||||||
quint16 getStatus() {return _status;}
|
quint16 getStatus() {return _status;}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,6 +88,9 @@ private:
|
||||||
QJsonValue collect_attributes(QJsonArray& attrs);
|
QJsonValue collect_attributes(QJsonArray& attrs);
|
||||||
QString consume_attribute(QJsonObject& attrs, Bytestream& data);
|
QString consume_attribute(QJsonObject& attrs, Bytestream& data);
|
||||||
void encode_attr(Bytestream& msg, quint8 tag, QString name, QJsonValue value, bool subCollection=false);
|
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;
|
||||||
|
|
||||||
quint8 _majVsn;
|
quint8 _majVsn;
|
||||||
quint8 _minVsn;
|
quint8 _minVsn;
|
||||||
|
|
|
@ -1,42 +1,41 @@
|
||||||
#include "ippprinter.h"
|
#include "ippprinter.h"
|
||||||
#include "ippdiscovery.h"
|
#include "ippdiscovery.h"
|
||||||
#include "mimer.h"
|
#include "mimer.h"
|
||||||
|
#include "convertchecker.h"
|
||||||
#include "papersizes.h"
|
#include "papersizes.h"
|
||||||
#include "overrider.h"
|
#include "overrider.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QMargins)
|
Q_DECLARE_METATYPE(QMargins)
|
||||||
|
Q_DECLARE_METATYPE(IppMsg)
|
||||||
|
|
||||||
IppPrinter::IppPrinter() : _worker(this)
|
IppPrinter::IppPrinter()
|
||||||
{
|
{
|
||||||
|
_worker = new PrinterWorker(this);
|
||||||
|
|
||||||
QObject::connect(this, &IppPrinter::urlChanged, this, &IppPrinter::onUrlChanged);
|
QObject::connect(this, &IppPrinter::urlChanged, this, &IppPrinter::onUrlChanged);
|
||||||
qRegisterMetaType<QTemporaryFile*>("QTemporaryFile*");
|
qRegisterMetaType<QTemporaryFile*>("QTemporaryFile*");
|
||||||
|
|
||||||
_worker.moveToThread(&_workerThread);
|
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(this, &IppPrinter::doDoGetPrinterAttributes, &_worker, &PrinterWorker::getPrinterAttributes);
|
connect(this, &IppPrinter::doGetStrings, _worker, &PrinterWorker::getStrings);
|
||||||
connect(this, &IppPrinter::doGetJobs, &_worker, &PrinterWorker::getJobs);
|
connect(this, &IppPrinter::doGetImage, _worker, &PrinterWorker::getImage);
|
||||||
connect(this, &IppPrinter::doCancelJob, &_worker, &PrinterWorker::cancelJob);
|
|
||||||
connect(this, &IppPrinter::doJustUpload, &_worker, &PrinterWorker::justUpload);
|
|
||||||
|
|
||||||
connect(this, &IppPrinter::doConvertPdf, &_worker, &PrinterWorker::convertPdf);
|
connect(_worker, &PrinterWorker::progress, this, &IppPrinter::setProgress);
|
||||||
connect(this, &IppPrinter::doConvertImage, &_worker, &PrinterWorker::convertImage);
|
connect(_worker, &PrinterWorker::busyMessage, this, &IppPrinter::setBusyMessage);
|
||||||
connect(this, &IppPrinter::doConvertOfficeDocument, &_worker, &PrinterWorker::convertOfficeDocument);
|
connect(_worker, &PrinterWorker::failed, this, &IppPrinter::convertFailed);
|
||||||
connect(this, &IppPrinter::doConvertPlaintext, &_worker, &PrinterWorker::convertPlaintext);
|
|
||||||
|
|
||||||
connect(this, &IppPrinter::doGetStrings, &_worker, &PrinterWorker::getStrings);
|
|
||||||
|
|
||||||
connect(&_worker, &PrinterWorker::progress, this, &IppPrinter::setProgress);
|
|
||||||
connect(&_worker, &PrinterWorker::busyMessage, this, &IppPrinter::setBusyMessage);
|
|
||||||
connect(&_worker, &PrinterWorker::failed, this, &IppPrinter::convertFailed);
|
|
||||||
|
|
||||||
qRegisterMetaType<QMargins>();
|
qRegisterMetaType<QMargins>();
|
||||||
|
qRegisterMetaType<IppMsg>();
|
||||||
_workerThread.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IppPrinter::~IppPrinter() {
|
IppPrinter::~IppPrinter() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject IppPrinter::opAttrs() {
|
QJsonObject IppPrinter::opAttrs() {
|
||||||
|
@ -84,6 +83,7 @@ void IppPrinter::setUrl(QString url_s)
|
||||||
|
|
||||||
void IppPrinter::onUrlChanged()
|
void IppPrinter::onUrlChanged()
|
||||||
{
|
{
|
||||||
|
QMetaObject::invokeMethod(_worker, "urlChanged", Q_ARG(QUrl, httpUrl()));
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,29 +92,48 @@ void IppPrinter::refresh() {
|
||||||
if(_url.scheme() == "file")
|
if(_url.scheme() == "file")
|
||||||
{
|
{
|
||||||
_attrs = QJsonObject();
|
_attrs = QJsonObject();
|
||||||
|
QString localFile = _url.toLocalFile();
|
||||||
|
|
||||||
QFile file(_url.toLocalFile());
|
if(localFile.endsWith(".raw") || localFile.endsWith(".bin"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::ifstream ifs = std::ifstream(localFile.toStdString(), std::ios::in | std::ios::binary);
|
||||||
|
Bytestream InBts(ifs);
|
||||||
|
IppMsg resp(InBts);
|
||||||
|
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getPrinterAttrs();
|
||||||
|
_attrs = resp.getPrinterAttrs();
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
qDebug() << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QFile file(localFile);
|
||||||
if(file.open(QIODevice::ReadOnly))
|
if(file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
QJsonDocument JsonDocument = QJsonDocument::fromJson(file.readAll());
|
QJsonDocument JsonDocument = QJsonDocument::fromJson(file.readAll());
|
||||||
|
|
||||||
_attrs = JsonDocument.object();
|
_attrs = JsonDocument.object();
|
||||||
// These won't load anyway...r
|
|
||||||
_attrs.remove("printer-icons");
|
|
||||||
file.close();
|
file.close();
|
||||||
Overrider::instance()->apply(_attrs);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Overrider::instance()->apply(_attrs);
|
||||||
emit attrsChanged();
|
emit attrsChanged();
|
||||||
|
|
||||||
MaybeGetStrings();
|
// For testing fake file-prinetrs with a strings file hosted elsewhere
|
||||||
|
// MaybeGetIcon();
|
||||||
|
// MaybeGetStrings();
|
||||||
|
|
||||||
UpdateAdditionalDocumentFormats();
|
UpdateAdditionalDocumentFormats();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QJsonObject o = opAttrs();
|
QJsonObject o = opAttrs();
|
||||||
|
|
||||||
IppMsg msg = IppMsg(o);
|
IppMsg msg = IppMsg(IppMsg::GetPrinterAttrs, o);
|
||||||
emit doDoGetPrinterAttributes(msg.encode(IppMsg::GetPrinterAttrs));
|
emit doDoGetPrinterAttributes(msg.encode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,11 +142,51 @@ void IppPrinter::MaybeGetStrings()
|
||||||
if(_attrs.contains("printer-strings-uri") && _strings.empty())
|
if(_attrs.contains("printer-strings-uri") && _strings.empty())
|
||||||
{
|
{
|
||||||
QUrl url(_attrs["printer-strings-uri"].toObject()["value"].toString());
|
QUrl url(_attrs["printer-strings-uri"].toObject()["value"].toString());
|
||||||
IppDiscovery::instance()->resolve(url);
|
resolveUrl(url);
|
||||||
|
if(isAllowedAddress(url))
|
||||||
|
{
|
||||||
emit doGetStrings(url);
|
emit doGetStrings(url);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IppPrinter::MaybeGetIcon(bool retry)
|
||||||
|
{
|
||||||
|
if(_attrs.contains("printer-icons") && (_icon.isNull() || retry) && !_iconRetried)
|
||||||
|
{
|
||||||
|
QUrl url;
|
||||||
|
QJsonArray icons = _attrs["printer-icons"].toObject()["value"].toArray();
|
||||||
|
|
||||||
|
if(retry)
|
||||||
|
{ // If there were more than one icon, try the last one on the retry
|
||||||
|
if(icons.size() > 1)
|
||||||
|
{
|
||||||
|
url = icons.last().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(icons.size() == 3)
|
||||||
|
{ // If there are 3 icons, the first will be the 48px one, ignore it
|
||||||
|
url = icons.at(1).toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = icons.at(0).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveUrl(url);
|
||||||
|
|
||||||
|
if(isAllowedAddress(url))
|
||||||
|
{
|
||||||
|
emit doGetImage(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_iconRetried = retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void IppPrinter::UpdateAdditionalDocumentFormats()
|
void IppPrinter::UpdateAdditionalDocumentFormats()
|
||||||
{
|
{
|
||||||
_additionalDocumentFormats = QStringList();
|
_additionalDocumentFormats = QStringList();
|
||||||
|
@ -180,6 +239,7 @@ void IppPrinter::getPrinterAttributesFinished(CURLcode res, Bytestream data)
|
||||||
emit attrsChanged();
|
emit attrsChanged();
|
||||||
|
|
||||||
MaybeGetStrings();
|
MaybeGetStrings();
|
||||||
|
MaybeGetIcon();
|
||||||
UpdateAdditionalDocumentFormats();
|
UpdateAdditionalDocumentFormats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,6 +312,11 @@ void IppPrinter::cancelJobFinished(CURLcode res, Bytestream data)
|
||||||
getJobs();
|
getJobs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IppPrinter::identifyFinished(CURLcode /*res*/, Bytestream /*data*/)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void IppPrinter::getStringsFinished(CURLcode res, Bytestream data)
|
void IppPrinter::getStringsFinished(CURLcode res, Bytestream data)
|
||||||
{
|
{
|
||||||
qDebug() << res << data.size();
|
qDebug() << res << data.size();
|
||||||
|
@ -261,7 +326,7 @@ void IppPrinter::getStringsFinished(CURLcode res, Bytestream data)
|
||||||
// "media-type.com.epson-coated" = "Epson Photo Quality Ink Jet";
|
// "media-type.com.epson-coated" = "Epson Photo Quality Ink Jet";
|
||||||
QRegularExpression re("^\\\"(.*)\\\"\\s*=\\s*\\\"(.*)\\\";");
|
QRegularExpression re("^\\\"(.*)\\\"\\s*=\\s*\\\"(.*)\\\";");
|
||||||
QList<QByteArray> bl = ba.split('\n');
|
QList<QByteArray> bl = ba.split('\n');
|
||||||
foreach(QByteArray l, bl)
|
for(QByteArray l : bl)
|
||||||
{
|
{
|
||||||
QRegularExpressionMatch match = re.match(l);
|
QRegularExpressionMatch match = re.match(l);
|
||||||
if(match.hasMatch())
|
if(match.hasMatch())
|
||||||
|
@ -272,13 +337,23 @@ void IppPrinter::getStringsFinished(CURLcode res, Bytestream data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IppPrinter::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
void IppPrinter::getImageFinished(CURLcode res, Bytestream data)
|
||||||
{
|
{
|
||||||
bool ignore = Settings::instance()->ignoreSslErrors();
|
qDebug() << res << data.size();
|
||||||
qDebug() << reply->request().url() << "SSL handshake failed" << errors << ignore;
|
if(res == CURLE_OK)
|
||||||
if(ignore)
|
|
||||||
{
|
{
|
||||||
reply->ignoreSslErrors(errors);
|
QImage tmp;
|
||||||
|
if(tmp.loadFromData(data.raw(), data.size(), "PNG"))
|
||||||
|
{
|
||||||
|
_icon = tmp;
|
||||||
|
qDebug() << "image loaded" << _icon;
|
||||||
|
emit iconChanged();
|
||||||
|
|
||||||
|
if(tmp.size().width() < 128)
|
||||||
|
{
|
||||||
|
MaybeGetIcon(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,17 +381,27 @@ QString targetFormatIfAuto(QString documentFormat, QString mimeType, QJsonArray
|
||||||
{
|
{
|
||||||
if(documentFormat == Mimer::OctetStream)
|
if(documentFormat == Mimer::OctetStream)
|
||||||
{
|
{
|
||||||
if(mimeType == Mimer::PDF || mimeType == Mimer::Plaintext)
|
QStringList PdfPrioList = {Mimer::PDF, Mimer::Postscript, Mimer::PWG, Mimer::URF};
|
||||||
|
if(mimeType == Mimer::PDF)
|
||||||
{
|
{
|
||||||
return firstMatch(supportedMimeTypes, {Mimer::PDF, Mimer::Postscript, Mimer::PWG, Mimer::URF });
|
return firstMatch(supportedMimeTypes, PdfPrioList);
|
||||||
}
|
}
|
||||||
else if(mimeType == Mimer::Postscript)
|
else if(mimeType == Mimer::Postscript)
|
||||||
{
|
{
|
||||||
return firstMatch(supportedMimeTypes, {Mimer::Postscript});
|
return firstMatch(supportedMimeTypes, {Mimer::Postscript});
|
||||||
}
|
}
|
||||||
|
else if(mimeType == Mimer::Plaintext)
|
||||||
|
{
|
||||||
|
return firstMatch(supportedMimeTypes, PdfPrioList << Mimer::Plaintext);
|
||||||
|
}
|
||||||
else if(Mimer::isOffice(mimeType))
|
else if(Mimer::isOffice(mimeType))
|
||||||
{
|
{
|
||||||
return firstMatch(supportedMimeTypes, {Mimer::PDF, Mimer::Postscript, Mimer::PWG, Mimer::URF });
|
return firstMatch(supportedMimeTypes, PdfPrioList);
|
||||||
|
}
|
||||||
|
else if(documentFormat == Mimer::SVG)
|
||||||
|
{
|
||||||
|
QStringList SvgPrioList {Mimer::PWG, Mimer::URF, Mimer::PDF, Mimer::Postscript};
|
||||||
|
return firstMatch(supportedMimeTypes, SvgPrioList);
|
||||||
}
|
}
|
||||||
else if(Mimer::isImage(mimeType))
|
else if(Mimer::isImage(mimeType))
|
||||||
{
|
{
|
||||||
|
@ -334,29 +419,28 @@ QString targetFormatIfAuto(QString documentFormat, QString mimeType, QJsonArray
|
||||||
return documentFormat;
|
return documentFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IppPrinter::adjustRasterSettings(QString documentFormat, QJsonObject& jobAttrs, quint32& HwResX, quint32& HwResY,
|
void IppPrinter::adjustRasterSettings(QString filename, QString mimeType, QJsonObject& jobAttrs, PrintParameters& Params)
|
||||||
bool& BackHFlip, bool& BackVFlip)
|
|
||||||
{
|
{
|
||||||
if(documentFormat != Mimer::PWG && documentFormat != Mimer::URF)
|
if(Params.format != PrintParameters::PWG && Params.format != PrintParameters::URF)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO? jobAttrs.remove("printer-resolution");
|
jobAttrs.remove("printer-resolution");
|
||||||
|
|
||||||
if(documentFormat == Mimer::PWG)
|
if(Params.format == PrintParameters::PWG)
|
||||||
{
|
{
|
||||||
quint32 diff = std::numeric_limits<quint32>::max();
|
quint32 diff = std::numeric_limits<quint32>::max();
|
||||||
quint32 AdjustedHwResX = HwResX;
|
quint32 AdjustedHwResX = Params.hwResW;
|
||||||
quint32 AdjustedHwResY = HwResY;
|
quint32 AdjustedHwResY = Params.hwResH;
|
||||||
foreach(QJsonValue res, _attrs["pwg-raster-document-resolution-supported"].toObject()["value"].toArray())
|
for(QJsonValue res : _attrs["pwg-raster-document-resolution-supported"].toObject()["value"].toArray())
|
||||||
{
|
{
|
||||||
QJsonObject resObj = res.toObject();
|
QJsonObject resObj = res.toObject();
|
||||||
if(resObj["units"] != 3)
|
if(resObj["units"] != 3)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
quint32 tmpDiff = std::abs(int(HwResX-resObj["x"].toInt())) + std::abs(int(HwResY-resObj["y"].toInt()));
|
quint32 tmpDiff = std::abs(int(Params.hwResW-resObj["x"].toInt())) + std::abs(int(Params.hwResH-resObj["y"].toInt()));
|
||||||
if(tmpDiff < diff)
|
if(tmpDiff < diff)
|
||||||
{
|
{
|
||||||
diff = tmpDiff;
|
diff = tmpDiff;
|
||||||
|
@ -364,27 +448,26 @@ void IppPrinter::adjustRasterSettings(QString documentFormat, QJsonObject& jobAt
|
||||||
AdjustedHwResY = resObj["y"].toInt();
|
AdjustedHwResY = resObj["y"].toInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HwResX = AdjustedHwResX;
|
Params.hwResW = AdjustedHwResX;
|
||||||
HwResY = AdjustedHwResY;
|
Params.hwResH = AdjustedHwResY;
|
||||||
}
|
}
|
||||||
|
else if(Params.format == PrintParameters::URF)
|
||||||
if(documentFormat == Mimer::URF)
|
{ // Ensure Params.format resolution for URF
|
||||||
{ // Ensure symmetric resolution for URF
|
Params.hwResW = Params.hwResH = std::min(Params.hwResW, Params.hwResH);
|
||||||
HwResX = HwResY = std::min(HwResX, HwResY);
|
|
||||||
|
|
||||||
quint32 diff = std::numeric_limits<quint32>::max();
|
quint32 diff = std::numeric_limits<quint32>::max();
|
||||||
quint32 AdjustedHwRes = HwResX;
|
quint32 AdjustedHwRes = Params.hwResW;
|
||||||
|
|
||||||
QJsonArray urfSupported = _attrs["urf-supported"].toObject()["value"].toArray();
|
QJsonArray urfSupported = _attrs["urf-supported"].toObject()["value"].toArray();
|
||||||
foreach(QJsonValue us, urfSupported)
|
for(QJsonValue us : urfSupported)
|
||||||
{
|
{
|
||||||
if(us.toString().startsWith("RS"))
|
if(us.toString().startsWith("RS"))
|
||||||
{ //RS300[-600]
|
{ //RS300[-600]
|
||||||
QStringList resolutions = us.toString().mid(2).split("-");
|
QStringList resolutions = us.toString().mid(2).split("-");
|
||||||
foreach(QString res, resolutions)
|
for(QString res : resolutions)
|
||||||
{
|
{
|
||||||
int intRes = res.toInt();
|
int intRes = res.toInt();
|
||||||
quint32 tmpDiff = std::abs(int(HwResX - intRes));
|
quint32 tmpDiff = std::abs(int(Params.hwResW - intRes));
|
||||||
if(tmpDiff < diff)
|
if(tmpDiff < diff)
|
||||||
{
|
{
|
||||||
diff = tmpDiff;
|
diff = tmpDiff;
|
||||||
|
@ -392,7 +475,7 @@ void IppPrinter::adjustRasterSettings(QString documentFormat, QJsonObject& jobAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HwResX = HwResY = AdjustedHwRes;
|
Params.hwResW = Params.hwResH = AdjustedHwRes;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,64 +485,105 @@ void IppPrinter::adjustRasterSettings(QString documentFormat, QJsonObject& jobAt
|
||||||
|
|
||||||
if(Sides != "" && Sides != "one-sided")
|
if(Sides != "" && Sides != "one-sided")
|
||||||
{
|
{
|
||||||
if(documentFormat == Mimer::PWG)
|
if(Params.format == PrintParameters::PWG)
|
||||||
{
|
{
|
||||||
QString DocumentSheetBack = _attrs["pwg-raster-document-sheet-back"].toObject()["value"].toString();
|
QString DocumentSheetBack = _attrs["pwg-raster-document-sheet-back"].toObject()["value"].toString();
|
||||||
if(Sides=="two-sided-long-edge")
|
if(Sides=="two-sided-long-edge")
|
||||||
{
|
{
|
||||||
if(DocumentSheetBack=="flipped")
|
if(DocumentSheetBack=="flipped")
|
||||||
{
|
{
|
||||||
BackVFlip=true;
|
Params.backVFlip=true;
|
||||||
}
|
}
|
||||||
else if(DocumentSheetBack=="rotated")
|
else if(DocumentSheetBack=="rotated")
|
||||||
{
|
{
|
||||||
BackHFlip=true;
|
Params.backHFlip=true;
|
||||||
BackVFlip=true;
|
Params.backVFlip=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Sides=="two-sided-short-edge")
|
else if(Sides=="two-sided-short-edge")
|
||||||
{
|
{
|
||||||
if(DocumentSheetBack=="flipped")
|
if(DocumentSheetBack=="flipped")
|
||||||
{
|
{
|
||||||
BackHFlip=true;
|
Params.backHFlip=true;
|
||||||
}
|
}
|
||||||
else if(DocumentSheetBack=="manual-tumble")
|
else if(DocumentSheetBack=="manual-tumble")
|
||||||
{
|
{
|
||||||
BackHFlip=true;
|
Params.backHFlip=true;
|
||||||
BackVFlip=true;
|
Params.backVFlip=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(documentFormat == Mimer::URF)
|
else if(Params.format == PrintParameters::URF)
|
||||||
{
|
{
|
||||||
QJsonArray URfSupported = _attrs["urf-supported"].toObject()["value"].toArray();
|
QJsonArray URfSupported = _attrs["urf-supported"].toObject()["value"].toArray();
|
||||||
if(Sides=="two-sided-long-edge")
|
if(Sides=="two-sided-long-edge")
|
||||||
{
|
{
|
||||||
if(URfSupported.contains("DM2"))
|
if(URfSupported.contains("DM2"))
|
||||||
{
|
{
|
||||||
BackVFlip=true;
|
Params.backVFlip=true;
|
||||||
}
|
}
|
||||||
else if(URfSupported.contains("DM3"))
|
else if(URfSupported.contains("DM3"))
|
||||||
{
|
{
|
||||||
BackHFlip=true;
|
Params.backHFlip=true;
|
||||||
BackVFlip=true;
|
Params.backVFlip=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Sides=="two-sided-short-edge")
|
else if(Sides=="two-sided-short-edge")
|
||||||
{
|
{
|
||||||
if(URfSupported.contains("DM2"))
|
if(URfSupported.contains("DM2"))
|
||||||
{
|
{
|
||||||
BackHFlip=true;
|
Params.backHFlip=true;
|
||||||
}
|
}
|
||||||
else if(URfSupported.contains("DM4"))
|
else if(URfSupported.contains("DM4"))
|
||||||
{
|
{
|
||||||
BackHFlip=true;
|
Params.backHFlip=true;
|
||||||
BackVFlip=true;
|
Params.backVFlip=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void IppPrinter::print(QJsonObject jobAttrs, QString filename)
|
||||||
|
@ -469,6 +593,7 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
|
||||||
_progress = "";
|
_progress = "";
|
||||||
emit progressChanged();
|
emit progressChanged();
|
||||||
|
|
||||||
|
PrintParameters Params;
|
||||||
QFileInfo fileinfo(filename);
|
QFileInfo fileinfo(filename);
|
||||||
|
|
||||||
if(!fileinfo.exists())
|
if(!fileinfo.exists())
|
||||||
|
@ -489,22 +614,48 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
|
||||||
|
|
||||||
qDebug() << supportedMimeTypes << supportedMimeTypes.contains(mimeType);
|
qDebug() << supportedMimeTypes << supportedMimeTypes.contains(mimeType);
|
||||||
|
|
||||||
QJsonObject o = opAttrs();
|
if(!Params.setPaperSize(getAttrOrDefault(jobAttrs, "media").toString(Params.paperSizeName.c_str()).toStdString()))
|
||||||
o.insert("job-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", fileinfo.fileName()}});
|
|
||||||
|
|
||||||
QString PaperSize = getAttrOrDefault(jobAttrs, "media").toString();
|
|
||||||
|
|
||||||
if(jobAttrs.contains("media-col") && jobAttrs.contains("media"))
|
|
||||||
{
|
{
|
||||||
qDebug() << "moving media to media-col" << PaperSize;
|
emit convertFailed(tr("Unsupported paper size"));
|
||||||
if(!PaperSizes.contains(PaperSize))
|
|
||||||
{
|
|
||||||
emit convertFailed(tr("Unknown document format dimensions"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = PaperSizes[PaperSize].width()*100;
|
QString targetFormat = getAttrOrDefault(jobAttrs, "document-format").toString();
|
||||||
int y = PaperSizes[PaperSize].height()*100;
|
qDebug() << "target format:" << targetFormat;
|
||||||
|
|
||||||
|
QMargins margins(getAttrOrDefault(jobAttrs, "media-left-margin", "media-col").toInt(),
|
||||||
|
getAttrOrDefault(jobAttrs, "media-top-margin", "media-col").toInt(),
|
||||||
|
getAttrOrDefault(jobAttrs, "media-right-margin", "media-col").toInt(),
|
||||||
|
getAttrOrDefault(jobAttrs, "media-bottom-margin", "media-col").toInt());
|
||||||
|
|
||||||
|
// Only keep margin setting for JPEG - but only attemt to remove it if media-col exists
|
||||||
|
if(!mimer->isImage(targetFormat) && jobAttrs.contains("media-col"))
|
||||||
|
{
|
||||||
|
QJsonObject MediaCol = jobAttrs["media-col"].toObject();
|
||||||
|
QJsonObject MediaColValue = MediaCol["value"].toObject();
|
||||||
|
|
||||||
|
MediaColValue.remove("media-left-margin");
|
||||||
|
MediaColValue.remove("media-top-margin");
|
||||||
|
MediaColValue.remove("media-right-margin");
|
||||||
|
MediaColValue.remove("media-bottom-margin");
|
||||||
|
|
||||||
|
if(!MediaColValue.empty())
|
||||||
|
{
|
||||||
|
MediaCol["value"] = MediaColValue;
|
||||||
|
jobAttrs["media-col"] = MediaCol;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jobAttrs.remove("media-col");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(jobAttrs.contains("media-col") && jobAttrs.contains("media"))
|
||||||
|
{
|
||||||
|
qDebug() << "moving media to media-col" << Params.paperSizeName.c_str();
|
||||||
|
|
||||||
|
int x = Params.getPaperSizeWInMillimeters()*100;
|
||||||
|
int y = Params.getPaperSizeHInMillimeters()*100;
|
||||||
|
|
||||||
QJsonObject Dimensions =
|
QJsonObject Dimensions =
|
||||||
{{"tag", IppMsg::BeginCollection},
|
{{"tag", IppMsg::BeginCollection},
|
||||||
|
@ -523,125 +674,114 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
|
||||||
jobAttrs.remove("media");
|
jobAttrs.remove("media");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString documentFormat = getAttrOrDefault(jobAttrs, "document-format").toString();
|
QJsonObject jobOpAttrs = opAttrs();
|
||||||
qDebug() << "target format:" << documentFormat;
|
|
||||||
|
|
||||||
// document-format goes in the op-attrs and not the job-attrs
|
// document-format goes in the op-attrs and not the job-attrs
|
||||||
o.insert("document-format", QJsonObject {{"tag", IppMsg::MimeMediaType}, {"value", documentFormat}});
|
jobOpAttrs.insert("document-format", QJsonObject {{"tag", IppMsg::MimeMediaType}, {"value", targetFormat}});
|
||||||
jobAttrs.remove("document-format");
|
jobAttrs.remove("document-format");
|
||||||
|
|
||||||
documentFormat = targetFormatIfAuto(documentFormat, mimeType, supportedMimeTypes);
|
targetFormat = targetFormatIfAuto(targetFormat, mimeType, supportedMimeTypes);
|
||||||
qDebug() << "adjusted target format:" << documentFormat;
|
qDebug() << "adjusted target format:" << targetFormat;
|
||||||
|
|
||||||
if(documentFormat == "" || documentFormat == Mimer::OctetStream)
|
if(targetFormat == "" || targetFormat == Mimer::OctetStream)
|
||||||
{
|
{
|
||||||
emit convertFailed(tr("Unknown document format"));
|
emit convertFailed(tr("Unknown document format"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Printing job" << o << jobAttrs;
|
if(targetFormat == Mimer::PDF)
|
||||||
|
|
||||||
QJsonValue PrinterResolutionRef = getAttrOrDefault(jobAttrs, "printer-resolution");
|
|
||||||
quint32 HwResX = PrinterResolutionRef.toObject()["x"].toInt(300);
|
|
||||||
quint32 HwResY = PrinterResolutionRef.toObject()["y"].toInt(300);
|
|
||||||
bool BackHFlip = false;
|
|
||||||
bool BackVFlip = false;
|
|
||||||
|
|
||||||
adjustRasterSettings(documentFormat, jobAttrs, HwResX, HwResY, BackHFlip, BackVFlip);
|
|
||||||
|
|
||||||
quint32 Quality = getAttrOrDefault(jobAttrs, "print-quality").toInt();
|
|
||||||
|
|
||||||
QString PrintColorMode = getAttrOrDefault(jobAttrs, "print-color-mode").toString();
|
|
||||||
quint32 Colors = PrintColorMode.contains("color") ? 3 : PrintColorMode.contains("monochrome") ? 1 : 0;
|
|
||||||
|
|
||||||
quint32 PageRangeLow = 0;
|
|
||||||
quint32 PageRangeHigh = 0;
|
|
||||||
if(jobAttrs.contains("page-ranges"))
|
|
||||||
{
|
{
|
||||||
QJsonObject PageRanges = getAttrOrDefault(jobAttrs, "page-ranges").toObject();
|
Params.format = PrintParameters::PDF;
|
||||||
PageRangeLow = PageRanges["low"].toInt();
|
|
||||||
PageRangeHigh = PageRanges["high"].toInt();
|
|
||||||
// Effected locally, unless it is Postscript which we cant't render
|
|
||||||
if(documentFormat != Mimer::Postscript)
|
|
||||||
{
|
|
||||||
jobAttrs.remove("page-ranges");
|
|
||||||
}
|
}
|
||||||
}
|
else if(targetFormat == Mimer::Postscript)
|
||||||
|
|
||||||
qDebug() << "Final op attributes:" << o;
|
|
||||||
qDebug() << "Final job attributes:" << jobAttrs;
|
|
||||||
|
|
||||||
IppMsg job = mk_msg(o, jobAttrs);
|
|
||||||
Bytestream contents = job.encode(IppMsg::PrintJob);
|
|
||||||
|
|
||||||
// Shouldn't and can't process these formats respectively
|
|
||||||
if((mimeType == documentFormat) && (documentFormat == Mimer::JPEG || documentFormat == Mimer::Postscript))
|
|
||||||
{
|
{
|
||||||
emit doJustUpload(filename, contents);
|
Params.format = PrintParameters::Postscript;
|
||||||
|
}
|
||||||
|
else if(targetFormat == Mimer::PWG)
|
||||||
|
{
|
||||||
|
Params.format = PrintParameters::PWG;
|
||||||
|
}
|
||||||
|
else if(targetFormat == Mimer::URF)
|
||||||
|
{
|
||||||
|
Params.format = PrintParameters::URF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(PaperSize == "")
|
Params.format = PrintParameters::Invalid;
|
||||||
{
|
|
||||||
PaperSize = "iso_a4_210x297mm";
|
|
||||||
}
|
|
||||||
else if(!PaperSizes.contains(PaperSize))
|
|
||||||
{
|
|
||||||
emit convertFailed(tr("Unsupported print media"));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TwoSided = false;
|
qDebug() << "Printing job" << jobOpAttrs << jobAttrs;
|
||||||
bool Tumble = false;
|
|
||||||
|
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(filename, mimeType, jobAttrs, Params);
|
||||||
|
|
||||||
QString Sides = getAttrOrDefault(jobAttrs, "sides").toString();
|
QString Sides = getAttrOrDefault(jobAttrs, "sides").toString();
|
||||||
|
|
||||||
if(Sides=="two-sided-long-edge")
|
if(Sides=="two-sided-long-edge")
|
||||||
{
|
{
|
||||||
TwoSided = true;
|
Params.duplex = true;
|
||||||
}
|
}
|
||||||
else if(Sides=="two-sided-short-edge")
|
else if(Sides=="two-sided-short-edge")
|
||||||
{
|
{
|
||||||
TwoSided = true;
|
Params.duplex = true;
|
||||||
Tumble = true;
|
Params.tumble = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setBusyMessage(tr("Preparing"));
|
Params.quality = getAttrOrDefault(jobAttrs, "print-quality").toInt();
|
||||||
|
|
||||||
if(mimeType == Mimer::PDF)
|
QString PrintColorMode = getAttrOrDefault(jobAttrs, "print-color-mode").toString();
|
||||||
{
|
Params.colors = PrintColorMode.contains("color") ? 3 : PrintColorMode.contains("monochrome") ? 1 : Params.colors;
|
||||||
emit doConvertPdf(filename, contents, documentFormat, Colors, Quality,
|
|
||||||
PaperSize, HwResX, HwResY, TwoSided, Tumble, PageRangeLow, PageRangeHigh,
|
|
||||||
BackHFlip, BackVFlip);
|
|
||||||
}
|
|
||||||
else if(mimeType == Mimer::Plaintext)
|
|
||||||
{
|
|
||||||
emit doConvertPlaintext(filename, contents, documentFormat, Colors, Quality,
|
|
||||||
PaperSize, HwResX, HwResY, TwoSided, Tumble, BackHFlip, BackVFlip);
|
|
||||||
}
|
|
||||||
else if (Mimer::isImage(mimeType))
|
|
||||||
{
|
|
||||||
QMargins margins(getAttrOrDefault(jobAttrs, "media-left-margin", "media-col").toInt(),
|
|
||||||
getAttrOrDefault(jobAttrs, "media-top-margin", "media-col").toInt(),
|
|
||||||
getAttrOrDefault(jobAttrs, "media-right-margin", "media-col").toInt(),
|
|
||||||
getAttrOrDefault(jobAttrs, "media-bottom-margin", "media-col").toInt());
|
|
||||||
|
|
||||||
emit doConvertImage(filename, contents, documentFormat, Colors, Quality,
|
QJsonArray supportedOperations = _attrs["operations-supported"].toObject()["value"].toArray();
|
||||||
PaperSize, HwResX, HwResY, margins);
|
|
||||||
}
|
if(supportedOperations.contains(IppMsg::CreateJob) && supportedOperations.contains(IppMsg::SendDocument))
|
||||||
else if(Mimer::isOffice(mimeType))
|
|
||||||
{
|
{
|
||||||
emit doConvertOfficeDocument(filename, contents, documentFormat, Colors, Quality,
|
QJsonObject createJobOpAttrs = opAttrs();
|
||||||
PaperSize, HwResX, HwResY, TwoSided, Tumble, PageRangeLow, PageRangeHigh,
|
createJobOpAttrs.insert("job-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", fileinfo.fileName()}});
|
||||||
BackHFlip, BackVFlip);
|
|
||||||
|
qDebug() << "Final create op attributes:" << createJobOpAttrs;
|
||||||
|
qDebug() << "Final job attributes:" << jobAttrs;
|
||||||
|
|
||||||
|
IppMsg createJob = mk_msg(IppMsg::CreateJob, createJobOpAttrs, jobAttrs);
|
||||||
|
qDebug() << "Final job op attributes:" << jobOpAttrs;
|
||||||
|
|
||||||
|
IppMsg sendDoc = mk_msg(IppMsg::SendDocument, jobOpAttrs);
|
||||||
|
|
||||||
|
emit doPrint2(filename, mimeType, targetFormat, createJob, sendDoc, Params, margins);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
emit convertFailed(tr("Cannot convert this file format"));
|
jobOpAttrs.insert("job-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", fileinfo.fileName()}});
|
||||||
return;
|
|
||||||
}
|
qDebug() << "Final op attributes:" << jobOpAttrs;
|
||||||
|
qDebug() << "Final job attributes:" << jobAttrs;
|
||||||
|
|
||||||
|
IppMsg job = mk_msg(IppMsg::PrintJob, jobOpAttrs, jobAttrs);
|
||||||
|
emit doPrint(filename, mimeType, targetFormat, job, Params, margins);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IppPrinter::getJobs() {
|
bool IppPrinter::getJobs() {
|
||||||
|
@ -650,9 +790,9 @@ bool IppPrinter::getJobs() {
|
||||||
QJsonObject o = opAttrs();
|
QJsonObject o = opAttrs();
|
||||||
o.insert("requested-attributes", QJsonObject {{"tag", IppMsg::Keyword}, {"value", "all"}});
|
o.insert("requested-attributes", QJsonObject {{"tag", IppMsg::Keyword}, {"value", "all"}});
|
||||||
|
|
||||||
IppMsg job = IppMsg(o, QJsonObject());
|
IppMsg job = IppMsg(IppMsg::GetJobs, o, QJsonObject());
|
||||||
|
|
||||||
emit doGetJobs(job.encode(IppMsg::GetJobs));
|
emit doGetJobs(job.encode());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -664,16 +804,29 @@ bool IppPrinter::cancelJob(qint32 jobId) {
|
||||||
QJsonObject o = opAttrs();
|
QJsonObject o = opAttrs();
|
||||||
o.insert("job-id", QJsonObject {{"tag", IppMsg::Integer}, {"value", jobId}});
|
o.insert("job-id", QJsonObject {{"tag", IppMsg::Integer}, {"value", jobId}});
|
||||||
|
|
||||||
IppMsg job = IppMsg(o, QJsonObject());
|
IppMsg job = IppMsg(IppMsg::CancelJob, o, QJsonObject());
|
||||||
|
|
||||||
emit doCancelJob(job.encode(IppMsg::CancelJob));
|
emit doCancelJob(job.encode());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IppPrinter::identify() {
|
||||||
|
|
||||||
|
qDebug() << "identifying";
|
||||||
|
|
||||||
|
QJsonObject o = opAttrs();
|
||||||
|
|
||||||
|
IppMsg job = IppMsg(IppMsg::IdentifyPrinter, o, QJsonObject());
|
||||||
|
|
||||||
|
emit doCancelJob(job.encode());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IppPrinter::correctSuffix()
|
bool IppPrinter::correctSuffix()
|
||||||
{
|
{
|
||||||
foreach(QJsonValue u, _attrs["printer-uri-supported"].toObject()["value"].toArray())
|
for(QJsonValue u : _attrs["printer-uri-supported"].toObject()["value"].toArray())
|
||||||
{
|
{
|
||||||
QUrl url(u.toString());
|
QUrl url(u.toString());
|
||||||
if(url.path() == _url.path())
|
if(url.path() == _url.path())
|
||||||
|
@ -687,7 +840,7 @@ bool IppPrinter::correctSuffix()
|
||||||
QStringList IppPrinter::suffixes()
|
QStringList IppPrinter::suffixes()
|
||||||
{
|
{
|
||||||
QStringList res;
|
QStringList res;
|
||||||
foreach(QJsonValue u, _attrs["printer-uri-supported"].toObject()["value"].toArray())
|
for(QJsonValue u : _attrs["printer-uri-supported"].toObject()["value"].toArray())
|
||||||
{
|
{
|
||||||
QUrl url(u.toString());
|
QUrl url(u.toString());
|
||||||
if(!res.contains(url.path()))
|
if(!res.contains(url.path()))
|
||||||
|
@ -735,6 +888,13 @@ void IppPrinter::setProgress(qint64 sent, qint64 total)
|
||||||
emit progressChanged();
|
emit progressChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IppPrinter::isAllowedAddress(QUrl url)
|
||||||
|
{
|
||||||
|
bool allowed = ((url.host() == _url.host()) || Settings::instance()->allowExternalConnections());
|
||||||
|
qDebug() << url << " is allowed: " << allowed;
|
||||||
|
return allowed;
|
||||||
|
}
|
||||||
|
|
||||||
QJsonValue IppPrinter::getAttrOrDefault(QJsonObject jobAttrs, QString name, QString subkey)
|
QJsonValue IppPrinter::getAttrOrDefault(QJsonObject jobAttrs, QString name, QString subkey)
|
||||||
{
|
{
|
||||||
if(subkey == "")
|
if(subkey == "")
|
||||||
|
@ -762,13 +922,34 @@ QJsonValue IppPrinter::getAttrOrDefault(QJsonObject jobAttrs, QString name, QStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IppMsg IppPrinter::mk_msg(QJsonObject opAttrs, QJsonObject jobAttrs)
|
IppMsg IppPrinter::mk_msg(IppMsg::Operation operation, QJsonObject opAttrs, QJsonObject jobAttrs)
|
||||||
{
|
{
|
||||||
if(_attrs.contains("ipp-versions-supported") &&
|
if(_attrs.contains("ipp-versions-supported") &&
|
||||||
_attrs["ipp-versions-supported"].toObject()["value"].toArray().contains("2.0"))
|
_attrs["ipp-versions-supported"].toObject()["value"].toArray().contains("2.0"))
|
||||||
{
|
{
|
||||||
qDebug() << "TWO-POINT-ZERO";
|
qDebug() << "TWO-POINT-ZERO";
|
||||||
return IppMsg(opAttrs, jobAttrs, 2, 0);
|
return IppMsg(operation, opAttrs, jobAttrs, 2, 0);
|
||||||
|
}
|
||||||
|
return IppMsg(operation, opAttrs, jobAttrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IppPrinter::resolveUrl(QUrl& url)
|
||||||
|
{
|
||||||
|
if(!IppDiscovery::instance()->resolve(url))
|
||||||
|
{ // If "proper" resolution fails, cheat...
|
||||||
|
QString host = url.host();
|
||||||
|
|
||||||
|
if(host.endsWith("."))
|
||||||
|
{
|
||||||
|
host.chop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString dnsSdName = _attrs["printer-dns-sd-name"].toObject()["value"].toString();
|
||||||
|
dnsSdName = dnsSdName.append(".local");
|
||||||
|
|
||||||
|
if(host.compare(dnsSdName, Qt::CaseInsensitive) == 0)
|
||||||
|
{ // This could be done unconditionally, but some might want their externally hosted stuff to work
|
||||||
|
url.setHost(_url.host());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return IppMsg(opAttrs, jobAttrs);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#ifndef IPPPRINTER_H
|
#ifndef IPPPRINTER_H
|
||||||
#define IPPPRINTER_H
|
#define IPPPRINTER_H
|
||||||
|
|
||||||
#include <QtNetwork>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include "ippmsg.h"
|
#include "ippmsg.h"
|
||||||
#include "printerworker.h"
|
#include "printerworker.h"
|
||||||
#include "curlrequester.h"
|
#include "curlrequester.h"
|
||||||
#include <mlite5/MGConfItem>
|
#include <QImage>
|
||||||
|
|
||||||
|
|
||||||
class IppPrinter : public QObject
|
class IppPrinter : public QObject
|
||||||
{
|
{
|
||||||
|
@ -19,6 +18,7 @@ class IppPrinter : public QObject
|
||||||
Q_PROPERTY(QJsonObject jobAttrs MEMBER _jobAttrs NOTIFY jobAttrsChanged)
|
Q_PROPERTY(QJsonObject jobAttrs MEMBER _jobAttrs NOTIFY jobAttrsChanged)
|
||||||
Q_PROPERTY(QJsonArray jobs MEMBER _jobs NOTIFY jobsChanged)
|
Q_PROPERTY(QJsonArray jobs MEMBER _jobs NOTIFY jobsChanged)
|
||||||
Q_PROPERTY(QJsonObject strings MEMBER _strings NOTIFY stringsChanged)
|
Q_PROPERTY(QJsonObject strings MEMBER _strings NOTIFY stringsChanged)
|
||||||
|
Q_PROPERTY(QImage icon MEMBER _icon NOTIFY iconChanged)
|
||||||
Q_PROPERTY(QStringList additionalDocumentFormats MEMBER _additionalDocumentFormats NOTIFY additionalDocumentFormatsChanged)
|
Q_PROPERTY(QStringList additionalDocumentFormats MEMBER _additionalDocumentFormats NOTIFY additionalDocumentFormatsChanged)
|
||||||
Q_PROPERTY(QString busyMessage MEMBER _busyMessage NOTIFY busyMessageChanged)
|
Q_PROPERTY(QString busyMessage MEMBER _busyMessage NOTIFY busyMessageChanged)
|
||||||
Q_PROPERTY(QString progress MEMBER _progress NOTIFY progressChanged)
|
Q_PROPERTY(QString progress MEMBER _progress NOTIFY progressChanged)
|
||||||
|
@ -38,6 +38,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE bool getJobs();
|
Q_INVOKABLE bool getJobs();
|
||||||
Q_INVOKABLE bool cancelJob(qint32 jobId);
|
Q_INVOKABLE bool cancelJob(qint32 jobId);
|
||||||
|
Q_INVOKABLE bool identify();
|
||||||
|
|
||||||
bool correctSuffix();
|
bool correctSuffix();
|
||||||
QStringList suffixes();
|
QStringList suffixes();
|
||||||
|
@ -49,6 +50,7 @@ signals:
|
||||||
void jobsChanged();
|
void jobsChanged();
|
||||||
|
|
||||||
void stringsChanged();
|
void stringsChanged();
|
||||||
|
void iconChanged();
|
||||||
|
|
||||||
void jobFinished(bool status);
|
void jobFinished(bool status);
|
||||||
void cancelStatus(bool status);
|
void cancelStatus(bool status);
|
||||||
|
@ -56,28 +58,25 @@ signals:
|
||||||
void doDoGetPrinterAttributes(Bytestream msg);
|
void doDoGetPrinterAttributes(Bytestream msg);
|
||||||
void doGetJobs(Bytestream msg);
|
void doGetJobs(Bytestream msg);
|
||||||
void doCancelJob(Bytestream msg);
|
void doCancelJob(Bytestream msg);
|
||||||
|
void doIdentify(Bytestream msg);
|
||||||
|
|
||||||
void doJustUpload(QString filename, Bytestream header);
|
void doJustUpload(QString filename, Bytestream header);
|
||||||
|
void doFixupPlaintext(QString filename, Bytestream header);
|
||||||
|
void doPrintImageAsImage(QString filename, Bytestream header, QString targetFormat);
|
||||||
|
|
||||||
void doConvertPdf(QString filename, Bytestream header,
|
void doConvertPdf(QString filename, Bytestream header, PrintParameters Params);
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
|
|
||||||
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
|
|
||||||
|
|
||||||
void doConvertImage(QString filename, Bytestream header,
|
void doConvertImage(QString filename, Bytestream header, PrintParameters Params, QMargins margins);
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, QMargins margins);
|
|
||||||
|
|
||||||
void doConvertOfficeDocument(QString filename, Bytestream header,
|
void doConvertOfficeDocument(QString filename, Bytestream header, PrintParameters Params);
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
|
|
||||||
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
|
|
||||||
|
|
||||||
void doConvertPlaintext(QString filename, Bytestream header,
|
void doConvertPlaintext(QString filename, Bytestream header, PrintParameters Params);
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble, bool BackHFlip, bool BackVFlip);
|
void doPrint(QString filename, QString mimeType, QString targetFormat, IppMsg job, PrintParameters Params, QMargins margins);
|
||||||
|
void doPrint2(QString filename, QString mimeType, QString targetFormat, IppMsg createJob, IppMsg sendDocument, PrintParameters Params, QMargins margins);
|
||||||
|
|
||||||
void doGetStrings(QUrl url);
|
void doGetStrings(QUrl url);
|
||||||
|
void doGetImage(QUrl url);
|
||||||
|
|
||||||
void additionalDocumentFormatsChanged();
|
void additionalDocumentFormatsChanged();
|
||||||
void busyMessageChanged();
|
void busyMessageChanged();
|
||||||
|
@ -86,51 +85,54 @@ signals:
|
||||||
public slots:
|
public slots:
|
||||||
void print(QJsonObject attrs, QString file);
|
void print(QJsonObject attrs, QString file);
|
||||||
|
|
||||||
|
|
||||||
void onUrlChanged();
|
void onUrlChanged();
|
||||||
void MaybeGetStrings();
|
void MaybeGetStrings();
|
||||||
|
void MaybeGetIcon(bool retry=false);
|
||||||
void UpdateAdditionalDocumentFormats();
|
void UpdateAdditionalDocumentFormats();
|
||||||
void getPrinterAttributesFinished(CURLcode res, Bytestream data);
|
void getPrinterAttributesFinished(CURLcode res, Bytestream data);
|
||||||
void printRequestFinished(CURLcode res, Bytestream data);
|
void printRequestFinished(CURLcode res, Bytestream data);
|
||||||
void getJobsRequestFinished(CURLcode res, Bytestream data);
|
void getJobsRequestFinished(CURLcode res, Bytestream data);
|
||||||
void cancelJobFinished(CURLcode res, Bytestream data);
|
void cancelJobFinished(CURLcode res, Bytestream data);
|
||||||
|
void identifyFinished(CURLcode res, Bytestream data);
|
||||||
|
|
||||||
void getStringsFinished(CURLcode res, Bytestream data);
|
void getStringsFinished(CURLcode res, Bytestream data);
|
||||||
|
void getImageFinished(CURLcode res, Bytestream data);
|
||||||
static void ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
|
|
||||||
|
|
||||||
void convertFailed(QString message);
|
void convertFailed(QString message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUrl _url;
|
QUrl _url;
|
||||||
QUrl httpUrl();
|
QUrl httpUrl();
|
||||||
|
void resolveUrl(QUrl& url);
|
||||||
|
|
||||||
QJsonObject opAttrs();
|
QJsonObject opAttrs();
|
||||||
|
|
||||||
void adjustRasterSettings(QString documentFormat, QJsonObject& jobAttrs, quint32& HwResX, quint32& HwResY,
|
void adjustRasterSettings(QString filename, QString mimeType, QJsonObject& jobAttrs, PrintParameters& Params);
|
||||||
bool& BackHFlip, bool& BackVFlip);
|
|
||||||
|
|
||||||
void setBusyMessage(QString msg);
|
void setBusyMessage(QString msg);
|
||||||
void setProgress(qint64 sent, qint64 total);
|
void setProgress(qint64 sent, qint64 total);
|
||||||
|
|
||||||
|
bool isAllowedAddress(QUrl addr);
|
||||||
|
|
||||||
QJsonValue getAttrOrDefault(QJsonObject jobAttrs, QString name, QString subkey = "");
|
QJsonValue getAttrOrDefault(QJsonObject jobAttrs, QString name, QString subkey = "");
|
||||||
|
|
||||||
IppMsg mk_msg(QJsonObject opAttrs, QJsonObject jobAttrs=QJsonObject());
|
IppMsg mk_msg(IppMsg::Operation operation, QJsonObject opAttrs, QJsonObject jobAttrs=QJsonObject());
|
||||||
|
|
||||||
QJsonObject _attrs;
|
QJsonObject _attrs;
|
||||||
QJsonObject _jobAttrs;
|
QJsonObject _jobAttrs;
|
||||||
QJsonArray _jobs;
|
QJsonArray _jobs;
|
||||||
|
|
||||||
QJsonObject _strings;
|
QJsonObject _strings;
|
||||||
|
QImage _icon;
|
||||||
|
|
||||||
QStringList _additionalDocumentFormats;
|
QStringList _additionalDocumentFormats;
|
||||||
|
|
||||||
QString _busyMessage;
|
QString _busyMessage;
|
||||||
QString _progress;
|
QString _progress;
|
||||||
|
|
||||||
QThread _workerThread;
|
PrinterWorker* _worker;
|
||||||
PrinterWorker _worker;
|
|
||||||
|
|
||||||
|
bool _iconRetried = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IPPPRINTER_H
|
#endif // IPPPRINTER_H
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "mimer.h"
|
#include "mimer.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
const QString Mimer::OctetStream = "application/octet-stream";
|
const QString Mimer::OctetStream = "application/octet-stream";
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@ const QString Mimer::PNG = "image/png";
|
||||||
const QString Mimer::GIF = "image/gif";
|
const QString Mimer::GIF = "image/gif";
|
||||||
const QString Mimer::JPEG = "image/jpeg";
|
const QString Mimer::JPEG = "image/jpeg";
|
||||||
const QString Mimer::TIFF = "image/tiff";
|
const QString Mimer::TIFF = "image/tiff";
|
||||||
|
const QString Mimer::SVG = "image/svg+xml";
|
||||||
|
const QString Mimer::RBMP = "image/reverse-encoding-bmp";
|
||||||
|
|
||||||
const QString Mimer::DOC = "application/msword";
|
const QString Mimer::DOC = "application/msword";
|
||||||
const QString Mimer::DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
const QString Mimer::DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||||
|
@ -23,6 +26,7 @@ const QString Mimer::ODP = "application/vnd.oasis.opendocument.presentation";
|
||||||
|
|
||||||
const QString Mimer::Plaintext = "text/plain";
|
const QString Mimer::Plaintext = "text/plain";
|
||||||
|
|
||||||
|
const QStringList Mimer::RasterFormats = {PWG, URF};
|
||||||
const QStringList Mimer::OfficeFormats = {DOC, DOCX, RTF, RTF_APP, ODT, PPT, PPTX, ODP};
|
const QStringList Mimer::OfficeFormats = {DOC, DOCX, RTF, RTF_APP, ODT, PPT, PPTX, ODP};
|
||||||
|
|
||||||
Mimer::Mimer()
|
Mimer::Mimer()
|
||||||
|
@ -49,5 +53,14 @@ Mimer* Mimer::instance()
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Mimer::get_type(QString filename) {
|
QString Mimer::get_type(QString filename) {
|
||||||
return _db.mimeTypeForFile(filename).name();
|
QString type = _db.mimeTypeForFile(filename).name();
|
||||||
|
qDebug() << "MimeType:" << type;
|
||||||
|
if(type == PDF || type == Postscript || type == Plaintext || isImage(type) || isOffice(type))
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
11
src/mimer.h
11
src/mimer.h
|
@ -24,6 +24,8 @@ public:
|
||||||
Q_PROPERTY(const QString GIF MEMBER GIF CONSTANT);
|
Q_PROPERTY(const QString GIF MEMBER GIF CONSTANT);
|
||||||
Q_PROPERTY(const QString JPEG MEMBER JPEG CONSTANT);
|
Q_PROPERTY(const QString JPEG MEMBER JPEG CONSTANT);
|
||||||
Q_PROPERTY(const QString TIFF MEMBER TIFF CONSTANT);
|
Q_PROPERTY(const QString TIFF MEMBER TIFF CONSTANT);
|
||||||
|
Q_PROPERTY(const QString SVG MEMBER SVG CONSTANT);
|
||||||
|
Q_PROPERTY(const QString RBMP MEMBER RBMP CONSTANT);
|
||||||
|
|
||||||
Q_PROPERTY(const QString DOC MEMBER DOC CONSTANT);
|
Q_PROPERTY(const QString DOC MEMBER DOC CONSTANT);
|
||||||
Q_PROPERTY(const QString DOCX MEMBER DOCX CONSTANT);
|
Q_PROPERTY(const QString DOCX MEMBER DOCX CONSTANT);
|
||||||
|
@ -49,6 +51,8 @@ public:
|
||||||
static const QString GIF;
|
static const QString GIF;
|
||||||
static const QString JPEG;
|
static const QString JPEG;
|
||||||
static const QString TIFF;
|
static const QString TIFF;
|
||||||
|
static const QString SVG;
|
||||||
|
static const QString RBMP;
|
||||||
|
|
||||||
static const QString DOC;
|
static const QString DOC;
|
||||||
static const QString DOCX;
|
static const QString DOCX;
|
||||||
|
@ -61,11 +65,16 @@ public:
|
||||||
|
|
||||||
static const QString Plaintext;
|
static const QString Plaintext;
|
||||||
|
|
||||||
|
static const QStringList RasterFormats;
|
||||||
static const QStringList OfficeFormats;
|
static const QStringList OfficeFormats;
|
||||||
|
|
||||||
Q_INVOKABLE static bool isImage(QString mimeType)
|
Q_INVOKABLE static bool isImage(QString mimeType)
|
||||||
{
|
{
|
||||||
return mimeType.startsWith("image/");
|
return mimeType.startsWith("image/") && ! isRaster(mimeType);
|
||||||
|
}
|
||||||
|
Q_INVOKABLE static bool isRaster(QString mimeType)
|
||||||
|
{
|
||||||
|
return RasterFormats.contains(mimeType);
|
||||||
}
|
}
|
||||||
Q_INVOKABLE static bool isOffice(QString mimeType)
|
Q_INVOKABLE static bool isOffice(QString mimeType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,7 @@ Overrider* Overrider::instance()
|
||||||
bool Overrider::apply(QJsonObject& attrs)
|
bool Overrider::apply(QJsonObject& attrs)
|
||||||
{
|
{
|
||||||
bool applied = false;
|
bool applied = false;
|
||||||
foreach(const QString& key, _overrides.keys())
|
for(const QString& key : _overrides.keys())
|
||||||
{
|
{
|
||||||
if(attrs.contains(key))
|
if(attrs.contains(key))
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ bool Overrider::apply(QJsonObject& attrs)
|
||||||
if(match != "" && _overrides[key].toObject().contains(match))
|
if(match != "" && _overrides[key].toObject().contains(match))
|
||||||
{
|
{
|
||||||
QJsonObject overrideden_data = _overrides[key].toObject()[match].toObject();
|
QJsonObject overrideden_data = _overrides[key].toObject()[match].toObject();
|
||||||
foreach(const QString& o_key, overrideden_data.keys())
|
for(const QString& o_key : overrideden_data.keys())
|
||||||
{
|
{
|
||||||
attrs.insert(o_key, overrideden_data[o_key]);
|
attrs.insert(o_key, overrideden_data[o_key]);
|
||||||
}
|
}
|
||||||
|
|
202
src/papersizes.h
202
src/papersizes.h
|
@ -3,208 +3,6 @@
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSizeF>
|
#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 =
|
static QMap<QString, QString> CalligraPaperSizes =
|
||||||
{{"iso_a0_841x1189mm", "A0"},
|
{{"iso_a0_841x1189mm", "A0"},
|
||||||
{"iso_a1_594x841mm", "A1"},
|
{"iso_a1_594x841mm", "A1"},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "printerworker.h"
|
#include "printerworker.h"
|
||||||
#include <sailfishapp.h>
|
|
||||||
#include "papersizes.h"
|
#include "papersizes.h"
|
||||||
#include "convertchecker.h"
|
#include "convertchecker.h"
|
||||||
#include "mimer.h"
|
#include "mimer.h"
|
||||||
|
@ -9,51 +8,188 @@
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
#include <QPdfWriter>
|
#include <QPdfWriter>
|
||||||
#include <QAbstractTextDocumentLayout>
|
#include <QAbstractTextDocumentLayout>
|
||||||
|
#include <QtSvg>
|
||||||
#include "ippprinter.h"
|
#include "ippprinter.h"
|
||||||
#include "pdf2printable.h"
|
#include "pdf2printable.h"
|
||||||
#include "ppm2pwg.h"
|
#include "ppm2pwg.h"
|
||||||
|
#include "baselinify.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#define OK(call) if(!(call)) throw ConvertFailedException()
|
#define OK(call) if(!(call)) throw ConvertFailedException()
|
||||||
|
|
||||||
PrinterWorker::PrinterWorker(IppPrinter* parent)
|
PrinterWorker::PrinterWorker(IppPrinter* parent)
|
||||||
{
|
{
|
||||||
_printer = 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)
|
void PrinterWorker::getStrings(QUrl url)
|
||||||
{
|
{
|
||||||
CurlRequester cr(url, CurlRequester::HttpGetRequest);
|
CurlRequester cr(url, CurlRequester::HttpGetRequest);
|
||||||
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::getStringsFinished);
|
awaitResult(cr, "getStringsFinished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrinterWorker::getImage(QUrl url)
|
||||||
|
{
|
||||||
|
CurlRequester cr(url, CurlRequester::HttpGetRequest);
|
||||||
|
awaitResult(cr, "getImageFinished");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PrinterWorker::getPrinterAttributes(Bytestream msg)
|
void PrinterWorker::getPrinterAttributes(Bytestream msg)
|
||||||
{
|
{
|
||||||
CurlRequester cr(_printer->httpUrl());
|
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
|
||||||
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::getPrinterAttributesFinished);
|
awaitResult(cr, "getPrinterAttributesFinished");
|
||||||
cr.write((char*)msg.raw(), msg.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrinterWorker::getJobs(Bytestream msg)
|
void PrinterWorker::getJobs(Bytestream msg)
|
||||||
{
|
{
|
||||||
CurlRequester cr(_printer->httpUrl());
|
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
|
||||||
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::getJobsRequestFinished);
|
awaitResult(cr, "getJobsRequestFinished");
|
||||||
cr.write((char*)msg.raw(), msg.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrinterWorker::cancelJob(Bytestream msg)
|
void PrinterWorker::cancelJob(Bytestream msg)
|
||||||
{
|
{
|
||||||
CurlRequester cr(_printer->httpUrl());
|
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
|
||||||
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::cancelJobFinished);
|
awaitResult(cr, "cancelJobFinished");
|
||||||
cr.write((char*)msg.raw(), msg.size());
|
}
|
||||||
|
|
||||||
|
void PrinterWorker::identify(Bytestream msg)
|
||||||
|
{
|
||||||
|
CurlRequester cr(_url, CurlRequester::IppRequest, &msg);
|
||||||
|
awaitResult(cr, "identifyFinished");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterWorker::print2(QString filename, QString mimeType, QString targetFormat, IppMsg createJob, IppMsg sendDocument, PrintParameters Params, QMargins margins)
|
||||||
|
{
|
||||||
|
emit busyMessage(tr("Preparing"));
|
||||||
|
|
||||||
|
Bytestream header = createJob.encode();
|
||||||
|
|
||||||
|
CurlRequester cr(_url, CurlRequester::IppRequest, &header);
|
||||||
|
|
||||||
|
Bytestream resData;
|
||||||
|
CURLcode res = cr.await(&resData);
|
||||||
|
|
||||||
|
if(res == CURLE_OK)
|
||||||
|
{
|
||||||
|
IppMsg resMsg(resData);
|
||||||
|
qDebug() << resMsg.getOpAttrs() << resMsg.getJobAttrs();
|
||||||
|
|
||||||
|
QJsonObject resJobAttrs = resMsg.getJobAttrs()[0].toObject();
|
||||||
|
if(resMsg.getStatus() <= 0xff && resJobAttrs.contains("job-id"))
|
||||||
|
{
|
||||||
|
int jobId = resJobAttrs["job-id"].toObject()["value"].toInt();
|
||||||
|
sendDocument.setOpAttr("job-id", IppMsg::Integer, jobId);
|
||||||
|
sendDocument.setOpAttr("last-document", IppMsg::Boolean, true);
|
||||||
|
print(filename, mimeType, targetFormat, sendDocument, Params, margins);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resData.setPos(0);
|
||||||
|
QMetaObject::invokeMethod(_printer, "printRequestFinished", Qt::QueuedConnection,
|
||||||
|
Q_ARG(CURLcode, res),
|
||||||
|
Q_ARG(Bytestream, resData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(_printer, "printRequestFinished", Qt::QueuedConnection,
|
||||||
|
Q_ARG(CURLcode, res),
|
||||||
|
Q_ARG(Bytestream, resData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterWorker::print(QString filename, QString mimeType, QString targetFormat, IppMsg job, PrintParameters Params, QMargins margins)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Mimer* mimer = Mimer::instance();
|
||||||
|
|
||||||
|
Bytestream contents = job.encode();
|
||||||
|
|
||||||
|
emit busyMessage(tr("Preparing"));
|
||||||
|
|
||||||
|
if((mimeType == targetFormat) && (targetFormat == Mimer::Postscript))
|
||||||
|
{ // Can't process Postscript
|
||||||
|
justUpload(filename, contents);
|
||||||
|
}
|
||||||
|
else if((mimeType == targetFormat) && (targetFormat == Mimer::Plaintext))
|
||||||
|
{
|
||||||
|
fixupPlaintext(filename, contents);
|
||||||
|
}
|
||||||
|
else if((mimeType != Mimer::SVG) && mimer->isImage(mimeType) && mimer->isImage(targetFormat))
|
||||||
|
{ // Just make sure the image is in the desired format (and jpeg baseline-encoded), don't resize locally
|
||||||
|
printImageAsImage(filename, contents, targetFormat);
|
||||||
|
}
|
||||||
|
else if(Params.format != PrintParameters::Invalid) // Params.format can be trusted
|
||||||
|
{
|
||||||
|
if(mimeType == Mimer::PDF)
|
||||||
|
{
|
||||||
|
convertPdf(filename, contents, Params);
|
||||||
|
}
|
||||||
|
else if(mimeType == Mimer::Plaintext)
|
||||||
|
{
|
||||||
|
if(Params.paperSizeH == 0 && Params.getPaperSizeWInMillimeters() < 26)
|
||||||
|
{
|
||||||
|
convertPlaintextLabel(filename, contents, Params);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
convertPlaintext(filename, contents, Params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Mimer::isImage(mimeType))
|
||||||
|
{
|
||||||
|
convertImage(filename, contents, Params, margins);
|
||||||
|
}
|
||||||
|
else if(Mimer::isOffice(mimeType))
|
||||||
|
{
|
||||||
|
convertOfficeDocument(filename, contents, Params);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit failed(tr("Cannot convert this file format"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit failed(tr("Cannot convert this file format"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch(const ConvertFailedException& e)
|
||||||
|
{
|
||||||
|
emit failed(e.what() == QString("") ? tr("Print error") : e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrinterWorker::justUpload(QString filename, Bytestream header)
|
void PrinterWorker::justUpload(QString filename, Bytestream header)
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
emit busyMessage(tr("Printing"));
|
emit busyMessage(tr("Printing"));
|
||||||
|
|
||||||
CurlRequester cr(_printer->httpUrl());
|
CurlRequester cr(_url);
|
||||||
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::printRequestFinished);
|
|
||||||
|
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
file.open(QFile::ReadOnly);
|
file.open(QFile::ReadOnly);
|
||||||
|
@ -62,51 +198,145 @@ try {
|
||||||
QByteArray tmp = file.readAll();
|
QByteArray tmp = file.readAll();
|
||||||
OK(cr.write(tmp.data(), tmp.length()));
|
OK(cr.write(tmp.data(), tmp.length()));
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
awaitResult(cr, "printRequestFinished");
|
||||||
}
|
}
|
||||||
catch(const ConvertFailedException& e)
|
|
||||||
|
void PrinterWorker::printImageAsImage(QString filename, Bytestream header, QString targetFormat)
|
||||||
{
|
{
|
||||||
emit failed(e.what() == QString("") ? tr("Upload error") : e.what());
|
QString imageFormat = "";
|
||||||
}
|
QStringList supportedImageFormats = {Mimer::JPEG, Mimer::PNG};
|
||||||
}
|
|
||||||
|
|
||||||
void PrinterWorker::convertPdf(QString filename, Bytestream header,
|
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
|
|
||||||
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
Format format;
|
|
||||||
|
|
||||||
emit busyMessage(tr("Printing"));
|
if(targetFormat == Mimer::RBMP)
|
||||||
|
|
||||||
if(targetFormat == Mimer::URF)
|
|
||||||
{
|
{
|
||||||
format = Format::URF;
|
// ok
|
||||||
}
|
}
|
||||||
else if(targetFormat == Mimer::PWG)
|
else if(supportedImageFormats.contains(targetFormat))
|
||||||
{
|
{
|
||||||
format = Format::PWG;
|
imageFormat = targetFormat.split("/")[1];
|
||||||
}
|
|
||||||
else if(targetFormat == Mimer::Postscript)
|
|
||||||
{
|
|
||||||
format = Format::Postscript;
|
|
||||||
}
|
|
||||||
else if (targetFormat == Mimer::PDF)
|
|
||||||
{
|
|
||||||
format = Format::PDF;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw ConvertFailedException(tr("Unsupported target format"));
|
throw ConvertFailedException(tr("Unknown target format"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Colors == 0)
|
QString mimeType = Mimer::instance()->get_type(filename);
|
||||||
|
Bytestream OutBts;
|
||||||
|
|
||||||
|
CurlRequester cr(_url);
|
||||||
|
|
||||||
|
if(mimeType == Mimer::JPEG && targetFormat == Mimer::JPEG)
|
||||||
{
|
{
|
||||||
Colors = 3;
|
std::ifstream ifs = std::ifstream(filename.toStdString(), std::ios::in | std::ios::binary);
|
||||||
|
Bytestream InBts(ifs);
|
||||||
|
|
||||||
|
baselinify(InBts, OutBts);
|
||||||
|
}
|
||||||
|
else if(targetFormat == Mimer::RBMP)
|
||||||
|
{
|
||||||
|
QImageReader reader(filename);
|
||||||
|
reader.setAutoTransform(true);
|
||||||
|
QImage inImage = reader.read();
|
||||||
|
QBuffer buf;
|
||||||
|
|
||||||
|
if(inImage.isNull())
|
||||||
|
{
|
||||||
|
qDebug() << "failed to load";
|
||||||
|
throw ConvertFailedException(tr("Failed to load image"));
|
||||||
}
|
}
|
||||||
|
|
||||||
CurlRequester cr(_printer->httpUrl());
|
// TODO: calculate paper width minus margins
|
||||||
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::printRequestFinished);
|
// (depends on understanding/parsing custom paper sizes)
|
||||||
|
int width = 576;
|
||||||
|
int height = inImage.height() * ((width*1.0)/inImage.width());
|
||||||
|
inImage = inImage.scaled(width, height);
|
||||||
|
inImage = inImage.convertToFormat(QImage::Format_Mono);
|
||||||
|
inImage = inImage.transformed(QMatrix().scale(1,-1));
|
||||||
|
buf.open(QIODevice::ReadWrite);
|
||||||
|
inImage.save(&buf, "bmp");
|
||||||
|
buf.seek(0);
|
||||||
|
OutBts = Bytestream(buf.size());
|
||||||
|
buf.read((char*)(OutBts.raw()), buf.size());
|
||||||
|
}
|
||||||
|
else if(targetFormat == mimeType)
|
||||||
|
{
|
||||||
|
std::ifstream ifs = std::ifstream(filename.toStdString(), std::ios::in | std::ios::binary);
|
||||||
|
OutBts = Bytestream(ifs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QImageReader reader(filename);
|
||||||
|
reader.setAutoTransform(true);
|
||||||
|
QImage inImage = reader.read();
|
||||||
|
QBuffer buf;
|
||||||
|
|
||||||
|
if(inImage.isNull())
|
||||||
|
{
|
||||||
|
qDebug() << "failed to load";
|
||||||
|
throw ConvertFailedException(tr("Failed to load image"));
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.open(QIODevice::ReadWrite);
|
||||||
|
inImage.save(&buf, imageFormat.toStdString().c_str());
|
||||||
|
buf.seek(0);
|
||||||
|
OutBts = Bytestream(buf.size());
|
||||||
|
buf.read((char*)(OutBts.raw()), buf.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
emit busyMessage(tr("Printing"));
|
||||||
|
|
||||||
|
OK(cr.write((char*)header.raw(), header.size()));
|
||||||
|
OK(cr.write((char*)OutBts.raw(), OutBts.size()));
|
||||||
|
|
||||||
|
awaitResult(cr, "printRequestFinished");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterWorker::fixupPlaintext(QString filename, Bytestream header)
|
||||||
|
{
|
||||||
|
CurlRequester cr(_url);
|
||||||
|
|
||||||
|
QFile inFile(filename);
|
||||||
|
if(!inFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
throw ConvertFailedException(tr("Failed to open file"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString allText = inFile.readAll();
|
||||||
|
if(allText.startsWith("\f"))
|
||||||
|
{
|
||||||
|
allText.remove(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(allText.endsWith("\f"))
|
||||||
|
{
|
||||||
|
allText.chop(1);
|
||||||
|
}
|
||||||
|
else if(allText.endsWith("\f\n"))
|
||||||
|
{
|
||||||
|
allText.chop(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList lines;
|
||||||
|
|
||||||
|
for(QString rnline : allText.split("\r\n"))
|
||||||
|
{
|
||||||
|
lines.append(rnline.split("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray outData = lines.join("\r\n").toUtf8();
|
||||||
|
|
||||||
|
OK(cr.write((char*)header.raw(), header.size()));
|
||||||
|
OK(cr.write(outData.data(), outData.length()));
|
||||||
|
|
||||||
|
awaitResult(cr, "printRequestFinished");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterWorker::convertPdf(QString filename, Bytestream header, PrintParameters Params)
|
||||||
|
{
|
||||||
|
emit busyMessage(tr("Printing"));
|
||||||
|
|
||||||
|
CurlRequester cr(_url);
|
||||||
|
|
||||||
OK(cr.write((char*)header.raw(), header.size()));
|
OK(cr.write((char*)header.raw(), header.size()));
|
||||||
|
|
||||||
|
@ -122,133 +352,124 @@ try {
|
||||||
emit progress(page, total);
|
emit progress(page, total);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!PaperSizes.contains(PaperSize))
|
|
||||||
{
|
|
||||||
qDebug() << "Unsupported paper size" << PaperSize;
|
|
||||||
throw ConvertFailedException(tr("Unsupported paper size"));
|
|
||||||
}
|
|
||||||
QSizeF size = PaperSizes[PaperSize];
|
|
||||||
float Width = size.width();
|
|
||||||
float Height = size.height();
|
|
||||||
|
|
||||||
bool verbose = QLoggingCategory::defaultCategory()->isDebugEnabled();
|
bool verbose = QLoggingCategory::defaultCategory()->isDebugEnabled();
|
||||||
|
|
||||||
int res = pdf_to_printable(filename.toStdString(), WriteFun, Colors, Quality, PaperSize.toStdString(), Width, Height, HwResX, HwResY,
|
int res = pdf_to_printable(filename.toStdString(), WriteFun, Params, ProgressFun, verbose);
|
||||||
format, TwoSided, Tumble, BackHFlip, BackVFlip, PageRangeLow, PageRangeHigh, ProgressFun, verbose);
|
|
||||||
|
|
||||||
if(res != 0)
|
if(res != 0)
|
||||||
{
|
{
|
||||||
throw ConvertFailedException(tr("Conversion failed"));
|
throw ConvertFailedException(tr("Conversion failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
awaitResult(cr, "printRequestFinished");
|
||||||
qDebug() << "Finished";
|
qDebug() << "Finished";
|
||||||
}
|
}
|
||||||
catch(const ConvertFailedException& e)
|
|
||||||
|
void PrinterWorker::convertImage(QString filename, Bytestream header, PrintParameters Params, QMargins margins)
|
||||||
{
|
{
|
||||||
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
|
QString mimeType = Mimer::instance()->get_type(filename);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrinterWorker::convertImage(QString filename, Bytestream header,
|
if(Params.format == PrintParameters::URF && (Params.hwResW != Params.hwResH))
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, QMargins margins)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
|
|
||||||
bool urf = false;
|
|
||||||
bool pdfOrPostscript = false;
|
|
||||||
QString imageFormat = "";
|
|
||||||
QStringList supportedImageFormats = {Mimer::JPEG, Mimer::PNG};
|
|
||||||
|
|
||||||
if(targetFormat == Mimer::URF)
|
|
||||||
{
|
|
||||||
urf = true;
|
|
||||||
}
|
|
||||||
else if(targetFormat == Mimer::PWG)
|
|
||||||
{
|
|
||||||
//ok
|
|
||||||
}
|
|
||||||
else if(targetFormat == Mimer::PDF || targetFormat == Mimer::Postscript)
|
|
||||||
{
|
|
||||||
HwResX = HwResY = std::min(HwResX, HwResY);
|
|
||||||
pdfOrPostscript = true;
|
|
||||||
}
|
|
||||||
else if(supportedImageFormats.contains(targetFormat))
|
|
||||||
{
|
|
||||||
imageFormat = targetFormat.split("/")[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw ConvertFailedException(tr("Unsupported target format"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Colors == 0)
|
|
||||||
{
|
|
||||||
Colors = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(urf && (HwResX != HwResY))
|
|
||||||
{ // URF only supports symmetric resolutions
|
{ // URF only supports symmetric resolutions
|
||||||
qDebug() << "Unsupported URF resolution" << PaperSize;
|
qDebug() << "Unsupported URF resolution";
|
||||||
throw ConvertFailedException(tr("Unsupported resolution (dpi)"));
|
throw ConvertFailedException(tr("Unsupported resolution (dpi)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!PaperSizes.contains(PaperSize))
|
qDebug() << "Size is" << Params.getPaperSizeWInPixels() << "x" << Params.getPaperSizeHInPixels();
|
||||||
{
|
|
||||||
qDebug() << "Unsupported paper size" << PaperSize;
|
|
||||||
throw ConvertFailedException(tr("Unsupported paper size"));
|
|
||||||
}
|
|
||||||
QSizeF size = PaperSizes[PaperSize];
|
|
||||||
quint32 Width = qRound(size.width()/25.4*HwResX);
|
|
||||||
quint32 Height = qRound(size.height()/25.4*HwResY);
|
|
||||||
|
|
||||||
qDebug() << "Size is" << Width << "x" << Height;
|
int leftMarginPx = (margins.left()/2540.0)*Params.hwResW;
|
||||||
|
int rightMarginPx = (margins.right()/2540.0)*Params.hwResW;
|
||||||
|
int topMarginPx = (margins.top()/2540.0)*Params.hwResH;
|
||||||
|
int bottomMarginPx = (margins.bottom()/2540.0)*Params.hwResH;
|
||||||
|
|
||||||
|
int totalXMarginPx = leftMarginPx+rightMarginPx;
|
||||||
|
int totalYMarginPx = topMarginPx+bottomMarginPx;
|
||||||
|
|
||||||
|
size_t targetWidth = Params.getPaperSizeWInPixels()-totalXMarginPx;
|
||||||
|
size_t targetHeight = Params.getPaperSizeHInPixels()-totalYMarginPx;
|
||||||
|
|
||||||
QImage inImage;
|
QImage inImage;
|
||||||
if(!inImage.load(filename))
|
if(mimeType == Mimer::SVG)
|
||||||
{
|
{
|
||||||
qDebug() << "failed to load";
|
QSvgRenderer renderer(filename);
|
||||||
|
if(!renderer.isValid())
|
||||||
|
{
|
||||||
|
qDebug() << "failed to load svg";
|
||||||
throw ConvertFailedException(tr("Failed to load image"));
|
throw ConvertFailedException(tr("Failed to load image"));
|
||||||
}
|
}
|
||||||
|
QSize defaultSize = renderer.defaultSize();
|
||||||
|
QSize targetSize(targetWidth, targetHeight);
|
||||||
|
|
||||||
|
if(defaultSize.width() > defaultSize.height())
|
||||||
|
{
|
||||||
|
targetSize.transpose();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize initialSize = defaultSize.scaled(targetSize, Qt::KeepAspectRatio);
|
||||||
|
|
||||||
|
inImage = QImage(initialSize, QImage::Format_RGB32);
|
||||||
|
inImage.fill(QColor("white"));
|
||||||
|
QPainter painter(&inImage);
|
||||||
|
|
||||||
|
renderer.render(&painter);
|
||||||
|
painter.end(); // Or else the painter segfaults on destruction if we have messed with the image
|
||||||
|
|
||||||
if(inImage.width() > inImage.height())
|
if(inImage.width() > inImage.height())
|
||||||
{
|
{
|
||||||
inImage = inImage.transformed(QMatrix().rotate(270.0));
|
inImage = inImage.transformed(QMatrix().rotate(270.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
int leftMarginPx = (margins.left()/2540.0)*HwResX;
|
}
|
||||||
int rightMarginPx = (margins.right()/2540.0)*HwResX;
|
else
|
||||||
int topMarginPx = (margins.top()/2540.0)*HwResY;
|
{
|
||||||
int bottomMarginPx = (margins.bottom()/2540.0)*HwResY;
|
QImageReader reader(filename);
|
||||||
|
reader.setAutoTransform(true);
|
||||||
|
inImage = reader.read();
|
||||||
|
|
||||||
int totalXMarginPx = leftMarginPx+rightMarginPx;
|
if(inImage.isNull())
|
||||||
int totalYMarginPx = topMarginPx+bottomMarginPx;
|
{
|
||||||
|
qDebug() << "failed to load";
|
||||||
|
throw ConvertFailedException(tr("Failed to load image"));
|
||||||
|
}
|
||||||
|
if(inImage.width() > inImage.height())
|
||||||
|
{
|
||||||
|
inImage = inImage.transformed(QMatrix().rotate(270.0));
|
||||||
|
}
|
||||||
|
|
||||||
inImage = inImage.scaled(Width-totalXMarginPx, Height-totalYMarginPx,
|
inImage = inImage.scaled(targetWidth, targetHeight,
|
||||||
Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
}
|
||||||
|
|
||||||
if(pdfOrPostscript)
|
|
||||||
|
if(Params.format == PrintParameters::PDF || Params.format == PrintParameters::Postscript)
|
||||||
{
|
{
|
||||||
QTemporaryFile tmpPdfFile;
|
QTemporaryFile tmpPdfFile;
|
||||||
tmpPdfFile.open();
|
tmpPdfFile.open();
|
||||||
QPdfWriter pdfWriter(tmpPdfFile.fileName());
|
QPdfWriter pdfWriter(tmpPdfFile.fileName());
|
||||||
pdfWriter.setCreator("SeaPrint " SEAPRINT_VERSION);
|
pdfWriter.setCreator("SeaPrint " SEAPRINT_VERSION);
|
||||||
QPageSize pageSize(size, QPageSize::Millimeter);
|
QPageSize pageSize({Params.getPaperSizeWInPoints(), Params.getPaperSizeHInPoints()}, QPageSize::Point);
|
||||||
pdfWriter.setPageSize(pageSize);
|
pdfWriter.setPageSize(pageSize);
|
||||||
pdfWriter.setResolution(HwResX);
|
pdfWriter.setResolution(Params.hwResH);
|
||||||
QPainter painter(&pdfWriter);
|
QPainter painter(&pdfWriter);
|
||||||
int xOffset = ((pdfWriter.width()-totalXMarginPx)-inImage.width())/2 + leftMarginPx;
|
int xOffset = ((pdfWriter.width()-totalXMarginPx)-inImage.width())/2 + leftMarginPx;
|
||||||
int yOffset = ((pdfWriter.height()-totalYMarginPx)-inImage.height())/2 + topMarginPx;
|
int yOffset = ((pdfWriter.height()-totalYMarginPx)-inImage.height())/2 + topMarginPx;
|
||||||
painter.drawImage(xOffset, yOffset, inImage);
|
painter.drawImage(xOffset, yOffset, inImage);
|
||||||
painter.end();
|
painter.end();
|
||||||
|
|
||||||
convertPdf(tmpPdfFile.fileName(), header, targetFormat, Colors, Quality, PaperSize,
|
convertPdf(tmpPdfFile.fileName(), header, Params);
|
||||||
HwResX, HwResY, false, false, 0, 0, false, false);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QImage outImage = QImage(Width, Height, inImage.format());
|
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);
|
outImage.fill(Qt::white);
|
||||||
QPainter painter(&outImage);
|
QPainter painter(&outImage);
|
||||||
int xOffset = ((outImage.width()-totalXMarginPx)-inImage.width())/2 + leftMarginPx;
|
int xOffset = ((outImage.width()-totalXMarginPx)-inImage.width())/2 + leftMarginPx;
|
||||||
|
@ -258,30 +479,24 @@ try {
|
||||||
|
|
||||||
QBuffer buf;
|
QBuffer buf;
|
||||||
buf.open(QIODevice::ReadWrite);
|
buf.open(QIODevice::ReadWrite);
|
||||||
Bytestream outBts;
|
Bytestream fileHdr, outBts;
|
||||||
|
|
||||||
if(imageFormat != "")
|
|
||||||
{ // We are converting to a supported image format
|
if(inImage.allGray())
|
||||||
outImage.save(&buf, imageFormat.toStdString().c_str());
|
{
|
||||||
buf.seek(0);
|
Params.colors = 1; // No need to waste space/bandwidth...
|
||||||
outBts = Bytestream(buf.size());
|
|
||||||
buf.read((char*)(outBts.raw()), buf.size());
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{ // We are converting to a raster format
|
|
||||||
|
|
||||||
bool gray = Colors == 0 ? inImage.allGray() : Colors == 1;
|
outImage.save(&buf, Params.colors==1 ? "pgm" : "ppm");
|
||||||
|
|
||||||
outImage.save(&buf, gray ? "pgm" : "ppm");
|
|
||||||
buf.seek(0);
|
buf.seek(0);
|
||||||
// Skip header - TODO consider reimplementing
|
// Skip header - TODO consider reimplementing
|
||||||
buf.readLine(255);
|
buf.readLine(255);
|
||||||
buf.readLine(255);
|
buf.readLine(255);
|
||||||
buf.readLine(255);
|
buf.readLine(255);
|
||||||
|
|
||||||
Bytestream inBts(Width*Height*Colors);
|
Bytestream inBts(Params.getPaperSizeWInPixels() * Params.getPaperSizeHInPixels() * Params.colors);
|
||||||
|
|
||||||
if((buf.size()-buf.pos()) != inBts.size())
|
if((((size_t)buf.size())-buf.pos()) != inBts.size())
|
||||||
{
|
{
|
||||||
qDebug() << buf.size() << buf.pos() << inBts.size();
|
qDebug() << buf.size() << buf.pos() << inBts.size();
|
||||||
throw ConvertFailedException();
|
throw ConvertFailedException();
|
||||||
|
@ -289,51 +504,46 @@ try {
|
||||||
|
|
||||||
buf.read((char*)(inBts.raw()), inBts.size());
|
buf.read((char*)(inBts.raw()), inBts.size());
|
||||||
|
|
||||||
outBts << (urf ? make_urf_file_hdr(1) : make_pwg_file_hdr());
|
fileHdr << (Params.format == PrintParameters::URF ? make_urf_file_hdr(1) : make_pwg_file_hdr());
|
||||||
|
|
||||||
bool verbose = QLoggingCategory::defaultCategory()->isDebugEnabled();
|
bool verbose = QLoggingCategory::defaultCategory()->isDebugEnabled();
|
||||||
|
|
||||||
bmp_to_pwg(inBts, outBts, urf, 1, Colors, Quality, HwResX, HwResY, Width, Height, false, false, PaperSize.toStdString(), false, false, verbose);
|
bmp_to_pwg(inBts, outBts, 1, Params, verbose);
|
||||||
emit busyMessage(tr("Printing"));
|
|
||||||
}
|
|
||||||
|
|
||||||
CurlRequester cr(_printer->httpUrl());
|
CurlRequester cr(_url);
|
||||||
connect(&cr, &CurlRequester::done, _printer, &IppPrinter::printRequestFinished);
|
|
||||||
|
emit busyMessage(tr("Printing"));
|
||||||
|
|
||||||
OK(cr.write((char*)header.raw(), header.size()));
|
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()));
|
OK(cr.write((char*)(outBts.raw()), outBts.size()));
|
||||||
|
emit progress(c+1, total_pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
awaitResult(cr, "printRequestFinished");
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "posted";
|
qDebug() << "posted";
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(const ConvertFailedException& e)
|
|
||||||
|
void PrinterWorker::convertOfficeDocument(QString filename, Bytestream header, PrintParameters Params)
|
||||||
{
|
{
|
||||||
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
|
if(Params.format == PrintParameters::URF && (Params.hwResW != Params.hwResH))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrinterWorker::convertOfficeDocument(QString filename, Bytestream header,
|
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
|
|
||||||
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
|
|
||||||
if(targetFormat == Mimer::URF && (HwResX != HwResY))
|
|
||||||
{ // URF only supports symmetric resolutions
|
{ // URF only supports symmetric resolutions
|
||||||
qDebug() << "Unsupported URF resolution" << PaperSize;
|
qDebug() << "Unsupported URF resolution";
|
||||||
throw ConvertFailedException(tr("Unsupported resolution (dpi)"));
|
throw ConvertFailedException(tr("Unsupported resolution (dpi)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ShortPaperSize;
|
QString ShortPaperSize;
|
||||||
if(CalligraPaperSizes.contains(PaperSize))
|
if(CalligraPaperSizes.contains(Params.paperSizeName.c_str()))
|
||||||
{
|
{
|
||||||
ShortPaperSize = CalligraPaperSizes[PaperSize];
|
ShortPaperSize = CalligraPaperSizes[Params.paperSizeName.c_str()];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "Unsupported PDF paper size" << PaperSize;
|
qDebug() << "Unsupported PDF paper size" << Params.paperSizeName.c_str();
|
||||||
throw ConvertFailedException(tr("Unsupported PDF paper size"));
|
throw ConvertFailedException(tr("Unsupported PDF paper size"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,53 +580,29 @@ try {
|
||||||
|
|
||||||
// qDebug() << CalligraConverter->readAllStandardError();
|
// qDebug() << CalligraConverter->readAllStandardError();
|
||||||
|
|
||||||
quint32 pages = ConvertChecker::instance()->pdfPages(tmpPdfFile.fileName());
|
convertPdf(tmpPdfFile.fileName(), header, Params);
|
||||||
if (!pages)
|
|
||||||
{
|
|
||||||
qDebug() << "pdfinfo returned 0 pages";
|
|
||||||
throw ConvertFailedException(tr("Failed to get info about PDF file"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(PageRangeLow==0)
|
|
||||||
{
|
|
||||||
PageRangeLow=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(PageRangeHigh==0 || PageRangeHigh > pages)
|
|
||||||
{
|
|
||||||
PageRangeHigh=pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual number of pages to print
|
|
||||||
pages = PageRangeHigh-PageRangeLow+1;
|
|
||||||
|
|
||||||
qDebug() << "PageRangeLow" << PageRangeLow << "PageRangeHigh" << PageRangeHigh << "pages" << pages;
|
|
||||||
|
|
||||||
convertPdf(tmpPdfFile.fileName(), header, targetFormat, Colors, Quality, PaperSize, HwResX, HwResY, TwoSided, Tumble,
|
|
||||||
PageRangeLow, PageRangeHigh, BackHFlip, BackVFlip);
|
|
||||||
|
|
||||||
qDebug() << "posted";
|
qDebug() << "posted";
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(const ConvertFailedException& e)
|
|
||||||
|
void PrinterWorker::convertPlaintext(QString filename, Bytestream header, PrintParameters Params)
|
||||||
{
|
{
|
||||||
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrinterWorker::convertPlaintext(QString filename, Bytestream header,
|
QPageSize pageSize;
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
|
|
||||||
bool BackHFlip, bool BackVFlip)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
|
|
||||||
if(!PaperSizes.contains(PaperSize))
|
if(Params.paperSizeUnits == PrintParameters::Millimeters)
|
||||||
{
|
{
|
||||||
qDebug() << "Unsupported paper size" << PaperSize;
|
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
|
||||||
|
{
|
||||||
|
qDebug() << "Unsupported paper size" << Params.paperSizeName.c_str();
|
||||||
throw ConvertFailedException(tr("Unsupported paper size"));
|
throw ConvertFailedException(tr("Unsupported paper size"));
|
||||||
}
|
}
|
||||||
QSizeF size = PaperSizes[PaperSize];
|
|
||||||
|
|
||||||
QFile inFile(filename);
|
QFile inFile(filename);
|
||||||
if(!inFile.open(QIODevice::ReadOnly))
|
if(!inFile.open(QIODevice::ReadOnly))
|
||||||
|
@ -424,14 +610,14 @@ try {
|
||||||
throw ConvertFailedException(tr("Failed to open file"));
|
throw ConvertFailedException(tr("Failed to open file"));
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 resolution = std::min(HwResX, HwResY);
|
quint32 resolution = std::min(Params.hwResW, Params.hwResH);
|
||||||
|
|
||||||
QTemporaryFile tmpPdfFile;
|
QTemporaryFile tmpPdfFile;
|
||||||
tmpPdfFile.open();
|
tmpPdfFile.open();
|
||||||
|
|
||||||
QPdfWriter pdfWriter(tmpPdfFile.fileName());
|
QPdfWriter pdfWriter(tmpPdfFile.fileName());
|
||||||
pdfWriter.setCreator("SeaPrint " SEAPRINT_VERSION);
|
pdfWriter.setCreator("SeaPrint " SEAPRINT_VERSION);
|
||||||
QPageSize pageSize(size, QPageSize::Millimeter);
|
|
||||||
pdfWriter.setPageSize(pageSize);
|
pdfWriter.setPageSize(pageSize);
|
||||||
pdfWriter.setResolution(resolution);
|
pdfWriter.setResolution(resolution);
|
||||||
|
|
||||||
|
@ -470,7 +656,6 @@ try {
|
||||||
doc.setDefaultFont(font);
|
doc.setDefaultFont(font);
|
||||||
(void)doc.documentLayout(); // wat
|
(void)doc.documentLayout(); // wat
|
||||||
|
|
||||||
|
|
||||||
// Needs to be before painter
|
// Needs to be before painter
|
||||||
pdfWriter.setMargins({mmMargin, mmMargin, mmMargin, mmMargin});
|
pdfWriter.setMargins({mmMargin, mmMargin, mmMargin, mmMargin});
|
||||||
|
|
||||||
|
@ -506,7 +691,7 @@ try {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
int pageCount = 0;
|
int pageCount = 0;
|
||||||
|
|
||||||
foreach(QString page, pages)
|
for(QString page : pages)
|
||||||
{
|
{
|
||||||
if(!first)
|
if(!first)
|
||||||
{
|
{
|
||||||
|
@ -524,6 +709,7 @@ try {
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
|
painter.save();
|
||||||
painter.translate(body.left(), body.top() - p*body.height());
|
painter.translate(body.left(), body.top() - p*body.height());
|
||||||
QRectF view(0, p*body.height(), body.width(), body.height());
|
QRectF view(0, p*body.height(), body.width(), body.height());
|
||||||
painter.setClipRect(view);
|
painter.setClipRect(view);
|
||||||
|
@ -532,6 +718,7 @@ try {
|
||||||
context.clip = view;
|
context.clip = view;
|
||||||
context.palette.setColor(QPalette::Text, Qt::black);
|
context.palette.setColor(QPalette::Text, Qt::black);
|
||||||
doc.documentLayout()->draw(&painter, context);
|
doc.documentLayout()->draw(&painter, context);
|
||||||
|
painter.restore();
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
pageCount++;
|
pageCount++;
|
||||||
|
@ -545,15 +732,81 @@ try {
|
||||||
|
|
||||||
painter.end();
|
painter.end();
|
||||||
|
|
||||||
convertPdf(tmpPdfFile.fileName(), header, targetFormat, Colors, Quality, PaperSize, HwResX, HwResY,
|
convertPdf(tmpPdfFile.fileName(), header, Params);
|
||||||
TwoSided, Tumble, 0, 0, BackHFlip, BackVFlip);
|
|
||||||
|
|
||||||
qDebug() << "Finished";
|
qDebug() << "Finished";
|
||||||
qDebug() << "posted";
|
qDebug() << "posted";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
void PrinterWorker::convertPlaintextLabel(QString filename, Bytestream header, PrintParameters Params)
|
||||||
catch(const ConvertFailedException& e)
|
|
||||||
{
|
{
|
||||||
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
|
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;
|
||||||
|
CURLcode res = cr.await(&resMsg);
|
||||||
|
QMetaObject::invokeMethod(_printer, callback.toStdString().c_str(), Qt::QueuedConnection,
|
||||||
|
Q_ARG(CURLcode, res),
|
||||||
|
Q_ARG(Bytestream, resMsg));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
#ifndef PRINTERWORKER_H
|
#ifndef PRINTERWORKER_H
|
||||||
#define PRINTERWORKER_H
|
#define PRINTERWORKER_H
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QtNetwork>
|
#include <memory>
|
||||||
#include "curlrequester.h"
|
#include "curlrequester.h"
|
||||||
|
#include "ippmsg.h"
|
||||||
|
#include "ppm2pwg/printparameters.h"
|
||||||
|
|
||||||
class IppPrinter;
|
class IppPrinter;
|
||||||
|
|
||||||
class ConvertFailedException: public std::exception
|
class ConvertFailedException: public std::exception
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
QString _msg;
|
std::string _msg;
|
||||||
public:
|
public:
|
||||||
ConvertFailedException(QString msg = "") : _msg(msg = msg)
|
ConvertFailedException(QString msg = "") : _msg(msg.toStdString())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual const char* what() const throw()
|
virtual const char* what() const throw()
|
||||||
{
|
{
|
||||||
return _msg.toStdString().c_str();
|
return _msg.c_str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,46 +28,45 @@ class PrinterWorker : public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PrinterWorker(IppPrinter* parent);
|
PrinterWorker(IppPrinter* parent);
|
||||||
|
~PrinterWorker();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PrinterWorker();
|
PrinterWorker();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void urlChanged(QUrl url);
|
||||||
void getStrings(QUrl url);
|
void getStrings(QUrl url);
|
||||||
|
void getImage(QUrl url);
|
||||||
void getPrinterAttributes(Bytestream msg);
|
void getPrinterAttributes(Bytestream msg);
|
||||||
void getJobs(Bytestream msg);
|
void getJobs(Bytestream msg);
|
||||||
void cancelJob(Bytestream msg);
|
void cancelJob(Bytestream msg);
|
||||||
|
void identify(Bytestream msg);
|
||||||
|
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);
|
||||||
|
|
||||||
void justUpload(QString filename, Bytestream header);
|
private slots:
|
||||||
|
void cleanup();
|
||||||
void convertPdf(QString filename, Bytestream header,
|
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
|
|
||||||
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
|
|
||||||
|
|
||||||
void convertImage(QString filename, Bytestream header,
|
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, QMargins margins);
|
|
||||||
|
|
||||||
void convertOfficeDocument(QString filename, Bytestream header,
|
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
|
|
||||||
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
|
|
||||||
|
|
||||||
void convertPlaintext(QString filename, Bytestream header,
|
|
||||||
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
|
|
||||||
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble, bool BackHFlip, bool BackVFlip);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void done(QNetworkRequest request, QTemporaryFile* data);
|
|
||||||
void progress(qint64 done, qint64 pages);
|
void progress(qint64 done, qint64 pages);
|
||||||
void busyMessage(QString msg);
|
void busyMessage(QString msg);
|
||||||
void failed(QString message);
|
void failed(QString message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void justUpload(QString filename, Bytestream header);
|
||||||
|
void printImageAsImage(QString filename, Bytestream header, QString targetFormat);
|
||||||
|
void fixupPlaintext(QString filename, Bytestream header);
|
||||||
|
void convertPdf(QString filename, Bytestream header, PrintParameters Params);
|
||||||
|
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);
|
||||||
|
|
||||||
IppPrinter* _printer;
|
void awaitResult(CurlRequester& cr, QString callback);
|
||||||
|
|
||||||
|
std::unique_ptr<QThread> _thread;
|
||||||
|
QPointer<IppPrinter> _printer;
|
||||||
|
QUrl _url;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PRINTERWORKER_H
|
#endif // PRINTERWORKER_H
|
||||||
|
|
47
src/rangelistchecker.cpp
Normal file
47
src/rangelistchecker.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#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;
|
||||||
|
}
|
29
src/rangelistchecker.h
Normal file
29
src/rangelistchecker.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
21
src/seaprintdbusadaptor.cpp
Normal file
21
src/seaprintdbusadaptor.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#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);
|
||||||
|
}
|
21
src/seaprintdbusadaptor.h
Normal file
21
src/seaprintdbusadaptor.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#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
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
|
|
||||||
Settings::Settings() : _ignoreSslErrorsSetting("/apps/harbour-seaprint/settings/ignore-ssl-errors", this),
|
Settings::Settings() : _ignoreSslErrorsSetting("/apps/harbour-seaprint/settings/ignore-ssl-errors", this),
|
||||||
_debugLogSetting("/apps/harbour-seaprint/settings/debug-log", this)
|
_debugLogSetting("/apps/harbour-seaprint/settings/debug-log", this),
|
||||||
|
_allowExternalConnectionsSetting("/apps/harbour-seaprint/settings/allow-external-connections", this)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,3 +49,13 @@ QString Settings::debugLogPath()
|
||||||
{
|
{
|
||||||
return _debugLogSetting.key();
|
return _debugLogSetting.key();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Settings::allowExternalConnections()
|
||||||
|
{
|
||||||
|
return _allowExternalConnectionsSetting.value(_allowExternalConnectionsDefault).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Settings::allowExternalConnectionsPath()
|
||||||
|
{
|
||||||
|
return _allowExternalConnectionsSetting.key();
|
||||||
|
}
|
||||||
|
|
|
@ -10,14 +10,19 @@ public:
|
||||||
|
|
||||||
Q_PROPERTY(QString ignoreSslErrorsPath READ ignoreSslErrorsPath CONSTANT)
|
Q_PROPERTY(QString ignoreSslErrorsPath READ ignoreSslErrorsPath CONSTANT)
|
||||||
Q_PROPERTY(bool ignoreSslErrorsDefault MEMBER _ignoreSslErrorsDefault CONSTANT)
|
Q_PROPERTY(bool ignoreSslErrorsDefault MEMBER _ignoreSslErrorsDefault CONSTANT)
|
||||||
|
|
||||||
Q_PROPERTY(QString debugLogPath READ debugLogPath CONSTANT)
|
Q_PROPERTY(QString debugLogPath READ debugLogPath CONSTANT)
|
||||||
Q_PROPERTY(bool debugLogDefault MEMBER _debugLogDefault CONSTANT)
|
Q_PROPERTY(bool debugLogDefault MEMBER _debugLogDefault CONSTANT)
|
||||||
|
|
||||||
|
Q_PROPERTY(QString allowExternalConnectionsPath READ allowExternalConnectionsPath CONSTANT)
|
||||||
|
Q_PROPERTY(bool allowExternalConnectionsDefault MEMBER _allowExternalConnectionsDefault CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Settings* instance();
|
static Settings* instance();
|
||||||
|
|
||||||
bool ignoreSslErrors();
|
bool ignoreSslErrors();
|
||||||
bool debugLog();
|
bool debugLog();
|
||||||
|
bool allowExternalConnections();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Settings();
|
Settings();
|
||||||
|
@ -29,12 +34,15 @@ private:
|
||||||
|
|
||||||
MGConfItem _ignoreSslErrorsSetting;
|
MGConfItem _ignoreSslErrorsSetting;
|
||||||
MGConfItem _debugLogSetting;
|
MGConfItem _debugLogSetting;
|
||||||
|
MGConfItem _allowExternalConnectionsSetting;
|
||||||
|
|
||||||
QString ignoreSslErrorsPath();
|
QString ignoreSslErrorsPath();
|
||||||
QString debugLogPath();
|
QString debugLogPath();
|
||||||
|
QString allowExternalConnectionsPath();
|
||||||
|
|
||||||
bool _ignoreSslErrorsDefault = true;
|
bool _ignoreSslErrorsDefault = true;
|
||||||
bool _debugLogDefault = false;
|
bool _debugLogDefault = false;
|
||||||
|
bool _allowExternalConnectionsDefault = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
#include "svgprovider.h"
|
|
||||||
|
|
||||||
|
|
||||||
SvgProvider::SvgProvider() : QQuickImageProvider(QQuickImageProvider::Image, ForceAsynchronousImageLoading)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SvgProvider::~SvgProvider() {
|
|
||||||
}
|
|
||||||
|
|
||||||
SvgProvider* SvgProvider::m_Instance = nullptr;
|
|
||||||
|
|
||||||
SvgProvider* SvgProvider::instance()
|
|
||||||
{
|
|
||||||
static QMutex mutex;
|
|
||||||
if (!m_Instance)
|
|
||||||
{
|
|
||||||
mutex.lock();
|
|
||||||
|
|
||||||
if (!m_Instance)
|
|
||||||
m_Instance = new SvgProvider;
|
|
||||||
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage SvgProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
|
|
||||||
{
|
|
||||||
QSvgRenderer renderer(SailfishApp::pathTo(id).toLocalFile());
|
|
||||||
*size = requestedSize.isValid() ? requestedSize : renderer.defaultSize();
|
|
||||||
|
|
||||||
QImage img(*size, QImage::Format_ARGB32);
|
|
||||||
img.fill(QColor("transparent"));
|
|
||||||
QPainter painter(&img);
|
|
||||||
|
|
||||||
renderer.render(&painter);
|
|
||||||
|
|
||||||
return img;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef SVGPROVIDER_H
|
|
||||||
#define SVGPROVIDER_H
|
|
||||||
|
|
||||||
#include <QQuickImageProvider>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QtSvg/QSvgRenderer>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QtDebug>
|
|
||||||
#include <sailfishapp.h>
|
|
||||||
|
|
||||||
class SvgProvider : public QQuickImageProvider
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static SvgProvider* instance();
|
|
||||||
|
|
||||||
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
SvgProvider();
|
|
||||||
~SvgProvider();
|
|
||||||
SvgProvider(const SvgProvider &);
|
|
||||||
SvgProvider& operator=(const SvgProvider &);
|
|
||||||
|
|
||||||
static SvgProvider* m_Instance;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SVGPROVIDER_H
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue