Index: mythtv/libs/libmythui/mythuiimage.cpp =================================================================== --- mythtv/libs/libmythui/mythuiimage.cpp (revision 21272) +++ mythtv/libs/libmythui/mythuiimage.cpp (working copy) @@ -1,18 +1,78 @@ #include +// Mythui +#include "mythuiimage.h" +#include "mythpainter.h" +#include "mythmainwindow.h" +#include "mythuihelper.h" +#include "mythscreentype.h" + +// QT #include #include #include #include +#include +#include +#include +// Libmythdb #include "mythverbose.h" -#include "mythuiimage.h" -#include "mythpainter.h" -#include "mythmainwindow.h" -#include "mythuihelper.h" -#include "mythscreentype.h" +class ImageLoadThread; +const int kImageLoadEventType = 35112; + +/*! +* \class ImageLoadThread +*/ +class ImageLoadEvent : public QEvent +{ + public: + ImageLoadEvent(ImageLoadThread *thread, MythImage *image, + const QString &filename, int number) + : QEvent((QEvent::Type)kImageLoadEventType), + m_thread(thread), m_image(image), m_filename(filename), + m_number(number) { } + + ImageLoadThread *GetThread() const { return m_thread; } + MythImage *GetImage() const { return m_image; } + const QString GetFilename() const { return m_filename; } + const int GetNumber() const { return m_number; } + + private: + ImageLoadThread *m_thread; + MythImage *m_image; + QString m_filename; + int m_number; +}; + +/*! +* \class ImageLoadThread +*/ +class ImageLoadThread : public QThread +{ + public: + ImageLoadThread(MythUIImage *parent, const QString &filename, + int number) + : m_parent(parent), m_filename(filename), m_number(number) { }; + + void run() + { + MythImage *image = m_parent->LoadImage(m_filename, m_number); + ImageLoadEvent *le = new ImageLoadEvent(this, image, m_filename, + m_number); + QCoreApplication::sendEvent(m_parent, le); + } + + private: + MythUIImage *m_parent; + QString m_filename; + int m_number; +}; + +///////////////////////////////////////////////////////////////// + MythUIImage::MythUIImage(const QString &filepattern, int low, int high, int delayms, MythUIType *parent, const QString &name) @@ -317,7 +377,7 @@ * \brief Generates a unique identifying string for this image which is used * as a key in the image cache. */ -QString MythUIImage::GenImageLabel(const QString &filename, int w, int h) +QString MythUIImage::GenImageLabel(const QString &filename, int w, int h) const { QString imagelabel; QString s_Attrib; @@ -345,7 +405,7 @@ * \brief Generates a unique identifying string for this image which is used * as a key in the image cache. */ -QString MythUIImage::GenImageLabel(int w, int h) +QString MythUIImage::GenImageLabel(int w, int h) const { return GenImageLabel(m_Filename, w, h); } @@ -356,154 +416,156 @@ bool MythUIImage::Load(void) { Clear(); - + SetRedraw(); - -// if (!IsVisible(true)) -// return false; - + if (m_Filename.isEmpty() && (!m_gradient)) return false; - QSize newSize; + // if (!IsVisible(true)) + // return false; - VERBOSE(VB_FILE, QString("MythUIImage::Load (%1) Object %2").arg(m_Filename).arg(objectName())); - for (int i = m_LowNum; i <= m_HighNum; i++) { - MythImage *image = NULL; - bool bNeedLoad = false; + ImageLoadThread *thread = new ImageLoadThread(this, m_Filename, i); + thread->run(); + } - if (m_gradient) - { - QSize gradsize; - if (!m_Area.isEmpty()) - gradsize = m_Area.size(); - else - gradsize = QSize(10, 10); + return true; +} - image = MythImage::Gradient(gradsize, m_gradientStart, - m_gradientEnd, m_gradientAlpha, - m_gradientDirection); - image->UpRef(); - } +/** +* \brief Load the images in a another thread, do not call directly +*/ +MythImage *MythUIImage::LoadImage(const QString &imFile, int imageNumber) const +{ + QString filename = imFile; + + VERBOSE(VB_FILE, QString("MythUIImage::Load (%1) Object %2").arg(filename) + .arg(objectName())); + + MythImage *image = NULL; + bool bNeedLoad = false; + + if (m_gradient) + { + QSize gradsize; + if (!m_Area.isEmpty()) + gradsize = m_Area.size(); else - bNeedLoad = true; + gradsize = QSize(10, 10); - int w = -1; - int h = -1; + image = MythImage::Gradient(gradsize, m_gradientStart, + m_gradientEnd, m_gradientAlpha, + m_gradientDirection); + image->UpRef(); + } + else + bNeedLoad = true; - bool bForceResize = false; - bool bFoundInCache = false; + int w = -1; + int h = -1; - QString imagelabel; + bool bForceResize = false; + bool bFoundInCache = false; - if (!m_ForceSize.isNull()) - { - if (m_ForceSize.width() != -1) - w = m_ForceSize.width(); + QString imagelabel; - if (m_ForceSize.height() != -1) - h = m_ForceSize.height(); + if (!m_ForceSize.isNull()) + { + if (m_ForceSize.width() != -1) + w = m_ForceSize.width(); - bForceResize = true; - } + if (m_ForceSize.height() != -1) + h = m_ForceSize.height(); - if (bNeedLoad) - { + bForceResize = true; + } - QString filename = m_Filename; - if (m_HighNum >= 1) - filename = QString(m_Filename).arg(i); + if (bNeedLoad) + { + if (imageNumber >= 1) + filename = QString(filename).arg(imageNumber); - imagelabel = GenImageLabel(filename, w, h); + imagelabel = GenImageLabel(filename, w, h); - image = GetMythUI()->LoadCacheImage(filename, imagelabel); - if (image) - { - image->UpRef(); - VERBOSE(VB_FILE, QString("MythUIImage::Load found in cache :%1:").arg(imagelabel)); - if (m_isReflected) - image->setIsReflected(true); + image = GetMythUI()->LoadCacheImage(filename, imagelabel); + if (image) + { + image->UpRef(); + VERBOSE(VB_FILE, QString("MythUIImage::Load found in cache :%1:").arg(imagelabel)); + if (m_isReflected) + image->setIsReflected(true); - bFoundInCache = true; - } - else - { - VERBOSE(VB_FILE, QString("MythUIImage::Load Not Found in " - "cache. Loading Directly :%1:") - .arg(filename)); - image = GetMythPainter()->GetFormatImage(); - image->UpRef(); - if (!image->Load(filename)) - { - VERBOSE(VB_FILE, QString("MythUIImage::Load Could not load :%1:").arg(filename)); - image->DownRef(); - SetRedraw(); - return false; - } - } + bFoundInCache = true; } else - imagelabel = GenImageLabel(w,h); - - if (!bFoundInCache) { - if (bForceResize) - image->Resize(QSize(w, h), m_preserveAspect); - - if (m_isMasked) + VERBOSE(VB_FILE, QString("MythUIImage::Load Not Found in " + "cache. Loading Directly :%1:") + .arg(filename)); + image = GetMythPainter()->GetFormatImage(); + image->UpRef(); + if (!image->Load(filename)) { - QRect imageArea = image->rect(); - QRect maskArea = m_maskImage->rect(); - - // Crop the mask to the image - int x = 0; - int y = 0; - if (maskArea.width() > imageArea.width()) - x = (maskArea.width() - imageArea.width()) / 2; - if (maskArea.height() > imageArea.height()) - y = (maskArea.height() - imageArea.height()) / 2; - - if (x > 0 || y > 0) - imageArea.translate(x,y); - QImage mask = m_maskImage->copy(imageArea); - image->setAlphaChannel(mask.alphaChannel()); + VERBOSE(VB_FILE, QString("MythUIImage::Load Could not load " + ":%1:").arg(filename)); + image->DownRef(); + return NULL; } + } + } + else + imagelabel = GenImageLabel(w,h); - if (m_isReflected) - image->Reflect(m_reflectAxis, m_reflectShear, m_reflectScale, - m_reflectLength, m_reflectSpacing); + if (!bFoundInCache) + { + if (bForceResize) + image->Resize(QSize(w, h), m_preserveAspect); - if (m_isGreyscale) - image->ToGreyscale(); + if (m_isMasked) + { + QRect imageArea = image->rect(); + QRect maskArea = m_maskImage->rect(); - // Save scaled copy to cache - if (bNeedLoad) - GetMythUI()->CacheImage(imagelabel, image); - } + // Crop the mask to the image + int x = 0; + int y = 0; + if (maskArea.width() > imageArea.width()) + x = (maskArea.width() - imageArea.width()) / 2; + if (maskArea.height() > imageArea.height()) + y = (maskArea.height() - imageArea.height()) / 2; - if (!bForceResize) - { - newSize = newSize.expandedTo(image->size()); - SetSize(newSize); + if (x > 0 || y > 0) + imageArea.translate(x,y); + QImage mask = m_maskImage->copy(imageArea); + image->setAlphaChannel(mask.alphaChannel()); } - if (image->isNull()) - { - VERBOSE(VB_FILE, QString("MythUIImage::Load Image is NULL :%1:").arg(m_Filename)); - image->DownRef(); - } - else - { - image->SetChanged(); - m_Images.push_back(image); - } + if (m_isReflected) + image->Reflect(m_reflectAxis, m_reflectShear, m_reflectScale, + m_reflectLength, m_reflectSpacing); + + if (m_isGreyscale) + image->ToGreyscale(); + + // Save scaled copy to cache + if (bNeedLoad) + GetMythUI()->CacheImage(imagelabel, image); } - m_LastDisplay = QTime::currentTime(); + if (image->isNull()) + { + VERBOSE(VB_FILE, QString("MythUIImage::Load Image is NULL :%1:") + .arg(filename)); + image->DownRef(); + } + else + { + image->SetChanged(); + } - return true; + return image; } /** @@ -787,3 +849,67 @@ MythUIType::LoadNow(); } +/** +* \copydoc MythUIType::customEvent() +*/ +void MythUIImage::customEvent(QEvent *event) +{ + if (event->type() == kImageLoadEventType) + { + ImageLoadEvent *le = dynamic_cast(event); + + ImageLoadThread *thread = le->GetThread(); + MythImage *image = le->GetImage(); + + if (thread) + delete thread; + + if (image) + { + QString filename = le->GetFilename(); + + if (filename == m_Filename) + { + int number = le->GetNumber(); + + if (m_ForceSize.isNull()) + SetSize(image->size()); + + // Image events may arrive out of sequence because some images + // load faster than others, so we ensure they are inserted + // in the intended order + if (number > 0) + { + // Debugging + if (m_Images.value(number)) + { + // There should be no image that this location, if + // we find one then something is wrong. + VERBOSE(VB_IMPORTANT, QString("DEBUG Image Thread: " + "Found image in m_Images position %1 where " + "there should be none. Filename %2").arg(number) + .arg(filename)); + image->DownRef(); + } + else + { + //m_Images.insert(number, image); + m_Images.push_back(image); + //image->DownRef(); + } + } + else + m_Images.push_back(image); + + SetRedraw(); + m_LastDisplay = QTime::currentTime(); + } + else + { + VERBOSE(VB_IMPORTANT, QString("Mis-Match File: %1 Not: %2") + .arg(filename).arg(m_Filename)); + image->DownRef(); + } + } + } +} Index: mythtv/libs/libmythui/mythuiimage.h =================================================================== --- mythtv/libs/libmythui/mythuiimage.h (revision 21272) +++ mythtv/libs/libmythui/mythuiimage.h (working copy) @@ -7,8 +7,9 @@ #include "mythimage.h" class MythScreenType; +class ImageLoadThread; -/** +/*! * \class MythUIImage * * \brief Image widget, displays a single image or multiple images in sequence @@ -57,6 +58,8 @@ void Init(void); void Clear(void); + MythImage* LoadImage(const QString &imFile, int imageNumber = 0) const; + void customEvent(QEvent *event); virtual bool ParseElement(QDomElement &element); virtual void CopyFrom(MythUIType *base); @@ -70,8 +73,8 @@ void SetCropRect(int x, int y, int width, int height); void SetCropRect(const MythRect &rect); - QString GenImageLabel(const QString &filename, int w, int h); - QString GenImageLabel(int w, int h); + QString GenImageLabel(const QString &filename, int w, int h) const; + QString GenImageLabel(int w, int h) const; QString m_Filename; QString m_OrigFilename; @@ -110,10 +113,13 @@ bool m_isGreyscale; + ImageLoadThread *m_imageLoadThread; + friend class MythThemeBase; friend class MythUIButtonListItem; friend class MythUIProgressBar; friend class MythUITextEdit; + friend class ImageLoadThread; }; #endif