rendered paste bodyIndex: mythtv/libs/libmythui/mythuiimage.cpp
===================================================================
--- mythtv/libs/libmythui/mythuiimage.cpp (revision 21272)
+++ mythtv/libs/libmythui/mythuiimage.cpp (working copy)
@@ -1,18 +1,78 @@
#include <cstdlib>
+// Mythui
+#include "mythuiimage.h"
+#include "mythpainter.h"
+#include "mythmainwindow.h"
+#include "mythuihelper.h"
+#include "mythscreentype.h"
+
+// QT
#include <QFile>
#include <QDir>
#include <QDomDocument>
#include <QImageReader>
+#include <QThread>
+#include <QEvent>
+#include <QCoreApplication>
+// 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<ImageLoadEvent*>(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