From 7cf03c4de5244e7db3f44362a275f92368fd86ac Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sun, 8 Jan 2023 14:08:38 +0100 Subject: moved desktop widgets to windows --- tagit/windows/desktop.kv | 136 +++++++++++++++++++++++++ tagit/windows/desktop.py | 258 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 394 insertions(+) create mode 100644 tagit/windows/desktop.kv create mode 100644 tagit/windows/desktop.py (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.kv b/tagit/windows/desktop.kv new file mode 100644 index 0000000..cbc5c48 --- /dev/null +++ b/tagit/windows/desktop.kv @@ -0,0 +1,136 @@ +#:import TileDecorationBorder tagit.tiles.decoration.TileDecorationBorder +#:import TileDecorationFilledRectangle tagit.tiles.decoration.TileDecorationFilledRectangle + +# DEBUG: Draw borders around all widgets +#: +# canvas.after: +# Line: +# rectangle: self.x+1,self.y+1,self.width-1,self.height-1 +# dash_offset: 5 +# dash_length: 3 + +: + # main content + # required by most tiles and actions + browser: browser + filter: filter + status: status + # required by actions.planes + planes: planes + # required by Menu + context: context + + Carousel: + id: planes + loop: True + scroll_timeout: 0 # disables switching by touch event + # plane references + dashboard: dashboard + browsing: browsing + codash: codash + + # planes + + TileDock: # static dashboard plane + id: dashboard + root: root + # plane config + size_hint: 1, 1 + visible: planes.current_slide == self + # dock config + name: 'dashboard' + decoration: TileDecorationBorder + cols: 3 + rows: 2 + # self.size won't be updated correctly + tile_width: self.width / self.cols + tile_height: self.height / self.rows + + BoxLayout: # browsing plane + id: browsing + orientation: 'horizontal' + visible: planes.current_slide == self + + ButtonDock: # one column of buttons on the left + root: root + orientation: 'tb-lr' + # one column of buttons + width: 30 + 2*10 + name: 'sidebar_left' + spacing: 10 + padding: 10 + size_hint: None, 1 + button_height: 30 + button_show: 'image', + + BoxLayout: # main content + orientation: 'vertical' + size_hint: 1, 1 + + BoxLayout: + orientation: 'horizontal' + size_hint: 1, 1 + current: 0 + + BoxLayout: + orientation: 'vertical' + size_hint: 1, 1 + + Filter: + id: filter + root: root + size_hint: 1, None + height: 30 + + Browser: + id: browser + root: root + size_hint: 1, 0.96 + + Status: + id: status + root: root + size_hint: 1, None + height: 30 + + TileDock: # context info to the right + root: root + visible: planes.current_slide == self.parent + name: 'sidebar_right' + decoration: TileDecorationFilledRectangle + cols: 1 + rows: 3 + # self.height won't be updated correctly + #tile_height: self.size[1] / 4 + width: 180 + size_hint: None, 1 + + TileDock: # contextual dashboard + id: codash + root: root + # plane config + size_hint: 1, 1 + visible: planes.current_slide == self + # dock config + name: 'codash' + decoration: TileDecorationBorder + cols: 4 + rows: 2 + # self.size won't be update correctly + tile_width: self.width / 4 + tile_height: self.height / 2 + + Context: # context menu + id: context + root: root + cancel_handler_widget: root + bounding_box_widget: root + name: 'context' + + KeybindDock: + # key-only actions + root: root + size_hint: None, None + size: 0, 0 + +## EOF ## diff --git a/tagit/windows/desktop.py b/tagit/windows/desktop.py new file mode 100644 index 0000000..5128454 --- /dev/null +++ b/tagit/windows/desktop.py @@ -0,0 +1,258 @@ +"""Main container of the tagit UI. + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 + +""" +# standard imports +import logging +import os +import typing + +# kivy imports +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.uix.floatlayout import FloatLayout +import kivy.properties as kp + +# import Image and Loader to overwrite their caches later on +from kivy.loader import Loader +from kivy.cache import Cache + +# tagit imports +from tagit import actions, config, dialogues +from tagit.widgets.browser import Browser +from tagit.widgets.context import Context +from tagit.widgets.dock import TileDock, ButtonDock, KeybindDock +from tagit.widgets.filter import Filter +from tagit.widgets.keyboard import Keyboard +from tagit.widgets.session import Session +from tagit.widgets.status import Status + +# exports +__all__: typing.Sequence[str] = ( + 'KIVY_IMAGE_CACHE_SIZE', + 'KIVY_IMAGE_CACHE_TIMEOUT', + 'MainWindow', + ) + + +## code ## + +logger = logging.getLogger(__name__) + +# load kv +Builder.load_file(os.path.join(os.path.dirname(__file__), 'desktop.kv')) + +# classes +class MainWindow(FloatLayout): + """A self-contained user interface for desktop usage. + See `tagit.apps.gui` for an example of how to invoke it. + """ + + keys = kp.ObjectProperty(None) + + # unnecessary but nicely explicit + browser = kp.ObjectProperty(None) + filter = kp.ObjectProperty(None) + keytriggers = kp.ObjectProperty(None) + + # FIXME: log actions and and replay them + action_log = kp.ListProperty() + + def __init__ (self, cfg, stor, log, **kwargs): + # initialize the session + self._session = Session(cfg, stor, log) + # initialize key-only actions + self.keys = Keyboard() + + # initialize the cache + cache_size = max(0, cfg('ui', 'standalone', 'browser', 'cache_size')) + cache_size = cache_size if cache_size > 0 else None + cache_timeout = max(0, cfg('ui', 'standalone', 'browser', 'cache_timeout')) + cache_timeout = cache_timeout if cache_timeout > 0 else None + Cache.register('kv.loader', limit=cache_size, timeout=cache_timeout) + + # initialize the widget + super(MainWindow, self).__init__(**kwargs) + + # bind pre-close checks + from kivy.core.window import Window + Window.bind(on_request_close=self.on_request_close) + + + ## properties + + @property + def session(self): + return self._session + + def trigger(self, action, *args, **kwargs): + """Trigger an action once.""" + actions.ActionBuilder().get(action).single_shot(self, *args, **kwargs) + + + ## functions + + def autoindex(self, *args): + self.trigger('AutoImport') + + def autoupdate(self, *args): + self.trigger('AutoUpdate') + + def autosync(self, *args): + self.trigger('AutoSync') + + def autosave(self, *args): + if not self.session.storage.file_connected(): + return + + try: + self.trigger('SaveLibrary') + logger.info('Database: Autosaved') + except Exception as e: + logger.error(f'Database: Autosave failed ({e})') + + + ## startup and shutdown + + def on_startup(self): + # start autosave + autosave = self.session.cfg('storage', 'library', 'autosave') + if autosave > 0: + # autosave is in minutes + Clock.schedule_interval(self.autosave, autosave * 60) + + # start index + autoindex = self.session.cfg('storage', 'index', 'autoindex') + autoindex = 0 if autoindex == float('inf') else autoindex + if autoindex > 0: + # autoindex is in minutes + Clock.schedule_interval(self.autoindex, autoindex * 60) + + # start update + autoupdate = self.session.cfg('storage', 'index', 'autoupdate') + autoupdate = 0 if autoupdate == float('inf') else autoupdate + if autoupdate > 0: + # autoupdate is in minutes + Clock.schedule_interval(self.autoupdate, autoupdate * 60) + + # start sync + autosync = self.session.cfg('storage', 'index', 'autosync') + autosync = 0 if autosync == float('inf') else autosync + if autosync > 0: + # autosync is in minutes + Clock.schedule_interval(self.autosync, autosync * 60) + + # trigger operations on startup + if self.session.cfg('storage', 'index', 'index_on_startup'): + self.autoindex() + + if self.session.cfg('storage', 'index', 'update_on_startup'): + self.autoupdate() + + if self.session.cfg('storage', 'index', 'sync_on_startup'): + self.autosync() + + # switch to starting plane - if it's the dashboard no action is needed + if self.session.cfg('ui', 'standalone', 'plane') == 'browsing': + self.trigger('ShowBrowsing') + + # show welcome message + if self.session.cfg('session', 'first_start'): + self.display_welcome() + + # script + return + Clock.schedule_once(lambda dt: self.trigger('Search'), 0) + Clock.schedule_once(lambda dt: self.trigger('MoveCursorFirst'), 0) + Clock.schedule_once(lambda dt: self.trigger('SortKey', 'fid:image.colors_spatial:726b4e8ea45546e55dfcd4216b276284'), 0) + from kivy.app import App + App.get_running_app().stop() + Clock.schedule_once(lambda dt: self.trigger('ZoomOut'), 0) + Clock.schedule_once(lambda dt: self.trigger('ZoomOut'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + #from kivy.app import App + #App.get_running_app().stop() + + def on_request_close(self, *args): + + with open('.action_history', 'a') as ofile: + for itm in self.action_log: + ofile.write(f'{itm}\n') + + return False # FIXME: mb/port + if self.session.storage.changed() and not self.session.cfg('session', 'debug'): + # save and close + self.trigger('CloseSessionAndExit') + return True + # close w/o saving + return False + + def display_welcome(self): + """Display a welcome dialogue on the first start.""" + message = """ +[size=20sp]Welcome to [b]tagit[/b]![/size] + +Since you see this message, it's time to configure tagit. It's a good idea to get familiar with the configuration. Hit F1 or the config button to see all relevant settings. There, you can also get rid of this message. If you desire more flexibility, you can edit the config file directly. Check out the project homepage for more details. +""" # FIXME! + dialogues.Message(text=message, align='left').open() + + +## config ## + +config.declare(('storage', 'library', 'autosave'), config.Float(), 0, + __name__, 'Autosave', 'Time interval in minutes at which the library is saved to disk while running the GUI. A value of 0 means that the feature is disabled.') + +config.declare(('storage', 'index', 'autoindex'), config.Float(), 0, + __name__, 'Autoindex', 'Time interval in minutes at which indexing is triggered while running the GUI. A value of 0 means that the feature is disabled. Also configure the index watchlist.') + +config.declare(('storage', 'index', 'autoupdate'), config.Float(), 0, + __name__, 'Autoupdate', 'Time interval in minutes at which updating is triggered while running the GUI. A value of 0 means that the feature is disabled.') + +config.declare(('storage', 'index', 'autosync'), config.Float(), 0, + __name__, 'Autosync', 'Time interval in minutes at which synchronization is triggered while running the GUI. A value of 0 means that the feature is disabled.') + +config.declare(('storage', 'index', 'index_on_startup'), config.Bool(), False, + __name__, 'Index on startup', 'Trigger indexing when the GUI is started. Also configure the index watchlist') + +config.declare(('storage', 'index', 'update_on_startup'), config.Bool(), False, + __name__, 'Update on startup', 'Trigger updating when the GUI is started.') + +config.declare(('storage', 'index', 'sync_on_startup'), config.Bool(), False, + __name__, 'Sync on startup', 'Trigger synchronization when the GUI is started.') + +config.declare(('session', 'first_start'), config.Bool(), True, + __name__, 'First start', 'Show the welcome message typically shown when tagit is started the first time.') + +config.declare(('ui', 'standalone', 'plane'), config.Enum('browsing', 'dashboard'), 'dashboard', + __name__, 'Initial plane', 'Start with the dashboard or browsing plane.') + +config.declare(('ui', 'standalone', 'browser', 'cache_size'), config.Unsigned(), 1000, + __name__, 'Cache size', 'Number of preview images that are held in the cache. Should be high or zero if memory is not an issue. Set to a small value to preserve memory, but should be at least the most common page size. It is advised to set a value in accordance with `ui.standalone.browser.cache_items`. If zero, no limit applies.') + +config.declare(('ui', 'standalone', 'browser', 'cache_timeout'), config.Unsigned(), 0, + __name__, 'Cache timeout', 'Number of seconds until cached items are discarded. Should be high or zero if memory is not an issue. Set it to a small value to preserve memory when browsing through many images. If zero, no limit applies. Specify in seconds.') + +## EOF ## -- cgit v1.2.3 From 8f2f697f7ed52b7e1c7a17411b2de526b6490691 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 17:18:43 +0100 Subject: removed save and sync functionality since they no longer apply --- tagit/windows/desktop.py | 40 +--------------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.py b/tagit/windows/desktop.py index 5128454..0b28230 100644 --- a/tagit/windows/desktop.py +++ b/tagit/windows/desktop.py @@ -101,29 +101,10 @@ class MainWindow(FloatLayout): def autoupdate(self, *args): self.trigger('AutoUpdate') - def autosync(self, *args): - self.trigger('AutoSync') - - def autosave(self, *args): - if not self.session.storage.file_connected(): - return - - try: - self.trigger('SaveLibrary') - logger.info('Database: Autosaved') - except Exception as e: - logger.error(f'Database: Autosave failed ({e})') - ## startup and shutdown def on_startup(self): - # start autosave - autosave = self.session.cfg('storage', 'library', 'autosave') - if autosave > 0: - # autosave is in minutes - Clock.schedule_interval(self.autosave, autosave * 60) - # start index autoindex = self.session.cfg('storage', 'index', 'autoindex') autoindex = 0 if autoindex == float('inf') else autoindex @@ -138,13 +119,6 @@ class MainWindow(FloatLayout): # autoupdate is in minutes Clock.schedule_interval(self.autoupdate, autoupdate * 60) - # start sync - autosync = self.session.cfg('storage', 'index', 'autosync') - autosync = 0 if autosync == float('inf') else autosync - if autosync > 0: - # autosync is in minutes - Clock.schedule_interval(self.autosync, autosync * 60) - # trigger operations on startup if self.session.cfg('storage', 'index', 'index_on_startup'): self.autoindex() @@ -152,9 +126,6 @@ class MainWindow(FloatLayout): if self.session.cfg('storage', 'index', 'update_on_startup'): self.autoupdate() - if self.session.cfg('storage', 'index', 'sync_on_startup'): - self.autosync() - # switch to starting plane - if it's the dashboard no action is needed if self.session.cfg('ui', 'standalone', 'plane') == 'browsing': self.trigger('ShowBrowsing') @@ -204,7 +175,7 @@ class MainWindow(FloatLayout): return False # FIXME: mb/port if self.session.storage.changed() and not self.session.cfg('session', 'debug'): - # save and close + # close self.trigger('CloseSessionAndExit') return True # close w/o saving @@ -222,27 +193,18 @@ Since you see this message, it's time to configure tagit. It's a good idea to ge ## config ## -config.declare(('storage', 'library', 'autosave'), config.Float(), 0, - __name__, 'Autosave', 'Time interval in minutes at which the library is saved to disk while running the GUI. A value of 0 means that the feature is disabled.') - config.declare(('storage', 'index', 'autoindex'), config.Float(), 0, __name__, 'Autoindex', 'Time interval in minutes at which indexing is triggered while running the GUI. A value of 0 means that the feature is disabled. Also configure the index watchlist.') config.declare(('storage', 'index', 'autoupdate'), config.Float(), 0, __name__, 'Autoupdate', 'Time interval in minutes at which updating is triggered while running the GUI. A value of 0 means that the feature is disabled.') -config.declare(('storage', 'index', 'autosync'), config.Float(), 0, - __name__, 'Autosync', 'Time interval in minutes at which synchronization is triggered while running the GUI. A value of 0 means that the feature is disabled.') - config.declare(('storage', 'index', 'index_on_startup'), config.Bool(), False, __name__, 'Index on startup', 'Trigger indexing when the GUI is started. Also configure the index watchlist') config.declare(('storage', 'index', 'update_on_startup'), config.Bool(), False, __name__, 'Update on startup', 'Trigger updating when the GUI is started.') -config.declare(('storage', 'index', 'sync_on_startup'), config.Bool(), False, - __name__, 'Sync on startup', 'Trigger synchronization when the GUI is started.') - config.declare(('session', 'first_start'), config.Bool(), True, __name__, 'First start', 'Show the welcome message typically shown when tagit is started the first time.') -- cgit v1.2.3 From b6a57a3a84bc4ea0b5db33e6c82b30944fad7e54 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 13 Jan 2023 10:16:37 +0100 Subject: load bsfs storage --- tagit/windows/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tagit/windows/__init__.py (limited to 'tagit/windows') diff --git a/tagit/windows/__init__.py b/tagit/windows/__init__.py new file mode 100644 index 0000000..c3ec3c0 --- /dev/null +++ b/tagit/windows/__init__.py @@ -0,0 +1,10 @@ +""" + +Part of the tagit module. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# inner-module imports +from .desktop import MainWindow + +## EOF ## -- cgit v1.2.3 From 725921507c04e998c6ce1d4416af97a5e9470443 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 13 Jan 2023 10:18:20 +0100 Subject: action replay for development and testing --- tagit/windows/desktop.py | 53 ++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.py b/tagit/windows/desktop.py index 0b28230..bff983c 100644 --- a/tagit/windows/desktop.py +++ b/tagit/windows/desktop.py @@ -131,39 +131,24 @@ class MainWindow(FloatLayout): self.trigger('ShowBrowsing') # show welcome message - if self.session.cfg('session', 'first_start'): + if self.session.cfg('session', 'first_start'): # FIXME: mb/port: move to starting app self.display_welcome() - # script - return - Clock.schedule_once(lambda dt: self.trigger('Search'), 0) - Clock.schedule_once(lambda dt: self.trigger('MoveCursorFirst'), 0) - Clock.schedule_once(lambda dt: self.trigger('SortKey', 'fid:image.colors_spatial:726b4e8ea45546e55dfcd4216b276284'), 0) - from kivy.app import App - App.get_running_app().stop() - Clock.schedule_once(lambda dt: self.trigger('ZoomOut'), 0) - Clock.schedule_once(lambda dt: self.trigger('ZoomOut'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) - Clock.schedule_once(lambda dt: self.trigger('NextPage'), 0) + # run script + for args in self.session.cfg('session', 'script'): + if isinstance(args, str): + cmd, args = args, [] + else: + cmd = args.pop(0) + Clock.schedule_once( + lambda dt, cmd=cmd, args=args: self.trigger(cmd, *args), + self.session.cfg('session', 'script_delay')) + + # FIXME: mb/port: debugging only + #return + #Clock.schedule_once(lambda dt: self.trigger('Search'), 0) + #Clock.schedule_once(lambda dt: self.trigger('ZoomOut'), 0) + #Clock.schedule_once(lambda dt: self.trigger('ZoomOut'), 0) #from kivy.app import App #App.get_running_app().stop() @@ -208,6 +193,12 @@ config.declare(('storage', 'index', 'update_on_startup'), config.Bool(), False, config.declare(('session', 'first_start'), config.Bool(), True, __name__, 'First start', 'Show the welcome message typically shown when tagit is started the first time.') +config.declare(('session', 'script'), config.List(config.Any()), [], + __name__, 'start script', 'Actions to run after startup. Intended for testing.') + +config.declare(('session', 'script_delay'), config.Unsigned(), 0, + __name__, 'script delay', 'Start script execution delay in seconds.') + config.declare(('ui', 'standalone', 'plane'), config.Enum('browsing', 'dashboard'), 'dashboard', __name__, 'Initial plane', 'Start with the dashboard or browsing plane.') -- cgit v1.2.3 From 17a0fbed3d4aaa2371c822a376ab06f0bc78e3fd Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 13 Jan 2023 10:30:58 +0100 Subject: removed index and update functionality since they no longer apply --- tagit/windows/desktop.py | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.py b/tagit/windows/desktop.py index bff983c..915980f 100644 --- a/tagit/windows/desktop.py +++ b/tagit/windows/desktop.py @@ -93,39 +93,9 @@ class MainWindow(FloatLayout): actions.ActionBuilder().get(action).single_shot(self, *args, **kwargs) - ## functions - - def autoindex(self, *args): - self.trigger('AutoImport') - - def autoupdate(self, *args): - self.trigger('AutoUpdate') - - ## startup and shutdown def on_startup(self): - # start index - autoindex = self.session.cfg('storage', 'index', 'autoindex') - autoindex = 0 if autoindex == float('inf') else autoindex - if autoindex > 0: - # autoindex is in minutes - Clock.schedule_interval(self.autoindex, autoindex * 60) - - # start update - autoupdate = self.session.cfg('storage', 'index', 'autoupdate') - autoupdate = 0 if autoupdate == float('inf') else autoupdate - if autoupdate > 0: - # autoupdate is in minutes - Clock.schedule_interval(self.autoupdate, autoupdate * 60) - - # trigger operations on startup - if self.session.cfg('storage', 'index', 'index_on_startup'): - self.autoindex() - - if self.session.cfg('storage', 'index', 'update_on_startup'): - self.autoupdate() - # switch to starting plane - if it's the dashboard no action is needed if self.session.cfg('ui', 'standalone', 'plane') == 'browsing': self.trigger('ShowBrowsing') @@ -178,18 +148,6 @@ Since you see this message, it's time to configure tagit. It's a good idea to ge ## config ## -config.declare(('storage', 'index', 'autoindex'), config.Float(), 0, - __name__, 'Autoindex', 'Time interval in minutes at which indexing is triggered while running the GUI. A value of 0 means that the feature is disabled. Also configure the index watchlist.') - -config.declare(('storage', 'index', 'autoupdate'), config.Float(), 0, - __name__, 'Autoupdate', 'Time interval in minutes at which updating is triggered while running the GUI. A value of 0 means that the feature is disabled.') - -config.declare(('storage', 'index', 'index_on_startup'), config.Bool(), False, - __name__, 'Index on startup', 'Trigger indexing when the GUI is started. Also configure the index watchlist') - -config.declare(('storage', 'index', 'update_on_startup'), config.Bool(), False, - __name__, 'Update on startup', 'Trigger updating when the GUI is started.') - config.declare(('session', 'first_start'), config.Bool(), True, __name__, 'First start', 'Show the welcome message typically shown when tagit is started the first time.') -- cgit v1.2.3 From cdd1dc960a3da5e73a86dd3ec5412417387c70d6 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 25 Jan 2023 17:11:13 +0100 Subject: minor cleanup --- tagit/windows/desktop.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.py b/tagit/windows/desktop.py index 915980f..42b279e 100644 --- a/tagit/windows/desktop.py +++ b/tagit/windows/desktop.py @@ -123,17 +123,10 @@ class MainWindow(FloatLayout): #App.get_running_app().stop() def on_request_close(self, *args): - with open('.action_history', 'a') as ofile: for itm in self.action_log: ofile.write(f'{itm}\n') - - return False # FIXME: mb/port - if self.session.storage.changed() and not self.session.cfg('session', 'debug'): - # close - self.trigger('CloseSessionAndExit') - return True - # close w/o saving + #App.get_running_app().stop() # FIXME: mb/port: from CloseSessionAndExit return False def display_welcome(self): -- cgit v1.2.3 From 580caf6f5c9b795f9c38b9c970efce12d006ce1d Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 17 Feb 2023 08:25:44 +0100 Subject: New UI design * Moved style definitions to its own file (themes/default) * Updated the desktop.kv to the new UI design * Removed planes * Adjusted port config --- tagit/windows/desktop.kv | 145 ++++++++++++++++++++--------------------------- tagit/windows/desktop.py | 35 ++++-------- 2 files changed, 72 insertions(+), 108 deletions(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.kv b/tagit/windows/desktop.kv index cbc5c48..685cc10 100644 --- a/tagit/windows/desktop.kv +++ b/tagit/windows/desktop.kv @@ -1,13 +1,9 @@ +#:import TileDecorationRoundedBorder tagit.tiles.decoration.TileDecorationRoundedBorder #:import TileDecorationBorder tagit.tiles.decoration.TileDecorationBorder #:import TileDecorationFilledRectangle tagit.tiles.decoration.TileDecorationFilledRectangle -# DEBUG: Draw borders around all widgets -#: -# canvas.after: -# Line: -# rectangle: self.x+1,self.y+1,self.width-1,self.height-1 -# dash_offset: 5 -# dash_length: 3 +: + : # main content @@ -15,110 +11,89 @@ browser: browser filter: filter status: status - # required by actions.planes - planes: planes # required by Menu context: context - Carousel: - id: planes - loop: True - scroll_timeout: 0 # disables switching by touch event - # plane references - dashboard: dashboard - browsing: browsing - codash: codash + BoxLayout: + orientation: 'vertical' - # planes + Widget: + height: 5 + size_hint: 1, None - TileDock: # static dashboard plane - id: dashboard + Filter: + id: filter root: root - # plane config - size_hint: 1, 1 - visible: planes.current_slide == self - # dock config - name: 'dashboard' - decoration: TileDecorationBorder - cols: 3 - rows: 2 - # self.size won't be updated correctly - tile_width: self.width / self.cols - tile_height: self.height / self.rows - - BoxLayout: # browsing plane - id: browsing + size_hint: 1, None + height: 30 + + HGuide: + height: 20 + size_hint: 1, None + + Widget: # spacer + height: 20 + size_hint: 1, None + + BoxLayout: orientation: 'horizontal' - visible: planes.current_slide == self ButtonDock: # one column of buttons on the left root: root - orientation: 'tb-lr' + orientation: 'lr-tb' # one column of buttons - width: 30 + 2*10 + width: 1*30 + 2*10 name: 'sidebar_left' spacing: 10 padding: 10 - size_hint: None, 1 + size_hint: None, None button_height: 30 button_show: 'image', + # adjust height automatically to content + height: self.minimum_height + pos_hint: {'center_y': 0.5} - BoxLayout: # main content - orientation: 'vertical' + Widget: # spacer + width: 20 # ButtonDock already has a space of 10px + size_hint: None, 1 + + Browser: # browsing space + id: browser + root: root size_hint: 1, 1 - BoxLayout: - orientation: 'horizontal' - size_hint: 1, 1 - current: 0 - - BoxLayout: - orientation: 'vertical' - size_hint: 1, 1 - - Filter: - id: filter - root: root - size_hint: 1, None - height: 30 - - Browser: - id: browser - root: root - size_hint: 1, 0.96 - - Status: - id: status - root: root - size_hint: 1, None - height: 30 - + Widget: # spacer + width: 30 + size_hint: None, 1 + TileDock: # context info to the right root: root - visible: planes.current_slide == self.parent name: 'sidebar_right' - decoration: TileDecorationFilledRectangle + decoration: TileDecorationRoundedBorder + visible: True cols: 1 - rows: 3 + rows: 1 + width: 220 + size_hint: None, None # self.height won't be updated correctly #tile_height: self.size[1] / 4 - width: 180 - size_hint: None, 1 - - TileDock: # contextual dashboard - id: codash + #height: sum(tile.client.default_size[1] for tile in self.children) + height: self.parent.height / 2 + pos_hint: {'center_y': 0.5} + + Widget: # spacer + height: 20 + size_hint: 1, None + + HGuide: + height: 20 + size_hint: 1, None + + Status: + id: status root: root - # plane config - size_hint: 1, 1 - visible: planes.current_slide == self - # dock config - name: 'codash' - decoration: TileDecorationBorder - cols: 4 - rows: 2 - # self.size won't be update correctly - tile_width: self.width / 4 - tile_height: self.height / 2 + size_hint: 1, None + height: 30 Context: # context menu id: context diff --git a/tagit/windows/desktop.py b/tagit/windows/desktop.py index 42b279e..60e23d4 100644 --- a/tagit/windows/desktop.py +++ b/tagit/windows/desktop.py @@ -17,8 +17,9 @@ from kivy.uix.floatlayout import FloatLayout import kivy.properties as kp # import Image and Loader to overwrite their caches later on -from kivy.loader import Loader from kivy.cache import Cache +from kivy.loader import Loader +from kivy.resources import resource_find # tagit imports from tagit import actions, config, dialogues @@ -44,6 +45,8 @@ logger = logging.getLogger(__name__) # load kv Builder.load_file(os.path.join(os.path.dirname(__file__), 'desktop.kv')) +# load styles +Builder.load_file(resource_find('default/style.kv')) # classes class MainWindow(FloatLayout): @@ -80,6 +83,9 @@ class MainWindow(FloatLayout): # bind pre-close checks from kivy.core.window import Window Window.bind(on_request_close=self.on_request_close) + Window.size = tuple(cfg('ui', 'standalone', 'window_size')) + if cfg('ui', 'standalone', 'maximize'): + Window.maximize() ## properties @@ -96,14 +102,6 @@ class MainWindow(FloatLayout): ## startup and shutdown def on_startup(self): - # switch to starting plane - if it's the dashboard no action is needed - if self.session.cfg('ui', 'standalone', 'plane') == 'browsing': - self.trigger('ShowBrowsing') - - # show welcome message - if self.session.cfg('session', 'first_start'): # FIXME: mb/port: move to starting app - self.display_welcome() - # run script for args in self.session.cfg('session', 'script'): if isinstance(args, str): @@ -129,29 +127,20 @@ class MainWindow(FloatLayout): #App.get_running_app().stop() # FIXME: mb/port: from CloseSessionAndExit return False - def display_welcome(self): - """Display a welcome dialogue on the first start.""" - message = """ -[size=20sp]Welcome to [b]tagit[/b]![/size] - -Since you see this message, it's time to configure tagit. It's a good idea to get familiar with the configuration. Hit F1 or the config button to see all relevant settings. There, you can also get rid of this message. If you desire more flexibility, you can edit the config file directly. Check out the project homepage for more details. -""" # FIXME! - dialogues.Message(text=message, align='left').open() - ## config ## -config.declare(('session', 'first_start'), config.Bool(), True, - __name__, 'First start', 'Show the welcome message typically shown when tagit is started the first time.') - config.declare(('session', 'script'), config.List(config.Any()), [], __name__, 'start script', 'Actions to run after startup. Intended for testing.') config.declare(('session', 'script_delay'), config.Unsigned(), 0, __name__, 'script delay', 'Start script execution delay in seconds.') -config.declare(('ui', 'standalone', 'plane'), config.Enum('browsing', 'dashboard'), 'dashboard', - __name__, 'Initial plane', 'Start with the dashboard or browsing plane.') +config.declare(('ui', 'standalone', 'maximize'), config.Bool(), False, + __name__, 'Window maximization', 'Maximize the window upon startup.') + +config.declare(('ui', 'standalone', 'window_size'), config.List(config.Unsigned()), (1024, 768), + __name__, 'Wndow size', 'Set the window size upon startup.') config.declare(('ui', 'standalone', 'browser', 'cache_size'), config.Unsigned(), 1000, __name__, 'Cache size', 'Number of preview images that are held in the cache. Should be high or zero if memory is not an issue. Set to a small value to preserve memory, but should be at least the most common page size. It is advised to set a value in accordance with `ui.standalone.browser.cache_items`. If zero, no limit applies.') -- cgit v1.2.3 From b6f43e68f864f1c15bd56e9775da8edf5c1ac27b Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 17 Feb 2023 17:53:03 +0100 Subject: filter design update --- tagit/windows/desktop.kv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.kv b/tagit/windows/desktop.kv index 685cc10..8fde41a 100644 --- a/tagit/windows/desktop.kv +++ b/tagit/windows/desktop.kv @@ -25,7 +25,7 @@ id: filter root: root size_hint: 1, None - height: 30 + height: 40 HGuide: height: 20 -- cgit v1.2.3 From ceb95600c5d3cff789d466706bcdec7143c11bb3 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sat, 4 Mar 2023 14:19:06 +0100 Subject: info tile refactoring --- tagit/windows/desktop.kv | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.kv b/tagit/windows/desktop.kv index 8fde41a..d2ca0e7 100644 --- a/tagit/windows/desktop.kv +++ b/tagit/windows/desktop.kv @@ -74,11 +74,7 @@ cols: 1 rows: 1 width: 220 - size_hint: None, None - # self.height won't be updated correctly - #tile_height: self.size[1] / 4 - #height: sum(tile.client.default_size[1] for tile in self.children) - height: self.parent.height / 2 + size_hint: None, 0.5 pos_hint: {'center_y': 0.5} Widget: # spacer -- cgit v1.2.3 From c0443fc60c07bc42a0a4dd1bf7fe292df8d3a48d Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sat, 4 Mar 2023 16:16:34 +0100 Subject: cleanup --- tagit/windows/desktop.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tagit/windows') diff --git a/tagit/windows/desktop.py b/tagit/windows/desktop.py index 60e23d4..2c087b2 100644 --- a/tagit/windows/desktop.py +++ b/tagit/windows/desktop.py @@ -121,9 +121,9 @@ class MainWindow(FloatLayout): #App.get_running_app().stop() def on_request_close(self, *args): - with open('.action_history', 'a') as ofile: - for itm in self.action_log: - ofile.write(f'{itm}\n') + #with open('.action_history', 'a') as ofile: + # for itm in self.action_log: + # ofile.write(f'{itm}\n') #App.get_running_app().stop() # FIXME: mb/port: from CloseSessionAndExit return False -- cgit v1.2.3