From 0efd96c072df97d3797310411a510eecdd775211 Mon Sep 17 00:00:00 2001 From: Anton Thomasson Date: Sat, 19 Feb 2022 17:33:59 +0100 Subject: [PATCH] Make the icon an attribute on the printer object This allows retrying based on actual size and using cURL for getting the icon to avoid old Qt network code. --- harbour-seaprint.pro | 2 ++ qml/pages/FirstPage.qml | 19 ++++++++----- qml/pages/utils.js | 20 -------------- src/harbour-seaprint.cpp | 3 +- src/imageitem.cpp | 32 ++++++++++++++++++++++ src/imageitem.h | 31 +++++++++++++++++++++ src/ippdiscovery.cpp | 36 +----------------------- src/ippdiscovery.h | 10 +------ src/ippprinter.cpp | 59 +++++++++++++++++++++++++++++++++++++++- src/ippprinter.h | 9 ++++-- src/printerworker.cpp | 7 +++++ src/printerworker.h | 1 + 12 files changed, 154 insertions(+), 75 deletions(-) create mode 100644 src/imageitem.cpp create mode 100644 src/imageitem.h diff --git a/harbour-seaprint.pro b/harbour-seaprint.pro index 426ecb0..dc221cb 100644 --- a/harbour-seaprint.pro +++ b/harbour-seaprint.pro @@ -36,6 +36,7 @@ DEFINES += SEAPRINT_VERSION='\\"$$VERSION\\"' SOURCES += src/harbour-seaprint.cpp \ src/convertchecker.cpp \ src/curlrequester.cpp \ + src/imageitem.cpp \ src/ippdiscovery.cpp \ src/ippmsg.cpp \ src/ippprinter.cpp \ @@ -82,6 +83,7 @@ TRANSLATIONS += translations/harbour-seaprint-de.ts \ HEADERS += \ src/convertchecker.h \ src/curlrequester.h \ + src/imageitem.h \ src/ippdiscovery.h \ src/ippmsg.h \ src/ippprinter.h \ diff --git a/qml/pages/FirstPage.qml b/qml/pages/FirstPage.qml index 13f5683..7776c6d 100644 --- a/qml/pages/FirstPage.qml +++ b/qml/pages/FirstPage.qml @@ -4,6 +4,7 @@ import Sailfish.Pickers 1.0 import seaprint.ippdiscovery 1.0 import seaprint.convertchecker 1.0 import seaprint.ippprinter 1.0 +import seaprint.imageitem 1.0 import seaprint.mimer 1.0 import "utils.js" as Utils @@ -212,7 +213,7 @@ Page { } } - Image { + ImageItem { id: icon anchors.top: parent.top anchors.left: parent.left @@ -221,13 +222,17 @@ Page { height: Theme.itemSizeLarge width: Theme.itemSizeLarge - sourceSize.height: height - sourceSize.width: width - source: printer.attrs["printer-icons"] ? "image://ippdiscovery/"+Utils.selectIcon(printer.attrs["printer-icons"].value) - : "image://svg/qml/pages/icon-seaprint-nobg.svg" - // Some printers serve their icons over https with invalid certs... - onStatusChanged: if (status == Image.Error) source = "image://svg/qml/pages/icon-seaprint-nobg.svg" + image: printer.icon + Image { + id: placeholder + anchors.fill: parent + sourceSize.height: height + sourceSize.width: width + + visible: !parent.valid + source: "image://svg/qml/pages/icon-seaprint-nobg.svg" + } } Image { diff --git a/qml/pages/utils.js b/qml/pages/utils.js index 04a2fc1..d8d13fa 100644 --- a/qml/pages/utils.js +++ b/qml/pages/utils.js @@ -461,26 +461,6 @@ function fixupChoices(name, choices, mimeType) } } -function selectIcon(icons) -{ - for(var i=0; i < icons.length; i++) - { - if(endsWith("M.png", icons[i]) || endsWith("128.png", icons[i]) || endsWith("128.PNG", icons[i])) - { - return icons[i]; - } - } - // Icons must be 48, 128 or 256px and sorted by size, so if all 3 are provided we want the middle one - if(icons.length == 3) - { - return icons[1]; - } - else - { - return icons[0]; - } -} - function isWaringState(printer) { if(printer.attrs["printer-state"].value > 4) diff --git a/src/harbour-seaprint.cpp b/src/harbour-seaprint.cpp index 24e3f89..984216c 100644 --- a/src/harbour-seaprint.cpp +++ b/src/harbour-seaprint.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -41,12 +42,12 @@ int main(int argc, char *argv[]) qmlRegisterSingletonType("seaprint.convertchecker", 1, 0, "ConvertChecker", singletontype_provider); qmlRegisterSingletonType("seaprint.settings", 1, 0, "SeaPrintSettings", singletontype_provider); qmlRegisterType("seaprint.ippprinter", 1, 0, "IppPrinter"); + qmlRegisterType("seaprint.imageitem", 1, 0, "ImageItem"); qmlRegisterUncreatableType("seaprint.ippmsg", 1, 0, "IppMsg", "Only used to supply an enum type"); QQuickView* view = SailfishApp::createView(); view->engine()->addImportPath(SailfishApp::pathTo("qml/pages").toString()); - view->engine()->addImageProvider(QLatin1String("ippdiscovery"), IppDiscovery::instance()); view->engine()->addImageProvider(QLatin1String("svg"), SvgProvider::instance()); view->setSource(SailfishApp::pathToMainQml()); diff --git a/src/imageitem.cpp b/src/imageitem.cpp new file mode 100644 index 0000000..548d6be --- /dev/null +++ b/src/imageitem.cpp @@ -0,0 +1,32 @@ +#include "imageitem.h" +#include "svgprovider.h" + +ImageItem::ImageItem() +{ + +} + +void ImageItem::paint(QPainter *painter) +{ + + QImage scaled = _image.scaledToHeight(boundingRect().height(), Qt::SmoothTransformation); + painter->drawImage(QPoint {0, 0}, scaled); +} + +QImage ImageItem::getImage() const +{ + return _image; +} + +void ImageItem::setImage(const QImage &image) +{ + _image = image; + emit imageChanged(); + update(); +} + + +bool ImageItem::isValid() const +{ + return !_image.isNull(); +} diff --git a/src/imageitem.h b/src/imageitem.h new file mode 100644 index 0000000..0a49c9f --- /dev/null +++ b/src/imageitem.h @@ -0,0 +1,31 @@ +#ifndef IMAGEITEM_H +#define IMAGEITEM_H + +#include +#include +#include + +class ImageItem : public QQuickPaintedItem +{ + Q_OBJECT + + Q_PROPERTY(QImage image READ getImage WRITE setImage NOTIFY imageChanged) + Q_PROPERTY(bool valid READ isValid NOTIFY imageChanged) +public: + ImageItem(); + + void paint(QPainter *painter); + +signals: + void imageChanged(); + +private: + QImage getImage() const; + void setImage(const QImage &image); + + bool isValid() const; + + QImage _image; +}; + +#endif // IMAGEITEM_H diff --git a/src/ippdiscovery.cpp b/src/ippdiscovery.cpp index e2654aa..19d0b33 100644 --- a/src/ippdiscovery.cpp +++ b/src/ippdiscovery.cpp @@ -37,7 +37,7 @@ QStringList get_addr(Bytestream& bts) return addr; } -IppDiscovery::IppDiscovery() : QStringListModel(), QQuickImageProvider(QQuickImageProvider::Image, ForceAsynchronousImageLoading) +IppDiscovery::IppDiscovery() : QStringListModel() { socket = new QUdpSocket(this); connect(socket, &QUdpSocket::readyRead, this, &IppDiscovery::readPendingDatagrams); @@ -419,37 +419,3 @@ void IppDiscovery::resolve(QUrl& url) url.setHost(_AAs.value(host)); } } - -QImage IppDiscovery::requestImage(const QString &id, QSize *size, const QSize &requestedSize) -{ //TODO: consider caching images (doesn't appear to be needed currently) - Q_UNUSED(requestedSize); - qDebug() << "requesting image" << id; - - QImage img; - - QNetworkAccessManager* nam = new QNetworkAccessManager(); - QUrl url(id); - - resolve(url); - - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint " SEAPRINT_VERSION); - connect(nam, &QNetworkAccessManager::sslErrors, &IppPrinter::ignoreSslErrors); - - QNetworkReply* reply = nam->get(request); - - QEventLoop loop; - connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - loop.exec(); - - if (reply->error() == QNetworkReply::NoError) - { - QImageReader imageReader(reply); - img = imageReader.read(); - } - - *size = img.size(); - delete nam; - return img; - -} diff --git a/src/ippdiscovery.h b/src/ippdiscovery.h index aab9b4b..020a01d 100644 --- a/src/ippdiscovery.h +++ b/src/ippdiscovery.h @@ -1,16 +1,11 @@ #ifndef IPPDISCOVERY_H #define IPPDISCOVERY_H #include -#include #include #include -#include -#include -#include -#include #include "bytestream.h" -class IppDiscovery : public QStringListModel, public QQuickImageProvider +class IppDiscovery : public QStringListModel { Q_OBJECT public: @@ -49,9 +44,6 @@ private: void updateAndQueryPtrs(QStringList& ptrs, QStringList new_ptrs); - - QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; - QStringList _ipp; QStringList _ipps; QMap _rps; diff --git a/src/ippprinter.cpp b/src/ippprinter.cpp index 5cb64ec..f7d194e 100644 --- a/src/ippprinter.cpp +++ b/src/ippprinter.cpp @@ -25,6 +25,7 @@ IppPrinter::IppPrinter() : _worker(this) connect(this, &IppPrinter::doConvertPlaintext, &_worker, &PrinterWorker::convertPlaintext); connect(this, &IppPrinter::doGetStrings, &_worker, &PrinterWorker::getStrings); + connect(this, &IppPrinter::doGetImage, &_worker, &PrinterWorker::getImage); connect(&_worker, &PrinterWorker::progress, this, &IppPrinter::setProgress); connect(&_worker, &PrinterWorker::busyMessage, this, &IppPrinter::setBusyMessage); @@ -106,7 +107,7 @@ void IppPrinter::refresh() { } emit attrsChanged(); - MaybeGetStrings(); +// MaybeGetStrings(); - for testing fake file-prinetrs with a strings file hosted elsewhere UpdateAdditionalDocumentFormats(); } else @@ -128,6 +129,41 @@ void IppPrinter::MaybeGetStrings() } } +void IppPrinter::MaybeGetIcon(bool retry) +{ + if(_attrs.contains("printer-icons") && (_icon.isNull() || retry)) + { + QUrl url; + QJsonArray icons = _attrs["printer-icons"].toObject()["value"].toArray(); + + if(retry) + { // If there were more than one icon, try the last one on the retry + if(icons.size() > 1) + { + url = icons.last().toString(); + } + } + else + { + if(icons.size() == 3) + { // If there are 3 icons, the first will be the 48px one, ignore it + url = icons.at(1).toString(); + } + else + { + url = icons.at(0).toString(); + } + } + + if(!url.isEmpty()) + { + IppDiscovery::instance()->resolve(url); + emit doGetImage(url); + } + } +} + + void IppPrinter::UpdateAdditionalDocumentFormats() { _additionalDocumentFormats = QStringList(); @@ -180,6 +216,7 @@ void IppPrinter::getPrinterAttributesFinished(CURLcode res, Bytestream data) emit attrsChanged(); MaybeGetStrings(); + MaybeGetIcon(); UpdateAdditionalDocumentFormats(); } @@ -272,6 +309,26 @@ void IppPrinter::getStringsFinished(CURLcode res, Bytestream data) } } +void IppPrinter::getImageFinished(CURLcode res, Bytestream data) +{ + qDebug() << res << data.size(); + if(res == CURLE_OK) + { + QImage tmp; + if(tmp.loadFromData(data.raw(), data.size(), "PNG")) + { + _icon = tmp; + qDebug() << "image loaded" << _icon; + emit iconChanged(); + + if(tmp.size().width() < 128) + { + MaybeGetIcon(true); + } + } + } +} + void IppPrinter::ignoreSslErrors(QNetworkReply *reply, const QList &errors) { bool ignore = Settings::instance()->ignoreSslErrors(); diff --git a/src/ippprinter.h b/src/ippprinter.h index 126b360..548587d 100644 --- a/src/ippprinter.h +++ b/src/ippprinter.h @@ -1,8 +1,7 @@ #ifndef IPPPRINTER_H #define IPPPRINTER_H -#include -#include +#include #include "ippmsg.h" #include "printerworker.h" #include "curlrequester.h" @@ -19,6 +18,7 @@ class IppPrinter : public QObject Q_PROPERTY(QJsonObject jobAttrs MEMBER _jobAttrs NOTIFY jobAttrsChanged) Q_PROPERTY(QJsonArray jobs MEMBER _jobs NOTIFY jobsChanged) Q_PROPERTY(QJsonObject strings MEMBER _strings NOTIFY stringsChanged) + Q_PROPERTY(QImage icon MEMBER _icon NOTIFY iconChanged) Q_PROPERTY(QStringList additionalDocumentFormats MEMBER _additionalDocumentFormats NOTIFY additionalDocumentFormatsChanged) Q_PROPERTY(QString busyMessage MEMBER _busyMessage NOTIFY busyMessageChanged) Q_PROPERTY(QString progress MEMBER _progress NOTIFY progressChanged) @@ -49,6 +49,7 @@ signals: void jobsChanged(); void stringsChanged(); + void iconChanged(); void jobFinished(bool status); void cancelStatus(bool status); @@ -78,6 +79,7 @@ signals: quint32 HwResX, quint32 HwResY, bool TwoSided, bool Tumble, bool BackHFlip, bool BackVFlip); void doGetStrings(QUrl url); + void doGetImage(QUrl url); void additionalDocumentFormatsChanged(); void busyMessageChanged(); @@ -89,6 +91,7 @@ public slots: void onUrlChanged(); void MaybeGetStrings(); + void MaybeGetIcon(bool retry=false); void UpdateAdditionalDocumentFormats(); void getPrinterAttributesFinished(CURLcode res, Bytestream data); void printRequestFinished(CURLcode res, Bytestream data); @@ -96,6 +99,7 @@ public slots: void cancelJobFinished(CURLcode res, Bytestream data); void getStringsFinished(CURLcode res, Bytestream data); + void getImageFinished(CURLcode res, Bytestream data); static void ignoreSslErrors(QNetworkReply *reply, const QList &errors); @@ -122,6 +126,7 @@ private: QJsonArray _jobs; QJsonObject _strings; + QImage _icon; QStringList _additionalDocumentFormats; diff --git a/src/printerworker.cpp b/src/printerworker.cpp index feafda3..4a0754e 100644 --- a/src/printerworker.cpp +++ b/src/printerworker.cpp @@ -26,6 +26,13 @@ void PrinterWorker::getStrings(QUrl url) connect(&cr, &CurlRequester::done, _printer, &IppPrinter::getStringsFinished); } +void PrinterWorker::getImage(QUrl url) +{ + CurlRequester cr(url, CurlRequester::HttpGetRequest); + connect(&cr, &CurlRequester::done, _printer, &IppPrinter::getImageFinished); +} + + void PrinterWorker::getPrinterAttributes(Bytestream msg) { CurlRequester cr(_printer->httpUrl()); diff --git a/src/printerworker.h b/src/printerworker.h index 72682b5..f3503e0 100644 --- a/src/printerworker.h +++ b/src/printerworker.h @@ -32,6 +32,7 @@ private: public slots: void getStrings(QUrl url); + void getImage(QUrl url); void getPrinterAttributes(Bytestream msg); void getJobs(Bytestream msg); void cancelJob(Bytestream msg);