1 // Commit: 462429f5692f810bdd4e04b916db5f9af428d9e4
2 /****************************************************************************
4 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** No Commercial Usage
12 ** This file contains pre-release code and may not be distributed.
13 ** You may use this file in accordance with the terms and conditions
14 ** contained in the Technology Preview License Agreement accompanying
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
41 ****************************************************************************/
43 #include "qsgborderimage_p.h"
44 #include "qsgborderimage_p_p.h"
45 #include "qsgninepatchnode_p.h"
47 #include <QtDeclarative/qdeclarativeinfo.h>
48 #include <QtCore/qfile.h>
50 #include <private/qdeclarativeengine_p.h>
54 QSGBorderImage::QSGBorderImage(QSGItem *parent)
55 : QSGImageBase(*(new QSGBorderImagePrivate), parent)
59 QSGBorderImage::~QSGBorderImage()
63 d->sciReply->deleteLater();
66 void QSGBorderImage::setSource(const QUrl &url)
69 //equality is fairly expensive, so we bypass for simple, common case
70 if ((d->url.isEmpty() == url.isEmpty()) && url == d->url)
74 d->sciReply->deleteLater();
80 emit sourceChanged(d->url);
82 if (isComponentComplete())
86 void QSGBorderImage::load()
89 if (d->progress != 0.0) {
91 emit progressChanged(d->progress);
94 if (d->url.isEmpty()) {
99 emit statusChanged(d->status);
103 if (d->url.path().endsWith(QLatin1String("sci"))) {
104 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
105 QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
108 file.open(QIODevice::ReadOnly);
109 setGridScaledImage(QSGGridScaledImage(&file));
113 QNetworkRequest req(d->url);
114 d->sciReply = qmlEngine(this)->networkAccessManager()->get(req);
116 static int sciReplyFinished = -1;
117 static int thisSciRequestFinished = -1;
118 if (sciReplyFinished == -1) {
120 QNetworkReply::staticMetaObject.indexOfSignal("finished()");
121 thisSciRequestFinished =
122 QSGBorderImage::staticMetaObject.indexOfSlot("sciRequestFinished()");
125 QMetaObject::connect(d->sciReply, sciReplyFinished, this,
126 thisSciRequestFinished, Qt::DirectConnection);
130 QDeclarativePixmap::Options options;
132 options |= QDeclarativePixmap::Asynchronous;
134 options |= QDeclarativePixmap::Cache;
136 d->pix.load(qmlEngine(this), d->url, options);
138 if (d->pix.isLoading()) {
139 d->pix.connectFinished(this, SLOT(requestFinished()));
140 d->pix.connectDownloadProgress(this, SLOT(requestProgress(qint64,qint64)));
142 QSize impsize = d->pix.implicitSize();
143 setImplicitWidth(impsize.width());
144 setImplicitHeight(impsize.height());
146 if (d->pix.isReady()) {
150 qmlInfo(this) << d->pix.error();
154 emit statusChanged(d->status);
155 emit progressChanged(d->progress);
161 emit statusChanged(d->status);
164 QSGScaleGrid *QSGBorderImage::border()
167 return d->getScaleGrid();
170 QSGBorderImage::TileMode QSGBorderImage::horizontalTileMode() const
172 Q_D(const QSGBorderImage);
173 return d->horizontalTileMode;
176 void QSGBorderImage::setHorizontalTileMode(TileMode t)
179 if (t != d->horizontalTileMode) {
180 d->horizontalTileMode = t;
181 emit horizontalTileModeChanged();
186 QSGBorderImage::TileMode QSGBorderImage::verticalTileMode() const
188 Q_D(const QSGBorderImage);
189 return d->verticalTileMode;
192 void QSGBorderImage::setVerticalTileMode(TileMode t)
195 if (t != d->verticalTileMode) {
196 d->verticalTileMode = t;
197 emit verticalTileModeChanged();
202 void QSGBorderImage::setGridScaledImage(const QSGGridScaledImage& sci)
205 if (!sci.isValid()) {
207 emit statusChanged(d->status);
209 QSGScaleGrid *sg = border();
210 sg->setTop(sci.gridTop());
211 sg->setBottom(sci.gridBottom());
212 sg->setLeft(sci.gridLeft());
213 sg->setRight(sci.gridRight());
214 d->horizontalTileMode = sci.horizontalTileRule();
215 d->verticalTileMode = sci.verticalTileRule();
217 d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
219 QDeclarativePixmap::Options options;
221 options |= QDeclarativePixmap::Asynchronous;
223 options |= QDeclarativePixmap::Cache;
225 d->pix.load(qmlEngine(this), d->sciurl, options);
227 if (d->pix.isLoading()) {
228 static int thisRequestProgress = -1;
229 static int thisRequestFinished = -1;
230 if (thisRequestProgress == -1) {
231 thisRequestProgress =
232 QSGBorderImage::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)");
233 thisRequestFinished =
234 QSGBorderImage::staticMetaObject.indexOfSlot("requestFinished()");
237 d->pix.connectFinished(this, thisRequestFinished);
238 d->pix.connectDownloadProgress(this, thisRequestProgress);
242 QSize impsize = d->pix.implicitSize();
243 setImplicitWidth(impsize.width());
244 setImplicitHeight(impsize.height());
246 if (d->pix.isReady()) {
250 qmlInfo(this) << d->pix.error();
254 emit statusChanged(d->status);
255 emit progressChanged(1.0);
262 void QSGBorderImage::requestFinished()
266 QSize impsize = d->pix.implicitSize();
267 if (d->pix.isError()) {
269 qmlInfo(this) << d->pix.error();
274 setImplicitWidth(impsize.width());
275 setImplicitHeight(impsize.height());
277 if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height())
278 emit sourceSizeChanged();
281 emit statusChanged(d->status);
282 emit progressChanged(1.0);
286 #define BORDERIMAGE_MAX_REDIRECT 16
288 void QSGBorderImage::sciRequestFinished()
293 if (d->redirectCount < BORDERIMAGE_MAX_REDIRECT) {
294 QVariant redirect = d->sciReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
295 if (redirect.isValid()) {
296 QUrl url = d->sciReply->url().resolved(redirect.toUrl());
303 if (d->sciReply->error() != QNetworkReply::NoError) {
305 d->sciReply->deleteLater();
307 emit statusChanged(d->status);
309 QSGGridScaledImage sci(d->sciReply);
310 d->sciReply->deleteLater();
312 setGridScaledImage(sci);
316 void QSGBorderImage::doUpdate()
321 QSGNode *QSGBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
325 if (!d->pix.texture() || width() <= 0 || height() <= 0) {
330 QSGNinePatchNode *node = static_cast<QSGNinePatchNode *>(oldNode);
333 node = new QSGNinePatchNode();
336 node->setTexture(d->pix.texture());
338 const QSGScaleGrid *border = d->getScaleGrid();
339 node->setInnerRect(QRectF(border->left(),
341 d->pix.width() - border->right() - border->left(),
342 d->pix.height() - border->bottom() - border->top()));
343 node->setRect(QRectF(0, 0, width(), height()));
344 node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
345 node->setHorzontalTileMode(d->horizontalTileMode);
346 node->setVerticalTileMode(d->verticalTileMode);
352 void QSGBorderImage::pixmapChange()
356 d->pixmapChanged = true;