forked from etc/pineapple-src
early-access version 1600
This commit is contained in:
parent
0a5c4414b1
commit
11641be04e
20 changed files with 165 additions and 27 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1599.
|
This is the source code for early-access 1600.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
3
dist/license.md
vendored
3
dist/license.md
vendored
|
@ -12,6 +12,7 @@ qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||||
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
qt_themes/default/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
qt_themes/qdarkstyle/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
||||||
qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
@ -20,6 +21,7 @@ qt_themes/qdarkstyle/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
qt_themes/qdarkstyle/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
|
||||||
qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/qdarkstyle/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
qt_themes/qdarkstyle/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
qt_themes/colorful/icons/16x16/view-refresh.png | Apache 2.0 | https://material.io
|
||||||
qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
@ -28,5 +30,6 @@ qt_themes/colorful/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/48x48/plus.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/48x48/plus.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
qt_themes/colorful/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
qt_themes/colorful/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
qt_themes/colorful/icons/48x48/star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
|
||||||
<!-- TODO: Add the license of the yuzu icon -->
|
<!-- TODO: Add the license of the yuzu icon -->
|
BIN
dist/qt_themes/colorful/icons/48x48/star.png
vendored
Executable file
BIN
dist/qt_themes/colorful/icons/48x48/star.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
1
dist/qt_themes/colorful/style.qrc
vendored
1
dist/qt_themes/colorful/style.qrc
vendored
|
@ -7,6 +7,7 @@
|
||||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="colorful">
|
<qresource prefix="colorful">
|
||||||
|
|
1
dist/qt_themes/default/default.qrc
vendored
1
dist/qt_themes/default/default.qrc
vendored
|
@ -10,6 +10,7 @@
|
||||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
|
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
|
BIN
dist/qt_themes/default/icons/48x48/star.png
vendored
Executable file
BIN
dist/qt_themes/default/icons/48x48/star.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 686 B |
BIN
dist/qt_themes/qdarkstyle/icons/48x48/star.png
vendored
Executable file
BIN
dist/qt_themes/qdarkstyle/icons/48x48/star.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 725 B |
1
dist/qt_themes/qdarkstyle/style.qrc
vendored
1
dist/qt_themes/qdarkstyle/style.qrc
vendored
|
@ -8,6 +8,7 @@
|
||||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="qss_icons">
|
<qresource prefix="qss_icons">
|
||||||
|
|
BIN
dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.png
vendored
Executable file
BIN
dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/star.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 725 B |
|
@ -8,6 +8,7 @@
|
||||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||||
|
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="qss_icons">
|
<qresource prefix="qss_icons">
|
||||||
|
|
|
@ -358,6 +358,7 @@ chip.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||||
folder.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
folder.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||||
plus.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
plus.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||||
sd_card.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
sd_card.png (Colorful, Colorful Dark) | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
star.png | CC BY-ND 3.0 | https://icons8.com
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
Some icons are different in different themes, and they are separately listed
|
Some icons are different in different themes, and they are separately listed
|
||||||
|
|
|
@ -2,21 +2,16 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
// This file references various implementation details from Atmosphere, an open-source firmware for
|
|
||||||
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/svc_results.h"
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
|
constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
|
||||||
|
|
||||||
KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system)
|
KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_)
|
||||||
: Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {}
|
: Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {}
|
||||||
KResourceLimit::~KResourceLimit() = default;
|
KResourceLimit::~KResourceLimit() = default;
|
||||||
|
|
||||||
s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
|
s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
|
||||||
|
@ -83,7 +78,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
|
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
|
||||||
return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout);
|
return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
||||||
|
@ -114,7 +109,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_hints[index] + value <= limit_values[index] &&
|
if (current_hints[index] + value <= limit_values[index] &&
|
||||||
(timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) {
|
(timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) {
|
||||||
waiter_count++;
|
waiter_count++;
|
||||||
cond_var.Wait(&lock, timeout);
|
cond_var.Wait(&lock, timeout);
|
||||||
waiter_count--;
|
waiter_count--;
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
// This file references various implementation details from Atmosphere, an open-source firmware for
|
|
||||||
// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -15,8 +12,8 @@
|
||||||
|
|
||||||
union ResultCode;
|
union ResultCode;
|
||||||
|
|
||||||
namespace Core {
|
namespace Core::Timing {
|
||||||
class System;
|
class CoreTiming;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
@ -37,7 +34,7 @@ constexpr bool IsValidResourceType(LimitableResource type) {
|
||||||
|
|
||||||
class KResourceLimit final : public Object {
|
class KResourceLimit final : public Object {
|
||||||
public:
|
public:
|
||||||
explicit KResourceLimit(KernelCore& kernel, Core::System& system);
|
explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_);
|
||||||
~KResourceLimit();
|
~KResourceLimit();
|
||||||
|
|
||||||
s64 GetLimitValue(LimitableResource which) const;
|
s64 GetLimitValue(LimitableResource which) const;
|
||||||
|
@ -75,7 +72,6 @@ private:
|
||||||
mutable KLightLock lock;
|
mutable KLightLock lock;
|
||||||
s32 waiter_count{};
|
s32 waiter_count{};
|
||||||
KLightConditionVariable cond_var;
|
KLightConditionVariable cond_var;
|
||||||
KernelCore& kernel;
|
const Core::Timing::CoreTiming& core_timing;
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct KernelCore::Impl {
|
||||||
KMemoryLayout memory_layout;
|
KMemoryLayout memory_layout;
|
||||||
DeriveInitialMemoryLayout(memory_layout);
|
DeriveInitialMemoryLayout(memory_layout);
|
||||||
InitializeMemoryLayout(memory_layout);
|
InitializeMemoryLayout(memory_layout);
|
||||||
InitializeSystemResourceLimit(kernel, system, memory_layout);
|
InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout);
|
||||||
InitializeSlabHeaps();
|
InitializeSlabHeaps();
|
||||||
InitializeSchedulers();
|
InitializeSchedulers();
|
||||||
InitializeSuspendThreads();
|
InitializeSuspendThreads();
|
||||||
|
@ -142,9 +142,10 @@ struct KernelCore::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the default system resource limit
|
// Creates the default system resource limit
|
||||||
void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system,
|
void InitializeSystemResourceLimit(KernelCore& kernel,
|
||||||
|
const Core::Timing::CoreTiming& core_timing,
|
||||||
const KMemoryLayout& memory_layout) {
|
const KMemoryLayout& memory_layout) {
|
||||||
system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
|
system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing);
|
||||||
const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
|
const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
|
||||||
|
|
||||||
// If setting the default system values fails, then something seriously wrong has occurred.
|
// If setting the default system values fails, then something seriously wrong has occurred.
|
||||||
|
|
|
@ -2156,7 +2156,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
|
||||||
LOG_DEBUG(Kernel_SVC, "called");
|
LOG_DEBUG(Kernel_SVC, "called");
|
||||||
|
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
auto resource_limit = std::make_shared<KResourceLimit>(kernel, system);
|
auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming());
|
||||||
|
|
||||||
auto* const current_process = kernel.CurrentProcess();
|
auto* const current_process = kernel.CurrentProcess();
|
||||||
ASSERT(current_process != nullptr);
|
ASSERT(current_process != nullptr);
|
||||||
|
|
|
@ -936,6 +936,13 @@ void Config::ReadUIGamelistValues() {
|
||||||
UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt();
|
UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt();
|
||||||
UISettings::values.cache_game_list =
|
UISettings::values.cache_game_list =
|
||||||
ReadSetting(QStringLiteral("cache_game_list"), true).toBool();
|
ReadSetting(QStringLiteral("cache_game_list"), true).toBool();
|
||||||
|
const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites"));
|
||||||
|
for (int i = 0; i < favorites_size; i++) {
|
||||||
|
qt_config->setArrayIndex(i);
|
||||||
|
UISettings::values.favorited_ids.append(
|
||||||
|
ReadSetting(QStringLiteral("program_id")).toULongLong());
|
||||||
|
}
|
||||||
|
qt_config->endArray();
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
@ -1479,6 +1486,13 @@ void Config::SaveUIGamelistValues() {
|
||||||
WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3);
|
WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3);
|
||||||
WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2);
|
WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2);
|
||||||
WriteSetting(QStringLiteral("cache_game_list"), UISettings::values.cache_game_list, true);
|
WriteSetting(QStringLiteral("cache_game_list"), UISettings::values.cache_game_list, true);
|
||||||
|
qt_config->beginWriteArray(QStringLiteral("favorites"));
|
||||||
|
for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
|
||||||
|
qt_config->setArrayIndex(i);
|
||||||
|
WriteSetting(QStringLiteral("program_id"),
|
||||||
|
QVariant::fromValue(UISettings::values.favorited_ids[i]));
|
||||||
|
}
|
||||||
|
qt_config->endArray();
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QList>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
@ -84,6 +85,10 @@ void GameListSearchField::setFilterResult(int visible, int total) {
|
||||||
label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible));
|
label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameListSearchField::SearchFieldEmpty() {
|
||||||
|
return edit_filter->text().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
QString GameList::GetLastFilterResultItem() const {
|
QString GameList::GetLastFilterResultItem() const {
|
||||||
QString file_path;
|
QString file_path;
|
||||||
const int folder_count = item_model->rowCount();
|
const int folder_count = item_model->rowCount();
|
||||||
|
@ -187,7 +192,9 @@ void GameList::OnTextChanged(const QString& new_text) {
|
||||||
// If the searchfield is empty every item is visible
|
// If the searchfield is empty every item is visible
|
||||||
// Otherwise the filter gets applied
|
// Otherwise the filter gets applied
|
||||||
if (edit_filter_text.isEmpty()) {
|
if (edit_filter_text.isEmpty()) {
|
||||||
for (int i = 0; i < folder_count; ++i) {
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(),
|
||||||
|
UISettings::values.favorited_ids.size() == 0);
|
||||||
|
for (int i = 1; i < folder_count; ++i) {
|
||||||
folder = item_model->item(i, 0);
|
folder = item_model->item(i, 0);
|
||||||
const QModelIndex folder_index = folder->index();
|
const QModelIndex folder_index = folder->index();
|
||||||
const int children_count = folder->rowCount();
|
const int children_count = folder->rowCount();
|
||||||
|
@ -198,8 +205,9 @@ void GameList::OnTextChanged(const QString& new_text) {
|
||||||
}
|
}
|
||||||
search_field->setFilterResult(children_total, children_total);
|
search_field->setFilterResult(children_total, children_total);
|
||||||
} else {
|
} else {
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), true);
|
||||||
int result_count = 0;
|
int result_count = 0;
|
||||||
for (int i = 0; i < folder_count; ++i) {
|
for (int i = 1; i < folder_count; ++i) {
|
||||||
folder = item_model->item(i, 0);
|
folder = item_model->item(i, 0);
|
||||||
const QModelIndex folder_index = folder->index();
|
const QModelIndex folder_index = folder->index();
|
||||||
const int children_count = folder->rowCount();
|
const int children_count = folder->rowCount();
|
||||||
|
@ -280,6 +288,13 @@ void GameList::OnUpdateThemedIcons() {
|
||||||
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
Qt::DecorationRole);
|
Qt::DecorationRole);
|
||||||
break;
|
break;
|
||||||
|
case GameListItemType::Favorites:
|
||||||
|
child->setData(
|
||||||
|
QIcon::fromTheme(QStringLiteral("star"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -427,6 +442,13 @@ void GameList::DonePopulating(const QStringList& watch_list) {
|
||||||
emit ShowList(!IsEmpty());
|
emit ShowList(!IsEmpty());
|
||||||
|
|
||||||
item_model->invisibleRootItem()->appendRow(new GameListAddDir());
|
item_model->invisibleRootItem()->appendRow(new GameListAddDir());
|
||||||
|
item_model->invisibleRootItem()->insertRow(0, new GameListFavorites());
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(),
|
||||||
|
UISettings::values.favorited_ids.size() == 0);
|
||||||
|
tree_view->expand(item_model->invisibleRootItem()->child(0)->index());
|
||||||
|
for (u64 id : UISettings::values.favorited_ids) {
|
||||||
|
AddFavorite(id);
|
||||||
|
}
|
||||||
|
|
||||||
// Clear out the old directories to watch for changes and add the new ones
|
// Clear out the old directories to watch for changes and add the new ones
|
||||||
auto watch_dirs = watcher->directories();
|
auto watch_dirs = watcher->directories();
|
||||||
|
@ -446,7 +468,7 @@ void GameList::DonePopulating(const QStringList& watch_list) {
|
||||||
tree_view->setEnabled(true);
|
tree_view->setEnabled(true);
|
||||||
const int folder_count = tree_view->model()->rowCount();
|
const int folder_count = tree_view->model()->rowCount();
|
||||||
int children_total = 0;
|
int children_total = 0;
|
||||||
for (int i = 0; i < folder_count; ++i) {
|
for (int i = 1; i < folder_count; ++i) {
|
||||||
children_total += item_model->item(i, 0)->rowCount();
|
children_total += item_model->item(i, 0)->rowCount();
|
||||||
}
|
}
|
||||||
search_field->setFilterResult(children_total, children_total);
|
search_field->setFilterResult(children_total, children_total);
|
||||||
|
@ -478,6 +500,9 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
|
||||||
case GameListItemType::SysNandDir:
|
case GameListItemType::SysNandDir:
|
||||||
AddPermDirPopup(context_menu, selected);
|
AddPermDirPopup(context_menu, selected);
|
||||||
break;
|
break;
|
||||||
|
case GameListItemType::Favorites:
|
||||||
|
AddFavoritesPopup(context_menu);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -485,6 +510,8 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path) {
|
void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path) {
|
||||||
|
QAction* favorite = context_menu.addAction(tr("Favorite"));
|
||||||
|
context_menu.addSeparator();
|
||||||
QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
|
QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
|
||||||
QAction* open_mod_location = context_menu.addAction(tr("Open Mod Data Location"));
|
QAction* open_mod_location = context_menu.addAction(tr("Open Mod Data Location"));
|
||||||
QAction* open_transferable_shader_cache =
|
QAction* open_transferable_shader_cache =
|
||||||
|
@ -503,6 +530,9 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
|
||||||
context_menu.addSeparator();
|
context_menu.addSeparator();
|
||||||
QAction* properties = context_menu.addAction(tr("Properties"));
|
QAction* properties = context_menu.addAction(tr("Properties"));
|
||||||
|
|
||||||
|
favorite->setVisible(program_id != 0);
|
||||||
|
favorite->setCheckable(true);
|
||||||
|
favorite->setChecked(UISettings::values.favorited_ids.contains(program_id));
|
||||||
open_save_location->setVisible(program_id != 0);
|
open_save_location->setVisible(program_id != 0);
|
||||||
open_mod_location->setVisible(program_id != 0);
|
open_mod_location->setVisible(program_id != 0);
|
||||||
open_transferable_shader_cache->setVisible(program_id != 0);
|
open_transferable_shader_cache->setVisible(program_id != 0);
|
||||||
|
@ -513,6 +543,7 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
|
||||||
auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
|
auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
|
||||||
navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0);
|
navigate_to_gamedb_entry->setVisible(it != compatibility_list.end() && program_id != 0);
|
||||||
|
|
||||||
|
connect(favorite, &QAction::triggered, [this, program_id]() { ToggleFavorite(program_id); });
|
||||||
connect(open_save_location, &QAction::triggered, [this, program_id, path]() {
|
connect(open_save_location, &QAction::triggered, [this, program_id, path]() {
|
||||||
emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
|
emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
|
||||||
});
|
});
|
||||||
|
@ -576,7 +607,7 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) {
|
||||||
|
|
||||||
const int row = selected.row();
|
const int row = selected.row();
|
||||||
|
|
||||||
move_up->setEnabled(row > 0);
|
move_up->setEnabled(row > 1);
|
||||||
move_down->setEnabled(row < item_model->rowCount() - 2);
|
move_down->setEnabled(row < item_model->rowCount() - 2);
|
||||||
|
|
||||||
connect(move_up, &QAction::triggered, [this, selected, row, game_dir_index] {
|
connect(move_up, &QAction::triggered, [this, selected, row, game_dir_index] {
|
||||||
|
@ -614,6 +645,18 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameList::AddFavoritesPopup(QMenu& context_menu) {
|
||||||
|
QAction* clear_all = context_menu.addAction(tr("Clear"));
|
||||||
|
|
||||||
|
connect(clear_all, &QAction::triggered, [this] {
|
||||||
|
for (u64 id : UISettings::values.favorited_ids) {
|
||||||
|
RemoveFavorite(id);
|
||||||
|
}
|
||||||
|
UISettings::values.favorited_ids.clear();
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void GameList::LoadCompatibilityList() {
|
void GameList::LoadCompatibilityList() {
|
||||||
QFile compat_list{QStringLiteral(":compatibility_list/compatibility_list.json")};
|
QFile compat_list{QStringLiteral(":compatibility_list/compatibility_list.json")};
|
||||||
|
|
||||||
|
@ -728,6 +771,57 @@ void GameList::RefreshGameDirectory() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameList::ToggleFavorite(u64 program_id) {
|
||||||
|
if (!UISettings::values.favorited_ids.contains(program_id)) {
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(),
|
||||||
|
!search_field->SearchFieldEmpty());
|
||||||
|
UISettings::values.favorited_ids.append(program_id);
|
||||||
|
AddFavorite(program_id);
|
||||||
|
item_model->sort(tree_view->header()->sortIndicatorSection(),
|
||||||
|
tree_view->header()->sortIndicatorOrder());
|
||||||
|
} else {
|
||||||
|
UISettings::values.favorited_ids.removeOne(program_id);
|
||||||
|
RemoveFavorite(program_id);
|
||||||
|
if (UISettings::values.favorited_ids.size() == 0) {
|
||||||
|
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::AddFavorite(const u64& program_id) {
|
||||||
|
const auto favorites_row = item_model->item(0);
|
||||||
|
|
||||||
|
for (int i = 1; i < item_model->rowCount() - 1; i++) {
|
||||||
|
const auto folder = item_model->item(i);
|
||||||
|
for (int j = 0; j < folder->rowCount(); j++) {
|
||||||
|
if (folder->child(j)->data(GameListItemPath::ProgramIdRole) == program_id) {
|
||||||
|
QList<QStandardItem*> list;
|
||||||
|
for (int k = 0; k < item_model->columnCount(); k++) {
|
||||||
|
list.append(folder->child(j, k)->clone());
|
||||||
|
}
|
||||||
|
list[0]->setData(folder->child(j)->data(GameListItem::SortRole),
|
||||||
|
GameListItem::SortRole);
|
||||||
|
list[0]->setText(folder->child(j)->data(Qt::DisplayRole).toString());
|
||||||
|
|
||||||
|
favorites_row->appendRow(list);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::RemoveFavorite(const u64& program_id) {
|
||||||
|
const auto favorites_row = item_model->item(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < favorites_row->rowCount(); i++) {
|
||||||
|
const auto game = favorites_row->child(i);
|
||||||
|
if (game->data(GameListItemPath::ProgramIdRole) == program_id) {
|
||||||
|
favorites_row->removeRow(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GameListPlaceholder::GameListPlaceholder(GMainWindow* parent) : QWidget{parent} {
|
GameListPlaceholder::GameListPlaceholder(GMainWindow* parent) : QWidget{parent} {
|
||||||
connect(parent, &GMainWindow::UpdateThemedIcons, this,
|
connect(parent, &GMainWindow::UpdateThemedIcons, this,
|
||||||
&GameListPlaceholder::onUpdateThemedIcons);
|
&GameListPlaceholder::onUpdateThemedIcons);
|
||||||
|
|
|
@ -112,10 +112,15 @@ private:
|
||||||
|
|
||||||
void RefreshGameDirectory();
|
void RefreshGameDirectory();
|
||||||
|
|
||||||
|
void ToggleFavorite(u64 program_id);
|
||||||
|
void AddFavorite(const u64& program_id);
|
||||||
|
void RemoveFavorite(const u64& program_id);
|
||||||
|
|
||||||
void PopupContextMenu(const QPoint& menu_location);
|
void PopupContextMenu(const QPoint& menu_location);
|
||||||
void AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path);
|
void AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path);
|
||||||
void AddCustomDirPopup(QMenu& context_menu, QModelIndex selected);
|
void AddCustomDirPopup(QMenu& context_menu, QModelIndex selected);
|
||||||
void AddPermDirPopup(QMenu& context_menu, QModelIndex selected);
|
void AddPermDirPopup(QMenu& context_menu, QModelIndex selected);
|
||||||
|
void AddFavoritesPopup(QMenu& context_menu);
|
||||||
|
|
||||||
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
||||||
FileSys::ManualContentProvider* provider;
|
FileSys::ManualContentProvider* provider;
|
||||||
|
|
|
@ -29,7 +29,8 @@ enum class GameListItemType {
|
||||||
SdmcDir = QStandardItem::UserType + 3,
|
SdmcDir = QStandardItem::UserType + 3,
|
||||||
UserNandDir = QStandardItem::UserType + 4,
|
UserNandDir = QStandardItem::UserType + 4,
|
||||||
SysNandDir = QStandardItem::UserType + 5,
|
SysNandDir = QStandardItem::UserType + 5,
|
||||||
AddDir = QStandardItem::UserType + 6
|
AddDir = QStandardItem::UserType + 6,
|
||||||
|
Favorites = QStandardItem::UserType + 7
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(GameListItemType);
|
Q_DECLARE_METATYPE(GameListItemType);
|
||||||
|
@ -310,6 +311,28 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GameListFavorites : public GameListItem {
|
||||||
|
public:
|
||||||
|
explicit GameListFavorites() {
|
||||||
|
setData(type(), TypeRole);
|
||||||
|
|
||||||
|
const int icon_size = std::min(static_cast<int>(UISettings::values.icon_size), 64);
|
||||||
|
setData(QIcon::fromTheme(QStringLiteral("star"))
|
||||||
|
.pixmap(icon_size)
|
||||||
|
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
|
||||||
|
Qt::DecorationRole);
|
||||||
|
setData(QObject::tr("Favorites"), Qt::DisplayRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
int type() const override {
|
||||||
|
return static_cast<int>(GameListItemType::Favorites);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const QStandardItem& other) const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class GameList;
|
class GameList;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
|
@ -324,6 +347,7 @@ public:
|
||||||
explicit GameListSearchField(GameList* parent = nullptr);
|
explicit GameListSearchField(GameList* parent = nullptr);
|
||||||
|
|
||||||
void setFilterResult(int visible, int total);
|
void setFilterResult(int visible, int total);
|
||||||
|
bool SearchFieldEmpty();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
void setFocus();
|
void setFocus();
|
||||||
|
|
|
@ -74,6 +74,7 @@ struct Values {
|
||||||
QString game_dir_deprecated;
|
QString game_dir_deprecated;
|
||||||
bool game_dir_deprecated_deepscan;
|
bool game_dir_deprecated_deepscan;
|
||||||
QVector<UISettings::GameDir> game_dirs;
|
QVector<UISettings::GameDir> game_dirs;
|
||||||
|
QVector<u64> favorited_ids;
|
||||||
QStringList recent_files;
|
QStringList recent_files;
|
||||||
QString language;
|
QString language;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue