From 010fad236a6c31b1e134738bd2fa8784df492531 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 18 Sep 2018 14:09:25 -0400 Subject: [PATCH] Qt: add option to rename playlists --- intl/msg_hash_ja.h | 2 + intl/msg_hash_us.h | 4 ++ msg_hash.h | 1 + ui/drivers/qt/playlist.cpp | 29 +++++++++- ui/drivers/qt/ui_qt_window.cpp | 100 +++++++++++++++++++++++++++++++-- ui/drivers/ui_qt.h | 21 ++++++- 6 files changed, 147 insertions(+), 10 deletions(-) diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index 953c32192f..fd72f2d852 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -3712,6 +3712,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ENTER_NEW_PLAYLIST_NAME, "新しいプレイリストの名前を入力してください:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST, "プレイリストを削除") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_RENAME_PLAYLIST, + "プレイリストの名前を変更") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST, "「%1」というプレイリストを削除しますか?") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_QUESTION, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index ede48bca8c..cbcad81a7a 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -7230,6 +7230,10 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST, "Delete Playlist" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_RENAME_PLAYLIST, + "Rename Playlist" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST, "Are you sure you want to delete the playlist \"%1\"?" diff --git a/msg_hash.h b/msg_hash.h index 822c787755..45206881aa 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1972,6 +1972,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_QT_NEW_PLAYLIST, MENU_ENUM_LABEL_VALUE_QT_ENTER_NEW_PLAYLIST_NAME, MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST, + MENU_ENUM_LABEL_VALUE_QT_RENAME_PLAYLIST, MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST, MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM, MENU_ENUM_LABEL_VALUE_QT_QUESTION, diff --git a/ui/drivers/qt/playlist.cpp b/ui/drivers/qt/playlist.cpp index f56751ccb4..38d97a9038 100644 --- a/ui/drivers/qt/playlist.cpp +++ b/ui/drivers/qt/playlist.cpp @@ -492,6 +492,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) QScopedPointer hideAction; QScopedPointer newPlaylistAction; QScopedPointer deletePlaylistAction; + QScopedPointer renamePlaylistAction; QScopedPointer downloadAllThumbnailsEntireSystemAction; QScopedPointer downloadAllThumbnailsThisPlaylistAction; QPointer selectedAction; @@ -551,6 +552,9 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) { deletePlaylistAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST)) + "...", this)); menu->addAction(deletePlaylistAction.data()); + + renamePlaylistAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_RENAME_PLAYLIST)) + "...", this)); + menu->addAction(renamePlaylistAction.data()); } if (selectedItem) @@ -704,6 +708,20 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) } } } + else if (selectedItem && selectedAction == renamePlaylistAction.data()) + { + if (currentPlaylistFile.exists()) + { + QString oldName = selectedItem->text(); + QString name = QInputDialog::getText(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_RENAME_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ENTER_NEW_PLAYLIST_NAME), QLineEdit::Normal, oldName); + + if (!name.isEmpty()) + { + renamePlaylistItem(selectedItem, name); + reloadPlaylists(); + } + } + } else if (selectedAction == newPlaylistAction.data()) { QString name = QInputDialog::getText(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NEW_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ENTER_NEW_PLAYLIST_NAME)); @@ -812,13 +830,17 @@ void MainWindow::reloadPlaylists() currentItem = m_listWidget->currentItem(); if (currentItem) - { currentPlaylistPath = currentItem->data(Qt::UserRole).toString(); - } getPlaylistFiles(); + /* block this signal because setData() would trigger an infinite loop */ + disconnect(m_listWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onCurrentListItemDataChanged(QListWidgetItem*))); + m_listWidget->clear(); + m_listWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + m_listWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_listWidget->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed); allPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ALL_PLAYLISTS)); allPlaylistsItem->setData(Qt::UserRole, ALL_PLAYLISTS_TOKEN); @@ -880,6 +902,7 @@ void MainWindow::reloadPlaylists() icon = m_folderIcon; item = new QListWidgetItem(icon, fileDisplayName); + item->setFlags(item->flags() | Qt::ItemIsEditable); item->setData(Qt::UserRole, playlistDir.absoluteFilePath(file)); m_listWidget->addItem(item); @@ -944,6 +967,8 @@ void MainWindow::reloadPlaylists() } } } + + connect(m_listWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onCurrentListItemDataChanged(QListWidgetItem*))); } QString MainWindow::getCurrentPlaylistPath() diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index 548f6c153d..00d6b1e398 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -20,9 +20,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -214,6 +212,26 @@ void TableWidget::keyPressEvent(QKeyEvent *event) QTableWidget::keyPressEvent(event); } +ListWidget::ListWidget(QWidget *parent) : + QListWidget(parent) +{ +} + +bool ListWidget::isEditorOpen() +{ + return (state() == QAbstractItemView::EditingState); +} + +void ListWidget::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) + emit enterPressed(); + else if (event->key() == Qt::Key_Delete) + emit deletePressed(); + + QListWidget::keyPressEvent(event); +} + CoreInfoLabel::CoreInfoLabel(QString text, QWidget *parent) : QLabel(text, parent) { @@ -264,7 +282,7 @@ MainWindow::MainWindow(QWidget *parent) : ,m_statusLabel(new QLabel(this)) ,m_dirTree(new TreeView(this)) ,m_dirModel(new QFileSystemModel(m_dirTree)) - ,m_listWidget(new QListWidget(this)) + ,m_listWidget(new ListWidget(this)) ,m_tableWidget(new TableWidget(this)) ,m_searchWidget(new QWidget(this)) ,m_searchLineEdit(new QLineEdit(this)) @@ -2374,7 +2392,7 @@ void MainWindow::onCurrentTableItemDataChanged(QTableWidgetItem *item) if (!item) return; - /* block this signal because setData() would trigger an infinite look here */ + /* block this signal because setData() would trigger an infinite loop here */ disconnect(m_tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onCurrentTableItemDataChanged(QTableWidgetItem*))); hash = item->data(Qt::UserRole).value >(); @@ -2390,6 +2408,78 @@ void MainWindow::onCurrentTableItemDataChanged(QTableWidgetItem *item) connect(m_tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(onCurrentTableItemDataChanged(QTableWidgetItem*))); } +void MainWindow::onCurrentListItemDataChanged(QListWidgetItem *item) +{ + renamePlaylistItem(item, item->text()); +} + +void MainWindow::renamePlaylistItem(QListWidgetItem *item, QString newName) +{ + QString oldPath; + QString newPath; + QString extension; + QString oldName; + QFile file; + QFileInfo info; + QFileInfo playlistInfo; + QString playlistPath; + settings_t *settings = config_get_ptr(); + QDir playlistDir(settings->paths.directory_playlist); + bool specialPlaylist = false; + + if (!item) + return; + + playlistPath = item->data(Qt::UserRole).toString(); + playlistInfo = playlistPath; + oldName = playlistInfo.completeBaseName(); + + /* Don't just compare strings in case there are case differences on Windows that should be ignored. */ + if (QDir(playlistInfo.absoluteDir()) != QDir(playlistDir)) + { + /* special playlists like history etc. can't have an association */ + specialPlaylist = true; + } + + if (specialPlaylist) + { + /* special playlists shouldn't be editable already, but just in case, set the old name back and early return if they rename it */ + item->setText(oldName); + return; + } + + /* block this signal because setData() would trigger an infinite loop here */ + disconnect(m_listWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onCurrentListItemDataChanged(QListWidgetItem*))); + + oldPath = item->data(Qt::UserRole).toString(); + + file.setFileName(oldPath); + info = file; + + extension = info.suffix(); + + newPath = info.absolutePath(); + + /* absolutePath() will always use / even on Windows */ + if (newPath.at(newPath.count() - 1) != '/') + { + /* add trailing slash if the path doesn't have one */ + newPath += '/'; + } + + newPath += newName + "." + extension; + + item->setData(Qt::UserRole, newPath); + + if (!file.rename(newPath)) + { + RARCH_ERR("[Qt]: Could not rename playlist.\n"); + item->setText(oldName); + } + + connect(m_listWidget, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(onCurrentListItemDataChanged(QListWidgetItem*))); +} + void MainWindow::currentItemChanged(const QHash &hash) { settings_t *settings = config_get_ptr(); @@ -2637,7 +2727,7 @@ void MainWindow::onBrowserStartClicked() m_dirTree->scrollTo(m_dirTree->currentIndex(), QAbstractItemView::PositionAtTop); } -QListWidget* MainWindow::playlistListWidget() +ListWidget* MainWindow::playlistListWidget() { return m_listWidget; } diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index f04961cd3b..ee0f75752f 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,6 @@ class QCloseEvent; class QKeyEvent; class QTimer; class QFileSystemModel; -class QListWidget; class QListWidgetItem; class QTableWidgetItem; class QResizeEvent; @@ -177,6 +177,19 @@ protected: void keyPressEvent(QKeyEvent *event); }; +class ListWidget : public QListWidget +{ + Q_OBJECT +public: + ListWidget(QWidget *parent = 0); + bool isEditorOpen(); +signals: + void enterPressed(); + void deletePressed(); +protected: + void keyPressEvent(QKeyEvent *event); +}; + class AppHandler : public QObject { Q_OBJECT @@ -250,7 +263,7 @@ public: MainWindow(QWidget *parent = NULL); ~MainWindow(); TreeView* dirTreeView(); - QListWidget* playlistListWidget(); + ListWidget* playlistListWidget(); TableWidget* contentTableWidget(); FlowLayout* contentGridLayout(); QWidget* contentGridWidget(); @@ -361,6 +374,7 @@ private slots: void onCurrentListItemChanged(QListWidgetItem *current, QListWidgetItem *previous); void onCurrentTableItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous); void onCurrentTableItemDataChanged(QTableWidgetItem *item); + void onCurrentListItemDataChanged(QListWidgetItem *item); void currentItemChanged(const QHash &hash); void onSearchEnterPressed(); void onSearchLineEditEdited(const QString &text); @@ -437,6 +451,7 @@ private: int extractArchive(QString path); void removeUpdateTempFiles(); bool addDirectoryFilesToList(QProgressDialog *dialog, QStringList &list, QDir &dir, QStringList &extensions); + void renamePlaylistItem(QListWidgetItem *item, QString newName); QVector > getPlaylistItems(QString pathString); LoadCoreWindow *m_loadCoreWindow; @@ -446,7 +461,7 @@ private: QLabel *m_statusLabel; TreeView *m_dirTree; QFileSystemModel *m_dirModel; - QListWidget *m_listWidget; + ListWidget *m_listWidget; TableWidget *m_tableWidget; QWidget *m_searchWidget; QLineEdit *m_searchLineEdit;