All pastes #1529959 Raw Edit

Miscellany

public text v1 · immutable
#1529959 ·published 2009-08-14 22:10 UTC
rendered paste body
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 <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