diff options
Diffstat (limited to 'weather/src/pixmaploader.cpp')
-rw-r--r-- | weather/src/pixmaploader.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/weather/src/pixmaploader.cpp b/weather/src/pixmaploader.cpp new file mode 100644 index 0000000..e60cef4 --- /dev/null +++ b/weather/src/pixmaploader.cpp @@ -0,0 +1,125 @@ +#include "pixmaploader.h" +#include "settings.h" +#include <QMutexLocker> + +#include "settings.h" + +// PixmapLoaderThread + +PixmapLoaderThread::PixmapLoaderThread(PixmapLoader *loader) + : QThread(loader) + , m_loader(loader) +{ +} + +void PixmapLoaderThread::run() +{ + static const qreal widthFactor = Settings::widthFactor(); + static const qreal heightFactor = Settings::heightFactor(); + QString name = m_loader->dequeue(); + while (!name.isEmpty()) { + QImage image(":images/weather_elements/" + name + ".png"); + if (!image.isNull()) { + QSize size(widthFactor * image.size().width(), heightFactor * image.size().height()); + if (size.width() && size.height()) + image = image.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + emit imageIsReady(name, image); + name = m_loader->dequeue(); + } + deleteLater(); +} + +// PixmapLoader + +PixmapLoader::PixmapLoader(QObject *parent) + : QObject(parent) + , m_thread(0) +{ +} + +void PixmapLoader::load(const QString &name) +{ + instance()->enqueue(name); +} + +PixmapLoader *PixmapLoader::instance() +{ + static PixmapLoader * const result(new PixmapLoader()); + return result; +} + +void PixmapLoader::connectToOnIdleSignal(QObject *receiver, const char *method) +{ + QObject::connect(instance(), SIGNAL(onIdle()), receiver, method, Qt::QueuedConnection); +} + +void PixmapLoader::disconnectReceiver(QObject *receiver) +{ + instance()->disconnect(receiver); +} + +QPixmap PixmapLoader::getPic(const QString &name) +{ + PixmapLoader *obj = instance(); + QMutexLocker locker(&obj->m_mutex); + return obj->m_store.contains(name) ? obj->m_store[name] : QPixmap(); +} + +void PixmapLoader::enqueue(const QString &name) +{ + QMutexLocker locker(&m_mutex); + + if (m_queue.indexOf(name) >= 0 || m_currentImages.indexOf(name) >= 0 || m_store.contains(name)) + return; + + m_queue.append(name); + + if (!m_thread) { + m_thread = new PixmapLoaderThread(this); + connect(m_thread, SIGNAL(imageIsReady(QString,QImage)), + this, SLOT(imageIsReady(QString,QImage))); + m_thread->start(); + } + m_condition.wakeOne(); +} + +QString PixmapLoader::doDequeue() +{ + QString name = m_queue.isEmpty() ? QString() : m_queue.takeAt(0); + + while (!name.isEmpty() && (m_currentImages.indexOf(name) >= 0 || m_store.contains(name))) + name = m_queue.isEmpty() ? QString() : m_queue.takeAt(0); + + if (!name.isEmpty()) + m_currentImages.append(name); + + return name; +} + +QString PixmapLoader::dequeue() +{ + static const int waitTime = 60000; + QMutexLocker locker(&m_mutex); + QString result; + do + result = doDequeue(); + while (result.isEmpty() && m_condition.wait(&m_mutex, waitTime)); + if (result.isEmpty()) { + m_thread = 0; + } + return result; +} + +void PixmapLoader::imageIsReady(const QString &name, QImage image) +{ + QMutexLocker locker(&m_mutex); + + QPixmap pixmap = QPixmap::fromImage(image, Qt::ColorOnly); + if (!pixmap.isNull()) + m_store[name] = pixmap; + + m_currentImages.removeAll(name); + if (m_currentImages.isEmpty() && m_queue.isEmpty()) + emit onIdle(); +} |