From 86b5556efbd41cb7bed0233dba40d580d1466480 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Tue, 25 Jun 2024 11:25:05 -0400 Subject: [PATCH] [748] Enable Plugin Change w/ App Restart --- EDMarketConnector.py | 3 +- L10n/en.template | 14 +++++++-- config/__init__.py | 6 ++++ config/linux.py | 6 +++- config/windows.py | 34 ++++++++++++---------- prefs.py | 69 ++++++++++++++++++++++++++++++++------------ 6 files changed, 93 insertions(+), 39 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 2582f570..390841cc 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -849,9 +849,10 @@ class AppWindow: if stable_popup: webbrowser.open("https://github.com/edCD/eDMarketConnector/releases/latest") if postargs.get('Restart_Req'): + # LANG: Text of Notification Popup for EDMC Restart restart_msg = tr.tl('A restart of EDMC is required. EDMC will now shut down.') restart_box = tk.messagebox.Message( - title=tr.tl('Restart Required'), + title=tr.tl('Restart Required'), # LANG: Title of Notification Popup for EDMC Restart message=restart_msg, type=tk.messagebox.OK ) diff --git a/L10n/en.template b/L10n/en.template index 1c1e110f..a7b3ec29 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -468,8 +468,11 @@ /* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */ "Plugins folder" = "Plugins folder"; -/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */ -"Open" = "Open"; +/* prefs.py: Label on button used to open the Plugin Folder; */ +"Open Plugins Folder" = "Open Plugins Folder"; + +/* prefs.py: Selecting the Location of the Plugin Directory on the Filesystem; */ +"Plugin Directory Location" = "Plugin Directory Location"; /* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */ "Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name"; @@ -804,10 +807,15 @@ /* EDMarketConnector.py: Inform the user the Update Track has changed; */ "Update Track Changed to {TRACK}" = "Update Track Changed to {TRACK}"; - /* EDMarketConnector.py: Inform User of Beta -> Stable Transition Risks; */ "Update track changed to Stable from Beta. You will no longer receive Beta updates. You will stay on your current Beta version until the next Stable release.\r\n\r\nYou can manually revert to the latest Stable version. To do so, you must download and install the latest Stable version manually. Note that this may introduce bugs or break completely if downgrading between major versions with significant changes.\r\n\r\nDo you want to open GitHub to download the latest release?" = "Update track changed to Stable from Beta. You will no longer receive Beta updates. You will stay on your current Beta version until the next Stable release.\r\n\r\nYou can manually revert to the latest Stable version. To do so, you must download and install the latest Stable version manually. Note that this may introduce bugs or break completely if downgrading between major versions with significant changes.\r\n\r\nDo you want to open GitHub to download the latest release?"; +/* EDMarketConnector.py: Title of Notification Popup for EDMC Restart; */ +"Restart Required" = "Restart Required"; + +/* EDMarketConnector.py: Text of Notification Popup for EDMC Restart; */ +"A restart of EDMC is required. EDMC will now shut down." = "A restart of EDMC is required. EDMC will now shut down."; + /* myNotebook.py: Can't Paste Images or Files in Text; */ "Cannot paste non-text content." = "Cannot paste non-text content."; diff --git a/config/__init__.py b/config/__init__.py index 8dfcf46b..9a00b9a9 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -189,6 +189,7 @@ class AbstractConfig(abc.ABC): app_dir_path: pathlib.Path plugin_dir_path: pathlib.Path + default_plugin_dir_path: pathlib.Path internal_plugin_dir_path: pathlib.Path respath_path: pathlib.Path home_path: pathlib.Path @@ -279,6 +280,11 @@ class AbstractConfig(abc.ABC): """Return a string version of plugin_dir.""" return str(self.plugin_dir_path) + @property + def default_plugin_dir(self) -> str: + """Return a string version of plugin_dir.""" + return str(self.default_plugin_dir_path) + @property def internal_plugin_dir(self) -> str: """Return a string version of internal_plugin_dir.""" diff --git a/config/linux.py b/config/linux.py index 51a40626..5900fe98 100644 --- a/config/linux.py +++ b/config/linux.py @@ -31,7 +31,11 @@ class LinuxConfig(AbstractConfig): self.app_dir_path = xdg_data_home / appname self.app_dir_path.mkdir(exist_ok=True, parents=True) - self.plugin_dir_path = self.app_dir_path / 'plugins' + self.default_plugin_dir_path = self.app_dir_path / 'plugins' + if (plugdir_str := self.get_str('plugin_dir')) is None or not pathlib.Path(plugdir_str).is_dir(): + self.set("plugin_dir", str(self.default_plugin_dir_path)) + plugdir_str = self.default_plugin_dir + self.plugin_dir_path = pathlib.Path(plugdir_str) self.plugin_dir_path.mkdir(exist_ok=True) self.respath_path = pathlib.Path(__file__).parent.parent diff --git a/config/windows.py b/config/windows.py index 75e3f697..c0d25b71 100644 --- a/config/windows.py +++ b/config/windows.py @@ -49,10 +49,28 @@ class WinConfig(AbstractConfig): def __init__(self) -> None: super().__init__() + REGISTRY_SUBKEY = r'Software\Marginal\EDMarketConnector' # noqa: N806 + create_key_defaults = functools.partial( + winreg.CreateKeyEx, + key=winreg.HKEY_CURRENT_USER, + access=winreg.KEY_ALL_ACCESS | winreg.KEY_WOW64_64KEY, + ) + + try: + self.__reg_handle: winreg.HKEYType = create_key_defaults(sub_key=REGISTRY_SUBKEY) + + except OSError: + logger.exception('Could not create required registry keys') + raise + self.app_dir_path = pathlib.Path(known_folder_path(FOLDERID_LocalAppData)) / appname # type: ignore self.app_dir_path.mkdir(exist_ok=True) - self.plugin_dir_path = self.app_dir_path / 'plugins' + self.default_plugin_dir_path = self.app_dir_path / 'plugins' + if (plugdir_str := self.get_str('plugin_dir')) is None or not pathlib.Path(plugdir_str).is_dir(): + self.set("plugin_dir", str(self.default_plugin_dir_path)) + plugdir_str = self.default_plugin_dir + self.plugin_dir_path = pathlib.Path(plugdir_str) self.plugin_dir_path.mkdir(exist_ok=True) if getattr(sys, 'frozen', False): @@ -68,20 +86,6 @@ class WinConfig(AbstractConfig): known_folder_path(FOLDERID_SavedGames)) / 'Frontier Developments' / 'Elite Dangerous' # type: ignore self.default_journal_dir_path = journal_dir_path if journal_dir_path.is_dir() else None # type: ignore - REGISTRY_SUBKEY = r'Software\Marginal\EDMarketConnector' # noqa: N806 - create_key_defaults = functools.partial( - winreg.CreateKeyEx, - key=winreg.HKEY_CURRENT_USER, - access=winreg.KEY_ALL_ACCESS | winreg.KEY_WOW64_64KEY, - ) - - try: - self.__reg_handle: winreg.HKEYType = create_key_defaults(sub_key=REGISTRY_SUBKEY) - - except OSError: - logger.exception('Could not create required registry keys') - raise - self.identifier = applongname if (outdir_str := self.get_str('outdir')) is None or not pathlib.Path(outdir_str).is_dir(): docs = known_folder_path(FOLDERID_Documents) diff --git a/prefs.py b/prefs.py index dffe71b9..be989601 100644 --- a/prefs.py +++ b/prefs.py @@ -912,20 +912,15 @@ class PreferencesDialog(tk.Toplevel): # Plugin settings and info plugins_frame = nb.Frame(notebook) plugins_frame.columnconfigure(0, weight=1) - plugdir = tk.StringVar() - plugdir.set(config.plugin_dir) row = AutoInc(start=0) - - # Section heading in settings + self.plugdir = tk.StringVar() + self.plugdir.set(str(config.get_str('plugin_dir'))) # LANG: Label for location of third-party plugins folder - nb.Label(plugins_frame, text=tr.tl('Plugins folder') + ':').grid( - padx=self.PADX, pady=self.PADY, sticky=tk.W, row=row.get() - ) - - plugdirentry = ttk.Entry(plugins_frame, justify=tk.LEFT) - self.displaypath(plugdir, plugdirentry) - plugdirentry.grid(columnspan=2, padx=self.PADX, pady=self.BOXY, sticky=tk.EW, row=row.get()) - + self.plugdir_label = nb.Label(plugins_frame, text=tr.tl('Plugins folder') + ':') + self.plugdir_label.grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, row=row.get()) + self.plugdir_entry = ttk.Entry(plugins_frame, takefocus=False, + textvariable=self.plugdir) # Link StringVar to Entry widget + self.plugdir_entry.grid(columnspan=4, padx=self.PADX, pady=self.BOXY, sticky=tk.EW, row=row.get()) with row as cur_row: nb.Label( plugins_frame, @@ -933,19 +928,41 @@ class PreferencesDialog(tk.Toplevel): # LANG: Tip/label about how to disable plugins text=tr.tl( "Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name").format(EXT='.disabled') - ).grid(columnspan=2, padx=self.PADX, pady=self.PADY, sticky=tk.EW, row=cur_row) + ).grid(columnspan=1, padx=self.PADX, pady=self.PADY, sticky=tk.EW, row=cur_row) - ttk.Button( + # Open Plugin Folder Button + self.open_plug_folder_btn = ttk.Button( plugins_frame, - # LANG: Label on button used to open a filesystem folder - text=tr.tl('Open'), # Button that opens a folder in Explorer/Finder + # LANG: Label on button used to open the Plugin Folder + text=tr.tl('Open Plugins Folder'), command=lambda: open_folder(config.plugin_dir_path) - ).grid(column=1, padx=self.PADX, pady=self.PADY, sticky=tk.N, row=cur_row) + ) + self.open_plug_folder_btn.grid(column=1, padx=self.PADX, pady=self.PADY, sticky=tk.EW, row=cur_row) + + # Browse Button + text = tr.tl('Browse...') # LANG: NOT-macOS Settings - files location selection button + self.plugbutton = ttk.Button( + plugins_frame, + text=text, + # LANG: Selecting the Location of the Plugin Directory on the Filesystem + command=lambda: self.filebrowse(tr.tl('Plugin Directory Location'), self.plugdir) + ) + self.plugbutton.grid(column=2, padx=self.PADX, pady=self.PADY, sticky=tk.EW, row=cur_row) + + if config.default_journal_dir_path: + # Appearance theme and language setting + ttk.Button( + plugins_frame, + # LANG: Settings > Configuration - Label on 'reset journal files location to default' button + text=tr.tl('Default'), + command=self.plugdir_reset, + state=tk.NORMAL if config.get_str('plugin_dir') else tk.DISABLED + ).grid(column=3, padx=self.PADX, pady=self.PADY, sticky=tk.EW, row=cur_row) enabled_plugins = list(filter(lambda x: x.folder and x.module, plug.PLUGINS)) if enabled_plugins: ttk.Separator(plugins_frame, orient=tk.HORIZONTAL).grid( - columnspan=3, padx=self.PADX, pady=self.SEPY, sticky=tk.EW, row=row.get() + columnspan=4, padx=self.PADX, pady=self.SEPY, sticky=tk.EW, row=row.get() ) nb.Label( plugins_frame, @@ -1123,6 +1140,13 @@ class PreferencesDialog(tk.Toplevel): self.outvarchanged() + def plugdir_reset(self) -> None: + """Reset the log dir to the default.""" + if config.default_plugin_dir_path: + self.plugdir.set(config.default_plugin_dir) + + self.outvarchanged() + def disable_autoappupdatecheckingame_changed(self) -> None: """Save out the auto update check in game config.""" config.set('disable_autoappupdatecheckingame', self.disable_autoappupdatecheckingame.get()) @@ -1218,7 +1242,7 @@ class PreferencesDialog(tk.Toplevel): return 'break' # stops further processing - insertion, Tab traversal etc - def apply(self) -> None: + def apply(self) -> None: # noqa: CCR001 """Update the config with the options set on the dialog.""" config.set('PrefsVersion', prefsVersion.stringToSerial(appversion_nobuild())) config.set( @@ -1274,6 +1298,13 @@ class PreferencesDialog(tk.Toplevel): config.set('dark_text', self.theme_colors[0]) config.set('dark_highlight', self.theme_colors[1]) theme.apply(self.parent) + if self.plugdir.get() != config.get('plugin_dir'): + config.set( + 'plugin_dir', + join(config.home_path, self.plugdir.get()[2:]) if self.plugdir.get().startswith( + '~') else self.plugdir.get() + ) + self.req_restart = True # Notify if self.callback: