frontend: Added icons for everything except titlebar
@@ -0,0 +1,19 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="icons/default">
|
||||||
|
<file alias="index.theme">icons/index.theme</file>
|
||||||
|
|
||||||
|
<file alias="24x24/app.png">icons/24x24/app.png</file>
|
||||||
|
|
||||||
|
<file alias="24x24/dlc.png">icons/24x24/dlc.png</file>
|
||||||
|
|
||||||
|
<file alias="24x24/save_data.png">icons/24x24/save_data.png</file>
|
||||||
|
|
||||||
|
<file alias="24x24/system_archive.png">icons/24x24/system_archive.png</file>
|
||||||
|
|
||||||
|
<file alias="24x24/system_data.png">icons/24x24/system_data.png</file>
|
||||||
|
|
||||||
|
<file alias="24x24/unknown.png">icons/24x24/unknown.png</file>
|
||||||
|
|
||||||
|
<file alias="24x24/update.png">icons/24x24/update.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
|
After Width: | Height: | Size: 179 B |
|
After Width: | Height: | Size: 210 B |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 97 B |
|
After Width: | Height: | Size: 193 B |
|
After Width: | Height: | Size: 289 B |
|
After Width: | Height: | Size: 232 B |
@@ -0,0 +1,7 @@
|
|||||||
|
[Icon Theme]
|
||||||
|
Name=default
|
||||||
|
Comment=default theme
|
||||||
|
Directories=24x24
|
||||||
|
|
||||||
|
[24x24]
|
||||||
|
Size=24
|
||||||
@@ -337,3 +337,8 @@ proprietary programs. If your program is a subroutine library, you may
|
|||||||
consider it more useful to permit linking proprietary applications with the
|
consider it more useful to permit linking proprietary applications with the
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License.
|
Public License instead of this License.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
The icons used in this project are from https://github.com/google/material-design-icons,
|
||||||
|
licensed under Apache License 2.0.
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ if (POLICY CMP0071)
|
|||||||
cmake_policy(SET CMP0071 NEW)
|
cmake_policy(SET CMP0071 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/themes/*)
|
||||||
|
|
||||||
add_executable(threeSD
|
add_executable(threeSD
|
||||||
import_dialog.cpp
|
import_dialog.cpp
|
||||||
import_dialog.h
|
import_dialog.h
|
||||||
@@ -15,6 +17,7 @@ add_executable(threeSD
|
|||||||
main.cpp
|
main.cpp
|
||||||
main.h
|
main.h
|
||||||
main.ui
|
main.ui
|
||||||
|
${THEMES}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(threeSD PRIVATE common core)
|
target_link_libraries(threeSD PRIVATE common core)
|
||||||
|
|||||||
@@ -31,15 +31,17 @@ QString ReadableByteSize(qulonglong size) {
|
|||||||
.arg(QObject::tr(units[digit_groups], "ImportDialog"));
|
.arg(QObject::tr(units[digit_groups], "ImportDialog"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::array<std::pair<Core::ContentType, const char*>, 7> ContentTypeMap{{
|
// content type, name, icon name
|
||||||
{Core::ContentType::Application, QT_TR_NOOP("Application")},
|
static constexpr std::array<std::tuple<Core::ContentType, const char*, const char*>, 7>
|
||||||
{Core::ContentType::Update, QT_TR_NOOP("Update")},
|
ContentTypeMap{{
|
||||||
{Core::ContentType::DLC, QT_TR_NOOP("DLC")},
|
{Core::ContentType::Application, QT_TR_NOOP("Application"), "app"},
|
||||||
{Core::ContentType::Savegame, QT_TR_NOOP("Save Data")},
|
{Core::ContentType::Update, QT_TR_NOOP("Update"), "update"},
|
||||||
{Core::ContentType::Extdata, QT_TR_NOOP("Extra Data")},
|
{Core::ContentType::DLC, QT_TR_NOOP("DLC"), "dlc"},
|
||||||
{Core::ContentType::SystemArchive, QT_TR_NOOP("System Archive")},
|
{Core::ContentType::Savegame, QT_TR_NOOP("Save Data"), "save_data"},
|
||||||
{Core::ContentType::Sysdata, QT_TR_NOOP("System Data")},
|
{Core::ContentType::Extdata, QT_TR_NOOP("Extra Data"), "save_data"},
|
||||||
}};
|
{Core::ContentType::SystemArchive, QT_TR_NOOP("System Archive"), "system_archive"},
|
||||||
|
{Core::ContentType::Sysdata, QT_TR_NOOP("System Data"), "system_data"},
|
||||||
|
}};
|
||||||
|
|
||||||
static const std::unordered_map<Core::EncryptionType, const char*> EncryptionTypeMap{{
|
static const std::unordered_map<Core::EncryptionType, const char*> EncryptionTypeMap{{
|
||||||
{Core::EncryptionType::None, QT_TR_NOOP("None")},
|
{Core::EncryptionType::None, QT_TR_NOOP("None")},
|
||||||
@@ -57,10 +59,22 @@ QString GetContentName(const Core::ContentSpecifier& specifier) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString GetContentTypeName(Core::ContentType type) {
|
QString GetContentTypeName(Core::ContentType type) {
|
||||||
return QObject::tr(ContentTypeMap.at(static_cast<std::size_t>(type)).second, "ImportDialog");
|
return QObject::tr(std::get<1>(ContentTypeMap.at(static_cast<std::size_t>(type))),
|
||||||
|
"ImportDialog");
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap GetContentIcon(const Core::ContentSpecifier& specifier) {
|
QPixmap GetContentTypeIcon(Core::ContentType type) {
|
||||||
|
return QIcon::fromTheme(
|
||||||
|
QString::fromUtf8(std::get<2>(ContentTypeMap.at(static_cast<std::size_t>(type)))))
|
||||||
|
.pixmap(24);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap GetContentIcon(const Core::ContentSpecifier& specifier, bool use_category_icon = false) {
|
||||||
|
if (specifier.icon.empty()) {
|
||||||
|
// Return a category icon, or a null icon
|
||||||
|
return use_category_icon ? GetContentTypeIcon(specifier.type)
|
||||||
|
: QIcon::fromTheme(QStringLiteral("unknown")).pixmap(24);
|
||||||
|
}
|
||||||
return QPixmap::fromImage(QImage(reinterpret_cast<const uchar*>(specifier.icon.data()), 24, 24,
|
return QPixmap::fromImage(QImage(reinterpret_cast<const uchar*>(specifier.icon.data()), 24, 24,
|
||||||
QImage::Format::Format_RGB16));
|
QImage::Format::Format_RGB16));
|
||||||
}
|
}
|
||||||
@@ -179,8 +193,10 @@ void ImportDialog::InsertSecondLevelItem(std::size_t row, const Core::ContentSpe
|
|||||||
// HACK: The checkbox is used to record ID. Is there a better way?
|
// HACK: The checkbox is used to record ID. Is there a better way?
|
||||||
checkBox->setProperty("id", id);
|
checkBox->setProperty("id", id);
|
||||||
|
|
||||||
|
const bool use_title_view = ui->title_view_button->isChecked();
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
if (ui->title_view_button->isChecked()) {
|
if (use_title_view) {
|
||||||
if (row == 0) {
|
if (row == 0) {
|
||||||
name = QStringLiteral("%1 (%2)")
|
name = QStringLiteral("%1 (%2)")
|
||||||
.arg(GetContentName(content))
|
.arg(GetContentName(content))
|
||||||
@@ -214,11 +230,17 @@ void ImportDialog::InsertSecondLevelItem(std::size_t row, const Core::ContentSpe
|
|||||||
{QString{}, name, ReadableByteSize(content.maximum_size), encryption,
|
{QString{}, name, ReadableByteSize(content.maximum_size), encryption,
|
||||||
content.already_exists ? QStringLiteral("Yes") : QStringLiteral("No")}};
|
content.already_exists ? QStringLiteral("Yes") : QStringLiteral("No")}};
|
||||||
|
|
||||||
if (!ui->title_view_button->isChecked()) {
|
QPixmap icon;
|
||||||
// Display icon when present
|
if (replace_icon.isNull()) {
|
||||||
item->setData(1, Qt::DecorationRole,
|
// When not in title view, only System Data and System Archive groups use category icons.
|
||||||
replace_icon.isNull() ? GetContentIcon(content) : replace_icon);
|
const bool use_category_icon = content.type == Core::ContentType::Sysdata ||
|
||||||
|
content.type == Core::ContentType::SystemArchive;
|
||||||
|
icon = use_title_view ? GetContentTypeIcon(content.type)
|
||||||
|
: GetContentIcon(content, use_category_icon);
|
||||||
|
} else {
|
||||||
|
icon = replace_icon;
|
||||||
}
|
}
|
||||||
|
item->setData(1, Qt::DecorationRole, icon);
|
||||||
|
|
||||||
ui->main->invisibleRootItem()->child(row)->addChild(item);
|
ui->main->invisibleRootItem()->child(row)->addChild(item);
|
||||||
ui->main->setItemWidget(item, 0, checkBox);
|
ui->main->setItemWidget(item, 0, checkBox);
|
||||||
@@ -276,6 +298,10 @@ void ImportDialog::RepopulateContent() {
|
|||||||
title_name_map.insert_or_assign(1, tr("System Archive"));
|
title_name_map.insert_or_assign(1, tr("System Archive"));
|
||||||
title_name_map.insert_or_assign(2, tr("System Data"));
|
title_name_map.insert_or_assign(2, tr("System Data"));
|
||||||
|
|
||||||
|
title_icon_map.insert_or_assign(0, QIcon::fromTheme(QStringLiteral("unknown")).pixmap(24));
|
||||||
|
title_icon_map.insert_or_assign(1, GetContentTypeIcon(Core::ContentType::SystemArchive));
|
||||||
|
title_icon_map.insert_or_assign(2, GetContentTypeIcon(Core::ContentType::Sysdata));
|
||||||
|
|
||||||
std::unordered_map<u64, u64> title_row_map;
|
std::unordered_map<u64, u64> title_row_map;
|
||||||
for (const auto& [id, name] : title_name_map) {
|
for (const auto& [id, name] : title_name_map) {
|
||||||
InsertTopLevelItem(name, title_icon_map.count(id) ? title_icon_map.at(id) : QPixmap{});
|
InsertTopLevelItem(name, title_icon_map.count(id) ? title_icon_map.at(id) : QPixmap{});
|
||||||
@@ -316,8 +342,8 @@ void ImportDialog::RepopulateContent() {
|
|||||||
InsertSecondLevelItem(row, content, i);
|
InsertSecondLevelItem(row, content, i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const auto& [type, name] : ContentTypeMap) {
|
for (const auto& [type, name, _] : ContentTypeMap) {
|
||||||
InsertTopLevelItem(tr(name));
|
InsertTopLevelItem(tr(name), GetContentTypeIcon(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < contents.size(); ++i) {
|
for (std::size_t i = 0; i < contents.size(); ++i) {
|
||||||
|
|||||||
@@ -219,6 +219,9 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons/default")));
|
||||||
|
QIcon::setThemeName(QStringLiteral(":/icons/default"));
|
||||||
|
|
||||||
MainDialog main_dialog;
|
MainDialog main_dialog;
|
||||||
main_dialog.show();
|
main_dialog.show();
|
||||||
|
|
||||||
|
|||||||