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.
This commit is contained in:
Anton Thomasson 2022-02-19 17:33:59 +01:00
parent d8267db9fe
commit 0efd96c072
12 changed files with 154 additions and 75 deletions

View file

@ -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 \

View file

@ -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 {

View file

@ -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)

View file

@ -3,6 +3,7 @@
#include <sailfishapp.h>
#include <src/ippdiscovery.h>
#include <src/ippprinter.h>
#include <src/imageitem.h>
#include <src/mimer.h>
#include <src/convertchecker.h>
#include <src/svgprovider.h>
@ -41,12 +42,12 @@ int main(int argc, char *argv[])
qmlRegisterSingletonType<ConvertChecker>("seaprint.convertchecker", 1, 0, "ConvertChecker", singletontype_provider<ConvertChecker>);
qmlRegisterSingletonType<ConvertChecker>("seaprint.settings", 1, 0, "SeaPrintSettings", singletontype_provider<Settings>);
qmlRegisterType<IppPrinter>("seaprint.ippprinter", 1, 0, "IppPrinter");
qmlRegisterType<ImageItem>("seaprint.imageitem", 1, 0, "ImageItem");
qmlRegisterUncreatableType<IppMsg>("seaprint.ippmsg", 1, 0, "IppMsg", "Only used to supply an enum type");
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());

32
src/imageitem.cpp Normal file
View file

@ -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();
}

31
src/imageitem.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef IMAGEITEM_H
#define IMAGEITEM_H
#include <QQuickPaintedItem>
#include <QPainter>
#include <QImage>
class ImageItem : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QImage image READ getImage WRITE setImage NOTIFY imageChanged)
Q_PROPERTY(bool valid READ isValid NOTIFY imageChanged)
public:
ImageItem();
void paint(QPainter *painter);
signals:
void imageChanged();
private:
QImage getImage() const;
void setImage(const QImage &image);
bool isValid() const;
QImage _image;
};
#endif // IMAGEITEM_H

View file

@ -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;
}

View file

@ -1,16 +1,11 @@
#ifndef IPPDISCOVERY_H
#define IPPDISCOVERY_H
#include <QStringListModel>
#include <QQuickImageProvider>
#include <QUdpSocket>
#include <QMutex>
#include <QImageReader>
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QEventLoop>
#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<QString,QString> _rps;

View file

@ -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<QSslError> &errors)
{
bool ignore = Settings::instance()->ignoreSslErrors();

View file

@ -1,8 +1,7 @@
#ifndef IPPPRINTER_H
#define IPPPRINTER_H
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QImage>
#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<QSslError> &errors);
@ -122,6 +126,7 @@ private:
QJsonArray _jobs;
QJsonObject _strings;
QImage _icon;
QStringList _additionalDocumentFormats;

View file

@ -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());

View file

@ -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);