68 #define CACHE_EXPIRE_TIME 30 |
68 #define CACHE_EXPIRE_TIME 30 |
69 #define CACHE_REMOVAL_FRACTION 4 |
69 #define CACHE_REMOVAL_FRACTION 4 |
70 |
70 |
71 QT_BEGIN_NAMESPACE |
71 QT_BEGIN_NAMESPACE |
72 |
72 |
|
73 // The cache limit describes the maximum "junk" in the cache. |
|
74 // These are the same defaults as QPixmapCache |
|
75 #if defined(Q_OS_SYMBIAN) |
|
76 static int cache_limit = 1024 * 1024; // 1048 KB cache limit for symbian |
|
77 #elif defined(Q_WS_QWS) || defined(Q_WS_WINCE) |
|
78 static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded |
|
79 #else |
|
80 static int cache_limit = 10240 * 1024; // 10 MB cache limit for desktop |
|
81 #endif |
|
82 |
73 class QDeclarativePixmapReader; |
83 class QDeclarativePixmapReader; |
74 class QDeclarativePixmapData; |
84 class QDeclarativePixmapData; |
75 class QDeclarativePixmapReply : public QObject |
85 class QDeclarativePixmapReply : public QObject |
76 { |
86 { |
77 Q_OBJECT |
87 Q_OBJECT |
143 void run(); |
153 void run(); |
144 |
154 |
145 private: |
155 private: |
146 friend class QDeclarativePixmapReaderThreadObject; |
156 friend class QDeclarativePixmapReaderThreadObject; |
147 void processJobs(); |
157 void processJobs(); |
148 void processJob(QDeclarativePixmapReply *); |
158 void processJob(QDeclarativePixmapReply *, const QUrl &, const QSize &); |
149 void networkRequestDone(QNetworkReply *); |
159 void networkRequestDone(QNetworkReply *); |
150 |
160 |
151 QList<QDeclarativePixmapReply*> jobs; |
161 QList<QDeclarativePixmapReply*> jobs; |
152 QList<QDeclarativePixmapReply*> cancelled; |
162 QList<QDeclarativePixmapReply*> cancelled; |
153 QDeclarativeEngine *engine; |
163 QDeclarativeEngine *engine; |
422 |
432 |
423 if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) { |
433 if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) { |
424 QDeclarativePixmapReply *runningJob = jobs.takeLast(); |
434 QDeclarativePixmapReply *runningJob = jobs.takeLast(); |
425 runningJob->loading = true; |
435 runningJob->loading = true; |
426 |
436 |
|
437 QUrl url = runningJob->data->url; |
|
438 QSize requestSize = runningJob->data->requestSize; |
427 locker.unlock(); |
439 locker.unlock(); |
428 processJob(runningJob); |
440 processJob(runningJob, url, requestSize); |
429 locker.relock(); |
441 locker.relock(); |
430 } |
442 } |
431 } |
443 } |
432 } |
444 } |
433 |
445 |
434 void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob) |
446 void QDeclarativePixmapReader::processJob(QDeclarativePixmapReply *runningJob, const QUrl &url, |
435 { |
447 const QSize &requestSize) |
436 QUrl url = runningJob->data->url; |
448 { |
437 |
|
438 // fetch |
449 // fetch |
439 if (url.scheme() == QLatin1String("image")) { |
450 if (url.scheme() == QLatin1String("image")) { |
440 // Use QmlImageProvider |
451 // Use QmlImageProvider |
441 QSize readSize; |
452 QSize readSize; |
442 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); |
453 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); |
443 QImage image = ep->getImageFromProvider(url, &readSize, runningJob->data->requestSize); |
454 QImage image = ep->getImageFromProvider(url, &readSize, requestSize); |
444 |
455 |
445 QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError; |
456 QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError; |
446 QString errorStr; |
457 QString errorStr; |
447 if (image.isNull()) { |
458 if (image.isNull()) { |
448 errorCode = QDeclarativePixmapReply::Loading; |
459 errorCode = QDeclarativePixmapReply::Loading; |
460 QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError; |
471 QDeclarativePixmapReply::ReadError errorCode = QDeclarativePixmapReply::NoError; |
461 QString errorStr; |
472 QString errorStr; |
462 QFile f(lf); |
473 QFile f(lf); |
463 QSize readSize; |
474 QSize readSize; |
464 if (f.open(QIODevice::ReadOnly)) { |
475 if (f.open(QIODevice::ReadOnly)) { |
465 if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->data->requestSize)) |
476 if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize)) |
466 errorCode = QDeclarativePixmapReply::Loading; |
477 errorCode = QDeclarativePixmapReply::Loading; |
467 } else { |
478 } else { |
468 errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString()); |
479 errorStr = QDeclarativePixmap::tr("Cannot open: %1").arg(url.toString()); |
469 errorCode = QDeclarativePixmapReply::Loading; |
480 errorCode = QDeclarativePixmapReply::Loading; |
470 } |
481 } |
513 void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply) |
524 void QDeclarativePixmapReader::cancel(QDeclarativePixmapReply *reply) |
514 { |
525 { |
515 mutex.lock(); |
526 mutex.lock(); |
516 if (reply->loading) { |
527 if (reply->loading) { |
517 cancelled.append(reply); |
528 cancelled.append(reply); |
|
529 reply->data = 0; |
518 // XXX |
530 // XXX |
519 if (threadObject) threadObject->processJobs(); |
531 if (threadObject) threadObject->processJobs(); |
520 } else { |
532 } else { |
521 jobs.removeAll(reply); |
533 jobs.removeAll(reply); |
522 delete reply; |
534 delete reply; |
578 |
590 |
579 public: |
591 public: |
580 QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache; |
592 QHash<QDeclarativePixmapKey, QDeclarativePixmapData *> m_cache; |
581 |
593 |
582 private: |
594 private: |
|
595 void shrinkCache(int remove); |
|
596 |
583 QDeclarativePixmapData *m_unreferencedPixmaps; |
597 QDeclarativePixmapData *m_unreferencedPixmaps; |
584 QDeclarativePixmapData *m_lastUnreferencedPixmap; |
598 QDeclarativePixmapData *m_lastUnreferencedPixmap; |
585 |
599 |
586 int m_unreferencedCost; |
600 int m_unreferencedCost; |
587 int m_timerId; |
601 int m_timerId; |
611 if (!m_lastUnreferencedPixmap) |
625 if (!m_lastUnreferencedPixmap) |
612 m_lastUnreferencedPixmap = data; |
626 m_lastUnreferencedPixmap = data; |
613 |
627 |
614 m_unreferencedCost += data->cost(); |
628 m_unreferencedCost += data->cost(); |
615 |
629 |
616 if (m_timerId == -1) |
630 shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit |
|
631 |
|
632 if (m_timerId == -1 && m_unreferencedPixmaps) |
617 m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000); |
633 m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000); |
618 } |
634 } |
619 |
635 |
620 void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data) |
636 void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data) |
621 { |
637 { |
634 data->prevUnreferenced = 0; |
650 data->prevUnreferenced = 0; |
635 |
651 |
636 m_unreferencedCost -= data->cost(); |
652 m_unreferencedCost -= data->cost(); |
637 } |
653 } |
638 |
654 |
639 void QDeclarativePixmapStore::timerEvent(QTimerEvent *) |
655 void QDeclarativePixmapStore::shrinkCache(int remove) |
640 { |
656 { |
641 int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION; |
657 while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) { |
642 |
|
643 while (removalCost > 0 && m_lastUnreferencedPixmap) { |
|
644 QDeclarativePixmapData *data = m_lastUnreferencedPixmap; |
658 QDeclarativePixmapData *data = m_lastUnreferencedPixmap; |
645 Q_ASSERT(data->nextUnreferenced == 0); |
659 Q_ASSERT(data->nextUnreferenced == 0); |
646 |
660 |
647 *data->prevUnreferencedPtr = 0; |
661 *data->prevUnreferencedPtr = 0; |
648 m_lastUnreferencedPixmap = data->prevUnreferenced; |
662 m_lastUnreferencedPixmap = data->prevUnreferenced; |
649 data->prevUnreferencedPtr = 0; |
663 data->prevUnreferencedPtr = 0; |
650 data->prevUnreferenced = 0; |
664 data->prevUnreferenced = 0; |
651 |
665 |
652 removalCost -= data->cost(); |
666 remove -= data->cost(); |
|
667 m_unreferencedCost -= data->cost(); |
653 data->removeFromCache(); |
668 data->removeFromCache(); |
654 delete data; |
669 delete data; |
655 } |
670 } |
|
671 } |
|
672 |
|
673 void QDeclarativePixmapStore::timerEvent(QTimerEvent *) |
|
674 { |
|
675 int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION; |
|
676 |
|
677 shrinkCache(removalCost); |
656 |
678 |
657 if (m_unreferencedPixmaps == 0) { |
679 if (m_unreferencedPixmaps == 0) { |
658 killTimer(m_timerId); |
680 killTimer(m_timerId); |
659 m_timerId = -1; |
681 m_timerId = -1; |
660 } |
682 } |