mirror of
https://github.com/libretro/RetroArch
synced 2025-03-03 04:14:00 +00:00
Merge pull request #8080 from CozmoP/thumbnail
Qt: Allow changing thumbnails by drag and drop.
This commit is contained in:
commit
997cd88c95
@ -130,18 +130,25 @@ void PlaylistModel::setThumbnailCacheLimit(int limit)
|
||||
|
||||
QString PlaylistModel::getThumbnailPath(const QModelIndex &index, QString type) const
|
||||
{
|
||||
return getThumbnailPath(m_contents.at(index.row()), type);
|
||||
}
|
||||
|
||||
QString PlaylistModel::getPlaylistThumbnailsDir(const QString playlistName) const
|
||||
{
|
||||
return QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + playlistName;
|
||||
}
|
||||
|
||||
bool PlaylistModel::isSupportedImage(const QString path) const
|
||||
{
|
||||
int lastIndex = -1;
|
||||
QByteArray extension;
|
||||
QString extensionStr;
|
||||
|
||||
QString thumbnailFileNameNoExt;
|
||||
int lastIndex = -1;
|
||||
|
||||
const QHash<QString, QString> &hash = m_contents.at(index.row());
|
||||
lastIndex = hash["path"].lastIndexOf('.');
|
||||
lastIndex = path.lastIndexOf('.');
|
||||
|
||||
if (lastIndex >= 0)
|
||||
{
|
||||
extensionStr = hash["path"].mid(lastIndex + 1);
|
||||
extensionStr = path.mid(lastIndex + 1);
|
||||
|
||||
if (!extensionStr.isEmpty())
|
||||
{
|
||||
@ -150,15 +157,26 @@ QString PlaylistModel::getThumbnailPath(const QModelIndex &index, QString type)
|
||||
}
|
||||
|
||||
if (!extension.isEmpty() && m_imageFormats.contains(extension))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString PlaylistModel::getSanitizedThumbnailName(QString label) const
|
||||
{
|
||||
return label.replace(m_fileSanitizerRegex, "_") + ".png";
|
||||
}
|
||||
|
||||
QString PlaylistModel::getThumbnailPath(const QHash<QString, QString> &hash, QString type) const
|
||||
{
|
||||
if (isSupportedImage(hash["path"]))
|
||||
{
|
||||
/* use thumbnail widgets to show regular image files */
|
||||
return hash["path"];
|
||||
}
|
||||
else
|
||||
{
|
||||
thumbnailFileNameNoExt = hash["label_noext"];
|
||||
thumbnailFileNameNoExt.replace(m_fileSanitizerRegex, "_");
|
||||
return QDir::cleanPath(QString(config_get_ptr()->paths.directory_thumbnails)) + "/" + hash.value("db_name") + "/" + type + "/" + thumbnailFileNameNoExt + ".png";
|
||||
return getPlaylistThumbnailsDir(hash.value("db_name")) + "/" + type + "/" + getSanitizedThumbnailName(hash["label_noext"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
,m_thumbnailPixmap(NULL)
|
||||
,m_thumbnailPixmap2(NULL)
|
||||
,m_thumbnailPixmap3(NULL)
|
||||
,m_fileSanitizerRegex("[&*/:`<>?\\|]")
|
||||
,m_settings(NULL)
|
||||
,m_viewOptionsDialog(NULL)
|
||||
,m_coreInfoDialog(new CoreInfoDialog(this, NULL))
|
||||
@ -1265,6 +1264,108 @@ void MainWindow::changeThumbnailType(ThumbnailType type)
|
||||
m_gridView->viewport()->update();
|
||||
}
|
||||
|
||||
QString MainWindow::changeThumbnail(const QImage &image, QString type)
|
||||
{
|
||||
QHash<QString, QString> hash = getCurrentContentHash();
|
||||
QString dirString = m_playlistModel->getPlaylistThumbnailsDir(hash["db_name"]) + "/" + type;
|
||||
QString thumbPath = dirString + "/" + m_playlistModel->getSanitizedThumbnailName(hash["label_noext"]);
|
||||
QByteArray dirArray = QDir::toNativeSeparators(dirString).toUtf8();
|
||||
const char *dirData = dirArray.constData();
|
||||
QByteArray thumbArray = QDir::toNativeSeparators(thumbPath).toUtf8();
|
||||
const char *thumbData = thumbArray.constData();
|
||||
QDir dir(dirString);
|
||||
int quality = -1;
|
||||
QImage scaledImage(image);
|
||||
|
||||
if (!dir.exists())
|
||||
{
|
||||
if (dir.mkpath("."))
|
||||
RARCH_LOG("[Qt]: Created directory: %s\n", dirData);
|
||||
else
|
||||
{
|
||||
RARCH_ERR("[Qt]: Could not create directory: %s\n", dirData);
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_settings->contains("thumbnail_max_size"))
|
||||
{
|
||||
int size = m_settings->value("thumbnail_max_size", 512).toInt();
|
||||
|
||||
if (size != 0)
|
||||
scaledImage = image.scaled(size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
if (m_settings->contains("thumbnail_quality"))
|
||||
quality = m_settings->value("thumbnail_quality", -1).toInt();
|
||||
|
||||
if (scaledImage.save(thumbPath, "png", quality))
|
||||
{
|
||||
RARCH_LOG("[Qt]: Saved image: %s\n", thumbData);
|
||||
m_playlistModel->reloadThumbnailPath(thumbPath);
|
||||
updateVisibleItems();
|
||||
|
||||
return thumbPath;
|
||||
}
|
||||
|
||||
RARCH_ERR("[Qt]: Could not save image: %s\n", thumbData);
|
||||
return QString();
|
||||
}
|
||||
|
||||
void MainWindow::onThumbnailDropped(const QImage &image, ThumbnailType thumbnailType)
|
||||
{
|
||||
switch (thumbnailType)
|
||||
{
|
||||
case THUMBNAIL_TYPE_BOXART:
|
||||
{
|
||||
QString path = changeThumbnail(image, THUMBNAIL_BOXART);
|
||||
|
||||
if (path.isNull())
|
||||
return;
|
||||
|
||||
if (m_thumbnailPixmap)
|
||||
delete m_thumbnailPixmap;
|
||||
|
||||
m_thumbnailPixmap = new QPixmap(path);
|
||||
|
||||
onResizeThumbnailOne();
|
||||
break;
|
||||
}
|
||||
|
||||
case THUMBNAIL_TYPE_TITLE_SCREEN:
|
||||
{
|
||||
QString path = changeThumbnail(image, THUMBNAIL_TITLE);
|
||||
|
||||
if (path.isNull())
|
||||
return;
|
||||
|
||||
if (m_thumbnailPixmap2)
|
||||
delete m_thumbnailPixmap2;
|
||||
|
||||
m_thumbnailPixmap2 = new QPixmap(path);
|
||||
|
||||
onResizeThumbnailTwo();
|
||||
break;
|
||||
}
|
||||
|
||||
case THUMBNAIL_TYPE_SCREENSHOT:
|
||||
{
|
||||
QString path = changeThumbnail(image, THUMBNAIL_SCREENSHOT);
|
||||
|
||||
if (path.isNull())
|
||||
return;
|
||||
|
||||
if (m_thumbnailPixmap3)
|
||||
delete m_thumbnailPixmap3;
|
||||
|
||||
m_thumbnailPixmap3 = new QPixmap(path);
|
||||
|
||||
onResizeThumbnailThree();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QHash<QString, QString> > MainWindow::getCoreInfo()
|
||||
{
|
||||
QVector<QHash<QString, QString> > infoList;
|
||||
@ -2107,6 +2208,22 @@ void MainWindow::setCoreActions()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setThumbnailsAcceptDrops(bool accept)
|
||||
{
|
||||
ThumbnailWidget *thumbnail = findChild<ThumbnailWidget*>("thumbnail1Widget");
|
||||
ThumbnailWidget *thumbnail2 = findChild<ThumbnailWidget*>("thumbnail2Widget");
|
||||
ThumbnailWidget *thumbnail3 = findChild<ThumbnailWidget*>("thumbnail3Widget");
|
||||
|
||||
if (thumbnail)
|
||||
thumbnail->setAcceptDrops(accept);
|
||||
|
||||
if (thumbnail2)
|
||||
thumbnail2->setAcceptDrops(accept);
|
||||
|
||||
if (thumbnail3)
|
||||
thumbnail3->setAcceptDrops(accept);
|
||||
}
|
||||
|
||||
void MainWindow::onTabWidgetIndexChanged(int index)
|
||||
{
|
||||
if (m_browserAndPlaylistTabWidget->tabText(index) == msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_TAB_FILE_BROWSER))
|
||||
@ -2394,29 +2511,7 @@ void MainWindow::onCurrentFileChanged(const QModelIndex &index)
|
||||
|
||||
void MainWindow::onCurrentItemChanged(const QHash<QString, QString> &hash)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
QString label;
|
||||
QString playlist_name;
|
||||
QByteArray extension;
|
||||
QString extensionStr;
|
||||
int lastIndex = -1;
|
||||
|
||||
label = hash["label_noext"];
|
||||
label.replace(m_fileSanitizerRegex, "_");
|
||||
|
||||
lastIndex = hash["path"].lastIndexOf('.');
|
||||
|
||||
if (lastIndex >= 0)
|
||||
{
|
||||
extensionStr = hash["path"].mid(lastIndex + 1);
|
||||
|
||||
if (!extensionStr.isEmpty())
|
||||
{
|
||||
extension = extensionStr.toLower().toUtf8();
|
||||
}
|
||||
}
|
||||
|
||||
playlist_name = hash["db_name"];
|
||||
QString path = hash["path"];
|
||||
|
||||
if (m_thumbnailPixmap)
|
||||
delete m_thumbnailPixmap;
|
||||
@ -2425,18 +2520,31 @@ void MainWindow::onCurrentItemChanged(const QHash<QString, QString> &hash)
|
||||
if (m_thumbnailPixmap3)
|
||||
delete m_thumbnailPixmap3;
|
||||
|
||||
if (!extension.isEmpty() && m_imageFormats.contains(extension))
|
||||
if (m_playlistModel->isSupportedImage(path))
|
||||
{
|
||||
/* use thumbnail widgets to show regular image files */
|
||||
m_thumbnailPixmap = new QPixmap(hash["path"]);
|
||||
m_thumbnailPixmap = new QPixmap(path);
|
||||
m_thumbnailPixmap2 = new QPixmap(*m_thumbnailPixmap);
|
||||
m_thumbnailPixmap3 = new QPixmap(*m_thumbnailPixmap);
|
||||
|
||||
setThumbnailsAcceptDrops(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_thumbnailPixmap = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_BOXART + "/" + label + ".png");
|
||||
m_thumbnailPixmap2 = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_TITLE + "/" + label + ".png");
|
||||
m_thumbnailPixmap3 = new QPixmap(QString(settings->paths.directory_thumbnails) + "/" + playlist_name + "/" + THUMBNAIL_SCREENSHOT + "/" + label + ".png");
|
||||
QString thumbnailsDir = m_playlistModel->getPlaylistThumbnailsDir(hash["db_name"]);
|
||||
QString thumbnailName = m_playlistModel->getSanitizedThumbnailName(hash["label_noext"]);
|
||||
|
||||
m_thumbnailPixmap = new QPixmap(thumbnailsDir + "/" + THUMBNAIL_BOXART + "/" + thumbnailName);
|
||||
m_thumbnailPixmap2 = new QPixmap(thumbnailsDir + "/" + THUMBNAIL_TITLE + "/" + thumbnailName);
|
||||
m_thumbnailPixmap3 = new QPixmap(thumbnailsDir + "/" + THUMBNAIL_SCREENSHOT + "/" + thumbnailName);
|
||||
|
||||
if (m_currentBrowser == BROWSER_TYPE_PLAYLISTS)
|
||||
{
|
||||
if (currentPlaylistIsSpecial())
|
||||
setThumbnailsAcceptDrops(false);
|
||||
else
|
||||
setThumbnailsAcceptDrops(true);
|
||||
}
|
||||
}
|
||||
|
||||
resizeThumbnails(true, true, true);
|
||||
|
@ -63,9 +63,10 @@ typedef struct ui_companion_qt
|
||||
ui_window_qt_t *window;
|
||||
} ui_companion_qt_t;
|
||||
|
||||
ThumbnailWidget::ThumbnailWidget(QWidget *parent) :
|
||||
ThumbnailWidget::ThumbnailWidget(ThumbnailType type, QWidget *parent) :
|
||||
QFrame(parent)
|
||||
,m_sizeHint(QSize(256, 256))
|
||||
,m_thumbnailType(type)
|
||||
{
|
||||
}
|
||||
|
||||
@ -111,6 +112,40 @@ void ThumbnailWidget::setSizeHint(QSize size)
|
||||
m_sizeHint = size;
|
||||
}
|
||||
|
||||
void ThumbnailWidget::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
const QMimeData *data = event->mimeData();
|
||||
|
||||
if (data->hasUrls())
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
/* Workaround for QTBUG-72844. Without it, you can't drop on this if you first drag over another widget that doesn't accept drops. */
|
||||
void ThumbnailWidget::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void ThumbnailWidget::dropEvent(QDropEvent *event)
|
||||
{
|
||||
const QMimeData *data = event->mimeData();
|
||||
|
||||
if (data->hasUrls())
|
||||
{
|
||||
const QString imageString = data->urls().at(0).toLocalFile();
|
||||
const QImage image(imageString);
|
||||
|
||||
if (!image.isNull())
|
||||
emit(filesDropped(image, m_thumbnailType));
|
||||
else
|
||||
{
|
||||
QByteArray stringArray = QDir::toNativeSeparators(imageString).toUtf8();
|
||||
const char *stringData = stringArray.constData();
|
||||
RARCH_ERR("[Qt]: Could not read image: %s\n", stringData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThumbnailLabel::ThumbnailLabel(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
,m_pixmap(NULL)
|
||||
@ -403,9 +438,14 @@ static void* ui_companion_qt_init(void)
|
||||
|
||||
browserButtonsHBoxLayout->addItem(new QSpacerItem(browserAndPlaylistTabWidget->tabBar()->width(), 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||
|
||||
thumbnailWidget = new ThumbnailWidget();
|
||||
thumbnail2Widget = new ThumbnailWidget();
|
||||
thumbnail3Widget = new ThumbnailWidget();
|
||||
thumbnailWidget = new ThumbnailWidget(THUMBNAIL_TYPE_BOXART);
|
||||
thumbnailWidget->setObjectName("thumbnail1Widget");
|
||||
|
||||
thumbnail2Widget = new ThumbnailWidget(THUMBNAIL_TYPE_TITLE_SCREEN);
|
||||
thumbnail2Widget->setObjectName("thumbnail2Widget");
|
||||
|
||||
thumbnail3Widget = new ThumbnailWidget(THUMBNAIL_TYPE_SCREENSHOT);
|
||||
thumbnail3Widget->setObjectName("thumbnail3Widget");
|
||||
|
||||
thumbnailWidget->setLayout(new QVBoxLayout());
|
||||
thumbnail2Widget->setLayout(new QVBoxLayout());
|
||||
@ -415,6 +455,10 @@ static void* ui_companion_qt_init(void)
|
||||
thumbnail2Widget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
thumbnail3Widget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
|
||||
QObject::connect(thumbnailWidget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType)));
|
||||
QObject::connect(thumbnail2Widget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType)));
|
||||
QObject::connect(thumbnail3Widget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType)));
|
||||
|
||||
thumbnail = new ThumbnailLabel();
|
||||
thumbnail->setObjectName("thumbnail");
|
||||
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <QCache>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QDir>
|
||||
#include <QStackedWidget>
|
||||
|
||||
#include "qt/filedropwidget.h"
|
||||
|
||||
@ -143,6 +142,9 @@ public:
|
||||
void reloadThumbnailPath(const QString path);
|
||||
void reloadSystemThumbnails(const QString system);
|
||||
void setThumbnailCacheLimit(int limit);
|
||||
bool isSupportedImage(const QString path) const;
|
||||
QString getPlaylistThumbnailsDir(const QString playlistName) const;
|
||||
QString getSanitizedThumbnailName(QString label) const;
|
||||
|
||||
signals:
|
||||
void imageLoaded(const QImage image, const QModelIndex &index, const QString &path);
|
||||
@ -158,6 +160,7 @@ private:
|
||||
QRegularExpression m_fileSanitizerRegex;
|
||||
ThumbnailType m_thumbnailType = THUMBNAIL_TYPE_BOXART;
|
||||
QString getThumbnailPath(const QModelIndex &index, QString type) const;
|
||||
QString getThumbnailPath(const QHash<QString, QString> &hash, QString type) const;
|
||||
QString getCurrentTypeThumbnailPath(const QModelIndex &index) const;
|
||||
void getPlaylistItems(QString path);
|
||||
void loadImage(const QModelIndex &index, const QString &path);
|
||||
@ -168,6 +171,7 @@ class ThumbnailWidget : public QFrame
|
||||
Q_OBJECT
|
||||
public:
|
||||
ThumbnailWidget(QWidget *parent = 0);
|
||||
ThumbnailWidget(ThumbnailType type, QWidget *parent = 0);
|
||||
ThumbnailWidget(const ThumbnailWidget& other) { retro_assert(false && "DONT EVER USE THIS"); }
|
||||
|
||||
QSize sizeHint() const;
|
||||
@ -175,13 +179,18 @@ public:
|
||||
signals:
|
||||
void mouseDoubleClicked();
|
||||
void mousePressed();
|
||||
void filesDropped(const QImage& image, ThumbnailType type);
|
||||
private:
|
||||
QSize m_sizeHint;
|
||||
ThumbnailType m_thumbnailType;
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
};
|
||||
|
||||
class ThumbnailLabel : public QWidget
|
||||
@ -457,6 +466,7 @@ public slots:
|
||||
void downloadPlaylistThumbnails(QString playlistPath);
|
||||
void downloadNextPlaylistThumbnail(QString system, QString title, QString type, QUrl url = QUrl());
|
||||
void changeThumbnailType(ThumbnailType type);
|
||||
void onThumbnailDropped(const QImage &image, ThumbnailType type);
|
||||
|
||||
private slots:
|
||||
void onLoadCoreClicked(const QStringList &extensionFilters = QStringList());
|
||||
@ -540,6 +550,8 @@ private:
|
||||
bool currentPlaylistIsAll();
|
||||
void applySearch();
|
||||
void updateItemsCount();
|
||||
void setThumbnailsAcceptDrops(bool accept);
|
||||
QString changeThumbnail(const QImage &image, QString type);
|
||||
|
||||
PlaylistModel *m_playlistModel;
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
@ -571,7 +583,6 @@ private:
|
||||
QPixmap *m_thumbnailPixmap;
|
||||
QPixmap *m_thumbnailPixmap2;
|
||||
QPixmap *m_thumbnailPixmap3;
|
||||
QRegularExpression m_fileSanitizerRegex;
|
||||
QSettings *m_settings;
|
||||
ViewOptionsDialog *m_viewOptionsDialog;
|
||||
CoreInfoDialog *m_coreInfoDialog;
|
||||
|
Loading…
x
Reference in New Issue
Block a user