Merge pull request #2 from attah/master

Updated from original project
This commit is contained in:
Carmen F. B 2020-06-08 18:05:47 +02:00 committed by GitHub
commit 06633bc537
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 3834 additions and 970 deletions

1
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1 @@
custom: paypal.me/AntonThomasson

4
.gitignore vendored
View file

@ -41,3 +41,7 @@ target_wrapper.*
# QtCreator CMake
CMakeLists.txt.user*
# Automatically generated
seaprint_version.h

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "ppm2pwg"]
path = ppm2pwg
url = https://github.com/attah/ppm2pwg.git

View file

@ -22,18 +22,26 @@ VERSION_H = \
write_file($$$$OUT_PWD/seaprint_version.h, VERSION_H)
SOURCES += src/harbour-seaprint.cpp \
src/convertchecker.cpp \
src/convertworker.cpp \
src/ippdiscovery.cpp \
src/bytestream.cpp \
src/ippmsg.cpp \
src/ippprinter.cpp
src/ippprinter.cpp \
src/mimer.cpp \
ppm2pwg/ppm2pwg.cpp \
ppm2pwg/bytestream/bytestream.cpp
DISTFILES += qml/harbour-seaprint.qml \
qml/components/LargeChoiceDialog.qml \
qml/cover/CoverPage.qml \
qml/components/*.qml \
qml/pages/*.qml \
qml/pages/*.js \
qml/pages/*svg \
qml/pages/BusyPage.qml \
qml/pages/DebugPage.qml \
qml/pages/NagScreen.qml \
qml/pages/SettingsPage.qml \
rpm/harbour-seaprint.changes.in \
rpm/harbour-seaprint.changes.run.in \
rpm/harbour-seaprint.spec \
@ -57,7 +65,17 @@ TRANSLATIONS += translations/harbour-seaprint-de.ts \
translations/harbour-seaprint-es.ts
HEADERS += \
src/convertchecker.h \
src/convertworker.h \
src/ippdiscovery.h \
src/bytestream.h \
src/ippmsg.h \
src/ippprinter.h
src/ippprinter.h \
src/mimer.h \
ppm2pwg/pwg_pghdr_codable.h \
ppm2pwg/urf_pghdr_codable.h \
ppm2pwg/bytestream/bytestream.h \
ppm2pwg/bytestream/codable.h \
src/papersizes.h
INCLUDEPATH += ppm2pwg \
ppm2pwg/bytestream

1
ppm2pwg Submodule

@ -0,0 +1 @@
Subproject commit 8565ddfe2e401e627daeca55d1b821085a1af0ea

View file

@ -1,9 +1,15 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import seaprint.convertchecker 1.0
import "../pages/utils.js" as Utils
Setting {
property var choices
property string mime_type
property var limited_choices: Utils.limitChoices(name, choices, mime_type, ConvertChecker)
property int num_large_choices: 8
ValueButton {
enabled: valid
@ -13,15 +19,27 @@ Setting {
onClicked: parent.clicked()
}
onClicked: {
if(limited_choices.length>num_large_choices)
{
var dialog = pageStack.push("LargeChoiceDialog.qml",
{name:name, choice: choice ? choice : default_choice, choices: limited_choices})
dialog.accepted.connect(function() {
choice = dialog.choice
})
}
}
property var menu: ContextMenu {
id: menu
enabled: valid && limited_choices.length <= num_large_choices
Repeater {
model: choices
model: limited_choices
MenuItem {
text: Utils.ippName(name, choices[index])
text: Utils.ippName(name, limited_choices[index])
onClicked:
{
choice = choices[index];
choice = limited_choices[index];
}
}
}

View file

@ -16,6 +16,7 @@ Setting {
property var menu: ContextMenu {
id: menu
enabled: valid
MenuItem {
Slider
{

View file

@ -0,0 +1,40 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../pages/utils.js" as Utils
Dialog {
id: dialog
property string name
property string choice
property string new_choice: choice
property var choices
canAccept: false
SilicaListView
{
anchors.fill: parent
header: DialogHeader {}
model: choices
delegate: BackgroundItem {
onClicked: {
new_choice=choices[index]
dialog.canAccept = true
}
Label {
x: Theme.paddingLarge
anchors.verticalCenter: parent.verticalCenter
highlighted: choices[index]==new_choice
text: Utils.ippName(name, choices[index])
}
}
}
onDone: {
if (result == DialogResult.Accepted) {
choice = new_choice
}
}
}

View file

@ -20,6 +20,7 @@ Setting {
property var menu: ContextMenu {
id: menu
enabled: valid
MenuItem {
}

View file

@ -2,6 +2,7 @@ import QtQuick 2.0
import Sailfish.Silica 1.0
import QtQuick.LocalStorage 2.0
import Nemo.Notifications 1.0
import Nemo.Configuration 1.0
import "pages"
ApplicationWindow
@ -73,5 +74,42 @@ ApplicationWindow
publish()
}
}
ConfigurationValue
{
id: nagScreenSetting
key: "/apps/harbour-seaprint/settings/nag-screen"
defaultValue: 0
property int expectedValue: 1
}
ConfigurationValue
{
id: considerAdditionalFormatsSetting
key: "/apps/harbour-seaprint/settings/consider-additional-formats"
defaultValue: true
}
ConfigurationValue
{
id: alwaysConvertSetting
key: "/apps/harbour-seaprint/settings/always-convert"
defaultValue: false
}
ConfigurationValue
{
id: forceIncluDeDocumentFormatSetting
key: "/apps/harbour-seaprint/settings/force-include-document-format"
defaultValue: false
}
ConfigurationValue
{
id: removeRedundantConvertAttrsSetting
key: "/apps/harbour-seaprint/settings/remove-redundant-convert-attributes"
defaultValue: true
}
}

View file

@ -1,5 +1,6 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import seaprint.convertchecker 1.0
import "../components"
Page {
@ -61,7 +62,7 @@ Page {
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
color: Theme.primaryColor
text: "© 2019 Anton Thomasson"
text: "© 2019-2020 Anton Thomasson"
}
AboutLabel {
@ -89,8 +90,16 @@ Page {
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
text: qsTr("Chinese")+" - dashinfantry\n"+
qsTr("French")+" - ensag-dev\n"+
qsTr("Spanish")+" - carmenfdezb"
qsTr("French")+" - ensag-dev, Quentí\n"+
qsTr("Spanish")+" - carmenfdezb\n"+
qsTr("Polish")+" - atlochowski"
}
SectionHeader { text: qsTr("Optional dependencies") }
AboutLabel {
font.pixelSize: Theme.fontSizeSmall
text: "poppler-utils - "+(ConvertChecker.pdf ? qsTr("Installed") : qsTr("Not installed"))
}
SectionHeader { text: qsTr("Licensing") }

35
qml/pages/BusyPage.qml Normal file
View file

@ -0,0 +1,35 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import "utils.js" as Utils
Page {
property var printer
backNavigation: false
Connections {
target: printer
onJobFinished: {
var msg = qsTr("Unknown")
if (printer.jobAttrs.hasOwnProperty("job-state-message") && printer.jobAttrs["job-state-message"].value != "") {
msg = printer.jobAttrs["job-state-message"].value
}
else if (printer.jobAttrs.hasOwnProperty("status-message") && printer.jobAttrs["status-message"].value != "") {
msg = printer.jobAttrs["status-message"].value
}
else if (printer.jobAttrs.hasOwnProperty("job-state") && printer.jobAttrs["job-state"].value != "") {
msg = Utils.ippName("job-state", printer.jobAttrs["job-state"].value)
}
pageStack.pop()
if(status == true) {
notifier.notify(qsTr("Print success: ") + msg)
}
else {
notifier.notify(qsTr("Print failed: ") + msg)
}
}
}
BusyLabel {
text: printer.busyMessage+"\n"+printer.progress;
running: true
}
}

43
qml/pages/DebugPage.qml Normal file
View file

@ -0,0 +1,43 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Page {
id: aboutPage
allowedOrientations: Orientation.All
property var printer
SilicaFlickable {
id: flick
anchors.fill : parent
contentHeight: textArea.height + header.height
contentWidth : parent.width - (2.0 * Theme.paddingLarge)
PageHeader {
id: header
title: printer.attrs["printer-name"].value
}
TextArea {
id: textArea
readOnly: true
width: parent.width
anchors.top: header.bottom
anchors.bottom: flick.bottom
font.family: "courier"
font.pixelSize: Theme.fontSizeTiny
wrapMode: TextEdit.Wrap
text: JSON.stringify(printer.attrs, null, " ")
onPressAndHold: {
selectAll()
copy()
deselect()
notifier.notify("Copied to clipboard")
}
}
}
}

View file

@ -2,7 +2,9 @@ import QtQuick 2.0
import Sailfish.Silica 1.0
import Sailfish.Pickers 1.0
import seaprint.ippdiscovery 1.0
import seaprint.convertchecker 1.0
import seaprint.ippprinter 1.0
import seaprint.mimer 1.0
import "utils.js" as Utils
import "../components"
import Nemo.DBus 2.0
@ -46,18 +48,23 @@ Page {
Component.onCompleted: {
IppDiscovery.discover();
if(selectedFile != "")
{ // Until i can convince FilePickerPage to do its magic without user interaction
if(Utils.endsWith(".pdf", selectedFile))
{
var type = Mimer.get_type(selectedFile);
console.log(type);
selectedFileType = type;
}
}
property bool nagged: false
onStatusChanged: {
if(status==PageStatus.Active && !nagged && nagScreenSetting.value != nagScreenSetting.expectedValue)
{
console.log("Can convert from PDF:", ConvertChecker.pdf)
if(!ConvertChecker.pdf)
{
selectedFileType = "application/pdf"
}
else if(Utils.endsWith(".jpg", selectedFile) || Utils.endsWith(".jpeg", selectedFile))
{
selectedFileType = "image/jpeg"
}
else
{
selectedFile = ""
nagged=true
pageStack.push(Qt.resolvedUrl("NagScreen.qml"))
}
}
}
@ -71,7 +78,11 @@ Page {
MenuItem {
text: qsTr("About SeaPrint")
onClicked: pageStack.push(Qt.resolvedUrl("AboutPage.qml"))
}
}
MenuItem {
text: qsTr("Settings")
onClicked: pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
}
MenuItem {
text: qsTr("Add by URL")
enabled: wifi.connected
@ -108,7 +119,7 @@ Page {
visible: false
property string name: printer.attrs["printer-name"].value != "" ? printer.attrs["printer-name"].value : qsTr("Unknown")
property bool canPrint: printer.attrs["document-format-supported"].value.indexOf(selectedFileType) != -1
property bool canPrint: Utils.supported_formats(printer, ConvertChecker, considerAdditionalFormatsSetting.value).mimetypes.indexOf(selectedFileType) != -1
Connections {
target: printer
@ -131,7 +142,27 @@ Page {
}
}
Timer
{
id: debugCountReset
interval: 666
repeat: false
onTriggered:
{
debugCount = 0;
}
}
property int debugCount: 0
onClicked: {
if(++debugCount == 5)
{
pageStack.push(Qt.resolvedUrl("DebugPage.qml"), {printer: printer})
return;
}
debugCountReset.restart();
if(!canPrint)
return;
if(selectedFile != "")
@ -161,6 +192,7 @@ Page {
source: printer.attrs["printer-icons"] ? "image://ippdiscovery/"+printer.attrs["printer-icons"].value[0] : "icon-seaprint-nobg.svg"
// Some printers serve their icons over https with invalid certs...
onStatusChanged: if (status == Image.Error) source = "icon-seaprint-nobg.svg"
}
Column {
@ -170,30 +202,41 @@ Page {
Label {
id: name_label
color: canPrint ? Theme.primaryColor : Theme.secondaryColor
color: canPrint || selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
text: name
}
Label {
id: mm_label
color: canPrint ? Theme.primaryColor : Theme.secondaryColor
color: canPrint || selectedFile == "" ? Theme.primaryColor : Theme.secondaryColor
font.pixelSize: Theme.fontSizeExtraSmall
text: printer.attrs["printer-make-and-model"].value
}
Label {
id: uri_label
color: canPrint ? Theme.highlightColor : Theme.secondaryColor
color: canPrint || selectedFile == "" ? Theme.highlightColor : Theme.secondaryColor
font.pixelSize: Theme.fontSizeTiny
text: printer.url
}
Label {
id: format_label
color: canPrint ? Theme.primaryColor : "red"
font.pixelSize: Theme.fontSizeExtraSmall
text: Utils.supported_formats(printer)
Row {
spacing: Theme.paddingMedium
Label {
id: format_unsupported_label
visible: format_label.text == ""
color: "red"
font.pixelSize: Theme.fontSizeExtraSmall
text: qsTr("No compatible formats supported")
}
Label {
id: format_label
color: selectedFile == "" ? Theme.secondaryColor : canPrint ? Theme.primaryColor : "red"
font.pixelSize: Theme.fontSizeExtraSmall
text: Utils.supported_formats(printer, ConvertChecker, considerAdditionalFormatsSetting.value).supported
}
}
}
RemorseItem {
@ -225,28 +268,56 @@ Page {
DockedPanel {
id: fileDock
open: true
height: fileButton.height*2
height: fileLabel.height+folderButton.height+3*Theme.paddingLarge
width: parent.width
dock: Dock.Bottom
ValueButton {
id: fileButton
Label {
id: fileLabel
width: parent.width
anchors.verticalCenter: parent.verticalCenter
label: qsTr("Choose file")
value: selectedFile != "" ? selectedFile : qsTr("None")
onClicked: pageStack.push(filePickerPage)
anchors.top: parent.top
anchors.topMargin: Theme.paddingLarge
leftPadding: Theme.paddingMedium
color: Theme.highlightColor
text: selectedFile != "" ? selectedFile : qsTr("No file selected")
}
Row {
width: parent.width
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.paddingLarge
IconButton {
id: folderButton
icon.source: "image://theme/icon-m-file-folder"
width: parent.width/2
onClicked: pageStack.push(filePickerPage)
}
IconButton {
icon.source: "image://theme/icon-m-file-image"
width: parent.width/2
onClicked: pageStack.push(imagePickerPage)
}
}
Component {
id: filePickerPage
FilePickerPage {
title: fileButton.label
title: qsTr("Choose file")
showSystemFiles: false
nameFilters: ["*.pdf", "*.jpg", "*.jpeg"]
nameFilters: ["*.pdf", "*.jpg", "*.jpeg", "*.ps"]
onSelectedContentPropertiesChanged: {
page.selectedFile = selectedContentProperties.filePath
page.selectedFileType = selectedContentProperties.mimeType
page.selectedFileType = Mimer.get_type(selectedContentProperties.filePath)
}
}
}
Component {
id: imagePickerPage
ImagePickerPage {
onSelectedContentPropertiesChanged: {
page.selectedFile = selectedContentProperties.filePath
page.selectedFileType = Mimer.get_type(selectedContentProperties.filePath)
}
}
}

View file

@ -13,6 +13,15 @@ Page {
console.log(JSON.stringify(printer.jobs))
}
Connections {
target: printer
onCancelStatus: {
if(status != true) {
notifier.notify(qsTr("Cancelling job failed"))
}
}
}
// To enable PullDownMenu, place our content in a SilicaFlickable
SilicaFlickable {
anchors.fill: parent

82
qml/pages/NagScreen.qml Normal file
View file

@ -0,0 +1,82 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Page {
backNavigation: false
Column {
y: Theme.paddingLarge
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - 2*Theme.paddingLarge
spacing: Theme.paddingLarge
Label {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Optional dependencies are not installed!")
}
Label {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("In order to convert PDF files to other formats, you need utilities from the package \"poppler-utils\"")
}
Label {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("To install, enable delveloper mode, and open a terminal.")
}
Label {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Become root:")
}
Label {
width: parent.width
wrapMode: Text.WordWrap
font.family: "monospace"
text: "devel-su"
}
Label {
width: parent.width
wrapMode: Text.WordWrap
text: qsTr("Install poppler-utils:")
}
Label {
width: parent.width
wrapMode: Text.WordWrap
font.family: "monospace"
text: "pkcon install poppler-utils"
}
Item{}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Dismiss")
onClicked: pageStack.pop()
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Don't show again")
onClicked: {
nagScreenSetting.value = nagScreenSetting.expectedValue
pageStack.pop()
}
}
}
}

View file

@ -1,5 +1,7 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import seaprint.mimer 1.0
import seaprint.ippmsg 1.0
import "utils.js" as Utils
Page {
@ -12,21 +14,6 @@ Page {
console.log(JSON.stringify(printer.attrs))
}
Connections {
target: printer
onJobAttrsFinished: {
var msg = printer.jobAttrs["job-state-message"] && printer.jobAttrs["job-state-message"].value != ""
? printer.jobAttrs["job-state-message"].value : Utils.ippName("job-state", printer.jobAttrs["job-state"].value)
if(status == true) {
notifier.notify(qsTr("Print success: ") + msg)
pageStack.pop() //or replace?
}
else {
notifier.notify(qsTr("Print failed: ") + msg)
}
}
}
// To enable PullDownMenu, place our content in a SilicaFlickable
SilicaFlickable {
anchors.fill: parent
@ -37,21 +24,28 @@ Page {
text: qsTr("Print")
onClicked: {
console.log(JSON.stringify(jobParams))
printer.print(jobParams, page.selectedFile)
pageStack.replace(Qt.resolvedUrl("BusyPage.qml"),{printer:printer},
PageStackAction.Immediate)
printer.print(jobParams, page.selectedFile,
alwaysConvertSetting.value,
forceIncluDeDocumentFormatSetting.value,
removeRedundantConvertAttrsSetting.value)
}
}
}
ListModel {
id:mod
ListElement {name: "sides"; prettyName: qsTr("Sides"); tag: 0x23}
ListElement {name: "copies"; prettyName: qsTr("Copies"); tag: 0x21}
// ListElement {name: "page-ranges"; prettyName: qsTr("Page range"); tag: 0x33}
ListElement {name: "print-color-mode"; prettyName: qsTr("Color mode"); tag: 0x23}
// ListElement {name: "orientation-requested"; prettyName: qsTr("Orientation"); tag: 0x23}
ListElement {name: "print-quality"; prettyName: qsTr("Quality"); tag: 0x23}
ListElement {name: "printer-resolution"; prettyName: qsTr("Resolution"); tag: 0x32}
ListElement {name: "sides"; prettyName: qsTr("Sides"); tag: IppMsg.Enum}
ListElement {name: "media"; prettyName: qsTr("Print media"); tag: IppMsg.Keyword}
ListElement {name: "copies"; prettyName: qsTr("Copies"); tag: IppMsg.Integer}
// ListElement {name: "page-ranges"; prettyName: qsTr("Page range"); tag: IppMsg.IntegerRange}
ListElement {name: "print-color-mode"; prettyName: qsTr("Color mode"); tag: IppMsg.Enum}
// ListElement {name: "orientation-requested"; prettyName: qsTr("Orientation"); tag: IppMsg.Enum}
ListElement {name: "print-quality"; prettyName: qsTr("Quality"); tag: IppMsg.Enum}
ListElement {name: "printer-resolution"; prettyName: qsTr("Resolution"); tag: IppMsg.Resolution}
ListElement {name: "document-format"; prettyName: qsTr("Transfer format"); tag: IppMsg.MimeMediaType}
ListElement {name: "media-source"; prettyName: qsTr("Media source"); tag: IppMsg.Keyword}
}
SilicaListView {
@ -79,52 +73,66 @@ Page {
Loader {
id: loader
anchors.fill: parent
onLoaded: {
if(loaderItem.menu.enabled)
{
menu = loaderItem.menu
loaderItem.clicked.connect(openMenu)
}
loaderItem.choiceMade.connect(function(tag, choice) {
console.log("choice changed", tag, JSON.stringify(choice))
jobParams[name] = {tag: tag, value: choice};
console.log(JSON.stringify(jobParams));
})
}
}
Component.onCompleted: {
console.log("handling", tag, name, prettyName, JSON.stringify(printer.attrs[name+"-supported"]), JSON.stringify(printer.attrs[name+"-default"]))
switch(tag) {
case 0x21:
case IppMsg.Integer:
loader.setSource("../components/IntegerSetting.qml",
{name: name,
prettyName: prettyName,
tag: tag,
valid: printer.attrs.hasOwnProperty(name+"-supported"),
low: printer.attrs[name+"-supported"].value.low,
high: printer.attrs[name+"-supported"].value.high,
default_choice: printer.attrs[name+"-default"].value
})
break
case 0x33:
case IppMsg.IntegerRange:
loader.setSource("../components/RangeSetting.qml",
{name: name,
prettyName: prettyName,
valid: false, //TODO
tag: 0x33 // integer-range
tag: tag,
valid: false //TODO printer.attrs.hasOwnProperty(name+"-supported"),
})
break
case 0x32:
case 0x23:
case IppMsg.Resolution:
case IppMsg.Enum:
case IppMsg.Keyword:
case IppMsg.MimeMediaType:
loader.setSource("../components/ChoiceSetting.qml",
{name: name,
prettyName: prettyName,
tag: tag,
choices: printer.attrs[name+"-supported"].value,
default_choice: printer.attrs[name+"-default"].value
valid: printer.attrs.hasOwnProperty(name+"-supported"),
choices: maybeSupplementChoices(name, printer.attrs[name+"-supported"].value),
default_choice: printer.attrs[name+"-default"].value,
mime_type: Mimer.get_type(selectedFile)
})
break
}
}
onLoaderItemChanged: {
menu = loaderItem.menu
loaderItem.clicked.connect(function() {
openMenu()
})
loaderItem.choiceMade.connect(function(tag, choice) {
console.log("choice changed", tag, JSON.stringify(choice))
jobParams[name] = {tag: tag, value: choice};
console.log(JSON.stringify(jobParams));
})
function maybeSupplementChoices(name, choices)
{
if(name == "document-format" && considerAdditionalFormatsSetting.value)
{
return choices.concat(printer.additionalDocumentFormats)
}
return choices
}
}

View file

@ -0,0 +1,71 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Page {
SilicaFlickable {
anchors.fill: parent
contentHeight: column.height
Column {
id: column
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - 2*Theme.paddingLarge
spacing: Theme.paddingLarge
PageHeader{}
TextSwitch {
text: qsTr("Show nag-screen")
description: qsTr("Display the warning page about optional dependencies not being installed, if they are not installed.")
checked: nagScreenSetting.value != nagScreenSetting.expectedValue
onCheckedChanged: {
if(checked)
{
nagScreenSetting.value=0
}
else
{
nagScreenSetting.value = nagScreenSetting.expectedValue
}
}
}
TextSwitch {
text: qsTr("Consider additional formats")
description: qsTr("Some printers support more formats than they advertise correctly. However, additional formats can be inferred from other attributes. Mainly relevant for Postscript-compatible printers that also support PDF.")
checked: considerAdditionalFormatsSetting.value
onCheckedChanged: {
considerAdditionalFormatsSetting.value = checked
}
}
TextSwitch {
text: qsTr("Always convert to raster format")
description: qsTr("Force conversion to PWG/URF raster format. This is mainly intended for testing.")
checked: alwaysConvertSetting.value
onCheckedChanged: {
alwaysConvertSetting.value = checked
}
}
TextSwitch {
text: qsTr("Force-include document format")
description: qsTr("Force the document-format attribute to be included. Some printers have trouble recognizing certain formats, sometimes it helps to include this atribute even if the printer does not claim to support it.")
checked: forceIncluDeDocumentFormatSetting.value
onCheckedChanged: {
forceIncluDeDocumentFormatSetting.value = checked
}
}
TextSwitch {
text: qsTr("Remove redundant attributes")
description: qsTr("Remove redundant IPP attributes, if they are also conveyed in the transfer format. Some printers reject the job even if the settings are consistent.")
checked: removeRedundantConvertAttrsSetting.value
onCheckedChanged: {
removeRedundantConvertAttrsSetting.value = checked
}
}
}
}
}

View file

@ -1,32 +1,41 @@
function supported_formats(printer)
function supported_formats(printer, ConvertChecker, considerAdditionalFormats)
{
var formats = printer.attrs["document-format-supported"].value;
if(considerAdditionalFormats)
{
formats=formats+printer.additionalDocumentFormats;
}
var mimetypes = [];
var supported = [];
if(has(formats, "application/pdf"))
if(has(formats, "application/pdf") ||
(ConvertChecker.pdf && ( has(formats, "application/postscript") ||
has(formats, "image/pwg-raster") ||
has(formats, "image/urf"))) )
{
mimetypes.push("application/pdf");
supported.push("PDF");
}
if(has(formats, "image/jpeg"))
if(has(formats, "application/postscript"))
{
mimetypes.push("application/postscript");
supported.push("Postscript");
}
if ( has(formats, "image/pwg-raster") || has(formats, "image/urf"))
{
mimetypes.push("image/jpeg");
supported.push("JPEG");
mimetypes.push("image/png");
supported.push("PNG");
}
if(supported.length == 0)
{
supported.push(qsTr("No compatible formats supported"))
}
return supported.join(" ");
return {supported: supported.join(" "), mimetypes: mimetypes};
}
function has(arrayish, what)
{
for(var i in arrayish)
{
if(arrayish[i] == what)
return true
}
return false
return arrayish.indexOf(what) != -1;
}
function ippName(name, value)
@ -83,6 +92,104 @@ function ippName(name, value)
units=qsTr("dots/cm")
}
return ""+value.x+"x"+value.y+units;
case "media":
if(media.hasOwnProperty(value))
{
return media[value];
}
else
{
return value;
}
case "sides":
switch(value) {
case "one-sided":
return qsTr("one-sided");
case "two-sided-long-edge":
return qsTr("two-sided");
case "two-sided-short-edge":
return qsTr("two-sided flipped");
default:
return value
}
case "print-color-mode":
switch(value) {
case "auto":
return qsTr("automatic");
case "auto-monochrome":
return qsTr("auto monochrome");
case "bi-level":
return qsTr("bi-level");
case "color":
return qsTr("color");
case "highlight":
return qsTr("highlight");
case "monochrome":
return qsTr("monochrome");
case "process-bi-level":
return qsTr("process bi-level");
case "process-monochrome":
return qsTr("process monochrome");
default:
return value
}
case "document-format":
switch(value) {
case "application/octet-stream":
return qsTr("auto-sense");
case "application/pdf":
return qsTr("PDF");
case "application/postscript":
return qsTr("Postscript");
case "image/pwg-raster":
return qsTr("PWG-raster");
case "image/urf":
return qsTr("URF-raster");
case "image/png":
return qsTr("PNG");
case "image/jpeg":
return qsTr("JPEG");
case "image/gif":
return qsTr("GIF");
default:
return value;
}
case "media-source":
if(value.indexOf("tray-")==0)
{
return qsTr("tray")+" "+value.split("-")[1];
}
else
{
switch(value) {
case "by-pass-tray":
return qsTr("by-pass tray");
case "auto":
return qsTr("automatic");
case "bottom":
return qsTr("bottom");
case "center":
return qsTr("center");
case "main":
return qsTr("main");
case "manual":
return qsTr("manual");
case "middle":
return qsTr("middle");
case "photo":
return qsTr("photo");
case "rear":
return qsTr("rear");
case "right":
return qsTr("right");
case "side":
return qsTr("side");
case "top":
return qsTr("top");
default:
return value;
}
}
}
return value;
}
@ -91,3 +198,261 @@ function endsWith(ending, string)
{
return string.lastIndexOf(ending) == (string.length - ending.length);
}
function canConvertPdfTo(type)
{
var targets = ["application/octet-stream", "application/pdf", "application/postscript", "image/pwg-raster", "image/urf"];
return has(targets, type)
}
function canTransferPdfAs(type)
{
var targets = ["application/octet-stream", "application/pdf"];
return has(targets, type)
}
function canConvertImageTo(type)
{
var targets = ["application/octet-stream", "image/jpeg", "image/png", "image/pwg-raster", "image/urf", "image/gif"];
return has(targets, type)
}
function unitsIsDpi(resolution)
{
return resolution.units == 3;
}
function limitChoices(name, choices, mimeType, ConvertChecker)
{
switch(name) {
case "document-format":
if(mimeType == "application/pdf")
{
if(ConvertChecker.pdf)
{
return choices.filter(canConvertPdfTo)
}
else
{
return choices.filter(canTransferPdfAs)
}
}
else if(mimeType == "image/jpeg" || mimeType == "image/png")
{
return choices.filter(canConvertImageTo);
}
else
{
return ["application/octet-stream"];
}
case "printer-resolution":
return choices.filter(unitsIsDpi);
default:
return choices;
}
}
var media =
{"asme_f_28x40in": "28 x 40″",
"choice_iso_a4_210x297mm_na_letter_8.5x11in": "A4 or US Letter",
"iso_2a0_1189x1682mm": "2a0",
"iso_a0_841x1189mm": "A0",
"iso_a0x3_1189x2523mm": "A0x3",
"iso_a10_26x37mm": "A10",
"iso_a1_594x841mm": "A1",
"iso_a1x3_841x1783mm": "A1x3",
"iso_a1x4_841x2378mm": "A1x4",
"iso_a2_420x594mm": "A2",
"iso_a2x3_594x1261mm": "A2x3",
"iso_a2x4_594x1682mm": "A2x4",
"iso_a2x5_594x2102mm": "A2x5",
"iso_a3-extra_322x445mm": "A3 (Extra)",
"iso_a3_297x420mm": "A3",
"iso_a3x3_420x891mm": "A3x3",
"iso_a3x4_420x1189mm": "A3x4",
"iso_a3x5_420x1486mm": "A3x5",
"iso_a3x6_420x1783mm": "A3x6",
"iso_a3x7_420x2080mm": "A3x7",
"iso_a4-extra_235.5x322.3mm": "A4 (Extra)",
"iso_a4-tab_225x297mm": "A4 (Tab)",
"iso_a4_210x297mm": "A4",
"iso_a4x3_297x630mm": "A4x3",
"iso_a4x4_297x841mm": "A4x4",
"iso_a4x5_297x1051mm": "A4x5",
"iso_a4x6_297x1261mm": "A4x6",
"iso_a4x7_297x1471mm": "A4x7",
"iso_a4x8_297x1682mm": "A4x8",
"iso_a4x9_297x1892mm": "A4x9",
"iso_a5-extra_174x235mm": "A5 (Extra)",
"iso_a5_148x210mm": "A5",
"iso_a6_105x148mm": "A6",
"iso_a7_74x105mm": "A7",
"iso_a8_52x74mm": "A8",
"iso_a9_37x52mm": "A9",
"iso_b0_1000x1414mm": "B0",
"iso_b10_31x44mm": "B10",
"iso_b1_707x1000mm": "B1",
"iso_b2_500x707mm": "B2",
"iso_b3_353x500mm": "B3",
"iso_b4_250x353mm": "B4",
"iso_b5-extra_201x276mm": "B5 (Extra)",
"iso_b5_176x250mm": "Envelope B5",
"iso_b6_125x176mm": "B6",
"iso_b6c4_125x324mm": "Envelope B6/C4",
"iso_b7_88x125mm": "B7",
"iso_b8_62x88mm": "B8",
"iso_b9_44x62mm": "B9",
"iso_c0_917x1297mm": "CEnvelope 0",
"iso_c10_28x40mm": "CEnvelope 10",
"iso_c1_648x917mm": "CEnvelope 1",
"iso_c2_458x648mm": "CEnvelope 2",
"iso_c3_324x458mm": "CEnvelope 3",
"iso_c4_229x324mm": "CEnvelope 4",
"iso_c5_162x229mm": "CEnvelope 5",
"iso_c6_114x162mm": "CEnvelope 6",
"iso_c6c5_114x229mm": "CEnvelope 6c5",
"iso_c7_81x114mm": "CEnvelope 7",
"iso_c7c6_81x162mm": "CEnvelope 7c6",
"iso_c8_57x81mm": "CEnvelope 8",
"iso_c9_40x57mm": "CEnvelope 9",
"iso_dl_110x220mm": "Envelope DL",
"iso_id-1_53.98x85.6mm": "Id-1",
"iso_id-3_88x125mm": "Id-3",
"iso_ra0_860x1220mm": "ISO RA0",
"iso_ra1_610x860mm": "ISO RA1",
"iso_ra2_430x610mm": "ISO RA2",
"iso_ra3_305x430mm": "ISO RA3",
"iso_ra4_215x305mm": "ISO RA4",
"iso_sra0_900x1280mm": "ISO SRA0",
"iso_sra1_640x900mm": "ISO SRA1",
"iso_sra2_450x640mm": "ISO SRA2",
"iso_sra3_320x450mm": "ISO SRA3",
"iso_sra4_225x320mm": "ISO SRA4",
"jis_b0_1030x1456mm": "JIS B0",
"jis_b10_32x45mm": "JIS B10",
"jis_b1_728x1030mm": "JIS B1",
"jis_b2_515x728mm": "JIS B2",
"jis_b3_364x515mm": "JIS B3",
"jis_b4_257x364mm": "JIS B4",
"jis_b5_182x257mm": "JIS B5",
"jis_b6_128x182mm": "JIS B6",
"jis_b7_91x128mm": "JIS B7",
"jis_b8_64x91mm": "JIS B8",
"jis_b9_45x64mm": "JIS B9",
"jis_exec_216x330mm": "JIS Executive",
"jpn_chou2_111.1x146mm": "Envelope Chou 2",
"jpn_chou3_120x235mm": "Envelope Chou 3",
"jpn_chou40_90x225mm": "Envelope Chou 40",
"jpn_chou4_90x205mm": "Envelope Chou 4",
"jpn_hagaki_100x148mm": "Hagaki",
"jpn_kahu_240x322.1mm": "Envelope Kahu",
"jpn_kaku1_270x382mm": "270 x 382mm",
"jpn_kaku2_240x332mm": "Envelope Kahu 2",
"jpn_kaku3_216x277mm": "216 x 277mm",
"jpn_kaku4_197x267mm": "197 x 267mm",
"jpn_kaku5_190x240mm": "190 x 240mm",
"jpn_kaku7_142x205mm": "142 x 205mm",
"jpn_kaku8_119x197mm": "119 x 197mm",
"jpn_oufuku_148x200mm": "Oufuku Reply Postcard",
"jpn_you4_105x235mm": "Envelope You 4",
"na_10x11_10x11in": "10 x 11″",
"na_10x13_10x13in": "10 x 13″",
"na_10x14_10x14in": "10 x 14″",
"na_10x15_10x15in": "10 x 15″",
"na_11x12_11x12in": "11 x 12″",
"na_11x15_11x15in": "11 x 15″",
"na_12x19_12x19in": "12 x 19″",
"na_5x7_5x7in": "5 x 7″",
"na_6x9_6x9in": "6 x 9″",
"na_7x9_7x9in": "7 x 9″",
"na_9x11_9x11in": "9 x 11″",
"na_a2_4.375x5.75in": "Envelope A2",
"na_arch-a_9x12in": "9 x 12″",
"na_arch-b_12x18in": "12 x 18″",
"na_arch-c_18x24in": "18 x 24″",
"na_arch-d_24x36in": "24 x 36″",
"na_arch-e2_26x38in": "26 x 38″",
"na_arch-e3_27x39in": "27 x 39″",
"na_arch-e_36x48in": "36 x 48″",
"na_b-plus_12x19.17in": "12 x 19.17″",
"na_c5_6.5x9.5in": "Envelope C5",
"na_c_17x22in": "17 x 22″",
"na_d_22x34in": "22 x 34″",
"na_e_34x44in": "34 x 44″",
"na_edp_11x14in": "11 x 14″",
"na_eur-edp_12x14in": "12 x 14″",
"na_executive_7.25x10.5in": "Executive",
"na_f_44x68in": "44 x 68″",
"na_fanfold-eur_8.5x12in": "European Fanfold",
"na_fanfold-us_11x14.875in": "US Fanfold",
"na_foolscap_8.5x13in": "Foolscap",
"na_govt-legal_8x13in": "8 x 13″",
"na_govt-letter_8x10in": "8 x 10″",
"na_index-3x5_3x5in": "3 x 5″",
"na_index-4x6-ext_6x8in": "6 x 8″",
"na_index-4x6_4x6in": "4 x 6″",
"na_index-5x8_5x8in": "5 x 8″",
"na_invoice_5.5x8.5in": "Statement",
"na_ledger_11x17in": "11 x 17″",
"na_legal-extra_9.5x15in": "US Legal (Extra)",
"na_legal_8.5x14in": "US Legal",
"na_letter-extra_9.5x12in": "US Letter (Extra)",
"na_letter-plus_8.5x12.69in": "US Letter (Plus)",
"na_letter_8.5x11in": "US Letter",
"na_monarch_3.875x7.5in": "Envelope Monarch",
"na_number-10_4.125x9.5in": "Envelope #10",
"na_number-11_4.5x10.375in": "Envelope #11",
"na_number-12_4.75x11in": "Envelope #12",
"na_number-14_5x11.5in": "Envelope #14",
"na_number-9_3.875x8.875in": "Envelope #9",
"na_oficio_8.5x13.4in": "8.5 x 13.4″",
"na_personal_3.625x6.5in": "Envelope Personal",
"na_quarto_8.5x10.83in": "Quarto",
"na_super-a_8.94x14in": "8.94 x 14″",
"na_super-b_13x19in": "13 x 19″",
"na_wide-format_30x42in": "30 x 42″",
"oe_12x16_12x16in": "12 x 16″",
"oe_14x17_14x17in": "14 x 17″",
"oe_18x22_18x22in": "18 x 22″",
"oe_a2plus_17x24in": "17 x 24″",
"oe_business-card_2x3.5in": "2 x 3.5″",
"oe_photo-10r_10x12in": "10 x 12″",
"oe_photo-20r_20x24in": "20 x 24″",
"oe_photo-l_3.5x5in": "3.5 x 5″",
"oe_photo-s10r_10x15in": "10 x 15″",
"oe_square-photo_4x4in": "4 x 4″",
"oe_square-photo_5x5in": "5 x 5″",
"om_16k_184x260mm": "184 x 260mm",
"om_16k_195x270mm": "195 x 270mm",
"om_business-card_55x85mm": "55 x 85mm",
"om_business-card_55x91mm": "55 x 91mm",
"om_card_54x86mm": "54 x 86mm",
"om_dai-pa-kai_275x395mm": "275 x 395mm",
"om_dsc-photo_89x119mm": "89 x 119mm",
"om_folio-sp_215x315mm": "Folio",
"om_folio_210x330mm": "Folio (Special)",
"om_invite_220x220mm": "Envelope Invitation",
"om_italian_110x230mm": "Envelope Italian",
"om_juuro-ku-kai_198x275mm": "198 x 275mm",
"om_large-photo_200x300": "200 x 300",
"om_medium-photo_130x180mm": "130 x 180mm",
"om_pa-kai_267x389mm": "267 x 389mm",
"om_postfix_114x229mm": "Envelope Postfix",
"om_small-photo_100x150mm": "100 x 150mm",
"om_square-photo_89x89mm": "89 x 89mm",
"om_wide-photo_100x200mm": "100 x 200mm",
"prc_10_324x458mm": "Envelope Chinese #10",
"prc_16k_146x215mm": "Chinese 16k",
"prc_1_102x165mm": "Envelope Chinese #1",
"prc_2_102x176mm": "Envelope Chinese #2",
"prc_32k_97x151mm": "Chinese 32k",
"prc_3_125x176mm": "Envelope Chinese #3",
"prc_4_110x208mm": "Envelope Chinese #4",
"prc_5_110x220mm": "Envelope Chinese #5",
"prc_6_120x320mm": "Envelope Chinese #6",
"prc_7_160x230mm": "Envelope Chinese #7",
"prc_8_120x309mm": "Envelope Chinese #8",
"roc_16k_7.75x10.75in": "ROC 16k",
"roc_8k_10.75x15.5in": "ROC 8k"}

View file

@ -9,8 +9,8 @@ Name: harbour-seaprint
# << macros
Summary: SeaPrint
Version: 0.4
Release: 3
Version: 0.5
Release: 1
Group: Qt/Qt
License: LICENSE
URL: http://example.org/

View file

@ -1,7 +1,7 @@
Name: harbour-seaprint
Summary: SeaPrint
Version: 0.4
Release: 3
Version: 0.5
Release: 1
# The contents of the Group field should be one of the groups listed here:
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
Group: Qt/Qt

View file

@ -1,553 +0,0 @@
#include "bytestream.h"
#include <iostream>
#include <cstdint>
#include <cstring>
using namespace std;
Bytestream::Bytestream()
{
_size = 0;
_pos = 0;
_noOfNextBytes = 0;
_noOfNextBytesValid = false;
_endianness = BigEndian;
}
Bytestream::Bytestream(size_t len)
{
_size = len;
_data = new uint8_t[_size];
memset(_data, 0, _size);
_pos = 0;
_noOfNextBytes = 0;
_noOfNextBytesValid = false;
_endianness = BigEndian;
}
Bytestream::Bytestream(const void* data, size_t len)
{
_size = len;
_data = new uint8_t[_size];
memcpy(_data, data, _size);
_pos = 0;
_noOfNextBytes = 0;
_noOfNextBytesValid = false;
_endianness = BigEndian;
}
Bytestream::Bytestream(const void* data, size_t len, Endianness e)
{
_size = len;
_data = new uint8_t[_size];
memcpy(_data, data, _size);
_pos = 0;
_noOfNextBytes = 0;
_noOfNextBytesValid = false;
_endianness = e;
}
Bytestream::Bytestream(const Bytestream& rhs)
{
_size = rhs._size;
_data = new uint8_t[_size];
memcpy(_data, rhs._data, _size);
_pos = rhs._pos;
_noOfNextBytes = 0;
_noOfNextBytesValid = false;
_endianness = rhs._endianness;
}
Bytestream::~Bytestream()
{
if(_size != 0)
{
delete _data;
}
}
bool Bytestream::operator==(const Bytestream& other) const
{
if(_size != other.size())
{
return false;
}
return memcmp(_data, other.raw(), _size) == 0;
}
bool Bytestream::operator!=(const Bytestream& other) const
{
if(_size != other.size())
{
return true;
}
return memcmp(_data, other.raw(), _size) != 0;
}
Bytestream& Bytestream::operator=(const Bytestream& other)
{
if(_size != 0)
{
delete _data;
}
_pos = other.pos();
_size = other.size();
_data = new uint8_t[_size];
memcpy(_data, other.raw(), _size);
return *this;
}
template <typename T>
T bswap(T u)
{
uint8_t* const p = reinterpret_cast<uint8_t*>(&u);
for (size_t i = 0; i < sizeof(T) / 2; i++)
{
std::swap(p[i], p[sizeof(T) - i - 1]);
}
return u;
}
#define GET(type, shorthand, len) GET_(type##len##_t, shorthand##len, len)
#define GET_(type, shortType, len) \
type Bytestream::get##shortType() \
{type tmp; getBytes(&tmp, sizeof(type));\
if(needsSwap()){tmp=bswap(tmp);} return tmp;}
GET(uint, U, 8)
GET(uint, U, 16)
GET(uint, U, 32)
GET(uint, U, 64)
GET(int, S, 8)
GET(int, S, 16)
GET(int, S, 32)
GET(int, S, 64)
GET(float, F, 32)
GET(float, F, 64)
std::string Bytestream::getString()
{
if(!_noOfNextBytesValid)
{
throw invalid_argument("No length given");
}
char* cs = new char[_noOfNextBytes+1];
cs[_noOfNextBytes] = 0;
getBytes(cs, _noOfNextBytes);
string s = std::string(cs, _noOfNextBytes);
delete cs;
return s;
}
Bytestream Bytestream::getBytestream()
{
if(!_noOfNextBytesValid)
{
throw invalid_argument("No length given");
}
uint8_t* cs = new uint8_t[_noOfNextBytes];
getBytes(cs, _noOfNextBytes);
Bytestream other = Bytestream(cs, _noOfNextBytes);
delete cs;
return other;
}
std::string Bytestream::getString(size_t len)
{
if(_noOfNextBytesValid && len != _noOfNextBytes)
{
throw logic_error("Desired lengths does not match");
}
else if(!_noOfNextBytesValid)
{
setNoOfNextBytes(len);
}
return getString();
}
Bytestream Bytestream::getBytestream(size_t len)
{
if(!_noOfNextBytesValid && len != _noOfNextBytes)
{
throw logic_error("Desired lengths does not match");
}
setNoOfNextBytes(len);
return getBytestream();
}
void Bytestream::getBytes(void* cs, size_t len)
{
_before(len);
memcpy(cs, &(_data[_pos]), len);
_after(len);
}
#define PEEK(type, shorthand, len) PEEK_(type##len##_t, shorthand##len, len)
#define PEEK_(type, shortType, len) \
type Bytestream::peek##shortType() \
{type tmp; getBytes(&tmp, sizeof(type));\
if(needsSwap()){tmp=bswap(tmp);} (*this) -= sizeof(type); return tmp;}
PEEK(uint, U, 8)
PEEK(uint, U, 16)
PEEK(uint, U, 32)
PEEK(uint, U, 64)
PEEK(int, S, 8)
PEEK(int, S, 16)
PEEK(int, S, 32)
PEEK(int, S, 64)
PEEK(float, F, 32)
PEEK(float, F, 64)
std::string Bytestream::peekString()
{
if(!_noOfNextBytesValid)
{
throw invalid_argument("No length given");
}
char* cs = new char[_noOfNextBytes+1];
cs[_noOfNextBytes] = 0;
getBytes(cs, _noOfNextBytes);
string s = std::string(cs, _noOfNextBytes);
delete cs;
(*this) -= _noOfNextBytes;
return s;
}
Bytestream Bytestream::peekBytestream()
{
if(!_noOfNextBytesValid)
{
throw invalid_argument("No length given");
}
uint8_t* cs = new uint8_t[_noOfNextBytes];
getBytes(cs, _noOfNextBytes);
Bytestream other = Bytestream(cs, _noOfNextBytes);
delete cs;
(*this) -= _noOfNextBytes;
return other;
}
std::string Bytestream::peekString(size_t len)
{
if(_noOfNextBytesValid && len != _noOfNextBytes)
{
throw logic_error("Desired lengths does not match");
}
else if(!_noOfNextBytesValid)
{
setNoOfNextBytes(len);
}
return peekString();
}
Bytestream Bytestream::peekBytestream(size_t len)
{
if(!_noOfNextBytesValid && len != _noOfNextBytes)
{
throw logic_error("Desired lengths does not match");
}
setNoOfNextBytes(len);
return peekBytestream();
}
#define NEXT(type, shorthand, len) NEXT_(type##len##_t, shorthand##len)
#define NEXT_(type, shortType) \
bool Bytestream::next##shortType(type u) \
{if(u == get##shortType())\
{return true;} \
else\
{(*this) -= sizeof(type);\
return false;}}
NEXT(uint, U, 8)
NEXT(uint, U, 16)
NEXT(uint, U, 32)
NEXT(uint, U, 64)
NEXT(int, S, 8)
NEXT(int, S, 16)
NEXT(int, S, 32)
NEXT(int, S, 64)
NEXT(float, F, 32)
NEXT(float, F, 64)
bool Bytestream::nextString(const std::string& s)
{
if(_noOfNextBytesValid && getNoOfNextBytes() != s.length())
{
throw logic_error("Desired length does not match const length");
}
else if(!_noOfNextBytesValid)
{
setNoOfNextBytes(s.length());
}
size_t noOfNextBytes = getNoOfNextBytes();
if(noOfNextBytes > remaining())
{
invalidateNoOfNextBytes();
return false;
}
if(getString() == s)
{
return true;
}
else
{
(*this) -= noOfNextBytes;
return false;
}
}
bool Bytestream::nextBytestream(const Bytestream& other)
{
if(_noOfNextBytesValid && getNoOfNextBytes() != other.size())
{
throw logic_error("Desired length does not match const length");
}
else if(!_noOfNextBytesValid)
{
setNoOfNextBytes(other.size());
}
size_t noOfNextBytes = getNoOfNextBytes();
if(noOfNextBytes > remaining())
{
invalidateNoOfNextBytes();
return false;
}
if(getBytestream() == other)
{
return true;
}
else
{
(*this) -= noOfNextBytes;
return false;
}
}
#define PUT(type, shorthand, len) PUT_(type##len##_t, shorthand##len, len)
#define PUT_(type, shortType, len) \
void Bytestream::put##shortType(type u) \
{if(needsSwap()){u=bswap(u);} \
putBytes(&u, sizeof(u));}
PUT(uint, U, 8)
PUT(uint, U, 16)
PUT(uint, U, 32)
PUT(uint, U, 64)
PUT(int, S, 8)
PUT(int, S, 16)
PUT(int, S, 32)
PUT(int, S, 64)
PUT(float, F, 32)
PUT(float, F, 64)
void Bytestream::putString(const std::string& s)
{
putBytes(s.c_str(), s.length());
}
void Bytestream::putBytestream(const Bytestream& other)
{
putBytes(other.raw(), other.size());
}
void Bytestream::putBytes(const void* c, size_t len)
{
uint8_t* old = _data;
_data = new uint8_t[_size+len];
if (_size != 0)
{
memcpy(_data, old, _size);
delete old;
}
memcpy((_data+_size), c, len);
_size += len;
}
void Bytestream::setNoOfNextBytes(size_t n)
{
_noOfNextBytes = n;
_noOfNextBytesValid = true;
}
void Bytestream::invalidateNoOfNextBytes()
{
_noOfNextBytes = 0;
_noOfNextBytesValid = false;
}
void Bytestream::_before(size_t bytesToRead)
{
if(bytesToRead > remaining())
{
invalidateNoOfNextBytes();
throw out_of_range("Tried to read past end");
}
}
void Bytestream::_after(size_t bytesRead)
{
_pos += bytesRead;
_noOfNextBytesValid = false;
}
Bytestream Bytestream::operator[](size_t i)
{
Bytestream tmp(_data+i, _size-i);
return tmp;
}
Bytestream& Bytestream::operator+=(size_t i)
{
if((_pos+i) > _size)
{
invalidateNoOfNextBytes();
throw out_of_range("Tried to address data past end");
}
_pos += i;
return *this;
}
Bytestream& Bytestream::operator-=(size_t i)
{
_pos -= i;
return *this;
}
Bytestream& Bytestream::operator/(int i)
{
setNoOfNextBytes(i);
return *this;
}
#define PUTOP(type, shorthand, len) PUTOP_(type##len##_t, shorthand##len)
#define PUTOP_(type, shortType) \
Bytestream& Bytestream::operator<<(const type& u) \
{put##shortType(u); return *this;}
PUTOP(uint, U, 8)
PUTOP(uint, U, 16)
PUTOP(uint, U, 32)
PUTOP(uint, U, 64)
PUTOP(int, S, 8)
PUTOP(int, S, 16)
PUTOP(int, S, 32)
PUTOP(int, S, 64)
PUTOP(float, F, 32)
PUTOP(float, F, 64)
Bytestream& Bytestream::operator<<(const std::string& s)
{
putString(s);
return *this;
}
Bytestream& Bytestream::operator<<(const Bytestream& other)
{
putBytestream(other);
return *this;
}
#define GETOP(type, shorthand, len) GETOP_(type##len##_t, shorthand##len)
#define GETOP_(type, shortType) \
Bytestream& Bytestream::operator>>(type& u) \
{u = get##shortType(); return *this;}
GETOP(uint, U, 8)
GETOP(uint, U, 16)
GETOP(uint, U, 32)
GETOP(uint, U, 64)
GETOP(int, S, 8)
GETOP(int, S, 16)
GETOP(int, S, 32)
GETOP(int, S, 64)
GETOP(float, F, 32)
GETOP(float, F, 64)
Bytestream& Bytestream::operator>>(std::string& s)
{
s = getString();
return *this;
}
Bytestream& Bytestream::operator>>(Bytestream& other)
{
other = getBytestream();
return *this;
}
#define GETOP_CONST(type, shorthand, len) \
GETOP_CONST_(type##len##_t, shorthand##len)
#define GETOP_CONST_(type, shortType) \
Bytestream& Bytestream::operator>>(const type& u) \
{type v = get##shortType();\
if(u!=v) {(*this) -= sizeof(type);\
throw Badmatch("Does not match const", v, u);}\
else{return *this;}}
GETOP_CONST(uint, U, 8)
GETOP_CONST(uint, U, 16)
GETOP_CONST(uint, U, 32)
GETOP_CONST(uint, U, 64)
GETOP_CONST(int, S, 8)
GETOP_CONST(int, S, 16)
GETOP_CONST(int, S, 32)
GETOP_CONST(int, S, 64)
GETOP_CONST(float, F, 32)
GETOP_CONST(float, F, 64)
Bytestream& Bytestream::operator>>(const std::string& s)
{
if (_noOfNextBytesValid && getNoOfNextBytes() != s.length())
{
throw logic_error("Desired length does not match const length");
}
else if(!_noOfNextBytesValid)
{
setNoOfNextBytes(s.length());
}
std::string sv = getString();
if(sv != s)
{
(*this) -= s.length();
throw Badmatch("Does not match const", sv, s);
}
return *this;
}
#define NEXTOP(type, shorthand, len) NEXTOP_(type##len##_t, shorthand##len)
#define NEXTOP_(type, shortType) \
bool Bytestream::operator>>=(const type& u) \
{return next##shortType(u);}
NEXTOP(uint, U, 8)
NEXTOP(uint, U, 16)
NEXTOP(uint, U, 32)
NEXTOP(uint, U, 64)
NEXTOP(int, S, 8)
NEXTOP(int, S, 16)
NEXTOP(int, S, 32)
NEXTOP(int, S, 64)
NEXTOP(float, F, 32)
NEXTOP(float, F, 64)
bool Bytestream::operator>>=(const std::string& s)
{
return nextString(s);
}
bool Bytestream::operator>>=(const Bytestream& other)
{
return nextBytestream(other);
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
bool Bytestream::needsSwap()
{
return _endianness != Endianness::NativeEndian
&& _endianness != Endianness::LittleEndian;
}
#elif __BYTE_ORDER == __BIG_ENDIAN
bool Bytestream::needsSwap()
{
return _endianness != Endianness::NativeEndian
&& _endianness != Endianness::BigEndian;
}
#else
#error
#endif

View file

@ -1,189 +0,0 @@
#ifndef BYTESTREAM_H
#define BYTESTREAM_H
#include <string>
#include <stdexcept>
#include <byteswap.h>
#ifndef __STDC_IEC_559__
#error "Double must be IEEE 754"
#endif
#define float32_t float
#define float64_t double
class Bytestream
{
public:
class Badmatch : public std::invalid_argument::invalid_argument
{
public:
Badmatch(std::string s, std::string v, std::string u) :
invalid_argument(s+": "+v+" != "+u) {}
template<typename T>
Badmatch(std::string s, T v, T u) :
invalid_argument(s+": "+std::to_string(v)+" != "+std::to_string(u)) {}
};
enum Endianness {
NativeEndian,
BigEndian,
LittleEndian
};
Bytestream();
Bytestream(size_t len);
Bytestream(const void* data, size_t len);
Bytestream(const void* data, size_t len, Endianness e);
Bytestream(const Bytestream& rhs);
~Bytestream();
bool operator==(const Bytestream& other) const;
bool operator!=(const Bytestream& other) const;
Bytestream& operator=(const Bytestream& other);
uint8_t* raw() const {return _data;}
size_t size() const {return _size;}
size_t pos() const {return _pos;}
size_t remaining() const {return _size - _pos;}
bool atEnd() const {return _pos >= _size;}
void setPos(size_t pos) {_pos = pos;}
Endianness getEndianness() {return _endianness;}
void setEndianness(Endianness e) {_endianness = e;}
uint8_t getU8();
uint16_t getU16();
uint32_t getU32();
uint64_t getU64();
int8_t getS8();
int16_t getS16();
int32_t getS32();
int64_t getS64();
float32_t getF32();
float64_t getF64();
std::string getString();
Bytestream getBytestream();
std::string getString(size_t len);
Bytestream getBytestream(size_t len);
void getBytes(void* cs, size_t len);
uint8_t peekU8();
uint16_t peekU16();
uint32_t peekU32();
uint64_t peekU64();
int8_t peekS8();
int16_t peekS16();
int32_t peekS32();
int64_t peekS64();
float32_t peekF32();
float64_t peekF64();
std::string peekString();
Bytestream peekBytestream();
std::string peekString(size_t len);
Bytestream peekBytestream(size_t len);
bool nextU8(uint8_t);
bool nextU16(uint16_t);
bool nextU32(uint32_t);
bool nextU64(uint64_t);
bool nextS8(int8_t);
bool nextS16(int16_t);
bool nextS32(int32_t);
bool nextS64(int64_t);
bool nextF32(float32_t);
bool nextF64(float64_t);
bool nextString(const std::string& bts);
bool nextBytestream(const Bytestream& bts);
void putU8(uint8_t);
void putU16(uint16_t);
void putU32(uint32_t);
void putU64(uint64_t);
void putS8(int8_t);
void putS16(int16_t);
void putS32(int32_t);
void putS64(int64_t);
void putF32(float32_t);
void putF64(float64_t);
void putString(const std::string&);
void putBytestream(const Bytestream&);
void putBytes(const void* c, size_t len);
void setNoOfNextBytes(size_t n);
void invalidateNoOfNextBytes();
size_t getNoOfNextBytes() {return _noOfNextBytes;}
bool noOfNextBytesValid() const {return _noOfNextBytesValid;}
Bytestream operator[](size_t i);
Bytestream& operator+=(size_t i);
Bytestream& operator-=(size_t i);
Bytestream& operator/(int i);
Bytestream& operator<<(const uint8_t& u);
Bytestream& operator<<(const uint16_t& u);
Bytestream& operator<<(const uint32_t& u);
Bytestream& operator<<(const uint64_t& u);
Bytestream& operator<<(const int8_t& u);
Bytestream& operator<<(const int16_t& u);
Bytestream& operator<<(const int32_t& u);
Bytestream& operator<<(const int64_t& u);
Bytestream& operator<<(const float32_t& u);
Bytestream& operator<<(const float64_t& u);
Bytestream& operator<<(const std::string& s);
Bytestream& operator<<(const Bytestream& other);
Bytestream& operator>>(uint8_t& u);
Bytestream& operator>>(uint16_t& u);
Bytestream& operator>>(uint32_t& u);
Bytestream& operator>>(uint64_t& u);
Bytestream& operator>>(int8_t& u);
Bytestream& operator>>(int16_t& u);
Bytestream& operator>>(int32_t& u);
Bytestream& operator>>(int64_t& u);
Bytestream& operator>>(float32_t& u);
Bytestream& operator>>(float64_t& u);
Bytestream& operator>>(std::string& s);
Bytestream& operator>>(Bytestream& other);
Bytestream& operator>>(const uint8_t& u);
Bytestream& operator>>(const uint16_t& u);
Bytestream& operator>>(const uint32_t& u);
Bytestream& operator>>(const uint64_t& u);
Bytestream& operator>>(const int8_t& u);
Bytestream& operator>>(const int16_t& u);
Bytestream& operator>>(const int32_t& u);
Bytestream& operator>>(const int64_t& u);
Bytestream& operator>>(const float32_t& u);
Bytestream& operator>>(const float64_t& u);
Bytestream& operator>>(const std::string& s);
bool operator>>=(const uint8_t& u);
bool operator>>=(const uint16_t& u);
bool operator>>=(const uint32_t& u);
bool operator>>=(const uint64_t& u);
bool operator>>=(const int8_t& u);
bool operator>>=(const int16_t& u);
bool operator>>=(const int32_t& u);
bool operator>>=(const int64_t& u);
bool operator>>=(const float32_t& u);
bool operator>>=(const float64_t& u);
bool operator>>=(const std::string& s);
bool operator>>=(const Bytestream& other);
private:
uint8_t* _data;
size_t _size;
size_t _pos;
size_t _noOfNextBytes;
bool _noOfNextBytesValid;
Endianness _endianness;
bool needsSwap();
void _after(size_t bytesRead);
void _before(size_t bytesToRead);
};
#endif

40
src/convertchecker.cpp Normal file
View file

@ -0,0 +1,40 @@
#include "convertchecker.h"
#include <QProcess>
ConvertChecker::ConvertChecker()
{
_pdf = false;
QProcess* pdftoppm = new QProcess(this);
pdftoppm->setProgram("pdftoppm");
pdftoppm->setArguments({"-h"});
pdftoppm->start();
if(pdftoppm->waitForFinished(2000))
{
if(pdftoppm->exitStatus() == QProcess::NormalExit && pdftoppm->exitCode() == 0)
{
_pdf = true;
}
}
}
ConvertChecker::~ConvertChecker() {
}
ConvertChecker* ConvertChecker::m_Instance = 0;
ConvertChecker* ConvertChecker::instance()
{
static QMutex mutex;
if (!m_Instance)
{
mutex.lock();
if (!m_Instance)
m_Instance = new ConvertChecker;
mutex.unlock();
}
return m_Instance;
}

26
src/convertchecker.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef CONVERTCHECKER_H
#define CONVERTCHECKER_H
#include <QObject>
#include <QMutex>
class ConvertChecker : public QObject
{
Q_OBJECT
public:
static ConvertChecker* instance();
Q_PROPERTY(bool pdf MEMBER _pdf)
signals:
protected:
private:
static ConvertChecker* m_Instance;
ConvertChecker();
~ConvertChecker();
ConvertChecker(const ConvertChecker &);
ConvertChecker& operator=(const ConvertChecker &);
bool _pdf;
};
#endif // CONVERTCHECKER_H

370
src/convertworker.cpp Normal file
View file

@ -0,0 +1,370 @@
#include "convertworker.h"
#include <sailfishapp.h>
#include "papersizes.h"
#include <QImage>
#include <QMatrix>
#include <QPainter>
void ppm2PwgEnv(QStringList& env, bool urf, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble, bool srgb, quint32 pages)
{
env.append("HWRES_X="+QString::number(HwResX));
env.append("HWRES_Y="+QString::number(HwResY));
if(urf)
{
env.append("URF=true");
}
if(Quality >= 3 && Quality <= 5)
{
env.append("QUALITY="+QString::number(Quality));
}
if(PaperSize != "")
{
env.append("PAGE_SIZE_NAME="+PaperSize);
}
env.append("DUPLEX="+QString::number(TwoSided));
env.append("TUMBLE="+QString::number(Tumble));
env.append("SRGB="+QString::number(srgb));
if(pages != 0)
{
env.append("PAGES="+QString::number(pages));
}
}
void ConvertWorker::convertPdf(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble)
{
QProcess* pdfinfo = new QProcess(this);
pdfinfo->setProgram("pdfinfo");
pdfinfo->setArguments({filename});
pdfinfo->start();
if(!pdfinfo->waitForStarted() || !pdfinfo->waitForFinished())
{
qDebug() << "pdfinfo died";
pdfinfo->deleteLater();
tempfile->deleteLater();
emit failed(tr("Failed to get info about PDF file"));
return;
}
QByteArray pdfInfoOutput = pdfinfo->readAllStandardOutput();
pdfinfo->deleteLater();
qDebug() << pdfInfoOutput;
QList<QByteArray> pdfInfoOutputLines = pdfInfoOutput.split('\n');
quint32 pages = 0;
for(QList<QByteArray>::iterator it = pdfInfoOutputLines.begin(); it != pdfInfoOutputLines.end(); it++)
{
if(it->startsWith("Pages"))
{
QList<QByteArray> pagesTokens = it->split(' ');
pages = pagesTokens.last().toInt();
}
}
bool urf = false;
bool ps = false;
if(targetFormat == "image/urf")
{
urf = true;
}
else if(targetFormat == "image/pwg-raster")
{
//ok
}
else if(targetFormat == "application/postscript")
{
ps = true;
}
else
{
emit failed(tr("Unsupported target format"));
return;
}
if(urf && (HwResX != HwResY))
{ // URF only supports symmetric resolutions
qDebug() << "Unsupported URF resolution" << PaperSize;
tempfile->deleteLater();
emit failed(tr("Unsupported resolution (dpi)"));
return;
}
QString ShortPaperSize;
if(PaperSize == "iso_a4_210x297mm")
{
ShortPaperSize = "A4";
}
else if (PaperSize == "iso_a3_297x420mm")
{
ShortPaperSize = "A3";
}
else if (PaperSize == "na_letter_8.5x11in")
{
ShortPaperSize = "letter";
}
else if (PaperSize == "na_legal_8.5x14in")
{
ShortPaperSize = "legal";
}
else
{
qDebug() << "Unsupported PDF paper size" << PaperSize;
tempfile->deleteLater();
emit failed(tr("Unsupported PDF paper size"));
return;
}
if(ps)
{
QProcess* pdftops = new QProcess(this);
pdftops->setProgram("pdftops");
QStringList PdfToPsArgs = {"-paper", ShortPaperSize, filename, "-"};
if(TwoSided)
{
PdfToPsArgs.prepend("-duplex");
}
pdftops->setArguments(PdfToPsArgs);
pdftops->setStandardOutputFile(tempfile->fileName(), QIODevice::Append);
connect(pdftops, SIGNAL(finished(int, QProcess::ExitStatus)), pdftops, SLOT(deleteLater()));
pdftops->start();
qDebug() << "Starting";
if(!pdftops->waitForStarted())
{
qDebug() << "pdftops died";
tempfile->deleteLater();
emit failed(tr("Conversion error"));
return;
}
qDebug() << "Started";
if(!pdftops->waitForFinished())
{
qDebug() << "pdftops failed";
tempfile->deleteLater();
emit failed(tr("Conversion error"));
return;
}
}
else
{
QProcess* pdftocairo = new QProcess(this);
pdftocairo->setProgram("pdftocairo");
pdftocairo->setArguments({"-pdf", "-paper", ShortPaperSize, filename, "-"});
QProcess* pdftoppm = new QProcess(this);
pdftoppm->setProgram("pdftoppm");
QStringList Pdf2PpmArgs = {"-rx", QString::number(HwResX), "-ry", QString::number(HwResY)};
if(Colors != 3)
{
Pdf2PpmArgs.append("-gray");
}
pdftoppm->setArguments(Pdf2PpmArgs);
QProcess* ppm2pwg = new QProcess(this);
// Yo dawg, I heard you like programs...
ppm2pwg->setProgram("harbour-seaprint");
ppm2pwg->setArguments({"ppm2pwg"});
QStringList env;
ppm2PwgEnv(env, urf, Quality, PaperSize, HwResX, HwResY, TwoSided, Tumble, false, pages);
qDebug() << "ppm2pwg env is " << env;
ppm2pwg->setEnvironment(env);
pdftocairo->setStandardOutputProcess(pdftoppm);
pdftoppm->setStandardOutputProcess(ppm2pwg);
ppm2pwg->setStandardOutputFile(tempfile->fileName(), QIODevice::Append);
connect(pdftocairo, SIGNAL(finished(int, QProcess::ExitStatus)), pdftocairo, SLOT(deleteLater()));
connect(pdftoppm, SIGNAL(finished(int, QProcess::ExitStatus)), pdftoppm, SLOT(deleteLater()));
connect(ppm2pwg, SIGNAL(finished(int, QProcess::ExitStatus)), ppm2pwg, SLOT(deleteLater()));
qDebug() << "All connected";
pdftocairo->start();
pdftoppm->start();
ppm2pwg->start();
qDebug() << "Starting";
if(!pdftocairo->waitForStarted())
{
qDebug() << "pdftocairo died";
tempfile->deleteLater();
emit failed(tr("Conversion error"));
return;
}
if(!pdftoppm->waitForStarted())
{
qDebug() << "pdftoppm died";
tempfile->deleteLater();
emit failed(tr("Conversion error"));
return;
}
if(!ppm2pwg->waitForStarted())
{
qDebug() << "ppm2pwg died";
tempfile->deleteLater();
emit failed(tr("Conversion error"));
return;
}
qDebug() << "All started";
if(!ppm2pwg->waitForFinished())
{
qDebug() << "ppm2pwg failed";
tempfile->deleteLater();
emit failed(tr("Conversion error"));
return;
}
}
qDebug() << "Finished";
emit done(request, tempfile);
qDebug() << "posted";
}
void ConvertWorker::convertImage(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY)
{
bool urf = false;
QString imageFormat = "";
QStringList supportedImageFormats = {"image/jpeg", "image/png", "image/gif"};
if(targetFormat == "image/urf")
{
urf = true;
}
else if(targetFormat == "image/pwg-raster")
{
//ok
}
else if(supportedImageFormats.contains(targetFormat))
{
imageFormat = targetFormat.split("/")[1];
}
else
{
emit failed(tr("Unsupported target format"));
return;
}
if(urf && (HwResX != HwResY))
{ // URF only supports symmetric resolutions
qDebug() << "Unsupported URF resolution" << PaperSize;
tempfile->deleteLater();
emit failed(tr("Unsupported resolution (dpi)"));
return;
}
if(!PaperSizes.contains(PaperSize))
{
qDebug() << "Unsupported paper size" << PaperSize;
tempfile->deleteLater();
emit failed(tr("Unsupported paper size"));
return;
}
QPair<float,float> wh = PaperSizes[PaperSize];
quint32 Width = qRound(wh.first/25.4*HwResX);
quint32 Height = qRound(wh.second/25.4*HwResY);
qDebug() << "Size is" << Width << "x" << Height;
QImage inImage;
if(!inImage.load(filename))
{
qDebug() << "failed to load";
emit failed(tr("Failed to load image"));
return;
}
if(inImage.width() > inImage.height())
{
inImage = inImage.transformed(QMatrix().rotate(90.0));
}
inImage = inImage.scaled(Width, Height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
QImage outImage = QImage(Width, Height, inImage.format());
outImage.fill(Qt::white);
QPainter painter(&outImage);
painter.drawImage(0, (outImage.height()-inImage.height())/2, inImage);
painter.end();
if(imageFormat != "")
{ // We are converting to a supported image format
QTemporaryFile tmpImage;
tmpImage.open();
qDebug() << "Raw image: " << tmpImage.fileName();
outImage.save(tmpImage.fileName(), imageFormat.toStdString().c_str());
QFile tempfileAsFile(tempfile->fileName());
tempfileAsFile.open(QIODevice::Append);
tempfileAsFile.write(tmpImage.readAll());
tempfileAsFile.close();
tmpImage.close();
}
else
{ // We are converting to a raster format
QTemporaryFile tmpImage;
tmpImage.open();
qDebug() << "Raw image: " << tmpImage.fileName();
outImage.save(tmpImage.fileName(), Colors == 1 ? "pgm" : "ppm");
tmpImage.close();
QProcess* ppm2pwg = new QProcess(this);
// Yo dawg, I heard you like programs...
ppm2pwg->setProgram("harbour-seaprint");
ppm2pwg->setArguments({"ppm2pwg"});
QStringList env;
ppm2PwgEnv(env, urf, Quality, PaperSize, HwResX, HwResY, false, false, true, 0);
qDebug() << "ppm2pwg env is " << env;
ppm2pwg->setEnvironment(env);
ppm2pwg->setStandardInputFile(tmpImage.fileName());
ppm2pwg->setStandardOutputFile(tempfile->fileName(), QIODevice::Append);
connect(ppm2pwg, SIGNAL(finished(int, QProcess::ExitStatus)), ppm2pwg, SLOT(deleteLater()));
qDebug() << "All connected";
ppm2pwg->start();
qDebug() << "Starting";
if(!ppm2pwg->waitForStarted())
{
qDebug() << "ppm2pwg died";
tempfile->deleteLater();
emit failed(tr("Conversion error"));
return;
}
qDebug() << "All started";
ppm2pwg->waitForFinished();
qDebug() << "Finished";
}
emit done(request, tempfile);
qDebug() << "posted";
}

24
src/convertworker.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef CONVERTWORKER_H
#define CONVERTWORKER_H
#include <QObject>
#include <QtNetwork>
class ConvertWorker : public QObject
{
Q_OBJECT
public slots:
void convertPdf(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble);
void convertImage(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY);
signals:
void done(QNetworkRequest request, QTemporaryFile* data);
void failed(QString message);
};
#endif // CONVERTWORKER_H

View file

@ -4,25 +4,40 @@
#include <seaprint_version.h>
#include <src/ippdiscovery.h>
#include <src/ippprinter.h>
#include <src/mimer.h>
#include <src/convertchecker.h>
static QObject* ippdiscovery_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
#define PPM2PWG_MAIN ppm2pwg_main
#include <ppm2pwg/ppm2pwg.cpp>
template <class T>
static QObject* singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
Q_UNUSED(scriptEngine)
IppDiscovery *ippdiscovery = IppDiscovery::instance();
return ippdiscovery;
T *inst = T::instance();
return inst;
}
int main(int argc, char *argv[])
{
if(argc >= 1 && QString("ppm2pwg") == argv[1])
{
return ppm2pwg_main(argc-1, &(argv[1]));
}
QGuiApplication* app = SailfishApp::application(argc, argv);
app->setApplicationVersion(QStringLiteral(SEAPRINT_VERSION));
qmlRegisterSingletonType<IppDiscovery>("seaprint.ippdiscovery", 1, 0, "IppDiscovery", ippdiscovery_singletontype_provider);
qmlRegisterSingletonType<IppDiscovery>("seaprint.ippdiscovery", 1, 0, "IppDiscovery", singletontype_provider<IppDiscovery>);
qmlRegisterSingletonType<Mimer>("seaprint.mimer", 1, 0, "Mimer", singletontype_provider<Mimer>);
qmlRegisterSingletonType<ConvertChecker>("seaprint.convertchecker", 1, 0, "ConvertChecker", singletontype_provider<ConvertChecker>);
qmlRegisterType<IppPrinter>("seaprint.ippprinter", 1, 0, "IppPrinter");
qmlRegisterUncreatableType<IppMsg>("seaprint.ippmsg", 1, 0, "IppMsg", "Only used to supply an enum type");
QQuickView* view = SailfishApp::createView();

View file

@ -1,4 +1,6 @@
#include "ippdiscovery.h"
#include <seaprint_version.h>
#define A 1
#define PTR 12
#define TXT 16
@ -148,7 +150,8 @@ void IppDiscovery::readPendingDatagrams()
QHostAddress sender;
quint16 senderPort;
QStringList ipp_ptrs;
QStringList new_ipp_ptrs;
QStringList new_targets;
socket->readDatagram((char*)(resp.raw()), size, &sender, &senderPort);
sender = QHostAddress(sender.toIPv4Address());
@ -180,7 +183,7 @@ void IppDiscovery::readPendingDatagrams()
QString tmpname = get_addr(resp).join(".");
if(aaddr.endsWith("_ipp._tcp.local"))
{
ipp_ptrs.append(tmpname);
new_ipp_ptrs.append(tmpname);
}
}
else if(atype == TXT)
@ -204,6 +207,7 @@ void IppDiscovery::readPendingDatagrams()
QString target = get_addr(resp).join(".");
_ports[aaddr] = port;
_targets[aaddr] = target;
new_targets.append(target);
}
else if(atype == A)
{
@ -225,25 +229,35 @@ void IppDiscovery::readPendingDatagrams()
qDebug() << e.what();
return;
}
qDebug() << "new ipp ptrs" << ipp_ptrs;
qDebug() << "new ipp ptrs" << new_ipp_ptrs;
qDebug() << "ipp ptrs" << _ipp;
qDebug() << "rps" << _rps;
qDebug() << "ports" << _ports;
qDebug() << "new targets" << new_targets;
qDebug() << "targets" << _targets;
qDebug() << "AAs" << _AAs;
qDebug() << "AAAAs" << _AAAAs;
for(QStringList::Iterator it = ipp_ptrs.begin(); it != ipp_ptrs.end(); it++)
for(QStringList::Iterator it = new_ipp_ptrs.begin(); it != new_ipp_ptrs.end(); it++)
{
if(!_ipp.contains(*it))
{
_ipp.append(*it);
}
if(!_ports.contains(*it) || !_targets.contains(*it) || !_rps.contains(*it))
// If pointer does not resolve to a target or is missing information, query about it
if( !_targets.contains(*it) || !_ports.contains(*it) || !_rps.contains(*it))
{ // if the PTR doesn't already resolve, ask for everything about it
sendQuery(ALL, it->split('.'));
}
}
for(QStringList::Iterator it = new_targets.begin(); it != new_targets.end(); it++)
{
// If target does not resolve to an address, query about it
if(!_AAs.contains(*it))
{
sendQuery(ALL, it->split('.'));
}
}
}
this->update();
@ -287,7 +301,10 @@ QImage IppDiscovery::requestImage(const QString &id, QSize *size, const QSize &r
url.setHost(_AAs.value(url.host()));
}
QNetworkReply* reply = nam->get(QNetworkRequest(url));
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint "SEAPRINT_VERSION);
QNetworkReply* reply = nam->get(request);
QEventLoop el;
connect(reply, SIGNAL(finished()),&el,SLOT(quit()));

View file

@ -38,7 +38,7 @@ IppMsg::IppMsg(QNetworkReply* resp)
while(!bts.atEnd())
{
if(bts.peekU8() <= IppTag::PrinterAttrs) {
if(bts.peekU8() <= IppTag::UnsupportedAttrs) {
if(currentAttrType == IppTag::OpAttrs) {
_opAttrs = attrs;
@ -49,6 +49,9 @@ IppMsg::IppMsg(QNetworkReply* resp)
else if (currentAttrType == IppTag::PrinterAttrs) {
_printerAttrs = attrs;
}
else if (currentAttrType == IppTag::UnsupportedAttrs) {
qDebug() << "WARNING: unsupported attrs reported:" << attrs;
}
if(bts >>= (uint8_t)IppTag::EndAttrs) {
break;
@ -78,12 +81,12 @@ QString IppMsg::consume_attribute(QJsonObject& attrs, Bytestream& data, QString
data/tmp_len >> tmp_str;
name = tmp_str!="" ? tmp_str.c_str() : lastName;
switch (tag) {
case OpAttrs:
case JobAttrs:
case EndAttrs:
case PrinterAttrs:
case UnsupportedAttrs:
Q_ASSERT(false);
case Integer:
case Enum:
@ -197,14 +200,16 @@ QByteArray IppMsg::encode(Operation op)
ipp << encode_attr(val["tag"].toInt(), it.key(), val["value"]);
}
}
for(QJsonArray::iterator ait = _jobAttrs.begin(); ait != _jobAttrs.begin(); ait++)
for(QJsonArray::iterator ait = _jobAttrs.begin(); ait != _jobAttrs.end(); ait++)
{
ipp << quint8(2);
QJsonObject tmpObj = ait->toObject();
for(QJsonObject::iterator it = tmpObj.begin(); it != tmpObj.end(); it++)
{
QJsonObject val = it.value().toObject();
ipp << encode_attr(val["tag"].toInt(), it.key(), val["value"]);
if (!tmpObj.isEmpty()) {
ipp << quint8(2);
for(QJsonObject::iterator it = tmpObj.begin(); it != tmpObj.end(); it++)
{
QJsonObject val = it.value().toObject();
ipp << encode_attr(val["tag"].toInt(), it.key(), val["value"]);
}
}
}
@ -243,7 +248,6 @@ Bytestream IppMsg::encode_attr(quint8 tag, QString name, QJsonValueRef value)
}
case Resolution:
{
qDebug() << value << value.toObject();
qint32 x = value.toObject()["x"].toInt();
qint32 y = value.toObject()["y"].toInt();
qint8 units = value.toObject()["units"].toInt();
@ -268,8 +272,12 @@ Bytestream IppMsg::encode_attr(quint8 tag, QString name, QJsonValueRef value)
case Charset:
case NaturalLanguage:
case MimeMediaType:
req << quint16(value.toString().length()) << value.toString().toStdString();
{
QByteArray tmpstr = value.toString().toUtf8();
req << quint16(tmpstr.length());
req.putBytes(tmpstr.data(), tmpstr.length());
break;
}
default:
qDebug() << "uncaught tag" << tag;
Q_ASSERT(false);

View file

@ -4,6 +4,7 @@
#include "bytestream.h"
#include <QByteArray>
#include <QObject>
#include <QDebug>
#include <QUrl>
#include <QtNetwork>
@ -12,6 +13,7 @@
class IppMsg
{
Q_GADGET
public:
enum IppTag : quint8 {
@ -19,6 +21,8 @@ public:
JobAttrs = 0x02,
EndAttrs = 0x03,
PrinterAttrs = 0x04,
UnsupportedAttrs = 0x05,
Unsupported = 0x10,
Integer = 0x21,
Boolean = 0x22,
Enum = 0x23,
@ -37,6 +41,7 @@ public:
NaturalLanguage = 0x48,
MimeMediaType = 0x49
};
Q_ENUMS(IppTag)
enum Operation : quint16 {
PrintJob = 0x0002,
@ -57,8 +62,8 @@ public:
PurgeJobs = 0x0012
};
IppMsg();
IppMsg(QNetworkReply* resp);
explicit IppMsg();
explicit IppMsg(QNetworkReply* resp);
IppMsg(QJsonObject opAttrs, QJsonObject jobAttrs = QJsonObject());
IppMsg(const IppMsg& other) = default;
~IppMsg();

View file

@ -1,4 +1,7 @@
#include "ippprinter.h"
#include <seaprint_version.h>
#include "mimer.h"
#include "papersizes.h"
IppPrinter::IppPrinter()
{
@ -7,19 +10,32 @@ IppPrinter::IppPrinter()
_jobs_nam = new QNetworkAccessManager(this);
_job_cancel_nam = new QNetworkAccessManager(this);
connect(_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(getPrinterAttributesFinished(QNetworkReply*)));
connect(_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
connect(_nam, &QNetworkAccessManager::finished, this, &IppPrinter::getPrinterAttributesFinished);
connect(_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
connect(_print_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(printRequestFinished(QNetworkReply*)));
connect(_print_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
connect(_print_nam, &QNetworkAccessManager::finished, this, &IppPrinter::printRequestFinished);
connect(_print_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
connect(_jobs_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(getJobsRequestFinished(QNetworkReply*)));
connect(_jobs_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
connect(_jobs_nam, &QNetworkAccessManager::finished,this, &IppPrinter::getJobsRequestFinished);
connect(_jobs_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
connect(_job_cancel_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(cancelJobFinished(QNetworkReply*)));
connect(_job_cancel_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
connect(_job_cancel_nam, &QNetworkAccessManager::finished,this, &IppPrinter::cancelJobFinished);
connect(_job_cancel_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
QObject::connect(this, &IppPrinter::urlChanged, this, &IppPrinter::onUrlChanged);
qRegisterMetaType<QTemporaryFile*>("QTemporaryFile*");
_worker = new ConvertWorker;
_worker->moveToThread(&_workerThread);
connect(&_workerThread, &QThread::finished, _worker, &QObject::deleteLater);
connect(this, &IppPrinter::doConvertPdf, _worker, &ConvertWorker::convertPdf);
connect(this, &IppPrinter::doConvertImage, _worker, &ConvertWorker::convertImage);
connect(_worker, &ConvertWorker::done, this, &IppPrinter::convertDone);
connect(_worker, &ConvertWorker::failed, this, &IppPrinter::convertFailed);
_workerThread.start();
}
IppPrinter::~IppPrinter() {
@ -79,11 +95,15 @@ void IppPrinter::refresh() {
_attrs = QJsonObject();
emit attrsChanged();
_additionalDocumentFormats = QStringList();
emit additionalDocumentFormatsChanged();
QNetworkRequest request;
request.setUrl(httpUrl());
// request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
QJsonObject o = opAttrs();
IppMsg msg = IppMsg(o);
@ -101,12 +121,42 @@ void IppPrinter::getPrinterAttributesFinished(QNetworkReply *reply)
IppMsg resp(reply);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getPrinterAttrs();
_attrs = resp.getPrinterAttrs();
if(resp.getOpAttrs().keys().contains("status-message"))
{ // Sometimes there are no response attributes at all,
// maybe status-message from the operation attributes is somewhat useful
_attrs["status-message"] = resp.getOpAttrs()["status-message"];
}
}
catch(std::exception e)
{
qDebug() << e.what();
}
}
if(_attrs.contains("printer-device-id"))
{
QJsonArray supportedMimeTypes = _attrs["document-format-supported"].toObject()["value"].toArray();
QStringList printerDeviceId = _attrs["printer-device-id"].toObject()["value"].toString().split(";");
for (QStringList::iterator it = printerDeviceId.begin(); it != printerDeviceId.end(); it++)
{
QStringList kv = it->split(":");
if(kv.length()==2 && kv[0]=="CMD")
{
QStringList cmds = kv[1].split(",");
if(cmds.contains("PDF") && !supportedMimeTypes.contains("application/pdf"))
{
_additionalDocumentFormats.append("application/pdf");
}
if(cmds.contains("POSTSCRIPT") && !supportedMimeTypes.contains("application/postscript"))
{
_additionalDocumentFormats.append("application/postscript");
}
}
}
qDebug() << "additionalDocumentFormats" << _additionalDocumentFormats;
emit additionalDocumentFormatsChanged();
}
emit attrsChanged();
}
@ -131,7 +181,7 @@ void IppPrinter::printRequestFinished(QNetworkReply *reply)
_jobAttrs.insert("job-state-message", QJsonObject {{"tag", IppMsg::TextWithoutLanguage}, {"value", "Network error"}});
}
emit jobAttrsChanged();
emit jobAttrsFinished(status);
emit jobFinished(status);
}
void IppPrinter::getJobsRequestFinished(QNetworkReply *reply)
@ -154,17 +204,20 @@ void IppPrinter::getJobsRequestFinished(QNetworkReply *reply)
void IppPrinter::cancelJobFinished(QNetworkReply *reply)
{
bool status = false;
if(reply->error() == QNetworkReply::NoError)
{
try {
IppMsg resp(reply);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
status = resp.getStatus() <= 0xff;
}
catch(std::exception e)
{
qDebug() << e.what();
}
}
emit cancelStatus(status);
getJobs();
}
@ -190,45 +243,223 @@ void IppPrinter::ignoreKnownSslErrors(QNetworkReply *reply, const QList<QSslErro
reply->ignoreSslErrors(errors);
}
void IppPrinter::convertDone(QNetworkRequest request, QTemporaryFile* data)
{
connect(_print_nam, SIGNAL(finished(QNetworkReply*)), data, SLOT(deleteLater()));
data->open();
setBusyMessage("Transferring");
bool IppPrinter::print(QJsonObject attrs, QString filename){
qDebug() << "printing" << filename << attrs;
QNetworkReply* reply = _print_nam->post(request, data);
connect(reply, &QNetworkReply::uploadProgress, this, &IppPrinter::setProgress);
}
void IppPrinter::convertFailed(QString message)
{
_jobAttrs = QJsonObject();
_jobAttrs.insert("job-state-message", QJsonObject {{"tag", IppMsg::TextWithoutLanguage}, {"value", message}});
emit jobAttrsChanged();
emit jobFinished(false);
}
QString firstMatch(QJsonArray supported, QStringList wanted)
{
for(QStringList::iterator it = wanted.begin(); it != wanted.end(); it++)
{
if(supported.contains(*it))
{
return *it;
}
}
return "";
}
QString targetFormatIfAuto(QString documentFormat, QString mimeType, QJsonArray supportedMimeTypes, bool forceRaster)
{
if(forceRaster)
{
return firstMatch(supportedMimeTypes, {"image/pwg-raster", "image/urf"});
}
else if(documentFormat == "application/octet-stream")
{
if(mimeType == "application/pdf")
{
return firstMatch(supportedMimeTypes, {"application/pdf", "application/postscript", "image/pwg-raster", "image/urf" });
}
else if (mimeType.contains("image"))
{
return firstMatch(supportedMimeTypes, {"image/png", "image/gif", "image/jpeg", "image/pwg-raster", "image/urf"});
}
return documentFormat;
}
return documentFormat;
}
void IppPrinter::print(QJsonObject attrs, QString filename,
bool alwaysConvert, bool forceIncluDeDocumentFormat, bool removeRedundantConvertAttrs)
{
qDebug() << "printing" << filename << attrs
<< alwaysConvert << forceIncluDeDocumentFormat << removeRedundantConvertAttrs;
_progress = "";
emit progressChanged();
QFile file(filename);
bool file_ok = file.open(QIODevice::ReadOnly);
if(!file_ok)
return false;
{
emit convertFailed(tr("Failed to open file"));
return;
}
Mimer* mimer = Mimer::instance();
QString mimeType = mimer->get_type(filename);
QJsonArray supportedMimeTypes = _attrs["document-format-supported"].toObject()["value"].toArray();
for(QStringList::iterator it = _additionalDocumentFormats.begin(); it != _additionalDocumentFormats.end(); it++)
{
supportedMimeTypes.append(*it);
}
qDebug() << supportedMimeTypes << supportedMimeTypes.contains(mimeType);
QFileInfo fileinfo(file);
QNetworkRequest request;
request.setUrl(httpUrl());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
QJsonObject o = opAttrs();
o.insert("job-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", fileinfo.fileName()}});
QJsonArray jobCreationAttributes = _attrs["job-creation-attributes-supported"].toObject()["value"].toArray();
// Only include if printer supports it
// if (filename.endsWith("pdf"))
// {
// attrs.insert("document-format", QJsonObject {{"tag", 73}, {"value", "application/pdf"}});
// }
// else if (filename.endsWith("jpg")) {
// attrs.insert("document-format", QJsonObject {{"tag", 73}, {"value", "image/jpeg"}});
// }
QString documentFormat = getAttrOrDefault(attrs, "document-format").toString();
qDebug() << "target format:" << documentFormat << "alwaysConvert:" << alwaysConvert;
documentFormat = targetFormatIfAuto(documentFormat, mimeType, supportedMimeTypes, alwaysConvert);
qDebug() << "adjusted target format:" << documentFormat;
if(documentFormat == "" || documentFormat == "application/octet-string")
{
emit convertFailed(tr("Unknown document format"));
return;
}
if(!jobCreationAttributes.contains("document-format") && !forceIncluDeDocumentFormat)
{ // Only include if printer supports it
attrs.remove("document-format");
}
qDebug() << "Printing job" << o << attrs;
QNetworkRequest request;
request.setUrl(httpUrl());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
QJsonValue PrinterResolutionRef = getAttrOrDefault(attrs, "printer-resolution");
quint32 HwResX = PrinterResolutionRef.toObject()["x"].toInt();
quint32 HwResY = PrinterResolutionRef.toObject()["y"].toInt();
if(documentFormat == "image/urf")
{ // Ensure symmetric resolution for URF
if(HwResX < HwResY)
{
HwResY = HwResX;
}
else
{
HwResX = HwResY;
}
QJsonObject tmpObj;
tmpObj["units"] = PrinterResolutionRef.toObject()["units"];
tmpObj["x"] = (int)HwResX;
tmpObj["y"] = (int)HwResY;
attrs["printer-resolution"] = tmpObj;
}
quint32 Quality = getAttrOrDefault(attrs, "print-quality").toInt();
QString PrintColorMode = getAttrOrDefault(attrs, "print-color-mode").toString();
quint32 Colors = PrintColorMode.contains("color") ? 3 : PrintColorMode.contains("monochrome") ? 1 : 0;
QString PaperSize = getAttrOrDefault(attrs, "media").toString();
if(!PaperSizes.contains(PaperSize))
{
emit convertFailed(tr("Unsupported print media"));
return;
}
QString Sides = getAttrOrDefault(attrs, "sides").toString();
if(removeRedundantConvertAttrs && (documentFormat=="image/pwg-raster" ||
documentFormat=="image/urf"))
{
attrs.remove("sides");
attrs.remove("print-color-mode");
}
if(removeRedundantConvertAttrs && documentFormat == "application/postscript")
{
attrs.remove("sides");
}
qDebug() << "Final job attributes:" << attrs;
IppMsg job = IppMsg(o, attrs);
QByteArray contents = job.encode(IppMsg::PrintJob);
QByteArray filedata = file.readAll();
contents = contents.append(filedata);
// Always convert images to get resizing
if((mimeType == documentFormat) && !mimeType.contains("image"))
{
QByteArray filedata = file.readAll();
contents = contents.append(filedata);
file.close();
_print_nam->post(request, contents);
file.close();
return true;
setBusyMessage("Transferring");
QNetworkReply* reply = _print_nam->post(request, contents);
connect(reply, &QNetworkReply::uploadProgress, this, &IppPrinter::setProgress);
}
else
{
file.close();
QTemporaryFile* tempfile = new QTemporaryFile();
tempfile->open();
tempfile->write(contents);
qDebug() << tempfile->fileName();
tempfile->close();
setBusyMessage("Converting");
if(mimeType == "application/pdf")
{
bool TwoSided = false;
bool Tumble = false;
if(Sides=="two-sided-long-edge")
{
TwoSided = true;
}
else if(Sides=="two-sided-short-edge")
{
TwoSided = true;
Tumble = true;
}
emit doConvertPdf(request, filename, tempfile, documentFormat, Colors, Quality,
PaperSize, HwResX, HwResY, TwoSided, Tumble);
}
else if (mimeType.contains("image"))
{
emit doConvertImage(request, filename, tempfile, documentFormat, Colors, Quality,
PaperSize, HwResX, HwResY);
}
else
{
emit convertFailed(tr("Cannot convert this file format"));
return;
}
}
return;
}
bool IppPrinter::getJobs() {
@ -246,6 +477,8 @@ bool IppPrinter::getJobs() {
request.setUrl(httpUrl());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
_jobs_nam->post(request, contents);
return true;
@ -253,7 +486,7 @@ bool IppPrinter::getJobs() {
bool IppPrinter::cancelJob(qint32 jobId) {
qDebug() << "getting jobs";
qDebug() << "cancelling jobs";
QJsonObject o = opAttrs();
o.insert("job-id", QJsonObject {{"tag", IppMsg::Integer}, {"value", jobId}});
@ -266,6 +499,8 @@ bool IppPrinter::cancelJob(qint32 jobId) {
request.setUrl(httpUrl());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
_job_cancel_nam->post(request, contents);
return true;
@ -280,3 +515,29 @@ QUrl IppPrinter::httpUrl() {
return url;
}
void IppPrinter::setBusyMessage(QString msg)
{
_busyMessage = msg;
emit busyMessageChanged();
}
void IppPrinter::setProgress(qint64 sent, qint64 total)
{
if(total == 0)
return;
_progress = QString::number(100*sent/total);
_progress += "%";
emit progressChanged();
}
QJsonValue IppPrinter::getAttrOrDefault(QJsonObject jobAttrs, QString name)
{
if(jobAttrs.contains(name))
{
return jobAttrs[name].toObject()["value"];
}
else {
return _attrs[name+"-default"].toObject()["value"];
}
}

View file

@ -4,6 +4,7 @@
#include <QtNetwork>
#include <QNetworkAccessManager>
#include "ippmsg.h"
#include "convertworker.h"
class IppPrinter : public QObject
{
@ -12,6 +13,9 @@ class IppPrinter : public QObject
Q_PROPERTY(QJsonObject attrs MEMBER _attrs NOTIFY attrsChanged)
Q_PROPERTY(QJsonObject jobAttrs MEMBER _jobAttrs NOTIFY jobAttrsChanged)
Q_PROPERTY(QJsonArray jobs MEMBER _jobs NOTIFY jobsChanged)
Q_PROPERTY(QStringList additionalDocumentFormats MEMBER _additionalDocumentFormats NOTIFY additionalDocumentFormatsChanged)
Q_PROPERTY(QString busyMessage MEMBER _busyMessage NOTIFY busyMessageChanged)
Q_PROPERTY(QString progress MEMBER _progress NOTIFY progressChanged)
public:
@ -24,7 +28,6 @@ public:
Q_INVOKABLE void refresh();
Q_INVOKABLE bool print(QJsonObject attrs, QString file);
Q_INVOKABLE bool getJobs();
Q_INVOKABLE bool cancelJob(qint32 jobId);
@ -34,9 +37,26 @@ signals:
void jobAttrsChanged();
void jobsChanged();
void jobAttrsFinished(bool status);
void jobFinished(bool status);
void cancelStatus(bool status);
void doConvertPdf(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble);
void doConvertImage(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY);
void additionalDocumentFormatsChanged();
void busyMessageChanged();
void progressChanged();
public slots:
void print(QJsonObject attrs, QString file,
bool alwaysConvert, bool forceIncluDeDocumentFormat, bool removeRedundantAttributesForRaster);
void onUrlChanged();
void getPrinterAttributesFinished(QNetworkReply* reply);
void printRequestFinished(QNetworkReply* reply);
@ -45,12 +65,20 @@ public slots:
void ignoreKnownSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
void convertDone(QNetworkRequest request, QTemporaryFile* data);
void convertFailed(QString message);
private:
QUrl _url;
QUrl httpUrl();
QJsonObject opAttrs();
void setBusyMessage(QString msg);
void setProgress(qint64 sent, qint64 total);
QJsonValue getAttrOrDefault(QJsonObject jobAttrs, QString name);
QNetworkAccessManager* _nam;
QNetworkAccessManager* _jobs_nam;
QNetworkAccessManager* _job_cancel_nam;
@ -60,6 +88,14 @@ private:
QJsonObject _jobAttrs;
QJsonArray _jobs;
QStringList _additionalDocumentFormats;
QString _busyMessage;
QString _progress;
QThread _workerThread;
ConvertWorker* _worker;
};
#endif // IPPPRINTER_H

28
src/mimer.cpp Normal file
View file

@ -0,0 +1,28 @@
#include "mimer.h"
Mimer::Mimer()
{
}
Mimer* Mimer::m_Instance = 0;
Mimer* Mimer::instance()
{
static QMutex mutex;
if (!m_Instance)
{
mutex.lock();
if (!m_Instance)
m_Instance = new Mimer;
mutex.unlock();
}
return m_Instance;
}
QString Mimer::get_type(QString filename) {
return _db.mimeTypeForFile(filename).name();
}

22
src/mimer.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef MIMER_H
#define MIMER_H
#include <QString>
#include <QObject>
#include <QMutex>
#include <QMimeDatabase>
class Mimer : public QObject
{
Q_OBJECT
public:
static Mimer* instance();
Q_INVOKABLE QString get_type(QString filename);
private:
Mimer();
static Mimer* m_Instance;
QMimeDatabase _db;
};
#endif // MIMER_H

209
src/papersizes.h Normal file
View file

@ -0,0 +1,209 @@
#ifndef PAPERSIZES_H
#define PAPERSIZES_H
#include <QMap>
#include <QPair>
static QMap<QString, QPair<float,float>> 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}}};
#endif // PAPERSIZES_H

View file

@ -63,6 +63,22 @@
<source>Spanish</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Polish</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Installed</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Not installed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AddPrinterDialog</name>
@ -87,6 +103,52 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>BusyPage</name>
<message>
<source>Print success: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Print failed: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ConvertWorker</name>
<message>
<source>Conversion error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to load image</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported PDF paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported resolution (dpi)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported target format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to get info about PDF file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
@ -112,14 +174,6 @@
<source>No file selected</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Choose file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>View jobs</source>
<translation type="unfinished"></translation>
@ -140,6 +194,37 @@
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Choose file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IppPrinter</name>
<message>
<source>Failed to open file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cannot convert this file format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown document format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JobsPage</name>
@ -167,6 +252,41 @@
<source>job</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cancelling job failed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NagScreen</name>
<message>
<source>Dismiss</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Don&apos;t show again</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies are not installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>In order to convert PDF files to other formats, you need utilities from the package &quot;poppler-utils&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>To install, enable delveloper mode, and open a terminal.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Become root:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Install poppler-utils:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrinterPage</name>
@ -195,11 +315,58 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Print success: </source>
<source>Print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Print failed: </source>
<source>Transfer format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Media source</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Show nag-screen</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Consider additional formats</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Some printers support more formats than they advertise correctly. However, additional formats can be inferred from other attributes. Mainly relevant for Postscript-compatible printers that also support PDF.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Always convert to raster format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force conversion to PWG/URF raster format. This is mainly intended for testing.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force-include document format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force the document-format attribute to be included. Some printers have trouble recognizing certain formats, sometimes it helps to include this atribute even if the printer does not claim to support it.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant attributes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant IPP attributes, if they are also conveyed in the transfer format. Some printers reject the job even if the settings are consistent.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display the warning page about optional dependencies not being installed, if they are not installed.</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -282,7 +449,127 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>No compatible formats supported</source>
<source>PDF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Postscript</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PWG-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>URF-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PNG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JPEG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>GIF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto-sense</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>by-pass tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bottom</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>center</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>manual</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>middle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>photo</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>rear</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>right</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>side</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>top</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>color</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>highlight</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>one-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided flipped</source>
<translation type="unfinished"></translation>
</message>
</context>

View file

@ -63,6 +63,22 @@
<source>Spanish</source>
<translation>Español</translation>
</message>
<message>
<source>Polish</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Installed</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Not installed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AddPrinterDialog</name>
@ -87,6 +103,52 @@
<translation>Desconocida</translation>
</message>
</context>
<context>
<name>BusyPage</name>
<message>
<source>Print success: </source>
<translation type="unfinished">Impresión correcta: </translation>
</message>
<message>
<source>Print failed: </source>
<translation type="unfinished">Impresión fallida: </translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ConvertWorker</name>
<message>
<source>Conversion error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to load image</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported PDF paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported resolution (dpi)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported target format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to get info about PDF file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
@ -112,14 +174,6 @@
<source>No file selected</source>
<translation>Ningún archivo seleccionado</translation>
</message>
<message>
<source>Choose file</source>
<translation>Elegir archivo</translation>
</message>
<message>
<source>None</source>
<translation>Ninguno</translation>
</message>
<message>
<source>View jobs</source>
<translation>Ver trabajos</translation>
@ -140,6 +194,37 @@
<source>Unknown</source>
<translation>Desconocido</translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation type="unfinished">No hay formatos compatibles</translation>
</message>
<message>
<source>Choose file</source>
<translation type="unfinished">Elegir archivo</translation>
</message>
<message>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IppPrinter</name>
<message>
<source>Failed to open file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cannot convert this file format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown document format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JobsPage</name>
@ -167,6 +252,41 @@
<source>job</source>
<translation>trabajo</translation>
</message>
<message>
<source>Cancelling job failed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NagScreen</name>
<message>
<source>Dismiss</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Don&apos;t show again</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies are not installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>In order to convert PDF files to other formats, you need utilities from the package &quot;poppler-utils&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>To install, enable delveloper mode, and open a terminal.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Become root:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Install poppler-utils:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrinterPage</name>
@ -195,12 +315,59 @@
<translation>Resolución</translation>
</message>
<message>
<source>Print success: </source>
<translation>Impresión correcta: </translation>
<source>Print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Print failed: </source>
<translation>Impresión fallida: </translation>
<source>Transfer format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Media source</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Show nag-screen</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Consider additional formats</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Some printers support more formats than they advertise correctly. However, additional formats can be inferred from other attributes. Mainly relevant for Postscript-compatible printers that also support PDF.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Always convert to raster format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force conversion to PWG/URF raster format. This is mainly intended for testing.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force-include document format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force the document-format attribute to be included. Some printers have trouble recognizing certain formats, sometimes it helps to include this atribute even if the printer does not claim to support it.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant attributes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant IPP attributes, if they are also conveyed in the transfer format. Some printers reject the job even if the settings are consistent.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display the warning page about optional dependencies not being installed, if they are not installed.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -282,8 +449,128 @@
<translation>ppp</translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation>No hay formatos compatibles</translation>
<source>PDF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Postscript</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PWG-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>URF-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PNG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JPEG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>GIF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto-sense</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>by-pass tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bottom</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>center</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>manual</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>middle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>photo</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>rear</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>right</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>side</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>top</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>color</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>highlight</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>one-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided flipped</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -63,6 +63,22 @@
<source>Spanish</source>
<translation>Espagnol</translation>
</message>
<message>
<source>Polish</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Installed</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Not installed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AddPrinterDialog</name>
@ -87,6 +103,52 @@
<translation>Inconnu</translation>
</message>
</context>
<context>
<name>BusyPage</name>
<message>
<source>Print success: </source>
<translation type="unfinished">Impression réussie :</translation>
</message>
<message>
<source>Print failed: </source>
<translation type="unfinished">Échec de l&apos;impression :</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished">Inconnu</translation>
</message>
</context>
<context>
<name>ConvertWorker</name>
<message>
<source>Conversion error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to load image</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported PDF paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported resolution (dpi)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported target format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to get info about PDF file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
@ -112,14 +174,6 @@
<source>No file selected</source>
<translation>Aucun fichier sélectionné</translation>
</message>
<message>
<source>Choose file</source>
<translation>Choisir un fichier</translation>
</message>
<message>
<source>None</source>
<translation>Aucun</translation>
</message>
<message>
<source>View jobs</source>
<translation>Voir les travaux</translation>
@ -140,6 +194,37 @@
<source>Unknown</source>
<translation>Inconnu</translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation>Aucun format compatible supporté</translation>
</message>
<message>
<source>Choose file</source>
<translation type="unfinished">Choisir un fichier</translation>
</message>
<message>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IppPrinter</name>
<message>
<source>Failed to open file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cannot convert this file format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown document format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JobsPage</name>
@ -167,6 +252,41 @@
<source>job</source>
<translation>tâche</translation>
</message>
<message>
<source>Cancelling job failed</source>
<translation>Échec de l&apos;annulation de la tâche d&apos;impression</translation>
</message>
</context>
<context>
<name>NagScreen</name>
<message>
<source>Dismiss</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Don&apos;t show again</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies are not installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>In order to convert PDF files to other formats, you need utilities from the package &quot;poppler-utils&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>To install, enable delveloper mode, and open a terminal.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Become root:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Install poppler-utils:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrinterPage</name>
@ -195,23 +315,70 @@
<translation>Résolution</translation>
</message>
<message>
<source>Print success: </source>
<translation>Impression réussie :</translation>
<source>Print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Print failed: </source>
<translation>Échec de l&apos;impression :</translation>
<source>Transfer format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Media source</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Show nag-screen</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Consider additional formats</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Some printers support more formats than they advertise correctly. However, additional formats can be inferred from other attributes. Mainly relevant for Postscript-compatible printers that also support PDF.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Always convert to raster format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force conversion to PWG/URF raster format. This is mainly intended for testing.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force-include document format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force the document-format attribute to be included. Some printers have trouble recognizing certain formats, sometimes it helps to include this atribute even if the printer does not claim to support it.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant attributes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant IPP attributes, if they are also conveyed in the transfer format. Some printers reject the job even if the settings are consistent.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display the warning page about optional dependencies not being installed, if they are not installed.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>utils</name>
<message>
<source>pending</source>
<translation type="unfinished"></translation>
<translation>en attente</translation>
</message>
<message>
<source>pending-held</source>
<translation type="unfinished"></translation>
<translation>en attente de confirmation</translation>
</message>
<message>
<source>processing</source>
@ -223,15 +390,15 @@
</message>
<message>
<source>canceled</source>
<translation>annulé</translation>
<translation>annulée</translation>
</message>
<message>
<source>aborted</source>
<translation>abandonné</translation>
<translation>abandonnée</translation>
</message>
<message>
<source>completed</source>
<translation>terminé</translation>
<translation>terminée</translation>
</message>
<message>
<source>unknown state </source>
@ -282,7 +449,127 @@
<translation>pts/cm</translation>
</message>
<message>
<source>No compatible formats supported</source>
<source>PDF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Postscript</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PWG-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>URF-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PNG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JPEG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>GIF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto-sense</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>by-pass tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bottom</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>center</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>manual</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>middle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>photo</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>rear</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>right</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>side</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>top</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>color</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>highlight</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>one-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided flipped</source>
<translation type="unfinished"></translation>
</message>
</context>

View file

@ -0,0 +1,292 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="pl">
<context>
<name>AboutPage</name>
<message>
<source>GitHub repository</source>
<translation>Repozytorium GitHub</translation>
</message>
<message>
<source>Report an Issue</source>
<translation>Raportuj błąd</translation>
</message>
<message>
<source>About</source>
<translation>O SeaPrint</translation>
</message>
<message>
<source>Network printing for Sailfish OS.</source>
<translation>Drukowanie sieciowe dla SailfishOS</translation>
</message>
<message>
<source>Icons</source>
<translation>Ikony</translation>
</message>
<message>
<source>Icon made by Gregguh.</source>
<translation>Ikona stworzona przez Gregguh.</translation>
</message>
<message>
<source>General contributions</source>
<translation>Główni developerzy</translation>
</message>
<message>
<source>Translations</source>
<translation>Tłumaczenia</translation>
</message>
<message>
<source>Chinese</source>
<translation>Chiński</translation>
</message>
<message>
<source>Licensing</source>
<translation>Licencjonowanie</translation>
</message>
<message>
<source>Source code is available at GitHub. Translations, bug reports and other contributions are welcome!</source>
<translation>Źródła dostępne na GitHub. Tłumaczenia,raportowanie błędów i inna pomoc mile widziane!</translation>
</message>
<message>
<source>SeaPrint licencing is still TBD, but will be some flavor of open.</source>
<translation>Licencjonowanie SeaPrint jest jeszcze nieustalone, ale będzie jakąś odmianą wolnej licencji.</translation>
</message>
<message>
<source>French</source>
<translation>Francuski</translation>
</message>
<message>
<source>Code and Testing - Rudi Timmermans</source>
<translation>Kod i Testowanie - Rudi Timmermans</translation>
</message>
<message>
<source>Spanish</source>
<translation>Hiszpański</translation>
</message>
</context>
<context>
<name>AddPrinterDialog</name>
<message>
<source>Add printer</source>
<translation>Dodaj drukarkę</translation>
</message>
<message>
<source>On WiFI:</source>
<translation>Na WIFI:</translation>
</message>
<message>
<source>Found:</source>
<translation>Znalezione:</translation>
</message>
<message>
<source>No printer found</source>
<translation>Nie znaleziono drukarek</translation>
</message>
<message>
<source>Unknown</source>
<translation>Nieznana drukarka</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>SeaPrint</source>
<translation>SeaPrint</translation>
</message>
</context>
<context>
<name>FirstPage</name>
<message>
<source>Add by URL</source>
<translation>Dodaj za pomocą URL</translation>
</message>
<message>
<source>URL</source>
<translation>URL</translation>
</message>
<message>
<source>Refresh</source>
<translation>Odśwież</translation>
</message>
<message>
<source>No file selected</source>
<translation>Nie wybrano pliku</translation>
</message>
<message>
<source>View jobs</source>
<translation>Wyświetl zadania</translation>
</message>
<message>
<source>Remove printer</source>
<translation>Usuń drukarkę</translation>
</message>
<message>
<source>Removing printer</source>
<translation>Usuwanie drukarki</translation>
</message>
<message>
<source>About SeaPrint</source>
<translation>O SeaPrint</translation>
</message>
<message>
<source>Unknown</source>
<translation>Nieznany</translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation>Brak obsługiwanych kompatybilnych formatów</translation>
</message>
<message>
<source>Choose file</source>
<translation>Wybierz plik</translation>
</message>
</context>
<context>
<name>JobsPage</name>
<message>
<source>Refresh</source>
<translation>Odśwież</translation>
</message>
<message>
<source>jobs</source>
<translation>zadania</translation>
</message>
<message>
<source>Untitled job</source>
<translation>Zadania bez nazwy</translation>
</message>
<message>
<source>Cancel job</source>
<translation>Anuluj zadanie</translation>
</message>
<message>
<source>Cancelling job</source>
<translation>usuwanie zadania</translation>
</message>
<message>
<source>job</source>
<translation>zadanie</translation>
</message>
<message>
<source>Cancelling job failed</source>
<translation>Nieudane usuwanie zadania</translation>
</message>
</context>
<context>
<name>PrinterPage</name>
<message>
<source>Print</source>
<translation>Drukuj</translation>
</message>
<message>
<source>Sides</source>
<translation>Strony</translation>
</message>
<message>
<source>Copies</source>
<translation>Kopie</translation>
</message>
<message>
<source>Color mode</source>
<translation>Tryb koloru</translation>
</message>
<message>
<source>Quality</source>
<translation>Jakość</translation>
</message>
<message>
<source>Resolution</source>
<translation>Rozdzielczość</translation>
</message>
<message>
<source>Print success: </source>
<translation>Drukowanie udane: </translation>
</message>
<message>
<source>Print failed: </source>
<translation>Nieudane drukowanie: </translation>
</message>
<message>
<source>Print media</source>
<translation>Drukuj multimedia</translation>
</message>
</context>
<context>
<name>utils</name>
<message>
<source>pending</source>
<translation>oczekiwanie</translation>
</message>
<message>
<source>pending-held</source>
<translation>w toku</translation>
</message>
<message>
<source>processing</source>
<translation>procesowanie</translation>
</message>
<message>
<source>processing-stopped</source>
<translation>procesowanie zatrzymane</translation>
</message>
<message>
<source>canceled</source>
<translation>anulowano</translation>
</message>
<message>
<source>aborted</source>
<translation>przerwano</translation>
</message>
<message>
<source>completed</source>
<translation>ukończone</translation>
</message>
<message>
<source>unknown state </source>
<translation>nieznany stan</translation>
</message>
<message>
<source>draft</source>
<translation>szkic</translation>
</message>
<message>
<source>normal</source>
<translation>normalny</translation>
</message>
<message>
<source>high</source>
<translation>wysoka</translation>
</message>
<message>
<source>unknown quality </source>
<translation>nieznana jakość</translation>
</message>
<message>
<source>portrait</source>
<translation>portretowy</translation>
</message>
<message>
<source>landscape</source>
<translation>horyzontalny</translation>
</message>
<message>
<source>reverse landscape</source>
<translation>odwrócony horyzontalny</translation>
</message>
<message>
<source>reverse portrait</source>
<translation>odwrócony horyzontalny</translation>
</message>
<message>
<source>unknown orientation </source>
<translation>nieznany układ</translation>
</message>
<message>
<source>dpi</source>
<translation>dpi</translation>
</message>
<message>
<source>dots/cm</source>
<translation>punkty/cm</translation>
</message>
</context>

View file

@ -63,6 +63,22 @@
<source>Spanish</source>
<translation>西</translation>
</message>
<message>
<source>Polish</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Installed</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Not installed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AddPrinterDialog</name>
@ -87,6 +103,52 @@
<translation></translation>
</message>
</context>
<context>
<name>BusyPage</name>
<message>
<source>Print success: </source>
<translation type="unfinished">:</translation>
</message>
<message>
<source>Print failed: </source>
<translation type="unfinished">:</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ConvertWorker</name>
<message>
<source>Conversion error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to load image</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported PDF paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported resolution (dpi)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported target format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to get info about PDF file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
@ -112,14 +174,6 @@
<source>No file selected</source>
<translation></translation>
</message>
<message>
<source>Choose file</source>
<translation></translation>
</message>
<message>
<source>None</source>
<translation></translation>
</message>
<message>
<source>View jobs</source>
<translation></translation>
@ -140,6 +194,37 @@
<source>Unknown</source>
<translation></translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation></translation>
</message>
<message>
<source>Choose file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IppPrinter</name>
<message>
<source>Failed to open file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cannot convert this file format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown document format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JobsPage</name>
@ -167,6 +252,41 @@
<source>Cancelling job</source>
<translation></translation>
</message>
<message>
<source>Cancelling job failed</source>
<translation></translation>
</message>
</context>
<context>
<name>NagScreen</name>
<message>
<source>Dismiss</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Don&apos;t show again</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies are not installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>In order to convert PDF files to other formats, you need utilities from the package &quot;poppler-utils&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>To install, enable delveloper mode, and open a terminal.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Become root:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Install poppler-utils:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrinterPage</name>
@ -195,12 +315,59 @@
<translation></translation>
</message>
<message>
<source>Print success: </source>
<translation>:</translation>
<source>Print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Print failed: </source>
<translation>:</translation>
<source>Transfer format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Media source</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Show nag-screen</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Consider additional formats</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Some printers support more formats than they advertise correctly. However, additional formats can be inferred from other attributes. Mainly relevant for Postscript-compatible printers that also support PDF.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Always convert to raster format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force conversion to PWG/URF raster format. This is mainly intended for testing.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force-include document format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force the document-format attribute to be included. Some printers have trouble recognizing certain formats, sometimes it helps to include this atribute even if the printer does not claim to support it.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant attributes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant IPP attributes, if they are also conveyed in the transfer format. Some printers reject the job even if the settings are consistent.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display the warning page about optional dependencies not being installed, if they are not installed.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -282,8 +449,128 @@
<translation>/</translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation type="unfinished"></translation>
<source>PDF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Postscript</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PWG-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>URF-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PNG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JPEG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>GIF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto-sense</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>by-pass tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bottom</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>center</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>manual</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>middle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>photo</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>rear</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>right</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>side</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>top</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>color</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>highlight</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>one-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided flipped</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -63,6 +63,22 @@
<source>Spanish</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Polish</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Installed</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Not installed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AddPrinterDialog</name>
@ -87,6 +103,52 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>BusyPage</name>
<message>
<source>Print success: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Print failed: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ConvertWorker</name>
<message>
<source>Conversion error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to load image</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported PDF paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported paper size</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported resolution (dpi)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported target format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to get info about PDF file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
@ -112,14 +174,6 @@
<source>No file selected</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Choose file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>View jobs</source>
<translation type="unfinished"></translation>
@ -140,6 +194,37 @@
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No compatible formats supported</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Choose file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>IppPrinter</name>
<message>
<source>Failed to open file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cannot convert this file format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unknown document format</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JobsPage</name>
@ -167,6 +252,41 @@
<source>job</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cancelling job failed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NagScreen</name>
<message>
<source>Dismiss</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Don&apos;t show again</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Optional dependencies are not installed!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>In order to convert PDF files to other formats, you need utilities from the package &quot;poppler-utils&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>To install, enable delveloper mode, and open a terminal.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Become root:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Install poppler-utils:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PrinterPage</name>
@ -195,11 +315,58 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Print success: </source>
<source>Print media</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Print failed: </source>
<source>Transfer format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Media source</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Show nag-screen</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Consider additional formats</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Some printers support more formats than they advertise correctly. However, additional formats can be inferred from other attributes. Mainly relevant for Postscript-compatible printers that also support PDF.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Always convert to raster format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force conversion to PWG/URF raster format. This is mainly intended for testing.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force-include document format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Force the document-format attribute to be included. Some printers have trouble recognizing certain formats, sometimes it helps to include this atribute even if the printer does not claim to support it.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant attributes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove redundant IPP attributes, if they are also conveyed in the transfer format. Some printers reject the job even if the settings are consistent.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Display the warning page about optional dependencies not being installed, if they are not installed.</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -282,7 +449,127 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>No compatible formats supported</source>
<source>PDF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Postscript</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PWG-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>URF-raster</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PNG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JPEG</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>GIF</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto-sense</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>by-pass tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bottom</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>center</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>main</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>manual</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>middle</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>photo</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>rear</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>right</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>side</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>top</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>automatic</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>auto monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>color</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>highlight</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process bi-level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>process monochrome</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>one-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>two-sided flipped</source>
<translation type="unfinished"></translation>
</message>
</context>