Compare commits

...

4 Commits

Author SHA1 Message Date
f674c8904d merge upstream 2025-05-31 00:00:37 -04:00
cffa8f79ff
Fix background of theme options QMenu 2025-05-27 21:08:24 -04:00
109e3dc25a
Allow setting theme color theme from the menu bar
This functions essentially the same as the language selector. The language selector now also checks the currently set option on launch, and both the language and theme selectors spawn a popup prompting the user to restart NUSGet after selecting a new value.
2025-05-27 14:44:48 -04:00
db6dc65791
Work in progress language selection support
Still need to add a popup telling you that NUSGet needs to be restarted after changing the language, and having it load the selected language in the selection menu so that it's checked on launch.
2025-05-26 21:50:04 -04:00
9 changed files with 465 additions and 80 deletions

105
NUSGet.py
View File

@ -22,15 +22,17 @@ import sys
import webbrowser import webbrowser
from importlib.metadata import version from importlib.metadata import version
from PySide6.QtGui import QIcon from PySide6.QtGui import QActionGroup, QIcon
from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QFileDialog, QListView from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QFileDialog, QListView
from PySide6.QtCore import QRunnable, Slot, QThreadPool, Signal, QObject, QLibraryInfo, QTranslator, QLocale from PySide6.QtCore import QRunnable, Slot, QThreadPool, Signal, QObject, QLibraryInfo
from qt.py.ui_AboutDialog import AboutNUSGet from qt.py.ui_AboutDialog import AboutNUSGet
from qt.py.ui_MainMenu import Ui_MainWindow from qt.py.ui_MainMenu import Ui_MainWindow
from modules.config import *
from modules.core import * from modules.core import *
from modules.theme import is_dark_theme from modules.language import *
from modules.theme import *
from modules.tree import NUSGetTreeModel, TIDFilterProxyModel from modules.tree import NUSGetTreeModel, TIDFilterProxyModel
from modules.download_batch import run_nus_download_batch from modules.download_batch import run_nus_download_batch
from modules.download_wii import run_nus_download_wii from modules.download_wii import run_nus_download_wii
@ -81,9 +83,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.download_btn.clicked.connect(self.download_btn_pressed) self.ui.download_btn.clicked.connect(self.download_btn_pressed)
self.ui.script_btn.clicked.connect(self.script_btn_pressed) self.ui.script_btn.clicked.connect(self.script_btn_pressed)
self.ui.custom_out_dir_btn.clicked.connect(self.choose_output_dir) self.ui.custom_out_dir_btn.clicked.connect(self.choose_output_dir)
# About and About Qt Buttons
self.ui.actionAbout.triggered.connect(self.about_nusget)
self.ui.actionAbout_Qt.triggered.connect(lambda: QMessageBox.aboutQt(self))
self.ui.pack_archive_checkbox.toggled.connect( self.ui.pack_archive_checkbox.toggled.connect(
lambda: connect_is_enabled_to_checkbox([self.ui.archive_file_entry], self.ui.pack_archive_checkbox)) lambda: connect_is_enabled_to_checkbox([self.ui.archive_file_entry], self.ui.pack_archive_checkbox))
self.ui.custom_out_dir_checkbox.toggled.connect( self.ui.custom_out_dir_checkbox.toggled.connect(
@ -126,19 +125,65 @@ class MainWindow(QMainWindow, Ui_MainWindow):
dropdown_delegate = ComboBoxItemDelegate() dropdown_delegate = ComboBoxItemDelegate()
self.ui.console_select_dropdown.setItemDelegate(dropdown_delegate) self.ui.console_select_dropdown.setItemDelegate(dropdown_delegate)
self.ui.console_select_dropdown.currentIndexChanged.connect(self.selected_console_changed) self.ui.console_select_dropdown.currentIndexChanged.connect(self.selected_console_changed)
# Fix the annoying background on the help menu items. # ------------
self.ui.menuHelp.setWindowFlags(self.ui.menuHelp.windowFlags() | Qt.FramelessWindowHint) # Options Menu
self.ui.menuHelp.setWindowFlags(self.ui.menuHelp.windowFlags() | Qt.NoDropShadowWindowHint) # ------------
self.ui.menuHelp.setAttribute(Qt.WA_TranslucentBackground) # Fix the annoying background on the option menu items and submenus.
fixup_qmenu_background(self.ui.menu_options)
fixup_qmenu_background(self.ui.menu_options_language)
fixup_qmenu_background(self.ui.menu_options_theme)
# Build a QActionGroup so that the language options function like radio buttons, because selecting multiple
# languages at once makes no sense.
language_group = QActionGroup(self)
language_group.setExclusive(True)
current_language = ""
try:
current_language = config_data["language"]
except KeyError:
pass
for action in self.ui.menu_options_language.actions():
language_group.addAction(action)
if current_language != "":
if LANGS[current_language] == action.text():
action.setChecked(True)
# There is no language set, so check the system language option.
if current_language == "":
self.ui.action_language_system.setChecked(True)
language_group.triggered.connect(lambda lang=action: self.change_language(lang.text()))
# Another QActionGroup used for the theme selector.
theme_group = QActionGroup(self)
theme_group.setExclusive(True)
for action in self.ui.menu_options_theme.actions():
theme_group.addAction(action)
self.ui.action_theme_system.triggered.connect(lambda: self.change_theme("system"))
self.ui.action_theme_light.triggered.connect(lambda: self.change_theme("light"))
self.ui.action_theme_dark.triggered.connect(lambda: self.change_theme("dark"))
try:
match config_data["theme"]:
case "light":
self.ui.action_theme_light.setChecked(True)
case "dark":
self.ui.action_theme_dark.setChecked(True)
case _:
self.ui.action_theme_system.setChecked(True)
except KeyError:
self.ui.action_theme_system.setChecked(True)
# ---------
# Help Menu
# ---------
# Same fix for help menu items.
fixup_qmenu_background(self.ui.menu_help)
self.ui.action_about.triggered.connect(self.about_nusget)
self.ui.action_about_qt.triggered.connect(lambda: QMessageBox.aboutQt(self))
# Save some light/dark theme values for later, including the appropriately colored info icon. # Save some light/dark theme values for later, including the appropriately colored info icon.
if is_dark_theme(): if is_dark_theme(config_data):
bg_color = "#2b2b2b" bg_color = "#2b2b2b"
icon = QIcon(os.path.join(os.path.dirname(__file__), "resources", "information_white.svg")) icon = QIcon(os.path.join(os.path.dirname(__file__), "resources", "information_white.svg"))
else: else:
bg_color = "#e3e3e3" bg_color = "#e3e3e3"
icon = QIcon(os.path.join(os.path.dirname(__file__), "resources", "information_black.svg")) icon = QIcon(os.path.join(os.path.dirname(__file__), "resources", "information_black.svg"))
self.ui.actionAbout.setIcon(icon) self.ui.action_about.setIcon(icon)
self.ui.actionAbout_Qt.setIcon(icon) self.ui.action_about_qt.setIcon(icon)
# Title tree loading code. Now powered by Models:tm: # Title tree loading code. Now powered by Models:tm:
wii_model = NUSGetTreeModel(wii_database, root_name="Wii Titles") wii_model = NUSGetTreeModel(wii_database, root_name="Wii Titles")
vwii_model = NUSGetTreeModel(vwii_database, root_name="vWii Titles") vwii_model = NUSGetTreeModel(vwii_database, root_name="vWii Titles")
@ -607,6 +652,26 @@ class MainWindow(QMainWindow, Ui_MainWindow):
about_box = AboutNUSGet([nusget_version, version("libWiiPy"), version("libTWLPy")]) about_box = AboutNUSGet([nusget_version, version("libWiiPy"), version("libTWLPy")])
about_box.exec() about_box.exec()
def change_language(self, new_lang):
set_language(config_data, new_lang)
msg_box = QMessageBox()
msg_box.setIcon(QMessageBox.Icon.Warning)
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
msg_box.setDefaultButton(QMessageBox.StandardButton.Ok)
msg_box.setWindowTitle(app.translate("MainWindow", "Restart Required"))
msg_box.setText(app.translate("MainWindow", "NUSGet must be restarted for the selected language to take effect."))
msg_box.exec()
def change_theme(self, new_theme):
set_theme(config_data, new_theme)
msg_box = QMessageBox()
msg_box.setIcon(QMessageBox.Icon.Warning)
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
msg_box.setDefaultButton(QMessageBox.StandardButton.Ok)
msg_box.setWindowTitle(app.translate("MainWindow", "Restart Required"))
msg_box.setText(app.translate("MainWindow", "NUSGet must be restarted for the selected theme to take effect."))
msg_box.exec()
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
@ -669,7 +734,7 @@ if __name__ == "__main__":
# NUSGet look nice and pretty. # NUSGet look nice and pretty.
app.setStyle("fusion") app.setStyle("fusion")
theme_sheet = "style_dark.qss" theme_sheet = "style_dark.qss"
if is_dark_theme(): if is_dark_theme(config_data):
theme_sheet = "style_dark.qss" theme_sheet = "style_dark.qss"
else: else:
theme_sheet = "style_light.qss" theme_sheet = "style_light.qss"
@ -683,16 +748,10 @@ if __name__ == "__main__":
translator = QTranslator(app) translator = QTranslator(app)
if translator.load(QLocale.system(), 'qtbase', '_', path): if translator.load(QLocale.system(), 'qtbase', '_', path):
app.installTranslator(translator) app.installTranslator(translator)
translator = QTranslator(app) # Get the translation path, and call get_language() to find the appropriate translations to load based on the
# settings and system language.
path = os.path.join(os.path.dirname(__file__), "resources", "translations") path = os.path.join(os.path.dirname(__file__), "resources", "translations")
# Unix-likes and Windows handle this differently, apparently. Unix-likes will try `nusget_xx_XX.qm` and then fall translator = get_language(QTranslator(app), config_data, path)
# back on just `nusget_xx.qm` if the region-specific translation for the language can't be found. On Windows, no
# such fallback exists, and so this code manually implements that fallback, since for languages like Spanish NUSGet
# doesn't use region-specific translations.
locale = QLocale.system()
if not translator.load(QLocale.system(), 'nusget', '_', path):
base_locale = QLocale(locale.language())
translator.load(base_locale, 'nusget', '_', path)
app.installTranslator(translator) app.installTranslator(translator)
window = MainWindow() window = MainWindow()

27
modules/config.py Normal file
View File

@ -0,0 +1,27 @@
# "modules/config.py", licensed under the MIT license
# Copyright 2024-2025 NinjaCheetah & Contributors
import os
import json
import pathlib
def get_config_file() -> pathlib.Path:
config_dir = pathlib.Path(os.path.join(
os.environ.get('APPDATA') or
os.environ.get('XDG_CONFIG_HOME') or
os.path.join(os.environ['HOME'], '.config'),
"NUSGet"
))
config_dir.mkdir(exist_ok=True)
return config_dir.joinpath("config.json")
def save_config(config_data: dict) -> None:
config_file = get_config_file()
print(f"writing data: {config_data}")
open(config_file, "w").write(json.dumps(config_data, indent=4))
def update_setting(config_data: dict, setting: str, value: any) -> None:
config_data[setting] = value
save_config(config_data)

View File

@ -1,15 +1,12 @@
# "modules/core.py", licensed under the MIT license # "modules/core.py", licensed under the MIT license
# Copyright 2024-2025 NinjaCheetah & Contributors # Copyright 2024-2025 NinjaCheetah & Contributors
import os
import json
import pathlib
import requests import requests
from dataclasses import dataclass from dataclasses import dataclass
from typing import List from typing import List
from PySide6.QtCore import Qt, QSize from PySide6.QtCore import Qt, QSize
from PySide6.QtWidgets import QStyledItemDelegate, QSizePolicy from PySide6.QtWidgets import QStyledItemDelegate
# This is required to make the dropdown look correct with the custom styling. A little fuzzy on the why, but it has to # This is required to make the dropdown look correct with the custom styling. A little fuzzy on the why, but it has to
@ -63,6 +60,13 @@ def connect_is_enabled_to_checkbox(items, chkbox):
item.setEnabled(False) item.setEnabled(False)
def fixup_qmenu_background(menu):
# These fixes are required to not have a square background poking out from behind the rounded corners of a QMenu.
menu.setWindowFlags(menu.windowFlags() | Qt.FramelessWindowHint)
menu.setWindowFlags(menu.windowFlags() | Qt.NoDropShadowWindowHint)
menu.setAttribute(Qt.WA_TranslucentBackground)
def check_nusget_updates(app, current_version: str, progress_callback=None) -> str | None: def check_nusget_updates(app, current_version: str, progress_callback=None) -> str | None:
# Simple function to make a request to the GitHub API and then check if the latest available version is newer. # Simple function to make a request to the GitHub API and then check if the latest available version is newer.
gh_api_request = requests.get(url="https://api.github.com/repos/NinjaCheetah/NUSGet/releases/latest", stream=True) gh_api_request = requests.get(url="https://api.github.com/repos/NinjaCheetah/NUSGet/releases/latest", stream=True)
@ -81,25 +85,3 @@ def check_nusget_updates(app, current_version: str, progress_callback=None) -> s
return new_version return new_version
progress_callback.emit(app.translate("MainWindow", "\n\nYou're running the latest release of NUSGet.")) progress_callback.emit(app.translate("MainWindow", "\n\nYou're running the latest release of NUSGet."))
return None return None
def get_config_file() -> pathlib.Path:
config_dir = pathlib.Path(os.path.join(
os.environ.get('APPDATA') or
os.environ.get('XDG_CONFIG_HOME') or
os.path.join(os.environ['HOME'], '.config'),
"NUSGet"
))
config_dir.mkdir(exist_ok=True)
return config_dir.joinpath("config.json")
def save_config(config_data: dict) -> None:
config_file = get_config_file()
print(f"writing data: {config_data}")
open(config_file, "w").write(json.dumps(config_data))
def update_setting(config_data: dict, setting: str, value: any) -> None:
config_data[setting] = value
save_config(config_data)

79
modules/language.py Normal file
View File

@ -0,0 +1,79 @@
# "modules/language.py", licensed under the MIT license
# Copyright 2024-2025 NinjaCheetah & Contributors
from modules.config import update_setting
from PySide6.QtCore import QLocale, QTranslator
LANGS = {
"en": "English",
"es": "Español",
"de": "Deutsch",
"fr": "Français",
"it": "Italiano",
"no": "Norsk",
"ro": "Românǎ",
"ko": "한국어",
}
def set_language(config_data: dict, lang: str) -> None:
# Match the selected language. These names will NOT be translated since they represent each language in that
# language, but the "System (Default)" option will, so that will match the default case.
match lang:
case "English":
print("setting language to English")
update_setting(config_data, "language", "en")
case "Español":
print("setting language to Spanish")
update_setting(config_data, "language", "es")
case "Deutsch":
print("setting language to German")
update_setting(config_data, "language", "de")
case "Français":
print("setting language to French")
update_setting(config_data, "language", "fr")
case "Italiano":
print("setting language to Italian")
update_setting(config_data, "language", "it")
case "Norsk":
print("setting language to Norwegian")
update_setting(config_data, "language", "no")
case "Română":
print("setting language to Romanian")
update_setting(config_data, "language", "ro")
case "한국어":
print("setting language to Korean")
update_setting(config_data, "language", "ko")
case _:
print("setting language to system (default)")
update_setting(config_data, "language", "")
def get_language(translator: QTranslator, config_data: dict, path: str) -> QTranslator:
try:
lang = config_data["language"]
except KeyError:
lang = ""
# A specific language was set in the app's settings.
if lang != "":
# If the target language is English, then return an empty translator because that's the default.
if lang == "en":
return translator
if translator.load(QLocale(lang), 'nusget', '_', path):
return translator
else:
# If we get here, then the saved language is invalid, so clear it and run again to use the system language.
update_setting(config_data, "language", "")
return get_language(translator, config_data, path)
else:
# Unix-likes and Windows handle this differently, apparently. Unix-likes will try `nusget_xx_XX.qm` and then
# fall back on just `nusget_xx.qm` if the region-specific translation for the language can't be found. On
# Windows, no such fallback exists, and so this code manually implements that fallback, since for languages like
# Spanish NUSGet doesn't use region-specific translations.
locale = QLocale.system()
if not translator.load(QLocale.system(), 'nusget', '_', path):
base_locale = QLocale(locale.language())
translator.load(base_locale, 'nusget', '_', path)
return translator

View File

@ -5,6 +5,9 @@ import os
import platform import platform
import subprocess import subprocess
from modules.config import update_setting
def is_dark_theme_windows(): def is_dark_theme_windows():
# This has to be here so that Python doesn't try to import it on non-Windows. # This has to be here so that Python doesn't try to import it on non-Windows.
import winreg import winreg
@ -17,6 +20,7 @@ def is_dark_theme_windows():
except Exception: except Exception:
return False return False
def is_dark_theme_macos(): def is_dark_theme_macos():
# macOS is weird. If the dark theme is on, then `defaults read -g AppleInterfaceStyle` returns "Dark". If the light # macOS is weird. If the dark theme is on, then `defaults read -g AppleInterfaceStyle` returns "Dark". If the light
# theme is on, then trying to read this key fails and returns an error instead. # theme is on, then trying to read this key fails and returns an error instead.
@ -29,6 +33,7 @@ def is_dark_theme_macos():
except Exception: except Exception:
return False return False
def is_dark_theme_linux(): def is_dark_theme_linux():
try: try:
import subprocess import subprocess
@ -43,7 +48,14 @@ def is_dark_theme_linux():
except Exception: except Exception:
return False return False
def is_dark_theme():
def is_dark_theme(config_data: dict):
# Theming priority order:
# 1. `THEME` environment variable
# 2. Theme saved in config.json
# 3. The system theme
# 4. Light, if all else fails (though personally I'd prefer dark)
#
# First, check for an environment variable overriding the theme, and use that if it exists. # First, check for an environment variable overriding the theme, and use that if it exists.
try: try:
if os.environ["THEME"].lower() == "light": if os.environ["THEME"].lower() == "light":
@ -54,7 +66,18 @@ def is_dark_theme():
print(f"Unknown theme specified: \"{os.environ['THEME']}\"") print(f"Unknown theme specified: \"{os.environ['THEME']}\"")
except KeyError: except KeyError:
pass pass
# If the theme wasn't overridden, then check the current system theme. # If the theme wasn't overridden, read the user's preference in config.json.
try:
match config_data["theme"]:
case "light":
return False
case "dark":
return True
case _:
pass
except KeyError:
pass
# If a theme wasn't set (or the theme is "system"), then check for the system theme.
system = platform.system() system = platform.system()
if system == "Windows": if system == "Windows":
return is_dark_theme_windows() return is_dark_theme_windows()
@ -62,3 +85,16 @@ def is_dark_theme():
return is_dark_theme_macos() return is_dark_theme_macos()
else: else:
return is_dark_theme_linux() return is_dark_theme_linux()
def set_theme(config_data: dict, theme: str) -> None:
match theme:
case "light":
print("setting theme to light")
update_setting(config_data, "theme", "light")
case "dark":
print("setting theme to dark")
update_setting(config_data, "theme", "dark")
case _:
print("setting theme to system (default)")
update_setting(config_data, "theme", "")

View File

@ -31,15 +31,52 @@ class Ui_MainWindow(object):
MainWindow.resize(1010, 675) MainWindow.resize(1010, 675)
MainWindow.setMinimumSize(QSize(1010, 675)) MainWindow.setMinimumSize(QSize(1010, 675))
MainWindow.setMaximumSize(QSize(1010, 675)) MainWindow.setMaximumSize(QSize(1010, 675))
self.actionAbout = QAction(MainWindow) self.action_about = QAction(MainWindow)
self.actionAbout.setObjectName(u"actionAbout") self.action_about.setObjectName(u"action_about")
icon = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.HelpAbout)) icon = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.HelpAbout))
self.actionAbout.setIcon(icon) self.action_about.setIcon(icon)
self.actionAbout.setMenuRole(QAction.MenuRole.ApplicationSpecificRole) self.action_about.setMenuRole(QAction.MenuRole.ApplicationSpecificRole)
self.actionAbout_Qt = QAction(MainWindow) self.action_about_qt = QAction(MainWindow)
self.actionAbout_Qt.setObjectName(u"actionAbout_Qt") self.action_about_qt.setObjectName(u"action_about_qt")
self.actionAbout_Qt.setIcon(icon) self.action_about_qt.setIcon(icon)
self.actionAbout_Qt.setMenuRole(QAction.MenuRole.ApplicationSpecificRole) self.action_about_qt.setMenuRole(QAction.MenuRole.ApplicationSpecificRole)
self.action_language_system = QAction(MainWindow)
self.action_language_system.setObjectName(u"action_language_system")
self.action_language_system.setCheckable(True)
self.action_language_system.setChecked(False)
self.action_language_english = QAction(MainWindow)
self.action_language_english.setObjectName(u"action_language_english")
self.action_language_english.setCheckable(True)
self.action_language_spanish = QAction(MainWindow)
self.action_language_spanish.setObjectName(u"action_language_spanish")
self.action_language_spanish.setCheckable(True)
self.action_language_german = QAction(MainWindow)
self.action_language_german.setObjectName(u"action_language_german")
self.action_language_german.setCheckable(True)
self.action_language_french = QAction(MainWindow)
self.action_language_french.setObjectName(u"action_language_french")
self.action_language_french.setCheckable(True)
self.action_language_italian = QAction(MainWindow)
self.action_language_italian.setObjectName(u"action_language_italian")
self.action_language_italian.setCheckable(True)
self.action_language_norwegian = QAction(MainWindow)
self.action_language_norwegian.setObjectName(u"action_language_norwegian")
self.action_language_norwegian.setCheckable(True)
self.action_language_romanian = QAction(MainWindow)
self.action_language_romanian.setObjectName(u"action_language_romanian")
self.action_language_romanian.setCheckable(True)
self.action_language_korean = QAction(MainWindow)
self.action_language_korean.setObjectName(u"action_language_korean")
self.action_language_korean.setCheckable(True)
self.action_theme_system = QAction(MainWindow)
self.action_theme_system.setObjectName(u"action_theme_system")
self.action_theme_system.setCheckable(True)
self.action_theme_light = QAction(MainWindow)
self.action_theme_light.setObjectName(u"action_theme_light")
self.action_theme_light.setCheckable(True)
self.action_theme_dark = QAction(MainWindow)
self.action_theme_dark.setObjectName(u"action_theme_dark")
self.action_theme_dark.setCheckable(True)
self.centralwidget = QWidget(MainWindow) self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget") self.centralwidget.setObjectName(u"centralwidget")
self.horizontalLayout_3 = QHBoxLayout(self.centralwidget) self.horizontalLayout_3 = QHBoxLayout(self.centralwidget)
@ -326,15 +363,36 @@ class Ui_MainWindow(object):
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow) self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar") self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 1010, 30)) self.menubar.setGeometry(QRect(0, 0, 1010, 21))
self.menuHelp = QMenu(self.menubar) self.menu_help = QMenu(self.menubar)
self.menuHelp.setObjectName(u"menuHelp") self.menu_help.setObjectName(u"menu_help")
self.menu_options = QMenu(self.menubar)
self.menu_options.setObjectName(u"menu_options")
self.menu_options_language = QMenu(self.menu_options)
self.menu_options_language.setObjectName(u"menu_options_language")
self.menu_options_theme = QMenu(self.menu_options)
self.menu_options_theme.setObjectName(u"menu_options_theme")
MainWindow.setMenuBar(self.menubar) MainWindow.setMenuBar(self.menubar)
self.menubar.addAction(self.menuHelp.menuAction()) self.menubar.addAction(self.menu_options.menuAction())
self.menuHelp.addAction(self.actionAbout) self.menubar.addAction(self.menu_help.menuAction())
self.menuHelp.addAction(self.actionAbout_Qt) self.menu_help.addAction(self.action_about)
self.menuHelp.addSeparator() self.menu_help.addAction(self.action_about_qt)
self.menu_help.addSeparator()
self.menu_options.addAction(self.menu_options_language.menuAction())
self.menu_options.addAction(self.menu_options_theme.menuAction())
self.menu_options_language.addAction(self.action_language_system)
self.menu_options_language.addAction(self.action_language_english)
self.menu_options_language.addAction(self.action_language_spanish)
self.menu_options_language.addAction(self.action_language_german)
self.menu_options_language.addAction(self.action_language_french)
self.menu_options_language.addAction(self.action_language_italian)
self.menu_options_language.addAction(self.action_language_norwegian)
self.menu_options_language.addAction(self.action_language_romanian)
self.menu_options_language.addAction(self.action_language_korean)
self.menu_options_theme.addAction(self.action_theme_system)
self.menu_options_theme.addAction(self.action_theme_light)
self.menu_options_theme.addAction(self.action_theme_dark)
self.retranslateUi(MainWindow) self.retranslateUi(MainWindow)
@ -347,8 +405,20 @@ class Ui_MainWindow(object):
def retranslateUi(self, MainWindow): def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.actionAbout.setText(QCoreApplication.translate("MainWindow", u"About NUSGet", None)) self.action_about.setText(QCoreApplication.translate("MainWindow", u"About NUSGet", None))
self.actionAbout_Qt.setText(QCoreApplication.translate("MainWindow", u"About Qt", None)) self.action_about_qt.setText(QCoreApplication.translate("MainWindow", u"About Qt", None))
self.action_language_system.setText(QCoreApplication.translate("MainWindow", u"System (Default)", None))
self.action_language_english.setText(QCoreApplication.translate("MainWindow", u"English", None))
self.action_language_spanish.setText(QCoreApplication.translate("MainWindow", u"Espa\u00f1ol", None))
self.action_language_german.setText(QCoreApplication.translate("MainWindow", u"Deutsch", None))
self.action_language_french.setText(QCoreApplication.translate("MainWindow", u"Fran\u00e7ais", None))
self.action_language_italian.setText(QCoreApplication.translate("MainWindow", u"Italiano", None))
self.action_language_norwegian.setText(QCoreApplication.translate("MainWindow", u"Norsk", None))
self.action_language_romanian.setText(QCoreApplication.translate("MainWindow", u"Rom\u00e2n\u0103", None))
self.action_language_korean.setText(QCoreApplication.translate("MainWindow", u"\ud55c\uad6d\uc5b4", None))
self.action_theme_system.setText(QCoreApplication.translate("MainWindow", u"System (Default)", None))
self.action_theme_light.setText(QCoreApplication.translate("MainWindow", u"Light", None))
self.action_theme_dark.setText(QCoreApplication.translate("MainWindow", u"Dark", None))
self.tree_filter_input.setPlaceholderText(QCoreApplication.translate("MainWindow", u"Search", None)) self.tree_filter_input.setPlaceholderText(QCoreApplication.translate("MainWindow", u"Search", None))
self.tree_filter_reset_btn.setText(QCoreApplication.translate("MainWindow", u"Clear", None)) self.tree_filter_reset_btn.setText(QCoreApplication.translate("MainWindow", u"Clear", None))
self.platform_tabs.setTabText(self.platform_tabs.indexOf(self.wii_tab), QCoreApplication.translate("MainWindow", u"Wii", None)) self.platform_tabs.setTabText(self.platform_tabs.indexOf(self.wii_tab), QCoreApplication.translate("MainWindow", u"Wii", None))
@ -375,8 +445,11 @@ class Ui_MainWindow(object):
"hr { height: 1px; border-width: 0; }\n" "hr { height: 1px; border-width: 0; }\n"
"li.unchecked::marker { content: \"\\2610\"; }\n" "li.unchecked::marker { content: \"\\2610\"; }\n"
"li.checked::marker { content: \"\\2612\"; }\n" "li.checked::marker { content: \"\\2612\"; }\n"
"</style></head><body style=\" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;\">\n" "</style></head><body style=\" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;\"><br /></p></body></html>", None)) "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;\"><br /></p></body></html>", None))
self.menuHelp.setTitle(QCoreApplication.translate("MainWindow", u"Help", None)) self.menu_help.setTitle(QCoreApplication.translate("MainWindow", u"Help", None))
self.menu_options.setTitle(QCoreApplication.translate("MainWindow", u"Options", None))
self.menu_options_language.setTitle(QCoreApplication.translate("MainWindow", u"Language", None))
self.menu_options_theme.setTitle(QCoreApplication.translate("MainWindow", u"Theme", None))
# retranslateUi # retranslateUi

View File

@ -435,7 +435,7 @@ p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; } hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: &quot;\2610&quot;; } li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; } li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
@ -469,20 +469,50 @@ li.checked::marker { content: &quot;\2612&quot;; }
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1010</width> <width>1010</width>
<height>30</height> <height>21</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuHelp"> <widget class="QMenu" name="menu_help">
<property name="title"> <property name="title">
<string>Help</string> <string>Help</string>
</property> </property>
<addaction name="actionAbout"/> <addaction name="action_about"/>
<addaction name="actionAbout_Qt"/> <addaction name="action_about_qt"/>
<addaction name="separator"/> <addaction name="separator"/>
</widget> </widget>
<addaction name="menuHelp"/> <widget class="QMenu" name="menu_options">
<property name="title">
<string>Options</string>
</property>
<widget class="QMenu" name="menu_options_language">
<property name="title">
<string>Language</string>
</property>
<addaction name="action_language_system"/>
<addaction name="action_language_english"/>
<addaction name="action_language_spanish"/>
<addaction name="action_language_german"/>
<addaction name="action_language_french"/>
<addaction name="action_language_italian"/>
<addaction name="action_language_norwegian"/>
<addaction name="action_language_romanian"/>
<addaction name="action_language_korean"/>
</widget> </widget>
<action name="actionAbout"> <widget class="QMenu" name="menu_options_theme">
<property name="title">
<string>Theme</string>
</property>
<addaction name="action_theme_system"/>
<addaction name="action_theme_light"/>
<addaction name="action_theme_dark"/>
</widget>
<addaction name="menu_options_language"/>
<addaction name="menu_options_theme"/>
</widget>
<addaction name="menu_options"/>
<addaction name="menu_help"/>
</widget>
<action name="action_about">
<property name="icon"> <property name="icon">
<iconset theme="QIcon::ThemeIcon::HelpAbout"/> <iconset theme="QIcon::ThemeIcon::HelpAbout"/>
</property> </property>
@ -493,7 +523,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<enum>QAction::MenuRole::ApplicationSpecificRole</enum> <enum>QAction::MenuRole::ApplicationSpecificRole</enum>
</property> </property>
</action> </action>
<action name="actionAbout_Qt"> <action name="action_about_qt">
<property name="icon"> <property name="icon">
<iconset theme="QIcon::ThemeIcon::HelpAbout"/> <iconset theme="QIcon::ThemeIcon::HelpAbout"/>
</property> </property>
@ -504,6 +534,105 @@ li.checked::marker { content: &quot;\2612&quot;; }
<enum>QAction::MenuRole::ApplicationSpecificRole</enum> <enum>QAction::MenuRole::ApplicationSpecificRole</enum>
</property> </property>
</action> </action>
<action name="action_language_system">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="text">
<string>System (Default)</string>
</property>
</action>
<action name="action_language_english">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>English</string>
</property>
</action>
<action name="action_language_spanish">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Español</string>
</property>
</action>
<action name="action_language_german">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Deutsch</string>
</property>
</action>
<action name="action_language_french">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Français</string>
</property>
</action>
<action name="action_language_italian">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Italiano</string>
</property>
</action>
<action name="action_language_norwegian">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Norsk</string>
</property>
</action>
<action name="action_language_romanian">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Română</string>
</property>
</action>
<action name="action_language_korean">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>한국어</string>
</property>
</action>
<action name="action_theme_system">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>System (Default)</string>
</property>
</action>
<action name="action_theme_light">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Light</string>
</property>
</action>
<action name="action_theme_dark">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Dark</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -61,7 +61,7 @@ QMenu {
} }
QMenu::item { QMenu::item {
padding: 6px 2px; padding: 6px 16px 6px 4px;
margin: 2px; margin: 2px;
border-radius: 4px; border-radius: 4px;
background-color: transparent; background-color: transparent;

View File

@ -62,7 +62,7 @@ QMenu {
} }
QMenu::item { QMenu::item {
padding: 6px 2px; padding: 6px 16px 6px 4px;
margin: 2px; margin: 2px;
border-radius: 4px; border-radius: 4px;
background-color: transparent; background-color: transparent;