diff options
| author | crueter <crueter@eden-emu.dev> | 2025-10-15 04:54:41 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2025-10-15 04:54:41 +0200 |
| commit | 5f9dba40a0fe71ccd7014ae37a2fbfd8f225396e (patch) | |
| tree | 4a0258d989bb795dd68fc2067fb01a7d7703868b /src/yuzu | |
| parent | 0a54ac63f00782605b74044e1661569d931354fe (diff) | |
[desktop] Data Manager, data import/export (#2700)
This adds a "Data Manager" dialog to the Tools menu. The Data Manager allows for the following operations:
- Open w/ system file manager
- Clear
- Export
- Import
On any of the following directories:
- Save (w/ profile selector)
- UserNAND
- SysNAND
- Mods
- Shaders
TODO for the future:
- "Cleanup" for each directory
- TitleID -> Game name--let users clean data for a specific game if applicable
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2700
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Diffstat (limited to 'src/yuzu')
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 24 | ||||
| -rw-r--r-- | src/yuzu/compatdb.cpp | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_web.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/data_dialog.cpp | 167 | ||||
| -rw-r--r-- | src/yuzu/data_dialog.h | 54 | ||||
| -rw-r--r-- | src/yuzu/data_dialog.ui | 148 | ||||
| -rw-r--r-- | src/yuzu/data_widget.ui | 205 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 17 | ||||
| -rw-r--r-- | src/yuzu/main.h | 1 | ||||
| -rw-r--r-- | src/yuzu/main.ui | 30 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/chat_room.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/client_room.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/direct_connect.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/host_room.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/lobby.cpp | 2 |
15 files changed, 626 insertions, 37 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index f6f752af3b..481d7c2f48 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -234,6 +234,9 @@ add_executable(yuzu deps_dialog.cpp deps_dialog.h deps_dialog.ui + + data_dialog.h data_dialog.cpp data_dialog.ui + data_widget.ui ) set_target_properties(yuzu PROPERTIES OUTPUT_NAME "eden") @@ -390,32 +393,13 @@ endif() target_link_libraries(yuzu PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core qt_common) -target_link_libraries(yuzu PRIVATE Boost::headers glad Qt6::Widgets) +target_link_libraries(yuzu PRIVATE Boost::headers glad Qt6::Widgets Qt6::Concurrent) target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) if (UNIX AND NOT APPLE) target_link_libraries(yuzu PRIVATE Qt6::DBus) endif() -target_compile_definitions(yuzu PRIVATE - # Use QStringBuilder for string concatenation to reduce - # the overall number of temporary strings created. - QT_USE_QSTRINGBUILDER - - # Disable implicit conversions from/to C strings - QT_NO_CAST_FROM_ASCII - QT_NO_CAST_TO_ASCII - - # Disable implicit type narrowing in signal/slot connect() calls. - QT_NO_NARROWING_CONVERSIONS_IN_CONNECT - - # Disable unsafe overloads of QProcess' start() function. - QT_NO_PROCESS_COMBINED_ARGUMENT_START - - # Disable implicit QString->QUrl conversions to enforce use of proper resolving functions. - QT_NO_URL_CAST_FROM_STRING -) - if (YUZU_ENABLE_COMPATIBILITY_REPORTING) target_compile_definitions(yuzu PRIVATE YUZU_ENABLE_COMPATIBILITY_REPORTING) endif() diff --git a/src/yuzu/compatdb.cpp b/src/yuzu/compatdb.cpp index 0e58f17405..6d5d263e16 100644 --- a/src/yuzu/compatdb.cpp +++ b/src/yuzu/compatdb.cpp @@ -1,10 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2017 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include <QButtonGroup> #include <QMessageBox> #include <QPushButton> -#include <QtConcurrent/qtconcurrentrun.h> +#include <qtconcurrentrun.h> #include "common/logging/log.h" #include "ui_compatdb.h" #include "yuzu/compatdb.h" diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp index 15a0029901..7a693be10c 100644 --- a/src/yuzu/configuration/configure_web.cpp +++ b/src/yuzu/configuration/configure_web.cpp @@ -14,7 +14,7 @@ #include <QRegExpValidator> #endif -#include <QtConcurrent/QtConcurrentRun> +#include <QtConcurrentRun> #include "common/settings.h" #include "ui_configure_web.h" #include "qt_common/uisettings.h" diff --git a/src/yuzu/data_dialog.cpp b/src/yuzu/data_dialog.cpp new file mode 100644 index 0000000000..bae49ff351 --- /dev/null +++ b/src/yuzu/data_dialog.cpp @@ -0,0 +1,167 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "data_dialog.h" +#include "core/hle/service/acc/profile_manager.h" +#include "frontend_common/data_manager.h" +#include "qt_common/qt_common.h" +#include "qt_common/qt_content_util.h" +#include "qt_common/qt_string_lookup.h" +#include "ui_data_dialog.h" + +#include <QDesktopServices> +#include <QFileDialog> +#include <QFutureWatcher> +#include <QProgressDialog> +#include <QtConcurrentRun> + +#include <core/frontend/applets/profile_select.h> + +#include <applets/qt_profile_select.h> + +DataDialog::DataDialog(QWidget *parent) + : QDialog(parent) + , ui(std::make_unique<Ui::DataDialog>()) +{ + ui->setupUi(this); + + // TODO: Should we make this a single widget that pulls data from a model? +#define WIDGET(name) \ + ui->page->addWidget(new DataWidget(FrontendCommon::DataManager::DataDir::name, \ + QtCommon::StringLookup::name##Tooltip, \ + QStringLiteral(#name), \ + this)); + + WIDGET(Saves) + WIDGET(Shaders) + WIDGET(UserNand) + WIDGET(SysNand) + WIDGET(Mods) + +#undef WIDGET + + connect(ui->labels, &QListWidget::itemSelectionChanged, this, [this]() { + const auto items = ui->labels->selectedItems(); + if (items.isEmpty()) { + return; + } + + ui->page->setCurrentIndex(ui->labels->row(items[0])); + }); +} + +DataDialog::~DataDialog() = default; + +DataWidget::DataWidget(FrontendCommon::DataManager::DataDir data_dir, + QtCommon::StringLookup::StringKey tooltip, + const QString &exportName, + QWidget *parent) + : QWidget(parent) + , ui(std::make_unique<Ui::DataWidget>()) + , m_dir(data_dir) + , m_exportName(exportName) +{ + ui->setupUi(this); + + ui->tooltip->setText(QtCommon::StringLookup::Lookup(tooltip)); + + ui->clear->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); + ui->open->setIcon(QIcon::fromTheme(QStringLiteral("folder"))); + ui->upload->setIcon(QIcon::fromTheme(QStringLiteral("upload"))); + ui->download->setIcon(QIcon::fromTheme(QStringLiteral("download"))); + + connect(ui->clear, &QPushButton::clicked, this, &DataWidget::clear); + connect(ui->open, &QPushButton::clicked, this, &DataWidget::open); + connect(ui->upload, &QPushButton::clicked, this, &DataWidget::upload); + connect(ui->download, &QPushButton::clicked, this, &DataWidget::download); + + scan(); +} + +void DataWidget::clear() +{ + std::string user_id{}; + if (m_dir == FrontendCommon::DataManager::DataDir::Saves) { + user_id = selectProfile(); + } + QtCommon::Content::ClearDataDir(m_dir, user_id); + scan(); +} + +void DataWidget::open() +{ + std::string user_id{}; + if (m_dir == FrontendCommon::DataManager::DataDir::Saves) { + user_id = selectProfile(); + } + QDesktopServices::openUrl(QUrl::fromLocalFile( + QString::fromStdString(FrontendCommon::DataManager::GetDataDir(m_dir, user_id)))); +} + +void DataWidget::upload() +{ + std::string user_id{}; + if (m_dir == FrontendCommon::DataManager::DataDir::Saves) { + user_id = selectProfile(); + } + QtCommon::Content::ExportDataDir(m_dir, user_id, m_exportName); +} + +void DataWidget::download() +{ + std::string user_id{}; + if (m_dir == FrontendCommon::DataManager::DataDir::Saves) { + user_id = selectProfile(); + } + QtCommon::Content::ImportDataDir(m_dir, user_id, std::bind(&DataWidget::scan, this)); +} + +void DataWidget::scan() { + ui->size->setText(tr("Calculating...")); + + QFutureWatcher<u64> *watcher = new QFutureWatcher<u64>(this); + + connect(watcher, &QFutureWatcher<u64>::finished, this, [=, this]() { + u64 size = watcher->result(); + ui->size->setText( + QString::fromStdString(FrontendCommon::DataManager::ReadableBytesSize(size))); + watcher->deleteLater(); + }); + + watcher->setFuture( + QtConcurrent::run([this]() { return FrontendCommon::DataManager::DataDirSize(m_dir); })); +} + +std::string DataWidget::selectProfile() +{ + const auto select_profile = [this] { + const Core::Frontend::ProfileSelectParameters parameters{ + .mode = Service::AM::Frontend::UiMode::UserSelector, + .invalid_uid_list = {}, + .display_options = {}, + .purpose = Service::AM::Frontend::UserSelectionPurpose::General, + }; + QtProfileSelectionDialog dialog(*QtCommon::system, this, parameters); + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint + | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::WindowModal); + + if (dialog.exec() == QDialog::Rejected) { + return -1; + } + + return dialog.GetIndex(); + }; + + const auto index = select_profile(); + if (index == -1) { + return ""; + } + + const auto uuid = QtCommon::system->GetProfileManager().GetUser(static_cast<std::size_t>(index)); + ASSERT(uuid); + + const auto user_id = uuid->AsU128(); + + return fmt::format("{:016X}{:016X}", user_id[1], user_id[0]); +} diff --git a/src/yuzu/data_dialog.h b/src/yuzu/data_dialog.h new file mode 100644 index 0000000000..70714be7cb --- /dev/null +++ b/src/yuzu/data_dialog.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef DATA_DIALOG_H +#define DATA_DIALOG_H + +#include <QDialog> +#include "frontend_common/data_manager.h" +#include "qt_common/qt_string_lookup.h" + +#include "ui_data_widget.h" + +namespace Ui { +class DataDialog; +} + +class DataDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DataDialog(QWidget *parent = nullptr); + ~DataDialog(); + +private: + std::unique_ptr<Ui::DataDialog> ui; +}; + +class DataWidget : public QWidget +{ + Q_OBJECT +public: + explicit DataWidget(FrontendCommon::DataManager::DataDir data_dir, + QtCommon::StringLookup::StringKey tooltip, + const QString &exportName, + QWidget *parent = nullptr); + +public slots: + void clear(); + void open(); + void upload(); + void download(); + + void scan(); + +private: + std::unique_ptr<Ui::DataWidget> ui; + FrontendCommon::DataManager::DataDir m_dir; + const QString m_exportName; + + std::string selectProfile(); +}; + +#endif // DATA_DIALOG_H diff --git a/src/yuzu/data_dialog.ui b/src/yuzu/data_dialog.ui new file mode 100644 index 0000000000..06751e2fb1 --- /dev/null +++ b/src/yuzu/data_dialog.ui @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DataDialog</class> + <widget class="QDialog" name="DataDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>480</width> + <height>320</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>320</height> + </size> + </property> + <property name="windowTitle"> + <string>Data Manager</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1"> + <item> + <widget class="QListWidget" name="labels"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text"> + <string>Saves</string> + </property> + </item> + <item> + <property name="text"> + <string>Shaders</string> + </property> + </item> + <item> + <property name="text"> + <string>UserNAND</string> + </property> + </item> + <item> + <property name="text"> + <string>SysNAND</string> + </property> + </item> + <item> + <property name="text"> + <string>Mods</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QStackedWidget" name="page"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>275</width> + <height>200</height> + </size> + </property> + <property name="currentIndex"> + <number>-1</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="leftMargin"> + <number>10</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Deleting ANY data is IRREVERSABLE!</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::StandardButton::Ok</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>DataDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>DataDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/yuzu/data_widget.ui b/src/yuzu/data_widget.ui new file mode 100644 index 0000000000..99010d8856 --- /dev/null +++ b/src/yuzu/data_widget.ui @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DataWidget</class> + <widget class="QWidget" name="DataWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>275</width> + <height>200</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="3,2"> + <item> + <widget class="QLabel" name="tooltip"> + <property name="text"> + <string>Tooltip</string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignCenter</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="size"> + <property name="font"> + <font> + <pointsize>10</pointsize> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string notr="true">Size</string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignCenter</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QPushButton" name="open"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>52</width> + <height>47</height> + </size> + </property> + <property name="toolTip"> + <string>Open with your system file manager</string> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton { +max-width: 50px; +max-height: 45px; +min-width: 50px; +min-height: 45px; +}</string> + </property> + <property name="text"> + <string/> + </property> + <property name="iconSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="clear"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>52</width> + <height>47</height> + </size> + </property> + <property name="toolTip"> + <string>Delete all data in this directory. THIS IS 100% IRREVERSABLE!</string> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton { +max-width: 50px; +max-height: 45px; +min-width: 50px; +min-height: 45px; +}</string> + </property> + <property name="text"> + <string/> + </property> + <property name="iconSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="upload"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>52</width> + <height>47</height> + </size> + </property> + <property name="toolTip"> + <string>Export all data in this directory. This may take a while!</string> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton { +max-width: 50px; +max-height: 45px; +min-width: 50px; +min-height: 45px; +}</string> + </property> + <property name="text"> + <string/> + </property> + <property name="iconSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="download"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>1</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>52</width> + <height>47</height> + </size> + </property> + <property name="toolTip"> + <string>Import data for this directory. This may take a while, and will delete ALL EXISTING DATA!</string> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton { +max-width: 50px; +max-height: 45px; +min-width: 50px; +min-height: 45px; +}</string> + </property> + <property name="text"> + <string/> + </property> + <property name="iconSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 2c991b9208..77bfe5db9f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -156,6 +156,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "yuzu/debugger/console.h" #include "yuzu/debugger/controller.h" #include "yuzu/debugger/wait_tree.h" +#include "yuzu/data_dialog.h" #include "yuzu/deps_dialog.h" #include "yuzu/discord.h" #include "yuzu/game_list.h" @@ -1705,6 +1706,7 @@ void GMainWindow::ConnectMenuEvents() { connect_menu(ui->action_Install_Keys, &GMainWindow::OnInstallDecryptionKeys); connect_menu(ui->action_About, &GMainWindow::OnAbout); connect_menu(ui->action_Eden_Dependencies, &GMainWindow::OnEdenDependencies); + connect_menu(ui->action_Data_Manager, &GMainWindow::OnDataDialog); } void GMainWindow::UpdateMenuState() { @@ -2406,7 +2408,6 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target ASSERT_MSG(has_user_save != has_device_save, "Game uses both user and device savedata?"); - // TODO(alekpop): It returns the wrong user switch (target) { case GameListOpenTarget::SaveData: { open_target = tr("Save Data"); @@ -2792,6 +2793,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } void GMainWindow::OnGameListOpenDirectory(const QString& directory) { + // TODO(crueter): QtCommon std::filesystem::path fs_path; if (directory == QStringLiteral("SDMC")) { fs_path = @@ -3934,6 +3936,15 @@ void GMainWindow::OnEdenDependencies() { depsDialog.exec(); } +void GMainWindow::OnDataDialog() { + DataDialog dataDialog(this); + dataDialog.exec(); + + // refresh stuff in case it was cleared + OnGameListRefresh(); + +} + void GMainWindow::OnToggleFilterBar() { game_list->SetFilterVisible(ui->action_Show_Filter_Bar->isChecked()); if (ui->action_Show_Filter_Bar->isChecked()) { @@ -4474,11 +4485,15 @@ void GMainWindow::SetFirmwareVersion() { if (result.IsError() || !CheckFirmwarePresence()) { LOG_INFO(Frontend, "Installed firmware: No firmware available"); + ui->menu_Applets->setEnabled(false); + ui->menu_Create_Shortcuts->setEnabled(false); firmware_label->setVisible(false); return; } firmware_label->setVisible(true); + ui->menu_Applets->setEnabled(true); + ui->menu_Create_Shortcuts->setEnabled(true); const std::string display_version(firmware_data.display_version.data()); const std::string display_title(firmware_data.display_title.data()); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index e3922759b0..a3e99c05fe 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -387,6 +387,7 @@ private slots: void OnInstallDecryptionKeys(); void OnAbout(); void OnEdenDependencies(); + void OnDataDialog(); void OnToggleFilterBar(); void OnToggleStatusBar(); void OnGameListRefresh(); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 5f56c9e6d1..12ff4efdf1 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -158,13 +158,23 @@ </property> <widget class="QMenu" name="menu_cabinet_applet"> <property name="title"> - <string>&Amiibo</string> + <string>Am&iibo</string> </property> <addaction name="action_Load_Cabinet_Nickname_Owner"/> <addaction name="action_Load_Cabinet_Eraser"/> <addaction name="action_Load_Cabinet_Restorer"/> <addaction name="action_Load_Cabinet_Formatter"/> </widget> + <widget class="QMenu" name="menu_Applets"> + <property name="title"> + <string>&Applets</string> + </property> + <addaction name="action_Load_Home_Menu"/> + <addaction name="action_Load_Album"/> + <addaction name="action_Load_Mii_Edit"/> + <addaction name="action_Open_Controller_Menu"/> + <addaction name="action_Open_Setup"/> + </widget> <widget class="QMenu" name="menuTAS"> <property name="title"> <string>&TAS</string> @@ -184,7 +194,7 @@ </widget> <widget class="QMenu" name="menuInstall_Firmware"> <property name="title"> - <string>Install Firmware</string> + <string>Install &Firmware</string> </property> <addaction name="action_Firmware_From_Folder"/> <addaction name="action_Firmware_From_ZIP"/> @@ -192,13 +202,10 @@ <addaction name="action_Install_Keys"/> <addaction name="menuInstall_Firmware"/> <addaction name="action_Verify_installed_contents"/> + <addaction name="action_Data_Manager"/> <addaction name="separator"/> <addaction name="menu_cabinet_applet"/> - <addaction name="action_Load_Album"/> - <addaction name="action_Load_Mii_Edit"/> - <addaction name="action_Open_Controller_Menu"/> - <addaction name="action_Load_Home_Menu"/> - <addaction name="action_Open_Setup"/> + <addaction name="menu_Applets"/> <addaction name="menu_Create_Shortcuts"/> <addaction name="separator"/> <addaction name="action_Capture_Screenshot"/> @@ -497,12 +504,12 @@ </action> <action name="action_Install_Keys"> <property name="text"> - <string>Install Decryption Keys</string> + <string>Install Decryption &Keys</string> </property> </action> <action name="action_Load_Home_Menu"> <property name="text"> - <string>Open Home Menu</string> + <string>Open &Home Menu</string> </property> </action> <action name="action_Discord"> @@ -593,6 +600,11 @@ <string>&Eden Dependencies</string> </property> </action> + <action name="action_Data_Manager"> + <property name="text"> + <string>&Data Manager</string> + </property> + </action> </widget> <resources> <include location="yuzu.qrc"/> diff --git a/src/yuzu/multiplayer/chat_room.cpp b/src/yuzu/multiplayer/chat_room.cpp index 4c2c41ea2a..53beda0f8e 100644 --- a/src/yuzu/multiplayer/chat_room.cpp +++ b/src/yuzu/multiplayer/chat_room.cpp @@ -16,7 +16,7 @@ #include <QMetaType> #include <QTime> #include <QUrl> -#include <QtConcurrent/QtConcurrentRun> +#include <QtConcurrentRun> #include "common/logging/log.h" #include "network/announce_multiplayer_session.h" #include "ui_chat_room.h" diff --git a/src/yuzu/multiplayer/client_room.cpp b/src/yuzu/multiplayer/client_room.cpp index 93d6662c1e..4e995c044f 100644 --- a/src/yuzu/multiplayer/client_room.cpp +++ b/src/yuzu/multiplayer/client_room.cpp @@ -10,7 +10,7 @@ #include <QLocale> #include <QMetaType> #include <QTime> -#include <QtConcurrent/QtConcurrentRun> +#include <QtConcurrentRun> #include "common/logging/log.h" #include "network/announce_multiplayer_session.h" #include "ui_client_room.h" diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp index deac3b9e59..6291979fe6 100644 --- a/src/yuzu/multiplayer/direct_connect.cpp +++ b/src/yuzu/multiplayer/direct_connect.cpp @@ -9,7 +9,7 @@ #include <QIntValidator> #include <QRegularExpressionValidator> #include <QString> -#include <QtConcurrent/QtConcurrentRun> +#include <QtConcurrentRun> #include "common/settings.h" #include "core/core.h" #include "core/internal_network/network_interface.h" diff --git a/src/yuzu/multiplayer/host_room.cpp b/src/yuzu/multiplayer/host_room.cpp index 4dd3958550..cc163a5420 100644 --- a/src/yuzu/multiplayer/host_room.cpp +++ b/src/yuzu/multiplayer/host_room.cpp @@ -12,7 +12,7 @@ #include <QMessageBox> #include <QMetaType> #include <QTime> -#include <QtConcurrent/QtConcurrentRun> +#include <QtConcurrentRun> #include "common/logging/log.h" #include "common/settings.h" #include "core/core.h" diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 84723041df..e8daa0c6eb 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp @@ -6,7 +6,7 @@ #include <QInputDialog> #include <QList> -#include <QtConcurrent/QtConcurrentRun> +#include <QtConcurrentRun> #include "common/logging/log.h" #include "common/settings.h" #include "core/core.h" |
