From a18219d77d279710cf5e9eee127c7a41dfc6128b Mon Sep 17 00:00:00 2001 From: Masayuki Satoh Date: Sun, 14 Sep 2014 22:29:03 +0900 Subject: [PATCH] =?utf8?q?=E3=82=B5=E3=83=A0=E3=83=8D=E3=82=A4=E3=83=AB?= =?utf8?q?=E7=94=9F=E6=88=90=E3=82=92=E5=88=A5=E3=82=B9=E3=83=AC=E3=83=83?= =?utf8?q?=E3=83=89=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- Gefu.pro | 6 +++-- README.md | 2 ++ foldermodel.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++- foldermodel.h | 9 ++++--- folderpanel.ui | 9 +++++++ thumbnaildelegate.cpp | 23 +++-------------- thumbnailworker.cpp | 28 +++++++++++++++++++++ thumbnailworker.h | 29 ++++++++++++++++++++++ 8 files changed, 149 insertions(+), 25 deletions(-) create mode 100644 thumbnailworker.cpp create mode 100644 thumbnailworker.h diff --git a/Gefu.pro b/Gefu.pro index 4476cbb..d62af24 100644 --- a/Gefu.pro +++ b/Gefu.pro @@ -37,7 +37,8 @@ SOURCES += main.cpp\ global.cpp \ win32.cpp \ thumbnailview.cpp \ - thumbnaildelegate.cpp + thumbnaildelegate.cpp \ + thumbnailworker.cpp HEADERS += mainwindow.h \ renamesingledialog.h \ @@ -65,7 +66,8 @@ HEADERS += mainwindow.h \ abstractview.h \ abstractrenamedialog.h \ thumbnailview.h \ - thumbnaildelegate.h + thumbnaildelegate.h \ + thumbnailworker.h FORMS += mainwindow.ui \ renamesingledialog.ui \ diff --git a/README.md b/README.md index 996dc97..19ecaf7 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Gefu is an Experimental File Utility. * 画像ビューアの画質を向上。 * アイコンを変更。 * フォルダビューの列ヘッダーを削除。 + * 単画面モードを実装。 + * サムネイルモードを実装。 #### 2014/08/31 Ver0.20 * ウィンドウ自体が非アクティブになったとき、両パネルとも暗くなっていたのを修正。 diff --git a/foldermodel.cpp b/foldermodel.cpp index 9d881ef..4f7fbec 100644 --- a/foldermodel.cpp +++ b/foldermodel.cpp @@ -1,5 +1,6 @@ #include "global.h" #include "preferences.h" +#include "thumbnailworker.h" #include "win32.h" #include "foldermodel.h" @@ -8,6 +9,7 @@ #include #include #include +#include FolderModel* FolderModel::m_activeModel = NULL; @@ -25,7 +27,9 @@ FolderModel::FolderModel(QObject *parent) : m_IconProvider(), m_fsWatcher(this), m_history(), - m_historyPos(-1) + m_historyPos(-1), + m_pixmapCache(), + m_pixmapCacheMutex() { connect(&m_fsWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(fsWatcher_directoryChanged(QString))); } @@ -101,6 +105,42 @@ QModelIndex FolderModel::mkdir(const QString &name) } /////////////////////////////////////////////////////////////////////////////// +/// \brief FolderModel::pixmap +/// \param index アイテムのインデックス +/// \param size 要求サイズ +/// \return 画像またはアイコンを返します。 +/// +QPixmap FolderModel::pixmap(const QModelIndex &index, const QSize &size) const +{ + QPixmap pixmap; + const_cast(this)->m_pixmapCacheMutex.lock(); + if (m_pixmapCache.find(filePath(index)) != m_pixmapCache.end()) { + pixmap = m_pixmapCache[filePath(index)]; + } + const_cast(this)->m_pixmapCacheMutex.unlock(); + + if (!pixmap.isNull()) { + return pixmap; + } + + // 別スレッドでサムネイルを生成する + QThread *thread = new QThread(); + ThumbnailWorker *worker = new ThumbnailWorker(); + worker->setPath(filePath(index)); + worker->setSize(size); + worker->moveToThread(thread); + connect(worker, SIGNAL(resultReady(QString,QPixmap)), this, SLOT(thumbnail_Ready(QString,QPixmap))); + connect(worker, SIGNAL(finished()), thread, SLOT(quit())); + connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + connect(thread, SIGNAL(started()), worker, SLOT(doWork())); + thread->start(); + + // とりあえずアイコンを返す。 + return fileIcon(index).pixmap(32, 32); +} + +/////////////////////////////////////////////////////////////////////////////// /// \brief FolderModel::search /// \param value 検索する文字列 /// \param start 開始位置 @@ -180,6 +220,10 @@ void FolderModel::setRootPath(const QString &path, bool addHistory) m_history << m_dir.absolutePath(); m_historyPos = m_history.size() - 1; } + + m_pixmapCacheMutex.lock(); + m_pixmapCache.clear(); + m_pixmapCacheMutex.unlock(); } foreach (const QFileInfo &fi, list) { @@ -364,6 +408,28 @@ void FolderModel::onMarkInvert() emit dataChanged(index(0, 0), index(rowCount(), columnCount())); } +/////////////////////////////////////////////////////////////////////////////// +/// \brief FolderModel::thumbnail_Ready +/// \param path ファイルパス +/// \param pixmap サムネイル画像 +/// +/// サムネイルの生成終了時の処理を行います。 +/// +void FolderModel::thumbnail_Ready(const QString &path, const QPixmap &pixmap) +{ + QFileInfo fi(path); + if (fi.absolutePath() == m_dir.absolutePath()) { + m_pixmapCacheMutex.lock(); + m_pixmapCache[path] = pixmap; + m_pixmapCacheMutex.unlock(); + + QModelIndex index = search(fi.fileName()); + if (index.isValid()) { + emit dataChanged(index, index); + } + } +} + int FolderModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); diff --git a/foldermodel.h b/foldermodel.h index 15b0e56..1e36bbf 100644 --- a/foldermodel.h +++ b/foldermodel.h @@ -38,6 +38,7 @@ public: QFileInfoList markedItems() const; QModelIndex mkdir(const QString &name); QStringList nameFilters() const; + QPixmap pixmap(const QModelIndex &index, const QSize &size) const; QString rootPath() const; QModelIndex search(const QString &value, const QModelIndex &start = QModelIndex(), int step = 1); void setActive(); @@ -54,6 +55,7 @@ public: signals: public slots: + void fsWatcher_directoryChanged(const QString &path); void onCdHome(); void onCdRoot(); void onCdUp(); @@ -64,14 +66,13 @@ public slots: void onMarkAllOff(); void onMarkInvert(); void refresh(); - -private slots: - void fsWatcher_directoryChanged(const QString &path); + void thumbnail_Ready(const QString &path, const QPixmap &pixmap); private: static FolderModel* m_activeModel; typedef QMap CheckContainer; + typedef QMap PixmapContainer; QString m_error; QDir m_dir; @@ -81,6 +82,8 @@ private: QFileSystemWatcher m_fsWatcher; History m_history; int m_historyPos; + PixmapContainer m_pixmapCache; + QMutex m_pixmapCacheMutex; bool isDotFile(const QModelIndex &index) const; void setError(const QString &error = QString()); diff --git a/folderpanel.ui b/folderpanel.ui index d58c939..4c21d0d 100644 --- a/folderpanel.ui +++ b/folderpanel.ui @@ -117,9 +117,18 @@ Qt::ElideMiddle + + QListView::Snap + + + QListView::Adjust + QListView::IconMode + + false + diff --git a/thumbnaildelegate.cpp b/thumbnaildelegate.cpp index fcb79c6..17ae692 100644 --- a/thumbnaildelegate.cpp +++ b/thumbnaildelegate.cpp @@ -14,6 +14,8 @@ ThumbnailDelegate::ThumbnailDelegate(QObject *parent) : void ThumbnailDelegate::model_Reset() { + qDebug() << "ThumbnailDelegate::model_Reset()"; + m_pixmapCache.clear(); } @@ -55,28 +57,11 @@ void ThumbnailDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt // アイコンまたは画像 QSize size(option.rect.size()); size -= padding; - if (m_pixmapCache.find(model->fileName(index)) == m_pixmapCache.end()) { - QPixmap pixmap(model->filePath(index)); - if (pixmap.isNull()) { - pixmap = model->fileIcon(index).pixmap(32, 32); - } - if (pixmap.width() > size.width() || pixmap.height() > size.height()) { - 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); - } - const_cast(this)->m_pixmapCache[model->fileName(index)] = pixmap; - } - const QPixmap &pixmap = m_pixmapCache[model->fileName(index)]; - + QPixmap pixmap = model->pixmap(index, size); painter->drawPixmap(padding.width() + option.rect.left() + (size.width() - pixmap.width()) / 2, option.rect.top() + (size.height() - pixmap.height()) / 2, pixmap); - //QStyledItemDelegate::paint(painter, option, index); } QSize ThumbnailDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const @@ -86,5 +71,5 @@ QSize ThumbnailDelegate::sizeHint(const QStyleOptionViewItem &option, const QMod const FolderModel *model = static_cast(index.model()); int pointSize = model->data(index, Qt::FontRole).value().pointSize(); - return QSize(pointSize * 10, pointSize * 10 * 11 / 16); + return QSize(pointSize * 10, pointSize * 10 * 3 / 4); } diff --git a/thumbnailworker.cpp b/thumbnailworker.cpp new file mode 100644 index 0000000..497577b --- /dev/null +++ b/thumbnailworker.cpp @@ -0,0 +1,28 @@ +#include "thumbnailworker.h" + +ThumbnailWorker::ThumbnailWorker(QObject *parent) : + QObject(parent) +{ +} + +void ThumbnailWorker::doWork() +{ + QPixmap pixmap(m_path); + if (pixmap.isNull()) { + emit finished(); + return; + } + + 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; + + pixmap = pixmap.scaled(pixmap.size() * scaleFactor, + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); + } + + emit resultReady(m_path, pixmap); + emit finished(); +} diff --git a/thumbnailworker.h b/thumbnailworker.h new file mode 100644 index 0000000..2f1e813 --- /dev/null +++ b/thumbnailworker.h @@ -0,0 +1,29 @@ +#ifndef THUMBNAILWORKER_H +#define THUMBNAILWORKER_H + +#include +#include +#include + +class ThumbnailWorker : public QObject +{ + Q_OBJECT +public: + explicit ThumbnailWorker(QObject *parent = 0); + + void setPath(const QString &path) { m_path = path; } + void setSize(const QSize &size) { m_size = size; } + +private: + QString m_path; + QSize m_size; + +signals: + void finished(); + void resultReady(const QString &path, const QPixmap &pixmap); + +public slots: + void doWork(); +}; + +#endif // THUMBNAILWORKER_H -- 2.11.0