Change to cURL for IPP requests

This commit is contained in:
Anton Thomasson 2021-08-28 22:16:26 +02:00
parent 1a48bf80b3
commit 0ef25112a5
19 changed files with 456 additions and 180 deletions

View file

@ -27,7 +27,8 @@ system(lrelease $$PWD/translations/*.ts)
CONFIG += sailfishapp
QT += svg
PKGCONFIG += mlite5
PKGCONFIG += mlite5 libcurl
LIBS += -lcurl
# Write version file
VERSION_H = \
@ -39,6 +40,8 @@ write_file($$$$OUT_PWD/seaprint_version.h, VERSION_H)
SOURCES += src/harbour-seaprint.cpp \
src/convertchecker.cpp \
src/convertworker.cpp \
src/curliodevice.cpp \
src/curlworker.cpp \
src/ippdiscovery.cpp \
src/ippmsg.cpp \
src/ippprinter.cpp \
@ -83,6 +86,8 @@ TRANSLATIONS += translations/harbour-seaprint-de.ts \
HEADERS += \
src/convertchecker.h \
src/convertworker.h \
src/curliodevice.h \
src/curlworker.h \
src/ippdiscovery.h \
src/ippmsg.h \
src/ippprinter.h \

View file

@ -15,6 +15,7 @@ BuildRequires: pkgconfig(Qt5Quick)
BuildRequires: pkgconfig(Qt5Svg)
BuildRequires: pkgconfig(mlite5)
BuildRequires: desktop-file-utils
BuildRequires: pkgconfig(libcurl)
%description
Network printing for Sailfish OS

View file

@ -10,6 +10,7 @@
#include <QTextDocument>
#include <QPdfWriter>
#include <QAbstractTextDocumentLayout>
#include "ippprinter.h"
void ppm2PwgEnv(QStringList& env, bool urf, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
@ -56,7 +57,57 @@ void ppm2PwgEnv(QStringList& env, bool urf, quint32 Quality, QString PaperSize,
}
}
void ConvertWorker::convertPdf(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
ConvertWorker::ConvertWorker(IppPrinter* parent) // : QObject((QObject*)parent) borks multithereading?!
{
_printer = parent;
}
void ConvertWorker::command(QByteArray msg)
{
CurlIODevice cid(_printer->httpUrl());
cid.setFinishedCallback(_printer, &IppPrinter::getPrinterAttributesFinished);
qDebug() << "command...";
cid.write(msg.data(), msg.length());
}
// TODO: de-duplicate
void ConvertWorker::getJobs(QByteArray msg)
{
CurlIODevice cid(_printer->httpUrl());
cid.setFinishedCallback(_printer, &IppPrinter::getJobsRequestFinished);
cid.write(msg.data(), msg.length());
}
void ConvertWorker::cancelJob(QByteArray msg)
{
CurlIODevice cid(_printer->httpUrl());
cid.setFinishedCallback(_printer, &IppPrinter::cancelJobFinished);
cid.write(msg.data(), msg.length());
}
void ConvertWorker::justUpload(QString filename, QByteArray header)
{
qDebug() << "justupload";
CurlIODevice cid(_printer->httpUrl());
cid.setFinishedCallback(_printer, &IppPrinter::printRequestFinished);
qDebug() << "justupload cp set";
QFile file(filename);
file.open(QFile::ReadOnly);
cid.write(header.data(), header.length());
QByteArray tmp = file.readAll();
cid.write(tmp.data(), tmp.length());
file.close();
}
void ConvertWorker::convertPdf(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip)
@ -116,40 +167,41 @@ try {
throw ConvertFailedException(tr("Unsupported resolution (dpi)"));
}
QTemporaryFile tempfile;
tempfile.open();
tempfile.close();
if(ps)
{
pdftoPs(PaperSize, TwoSided, PageRangeLow, PageRangeHigh, filename, tempfile);
pdftoPs(PaperSize, TwoSided, PageRangeLow, PageRangeHigh, filename, &tempfile);
}
else if(pdf)
{
adjustPageRange(PaperSize, PageRangeLow, PageRangeHigh, filename, tempfile);
adjustPageRange(PaperSize, PageRangeLow, PageRangeHigh, filename, &tempfile);
}
else
{
pdfToRaster(targetFormat, Colors, Quality, PaperSize,
HwResX, HwResY, TwoSided, Tumble,
PageRangeLow, PageRangeHigh, pages, BackHFlip, BackVFlip,
filename, tempfile, true);
filename, &tempfile, true);
}
qDebug() << "Finished";
emit done(request, tempfile);
justUpload(tempfile.fileName(), header);
qDebug() << "posted";
}
catch(const ConvertFailedException& e)
{
tempfile->deleteLater();
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
}
}
void ConvertWorker::convertImage(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void ConvertWorker::convertImage(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, QMargins margins)
{
@ -222,6 +274,10 @@ try {
inImage = inImage.scaled(Width-totalXMarginPx, Height-totalYMarginPx,
Qt::KeepAspectRatio, Qt::SmoothTransformation);
QTemporaryFile tempfile;
tempfile.open();
tempfile.close();
if(pdfOrPostscript)
{
QTemporaryFile tmpPdfFile;
@ -239,14 +295,14 @@ try {
if(targetFormat == Mimer::PDF)
{
QFile tempfileAsFile(tempfile->fileName());
QFile tempfileAsFile(tempfile.fileName());
tempfileAsFile.open(QIODevice::Append);
tempfileAsFile.write(tmpPdfFile.readAll());
tempfileAsFile.close();
}
else if(targetFormat == Mimer::Postscript)
{
pdftoPs(PaperSize, false, 0, 0, tmpPdfFile.fileName(), tempfile);
pdftoPs(PaperSize, false, 0, 0, tmpPdfFile.fileName(), &tempfile);
}
}
@ -263,7 +319,7 @@ try {
if(imageFormat != "")
{ // We are converting to a supported image format
QFile tempfileAsFile(tempfile->fileName());
QFile tempfileAsFile(tempfile.fileName());
tempfileAsFile.open(QIODevice::Append);
outImage.save(&tempfileAsFile, imageFormat.toStdString().c_str());
tempfileAsFile.close();
@ -280,7 +336,7 @@ try {
qDebug() << "ppm2pwg env is " << env;
ppm2pwg.setEnvironment(env);
ppm2pwg.setStandardOutputFile(tempfile->fileName(), QIODevice::Append);
ppm2pwg.setStandardOutputFile(tempfile.fileName(), QIODevice::WriteOnly);
qDebug() << "All connected";
ppm2pwg.start();
@ -304,19 +360,17 @@ try {
}
}
emit done(request, tempfile);
justUpload(tempfile.fileName(), header);
qDebug() << "posted";
}
catch(const ConvertFailedException& e)
{
tempfile->deleteLater();
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
}
}
void ConvertWorker::convertOfficeDocument(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void ConvertWorker::convertOfficeDocument(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip)
@ -395,6 +449,10 @@ try {
qDebug() << "PageRangeLow" << PageRangeLow << "PageRangeHigh" << PageRangeHigh << "pages" << pages;
QTemporaryFile tempfile;
tempfile.open();
tempfile.close();
if(targetFormat == Mimer::PDF)
{
@ -402,12 +460,12 @@ try {
{
qDebug() << "adjusting pages in PDF" << PageRangeLow << PageRangeHigh;
adjustPageRange(PaperSize, PageRangeLow, PageRangeHigh, tmpPdfFile.fileName(), tempfile);
adjustPageRange(PaperSize, PageRangeLow, PageRangeHigh, tmpPdfFile.fileName(), &tempfile);
}
else
{
QFile tempfileAsFile(tempfile->fileName());
QFile tempfileAsFile(tempfile.fileName());
tempfileAsFile.open(QIODevice::Append);
tempfileAsFile.write(tmpPdfFile.readAll());
tempfileAsFile.close();
@ -416,7 +474,7 @@ try {
}
else if(targetFormat == Mimer::Postscript)
{
pdftoPs(PaperSize, TwoSided, PageRangeLow, PageRangeHigh, tmpPdfFile.fileName(), tempfile);
pdftoPs(PaperSize, TwoSided, PageRangeLow, PageRangeHigh, tmpPdfFile.fileName(), &tempfile);
}
else
{
@ -424,23 +482,22 @@ try {
pdfToRaster(targetFormat, Colors, Quality, PaperSize,
HwResX, HwResY, TwoSided, Tumble,
PageRangeLow, PageRangeHigh, pages, BackHFlip, BackVFlip,
tmpPdfFile.fileName(), tempfile, false);
tmpPdfFile.fileName(), &tempfile, false);
}
qDebug() << "Finished";
emit done(request, tempfile);
justUpload(tempfile.fileName(), header);
qDebug() << "posted";
}
catch(const ConvertFailedException& e)
{
tempfile->deleteLater();
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
}
}
void ConvertWorker::convertPlaintext(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void ConvertWorker::convertPlaintext(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
bool BackHFlip, bool BackVFlip)
@ -581,34 +638,37 @@ try {
painter.end();
QTemporaryFile tempfile;
tempfile.open();
tempfile.close();
if(targetFormat == Mimer::PDF)
{
QFile tempfileAsFile(tempfile->fileName());
QFile tempfileAsFile(tempfile.fileName());
tempfileAsFile.open(QIODevice::Append);
tempfileAsFile.write(tmpPdfFile.readAll());
tempfileAsFile.close();
}
else if(targetFormat == Mimer::Postscript)
{
pdftoPs(PaperSize, TwoSided, 0, 0, tmpPdfFile.fileName(), tempfile);
pdftoPs(PaperSize, TwoSided, 0, 0, tmpPdfFile.fileName(), &tempfile);
}
else
{
pdfToRaster(targetFormat, Colors, Quality, PaperSize,
HwResX, HwResY, TwoSided, Tumble,
0, 0, pageCount, BackHFlip, BackVFlip,
tmpPdfFile.fileName(), tempfile, false);
tmpPdfFile.fileName(), &tempfile, false);
}
qDebug() << "Finished";
emit done(request, tempfile);
justUpload(tempfile.fileName(), header);
qDebug() << "posted";
}
catch(const ConvertFailedException& e)
{
tempfile->deleteLater();
emit failed(e.what() == QString("") ? tr("Conversion error") : e.what());
}
}
@ -656,7 +716,7 @@ void ConvertWorker::adjustPageRange(QString PaperSize, quint32 PageRangeLow, qui
qDebug() << "pdftocairo args is " << PdfToCairoArgs;
pdftocairo.setArguments(PdfToCairoArgs);
pdftocairo.setStandardOutputFile(tempfile->fileName(), QIODevice::Append);
pdftocairo.setStandardOutputFile(tempfile->fileName(), QIODevice::WriteOnly);
pdftocairo.start();
@ -791,7 +851,7 @@ void ConvertWorker::pdfToRaster(QString targetFormat, quint32 Colors, quint32 Qu
ppm2pwg.setEnvironment(env);
pdftoppm.setStandardOutputProcess(&ppm2pwg);
ppm2pwg.setStandardOutputFile(tempfile->fileName(), QIODevice::Append);
ppm2pwg.setStandardOutputFile(tempfile->fileName(), QIODevice::WriteOnly);
qDebug() << "All connected";

View file

@ -2,6 +2,9 @@
#define CONVERTWORKER_H
#include <QObject>
#include <QtNetwork>
#include "curliodevice.h"
class IppPrinter;
class ConvertFailedException: public std::exception
{
@ -21,22 +24,34 @@ class ConvertWorker : public QObject
{
Q_OBJECT
public:
ConvertWorker(IppPrinter* parent);
private:
ConvertWorker();
public slots:
void convertPdf(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void command(QByteArray msg);
void getJobs(QByteArray msg);
void cancelJob(QByteArray msg);
void justUpload(QString filename, QByteArray header);
void convertPdf(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
void convertImage(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void convertImage(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, QMargins margins);
void convertOfficeDocument(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void convertOfficeDocument(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
void convertPlaintext(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void convertPlaintext(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble, bool BackHFlip, bool BackVFlip);
@ -47,6 +62,8 @@ signals:
private:
IppPrinter* _printer;
QString getPopplerShortPaperSize(QString PaperSize);
void adjustPageRange(QString PaperSize, quint32 PageRangeLow, quint32 PageRangeHigh,

124
src/curliodevice.cpp Normal file
View file

@ -0,0 +1,124 @@
#include "curliodevice.h"
#include <seaprint_version.h>
#include <algorithm>
Q_DECLARE_METATYPE(CURLcode)
static size_t trampoline(char* dest, size_t size, size_t nmemb, void* userp)
{
qDebug() << "boingiddy!";
CurlIODevice* cid = (CurlIODevice*)userp;
return cid->requestWrite(dest, size*nmemb);
}
CurlIODevice::CurlIODevice(QUrl addr) : _addr(addr), _canWrite(1), _canRead(), _reading(false), _done(false), _dest(nullptr), _size(0), _offset(0)
{
qRegisterMetaType<CURLcode>();
// if(openMode() != NotOpen && mode != WriteOnly)
// return false;
CURL* curl = curl_easy_init();
// if(!curl)
// return false;
curl_easy_setopt(curl, CURLOPT_URL, _addr.toString().toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, trampoline);
curl_easy_setopt(curl, CURLOPT_READDATA, this);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 0L);
//TODO: free this list
struct curl_slist *opts = NULL;
opts = curl_slist_append(opts, "Transfer-Encoding: chunked");
opts = curl_slist_append(opts, "Content-Type: application/ipp");
opts = curl_slist_append(opts, "User-Agent: SeaPrint " SEAPRINT_VERSION);
opts = curl_slist_append(opts, "Accept-Encoding: identity");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, opts);
_performer = new CurlWorker(curl);
connect(_performer, &CurlWorker::done, this, &CurlIODevice::done);
connect(_performer, &CurlWorker::finished, _performer, &CurlWorker::deleteLater);
_performer->start();
qDebug() << "worker started";
}
CurlIODevice::~CurlIODevice()
{
qDebug() << "destroying";
_canWrite.acquire();
_done = true;
_canRead.release();
_performer->wait();
if(_dest != nullptr)
{
delete[] _dest;
}
qDebug() << "done destroying";
}
void CurlIODevice::write(const char *data, size_t size)
{
qDebug() << "write " << size;
_canWrite.acquire();
if(_dest != nullptr)
{
delete[] _dest;
}
_dest = new char[size];
memcpy(_dest, data, size);
_size = size;
_offset = 0;
_canRead.release();
}
size_t CurlIODevice::requestWrite(char* dest, size_t size)
{
qDebug() << "requestWrite " << size;
if(!_reading)
{
_canRead.acquire();
if(_done) // Can only have been set by write() - only relevant to check if strating to write
{
return 0;
}
_reading = true;
}
size_t remaining = _size - _offset;
qDebug() << "requestWrite canwrite";
size_t actualSize = std::min(size, remaining);
memcpy(dest, (_dest+_offset), actualSize);
_offset += actualSize;
remaining = _size - _offset;
if(remaining == 0)
{
_reading = false;
_canWrite.release();
}
qDebug() << "requestWrite returns " << _size;
return actualSize;
}
void CurlIODevice::done(CURLcode)
{
}

49
src/curliodevice.h Normal file
View file

@ -0,0 +1,49 @@
#ifndef CURLIODEVICE_H
#define CURLIODEVICE_H
#include <QUrl>
#include <QThread>
#include <QSemaphore>
#include <QMetaMethod>
#include <curl/curl.h>
#include <QDebug>
#include "curlworker.h"
class CurlIODevice : public QObject
{
Q_OBJECT
public:
CurlIODevice(QUrl addr);
~CurlIODevice();
template<typename Class, typename Callback>
bool setFinishedCallback(const Class* receiverObject, Callback cb)
{
connect(_performer, &CurlWorker::done, receiverObject, cb);
return true;
}
void write(const char *data, size_t size);
size_t requestWrite(char* dest, size_t size);
public slots:
void done(CURLcode);
private:
QUrl _addr;
bool _open;
CurlWorker* _performer;
QSemaphore _canWrite;
QSemaphore _canRead;
bool _reading;
bool _done;
char* _dest;
size_t _size;
size_t _offset;
};
#endif // CURLIODEVICE_H

22
src/curlworker.cpp Normal file
View file

@ -0,0 +1,22 @@
#include "curlworker.h"
CurlWorker::CurlWorker(CURL* curl)
{
_curl = curl;
}
void CurlWorker::run(){
QByteArray buf;
curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &buf);
curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, write_callback);
qDebug() << "performer running";
CURLcode res = curl_easy_perform(_curl);
if(res != CURLE_OK)
qDebug() << "curl_easy_perform() failed: " << curl_easy_strerror(res);
curl_easy_cleanup(_curl);
curl_global_cleanup();
qDebug() << "performer done " << buf.length();
emit done(res, buf);
}

47
src/curlworker.h Normal file
View file

@ -0,0 +1,47 @@
#ifndef CURLWORKER_H
#define CURLWORKER_H
#include <QThread>
#include <curl/curl.h>
#include <QtDebug>
class CurlWorker : public QThread
{
Q_OBJECT
public:
CurlWorker(CURL* curl);
void run() override;
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void* userdata)
{
qDebug() << "writing resp" << size*nmemb;
size_t bytes_to_write = size*nmemb;
((QByteArray*)userdata)->append(ptr, bytes_to_write);
return bytes_to_write;
}
signals:
void done(CURLcode, QByteArray);
private:
// Container for the cURL global init and cleanup
class GlobalEnv
{
public:
GlobalEnv()
{
curl_global_init(CURL_GLOBAL_DEFAULT);
}
~GlobalEnv()
{
curl_global_cleanup();
}
};
// Must be run exactly once, thus static
static GlobalEnv _gEnv;
CurlWorker();
CURL* _curl = nullptr;
};
#endif // CURLWORKER_H

View file

@ -62,6 +62,48 @@ IppMsg::IppMsg(QNetworkReply* resp)
}
}
IppMsg::IppMsg(QByteArray resp)
{
Bytestream bts(resp.constData(), resp.length());
quint32 reqId;
bts >> _majVsn >> _minVsn >> _status >> reqId;
QJsonObject attrs;
IppMsg::IppTag currentAttrType = IppTag::EndAttrs;
while(!bts.atEnd())
{
if(bts.peekU8() <= IppTag::UnsupportedAttrs) {
if(currentAttrType == IppTag::OpAttrs) {
_opAttrs = attrs;
}
else if (currentAttrType == IppTag::JobAttrs) {
_jobAttrs.append(attrs);
}
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;
}
currentAttrType = (IppTag)bts.getU8();
attrs = QJsonObject();
}
else {
consume_attribute(attrs, bts);
}
}
}
QJsonValue IppMsg::consume_value(quint8 tag, Bytestream& data)
{
QJsonValue value;

View file

@ -67,6 +67,7 @@ public:
explicit IppMsg();
explicit IppMsg(QNetworkReply* resp);
explicit IppMsg(QByteArray resp);
IppMsg(QJsonObject opAttrs, QJsonObject jobAttrs=QJsonObject(), quint8 majVsn=1, quint8 minVsn=1);
IppMsg(const IppMsg& other) = default;
~IppMsg();

View file

@ -9,36 +9,23 @@ Q_DECLARE_METATYPE(QMargins)
IppPrinter::IppPrinter()
{
_nam = new QNetworkAccessManager(this);
_print_nam = new QNetworkAccessManager(this);
_jobs_nam = new QNetworkAccessManager(this);
_job_cancel_nam = new QNetworkAccessManager(this);
connect(_nam, &QNetworkAccessManager::finished, this, &IppPrinter::getPrinterAttributesFinished);
connect(_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::onSslErrors);
connect(_print_nam, &QNetworkAccessManager::finished, this, &IppPrinter::printRequestFinished);
connect(_print_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::onSslErrors);
connect(_jobs_nam, &QNetworkAccessManager::finished,this, &IppPrinter::getJobsRequestFinished);
connect(_jobs_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::onSslErrors);
connect(_job_cancel_nam, &QNetworkAccessManager::finished,this, &IppPrinter::cancelJobFinished);
connect(_job_cancel_nam, &QNetworkAccessManager::sslErrors, this, &IppPrinter::onSslErrors);
QObject::connect(this, &IppPrinter::urlChanged, this, &IppPrinter::onUrlChanged);
qRegisterMetaType<QTemporaryFile*>("QTemporaryFile*");
_worker = new ConvertWorker;
_worker = new ConvertWorker(this);
_worker->moveToThread(&_workerThread);
connect(&_workerThread, &QThread::finished, _worker, &QObject::deleteLater);
connect(this, &IppPrinter::doCommand, _worker, &ConvertWorker::command);
connect(this, &IppPrinter::doGetJobs, _worker, &ConvertWorker::getJobs);
connect(this, &IppPrinter::doCancelJob, _worker, &ConvertWorker::cancelJob);
connect(this, &IppPrinter::doJustUpload, _worker, &ConvertWorker::justUpload);
connect(this, &IppPrinter::doConvertPdf, _worker, &ConvertWorker::convertPdf);
connect(this, &IppPrinter::doConvertImage, _worker, &ConvertWorker::convertImage);
connect(this, &IppPrinter::doConvertOfficeDocument, _worker, &ConvertWorker::convertOfficeDocument);
connect(this, &IppPrinter::doConvertPlaintext, _worker, &ConvertWorker::convertPlaintext);
connect(_worker, &ConvertWorker::done, this, &IppPrinter::convertDone);
connect(_worker, &ConvertWorker::progress, this, &IppPrinter::setProgress);
connect(_worker, &ConvertWorker::failed, this, &IppPrinter::convertFailed);
@ -49,10 +36,8 @@ IppPrinter::IppPrinter()
}
IppPrinter::~IppPrinter() {
delete _nam;
delete _print_nam;
delete _jobs_nam;
delete _job_cancel_nam;
// TODO: delete worker and workerthread?
}
QJsonObject IppPrinter::opAttrs() {
@ -112,11 +97,6 @@ void IppPrinter::refresh() {
// _additionalDocumentFormats = QStringList();
// emit additionalDocumentFormatsChanged();
// FFFFUUUU
_nam->clearAccessCache();
_jobs_nam->clearAccessCache();
_job_cancel_nam->clearAccessCache();
_print_nam->clearAccessCache();
if(_url.scheme() == "file")
{
@ -138,11 +118,10 @@ void IppPrinter::refresh() {
}
else
{
QNetworkRequest request = mkReq();
QJsonObject o = opAttrs();
IppMsg msg = IppMsg(o);
_nam->post(request, msg.encode(IppMsg::GetPrinterAttrs));
emit doCommand(msg.encode(IppMsg::GetPrinterAttrs));
}
}
@ -175,15 +154,15 @@ void IppPrinter::UpdateAdditionalDocumentFormats()
emit additionalDocumentFormatsChanged();
}
void IppPrinter::getPrinterAttributesFinished(QNetworkReply *reply)
void IppPrinter::getPrinterAttributesFinished(CURLcode res, QByteArray data)
{
qDebug() << reply->request().url() << reply->error() << reply->errorString() << reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
qDebug() << res;
_attrs = QJsonObject();
if(reply->error() == QNetworkReply::NoError)
if(res == CURLE_OK)
{
try {
IppMsg resp(reply);
IppMsg resp(data);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getPrinterAttrs();
_attrs = resp.getPrinterAttrs();
Overrider::instance()->apply(_attrs);
@ -200,14 +179,15 @@ void IppPrinter::getPrinterAttributesFinished(QNetworkReply *reply)
UpdateAdditionalDocumentFormats();
}
void IppPrinter::printRequestFinished(QNetworkReply *reply)
void IppPrinter::printRequestFinished(CURLcode res, QByteArray data)
{
_jobAttrs = QJsonObject();
bool status = false;
if(reply->error() == QNetworkReply::NoError)
if(res == CURLE_OK)
{
try {
IppMsg resp(reply);
IppMsg resp(data);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
_jobAttrs = resp.getJobAttrs()[0].toObject();
if(resp.getOpAttrs().keys().contains("status-message"))
@ -226,16 +206,17 @@ void IppPrinter::printRequestFinished(QNetworkReply *reply)
_jobAttrs.insert("job-state-message", QJsonObject {{"tag", IppMsg::TextWithoutLanguage},
{"value", "Network error"}});
}
emit jobAttrsChanged();
emit jobFinished(status);
}
void IppPrinter::getJobsRequestFinished(QNetworkReply *reply)
void IppPrinter::getJobsRequestFinished(CURLcode res, QByteArray data)
{
if(reply->error() == QNetworkReply::NoError)
if(res == CURLE_OK)
{
try {
IppMsg resp(reply);
IppMsg resp(data);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
_jobs = resp.getJobAttrs();
emit jobsChanged();
@ -248,13 +229,13 @@ void IppPrinter::getJobsRequestFinished(QNetworkReply *reply)
}
void IppPrinter::cancelJobFinished(QNetworkReply *reply)
void IppPrinter::cancelJobFinished(CURLcode res, QByteArray data)
{
bool status = false;
if(reply->error() == QNetworkReply::NoError)
if(res == CURLE_OK)
{
try {
IppMsg resp(reply);
IppMsg resp(data);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
status = resp.getStatus() <= 0xff;
}
@ -284,19 +265,6 @@ void IppPrinter::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &e
}
}
void IppPrinter::convertDone(QNetworkRequest request, QTemporaryFile* data)
{
connect(_print_nam, SIGNAL(finished(QNetworkReply*)), data, SLOT(deleteLater()));
data->open();
setBusyMessage(tr("Transferring"));
QNetworkReply* reply = _print_nam->post(request, data);
connect(reply, &QNetworkReply::uploadProgress, this, &IppPrinter::setProgress);
}
void IppPrinter::convertFailed(QString message)
{
_jobAttrs = QJsonObject();
@ -484,9 +452,9 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
_progress = "";
emit progressChanged();
QFile file(filename);
bool file_ok = file.open(QIODevice::ReadOnly);
if(!file_ok)
QFileInfo fileinfo(filename);
if(!fileinfo.exists())
{
emit convertFailed(tr("Failed to open file"));
return;
@ -504,8 +472,6 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
qDebug() << supportedMimeTypes << supportedMimeTypes.contains(mimeType);
QFileInfo fileinfo(file);
QJsonObject o = opAttrs();
o.insert("job-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", fileinfo.fileName()}});
@ -558,8 +524,6 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
qDebug() << "Printing job" << o << jobAttrs;
QNetworkRequest request = mkReq();
QJsonValue PrinterResolutionRef = getAttrOrDefault(jobAttrs, "printer-resolution");
quint32 HwResX = PrinterResolutionRef.toObject()["x"].toInt(300);
quint32 HwResY = PrinterResolutionRef.toObject()["y"].toInt(300);
@ -610,18 +574,12 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
&& (documentFormat == Mimer::JPEG || !Mimer::isImage(mimeType))
&& !((documentFormat == Mimer::PDF) && pdfPageRangeAdjustNeeded))
{
QByteArray filedata = file.readAll();
contents = contents.append(filedata);
file.close();
setBusyMessage(tr("Transferring"));
QNetworkReply* reply = _print_nam->post(request, contents);
connect(reply, &QNetworkReply::uploadProgress, this, &IppPrinter::setProgress);
emit doJustUpload(filename, contents);
}
else
{
file.close();
if(PaperSize == "")
{
PaperSize = "iso_a4_210x297mm";
@ -632,12 +590,6 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
return;
}
QTemporaryFile* tempfile = new QTemporaryFile();
tempfile->open();
tempfile->write(contents);
qDebug() << tempfile->fileName();
tempfile->close();
bool TwoSided = false;
bool Tumble = false;
if(Sides=="two-sided-long-edge")
@ -654,13 +606,13 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
if(mimeType == Mimer::PDF)
{
emit doConvertPdf(request, filename, tempfile, documentFormat, Colors, Quality,
emit doConvertPdf(filename, contents, documentFormat, Colors, Quality,
PaperSize, HwResX, HwResY, TwoSided, Tumble, PageRangeLow, PageRangeHigh,
BackHFlip, BackVFlip);
}
else if(mimeType == Mimer::Plaintext)
{
emit doConvertPlaintext(request, filename, tempfile, documentFormat, Colors, Quality,
emit doConvertPlaintext(filename, contents, documentFormat, Colors, Quality,
PaperSize, HwResX, HwResY, TwoSided, Tumble, BackHFlip, BackVFlip);
}
else if (Mimer::isImage(mimeType))
@ -670,12 +622,12 @@ void IppPrinter::print(QJsonObject jobAttrs, QString filename)
getAttrOrDefault(jobAttrs, "media-right-margin", "media-col").toInt(),
getAttrOrDefault(jobAttrs, "media-bottom-margin", "media-col").toInt());
emit doConvertImage(request, filename, tempfile, documentFormat, Colors, Quality,
emit doConvertImage(filename, contents, documentFormat, Colors, Quality,
PaperSize, HwResX, HwResY, margins);
}
else if(Mimer::isOffice(mimeType))
{
emit doConvertOfficeDocument(request, filename, tempfile, documentFormat, Colors, Quality,
emit doConvertOfficeDocument(filename, contents, documentFormat, Colors, Quality,
PaperSize, HwResX, HwResY, TwoSided, Tumble, PageRangeLow, PageRangeHigh,
BackHFlip, BackVFlip);
}
@ -697,11 +649,7 @@ bool IppPrinter::getJobs() {
IppMsg job = IppMsg(o, QJsonObject());
QNetworkRequest request = mkReq();
QByteArray contents = job.encode(IppMsg::GetJobs);
_jobs_nam->post(request, contents);
emit doGetJobs(job.encode(IppMsg::GetJobs));
return true;
}
@ -715,12 +663,7 @@ bool IppPrinter::cancelJob(qint32 jobId) {
IppMsg job = IppMsg(o, QJsonObject());
QNetworkRequest request = mkReq();
QByteArray contents = job.encode(IppMsg::CancelJob);
_job_cancel_nam->post(request, contents);
emit doCancelJob(job.encode(IppMsg::CancelJob));
return true;
}
@ -778,16 +721,6 @@ QUrl IppPrinter::httpUrl() {
return url;
}
QNetworkRequest IppPrinter::mkReq() {
QNetworkRequest request;
request.setUrl(httpUrl());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION);
request.setRawHeader("Accept-Encoding", "identity");
request.setSslConfiguration(QSslConfiguration());
return request;
}
void IppPrinter::setBusyMessage(QString msg)
{
_busyMessage = msg;

View file

@ -5,11 +5,15 @@
#include <QNetworkAccessManager>
#include "ippmsg.h"
#include "convertworker.h"
#include "curliodevice.h"
#include <mlite5/MGConfItem>
class IppPrinter : public QObject
{
Q_OBJECT
friend class ConvertWorker;
Q_PROPERTY(QString url READ getUrl WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(QJsonObject attrs MEMBER _attrs NOTIFY attrsChanged)
Q_PROPERTY(QJsonObject jobAttrs MEMBER _jobAttrs NOTIFY jobAttrsChanged)
@ -49,21 +53,27 @@ signals:
void jobFinished(bool status);
void cancelStatus(bool status);
void doConvertPdf(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void doCommand(QByteArray msg);
void doGetJobs(QByteArray msg);
void doCancelJob(QByteArray msg);
void doJustUpload(QString filename, QByteArray header);
void doConvertPdf(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
void doConvertImage(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void doConvertImage(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, QMargins margins);
void doConvertOfficeDocument(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void doConvertOfficeDocument(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble,
quint32 PageRangeLow, quint32 PageRangeHigh, bool BackHFlip, bool BackVFlip);
void doConvertPlaintext(QNetworkRequest request, QString filename, QTemporaryFile* tempfile,
void doConvertPlaintext(QString filename, QByteArray header,
QString targetFormat, quint32 Colors, quint32 Quality, QString PaperSize,
quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble, bool BackHFlip, bool BackVFlip);
@ -78,21 +88,19 @@ public slots:
void onUrlChanged();
void UpdateAdditionalDocumentFormats();
void getPrinterAttributesFinished(QNetworkReply* reply);
void printRequestFinished(QNetworkReply* reply);
void getJobsRequestFinished(QNetworkReply* reply);
void cancelJobFinished(QNetworkReply* reply);
void getPrinterAttributesFinished(CURLcode res, QByteArray data);
void printRequestFinished(CURLcode res, QByteArray data);
void getJobsRequestFinished(CURLcode res, QByteArray data);
void cancelJobFinished(CURLcode res, QByteArray data);
void onSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
static void ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
void convertDone(QNetworkRequest request, QTemporaryFile* data);
void convertFailed(QString message);
private:
QUrl _url;
QUrl httpUrl();
QNetworkRequest mkReq();
QJsonObject opAttrs();
@ -106,11 +114,6 @@ private:
IppMsg mk_msg(QJsonObject opAttrs, QJsonObject jobAttrs=QJsonObject());
QNetworkAccessManager* _nam;
QNetworkAccessManager* _jobs_nam;
QNetworkAccessManager* _job_cancel_nam;
QNetworkAccessManager* _print_nam;
QJsonObject _attrs;
QJsonObject _jobAttrs;
QJsonArray _jobs;

View file

@ -330,10 +330,6 @@
<source>Unknown document format dimensions</source>
<translation>Unbekannte Dokumentenformat Größe</translation>
</message>
<message>
<source>Transferring</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Converting</source>
<translation type="unfinished"></translation>

View file

@ -330,10 +330,6 @@
<source>Unknown document format dimensions</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transferring</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Converting</source>
<translation type="unfinished"></translation>

View file

@ -330,10 +330,6 @@
<source>Unknown document format dimensions</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transferring</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Converting</source>
<translation type="unfinished"></translation>

View file

@ -330,10 +330,6 @@
<source>Unknown document format dimensions</source>
<translation>Onbekende afmetingen van documentformaat</translation>
</message>
<message>
<source>Transferring</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Converting</source>
<translation type="unfinished"></translation>

View file

@ -330,10 +330,6 @@
<source>Cannot convert this file format</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transferring</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Converting</source>
<translation type="unfinished"></translation>

View file

@ -330,10 +330,6 @@
<source>Unknown document format dimensions</source>
<translation></translation>
</message>
<message>
<source>Transferring</source>
<translation></translation>
</message>
<message>
<source>Converting</source>
<translation></translation>

View file

@ -330,10 +330,6 @@
<source>Unknown document format dimensions</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Transferring</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Converting</source>
<translation type="unfinished"></translation>