Merge pull request #7022 from bparker06/qt_playlist

Qt: ability to add/delete playlists and drag&drop files into a playlist
This commit is contained in:
Twinaphex 2018-07-28 18:29:07 +02:00 committed by GitHub
commit fb3b5df350
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 687 additions and 39 deletions

View File

@ -3638,3 +3638,31 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT
"「すべてのプレイリスト」アイコンの最大個数:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SHOW_HIDDEN_FILES,
"隠しファイルとフォルダを表示:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_NEW_PLAYLIST,
"新規プレイリスト")
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_CONFIRM_DELETE_PLAYLIST,
"「%1」というプレイリストを削除しますか")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_QUESTION,
"質問")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE,
"ファイル削除に失敗しました。")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
"ファイルの一覧を構築しています...")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
"ファイルをプレイリストに追加しています...")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY,
"プレイリストエントリー")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE,
"コア:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE,
"データベース:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS,
"(サムネイルを見つかることに使う)")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM,
"「%1」というアイテムを削除しますか")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS,
"まずひとつのプレイリストを選択してください。")

View File

@ -3796,3 +3796,31 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT
"\"All Playlists\" max grid entries:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SHOW_HIDDEN_FILES,
"Show hidden files and folders:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_NEW_PLAYLIST,
"New Playlist")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ENTER_NEW_PLAYLIST_NAME,
"Please enter the new playlist name:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST,
"Delete Playlist")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST,
"Are you sure you want to delete the playlist \"%1\"?")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_QUESTION,
"Question")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE,
"Could not delete file.")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
"Gathering list of files...")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
"Adding files to playlist...")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY,
"Playlist Entry")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE,
"Core:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE,
"Database:")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS,
"(used to find thumbnails)")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM,
"Are you sure you want to delete the item \"%1\"?")
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS,
"Please choose a single playlist first.")

View File

@ -1879,6 +1879,20 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_ICONS,
MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_LIST,
MENU_ENUM_LABEL_VALUE_QT_PROGRESS,
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_CONFIRM_DELETE_PLAYLIST,
MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM,
MENU_ENUM_LABEL_VALUE_QT_QUESTION,
MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE,
MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY,
MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE,
MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE,
MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS,
MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS,
MENU_LABEL(MIDI_INPUT),
MENU_LABEL(MIDI_OUTPUT),

View File

@ -29,6 +29,11 @@
#include <QMenu>
#include <QDockWidget>
#include <QList>
#include <QInputDialog>
#include <QMimeData>
#include <QProgressDialog>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QtConcurrentRun>
#include "../ui_qt.h"
@ -125,9 +130,53 @@ static void scan_finished_handler(void *task_data, void *user_data, const char *
}
#endif
inline static bool comp_hash_label_key(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
inline static bool comp_string_lower(const QString &lhs, const QString &rhs)
{
return lhs.value("label") < rhs.value("label");
return lhs.toLower() < rhs.toLower();
}
inline static bool comp_hash_ui_display_name_key_lower(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
{
return lhs.value("ui_display_name").toLower() < rhs.value("ui_display_name").toLower();
}
inline static bool comp_hash_label_key_lower(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
{
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() :
@ -142,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) :
QTreeView(parent)
{
@ -170,6 +210,52 @@ void TreeView::selectionChanged(const QItemSelection &selected, const QItemSelec
emit itemsSelected(list);
}
FileDropWidget::FileDropWidget(QWidget *parent) :
QWidget(parent)
{
setAcceptDrops(true);
}
void FileDropWidget::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Delete)
{
event->accept();
emit deletePressed();
}
else
QWidget::keyPressEvent(event);
}
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) :
QTableWidget(parent)
{
@ -182,6 +268,11 @@ void TableWidget::keyPressEvent(QKeyEvent *event)
event->accept();
emit enterPressed();
}
else if (event->key() == Qt::Key_Delete)
{
event->accept();
emit deletePressed();
}
else
QTableWidget::keyPressEvent(event);
}
@ -276,6 +367,151 @@ void CoreInfoDialog::showCoreInfo()
show();
}
PlaylistEntryDialog::PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent) :
QDialog(parent)
,m_mainwindow(mainwindow)
,m_settings(mainwindow->settings())
,m_coreComboBox(new QComboBox(this))
,m_databaseComboBox(new QComboBox(this))
{
QFormLayout *form = new QFormLayout();
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
QVBoxLayout *databaseVBoxLayout = new QVBoxLayout();
QLabel *databaseLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS), this);
databaseVBoxLayout->addWidget(m_databaseComboBox);
databaseVBoxLayout->addWidget(databaseLabel);
setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY));
form->setFormAlignment(Qt::AlignCenter);
form->setLabelAlignment(Qt::AlignCenter);
setLayout(new QVBoxLayout(this));
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(this, SIGNAL(accepted()), this, SLOT(onAccepted()));
connect(this, SIGNAL(rejected()), this, SLOT(onRejected()));
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE), m_coreComboBox);
form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE), databaseVBoxLayout);
qobject_cast<QVBoxLayout*>(layout())->addLayout(form);
layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
layout()->addWidget(buttonBox);
}
void PlaylistEntryDialog::loadPlaylistOptions()
{
core_info_list_t *core_info_list = NULL;
const core_info_t *core_info = NULL;
unsigned i = 0;
int j = 0;
m_coreComboBox->clear();
m_databaseComboBox->clear();
m_coreComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE_SELECTION_ASK));
m_databaseComboBox->addItem(QString("<") + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE) + ">");
core_info_get_list(&core_info_list);
if (core_info_list && core_info_list->count > 0)
{
QVector<QHash<QString, QString> > allCores;
QStringList allDatabases;
for (i = 0; i < core_info_list->count; i++)
{
const core_info_t *core = &core_info_list->list[i];
QStringList databases = QString(core->databases).split("|");
QHash<QString, QString> hash;
QString ui_display_name;
hash["core_name"] = core->core_name;
hash["core_display_name"] = core->display_name;
hash["core_path"] = core->path;
hash["core_databases"] = core->databases;
ui_display_name = hash.value("core_name");
if (ui_display_name.isEmpty())
ui_display_name = hash.value("core_display_name");
if (ui_display_name.isEmpty())
ui_display_name = QFileInfo(hash.value("core_path")).fileName();
if (ui_display_name.isEmpty())
continue;
hash["ui_display_name"] = ui_display_name;
for (j = 0; j < databases.count(); j++)
{
QString database = databases.at(j);
if (database.isEmpty())
continue;
if (!allDatabases.contains(database))
allDatabases.append(database);
}
if (!allCores.contains(hash))
allCores.append(hash);
}
std::sort(allCores.begin(), allCores.end(), comp_hash_ui_display_name_key_lower);
std::sort(allDatabases.begin(), allDatabases.end(), comp_string_lower);
for (j = 0; j < allCores.count(); j++)
{
const QHash<QString, QString> &hash = allCores.at(j);
m_coreComboBox->addItem(hash.value("ui_display_name"), QVariant::fromValue(hash));
}
for (j = 0; j < allDatabases.count(); j++)
{
QString database = allDatabases.at(j);
m_databaseComboBox->addItem(database, database);
}
}
}
const QHash<QString, QString> PlaylistEntryDialog::getSelectedCore()
{
return m_coreComboBox->currentData(Qt::UserRole).value<QHash<QString, QString> >();
}
const QString PlaylistEntryDialog::getSelectedDatabase()
{
return m_databaseComboBox->currentData(Qt::UserRole).toString();
}
void PlaylistEntryDialog::onAccepted()
{
}
void PlaylistEntryDialog::onRejected()
{
}
bool PlaylistEntryDialog::showDialog()
{
loadPlaylistOptions();
if (exec() == QDialog::Accepted)
return true;
return false;
}
void PlaylistEntryDialog::hideDialog()
{
reject();
}
ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
QDialog(parent)
,m_mainwindow(mainwindow)
@ -556,7 +792,7 @@ MainWindow::MainWindow(QWidget *parent) :
,m_gridWidget(new QWidget(this))
,m_gridScrollArea(new QScrollArea(m_gridWidget))
,m_gridItems()
,m_gridLayoutWidget(new QWidget())
,m_gridLayoutWidget(new FileDropWidget())
,m_zoomSlider(NULL)
,m_lastZoomSliderValue(0)
,m_pendingItemUpdates()
@ -568,6 +804,7 @@ MainWindow::MainWindow(QWidget *parent) :
,m_currentGridWidget(NULL)
,m_allPlaylistsListMaxCount(0)
,m_allPlaylistsGridMaxCount(0)
,m_playlistEntryDialog(NULL)
{
settings_t *settings = config_get_ptr();
QDir playlistDir(settings->paths.directory_playlist);
@ -663,6 +900,7 @@ MainWindow::MainWindow(QWidget *parent) :
/* ViewOptionsDialog needs m_settings set before it's constructed */
m_settings = new QSettings(configDir + "/retroarch_qt.cfg", QSettings::IniFormat, this);
m_viewOptionsDialog = new ViewOptionsDialog(this, 0);
m_playlistEntryDialog = new PlaylistEntryDialog(this, 0);
/* default NULL parameter for parent wasn't added until 5.7 */
m_startCorePushButton->setDefaultAction(new QAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_START_CORE), m_startCorePushButton));
@ -763,6 +1001,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(m_tableWidget, SIGNAL(currentItemChanged(QTableWidgetItem*, QTableWidgetItem*)), this, SLOT(onCurrentTableItemChanged(QTableWidgetItem*, QTableWidgetItem*)));
connect(m_tableWidget, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(onContentItemDoubleClicked(QTableWidgetItem*)));
connect(m_tableWidget, SIGNAL(enterPressed()), this, SLOT(onTableWidgetEnterPressed()));
connect(m_tableWidget, SIGNAL(deletePressed()), this, SLOT(onTableWidgetDeletePressed()));
connect(m_startCorePushButton, SIGNAL(clicked()), this, SLOT(onStartCoreClicked()));
connect(m_coreInfoPushButton, SIGNAL(clicked()), m_coreInfoDialog, SLOT(showCoreInfo()));
connect(m_runPushButton, SIGNAL(clicked()), this, SLOT(onRunClicked()));
@ -774,6 +1013,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(onZoomValueChanged(int)));
connect(viewTypeIconsAction, SIGNAL(triggered()), this, SLOT(onIconViewClicked()));
connect(viewTypeListAction, SIGNAL(triggered()), this, SLOT(onListViewClicked()));
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) */
connect(this, SIGNAL(gotLogMessage(const QString&)), this, SLOT(onGotLogMessage(const QString&)), Qt::AutoConnection);
@ -811,6 +1051,167 @@ MainWindow::~MainWindow()
removeGridItems();
}
void MainWindow::onPlaylistFilesDropped(QStringList files)
{
addFilesToPlaylist(files);
}
/* 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 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;
if (currentItem)
{
currentPlaylistPath = currentItem->data(Qt::UserRole).toString();
if (!currentPlaylistPath.isEmpty())
{
currentPlaylistArray = currentPlaylistPath.toUtf8();
currentPlaylistData = currentPlaylistArray.constData();
}
}
if (currentPlaylistPath == ALL_PLAYLISTS_TOKEN)
{
ui_window.qtWindow->showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal);
return;
}
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);
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));
dialog->setMaximum(list.count());
playlist = playlist_init(currentPlaylistData, COLLECTION_SIZE);
for (i = 0; i < list.count(); i++)
{
QString fileName = list.at(i);
QFileInfo fileInfo;
QByteArray fileBaseNameArray;
QByteArray pathArray;
QByteArray corePathArray;
QByteArray coreNameArray;
QByteArray databaseArray;
const char *pathData = NULL;
const char *fileNameNoExten = NULL;
const char *corePathData = NULL;
const char *coreNameData = NULL;
const char *databaseData = NULL;
if (dialog->wasCanceled())
{
playlist_free(playlist);
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();
pathData = pathArray.constData();
}
string_list_free(list);
}
}
playlist_push(playlist, pathData, fileNameNoExten,
corePathData, coreNameData, "00000000|crc", databaseData);
}
playlist_write_file(playlist);
playlist_free(playlist);
reloadPlaylists();
}
void MainWindow::onGridItemClicked()
{
QHash<QString, QString> hash;
@ -883,9 +1284,9 @@ inline void MainWindow::calcGridItemSize(GridItem *item, int zoomValue)
void MainWindow::onZoomValueChanged(int value)
{
int i = 0;
int i;
for (i = 0; i < m_gridItems.count() && m_gridItems.count() > 0; i++)
for (i = 0; i < m_gridItems.count(); i++)
{
GridItem *item = m_gridItems.at(i);
calcGridItemSize(item, value);
@ -978,7 +1379,7 @@ void MainWindow::setCustomThemeString(QString qss)
m_customThemeString = qss;
}
bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowModality modality)
bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowModality modality, bool showDontAsk)
{
QPointer<QMessageBox> msgBoxPtr;
QMessageBox *msgBox = NULL;
@ -986,13 +1387,16 @@ bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowM
msgBoxPtr = new QMessageBox(this);
msgBox = msgBoxPtr.data();
checkBox = new QCheckBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DONT_SHOW_AGAIN), msgBox);
msgBox->setWindowModality(modality);
msgBox->setTextFormat(Qt::RichText);
/* QMessageBox::setCheckBox() is available since 5.2 */
msgBox->setCheckBox(checkBox);
if (showDontAsk)
{
checkBox = new QCheckBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DONT_SHOW_AGAIN), msgBox);
/* QMessageBox::setCheckBox() is available since 5.2 */
msgBox->setCheckBox(checkBox);
}
switch (msgType)
{
@ -1014,6 +1418,13 @@ bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowM
msgBox->setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ERROR));
break;
}
case MSGBOX_TYPE_QUESTION:
{
msgBox->setIcon(QMessageBox::Question);
msgBox->setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_QUESTION));
msgBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
break;
}
default:
break;
}
@ -1024,7 +1435,10 @@ bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowM
if (!msgBoxPtr)
return true;
if (checkBox->isChecked())
if (checkBox && checkBox->isChecked())
return false;
if (msgBox->result() == QMessageBox::Cancel)
return false;
return true;
@ -1037,6 +1451,8 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
QScopedPointer<QMenu> associateMenu;
QScopedPointer<QMenu> hiddenPlaylistsMenu;
QScopedPointer<QAction> hideAction;
QScopedPointer<QAction> newPlaylistAction;
QScopedPointer<QAction> deletePlaylistAction;
QPointer<QAction> selectedAction;
QPoint cursorPos = QCursor::pos();
QListWidgetItem *selectedItem = m_listWidget->itemAt(m_listWidget->viewport()->mapFromGlobal(cursorPos));
@ -1045,6 +1461,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
QString currentPlaylistDirPath;
QString currentPlaylistPath;
QString currentPlaylistFileName;
QFile currentPlaylistFile;
QByteArray currentPlaylistFileNameArray;
QFileInfo currentPlaylistFileInfo;
QMap<QString, const core_info_t*> coreList;
@ -1061,33 +1478,47 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
bool specialPlaylist = false;
bool foundHiddenPlaylist = false;
if (!selectedItem)
return;
new_playlist_names[0] = new_playlist_cores[0] = '\0';
stnames = string_split(settings->arrays.playlist_names, ";");
stcores = string_split(settings->arrays.playlist_cores, ";");
currentPlaylistPath = selectedItem->data(Qt::UserRole).toString();
currentPlaylistFileInfo = QFileInfo(currentPlaylistPath);
currentPlaylistFileName = currentPlaylistFileInfo.fileName();
currentPlaylistDirPath = currentPlaylistFileInfo.absoluteDir().absolutePath();
if (selectedItem)
{
currentPlaylistPath = selectedItem->data(Qt::UserRole).toString();
currentPlaylistFile.setFileName(currentPlaylistPath);
currentPlaylistFileNameArray.append(currentPlaylistFileName);
currentPlaylistFileNameData = currentPlaylistFileNameArray.constData();
currentPlaylistFileInfo = QFileInfo(currentPlaylistPath);
currentPlaylistFileName = currentPlaylistFileInfo.fileName();
currentPlaylistDirPath = currentPlaylistFileInfo.absoluteDir().absolutePath();
currentPlaylistFileNameArray.append(currentPlaylistFileName);
currentPlaylistFileNameData = currentPlaylistFileNameArray.constData();
}
menu.reset(new QMenu(this));
menu->setObjectName("menu");
hiddenPlaylistsMenu.reset(new QMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_HIDDEN_PLAYLISTS), this));
newPlaylistAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NEW_PLAYLIST)) + "...", this));
hiddenPlaylistsMenu->setObjectName("hiddenPlaylistsMenu");
hideAction.reset(new QAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_HIDE), this));
menu->addAction(newPlaylistAction.data());
menu->addAction(hideAction.data());
if (selectedItem)
{
hideAction.reset(new QAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_HIDE), this));
menu->addAction(hideAction.data());
}
for (j = 0; j < m_listWidget->count() && m_listWidget->count() > 0; j++)
if (currentPlaylistFile.exists())
{
deletePlaylistAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST)) + "...", this));
menu->addAction(deletePlaylistAction.data());
}
for (j = 0; j < m_listWidget->count(); j++)
{
QListWidgetItem *item = m_listWidget->item(j);
bool hidden = m_listWidget->isItemHidden(item);
@ -1181,6 +1612,30 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
strlcpy(settings->arrays.playlist_cores,
new_playlist_cores, sizeof(settings->arrays.playlist_cores));
}
else if (selectedAction == deletePlaylistAction.data())
{
if (currentPlaylistFile.exists())
{
if (ui_window.qtWindow->showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST)).arg(selectedItem->text()), MainWindow::MSGBOX_TYPE_QUESTION, Qt::ApplicationModal, false))
{
if (currentPlaylistFile.remove())
reloadPlaylists();
else
ui_window.qtWindow->showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
}
}
}
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));
QString newPlaylistPath = playlistDirAbsPath + "/" + name + file_path_str(FILE_PATH_LPL_EXTENSION);
QFile file(newPlaylistPath);
if (file.open(QIODevice::WriteOnly))
file.close();
reloadPlaylists();
}
else if (selectedAction == hideAction.data())
{
int row = m_listWidget->row(selectedItem);
@ -1380,7 +1835,7 @@ void MainWindow::reloadPlaylists()
if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_video_history).fileName()))
m_listWidget->setRowHidden(m_listWidget->row(videoPlaylistsItem), true);
for (i = 0; i < m_playlistFiles.count() && m_playlistFiles.count() > 0; i++)
for (i = 0; i < m_playlistFiles.count(); i++)
{
QListWidgetItem *item = NULL;
const QString &file = m_playlistFiles.at(i);
@ -1948,6 +2403,67 @@ void MainWindow::onTableWidgetEnterPressed()
onRunClicked();
}
void MainWindow::onTableWidgetDeletePressed()
{
deleteCurrentPlaylistItem();
}
void MainWindow::deleteCurrentPlaylistItem()
{
QTableWidgetItem *contentItem = m_tableWidget->currentItem();
QListWidgetItem *playlistItem = m_listWidget->currentItem();
QHash<QString, QString> contentHash;
QString playlistPath;
QByteArray playlistArray;
ViewType viewType = getCurrentViewType();
playlist_t *playlist = NULL;
const char *playlistData = NULL;
unsigned index = 0;
bool ok = false;
if (!playlistItem)
return;
playlistPath = playlistItem->data(Qt::UserRole).toString();
if (playlistPath.isEmpty())
return;
if (viewType == VIEW_TYPE_LIST)
{
if (!contentItem)
return;
contentHash = contentItem->data(Qt::UserRole).value<QHash<QString, QString> >();
}
else if (viewType == VIEW_TYPE_ICONS)
contentHash = m_currentGridHash;
else
return;
if (contentHash.isEmpty())
return;
playlistArray = playlistPath.toUtf8();
playlistData = playlistArray.constData();
index = contentHash.value("index").toUInt(&ok);
if (!ok)
return;
if (!ui_window.qtWindow->showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM)).arg(contentHash["label"]), MainWindow::MSGBOX_TYPE_QUESTION, Qt::ApplicationModal, false))
return;
playlist = playlist_init(playlistData, COLLECTION_SIZE);
playlist_delete_index(playlist, index);
playlist_write_file(playlist);
playlist_free(playlist);
reloadPlaylists();
}
void MainWindow::onContentItemDoubleClicked(QTableWidgetItem*)
{
onRunClicked();
@ -1983,6 +2499,8 @@ QHash<QString, QString> MainWindow::getSelectedCore()
contentHash = contentItem->data(Qt::UserRole).value<QHash<QString, QString> >();
else if (viewType == VIEW_TYPE_ICONS)
contentHash = m_currentGridHash;
else
return coreHash;
switch(coreSelection)
{
@ -2188,6 +2706,8 @@ void MainWindow::onRunClicked()
contentHash = item->data(Qt::UserRole).value<QHash<QString, QString> >();
else if (viewType == VIEW_TYPE_ICONS)
contentHash = m_currentGridHash;
else
return;
loadContent(contentHash);
#endif
@ -2208,6 +2728,11 @@ bool MainWindow::isCoreLoaded()
return true;
}
PlaylistEntryDialog* MainWindow::playlistEntryDialog()
{
return m_playlistEntryDialog;
}
ViewOptionsDialog* MainWindow::viewOptionsDialog()
{
return m_viewOptionsDialog;
@ -2636,6 +3161,8 @@ void MainWindow::onSearchLineEditEdited(const QString &text)
break;
}
default:
break;
}
}
@ -2659,7 +3186,7 @@ void MainWindow::onViewClosedDocksAboutToShow()
return;
}
for (i = 0; i < dockWidgets.count() && dockWidgets.count() > 0; i++)
for (i = 0; i < dockWidgets.count(); i++)
{
const QDockWidget *dock = dockWidgets.at(i);
@ -2863,6 +3390,7 @@ void MainWindow::setCurrentViewType(ViewType viewType)
case VIEW_TYPE_LIST:
default:
{
m_viewType = VIEW_TYPE_LIST;
m_gridWidget->hide();
m_tableWidget->show();
break;
@ -3219,7 +3747,7 @@ void MainWindow::addPlaylistItemsToGrid(const QStringList &paths, bool add)
}
}
finish:
std::sort(items.begin(), items.end(), comp_hash_label_key);
std::sort(items.begin(), items.end(), comp_hash_label_key_lower);
addPlaylistHashToGrid(items);
}
@ -3363,7 +3891,7 @@ void MainWindow::initContentGridLayout()
QStringList playlists;
int i = 0;
for (i = 0; i < m_playlistFiles.count() && m_playlistFiles.count() > 0; i++)
for (i = 0; i < m_playlistFiles.count(); i++)
{
const QString &playlist = m_playlistFiles.at(i);
playlists.append(playlistDir.absoluteFilePath(playlist));
@ -3430,7 +3958,7 @@ void MainWindow::initContentTableWidget()
QStringList playlists;
int i = 0;
for (i = 0; i < m_playlistFiles.count() && m_playlistFiles.count() > 0; i++)
for (i = 0; i < m_playlistFiles.count(); i++)
{
const QString &playlist = m_playlistFiles.at(i);
playlists.append(playlistDir.absoluteFilePath(playlist));
@ -3495,6 +4023,8 @@ QVector<QHash<QString, QString> > MainWindow::getPlaylistItems(QString pathStrin
else
hash["path"] = path;
hash["index"] = QString::number(i);
if (string_is_empty(label))
{
hash["label"] = path;

View File

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

View File

@ -64,6 +64,8 @@ class QFormLayout;
class QStyle;
class QScrollArea;
class QSlider;
class QDragEnterEvent;
class QDropEvent;
class LoadCoreWindow;
class MainWindow;
class ThumbnailWidget;
@ -138,6 +140,20 @@ protected slots:
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
};
class FileDropWidget : public QWidget
{
Q_OBJECT
public:
FileDropWidget(QWidget *parent = 0);
signals:
void filesDropped(QStringList files);
void deletePressed();
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
void keyPressEvent(QKeyEvent *event);
};
class TableWidget : public QTableWidget
{
Q_OBJECT
@ -145,7 +161,8 @@ public:
TableWidget(QWidget *parent = 0);
signals:
void enterPressed();
protected slots:
void deletePressed();
protected:
void keyPressEvent(QKeyEvent *event);
};
@ -163,6 +180,27 @@ private slots:
void onLastWindowClosed();
};
class PlaylistEntryDialog : public QDialog
{
Q_OBJECT
public:
PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent = 0);
const QHash<QString, QString> getSelectedCore();
const QString getSelectedDatabase();
public slots:
bool showDialog();
void hideDialog();
void onAccepted();
void onRejected();
private:
void loadPlaylistOptions();
MainWindow *m_mainwindow;
QSettings *m_settings;
QComboBox *m_coreComboBox;
QComboBox *m_databaseComboBox;
};
class ViewOptionsDialog : public QDialog
{
Q_OBJECT
@ -261,6 +299,7 @@ public:
MSGBOX_TYPE_INFO,
MSGBOX_TYPE_WARNING,
MSGBOX_TYPE_ERROR,
MSGBOX_TYPE_QUESTION,
};
MainWindow(QWidget *parent = NULL);
@ -288,7 +327,7 @@ public:
QString getThemeString(Theme theme);
QHash<QString, QString> getSelectedCore();
void showStatusMessage(QString msg, unsigned priority, unsigned duration, bool flush);
bool showMessageBox(QString msg, MessageBoxType msgType = MSGBOX_TYPE_INFO, Qt::WindowModality modality = Qt::ApplicationModal);
bool showMessageBox(QString msg, MessageBoxType msgType = MSGBOX_TYPE_INFO, Qt::WindowModality modality = Qt::ApplicationModal, bool showDontAsk = true);
bool setCustomThemeFile(QString filePath);
void setCustomThemeString(QString qss);
const QString& customThemeString() const;
@ -298,6 +337,8 @@ public:
ViewType getCurrentViewType();
void setAllPlaylistsListMaxCount(int count);
void setAllPlaylistsGridMaxCount(int count);
PlaylistEntryDialog* playlistEntryDialog();
void addFilesToPlaylist(QStringList files);
signals:
void thumbnailChanged(const QPixmap &pixmap);
@ -320,6 +361,7 @@ public slots:
void loadContent(const QHash<QString, QString> &contentHash);
void onStartCoreClicked();
void onTableWidgetEnterPressed();
void onTableWidgetDeletePressed();
void selectBrowserDir(QString path);
void resizeThumbnails(bool one, bool two, bool three);
void onResizeThumbnailOne();
@ -335,6 +377,7 @@ public slots:
void onIconViewClicked();
void onListViewClicked();
void onTabWidgetIndexChanged(int index);
void deleteCurrentPlaylistItem();
private slots:
void onLoadCoreClicked(const QStringList &extensionFilters = QStringList());
@ -365,6 +408,7 @@ private slots:
void onPendingItemUpdates();
void onGridItemDoubleClicked();
void onGridItemClicked();
void onPlaylistFilesDropped(QStringList files);
private:
void setCurrentCoreLabel();
@ -432,6 +476,7 @@ private:
QPointer<ThumbnailWidget> m_currentGridWidget;
int m_allPlaylistsListMaxCount;
int m_allPlaylistsGridMaxCount;
PlaylistEntryDialog *m_playlistEntryDialog;
protected:
void closeEvent(QCloseEvent *event);