Qt: only allow dropping files onto center list/grid view

This commit is contained in:
Brad Parker 2018-07-28 10:39:21 -04:00
parent 489601fadb
commit c883a81c42
3 changed files with 209 additions and 165 deletions

View File

@ -32,6 +32,8 @@
#include <QInputDialog> #include <QInputDialog>
#include <QMimeData> #include <QMimeData>
#include <QProgressDialog> #include <QProgressDialog>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QtConcurrentRun> #include <QtConcurrentRun>
#include "../ui_qt.h" #include "../ui_qt.h"
@ -143,6 +145,40 @@ inline static bool comp_hash_label_key_lower(const QHash<QString, QString> &lhs,
return lhs.value("label").toLower() < rhs.value("label").toLower(); return lhs.value("label").toLower() < rhs.value("label").toLower();
} }
static void addDirectoryFilesToList(QStringList &list, QDir &dir)
{
QStringList dirList = dir.entryList(QStringList(), QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System, QDir::Name);
int i;
for (i = 0; i < dirList.count(); i++)
{
QString path(dir.path() + "/" + dirList.at(i));
QFileInfo fileInfo(path);
if (fileInfo.isDir())
{
QDir fileInfoDir(path);
addDirectoryFilesToList(list, fileInfoDir);
continue;
}
if (fileInfo.isFile())
{
list.append(fileInfo.absoluteFilePath());
}
}
}
/* https://gist.github.com/andrey-str/0f9c7709cbf0c9c49ef9 */
static void setElidedText(QLabel *label, QWidget *clipWidget, int padding, const QString &text)
{
QFontMetrics metrix(label->font());
int width = clipWidget->width() - padding;
QString clippedText = metrix.elidedText(text, Qt::ElideRight, width);
label->setText(clippedText);
}
GridItem::GridItem() : GridItem::GridItem() :
QObject() QObject()
,widget(NULL) ,widget(NULL)
@ -155,15 +191,6 @@ GridItem::GridItem() :
{ {
} }
/* https://gist.github.com/andrey-str/0f9c7709cbf0c9c49ef9 */
static void setElidedText(QLabel *label, QWidget *clipWidget, int padding, const QString &text)
{
QFontMetrics metrix(label->font());
int width = clipWidget->width() - padding;
QString clippedText = metrix.elidedText(text, Qt::ElideRight, width);
label->setText(clippedText);
}
TreeView::TreeView(QWidget *parent) : TreeView::TreeView(QWidget *parent) :
QTreeView(parent) QTreeView(parent)
{ {
@ -183,6 +210,41 @@ void TreeView::selectionChanged(const QItemSelection &selected, const QItemSelec
emit itemsSelected(list); emit itemsSelected(list);
} }
FileDropWidget::FileDropWidget(QWidget *parent) :
QWidget(parent)
{
setAcceptDrops(true);
}
void FileDropWidget::dragEnterEvent(QDragEnterEvent *event)
{
const QMimeData *data = event->mimeData();
if (data->hasUrls())
event->acceptProposedAction();
}
void FileDropWidget::dropEvent(QDropEvent *event)
{
const QMimeData *data = event->mimeData();
if (data->hasUrls())
{
QList<QUrl> urls = data->urls();
QStringList files;
int i;
for (i = 0; i < urls.count(); i++)
{
QString path(urls.at(i).toLocalFile());
files.append(path);
}
emit filesDropped(files);
}
}
TableWidget::TableWidget(QWidget *parent) : TableWidget::TableWidget(QWidget *parent) :
QTableWidget(parent) QTableWidget(parent)
{ {
@ -714,7 +776,7 @@ MainWindow::MainWindow(QWidget *parent) :
,m_gridWidget(new QWidget(this)) ,m_gridWidget(new QWidget(this))
,m_gridScrollArea(new QScrollArea(m_gridWidget)) ,m_gridScrollArea(new QScrollArea(m_gridWidget))
,m_gridItems() ,m_gridItems()
,m_gridLayoutWidget(new QWidget()) ,m_gridLayoutWidget(new FileDropWidget())
,m_zoomSlider(NULL) ,m_zoomSlider(NULL)
,m_lastZoomSliderValue(0) ,m_lastZoomSliderValue(0)
,m_pendingItemUpdates() ,m_pendingItemUpdates()
@ -746,8 +808,6 @@ MainWindow::MainWindow(QWidget *parent) :
qRegisterMetaType<QPointer<ThumbnailWidget> >("ThumbnailWidget"); qRegisterMetaType<QPointer<ThumbnailWidget> >("ThumbnailWidget");
setAcceptDrops(true);
m_gridProgressWidget = new QWidget(); m_gridProgressWidget = new QWidget();
gridProgressLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PROGRESS), m_gridProgressWidget); gridProgressLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PROGRESS), m_gridProgressWidget);
@ -935,6 +995,8 @@ MainWindow::MainWindow(QWidget *parent) :
connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(onZoomValueChanged(int))); connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(onZoomValueChanged(int)));
connect(viewTypeIconsAction, SIGNAL(triggered()), this, SLOT(onIconViewClicked())); connect(viewTypeIconsAction, SIGNAL(triggered()), this, SLOT(onIconViewClicked()));
connect(viewTypeListAction, SIGNAL(triggered()), this, SLOT(onListViewClicked())); connect(viewTypeListAction, SIGNAL(triggered()), this, SLOT(onListViewClicked()));
connect(m_tableWidget, SIGNAL(filesDropped(QStringList)), this, SLOT(onPlaylistFilesDropped(QStringList)));
connect(m_gridLayoutWidget, SIGNAL(filesDropped(QStringList)), this, SLOT(onPlaylistFilesDropped(QStringList)));
/* make sure these use an auto connection so it will be queued if called from a different thread (some facilities in RA log messages from other threads) */ /* make sure these use an auto connection so it will be queued if called from a different thread (some facilities in RA log messages from other threads) */
connect(this, SIGNAL(gotLogMessage(const QString&)), this, SLOT(onGotLogMessage(const QString&)), Qt::AutoConnection); connect(this, SIGNAL(gotLogMessage(const QString&)), this, SLOT(onGotLogMessage(const QString&)), Qt::AutoConnection);
@ -972,29 +1034,61 @@ MainWindow::~MainWindow()
removeGridItems(); removeGridItems();
} }
void MainWindow::dragEnterEvent(QDragEnterEvent *event) void MainWindow::onPlaylistFilesDropped(QStringList files)
{ {
const QMimeData *data = event->mimeData(); addFilesToPlaylist(files);
if (data->hasUrls())
event->acceptProposedAction();
} }
static void addDirectoryFilesToList(QStringList &list, QDir &dir) /* Takes a list of files and folders and adds them to the currently selected playlist. Folders will have their contents added recursively. */
void MainWindow::addFilesToPlaylist(QStringList files)
{ {
QStringList dirList = dir.entryList(QStringList(), QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System, QDir::Name); QStringList list;
QString currentPlaylistPath;
QListWidgetItem *currentItem = m_listWidget->currentItem();
QByteArray currentPlaylistArray;
QScopedPointer<QProgressDialog> dialog(NULL);
PlaylistEntryDialog *playlistDialog = playlistEntryDialog();
QHash<QString, QString> selectedCore;
QString selectedDatabase;
const char *currentPlaylistData = NULL;
playlist_t *playlist = NULL;
int i; int i;
for (i = 0; i < dirList.count(); i++) if (currentItem)
{ {
QString path(dir.path() + "/" + dirList.at(i)); currentPlaylistPath = currentItem->data(Qt::UserRole).toString();
if (!currentPlaylistPath.isEmpty())
{
currentPlaylistArray = currentPlaylistPath.toUtf8();
currentPlaylistData = currentPlaylistArray.constData();
}
}
if (!playlistDialog->showDialog())
return;
selectedCore = m_playlistEntryDialog->getSelectedCore();
selectedDatabase = m_playlistEntryDialog->getSelectedDatabase();
dialog.reset(new QProgressDialog(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES), "Cancel", 0, 0, this));
dialog->setWindowModality(Qt::ApplicationModal);
for (i = 0; i < files.count(); i++)
{
QString path(files.at(i));
QFileInfo fileInfo(path); QFileInfo fileInfo(path);
if (dialog->wasCanceled())
return;
if (i % 25 == 0)
qApp->processEvents();
if (fileInfo.isDir()) if (fileInfo.isDir())
{ {
QDir fileInfoDir(path); QDir dir(path);
addDirectoryFilesToList(list, dir);
addDirectoryFilesToList(list, fileInfoDir);
continue; continue;
} }
@ -1003,161 +1097,96 @@ static void addDirectoryFilesToList(QStringList &list, QDir &dir)
list.append(fileInfo.absoluteFilePath()); list.append(fileInfo.absoluteFilePath());
} }
} }
}
void MainWindow::dropEvent(QDropEvent *event) dialog->setLabelText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST));
{ dialog->setMaximum(list.count());
const QMimeData *data = event->mimeData();
if (data->hasUrls()) playlist = playlist_init(currentPlaylistData, COLLECTION_SIZE);
for (i = 0; i < list.count(); i++)
{ {
QList<QUrl> urls = data->urls(); QString fileName = list.at(i);
QStringList list; QFileInfo fileInfo;
QString currentPlaylistPath; QByteArray fileBaseNameArray;
QListWidgetItem *currentItem = m_listWidget->currentItem(); QByteArray pathArray;
QByteArray currentPlaylistArray; QByteArray corePathArray;
QScopedPointer<QProgressDialog> dialog(NULL); QByteArray coreNameArray;
PlaylistEntryDialog *playlistDialog = playlistEntryDialog(); QByteArray databaseArray;
QHash<QString, QString> selectedCore; const char *pathData = NULL;
QString selectedDatabase; const char *fileNameNoExten = NULL;
const char *currentPlaylistData = NULL; const char *corePathData = NULL;
playlist_t *playlist = NULL; const char *coreNameData = NULL;
int i; const char *databaseData = NULL;
if (currentItem) if (dialog->wasCanceled())
{ {
currentPlaylistPath = currentItem->data(Qt::UserRole).toString(); playlist_free(playlist);
if (!currentPlaylistPath.isEmpty())
{
currentPlaylistArray = currentPlaylistPath.toUtf8();
currentPlaylistData = currentPlaylistArray.constData();
}
}
if (!playlistDialog->showDialog())
return; return;
selectedCore = m_playlistEntryDialog->getSelectedCore();
selectedDatabase = m_playlistEntryDialog->getSelectedDatabase();
dialog.reset(new QProgressDialog(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES), "Cancel", 0, 0, this));
dialog->setWindowModality(Qt::ApplicationModal);
for (i = 0; i < urls.count(); i++)
{
QString path(urls.at(i).toLocalFile());
QFileInfo fileInfo(path);
if (dialog->wasCanceled())
return;
if (i % 25 == 0)
qApp->processEvents();
if (fileInfo.isDir())
{
QDir dir(path);
addDirectoryFilesToList(list, dir);
continue;
}
if (fileInfo.isFile())
{
list.append(fileInfo.absoluteFilePath());
}
} }
dialog->setLabelText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST)); if (fileName.isEmpty())
dialog->setMaximum(list.count()); continue;
playlist = playlist_init(currentPlaylistData, COLLECTION_SIZE); fileInfo = fileName;
fileBaseNameArray = fileInfo.baseName().toUtf8();
fileNameNoExten = fileBaseNameArray.constData();
for (i = 0; i < list.count(); i++) /* a modal QProgressDialog calls processEvents() automatically in setValue() */
dialog->setValue(i + 1);
pathArray = fileName.toUtf8();
pathData = pathArray.constData();
if (selectedCore.isEmpty())
{ {
QString fileName = list.at(i); corePathData = "DETECT";
QFileInfo fileInfo; coreNameData = "DETECT";
QByteArray fileBaseNameArray; }
QByteArray pathArray; else
QByteArray corePathArray; {
QByteArray coreNameArray; corePathArray = selectedCore.value("core_path").toUtf8();
QByteArray databaseArray; coreNameArray = selectedCore.value("core_name").toUtf8();
const char *pathData = NULL; corePathData = corePathArray.constData();
const char *fileNameNoExten = NULL; coreNameData = coreNameArray.constData();
const char *corePathData = NULL; }
const char *coreNameData = NULL;
const char *databaseData = NULL;
if (dialog->wasCanceled()) if (selectedDatabase.isEmpty())
{
databaseArray = QFileInfo(currentPlaylistPath).fileName().toUtf8();
databaseData = databaseArray.constData();
}
else
{
selectedDatabase += file_path_str(FILE_PATH_LPL_EXTENSION);
databaseArray = selectedDatabase.toUtf8();
databaseData = databaseArray.constData();
}
if (path_is_compressed_file(pathData))
{
struct string_list *list = file_archive_get_file_list(pathData, NULL);
if (list)
{ {
playlist_free(playlist); if (list->size == 1)
return;
}
if (fileName.isEmpty())
continue;
fileInfo = fileName;
fileBaseNameArray = fileInfo.baseName().toUtf8();
fileNameNoExten = fileBaseNameArray.constData();
/* a modal QProgressDialog calls processEvents() automatically in setValue() */
dialog->setValue(i + 1);
pathArray = fileName.toUtf8();
pathData = pathArray.constData();
if (selectedCore.isEmpty())
{
corePathData = "DETECT";
coreNameData = "DETECT";
}
else
{
corePathArray = selectedCore.value("core_path").toUtf8();
coreNameArray = selectedCore.value("core_name").toUtf8();
corePathData = corePathArray.constData();
coreNameData = coreNameArray.constData();
}
if (selectedDatabase.isEmpty())
{
databaseArray = QFileInfo(currentPlaylistPath).fileName().toUtf8();
databaseData = databaseArray.constData();
}
else
{
selectedDatabase += file_path_str(FILE_PATH_LPL_EXTENSION);
databaseArray = selectedDatabase.toUtf8();
databaseData = databaseArray.constData();
}
if (path_is_compressed_file(pathData))
{
struct string_list *list = file_archive_get_file_list(pathData, NULL);
if (list)
{ {
if (list->size == 1) /* assume archives with one file should have that file loaded directly */
{ pathArray = (QString(pathData) + "#" + list->elems[0].data).toUtf8();
/* assume archives with one file should have that file loaded directly */ pathData = pathArray.constData();
pathArray = (QString(pathData) + "#" + list->elems[0].data).toUtf8();
pathData = pathArray.constData();
}
string_list_free(list);
} }
}
playlist_push(playlist, pathData, fileNameNoExten, string_list_free(list);
corePathData, coreNameData, "00000000|crc", databaseData); }
} }
playlist_write_file(playlist); playlist_push(playlist, pathData, fileNameNoExten,
playlist_free(playlist); corePathData, coreNameData, "00000000|crc", databaseData);
reloadPlaylists();
} }
playlist_write_file(playlist);
playlist_free(playlist);
reloadPlaylists();
} }
void MainWindow::onGridItemClicked() void MainWindow::onGridItemClicked()

View File

@ -275,9 +275,11 @@ static void* ui_companion_qt_init(void)
listWidget = mainwindow->playlistListWidget(); listWidget = mainwindow->playlistListWidget();
widget = new QWidget(mainwindow); widget = new FileDropWidget(mainwindow);
widget->setObjectName("tableWidget"); widget->setObjectName("tableWidget");
QObject::connect(widget, SIGNAL(filesDropped(QStringList)), mainwindow, SLOT(onPlaylistFilesDropped(QStringList)));
layout = new QVBoxLayout(); layout = new QVBoxLayout();
layout->addWidget(mainwindow->contentTableWidget()); layout->addWidget(mainwindow->contentTableWidget());
layout->addWidget(mainwindow->contentGridWidget()); layout->addWidget(mainwindow->contentGridWidget());

View File

@ -34,7 +34,6 @@
#include <QImage> #include <QImage>
#include <QPointer> #include <QPointer>
#include <QProgressBar> #include <QProgressBar>
#include <QDragEnterEvent>
extern "C" { extern "C" {
#include <retro_assert.h> #include <retro_assert.h>
@ -65,6 +64,8 @@ class QFormLayout;
class QStyle; class QStyle;
class QScrollArea; class QScrollArea;
class QSlider; class QSlider;
class QDragEnterEvent;
class QDropEvent;
class LoadCoreWindow; class LoadCoreWindow;
class MainWindow; class MainWindow;
class ThumbnailWidget; class ThumbnailWidget;
@ -139,6 +140,18 @@ protected slots:
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
}; };
class FileDropWidget : public QWidget
{
Q_OBJECT
public:
FileDropWidget(QWidget *parent = 0);
signals:
void filesDropped(QStringList files);
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
};
class TableWidget : public QTableWidget class TableWidget : public QTableWidget
{ {
Q_OBJECT Q_OBJECT
@ -146,7 +159,7 @@ public:
TableWidget(QWidget *parent = 0); TableWidget(QWidget *parent = 0);
signals: signals:
void enterPressed(); void enterPressed();
protected slots: protected:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
}; };
@ -322,6 +335,7 @@ public:
void setAllPlaylistsListMaxCount(int count); void setAllPlaylistsListMaxCount(int count);
void setAllPlaylistsGridMaxCount(int count); void setAllPlaylistsGridMaxCount(int count);
PlaylistEntryDialog* playlistEntryDialog(); PlaylistEntryDialog* playlistEntryDialog();
void addFilesToPlaylist(QStringList files);
signals: signals:
void thumbnailChanged(const QPixmap &pixmap); void thumbnailChanged(const QPixmap &pixmap);
@ -389,6 +403,7 @@ private slots:
void onPendingItemUpdates(); void onPendingItemUpdates();
void onGridItemDoubleClicked(); void onGridItemDoubleClicked();
void onGridItemClicked(); void onGridItemClicked();
void onPlaylistFilesDropped(QStringList files);
private: private:
void setCurrentCoreLabel(); void setCurrentCoreLabel();
@ -461,8 +476,6 @@ private:
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
}; };
Q_DECLARE_METATYPE(ThumbnailWidget) Q_DECLARE_METATYPE(ThumbnailWidget)