diff --git a/Makefile.common b/Makefile.common index 647e1e6c3b..7721c15c32 100644 --- a/Makefile.common +++ b/Makefile.common @@ -339,11 +339,23 @@ OBJ += ui/drivers/ui_qt.o \ ui/drivers/qt/ui_qt_browser_window.o \ ui/drivers/qt/ui_qt_load_core_window.o \ ui/drivers/qt/ui_qt_msg_window.o \ - ui/drivers/qt/flowlayout.o + ui/drivers/qt/flowlayout.o \ + ui/drivers/qt/shaderparamsdialog.o \ + ui/drivers/qt/filedropwidget.o \ + ui/drivers/qt/coreinfodialog.o \ + ui/drivers/qt/playlistentrydialog.o \ + ui/drivers/qt/viewoptionsdialog.o \ + ui/drivers/qt/playlist.o \ + ui/drivers/qt/updateretroarch.o MOC_HEADERS += ui/drivers/ui_qt.h \ ui/drivers/qt/ui_qt_load_core_window.h \ - ui/drivers/qt/flowlayout.h + ui/drivers/qt/flowlayout.h \ + ui/drivers/qt/shaderparamsdialog.h \ + ui/drivers/qt/filedropwidget.h \ + ui/drivers/qt/coreinfodialog.h \ + ui/drivers/qt/playlistentrydialog.h \ + ui/drivers/qt/viewoptionsdialog.h DEFINES += $(QT5CORE_CFLAGS) $(QT5GUI_CFLAGS) $(QT5WIDGETS_CFLAGS) $(QT5CONCURRENT_CFLAGS) $(QT5NETWORK_CFLAGS) -DHAVE_MAIN #DEFINES += $(QT5WEBENGINE_CFLAGS) diff --git a/griffin/griffin_cpp.cpp b/griffin/griffin_cpp.cpp index 17aae41d3d..a51280b7bf 100644 --- a/griffin/griffin_cpp.cpp +++ b/griffin/griffin_cpp.cpp @@ -42,6 +42,13 @@ UI #include "../ui/drivers/qt/ui_qt_msg_window.cpp" #include "../ui/drivers/qt/ui_qt_application.cpp" #include "../ui/drivers/qt/flowlayout.cpp" +#include "../ui/drivers/qt/shaderparamsdialog.cpp" +#include "../ui/drivers/qt/filedropwidget.cpp" +#include "../ui/drivers/qt/coreinfodialog.cpp" +#include "../ui/drivers/qt/playlistentrydialog.cpp" +#include "../ui/drivers/qt/viewoptionsdialog.cpp" +#include "../ui/drivers/qt/playlist.cpp" +#include "../ui/drivers/qt/updateretroarch.cpp" #endif /*============================================================ diff --git a/menu/menu_displaylist.h b/menu/menu_displaylist.h index 8fe0bea1a7..0109486219 100644 --- a/menu/menu_displaylist.h +++ b/menu/menu_displaylist.h @@ -23,6 +23,8 @@ #include #include +#include "../setting_list.h" + #ifndef COLLECTION_SIZE #define COLLECTION_SIZE 99999 #endif diff --git a/ui/drivers/qt/coreinfodialog.cpp b/ui/drivers/qt/coreinfodialog.cpp new file mode 100644 index 0000000000..8361bbcab9 --- /dev/null +++ b/ui/drivers/qt/coreinfodialog.cpp @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include "coreinfodialog.h" +#include "../ui_qt.h" + +extern "C" +{ +#include "../../../msg_hash.h" +} + +CoreInfoDialog::CoreInfoDialog(MainWindow *mainwindow, QWidget *parent) : + QDialog(parent) + ,m_formLayout(new QFormLayout()) + ,m_mainwindow(mainwindow) +{ + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFORMATION)); + + m_formLayout->setFormAlignment(Qt::AlignCenter); + m_formLayout->setLabelAlignment(Qt::AlignCenter); + + setLayout(new QVBoxLayout()); + + qobject_cast(layout())->addLayout(m_formLayout); + layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); + layout()->addWidget(buttonBox); +} + +void CoreInfoDialog::showCoreInfo() +{ + int row = 0; + int rowCount = m_formLayout->rowCount(); + int i = 0; + QVector > infoList = m_mainwindow->getCoreInfo(); + + if (rowCount > 0) + { + for (row = 0; row < rowCount; row++) + { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) + /* removeRow() and takeRow() was only added in 5.8! */ + m_formLayout->removeRow(0); +#else + /* something is buggy here... sometimes items appear duplicated, and other times not */ + QLayoutItem *item = m_formLayout->itemAt(0); + QWidget *w = NULL; + + if (item) + { + w = item->widget(); + + if (w) + { + QWidget *label = m_formLayout->labelForField(w); + + if (label) + delete label; + + m_formLayout->removeWidget(w); + + delete w; + } + } +#endif + } + } + + if (infoList.count() == 0) + return; + + for (i = 0; i < infoList.count(); i++) + { + const QHash &line = infoList.at(i); + QLabel *label = new QLabel(line.value("key")); + CoreInfoLabel *value = new CoreInfoLabel(line.value("value")); + QString labelStyle = line.value("label_style"); + QString valueStyle = line.value("value_style"); + + if (!labelStyle.isEmpty()) + label->setStyleSheet(labelStyle); + + if (!valueStyle.isEmpty()) + value->setStyleSheet(valueStyle); + + m_formLayout->addRow(label, value); + } + + show(); +} + diff --git a/ui/drivers/qt/coreinfodialog.h b/ui/drivers/qt/coreinfodialog.h new file mode 100644 index 0000000000..c0cb3f9f30 --- /dev/null +++ b/ui/drivers/qt/coreinfodialog.h @@ -0,0 +1,21 @@ +#ifndef COREINFODIALOG_H +#define COREINFODIALOG_H + +#include + +class QFormLayout; +class MainWindow; + +class CoreInfoDialog : public QDialog +{ + Q_OBJECT +public: + CoreInfoDialog(MainWindow *mainwindow, QWidget *parent = 0); +public slots: + void showCoreInfo(); +private: + QFormLayout *m_formLayout; + MainWindow *m_mainwindow; +}; + +#endif diff --git a/ui/drivers/qt/filedropwidget.cpp b/ui/drivers/qt/filedropwidget.cpp new file mode 100644 index 0000000000..09eaf0abed --- /dev/null +++ b/ui/drivers/qt/filedropwidget.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "filedropwidget.h" + +FileDropWidget::FileDropWidget(QWidget *parent) : + QWidget(parent) +{ + setAcceptDrops(true); +} + +void FileDropWidget::paintEvent(QPaintEvent *event) +{ + QStyleOption o; + QPainter p; + o.initFrom(this); + p.begin(this); + style()->drawPrimitive( + QStyle::PE_Widget, &o, &p, this); + p.end(); + + QWidget::paintEvent(event); +} + +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 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); + } +} + diff --git a/ui/drivers/qt/filedropwidget.h b/ui/drivers/qt/filedropwidget.h new file mode 100644 index 0000000000..9301d948df --- /dev/null +++ b/ui/drivers/qt/filedropwidget.h @@ -0,0 +1,26 @@ +#ifndef FILEDROPWIDGET_H +#define FILEDROPWIDGET_H + +#include + +class QDragEnterEvent; +class QDropEvent; +class QKeyEvent; +class QPaintEvent; + +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); + void paintEvent(QPaintEvent *event); +}; + +#endif diff --git a/ui/drivers/qt/playlist.cpp b/ui/drivers/qt/playlist.cpp new file mode 100644 index 0000000000..a3c81c3502 --- /dev/null +++ b/ui/drivers/qt/playlist.cpp @@ -0,0 +1,1149 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../ui_qt.h" +#include "flowlayout.h" +#include "playlistentrydialog.h" + +extern "C" { +#include +#include +#include +#include +#include "../../../file_path_special.h" +#include "../../../playlist.h" +#include "../../../menu/menu_displaylist.h" +#include "../../../setting_list.h" +#include "../../../configuration.h" +#include "../../../core_info.h" +#include "../../../verbosity.h" +} + +inline static bool comp_hash_name_key_lower(const QHash &lhs, const QHash &rhs) +{ + return lhs.value("name").toLower() < rhs.value("name").toLower(); +} + +inline static bool comp_hash_label_key_lower(const QHash &lhs, const QHash &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()); + } + } +} + +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 dialog(NULL); + PlaylistEntryDialog *playlistDialog = playlistEntryDialog(); + QHash selectedCore; + QHash itemToAdd; + QString selectedDatabase; + QString selectedName; + QString selectedPath; + const char *currentPlaylistData = NULL; + playlist_t *playlist = NULL; + int i; + + /* Assume a blank list means we will manually enter in all fields. */ + if (files.isEmpty()) + { + /* Make sure hash isn't blank, that would mean there's multiple entries to add at once. */ + itemToAdd["label"] = ""; + itemToAdd["path"] = ""; + } + else if (files.count() == 1) + { + QString path = files.at(0); + QFileInfo info(path); + + if (info.isFile()) + { + itemToAdd["label"] = info.completeBaseName(); + itemToAdd["path"] = path; + } + } + + if (currentItem) + { + currentPlaylistPath = currentItem->data(Qt::UserRole).toString(); + + if (!currentPlaylistPath.isEmpty()) + { + currentPlaylistArray = currentPlaylistPath.toUtf8(); + currentPlaylistData = currentPlaylistArray.constData(); + } + } + + if (currentPlaylistPath == ALL_PLAYLISTS_TOKEN) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + return; + } + + /* a blank itemToAdd means there will be multiple */ + if (!playlistDialog->showDialog(itemToAdd)) + return; + + selectedName = m_playlistEntryDialog->getSelectedName(); + selectedPath = m_playlistEntryDialog->getSelectedPath(); + selectedCore = m_playlistEntryDialog->getSelectedCore(); + selectedDatabase = m_playlistEntryDialog->getSelectedDatabase(); + + if (selectedDatabase.isEmpty()) + selectedDatabase = QFileInfo(currentPlaylistPath).fileName(); + else + selectedDatabase += file_path_str(FILE_PATH_LPL_EXTENSION); + + 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); + + if (selectedName.isEmpty() || selectedPath.isEmpty() || + selectedDatabase.isEmpty()) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + return; + } + + if (files.isEmpty()) + files.append(selectedPath); + + for (i = 0; i < files.count(); i++) + { + QString path(files.at(i)); + QFileInfo fileInfo(path); + + if (dialog->wasCanceled()) + return; + + if (i % 25 == 0) + { + /* Needed to update progress dialog while doing a lot of stuff on the main thread. */ + qApp->processEvents(); + } + + if (fileInfo.isDir()) + { + QDir dir(path); + addDirectoryFilesToList(list, dir); + continue; + } + + if (fileInfo.isFile()) + list.append(fileInfo.absoluteFilePath()); + else if (files.count() == 1) + { + /* If adding a single file, tell user that it doesn't exist. */ + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + return; + } + } + + 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; + + if (files.count() == 1 && list.count() == 1 && i == 0) + { + fileBaseNameArray = selectedName.toUtf8(); + pathArray = QDir::toNativeSeparators(selectedPath).toUtf8(); + } + else + { + fileBaseNameArray = fileInfo.completeBaseName().toUtf8(); + pathArray = QDir::toNativeSeparators(fileName).toUtf8(); + } + + fileNameNoExten = fileBaseNameArray.constData(); + + /* a modal QProgressDialog calls processEvents() automatically in setValue() */ + dialog->setValue(i + 1); + + pathData = pathArray.constData(); + + if (selectedCore.isEmpty()) + { + corePathData = "DETECT"; + coreNameData = "DETECT"; + } + else + { + corePathArray = QDir::toNativeSeparators(selectedCore.value("core_path")).toUtf8(); + coreNameArray = selectedCore.value("core_name").toUtf8(); + corePathData = corePathArray.constData(); + coreNameData = coreNameArray.constData(); + } + + 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 = QDir::toNativeSeparators(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(); +} + +bool MainWindow::updateCurrentPlaylistEntry(const QHash &contentHash) +{ + QString playlistPath = getCurrentPlaylistPath(); + QString path; + QString label; + QString corePath; + QString coreName; + QString dbName; + QString crc32; + QByteArray playlistPathArray; + QByteArray pathArray; + QByteArray labelArray; + QByteArray corePathArray; + QByteArray coreNameArray; + QByteArray dbNameArray; + QByteArray crc32Array; + const char *playlistPathData = NULL; + const char *pathData = NULL; + const char *labelData = NULL; + const char *corePathData = NULL; + const char *coreNameData = NULL; + const char *dbNameData = NULL; + const char *crc32Data = NULL; + playlist_t *playlist = NULL; + unsigned index = 0; + bool ok = false; + + if (playlistPath.isEmpty() || contentHash.isEmpty() || !contentHash.contains("index")) + return false; + + index = contentHash.value("index").toUInt(&ok); + + if (!ok) + return false; + + path = contentHash.value("path"); + label = contentHash.value("label"); + coreName = contentHash.value("core_name"); + corePath = contentHash.value("core_path"); + dbName = contentHash.value("db_name"); + crc32 = contentHash.value("crc32"); + + if (path.isEmpty() || + label.isEmpty() || + coreName.isEmpty() || + corePath.isEmpty() || + dbName.isEmpty() || + crc32.isEmpty() + ) + return false; + + playlistPathArray = playlistPath.toUtf8(); + pathArray = QDir::toNativeSeparators(path).toUtf8(); + labelArray = label.toUtf8(); + coreNameArray = coreName.toUtf8(); + corePathArray = QDir::toNativeSeparators(corePath).toUtf8(); + dbNameArray = (dbName + file_path_str(FILE_PATH_LPL_EXTENSION)).toUtf8(); + crc32Array = crc32.toUtf8(); + + playlistPathData = playlistPathArray.constData(); + pathData = pathArray.constData(); + labelData = labelArray.constData(); + coreNameData = coreNameArray.constData(); + corePathData = corePathArray.constData(); + dbNameData = dbNameArray.constData(); + crc32Data = crc32Array.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 = QDir::toNativeSeparators(QString(pathData) + "#" + list->elems[0].data).toUtf8(); + pathData = pathArray.constData(); + } + + string_list_free(list); + } + } + + playlist = playlist_init(playlistPathData, COLLECTION_SIZE); + + playlist_update(playlist, index, pathData, labelData, + corePathData, coreNameData, crc32Data, dbNameData); + playlist_write_file(playlist); + playlist_free(playlist); + + reloadPlaylists(); + + return true; +} + +void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) +{ + settings_t *settings = config_get_ptr(); + QScopedPointer menu; + QScopedPointer associateMenu; + QScopedPointer hiddenPlaylistsMenu; + QScopedPointer hideAction; + QScopedPointer newPlaylistAction; + QScopedPointer deletePlaylistAction; + QPointer selectedAction; + QPoint cursorPos = QCursor::pos(); + QListWidgetItem *selectedItem = m_listWidget->itemAt(m_listWidget->viewport()->mapFromGlobal(cursorPos)); + QDir playlistDir(settings->paths.directory_playlist); + QString playlistDirAbsPath = playlistDir.absolutePath(); + QString currentPlaylistDirPath; + QString currentPlaylistPath; + QString currentPlaylistFileName; + QFile currentPlaylistFile; + QByteArray currentPlaylistFileNameArray; + QFileInfo currentPlaylistFileInfo; + QMap coreList; + core_info_list_t *core_info_list = NULL; + union string_list_elem_attr attr = {0}; + struct string_list *stnames = NULL; + struct string_list *stcores = NULL; + unsigned i = 0; + int j = 0; + size_t found = 0; + const char *currentPlaylistFileNameData = NULL; + char new_playlist_names[PATH_MAX_LENGTH]; + char new_playlist_cores[PATH_MAX_LENGTH]; + bool specialPlaylist = false; + bool foundHiddenPlaylist = false; + + new_playlist_names[0] = new_playlist_cores[0] = '\0'; + + stnames = string_split(settings->arrays.playlist_names, ";"); + stcores = string_split(settings->arrays.playlist_cores, ";"); + + if (selectedItem) + { + currentPlaylistPath = selectedItem->data(Qt::UserRole).toString(); + currentPlaylistFile.setFileName(currentPlaylistPath); + + 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"); + + menu->addAction(newPlaylistAction.data()); + + if (currentPlaylistFile.exists()) + { + deletePlaylistAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST)) + "...", this)); + menu->addAction(deletePlaylistAction.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(); j++) + { + QListWidgetItem *item = m_listWidget->item(j); + bool hidden = m_listWidget->isItemHidden(item); + + if (hidden) + { + QAction *action = hiddenPlaylistsMenu->addAction(item->text()); + action->setProperty("row", j); + action->setProperty("core_path", item->data(Qt::UserRole).toString()); + foundHiddenPlaylist = true; + } + } + + if (!foundHiddenPlaylist) + { + QAction *action = hiddenPlaylistsMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE)); + action->setProperty("row", -1); + } + + menu->addMenu(hiddenPlaylistsMenu.data()); + + if (currentPlaylistDirPath != playlistDirAbsPath) + { + /* special playlists like history etc. can't have an association */ + specialPlaylist = true; + } + + if (!specialPlaylist) + { + associateMenu.reset(new QMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ASSOCIATE_CORE), this)); + associateMenu->setObjectName("associateMenu"); + + core_info_get_list(&core_info_list); + + for (i = 0; i < core_info_list->count && core_info_list->count > 0; i++) + { + const core_info_t *core = &core_info_list->list[i]; + coreList[core->core_name] = core; + } + + { + QMapIterator coreListIterator(coreList); + QVector > cores; + + while (coreListIterator.hasNext()) + { + QString key; + const core_info_t *core = NULL; + QString name; + QHash hash; + + coreListIterator.next(); + + key = coreListIterator.key(); + core = coreList.value(key); + + if (string_is_empty(core->core_name)) + name = core->display_name; + else + name = core->core_name; + + if (name.isEmpty()) + continue; + + hash["name"] = name; + hash["core_path"] = core->path; + + cores.append(hash); + } + + std::sort(cores.begin(), cores.end(), comp_hash_name_key_lower); + + for (j = 0; j < cores.count(); j++) + { + const QHash &hash = cores.at(j); + QAction *action = associateMenu->addAction(hash.value("name")); + + action->setProperty("core_path", hash.value("core_path")); + } + } + + menu->addMenu(associateMenu.data()); + } + + selectedAction = menu->exec(cursorPos); + + if (!selectedAction) + goto end; + + if (!specialPlaylist && selectedAction->parent() == associateMenu.data()) + { + found = string_list_find_elem(stnames, currentPlaylistFileNameData); + + if (found) + string_list_set(stcores, static_cast(found - 1), selectedAction->property("core_path").toString().toUtf8().constData()); + else + { + string_list_append(stnames, currentPlaylistFileNameData, attr); + string_list_append(stcores, "DETECT", attr); + + found = string_list_find_elem(stnames, currentPlaylistFileNameData); + + if (found) + string_list_set(stcores, static_cast(found - 1), selectedAction->property("core_path").toString().toUtf8().constData()); + } + + string_list_join_concat(new_playlist_names, + sizeof(new_playlist_names), stnames, ";"); + string_list_join_concat(new_playlist_cores, + sizeof(new_playlist_cores), stcores, ";"); + + strlcpy(settings->arrays.playlist_names, + new_playlist_names, sizeof(settings->arrays.playlist_names)); + strlcpy(settings->arrays.playlist_cores, + new_playlist_cores, sizeof(settings->arrays.playlist_cores)); + } + else if (selectedAction == deletePlaylistAction.data()) + { + if (currentPlaylistFile.exists()) + { + if (showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST)).arg(selectedItem->text()), MainWindow::MSGBOX_TYPE_QUESTION_YESNO, Qt::ApplicationModal, false)) + { + if (currentPlaylistFile.remove()) + reloadPlaylists(); + else + 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); + + if (row >= 0) + { + QStringList hiddenPlaylists = m_settings->value("hidden_playlists").toStringList(); + + if (!hiddenPlaylists.contains(currentPlaylistFileName)) + { + hiddenPlaylists.append(currentPlaylistFileName); + m_settings->setValue("hidden_playlists", hiddenPlaylists); + } + + m_listWidget->setRowHidden(row, true); + } + } + else if (selectedAction->parent() == hiddenPlaylistsMenu.data()) + { + QVariant rowVariant = selectedAction->property("row"); + + if (rowVariant.isValid()) + { + QStringList hiddenPlaylists = m_settings->value("hidden_playlists").toStringList(); + int row = rowVariant.toInt(); + + if (row >= 0) + { + QString playlistPath = selectedAction->property("core_path").toString(); + QFileInfo playlistFileInfo(playlistPath); + QString playlistFileName = playlistFileInfo.fileName(); + + if (hiddenPlaylists.contains(playlistFileName)) + { + hiddenPlaylists.removeOne(playlistFileName); + m_settings->setValue("hidden_playlists", hiddenPlaylists); + } + + m_listWidget->setRowHidden(row, false); + } + } + } + + setCoreActions(); + +end: + if (stnames) + string_list_free(stnames); + if (stcores) + string_list_free(stcores); +} + +void MainWindow::deferReloadPlaylists() +{ + emit gotReloadPlaylists(); +} + +void MainWindow::onGotReloadPlaylists() +{ + reloadPlaylists(); +} + +void MainWindow::reloadPlaylists() +{ + QListWidgetItem *allPlaylistsItem = NULL; + QListWidgetItem *favoritesPlaylistsItem = NULL; + QListWidgetItem *imagePlaylistsItem = NULL; + QListWidgetItem *musicPlaylistsItem = NULL; + QListWidgetItem *videoPlaylistsItem = NULL; + QListWidgetItem *firstItem = NULL; + QListWidgetItem *currentItem = NULL; + settings_t *settings = config_get_ptr(); + QDir playlistDir(settings->paths.directory_playlist); + QString currentPlaylistPath; + QStringList hiddenPlaylists = m_settings->value("hidden_playlists").toStringList(); + int i = 0; + + currentItem = m_listWidget->currentItem(); + + if (currentItem) + { + currentPlaylistPath = currentItem->data(Qt::UserRole).toString(); + } + + getPlaylistFiles(); + + m_listWidget->clear(); + + allPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ALL_PLAYLISTS)); + allPlaylistsItem->setData(Qt::UserRole, ALL_PLAYLISTS_TOKEN); + + favoritesPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FAVORITES_TAB)); + favoritesPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_favorites); + + m_historyPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HISTORY_TAB)); + m_historyPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_history); + + imagePlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_IMAGES_TAB)); + imagePlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_image_history); + + musicPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MUSIC_TAB)); + musicPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_music_history); + + videoPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_TAB)); + videoPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_video_history); + + m_listWidget->addItem(allPlaylistsItem); + m_listWidget->addItem(favoritesPlaylistsItem); + m_listWidget->addItem(m_historyPlaylistsItem); + m_listWidget->addItem(imagePlaylistsItem); + m_listWidget->addItem(musicPlaylistsItem); + m_listWidget->addItem(videoPlaylistsItem); + + if (hiddenPlaylists.contains(ALL_PLAYLISTS_TOKEN)) + m_listWidget->setRowHidden(m_listWidget->row(allPlaylistsItem), true); + if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_favorites).fileName())) + m_listWidget->setRowHidden(m_listWidget->row(favoritesPlaylistsItem), true); + if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_history).fileName())) + m_listWidget->setRowHidden(m_listWidget->row(m_historyPlaylistsItem), true); + if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_image_history).fileName())) + m_listWidget->setRowHidden(m_listWidget->row(imagePlaylistsItem), true); + if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_music_history).fileName())) + m_listWidget->setRowHidden(m_listWidget->row(musicPlaylistsItem), true); + 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(); i++) + { + QListWidgetItem *item = NULL; + const QString &file = m_playlistFiles.at(i); + QString fileDisplayName = file; + QString fileName = file; + bool hasIcon = false; + QIcon icon; + QString iconPath; + + fileDisplayName.remove(file_path_str(FILE_PATH_LPL_EXTENSION)); + + iconPath = QString(settings->paths.directory_assets) + ICON_PATH + fileDisplayName + ".png"; + + hasIcon = QFile::exists(iconPath); + + if (hasIcon) + icon = QIcon(iconPath); + else + icon = m_folderIcon; + + item = new QListWidgetItem(icon, fileDisplayName); + item->setData(Qt::UserRole, playlistDir.absoluteFilePath(file)); + + m_listWidget->addItem(item); + + if (hiddenPlaylists.contains(fileName)) + { + int row = m_listWidget->row(item); + + if (row >= 0) + m_listWidget->setRowHidden(row, true); + } + } + + if (m_listWidget->count() > 0) + { + firstItem = m_listWidget->item(0); + + if (firstItem) + { + bool found = false; + + for (i = 0; i < m_listWidget->count(); i++) + { + QListWidgetItem *item = m_listWidget->item(i); + QString path; + + if (item) + { + path = item->data(Qt::UserRole).toString(); + + if (!currentPlaylistPath.isEmpty() && !path.isEmpty()) + { + if (path == currentPlaylistPath) + { + found = true; + m_listWidget->setCurrentItem(item); + break; + } + } + } + } + + /* the previous playlist must be gone now, just select the first one */ + if (!found) + m_listWidget->setCurrentItem(firstItem); + } + } +} + +QString MainWindow::getCurrentPlaylistPath() +{ + QListWidgetItem *playlistItem = m_listWidget->currentItem(); + QHash contentHash; + QString playlistPath; + + if (!playlistItem) + return playlistPath; + + playlistPath = playlistItem->data(Qt::UserRole).toString(); + + return playlistPath; +} + +void MainWindow::deleteCurrentPlaylistItem() +{ + QString playlistPath = getCurrentPlaylistPath(); + QByteArray playlistArray; + QHash contentHash = getCurrentContentHash(); + playlist_t *playlist = NULL; + const char *playlistData = NULL; + unsigned index = 0; + bool ok = false; + + if (playlistPath.isEmpty()) + return; + + if (contentHash.isEmpty()) + return; + + playlistArray = playlistPath.toUtf8(); + playlistData = playlistArray.constData(); + + index = contentHash.value("index").toUInt(&ok); + + if (!ok) + return; + + if (!showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM)).arg(contentHash["label"]), MainWindow::MSGBOX_TYPE_QUESTION_YESNO, Qt::ApplicationModal, false)) + return; + + playlist = playlist_init(playlistData, COLLECTION_SIZE); + + playlist_delete_index(playlist, index); + playlist_write_file(playlist); + playlist_free(playlist); + + reloadPlaylists(); +} + +QVector > MainWindow::getPlaylistDefaultCores() +{ + settings_t *settings = config_get_ptr(); + struct string_list *playlists = string_split(settings->arrays.playlist_names, ";"); + struct string_list *cores = string_split(settings->arrays.playlist_cores, ";"); + unsigned i = 0; + QVector > coreList; + + if (!playlists || !cores) + { + RARCH_WARN("[Qt]: Could not parse one of playlist_names or playlist_cores\n"); + goto finish; + } + else if (playlists->size != cores->size) + { + RARCH_WARN("[Qt]: playlist_names array size differs from playlist_cores\n"); + goto finish; + } + + if (playlists->size == 0) + goto finish; + + for (i = 0; i < playlists->size; i++) + { + const char *playlist = playlists->elems[i].data; + const char *core = cores->elems[i].data; + QHash hash; + + hash["playlist_filename"] = playlist; + hash["playlist_filename"].remove(file_path_str(FILE_PATH_LPL_EXTENSION)); + hash["core_path"] = core; + + coreList.append(hash); + } + +finish: + if (playlists) + string_list_free(playlists); + if (cores) + string_list_free(cores); + + return coreList; +} + +void MainWindow::getPlaylistFiles() +{ + settings_t *settings = config_get_ptr(); + QDir playlistDir(settings->paths.directory_playlist); + + m_playlistFiles = playlistDir.entryList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Files, QDir::Name); +} + +void MainWindow::addPlaylistItemsToGrid(const QStringList &paths, bool add) +{ + QVector > items; + int i; + + if (paths.isEmpty()) + return; + + for (i = 0; i < paths.size(); i++) + { + int j; + QVector > vec = getPlaylistItems(paths.at(i)); + /* QVector::append() wasn't added until 5.5, so just do it the old fashioned way */ + for (j = 0; j < vec.size(); j++) + { + if (add && m_allPlaylistsGridMaxCount > 0 && items.size() >= m_allPlaylistsGridMaxCount) + goto finish; + + items.append(vec.at(j)); + } + } +finish: + std::sort(items.begin(), items.end(), comp_hash_label_key_lower); + + addPlaylistHashToGrid(items); +} + +void MainWindow::addPlaylistHashToGrid(const QVector > &items) +{ + QScreen *screen = qApp->primaryScreen(); + QSize screenSize = screen->size(); + QListWidgetItem *currentItem = m_listWidget->currentItem(); + settings_t *settings = config_get_ptr(); + int i = 0; + int zoomValue = m_zoomSlider->value(); + + m_gridProgressBar->setMinimum(0); + m_gridProgressBar->setMaximum(qMax(0, items.count() - 1)); + m_gridProgressBar->setValue(0); + + for (i = 0; i < items.count(); i++) + { + const QHash &hash = items.at(i); + QPointer item; + QPointer label; + QString thumbnailFileNameNoExt; + QLabel *newLabel = NULL; + QSize thumbnailWidgetSizeHint(screenSize.width() / 8, screenSize.height() / 8); + QByteArray extension; + QString extensionStr; + QString imagePath; + int lastIndex = -1; + + if (m_listWidget->currentItem() != currentItem) + { + /* user changed the current playlist before we finished loading... abort */ + m_gridProgressWidget->hide(); + break; + } + + item = new GridItem(); + + lastIndex = hash["path"].lastIndexOf('.'); + + if (lastIndex >= 0) + { + extensionStr = hash["path"].mid(lastIndex + 1); + + if (!extensionStr.isEmpty()) + { + extension = extensionStr.toLower().toUtf8(); + } + } + + if (!extension.isEmpty() && m_imageFormats.contains(extension)) + { + /* use thumbnail widgets to show regular image files */ + imagePath = hash["path"]; + } + else + { + thumbnailFileNameNoExt = hash["label_noext"]; + thumbnailFileNameNoExt.replace(m_fileSanitizerRegex, "_"); + imagePath = QString(settings->paths.directory_thumbnails) + "/" + hash.value("db_name") + "/" + THUMBNAIL_BOXART + "/" + thumbnailFileNameNoExt + ".png"; + } + + item->hash = hash; + item->widget = new ThumbnailWidget(); + item->widget->setSizeHint(thumbnailWidgetSizeHint); + item->widget->setFixedSize(item->widget->sizeHint()); + item->widget->setLayout(new QVBoxLayout()); + item->widget->setObjectName("thumbnailWidget"); + item->widget->setProperty("hash", QVariant::fromValue >(hash)); + + connect(item->widget, SIGNAL(mouseDoubleClicked()), this, SLOT(onGridItemDoubleClicked())); + connect(item->widget, SIGNAL(mousePressed()), this, SLOT(onGridItemClicked())); + + label = new ThumbnailLabel(item->widget); + label->setObjectName("thumbnailGridLabel"); + + item->label = label; + item->labelText = hash.value("label"); + + newLabel = new QLabel(item->labelText, item->widget); + newLabel->setObjectName("thumbnailQLabel"); + newLabel->setAlignment(Qt::AlignCenter); + newLabel->setToolTip(item->labelText); + + calcGridItemSize(item, zoomValue); + + item->widget->layout()->addWidget(label); + + item->widget->layout()->addWidget(newLabel); + qobject_cast(item->widget->layout())->setStretchFactor(label, 1); + + m_gridLayout->addWidgetDeferred(item->widget); + m_gridItems.append(item); + + loadImageDeferred(item, imagePath); + + if (i % 25 == 0) + { + /* Needed to update progress dialog while doing a lot of stuff on the main thread. */ + qApp->processEvents(); + } + + m_gridProgressBar->setValue(i); + } + + /* If there's only one entry, a min/max/value of all zero would make an indeterminate progress bar that never ends... so just hide it when we are done. */ + if (m_gridProgressBar->value() == m_gridProgressBar->maximum()) + m_gridProgressWidget->hide(); +} + +QVector > MainWindow::getPlaylistItems(QString pathString) +{ + QByteArray pathArray; + QVector > items; + const char *pathData = NULL; + playlist_t *playlist = NULL; + unsigned playlistSize = 0; + unsigned i = 0; + + pathArray.append(pathString); + pathData = pathArray.constData(); + + playlist = playlist_init(pathData, COLLECTION_SIZE); + playlistSize = playlist_get_size(playlist); + + for (i = 0; i < playlistSize; i++) + { + const char *path = NULL; + const char *label = NULL; + const char *core_path = NULL; + const char *core_name = NULL; + const char *crc32 = NULL; + const char *db_name = NULL; + QHash hash; + + playlist_get_index(playlist, i, + &path, &label, &core_path, + &core_name, &crc32, &db_name); + + if (string_is_empty(path)) + continue; + else + hash["path"] = path; + + hash["index"] = QString::number(i); + + if (string_is_empty(label)) + { + hash["label"] = path; + hash["label_noext"] = path; + } + else + { + hash["label"] = label; + hash["label_noext"] = label; + } + + if (!string_is_empty(core_path)) + hash["core_path"] = core_path; + + if (!string_is_empty(core_name)) + hash["core_name"] = core_name; + + if (!string_is_empty(crc32)) + hash["crc32"] = crc32; + + if (!string_is_empty(db_name)) + { + hash["db_name"] = db_name; + hash["db_name"].remove(file_path_str(FILE_PATH_LPL_EXTENSION)); + } + + items.append(hash); + } + + playlist_free(playlist); + playlist = NULL; + + return items; +} + +void MainWindow::addPlaylistItemsToTable(const QStringList &paths, bool add) +{ + QVector > items; + int i; + + if (paths.isEmpty()) + return; + + for (i = 0; i < paths.size(); i++) + { + int j; + QVector > vec = getPlaylistItems(paths.at(i)); + /* QVector::append() wasn't added until 5.5, so just do it the old fashioned way */ + for (j = 0; j < vec.size(); j++) + { + if (add && m_allPlaylistsListMaxCount > 0 && items.size() >= m_allPlaylistsListMaxCount) + goto finish; + + items.append(vec.at(j)); + } + } +finish: + addPlaylistHashToTable(items); +} + +void MainWindow::addPlaylistHashToTable(const QVector > &items) +{ + int i = 0; + int oldRowCount = m_tableWidget->rowCount(); + + m_tableWidget->setRowCount(oldRowCount + items.count()); + + for (i = 0; i < items.count(); i++) + { + QTableWidgetItem *labelItem = NULL; + const QHash &hash = items.at(i); + + labelItem = new QTableWidgetItem(hash.value("label")); + labelItem->setData(Qt::UserRole, QVariant::fromValue >(hash)); + labelItem->setFlags(labelItem->flags() & ~Qt::ItemIsEditable); + + m_tableWidget->setItem(oldRowCount + i, 0, labelItem); + } +} + +void MainWindow::setAllPlaylistsListMaxCount(int count) +{ + if (count < 1) + count = 0; + + m_allPlaylistsListMaxCount = count; +} + +void MainWindow::setAllPlaylistsGridMaxCount(int count) +{ + if (count < 1) + count = 0; + + m_allPlaylistsGridMaxCount = count; +} + diff --git a/ui/drivers/qt/playlistentrydialog.cpp b/ui/drivers/qt/playlistentrydialog.cpp new file mode 100644 index 0000000000..d28dcf4000 --- /dev/null +++ b/ui/drivers/qt/playlistentrydialog.cpp @@ -0,0 +1,259 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "playlistentrydialog.h" +#include "../ui_qt.h" + +extern "C" { +#include "../../../core_info.h" +#include "../../../file_path_special.h" +} + +inline static bool comp_string_lower(const QString &lhs, const QString &rhs) +{ + return lhs.toLower() < rhs.toLower(); +} + +inline static bool comp_hash_ui_display_name_key_lower(const QHash &lhs, const QHash &rhs) +{ + return lhs.value("ui_display_name").toLower() < rhs.value("ui_display_name").toLower(); +} + +PlaylistEntryDialog::PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent) : + QDialog(parent) + ,m_mainwindow(mainwindow) + ,m_settings(mainwindow->settings()) + ,m_nameLineEdit(new QLineEdit(this)) + ,m_pathLineEdit(new QLineEdit(this)) + ,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(); + QHBoxLayout *pathHBoxLayout = new QHBoxLayout(); + QLabel *databaseLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS), this); + QToolButton *pathPushButton = new QToolButton(this); + + pathPushButton->setText("..."); + + pathHBoxLayout->addWidget(m_pathLineEdit); + pathHBoxLayout->addWidget(pathPushButton); + + 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_NAME), m_nameLineEdit); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_PATH), pathHBoxLayout); + 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(layout())->addLayout(form); + layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); + layout()->addWidget(buttonBox); + + connect(pathPushButton, SIGNAL(clicked()), this, SLOT(onPathClicked())); +} + +void PlaylistEntryDialog::onPathClicked() +{ + QString filePath = QFileDialog::getOpenFileName(this); + + if (filePath.isEmpty()) + return; + + m_pathLineEdit->setText(filePath); +} + +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_nameLineEdit->clear(); + m_pathLineEdit->clear(); + 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) + ">", QFileInfo(m_mainwindow->getCurrentPlaylistPath()).fileName().remove(file_path_str(FILE_PATH_LPL_EXTENSION))); + + core_info_get_list(&core_info_list); + + if (core_info_list && core_info_list->count > 0) + { + QVector > 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 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 &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); + } + } +} + +void PlaylistEntryDialog::setEntryValues(const QHash &contentHash) +{ + QString db; + QString coreName = contentHash.value("core_name"); + int foundDB = 0; + int i = 0; + + loadPlaylistOptions(); + + if (contentHash.isEmpty()) + { + m_nameLineEdit->setText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FIELD_MULTIPLE)); + m_pathLineEdit->setText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FIELD_MULTIPLE)); + m_nameLineEdit->setEnabled(false); + m_pathLineEdit->setEnabled(false); + } + else + { + m_nameLineEdit->setEnabled(true); + m_pathLineEdit->setEnabled(true); + m_nameLineEdit->setText(contentHash.value("label")); + m_pathLineEdit->setText(contentHash.value("path")); + } + + for (i = 0; i < m_coreComboBox->count(); i++) + { + const QHash hash = m_coreComboBox->itemData(i, Qt::UserRole).value >(); + + if (hash.isEmpty() || coreName.isEmpty()) + continue; + + if (hash.value("core_name") == coreName) + { + m_coreComboBox->setCurrentIndex(i); + break; + } + } + + db = contentHash.value("db_name"); + + if (!db.isEmpty()) + { + foundDB = m_databaseComboBox->findText(db); + + if (foundDB >= 0) + m_databaseComboBox->setCurrentIndex(foundDB); + } +} + +const QHash PlaylistEntryDialog::getSelectedCore() +{ + return m_coreComboBox->currentData(Qt::UserRole).value >(); +} + +const QString PlaylistEntryDialog::getSelectedName() +{ + return m_nameLineEdit->text(); +} + +const QString PlaylistEntryDialog::getSelectedPath() +{ + return m_pathLineEdit->text(); +} + +const QString PlaylistEntryDialog::getSelectedDatabase() +{ + return m_databaseComboBox->currentData(Qt::UserRole).toString(); +} + +void PlaylistEntryDialog::onAccepted() +{ +} + +void PlaylistEntryDialog::onRejected() +{ +} + +bool PlaylistEntryDialog::showDialog(const QHash &hash) +{ + loadPlaylistOptions(); + setEntryValues(hash); + + if (exec() == QDialog::Accepted) + return true; + + return false; +} + +void PlaylistEntryDialog::hideDialog() +{ + reject(); +} + diff --git a/ui/drivers/qt/playlistentrydialog.h b/ui/drivers/qt/playlistentrydialog.h new file mode 100644 index 0000000000..723f46304e --- /dev/null +++ b/ui/drivers/qt/playlistentrydialog.h @@ -0,0 +1,39 @@ +#ifndef PLAYLISTENTRYDIALOG_H +#define PLAYLISTENTRYDIALOG_H + +#include + +class QSettings; +class QLineEdit; +class QComboBox; +class MainWindow; + +class PlaylistEntryDialog : public QDialog +{ + Q_OBJECT +public: + PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent = 0); + const QHash getSelectedCore(); + const QString getSelectedDatabase(); + const QString getSelectedName(); + const QString getSelectedPath(); + void setEntryValues(const QHash &contentHash); +public slots: + bool showDialog(const QHash &hash = QHash()); + void hideDialog(); + void onAccepted(); + void onRejected(); +private slots: + void onPathClicked(); +private: + void loadPlaylistOptions(); + + MainWindow *m_mainwindow; + QSettings *m_settings; + QLineEdit *m_nameLineEdit; + QLineEdit *m_pathLineEdit; + QComboBox *m_coreComboBox; + QComboBox *m_databaseComboBox; +}; + +#endif diff --git a/ui/drivers/qt/shaderparamsdialog.cpp b/ui/drivers/qt/shaderparamsdialog.cpp new file mode 100644 index 0000000000..43dc6876ce --- /dev/null +++ b/ui/drivers/qt/shaderparamsdialog.cpp @@ -0,0 +1,27 @@ +#include +#include +#include "shaderparamsdialog.h" + +ShaderParamsDialog::ShaderParamsDialog(QWidget *parent) : + QDialog(parent) +{ +} + +ShaderParamsDialog::~ShaderParamsDialog() +{ +} + +void ShaderParamsDialog::resizeEvent(QResizeEvent *event) +{ + QDialog::resizeEvent(event); + + emit resized(event->size()); +} + +void ShaderParamsDialog::closeEvent(QCloseEvent *event) +{ + QDialog::closeEvent(event); + + emit closed(); +} + diff --git a/ui/drivers/qt/shaderparamsdialog.h b/ui/drivers/qt/shaderparamsdialog.h new file mode 100644 index 0000000000..f2b98a8118 --- /dev/null +++ b/ui/drivers/qt/shaderparamsdialog.h @@ -0,0 +1,23 @@ +#ifndef SHADERPARAMSDIALOG_H +#define SHADERPARAMSDIALOG_H + +#include + +class QCloseEvent; +class QResizeEvent; + +class ShaderParamsDialog : public QDialog +{ + Q_OBJECT +public: + ShaderParamsDialog(QWidget *parent = 0); + ~ShaderParamsDialog(); +signals: + void closed(); + void resized(QSize size); +protected: + void closeEvent(QCloseEvent *event); + void resizeEvent(QResizeEvent *event); +}; + +#endif diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index 2f09752689..44583f313a 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -40,10 +40,15 @@ #include #include "../ui_qt.h" +#include "invader_png.h" #include "ui_qt_load_core_window.h" #include "ui_qt_themes.h" #include "flowlayout.h" -#include "invader_png.h" +#include "shaderparamsdialog.h" +#include "filedropwidget.h" +#include "coreinfodialog.h" +#include "playlistentrydialog.h" +#include "viewoptionsdialog.h" extern "C" { #include "../../../version.h" @@ -57,9 +62,11 @@ extern "C" { #include "../../../file_path_special.h" #include "../../../playlist.h" #include "../../../content.h" +#ifdef HAVE_MENU #include "../../../menu/menu_driver.h" -#include "../../../tasks/tasks_internal.h" +#endif #include "../../../config.def.h" +#include "../../../tasks/tasks_internal.h" #include #include #include @@ -78,21 +85,14 @@ extern "C" { #endif #define GENERIC_FOLDER_ICON "/xmb/dot-art/png/folder.png" -#define ICON_PATH "/xmb/dot-art/png/" -#define THUMBNAIL_BOXART "Named_Boxarts" #define THUMBNAIL_SCREENSHOT "Named_Snaps" #define THUMBNAIL_TITLE "Named_Titles" -#define ALL_PLAYLISTS_TOKEN "|||ALL|||" #define HIRAGANA_START 0x3041U #define HIRAGANA_END 0x3096U #define KATAKANA_START 0x30A1U #define KATAKANA_END 0x30F6U #define HIRA_KATA_OFFSET (KATAKANA_START - HIRAGANA_START) -#define USER_AGENT "RetroArch-WIMP/1.0" #define DOCS_URL "http://docs.libretro.com/" -#define PARTIAL_EXTENSION ".partial" -#define TEMP_EXTENSION ".update_tmp" -#define RETROARCH_NIGHTLY_UPDATE_PATH "../RetroArch_update.zip" static ui_window_qt_t ui_window = {0}; @@ -105,6 +105,14 @@ enum CoreSelection CORE_SELECTION_LOAD_CORE }; +static const QPixmap getInvader() +{ + QPixmap pix; + pix.loadFromData(invader_png, invader_png_len, "PNG"); + + return pix; +} + static double lerp(double x, double y, double a, double b, double d) { return a + (b - a) * ((double)(d - x) / (double)(y - x)); } @@ -135,9 +143,9 @@ static void scan_finished_handler(void *task_data, void *user_data, const char * (void)task_data; (void)user_data; (void)err; - +#ifdef HAVE_MENU menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); - +#endif if (!ui_window.qtWindow->settings()->value("scan_finish_confirm", true).toBool()) return; @@ -148,51 +156,6 @@ static void scan_finished_handler(void *task_data, void *user_data, const char * } #endif -inline static bool comp_string_lower(const QString &lhs, const QString &rhs) -{ - return lhs.toLower() < rhs.toLower(); -} - -inline static bool comp_hash_ui_display_name_key_lower(const QHash &lhs, const QHash &rhs) -{ - return lhs.value("ui_display_name").toLower() < rhs.value("ui_display_name").toLower(); -} - -inline static bool comp_hash_name_key_lower(const QHash &lhs, const QHash &rhs) -{ - return lhs.value("name").toLower() < rhs.value("name").toLower(); -} - -inline static bool comp_hash_label_key_lower(const QHash &lhs, const QHash &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) { @@ -202,31 +165,6 @@ static void setElidedText(QLabel *label, QWidget *clipWidget, int padding, const label->setText(clippedText); } -const QPixmap getInvader(); - -ShaderParamsDialog::ShaderParamsDialog(QWidget *parent) : - QDialog(parent) -{ -} - -ShaderParamsDialog::~ShaderParamsDialog() -{ -} - -void ShaderParamsDialog::resizeEvent(QResizeEvent *event) -{ - QDialog::resizeEvent(event); - - emit resized(event->size()); -} - -void ShaderParamsDialog::closeEvent(QCloseEvent *event) -{ - QDialog::closeEvent(event); - - emit closed(); -} - GridItem::GridItem() : QObject() ,widget(NULL) @@ -258,65 +196,6 @@ void TreeView::selectionChanged(const QItemSelection &selected, const QItemSelec emit itemsSelected(list); } -FileDropWidget::FileDropWidget(QWidget *parent) : - QWidget(parent) -{ - setAcceptDrops(true); -} - -void FileDropWidget::paintEvent(QPaintEvent *event) -{ - QStyleOption o; - QPainter p; - o.initFrom(this); - p.begin(this); - style()->drawPrimitive( - QStyle::PE_Widget, &o, &p, this); - p.end(); - - QWidget::paintEvent(event); -} - -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 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) { @@ -344,518 +223,6 @@ CoreInfoLabel::CoreInfoLabel(QString text, QWidget *parent) : setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); } -CoreInfoDialog::CoreInfoDialog(MainWindow *mainwindow, QWidget *parent) : - QDialog(parent) - ,m_formLayout(new QFormLayout()) - ,m_mainwindow(mainwindow) -{ - QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); - - connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - - setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFORMATION)); - - m_formLayout->setFormAlignment(Qt::AlignCenter); - m_formLayout->setLabelAlignment(Qt::AlignCenter); - - setLayout(new QVBoxLayout()); - - qobject_cast(layout())->addLayout(m_formLayout); - layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); - layout()->addWidget(buttonBox); -} - -void CoreInfoDialog::showCoreInfo() -{ - int row = 0; - int rowCount = m_formLayout->rowCount(); - int i = 0; - QVector > infoList = m_mainwindow->getCoreInfo(); - - if (rowCount > 0) - { - for (row = 0; row < rowCount; row++) - { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - /* removeRow() and takeRow() was only added in 5.8! */ - m_formLayout->removeRow(0); -#else - /* something is buggy here... sometimes items appear duplicated, and other times not */ - QLayoutItem *item = m_formLayout->itemAt(0); - QWidget *w = NULL; - - if (item) - { - w = item->widget(); - - if (w) - { - QWidget *label = m_formLayout->labelForField(w); - - if (label) - delete label; - - m_formLayout->removeWidget(w); - - delete w; - } - } -#endif - } - } - - if (infoList.count() == 0) - return; - - for (i = 0; i < infoList.count(); i++) - { - const QHash &line = infoList.at(i); - QLabel *label = new QLabel(line.value("key")); - CoreInfoLabel *value = new CoreInfoLabel(line.value("value")); - QString labelStyle = line.value("label_style"); - QString valueStyle = line.value("value_style"); - - if (!labelStyle.isEmpty()) - label->setStyleSheet(labelStyle); - - if (!valueStyle.isEmpty()) - value->setStyleSheet(valueStyle); - - m_formLayout->addRow(label, value); - } - - show(); -} - -PlaylistEntryDialog::PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent) : - QDialog(parent) - ,m_mainwindow(mainwindow) - ,m_settings(mainwindow->settings()) - ,m_nameLineEdit(new QLineEdit(this)) - ,m_pathLineEdit(new QLineEdit(this)) - ,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(); - QHBoxLayout *pathHBoxLayout = new QHBoxLayout(); - QLabel *databaseLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS), this); - QToolButton *pathPushButton = new QToolButton(this); - - pathPushButton->setText("..."); - - pathHBoxLayout->addWidget(m_pathLineEdit); - pathHBoxLayout->addWidget(pathPushButton); - - 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_NAME), m_nameLineEdit); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_PATH), pathHBoxLayout); - 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(layout())->addLayout(form); - layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); - layout()->addWidget(buttonBox); - - connect(pathPushButton, SIGNAL(clicked()), this, SLOT(onPathClicked())); -} - -void PlaylistEntryDialog::onPathClicked() -{ - QString filePath = QFileDialog::getOpenFileName(this); - - if (filePath.isEmpty()) - return; - - m_pathLineEdit->setText(filePath); -} - -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_nameLineEdit->clear(); - m_pathLineEdit->clear(); - 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) + ">", QFileInfo(m_mainwindow->getCurrentPlaylistPath()).fileName().remove(file_path_str(FILE_PATH_LPL_EXTENSION))); - - core_info_get_list(&core_info_list); - - if (core_info_list && core_info_list->count > 0) - { - QVector > 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 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 &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); - } - } -} - -void PlaylistEntryDialog::setEntryValues(const QHash &contentHash) -{ - QString db; - QString coreName = contentHash.value("core_name"); - int foundDB = 0; - int i = 0; - - loadPlaylistOptions(); - - if (contentHash.isEmpty()) - { - m_nameLineEdit->setText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FIELD_MULTIPLE)); - m_pathLineEdit->setText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FIELD_MULTIPLE)); - m_nameLineEdit->setEnabled(false); - m_pathLineEdit->setEnabled(false); - } - else - { - m_nameLineEdit->setEnabled(true); - m_pathLineEdit->setEnabled(true); - m_nameLineEdit->setText(contentHash.value("label")); - m_pathLineEdit->setText(contentHash.value("path")); - } - - for (i = 0; i < m_coreComboBox->count(); i++) - { - const QHash hash = m_coreComboBox->itemData(i, Qt::UserRole).value >(); - - if (hash.isEmpty() || coreName.isEmpty()) - continue; - - if (hash.value("core_name") == coreName) - { - m_coreComboBox->setCurrentIndex(i); - break; - } - } - - db = contentHash.value("db_name"); - - if (!db.isEmpty()) - { - foundDB = m_databaseComboBox->findText(db); - - if (foundDB >= 0) - m_databaseComboBox->setCurrentIndex(foundDB); - } -} - -const QHash PlaylistEntryDialog::getSelectedCore() -{ - return m_coreComboBox->currentData(Qt::UserRole).value >(); -} - -const QString PlaylistEntryDialog::getSelectedName() -{ - return m_nameLineEdit->text(); -} - -const QString PlaylistEntryDialog::getSelectedPath() -{ - return m_pathLineEdit->text(); -} - -const QString PlaylistEntryDialog::getSelectedDatabase() -{ - return m_databaseComboBox->currentData(Qt::UserRole).toString(); -} - -void PlaylistEntryDialog::onAccepted() -{ -} - -void PlaylistEntryDialog::onRejected() -{ -} - -bool PlaylistEntryDialog::showDialog(const QHash &hash) -{ - loadPlaylistOptions(); - setEntryValues(hash); - - if (exec() == QDialog::Accepted) - return true; - - return false; -} - -void PlaylistEntryDialog::hideDialog() -{ - reject(); -} - -ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) : - QDialog(parent) - ,m_mainwindow(mainwindow) - ,m_settings(mainwindow->settings()) - ,m_saveGeometryCheckBox(new QCheckBox(this)) - ,m_saveDockPositionsCheckBox(new QCheckBox(this)) - ,m_saveLastTabCheckBox(new QCheckBox(this)) - ,m_showHiddenFilesCheckBox(new QCheckBox(this)) - ,m_themeComboBox(new QComboBox(this)) - ,m_highlightColorPushButton(new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CHOOSE), this)) - ,m_highlightColor() - ,m_highlightColorLabel(new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_HIGHLIGHT_COLOR), this)) - ,m_customThemePath() - ,m_suggestLoadedCoreFirstCheckBox(new QCheckBox(this)) - ,m_allPlaylistsListMaxCountSpinBox(new QSpinBox(this)) - ,m_allPlaylistsGridMaxCountSpinBox(new QSpinBox(this)) -{ - QFormLayout *form = new QFormLayout(); - QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - - setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_TITLE)); - - m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_SYSTEM_DEFAULT), MainWindow::THEME_SYSTEM_DEFAULT); - m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_DARK), MainWindow::THEME_DARK); - m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_CUSTOM), MainWindow::THEME_CUSTOM); - - m_allPlaylistsListMaxCountSpinBox->setRange(0, 99999); - m_allPlaylistsGridMaxCountSpinBox->setRange(0, 99999); - - 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_MENU_VIEW_OPTIONS_SAVE_GEOMETRY), m_saveGeometryCheckBox); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_DOCK_POSITIONS), m_saveDockPositionsCheckBox); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_LAST_TAB), m_saveLastTabCheckBox); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SHOW_HIDDEN_FILES), m_showHiddenFilesCheckBox); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SUGGEST_LOADED_CORE_FIRST), m_suggestLoadedCoreFirstCheckBox); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT), m_allPlaylistsListMaxCountSpinBox); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT), m_allPlaylistsGridMaxCountSpinBox); - form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME), m_themeComboBox); - form->addRow(m_highlightColorLabel, m_highlightColorPushButton); - - qobject_cast(layout())->addLayout(form); - layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); - layout()->addWidget(buttonBox); - - loadViewOptions(); - - connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int))); - connect(m_highlightColorPushButton, SIGNAL(clicked()), this, SLOT(onHighlightColorChoose())); -} - -void ViewOptionsDialog::onThemeComboBoxIndexChanged(int) -{ - MainWindow::Theme theme = static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()); - - if (theme == MainWindow::THEME_CUSTOM) - { - QString filePath = QFileDialog::getOpenFileName(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_THEME)); - - if (filePath.isEmpty()) - { - int oldThemeIndex = m_themeComboBox->findData(m_mainwindow->getThemeFromString(m_settings->value("theme", "default").toString())); - - if (m_themeComboBox->count() > oldThemeIndex) - { - disconnect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int))); - m_themeComboBox->setCurrentIndex(oldThemeIndex); - connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int))); - } - } - else - { - m_customThemePath = filePath; - - if (m_mainwindow->setCustomThemeFile(filePath)) - m_mainwindow->setTheme(theme); - } - } - else - m_mainwindow->setTheme(theme); - - showOrHideHighlightColor(); -} - -void ViewOptionsDialog::onHighlightColorChoose() -{ - QPixmap highlightPixmap(m_highlightColorPushButton->iconSize()); - QColor currentHighlightColor = m_settings->value("highlight_color", QApplication::palette().highlight().color()).value(); - QColor newHighlightColor = QColorDialog::getColor(currentHighlightColor, this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_COLOR)); - - if (newHighlightColor.isValid()) - { - MainWindow::Theme theme = static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()); - - m_highlightColor = newHighlightColor; - m_settings->setValue("highlight_color", m_highlightColor); - highlightPixmap.fill(m_highlightColor); - m_highlightColorPushButton->setIcon(highlightPixmap); - m_mainwindow->setTheme(theme); - } -} - -void ViewOptionsDialog::loadViewOptions() -{ - QColor highlightColor = m_settings->value("highlight_color", QApplication::palette().highlight().color()).value(); - QPixmap highlightPixmap(m_highlightColorPushButton->iconSize()); - int themeIndex = 0; - - m_saveGeometryCheckBox->setChecked(m_settings->value("save_geometry", false).toBool()); - m_saveDockPositionsCheckBox->setChecked(m_settings->value("save_dock_positions", false).toBool()); - m_saveLastTabCheckBox->setChecked(m_settings->value("save_last_tab", false).toBool()); - m_showHiddenFilesCheckBox->setChecked(m_settings->value("show_hidden_files", true).toBool()); - m_suggestLoadedCoreFirstCheckBox->setChecked(m_settings->value("suggest_loaded_core_first", false).toBool()); - m_allPlaylistsListMaxCountSpinBox->setValue(m_settings->value("all_playlists_list_max_count", 0).toInt()); - m_allPlaylistsGridMaxCountSpinBox->setValue(m_settings->value("all_playlists_grid_max_count", 5000).toInt()); - - themeIndex = m_themeComboBox->findData(m_mainwindow->getThemeFromString(m_settings->value("theme", "default").toString())); - - if (m_themeComboBox->count() > themeIndex) - m_themeComboBox->setCurrentIndex(themeIndex); - - if (highlightColor.isValid()) - { - m_highlightColor = highlightColor; - highlightPixmap.fill(m_highlightColor); - m_highlightColorPushButton->setIcon(highlightPixmap); - } - - showOrHideHighlightColor(); -} - -void ViewOptionsDialog::showOrHideHighlightColor() -{ - if (m_mainwindow->theme() == MainWindow::THEME_DARK) - { - m_highlightColorLabel->show(); - m_highlightColorPushButton->show(); - } - else - { - m_highlightColorLabel->hide(); - m_highlightColorPushButton->hide(); - } -} - -void ViewOptionsDialog::saveViewOptions() -{ - m_settings->setValue("save_geometry", m_saveGeometryCheckBox->isChecked()); - m_settings->setValue("save_dock_positions", m_saveDockPositionsCheckBox->isChecked()); - m_settings->setValue("save_last_tab", m_saveLastTabCheckBox->isChecked()); - m_settings->setValue("theme", m_mainwindow->getThemeString(static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()))); - m_settings->setValue("show_hidden_files", m_showHiddenFilesCheckBox->isChecked()); - m_settings->setValue("highlight_color", m_highlightColor); - m_settings->setValue("suggest_loaded_core_first", m_suggestLoadedCoreFirstCheckBox->isChecked()); - m_settings->setValue("all_playlists_list_max_count", m_allPlaylistsListMaxCountSpinBox->value()); - m_settings->setValue("all_playlists_grid_max_count", m_allPlaylistsGridMaxCountSpinBox->value()); - - if (!m_mainwindow->customThemeString().isEmpty()) - m_settings->setValue("custom_theme", m_customThemePath); - - m_mainwindow->setAllPlaylistsListMaxCount(m_allPlaylistsListMaxCountSpinBox->value()); - m_mainwindow->setAllPlaylistsGridMaxCount(m_allPlaylistsGridMaxCountSpinBox->value()); -} - -void ViewOptionsDialog::onAccepted() -{ - MainWindow::Theme newTheme = static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()); - - m_mainwindow->setTheme(newTheme); - - saveViewOptions(); -} - -void ViewOptionsDialog::onRejected() -{ - loadViewOptions(); -} - -void ViewOptionsDialog::showDialog() -{ - loadViewOptions(); - show(); -} - -void ViewOptionsDialog::hideDialog() -{ - reject(); -} - CoreInfoWidget::CoreInfoWidget(CoreInfoLabel *label, QWidget *parent) : QWidget(parent) ,m_label(label) @@ -1219,31 +586,6 @@ MainWindow::~MainWindow() removeGridItems(); } -void MainWindow::removeUpdateTempFiles() -{ - /* a QDir with no path means the current working directory */ - 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)); - QFile file(path); - - if (path.endsWith(TEMP_EXTENSION)) - { - QByteArray pathArray = path.toUtf8(); - const char *pathData = pathArray.constData(); - - if (file.remove()) - RARCH_LOG("[Qt]: removed temporary update file %s\n", pathData); - else - RARCH_LOG("[Qt]: could not remove temporary update file %s\n", pathData); - } - } -} - void MainWindow::onShaderParamsDialogResized(QSize size) { QVariant scrollAreaVariant = m_shaderParamsDialog->property("scrollArea"); @@ -1262,7 +604,7 @@ void MainWindow::onShaderParamsDialogResized(QSize size) void MainWindow::onShaderParamsClicked() { - video_shader_ctx_t shader_info; + video_shader_ctx_t shader_info = {0}; unsigned i; int last_pass = -1; QFormLayout *last_form = NULL; @@ -1271,7 +613,8 @@ void MainWindow::onShaderParamsClicked() QWidget *widget = NULL; QVBoxLayout *layout = NULL; - video_shader_driver_get_current_shader(&shader_info); + if (!video_shader_driver_get_current_shader(&shader_info)) + return; if (!shader_info.data || shader_info.data->num_parameters > GFX_MAX_PARAMETERS) return; @@ -1549,215 +892,6 @@ void MainWindow::onShaderParamDoubleSpinBoxValueChanged(double value) } } -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 dialog(NULL); - PlaylistEntryDialog *playlistDialog = playlistEntryDialog(); - QHash selectedCore; - QHash itemToAdd; - QString selectedDatabase; - QString selectedName; - QString selectedPath; - const char *currentPlaylistData = NULL; - playlist_t *playlist = NULL; - int i; - - /* Assume a blank list means we will manually enter in all fields. */ - if (files.isEmpty()) - { - /* Make sure hash isn't blank, that would mean there's multiple entries to add at once. */ - itemToAdd["label"] = ""; - itemToAdd["path"] = ""; - } - else if (files.count() == 1) - { - QString path = files.at(0); - QFileInfo info(path); - - if (info.isFile()) - { - itemToAdd["label"] = info.completeBaseName(); - itemToAdd["path"] = path; - } - } - - if (currentItem) - { - currentPlaylistPath = currentItem->data(Qt::UserRole).toString(); - - if (!currentPlaylistPath.isEmpty()) - { - currentPlaylistArray = currentPlaylistPath.toUtf8(); - currentPlaylistData = currentPlaylistArray.constData(); - } - } - - if (currentPlaylistPath == ALL_PLAYLISTS_TOKEN) - { - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - return; - } - - /* a blank itemToAdd means there will be multiple */ - if (!playlistDialog->showDialog(itemToAdd)) - return; - - selectedName = m_playlistEntryDialog->getSelectedName(); - selectedPath = m_playlistEntryDialog->getSelectedPath(); - selectedCore = m_playlistEntryDialog->getSelectedCore(); - selectedDatabase = m_playlistEntryDialog->getSelectedDatabase(); - - if (selectedDatabase.isEmpty()) - selectedDatabase = QFileInfo(currentPlaylistPath).fileName(); - else - selectedDatabase += file_path_str(FILE_PATH_LPL_EXTENSION); - - 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); - - if (selectedName.isEmpty() || selectedPath.isEmpty() || - selectedDatabase.isEmpty()) - { - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - return; - } - - if (files.isEmpty()) - files.append(selectedPath); - - for (i = 0; i < files.count(); i++) - { - QString path(files.at(i)); - QFileInfo fileInfo(path); - - if (dialog->wasCanceled()) - return; - - if (i % 25 == 0) - { - /* Needed to update progress dialog while doing a lot of stuff on the main thread. */ - qApp->processEvents(); - } - - if (fileInfo.isDir()) - { - QDir dir(path); - addDirectoryFilesToList(list, dir); - continue; - } - - if (fileInfo.isFile()) - list.append(fileInfo.absoluteFilePath()); - else if (files.count() == 1) - { - /* If adding a single file, tell user that it doesn't exist. */ - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - return; - } - } - - 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; - - if (files.count() == 1 && list.count() == 1 && i == 0) - { - fileBaseNameArray = selectedName.toUtf8(); - pathArray = QDir::toNativeSeparators(selectedPath).toUtf8(); - } - else - { - fileBaseNameArray = fileInfo.completeBaseName().toUtf8(); - pathArray = QDir::toNativeSeparators(fileName).toUtf8(); - } - - fileNameNoExten = fileBaseNameArray.constData(); - - /* a modal QProgressDialog calls processEvents() automatically in setValue() */ - dialog->setValue(i + 1); - - pathData = pathArray.constData(); - - if (selectedCore.isEmpty()) - { - corePathData = "DETECT"; - coreNameData = "DETECT"; - } - else - { - corePathArray = QDir::toNativeSeparators(selectedCore.value("core_path")).toUtf8(); - coreNameArray = selectedCore.value("core_name").toUtf8(); - corePathData = corePathArray.constData(); - coreNameData = coreNameArray.constData(); - } - - 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 = QDir::toNativeSeparators(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(ThumbnailWidget *widget) { QHash hash; @@ -2007,102 +1141,6 @@ bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowM return true; } -bool MainWindow::updateCurrentPlaylistEntry(const QHash &contentHash) -{ - QString playlistPath = getCurrentPlaylistPath(); - QString path; - QString label; - QString corePath; - QString coreName; - QString dbName; - QString crc32; - QByteArray playlistPathArray; - QByteArray pathArray; - QByteArray labelArray; - QByteArray corePathArray; - QByteArray coreNameArray; - QByteArray dbNameArray; - QByteArray crc32Array; - const char *playlistPathData = NULL; - const char *pathData = NULL; - const char *labelData = NULL; - const char *corePathData = NULL; - const char *coreNameData = NULL; - const char *dbNameData = NULL; - const char *crc32Data = NULL; - playlist_t *playlist = NULL; - unsigned index = 0; - bool ok = false; - - if (playlistPath.isEmpty() || contentHash.isEmpty() || !contentHash.contains("index")) - return false; - - index = contentHash.value("index").toUInt(&ok); - - if (!ok) - return false; - - path = contentHash.value("path"); - label = contentHash.value("label"); - coreName = contentHash.value("core_name"); - corePath = contentHash.value("core_path"); - dbName = contentHash.value("db_name"); - crc32 = contentHash.value("crc32"); - - if (path.isEmpty() || - label.isEmpty() || - coreName.isEmpty() || - corePath.isEmpty() || - dbName.isEmpty() || - crc32.isEmpty() - ) - return false; - - playlistPathArray = playlistPath.toUtf8(); - pathArray = QDir::toNativeSeparators(path).toUtf8(); - labelArray = label.toUtf8(); - coreNameArray = coreName.toUtf8(); - corePathArray = QDir::toNativeSeparators(corePath).toUtf8(); - dbNameArray = (dbName + file_path_str(FILE_PATH_LPL_EXTENSION)).toUtf8(); - crc32Array = crc32.toUtf8(); - - playlistPathData = playlistPathArray.constData(); - pathData = pathArray.constData(); - labelData = labelArray.constData(); - coreNameData = coreNameArray.constData(); - corePathData = corePathArray.constData(); - dbNameData = dbNameArray.constData(); - crc32Data = crc32Array.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 = QDir::toNativeSeparators(QString(pathData) + "#" + list->elems[0].data).toUtf8(); - pathData = pathArray.constData(); - } - - string_list_free(list); - } - } - - playlist = playlist_init(playlistPathData, COLLECTION_SIZE); - - playlist_update(playlist, index, pathData, labelData, - corePathData, coreNameData, crc32Data, dbNameData); - playlist_write_file(playlist); - playlist_free(playlist); - - reloadPlaylists(); - - return true; -} - void MainWindow::onFileDropWidgetContextMenuRequested(const QPoint &pos) { QScopedPointer menu; @@ -2202,273 +1240,6 @@ void MainWindow::onFileDropWidgetContextMenuRequested(const QPoint &pos) } } -void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) -{ - settings_t *settings = config_get_ptr(); - QScopedPointer menu; - QScopedPointer associateMenu; - QScopedPointer hiddenPlaylistsMenu; - QScopedPointer hideAction; - QScopedPointer newPlaylistAction; - QScopedPointer deletePlaylistAction; - QPointer selectedAction; - QPoint cursorPos = QCursor::pos(); - QListWidgetItem *selectedItem = m_listWidget->itemAt(m_listWidget->viewport()->mapFromGlobal(cursorPos)); - QDir playlistDir(settings->paths.directory_playlist); - QString playlistDirAbsPath = playlistDir.absolutePath(); - QString currentPlaylistDirPath; - QString currentPlaylistPath; - QString currentPlaylistFileName; - QFile currentPlaylistFile; - QByteArray currentPlaylistFileNameArray; - QFileInfo currentPlaylistFileInfo; - QMap coreList; - core_info_list_t *core_info_list = NULL; - union string_list_elem_attr attr = {0}; - struct string_list *stnames = NULL; - struct string_list *stcores = NULL; - unsigned i = 0; - int j = 0; - size_t found = 0; - const char *currentPlaylistFileNameData = NULL; - char new_playlist_names[PATH_MAX_LENGTH]; - char new_playlist_cores[PATH_MAX_LENGTH]; - bool specialPlaylist = false; - bool foundHiddenPlaylist = false; - - new_playlist_names[0] = new_playlist_cores[0] = '\0'; - - stnames = string_split(settings->arrays.playlist_names, ";"); - stcores = string_split(settings->arrays.playlist_cores, ";"); - - if (selectedItem) - { - currentPlaylistPath = selectedItem->data(Qt::UserRole).toString(); - currentPlaylistFile.setFileName(currentPlaylistPath); - - 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"); - - menu->addAction(newPlaylistAction.data()); - - if (currentPlaylistFile.exists()) - { - deletePlaylistAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST)) + "...", this)); - menu->addAction(deletePlaylistAction.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(); j++) - { - QListWidgetItem *item = m_listWidget->item(j); - bool hidden = m_listWidget->isItemHidden(item); - - if (hidden) - { - QAction *action = hiddenPlaylistsMenu->addAction(item->text()); - action->setProperty("row", j); - action->setProperty("core_path", item->data(Qt::UserRole).toString()); - foundHiddenPlaylist = true; - } - } - - if (!foundHiddenPlaylist) - { - QAction *action = hiddenPlaylistsMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE)); - action->setProperty("row", -1); - } - - menu->addMenu(hiddenPlaylistsMenu.data()); - - if (currentPlaylistDirPath != playlistDirAbsPath) - { - /* special playlists like history etc. can't have an association */ - specialPlaylist = true; - } - - if (!specialPlaylist) - { - associateMenu.reset(new QMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ASSOCIATE_CORE), this)); - associateMenu->setObjectName("associateMenu"); - - core_info_get_list(&core_info_list); - - for (i = 0; i < core_info_list->count && core_info_list->count > 0; i++) - { - const core_info_t *core = &core_info_list->list[i]; - coreList[core->core_name] = core; - } - - { - QMapIterator coreListIterator(coreList); - QVector > cores; - - while (coreListIterator.hasNext()) - { - QString key; - const core_info_t *core = NULL; - QString name; - QHash hash; - - coreListIterator.next(); - - key = coreListIterator.key(); - core = coreList.value(key); - - if (string_is_empty(core->core_name)) - name = core->display_name; - else - name = core->core_name; - - if (name.isEmpty()) - continue; - - hash["name"] = name; - hash["core_path"] = core->path; - - cores.append(hash); - } - - std::sort(cores.begin(), cores.end(), comp_hash_name_key_lower); - - for (j = 0; j < cores.count(); j++) - { - const QHash &hash = cores.at(j); - QAction *action = associateMenu->addAction(hash.value("name")); - - action->setProperty("core_path", hash.value("core_path")); - } - } - - menu->addMenu(associateMenu.data()); - } - - selectedAction = menu->exec(cursorPos); - - if (!selectedAction) - goto end; - - if (!specialPlaylist && selectedAction->parent() == associateMenu.data()) - { - found = string_list_find_elem(stnames, currentPlaylistFileNameData); - - if (found) - string_list_set(stcores, static_cast(found - 1), selectedAction->property("core_path").toString().toUtf8().constData()); - else - { - string_list_append(stnames, currentPlaylistFileNameData, attr); - string_list_append(stcores, "DETECT", attr); - - found = string_list_find_elem(stnames, currentPlaylistFileNameData); - - if (found) - string_list_set(stcores, static_cast(found - 1), selectedAction->property("core_path").toString().toUtf8().constData()); - } - - string_list_join_concat(new_playlist_names, - sizeof(new_playlist_names), stnames, ";"); - string_list_join_concat(new_playlist_cores, - sizeof(new_playlist_cores), stcores, ";"); - - strlcpy(settings->arrays.playlist_names, - new_playlist_names, sizeof(settings->arrays.playlist_names)); - strlcpy(settings->arrays.playlist_cores, - new_playlist_cores, sizeof(settings->arrays.playlist_cores)); - } - else if (selectedAction == deletePlaylistAction.data()) - { - if (currentPlaylistFile.exists()) - { - if (showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST)).arg(selectedItem->text()), MainWindow::MSGBOX_TYPE_QUESTION_YESNO, Qt::ApplicationModal, false)) - { - if (currentPlaylistFile.remove()) - reloadPlaylists(); - else - 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); - - if (row >= 0) - { - QStringList hiddenPlaylists = m_settings->value("hidden_playlists").toStringList(); - - if (!hiddenPlaylists.contains(currentPlaylistFileName)) - { - hiddenPlaylists.append(currentPlaylistFileName); - m_settings->setValue("hidden_playlists", hiddenPlaylists); - } - - m_listWidget->setRowHidden(row, true); - } - } - else if (selectedAction->parent() == hiddenPlaylistsMenu.data()) - { - QVariant rowVariant = selectedAction->property("row"); - - if (rowVariant.isValid()) - { - QStringList hiddenPlaylists = m_settings->value("hidden_playlists").toStringList(); - int row = rowVariant.toInt(); - - if (row >= 0) - { - QString playlistPath = selectedAction->property("core_path").toString(); - QFileInfo playlistFileInfo(playlistPath); - QString playlistFileName = playlistFileInfo.fileName(); - - if (hiddenPlaylists.contains(playlistFileName)) - { - hiddenPlaylists.removeOne(playlistFileName); - m_settings->setValue("hidden_playlists", hiddenPlaylists); - } - - m_listWidget->setRowHidden(row, false); - } - } - } - - setCoreActions(); - -end: - if (stnames) - string_list_free(stnames); - if (stcores) - string_list_free(stcores); -} - void MainWindow::onFileBrowserTreeContextMenuRequested(const QPoint&) { #ifdef HAVE_LIBRETRODB @@ -2560,151 +1331,6 @@ void MainWindow::onGotReloadShaderParams() onShaderParamsClicked(); } -void MainWindow::deferReloadPlaylists() -{ - emit gotReloadPlaylists(); -} - -void MainWindow::onGotReloadPlaylists() -{ - reloadPlaylists(); -} - -void MainWindow::reloadPlaylists() -{ - QListWidgetItem *allPlaylistsItem = NULL; - QListWidgetItem *favoritesPlaylistsItem = NULL; - QListWidgetItem *imagePlaylistsItem = NULL; - QListWidgetItem *musicPlaylistsItem = NULL; - QListWidgetItem *videoPlaylistsItem = NULL; - QListWidgetItem *firstItem = NULL; - QListWidgetItem *currentItem = NULL; - settings_t *settings = config_get_ptr(); - QDir playlistDir(settings->paths.directory_playlist); - QString currentPlaylistPath; - QStringList hiddenPlaylists = m_settings->value("hidden_playlists").toStringList(); - int i = 0; - - currentItem = m_listWidget->currentItem(); - - if (currentItem) - { - currentPlaylistPath = currentItem->data(Qt::UserRole).toString(); - } - - getPlaylistFiles(); - - m_listWidget->clear(); - - allPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ALL_PLAYLISTS)); - allPlaylistsItem->setData(Qt::UserRole, ALL_PLAYLISTS_TOKEN); - - favoritesPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FAVORITES_TAB)); - favoritesPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_favorites); - - m_historyPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HISTORY_TAB)); - m_historyPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_history); - - imagePlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_IMAGES_TAB)); - imagePlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_image_history); - - musicPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MUSIC_TAB)); - musicPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_music_history); - - videoPlaylistsItem = new QListWidgetItem(m_folderIcon, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_TAB)); - videoPlaylistsItem->setData(Qt::UserRole, settings->paths.path_content_video_history); - - m_listWidget->addItem(allPlaylistsItem); - m_listWidget->addItem(favoritesPlaylistsItem); - m_listWidget->addItem(m_historyPlaylistsItem); - m_listWidget->addItem(imagePlaylistsItem); - m_listWidget->addItem(musicPlaylistsItem); - m_listWidget->addItem(videoPlaylistsItem); - - if (hiddenPlaylists.contains(ALL_PLAYLISTS_TOKEN)) - m_listWidget->setRowHidden(m_listWidget->row(allPlaylistsItem), true); - if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_favorites).fileName())) - m_listWidget->setRowHidden(m_listWidget->row(favoritesPlaylistsItem), true); - if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_history).fileName())) - m_listWidget->setRowHidden(m_listWidget->row(m_historyPlaylistsItem), true); - if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_image_history).fileName())) - m_listWidget->setRowHidden(m_listWidget->row(imagePlaylistsItem), true); - if (hiddenPlaylists.contains(QFileInfo(settings->paths.path_content_music_history).fileName())) - m_listWidget->setRowHidden(m_listWidget->row(musicPlaylistsItem), true); - 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(); i++) - { - QListWidgetItem *item = NULL; - const QString &file = m_playlistFiles.at(i); - QString fileDisplayName = file; - QString fileName = file; - bool hasIcon = false; - QIcon icon; - QString iconPath; - - fileDisplayName.remove(file_path_str(FILE_PATH_LPL_EXTENSION)); - - iconPath = QString(settings->paths.directory_assets) + ICON_PATH + fileDisplayName + ".png"; - - hasIcon = QFile::exists(iconPath); - - if (hasIcon) - icon = QIcon(iconPath); - else - icon = m_folderIcon; - - item = new QListWidgetItem(icon, fileDisplayName); - item->setData(Qt::UserRole, playlistDir.absoluteFilePath(file)); - - m_listWidget->addItem(item); - - if (hiddenPlaylists.contains(fileName)) - { - int row = m_listWidget->row(item); - - if (row >= 0) - m_listWidget->setRowHidden(row, true); - } - } - - if (m_listWidget->count() > 0) - { - firstItem = m_listWidget->item(0); - - if (firstItem) - { - bool found = false; - - for (i = 0; i < m_listWidget->count(); i++) - { - QListWidgetItem *item = m_listWidget->item(i); - QString path; - - if (item) - { - path = item->data(Qt::UserRole).toString(); - - if (!currentPlaylistPath.isEmpty() && !path.isEmpty()) - { - if (path == currentPlaylistPath) - { - found = true; - m_listWidget->setCurrentItem(item); - break; - } - } - } - } - - /* the previous playlist must be gone now, just select the first one */ - if (!found) - m_listWidget->setCurrentItem(firstItem); - } - } -} - void MainWindow::appendLogMessage(const QString &msg) { emit gotLogMessage(msg); @@ -3207,20 +1833,6 @@ void MainWindow::onTableWidgetDeletePressed() deleteCurrentPlaylistItem(); } -QString MainWindow::getCurrentPlaylistPath() -{ - QListWidgetItem *playlistItem = m_listWidget->currentItem(); - QHash contentHash; - QString playlistPath; - - if (!playlistItem) - return playlistPath; - - playlistPath = playlistItem->data(Qt::UserRole).toString(); - - return playlistPath; -} - QHash MainWindow::getCurrentContentHash() { QTableWidgetItem *contentItem = m_tableWidget->currentItem(); @@ -3241,42 +1853,6 @@ QHash MainWindow::getCurrentContentHash() return contentHash; } -void MainWindow::deleteCurrentPlaylistItem() -{ - QString playlistPath = getCurrentPlaylistPath(); - QByteArray playlistArray; - QHash contentHash = getCurrentContentHash(); - playlist_t *playlist = NULL; - const char *playlistData = NULL; - unsigned index = 0; - bool ok = false; - - if (playlistPath.isEmpty()) - return; - - if (contentHash.isEmpty()) - return; - - playlistArray = playlistPath.toUtf8(); - playlistData = playlistArray.constData(); - - index = contentHash.value("index").toUInt(&ok); - - if (!ok) - return; - - if (!showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM)).arg(contentHash["label"]), MainWindow::MSGBOX_TYPE_QUESTION_YESNO, 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(); @@ -3558,50 +2134,6 @@ ViewOptionsDialog* MainWindow::viewOptionsDialog() return m_viewOptionsDialog; } -QVector > MainWindow::getPlaylistDefaultCores() -{ - settings_t *settings = config_get_ptr(); - struct string_list *playlists = string_split(settings->arrays.playlist_names, ";"); - struct string_list *cores = string_split(settings->arrays.playlist_cores, ";"); - unsigned i = 0; - QVector > coreList; - - if (!playlists || !cores) - { - RARCH_WARN("[Qt]: Could not parse one of playlist_names or playlist_cores\n"); - goto finish; - } - else if (playlists->size != cores->size) - { - RARCH_WARN("[Qt]: playlist_names array size differs from playlist_cores\n"); - goto finish; - } - - if (playlists->size == 0) - goto finish; - - for (i = 0; i < playlists->size; i++) - { - const char *playlist = playlists->elems[i].data; - const char *core = cores->elems[i].data; - QHash hash; - - hash["playlist_filename"] = playlist; - hash["playlist_filename"].remove(file_path_str(FILE_PATH_LPL_EXTENSION)); - hash["core_path"] = core; - - coreList.append(hash); - } - -finish: - if (playlists) - string_list_free(playlists); - if (cores) - string_list_free(cores); - - return coreList; -} - void MainWindow::setCoreActions() { QTableWidgetItem *currentContentItem = m_tableWidget->currentItem(); @@ -3836,14 +2368,6 @@ QComboBox* MainWindow::launchWithComboBox() return m_launchWithComboBox; } -void MainWindow::getPlaylistFiles() -{ - settings_t *settings = config_get_ptr(); - QDir playlistDir(settings->paths.directory_playlist); - - m_playlistFiles = playlistDir.entryList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Files, QDir::Name); -} - void MainWindow::onSearchLineEditEdited(const QString &text) { int i = 0; @@ -4545,140 +3069,6 @@ GridItem* MainWindow::doDeferredImageLoad(GridItem *item, QString path) return item; } -void MainWindow::addPlaylistItemsToGrid(const QStringList &paths, bool add) -{ - QVector > items; - int i; - - if (paths.isEmpty()) - return; - - for (i = 0; i < paths.size(); i++) - { - int j; - QVector > vec = getPlaylistItems(paths.at(i)); - /* QVector::append() wasn't added until 5.5, so just do it the old fashioned way */ - for (j = 0; j < vec.size(); j++) - { - if (add && m_allPlaylistsGridMaxCount > 0 && items.size() >= m_allPlaylistsGridMaxCount) - goto finish; - - items.append(vec.at(j)); - } - } -finish: - std::sort(items.begin(), items.end(), comp_hash_label_key_lower); - - addPlaylistHashToGrid(items); -} - -void MainWindow::addPlaylistHashToGrid(const QVector > &items) -{ - QScreen *screen = qApp->primaryScreen(); - QSize screenSize = screen->size(); - QListWidgetItem *currentItem = m_listWidget->currentItem(); - settings_t *settings = config_get_ptr(); - int i = 0; - int zoomValue = m_zoomSlider->value(); - - m_gridProgressBar->setMinimum(0); - m_gridProgressBar->setMaximum(qMax(0, items.count() - 1)); - m_gridProgressBar->setValue(0); - - for (i = 0; i < items.count(); i++) - { - const QHash &hash = items.at(i); - QPointer item; - QPointer label; - QString thumbnailFileNameNoExt; - QLabel *newLabel = NULL; - QSize thumbnailWidgetSizeHint(screenSize.width() / 8, screenSize.height() / 8); - QByteArray extension; - QString extensionStr; - QString imagePath; - int lastIndex = -1; - - if (m_listWidget->currentItem() != currentItem) - { - /* user changed the current playlist before we finished loading... abort */ - m_gridProgressWidget->hide(); - break; - } - - item = new GridItem(); - - lastIndex = hash["path"].lastIndexOf('.'); - - if (lastIndex >= 0) - { - extensionStr = hash["path"].mid(lastIndex + 1); - - if (!extensionStr.isEmpty()) - { - extension = extensionStr.toLower().toUtf8(); - } - } - - if (!extension.isEmpty() && m_imageFormats.contains(extension)) - { - /* use thumbnail widgets to show regular image files */ - imagePath = hash["path"]; - } - else - { - thumbnailFileNameNoExt = hash["label_noext"]; - thumbnailFileNameNoExt.replace(m_fileSanitizerRegex, "_"); - imagePath = QString(settings->paths.directory_thumbnails) + "/" + hash.value("db_name") + "/" + THUMBNAIL_BOXART + "/" + thumbnailFileNameNoExt + ".png"; - } - - item->hash = hash; - item->widget = new ThumbnailWidget(); - item->widget->setSizeHint(thumbnailWidgetSizeHint); - item->widget->setFixedSize(item->widget->sizeHint()); - item->widget->setLayout(new QVBoxLayout()); - item->widget->setObjectName("thumbnailWidget"); - item->widget->setProperty("hash", QVariant::fromValue >(hash)); - - connect(item->widget, SIGNAL(mouseDoubleClicked()), this, SLOT(onGridItemDoubleClicked())); - connect(item->widget, SIGNAL(mousePressed()), this, SLOT(onGridItemClicked())); - - label = new ThumbnailLabel(item->widget); - label->setObjectName("thumbnailGridLabel"); - - item->label = label; - item->labelText = hash.value("label"); - - newLabel = new QLabel(item->labelText, item->widget); - newLabel->setObjectName("thumbnailQLabel"); - newLabel->setAlignment(Qt::AlignCenter); - newLabel->setToolTip(item->labelText); - - calcGridItemSize(item, zoomValue); - - item->widget->layout()->addWidget(label); - - item->widget->layout()->addWidget(newLabel); - qobject_cast(item->widget->layout())->setStretchFactor(label, 1); - - m_gridLayout->addWidgetDeferred(item->widget); - m_gridItems.append(item); - - loadImageDeferred(item, imagePath); - - if (i % 25 == 0) - { - /* Needed to update progress dialog while doing a lot of stuff on the main thread. */ - qApp->processEvents(); - } - - m_gridProgressBar->setValue(i); - } - - /* If there's only one entry, a min/max/value of all zero would make an indeterminate progress bar that never ends... so just hide it when we are done. */ - if (m_gridProgressBar->value() == m_gridProgressBar->maximum()) - m_gridProgressWidget->hide(); -} - void MainWindow::initContentGridLayout() { QListWidgetItem *item = m_listWidget->currentItem(); @@ -4827,122 +3217,6 @@ void MainWindow::initContentTableWidget() onSearchEnterPressed(); } -QVector > MainWindow::getPlaylistItems(QString pathString) -{ - QByteArray pathArray; - QVector > items; - const char *pathData = NULL; - playlist_t *playlist = NULL; - unsigned playlistSize = 0; - unsigned i = 0; - - pathArray.append(pathString); - pathData = pathArray.constData(); - - playlist = playlist_init(pathData, COLLECTION_SIZE); - playlistSize = playlist_get_size(playlist); - - for (i = 0; i < playlistSize; i++) - { - const char *path = NULL; - const char *label = NULL; - const char *core_path = NULL; - const char *core_name = NULL; - const char *crc32 = NULL; - const char *db_name = NULL; - QHash hash; - - playlist_get_index(playlist, i, - &path, &label, &core_path, - &core_name, &crc32, &db_name); - - if (string_is_empty(path)) - continue; - else - hash["path"] = path; - - hash["index"] = QString::number(i); - - if (string_is_empty(label)) - { - hash["label"] = path; - hash["label_noext"] = path; - } - else - { - hash["label"] = label; - hash["label_noext"] = label; - } - - if (!string_is_empty(core_path)) - hash["core_path"] = core_path; - - if (!string_is_empty(core_name)) - hash["core_name"] = core_name; - - if (!string_is_empty(crc32)) - hash["crc32"] = crc32; - - if (!string_is_empty(db_name)) - { - hash["db_name"] = db_name; - hash["db_name"].remove(file_path_str(FILE_PATH_LPL_EXTENSION)); - } - - items.append(hash); - } - - playlist_free(playlist); - playlist = NULL; - - return items; -} - -void MainWindow::addPlaylistItemsToTable(const QStringList &paths, bool add) -{ - QVector > items; - int i; - - if (paths.isEmpty()) - return; - - for (i = 0; i < paths.size(); i++) - { - int j; - QVector > vec = getPlaylistItems(paths.at(i)); - /* QVector::append() wasn't added until 5.5, so just do it the old fashioned way */ - for (j = 0; j < vec.size(); j++) - { - if (add && m_allPlaylistsListMaxCount > 0 && items.size() >= m_allPlaylistsListMaxCount) - goto finish; - - items.append(vec.at(j)); - } - } -finish: - addPlaylistHashToTable(items); -} - -void MainWindow::addPlaylistHashToTable(const QVector > &items) -{ - int i = 0; - int oldRowCount = m_tableWidget->rowCount(); - - m_tableWidget->setRowCount(oldRowCount + items.count()); - - for (i = 0; i < items.count(); i++) - { - QTableWidgetItem *labelItem = NULL; - const QHash &hash = items.at(i); - - labelItem = new QTableWidgetItem(hash.value("label")); - labelItem->setData(Qt::UserRole, QVariant::fromValue >(hash)); - labelItem->setFlags(labelItem->flags() & ~Qt::ItemIsEditable); - - m_tableWidget->setItem(oldRowCount + i, 0, labelItem); - } -} - void MainWindow::keyPressEvent(QKeyEvent *event) { /* @@ -4994,22 +3268,6 @@ void MainWindow::closeEvent(QCloseEvent *event) QMainWindow::closeEvent(event); } -void MainWindow::setAllPlaylistsListMaxCount(int count) -{ - if (count < 1) - count = 0; - - m_allPlaylistsListMaxCount = count; -} - -void MainWindow::setAllPlaylistsGridMaxCount(int count) -{ - if (count < 1) - count = 0; - - m_allPlaylistsGridMaxCount = count; -} - void MainWindow::onContributorsClicked() { QScopedPointer dialog(new QDialog()); @@ -5077,56 +3335,6 @@ void MainWindow::showDocs() QDesktopServices::openUrl(QUrl(DOCS_URL)); } -void MainWindow::onUpdateNetworkError(QNetworkReply::NetworkError code) -{ - QNetworkReply *reply = m_updateReply.data(); - QByteArray errorStringArray; - const char *errorStringData = NULL; - - m_updateProgressDialog->cancel(); - - if (!reply) - return; - - errorStringArray = reply->errorString().toUtf8(); - errorStringData = errorStringArray.constData(); - - RARCH_ERR("[Qt]: Network error code %d received: %s\n", code, errorStringData); - - /* Deleting the reply here seems to cause a strange heap-use-after-free crash. */ - /* - reply->disconnect(); - reply->abort(); - reply->deleteLater(); - */ -} - -void MainWindow::onUpdateNetworkSslErrors(const QList &errors) -{ - QNetworkReply *reply = m_updateReply.data(); - int i; - - if (!reply) - return; - - for (i = 0; i < errors.count(); i++) - { - const QSslError &error = errors.at(i); - QString string = QString("Ignoring SSL error code ") + QString::number(error.error()) + ": " + error.errorString(); - QByteArray stringArray = string.toUtf8(); - const char *stringData = stringArray.constData(); - RARCH_ERR("[Qt]: %s\n", stringData); - } - - /* ignore all SSL errors for now, like self-signed, expired etc. */ - reply->ignoreSslErrors(); -} - -void MainWindow::onUpdateDownloadCanceled() -{ - m_updateProgressDialog->cancel(); -} - void MainWindow::onShowErrorMessage(QString msg) { showMessageBox(msg, MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); @@ -5137,275 +3345,6 @@ void MainWindow::onShowInfoMessage(QString msg) showMessageBox(msg, MainWindow::MSGBOX_TYPE_INFO, Qt::ApplicationModal, false); } -void MainWindow::onRetroArchUpdateDownloadFinished() -{ - QNetworkReply *reply = m_updateReply.data(); - QNetworkReply::NetworkError error; - int code; - - m_updateProgressDialog->cancel(); - - /* At least on Linux, the progress dialog will refuse to hide itself and will stay on screen in a corrupted way if we happen to show an error message in this function. processEvents() will sometimes fix it, other times not... seems random. */ - qApp->processEvents(); - - if (!reply) - return; - - error = reply->error(); - code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - if (m_updateFile.isOpen()) - m_updateFile.close(); - - if (code != 200) - { - emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": HTTP Code " + QString::number(code)); - RARCH_ERR("[Qt]: RetroArch update failed with HTTP status code: %d\n", code); - reply->disconnect(); - reply->abort(); - reply->deleteLater(); - return; - } - - if (error == QNetworkReply::NoError) - { - int index = m_updateFile.fileName().lastIndexOf(PARTIAL_EXTENSION); - QString newFileName = m_updateFile.fileName().left(index); - QFile newFile(newFileName); - - /* rename() requires the old file to be deleted first if it exists */ - if (newFile.exists() && !newFile.remove()) - RARCH_ERR("[Qt]: RetroArch update finished, but old file could not be deleted.\n"); - else - { - if (m_updateFile.rename(newFileName)) - { - RARCH_LOG("[Qt]: RetroArch update finished downloading successfully.\n"); - emit extractArchiveDeferred(newFileName); - } - else - { - RARCH_ERR("[Qt]: RetroArch update finished, but temp file could not be renamed.\n"); - emit showErrorMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE)); - } - } - } - else - { - QByteArray errorArray = reply->errorString().toUtf8(); - const char *errorData = errorArray.constData(); - - RARCH_ERR("[Qt]: RetroArch update ended prematurely: %s\n", errorData); - emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": Code " + QString::number(code) + ": " + errorData); - } - - reply->disconnect(); - reply->close(); - reply->deleteLater(); -} - -static void extractCB(void *task_data, void *user_data, const char *err) -{ - decompress_task_data_t *dec = (decompress_task_data_t*)task_data; - MainWindow *mainwindow = (MainWindow*)user_data; - - if (err) - RARCH_ERR("%s", err); - - if (dec) - { - if (filestream_exists(dec->source_file)) - filestream_delete(dec->source_file); - - free(dec->source_file); - free(dec); - } - - mainwindow->onUpdateRetroArchFinished(string_is_empty(err)); -} - -void MainWindow::onUpdateRetroArchFinished(bool success) -{ - m_updateProgressDialog->cancel(); - - if (!success) - { - RARCH_ERR("[Qt]: RetroArch update failed.\n"); - emit showErrorMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FAILED)); - return; - } - - RARCH_LOG("[Qt]: RetroArch update finished successfully.\n"); - - emit showInfoMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FINISHED)); -} - -int MainWindow::onExtractArchive(QString path) -{ - QByteArray pathArray = path.toUtf8(); - const char *file = pathArray.constData(); - file_archive_transfer_t state; - struct archive_extract_userdata userdata; - struct string_list *file_list = file_archive_get_file_list(file, NULL); - bool returnerr = true; - unsigned i; - - if (!file_list || file_list->size == 0) - { - showMessageBox("Error: Archive is empty.", MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - RARCH_ERR("[Qt]: Downloaded archive is empty?\n"); - return -1; - } - - for (i = 0; i < file_list->size; i++) - { - QFile fileObj(file_list->elems[i].data); - - if (fileObj.exists()) - { - if (!fileObj.remove()) - { - /* if we cannot delete the existing file to update it, rename it for now and delete later */ - QFile fileTemp(fileObj.fileName() + TEMP_EXTENSION); - - if (fileTemp.exists()) - { - if (!fileTemp.remove()) - { - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - RARCH_ERR("[Qt]: Could not delete file: %s\n", file_list->elems[i].data); - return -1; - } - } - - if (!fileObj.rename(fileTemp.fileName())) - { - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - RARCH_ERR("[Qt]: Could not rename file: %s\n", file_list->elems[i].data); - return -1; - } - } - } - } - - string_list_free(file_list); - - memset(&state, 0, sizeof(state)); - memset(&userdata, 0, sizeof(userdata)); - - state.type = ARCHIVE_TRANSFER_INIT; - - m_updateProgressDialog->setWindowModality(Qt::NonModal); - m_updateProgressDialog->setMinimumDuration(0); - m_updateProgressDialog->setRange(0, 0); - m_updateProgressDialog->setAutoClose(true); - m_updateProgressDialog->setAutoReset(true); - m_updateProgressDialog->setValue(0); - m_updateProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_EXTRACTING)) + "..."); - m_updateProgressDialog->setCancelButtonText(QString()); - m_updateProgressDialog->show(); - - if (!task_push_decompress(file, ".", - NULL, NULL, NULL, - extractCB, this)) - { - m_updateProgressDialog->cancel(); - return -1; - } - - return returnerr; -} - -void MainWindow::onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - QNetworkReply *reply = m_updateReply.data(); - int progress = (bytesReceived / (float)bytesTotal) * 100.0f; - - if (!reply) - return; - - m_updateProgressDialog->setValue(progress); -} - -void MainWindow::onUpdateDownloadReadyRead() -{ - QNetworkReply *reply = m_updateReply.data(); - - if (!reply) - return; - - m_updateFile.write(reply->readAll()); -} - -void MainWindow::updateRetroArchNightly() -{ - QUrl url(QUrl(buildbot_server_url).resolved(QUrl(RETROARCH_NIGHTLY_UPDATE_PATH))); - QNetworkRequest request(url); - QNetworkReply *reply = NULL; - QByteArray urlArray = url.toString().toUtf8(); - const char *urlData = urlArray.constData(); - - if (m_updateFile.isOpen()) - { - RARCH_ERR("[Qt]: File is already open.\n"); - return; - } - else - { - QString fileName = QFileInfo(url.toString()).fileName() + PARTIAL_EXTENSION; - QByteArray fileNameArray = fileName.toUtf8(); - const char *fileNameData = fileNameArray.constData(); - - m_updateFile.setFileName(fileName); - - if (!m_updateFile.open(QIODevice::WriteOnly)) - { - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - RARCH_ERR("[Qt]: Could not open file for writing: %s\n", fileNameData); - return; - } - } - - RARCH_LOG("[Qt]: Starting update of RetroArch...\n"); - RARCH_LOG("[Qt]: Downloading URL %s\n", urlData); - - request.setHeader(QNetworkRequest::UserAgentHeader, USER_AGENT); - - m_updateProgressDialog->setWindowModality(Qt::NonModal); - m_updateProgressDialog->setMinimumDuration(0); - m_updateProgressDialog->setRange(0, 100); - m_updateProgressDialog->setAutoClose(true); - m_updateProgressDialog->setAutoReset(true); - m_updateProgressDialog->setValue(0); - m_updateProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_DOWNLOADING)) + "..."); - m_updateProgressDialog->setCancelButtonText(tr("Cancel")); - m_updateProgressDialog->show(); - - m_updateReply = m_networkManager->get(request); - reply = m_updateReply.data(); - - /* make sure any previous connection is removed first */ - disconnect(m_updateProgressDialog, SIGNAL(canceled()), reply, SLOT(abort())); - disconnect(m_updateProgressDialog, SIGNAL(canceled()), m_updateProgressDialog, SLOT(cancel())); - connect(m_updateProgressDialog, SIGNAL(canceled()), reply, SLOT(abort())); - connect(m_updateProgressDialog, SIGNAL(canceled()), m_updateProgressDialog, SLOT(cancel())); - - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onUpdateNetworkError(QNetworkReply::NetworkError))); - connect(reply, SIGNAL(sslErrors(const QList&)), this, SLOT(onUpdateNetworkSslErrors(const QList&))); - connect(reply, SIGNAL(finished()), this, SLOT(onRetroArchUpdateDownloadFinished())); - connect(reply, SIGNAL(readyRead()), this, SLOT(onUpdateDownloadReadyRead())); - connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onUpdateDownloadProgress(qint64, qint64))); - -} - -const QPixmap getInvader() -{ - QPixmap pix; - pix.loadFromData(invader_png, invader_png_len, "PNG"); - - return pix; -} - static void* ui_window_qt_init(void) { ui_window.qtWindow = new MainWindow(); diff --git a/ui/drivers/qt/updateretroarch.cpp b/ui/drivers/qt/updateretroarch.cpp new file mode 100644 index 0000000000..da67edb862 --- /dev/null +++ b/ui/drivers/qt/updateretroarch.cpp @@ -0,0 +1,355 @@ +#include +#include +#include + +#include "../ui_qt.h" + +extern "C" { +#include +#include +#include +#include "../../../tasks/tasks_internal.h" +#include "../../../verbosity.h" +#include "../../../config.def.h" +} + +#define USER_AGENT "RetroArch-WIMP/1.0" +#define PARTIAL_EXTENSION ".partial" +#define TEMP_EXTENSION ".update_tmp" +#define RETROARCH_NIGHTLY_UPDATE_PATH "../RetroArch_update.zip" + +static void extractCB(void *task_data, void *user_data, const char *err) +{ + decompress_task_data_t *dec = (decompress_task_data_t*)task_data; + MainWindow *mainwindow = (MainWindow*)user_data; + + if (err) + RARCH_ERR("%s", err); + + if (dec) + { + if (filestream_exists(dec->source_file)) + filestream_delete(dec->source_file); + + free(dec->source_file); + free(dec); + } + + mainwindow->onUpdateRetroArchFinished(string_is_empty(err)); +} + +void MainWindow::removeUpdateTempFiles() +{ + /* a QDir with no path means the current working directory */ + 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)); + QFile file(path); + + if (path.endsWith(TEMP_EXTENSION)) + { + QByteArray pathArray = path.toUtf8(); + const char *pathData = pathArray.constData(); + + if (file.remove()) + RARCH_LOG("[Qt]: removed temporary update file %s\n", pathData); + else + RARCH_LOG("[Qt]: could not remove temporary update file %s\n", pathData); + } + } +} + +void MainWindow::onUpdateNetworkError(QNetworkReply::NetworkError code) +{ + QNetworkReply *reply = m_updateReply.data(); + QByteArray errorStringArray; + const char *errorStringData = NULL; + + m_updateProgressDialog->cancel(); + + if (!reply) + return; + + errorStringArray = reply->errorString().toUtf8(); + errorStringData = errorStringArray.constData(); + + RARCH_ERR("[Qt]: Network error code %d received: %s\n", code, errorStringData); + + /* Deleting the reply here seems to cause a strange heap-use-after-free crash. */ + /* + reply->disconnect(); + reply->abort(); + reply->deleteLater(); + */ +} + +void MainWindow::onUpdateNetworkSslErrors(const QList &errors) +{ + QNetworkReply *reply = m_updateReply.data(); + int i; + + if (!reply) + return; + + for (i = 0; i < errors.count(); i++) + { + const QSslError &error = errors.at(i); + QString string = QString("Ignoring SSL error code ") + QString::number(error.error()) + ": " + error.errorString(); + QByteArray stringArray = string.toUtf8(); + const char *stringData = stringArray.constData(); + RARCH_ERR("[Qt]: %s\n", stringData); + } + + /* ignore all SSL errors for now, like self-signed, expired etc. */ + reply->ignoreSslErrors(); +} + +void MainWindow::onUpdateDownloadCanceled() +{ + m_updateProgressDialog->cancel(); +} + +void MainWindow::onRetroArchUpdateDownloadFinished() +{ + QNetworkReply *reply = m_updateReply.data(); + QNetworkReply::NetworkError error; + int code; + + m_updateProgressDialog->cancel(); + + /* At least on Linux, the progress dialog will refuse to hide itself and will stay on screen in a corrupted way if we happen to show an error message in this function. processEvents() will sometimes fix it, other times not... seems random. */ + qApp->processEvents(); + + if (!reply) + return; + + error = reply->error(); + code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + if (m_updateFile.isOpen()) + m_updateFile.close(); + + if (code != 200) + { + emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": HTTP Code " + QString::number(code)); + RARCH_ERR("[Qt]: RetroArch update failed with HTTP status code: %d\n", code); + reply->disconnect(); + reply->abort(); + reply->deleteLater(); + return; + } + + if (error == QNetworkReply::NoError) + { + int index = m_updateFile.fileName().lastIndexOf(PARTIAL_EXTENSION); + QString newFileName = m_updateFile.fileName().left(index); + QFile newFile(newFileName); + + /* rename() requires the old file to be deleted first if it exists */ + if (newFile.exists() && !newFile.remove()) + RARCH_ERR("[Qt]: RetroArch update finished, but old file could not be deleted.\n"); + else + { + if (m_updateFile.rename(newFileName)) + { + RARCH_LOG("[Qt]: RetroArch update finished downloading successfully.\n"); + emit extractArchiveDeferred(newFileName); + } + else + { + RARCH_ERR("[Qt]: RetroArch update finished, but temp file could not be renamed.\n"); + emit showErrorMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE)); + } + } + } + else + { + QByteArray errorArray = reply->errorString().toUtf8(); + const char *errorData = errorArray.constData(); + + RARCH_ERR("[Qt]: RetroArch update ended prematurely: %s\n", errorData); + emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": Code " + QString::number(code) + ": " + errorData); + } + + reply->disconnect(); + reply->close(); + reply->deleteLater(); +} + +void MainWindow::onUpdateRetroArchFinished(bool success) +{ + m_updateProgressDialog->cancel(); + + if (!success) + { + RARCH_ERR("[Qt]: RetroArch update failed.\n"); + emit showErrorMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FAILED)); + return; + } + + RARCH_LOG("[Qt]: RetroArch update finished successfully.\n"); + + emit showInfoMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FINISHED)); +} + +int MainWindow::onExtractArchive(QString path) +{ + QByteArray pathArray = path.toUtf8(); + const char *file = pathArray.constData(); + file_archive_transfer_t state; + struct archive_extract_userdata userdata; + struct string_list *file_list = file_archive_get_file_list(file, NULL); + bool returnerr = true; + unsigned i; + + if (!file_list || file_list->size == 0) + { + showMessageBox("Error: Archive is empty.", MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Downloaded archive is empty?\n"); + return -1; + } + + for (i = 0; i < file_list->size; i++) + { + QFile fileObj(file_list->elems[i].data); + + if (fileObj.exists()) + { + if (!fileObj.remove()) + { + /* if we cannot delete the existing file to update it, rename it for now and delete later */ + QFile fileTemp(fileObj.fileName() + TEMP_EXTENSION); + + if (fileTemp.exists()) + { + if (!fileTemp.remove()) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Could not delete file: %s\n", file_list->elems[i].data); + return -1; + } + } + + if (!fileObj.rename(fileTemp.fileName())) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Could not rename file: %s\n", file_list->elems[i].data); + return -1; + } + } + } + } + + string_list_free(file_list); + + memset(&state, 0, sizeof(state)); + memset(&userdata, 0, sizeof(userdata)); + + state.type = ARCHIVE_TRANSFER_INIT; + + m_updateProgressDialog->setWindowModality(Qt::NonModal); + m_updateProgressDialog->setMinimumDuration(0); + m_updateProgressDialog->setRange(0, 0); + m_updateProgressDialog->setAutoClose(true); + m_updateProgressDialog->setAutoReset(true); + m_updateProgressDialog->setValue(0); + m_updateProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_EXTRACTING)) + "..."); + m_updateProgressDialog->setCancelButtonText(QString()); + m_updateProgressDialog->show(); + + if (!task_push_decompress(file, ".", + NULL, NULL, NULL, + extractCB, this)) + { + m_updateProgressDialog->cancel(); + return -1; + } + + return returnerr; +} + +void MainWindow::onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + QNetworkReply *reply = m_updateReply.data(); + int progress = (bytesReceived / (float)bytesTotal) * 100.0f; + + if (!reply) + return; + + m_updateProgressDialog->setValue(progress); +} + +void MainWindow::onUpdateDownloadReadyRead() +{ + QNetworkReply *reply = m_updateReply.data(); + + if (!reply) + return; + + m_updateFile.write(reply->readAll()); +} + +void MainWindow::updateRetroArchNightly() +{ + QUrl url(QUrl(buildbot_server_url).resolved(QUrl(RETROARCH_NIGHTLY_UPDATE_PATH))); + QNetworkRequest request(url); + QNetworkReply *reply = NULL; + QByteArray urlArray = url.toString().toUtf8(); + const char *urlData = urlArray.constData(); + + if (m_updateFile.isOpen()) + { + RARCH_ERR("[Qt]: File is already open.\n"); + return; + } + else + { + QString fileName = QFileInfo(url.toString()).fileName() + PARTIAL_EXTENSION; + QByteArray fileNameArray = fileName.toUtf8(); + const char *fileNameData = fileNameArray.constData(); + + m_updateFile.setFileName(fileName); + + if (!m_updateFile.open(QIODevice::WriteOnly)) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Could not open file for writing: %s\n", fileNameData); + return; + } + } + + RARCH_LOG("[Qt]: Starting update of RetroArch...\n"); + RARCH_LOG("[Qt]: Downloading URL %s\n", urlData); + + request.setHeader(QNetworkRequest::UserAgentHeader, USER_AGENT); + + m_updateProgressDialog->setWindowModality(Qt::NonModal); + m_updateProgressDialog->setMinimumDuration(0); + m_updateProgressDialog->setRange(0, 100); + m_updateProgressDialog->setAutoClose(true); + m_updateProgressDialog->setAutoReset(true); + m_updateProgressDialog->setValue(0); + m_updateProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_DOWNLOADING)) + "..."); + m_updateProgressDialog->setCancelButtonText(tr("Cancel")); + m_updateProgressDialog->show(); + + m_updateReply = m_networkManager->get(request); + reply = m_updateReply.data(); + + /* make sure any previous connection is removed first */ + disconnect(m_updateProgressDialog, SIGNAL(canceled()), reply, SLOT(abort())); + disconnect(m_updateProgressDialog, SIGNAL(canceled()), m_updateProgressDialog, SLOT(cancel())); + connect(m_updateProgressDialog, SIGNAL(canceled()), reply, SLOT(abort())); + connect(m_updateProgressDialog, SIGNAL(canceled()), m_updateProgressDialog, SLOT(cancel())); + + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onUpdateNetworkError(QNetworkReply::NetworkError))); + connect(reply, SIGNAL(sslErrors(const QList&)), this, SLOT(onUpdateNetworkSslErrors(const QList&))); + connect(reply, SIGNAL(finished()), this, SLOT(onRetroArchUpdateDownloadFinished())); + connect(reply, SIGNAL(readyRead()), this, SLOT(onUpdateDownloadReadyRead())); + connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onUpdateDownloadProgress(qint64, qint64))); + +} diff --git a/ui/drivers/qt/viewoptionsdialog.cpp b/ui/drivers/qt/viewoptionsdialog.cpp new file mode 100644 index 0000000000..a293b01a00 --- /dev/null +++ b/ui/drivers/qt/viewoptionsdialog.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "viewoptionsdialog.h" +#include "../ui_qt.h" + +extern "C" { +#include "../../../msg_hash.h" +} + +ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) : + QDialog(parent) + ,m_mainwindow(mainwindow) + ,m_settings(mainwindow->settings()) + ,m_saveGeometryCheckBox(new QCheckBox(this)) + ,m_saveDockPositionsCheckBox(new QCheckBox(this)) + ,m_saveLastTabCheckBox(new QCheckBox(this)) + ,m_showHiddenFilesCheckBox(new QCheckBox(this)) + ,m_themeComboBox(new QComboBox(this)) + ,m_highlightColorPushButton(new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CHOOSE), this)) + ,m_highlightColor() + ,m_highlightColorLabel(new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_HIGHLIGHT_COLOR), this)) + ,m_customThemePath() + ,m_suggestLoadedCoreFirstCheckBox(new QCheckBox(this)) + ,m_allPlaylistsListMaxCountSpinBox(new QSpinBox(this)) + ,m_allPlaylistsGridMaxCountSpinBox(new QSpinBox(this)) +{ + QFormLayout *form = new QFormLayout(); + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_TITLE)); + + m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_SYSTEM_DEFAULT), MainWindow::THEME_SYSTEM_DEFAULT); + m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_DARK), MainWindow::THEME_DARK); + m_themeComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_CUSTOM), MainWindow::THEME_CUSTOM); + + m_allPlaylistsListMaxCountSpinBox->setRange(0, 99999); + m_allPlaylistsGridMaxCountSpinBox->setRange(0, 99999); + + 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_MENU_VIEW_OPTIONS_SAVE_GEOMETRY), m_saveGeometryCheckBox); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_DOCK_POSITIONS), m_saveDockPositionsCheckBox); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_LAST_TAB), m_saveLastTabCheckBox); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SHOW_HIDDEN_FILES), m_showHiddenFilesCheckBox); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SUGGEST_LOADED_CORE_FIRST), m_suggestLoadedCoreFirstCheckBox); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT), m_allPlaylistsListMaxCountSpinBox); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT), m_allPlaylistsGridMaxCountSpinBox); + form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME), m_themeComboBox); + form->addRow(m_highlightColorLabel, m_highlightColorPushButton); + + qobject_cast(layout())->addLayout(form); + layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); + layout()->addWidget(buttonBox); + + loadViewOptions(); + + connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int))); + connect(m_highlightColorPushButton, SIGNAL(clicked()), this, SLOT(onHighlightColorChoose())); +} + +void ViewOptionsDialog::onThemeComboBoxIndexChanged(int) +{ + MainWindow::Theme theme = static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()); + + if (theme == MainWindow::THEME_CUSTOM) + { + QString filePath = QFileDialog::getOpenFileName(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_THEME)); + + if (filePath.isEmpty()) + { + int oldThemeIndex = m_themeComboBox->findData(m_mainwindow->getThemeFromString(m_settings->value("theme", "default").toString())); + + if (m_themeComboBox->count() > oldThemeIndex) + { + disconnect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int))); + m_themeComboBox->setCurrentIndex(oldThemeIndex); + connect(m_themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onThemeComboBoxIndexChanged(int))); + } + } + else + { + m_customThemePath = filePath; + + if (m_mainwindow->setCustomThemeFile(filePath)) + m_mainwindow->setTheme(theme); + } + } + else + m_mainwindow->setTheme(theme); + + showOrHideHighlightColor(); +} + +void ViewOptionsDialog::onHighlightColorChoose() +{ + QPixmap highlightPixmap(m_highlightColorPushButton->iconSize()); + QColor currentHighlightColor = m_settings->value("highlight_color", QApplication::palette().highlight().color()).value(); + QColor newHighlightColor = QColorDialog::getColor(currentHighlightColor, this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_COLOR)); + + if (newHighlightColor.isValid()) + { + MainWindow::Theme theme = static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()); + + m_highlightColor = newHighlightColor; + m_settings->setValue("highlight_color", m_highlightColor); + highlightPixmap.fill(m_highlightColor); + m_highlightColorPushButton->setIcon(highlightPixmap); + m_mainwindow->setTheme(theme); + } +} + +void ViewOptionsDialog::loadViewOptions() +{ + QColor highlightColor = m_settings->value("highlight_color", QApplication::palette().highlight().color()).value(); + QPixmap highlightPixmap(m_highlightColorPushButton->iconSize()); + int themeIndex = 0; + + m_saveGeometryCheckBox->setChecked(m_settings->value("save_geometry", false).toBool()); + m_saveDockPositionsCheckBox->setChecked(m_settings->value("save_dock_positions", false).toBool()); + m_saveLastTabCheckBox->setChecked(m_settings->value("save_last_tab", false).toBool()); + m_showHiddenFilesCheckBox->setChecked(m_settings->value("show_hidden_files", true).toBool()); + m_suggestLoadedCoreFirstCheckBox->setChecked(m_settings->value("suggest_loaded_core_first", false).toBool()); + m_allPlaylistsListMaxCountSpinBox->setValue(m_settings->value("all_playlists_list_max_count", 0).toInt()); + m_allPlaylistsGridMaxCountSpinBox->setValue(m_settings->value("all_playlists_grid_max_count", 5000).toInt()); + + themeIndex = m_themeComboBox->findData(m_mainwindow->getThemeFromString(m_settings->value("theme", "default").toString())); + + if (m_themeComboBox->count() > themeIndex) + m_themeComboBox->setCurrentIndex(themeIndex); + + if (highlightColor.isValid()) + { + m_highlightColor = highlightColor; + highlightPixmap.fill(m_highlightColor); + m_highlightColorPushButton->setIcon(highlightPixmap); + } + + showOrHideHighlightColor(); +} + +void ViewOptionsDialog::showOrHideHighlightColor() +{ + if (m_mainwindow->theme() == MainWindow::THEME_DARK) + { + m_highlightColorLabel->show(); + m_highlightColorPushButton->show(); + } + else + { + m_highlightColorLabel->hide(); + m_highlightColorPushButton->hide(); + } +} + +void ViewOptionsDialog::saveViewOptions() +{ + m_settings->setValue("save_geometry", m_saveGeometryCheckBox->isChecked()); + m_settings->setValue("save_dock_positions", m_saveDockPositionsCheckBox->isChecked()); + m_settings->setValue("save_last_tab", m_saveLastTabCheckBox->isChecked()); + m_settings->setValue("theme", m_mainwindow->getThemeString(static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()))); + m_settings->setValue("show_hidden_files", m_showHiddenFilesCheckBox->isChecked()); + m_settings->setValue("highlight_color", m_highlightColor); + m_settings->setValue("suggest_loaded_core_first", m_suggestLoadedCoreFirstCheckBox->isChecked()); + m_settings->setValue("all_playlists_list_max_count", m_allPlaylistsListMaxCountSpinBox->value()); + m_settings->setValue("all_playlists_grid_max_count", m_allPlaylistsGridMaxCountSpinBox->value()); + + if (!m_mainwindow->customThemeString().isEmpty()) + m_settings->setValue("custom_theme", m_customThemePath); + + m_mainwindow->setAllPlaylistsListMaxCount(m_allPlaylistsListMaxCountSpinBox->value()); + m_mainwindow->setAllPlaylistsGridMaxCount(m_allPlaylistsGridMaxCountSpinBox->value()); +} + +void ViewOptionsDialog::onAccepted() +{ + MainWindow::Theme newTheme = static_cast(m_themeComboBox->currentData(Qt::UserRole).toInt()); + + m_mainwindow->setTheme(newTheme); + + saveViewOptions(); +} + +void ViewOptionsDialog::onRejected() +{ + loadViewOptions(); +} + +void ViewOptionsDialog::showDialog() +{ + loadViewOptions(); + show(); +} + +void ViewOptionsDialog::hideDialog() +{ + reject(); +} + diff --git a/ui/drivers/qt/viewoptionsdialog.h b/ui/drivers/qt/viewoptionsdialog.h new file mode 100644 index 0000000000..7b5c7c71fe --- /dev/null +++ b/ui/drivers/qt/viewoptionsdialog.h @@ -0,0 +1,49 @@ +#ifndef VIEWOPTIONSDIALOG_H +#define VIEWOPTIONSDIALOG_H + +#include + +class MainWindow; +class QSettings; +class QCheckBox; +class QComboBox; +class QPushButton; +class QColor; +class QLabel; +class QSpinBox; + +class ViewOptionsDialog : public QDialog +{ + Q_OBJECT +public: + ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent = 0); +public slots: + void showDialog(); + void hideDialog(); + void onAccepted(); + void onRejected(); +private slots: + void onThemeComboBoxIndexChanged(int index); + void onHighlightColorChoose(); +private: + void loadViewOptions(); + void saveViewOptions(); + void showOrHideHighlightColor(); + + MainWindow *m_mainwindow; + QSettings *m_settings; + QCheckBox *m_saveGeometryCheckBox; + QCheckBox *m_saveDockPositionsCheckBox; + QCheckBox *m_saveLastTabCheckBox; + QCheckBox *m_showHiddenFilesCheckBox; + QComboBox *m_themeComboBox; + QPushButton *m_highlightColorPushButton; + QColor m_highlightColor; + QLabel *m_highlightColorLabel; + QString m_customThemePath; + QCheckBox *m_suggestLoadedCoreFirstCheckBox; + QSpinBox *m_allPlaylistsListMaxCountSpinBox; + QSpinBox *m_allPlaylistsGridMaxCountSpinBox; +}; + +#endif diff --git a/ui/drivers/ui_qt.cpp b/ui/drivers/ui_qt.cpp index 00c9d466fa..3909cb9209 100644 --- a/ui/drivers/ui_qt.cpp +++ b/ui/drivers/ui_qt.cpp @@ -16,6 +16,7 @@ extern "C" { #include +#include #ifdef HAVE_CONFIG_H #include "../../config.h" @@ -31,6 +32,8 @@ extern "C" { } #include "ui_qt.h" +#include "qt/filedropwidget.h" +#include "qt/viewoptionsdialog.h" #include #include diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index f1a1bd03b6..05972d13e2 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -45,6 +45,10 @@ extern "C" { #include "../../gfx/video_driver.h" } +#define ALL_PLAYLISTS_TOKEN "|||ALL|||" +#define ICON_PATH "/xmb/dot-art/png/" +#define THUMBNAIL_BOXART "Named_Boxarts" + class QApplication; class QCloseEvent; class QKeyEvent; @@ -78,6 +82,10 @@ class MainWindow; class ThumbnailWidget; class ThumbnailLabel; class FlowLayout; +class ShaderParamsDialog; +class CoreInfoDialog; +class PlaylistEntryDialog; +class ViewOptionsDialog; class GridItem : public QObject { @@ -147,21 +155,6 @@ 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); - void paintEvent(QPaintEvent *event); -}; - class TableWidget : public QTableWidget { Q_OBJECT @@ -188,82 +181,6 @@ private slots: void onLastWindowClosed(); }; -class PlaylistEntryDialog : public QDialog -{ - Q_OBJECT -public: - PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent = 0); - const QHash getSelectedCore(); - const QString getSelectedDatabase(); - const QString getSelectedName(); - const QString getSelectedPath(); - void setEntryValues(const QHash &contentHash); -public slots: - bool showDialog(const QHash &hash = QHash()); - void hideDialog(); - void onAccepted(); - void onRejected(); -private slots: - void onPathClicked(); -private: - void loadPlaylistOptions(); - - MainWindow *m_mainwindow; - QSettings *m_settings; - QLineEdit *m_nameLineEdit; - QLineEdit *m_pathLineEdit; - QComboBox *m_coreComboBox; - QComboBox *m_databaseComboBox; -}; - -class ViewOptionsDialog : public QDialog -{ - Q_OBJECT -public: - ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent = 0); -public slots: - void showDialog(); - void hideDialog(); - void onAccepted(); - void onRejected(); -private slots: - void onThemeComboBoxIndexChanged(int index); - void onHighlightColorChoose(); -private: - void loadViewOptions(); - void saveViewOptions(); - void showOrHideHighlightColor(); - - MainWindow *m_mainwindow; - QSettings *m_settings; - QCheckBox *m_saveGeometryCheckBox; - QCheckBox *m_saveDockPositionsCheckBox; - QCheckBox *m_saveLastTabCheckBox; - QCheckBox *m_showHiddenFilesCheckBox; - QComboBox *m_themeComboBox; - QPushButton *m_highlightColorPushButton; - QColor m_highlightColor; - QLabel *m_highlightColorLabel; - QString m_customThemePath; - QCheckBox *m_suggestLoadedCoreFirstCheckBox; - QSpinBox *m_allPlaylistsListMaxCountSpinBox; - QSpinBox *m_allPlaylistsGridMaxCountSpinBox; -}; - -class ShaderParamsDialog : public QDialog -{ - Q_OBJECT -public: - ShaderParamsDialog(QWidget *parent = 0); - ~ShaderParamsDialog(); -signals: - void closed(); - void resized(QSize size); -protected: - void closeEvent(QCloseEvent *event); - void resizeEvent(QResizeEvent *event); -}; - class CoreInfoLabel : public QLabel { Q_OBJECT @@ -271,18 +188,6 @@ public: CoreInfoLabel(QString text = QString(), QWidget *parent = 0); }; -class CoreInfoDialog : public QDialog -{ - Q_OBJECT -public: - CoreInfoDialog(MainWindow *mainwindow, QWidget *parent = 0); -public slots: - void showCoreInfo(); -private: - QFormLayout *m_formLayout; - MainWindow *m_mainwindow; -}; - class CoreInfoWidget : public QWidget { Q_OBJECT