Qt 4.8
qdeclarativepixmapcache.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
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.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qdeclarativepixmapcache_p.h"
45 
46 #include <qdeclarativeengine.h>
47 #include <private/qdeclarativeglobal_p.h>
48 #include <private/qdeclarativeengine_p.h>
49 
50 #include <QCoreApplication>
51 #include <QImageReader>
52 #include <QHash>
53 #include <QNetworkReply>
54 #include <QPixmapCache>
55 #include <QFile>
56 #include <QThread>
57 #include <QMutex>
58 #include <QMutexLocker>
59 #include <QWaitCondition>
60 #include <QBuffer>
61 #include <QWaitCondition>
62 #include <QtCore/qdebug.h>
63 #include <private/qobject_p.h>
64 #include <QSslError>
65 
66 #define IMAGEREQUEST_MAX_REQUEST_COUNT 8
67 #define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
68 #define CACHE_EXPIRE_TIME 30
69 #define CACHE_REMOVAL_FRACTION 4
70 
72 
73 // The cache limit describes the maximum "junk" in the cache.
74 // These are the same defaults as QPixmapCache
75 #if defined(Q_WS_QWS) || defined(Q_WS_WINCE)
76 static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded
77 #else
78 static int cache_limit = 10240 * 1024; // 10 MB cache limit for desktop
79 #endif
80 
84 {
85  Q_OBJECT
86 public:
88 
91 
93  QDeclarativeEngine *engineForReader; // always access reader inside readerMutex.
96 
97  bool loading;
99 
100  class Event : public QEvent {
101  public:
102  Event(ReadError, const QString &, const QSize &, const QImage &);
103 
108  };
109  void postReply(ReadError, const QString &, const QSize &, const QImage &);
110 
111 
112 Q_SIGNALS:
113  void finished();
115 
116 protected:
117  bool event(QEvent *event);
118 
119 private:
121 
122 public:
123  static int finishedIndex;
125 };
126 
128  Q_OBJECT
129 public:
131  void processJobs();
132  virtual bool event(QEvent *e);
133 private slots:
134  void networkRequestDone();
135 private:
137 };
138 
141 {
142  Q_OBJECT
143 public:
146 
148  void cancel(QDeclarativePixmapReply *rep);
149 
150  static QDeclarativePixmapReader *instance(QDeclarativeEngine *engine);
151  static QDeclarativePixmapReader *existingInstance(QDeclarativeEngine *engine);
152 
153 protected:
154  void run();
155 
156 private:
158  void processJobs();
159  void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &);
161 
166 
170 
171  QNetworkAccessManager *networkAccessManager();
173 
175 
177  static int replyFinished;
178  static int downloadProgress;
181 public:
183 };
184 
186 {
187 public:
188  QDeclarativePixmapData(const QUrl &u, const QSize &s, const QString &e)
189  : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Error),
190  url(u), errorString(e), requestSize(s), reply(0), prevUnreferenced(0),
191  prevUnreferencedPtr(0), nextUnreferenced(0)
192  {
193  }
194 
195  QDeclarativePixmapData(const QUrl &u, const QSize &r)
196  : refCount(1), inCache(false), pixmapStatus(QDeclarativePixmap::Loading),
197  url(u), requestSize(r), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0),
198  nextUnreferenced(0)
199  {
200  }
201 
202  QDeclarativePixmapData(const QUrl &u, const QPixmap &p, const QSize &s, const QSize &r)
203  : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QDeclarativePixmap::Ready),
204  url(u), pixmap(p), implicitSize(s), requestSize(r), reply(0), prevUnreferenced(0),
205  prevUnreferencedPtr(0), nextUnreferenced(0)
206  {
207  }
208 
210  : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QDeclarativePixmap::Ready),
211  pixmap(p), implicitSize(p.size()), requestSize(p.size()), reply(0), prevUnreferenced(0),
212  prevUnreferencedPtr(0), nextUnreferenced(0)
213  {
214  }
215 
216  int cost() const;
217  void addref();
218  void release();
219  void addToCache();
220  void removeFromCache();
221 
223 
224  bool inCache:1;
226 
233 
235 
239 };
240 
243 
244 // XXX
247 
252 
253 
255  const QSize &implicitSize, const QImage &image)
256 {
257  loading = false;
258  QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, image));
259 }
260 
262 : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i)
263 {
264 }
265 
267 {
268  if (!accessManager) {
269  Q_ASSERT(threadObject);
270  accessManager = QDeclarativeEnginePrivate::get(engine)->createNetworkAccessManager(threadObject);
271  }
272  return accessManager;
273 }
274 
275 static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
276  const QSize &requestSize)
277 {
278  QImageReader imgio(dev);
279 
280  bool force_scale = false;
281  if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) {
282  imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053
283  force_scale = true;
284  }
285 
286  bool scaled = false;
287  if (requestSize.width() > 0 || requestSize.height() > 0) {
288  QSize s = imgio.size();
289  if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
290  if (requestSize.height() <= 0)
291  s.setHeight(s.height()*requestSize.width()/s.width());
292  s.setWidth(requestSize.width()); scaled = true;
293  }
294  if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
295  if (requestSize.width() <= 0)
296  s.setWidth(s.width()*requestSize.height()/s.height());
297  s.setHeight(requestSize.height()); scaled = true;
298  }
299  if (scaled) { imgio.setScaledSize(s); }
300  }
301 
302  if (impsize)
303  *impsize = imgio.size();
304 
305  if (imgio.read(image)) {
306  if (impsize && impsize->width() < 0)
307  *impsize = image->size();
308  return true;
309  } else {
310  if (errorString)
311  *errorString = QDeclarativePixmap::tr("Error decoding: %1: %2").arg(url.toString())
312  .arg(imgio.errorString());
313  return false;
314  }
315 }
316 
318 : QThread(eng), engine(eng), threadObject(0), accessManager(0)
319 {
324 }
325 
327 {
328  readerMutex.lock();
331 
332  mutex.lock();
333  // manually cancel all outstanding jobs.
334  foreach (QDeclarativePixmapReply *reply, jobs) {
335  delete reply;
336  }
337  jobs.clear();
339  foreach (QDeclarativePixmapReply *reply, activeJobs) {
340  if (reply->loading) {
341  cancelled.append(reply);
342  reply->data = 0;
343  }
344  }
346  mutex.unlock();
347 
349  wait();
350 }
351 
353 {
354  QDeclarativePixmapReply *job = replies.take(reply);
355 
356  if (job) {
357  job->redirectCount++;
360  if (redirect.isValid()) {
361  QUrl url = reply->url().resolved(redirect.toUrl());
362  QNetworkRequest req(url);
364 
365  reply->deleteLater();
366  reply = networkAccessManager()->get(req);
367 
370 
371  replies.insert(reply, job);
372  return;
373  }
374  }
375 
376  QImage image;
379  QSize readSize;
380  if (reply->error()) {
382  errorString = reply->errorString();
383  } else {
384  QByteArray all = reply->readAll();
385  QBuffer buff(&all);
387  if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize)) {
389  }
390  }
391  // send completion event to the QDeclarativePixmapReply
392  mutex.lock();
393  if (!cancelled.contains(job)) job->postReply(error, errorString, readSize, image);
394  mutex.unlock();
395  }
396  reply->deleteLater();
397 
398  // kick off event loop again incase we have dropped below max request count
400 }
401 
403 : reader(i)
404 {
405 }
406 
408 {
410 }
411 
413 {
414  if (e->type() == QEvent::User) {
415  reader->processJobs();
416  return true;
417  } else {
418  return QObject::event(e);
419  }
420 }
421 
423 {
424  QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
425  reader->networkRequestDone(reply);
426 }
427 
429 {
430  QMutexLocker locker(&mutex);
431 
432  while (true) {
433  if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT))
434  return; // Nothing else to do
435 
436  // Clean cancelled jobs
437  if (cancelled.count()) {
438  for (int i = 0; i < cancelled.count(); ++i) {
439  QDeclarativePixmapReply *job = cancelled.at(i);
440  QNetworkReply *reply = replies.key(job, 0);
441  if (reply && reply->isRunning()) {
442  // cancel any jobs already started
443  replies.remove(reply);
444  reply->close();
445  }
446  // deleteLater, since not owned by this thread
447  job->deleteLater();
448  }
449  cancelled.clear();
450  }
451 
452  if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
453  QDeclarativePixmapReply *runningJob = jobs.takeLast();
454  runningJob->loading = true;
455  QUrl url = runningJob->url;
456  QSize requestSize = runningJob->requestSize;
457  locker.unlock();
458  processJob(runningJob, url, requestSize);
459  locker.relock();
460  }
461  }
462 }
463 
465  const QSize &requestSize)
466 {
467  // fetch
468  if (url.scheme() == QLatin1String("image")) {
469  // Use QmlImageProvider
470  QSize readSize;
472  QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
473 
475  QString errorStr;
476  if (image.isNull()) {
478  errorStr = QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString());
479  }
480  mutex.lock();
481  if (!cancelled.contains(runningJob)) runningJob->postReply(errorCode, errorStr, readSize, image);
482  mutex.unlock();
483  } else {
485  if (!lf.isEmpty()) {
486  // Image is local - load/decode immediately
487  QImage image;
489  QString errorStr;
490  QFile f(lf);
491  QSize readSize;
492  if (f.open(QIODevice::ReadOnly)) {
493  if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize))
495  } else {
496  errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
498  }
499  mutex.lock();
500  if (!cancelled.contains(runningJob)) runningJob->postReply(errorCode, errorStr, readSize, image);
501  mutex.unlock();
502  } else {
503  // Network resource
504  QNetworkRequest req(url);
506  QNetworkReply *reply = networkAccessManager()->get(req);
507  QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
508  QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
509  replies.insert(reply, runningJob);
510  }
511  }
512 }
513 
515 {
516  // XXX NOTE: must be called within readerMutex locking.
517  QDeclarativePixmapReader *reader = readers.value(engine);
518  if (!reader) {
519  reader = new QDeclarativePixmapReader(engine);
520  readers.insert(engine, reader);
521  }
522 
523  return reader;
524 }
525 
527 {
528  // XXX NOTE: must be called within readerMutex locking.
529  return readers.value(engine, 0);
530 }
531 
533 {
534  mutex.lock();
536  reply->engineForReader = engine;
537  jobs.append(reply);
538  // XXX
539  if (threadObject) threadObject->processJobs();
540  mutex.unlock();
541  return reply;
542 }
543 
545 {
546  mutex.lock();
547  if (reply->loading) {
548  cancelled.append(reply);
549  reply->data = 0;
550  // XXX
551  if (threadObject) threadObject->processJobs();
552  } else {
553  jobs.removeAll(reply);
554  delete reply;
555  }
556  mutex.unlock();
557 }
558 
560 {
561  if (replyDownloadProgress == -1) {
565  replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)");
566  replyFinished = nr->indexOfSignal("finished()");
567  downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)");
568  threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()");
569  }
570 
571  mutex.lock();
572  threadObject = new QDeclarativePixmapReaderThreadObject(this);
573  mutex.unlock();
574 
575  processJobs();
576  exec();
577 
578  delete threadObject;
579  threadObject = 0;
580 }
581 
583 {
584 public:
585  const QUrl *url;
586  const QSize *size;
587 };
588 
589 inline bool operator==(const QDeclarativePixmapKey &lhs, const QDeclarativePixmapKey &rhs)
590 {
591  return *lhs.size == *rhs.size && *lhs.url == *rhs.url;
592 }
593 
595 {
596  return qHash(*key.url) ^ key.size->width() ^ key.size->height();
597 }
598 
600 {
601  Q_OBJECT
602 public:
604 
605  void unreferencePixmap(QDeclarativePixmapData *);
606  void referencePixmap(QDeclarativePixmapData *);
607  void flushCache();
608 
609 protected:
610  virtual void timerEvent(QTimerEvent *);
611 
612 public:
614 
615 private:
616  void shrinkCache(int remove);
617 
620 
623 };
625 
627 : m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1)
628 {
629 }
630 
632 {
633  Q_ASSERT(data->prevUnreferenced == 0);
634  Q_ASSERT(data->prevUnreferencedPtr == 0);
635  Q_ASSERT(data->nextUnreferenced == 0);
636 
639 
644  }
645 
648 
649  m_unreferencedCost += data->cost();
650 
651  shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
652 
653  if (m_timerId == -1 && m_unreferencedPixmaps)
655 }
656 
658 {
660 
661  *data->prevUnreferencedPtr = data->nextUnreferenced;
662  if (data->nextUnreferenced) {
665  }
666  if (m_lastUnreferencedPixmap == data)
668 
669  data->nextUnreferenced = 0;
670  data->prevUnreferencedPtr = 0;
671  data->prevUnreferenced = 0;
672 
673  m_unreferencedCost -= data->cost();
674 }
675 
677 {
678  while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) {
680  Q_ASSERT(data->nextUnreferenced == 0);
681 
682  *data->prevUnreferencedPtr = 0;
684  data->prevUnreferencedPtr = 0;
685  data->prevUnreferenced = 0;
686 
687  remove -= data->cost();
688  m_unreferencedCost -= data->cost();
689  data->removeFromCache();
690  delete data;
691  }
692 }
693 
695 {
696  int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
697 
698  shrinkCache(removalCost);
699 
700  if (m_unreferencedPixmaps == 0) {
702  m_timerId = -1;
703  }
704 }
705 
706 /*
707  Remove all unreferenced pixmaps from the cache.
708 */
710 {
712 }
713 
715 : data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0)
716 {
717  if (finishedIndex == -1) {
720  }
721 }
722 
724 {
725 }
726 
728 {
729  if (event->type() == QEvent::User) {
730 
731  if (data) {
732  Event *de = static_cast<Event *>(event);
734 
738  } else {
740  data->removeFromCache(); // We don't continue to cache error'd pixmaps
741  }
742 
743  data->reply = 0;
744  emit finished();
745  }
746 
747  delete this;
748  return true;
749  } else {
750  return QObject::event(event);
751  }
752 }
753 
755 {
756  return (pixmap.width() * pixmap.height() * pixmap.depth()) / 8;
757 }
758 
760 {
761  ++refCount;
762  if (prevUnreferencedPtr)
763  pixmapStore()->referencePixmap(this);
764 }
765 
767 {
768  Q_ASSERT(refCount > 0);
769  --refCount;
770 
771  if (refCount == 0) {
772  if (reply) {
773  QDeclarativePixmapReply *cancelReply = reply;
774  reply->data = 0;
775  reply = 0;
776  QDeclarativePixmapReader::readerMutex.lock();
778  if (reader)
779  reader->cancel(cancelReply);
780  QDeclarativePixmapReader::readerMutex.unlock();
781  }
782 
783  if (pixmapStatus == QDeclarativePixmap::Ready) {
784  pixmapStore()->unreferencePixmap(this);
785  } else {
786  removeFromCache();
787  delete this;
788  }
789  }
790 }
791 
793 {
794  if (!inCache) {
796  pixmapStore()->m_cache.insert(key, this);
797  inCache = true;
798  }
799 }
800 
802 {
803  if (inCache) {
805  pixmapStore()->m_cache.remove(key);
806  inCache = false;
807  }
808 }
809 
811 {
812  if (url.scheme() == QLatin1String("image")) {
813  QSize readSize;
816 
817  switch (imageType) {
819  {
820  QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
821  if (!image.isNull()) {
822  *ok = true;
823  return new QDeclarativePixmapData(url, QPixmap::fromImage(image), readSize, requestSize);
824  }
825  }
827  {
828  QPixmap pixmap = ep->getPixmapFromProvider(url, &readSize, requestSize);
829  if (!pixmap.isNull()) {
830  *ok = true;
831  return new QDeclarativePixmapData(url, pixmap, readSize, requestSize);
832  }
833  }
834  }
835 
836  // no matching provider, or provider has bad image type, or provider returned null image
837  return new QDeclarativePixmapData(url, requestSize,
838  QDeclarativePixmap::tr("Failed to get image from provider: %1").arg(url.toString()));
839  }
840 
842  if (localFile.isEmpty())
843  return 0;
844 
845  QFile f(localFile);
846  QSize readSize;
848 
849  if (f.open(QIODevice::ReadOnly)) {
850  QImage image;
851  if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) {
852  *ok = true;
853  return new QDeclarativePixmapData(url, QPixmap::fromImage(image), readSize, requestSize);
854  }
855  } else {
856  errorString = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString());
857  }
858  return new QDeclarativePixmapData(url, requestSize, errorString);
859 }
860 
861 
866 };
868 
870 : d(0)
871 {
872 }
873 
875 : d(0)
876 {
877  load(engine, url);
878 }
879 
881 : d(0)
882 {
883  load(engine, url, size);
884 }
885 
887 {
888  if (d) {
889  d->release();
890  d = 0;
891  }
892 }
893 
895 {
896  return d == 0;
897 }
898 
900 {
901  return status() == Ready;
902 }
903 
905 {
906  return status() == Error;
907 }
908 
910 {
911  return status() == Loading;
912 }
913 
915 {
916  if (d)
917  return d->errorString;
918  else
919  return QString();
920 }
921 
923 {
924  if (d)
925  return d->pixmapStatus;
926  else
927  return Null;
928 }
929 
931 {
932  if (d)
933  return d->url;
934  else
935  return nullPixmap()->url;
936 }
937 
939 {
940  if (d)
941  return d->implicitSize;
942  else
943  return nullPixmap()->size;
944 }
945 
947 {
948  if (d)
949  return d->requestSize;
950  else
951  return nullPixmap()->size;
952 }
953 
955 {
956  if (d)
957  return d->pixmap;
958  else
959  return nullPixmap()->pixmap;
960 }
961 
963 {
964  clear();
965 
966  if (!p.isNull())
967  d = new QDeclarativePixmapData(p);
968 }
969 
971 {
972  if (d)
973  return d->pixmap.width();
974  else
975  return 0;
976 }
977 
979 {
980  if (d)
981  return d->pixmap.height();
982  else
983  return 0;
984 }
985 
987 {
988  if (d)
989  return d->pixmap.rect();
990  else
991  return QRect();
992 }
993 
995 {
996  load(engine, url, QSize(), QDeclarativePixmap::Cache);
997 }
998 
999 void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDeclarativePixmap::Options options)
1000 {
1001  load(engine, url, QSize(), options);
1002 }
1003 
1004 void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size)
1005 {
1006  load(engine, url, size, QDeclarativePixmap::Cache);
1007 }
1008 
1009 void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, QDeclarativePixmap::Options options)
1010 {
1011  if (d) { d->release(); d = 0; }
1012 
1013  QDeclarativePixmapKey key = { &url, &requestSize };
1014  QDeclarativePixmapStore *store = pixmapStore();
1015 
1017 
1018  if (iter == store->m_cache.end()) {
1019  if (options & QDeclarativePixmap::Asynchronous) {
1020  // pixmaps can only be loaded synchronously
1021  if (url.scheme() == QLatin1String("image")
1024  }
1025  }
1026 
1027  if (!(options & QDeclarativePixmap::Asynchronous)) {
1028  bool ok = false;
1029  d = createPixmapDataSync(engine, url, requestSize, &ok);
1030  if (ok) {
1031  if (options & QDeclarativePixmap::Cache)
1032  d->addToCache();
1033  return;
1034  }
1035  if (d) // loadable, but encountered error while loading
1036  return;
1037  }
1038 
1039  if (!engine)
1040  return;
1041 
1042  d = new QDeclarativePixmapData(url, requestSize);
1043  if (options & QDeclarativePixmap::Cache)
1044  d->addToCache();
1045  QDeclarativePixmapReader::readerMutex.lock();
1047  QDeclarativePixmapReader::readerMutex.unlock();
1048  } else {
1049  d = *iter;
1050  d->addref();
1051  }
1052 }
1053 
1055 {
1056  if (d) {
1057  d->release();
1058  d = 0;
1059  }
1060 }
1061 
1063 {
1064  if (d) {
1065  if (d->reply)
1066  QObject::disconnect(d->reply, 0, obj, 0);
1067  d->release();
1068  d = 0;
1069  }
1070 }
1071 
1072 bool QDeclarativePixmap::connectFinished(QObject *object, const char *method)
1073 {
1074  if (!d || !d->reply) {
1075  qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
1076  return false;
1077  }
1078 
1079  return QObject::connect(d->reply, SIGNAL(finished()), object, method);
1080 }
1081 
1083 {
1084  if (!d || !d->reply) {
1085  qWarning("QDeclarativePixmap: connectFinished() called when not loading.");
1086  return false;
1087  }
1088 
1090 }
1091 
1092 bool QDeclarativePixmap::connectDownloadProgress(QObject *object, const char *method)
1093 {
1094  if (!d || !d->reply) {
1095  qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
1096  return false;
1097  }
1098 
1099  return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method);
1100 }
1101 
1103 {
1104  if (!d || !d->reply) {
1105  qWarning("QDeclarativePixmap: connectDownloadProgress() called when not loading.");
1106  return false;
1107  }
1108 
1110 }
1111 
1113 {
1114  pixmapStore()->flushCache();
1115 }
1116 
1118 
1119 #include <qdeclarativepixmapcache.moc>
ImageType
Defines the type of image supported by this image provider.
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
int startTimer(int interval)
Starts a timer and returns a timer identifier, or returns zero if it could not start a timer...
Definition: qobject.cpp:1623
static QString urlToLocalFileOrQrc(const QUrl &url)
double d
Definition: qnumeric_p.h:62
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
#define CACHE_REMOVAL_FRACTION
QHash< QNetworkReply *, QDeclarativePixmapReply * > replies
QDeclarativePixmapData * data
Error
Definition: qaudio.h:58
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition: qpixmap.cpp:2197
NetworkError error() const
Returns the error that was found during the processing of this request.
void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &)
static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=0)
Definition: qobject.cpp:3194
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void lock()
Locks the mutex.
Definition: qmutex.cpp:151
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
int width() const
Returns the width of the pixmap.
Definition: qpixmap.cpp:630
int remove(const Key &key)
Removes all the items that have the key from the hash.
Definition: qhash.h:784
QString toString(FormattingOptions options=None) const
Returns the human-displayable string representation of the URL.
Definition: qurl.cpp:5896
QDeclarativePixmapReply(QDeclarativePixmapData *)
bool connectDownloadProgress(QObject *, const char *)
QDeclarativePixmapData(const QUrl &u, const QSize &r)
void setScaledSize(const QSize &size)
Sets the scaled size of the image to size.
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
QDeclarativePixmapData * d
static void postEvent(QObject *receiver, QEvent *event)
Adds the event event, with the object receiver as the receiver of the event, to an event queue and re...
QVariant attribute(QNetworkRequest::Attribute code) const
Returns the attribute associated with the code code.
#define IMAGEREQUEST_MAX_REQUEST_COUNT
bool open(OpenMode openMode)
Reimplemented Function
Definition: qbuffer.cpp:338
#define error(msg)
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
The QNetworkReply class contains the data and headers for a request sent with QNetworkAccessManager.
Definition: qnetworkreply.h:65
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
#define SLOT(a)
Definition: qobjectdefs.h:226
bool isRunning() const
Returns true when the request is still processing and the reply has not finished or was aborted yet...
QString errorString() const
Returns a human-readable description of the last device error that occurred.
Definition: qiodevice.cpp:1671
virtual void timerEvent(QTimerEvent *)
This event handler can be reimplemented in a subclass to receive timer events for the object...
Definition: qobject.cpp:1294
void unlock()
Unlocks this mutex locker.
Definition: qmutex.h:117
static const QMetaObject staticMetaObject
This variable stores the meta-object for the class.
Definition: qobject.h:128
QDeclarativePixmapReader(QDeclarativeEngine *eng)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
#define Q_DISABLE_COPY(Class)
Disables the use of copy constructors and assignment operators for the given Class.
Definition: qglobal.h:2523
quint16 u
void unreferencePixmap(QDeclarativePixmapData *)
void cancel(QDeclarativePixmapReply *rep)
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:57
The QUrl class provides a convenient interface for working with URLs.
Definition: qurl.h:61
The QString class provides a Unicode character string.
Definition: qstring.h:83
void setHeight(int h)
Sets the height to the given height.
Definition: qsize.h:135
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it...
Definition: qhash.h:807
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
Q_GLOBAL_STATIC(QDeclarativePixmapStore, pixmapStore)
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition: qobject.cpp:1200
#define Q_SIGNALS
Definition: qobjectdefs.h:72
#define CACHE_EXPIRE_TIME
static QDeclarativeEnginePrivate * get(QDeclarativeEngine *e)
void postReply(ReadError, const QString &, const QSize &, const QImage &)
void quit()
Tells the thread&#39;s event loop to exit with return code 0 (success).
Definition: qthread.cpp:614
void setAttribute(Attribute code, const QVariant &value)
Sets the attribute associated with code code to be value value.
QString path() const
Returns the path of the URL.
Definition: qurl.cpp:4977
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition: qobject.cpp:2327
void setFormat(const QByteArray &format)
Sets the format QImageReader will use when reading images, to format.
Q_GUI_EXPORT QString errorString(EGLint code=eglGetError())
Definition: qegl.cpp:743
void setWidth(int w)
Sets the width to the given width.
Definition: qsize.h:132
void relock()
Relocks an unlocked mutex locker.
Definition: qmutex.h:125
virtual void timerEvent(QTimerEvent *)
This event handler can be reimplemented in a subclass to receive timer events for the object...
#define SIGNAL(a)
Definition: qobjectdefs.h:227
QDeclarativeEngine * engineForReader
int width() const
Returns the width.
Definition: qsize.h:126
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
QString errorString() const
Returns a human readable description of the last error that occurred.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QList< QDeclarativePixmapReply * > jobs
const QUrl & url() const
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
const QPixmap & pixmap() const
QDeclarativePixmapReaderThreadObject(QDeclarativePixmapReader *)
virtual void close()
Closes this device for reading.
void destroyed(QObject *=0)
This signal is emitted immediately before the object obj is destroyed, and can not be blocked...
void referencePixmap(QDeclarativePixmapData *)
static QImage getImage(QTextDocument *doc, const QTextImageFormat &format)
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QDeclarativeImageProvider::ImageType getImageProviderType(const QUrl &url)
#define emit
Definition: qobjectdefs.h:76
QDeclarativePixmapReply * reply
QDeclarativePixmapData * m_lastUnreferencedPixmap
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition: qobject.cpp:1458
int indexOfSlot(const char *slot) const
Finds slot and returns its index; otherwise returns -1.
int indexOfSignal(const char *signal) const
Finds signal and returns its index; otherwise returns -1.
void clear()
Removes all items from the list.
Definition: qlist.h:764
__int64 qint64
Definition: qglobal.h:942
QDeclarativePixmapData * nextUnreferenced
const QSize & requestSize() const
QNetworkAccessManager * networkAccessManager()
const QSize & implicitSize() const
QDeclarativePixmapReply * getImage(QDeclarativePixmapData *)
void setPixmap(const QPixmap &)
QNetworkReply * get(const QNetworkRequest &request)
Posts a request to obtain the contents of the target request and returns a new QNetworkReply object o...
QUrl toUrl() const
Returns the variant as a QUrl if the variant has type() Url ; otherwise returns an invalid QUrl...
Definition: qvariant.cpp:2528
The QNetworkAccessManager class allows the application to send network requests and receive replies...
void unlock()
Unlocks the mutex.
Definition: qmutex.cpp:296
#define Q_OBJECT
Definition: qobjectdefs.h:157
The QImageReader class provides a format independent interface for reading images from files or other...
Definition: qimagereader.h:62
QSize size() const
Returns the size of the image, i.
Definition: qimage.cpp:1587
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
QDeclarativePixmapData(const QPixmap &p)
bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
QString scheme() const
Returns the scheme of the URL.
Definition: qurl.cpp:4550
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
void networkRequestDone(QNetworkReply *)
QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize &req_size)
QDeclarativePixmapData * prevUnreferenced
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:467
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:341
bool connectFinished(QObject *, const char *)
The QDeclarativeEngine class provides an environment for instantiating QML components.
QDeclarativePixmapData(const QUrl &u, const QSize &s, const QString &e)
void run()
The starting point for the thread.
#define store(x)
void start(Priority=InheritPriority)
Begins execution of the thread by calling run().
Q_INVOKABLE QObject(QObject *parent=0)
Constructs an object with parent object parent.
Definition: qobject.cpp:753
QList< T > values() const
Returns a list containing all the values in the hash, in an arbitrary order.
Definition: qhash.h:693
bool wait(unsigned long time=ULONG_MAX)
Blocks the thread until either of these conditions is met:
int key
static QDeclarativePixmapData * createPixmapDataSync(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok)
The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
Definition: qhash.h:330
QNetworkAccessManager * accessManager
QDeclarativePixmapData * m_unreferencedPixmaps
Event(ReadError, const QString &, const QSize &, const QImage &)
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
QRect rect() const
Returns the pixmap&#39;s enclosing rectangle.
Definition: qpixmap.cpp:676
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
QFuture< T > run(Function function,...)
int height() const
Returns the height of the pixmap.
Definition: qpixmap.cpp:645
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
static QHash< QDeclarativeEngine *, QDeclarativePixmapReader * > readers
virtual bool event(QEvent *e)
This virtual function receives events to an object and should return true if the event e was recogniz...
#define IMAGEREQUEST_MAX_REDIRECT_RECURSION
QSize size() const
Returns the size of the image, without actually reading the image contents.
QHash< QDeclarativePixmapKey, QDeclarativePixmapData * > m_cache
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
Definition: qhash.h:865
QList< QDeclarativePixmapReply * > cancelled
QUrl url() const
Returns the URL of the content downloaded or uploaded.
static bool readImage(const QUrl &url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, const QSize &requestSize)
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
#define slots
Definition: qobjectdefs.h:68
void downloadProgress(qint64, qint64)
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition: qurl.cpp:5819
bool isValid() const
Returns true if the storage type of this variant is not QVariant::Invalid; otherwise returns false...
Definition: qvariant.h:485
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
QDeclarativePixmapData ** prevUnreferencedPtr
uint qHash(const QDeclarativePixmapKey &key)
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
QDeclarativePixmap::Status pixmapStatus
The QThread class provides a platform-independent way to manage threads.
Definition: qthread.h:59
static int cache_limit
QNetworkAccessManager * createNetworkAccessManager(QObject *parent) const
void deleteLater()
Schedules this object for deletion.
Definition: qobject.cpp:2145
void load(QDeclarativeEngine *, const QUrl &)
QImage read()
Reads an image from the device.
static QDeclarativePixmapReader * instance(QDeclarativeEngine *engine)
QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize &req_size)
QDeclarativePixmapData(const QUrl &u, const QPixmap &p, const QSize &s, const QSize &r)
static QDeclarativePixmapReader * existingInstance(QDeclarativeEngine *engine)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition: qobject.cpp:1650
QDeclarativePixmapReaderThreadObject * threadObject
bool operator==(const QDeclarativePixmapKey &lhs, const QDeclarativePixmapKey &rhs)