From 45d38dcccf59a7be3b56dce7d38ba32f269d32ce Mon Sep 17 00:00:00 2001
From: Brad Parker <cbparker@gmail.com>
Date: Fri, 27 Jul 2018 23:45:48 -0400
Subject: [PATCH] Qt: add dialog to choose core/database for new playlist
 entries

---
 intl/msg_hash_ja.h             |   8 ++
 intl/msg_hash_us.h             |   8 ++
 msg_hash.h                     |   4 +
 ui/drivers/qt/ui_qt_window.cpp | 243 +++++++++++++++++++++++++++++++--
 ui/drivers/ui_qt.h             |  23 ++++
 5 files changed, 274 insertions(+), 12 deletions(-)

diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h
index 20d9fafb45..ef42845b81 100644
--- a/intl/msg_hash_ja.h
+++ b/intl/msg_hash_ja.h
@@ -3654,3 +3654,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
       "ファイルの一覧を構築しています...")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
       "ファイルをプレイリストに追加しています...")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY,
+      "プレイリストエントリー")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE,
+      "コア:")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE,
+      "データベース:")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS,
+      "(サムネイルを見つかることに使う)")
diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h
index 767256a865..300c2336bd 100644
--- a/intl/msg_hash_us.h
+++ b/intl/msg_hash_us.h
@@ -3812,3 +3812,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
       "Gathering list of files...")
 MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
       "Adding files to playlist...")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY,
+      "Playlist Entry")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE,
+      "Core:")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE,
+      "Database:")
+MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS,
+      "(used to find thumbnails)")
diff --git a/msg_hash.h b/msg_hash.h
index 727cc2fd0e..3b9dd94e1a 100644
--- a/msg_hash.h
+++ b/msg_hash.h
@@ -1887,6 +1887,10 @@ enum msg_hash_enums
    MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE,
    MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
    MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
+   MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY,
+   MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE,
+   MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE,
+   MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS,
 
    MENU_LABEL(MIDI_INPUT),
    MENU_LABEL(MIDI_OUTPUT),
diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp
index 823edff0d8..b959e32265 100644
--- a/ui/drivers/qt/ui_qt_window.cpp
+++ b/ui/drivers/qt/ui_qt_window.cpp
@@ -128,9 +128,19 @@ static void scan_finished_handler(void *task_data, void *user_data, const char *
 }
 #endif
 
-inline static bool comp_hash_label_key(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
+inline static bool comp_string_lower(const QString &lhs, const QString &rhs)
 {
-   return lhs.value("label") < rhs.value("label");
+   return lhs.toLower() < rhs.toLower();
+}
+
+inline static bool comp_hash_ui_display_name_key_lower(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
+{
+   return lhs.value("ui_display_name").toLower() < rhs.value("ui_display_name").toLower();
+}
+
+inline static bool comp_hash_label_key_lower(const QHash<QString, QString> &lhs, const QHash<QString, QString> &rhs)
+{
+   return lhs.value("label").toLower() < rhs.value("label").toLower();
 }
 
 GridItem::GridItem() :
@@ -279,6 +289,151 @@ void CoreInfoDialog::showCoreInfo()
    show();
 }
 
+PlaylistEntryDialog::PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent) :
+   QDialog(parent)
+   ,m_mainwindow(mainwindow)
+   ,m_settings(mainwindow->settings())
+   ,m_coreComboBox(new QComboBox(this))
+   ,m_databaseComboBox(new QComboBox(this))
+{
+   QFormLayout *form = new QFormLayout();
+   QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+   QVBoxLayout *databaseVBoxLayout = new QVBoxLayout();
+   QLabel *databaseLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS), this);
+
+   databaseVBoxLayout->addWidget(m_databaseComboBox);
+   databaseVBoxLayout->addWidget(databaseLabel);
+
+   setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY));
+
+   form->setFormAlignment(Qt::AlignCenter);
+   form->setLabelAlignment(Qt::AlignCenter);
+
+   setLayout(new QVBoxLayout(this));
+
+   connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+   connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+   connect(this, SIGNAL(accepted()), this, SLOT(onAccepted()));
+   connect(this, SIGNAL(rejected()), this, SLOT(onRejected()));
+
+   form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE), m_coreComboBox);
+   form->addRow(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE), databaseVBoxLayout);
+
+   qobject_cast<QVBoxLayout*>(layout())->addLayout(form);
+   layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
+   layout()->addWidget(buttonBox);
+}
+
+void PlaylistEntryDialog::loadPlaylistOptions()
+{
+   core_info_list_t *core_info_list = NULL;
+   const core_info_t *core_info = NULL;
+   unsigned i = 0;
+   int j = 0;
+
+   m_coreComboBox->clear();
+   m_databaseComboBox->clear();
+
+   m_coreComboBox->addItem(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE_SELECTION_ASK));
+   m_databaseComboBox->addItem(QString("<") + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE) + ">");
+
+   core_info_get_list(&core_info_list);
+
+   if (core_info_list && core_info_list->count > 0)
+   {
+      QVector<QHash<QString, QString> > allCores;
+      QStringList allDatabases;
+
+      for (i = 0; i < core_info_list->count; i++)
+      {
+         const core_info_t *core = &core_info_list->list[i];
+         QStringList databases = QString(core->databases).split("|");
+         QHash<QString, QString> hash;
+         QString ui_display_name;
+
+         hash["core_name"] = core->core_name;
+         hash["core_display_name"] = core->display_name;
+         hash["core_path"] = core->path;
+         hash["core_databases"] = core->databases;
+
+         ui_display_name = hash.value("core_name");
+
+         if (ui_display_name.isEmpty())
+            ui_display_name = hash.value("core_display_name");
+         if (ui_display_name.isEmpty())
+            ui_display_name = QFileInfo(hash.value("core_path")).fileName();
+         if (ui_display_name.isEmpty())
+            continue;
+
+         hash["ui_display_name"] = ui_display_name;
+
+         for (j = 0; j < databases.count(); j++)
+         {
+            QString database = databases.at(j);
+
+            if (database.isEmpty())
+               continue;
+
+            if (!allDatabases.contains(database))
+               allDatabases.append(database);
+         }
+
+         if (!allCores.contains(hash))
+            allCores.append(hash);
+      }
+
+      std::sort(allCores.begin(), allCores.end(), comp_hash_ui_display_name_key_lower);
+      std::sort(allDatabases.begin(), allDatabases.end(), comp_string_lower);
+
+      for (j = 0; j < allCores.count(); j++)
+      {
+         const QHash<QString, QString> &hash = allCores.at(j);
+
+         m_coreComboBox->addItem(hash.value("ui_display_name"), QVariant::fromValue(hash));
+      }
+
+      for (j = 0; j < allDatabases.count(); j++)
+      {
+         QString database = allDatabases.at(j);
+         m_databaseComboBox->addItem(database, database);
+      }
+   }
+}
+
+const QHash<QString, QString> PlaylistEntryDialog::getSelectedCore()
+{
+   return m_coreComboBox->currentData(Qt::UserRole).value<QHash<QString, QString> >();
+}
+
+const QString PlaylistEntryDialog::getSelectedDatabase()
+{
+   return m_databaseComboBox->currentData(Qt::UserRole).toString();
+}
+
+void PlaylistEntryDialog::onAccepted()
+{
+}
+
+void PlaylistEntryDialog::onRejected()
+{
+}
+
+bool PlaylistEntryDialog::showDialog()
+{
+   loadPlaylistOptions();
+
+   if (exec() == QDialog::Accepted)
+      return true;
+
+   return false;
+}
+
+void PlaylistEntryDialog::hideDialog()
+{
+   reject();
+}
+
 ViewOptionsDialog::ViewOptionsDialog(MainWindow *mainwindow, QWidget *parent) :
    QDialog(parent)
    ,m_mainwindow(mainwindow)
@@ -571,6 +726,7 @@ MainWindow::MainWindow(QWidget *parent) :
    ,m_currentGridWidget(NULL)
    ,m_allPlaylistsListMaxCount(0)
    ,m_allPlaylistsGridMaxCount(0)
+   ,m_playlistEntryDialog(NULL)
 {
    settings_t *settings = config_get_ptr();
    QDir playlistDir(settings->paths.directory_playlist);
@@ -667,6 +823,7 @@ MainWindow::MainWindow(QWidget *parent) :
    /* ViewOptionsDialog needs m_settings set before it's constructed */
    m_settings = new QSettings(configDir + "/retroarch_qt.cfg", QSettings::IniFormat, this);
    m_viewOptionsDialog = new ViewOptionsDialog(this, 0);
+   m_playlistEntryDialog = new PlaylistEntryDialog(this, 0);
 
    /* default NULL parameter for parent wasn't added until 5.7 */
    m_startCorePushButton->setDefaultAction(new QAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_START_CORE), m_startCorePushButton));
@@ -859,8 +1016,13 @@ void MainWindow::dropEvent(QDropEvent *event)
       QString currentPlaylistPath;
       QListWidgetItem *currentItem = m_listWidget->currentItem();
       QByteArray currentPlaylistArray;
+      QScopedPointer<QProgressDialog> dialog(NULL);
+      PlaylistEntryDialog *playlistDialog = playlistEntryDialog();
+      QHash<QString, QString> selectedCore;
+      QString selectedDatabase;
       const char *currentPlaylistData = NULL;
       playlist_t *playlist = NULL;
+      int i;
 
       if (currentItem)
       {
@@ -873,17 +1035,21 @@ void MainWindow::dropEvent(QDropEvent *event)
          }
       }
 
-      QProgressDialog dialog(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES), "Cancel", 0, 0, this);
-      int i;
+      if (!playlistDialog->showDialog())
+         return;
 
-      dialog.setWindowModality(Qt::ApplicationModal);
+      selectedCore = m_playlistEntryDialog->getSelectedCore();
+      selectedDatabase = m_playlistEntryDialog->getSelectedDatabase();
+
+      dialog.reset(new QProgressDialog(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES), "Cancel", 0, 0, this));
+      dialog->setWindowModality(Qt::ApplicationModal);
 
       for (i = 0; i < urls.count(); i++)
       {
          QString path(urls.at(i).toLocalFile());
          QFileInfo fileInfo(path);
 
-         if (dialog.wasCanceled())
+         if (dialog->wasCanceled())
             return;
 
          if (i % 25 == 0)
@@ -902,8 +1068,8 @@ void MainWindow::dropEvent(QDropEvent *event)
          }
       }
 
-      dialog.setLabelText(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST));
-      dialog.setMaximum(list.count());
+      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);
 
@@ -913,10 +1079,16 @@ void MainWindow::dropEvent(QDropEvent *event)
          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())
+         if (dialog->wasCanceled())
          {
             playlist_free(playlist);
             return;
@@ -930,13 +1102,55 @@ void MainWindow::dropEvent(QDropEvent *event)
          fileNameNoExten = fileBaseNameArray.constData();
 
          /* a modal QProgressDialog calls processEvents() automatically in setValue() */
-         dialog.setValue(i + 1);
+         dialog->setValue(i + 1);
 
          pathArray = fileName.toUtf8();
          pathData = pathArray.constData();
 
+         if (selectedCore.isEmpty())
+         {
+            corePathData = "DETECT";
+            coreNameData = "DETECT";
+         }
+         else
+         {
+            corePathArray = selectedCore.value("core_path").toUtf8();
+            coreNameArray = selectedCore.value("core_name").toUtf8();
+            corePathData = corePathArray.constData();
+            coreNameData = coreNameArray.constData();
+         }
+
+         if (selectedDatabase.isEmpty())
+         {
+            databaseArray = QFileInfo(currentPlaylistPath).fileName().toUtf8();
+            databaseData = databaseArray.constData();
+         }
+         else
+         {
+            selectedDatabase += file_path_str(FILE_PATH_LPL_EXTENSION);
+            databaseArray = selectedDatabase.toUtf8();
+            databaseData = databaseArray.constData();
+         }
+
+         if (path_is_compressed_file(pathData))
+         {
+            struct string_list *list = file_archive_get_file_list(pathData, NULL);
+
+            if (list)
+            {
+               if (list->size == 1)
+               {
+                  /* assume archives with one file should have that file loaded directly */
+                  pathArray = (QString(pathData) + "#" + list->elems[0].data).toUtf8();
+                  pathData = pathArray.constData();
+               }
+
+               string_list_free(list);
+            }
+         }
+
          playlist_push(playlist, pathData, fileNameNoExten,
-               "DETECT", "DETECT", fileNameNoExten, "00000000|crc");
+               corePathData, coreNameData, "00000000|crc", databaseData);
       }
 
       playlist_write_file(playlist);
@@ -2394,6 +2608,11 @@ bool MainWindow::isCoreLoaded()
    return true;
 }
 
+PlaylistEntryDialog* MainWindow::playlistEntryDialog()
+{
+   return m_playlistEntryDialog;
+}
+
 ViewOptionsDialog* MainWindow::viewOptionsDialog()
 {
    return m_viewOptionsDialog;
@@ -3405,7 +3624,7 @@ void MainWindow::addPlaylistItemsToGrid(const QStringList &paths, bool add)
       }
    }
 finish:
-   std::sort(items.begin(), items.end(), comp_hash_label_key);
+   std::sort(items.begin(), items.end(), comp_hash_label_key_lower);
 
    addPlaylistHashToGrid(items);
 }
diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h
index 0a87b23dd4..a9b017ea3a 100644
--- a/ui/drivers/ui_qt.h
+++ b/ui/drivers/ui_qt.h
@@ -164,6 +164,27 @@ private slots:
    void onLastWindowClosed();
 };
 
+class PlaylistEntryDialog : public QDialog
+{
+   Q_OBJECT
+public:
+   PlaylistEntryDialog(MainWindow *mainwindow, QWidget *parent = 0);
+   const QHash<QString, QString> getSelectedCore();
+   const QString getSelectedDatabase();
+public slots:
+   bool showDialog();
+   void hideDialog();
+   void onAccepted();
+   void onRejected();
+private:
+   void loadPlaylistOptions();
+
+   MainWindow *m_mainwindow;
+   QSettings *m_settings;
+   QComboBox *m_coreComboBox;
+   QComboBox *m_databaseComboBox;
+};
+
 class ViewOptionsDialog : public QDialog
 {
    Q_OBJECT
@@ -300,6 +321,7 @@ public:
    ViewType getCurrentViewType();
    void setAllPlaylistsListMaxCount(int count);
    void setAllPlaylistsGridMaxCount(int count);
+   PlaylistEntryDialog* playlistEntryDialog();
 
 signals:
    void thumbnailChanged(const QPixmap &pixmap);
@@ -434,6 +456,7 @@ private:
    QPointer<ThumbnailWidget> m_currentGridWidget;
    int m_allPlaylistsListMaxCount;
    int m_allPlaylistsGridMaxCount;
+   PlaylistEntryDialog *m_playlistEntryDialog;
 
 protected:
    void closeEvent(QCloseEvent *event);