diff --git a/rpcs3/rpcs3qt/vfs_dialog_path_widget.cpp b/rpcs3/rpcs3qt/vfs_dialog_path_widget.cpp index 090e97ee69..a540278133 100644 --- a/rpcs3/rpcs3qt/vfs_dialog_path_widget.cpp +++ b/rpcs3/rpcs3qt/vfs_dialog_path_widget.cpp @@ -16,14 +16,15 @@ vfs_dialog_path_widget::vfs_dialog_path_widget(const QString& name, const QStrin for (const QString& dir : all_dirs) { - QListWidgetItem* item = new QListWidgetItem(dir, m_dir_list); + QListWidgetItem* item = add_directory(dir); + if (dir == current_path) selected_item = item; } // We must show the currently selected config. if (!selected_item) - selected_item = new QListWidgetItem(current_path, m_dir_list); + selected_item = add_directory(current_path); selected_item->setSelected(true); @@ -54,21 +55,64 @@ vfs_dialog_path_widget::vfs_dialog_path_widget(const QString& name, const QStrin setLayout(vbox); + update_selection(); + + connect(m_dir_list->model(), &QAbstractItemModel::dataChanged, this, [this](const QModelIndex&, const QModelIndex&, const QList& roles) + { + if (m_is_changing_data || (!roles.empty() && !roles.contains(Qt::ItemDataRole::CheckStateRole))) + { + return; + } + + // Check if an item was selected + const QString selected_path = m_selected_config_label->text() == EmptyPath ? "" : m_selected_config_label->text(); + QAbstractItemModel* model = m_dir_list->model(); + + for (int i = 0; i < model->rowCount(); ++i) + { + if (model->index(i, 0).data(Qt::ItemDataRole::CheckStateRole).toInt() != Qt::Checked) continue; + + const QString path = model->index(i, 0).data(Qt::ItemDataRole::DisplayRole).toString(); + if (path == selected_path) continue; + + // Select new path + m_selected_config_label->setText(path.isEmpty() ? EmptyPath : path); + update_selection(); + break; + } + }); + connect(m_dir_list, &QListWidget::currentRowChanged, this, [this, button_remove_dir](int row) { - QListWidgetItem* item = m_dir_list->item(row); - m_selected_config_label->setText((item && !item->text().isEmpty()) ? item->text() : EmptyPath); - button_remove_dir->setEnabled(item && row > 0); + button_remove_dir->setEnabled(m_dir_list->item(row) && row > 0); }); } -void vfs_dialog_path_widget::reset() const +void vfs_dialog_path_widget::reset() { m_dir_list->clear(); - m_dir_list->setCurrentItem(new QListWidgetItem(m_default_path, m_dir_list)); + m_dir_list->setCurrentItem(add_directory(m_default_path)); + update_selection(); } -void vfs_dialog_path_widget::add_new_directory() const +QListWidgetItem* vfs_dialog_path_widget::add_directory(const QString& path) +{ + // Make sure to only add a path once + for (int i = 0; i < m_dir_list->count(); ++i) + { + if (m_dir_list->item(i)->text() == path) + { + return nullptr; + } + } + + QListWidgetItem* item = new QListWidgetItem(path, m_dir_list); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + + return item; +} + +void vfs_dialog_path_widget::add_new_directory() { QString dir = QFileDialog::getExistingDirectory(nullptr, tr("Choose a directory"), QCoreApplication::applicationDirPath(), QFileDialog::DontResolveSymlinks); @@ -78,19 +122,57 @@ void vfs_dialog_path_widget::add_new_directory() const if (!dir.endsWith("/")) dir += '/'; - m_dir_list->setCurrentItem(new QListWidgetItem(dir, m_dir_list)); + m_dir_list->setCurrentItem(add_directory(dir)); + update_selection(); } -void vfs_dialog_path_widget::remove_directory() const +void vfs_dialog_path_widget::remove_directory() { - const int row = m_dir_list->currentRow(); - if (row > 0) + if (const int row = m_dir_list->currentRow(); row > 0) { QListWidgetItem* item = m_dir_list->takeItem(row); delete item; + + update_selection(); } } +void vfs_dialog_path_widget::update_selection() +{ + const int count = m_dir_list->count(); + if (count <= 0) return; + + const QString selected_path = m_selected_config_label->text(); + bool found_path = false; + + m_is_changing_data = true; + + for (int i = 0; i < count; i++) + { + if (QListWidgetItem* item = m_dir_list->item(i)) + { + const bool is_selected = item->text() == selected_path; + item->setCheckState(is_selected ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + + if (is_selected) + { + m_dir_list->setCurrentItem(item); + found_path = true; + } + } + } + + if (!found_path) + { + QListWidgetItem* item = m_dir_list->item(0); + m_selected_config_label->setText(item->text().isEmpty() ? EmptyPath : item->text()); + item->setCheckState(Qt::CheckState::Checked); + m_dir_list->setCurrentItem(item); + } + + m_is_changing_data = false; +} + QStringList vfs_dialog_path_widget::get_dir_list() const { QStringList all_dirs; diff --git a/rpcs3/rpcs3qt/vfs_dialog_path_widget.h b/rpcs3/rpcs3qt/vfs_dialog_path_widget.h index a90a43d378..698d090509 100644 --- a/rpcs3/rpcs3qt/vfs_dialog_path_widget.h +++ b/rpcs3/rpcs3qt/vfs_dialog_path_widget.h @@ -22,11 +22,14 @@ public: std::string get_selected_path() const; // Reset this widget without saving the settings yet - void reset() const; + void reset(); protected: - void add_new_directory() const; - void remove_directory() const; + QListWidgetItem* add_directory(const QString& path); + void add_new_directory(); + void remove_directory(); + + void update_selection(); const QString EmptyPath = tr("Empty Path"); @@ -35,6 +38,7 @@ protected: std::shared_ptr m_gui_settings; // UI variables needed in higher scope - QListWidget* m_dir_list; - QLabel* m_selected_config_label; + QListWidget* m_dir_list = nullptr; + QLabel* m_selected_config_label = nullptr; + bool m_is_changing_data = false; };