From 1c45298281fc281fedced302ea27021b1369467c Mon Sep 17 00:00:00 2001 From: ashdriod Date: Sat, 16 Sep 2023 14:10:47 +0200 Subject: [PATCH 1/8] Cosmetic Changes for Pagination --- dtool_lookup_gui/views/main_window.py | 71 ++++++++++++++++----------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/dtool_lookup_gui/views/main_window.py b/dtool_lookup_gui/views/main_window.py index 1c3b598f..5b14aeac 100644 --- a/dtool_lookup_gui/views/main_window.py +++ b/dtool_lookup_gui/views/main_window.py @@ -261,9 +261,14 @@ def __init__(self, *args, **kwargs): _logger.debug(f"Constructed main window for app '{self.application.get_application_id()}'") + + # Initialize pagination parameters, hide page advancer button by default, set default items per page, and highlight the current page button. self.pagination = {} + self.page_advancer_button.set_visible(False) self.contents_per_page_value = 10 - self.login_semaphore = asyncio.Semaphore(1) + style_context = self.curr_page_button.get_style_context() + style_context.add_class('suggested-action') + # utility methods def refresh(self): @@ -381,7 +386,8 @@ async def _fetch_search_results(self, keyword, on_show=None, page_number=1, page self.show_error(e) async def retry(): - await asyncio.sleep(1) + await asyncio.sleep(0.5) + await self._fetch_search_results(keyword, on_show, page_number, page_size, widget) LoginWindow(application=self.application, follow_up_action=lambda: asyncio.create_task(retry())).show() @@ -821,85 +827,93 @@ def on_error_bar_response(self, widget, response_id): @Gtk.Template.Callback() def on_first_page_button_clicked(self, widget): + # Navigate to the first page if results are not currently being fetched if not self.fetching_results: page_number = 1 self.pagination['page'] = page_number self.disable_pagination_buttons() - asyncio.create_task( - self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, - page_size=int(self.contents_per_page_value), widget=widget)) - self.curr_page_button.set_label(str(page_number)) - self.page_advancer_button.set_label(str(page_number - 1)) - self.next_page_advancer_button.set_label(str(page_number + 1)) + asyncio.create_task(self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, + page_size=int(self.contents_per_page_value), widget=widget)) + self.update_pagination_buttons(page_number, widget) @Gtk.Template.Callback() def on_nextoption_page_button_clicked(self, widget): + # Navigate to the next page if available if not self.fetching_results and self.pagination['page'] < self.pagination['last_page']: page_number = self.pagination['page'] + 1 self.update_pagination_buttons(page_number, widget) self.disable_pagination_buttons() - asyncio.create_task( - self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, - page_size=int(self.contents_per_page_value), widget=widget)) + asyncio.create_task(self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, + page_size=int(self.contents_per_page_value), widget=widget)) @Gtk.Template.Callback() def on_last_page_button_clicked(self, widget): + # Navigate to the last page page_number = self.pagination['last_page'] self.update_pagination_buttons(page_number, widget) self.disable_pagination_buttons() - asyncio.create_task( - self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, - page_size=int(self.contents_per_page_value), widget=widget)) + asyncio.create_task(self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, + page_size=int(self.contents_per_page_value), widget=widget)) @Gtk.Template.Callback() def on_prev_page_button_clicked(self, widget): + # Navigate to the previous page if it exists if not self.fetching_results and self.pagination['page'] > 1: - self.pagination['page'] -= 1 - page_number = self.pagination['page'] + page_number = self.pagination['page'] - 1 self.update_pagination_buttons(page_number, widget) self.disable_pagination_buttons() - asyncio.create_task( - self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, - page_size=int(self.contents_per_page_value), widget=widget)) + asyncio.create_task(self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, + page_size=int(self.contents_per_page_value), widget=widget)) @Gtk.Template.Callback() def curr_page_button_clicked(self, widget): + # Highlight the current page button and fetch its results page_number = self.pagination['page'] + style_context = self.curr_page_button.get_style_context() + style_context.add_class('suggested-action') self.update_pagination_buttons(page_number, widget) self.disable_pagination_buttons() - asyncio.create_task( - self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, - page_size=int(self.contents_per_page_value), widget=widget)) + asyncio.create_task(self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, + page_size=int(self.contents_per_page_value), widget=widget)) @Gtk.Template.Callback() def page_advancer_button_clicked(self, widget): + # Navigate to the previous page using the advancer button page_number = self.pagination['page'] if not self.fetching_results and page_number > 1: page_number -= 1 self.update_pagination_buttons(page_number, widget) self.disable_pagination_buttons() - asyncio.create_task( - self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, - page_size=int(self.contents_per_page_value), widget=widget)) + asyncio.create_task(self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, + page_size=int(self.contents_per_page_value), widget=widget)) @Gtk.Template.Callback() def next_page_advancer_button_clicked(self, widget): + # Navigate to the next page using the advancer button page_number = self.pagination['page'] if not self.fetching_results and page_number < self.pagination['last_page']: page_number += 1 self.update_pagination_buttons(page_number, widget) self.disable_pagination_buttons() - asyncio.create_task( - self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, - page_size=int(self.contents_per_page_value), widget=widget)) + asyncio.create_task(self._fetch_search_results(keyword=None, on_show=None, page_number=page_number, + page_size=int(self.contents_per_page_value), widget=widget)) def update_pagination_buttons(self, page_number, widget): + # Update labels and visibility of pagination buttons based on current page self.pagination['page'] = page_number self.curr_page_button.set_label(str(page_number)) self.page_advancer_button.set_label(str(page_number - 1)) self.next_page_advancer_button.set_label(str(page_number + 1)) + # Hide next_page_advancer_button if current page is the last page or beyond + if page_number >= self.pagination['last_page']: + self.next_page_advancer_button.set_visible(False) + else: + self.next_page_advancer_button.set_visible(True) + self.page_advancer_button.set_visible(page_number != 1) + def disable_pagination_buttons(self): + # Disable all pagination buttons (typically while fetching results) self.fetching_results = True self.first_page_button.set_sensitive(False) self.nextoption_page_button.set_sensitive(False) @@ -910,6 +924,7 @@ def disable_pagination_buttons(self): self.next_page_advancer_button.set_sensitive(False) def enable_pagination_buttons(self): + # Enable all pagination buttons (typically after fetching results) self.fetching_results = False self.first_page_button.set_sensitive(True) self.nextoption_page_button.set_sensitive(True) From 3f3033de68f17223a14c61320fb34eb8a769cf7d Mon Sep 17 00:00:00 2001 From: ashdriod Date: Sun, 17 Sep 2023 03:52:25 +0200 Subject: [PATCH 2/8] Cosmetic Changes - Test Login Window Removed --- dtool_lookup_gui/views/main_window.py | 6 +----- dtool_lookup_gui/views/main_window.ui | 13 +------------ 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/dtool_lookup_gui/views/main_window.py b/dtool_lookup_gui/views/main_window.py index 5b14aeac..ba2959c0 100644 --- a/dtool_lookup_gui/views/main_window.py +++ b/dtool_lookup_gui/views/main_window.py @@ -170,7 +170,7 @@ class MainWindow(Gtk.ApplicationWindow): main_statusbar = Gtk.Template.Child() contents_per_page = Gtk.Template.Child() - test_login = Gtk.Template.Child() + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -584,10 +584,6 @@ def on_settings_clicked(self, widget): def version_button_clicked(self, widget): self.server_versions_dialog.show() - @Gtk.Template.Callback() - def on_test_login_clicked(self, widget): - self.login_window.show() - @Gtk.Template.Callback() def on_logging_clicked(self, widget): self.log_window.show() diff --git a/dtool_lookup_gui/views/main_window.ui b/dtool_lookup_gui/views/main_window.ui index 8f7f232e..b18e456c 100644 --- a/dtool_lookup_gui/views/main_window.ui +++ b/dtool_lookup_gui/views/main_window.ui @@ -74,18 +74,7 @@ - - True - True - True - Test Login - - - - False - True - 4 - + From 614e986ec42797ab09bf7a0c7096d968b1a1d68f Mon Sep 17 00:00:00 2001 From: ashdriod Date: Sun, 17 Sep 2023 13:01:29 +0200 Subject: [PATCH 3/8] Config WIP --- dtool_lookup_gui/views/config_details.py | 48 ++++++++++++++ dtool_lookup_gui/views/config_details.ui | 82 ++++++++++++++++++++++++ dtool_lookup_gui/views/main_window.py | 9 ++- dtool_lookup_gui/views/main_window.ui | 13 +++- 4 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 dtool_lookup_gui/views/config_details.py create mode 100644 dtool_lookup_gui/views/config_details.ui diff --git a/dtool_lookup_gui/views/config_details.py b/dtool_lookup_gui/views/config_details.py new file mode 100644 index 00000000..872458b1 --- /dev/null +++ b/dtool_lookup_gui/views/config_details.py @@ -0,0 +1,48 @@ +import asyncio +import logging +import os +import gi + +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +from dtool_lookup_api.asynchronous import config +from ..utils.logging import _log_nested + +# Set up logger for this module +logger = logging.getLogger(__name__) + +@Gtk.Template(filename=f'{os.path.dirname(__file__)}/config_details.ui') +class ConfigDialog(Gtk.Window): + __gtype_name__ = 'ConfigDialog' + config_label = Gtk.Template.Child() + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Apply margins to the config label for better aesthetics + self.config_label.set_margin_start(10) + self.config_label.set_margin_end(10) + self.config_label.set_margin_top(10) + self.config_label.set_margin_bottom(10) + + async def _retrieve_config(self): + """Asynchronously fetch server configuration and update the label with the first key-value pair.""" + server_config = await config() + config_info = self._format_server_config(server_config) + _log_nested(logger.info, config_info) + self.config_label.set_markup(config_info) + + def _format_server_config(self, server_config): + """Format the first key-value pair from the server configuration.""" + first_key = next(iter(server_config)) + return f"{first_key}: {server_config[first_key]}" + + @Gtk.Template.Callback() + def on_config_show(self, widget): + """Callback executed when the window is shown; fetches server config.""" + asyncio.create_task(self._retrieve_config()) + + @Gtk.Template.Callback() + def on_config_delete(self, widget, event): + """Callback executed when window close event is triggered; hides the window instead of deleting.""" + return self.hide_on_delete() diff --git a/dtool_lookup_gui/views/config_details.ui b/dtool_lookup_gui/views/config_details.ui new file mode 100644 index 00000000..3dccbf2c --- /dev/null +++ b/dtool_lookup_gui/views/config_details.ui @@ -0,0 +1,82 @@ + + + + + + diff --git a/dtool_lookup_gui/views/main_window.py b/dtool_lookup_gui/views/main_window.py index ba2959c0..8981294e 100644 --- a/dtool_lookup_gui/views/main_window.py +++ b/dtool_lookup_gui/views/main_window.py @@ -61,6 +61,7 @@ from .about_dialog import AboutDialog from .settings_dialog import SettingsDialog from .server_versions_dialog import ServerVersionsDialog +from .config_details import ConfigDialog from .login_window import LoginWindow from .log_window import LogWindow @@ -155,6 +156,7 @@ class MainWindow(Gtk.ApplicationWindow): settings_button = Gtk.Template.Child() version_button = Gtk.Template.Child() + config_button = Gtk.Template.Child() error_bar = Gtk.Template.Child() error_label = Gtk.Template.Child() @@ -202,8 +204,7 @@ def __init__(self, *args, **kwargs): self.log_window = LogWindow(application=self.application) self.settings_dialog = SettingsDialog(application=self.application) self.about_dialog = AboutDialog(application=self.application) - - # demo_server_versions = 1 + self.config_details = ConfigDialog(application=self.application) self.server_versions_dialog = ServerVersionsDialog(application=self.application) # self.login_window = LoginWindow(application=self.application) # window-scoped actions @@ -584,6 +585,10 @@ def on_settings_clicked(self, widget): def version_button_clicked(self, widget): self.server_versions_dialog.show() + @Gtk.Template.Callback() + def config_button_clicked(self, widget): + self.config_details.show() + @Gtk.Template.Callback() def on_logging_clicked(self, widget): self.log_window.show() diff --git a/dtool_lookup_gui/views/main_window.ui b/dtool_lookup_gui/views/main_window.ui index b18e456c..00fa2bf3 100644 --- a/dtool_lookup_gui/views/main_window.ui +++ b/dtool_lookup_gui/views/main_window.ui @@ -74,7 +74,18 @@ - + + True + True + True + Config Details + + + + False + True + 4 + From 39a917df8d276169ea1b0259b16241b0e20a6c40 Mon Sep 17 00:00:00 2001 From: ashdriod Date: Sun, 17 Sep 2023 14:22:57 +0200 Subject: [PATCH 4/8] Config WIP --- dtool_lookup_gui/views/config_details.py | 21 ++++++++----------- dtool_lookup_gui/views/config_details.ui | 26 ++++++++++++++++-------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/dtool_lookup_gui/views/config_details.py b/dtool_lookup_gui/views/config_details.py index 872458b1..7d1266c4 100644 --- a/dtool_lookup_gui/views/config_details.py +++ b/dtool_lookup_gui/views/config_details.py @@ -1,6 +1,7 @@ import asyncio import logging import os +import json import gi gi.require_version('Gtk', '3.0') @@ -11,31 +12,26 @@ # Set up logger for this module logger = logging.getLogger(__name__) + @Gtk.Template(filename=f'{os.path.dirname(__file__)}/config_details.ui') class ConfigDialog(Gtk.Window): __gtype_name__ = 'ConfigDialog' - config_label = Gtk.Template.Child() + config_text_view = Gtk.Template.Child() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # Apply margins to the config label for better aesthetics - self.config_label.set_margin_start(10) - self.config_label.set_margin_end(10) - self.config_label.set_margin_top(10) - self.config_label.set_margin_bottom(10) - async def _retrieve_config(self): - """Asynchronously fetch server configuration and update the label with the first key-value pair.""" + """Asynchronously fetch server configuration and update the text view.""" server_config = await config() config_info = self._format_server_config(server_config) _log_nested(logger.info, config_info) - self.config_label.set_markup(config_info) + buffer = self.config_text_view.get_buffer() + buffer.set_text(config_info) def _format_server_config(self, server_config): - """Format the first key-value pair from the server configuration.""" - first_key = next(iter(server_config)) - return f"{first_key}: {server_config[first_key]}" + """Format the server configuration into a string representation.""" + return json.dumps(server_config, indent=4) @Gtk.Template.Callback() def on_config_show(self, widget): @@ -46,3 +42,4 @@ def on_config_show(self, widget): def on_config_delete(self, widget, event): """Callback executed when window close event is triggered; hides the window instead of deleting.""" return self.hide_on_delete() + diff --git a/dtool_lookup_gui/views/config_details.ui b/dtool_lookup_gui/views/config_details.ui index 3dccbf2c..7a19d61d 100644 --- a/dtool_lookup_gui/views/config_details.ui +++ b/dtool_lookup_gui/views/config_details.ui @@ -3,8 +3,10 @@