summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-11-22 21:03:33 -0500
committerGravatar Zach Hilman2018-12-03 17:26:27 -0500
commitbf90f2402dae06ebf4292e59bf8703490596f6ba (patch)
tree89bb7e98853f74864d98122c2f8addd8eb7ac40b /src
parentam: Use ProfileSelect applet (diff)
downloadyuzu-bf90f2402dae06ebf4292e59bf8703490596f6ba.tar.gz
yuzu-bf90f2402dae06ebf4292e59bf8703490596f6ba.tar.xz
yuzu-bf90f2402dae06ebf4292e59bf8703490596f6ba.zip
qt: Implement GUI dialog frontend for ProfileSelector
Presents profiles in a list, similar to switch.
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/applets/profile_select.cpp168
-rw-r--r--src/yuzu/applets/profile_select.h73
-rw-r--r--src/yuzu/main.cpp22
-rw-r--r--src/yuzu/main.h2
6 files changed, 269 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 4b51943ab..4f0ea5d67 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -160,6 +160,8 @@ add_library(core STATIC
160 hle/service/am/applet_oe.h 160 hle/service/am/applet_oe.h
161 hle/service/am/applets/applets.cpp 161 hle/service/am/applets/applets.cpp
162 hle/service/am/applets/applets.h 162 hle/service/am/applets/applets.h
163 hle/service/am/applets/profile_select.cpp
164 hle/service/am/applets/profile_select.h
163 hle/service/am/applets/software_keyboard.cpp 165 hle/service/am/applets/software_keyboard.cpp
164 hle/service/am/applets/software_keyboard.h 166 hle/service/am/applets/software_keyboard.h
165 hle/service/am/applets/stub_applet.cpp 167 hle/service/am/applets/stub_applet.cpp
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index cfca8f4a8..61562b9b2 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -7,6 +7,8 @@ add_executable(yuzu
7 Info.plist 7 Info.plist
8 about_dialog.cpp 8 about_dialog.cpp
9 about_dialog.h 9 about_dialog.h
10 applets/profile_select.cpp
11 applets/profile_select.h
10 applets/software_keyboard.cpp 12 applets/software_keyboard.cpp
11 applets/software_keyboard.h 13 applets/software_keyboard.h
12 bootmanager.cpp 14 bootmanager.cpp
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp
new file mode 100644
index 000000000..5c1b65a2c
--- /dev/null
+++ b/src/yuzu/applets/profile_select.cpp
@@ -0,0 +1,168 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <mutex>
6#include <QDialogButtonBox>
7#include <QLabel>
8#include <QLineEdit>
9#include <QScrollArea>
10#include <QStandardItemModel>
11#include <QVBoxLayout>
12#include "common/file_util.h"
13#include "common/string_util.h"
14#include "core/hle/lock.h"
15#include "yuzu/applets/profile_select.h"
16#include "yuzu/main.h"
17
18// Same backup JPEG used by acc IProfile::GetImage if no jpeg found
19constexpr std::array<u8, 107> backup_jpeg{
20 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
21 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05,
22 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e,
23 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13,
24 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01,
25 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08,
26 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
27};
28
29QString FormatUserEntryText(const QString& username, Service::Account::UUID uuid) {
30 return QtProfileSelectionDialog::tr(
31 "%1\n%2", "%1 is the profile username, %2 is the formatted UUID (e.g. "
32 "00112233-4455-6677-8899-AABBCCDDEEFF))")
33 .arg(username, QString::fromStdString(uuid.FormatSwitch()));
34}
35
36QString GetImagePath(Service::Account::UUID uuid) {
37 const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
38 "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg";
39 return QString::fromStdString(path);
40}
41
42QPixmap GetIcon(Service::Account::UUID uuid) {
43 QPixmap icon{GetImagePath(uuid)};
44
45 if (!icon) {
46 icon.fill(Qt::black);
47 icon.loadFromData(backup_jpeg.data(), static_cast<u32>(backup_jpeg.size()));
48 }
49
50 return icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
51}
52
53QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
54 : QDialog(parent), profile_manager(std::make_unique<Service::Account::ProfileManager>()) {
55 outer_layout = new QVBoxLayout;
56
57 instruction_label = new QLabel(tr("Select a user:"));
58
59 scroll_area = new QScrollArea;
60
61 buttons = new QDialogButtonBox;
62 buttons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole);
63 buttons->addButton(tr("OK"), QDialogButtonBox::AcceptRole);
64
65 connect(buttons, &QDialogButtonBox::accepted, this, &QtProfileSelectionDialog::accept);
66 connect(buttons, &QDialogButtonBox::rejected, this, &QtProfileSelectionDialog::reject);
67
68 outer_layout->addWidget(instruction_label);
69 outer_layout->addWidget(scroll_area);
70 outer_layout->addWidget(buttons);
71
72 layout = new QVBoxLayout;
73 tree_view = new QTreeView;
74 item_model = new QStandardItemModel(tree_view);
75 tree_view->setModel(item_model);
76
77 tree_view->setAlternatingRowColors(true);
78 tree_view->setSelectionMode(QHeaderView::SingleSelection);
79 tree_view->setSelectionBehavior(QHeaderView::SelectRows);
80 tree_view->setVerticalScrollMode(QHeaderView::ScrollPerPixel);
81 tree_view->setHorizontalScrollMode(QHeaderView::ScrollPerPixel);
82 tree_view->setSortingEnabled(true);
83 tree_view->setEditTriggers(QHeaderView::NoEditTriggers);
84 tree_view->setUniformRowHeights(true);
85 tree_view->setIconSize({64, 64});
86 tree_view->setContextMenuPolicy(Qt::NoContextMenu);
87
88 item_model->insertColumns(0, 1);
89 item_model->setHeaderData(0, Qt::Horizontal, "Users");
90
91 // We must register all custom types with the Qt Automoc system so that we are able to use it
92 // with signals/slots. In this case, QList falls under the umbrells of custom types.
93 qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
94
95 layout->setContentsMargins(0, 0, 0, 0);
96 layout->setSpacing(0);
97 layout->addWidget(tree_view);
98
99 scroll_area->setLayout(layout);
100
101 connect(tree_view, &QTreeView::clicked, this, &QtProfileSelectionDialog::SelectUser);
102
103 const auto& profiles = profile_manager->GetAllUsers();
104 for (const auto& user : profiles) {
105 Service::Account::ProfileBase profile;
106 if (!profile_manager->GetProfileBase(user, profile))
107 continue;
108
109 const auto username = Common::StringFromFixedZeroTerminatedBuffer(
110 reinterpret_cast<const char*>(profile.username.data()), profile.username.size());
111
112 list_items.push_back(QList<QStandardItem*>{new QStandardItem{
113 GetIcon(user), FormatUserEntryText(QString::fromStdString(username), user)}});
114 }
115
116 for (const auto& item : list_items)
117 item_model->appendRow(item);
118
119 setLayout(outer_layout);
120 setWindowTitle(tr("Profile Selector"));
121 resize(550, 400);
122}
123
124QtProfileSelectionDialog::~QtProfileSelectionDialog() = default;
125
126void QtProfileSelectionDialog::accept() {
127 ok = true;
128 QDialog::accept();
129}
130
131void QtProfileSelectionDialog::reject() {
132 ok = false;
133 user_index = 0;
134 QDialog::reject();
135}
136
137bool QtProfileSelectionDialog::GetStatus() const {
138 return ok;
139}
140
141u32 QtProfileSelectionDialog::GetIndex() const {
142 return user_index;
143}
144
145void QtProfileSelectionDialog::SelectUser(const QModelIndex& index) {
146 user_index = index.row();
147}
148
149QtProfileSelector::QtProfileSelector(GMainWindow& parent) {
150 connect(this, &QtProfileSelector::MainWindowSelectProfile, &parent,
151 &GMainWindow::ProfileSelectorSelectProfile, Qt::QueuedConnection);
152 connect(&parent, &GMainWindow::ProfileSelectorFinishedSelection, this,
153 &QtProfileSelector::MainWindowFinishedSelection, Qt::DirectConnection);
154}
155
156QtProfileSelector::~QtProfileSelector() = default;
157
158void QtProfileSelector::SelectProfile(
159 std::function<void(std::optional<Service::Account::UUID>)> callback) const {
160 this->callback = std::move(callback);
161 emit MainWindowSelectProfile();
162}
163
164void QtProfileSelector::MainWindowFinishedSelection(std::optional<Service::Account::UUID> uuid) {
165 // Acquire the HLE mutex
166 std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
167 callback(uuid);
168}
diff --git a/src/yuzu/applets/profile_select.h b/src/yuzu/applets/profile_select.h
new file mode 100644
index 000000000..9acb092f3
--- /dev/null
+++ b/src/yuzu/applets/profile_select.h
@@ -0,0 +1,73 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <vector>
8#include <QDialog>
9#include <QList>
10#include "core/frontend/applets/profile_select.h"
11
12class GMainWindow;
13class QDialogButtonBox;
14class QGraphicsScene;
15class QLabel;
16class QScrollArea;
17class QStandardItem;
18class QStandardItemModel;
19class QTreeView;
20class QVBoxLayout;
21
22class QtProfileSelectionDialog final : public QDialog {
23 Q_OBJECT
24
25public:
26 QtProfileSelectionDialog(QWidget* parent);
27 ~QtProfileSelectionDialog() override;
28
29 void accept() override;
30 void reject() override;
31
32 bool GetStatus() const;
33 u32 GetIndex() const;
34
35private:
36 bool ok = false;
37 u32 user_index = 0;
38
39 void SelectUser(const QModelIndex& index);
40
41 QVBoxLayout* layout;
42 QTreeView* tree_view;
43 QStandardItemModel* item_model;
44 QGraphicsScene* scene;
45
46 std::vector<QList<QStandardItem*>> list_items;
47
48 QVBoxLayout* outer_layout;
49 QLabel* instruction_label;
50 QScrollArea* scroll_area;
51 QDialogButtonBox* buttons;
52
53 std::unique_ptr<Service::Account::ProfileManager> profile_manager;
54};
55
56class QtProfileSelector final : public QObject, public Core::Frontend::ProfileSelectApplet {
57 Q_OBJECT
58
59public:
60 explicit QtProfileSelector(GMainWindow& parent);
61 ~QtProfileSelector() override;
62
63 void SelectProfile(
64 std::function<void(std::optional<Service::Account::UUID>)> callback) const override;
65
66signals:
67 void MainWindowSelectProfile() const;
68
69private:
70 void MainWindowFinishedSelection(std::optional<Service::Account::UUID> uuid);
71
72 mutable std::function<void(std::optional<Service::Account::UUID>)> callback;
73};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b39bf1903..085cab74b 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -208,6 +208,28 @@ GMainWindow::~GMainWindow() {
208 delete render_window; 208 delete render_window;
209} 209}
210 210
211void GMainWindow::ProfileSelectorSelectProfile() {
212 QtProfileSelectionDialog dialog(this);
213 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
214 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
215 dialog.setWindowModality(Qt::WindowModal);
216 dialog.exec();
217
218 if (!dialog.GetStatus()) {
219 emit ProfileSelectorFinishedSelection(std::nullopt);
220 return;
221 }
222
223 Service::Account::ProfileManager manager;
224 const auto uuid = manager.GetUser(dialog.GetIndex());
225 if (!uuid.has_value()) {
226 emit ProfileSelectorFinishedSelection(std::nullopt);
227 return;
228 }
229
230 emit ProfileSelectorFinishedSelection(uuid);
231}
232
211void GMainWindow::SoftwareKeyboardGetText( 233void GMainWindow::SoftwareKeyboardGetText(
212 const Core::Frontend::SoftwareKeyboardParameters& parameters) { 234 const Core::Frontend::SoftwareKeyboardParameters& parameters) {
213 QtSoftwareKeyboardDialog dialog(this, parameters); 235 QtSoftwareKeyboardDialog dialog(this, parameters);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 674e73412..7c5eaf16b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -99,10 +99,12 @@ signals:
99 // Signal that tells widgets to update icons to use the current theme 99 // Signal that tells widgets to update icons to use the current theme
100 void UpdateThemedIcons(); 100 void UpdateThemedIcons();
101 101
102 void ProfileSelectorFinishedSelection(std::optional<Service::Account::UUID> uuid);
102 void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); 103 void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
103 void SoftwareKeyboardFinishedCheckDialog(); 104 void SoftwareKeyboardFinishedCheckDialog();
104 105
105public slots: 106public slots:
107 void ProfileSelectorSelectProfile();
106 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); 108 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
107 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); 109 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
108 110