aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-01-25 10:55:49 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-01-25 10:55:49 +0100
commit56865c524bddaee9ec86d57e62af9524be80d1b3 (patch)
treebda9e9631d4920ebb3073f1cd704e6a4c672fbb9
parentdf9adcb8d55300234d12f6737f9725df3bcfa4b4 (diff)
downloadtagit-56865c524bddaee9ec86d57e62af9524be80d1b3.tar.gz
tagit-56865c524bddaee9ec86d57e62af9524be80d1b3.tar.bz2
tagit-56865c524bddaee9ec86d57e62af9524be80d1b3.zip
first tiles
-rw-r--r--tagit/apps/port-config.yaml5
-rw-r--r--tagit/apps/port-schema.nt5
-rw-r--r--tagit/tiles/__init__.py8
-rw-r--r--tagit/tiles/browser_tags.py108
-rw-r--r--tagit/tiles/info.py84
-rw-r--r--tagit/tiles/tile.kv33
-rw-r--r--tagit/tiles/tile.py88
-rw-r--r--tagit/widgets/browser.py2
8 files changed, 321 insertions, 12 deletions
diff --git a/tagit/apps/port-config.yaml b/tagit/apps/port-config.yaml
index 35f524a..7335c16 100644
--- a/tagit/apps/port-config.yaml
+++ b/tagit/apps/port-config.yaml
@@ -129,8 +129,9 @@ ui:
#Searchtree: {}
#TagHistogram: {}
#Tagcloud: {}
- sidebar_right: {}
+ sidebar_right:
+ Info: {}
#CursorTags: {}
- #Info: {}
+ BrowserTags: {}
#Venn: {}
window_size: 1024x768
diff --git a/tagit/apps/port-schema.nt b/tagit/apps/port-schema.nt
index b18a6ad..7317496 100644
--- a/tagit/apps/port-schema.nt
+++ b/tagit/apps/port-schema.nt
@@ -55,11 +55,6 @@ bst:label rdfs:subClassOf bsfs:Predicate ;
rdfs:range xsd:string ;
bsfs:unique "true"^^xsd:boolean .
-bse:author rdfs:subClassOf bsfs:Predicate ;
- rdfs:domain bsfs:Entity ;
- rdfs:range xsd:string ;
- bsfs:unique "true"^^xsd:boolean .
-
bse:comment rdfs:subClassOf bsfs:Predicate ;
rdfs:domain bsfs:Node ;
rdfs:range xsd:string .
diff --git a/tagit/tiles/__init__.py b/tagit/tiles/__init__.py
index 3ed53b9..11f4a82 100644
--- a/tagit/tiles/__init__.py
+++ b/tagit/tiles/__init__.py
@@ -12,13 +12,13 @@ from tagit.utils.builder import BuilderBase
# inner-module imports
##from .anomalies import Anomalies # FIXME: skeleton only
-#from .browser_tags import BrowserTags
+from .browser_tags import BrowserTags
#from .buttons import Buttons
#from .cursor_tags import CursorTags
#from .entity_histogram import EntityHistogram
#from .geo import Map
#from .hints import Hints
-#from .info import Info
+from .info import Info
#from .libsummary import LibSummary
#from .searchtree import Searchtree
#from .selection_tags import SelectionTags
@@ -40,13 +40,13 @@ __all__: typing.Sequence[str] = (
class TileBuilder(BuilderBase):
_factories = {
# #'Anomalies': Anomalies,
-# 'BrowserTags': BrowserTags,
+ 'BrowserTags': BrowserTags,
# 'Buttons': Buttons,
# 'CursorTags': CursorTags,
# 'EntityHistogram': EntityHistogram,
# 'Geo': Map,
# 'Hints': Hints,
-# 'Info': Info,
+ 'Info': Info,
# 'LibSummary': LibSummary,
# 'Searchtree': Searchtree,
# 'SelectionTags': SelectionTags,
diff --git a/tagit/tiles/browser_tags.py b/tagit/tiles/browser_tags.py
new file mode 100644
index 0000000..3a9c25f
--- /dev/null
+++ b/tagit/tiles/browser_tags.py
@@ -0,0 +1,108 @@
+"""
+
+Part of the tagit module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# standard imports
+from functools import reduce
+import operator
+
+# kivy imports
+from kivy.lang import Builder
+
+# tagit imports
+from tagit.widgets.browser import BrowserAwareMixin
+
+# inner-module imports
+from .tile import TileWithLabel
+
+# exports
+__all__ = ('BrowserTags', )
+
+
+## code ##
+
+# load kv
+Builder.load_string('''
+<BrowserTags>:
+ title: 'Tags'
+ tooltip: 'Tags of displayed items.'
+''')
+
+# classes
+class BrowserTags(TileWithLabel, BrowserAwareMixin):
+ """Show tags of displayed items. Tags of selected items are highlighted."""
+
+ displayed = None
+
+ def on_browser(self, sender, browser):
+ # remove old binding
+ if self.browser is not None:
+ self.browser.unbind(cursor=self.update)
+ self.browser.unbind(selection=self.update)
+ self.browser.unbind(items=self.on_items)
+ # add new binding
+ self.browser = browser
+ if self.browser is not None:
+ self.browser.bind(cursor=self.update)
+ self.browser.bind(selection=self.update)
+ self.browser.bind(items=self.on_items)
+ # populate displayed first, then update
+ self.on_items(browser, browser.items)
+ self.update()
+
+ def __del__(self):
+ if self.browser is not None:
+ self.browser.unbind(cursor=self.update)
+ self.browser.unbind(selection=self.update)
+ self.browser.unbind(items=self.on_items)
+ self.browser = None
+
+ def on_items(self, browser, items):
+ # unfold
+ items = browser.unfold(items)
+ # get tags
+ self.displayed = items.tag.label(node=False)
+ # update view
+ self.update()
+
+ def update(self, *args):
+ if not self.visible:
+ self.text = ''
+
+ elif self.displayed is None:
+ self.on_items(self.root.browser, self.root.browser.items)
+ # calls update again with not-None self.displayed
+
+ else:
+ browser = self.root.browser
+
+ # handle cursor
+ if browser.cursor is None:
+ cursor = set()
+ else:
+ cursor = browser.cursor.tag.label()
+
+ # handle selection
+ if len(browser.selection) == 0:
+ selected = set()
+ else:
+ selection = reduce(operator.add, browser.selection)
+ selected = selection.tag.label(node=False)
+
+ # assemble tag list
+ tags = []
+ for tag in sorted(self.displayed | selected | cursor):
+ pretty = tag
+ if tag in cursor:
+ pretty = f'[b]{pretty}[/b]' # bold
+ if tag in selected:
+ pretty = f'[color=#415bCD]{pretty}[/color]' # blue color
+
+ tags.append(pretty)
+
+ # Apply prefix and display
+ self.text = ', '.join(tags)
+
+## EOF ##
diff --git a/tagit/tiles/info.py b/tagit/tiles/info.py
new file mode 100644
index 0000000..2221b60
--- /dev/null
+++ b/tagit/tiles/info.py
@@ -0,0 +1,84 @@
+"""
+
+Part of the tagit module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# standard imports
+from collections import OrderedDict
+
+# kivy imports
+from kivy.lang import Builder
+
+# tagit imports
+from tagit.utils import ttime, ns
+from tagit.widgets.browser import BrowserAwareMixin
+
+# inner-module imports
+from .tile import TileTabular
+
+# exports
+__all__ = ('Info', )
+
+
+## code ##
+
+# load kv
+Builder.load_string('''
+<Info>:
+ title: 'Item info'
+ tooltip: 'Key properties of the cursor item'
+ # assuming 7 info items
+ default_size: None, 7*self.font_size + 6*5
+ keywidth: min(65, self.width * 0.4)
+''')
+
+
+# classes
+class Info(TileTabular, BrowserAwareMixin):
+ """Show essential attributes about the cursor."""
+
+ def on_browser(self, sender, browser):
+ # remove old binding
+ if self.browser is not None:
+ self.browser.unbind(cursor=self.update)
+ # add new binding
+ self.browser = browser
+ if self.browser is not None:
+ self.browser.bind(cursor=self.update)
+ self.update()
+
+ def __del__(self):
+ if self.browser is not None:
+ self.browser.unbind(cursor=self.update)
+ self.browser = None
+
+ def update(self, *args):
+ cursor = self.root.browser.cursor
+ if not self.visible or cursor is None:
+ # invisible or no cursor, nothing to show
+ self.tabledata = OrderedDict({})
+
+ else:
+ preds = cursor.get(
+ ns.bsm.t_created,
+ ns.bse.filesize,
+ ns.bse.filename,
+ ns.bse.comment,
+ ns.bse.author,
+ )
+ self.tabledata = OrderedDict({
+ 'Date' : ttime.from_timestamp_utc(
+ preds.get(ns.bsm.t_created, ttime.timestamp_min)).strftime('%d.%m.%y %H:%M'),
+ #'Size' : f'{preds.get(ns.bse.width, "?")} x {preds.get(ns.bse.height, "?")}',
+ #'ISO' : preds.get(ns.bse.iso, '?'),
+ 'Filesize' : preds.get(ns.bse.filesize, 'n/a'),
+ 'Filename' : preds.get(ns.bse.filename, 'n/a'),
+ 'Comment' : '; '.join(preds.get(ns.bse.comment, [])),
+ #'Exposure' : f'1 / {preds.get(ns.bse.exposure, 0):0.2f}',
+ #'Aperture' : preds.get(ns.bse.aperture, '?'),
+ #'Fx' : preds.get(ns.bse.focal_length_35, '?'),
+ #'Flash' : 'Yes' if preds.get(ns.bse.flash, False) else 'No',
+ })
+
+## EOF ##
diff --git a/tagit/tiles/tile.kv b/tagit/tiles/tile.kv
new file mode 100644
index 0000000..277b23d
--- /dev/null
+++ b/tagit/tiles/tile.kv
@@ -0,0 +1,33 @@
+
+<Tile>:
+ title: ''
+ tooltip: ''
+ default_size: None, None
+
+<TileTabular>:
+ # config
+ font_size: sp(15)
+ spacer: 10
+ keywidth: 0.5
+
+ # table
+ grid: grid
+ GridLayout:
+ id: grid
+ cols: 2
+ size: root.size
+ size_hint: None, None
+
+<TileWithLabel>:
+ text: ''
+ text_align: 'left', 'top'
+ font_size: sp(15)
+ Label:
+ text: root.text
+ markup: True
+ text_size: root.size
+ font_size: root.font_size
+ halign: root.text_align[0]
+ valign: root.text_align[1]
+
+## EOF ##
diff --git a/tagit/tiles/tile.py b/tagit/tiles/tile.py
new file mode 100644
index 0000000..7ea690a
--- /dev/null
+++ b/tagit/tiles/tile.py
@@ -0,0 +1,88 @@
+"""
+
+Part of the tagit module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# standard imports
+import os
+
+# kivy imports
+from kivy.lang import Builder
+from kivy.uix.label import Label
+from kivy.uix.relativelayout import RelativeLayout
+import kivy.properties as kp
+
+# exports
+__all__ = ('Tile', 'TileWithLabel', 'TileTabular')
+
+
+## code ##
+
+# load kv
+Builder.load_file(os.path.join(os.path.dirname(__file__), 'tile.kv'))
+
+# classes
+class Tile(RelativeLayout):
+ visible = kp.BooleanProperty(False)
+ root = kp.ObjectProperty(None)
+
+ def on_visible(self, wx, visible):
+ if visible:
+ self.update()
+
+ def update(self, *args, **kwargs):
+ abstract()
+
+
+class TileWithLabel(Tile):
+ pass
+
+
+class TileTabular(Tile):
+
+ tabledata = kp.ObjectProperty()
+ spacer = kp.NumericProperty(10)
+ keywidth = kp.NumericProperty(0.5)
+
+ def on_size(self, wx, size):
+ if not self.visible or len(self.grid.children) == 0:
+ return
+
+ height = self.height / (len(self.grid.children) / 2)
+ kwidth = self.width * self.keywidth if self.keywidth < 1 else self.keywidth
+ vwidth = self.width - kwidth - self.spacer
+
+ # adjust size
+ for idx, child in enumerate(self.grid.children):
+ if idx % 2 == 1: # key
+ child.text_size = kwidth, height
+ child.width = kwidth
+ else: # label
+ child.text_size = vwidth, height
+
+ def on_tabledata(self, wx, data):
+ # set items
+ self.grid.clear_widgets()
+ for key, value in data.items():
+ # left column (keys)
+ self.grid.add_widget(Label(
+ text=key,
+ halign='right',
+ valign='top',
+ font_size = self.font_size,
+ size_hint = (None, 1),
+ ))
+
+ # right column (values)
+ self.grid.add_widget(Label(
+ text=str(value),
+ halign='left',
+ valign='top',
+ font_size = self.font_size,
+ ))
+
+ # set sizes
+ self.on_size(self, self.size)
+
+## EOF ##
diff --git a/tagit/widgets/browser.py b/tagit/widgets/browser.py
index 1dfc528..f778181 100644
--- a/tagit/widgets/browser.py
+++ b/tagit/widgets/browser.py
@@ -217,7 +217,7 @@ class Browser(GridLayout, StorageAwareMixin, ConfigAwareMixin):
unfolded |= self.folds[itm].shadow
else:
unfolded |= {itm}
- return reduce(operator.add, unfolded)
+ return reduce(operator.add, unfolded) # FIXME: What if items is empty?
def neighboring_unselected(self):
"""Return the item closest to the cursor and not being selected. May return None."""