FlightGear next
PreviewImageItem.cxx
Go to the documentation of this file.
2
3#include <QSGSimpleTextureNode>
4#include <QQuickWindow>
5#include <QFileInfo>
6#include <QDir>
7#include <QNetworkAccessManager>
8#include <QNetworkReply>
9
10#include <Main/globals.hxx>
11
12namespace {
13
14QNetworkAccessManager* global_previewNetAccess = nullptr;
15
16}
17
19 QQuickItem(parent)
20{
21 setFlag(ItemHasContents);
22 // setImplicitWidth(STANDARD_THUMBNAIL_WIDTH);
23 // setImplicitHeight(STANDARD_THUMBNAIL_HEIGHT);
24
25 Q_ASSERT(global_previewNetAccess);
26}
27
31
32QSGNode *PreviewImageItem::updatePaintNode(QSGNode* oldNode, QQuickItem::UpdatePaintNodeData *)
33{
34 if (m_image.isNull()) {
35 delete oldNode;
36 return nullptr;
37 }
38
39 QSGSimpleTextureNode* textureNode = static_cast<QSGSimpleTextureNode*>(oldNode);
40 if (m_imageDirty || !textureNode) {
41 if (!textureNode) {
42 textureNode = new QSGSimpleTextureNode;
43 textureNode->setOwnsTexture(true);
44 }
45
46 QSGTexture* tex = window()->createTextureFromImage(m_image);
47 textureNode->setTexture(tex);
48 textureNode->markDirty(QSGBasicGeometryNode::DirtyMaterial);
49 m_imageDirty = false;
50 }
51
52 textureNode->setRect(QRectF(0, 0, width(), height()));
53 return textureNode;
54}
55
57{
58 return m_imageUrl;
59}
60
62{
63 return m_image.size();
64}
65
66void PreviewImageItem::setGlobalNetworkAccess(QNetworkAccessManager *netAccess)
67{
68 global_previewNetAccess = netAccess;
69}
70
72{
73 return m_requestActive;
74}
75
77{
78 return static_cast<float>(m_image.width()) / m_image.height();
79}
80
82{
83 m_imageUrl.clear();
84 m_image = QImage{};
85 m_imageDirty = true;
86 m_requestActive = false;
87 update();
88 emit imageUrlChanged();
89 emit isLoadingChanged();
90}
91
93{
94 if (m_imageUrl == url)
95 return;
96
97 m_imageUrl = url;
98 m_downloadRetryCount = 0;
99 startDownload();
100 emit imageUrlChanged();
101}
102
103void PreviewImageItem::startDownload()
104{
105 if (m_imageUrl.isEmpty())
106 return;
107
108 QNetworkRequest request(m_imageUrl);
109 QNetworkReply* reply = global_previewNetAccess->get(request);
110 connect(reply, &QNetworkReply::finished, this, &PreviewImageItem::onFinished);
111
112#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
113 connect(reply, &QNetworkReply::errorOccurred,
114 this, &PreviewImageItem::onDownloadError);
115#else
116 connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
117 this, SLOT(onDownloadError(QNetworkReply::NetworkError)));
118#endif
119 m_requestActive = true;
120 emit isLoadingChanged();
121}
122
123void PreviewImageItem::setImage(QImage image)
124{
125 m_image = image;
126 m_imageDirty = true;
127 setImplicitSize(m_image.width(), m_image.height());
128 emit sourceSizeChanged();
129 update();
130}
131
132void PreviewImageItem::onFinished()
133{
134 QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
135 if (reply->url() != m_imageUrl) {
136 // if replies arrive out of order, don't trample the correct one
137 return;
138 }
139
140 QImage img;
141 if (!img.load(reply, nullptr)) {
142 qWarning() << Q_FUNC_INFO << "failed to read image data from" << reply->url();
143 return;
144 }
145 setImage(img);
146 m_requestActive = false;
147 emit isLoadingChanged();
148}
149
150void PreviewImageItem::onDownloadError(QNetworkReply::NetworkError errorCode)
151{
152 QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
153 if (errorCode == 403) {
154 if (m_downloadRetryCount++ < 4) {
155 startDownload(); // retry
156 return;
157 }
158 }
159
160 qWarning() << Q_FUNC_INFO << "failed to download:" << reply->url();
161 qWarning() << "\t" << reply->errorString();
162 m_requestActive = false;
163 emit isLoadingChanged();
164}
static void setGlobalNetworkAccess(QNetworkAccessManager *netAccess)
QSGNode * updatePaintNode(QSGNode *, UpdatePaintNodeData *) override
void setImageUrl(QUrl url)
PreviewImageItem(QQuickItem *parent=nullptr)
void isLoadingChanged()
Q_INVOKABLE void clear()
clear the image immediately, so we don't see a stale / expired one while attemtping to load the next ...
void imageUrlChanged()
void sourceSizeChanged()