From 0299d14902011c9076b3fa9ea0931887a05cdcef Mon Sep 17 00:00:00 2001 From: 0xMRTT <0xMRTT@proton.me> Date: Sat, 13 May 2023 13:04:37 +0200 Subject: [PATCH] feat: allow multiple windows (#22) (#23) --- data/ui/window.blp | 5 ++ po/Bavarder.pot | 18 +++++-- src/main.py | 119 ++++++++++++++++++++++++--------------------- src/window.py | 5 ++ 4 files changed, 89 insertions(+), 58 deletions(-) diff --git a/data/ui/window.blp b/data/ui/window.blp index e6f12c8..f0b78da 100644 --- a/data/ui/window.blp +++ b/data/ui/window.blp @@ -235,6 +235,11 @@ menu main-menu { action: "win.show-help-overlay"; } + item { + label: _("New window"); + action: "app.new"; + } + item { label: _("About Bavarder"); action: "app.about"; diff --git a/po/Bavarder.pot b/po/Bavarder.pot index 0124384..54bfa4d 100644 --- a/po/Bavarder.pot +++ b/po/Bavarder.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-05-12 16:35+0200\n" +"POT-Creation-Date: 2023-05-13 13:03+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -87,11 +87,11 @@ msgid "The prompt will be cleared after send" msgstr "" #: data/ui/preferences.blp:24 -msgid "Use text view" +msgid "Use plain text for output" msgstr "" #: data/ui/preferences.blp:25 -msgid "If the text view is used, you will lose formatting" +msgid "The plain text without formatting will be used" msgstr "" #: data/ui/preferences.blp:34 @@ -135,9 +135,21 @@ msgid "Keyboard Shortcuts" msgstr "" #: data/ui/window.blp:239 +msgid "New window" +msgstr "" + +#: data/ui/window.blp:244 msgid "About Bavarder" msgstr "" +#: src/main.py:262 +msgid "Special thanks to" +msgstr "" + +#: src/main.py:308 +msgid "Text copied" +msgstr "" + #: src/provider/base.py:43 msgid "No API key provided, you can provide one in settings" msgstr "" diff --git a/src/main.py b/src/main.py index 1154413..c2d5dbd 100644 --- a/src/main.py +++ b/src/main.py @@ -34,6 +34,7 @@ from .window import BavarderWindow from .preferences import Preferences from enum import auto, IntEnum +from gettext import gettext as _ from .constants import app_id, version, build_type from tempfile import NamedTemporaryFile @@ -102,6 +103,7 @@ class BavarderApplication(Adw.Application): self.create_action("ask", self.on_ask_action, ["Return"]) self.create_action("clear", self.on_clear_action, ["BackSpace"]) self.create_action("stop", self.on_stop_action, ["Escape"]) + self.create_action("new", self.on_new_window, ["n"]) # self.create_action("speak", self.on_speak_action, ["S"]) # self.create_action("listen", self.on_listen_action, ["L"]) @@ -115,15 +117,6 @@ class BavarderApplication(Adw.Application): ) self.latest_provider = self.settings.get_string("latest-provider") - self.web_view = None - self.web_view_pending_html = None - - self.loading = False - self.shown = False - self.preview_visible = False - - - def quitting(self, *args, **kwargs): """Called before closing main window.""" self.settings.set_strv("enabled-providers", list(self.enabled_providers)) @@ -132,7 +125,37 @@ class BavarderApplication(Adw.Application): print("Saving providers data...") self.save_providers() - self.quit() + self.win.close() + + @property + def win(self): + return self.props.active_window + + def on_new_window(self, action, *args): + self.new_window() + + def new_window(self, window=None): + if window: + win = self.props.active_window + else: + win = BavarderWindow(application=self) + win.connect("close-request", self.quitting) + self.load_dropdown(win) + self.load() + print(self.latest_provider) + for k, p in self.providers.items(): + if p.slug == self.latest_provider: + print("Setting selected provider to", k) + self.win.provider_selector.set_selected(k) + break + + win.web_view = None + win.web_view_pending_html = None + win.loading = False + win.shown = False + win.preview_visible = False + + win.present() def on_quit(self, action, param): """Called when the user activates the Quit action.""" @@ -161,27 +184,13 @@ class BavarderApplication(Adw.Application): We raise the application's main window, creating it if necessary. """ - self.win = self.props.active_window - if not self.win: - self.win = BavarderWindow(application=self) - self.win.present() - - self.win.connect("close-request", self.quitting) - - self.load_dropdown() - - self.load() - - print(self.latest_provider) - for k, p in self.providers.items(): - if p.slug == self.latest_provider: - print("Setting selected provider to", k) - self.win.provider_selector.set_selected(k) - break - + self.new_window() self.win.prompt_text_view.grab_focus() - def load_dropdown(self): + def load_dropdown(self, window=None): + + if window is None: + window = self.win self.provider_selector_model = Gtk.StringList() self.providers = {} @@ -202,12 +211,12 @@ class BavarderApplication(Adw.Application): continue else: try: - _ = self.providers[i] # doesn't re load if already loaded + self.providers[i] # doesn't re load if already loaded except KeyError: - self.providers[i] = PROVIDERS[provider](self.win, self) + self.providers[i] = PROVIDERS[provider](window, self) - self.win.provider_selector.set_model(self.provider_selector_model) - self.win.provider_selector.connect("notify", self.on_provider_selector_notify) + window.provider_selector.set_model(self.provider_selector_model) + window.provider_selector.connect("notify", self.on_provider_selector_notify) def load(self): for p in self.providers.values(): @@ -333,53 +342,53 @@ Providers: {self.enabled_providers} def show(self, html=None, step=Step.LOAD_WEBVIEW): if step == Step.LOAD_WEBVIEW: - self.loading = True - if not self.web_view: - self.web_view = WebKit.WebView() - self.web_view.get_settings().set_allow_universal_access_from_file_urls(True) + self.win.loading = True + if not self.win.web_view: + self.win.web_view = WebKit.WebView() + self.win.web_view.get_settings().set_allow_universal_access_from_file_urls(True) - self.web_view.get_settings().set_enable_developer_extras(True) + self.win.web_view.get_settings().set_enable_developer_extras(True) # Show preview once the load is finished - self.web_view.connect("load-changed", self.on_load_changed) + self.win.web_view.connect("load-changed", self.on_load_changed) # All links will be opened in default browser, but local files are opened in apps. - self.web_view.connect("decide-policy", self.on_click_link) + self.win.web_view.connect("decide-policy", self.on_click_link) - self.web_view.connect("context-menu", self.on_right_click) + self.win.web_view.connect("context-menu", self.on_right_click) - self.web_view.set_hexpand(True) - self.web_view.set_vexpand(True) + self.win.web_view.set_hexpand(True) + self.win.web_view.set_vexpand(True) - self.win.response_stack.add_child(self.web_view) - self.win.response_stack.set_visible_child(self.web_view) + self.win.response_stack.add_child(self.win.web_view) + self.win.response_stack.set_visible_child(self.win.web_view) - if self.web_view.is_loading(): - self.web_view_pending_html = html + if self.win.web_view.is_loading(): + self.win.web_view_pending_html = html else: try: - self.web_view.load_html(html, "file://localhost/") + self.win.web_view.load_html(html, "file://localhost/") except TypeError: # Argument 1 does not allow None as a value pass elif step == Step.RENDER: - if not self.preview_visible: - self.preview_visible = True + if not self.win.preview_visible: + self.win.preview_visible = True self.show() def reload(self, *_widget, reshow=False): - if self.preview_visible: + if self.win.preview_visible: if reshow: self.hide() self.show() def on_load_changed(self, _web_view, event): if event == WebKit.LoadEvent.FINISHED: - self.loading = False - if self.web_view_pending_html: - self.show(html=self.web_view_pending_html, step=Step.LOAD_WEBVIEW) - self.web_view_pending_html = None + self.win.loading = False + if self.win.web_view_pending_html: + self.show(html=self.win.web_view_pending_html, step=Step.LOAD_WEBVIEW) + self.win.web_view_pending_html = None else: # we only lazyload the webview once self.show(step=Step.RENDER) diff --git a/src/window.py b/src/window.py index efc17aa..71d9bef 100644 --- a/src/window.py +++ b/src/window.py @@ -46,6 +46,11 @@ class BavarderWindow(Adw.ApplicationWindow): def __init__(self, **kwargs): super().__init__(**kwargs) + app = kwargs.get('application') + if app is None: + raise ValueError("Application should be passed to ImaginerWindow") + self.app = app + self.settings = Gio.Settings(schema_id="io.github.Bavarder.Bavarder") self.settings.bind(