2019-12-01 22:27:00 +03:00
|
|
|
#include "ippprinter.h"
|
2020-01-20 22:11:41 +03:00
|
|
|
#include <seaprint_version.h>
|
2020-05-03 15:13:44 +03:00
|
|
|
#include "mimer.h"
|
2020-05-16 16:17:42 +03:00
|
|
|
#include "papersizes.h"
|
2019-12-01 22:27:00 +03:00
|
|
|
|
|
|
|
IppPrinter::IppPrinter()
|
|
|
|
{
|
|
|
|
_nam = new QNetworkAccessManager(this);
|
2019-12-08 15:55:56 +03:00
|
|
|
_print_nam = new QNetworkAccessManager(this);
|
|
|
|
_jobs_nam = new QNetworkAccessManager(this);
|
2019-12-12 22:53:46 +03:00
|
|
|
_job_cancel_nam = new QNetworkAccessManager(this);
|
|
|
|
|
2020-06-06 12:27:08 +03:00
|
|
|
connect(_nam, &QNetworkAccessManager::finished, this, &IppPrinter::getPrinterAttributesFinished);
|
|
|
|
connect(_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
|
2020-01-04 13:55:22 +03:00
|
|
|
|
2020-06-06 12:27:08 +03:00
|
|
|
connect(_print_nam, &QNetworkAccessManager::finished, this, &IppPrinter::printRequestFinished);
|
|
|
|
connect(_print_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
|
2020-01-04 13:55:22 +03:00
|
|
|
|
2020-06-06 12:27:08 +03:00
|
|
|
connect(_jobs_nam, &QNetworkAccessManager::finished,this, &IppPrinter::getJobsRequestFinished);
|
|
|
|
connect(_jobs_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
|
2020-01-04 13:55:22 +03:00
|
|
|
|
2020-06-06 12:27:08 +03:00
|
|
|
connect(_job_cancel_nam, &QNetworkAccessManager::finished,this, &IppPrinter::cancelJobFinished);
|
|
|
|
connect(_job_cancel_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::ignoreKnownSslErrors);
|
2020-01-04 13:55:22 +03:00
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
QObject::connect(this, &IppPrinter::urlChanged, this, &IppPrinter::onUrlChanged);
|
2020-05-01 14:49:17 +03:00
|
|
|
qRegisterMetaType<QTemporaryFile*>("QTemporaryFile*");
|
2020-05-01 16:02:29 +03:00
|
|
|
|
|
|
|
_worker = new ConvertWorker;
|
|
|
|
_worker->moveToThread(&_workerThread);
|
|
|
|
|
|
|
|
connect(&_workerThread, &QThread::finished, _worker, &QObject::deleteLater);
|
|
|
|
|
|
|
|
connect(this, &IppPrinter::doConvertPdf, _worker, &ConvertWorker::convertPdf);
|
2020-05-13 20:53:44 +03:00
|
|
|
connect(this, &IppPrinter::doConvertImage, _worker, &ConvertWorker::convertImage);
|
2020-05-01 16:02:29 +03:00
|
|
|
connect(_worker, &ConvertWorker::done, this, &IppPrinter::convertDone);
|
2020-07-30 23:21:14 +03:00
|
|
|
connect(_worker, &ConvertWorker::progress, this, &IppPrinter::setProgress);
|
2020-05-01 16:02:29 +03:00
|
|
|
connect(_worker, &ConvertWorker::failed, this, &IppPrinter::convertFailed);
|
|
|
|
|
|
|
|
_workerThread.start();
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
IppPrinter::~IppPrinter() {
|
|
|
|
delete _nam;
|
2019-12-08 15:55:56 +03:00
|
|
|
delete _print_nam;
|
|
|
|
delete _jobs_nam;
|
2019-12-12 22:53:46 +03:00
|
|
|
delete _job_cancel_nam;
|
|
|
|
}
|
|
|
|
|
|
|
|
QJsonObject IppPrinter::opAttrs() {
|
2020-08-02 12:44:38 +03:00
|
|
|
QString name = qgetenv("USER");
|
2019-12-12 22:53:46 +03:00
|
|
|
QJsonObject o
|
|
|
|
{
|
|
|
|
{"attributes-charset", QJsonObject {{"tag", IppMsg::Charset}, {"value", "utf-8"}}},
|
|
|
|
{"attributes-natural-language", QJsonObject {{"tag", IppMsg::NaturalLanguage}, {"value", "en-us"}}},
|
2020-01-03 18:36:24 +03:00
|
|
|
{"printer-uri", QJsonObject {{"tag", IppMsg::Uri}, {"value", _url.toString()}}},
|
2020-08-02 12:44:38 +03:00
|
|
|
{"requesting-user-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", name}}},
|
2019-12-12 22:53:46 +03:00
|
|
|
};
|
|
|
|
return o;
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
|
2020-01-03 18:36:24 +03:00
|
|
|
void IppPrinter::setUrl(QString url_s)
|
2019-12-01 22:27:00 +03:00
|
|
|
{
|
2020-01-03 18:36:24 +03:00
|
|
|
QUrl url = QUrl(url_s);
|
|
|
|
|
|
|
|
qDebug() << url.scheme();
|
|
|
|
|
|
|
|
if(url.scheme() != "ipp" /* or ipps */)
|
|
|
|
{
|
|
|
|
//if https -> ipps, else:
|
|
|
|
if(url.scheme() == "")
|
|
|
|
{
|
|
|
|
url = QUrl("ipp://"+url_s); // Why isn't setScheme working?
|
|
|
|
}
|
|
|
|
else if (url.scheme() == "http") {
|
|
|
|
url.setScheme("ipp");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
url = QUrl();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qDebug() << url_s << url;
|
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
if(url != _url)
|
|
|
|
{
|
|
|
|
_url = url;
|
|
|
|
emit urlChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IppPrinter::onUrlChanged()
|
|
|
|
{
|
2019-12-17 22:20:09 +03:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
void IppPrinter::refresh() {
|
2019-12-01 22:27:00 +03:00
|
|
|
_attrs = QJsonObject();
|
|
|
|
emit attrsChanged();
|
|
|
|
|
2020-06-05 21:05:48 +03:00
|
|
|
_additionalDocumentFormats = QStringList();
|
|
|
|
emit additionalDocumentFormatsChanged();
|
|
|
|
|
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
QNetworkRequest request;
|
2020-01-03 18:36:24 +03:00
|
|
|
|
|
|
|
request.setUrl(httpUrl());
|
2019-12-01 22:27:00 +03:00
|
|
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
|
2020-06-01 21:21:09 +03:00
|
|
|
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
|
2019-12-01 22:27:00 +03:00
|
|
|
|
2019-12-12 22:53:46 +03:00
|
|
|
QJsonObject o = opAttrs();
|
2020-06-16 21:34:27 +03:00
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
IppMsg msg = IppMsg(o);
|
|
|
|
_nam->post(request, msg.encode(IppMsg::GetPrinterAttrs));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void IppPrinter::getPrinterAttributesFinished(QNetworkReply *reply)
|
|
|
|
{
|
2019-12-08 15:55:56 +03:00
|
|
|
qDebug() << reply->error() << reply->errorString() << reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
|
2019-12-15 13:24:36 +03:00
|
|
|
_attrs = QJsonObject();
|
2019-12-01 22:27:00 +03:00
|
|
|
if(reply->error() == QNetworkReply::NoError)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
IppMsg resp(reply);
|
2019-12-08 15:55:56 +03:00
|
|
|
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getPrinterAttrs();
|
2019-12-01 22:27:00 +03:00
|
|
|
_attrs = resp.getPrinterAttrs();
|
|
|
|
}
|
2020-08-29 18:32:11 +03:00
|
|
|
catch(const std::exception& e)
|
2019-12-01 22:27:00 +03:00
|
|
|
{
|
|
|
|
qDebug() << e.what();
|
|
|
|
}
|
|
|
|
}
|
2020-06-05 21:05:48 +03:00
|
|
|
|
|
|
|
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(":");
|
2020-06-13 14:05:33 +03:00
|
|
|
if(kv.length()==2 && (kv[0]=="CMD" || kv[0]=="COMMAND SET"))
|
2020-06-05 21:05:48 +03:00
|
|
|
{
|
2020-06-13 14:05:33 +03:00
|
|
|
if(!supportedMimeTypes.contains("application/pdf") && kv[1].contains("PDF"))
|
2020-06-05 21:05:48 +03:00
|
|
|
{
|
|
|
|
_additionalDocumentFormats.append("application/pdf");
|
|
|
|
}
|
2020-06-13 14:05:33 +03:00
|
|
|
if(!supportedMimeTypes.contains("application/postscript") &&
|
|
|
|
kv[1].contains("Postscript", Qt::CaseInsensitive))
|
2020-06-05 21:05:48 +03:00
|
|
|
{
|
|
|
|
_additionalDocumentFormats.append("application/postscript");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
qDebug() << "additionalDocumentFormats" << _additionalDocumentFormats;
|
|
|
|
emit additionalDocumentFormatsChanged();
|
|
|
|
}
|
|
|
|
|
2019-12-15 13:24:36 +03:00
|
|
|
emit attrsChanged();
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
|
2019-12-08 15:55:56 +03:00
|
|
|
void IppPrinter::printRequestFinished(QNetworkReply *reply)
|
2019-12-01 22:27:00 +03:00
|
|
|
{
|
2019-12-17 22:18:57 +03:00
|
|
|
_jobAttrs = QJsonObject();
|
|
|
|
bool status = false;
|
2019-12-01 22:27:00 +03:00
|
|
|
if(reply->error() == QNetworkReply::NoError)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
IppMsg resp(reply);
|
2019-12-06 22:18:48 +03:00
|
|
|
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
|
2019-12-08 15:55:56 +03:00
|
|
|
_jobAttrs = resp.getJobAttrs()[0].toObject();
|
2020-06-12 18:02:24 +03:00
|
|
|
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
|
|
|
|
_jobAttrs["status-message"] = resp.getOpAttrs()["status-message"];
|
|
|
|
}
|
2019-12-17 22:18:57 +03:00
|
|
|
status = resp.getStatus() <= 0xff;
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
2020-08-29 18:32:11 +03:00
|
|
|
catch(const std::exception& e)
|
2019-12-01 22:27:00 +03:00
|
|
|
{
|
|
|
|
qDebug() << e.what();
|
|
|
|
}
|
|
|
|
}
|
2019-12-17 22:18:57 +03:00
|
|
|
else {
|
2020-06-13 14:05:33 +03:00
|
|
|
_jobAttrs.insert("job-state-message", QJsonObject {{"tag", IppMsg::TextWithoutLanguage},
|
|
|
|
{"value", "Network error"}});
|
2019-12-17 22:18:57 +03:00
|
|
|
}
|
|
|
|
emit jobAttrsChanged();
|
2020-04-04 14:56:36 +03:00
|
|
|
emit jobFinished(status);
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
|
2019-12-08 15:55:56 +03:00
|
|
|
void IppPrinter::getJobsRequestFinished(QNetworkReply *reply)
|
|
|
|
{
|
|
|
|
if(reply->error() == QNetworkReply::NoError)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
IppMsg resp(reply);
|
|
|
|
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
|
|
|
|
_jobs = resp.getJobAttrs();
|
|
|
|
emit jobsChanged();
|
|
|
|
}
|
2020-08-29 18:32:11 +03:00
|
|
|
catch(const std::exception& e)
|
2019-12-08 15:55:56 +03:00
|
|
|
{
|
|
|
|
qDebug() << e.what();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
|
2019-12-12 22:53:46 +03:00
|
|
|
void IppPrinter::cancelJobFinished(QNetworkReply *reply)
|
|
|
|
{
|
2020-02-23 15:11:28 +03:00
|
|
|
bool status = false;
|
2019-12-12 22:53:46 +03:00
|
|
|
if(reply->error() == QNetworkReply::NoError)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
IppMsg resp(reply);
|
|
|
|
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
|
2020-02-23 15:11:28 +03:00
|
|
|
status = resp.getStatus() <= 0xff;
|
2019-12-12 22:53:46 +03:00
|
|
|
}
|
2020-08-29 18:32:11 +03:00
|
|
|
catch(const std::exception& e)
|
2019-12-12 22:53:46 +03:00
|
|
|
{
|
|
|
|
qDebug() << e.what();
|
|
|
|
}
|
|
|
|
}
|
2020-02-23 15:11:28 +03:00
|
|
|
emit cancelStatus(status);
|
2019-12-12 22:53:46 +03:00
|
|
|
getJobs();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-04 13:55:22 +03:00
|
|
|
|
|
|
|
void IppPrinter::ignoreKnownSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
|
|
|
{
|
|
|
|
QList<QSslError> IgnoredSslErrors = {QSslError::NoError,
|
|
|
|
QSslError::SelfSignedCertificate,
|
|
|
|
QSslError::HostNameMismatch,
|
|
|
|
QSslError::UnableToGetLocalIssuerCertificate,
|
|
|
|
QSslError::UnableToVerifyFirstCertificate
|
|
|
|
};
|
|
|
|
|
|
|
|
qDebug() << errors;
|
|
|
|
for (QList<QSslError>::const_iterator it = errors.constBegin(); it != errors.constEnd(); it++) {
|
|
|
|
if(!IgnoredSslErrors.contains(it->error())) {
|
|
|
|
qDebug() << "Bad error: " << int(it->error()) << it->error();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// For whatever reason, it doesn't work to pass IgnoredSslErrors here
|
|
|
|
reply->ignoreSslErrors(errors);
|
|
|
|
}
|
|
|
|
|
2020-05-01 16:02:29 +03:00
|
|
|
void IppPrinter::convertDone(QNetworkRequest request, QTemporaryFile* data)
|
2020-05-01 14:49:17 +03:00
|
|
|
{
|
2020-05-01 16:02:29 +03:00
|
|
|
connect(_print_nam, SIGNAL(finished(QNetworkReply*)), data, SLOT(deleteLater()));
|
2020-05-01 14:49:17 +03:00
|
|
|
data->open();
|
2020-05-06 21:46:41 +03:00
|
|
|
|
|
|
|
setBusyMessage("Transferring");
|
|
|
|
|
2020-06-03 21:42:18 +03:00
|
|
|
QNetworkReply* reply = _print_nam->post(request, data);
|
|
|
|
|
|
|
|
connect(reply, &QNetworkReply::uploadProgress, this, &IppPrinter::setProgress);
|
2020-05-01 14:49:17 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-05-14 22:00:37 +03:00
|
|
|
void IppPrinter::convertFailed(QString message)
|
2020-05-01 16:02:29 +03:00
|
|
|
{
|
|
|
|
_jobAttrs = QJsonObject();
|
2020-05-14 22:00:37 +03:00
|
|
|
_jobAttrs.insert("job-state-message", QJsonObject {{"tag", IppMsg::TextWithoutLanguage}, {"value", message}});
|
2020-05-01 16:02:29 +03:00
|
|
|
emit jobAttrsChanged();
|
|
|
|
emit jobFinished(false);
|
|
|
|
}
|
2020-01-04 13:55:22 +03:00
|
|
|
|
2020-06-05 21:41:45 +03:00
|
|
|
QString firstMatch(QJsonArray supported, QStringList wanted)
|
|
|
|
{
|
|
|
|
for(QStringList::iterator it = wanted.begin(); it != wanted.end(); it++)
|
|
|
|
{
|
|
|
|
if(supported.contains(*it))
|
|
|
|
{
|
|
|
|
return *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2020-06-05 22:01:59 +03:00
|
|
|
QString targetFormatIfAuto(QString documentFormat, QString mimeType, QJsonArray supportedMimeTypes, bool forceRaster)
|
2020-06-05 21:41:45 +03:00
|
|
|
{
|
2020-06-05 22:01:59 +03:00
|
|
|
if(forceRaster)
|
|
|
|
{
|
|
|
|
return firstMatch(supportedMimeTypes, {"image/pwg-raster", "image/urf"});
|
|
|
|
}
|
|
|
|
else if(documentFormat == "application/octet-stream")
|
2020-06-05 21:41:45 +03:00
|
|
|
{
|
|
|
|
if(mimeType == "application/pdf")
|
|
|
|
{
|
2020-06-06 16:47:43 +03:00
|
|
|
return firstMatch(supportedMimeTypes, {"application/pdf", "application/postscript", "image/pwg-raster", "image/urf" });
|
2020-06-05 21:41:45 +03:00
|
|
|
}
|
|
|
|
else if (mimeType.contains("image"))
|
|
|
|
{
|
2020-09-10 21:01:21 +03:00
|
|
|
QStringList ImageFormatPrioList {"image/png", "image/gif", "image/pwg-raster", "image/urf", "image/jpeg"};
|
|
|
|
if(mimeType == "image/jpeg")
|
|
|
|
{
|
|
|
|
// Prioritize transferring JPEG as JPEG, as it will not be transcoded
|
|
|
|
// Normally, it is the last choice (as the others are lossless)
|
|
|
|
ImageFormatPrioList.prepend(mimeType);
|
|
|
|
}
|
|
|
|
return firstMatch(supportedMimeTypes, ImageFormatPrioList);
|
2020-06-05 21:41:45 +03:00
|
|
|
}
|
|
|
|
return documentFormat;
|
|
|
|
}
|
|
|
|
return documentFormat;
|
|
|
|
}
|
|
|
|
|
2020-09-23 21:23:23 +03:00
|
|
|
void IppPrinter::print(QJsonObject attrs, QString filename, bool alwaysConvert, bool alwaysUseMediaCol)
|
2020-06-04 22:31:46 +03:00
|
|
|
{
|
2020-09-23 21:23:23 +03:00
|
|
|
qDebug() << "printing" << filename << attrs << alwaysConvert;
|
2019-12-01 22:27:00 +03:00
|
|
|
|
2020-06-03 21:42:18 +03:00
|
|
|
_progress = "";
|
|
|
|
emit progressChanged();
|
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
QFile file(filename);
|
|
|
|
bool file_ok = file.open(QIODevice::ReadOnly);
|
|
|
|
if(!file_ok)
|
2020-04-04 14:56:36 +03:00
|
|
|
{
|
2020-05-14 22:00:37 +03:00
|
|
|
emit convertFailed(tr("Failed to open file"));
|
2020-04-04 14:56:36 +03:00
|
|
|
return;
|
|
|
|
}
|
2019-12-01 22:27:00 +03:00
|
|
|
|
2020-06-05 21:41:45 +03:00
|
|
|
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);
|
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
QFileInfo fileinfo(file);
|
|
|
|
|
2019-12-12 22:53:46 +03:00
|
|
|
QJsonObject o = opAttrs();
|
|
|
|
o.insert("job-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", fileinfo.fileName()}});
|
|
|
|
|
2020-06-16 21:34:27 +03:00
|
|
|
QString PaperSize = getAttrOrDefault(attrs, "media").toString();
|
|
|
|
|
2020-06-21 16:49:50 +03:00
|
|
|
if((attrs.contains("media-col") || alwaysUseMediaCol) && attrs.contains("media"))
|
2020-06-16 21:34:27 +03:00
|
|
|
{
|
|
|
|
qDebug() << "moving media to media-col" << PaperSize;
|
|
|
|
if(!PaperSizes.contains(PaperSize))
|
|
|
|
{
|
|
|
|
emit convertFailed(tr("Unknown document format dimensions"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = PaperSizes[PaperSize].first*100;
|
|
|
|
int y = PaperSizes[PaperSize].second*100;
|
|
|
|
|
|
|
|
QJsonObject Dimensions =
|
|
|
|
{{"tag", IppMsg::BeginCollection},
|
|
|
|
{"value", QJsonObject { {"x-dimension", QJsonObject{{"tag", IppMsg::Integer}, {"value", x}}},
|
|
|
|
{"y-dimension", QJsonObject{{"tag", IppMsg::Integer}, {"value", y}}} }
|
|
|
|
}};
|
|
|
|
|
|
|
|
// TODO: make a setter function
|
|
|
|
QJsonObject MediaCol = attrs["media-col"].toObject();
|
|
|
|
QJsonObject MediaColValue = MediaCol["value"].toObject();
|
|
|
|
MediaColValue["media-size"] = Dimensions;
|
|
|
|
MediaCol["value"] = MediaColValue;
|
2020-06-21 16:49:50 +03:00
|
|
|
MediaCol["tag"] = IppMsg::BeginCollection;
|
2020-06-16 21:34:27 +03:00
|
|
|
attrs["media-col"] = MediaCol;
|
|
|
|
|
|
|
|
attrs.remove("media");
|
|
|
|
}
|
2020-06-04 22:31:46 +03:00
|
|
|
|
|
|
|
QString documentFormat = getAttrOrDefault(attrs, "document-format").toString();
|
2020-06-05 22:01:59 +03:00
|
|
|
qDebug() << "target format:" << documentFormat << "alwaysConvert:" << alwaysConvert;
|
2020-06-04 22:31:46 +03:00
|
|
|
|
2020-06-13 18:56:28 +03:00
|
|
|
// document-format goes in the op-attrs and not the job-attrs
|
|
|
|
o.insert("document-format", QJsonObject {{"tag", IppMsg::MimeMediaType}, {"value", documentFormat}});
|
|
|
|
attrs.remove("document-format");
|
|
|
|
|
2020-06-05 22:01:59 +03:00
|
|
|
documentFormat = targetFormatIfAuto(documentFormat, mimeType, supportedMimeTypes, alwaysConvert);
|
2020-06-05 21:41:45 +03:00
|
|
|
qDebug() << "adjusted target format:" << documentFormat;
|
|
|
|
|
|
|
|
if(documentFormat == "" || documentFormat == "application/octet-string")
|
2020-06-04 22:31:46 +03:00
|
|
|
{
|
|
|
|
emit convertFailed(tr("Unknown document format"));
|
|
|
|
return;
|
|
|
|
}
|
2019-12-01 22:27:00 +03:00
|
|
|
|
2019-12-07 16:40:36 +03:00
|
|
|
qDebug() << "Printing job" << o << attrs;
|
2020-01-26 14:08:57 +03:00
|
|
|
|
2020-05-01 16:02:29 +03:00
|
|
|
QNetworkRequest request;
|
|
|
|
|
|
|
|
request.setUrl(httpUrl());
|
|
|
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
|
2020-06-01 21:21:09 +03:00
|
|
|
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
|
2020-05-01 16:02:29 +03:00
|
|
|
|
2020-05-09 21:39:50 +03:00
|
|
|
QJsonValue PrinterResolutionRef = getAttrOrDefault(attrs, "printer-resolution");
|
|
|
|
quint32 HwResX = PrinterResolutionRef.toObject()["x"].toInt();
|
|
|
|
quint32 HwResY = PrinterResolutionRef.toObject()["y"].toInt();
|
2020-05-05 21:36:01 +03:00
|
|
|
|
2020-06-04 22:31:46 +03:00
|
|
|
if(documentFormat == "image/urf")
|
2020-06-01 22:56:47 +03:00
|
|
|
{ // 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;
|
2020-06-10 20:30:22 +03:00
|
|
|
attrs["printer-resolution"] = QJsonObject { {"tag", IppMsg::Resolution}, {"value", tmpObj} };
|
2020-06-01 22:56:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-09 21:39:50 +03:00
|
|
|
quint32 Quality = getAttrOrDefault(attrs, "print-quality").toInt();
|
|
|
|
|
|
|
|
QString PrintColorMode = getAttrOrDefault(attrs, "print-color-mode").toString();
|
2020-06-05 22:46:17 +03:00
|
|
|
quint32 Colors = PrintColorMode.contains("color") ? 3 : PrintColorMode.contains("monochrome") ? 1 : 0;
|
2020-09-23 21:14:33 +03:00
|
|
|
bool pdfPageRangeAdjustNeeded = false;
|
2020-05-05 21:36:01 +03:00
|
|
|
|
2020-05-16 16:17:42 +03:00
|
|
|
if(!PaperSizes.contains(PaperSize))
|
|
|
|
{
|
|
|
|
emit convertFailed(tr("Unsupported print media"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-23 21:14:33 +03:00
|
|
|
quint32 PageRangeLow = 0;
|
|
|
|
quint32 PageRangeHigh = 0;
|
|
|
|
if(attrs.contains("page-ranges"))
|
|
|
|
{
|
|
|
|
QJsonObject PageRanges = getAttrOrDefault(attrs, "page-ranges").toObject();
|
|
|
|
PageRangeLow = PageRanges["low"].toInt();
|
|
|
|
PageRangeHigh = PageRanges["high"].toInt();
|
|
|
|
}
|
|
|
|
|
2020-06-06 15:59:44 +03:00
|
|
|
QString Sides = getAttrOrDefault(attrs, "sides").toString();
|
2020-09-23 21:23:23 +03:00
|
|
|
if(documentFormat=="image/pwg-raster" || documentFormat=="image/urf")
|
2020-06-06 15:59:44 +03:00
|
|
|
{
|
|
|
|
attrs.remove("sides");
|
2020-06-06 16:16:46 +03:00
|
|
|
attrs.remove("print-color-mode");
|
2020-09-23 21:14:33 +03:00
|
|
|
attrs.remove("page-ranges");
|
2020-06-06 15:59:44 +03:00
|
|
|
}
|
2020-09-23 21:23:23 +03:00
|
|
|
else if(documentFormat == "application/postscript")
|
2020-06-07 16:27:27 +03:00
|
|
|
{
|
|
|
|
attrs.remove("sides");
|
2020-09-23 21:14:33 +03:00
|
|
|
attrs.remove("page-ranges");
|
2020-06-07 16:27:27 +03:00
|
|
|
}
|
2020-09-23 21:14:33 +03:00
|
|
|
else if (documentFormat == "application/pdf")
|
2020-08-01 21:18:47 +03:00
|
|
|
{
|
2020-09-23 21:14:33 +03:00
|
|
|
if(attrs.contains("page-ranges") && !_attrs.contains("page-ranges-supported"))
|
2020-08-01 21:18:47 +03:00
|
|
|
{
|
2020-09-23 21:14:33 +03:00
|
|
|
pdfPageRangeAdjustNeeded = true;
|
|
|
|
attrs.remove("page-ranges");
|
2020-08-01 21:18:47 +03:00
|
|
|
}
|
|
|
|
}
|
2020-06-06 15:59:44 +03:00
|
|
|
|
2020-06-13 18:56:28 +03:00
|
|
|
qDebug() << "Final op attributes:" << o;
|
2020-06-06 16:16:46 +03:00
|
|
|
qDebug() << "Final job attributes:" << attrs;
|
|
|
|
|
2020-06-13 13:35:51 +03:00
|
|
|
IppMsg job = mk_msg(o, attrs);
|
2020-06-06 15:59:44 +03:00
|
|
|
QByteArray contents = job.encode(IppMsg::PrintJob);
|
2020-09-23 21:14:33 +03:00
|
|
|
|
|
|
|
// Non-jpeg images, Postscript and PDF (when not adjusting pages locally)
|
|
|
|
// Always convert non-jpeg images to get resizing
|
|
|
|
// TODO: make this sane
|
|
|
|
if((mimeType == documentFormat)
|
|
|
|
&& (documentFormat == "image/jpeg" || !mimeType.contains("image"))
|
|
|
|
&& !((documentFormat == "application/pdf") && pdfPageRangeAdjustNeeded))
|
2020-06-05 21:41:45 +03:00
|
|
|
{
|
|
|
|
QByteArray filedata = file.readAll();
|
|
|
|
contents = contents.append(filedata);
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
setBusyMessage("Transferring");
|
|
|
|
QNetworkReply* reply = _print_nam->post(request, contents);
|
|
|
|
connect(reply, &QNetworkReply::uploadProgress, this, &IppPrinter::setProgress);
|
|
|
|
}
|
|
|
|
else
|
2020-01-26 14:08:57 +03:00
|
|
|
{
|
|
|
|
file.close();
|
2020-05-09 21:39:50 +03:00
|
|
|
|
2020-01-26 14:08:57 +03:00
|
|
|
QTemporaryFile* tempfile = new QTemporaryFile();
|
|
|
|
tempfile->open();
|
|
|
|
tempfile->write(contents);
|
|
|
|
qDebug() << tempfile->fileName();
|
|
|
|
tempfile->close();
|
|
|
|
|
2020-05-06 21:46:41 +03:00
|
|
|
setBusyMessage("Converting");
|
|
|
|
|
2020-06-04 22:31:46 +03:00
|
|
|
if(mimeType == "application/pdf")
|
2020-05-13 20:53:44 +03:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-06-04 22:31:46 +03:00
|
|
|
emit doConvertPdf(request, filename, tempfile, documentFormat, Colors, Quality,
|
2020-08-01 21:18:47 +03:00
|
|
|
PaperSize, HwResX, HwResY, TwoSided, Tumble, PageRangeLow, PageRangeHigh);
|
2020-05-13 20:53:44 +03:00
|
|
|
}
|
2020-06-04 22:31:46 +03:00
|
|
|
else if (mimeType.contains("image"))
|
2020-05-13 20:53:44 +03:00
|
|
|
{
|
2020-06-04 22:31:46 +03:00
|
|
|
emit doConvertImage(request, filename, tempfile, documentFormat, Colors, Quality,
|
2020-05-16 16:17:42 +03:00
|
|
|
PaperSize, HwResX, HwResY);
|
2020-05-13 20:53:44 +03:00
|
|
|
}
|
2020-05-16 17:03:42 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
emit convertFailed(tr("Cannot convert this file format"));
|
|
|
|
return;
|
|
|
|
}
|
2020-01-26 14:08:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
2019-12-08 15:55:56 +03:00
|
|
|
|
|
|
|
bool IppPrinter::getJobs() {
|
|
|
|
|
|
|
|
qDebug() << "getting jobs";
|
|
|
|
|
2019-12-12 22:53:46 +03:00
|
|
|
QJsonObject o = opAttrs();
|
2020-01-03 15:37:51 +03:00
|
|
|
o.insert("requested-attributes", QJsonObject {{"tag", IppMsg::Keyword}, {"value", "all"}});
|
2019-12-08 15:55:56 +03:00
|
|
|
|
|
|
|
IppMsg job = IppMsg(o, QJsonObject());
|
|
|
|
|
|
|
|
QNetworkRequest request;
|
|
|
|
|
|
|
|
QByteArray contents = job.encode(IppMsg::GetJobs);
|
|
|
|
|
2020-01-03 18:36:24 +03:00
|
|
|
request.setUrl(httpUrl());
|
2019-12-08 15:55:56 +03:00
|
|
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
|
2020-06-01 21:21:09 +03:00
|
|
|
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
|
2020-01-20 22:11:41 +03:00
|
|
|
|
2019-12-08 15:55:56 +03:00
|
|
|
_jobs_nam->post(request, contents);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-12-12 22:53:46 +03:00
|
|
|
bool IppPrinter::cancelJob(qint32 jobId) {
|
|
|
|
|
2020-02-23 15:11:28 +03:00
|
|
|
qDebug() << "cancelling jobs";
|
2019-12-08 15:55:56 +03:00
|
|
|
|
2019-12-12 22:53:46 +03:00
|
|
|
QJsonObject o = opAttrs();
|
|
|
|
o.insert("job-id", QJsonObject {{"tag", IppMsg::Integer}, {"value", jobId}});
|
|
|
|
|
|
|
|
IppMsg job = IppMsg(o, QJsonObject());
|
|
|
|
|
|
|
|
QNetworkRequest request;
|
|
|
|
|
|
|
|
QByteArray contents = job.encode(IppMsg::CancelJob);
|
|
|
|
|
2020-01-03 18:36:24 +03:00
|
|
|
request.setUrl(httpUrl());
|
2019-12-12 22:53:46 +03:00
|
|
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
|
2020-06-01 21:21:09 +03:00
|
|
|
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
|
2020-01-20 22:11:41 +03:00
|
|
|
|
2019-12-12 22:53:46 +03:00
|
|
|
_job_cancel_nam->post(request, contents);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2020-01-03 18:36:24 +03:00
|
|
|
|
|
|
|
QUrl IppPrinter::httpUrl() {
|
|
|
|
QUrl url = _url;
|
|
|
|
url.setScheme("http");
|
|
|
|
if(url.port() == -1) {
|
|
|
|
url.setPort(631);
|
|
|
|
}
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2020-05-06 21:46:41 +03:00
|
|
|
void IppPrinter::setBusyMessage(QString msg)
|
|
|
|
{
|
|
|
|
_busyMessage = msg;
|
|
|
|
emit busyMessageChanged();
|
|
|
|
}
|
2020-05-09 21:39:50 +03:00
|
|
|
|
2020-06-03 21:42:18 +03:00
|
|
|
void IppPrinter::setProgress(qint64 sent, qint64 total)
|
|
|
|
{
|
|
|
|
if(total == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_progress = QString::number(100*sent/total);
|
|
|
|
_progress += "%";
|
|
|
|
emit progressChanged();
|
|
|
|
}
|
|
|
|
|
2020-05-09 21:39:50 +03:00
|
|
|
QJsonValue IppPrinter::getAttrOrDefault(QJsonObject jobAttrs, QString name)
|
|
|
|
{
|
|
|
|
if(jobAttrs.contains(name))
|
|
|
|
{
|
|
|
|
return jobAttrs[name].toObject()["value"];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return _attrs[name+"-default"].toObject()["value"];
|
|
|
|
}
|
|
|
|
}
|
2020-06-13 13:35:51 +03:00
|
|
|
|
|
|
|
IppMsg IppPrinter::mk_msg(QJsonObject opAttrs, QJsonObject jobAttrs)
|
|
|
|
{
|
|
|
|
if(_attrs.contains("ipp-versions-supported") &&
|
|
|
|
_attrs["ipp-versions-supported"].toObject()["value"].toArray().contains("2.0"))
|
|
|
|
{
|
|
|
|
qDebug() << "TWO-POINT-ZERO";
|
|
|
|
return IppMsg(opAttrs, jobAttrs, 2, 0);
|
|
|
|
}
|
|
|
|
return IppMsg(opAttrs, jobAttrs);
|
|
|
|
}
|