diff --git a/HISTORY.md b/HISTORY.md new file mode 100644 index 0000000..63a5323 --- /dev/null +++ b/HISTORY.md @@ -0,0 +1,124 @@ +# History of the project +This file collects notable milestones and events related to DZGUI, mainly around DZGUI as a framework and the history of development. +A chronological summary of features can be found in CHANGELOG.md. + +## 2021 +### 2021-12-03: DayZ adds support for Battleye over Proton +DayZ was among a handful of games with whitelisted anti-cheat support under Valve's emerging WINE-based Proton compatibility layer. +While adding anti-cheat compatibility at a technical level, this change did not actually allow the client to connect to servers running complex modlists. + +Development of the precursor to DZGUI began at around this time. + +### 2021-12-12: initial version of DZTUI is created +DZTUI, a Bash script and terminal user interface, was the precursor to DZGUI. +This was an initial attempt at bootstrapping the Steam client to handle mods correctly when launching DayZ. +Due to user interest, features continued to be added. This early tool is archived under the 'dztui' branch. + +## 2022 +### 2022-05-09: addition of zenity GUI and project name change (DZGUI) +With the introduction of the Steam Deck, more users wanted a graphical user interface +to interact with DZTUI. Being that DZTUI was purely a Bash script, a method of +drawing menus was needed, so the "zenity" package was used to create prefabricated dialogs. +While this met the minimum requirement to show prompts and selectable options, no rich customization was possible. + +The introduction of zenity as a dependency marked the shift from "DZTUI" to "DZGUI". + +Throughout 2022, the limits of zenity for DZGUI's purposes were tested, particularly in the context of SteamOS. +This led to the discovery of a number of bugs in zenity, GTK, and SteamOS, which were reported up to their respective channels. +While this was improving the SteamOS user experience, it started to become clear that a fully custom UI was needed. + +This barebones version of DZGUI sufficed for some time, with the Bash script and some standalone Python modules doing the heavy lifting, +and this period served to surface a number of bugs and interesting interactions with the Steam client. + +## 2023 +### 2023-11-23: Python 3.10 dependency +Prior to this time, DZGUI open-endedly allowed you to use any Python version for its modules, without any significant handling for +the idiosyncrasies of different versions. A minimum requirement of Python 3.10 was thus instituted to normalize expected behavior. + +Throughout 2023, various features related to server browsing were added, such as filters and more granular search parameters. + +There were still a lot of unknowns at this time, so things were being resolved through trial and error. + +## 2024 +### 2024-01-31: DZGUI 5 API introduces GTK UI +Using zenity as a simple GUI had exposed some bugs and limitations in that package, particularly when trying to push huge lists of server records +into tables and sorting them in a performant manner. + +Around this time it became clear that a more robust UI framework was needed. While keeping the original Bash script and Python modules for +background processing, PyGObject (GTK) was added to the project in order to ship a custom UI that could be designed from the ground up. + +However, it should be noted that at this point, the DZGUI logic itself was still a (increasingly large) Bash script to which a GTK UI had been stitched on. +These were totally separate components, with UI actions on the GTK side triggering calls to Bash functions in an overly complex helper file. +The UI was basically a thin client around the old Bash logic, but this was still a far cry from an integrated application with proper signals and dedicated components. + +Effectively, DZGUI 5 through 6 were a stepping stone that set the groundwork to go from DZGUI 4 (pure Bash script) to +DZGUI 7 (standalone Python application). Today, little of DZGUI 5's original logic remains outside of the basic UI grid. + +### 2024-10-15: Frostline DLC released, widespread parsing problems +DayZ's first DLC introduced a new format for server responses that packed extra metadata into the A2S_RULES format. +Upon its release, all third-party DayZ launchers and server listing web sites were unable to parse the mod information being returned from Frostline servers. + +For a period of two weeks, this remained unsolved and various attempts were made to understand the updated specification. + +### 2024-10-30: DZGUI hotfix adds support for Frostline servers +DZGUI was the first third-party tool to fix parsing for Frostline servers and restore functionality. +This was a small milestone, because it meant DZGUI was evolving from a "dumb" launcher to a featureful tool +touching upon and improving all aspects of the end-to-end DayZ experience. + +Particularly around this time, the sheer diversity of needs of modders, server operators, and players started to become clear. +Users had highly specific and diverse use cases for setting up their game environment, and requested a number of features to support that on +the DZGUI side. + +## 2025 +### 2025-01-17: DZGUI 6 API +With DZGUI 6, the difficult decision to enforce a Python 3.13 dependency was made. +While the previous dependency was Python 3.10+, it was deemed better to develop against and target identical versions. + +However, due to the vagaries of managing Python environments on end-user systems, this change added unnecessary complexity and frustration. +Users had to properly set up virtual environments, install the relevant dependencies, and create a wrapper script to run this version, whereas +previous versions had essentially been point and click. + +### 2025-10-23: DZGUI 7 API and the "Ship of Theseus" +It had become clear that the situation above was untenable and the legacy Bash script was unmaintainable given the project's enlarged scope. +The lack of a robust testing or typehinting framework made it difficult to diagnose rare bugs. + +Shipping a standalone, turnkey application with zero or minimal dependencies was the most urgent priority. +DZGUI was still carrying around small bits and pieces of the old Bash script logic, so the decision was made to +refactor the application into a pure Python + GTK tool. This would effectively be a total rewrite of all logic, +only preserving the most minimal skeleton of the original UI layout as a reference. + +Over the course of a year, a wholesale "Ship of Theseus" rewrite took place. +Nearly every component of DZGUI 6, both API and UI side, was taken apart and replaced. + +A soft alpha and beta phase were used to iterate on this concept further. DZGUI 7 was increasingly recommended to users +as the preferred choice. This allowed for keeping the established userbase on the (relatively) stable DZGUI 6 spec, while building up +the new spec and making it available to more users as features were elaborated. + +Through late 2025, several LLM-generated applications that recycled significant parts of DZGUI's code without the applicable GPL license were found. +The maintainers of those projects were advised to excise the offending segments or apply the necessary GPL licenses. + +## 2026 +### 2026-05-17: Switch to standalone releases +The DZGUI 7 beta starts shipping standalone glibc builds with an integrated setup wizard and installer. + +DZGUI 6 had relied on "over the air" updates delivered via either a "stable" or "testing" branch +(archived respectively under the "dzgui" and "testing" branches). Effectively, the script would bootstrap itself and +fetch raw files directly from the repository. This was prone to problems because updates were monolithic, not giving +an easy escape hatch if the user needed to rollback in the event of a regression. + +This was changed to atomic, tagged releases. In addition to updating directly through DZGUI, these prebuilt releases can be +downloaded manually as needed, and rollbacks are available for all prior versions under the DZGUI 7 specification. + +### 2026-10-27: 500 tickets closed +The milestone of 500 tickets/PRs being closed was reached. + +2026 was by far DZGUI's most intensive year by commits, perhaps suggesting the scope of the rewrite: + +- 2021: 16 +- 2022: 434 +- 2023: 322 +- 2024: 347 +- 2025: 426 +- 2026: 1300 + +DZGUI 7 is scheduled to release as a stable version within the year. diff --git a/dzgui/api/mods.py b/dzgui/api/mods.py index f8a9814..722e3dc 100644 --- a/dzgui/api/mods.py +++ b/dzgui/api/mods.py @@ -24,14 +24,6 @@ from typing import Any logger = logging.getLogger(APP_NAME) -@dataclass -class ModMeta: - protocol: str - published_id: str - name: str - timestamp: str - - def get_local_mod_ids(steam_path: Path) -> list[int]: workshop_path = get_local_mod_path(steam_path) mods = get_local_mods(workshop_path) diff --git a/dzgui/api/steam.py b/dzgui/api/steam.py index 4a7d1e8..23357f2 100644 --- a/dzgui/api/steam.py +++ b/dzgui/api/steam.py @@ -31,10 +31,10 @@ from dzgui.const.constants import ( VDF_PATH, ) from dzgui.const.endpoints import ( - APP_DETAILS, - SUB_ENDPOINT, + STEAM_APP_DETAILS, STEAM_PUBLISHED_FILES, - UNSUB_ENDPOINT, + STEAM_SUB, + STEAM_UNSUB, ) from dzgui.strings import wizard from dzgui.strings.errors import api_validation_error, workshop_endpoint_error @@ -310,11 +310,11 @@ def update_workshop(key: str, mod: int, endpoint: str) -> None: def subscribe(key: str, mod: int) -> None: - update_workshop(key, mod, SUB_ENDPOINT) + update_workshop(key, mod, STEAM_SUB) def unsubscribe(key: str, mod: int) -> None: - update_workshop(key, mod, UNSUB_ENDPOINT) + update_workshop(key, mod, STEAM_UNSUB) def validate_mod(client: str, mod: str) -> None: @@ -512,7 +512,7 @@ def get_app_path(folders_path: Path, appid: int) -> Path: def get_app_name(appid: int) -> str | None: payload = {"appids": [appid]} - res = requests.get(APP_DETAILS, params=payload) + res = requests.get(STEAM_APP_DETAILS, params=payload) if res.status_code != 200: return None try: diff --git a/dzgui/app_init.py b/dzgui/app_init.py index 1a942ab..4903b20 100644 --- a/dzgui/app_init.py +++ b/dzgui/app_init.py @@ -22,7 +22,6 @@ from dzgui.init.migrate import ( copy_state_files, migrate_cols_file, ) -from dzgui.init.flock import lock_acquire from dzgui.init.prereqs import has_flatpak_client, has_steam_client from dzgui.strings import boot @@ -122,8 +121,6 @@ def load_steam_icon() -> None: def build_gui(version: str, is_debug: bool) -> App | None: - lock = lock_acquire() # noqa - set_locale() # NOTE: consider aborting this check if steam deck xdg_paths = get_xdg_paths() @@ -158,9 +155,6 @@ def build_gui(version: str, is_debug: bool) -> App | None: f.truncate(0) if _is_steam_deck is False: - # TODO: sudo escalation dialog - # count = get_map_count() - # TODO: move into module if FLATPAK_ROOT_PATH in lookup(XDG.config, Preferences.DEFAULT): has_client = has_flatpak_client() else: diff --git a/dzgui/const/constants.py b/dzgui/const/constants.py index aba522f..daed17e 100644 --- a/dzgui/const/constants.py +++ b/dzgui/const/constants.py @@ -37,37 +37,8 @@ HEX_GREEN = "#32CD32" HEX_RED = "#FF0000" HEX_ORANGE = "#FFAC1C" -# TODO: normalize icon names -CALCULATOR = "accessories-calculator-symbolic" -CARET_DOWN = "go-down-symbolic" -CARET_UP = "go-up-symbolic" -CLIPBOARD = "edit-copy-symbolic" -CLOSE = "window-close-symbolic" -FOLDER = "folder-symbolic" -EDIT_DELETE = "edit-delete-symbolic" -ERROR = "dialog-error-symbolic" -HELP_BUBBLE = "help-about-symbolic" -INPUT_KEYBOARD = "input-keyboard-symbolic" -LIST_ADD = "list-add-symbolic" -REFRESH_ICON = "view-refresh-symbolic" -SEARCH_ICON = "system-search-symbolic" -STEAM_ICON = "steam-tray-symbolic" -VIEW_CONCEAL = "view-conceal-symbolic" -VIEW_REVEAL = "view-reveal-symbolic" -WARNING = "dialog-warning-symbolic" -WEB_BROWSER = "web-browser-symbolic" -DAY_ICON = "weather-clear-symbolic" -NIGHT_ICON = "weather-clear-night-symbolic" - SEPARATOR = "SEPARATOR" -# TODO: drop -NO_PADDING = 0 -NO_EXPAND = False -NO_FILL = False -EXPAND = True -FILL = True - SCROLL_INCREMENT = 50 WINDOW_DEFAULT_X = 1400 WINDOW_DEFAULT_Y = 800 diff --git a/dzgui/const/endpoints.py b/dzgui/const/endpoints.py index 7616ff0..ed6239d 100644 --- a/dzgui/const/endpoints.py +++ b/dzgui/const/endpoints.py @@ -3,9 +3,9 @@ STEAM_PUBLISHED_FILES = ( "https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1" ) STEAM_SERVERS = "https://api.steampowered.com/IGameServersService/GetServerList/v1" -SUB_ENDPOINT = "https://api.steampowered.com/IPublishedFileService/Subscribe/v1" -UNSUB_ENDPOINT = "https://api.steampowered.com/IPublishedFileService/Unsubscribe/v1" -APP_DETAILS = "https://store.steampowered.com/api/appdetails?" +STEAM_SUB = "https://api.steampowered.com/IPublishedFileService/Subscribe/v1" +STEAM_UNSUB = "https://api.steampowered.com/IPublishedFileService/Unsubscribe/v1" +STEAM_APP_DETAILS = "https://store.steampowered.com/api/appdetails?" GITHUB = "https://github.com/aclist" GITHUB_RELEASES = "https://api.github.com/repos/aclist/dztui/releases/latest" diff --git a/dzgui/const/icons.py b/dzgui/const/icons.py new file mode 100644 index 0000000..176e73e --- /dev/null +++ b/dzgui/const/icons.py @@ -0,0 +1,20 @@ +ICON_CALCULATOR = "accessories-calculator-symbolic" +ICON_CARET_DOWN = "go-down-symbolic" +ICON_CARET_UP = "go-up-symbolic" +ICON_CLIPBOARD = "edit-copy-symbolic" +ICON_CLOSE = "window-close-symbolic" +ICON_DAY = "weather-clear-symbolic" +ICON_EDIT_DELETE = "edit-delete-symbolic" +ICON_ERROR = "dialog-error-symbolic" +ICON_FOLDER = "folder-symbolic" +ICON_HELP_BUBBLE = "help-about-symbolic" +ICON_INPUT_KEYBOARD = "input-keyboard-symbolic" +ICON_LIST_ADD = "list-add-symbolic" +ICON_NIGHT = "weather-clear-night-symbolic" +ICON_REFRESH = "view-refresh-symbolic" +ICON_SEARCH = "system-search-symbolic" +ICON_STEAM = "steam-tray-symbolic" +ICON_VIEW_CONCEAL = "view-conceal-symbolic" +ICON_VIEW_REVEAL = "view-reveal-symbolic" +ICON_WARNING = "dialog-warning-symbolic" +ICON_WEB_BROWSER = "web-browser-symbolic" diff --git a/dzgui/controllers/emitter.py b/dzgui/controllers/emitter.py index 82b0e91..e21ac18 100644 --- a/dzgui/controllers/emitter.py +++ b/dzgui/controllers/emitter.py @@ -3,8 +3,8 @@ from typing import TYPE_CHECKING import gi gi.require_version("Gtk", "3.0") -from gi.repository.Gtk import ListStore # noqa E402 -from gi.repository import Gdk, GObject # noqa E402 +from gi.repository.Gtk import ListStore +from gi.repository import GObject if TYPE_CHECKING: from dzgui.const.enum import NotebookPage, ServerTab diff --git a/dzgui/controllers/mc.py b/dzgui/controllers/mc.py index 6074046..c6b2280 100644 --- a/dzgui/controllers/mc.py +++ b/dzgui/controllers/mc.py @@ -32,7 +32,7 @@ from dzgui.views.dialogs.generic import ExceptionDialog import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GLib, GObject # noqa E402 +from gi.repository import Gtk, Gdk, GLib, GObject logger = logging.getLogger(APP_NAME) diff --git a/dzgui/main.py b/dzgui/main.py index 5e660cf..a32d021 100644 --- a/dzgui/main.py +++ b/dzgui/main.py @@ -43,6 +43,9 @@ def main() -> None: # NOTE: only import ligbirepository modules after the above check from dzgui.app_init import build_gui + from dzgui.init.flock import lock_acquire + + lock = lock_acquire() # noqa app = build_gui(version, args.debug) if app is None: diff --git a/dzgui/managers/connection.py b/dzgui/managers/connection.py index 80291fa..a57a421 100644 --- a/dzgui/managers/connection.py +++ b/dzgui/managers/connection.py @@ -48,18 +48,13 @@ from dzgui.strings.dialogs import ( waiting_for_directories, ) from dzgui.strings import kb -from dzgui.strings.server_mods import checkmark, resync +from dzgui.strings.server_mods import checkmark, resync, invalid_mod from dzgui.util.format import format_exception, format_mib from dzgui.util.strings import dialog, server_timeout from dzgui.util.symlink import rebuild_symlinks from dzgui.views.dialogs.generic import ExceptionDialog from dzgui.views.dialogs.servers import ServerDetailsDialog, ServerModDialog -import gi - -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib # noqa E402 - if TYPE_CHECKING: from dzgui.api.servers import A2SInfo, Record from dzgui.controllers.mc import Controller @@ -197,9 +192,8 @@ class ConnectionManager: is_last = self.is_last_server() - # TODO: strings invalid_mods = [ - (mod[0], mod[1]) for mod in remote_mods if mod[2] == "Invalid mod" + (mod[0], mod[1]) for mod in remote_mods if mod[2] == invalid_mod ] prereqs = Prerequisites( @@ -277,8 +271,7 @@ class ConnectionManager: for mod in alpha_mods: # NOTE: if the mod is neither synched or out of date, it is a malformed mod if mod[2] == "": - # TODO: strings - mod[2] = "Invalid mod" + mod[2] = invalid_mod return alpha_mods, missing_mods diff --git a/dzgui/managers/filter.py b/dzgui/managers/filter.py index 357318f..5204d35 100644 --- a/dzgui/managers/filter.py +++ b/dzgui/managers/filter.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING from dzgui.model.model_factory import ModelFactory from dzgui.util import strings -from dzgui.util.strings import all_maps +from dzgui.strings.filters import all_maps if TYPE_CHECKING: from dzgui.model.model_factory import FastInsertListStore @@ -105,17 +105,11 @@ class FilterManager: self.reinit_map_store() maps.sort() - for m in maps: - # TODO: strings - if m == "All maps": - continue + clean = [m for m in maps if m != all_maps] + for m in clean: self.append_map([m]) - # TODO: currently unused - def get_unique_maps(self) -> list[str]: - return [row[0] for row in self.map_store if row[0] != "All maps"] - - def get_all_filters(self) -> tuple[str, ...]: + def get_all_filters(self) -> tuple: map_name = self.get_active_map_name() enabled = self.get_filters() kw = self.get_active_keyword() diff --git a/dzgui/managers/mods.py b/dzgui/managers/mods.py index b94a1c5..3bb2ace 100644 --- a/dzgui/managers/mods.py +++ b/dzgui/managers/mods.py @@ -30,7 +30,7 @@ import dzgui.api.pefile as PeFile import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/managers/threading.py b/dzgui/managers/threading.py index 023f017..0344103 100644 --- a/dzgui/managers/threading.py +++ b/dzgui/managers/threading.py @@ -15,7 +15,7 @@ if TYPE_CHECKING: import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib # noqa E402 +from gi.repository import GLib logger = logging.getLogger(APP_NAME) diff --git a/dzgui/managers/update.py b/dzgui/managers/update.py index 4bf201b..f08b279 100644 --- a/dzgui/managers/update.py +++ b/dzgui/managers/update.py @@ -15,11 +15,6 @@ from dzgui.strings import dialogs from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager from dzgui.views.dialogs.generic import ExceptionDialog, QuitDialog -import gi - -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib # noqa E402 - if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/model/model_factory.py b/dzgui/model/model_factory.py index a48c0d3..d2fb0a5 100644 --- a/dzgui/model/model_factory.py +++ b/dzgui/model/model_factory.py @@ -7,8 +7,8 @@ from dzgui.util.strings import delimiter import gi gi.require_version("Gtk", "3.0") -from gi.repository.Gtk import ListStore, TreeIter # noqa E402 -from gi.repository import GObject # noqa E402 +from gi.repository.Gtk import ListStore, TreeIter +from gi.repository import GObject GTYPE_TO_PYTHON = { GObject.type_from_name(GObject.type_name(ptype)): ptype # type: ignore[no-untyped-call] diff --git a/dzgui/model/proxy_model.py b/dzgui/model/proxy_model.py index 023da66..5cb3d97 100644 --- a/dzgui/model/proxy_model.py +++ b/dzgui/model/proxy_model.py @@ -6,6 +6,7 @@ from typing import Any, TYPE_CHECKING, Union from dzgui.const.enum import FilterMode from dzgui.model.model_factory import ModelFactory from dzgui.util import strings +from dzgui.strings import filters as str_filters if TYPE_CHECKING: from dzgui.managers.filter import FilterManager @@ -188,7 +189,7 @@ class ProxyModelManager: rows = self.filtered sel_map = self.filter_man.get_active_map_name() - if sel_map == strings.all_maps: + if sel_map == str_filters.all_maps: return rows rows = [row for row in rows if row[1] == sel_map] diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index 22fca92..dd4cf9b 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -21,7 +21,7 @@ from dzgui.views.dialogs.generic import ExceptionDialog import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib # noqa E402 +from gi.repository import Gtk, GLib if TYPE_CHECKING: from dzgui.api.servers import A2SInfo, Record diff --git a/dzgui/strings/buttons.py b/dzgui/strings/buttons.py index faa00a0..539b7a0 100644 --- a/dzgui/strings/buttons.py +++ b/dzgui/strings/buttons.py @@ -1,2 +1,16 @@ +clipboard_button = "Copy to clipboard" +clipboard_ip_button = "Copy IP to clipboard" + +dock_button_collapse = "Collapse the connection panel" +dock_button_expand = "Expand the connection panel" + workshop = "Steam Workshop" workshop_tooltip = "Open your Workshop subscriptions" + +version_notifier = "Copied!" +version_tooltip = "Click to copy to clipboard" + +update_button = "Updates available" + +unset_button_label = "Unset" +unset_button_tooltip = "Unset this server as favorite" diff --git a/dzgui/strings/dialogs.py b/dzgui/strings/dialogs.py index b895ba0..b31f58a 100644 --- a/dzgui/strings/dialogs.py +++ b/dzgui/strings/dialogs.py @@ -29,3 +29,5 @@ toggle_calc = "Toggle calculator" server_details = "Server details" server_message = "Server message" + +caught_cancel_signal = "Caught cancel signal, cleaning up" diff --git a/dzgui/strings/filters.py b/dzgui/strings/filters.py new file mode 100644 index 0000000..b6e6bc6 --- /dev/null +++ b/dzgui/strings/filters.py @@ -0,0 +1,4 @@ +all_maps = "All maps" +filters_heading = "Filters" +keyword_placeholder = "Filter by keyword" +map_placeholder = "Filter by map" diff --git a/dzgui/strings/generic.py b/dzgui/strings/generic.py index 1aff78a..68b9cd9 100644 --- a/dzgui/strings/generic.py +++ b/dzgui/strings/generic.py @@ -1 +1,2 @@ +tab_changed_label = "*" selectable_tree = "Ctrl-click to select multiple; Shift-click to select a range." diff --git a/dzgui/strings/notes.py b/dzgui/strings/notes.py new file mode 100644 index 0000000..77d53da --- /dev/null +++ b/dzgui/strings/notes.py @@ -0,0 +1,5 @@ +dialog_title = "Add a short note/reminder" +dialog_subtitle = "Limit 30 chars" +delete_button = "Delete note" +ok_button = "Update note" +current_note = "Current note: '{0}'" diff --git a/dzgui/strings/options.py b/dzgui/strings/options.py index a105f07..fd505f2 100644 --- a/dzgui/strings/options.py +++ b/dzgui/strings/options.py @@ -16,7 +16,9 @@ lan_combo = "LAN" fullscreen_eventbox = "This option is not available on Steam Deck." save_button = "Save" +api_placeholder = "Enter API key" api_failed = "API validation failed" +api_validate = "Validate" flatpak_label = "Flatpak client" flatpak_standard = "Standard" diff --git a/dzgui/strings/server_mods.py b/dzgui/strings/server_mods.py index c41b443..d5a2e42 100644 --- a/dzgui/strings/server_mods.py +++ b/dzgui/strings/server_mods.py @@ -3,4 +3,5 @@ mod_id = "ID" up_to_date = "Up to date" modlist = "Modlist" checkmark = "✓" -resync="⟳" +resync = "⟳" +invalid_mod = "Invalid mod" diff --git a/dzgui/util/clip.py b/dzgui/util/clip.py index 971515c..991346d 100644 --- a/dzgui/util/clip.py +++ b/dzgui/util/clip.py @@ -1,8 +1,7 @@ import gi gi.require_version("Gtk", "3.0") -gi.require_version("Gdk", "3.0") -from gi.repository import Gtk, Gdk # noqa E402 +from gi.repository import Gtk, Gdk def copy_clipboard(text: str) -> None: diff --git a/dzgui/util/css.py b/dzgui/util/css.py index 44bf7cd..2350be7 100644 --- a/dzgui/util/css.py +++ b/dzgui/util/css.py @@ -5,7 +5,7 @@ from dzgui.const.constants import APP_NAME_LOWER, CSS_PATH import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa E402 +from gi.repository import Gtk, Gdk def add_class(widget: Gtk.Widget, label: str) -> None: diff --git a/dzgui/util/dist.py b/dzgui/util/dist.py index 20db696..94ec811 100644 --- a/dzgui/util/dist.py +++ b/dzgui/util/dist.py @@ -7,11 +7,6 @@ from dzgui.const.constants import APP_NAME from dzgui.util.ip import get_coords from dzgui.util.localize import number -import gi - -gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 - if TYPE_CHECKING: from queue import Queue from dzgui.const.enum import ServerTab diff --git a/dzgui/util/format.py b/dzgui/util/format.py index 203ab3f..38894f8 100644 --- a/dzgui/util/format.py +++ b/dzgui/util/format.py @@ -8,7 +8,7 @@ from dzgui.util.strings import no_mods, no_servers, workshop import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk def format_pango(text: str) -> str: diff --git a/dzgui/util/keys.py b/dzgui/util/keys.py index 04f291d..5293d21 100644 --- a/dzgui/util/keys.py +++ b/dzgui/util/keys.py @@ -1,6 +1,8 @@ import gi + gi.require_version("Gtk", "3.0") -from gi.repository import Gdk # noqa E402 +from gi.repository import Gdk + def is_navkey(key: int) -> bool: nav_keys = [ @@ -18,6 +20,7 @@ def is_navkey(key: int) -> bool: return True return False + def is_ctrl_mask(event: Gdk.EventKey) -> bool: if event.state is Gdk.ModifierType.CONTROL_MASK: return True diff --git a/dzgui/util/margins.py b/dzgui/util/margins.py index f4f8883..82cef96 100644 --- a/dzgui/util/margins.py +++ b/dzgui/util/margins.py @@ -1,6 +1,8 @@ import gi + gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk + def set_surrounding_margins(widget: Gtk.Widget, margin: int) -> None: """ diff --git a/dzgui/util/save_screenshot.py b/dzgui/util/save_screenshot.py index 8c106bc..ffa769f 100644 --- a/dzgui/util/save_screenshot.py +++ b/dzgui/util/save_screenshot.py @@ -4,7 +4,7 @@ from typing import cast, TYPE_CHECKING import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GLib # noqa E402 +from gi.repository import Gdk, GLib if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/util/strings.py b/dzgui/util/strings.py index 21790a9..1043f01 100644 --- a/dzgui/util/strings.py +++ b/dzgui/util/strings.py @@ -160,9 +160,6 @@ filter_unofficial = "Unofficial" filter_modded = "Modded" filter_unmodded = "Unmodded" -# maps -all_maps = "All maps" - # state unknown = "Unknown" none_provided = "None provided" diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 79fde50..756dae2 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -38,7 +38,7 @@ import gi gi.require_version("Gtk", "3.0") gi.require_version("GLibUnix", "2.0") -from gi.repository import Gtk, GLib, GLibUnix, Gdk # type: ignore # noqa E402 +from gi.repository import Gtk, GLib, GLibUnix, Gdk # type: ignore if TYPE_CHECKING: from dzgui.config.userprefs import UserPrefs diff --git a/dzgui/views/components/buttonbox.py b/dzgui/views/components/buttonbox.py index 496f237..e54e0d4 100644 --- a/dzgui/views/components/buttonbox.py +++ b/dzgui/views/components/buttonbox.py @@ -1,13 +1,13 @@ import logging from typing import TYPE_CHECKING -from dzgui.const.constants import APP_NAME, NO_EXPAND, NO_FILL, NO_PADDING +from dzgui.const.constants import APP_NAME from dzgui.const.enum import ButtonType import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa E402 +from gi.repository import Gtk, Gdk logger = logging.getLogger(APP_NAME) @@ -63,7 +63,7 @@ class ButtonBox(Gtk.Box): self.buttons.append(button) button.connect("clicked", self._on_selection_button_clicked) - self.pack_start(button, NO_EXPAND, NO_FILL, NO_PADDING) + self.pack_start(button, expand=False, fill=False, padding=0) def _focus_first_button(self, emitter: "Emitter") -> None: self.buttons[0].grab_focus() diff --git a/dzgui/views/components/buttons.py b/dzgui/views/components/buttons.py index a913168..2fb62eb 100644 --- a/dzgui/views/components/buttons.py +++ b/dzgui/views/components/buttons.py @@ -5,21 +5,22 @@ from dzgui.strings import buttons from dzgui.util.strings import ( atomic_buttons, ) -from dzgui.const.constants import ( - CLIPBOARD, - CLOSE, - INPUT_KEYBOARD, - LIST_ADD, - REFRESH_ICON, - STEAM_ICON, - WEB_BROWSER, +from dzgui.const.icons import ( + ICON_CLIPBOARD, + ICON_CLOSE, + ICON_INPUT_KEYBOARD, + ICON_LIST_ADD, + ICON_REFRESH, + ICON_STEAM, + ICON_WARNING, + ICON_WEB_BROWSER, ) from dzgui.strings import connect_panel import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GLib # noqa E402 +from gi.repository import Gtk, GLib if TYPE_CHECKING: from gi.repository import GLib @@ -98,12 +99,12 @@ class LargeIconTextButton(IconButton): class ClipboardButton(IconTextButton): - def __init__(self, func: Callable[[], str]) -> None: - super().__init__(CLIPBOARD, atomic_buttons.copy) + def __init__(self, controller: Union["Controller", None], func: Callable) -> None: + super().__init__(ICON_CLIPBOARD, atomic_buttons.copy) + self.controller = controller self.connect("clicked", self._on_button_clicked, func) - # TODO: strings - self.set_tooltip_text("Copy to clipboard") + self.set_tooltip_text(buttons.clipboard_button) def _on_button_clicked(self, button: Self, func: Callable[[], str]) -> None: def revert() -> Literal[False]: @@ -120,28 +121,26 @@ class CopyIpButton(ClipboardButton): def __init__(self, func: Callable[[], str]) -> None: super().__init__(func) - # TODO: strings - self.set_tooltip_text("Copy IP to clipboard") + self.set_tooltip_text(buttons.clipboard_ip_button) class CloseButton(IconTextButton): def __init__(self, label: str) -> None: - super().__init__(icon=CLOSE, label=label) + super().__init__(icon=ICON_CLOSE, label=label) - # TODO: strings - self.set_tooltip_text("Unset this server as favorite") + self.set_tooltip_text(buttons.unset_button_tooltip) class WebButton(IconTextButton): def __init__(self, label: str) -> None: - super().__init__(icon=WEB_BROWSER, label=label) + super().__init__(icon=ICON_WEB_BROWSER, label=label) pass class RefreshButton(IconTextButton): def __init__(self, controller: "Controller") -> None: super().__init__( - icon=REFRESH_ICON, + icon=ICON_REFRESH, label=atomic_buttons.refresh, ) @@ -206,7 +205,7 @@ class RefreshButton(IconTextButton): class KeysButton(IconTextButton): def __init__(self, controller: "Controller") -> None: - super().__init__(icon=INPUT_KEYBOARD, label=atomic_buttons.keys) + super().__init__(icon=ICON_INPUT_KEYBOARD, label=atomic_buttons.keys) self.controller = controller self.set_margin_top(10) @@ -223,7 +222,7 @@ class KeysButton(IconTextButton): class SteamConnectButton(LargeIconTextButton): def __init__(self) -> None: - super().__init__(icon=STEAM_ICON, label=connect_panel.connect_button) + super().__init__(icon=ICON_STEAM, label=connect_panel.connect_button) self.set_tooltip_text(connect_panel.connect_tooltip) @@ -243,7 +242,7 @@ class SteamWorkshopButton(SteamTextButton): class AddButton(IconTextButton): def __init__(self) -> None: - super().__init__(icon=LIST_ADD, label=connect_panel.add_button) + super().__init__(icon=ICON_LIST_ADD, label=connect_panel.add_button) self.set_tooltip_text(connect_panel.add_tooltip) diff --git a/dzgui/views/components/connect_panel.py b/dzgui/views/components/connect_panel.py index 0f91f84..7ea9a34 100644 --- a/dzgui/views/components/connect_panel.py +++ b/dzgui/views/components/connect_panel.py @@ -1,8 +1,14 @@ from typing import Self, TYPE_CHECKING -from dzgui.const.constants import CARET_DOWN, CARET_UP, UDP_PORT +from dzgui.const.icons import ICON_CARET_DOWN, ICON_CARET_UP +from dzgui.const.constants import UDP_PORT from dzgui.model.servers import ServerModelManager from dzgui.strings import connect_panel +from dzgui.strings.buttons import ( + dock_button_collapse, + dock_button_expand, + unset_button_label, +) from dzgui.util.keys import is_ctrl_mask from dzgui.views.components.buttons import ( AddButton, @@ -18,7 +24,7 @@ from dzgui.views.components.labels import BoldLabel import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa E402 +from gi.repository import Gtk, Gdk if TYPE_CHECKING: from dzgui.controllers.mc import Controller @@ -30,27 +36,24 @@ ROWS = 1 class DockButton(IconButton): def __init__(self, child: Gtk.Widget) -> None: - super().__init__(CARET_DOWN) + super().__init__(ICON_CARET_DOWN) self.expanded = True self.child = child self.connect("clicked", self._on_click) - self.collapse_text = "Collapse the connection panel" - self.expand_text = "Expand the connection panel" - self.set_margin_top(10) - self.set_tooltip_text(self.collapse_text) + self.set_tooltip_text(dock_button_collapse) def collapse(self) -> None: - self.set_image(Icon(CARET_UP)) + self.set_image(Icon(ICON_CARET_UP)) self.child.hide() - self.set_tooltip_text(self.expand_text) + self.set_tooltip_text(dock_button_expand) def expand(self) -> None: - self.set_image(Icon(CARET_DOWN)) + self.set_image(Icon(ICON_CARET_DOWN)) self.child.show() - self.set_tooltip_text(self.collapse_text) + self.set_tooltip_text(dock_button_collapse) def _on_click(self, button: Self) -> None: if self.expanded: @@ -81,7 +84,6 @@ class LanPanel(Gtk.Frame): self.scan = Gtk.Button(label=connect_panel.lan_scan_button) self.scan.connect("clicked", self._on_scan_clicked) - # TODO: strings self.early_abort = Gtk.CheckButton(label=connect_panel.lan_checkbox) self.early_abort.set_active(True) self.early_abort.set_tooltip_text(connect_panel.lan_abort_tooltip) @@ -189,8 +191,7 @@ class FavPanel(Gtk.Frame): self.fav_button.connect("clicked", self._on_connect_clicked) self.copy_button = CopyIpButton(self.get_fav_ip) - # TODO: strings - self.unset_button = CloseButton("Unset") + self.unset_button = CloseButton(unset_button_label) self.unset_button.connect("clicked", self._on_unset_clicked) if favorite is None: diff --git a/dzgui/views/components/crumbs.py b/dzgui/views/components/crumbs.py index cd57426..610f8d6 100644 --- a/dzgui/views/components/crumbs.py +++ b/dzgui/views/components/crumbs.py @@ -7,7 +7,7 @@ from dzgui.util.format import embolden import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/components/entry.py b/dzgui/views/components/entry.py index 408ead8..db3fb94 100644 --- a/dzgui/views/components/entry.py +++ b/dzgui/views/components/entry.py @@ -1,15 +1,16 @@ from typing import Any, Callable, TYPE_CHECKING from dzgui.api.servers import validate_ip -from dzgui.const.constants import VIEW_CONCEAL, VIEW_REVEAL +from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_VIEW_REVEAL from dzgui.util.css import add_class, remove_class from dzgui.strings import connect_panel +from dzgui.strings.options import api_placeholder, api_validate from dzgui.strings.errors import api_popover import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GObject # noqa E402 +from gi.repository import Gtk, Gdk, GObject if TYPE_CHECKING: from dzgui.controllers.mc import Controller @@ -142,19 +143,17 @@ class APIEntry(Gtk.Box): self.func: Callable[[str], None] | None = None - # TODO: strings self.entry = Gtk.Entry( - width_chars=60, hexpand=True, placeholder_text="Enter API key" + width_chars=60, hexpand=True, placeholder_text=api_placeholder ) - self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, VIEW_REVEAL) + self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, ICON_VIEW_REVEAL) self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) self.entry.set_visibility(False) self.entry.connect("changed", self._on_text_changed) self.entry.connect("icon-release", self._on_icon_release) self.entry.connect("activate", self._on_field_activated) - # TODO: strings - self.submit = Gtk.Button(label="Validate") + self.submit = Gtk.Button(label=api_validate) self.submit.set_sensitive(False) self.submit.connect("clicked", self._on_submit) @@ -205,9 +204,9 @@ class APIEntry(Gtk.Box): ) -> None: visible = widget.get_visibility() if visible: - icon, state = VIEW_REVEAL, False + icon, state = ICON_VIEW_REVEAL, False else: - icon, state = VIEW_CONCEAL, True + icon, state = ICON_VIEW_CONCEAL, True widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon) widget.set_visibility(state) diff --git a/dzgui/views/components/eventbox.py b/dzgui/views/components/eventbox.py index 5e06127..92c97ca 100644 --- a/dzgui/views/components/eventbox.py +++ b/dzgui/views/components/eventbox.py @@ -1,12 +1,12 @@ from typing import TYPE_CHECKING from dzgui.const.enum import NotebookPage -from dzgui.const.constants import HELP_BUBBLE +from dzgui.const.icons import ICON_HELP_BUBBLE import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk # noqa E402 +from gi.repository import Gtk, Gdk if TYPE_CHECKING: from dzgui.controllers.mc import Controller @@ -20,7 +20,7 @@ class InfoEventBox(Gtk.EventBox): self.text = text self.icon = Gtk.Image.new_from_icon_name( - HELP_BUBBLE, Gtk.IconSize.LARGE_TOOLBAR + ICON_HELP_BUBBLE, Gtk.IconSize.LARGE_TOOLBAR ) self.icon.set_opacity(0.8) box = Gtk.Box() diff --git a/dzgui/views/components/filter_panel.py b/dzgui/views/components/filter_panel.py index 2fa69a5..b3bc584 100644 --- a/dzgui/views/components/filter_panel.py +++ b/dzgui/views/components/filter_panel.py @@ -3,21 +3,22 @@ from typing import Literal, TYPE_CHECKING from dzgui.const.constants import ( APP_NAME, - EXPAND, - NO_EXPAND, - NO_FILL, - NO_PADDING, - SEARCH_ICON, ) +from dzgui.const.icons import ICON_SEARCH from dzgui.util.format import format_exception -from dzgui.util.strings import all_maps +from dzgui.strings.filters import ( + all_maps, + filters_heading, + keyword_placeholder, + map_placeholder, +) from dzgui.views.components.maps_combo import MapsCombo from dzgui.views.components.labels import BoldLabel import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, Pango, GLib # noqa E402 +from gi.repository import Gtk, Gdk, Pango, GLib logger = logging.getLogger(APP_NAME) @@ -102,8 +103,7 @@ class ButtonGrid(Gtk.Grid): class KeywordEntry(Gtk.Entry): def __init__(self, controller: "Controller") -> None: - # TODO :strings - super().__init__(placeholder_text="Filter by keyword") + super().__init__(placeholder_text=keyword_placeholder) self.keyword = "" self.controller = controller @@ -112,7 +112,7 @@ class KeywordEntry(Gtk.Entry): self.connect("key-press-event", self._on_keypress) self.connect("icon-release", lambda *args: self.activate()) - self.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, SEARCH_ICON) + self.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, ICON_SEARCH) self.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) self.emitter.connect("load_maps", self._on_maps_loaded) @@ -177,8 +177,7 @@ class FilterPanel(Gtk.Box): self.keyword_entry = KeywordEntry(self.controller) self.button_grid = ButtonGrid(self.controller, defaults, tooltips) - # TODO: strings - self.filters_label = BoldLabel("Filters") + self.filters_label = BoldLabel(filters_heading) self.emitter.connect( "request_keyword_focus", lambda _: self.keyword_entry.grab_focus() @@ -198,13 +197,12 @@ class FilterPanel(Gtk.Box): self.maps_entry: Gtk.Entry = self.maps_combo.get_child() # type: ignore self.maps_entry.set_completion(completion) - # TODO: strings - self.maps_entry.set_placeholder_text("Filter by map") + self.maps_entry.set_placeholder_text(map_placeholder) self.maps_entry.connect("changed", self._on_map_completion, True) self.maps_entry.connect("key-press-event", self._on_map_entry_keypress) self.maps_entry.connect("activate", self._on_maps_activated) - self.maps_combo.pack_start(renderer_text, EXPAND) + self.maps_combo.pack_start(renderer_text, expand=True) self.maps_combo.connect("changed", self._on_map_changed) self.maps_combo.connect("key-press-event", self._on_combo_keypress) @@ -214,7 +212,7 @@ class FilterPanel(Gtk.Box): self.maps_combo, self.button_grid, ): - self.pack_start(el, NO_EXPAND, NO_FILL, NO_PADDING) + self.pack_start(el, expand=False, fill=False, padding=0) def _on_maps_activated(self, entry: Gtk.Entry) -> None: text = entry.get_text() diff --git a/dzgui/views/components/icon.py b/dzgui/views/components/icon.py index 2cb222d..54b88d9 100644 --- a/dzgui/views/components/icon.py +++ b/dzgui/views/components/icon.py @@ -1,7 +1,7 @@ import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk class Icon(Gtk.Image): diff --git a/dzgui/views/components/labels.py b/dzgui/views/components/labels.py index 9ecc52a..a9c7db0 100644 --- a/dzgui/views/components/labels.py +++ b/dzgui/views/components/labels.py @@ -3,7 +3,7 @@ from dzgui.util.format import embolden import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk class BoldLabel(Gtk.Label): diff --git a/dzgui/views/components/maps_combo.py b/dzgui/views/components/maps_combo.py index 0eea10f..821b831 100644 --- a/dzgui/views/components/maps_combo.py +++ b/dzgui/views/components/maps_combo.py @@ -1,7 +1,7 @@ import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib # noqa E402 +from gi.repository import Gtk class MapsCombo(Gtk.EntryCompletion): diff --git a/dzgui/views/components/misc.py b/dzgui/views/components/misc.py index cdc3f49..80e694e 100644 --- a/dzgui/views/components/misc.py +++ b/dzgui/views/components/misc.py @@ -1,7 +1,8 @@ from typing import Self from warnings import deprecated -from dzgui.const.constants import ERROR, FLATPAK_RUN_CMD, FLATPAK_SANDBOX, STEAM_CMD +from dzgui.const.constants import FLATPAK_RUN_CMD, FLATPAK_SANDBOX, STEAM_CMD +from dzgui.const.icons import ICON_ERROR from dzgui.init.prereqs import has_steam_client, has_flatpak_client from dzgui.strings import options from dzgui.views.components.box import HBox @@ -73,7 +74,7 @@ class ErrorPopover(Gtk.Popover): self.hbox = HBox() self.label = Gtk.Label(label="", margin_start=10, margin_end=10) - error_icon = Icon(ERROR, margin_start=10) + error_icon = Icon(ICON_ERROR, margin_start=10) self.hbox.extend([error_icon, self.label]) self.add(self.hbox) self.show_all() diff --git a/dzgui/views/components/mod_panel.py b/dzgui/views/components/mod_panel.py index 7c913c4..1fed7e8 100644 --- a/dzgui/views/components/mod_panel.py +++ b/dzgui/views/components/mod_panel.py @@ -1,14 +1,13 @@ from typing import Self, TYPE_CHECKING from dzgui.const.enum import ModButton -from dzgui.const.constants import NO_EXPAND, FILL, NO_PADDING from dzgui.util.strings import mod_panel from dzgui.views.components.labels import BoldLabel import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller @@ -55,7 +54,7 @@ class ModSelectionPanel(Gtk.Box): for button in buttons: b = EnumeratedModButton(button) b.connect("clicked", self._on_button_clicked) - self.main_panel.pack_start(b, NO_EXPAND, FILL, NO_PADDING) + self.main_panel.pack_start(b, expand=False, fill=True, padding=0) self.stale_panel = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.highlight_stale_button = ModPanelButton(ModButton.HIGHLIGHT_STALE) @@ -67,11 +66,11 @@ class ModSelectionPanel(Gtk.Box): self.unhighlight_stale_button, self.select_stale_button, ): - self.stale_panel.pack_start(b, NO_EXPAND, FILL, NO_PADDING) + self.stale_panel.pack_start(b, expand=False, fill=True, padding=0) b.connect("clicked", self._on_button_clicked) for el in header, self.main_panel, self.stale_panel: - self.pack_start(el, NO_EXPAND, FILL, NO_PADDING) + self.pack_start(el, expand=False, fill=True, padding=0) self.connect("map", self._reinit_button) diff --git a/dzgui/views/components/right_panel.py b/dzgui/views/components/right_panel.py index f38def4..c04bba7 100644 --- a/dzgui/views/components/right_panel.py +++ b/dzgui/views/components/right_panel.py @@ -6,13 +6,10 @@ from typing import Literal, TYPE_CHECKING from dzgui.const.constants import ( APP_NAME, - NO_EXPAND, - NO_FILL, - FILL, - NO_PADDING, ) from dzgui.const.enum import ServerTab from dzgui.managers.update import UpdateManager +from dzgui.strings.buttons import update_button, version_notifier, version_tooltip from dzgui.util.clip import copy_clipboard from dzgui.util.file import is_writeable from dzgui.views.components.buttonbox import ButtonBox @@ -23,7 +20,7 @@ from dzgui.views.components.buttons import IconTextButton, RefreshButton, KeysBu import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GLib # noqa E402 +from gi.repository import Gtk, Gdk, GLib if TYPE_CHECKING: from dzgui.controllers.mc import Controller @@ -65,20 +62,19 @@ class RightPanel(Gtk.Box): vexpand=True, halign=Gtk.Align.END, valign=Gtk.Align.END, - # TODO: strings - tooltip_text="Click to copy to clipboard", + tooltip_text=version_tooltip, ) eb = Gtk.EventBox(halign=Gtk.Align.END, valign=Gtk.Align.END) eb.add(self.version_label) eb.connect("button-press-event", self._on_version_clicked) for el in self.button_vbox, self.keys, self.filters_vbox, self.refresh_button: - self.pack_start(el, NO_EXPAND, FILL, NO_PADDING) + self.pack_start(el, expand=False, fill=True, padding=0) - self.pack_start(self.sel_panel, NO_EXPAND, NO_FILL, NO_PADDING) + self.pack_start(self.sel_panel, expand=False, fill=False, padding=0) self.update_button = IconTextButton( - "dialog-information-symbolic", label="Updates available" + "dialog-information-symbolic", label=update_button ) self.gutter_box = Gtk.Box( @@ -96,7 +92,7 @@ class RightPanel(Gtk.Box): "clicked", self._on_update_button_clicked, exe_path, update ) self.gutter_box.add(eb) - self.pack_start(self.gutter_box, NO_EXPAND, FILL, NO_PADDING) + self.pack_start(self.gutter_box, expand=False, fill=True, padding=0) def _on_update_button_clicked( self, button: Gtk.Button, exe_path: str, url: str @@ -131,7 +127,6 @@ class RightPanel(Gtk.Box): return self.copying = True version = self.version_label.get_text() - # TODO: strings - self.version_label.set_text("Copied!") + self.version_label.set_text(version_notifier) copy_clipboard(version) GLib.timeout_add_seconds(1, revert) diff --git a/dzgui/views/components/statusbar.py b/dzgui/views/components/statusbar.py index b9dc49b..6f9489c 100644 --- a/dzgui/views/components/statusbar.py +++ b/dzgui/views/components/statusbar.py @@ -6,7 +6,7 @@ from dzgui.util.strings import esc_to_return, question_to_return import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.const.enum import ServerTab diff --git a/dzgui/views/components/toast.py b/dzgui/views/components/toast.py index d6fd577..95e663f 100644 --- a/dzgui/views/components/toast.py +++ b/dzgui/views/components/toast.py @@ -2,8 +2,9 @@ from typing import Literal from dzgui.util import css import gi + gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib # noqa E402 +from gi.repository import Gtk, GLib class Toast(Gtk.EventBox): diff --git a/dzgui/views/dialogs/boot.py b/dzgui/views/dialogs/boot.py index f3809a6..bfc0b1e 100644 --- a/dzgui/views/dialogs/boot.py +++ b/dzgui/views/dialogs/boot.py @@ -14,7 +14,6 @@ from dzgui.const.constants import HEX_GREEN, HEX_RED from dzgui.init.coords import get_local_coords from dzgui.init.dayz import is_dayz_installed from dzgui.init.update import check_updates -from dzgui.const.constants import EXPAND, FILL from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager from dzgui.strings import preboot, dialogs from dzgui.util.format import format_exception @@ -118,8 +117,8 @@ class BootDialog(ColorAwareApp, Gtk.Dialog): # type: ignore self.error_box.add(self.button_hbox) self.content = self.get_content_area() - self.content.pack_start(self.scrollable_tree, EXPAND, FILL, 0) - self.content.pack_start(self.error_box, EXPAND, FILL, 0) + self.content.pack_start(self.scrollable_tree, expand=True, fill=True, padding=0) + self.content.pack_start(self.error_box, expand=True, fill=True, padding=0) self.show_all() self.error_box.hide() diff --git a/dzgui/views/dialogs/calc.py b/dzgui/views/dialogs/calc.py index 9b6267a..cf7e3be 100644 --- a/dzgui/views/dialogs/calc.py +++ b/dzgui/views/dialogs/calc.py @@ -3,14 +3,14 @@ from dataclasses import dataclass from datetime import datetime, time, timedelta from typing import Literal -from dzgui.const.constants import DAY_ICON, NIGHT_ICON +from dzgui.const.icons import ICON_DAY, ICON_NIGHT from dzgui.strings import calc from dzgui.views.components.icon import Icon from dzgui.views.components.labels import BoldLabel from dzgui.views.components.box import VBox, HBox gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, GObject # noqa E402 +from gi.repository import Gtk, GLib, GObject DAY_START_TIME = time(hour=6, minute=0, second=0) DAY_END_TIME = time(hour=18, minute=0, second=0) @@ -385,7 +385,7 @@ class TimePickerFrame(Gtk.Frame): h1 = BoldLabel(calc.heading_server_time) h2 = BoldLabel(calc.heading_target_time) - self.icon_indicator = Icon(DAY_ICON) + self.icon_indicator = Icon(ICON_DAY) self.update_server_icon() server_time_box = HBox(10) @@ -411,7 +411,7 @@ class TimePickerFrame(Gtk.Frame): self.add(flowbox) def update_server_icon(self) -> None: - icon = DAY_ICON if self.server_time.is_day() else NIGHT_ICON + icon = ICON_DAY if self.server_time.is_day() else ICON_NIGHT self.icon_indicator.set_icon_name(icon) def _on_server_clock_increment(self, emitter: Emitter, time_now: datetime) -> None: diff --git a/dzgui/views/dialogs/early_alert.py b/dzgui/views/dialogs/early_alert.py index ac4dfd4..c861725 100644 --- a/dzgui/views/dialogs/early_alert.py +++ b/dzgui/views/dialogs/early_alert.py @@ -8,7 +8,7 @@ from dzgui.views.mixins.colorscheme import ColorAwareApp import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk class AbortDialog(ColorAwareApp, Gtk.MessageDialog): # type: ignore diff --git a/dzgui/views/dialogs/filepicker.py b/dzgui/views/dialogs/filepicker.py index f72c70d..7951ae7 100644 --- a/dzgui/views/dialogs/filepicker.py +++ b/dzgui/views/dialogs/filepicker.py @@ -2,10 +2,10 @@ from pathlib import Path from dzgui.util.strings import picker -import gi # noqa E402 +import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk class FilePicker(Gtk.FileChooserDialog): diff --git a/dzgui/views/dialogs/generic.py b/dzgui/views/dialogs/generic.py index 08dc77b..da46346 100644 --- a/dzgui/views/dialogs/generic.py +++ b/dzgui/views/dialogs/generic.py @@ -1,6 +1,5 @@ from typing import Literal, Self, TYPE_CHECKING -from dzgui.const.constants import NO_EXPAND, NO_FILL, NO_PADDING, EXPAND, FILL from dzgui.strings import dialogs from dzgui.util import strings from dzgui.views.components.buttons import ClipboardButton @@ -8,7 +7,7 @@ from dzgui.views.components.buttons import ClipboardButton import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 +from gi.repository import Gtk, GLib if TYPE_CHECKING: from dzgui.controllers.mc import Controller @@ -46,7 +45,7 @@ class GenericDialog(Gtk.MessageDialog): def pack(self, widget: Gtk.Widget) -> None: content = self.get_content_area() - content.pack_start(widget, EXPAND, FILL, NO_PADDING) + content.pack_start(widget, expand=True, fill=True, padding=0) class ConfirmationDialog(GenericDialog): @@ -121,13 +120,13 @@ class WaitDialog(GenericDialog): spinner_box.add(spinner) if self.jobs > 1: - content.pack_start(self.prog, NO_EXPAND, NO_FILL, 0) + content.pack_start(self.prog, expand=False, fill=False, padding=0) else: - content.pack_start(spinner_box, NO_EXPAND, NO_FILL, 0) + content.pack_start(spinner_box, expand=False, fill=False, padding=0) spinner.start() if show_cancel is True: - content.pack_start(self.cancel, NO_EXPAND, NO_FILL, 0) + content.pack_start(self.cancel, expand=False, fill=False, padding=0) def update_text(self, msg: str) -> None: self.format_secondary_text(msg) @@ -140,8 +139,7 @@ class WaitDialog(GenericDialog): self.cur_job += 1 def _on_cancel_clicked(self, button: Gtk.Button) -> None: - # TODO: strings - GLib.idle_add(self.update_text, "Caught cancel signal, cleaning up") + GLib.idle_add(self.update_text, dialogs.caught_cancel_signal) self.controller.set_cancel_event() def show_cancel(self, state: bool) -> None: @@ -272,7 +270,7 @@ class ExceptionDialog(TextBufferDialog): bottom_margin=10, ) textview.set_buffer(Gtk.TextBuffer(text=trace)) - box.pack_start(textview, EXPAND, FILL, 0) + box.pack_start(textview, expand=True, fill=True, padding=0) self.error_details = Gtk.ScrolledWindow( overlay_scrolling=False, @@ -296,7 +294,7 @@ class ExceptionDialog(TextBufferDialog): ) details_textview.set_buffer(self.details_buffer) - details_box.pack_start(details_textview, EXPAND, FILL, 10) + details_box.pack_start(details_textview, expand=True, fill=True, padding=10) self.error_details.add(details_box) self.error_notebook = Gtk.Notebook(show_tabs=False, margin_bottom=15) diff --git a/dzgui/views/dialogs/link_dialog.py b/dzgui/views/dialogs/link_dialog.py index 294765c..32c39ec 100644 --- a/dzgui/views/dialogs/link_dialog.py +++ b/dzgui/views/dialogs/link_dialog.py @@ -1,7 +1,6 @@ import textwrap from typing import Self, TYPE_CHECKING -from dzgui.const.constants import NO_EXPAND, NO_FILL from dzgui.util.strings import notice from dzgui.views.dialogs.generic import GenericDialog from dzgui.views.components.buttons import SteamTextButton @@ -9,7 +8,7 @@ from dzgui.views.components.buttons import SteamTextButton import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: @@ -42,7 +41,7 @@ class WorkshopLinkDialog(GenericDialog): button.set_margin_start(60) button.set_margin_end(60) button.connect("clicked", self._on_button_clicked, uid) - self.dialogBox.pack_end(button, NO_EXPAND, NO_FILL, 0) + self.dialogBox.pack_end(button, expand=False, fill=False, padding=0) self.show_all() self.connect("response", self._on_dialog_response) diff --git a/dzgui/views/dialogs/note.py b/dzgui/views/dialogs/note.py index b595e90..362f1d8 100644 --- a/dzgui/views/dialogs/note.py +++ b/dzgui/views/dialogs/note.py @@ -1,12 +1,13 @@ from typing import Self, TYPE_CHECKING +from dzgui.strings import notes from dzgui.views.components.entry import ValidatedEntry from dzgui.views.dialogs.generic import GenericDialog -import gi # noqa E402 +import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gdk, Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller @@ -14,23 +15,20 @@ if TYPE_CHECKING: class NoteDialog(GenericDialog): def __init__(self, controller: "Controller"): - # TODO: add to strings - title = "Add a short note/reminder." - secondary = "Limit 30 chars" super().__init__( controller=controller, - text=title, + text=notes.dialog_title, buttons=Gtk.ButtonsType.NONE, mtype=Gtk.MessageType.INFO, - secondary=secondary, + secondary=notes.dialog_subtitle, ) self.controller = controller - delete_button = Gtk.Button(label="Delete note") + delete_button = Gtk.Button(label=notes.delete_button) delete_button.set_sensitive(False) self.add_action_widget(delete_button, Gtk.ResponseType.CANCEL) - self.ok = self.add_button("Update note", Gtk.ResponseType.OK) + self.ok = self.add_button(notes.ok_button, Gtk.ResponseType.OK) self.ok.grab_default() self.entry = ValidatedEntry(controller, self.validate) @@ -42,7 +40,7 @@ class NoteDialog(GenericDialog): self.entry.set_text(note) if len(note) > 0: delete_button.set_sensitive(True) - self.format_secondary_text(f"Current note: '{note}'") + self.format_secondary_text(notes.current_note.format(note)) elif len(note) == 0: self.ok.set_sensitive(False) @@ -55,9 +53,6 @@ class NoteDialog(GenericDialog): self.entry.connect("changed", self._on_text_changed) def _on_text_changed(self, entry: Gtk.Entry) -> None: - """ - Called in conjunction with signal callback in the parent class - """ if len(entry.get_text()) == 0: self.ok.set_sensitive(False) @@ -71,14 +66,11 @@ class NoteDialog(GenericDialog): def _on_response(self, dialog: Self, response: Gtk.ResponseType) -> None: match response: - case Gtk.ResponseType.DELETE_EVENT: - self.destroy() case Gtk.ResponseType.OK: note = self.entry.get_text() self.controller.add_note(note) - self.destroy() case Gtk.ResponseType.CANCEL: self.controller.delete_note() - self.destroy() - case Gtk.ResponseType.CANCEL | Gtk.ResponseType.CLOSE: - self.destroy() + case _: + pass + self.destroy() diff --git a/dzgui/views/dialogs/servers.py b/dzgui/views/dialogs/servers.py index 6166aee..b58d352 100644 --- a/dzgui/views/dialogs/servers.py +++ b/dzgui/views/dialogs/servers.py @@ -2,7 +2,7 @@ import gi import html from typing import Self, TYPE_CHECKING -from dzgui.const.constants import CALCULATOR +from dzgui.const.icons import ICON_CALCULATOR from dzgui.const.enum import ContextMenuGroup from dzgui.model.model_factory import ModelFactory from dzgui.util import css @@ -110,7 +110,7 @@ class ServerDetailsDialog(ServerDialog): text = format_hyperlinks(text) self.description.set_markup(html.escape(text)) - calc_button = IconTextButton(CALCULATOR, dialogs.toggle_calc) + calc_button = IconTextButton(ICON_CALCULATOR, dialogs.toggle_calc) calc_button.connect("clicked", self._on_calc_pressed) calc_button.set_halign(Gtk.Align.END) calc_button.set_valign(Gtk.Align.START) diff --git a/dzgui/views/dialogs/uninstall.py b/dzgui/views/dialogs/uninstall.py index b27f1d6..8b25510 100644 --- a/dzgui/views/dialogs/uninstall.py +++ b/dzgui/views/dialogs/uninstall.py @@ -18,7 +18,7 @@ from dzgui.views.mixins.colorscheme import ColorAwareApp import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Pango # noqa E402 +from gi.repository import Gtk, GLib, Pango class Assistant(Gtk.Assistant): diff --git a/dzgui/views/dialogs/wizard.py b/dzgui/views/dialogs/wizard.py index c2f38af..82d84f0 100644 --- a/dzgui/views/dialogs/wizard.py +++ b/dzgui/views/dialogs/wizard.py @@ -35,7 +35,7 @@ from dzgui.views.trees.tree_simple import SimpleTree import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gdk, Gtk, GLib, GObject, GdkPixbuf # noqa E402 +from gi.repository import Gtk, GLib, GObject, GdkPixbuf if TYPE_CHECKING: from dzgui.config.xdg import Xdg diff --git a/dzgui/views/mixins/context_mixin.py b/dzgui/views/mixins/context_mixin.py index 2fd7ca1..825deac 100644 --- a/dzgui/views/mixins/context_mixin.py +++ b/dzgui/views/mixins/context_mixin.py @@ -9,7 +9,7 @@ from dzgui.views.trees.tree_base import TreeView import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 +from gi.repository import Gtk, Gdk logger = logging.getLogger(APP_NAME) diff --git a/dzgui/views/mixins/cursor_mixin.py b/dzgui/views/mixins/cursor_mixin.py index 71d4851..0690e19 100644 --- a/dzgui/views/mixins/cursor_mixin.py +++ b/dzgui/views/mixins/cursor_mixin.py @@ -5,7 +5,7 @@ from dzgui.util.keys import is_ctrl_mask import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 +from gi.repository import Gtk, Gdk class CursorMixin: diff --git a/dzgui/views/mixins/mods_mixin.py b/dzgui/views/mixins/mods_mixin.py index 6cc7da8..1b76321 100644 --- a/dzgui/views/mixins/mods_mixin.py +++ b/dzgui/views/mixins/mods_mixin.py @@ -3,7 +3,7 @@ from dzgui.views.trees.tree_base import TreeView import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 +from gi.repository import Gtk class ModsMixin: diff --git a/dzgui/views/pages/changelog.py b/dzgui/views/pages/changelog.py index 108912c..86a7d32 100644 --- a/dzgui/views/pages/changelog.py +++ b/dzgui/views/pages/changelog.py @@ -15,7 +15,7 @@ from dzgui.views.mixins.scrollable_mixin import ScrollableMixin import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk logger = logging.getLogger(APP_NAME) diff --git a/dzgui/views/pages/devs.py b/dzgui/views/pages/devs.py index 7c95255..3eccae8 100644 --- a/dzgui/views/pages/devs.py +++ b/dzgui/views/pages/devs.py @@ -7,10 +7,10 @@ from dzgui.util.strings import developers from dzgui.views.components.labels import BoldLabel from dzgui.views.trees.tree_base import TreeView -import gi # noqa E402 +import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/pages/help.py b/dzgui/views/pages/help.py index bcfbfd8..e4b1f17 100644 --- a/dzgui/views/pages/help.py +++ b/dzgui/views/pages/help.py @@ -4,7 +4,7 @@ from dzgui.views.trees.tree_menu import MenuTreeView import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/pages/keys.py b/dzgui/views/pages/keys.py index 1da56d3..ddd630e 100644 --- a/dzgui/views/pages/keys.py +++ b/dzgui/views/pages/keys.py @@ -7,7 +7,7 @@ from dzgui.util.css import add_class import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/pages/log.py b/dzgui/views/pages/log.py index a9e1bd5..aad06a6 100644 --- a/dzgui/views/pages/log.py +++ b/dzgui/views/pages/log.py @@ -9,7 +9,7 @@ from dzgui.views.trees.tree_log import LogTreeView import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk if TYPE_CHECKING: from dzgui.controllers.mc import Controller diff --git a/dzgui/views/pages/offline.py b/dzgui/views/pages/offline.py index b0200b0..ceb5686 100644 --- a/dzgui/views/pages/offline.py +++ b/dzgui/views/pages/offline.py @@ -3,14 +3,12 @@ from enum import Enum from typing import Self, TYPE_CHECKING, Union from dzgui.util import css +from dzgui.const.icons import ICON_EDIT_DELETE, ICON_FOLDER, ICON_WARNING from dzgui.const.constants import ( APPID_DAYZ, APPID_DAYZ_EXP, APPNAME_DAYZ, APPNAME_DAYZ_EXP_HUMAN, - EDIT_DELETE, - FOLDER, - WARNING, ) from dzgui.const.enum import ContextMenuGroup, NotebookPage from dzgui.managers.offline import OfflineManager @@ -87,7 +85,7 @@ class FolderHBox(HBox): self.emitter = controller.get_emitter() self.eb = InfoEventBox(eb_text, controller) - self.button = IconTextButton(FOLDER, btn_label, Gtk.PositionType.LEFT) + self.button = IconTextButton(ICON_FOLDER, btn_label, Gtk.PositionType.LEFT) self.button.set_halign(Gtk.Align.START) self.button.set_image_position(Gtk.PositionType.LEFT) @@ -99,7 +97,7 @@ class FolderHBox(HBox): self.label = Gtk.Label() self.scrolled_label.add(self.label) - self.unset_button = IconTextButton(EDIT_DELETE, offline.unset_button) + self.unset_button = IconTextButton(ICON_EDIT_DELETE, offline.unset_button) self.unset_button.connect("clicked", self._on_unset_clicked) self.spinner = Gtk.Spinner() @@ -195,7 +193,7 @@ class ModFrame(HeadingFrame): self.tree_vbox.extend([self.scrolled, self.status]) self.no_mods = HBox(spacing=10) - no_mods_icon = Icon(WARNING, margin_start=10) + no_mods_icon = Icon(ICON_WARNING, margin_start=10) no_mods_label = Gtk.Label(label=offline.no_local_mods, halign=Gtk.Align.START) self.no_mods.extend([no_mods_icon, no_mods_label]) diff --git a/dzgui/views/pages/options.py b/dzgui/views/pages/options.py index 6269e89..1fa3fbb 100644 --- a/dzgui/views/pages/options.py +++ b/dzgui/views/pages/options.py @@ -13,12 +13,8 @@ from dzgui.const.constants import ( FLATPAK_RUN_CMD, FLATPAK_SANDBOX, FLATPAK_STEAM_PATH, - NO_EXPAND, - NO_FILL, - NO_PADDING, - VIEW_CONCEAL, - VIEW_REVEAL, ) +from dzgui.const.icons import ICON_VIEW_CONCEAL, ICON_VIEW_REVEAL from dzgui.const.endpoints import STEAM_API_SETUP from dzgui.const.enum import Preferences, ServerTab from dzgui.strings import options @@ -67,7 +63,7 @@ class SubmitField(Gtk.Box): # TODO: audit for all applicable callbacks if private: self.entry.set_icon_from_icon_name( - Gtk.EntryIconPosition.SECONDARY, VIEW_REVEAL + Gtk.EntryIconPosition.SECONDARY, ICON_VIEW_REVEAL ) self.entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, True) self.entry.connect("icon-release", self._on_icon_release) @@ -131,9 +127,9 @@ class SubmitField(Gtk.Box): ) -> None: visible = widget.get_visibility() if visible: - icon, state = VIEW_REVEAL, False + icon, state = ICON_VIEW_REVEAL, False else: - icon, state = VIEW_CONCEAL, True + icon, state = ICON_VIEW_CONCEAL, True widget.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon) widget.set_visibility(state) @@ -234,8 +230,8 @@ class ToggleField(Gtk.Box): self.radio1 = Gtk.RadioButton.new_with_label(None, first_option) self.radio2 = Gtk.RadioButton.new_from_widget(self.radio1) self.radio2.set_label(second_option) - self.pack_start(self.radio1, NO_EXPAND, NO_FILL, NO_PADDING) - self.pack_start(self.radio2, NO_EXPAND, NO_FILL, NO_PADDING) + self.pack_start(self.radio1, expand=False, fill=False, padding=0) + self.pack_start(self.radio2, expand=False, fill=False, padding=0) def set_suboption_active(self, state: bool) -> None: # NOTE: defer connection of signal until after state is set diff --git a/dzgui/views/pages/preconnect.py b/dzgui/views/pages/preconnect.py index 983e760..3f54b31 100644 --- a/dzgui/views/pages/preconnect.py +++ b/dzgui/views/pages/preconnect.py @@ -1,9 +1,9 @@ from dataclasses import dataclass from typing import Self, Sequence, TYPE_CHECKING -from dzgui.const.constants import ( - ERROR, - WARNING, +from dzgui.const.icons import ( + ICON_ERROR, + ICON_WARNING, ) from dzgui.const.enum import NotebookPage from dzgui.util.css import add_class @@ -18,7 +18,7 @@ from dzgui.views.trees.tree_server_mods import ServerModTreeView import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gdk, Gtk # noqa E402 +from gi.repository import Gdk, Gtk if TYPE_CHECKING: @@ -166,7 +166,7 @@ class PreConnectionAssistant(Gtk.Box): # TODO: abstract into components self.warning_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) - self.warning_tree = MaskedTree(WARNING) + self.warning_tree = MaskedTree(ICON_WARNING) self.warning_placeholder = Placeholder(preconnect.placeholder_no_warnings) self.warning_box.add(self.warning_tree) self.warning_box.add(self.warning_placeholder) @@ -175,7 +175,7 @@ class PreConnectionAssistant(Gtk.Box): ) self.error_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) - self.error_tree = MaskedTree(ERROR) + self.error_tree = MaskedTree(ICON_ERROR) self.error_placeholder = Placeholder(preconnect.no_errors) self.error_box.add(self.error_tree) self.error_box.add(self.error_placeholder) diff --git a/dzgui/views/pages/servers.py b/dzgui/views/pages/servers.py index caefe21..92090ba 100644 --- a/dzgui/views/pages/servers.py +++ b/dzgui/views/pages/servers.py @@ -5,12 +5,13 @@ from typing import Self, TYPE_CHECKING from dzgui.const.constants import APP_NAME from dzgui.const.enum import ContextMenuGroup, ServerTab from dzgui.views.trees.tree_servers import ServerTreeView +from dzgui.strings.generic import tab_changed_label from dzgui.util.strings import server_labels import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, Gdk, GLib # noqa E402 +from gi.repository import Gtk, Gdk logger = logging.getLogger(APP_NAME) @@ -147,8 +148,7 @@ class ServerNotebook(Gtk.ScrolledWindow): label = self.notebook.get_tab_label_text(child) if label is not None: - # TODO: strings - text = label.strip("*") + text = label.strip(tab_changed_label) self.notebook.set_tab_label_text(child, text) tree = child.get_tree() diff --git a/dzgui/views/pages/thanks.py b/dzgui/views/pages/thanks.py index 4adc39c..88e4256 100644 --- a/dzgui/views/pages/thanks.py +++ b/dzgui/views/pages/thanks.py @@ -8,7 +8,7 @@ from dzgui.views.mixins.scrollable_mixin import ScrollableMixin import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk # TODO: wrap and center long values if TYPE_CHECKING: diff --git a/dzgui/views/trees/tree_log.py b/dzgui/views/trees/tree_log.py index 7f141ef..fd4279d 100644 --- a/dzgui/views/trees/tree_log.py +++ b/dzgui/views/trees/tree_log.py @@ -12,7 +12,7 @@ from dzgui.views.mixins.context_mixin import ContextMixin import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk, GLib, Gdk, GObject, Pango # noqa E402 +from gi.repository import Gtk, Gdk if TYPE_CHECKING: from pathlib import Path diff --git a/pyproject.toml b/pyproject.toml index 65a3d7f..4283cec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,7 @@ line-length = 88 indent-width = 4 extend-exclude = ["*lib/a2s"] lint.unfixable = ["F401", "I001"] +lint.ignore = ["E402"] [tool.ruff.format] quote-style = "double" diff --git a/scripts/unused_imports.py b/scripts/unused_imports.py deleted file mode 100644 index 83498ad..0000000 --- a/scripts/unused_imports.py +++ /dev/null @@ -1,38 +0,0 @@ -from pathlib import Path - - -def iterate(search_str: str) -> None: - # TODO: exclude files from .gitignore - print() - print(f"Searching for '{search_str}'") - print() - files = Path(".").rglob("*") - ignore = [ - "scripts/", - ".git", - "egg", - "CHANGELOG", - ".mypy", - "build/", - "test.py", - "bugs", - "pyproject.toml", - ] - for file in files: - if file.is_dir(): - continue - if any(s in str(file) for s in ignore): - continue - try: - text = file.read_text() - if search_str in text: - c = text.count(search_str) - if 0 < c < 2: - print(file, c) - except Exception: - continue - - -imports = ["Pango", "GObject", "GLib", "Gdk", "Gtk"] -for i in imports: - iterate(i) diff --git a/tests/test_html_escaping.py b/tests/test_html_escaping.py index 904e5b2..2c3c03c 100644 --- a/tests/test_html_escaping.py +++ b/tests/test_html_escaping.py @@ -6,7 +6,7 @@ from dzgui.views.dialogs.servers import ServerDetailsDialog import gi gi.require_version("Gtk", "3.0") -from gi.repository import Gtk # noqa E402 +from gi.repository import Gtk class MockController: diff --git a/tests/test_paused_downloads.py b/tests/test_paused_downloads.py index 86bbb70..1c45ca2 100644 --- a/tests/test_paused_downloads.py +++ b/tests/test_paused_downloads.py @@ -16,7 +16,7 @@ from dzgui.api.steam import is_dayz_downloading (["state_221100_1111"], False), ], ) -def test_dayz_patch_pending(monkeypatch, file_list, expect) -> None: +def test_dayz_patch_pending(monkeypatch, file_list: list[str], expect: bool) -> None: def mock_get_pending_downloads(steam_path: Path, appid: int) -> None: files = [Path(file) for file in file_list] return files