mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-19 18:36:53 +02:00
launcher: add Import game button
Add a prominent Import button to ConfigurationListWidget that lets users select a game folder (containing eboot.bin) or a folder containing multiple games via QFileDialog. Handles: - Single game folder selected: adds its parent to game_dirs (Scan searches subdirectories, so parent is needed) - Folder with multiple games: adds the selected folder - Deduplication via PathKey/NormalizeGameDirectories, writes settings, rescans, and selects the imported game if found - Shows info/warning dialogs when no games are found UI: QToolButton with SP_DirOpenIcon and text Import beside the existing toolbar, styled with a blue background for visibility. Logic in ConfigurationListWidget::import_game().
This commit is contained in:
@@ -119,36 +119,64 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="delete_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Delete configuration</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<item>
|
||||
<widget class="QToolButton" name="delete_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<width>36</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Delete configuration</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="import_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>96</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Import game folder (containing eboot.bin)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
|
||||
@@ -63,6 +63,7 @@ protected slots:
|
||||
void edit_global_settings();
|
||||
void edit_input_mapping();
|
||||
void run_configuration();
|
||||
void import_game();
|
||||
void list_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
|
||||
void list_itemDoubleClicked(QTreeWidgetItem* witem, int column);
|
||||
void show_context_menu(const QPoint& pos);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <QDialog>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QHeaderView>
|
||||
#include <QIcon>
|
||||
@@ -234,6 +235,11 @@ ConfigurationListWidget::ConfigurationListWidget(QWidget* parent)
|
||||
m_ui->input_mapping_button->setToolTip(tr("Edit global input mapping"));
|
||||
m_ui->edit_button->setIcon(QIcon(QStringLiteral(":/icons/edit-configuration.svg")));
|
||||
m_ui->delete_button->setIcon(QIcon(QStringLiteral(":/icons/remove-configuration.svg")));
|
||||
m_ui->import_button->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon));
|
||||
m_ui->import_button->setStyleSheet(QStringLiteral(
|
||||
"QToolButton { background: rgba(32,118,210,90); border: 1px solid rgba(80,160,255,120); "
|
||||
"border-radius: 5px; padding: 3px 8px; color: #eef4ff; }"
|
||||
"QToolButton:hover { background: rgba(32,118,210,140); border-color: rgba(80,160,255,180); }"));
|
||||
|
||||
m_ui->delete_button->setEnabled(false);
|
||||
m_ui->edit_button->setEnabled(false);
|
||||
@@ -259,6 +265,8 @@ ConfigurationListWidget::ConfigurationListWidget(QWidget* parent)
|
||||
&ConfigurationListWidget::edit_configuration);
|
||||
connect(m_ui->delete_button, &QToolButton::clicked, this,
|
||||
&ConfigurationListWidget::delete_configuartion);
|
||||
connect(m_ui->import_button, &QToolButton::clicked, this,
|
||||
&ConfigurationListWidget::import_game);
|
||||
connect(m_ui->cfgs_list, &QTreeWidget::currentItemChanged, this,
|
||||
&ConfigurationListWidget::list_currentItemChanged);
|
||||
connect(m_ui->cfgs_list, &QTreeWidget::itemDoubleClicked, this,
|
||||
@@ -731,6 +739,80 @@ void ConfigurationListWidget::edit_input_mapping() {
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::import_game() {
|
||||
const QString selected = QFileDialog::getExistingDirectory(
|
||||
this, tr("Select game folder (containing eboot.bin) or folder containing games"),
|
||||
QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
|
||||
if (selected.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dir(selected);
|
||||
QString dir_to_add;
|
||||
QString expected_game_path;
|
||||
|
||||
if (dir.exists(QStringLiteral("eboot.bin"))) {
|
||||
// Selected a single game folder — add its parent so Scan finds it
|
||||
// (Scan only searches subdirectories of game_dirs, not the dirs themselves)
|
||||
dir_to_add = QDir::cleanPath(dir.absolutePath() + QStringLiteral("/.."));
|
||||
expected_game_path = QDir::cleanPath(dir.absolutePath());
|
||||
} else {
|
||||
dir_to_add = QDir::cleanPath(dir.absolutePath());
|
||||
}
|
||||
|
||||
const QString normalized = NormalizeGameDirectory(dir_to_add);
|
||||
if (normalized.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString key = PathKey(normalized);
|
||||
bool already_exists = false;
|
||||
for (const auto& existing: m_game_dirs) {
|
||||
if (PathKey(existing) == key) {
|
||||
already_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!already_exists) {
|
||||
m_game_dirs.append(normalized);
|
||||
m_game_dirs = NormalizeGameDirectories(m_game_dirs);
|
||||
WriteSettings();
|
||||
}
|
||||
|
||||
const int before_count = m_ui->cfgs_list->topLevelItemCount();
|
||||
ScanGameDirectory();
|
||||
|
||||
if (!expected_game_path.isEmpty()) {
|
||||
const QString expected_key = PathKey(expected_game_path);
|
||||
for (int i = 0; i < m_ui->cfgs_list->topLevelItemCount(); ++i) {
|
||||
auto* item = static_cast<ConfigurationItem*>(m_ui->cfgs_list->topLevelItem(i));
|
||||
if (PathKey(item->GetInfo().game_path) == expected_key) {
|
||||
m_ui->cfgs_list->setCurrentItem(item);
|
||||
SelectItem(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ui->cfgs_list->topLevelItemCount() == 0) {
|
||||
QMessageBox::information(this, tr("Import game"),
|
||||
tr("No games found in the selected folder.\n\n"
|
||||
"Make sure the folder contains a game with eboot.bin "
|
||||
"or subfolders with games."));
|
||||
} else if (!expected_game_path.isEmpty() && m_ui->cfgs_list->topLevelItemCount() == before_count) {
|
||||
// Single game import didn't appear
|
||||
const int after_count = m_ui->cfgs_list->topLevelItemCount();
|
||||
if (after_count == before_count) {
|
||||
QMessageBox::warning(this, tr("Import game"),
|
||||
tr("The selected game folder was added, but no game was detected.\n\n"
|
||||
"Expected eboot.bin at: %1")
|
||||
.arg(expected_game_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationListWidget::ClearCustomSettings(ConfigurationItem* item) {
|
||||
delete m_custom_infos.take(item->GetInfo().game_path);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user