Compare commits

...

12 Commits

Author SHA1 Message Date
9cb11f2f68
Style update for After Dark theme 2025-05-25 01:12:46 -04:00
dee71e03d0
Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	modules/download_wii.py
#	qt/py/ui_AboutDialog.py
2025-05-25 01:09:32 -04:00
e8d6a19d03
Disable debug line that was setting progress bar to busy on launch 2025-05-25 01:02:57 -04:00
811e2ef01f
Added progress bar to show download progress 2025-05-25 00:58:55 -04:00
4a08bd47cd
Allow overriding the color scheme with the THEME environment variable 2025-05-21 12:53:32 -04:00
f29964be53
Another quick style fix for light theme on Windows 2025-05-20 23:16:01 -04:00
1af938decd
Improved light theme based on testing on Linux/Windows 2025-05-20 23:07:24 -04:00
a4679be043
Added an experimental light theme and automatic system theme detection 2025-05-20 22:26:11 -04:00
7caa7775ff
Force correct coloring so that text is always legible on all system themes
Since NUSGet only supports a dark theme right now, but your system may use a light theme, the OS may recolor text on screen to be black on black, which is obviously bad for readability. All text will now be white, so you can always read it.
And hey, maybe there will be a proper light theme soon!
2025-05-20 21:11:29 -04:00
07579d7361
Improve illegal character removal
Now removes the NTFS-forbidden characters on all platforms, as some may still cause issues depending on your OS and FS. These characters are also now removed during the actual download process, so they'll still appear in the WAD name box, but will be stripped out before the file is created.
2025-05-20 13:54:27 -04:00
9b4addc8a5
Remove illegal characters from WAD names on Windows 2025-05-20 09:08:07 -04:00
LNLenost
a1bfcd5f8b
Update Italian translations (#31)
* Delete resources/translations/nusget_it.ts

* new translations
2025-05-20 08:52:37 -04:00
26 changed files with 1023 additions and 205 deletions

View File

@ -30,12 +30,13 @@ from qt.py.ui_AboutDialog import AboutNUSGet
from qt.py.ui_MainMenu import Ui_MainWindow
from modules.core import *
from modules.theme import is_dark_theme
from modules.tree import NUSGetTreeModel, TIDFilterProxyModel
from modules.download_batch import run_nus_download_batch
from modules.download_wii import run_nus_download_wii
from modules.download_dsi import run_nus_download_dsi
nusget_version = "1.4.0"
nusget_version = "1.4.1"
regions = {"World": ["41"], "USA/NTSC": ["45"], "Europe/PAL": ["50"], "Japan": ["4A"], "Korea": ["4B"], "China": ["43"],
"Australia/NZ": ["55"]}
@ -44,7 +45,7 @@ regions = {"World": ["41"], "USA/NTSC": ["45"], "Europe/PAL": ["50"], "Japan": [
# Signals needed for the worker used for threading the downloads.
class WorkerSignals(QObject):
result = Signal(object)
progress = Signal(str)
progress = Signal(int, int, str)
# Worker class used to thread the downloads.
@ -129,8 +130,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.menuHelp.setWindowFlags(self.ui.menuHelp.windowFlags() | Qt.FramelessWindowHint)
self.ui.menuHelp.setWindowFlags(self.ui.menuHelp.windowFlags() | Qt.NoDropShadowWindowHint)
self.ui.menuHelp.setAttribute(Qt.WA_TranslucentBackground)
# Load the custom information icon.
icon = QIcon(os.path.join(os.path.dirname(__file__), "resources", "information.svg"))
# Save some light/dark theme values for later, including the appropriately colored info icon.
if is_dark_theme():
bg_color = "#2b2b2b"
icon = QIcon(os.path.join(os.path.dirname(__file__), "resources", "information_white.svg"))
else:
bg_color = "#e3e3e3"
icon = QIcon(os.path.join(os.path.dirname(__file__), "resources", "information_black.svg"))
self.ui.actionAbout.setIcon(icon)
self.ui.actionAbout_Qt.setIcon(icon)
# Title tree loading code. Now powered by Models:tm:
@ -157,7 +163,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.trees[tree].setStyleSheet(self.trees[tree].styleSheet() + f"""
QTreeView QScrollBar::sub-line:vertical {{
border: 0;
background: #2b2b2b;
background: {bg_color};
height: {self.trees[tree].header().sizeHint().height()}px;
}}""")
# Prevent resizing.
@ -224,6 +230,18 @@ class MainWindow(QMainWindow, Ui_MainWindow):
return
self.ui.patch_ios_checkbox.setEnabled(False)
def download_progress_update(self, done, total, log_text):
if done == 0 and total == 0:
self.ui.progress_bar.setRange(0, 0)
elif done == -1 and total == -1:
pass
else:
self.ui.progress_bar.setRange(0, total)
self.ui.progress_bar.setValue(done)
# Pass the text on to the log text updater, if it was provided.
if log_text:
self.update_log_text(log_text)
def update_log_text(self, new_text):
# This method primarily exists to be the handler for the progress signal emitted by the worker thread.
self.log_text += new_text + "\n"
@ -379,7 +397,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.pack_vwii_mode_checkbox.isChecked(), self.ui.patch_ios_checkbox.isChecked(),
self.ui.archive_file_entry.text())
worker.signals.result.connect(self.check_download_result)
worker.signals.progress.connect(self.update_log_text)
worker.signals.progress.connect(self.download_progress_update)
self.threadpool.start(worker)
def check_download_result(self, result):
@ -546,7 +564,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.use_wiiu_nus_checkbox.isChecked(), self.ui.use_local_checkbox.isChecked(),
self.ui.pack_vwii_mode_checkbox.isChecked(), self.ui.patch_ios_checkbox.isChecked())
worker.signals.result.connect(self.check_batch_result)
worker.signals.progress.connect(self.update_log_text)
worker.signals.progress.connect(self.download_progress_update)
self.threadpool.start(worker)
def choose_output_dir(self):
@ -650,7 +668,12 @@ if __name__ == "__main__":
# Load Fusion because that's objectively the best base theme, and then load the fancy stylesheet on top to make
# NUSGet look nice and pretty.
app.setStyle("fusion")
stylesheet = open(os.path.join(os.path.dirname(__file__), "resources", "style.qss")).read()
theme_sheet = "style_dark.qss"
if is_dark_theme():
theme_sheet = "style_dark.qss"
else:
theme_sheet = "style_light.qss"
stylesheet = open(os.path.join(os.path.dirname(__file__), "resources", theme_sheet)).read()
image_path_prefix = pathlib.Path(os.path.join(os.path.dirname(__file__), "resources")).resolve().as_posix()
stylesheet = stylesheet.replace("{IMAGE_PREFIX}", image_path_prefix)
app.setStyleSheet(stylesheet)

View File

@ -54,6 +54,7 @@ def connect_label_to_checkbox(label, checkbox):
checkbox.toggle()
label.mousePressEvent = toggle_checkbox
def connect_is_enabled_to_checkbox(items, chkbox):
for item in items:
if chkbox.isChecked():
@ -61,6 +62,7 @@ def connect_is_enabled_to_checkbox(items, chkbox):
else:
item.setEnabled(False)
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.
gh_api_request = requests.get(url="https://api.github.com/repos/NinjaCheetah/NUSGet/releases/latest", stream=True)
@ -80,6 +82,7 @@ def check_nusget_updates(app, current_version: str, progress_callback=None) -> s
progress_callback.emit(app.translate("MainWindow", "\n\nYou're running the latest release of NUSGet."))
return None
def get_config_file() -> pathlib.Path:
config_dir = pathlib.Path(os.path.join(
os.environ.get('APPDATA') or
@ -90,11 +93,13 @@ def get_config_file() -> pathlib.Path:
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)

View File

@ -53,5 +53,5 @@ def run_nus_download_batch(out_folder: pathlib.Path, titles: List[BatchTitleData
# failed title.
result = 1
failed_titles.append(title.tid)
progress_callback.emit(f"Batch download finished.")
progress_callback.emit(0, 1, f"Batch download finished.")
return BatchResults(result, warning_titles, failed_titles)

View File

@ -29,10 +29,10 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_
title_dir.mkdir(exist_ok=True)
# Announce the title being downloaded, and the version if applicable.
if title_version is not None:
progress_callback.emit(f"Downloading title {tid} v{title_version}, please wait...")
progress_callback.emit(0, 0, f"Downloading title {tid} v{title_version}, please wait...")
else:
progress_callback.emit(f"Downloading title {tid} vLatest, please wait...")
progress_callback.emit(" - Downloading and parsing TMD...")
progress_callback.emit(0, 0, f"Downloading title {tid} vLatest, please wait...")
progress_callback.emit(-1, -1, " - Downloading and parsing TMD...")
# Download a specific TMD version if a version was specified, otherwise just download the latest TMD.
try:
if title_version is not None:
@ -50,17 +50,17 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_
version_dir.joinpath(f"tmd.{title_version}").write_bytes(title.tmd.dump())
# Use a local ticket, if one exists and "use local files" is enabled.
if use_local_chkbox and version_dir.joinpath("tik").exists():
progress_callback.emit(" - Parsing local copy of Ticket...")
progress_callback.emit(-1, -1, " - Parsing local copy of Ticket...")
title.load_ticket(version_dir.joinpath("tik").read_bytes())
else:
progress_callback.emit(" - Downloading and parsing Ticket...")
progress_callback.emit(-1, -1, " - Downloading and parsing Ticket...")
try:
title.load_ticket(libTWLPy.download_ticket(tid))
version_dir.joinpath("tik").write_bytes(title.ticket.dump())
except ValueError:
# If libTWLPy returns an error, then no ticket is available. Log this, and disable options requiring a
# ticket so that they aren't attempted later.
progress_callback.emit(" - No Ticket is available!")
progress_callback.emit(-1, -1, " - No Ticket is available!")
pack_tad_enabled = False
decrypt_contents_enabled = False
# Load the content record from the TMD, and download the content it lists. DSi titles only have one content.
@ -68,13 +68,13 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_
content_file_name = f"{title.tmd.content_record.content_id:08X}"
# Check for a local copy of the current content if "use local files" is enabled, and use it.
if use_local_chkbox and version_dir.joinpath(content_file_name).exists():
progress_callback.emit(" - Using local copy of content")
progress_callback.emit(-1, -1, " - Using local copy of content")
content = version_dir.joinpath(content_file_name).read_bytes()
else:
progress_callback.emit(f" - Downloading content (Content ID: {title.tmd.content_record.content_id}, Size: "
progress_callback.emit(-1, -1, f" - Downloading content (Content ID: {title.tmd.content_record.content_id}, Size: "
f"{title.tmd.content_record.content_size} bytes)...")
content = libTWLPy.download_content(tid, title.tmd.content_record.content_id)
progress_callback.emit(" - Done!")
progress_callback.emit(-1, -1, " - Done!")
# If keep encrypted contents is on, write out the content after its downloaded.
if keep_enc_chkbox is True:
version_dir.joinpath(content_file_name).write_bytes(content)
@ -82,7 +82,7 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_
# If decrypt local contents is still true, decrypt the content and write out the decrypted file.
if decrypt_contents_enabled is True:
try:
progress_callback.emit(f" - Decrypting content (Content ID: {title.tmd.content_record.content_id})...")
progress_callback.emit(-1, -1, f" - Decrypting content (Content ID: {title.tmd.content_record.content_id})...")
dec_content = title.get_content()
content_file_name = f"{title.tmd.content_record.content_id:08X}.app"
version_dir.joinpath(content_file_name).write_bytes(dec_content)
@ -93,10 +93,10 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_
# If pack TAD is still true, pack the TMD, ticket, and content into a TAD.
if pack_tad_enabled is True:
# Get the TAD certificate chain, courtesy of libTWLPy.
progress_callback.emit(" - Building certificate...")
progress_callback.emit(-1, -1, " - Building certificate...")
title.tad.set_cert_data(libTWLPy.download_cert())
# Use a typed TAD name if there is one, and auto generate one based on the TID and version if there isn't.
progress_callback.emit("Packing TAD...")
progress_callback.emit(-1, -1, "Packing TAD...")
if tad_file_name != "" and tad_file_name is not None:
# Batch downloads may insert -vLatest, so if it did we can fill in the real number now.
tad_file_name = tad_file_name.replace("-vLatest", f"-v{title_version}")
@ -104,9 +104,13 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_
tad_file_name += ".tad"
else:
tad_file_name = f"{tid}-v{title_version}.tad"
# Certain special characters are prone to breaking things, so strip them from the file name before actually
# opening the file for writing. On some platforms (like macOS), invalid characters get replaced automatically,
# but on Windows the file will just fail to be written out at all.
tad_file_name = tad_file_name.translate({ord(c): None for c in '/\\:*"?<>|'})
# Have libTWLPy dump the TAD, and write that data out.
version_dir.joinpath(tad_file_name).write_bytes(title.dump_tad())
progress_callback.emit("Download complete!")
progress_callback.emit(0, 1, "Download complete!")
# This is where the variables come in. If the state of these variables doesn't match the user's choice by this
# point, it means that they enabled decryption or TAD packing for a title that doesn't have a ticket. Return
# code 1 so that a warning popup is shown informing them of this.

View File

@ -11,6 +11,8 @@ from libWiiPy.title.ticket import _TitleLimit
def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_wad_chkbox: bool, keep_enc_chkbox: bool,
decrypt_contents_chkbox: bool, wiiu_nus_chkbox: bool, use_local_chkbox: bool,
repack_vwii_chkbox: bool, patch_ios: bool, wad_file_name: str, progress_callback=None):
def progress_update(done, total):
progress_callback.emit(done, total, None)
# Actual NUS download function that runs in a separate thread.
# Immediately knock out any invalidly formatted Title IDs.
if len(tid) != 16:
@ -33,16 +35,16 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_
title_dir.mkdir(exist_ok=True)
# Announce the title being downloaded, and the version if applicable.
if title_version is not None:
progress_callback.emit(f"Downloading title {tid} v{title_version}, please wait...")
progress_callback.emit(0, 0, f"Downloading title {tid} v{title_version}, please wait...")
else:
progress_callback.emit(f"Downloading title {tid} vLatest, please wait...")
progress_callback.emit(" - Downloading and parsing TMD...")
progress_callback.emit(-1, -1, f"Downloading title {tid} vLatest, please wait...")
progress_callback.emit(-1, -1, " - Downloading and parsing TMD...")
# Download a specific TMD version if a version was specified, otherwise just download the latest TMD.
try:
if title_version is not None:
title.load_tmd(libWiiPy.title.download_tmd(tid, title_version, wiiu_endpoint=wiiu_nus_enabled))
title.load_tmd(libWiiPy.title.download_tmd(tid, title_version, wiiu_endpoint=wiiu_nus_enabled, progress=progress_update))
else:
title.load_tmd(libWiiPy.title.download_tmd(tid, wiiu_endpoint=wiiu_nus_enabled))
title.load_tmd(libWiiPy.title.download_tmd(tid, wiiu_endpoint=wiiu_nus_enabled, progress=progress_update))
title_version = title.tmd.title_version
# If libWiiPy returns an error, that means that either the TID or version doesn't exist, so return code -2.
except ValueError:
@ -55,17 +57,17 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_
# Use a local ticket, if one exists and "use local files" is enabled.
forge_ticket = False
if use_local_chkbox and version_dir.joinpath("tik").exists():
progress_callback.emit(" - Parsing local copy of Ticket...")
progress_callback.emit(-1, -1, " - Parsing local copy of Ticket...")
title.load_ticket(version_dir.joinpath("tik").read_bytes())
else:
progress_callback.emit(" - Downloading and parsing Ticket...")
progress_callback.emit(-1, -1, " - Downloading and parsing Ticket...")
try:
title.load_ticket(libWiiPy.title.download_ticket(tid, wiiu_endpoint=wiiu_nus_enabled))
title.load_ticket(libWiiPy.title.download_ticket(tid, wiiu_endpoint=wiiu_nus_enabled, progress=progress_update))
version_dir.joinpath("tik").write_bytes(title.ticket.dump())
except ValueError:
# If libWiiPy returns an error, then no ticket is available. Try to forge a ticket after we download the
# content.
progress_callback.emit(" - No Ticket is available! Will try forging a Ticket.")
progress_callback.emit(0, 0, " - No Ticket is available! Will try forging a Ticket.")
forge_ticket = True
# Load the content records from the TMD, and begin iterating over the records.
title.load_content_records()
@ -75,22 +77,22 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_
content_file_name = f"{title.tmd.content_records[content].content_id:08X}"
# Check for a local copy of the current content if "use local files" is enabled, and use it.
if use_local_chkbox is True and version_dir.joinpath(content_file_name).exists():
progress_callback.emit(f" - Using local copy of content {content + 1} of {len(title.tmd.content_records)}")
progress_callback.emit(-1, -1, f" - Using local copy of content {content + 1} of {len(title.tmd.content_records)}")
content_list.append(version_dir.joinpath(content_file_name).read_bytes())
else:
progress_callback.emit(f" - Downloading content {content + 1} of {len(title.tmd.content_records)} "
progress_callback.emit(0, 0, f" - Downloading content {content + 1} of {len(title.tmd.content_records)} "
f"(Content ID: {title.tmd.content_records[content].content_id}, Size: "
f"{title.tmd.content_records[content].content_size} bytes)...")
content_list.append(libWiiPy.title.download_content(tid, title.tmd.content_records[content].content_id,
wiiu_endpoint=wiiu_nus_enabled))
progress_callback.emit(" - Done!")
wiiu_endpoint=wiiu_nus_enabled, progress=progress_update))
progress_callback.emit(-1, -1, " - Done!")
# If keep encrypted contents is on, write out each content after its downloaded.
if keep_enc_chkbox is True:
version_dir.joinpath(content_file_name).write_bytes(content_list[content])
title.content.content_list = content_list
# Try to forge a Ticket, if a common one wasn't available.
if forge_ticket is True:
progress_callback.emit(" - Attempting to forge Ticket...")
progress_callback.emit(0, 0, " - Attempting to forge Ticket...")
try:
title_key = find_tkey(tid, title.content.content_list[0], title.tmd.content_records[0])
title_key_enc = libWiiPy.title.encrypt_title_key(title_key, 0, tid)
@ -116,16 +118,16 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_
ticket.fakesign()
title.ticket = ticket
version_dir.joinpath("tik").write_bytes(title.ticket.dump())
progress_callback.emit(" - Successfully forged Ticket!")
progress_callback.emit(-1, -1, " - Successfully forged Ticket!")
except Exception:
progress_callback.emit(" - Ticket could not be forged!")
progress_callback.emit(-1, -1, " - Ticket could not be forged!")
pack_wad_enabled = False
decrypt_contents_enabled = False
# If decrypt local contents is still true, decrypt each content and write out the decrypted file.
if decrypt_contents_enabled is True:
try:
for content in range(len(title.tmd.content_records)):
progress_callback.emit(f" - Decrypting content {content + 1} of {len(title.tmd.content_records)} "
progress_callback.emit(-1, -1, f" - Decrypting content {content + 1} of {len(title.tmd.content_records)} "
f"(Content ID: {title.tmd.content_records[content].content_id})...")
dec_content = title.get_content_by_index(content)
content_file_name = f"{title.tmd.content_records[content].content_id:08X}.app"
@ -140,15 +142,15 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_
# re-encrypted with the common key instead of the vWii key, so that the title can be installed from within
# vWii mode. (vWii mode does not have access to the vWii key, only Wii U mode has that.)
if repack_vwii_chkbox is True and (tid[3] == "7" or tid[7] == "7"):
progress_callback.emit(" - Re-encrypting Title Key with the common key...")
progress_callback.emit(-1, -1, " - Re-encrypting Title Key with the common key...")
title_key_common = libWiiPy.title.encrypt_title_key(title.ticket.get_title_key(), 0, title.tmd.title_id)
title.ticket.common_key_index = 0
title.ticket.title_key_enc = title_key_common
# Get the WAD certificate chain, courtesy of libWiiPy.
progress_callback.emit(" - Building certificate...")
progress_callback.emit(-1, -1, " - Building certificate...")
title.load_cert_chain(libWiiPy.title.download_cert_chain(wiiu_endpoint=wiiu_nus_enabled))
# Use a typed WAD name if there is one, and auto generate one based on the TID and version if there isn't.
progress_callback.emit(" - Packing WAD...")
progress_callback.emit(-1, -1, " - Packing WAD...")
if wad_file_name != "" and wad_file_name is not None:
# Batch downloads may insert -vLatest, so if it did we can fill in the real number now.
wad_file_name = wad_file_name.replace("-vLatest", f"-v{title_version}")
@ -158,20 +160,24 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_
wad_file_name = f"{tid}-v{title_version}.wad"
# If enabled (after we make sure it's an IOS), apply all main IOS patches.
if patch_ios and (tid[:8] == "00000001" and int(tid[-2:], 16) > 2):
progress_callback.emit(" - Patching IOS...")
progress_callback.emit(-1, -1, " - Patching IOS...")
ios_patcher = libWiiPy.title.IOSPatcher()
ios_patcher.load(title)
patch_count = ios_patcher.patch_all()
if patch_count > 0:
progress_callback.emit(f" - Applied {patch_count} patches!")
progress_callback.emit(-1, -1, f" - Applied {patch_count} patches!")
else:
progress_callback.emit(" - No patches could be applied! Is this a stub IOS?")
progress_callback.emit(-1, -1, " - No patches could be applied! Is this a stub IOS?")
title = ios_patcher.dump()
# Append "-PATCHED" to the end of the WAD file name to make it clear that it was modified.
wad_file_name = wad_file_name[:-4] + "-PATCHED" + wad_file_name[-4:]
# Certain special characters are prone to breaking things, so strip them from the file name before actually
# opening the file for writing. On some platforms (like macOS), invalid characters get replaced automatically,
# but on Windows the file will just fail to be written out at all.
wad_file_name = wad_file_name.translate({ord(c): None for c in '/\\:*"?<>|'})
# Have libWiiPy dump the WAD, and write that data out.
version_dir.joinpath(wad_file_name).write_bytes(title.dump_wad())
progress_callback.emit("Download complete!")
progress_callback.emit(0, 1, "Download complete!")
# This is where the variables come in. If the state of these variables doesn't match the user's choice by this
# point, it means that they enabled decryption or WAD packing for a title that doesn't have a ticket. Return
# code 1 so that a warning popup is shown informing them of this.

64
modules/theme.py Normal file
View File

@ -0,0 +1,64 @@
# "modules/theme.py", licensed under the MIT license
# Copyright 2024-2025 NinjaCheetah & Contributors
import os
import platform
import subprocess
def is_dark_theme_windows():
# This has to be here so that Python doesn't try to import it on non-Windows.
import winreg
try:
registry = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER)
key = winreg.OpenKey(registry, r"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize")
# This value is "AppsUseLightTheme" so a "1" is light and a "0" is dark. Side note: I hate the Windows registry.
value, _ = winreg.QueryValueEx(key, "AppsUseLightTheme")
return value == 0
except Exception:
return False
def is_dark_theme_macos():
# 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.
try:
result = subprocess.run(
["defaults", "read", "-g", "AppleInterfaceStyle"],
capture_output=True, text=True
)
return "Dark" in result.stdout
except Exception:
return False
def is_dark_theme_linux():
try:
import subprocess
result = subprocess.run(
["gsettings", "get", "org.gnome.desktop.interface", "gtk-theme"],
capture_output=True, text=True
)
# Looking for *not* "Light", because I want any theme that isn't light to be dark. An example of this is my own
# KDE Plasma setup on my desktop, where I use the "Breeze" GTK theme and want dark NUSGet to be used in that
# case.
return not "light" in result.stdout.lower()
except Exception:
return False
def is_dark_theme():
# First, check for an environment variable overriding the theme, and use that if it exists.
try:
if os.environ["THEME"].lower() == "light":
return False
elif os.environ["THEME"].lower() == "dark":
return True
else:
print(f"Unknown theme specified: \"{os.environ['THEME']}\"")
except KeyError:
pass
# If the theme wasn't overridden, then check the current system theme.
system = platform.system()
if system == "Windows":
return is_dark_theme_windows()
elif system == "Darwin":
return is_dark_theme_macos()
else:
return is_dark_theme_linux()

View File

@ -17,56 +17,6 @@ class AboutNUSGet(QDialog):
self.setFixedWidth(450)
self.setFixedHeight(500)
# Set background color to match main app
self.setStyleSheet("""
Credits {
background-color: #222222;
color: #ffffff;
}
QLabel {
color: #ffffff;
}
QLabel[class="title"] {
font-size: 20px;
font-weight: bold;
color: #ffffff;
}
QLabel[class="version"] {
font-size: 13px;
color: #aaaaaa;
}
QLabel[class="copyright"] {
font-size: 12px;
color: #888888;
}
QLabel[class="header"] {
font-size: 14px;
font-weight: bold;
border-bottom: 1px solid #444444;
padding-bottom: 4px;
margin-top: 8px;
}
QPushButton {
outline: 0;
show-decoration-selected: 1;
background-color: transparent;
border: 1px solid rgba(70, 70, 70, 1);
border-radius: 8px;
padding: 6px 10px;
margin: 4px 0px;
font-size: 13px;
font-weight: 500;
color: #ffffff;
}
QPushButton:hover {
background-color: rgba(60, 60, 60, 1);
border-color: #9c4ae8;
}
QPushButton:pressed {
background-color: rgba(26, 115, 232, 0.15);
border: 1px solid #6c1ae8;
}""")
# Create main layout
self.layout = QVBoxLayout()
self.layout.setSpacing(4)

View File

@ -18,9 +18,9 @@ from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QTransform)
from PySide6.QtWidgets import (QApplication, QComboBox, QHBoxLayout, QHeaderView,
QLabel, QLayout, QLineEdit, QMainWindow,
QMenu, QMenuBar, QPushButton, QSizePolicy,
QSpacerItem, QTabWidget, QTextBrowser, QTreeView,
QVBoxLayout, QWidget)
QMenu, QMenuBar, QProgressBar, QPushButton,
QSizePolicy, QSpacerItem, QTabWidget, QTextBrowser,
QTreeView, QVBoxLayout, QWidget)
from qt.py.ui_WrapCheckboxWidget import WrapCheckboxWidget
@ -308,17 +308,25 @@ class Ui_MainWindow(object):
self.log_text_browser = QTextBrowser(self.centralwidget)
self.log_text_browser.setObjectName(u"log_text_browser")
self.log_text_browser.setMinimumSize(QSize(0, 247))
self.log_text_browser.setMinimumSize(QSize(0, 222))
self.vertical_layout_controls.addWidget(self.log_text_browser)
self.progress_bar = QProgressBar(self.centralwidget)
self.progress_bar.setObjectName(u"progress_bar")
self.progress_bar.setMinimumSize(QSize(0, 25))
self.progress_bar.setMaximumSize(QSize(16777215, 30))
self.progress_bar.setValue(0)
self.vertical_layout_controls.addWidget(self.progress_bar)
self.horizontalLayout_3.addLayout(self.vertical_layout_controls)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 1010, 21))
self.menubar.setGeometry(QRect(0, 0, 1010, 30))
self.menuHelp = QMenu(self.menubar)
self.menuHelp.setObjectName(u"menuHelp")
MainWindow.setMenuBar(self.menubar)
@ -367,7 +375,7 @@ class Ui_MainWindow(object):
"hr { height: 1px; border-width: 0; }\n"
"li.unchecked::marker { content: \"\\2610\"; }\n"
"li.checked::marker { content: \"\\2612\"; }\n"
"</style></head><body style=\" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;\">\n"
"</style></head><body style=\" font-family:'Noto Sans'; font-size:10pt; 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))
self.menuHelp.setTitle(QCoreApplication.translate("MainWindow", u"Help", None))
# retranslateUi

View File

@ -422,7 +422,7 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>247</height>
<height>222</height>
</size>
</property>
<property name="markdown">
@ -435,11 +435,30 @@ p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&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;/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;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>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progress_bar">
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -450,7 +469,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<x>0</x>
<y>0</y>
<width>1010</width>
<height>21</height>
<height>30</height>
</rect>
</property>
<widget class="QMenu" name="menuHelp">

View File

@ -1,7 +1,7 @@
pyside6
nuitka~=2.6.0
libWiiPy
git+https://github.com/NinjaCheetah/libWiiPy
libTWLPy
zstandard
requests
imageio
imageio

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
sodipodi:docname="down_arrow_black.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="57.72"
inkscape:cx="8.0128205"
inkscape:cy="8.3939709"
inkscape:window-width="1512"
inkscape:window-height="834"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="star"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.154168;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="path1"
inkscape:flatsided="false"
sodipodi:sides="3"
sodipodi:cx="5.0945272"
sodipodi:cy="5.9900498"
sodipodi:r1="1.9104478"
sodipodi:r2="0.95522392"
sodipodi:arg1="1.5707963"
sodipodi:arg2="2.6179939"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 5.0945273,7.9004977 4.2672791,6.4676618 3.4400309,5.034826 l 1.6544964,-10e-8 1.6544963,0 -0.8272482,1.4328359 z"
inkscape:transform-center-y="0.68257261"
transform="matrix(2.3912596,0,0,1.4291353,-4.1823371,-1.2431638)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="32"
viewBox="0 0 32 32"
version="1.1"
id="svg1"
inkscape:version="1.4.1 (93de688d07, 2025-03-30)"
sodipodi:docname="information_black.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="25.125"
inkscape:cx="16.139303"
inkscape:cy="16.835821"
inkscape:window-width="1920"
inkscape:window-height="1012"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="path1"
style="fill:#000000;stroke:#000000;stroke-width:1.306;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
d="M 16 1.6523438 A 14.346852 14.346854 0 0 0 1.6523438 16 A 14.346852 14.346854 0 0 0 16 30.347656 A 14.346852 14.346854 0 0 0 30.347656 16 A 14.346852 14.346854 0 0 0 16 1.6523438 z M 15.992188 4.7265625 C 16.642424 4.7265625 17.197259 4.94079 17.65625 5.3710938 C 18.124803 5.8013975 18.359375 6.3235594 18.359375 6.9355469 C 18.359375 7.5475344 18.124803 8.0677432 17.65625 8.4980469 C 17.197259 8.9283506 16.642424 9.1445312 15.992188 9.1445312 C 15.341951 9.1445312 14.787116 8.9283506 14.328125 8.4980469 C 13.869134 8.0677432 13.640625 7.5475344 13.640625 6.9355469 C 13.640625 6.3235594 13.869134 5.8013975 14.328125 5.3710938 C 14.787116 4.94079 15.341951 4.7265625 15.992188 4.7265625 z M 13.841797 11.238281 L 18.144531 11.238281 L 18.144531 27.273438 L 13.841797 27.273438 L 13.841797 11.238281 z " />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
sodipodi:docname="right_arrow_black.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="57.72"
inkscape:cx="6.8866944"
inkscape:cy="7.52772"
inkscape:window-width="1512"
inkscape:window-height="834"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="star"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.154168;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="path1"
inkscape:flatsided="false"
sodipodi:sides="3"
sodipodi:cx="5.0945272"
sodipodi:cy="5.9900498"
sodipodi:r1="1.9104478"
sodipodi:r2="0.95522392"
sodipodi:arg1="1.5707963"
sodipodi:arg2="2.6179939"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 5.0945273,7.9004977 4.2672791,6.4676618 3.4400309,5.034826 l 1.6544964,-10e-8 1.6544963,0 -0.8272482,1.4328359 z"
transform="matrix(0,-2.3912596,1.4291353,0,-0.56059112,19.499764)"
inkscape:transform-center-x="-0.68257261" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
sodipodi:docname="right_arrow.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="57.72"
inkscape:cx="6.8693694"
inkscape:cy="7.52772"
inkscape:window-width="1512"
inkscape:window-height="836"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.154168;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="path1"
inkscape:flatsided="false"
sodipodi:sides="3"
sodipodi:cx="5.0945272"
sodipodi:cy="5.9900498"
sodipodi:r1="1.9104478"
sodipodi:r2="0.95522392"
sodipodi:arg1="1.5707963"
sodipodi:arg2="2.6179939"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 5.0945273,7.9004977 4.2672791,6.4676618 3.4400309,5.034826 l 1.6544964,-10e-8 1.6544963,0 -0.8272482,1.4328359 z"
transform="matrix(0,-2.3912596,1.4291353,0,-0.56059112,19.499764)"
inkscape:transform-center-x="-0.68257261" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -10,6 +10,33 @@ QMainWindow QLabel {
color: #ffffff;
}
QDialog QLabel {
color: #ffffff;
}
QDialog QLabel[class="title"] {
font-size: 20px;
font-weight: bold;
}
QDialog QLabel[class="version"] {
font-size: 13px;
color: #aaaaaa;
}
QDialog QLabel[class="copyright"] {
font-size: 12px;
color: #888888;
}
QDialog QLabel[class="header"] {
font-size: 14px;
font-weight: bold;
border-bottom: 1px solid #444444;
padding-bottom: 4px;
margin-top: 8px;
}
QMenuBar {
background-color: #2b2b2b;
}
@ -145,6 +172,7 @@ QTreeView {
}
QTreeView QHeaderView::section {
color: white;
background-color: #2b2b2b;
border: 0;
font-weight: 500;
@ -170,7 +198,18 @@ QTreeView QScrollBar:vertical {
margin-top: 16px;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
image: url("{IMAGE_PREFIX}/right_arrow_white.svg");
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings {
image: url("{IMAGE_PREFIX}/down_arrow_white.svg");
}
QTextBrowser {
color: white;
background-color: #1a1a1a;
selection-background-color: #6c1ae8;
}
@ -242,7 +281,7 @@ QComboBox::drop-down {
}
QComboBox::down-arrow {
image: url("{IMAGE_PREFIX}/down_arrow.svg");
image: url("{IMAGE_PREFIX}/down_arrow_white.svg");
}
QComboBox QAbstractItemView {
@ -326,6 +365,28 @@ QScrollBar::sub-line:horizontal {
subcontrol-origin: margin;
}
QMessageBox QLabel {
color: white;
}
QProgressBar {
border: 1px solid rgba(70, 70, 70, 1);
border-radius: 8px;
background-color: #1a1a1a;
text-align: center;
color: white;
padding-left: 1px;
}
QProgressBar::chunk {
background-color: qlineargradient(
x1: 0, y1: 0, x2: 1, y2: 0,
stop: 0 #6c1ae8, stop: 1 #8941ec
);
border-radius: 5px;
margin: 0.5px;
}
WrapCheckboxWidget {
show-decoration-selected: 1;
outline: 0;

444
resources/style_light.qss Normal file
View File

@ -0,0 +1,444 @@
/* "resources/style.qss" from NUSGet by NinjaCheetah & Contributors */
/* Much of this QSS was written by Alex (https://github.com/Humanoidear) */
/* from WiiLink for the fancy new WiiLink Patcher GUI. Used with permission. */
QMainWindow, QDialog {
background-color: #ffffff;
}
QMainWindow QLabel {
color: #000000;
}
QDialog QLabel {
color: #000000;
}
QDialog QLabel[class="title"] {
font-size: 20px;
font-weight: bold;
}
QDialog QLabel[class="version"] {
font-size: 13px;
color: #777777;
}
QDialog QLabel[class="copyright"] {
font-size: 12px;
color: #444444;
}
QDialog QLabel[class="header"] {
font-size: 14px;
font-weight: bold;
border-bottom: 1px solid #111111;
padding-bottom: 4px;
margin-top: 8px;
}
QMenuBar {
background-color: #e3e3e3;
color: #000000;
}
QMenuBar::item:selected {
background-color: rgb(195, 195, 195);
color: #000000;
}
QMenuBar::item:pressed {
background-color: #1a73e8;
color: #ffffff;
}
QMenu {
background-color: #ffffff;
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
padding: 6px 2px;
margin: 4px 0;
color: #000000;
}
QMenu::item {
padding: 6px 2px;
margin: 2px;
border-radius: 4px;
background-color: transparent;
}
QMenu::item:selected {
background-color: #1a73e8;
color: #ffffff;
}
QMenu::icon {
padding: 4px;
}
QRadioButton {
background-color: transparent;
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
padding: 8px 10px;
font-size: 13px;
font-weight: 500;
color: #ffffff;
}
QRadioButton:hover {
background-color: rgba(60, 60, 60, 1);
border-color: #4a86e8;
}
QRadioButton:checked {
background-color: rgba(26, 115, 232, 0.08);
border: 1px solid #1a73e8;
color: #1a73e8;
}
QRadioButton::indicator {
width: 18px;
height: 18px;
border-radius: 5px;
border: 1px solid #5f6368;
margin-right: 8px;
subcontrol-position: left center;
}
QRadioButton::indicator:checked {
background-color: #1a73e8;
border: 1px solid #1a73e8;
image: url("{IMAGE_PREFIX}/rounded_square.svg");
}
QRadioButton::indicator:hover {
border-color: #1a73e8;
}
QLineEdit {
background-color: transparent;
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
padding: 6px 10px;
margin: 4px 0px;
font-size: 13px;
color: #000000;
selection-background-color: #1a73e8;
}
QLineEdit:focus {
border-color: #1a73e8;
}
QLineEdit:disabled {
background-color: rgba(182, 182, 182, 0.5);
border: 1px solid rgba(100, 100, 100, 0.3);
color: rgba(143, 143, 143, 0.3);
}
QTabWidget::pane {
border: 1px solid rgb(163, 163, 163);
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
background-color: #e3e3e3;
top: -1px;
}
QTabBar::tab {
background-color: transparent;
border-top: 1px solid rgb(163, 163, 163);
border-left: 1px solid rgb(163, 163, 163);
border-right: 1px solid rgb(163, 163, 163);
border-top-left-radius: 6px;
border-top-right-radius: 6px;
padding: 6px 10px;
font-size: 13px;
font-weight: 500;
color: #000000;
}
QTabBar::tab:selected, QTabBar::tab:hover {
background-color: #e3e3e3;
}
QTreeView {
show-decoration-selected: 1;
outline: 0;
background-color: #ffffff;
border: 0;
border-radius: 8px;
}
QTreeView QHeaderView::section {
color: #000000;
background-color: #e3e3e3;
border: 0;
font-weight: 500;
}
QTreeView::item {
color: #000000;
}
QTreeView::item:hover {
background-color: rgb(195, 195, 195);
}
QTreeView::item:focus {
background-color: rgba(26, 115, 232, 0.08);
}
QTreeView::item:selected {
background-color: rgb(127, 182, 255);
}
QTreeView::branch:selected {
background-color: rgb(127, 182, 255);
}
QTreeView QScrollBar:vertical {
margin-top: 16px;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
image: url("{IMAGE_PREFIX}/right_arrow_black.svg");
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings {
image: url("{IMAGE_PREFIX}/down_arrow_black.svg");
}
QTextBrowser {
color: #000000;
background-color: #ececec;
selection-background-color: #1a73e8;
selection-color: #ffffff;
}
QPushButton {
outline: 0;
show-decoration-selected: 1;
background-color: transparent;
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
padding: 6px 10px;
margin: 4px 0px;
font-size: 13px;
font-weight: 500;
color: #000000;
}
QPushButton:hover {
background-color: rgb(195, 195, 195);
border-color: #4a86e8;
}
QPushButton:focus {
background-color: rgb(195, 195, 195);
border-color: #4a86e8;
}
QPushButton:pressed {
background-color: rgba(26, 115, 232, 0.15);
border: 1px solid #1a73e8;
}
QPushButton:disabled {
background-color: rgba(182, 182, 182, 0.5);
border: 1px solid rgba(100, 100, 100, 0.3);
color: rgba(143, 143, 143, 0.3);
}
QComboBox {
background-color: transparent;
combobox-popup: 0;
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
padding: 6px 10px;
margin: 4px 0px;
font-size: 13px;
font-weight: 500;
color: #000000;
}
QComboBox:on {
background-color: rgba(26, 115, 232, 0.15);
border: 1px solid #1a73e8;
}
QComboBox:hover {
background-color: rgb(195, 195, 195);
border-color: #4a86e8;
}
QComboBox:focus {
background-color: rgb(195, 195, 195);
border-color: #4a86e8;
}
QComboBox::drop-down {
border: 0;
width: 24px;
}
QComboBox::down-arrow {
image: url("{IMAGE_PREFIX}/down_arrow_black.svg");
}
QComboBox QAbstractItemView {
background-color: #ffffff;
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
padding: 4px;
outline: none;
}
QComboBox QAbstractItemView::item {
height: 25px;
border-radius: 4px;
padding: 4px 8px;
margin: 2px 0px;
color: #000000;
}
QComboBox QAbstractItemView::item:hover {
background-color: #1a73e8;
color: #ffffff;
}
QScrollBar:vertical {
border: 0;
border-radius: 8px;
padding: 2px 0 2px 0;
background-color: #f1f1f1;
}
QScrollBar::handle:vertical {
background-color: #e3e3e3;
margin: 0 2px 0 2px;
width: 10px;
border: 1px solid rgb(163, 163, 163);
border-radius: 4px;
}
QScrollBar::handle:vertical:hover {
background-color: rgba(26, 115, 232, 0.4);
}
QScrollBar::add-line:vertical {
height: 0;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical {
height: 0;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar:horizontal {
border: 0;
border-radius: 8px;
padding: 2px 0 2px 0;
background-color: #f1f1f1;
}
QScrollBar::handle:horizontal {
background-color: #e3e3e3;
border: 1px solid rgb(163, 163, 163);
margin: 0px 2px 0px 2px;
border: 1px solid rgb(163, 163, 163);
border-radius: 4px;
}
QScrollBar::handle:horizontal:hover {
background-color: rgba(26, 115, 232, 0.4);
}
QScrollBar::add-line:horizontal {
height: 0;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal {
height: 0;
subcontrol-position: top;
subcontrol-origin: margin;
}
QMessageBox QLabel {
color: #000000;
}
QProgressBar {
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
background-color: #ececec;
text-align: center;
padding: 1px;
color: black;
}
QProgressBar::chunk {
background-color: qlineargradient(
x1: 0, y1: 0, x2: 1, y2: 0,
stop: 0 #1a73e8, stop: 1 #5596f4
);
border-radius: 5px;
margin: 0.5px;
}
WrapCheckboxWidget {
show-decoration-selected: 1;
outline: 0;
background-color: transparent;
border: 1px solid rgb(163, 163, 163);
border-radius: 8px;
padding: 12px 10px;
font-size: 13px;
font-weight: 500;
color: #000000;
}
WrapCheckboxWidget:hover {
background-color: rgb(195, 195, 195);
border-color: #4a86e8;
}
WrapCheckboxWidget:disabled {
background-color: rgba(182, 182, 182, 0.5);
border: 1px solid rgba(100, 100, 100, 0.3);
color: rgba(255, 255, 255, 0.3);
}
WrapCheckboxWidget QLabel:disabled {
color: rgba(143, 143, 143, 0.3);
}
WrapCheckboxWidget QCheckBox::indicator {
width: 16px;
height: 16px;
border-radius: 4px;
border: 1px solid #5f6368;
}
WrapCheckboxWidget QCheckBox::indicator:checked {
background-color: #1a73e8;
border: 1px solid #1a73e8;
image: url("{IMAGE_PREFIX}/check.svg");
}
WrapCheckboxWidget QCheckBox::indicator:hover {
border-color: #1a73e8;
}
WrapCheckboxWidget QCheckBox:checked {
color: #1a73e8;
}

View File

@ -439,17 +439,17 @@ Sie nutzen bereits die neuste Version von NUSGet.</translation>
<translation>App-Einstellungen</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translation>Downloads-Ordner</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation>Auswählen...</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -468,17 +468,17 @@ li.checked::marker { content: &quot;\2612&quot;; }
&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:&apos;Sans Serif&apos;; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation>Hilfe</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation type="unfinished">Über NUSGet</translation>
<translation>Über NUSGet</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation>Über Qt</translation>
</message>

View File

@ -147,7 +147,7 @@
<translation>Configuración general</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -159,7 +159,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation></translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation>Acerca de NUSGet</translation>
</message>
@ -214,22 +214,22 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation>Usar ruta de descarga personalizada</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation>Seleccionar...</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation>Ayuda</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation>Acerca de Qt</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translation>Ruta de descarga</translation>
</message>

View File

@ -410,7 +410,7 @@ Les titres seront téléchargés dans un dossier &quot;NUSGet Downloads&quot;,
<translation>Configuration</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -422,7 +422,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation></translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation>À propos de NUSGet</translation>
</message>
@ -486,22 +486,22 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation>Utiliser un dossier de téléchargement différent</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation>Choisir</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation>Aide</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation>À propos de Qt</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translation>Dossier de téléchargement</translation>
</message>

View File

@ -6,72 +6,72 @@
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="16"/>
<source>About NUSGet</source>
<translation type="unfinished"></translation>
<translation>Info su NUSGet</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="82"/>
<source>NUSGet</source>
<translation type="unfinished"></translation>
<translation>NUSGet</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="87"/>
<source>Version {nusget_version}</source>
<translation type="unfinished"></translation>
<translation>Versione {nusget_version}</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="93"/>
<source>Using libWiiPy {libwiipy_version} &amp; libTWLPy {libtwlpy_version}</source>
<translation type="unfinished"></translation>
<translation>Versione libWiiPy {libwiipy_version} &amp; libTWLPy {libtwlpy_version}</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="98"/>
<source>© 2024-2025 NinjaCheetah &amp; Contributors</source>
<translation type="unfinished"></translation>
<translation>© 2024-2025 NinjaCheetah &amp; Contributori</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="114"/>
<source>View Project on GitHub</source>
<translation type="unfinished"></translation>
<translation>Vedi il progetto su GitHub</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="130"/>
<source>Translations</source>
<translation type="unfinished"></translation>
<translation>Traduzioni</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="138"/>
<source>French (Français): &lt;a href=https://github.com/rougets style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;rougets&lt;/b&gt;&lt;/a&gt;</source>
<translation type="unfinished"></translation>
<translation>Francese (Français): &lt;a href=https://github.com/rougets style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;rougets&lt;/b&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="140"/>
<source>German (Deutsch): &lt;a href=https://github.com/yeah-its-gloria style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;yeah-its-gloria&lt;/b&gt;&lt;/a&gt;</source>
<translation type="unfinished"></translation>
<translation>Tedesco (Deutsch): &lt;a href=https://github.com/yeah-its-gloria style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;yeah-its-gloria&lt;/b&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="142"/>
<source>Italian (Italiano): &lt;a href=https://github.com/LNLenost style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;LNLenost&lt;/b&gt;&lt;/a&gt;</source>
<translation type="unfinished"></translation>
<translation>Italiano: &lt;a href=https://github.com/LNLenost style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;LNLenost&lt;/b&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="144"/>
<source>Korean (): &lt;a href=https://github.com/DDinghoya style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;DDinghoya&lt;/b&gt;&lt;/a&gt;</source>
<translation type="unfinished"></translation>
<translation>Coreano (): &lt;a href=https://github.com/DDinghoya style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;DDinghoya&lt;/b&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="146"/>
<source>Norwegian (Norsk): &lt;a href=https://github.com/rolfiee style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;rolfiee&lt;/b&gt;&lt;/a&gt;</source>
<translation type="unfinished"></translation>
<translation>Norvegese (Norsk): &lt;a href=https://github.com/rolfiee style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;rolfiee&lt;/b&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="148"/>
<source>Romanian (Română): &lt;a href=https://github.com/NotImplementedLife style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;NotImplementedLife&lt;/b&gt;&lt;/a&gt;</source>
<translation type="unfinished"></translation>
<translation>Rumeno (Română): &lt;a href=https://github.com/NotImplementedLife style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;NotImplementedLife&lt;/b&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../qt/py/ui_AboutDialog.py" line="150"/>
<source>Spanish (Español): &lt;a href=https://github.com/DarkMatterCore style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;DarkMatterCore&lt;/b&gt;&lt;/a&gt;</source>
<translation type="unfinished"></translation>
<translation>Spagnolo (Español): &lt;a href=https://github.com/DarkMatterCore style=&apos;color: #4a86e8; text-decoration: none;&apos;&gt;&lt;b&gt;DarkMatterCore&lt;/b&gt;&lt;/a&gt;</translation>
</message>
</context>
<context>
@ -146,9 +146,9 @@
<translation>Impostazioni generali</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation type="unfinished"></translation>
<translation>Info su NUSGet</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="167"/>
@ -192,25 +192,25 @@
<message>
<location filename="../../qt/ui/MainMenu.ui" line="343"/>
<source>App Settings</source>
<translation type="unfinished"></translation>
<translation>Impostazioni app</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="177"/>
<source>Check for updates on startup</source>
<translation type="unfinished"></translation>
<translation>Controlla aggiornamenti all&apos;avvio</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="178"/>
<source>Use a custom download directory</source>
<translation type="unfinished"></translation>
<translation>Usa una cartella di download personalizzata</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation type="unfinished"></translation>
<translation>Seleziona...</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -219,22 +219,29 @@ li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;.AppleSystemUIFont&apos;; 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:&apos;Sans Serif&apos;; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;.AppleSystemUIFont&apos;; 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:&apos;Sans Serif&apos;; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation type="unfinished"></translation>
<translation>Aiuto</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation type="unfinished"></translation>
<translation>Info su Qt</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translation type="unfinished"></translation>
<translation>Cartella output</translation>
</message>
<message>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
@ -295,17 +302,21 @@ I titoli verranno scaricati nella cartella &quot;NUSGet Downloads&quot; all&apos
Titles marked with a checkmark are free and have a ticket available, and can be decrypted and/or packed into a WAD or TAD. Titles with an X do not have a ticket, and only their encrypted contents can be saved.
By default, titles will be downloaded to a folder named &quot;NUSGet Downloads&quot; inside your downloads folder.</source>
<translation type="unfinished"></translation>
<translation>Scegli un titolo dalla lista a sinistra o inserisci un ID Titolo per iniziare.
I titoli marcati da una spunta sono disponibili e hanno un ticket libero, e possono essere decriptati e/o convertiti in WAD o TAD. I titoli con una X non hanno un ticket e solo il contenuto criptato può essere salvato.
Per impostazione predefinita, i titoli verranno scaricati nella cartella &quot;NUSGet Downloads&quot; all&apos;interno della cartella Download.</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="173"/>
<source>Use the Wii U NUS (faster, only affects Wii/vWii)</source>
<translation type="unfinished"></translation>
<translation>Usa il NUS di Wii U (più veloce, influisce solo su Wii/vWii)</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="243"/>
<source>&lt;b&gt;There&apos;s a newer version of NUSGet available!&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;È disponibile una nuova versione di NUSGet!&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="344"/>
@ -326,17 +337,17 @@ By default, titles will be downloaded to a folder named &quot;NUSGet Downloads&q
<location filename="../../NUSGet.py" line="359"/>
<location filename="../../NUSGet.py" line="565"/>
<source>Invalid Download Directory</source>
<translation type="unfinished"></translation>
<translation>Cartella di download non valida</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="360"/>
<source>The specified download directory does not exist!</source>
<translation type="unfinished"></translation>
<translation>La cartella di download specificata non esiste!</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="363"/>
<source>Please make sure the specified download directory exists, and that you have permission to access it.</source>
<translation type="unfinished"></translation>
<translation>Assicurati che la cartella di download specificata esista e che tu abbia i permessi per accedervi.</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="393"/>
@ -346,52 +357,52 @@ By default, titles will be downloaded to a folder named &quot;NUSGet Downloads&q
<message>
<location filename="../../NUSGet.py" line="394"/>
<source>&lt;b&gt;The Title ID you have entered is not in a valid format!&lt;/b&gt;</source>
<translation>&lt;b&gt;L&apos;ID Titolo che hai inserito non è in un formato valido!&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="396"/>
<source>Title IDs must be 16 digit strings of numbers and letters. Please enter a correctly formatted Title ID, or select one from the menu on the left.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../NUSGet.py" line="399"/>
<source>&lt;b&gt;No title with the provided Title ID or version could be found!&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;Non è stato trovato alcun titolo con l&apos;ID Titolo o la versione forniti!&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="404"/>
<source>&lt;b&gt;Content decryption was not successful! Decrypted contents could not be created.&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;La decriptazione dei contenuti non è riuscita! Non è stato possibile creare i contenuti decriptati.&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="411"/>
<source>&lt;b&gt;No Ticket is Available for the Requested Title!&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;Nessun ticket disponibile per il titolo richiesto!&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="417"/>
<source>&lt;b&gt;An Unknown Error has Occurred!&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;Si è verificato un errore sconosciuto!&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="439"/>
<source>&lt;b&gt;Some issues occurred while running the download script.&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;Si sono verificati alcuni problemi durante l&apos;esecuzione dello script di download.&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="489"/>
<source>&lt;b&gt;An error occurred while parsing the script file!&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;Si è verificato un errore durante l&apos;analisi del file script!&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="500"/>
<source>&lt;b&gt;An error occurred while parsing Title IDs!&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;Si è verificato un errore durante l&apos;analisi degli ID Titolo!&lt;/b&gt;</translation>
</message>
<message>
<source>The Title ID you have entered is not in a valid format!</source>
<translation type="vanished">L&apos; ID Titolo che hai inserito non è in un formato valido!</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="396"/>
<source>Title IDs must be 16 digit strings of numbers and letters. Please enter a correctly formatted Title ID, or select one from the menu on the left.</source>
<translation>Gli ID Titolo sono un codice di 16 caratteri tra numeri e lettere. Per favore inserisci in ID Titolo formattato correttamente, o scegline uno dal menù a sinistra.</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="398"/>
<source>Title ID/Version Not Found</source>
@ -470,7 +481,7 @@ By default, titles will be downloaded to a folder named &quot;NUSGet Downloads&q
<message>
<location filename="../../NUSGet.py" line="458"/>
<source>You enabled &quot;Create decrypted contents&quot; or &quot;Pack installable archive&quot;, but the following titles in the script do not have tickets available. If enabled, encrypted contents were still downloaded.</source>
<translation>You enabled &quot;Create decrypted contents&quot; or &quot;Pack installable archive&quot;, but the following titles in the script do not have tickets available. If enabled, encrypted contents were still downloaded.</translation>
<translation>Hai abilitato &quot;Crea contenuto decriptato&quot; o &quot;Archivio installabile&quot;, ma i seguenti titoli nello script non hanno ticket disponibili. Se abilitati, i contenuti criptati sono stati comunque scaricati.</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="477"/>
@ -494,7 +505,7 @@ By default, titles will be downloaded to a folder named &quot;NUSGet Downloads&q
<message>
<location filename="../../NUSGet.py" line="491"/>
<source>Error encountered at line {lineno}, column {colno}. Please double-check the script and try again.</source>
<translation>Error encountered at line {lineno}, column {colno}. Please double-check the script and try again.</translation>
<translation>Errore riscontrato alla riga {lineno}, colonna {colno}. Controlla nuovamente lo script e riprova.</translation>
</message>
<message>
<source>An error occurred while parsing Title IDs!</source>
@ -503,22 +514,22 @@ By default, titles will be downloaded to a folder named &quot;NUSGet Downloads&q
<message>
<location filename="../../NUSGet.py" line="502"/>
<source>The title at index {index} does not have a Title ID!</source>
<translation>The title at index {index} does not have a Title ID!</translation>
<translation>Il titolo all&apos;indice {index} non ha un ID Titolo!</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="555"/>
<source>Open Directory</source>
<translation type="unfinished"></translation>
<translation>Apri cartella</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="566"/>
<source>&lt;b&gt;The specified download directory does not exist!&lt;/b&gt;</source>
<translation type="unfinished"></translation>
<translation>&lt;b&gt;La cartella di download specificata non esiste!&lt;/b&gt;</translation>
</message>
<message>
<location filename="../../NUSGet.py" line="569"/>
<source>Please make sure the download directory you want to use exists, and that you have permission to access it.</source>
<translation type="unfinished"></translation>
<translation>Assicurati che la cartella di download che desideri utilizzare esista e che tu abbia i permessi per accedervi.</translation>
</message>
<message>
<source>Open NUS script</source>

View File

@ -146,9 +146,9 @@
<translation> </translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation type="unfinished">NUSGet </translation>
<translation>NUSGet </translation>
</message>
<message>
<location filename="../../NUSGet.py" line="167"/>
@ -205,12 +205,12 @@
<translation> </translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation>...</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -222,7 +222,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation></translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation></translation>
</message>
@ -231,12 +231,12 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation type="vanished"></translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation>Qt </translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translation> </translation>
</message>

View File

@ -146,7 +146,7 @@
<translation>Generelle Instillinger</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation>Om NUSGet</translation>
</message>
@ -205,12 +205,12 @@
<translation>Bruke en egendefinert nedlastingsmappe</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation>Velg...</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -229,17 +229,17 @@ li.checked::marker { content: &quot;\2612&quot;; }
&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:&apos;Sans Serif&apos;; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation>Hjelp</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation>Om Qt</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translatorcomment>Utgangsbane</translatorcomment>
<translation></translation>

View File

@ -146,7 +146,7 @@
<translation>Generelle Instillinger</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation>Om NUSGet</translation>
</message>
@ -205,12 +205,12 @@
<translation>Bruke en egendefinert nedlastingsmappe</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation>Velg...</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -229,17 +229,17 @@ li.checked::marker { content: &quot;\2612&quot;; }
&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:&apos;Sans Serif&apos;; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation>Hjelp</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation>Om Qt</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translatorcomment>Utgangsbane</translatorcomment>
<translation></translation>

View File

@ -447,7 +447,7 @@ Implicit, titlurile vor fi descărcate într-un folder numit „NUSGet Downloads
<translation>Setări Generale</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="425"/>
<location filename="../../qt/ui/MainMenu.ui" line="432"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
@ -459,7 +459,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation></translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="464"/>
<location filename="../../qt/ui/MainMenu.ui" line="471"/>
<source>About NUSGet</source>
<translation>Despre NUSGet</translation>
</message>
@ -523,22 +523,22 @@ li.checked::marker { content: &quot;\2612&quot;; }
<translation>Folosiți un director de descărcare propriu</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="371"/>
<location filename="../../qt/ui/MainMenu.ui" line="378"/>
<source>Select...</source>
<translation>Selectează...</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="451"/>
<location filename="../../qt/ui/MainMenu.ui" line="458"/>
<source>Help</source>
<translation>Ajutor</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="475"/>
<location filename="../../qt/ui/MainMenu.ui" line="482"/>
<source>About Qt</source>
<translation>Despre Qt</translation>
</message>
<message>
<location filename="../../qt/ui/MainMenu.ui" line="361"/>
<location filename="../../qt/ui/MainMenu.ui" line="368"/>
<source>Output Path</source>
<translation>Cale de ieșire</translation>
</message>