feat: allow multiple windows (#22) (#23)

This commit is contained in:
2023-05-13 13:04:37 +02:00
parent 020d6b84b3
commit 0299d14902
4 changed files with 89 additions and 58 deletions

View File

@@ -235,6 +235,11 @@ menu main-menu {
action: "win.show-help-overlay"; action: "win.show-help-overlay";
} }
item {
label: _("New window");
action: "app.new";
}
item { item {
label: _("About Bavarder"); label: _("About Bavarder");
action: "app.about"; action: "app.about";

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -87,11 +87,11 @@ msgid "The prompt will be cleared after send"
msgstr "" msgstr ""
#: data/ui/preferences.blp:24 #: data/ui/preferences.blp:24
msgid "Use text view" msgid "Use plain text for output"
msgstr "" msgstr ""
#: data/ui/preferences.blp:25 #: 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 "" msgstr ""
#: data/ui/preferences.blp:34 #: data/ui/preferences.blp:34
@@ -135,9 +135,21 @@ msgid "Keyboard Shortcuts"
msgstr "" msgstr ""
#: data/ui/window.blp:239 #: data/ui/window.blp:239
msgid "New window"
msgstr ""
#: data/ui/window.blp:244
msgid "About Bavarder" msgid "About Bavarder"
msgstr "" msgstr ""
#: src/main.py:262
msgid "Special thanks to"
msgstr ""
#: src/main.py:308
msgid "Text copied"
msgstr ""
#: src/provider/base.py:43 #: src/provider/base.py:43
msgid "No API key provided, you can provide one in settings" msgid "No API key provided, you can provide one in settings"
msgstr "" msgstr ""

View File

@@ -34,6 +34,7 @@ from .window import BavarderWindow
from .preferences import Preferences from .preferences import Preferences
from enum import auto, IntEnum from enum import auto, IntEnum
from gettext import gettext as _
from .constants import app_id, version, build_type from .constants import app_id, version, build_type
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
@@ -102,6 +103,7 @@ class BavarderApplication(Adw.Application):
self.create_action("ask", self.on_ask_action, ["<primary>Return"]) self.create_action("ask", self.on_ask_action, ["<primary>Return"])
self.create_action("clear", self.on_clear_action, ["<primary><shift>BackSpace"]) self.create_action("clear", self.on_clear_action, ["<primary><shift>BackSpace"])
self.create_action("stop", self.on_stop_action, ["<primary>Escape"]) self.create_action("stop", self.on_stop_action, ["<primary>Escape"])
self.create_action("new", self.on_new_window, ["<primary>n"])
# self.create_action("speak", self.on_speak_action, ["<primary>S"]) # self.create_action("speak", self.on_speak_action, ["<primary>S"])
# self.create_action("listen", self.on_listen_action, ["<primary>L"]) # self.create_action("listen", self.on_listen_action, ["<primary>L"])
@@ -115,15 +117,6 @@ class BavarderApplication(Adw.Application):
) )
self.latest_provider = self.settings.get_string("latest-provider") 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): def quitting(self, *args, **kwargs):
"""Called before closing main window.""" """Called before closing main window."""
self.settings.set_strv("enabled-providers", list(self.enabled_providers)) self.settings.set_strv("enabled-providers", list(self.enabled_providers))
@@ -132,7 +125,37 @@ class BavarderApplication(Adw.Application):
print("Saving providers data...") print("Saving providers data...")
self.save_providers() 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): def on_quit(self, action, param):
"""Called when the user activates the Quit action.""" """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 We raise the application's main window, creating it if
necessary. necessary.
""" """
self.win = self.props.active_window self.new_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.win.prompt_text_view.grab_focus() 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.provider_selector_model = Gtk.StringList()
self.providers = {} self.providers = {}
@@ -202,12 +211,12 @@ class BavarderApplication(Adw.Application):
continue continue
else: else:
try: try:
_ = self.providers[i] # doesn't re load if already loaded self.providers[i] # doesn't re load if already loaded
except KeyError: 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) window.provider_selector.set_model(self.provider_selector_model)
self.win.provider_selector.connect("notify", self.on_provider_selector_notify) window.provider_selector.connect("notify", self.on_provider_selector_notify)
def load(self): def load(self):
for p in self.providers.values(): for p in self.providers.values():
@@ -333,53 +342,53 @@ Providers: {self.enabled_providers}
def show(self, html=None, step=Step.LOAD_WEBVIEW): def show(self, html=None, step=Step.LOAD_WEBVIEW):
if step == Step.LOAD_WEBVIEW: if step == Step.LOAD_WEBVIEW:
self.loading = True self.win.loading = True
if not self.web_view: if not self.win.web_view:
self.web_view = WebKit.WebView() self.win.web_view = WebKit.WebView()
self.web_view.get_settings().set_allow_universal_access_from_file_urls(True) 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 # 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. # 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.win.web_view.set_hexpand(True)
self.web_view.set_vexpand(True) self.win.web_view.set_vexpand(True)
self.win.response_stack.add_child(self.web_view) self.win.response_stack.add_child(self.win.web_view)
self.win.response_stack.set_visible_child(self.web_view) self.win.response_stack.set_visible_child(self.win.web_view)
if self.web_view.is_loading(): if self.win.web_view.is_loading():
self.web_view_pending_html = html self.win.web_view_pending_html = html
else: else:
try: 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 except TypeError: # Argument 1 does not allow None as a value
pass pass
elif step == Step.RENDER: elif step == Step.RENDER:
if not self.preview_visible: if not self.win.preview_visible:
self.preview_visible = True self.win.preview_visible = True
self.show() self.show()
def reload(self, *_widget, reshow=False): def reload(self, *_widget, reshow=False):
if self.preview_visible: if self.win.preview_visible:
if reshow: if reshow:
self.hide() self.hide()
self.show() self.show()
def on_load_changed(self, _web_view, event): def on_load_changed(self, _web_view, event):
if event == WebKit.LoadEvent.FINISHED: if event == WebKit.LoadEvent.FINISHED:
self.loading = False self.win.loading = False
if self.web_view_pending_html: if self.win.web_view_pending_html:
self.show(html=self.web_view_pending_html, step=Step.LOAD_WEBVIEW) self.show(html=self.win.web_view_pending_html, step=Step.LOAD_WEBVIEW)
self.web_view_pending_html = None self.win.web_view_pending_html = None
else: else:
# we only lazyload the webview once # we only lazyload the webview once
self.show(step=Step.RENDER) self.show(step=Step.RENDER)

View File

@@ -46,6 +46,11 @@ class BavarderWindow(Adw.ApplicationWindow):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**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 = Gio.Settings(schema_id="io.github.Bavarder.Bavarder")
self.settings.bind( self.settings.bind(