OSDN Git Service

サムネイル生成スレッドの改良
authorMasayuki Satoh <miyabi.satoh@gmail.com>
Mon, 15 Sep 2014 00:44:54 +0000 (09:44 +0900)
committerMasayuki Satoh <miyabi.satoh@gmail.com>
Mon, 15 Sep 2014 00:44:54 +0000 (09:44 +0900)
foldermodel.cpp
foldermodel.h
thumbnailworker.cpp
thumbnailworker.h

index 43565f6..2badaf2 100644 (file)
@@ -4,10 +4,9 @@
 #include "win32.h"\r
 #include "foldermodel.h"\r
 \r
+#include <QApplication>\r
 #include <QDateTime>\r
 #include <QDebug>\r
-#include <QApplication>\r
-#include <QSettings>\r
 #include <QPalette>\r
 #include <QThread>\r
 \r
@@ -28,25 +27,47 @@ FolderModel::FolderModel(QObject *parent) :
     m_fsWatcher(this),\r
     m_history(),\r
     m_historyPos(-1),\r
+    m_worker(),\r
     m_pixmapCache(),\r
     m_pixmapCacheMutex(),\r
     m_Palette(),\r
     m_font()\r
 {\r
+    // サムネイル生成用スレッドを初期化する\r
+    QThread *thread = new QThread();\r
+    m_worker = new ThumbnailWorker();\r
+    m_worker->moveToThread(thread);\r
+    connect(m_worker, SIGNAL(resultReady(QString,QPixmap)), this, SLOT(thumbnail_Ready(QString,QPixmap)));\r
+    connect(m_worker, SIGNAL(finished()), thread, SLOT(quit()));\r
+    connect(m_worker, SIGNAL(finished()), m_worker, SLOT(deleteLater()));\r
+    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));\r
+    connect(thread, SIGNAL(started()), m_worker, SLOT(doWork()));\r
+    thread->start();\r
+\r
     connect(&m_fsWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(fsWatcher_directoryChanged(QString)));\r
 }\r
 \r
 ///////////////////////////////////////////////////////////////////////////////\r
+/// \brief FolderModel::~FolderModel\r
+///\r
+/// デストラクタ\r
+///\r
+FolderModel::~FolderModel()\r
+{\r
+    m_worker->finish();\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
 /// \brief FolderModel::clearPixmapCache\r
 ///\r
-/// サムネイルキャッシュをクリアします。\r
+/// ã\82µã\83 ã\83\8dã\82¤ã\83«ã\82­ã\83£ã\83\83ã\82·ã\83¥ã\82\92ã\82¯ã\83ªã\82¢ã\81\97ã\81\9fã\82\88ã\81\86ã\81«è¦\8bã\81\9bã\81\8bã\81\91ã\81¾ã\81\99ã\80\82\r
 ///\r
 void FolderModel::clearPixmapCache()\r
 {\r
     beginResetModel();\r
-    m_pixmapCacheMutex.lock();\r
-    m_pixmapCache.clear();\r
-    m_pixmapCacheMutex.unlock();\r
+//    m_pixmapCacheMutex.lock();\r
+//    m_pixmapCache.clear();\r
+//    m_pixmapCacheMutex.unlock();\r
     endResetModel();\r
 }\r
 \r
@@ -136,22 +157,14 @@ QPixmap FolderModel::pixmap(const QModelIndex &index, const QSize &size) const
     const_cast<FolderModel*>(this)->m_pixmapCacheMutex.unlock();\r
 \r
     if (!pixmap.isNull()) {\r
-        return pixmap;\r
+        double scaleX = 1.0 * size.width() / pixmap.width();\r
+        double scaleY = 1.0 * size.height() / pixmap.height();\r
+        double scaleFactor = (scaleX > scaleY) ? scaleY : scaleX;\r
+        return pixmap.scaled(pixmap.size() * scaleFactor,\r
+                             Qt::IgnoreAspectRatio,\r
+                             Qt::SmoothTransformation);\r
     }\r
 \r
-    // 別スレッドでサムネイルを生成する\r
-    QThread *thread = new QThread();\r
-    ThumbnailWorker *worker = new ThumbnailWorker();\r
-    worker->setPath(filePath(index));\r
-    worker->setSize(size);\r
-    worker->moveToThread(thread);\r
-    connect(worker, SIGNAL(resultReady(QString,QPixmap)), this, SLOT(thumbnail_Ready(QString,QPixmap)));\r
-    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));\r
-    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));\r
-    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));\r
-    connect(thread, SIGNAL(started()), worker, SLOT(doWork()));\r
-    thread->start();\r
-\r
     // とりあえずアイコンを返す。\r
     return fileIcon(index).pixmap(32, 32);\r
 }\r
@@ -236,6 +249,7 @@ void FolderModel::setRootPath(const QString &path, bool addHistory)
                 m_history << m_dir.absolutePath();\r
                 m_historyPos = m_history.size() - 1;\r
             }\r
+            m_worker->clearPath();\r
             m_pixmapCacheMutex.lock();\r
             m_pixmapCache.clear();\r
             m_pixmapCacheMutex.unlock();\r
@@ -257,6 +271,7 @@ void FolderModel::setRootPath(const QString &path, bool addHistory)
             m_fileInfoList << fi;\r
             if (m_checkStates.find(fi.fileName()) == m_checkStates.end()) {\r
                 m_checkStates[fi.fileName()] = Qt::Unchecked;\r
+                m_worker->addPath(fi.absoluteFilePath());\r
             }\r
         }\r
     }\r
index 23ddf3e..df253e4 100644 (file)
@@ -10,6 +10,7 @@
 #include <QMutex>\r
 #include <QPalette>\r
 class Preferences;\r
+class ThumbnailWorker;\r
 \r
 class FolderModel : public QAbstractTableModel\r
 {\r
@@ -25,6 +26,7 @@ public:
     typedef QVector<QString> History;\r
 \r
     explicit FolderModel(QObject *parent = 0);\r
+    ~FolderModel();\r
 \r
     void            clearPixmapCache();\r
     QString         error() const;\r
@@ -87,6 +89,7 @@ private:
     QFileSystemWatcher  m_fsWatcher;\r
     History             m_history;\r
     int                 m_historyPos;\r
+    ThumbnailWorker*    m_worker;\r
     PixmapContainer     m_pixmapCache;\r
     QMutex              m_pixmapCacheMutex;\r
     QPalette            m_Palette;\r
index 497577b..cda15e7 100644 (file)
@@ -1,28 +1,70 @@
 #include "thumbnailworker.h"
 
+#include <QTimer>
+#include <QThread>
+
 ThumbnailWorker::ThumbnailWorker(QObject *parent) :
-    QObject(parent)
+    QObject(parent),
+    m_mutex(),
+    m_pathList(),
+    m_loop(true)
 {
 }
 
-void ThumbnailWorker::doWork()
+void ThumbnailWorker::addPath(const QString &path)
+{
+    QMutexLocker locker(&m_mutex);
+    m_pathList << path;
+}
+
+void ThumbnailWorker::clearPath()
+{
+    QMutexLocker locker(&m_mutex);
+    m_pathList.clear();
+}
+
+void ThumbnailWorker::finish()
 {
-    QPixmap pixmap(m_path);
-    if (pixmap.isNull()) {
-        emit finished();
-        return;
+    QMutexLocker locker(&m_mutex);
+    m_loop = false;
+}
+
+QString ThumbnailWorker::getPath()
+{
+    QMutexLocker locker(&m_mutex);
+    if (m_pathList.isEmpty()) {
+        return QString();
     }
+    return m_pathList.takeFirst();
+}
 
-    if (pixmap.width() > m_size.width() || pixmap.height() > m_size.height()) {
-        double scaleX = 1.0 * m_size.width() / pixmap.width();
-        double scaleY = 1.0 * m_size.height() / pixmap.height();
-        double scaleFactor = (scaleX > scaleY) ? scaleY : scaleX;
+bool ThumbnailWorker::loop()
+{
+    QMutexLocker locker(&m_mutex);
+    return m_loop;
+}
 
-        pixmap = pixmap.scaled(pixmap.size() * scaleFactor,
-                               Qt::IgnoreAspectRatio,
-                               Qt::SmoothTransformation);
+void ThumbnailWorker::doWork()
+{
+    while (loop()) {
+        QString path = getPath();
+        if (path.isEmpty()) {
+            QThread::sleep(1);
+        }
+        else {
+            QPixmap pixmap(path);
+            if (!pixmap.isNull()) {
+                QSize size(256, 256);
+                double scaleX = 1.0 * size.width() / pixmap.width();
+                double scaleY = 1.0 * size.height() / pixmap.height();
+                double scaleFactor = (scaleX > scaleY) ? scaleY : scaleX;
+                pixmap = pixmap.scaled(pixmap.size() * scaleFactor,
+                                       Qt::IgnoreAspectRatio,
+                                       Qt::SmoothTransformation);
+                emit resultReady(path, pixmap);
+            }
+        }
     }
 
-    emit resultReady(m_path, pixmap);
     emit finished();
 }
index 2f1e813..1e1b178 100644 (file)
@@ -2,6 +2,7 @@
 #define THUMBNAILWORKER_H
 
 #include <QObject>
+#include <QMutex>
 #include <QSize>
 #include <QPixmap>
 
@@ -11,12 +12,17 @@ class ThumbnailWorker : public QObject
 public:
     explicit ThumbnailWorker(QObject *parent = 0);
 
-    void    setPath(const QString &path) { m_path = path; }
-    void    setSize(const QSize &size) { m_size = size; }
+    void    addPath(const QString &path);
+    void    clearPath();
+    void    finish();
 
 private:
-    QString m_path;
-    QSize m_size;
+    QMutex      m_mutex;
+    QStringList m_pathList;
+    bool        m_loop;
+
+    QString     getPath();
+    bool        loop();
 
 signals:
     void    finished();