1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-12 23:37:14 +03:00

Merge pull request #2267 from HullSeals/enhancement/748/change-plugin-dir

[748] Allow Custom Plugins Directory
This commit is contained in:
David Sangrey 2024-07-21 23:32:33 -04:00 committed by GitHub
commit 9ddf7aa28a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 120 additions and 50 deletions

View File

@ -845,9 +845,20 @@ class AppWindow:
)
update_msg = update_msg.replace('\\n', '\n')
update_msg = update_msg.replace('\\r', '\r')
stable_popup = tk.messagebox.askyesno(title=title, message=update_msg, parent=postargs.get('Parent'))
stable_popup = tk.messagebox.askyesno(title=title, message=update_msg)
if stable_popup:
webbrowser.open("https://github.com/edCD/eDMarketConnector/releases/latest")
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 restart.')
restart_box = tk.messagebox.Message(
title=tr.tl('Restart Required'), # LANG: Title of Notification Popup for EDMC Restart
message=restart_msg,
type=tk.messagebox.OK
)
restart_box.show()
if restart_box:
app.onexit(restart=True)
def set_labels(self):
"""Set main window labels, e.g. after language change."""
@ -1851,7 +1862,7 @@ class AppWindow:
)
exit_thread.start()
def onexit(self, event=None) -> None:
def onexit(self, event=None, restart: bool = False) -> None:
"""Application shutdown procedure."""
if sys.platform == 'win32':
shutdown_thread = threading.Thread(
@ -1914,6 +1925,8 @@ class AppWindow:
self.w.destroy()
logger.info('Done.')
if restart:
os.execv(sys.executable, ['python'] + sys.argv)
def drag_start(self, event) -> None:
"""Initiate dragging the window."""

View File

@ -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 restart." = "A restart of EDMC is required. EDMC will now restart.";
/* myNotebook.py: Can't Paste Images or Files in Text; */
"Cannot paste non-text content." = "Cannot paste non-text content.";

View File

@ -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."""

View File

@ -31,9 +31,7 @@ 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.plugin_dir_path.mkdir(exist_ok=True)
self.default_plugin_dir_path = self.app_dir_path / 'plugins'
self.respath_path = pathlib.Path(__file__).parent.parent
self.internal_plugin_dir_path = self.respath_path / 'plugins'
@ -62,6 +60,12 @@ class LinuxConfig(AbstractConfig):
self.config.add_section(self.SECTION)
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 (outdir := self.get_str('outdir')) is None or not pathlib.Path(outdir).is_dir():
self.set('outdir', self.home)

View File

@ -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)

View File

@ -239,6 +239,7 @@ class PreferencesDialog(tk.Toplevel):
self.parent = parent
self.callback = callback
self.req_restart = False
# LANG: File > Settings (macOS)
self.title(tr.tl('Settings'))
@ -911,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,
@ -932,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,
@ -1122,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())
@ -1217,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(
@ -1273,20 +1298,30 @@ 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
# Send to the Post Config if we updated the update branch
post_flags = {
'Update': True if self.curr_update_track != self.update_paths.get() else False,
'Track': self.update_paths.get(),
'Parent': self
}
# Notify
if self.callback:
self.callback(**post_flags)
self.callback()
plug.notify_prefs_changed(monitor.cmdr, monitor.is_beta)
self._destroy()
# Send to the Post Config if we updated the update branch or need to restart
post_flags = {
'Update': True if self.curr_update_track != self.update_paths.get() else False,
'Track': self.update_paths.get(),
'Parent': self,
'Restart_Req': True if self.req_restart else False
}
if self.callback:
self.callback(**post_flags)
def _destroy(self) -> None:
"""widget.destroy wrapper that does some extra cleanup."""