global.cpp \
win32.cpp \
thumbnailview.cpp \
- thumbnaildelegate.cpp
+ thumbnaildelegate.cpp \
+ thumbnailworker.cpp
HEADERS += mainwindow.h \
renamesingledialog.h \
abstractview.h \
abstractrenamedialog.h \
thumbnailview.h \
- thumbnaildelegate.h
+ thumbnaildelegate.h \
+ thumbnailworker.h
FORMS += mainwindow.ui \
renamesingledialog.ui \
* 画像ビューアの画質を向上。
* アイコンを変更。
* フォルダビューの列ヘッダーを削除。
+ * 単画面モードを実装。
+ * サムネイルモードを実装。
#### 2014/08/31 Ver0.20
* ウィンドウ自体が非アクティブになったとき、両パネルとも暗くなっていたのを修正。
#include "global.h"\r
#include "preferences.h"\r
+#include "thumbnailworker.h"\r
#include "win32.h"\r
#include "foldermodel.h"\r
\r
#include <QApplication>\r
#include <QSettings>\r
#include <QPalette>\r
+#include <QThread>\r
\r
FolderModel* FolderModel::m_activeModel = NULL;\r
\r
m_IconProvider(),\r
m_fsWatcher(this),\r
m_history(),\r
- m_historyPos(-1)\r
+ m_historyPos(-1),\r
+ m_pixmapCache(),\r
+ m_pixmapCacheMutex()\r
{\r
connect(&m_fsWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(fsWatcher_directoryChanged(QString)));\r
}\r
}\r
\r
///////////////////////////////////////////////////////////////////////////////\r
+/// \brief FolderModel::pixmap\r
+/// \param index アイテムのインデックス\r
+/// \param size 要求サイズ\r
+/// \return 画像またはアイコンを返します。\r
+///\r
+QPixmap FolderModel::pixmap(const QModelIndex &index, const QSize &size) const\r
+{\r
+ QPixmap pixmap;\r
+ const_cast<FolderModel*>(this)->m_pixmapCacheMutex.lock();\r
+ if (m_pixmapCache.find(filePath(index)) != m_pixmapCache.end()) {\r
+ pixmap = m_pixmapCache[filePath(index)];\r
+ }\r
+ const_cast<FolderModel*>(this)->m_pixmapCacheMutex.unlock();\r
+\r
+ if (!pixmap.isNull()) {\r
+ return pixmap;\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
+\r
+///////////////////////////////////////////////////////////////////////////////\r
/// \brief FolderModel::search\r
/// \param value 検索する文字列\r
/// \param start 開始位置\r
m_history << m_dir.absolutePath();\r
m_historyPos = m_history.size() - 1;\r
}\r
+\r
+ m_pixmapCacheMutex.lock();\r
+ m_pixmapCache.clear();\r
+ m_pixmapCacheMutex.unlock();\r
}\r
\r
foreach (const QFileInfo &fi, list) {\r
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));\r
}\r
\r
+///////////////////////////////////////////////////////////////////////////////\r
+/// \brief FolderModel::thumbnail_Ready\r
+/// \param path ファイルパス\r
+/// \param pixmap サムネイル画像\r
+///\r
+/// サムネイルの生成終了時の処理を行います。\r
+///\r
+void FolderModel::thumbnail_Ready(const QString &path, const QPixmap &pixmap)\r
+{\r
+ QFileInfo fi(path);\r
+ if (fi.absolutePath() == m_dir.absolutePath()) {\r
+ m_pixmapCacheMutex.lock();\r
+ m_pixmapCache[path] = pixmap;\r
+ m_pixmapCacheMutex.unlock();\r
+\r
+ QModelIndex index = search(fi.fileName());\r
+ if (index.isValid()) {\r
+ emit dataChanged(index, index);\r
+ }\r
+ }\r
+}\r
+\r
int FolderModel::rowCount(const QModelIndex &parent) const\r
{\r
Q_UNUSED(parent);\r
QFileInfoList markedItems() const;\r
QModelIndex mkdir(const QString &name);\r
QStringList nameFilters() const;\r
+ QPixmap pixmap(const QModelIndex &index, const QSize &size) const;\r
QString rootPath() const;\r
QModelIndex search(const QString &value, const QModelIndex &start = QModelIndex(), int step = 1);\r
void setActive();\r
signals:\r
\r
public slots:\r
+ void fsWatcher_directoryChanged(const QString &path);\r
void onCdHome();\r
void onCdRoot();\r
void onCdUp();\r
void onMarkAllOff();\r
void onMarkInvert();\r
void refresh();\r
-\r
-private slots:\r
- void fsWatcher_directoryChanged(const QString &path);\r
+ void thumbnail_Ready(const QString &path, const QPixmap &pixmap);\r
\r
private:\r
static FolderModel* m_activeModel;\r
\r
typedef QMap<QString, int> CheckContainer;\r
+ typedef QMap<QString, QPixmap> PixmapContainer;\r
\r
QString m_error;\r
QDir m_dir;\r
QFileSystemWatcher m_fsWatcher;\r
History m_history;\r
int m_historyPos;\r
+ PixmapContainer m_pixmapCache;\r
+ QMutex m_pixmapCacheMutex;\r
\r
bool isDotFile(const QModelIndex &index) const;\r
void setError(const QString &error = QString());\r
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
+ <property name="movement">
+ <enum>QListView::Snap</enum>
+ </property>
+ <property name="resizeMode">
+ <enum>QListView::Adjust</enum>
+ </property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
+ <property name="selectionRectVisible">
+ <bool>false</bool>
+ </property>
</widget>
</item>
<item>
void ThumbnailDelegate::model_Reset()
{
+ qDebug() << "ThumbnailDelegate::model_Reset()";
+
m_pixmapCache.clear();
}
// アイコンまたは画像
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<ThumbnailDelegate*>(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
const FolderModel *model = static_cast<const FolderModel*>(index.model());
int pointSize = model->data(index, Qt::FontRole).value<QFont>().pointSize();
- return QSize(pointSize * 10, pointSize * 10 * 11 / 16);
+ return QSize(pointSize * 10, pointSize * 10 * 3 / 4);
}
--- /dev/null
+#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();
+}
--- /dev/null
+#ifndef THUMBNAILWORKER_H
+#define THUMBNAILWORKER_H
+
+#include <QObject>
+#include <QSize>
+#include <QPixmap>
+
+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