aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--tagit/actions/__init__.py5
-rw-r--r--tagit/actions/tagging.kv11
-rw-r--r--tagit/actions/tagging.py162
-rw-r--r--tagit/apps/port-config.yaml12
-rw-r--r--tagit/assets/icons/scalable/tagging/add_tag.svg296
-rw-r--r--tagit/assets/icons/scalable/tagging/edit_tag.svg303
7 files changed, 783 insertions, 7 deletions
diff --git a/.gitignore b/.gitignore
index 4b3bd39..5c8310a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,5 +37,6 @@ tagit/assets/icons/kivy/filter*
tagit/assets/icons/kivy/misc*
tagit/assets/icons/kivy/planes*
tagit/assets/icons/kivy/search*
+tagit/assets/icons/kivy/tagging*
## EOF ##
diff --git a/tagit/actions/__init__.py b/tagit/actions/__init__.py
index bf99807..6416a4b 100644
--- a/tagit/actions/__init__.py
+++ b/tagit/actions/__init__.py
@@ -19,6 +19,7 @@ from . import misc
from . import planes
from . import search
#from . import session
+from . import tagging
# exports
__all__: typing.Sequence[str] = (
@@ -85,8 +86,8 @@ class ActionBuilder(BuilderBase):
#'RotateLeft': objects.RotateLeft,
#'RotateRight': objects.RotateRight,
#'DeleteObject': objects.DeleteObject,
- #'AddTag': objects.AddTag,
- #'EditTag': objects.EditTag,
+ 'AddTag': tagging.AddTag,
+ 'EditTag': tagging.EditTag,
#'SetRank1': objects.SetRank1,
#'SetRank2': objects.SetRank2,
#'SetRank3': objects.SetRank3,
diff --git a/tagit/actions/tagging.kv b/tagit/actions/tagging.kv
new file mode 100644
index 0000000..53ba926
--- /dev/null
+++ b/tagit/actions/tagging.kv
@@ -0,0 +1,11 @@
+#:import resource_find kivy.resources.resource_find
+
+<AddTag>:
+ source: resource_find('atlas://objects/add_tag')
+ tooltip: 'Add tags to items'
+
+<EditTag>:
+ source: resource_find('atlas://objects/edit_tag')
+ tooltip: 'Edit tags of items'
+
+## EOF ##
diff --git a/tagit/actions/tagging.py b/tagit/actions/tagging.py
new file mode 100644
index 0000000..c6d920d
--- /dev/null
+++ b/tagit/actions/tagging.py
@@ -0,0 +1,162 @@
+"""
+
+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, partial
+import operator
+import os
+
+# kivy imports
+from kivy.lang import Builder
+import kivy.properties as kp
+
+# tagit imports
+from tagit import config, dialogues
+from tagit.utils import ns
+from tagit.utils.bsfs import Namespace
+from tagit.widgets import Binding
+
+# inner-module imports
+from .action import Action
+
+# constants
+TAGS_SEPERATOR = ','
+TAG_PREFIX = Namespace('http://example.com/me/tag')
+
+# exports
+__all__ = []
+
+
+## code ##
+
+# load kv
+Builder.load_file(os.path.join(os.path.dirname(__file__), 'tagging.kv'))
+
+# classes
+class AddTag(Action):
+ """Add tags to the selected items."""
+ text = kp.StringProperty('Add tag')
+
+ def ktrigger(self, evt):
+ return Binding.check(evt, self.cfg('bindings', 'objects', 'add_tag'))
+
+ def apply(self):
+ if len(self.root.browser.selection) > 0:
+ tags = self.root.session.storage.all(ns.bsfs.Tag).label(node=True)
+ dlg = dialogues.SimpleInput(
+ suggestions=set(tags.values()),
+ suggestion_sep=TAGS_SEPERATOR)
+ dlg.bind(on_ok=partial(self.add_tags, tags))
+ dlg.open()
+
+ else:
+ dialogues.Error(text='You must select some images first.').open()
+
+ def add_tags(self, tags, wx):
+ # user-specified labels
+ labels = {t.strip() for t in wx.text.split(TAGS_SEPERATOR) if len(t.strip())}
+ # label to tag mapping
+ lut = {label: tag for tag, label in tags.items()}
+ # get previous tags
+ tags = {lut[lbl] for lbl in labels if lbl in lut}
+ # create new tag nodes and set their label
+ # FIXME: deny adding tags if tag vocabulary is fixed (ontology case)
+ # FIXME: replace with proper tag factory
+ for lbl in labels:
+ if lbl not in lut:
+ tag = self.root.session.storage.node(ns.bsfs.Tag, TAG_PREFIX[lbl])
+ tag.set(ns.bst.label, lbl)
+ tags.add(tag)
+ with self.root.browser as browser, \
+ self.root.session as session:
+ # get objects
+ ents = browser.unfold(browser.selection)
+ # collect tags
+ tags = reduce(operator.add, tags) # FIXME: mb/port: pass set once supported by Nodes.set
+ # set tags
+ ents.set(ns.bse.tag, tags)
+ session.dispatch('on_predicate_modified', 'tag', ents, tags)
+ # cursor and selection might become invalid. Will be fixed in Browser.
+
+
+class EditTag(Action):
+ """Edit tags of the selected items"""
+ text = kp.StringProperty('Edit tags')
+
+ def ktrigger(self, evt):
+ return Binding.check(evt, self.cfg('bindings', 'objects', 'edit_tag'))
+
+ def apply(self):
+ with self.root.browser as browser:
+ if len(browser.selection) > 0:
+ # get all known tags
+ all_tags = self.root.session.storage.all(ns.bsfs.Tag).label(node=True)
+ # get selection tags
+ ent_tags = browser.unfold(browser.selection).tag.label(node=True)
+ if len(ent_tags) == 0:
+ text = ''
+ else:
+ sep = TAGS_SEPERATOR + ' '
+ text = sep.join(sorted(set.intersection(*ent_tags.values())))
+
+ dlg = dialogues.SimpleInput(
+ text=text,
+ suggestions=set(all_tags.values()),
+ suggestion_sep=TAGS_SEPERATOR,
+ )
+ dlg.bind(on_ok=partial(self.edit_tag, ent_tags, all_tags))
+ dlg.open()
+
+ else:
+ dialogues.Error(text='You must select some images first.').open()
+
+ def edit_tag(self, original, tags, wx):
+ """Add or remove tags from images.
+ *original* and *modified* are strings, split at *TAGS_SEPERATOR*.
+ Tags are added and removed with respect to the difference between those two sets.
+ """
+ # user-specified labels
+ labels = {t.strip() for t in wx.text.split(TAGS_SEPERATOR) if len(t.strip())}
+ # label differences
+ original_labels = {lbl for lbls in original.values() for lbl in lbls}
+ removed_labels = original_labels - labels
+ added_labels = labels - original_labels
+ # get tags of removed labels
+ removed = {tag for tag, lbl in tags.items() if lbl in removed_labels}
+ removed = reduce(operator.add, removed)
+ # get tags of added labels
+ # FIXME: deny adding tags if tag vocabulary is fixed (ontology case)
+ lut = {label: tag for tag, label in tags.items()}
+ added = {lut[lbl] for lbl in added_labels if lbl in lut}
+ # FIXME: replace with proper tag factory
+ for lbl in added_labels:
+ if lbl not in lut:
+ tag = self.root.session.storage.node(ns.bsfs.Tag, TAG_PREFIX[lbl])
+ tag.set(ns.bst.label, lbl)
+ added.add(tag)
+ added = reduce(operator.add, added)
+ # apply differences
+ with self.root.browser as browser, \
+ self.root.session as session:
+ ents = browser.unfold(browser.selection)
+ ents.set(ns.bse.tag, added)
+ #ents.remove(ns.bse.tag, removed) # FIXME: mb/port
+ session.dispatch('on_predicate_modified', 'tag', ents, added | removed)
+ # cursor and selection might become invalid. Will be fixed in Browser.
+
+## config ##
+
+# keybindings
+
+config.declare(('bindings', 'objects', 'add_tag'),
+ config.Keybind(), Binding.simple('t', Binding.mCTRL, Binding.mSHIFT),
+ __name__, AddTag.text.defaultvalue, AddTag.__doc__)
+
+config.declare(('bindings', 'objects', 'edit_tag'),
+ config.Keybind(), Binding.simple('e', Binding.mCTRL),
+ __name__, EditTag.text.defaultvalue, EditTag.__doc__)
+
+## EOF ##
diff --git a/tagit/apps/port-config.yaml b/tagit/apps/port-config.yaml
index 872ac29..33afbbd 100644
--- a/tagit/apps/port-config.yaml
+++ b/tagit/apps/port-config.yaml
@@ -37,6 +37,8 @@ ui:
- SelectNone
- SelectMulti
- SelectRange
+ - AddTag
+ - EditTag
- ShowHelp
browser:
maxcols: 8
@@ -45,9 +47,9 @@ ui:
sidebar_left:
- Menu
- ShowDashboard
- #- AddTag
- #- EditTag
- AddToken
+ - AddTag
+ - EditTag
#- CreateGroup
#- DissolveGroup
- SelectAll
@@ -94,9 +96,9 @@ ui:
- SelectRange
- SelectAdditive
- SelectSubtractive
- # tagging:
- # - AddTag
- # - EditTag
+ tagging:
+ - AddTag
+ - EditTag
# - SetRank1
# - SetRank3
# - SetRank5
diff --git a/tagit/assets/icons/scalable/tagging/add_tag.svg b/tagit/assets/icons/scalable/tagging/add_tag.svg
new file mode 100644
index 0000000..6e73d56
--- /dev/null
+++ b/tagit/assets/icons/scalable/tagging/add_tag.svg
@@ -0,0 +1,296 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100mm"
+ height="100mm"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ sodipodi:docname="add_tag.svg"
+ inkscape:export-filename="../../kivy/objects/add_tag.png"
+ inkscape:export-xdpi="7.6199999"
+ inkscape:export-ydpi="7.6199999">
+ <defs
+ id="defs4">
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-3"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-7"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-7-3"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-7-6"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-2"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9-0"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-93"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9-6"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-26"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9-9"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-20"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="-207.59181"
+ inkscape:cy="167.43915"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:snap-global="false"
+ inkscape:snap-bbox="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1151"
+ inkscape:window-x="0"
+ inkscape:window-y="25"
+ inkscape:window-maximized="1"
+ inkscape:pagecheckerboard="true"
+ units="mm"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:object-paths="true"
+ inkscape:snap-intersection-paths="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:snap-text-baseline="true"
+ inkscape:snap-page="true"
+ inkscape:lockguides="false">
+ <sodipodi:guide
+ orientation="0,1"
+ position="13.637059,643.40404"
+ id="guide3788"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="188.97638,188.97638"
+ orientation="0,1"
+ id="guide1099"
+ inkscape:locked="false"
+ inkscape:label=""
+ inkscape:color="rgb(0,0,255)" />
+ <sodipodi:guide
+ position="188.97638,188.97638"
+ orientation="1,0"
+ id="guide1101"
+ inkscape:locked="false"
+ inkscape:label=""
+ inkscape:color="rgb(0,0,255)" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-167.28122,-322.85977)">
+ <g
+ transform="matrix(0.846821,-1.0151333,1.0151333,0.846821,-484.44796,260.70334)"
+ id="g870"
+ style="stroke:#c8c8c8;stroke-width:14.89931583;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
+ <circle
+ r="23.687183"
+ cy="510.56808"
+ cx="261.76941"
+ id="path839"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#c8c8c8;stroke-width:14.89931583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
+ <g
+ style="stroke:#c8c8c8;stroke-width:14.89931583;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(-9.9999667e-7,6.2227844)"
+ id="g864">
+ <path
+ style="fill:none;stroke:#c8c8c8;stroke-width:14.89931583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 274.44346,437.98197 79.87503,66.36332 V 698.87342 H 169.22033 V 504.34529 l 80.13837,-66.36306"
+ id="path837"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#c8c8c8;stroke-width:14.89931583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
+ id="path839-3"
+ sodipodi:type="arc"
+ sodipodi:cx="-420.58212"
+ sodipodi:cy="-313.05319"
+ sodipodi:rx="20.524721"
+ sodipodi:ry="20.524721"
+ sodipodi:start="0.40543239"
+ sodipodi:end="1.917446"
+ sodipodi:open="true"
+ d="m -401.7213,-304.95791 a 20.524721,20.524721 0 0 1 -25.83407,11.20855"
+ transform="rotate(-156.62757)" />
+ </g>
+ </g>
+ <g
+ id="g848"
+ transform="translate(342.14286,-91.176621)">
+ <path
+ inkscape:original-d="m -17.767337,666.45535 c 30.71351,-37.05555 61.4269,-74.11251 92.14015,-111.17087"
+ inkscape:path-effect="#path-effect906-26"
+ inkscape:connector-curvature="0"
+ id="path904-18"
+ d="M -17.767337,666.45535 C 12.945407,629.39916 43.658794,592.3422 74.372813,555.28448"
+ style="fill:none;stroke:#c8c8c8;stroke-width:15.01094818;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:original-d="M 83.888173,656.93999 C 46.832623,626.22647 9.7756729,595.51308 -27.282697,564.79983"
+ inkscape:path-effect="#path-effect906-20"
+ inkscape:connector-curvature="0"
+ id="path904-2"
+ d="M 83.888173,656.93999 C 46.831985,626.22724 9.7750303,595.51386 -27.282697,564.79983"
+ style="fill:none;stroke:#c8c8c8;stroke-width:15.01094818;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>
diff --git a/tagit/assets/icons/scalable/tagging/edit_tag.svg b/tagit/assets/icons/scalable/tagging/edit_tag.svg
new file mode 100644
index 0000000..c7d64e1
--- /dev/null
+++ b/tagit/assets/icons/scalable/tagging/edit_tag.svg
@@ -0,0 +1,303 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100mm"
+ height="100mm"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ sodipodi:docname="edit_tag.svg"
+ inkscape:export-filename="../../kivy/objects/edit_tag.png"
+ inkscape:export-xdpi="7.6199999"
+ inkscape:export-ydpi="7.6199999">
+ <defs
+ id="defs4">
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-3"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-7"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-7-3"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect850-7-6"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-2"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9-0"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-93"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9-6"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-26"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-9-9"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ <inkscape:path-effect
+ effect="bspline"
+ id="path-effect906-20"
+ is_visible="true"
+ weight="33.333333"
+ steps="2"
+ helper_size="0"
+ apply_no_weight="true"
+ apply_with_weight="true"
+ only_selected="false" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="-97.948957"
+ inkscape:cy="170.29629"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:snap-global="true"
+ inkscape:snap-bbox="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1151"
+ inkscape:window-x="0"
+ inkscape:window-y="25"
+ inkscape:window-maximized="1"
+ inkscape:pagecheckerboard="true"
+ units="mm"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:object-paths="true"
+ inkscape:snap-intersection-paths="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-midpoints="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:snap-text-baseline="true"
+ inkscape:snap-page="true"
+ inkscape:lockguides="false">
+ <sodipodi:guide
+ orientation="0,1"
+ position="13.637059,643.40404"
+ id="guide3788"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="188.97638,188.97638"
+ orientation="0,1"
+ id="guide1099"
+ inkscape:locked="false"
+ inkscape:label=""
+ inkscape:color="rgb(0,0,255)" />
+ <sodipodi:guide
+ position="188.97638,188.97638"
+ orientation="1,0"
+ id="guide1101"
+ inkscape:locked="false"
+ inkscape:label=""
+ inkscape:color="rgb(0,0,255)" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-167.28122,-322.85977)">
+ <g
+ id="g1018"
+ transform="matrix(0.77049115,0.63859513,-0.63859513,0.77049115,403.95705,-187.73351)">
+ <g
+ style="stroke:#c8c8c8;stroke-width:14.89931583;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="g870"
+ transform="matrix(0.00420274,-1.3209979,1.3209979,0.00420274,-397.55803,911.5166)">
+ <circle
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#c8c8c8;stroke-width:14.89931583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
+ id="path839"
+ cx="261.76941"
+ cy="510.56808"
+ r="23.687183" />
+ <g
+ id="g864"
+ transform="translate(-9.9999667e-7,6.2227844)"
+ style="stroke:#c8c8c8;stroke-width:14.89931583;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
+ <path
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0"
+ id="path837"
+ d="m 274.44346,437.98197 79.87503,66.36332 V 698.87342 H 169.22033 V 504.34529 l 80.13837,-66.36306"
+ style="fill:none;stroke:#c8c8c8;stroke-width:14.89931583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ transform="rotate(-156.62757)"
+ d="m -401.7213,-304.95791 a 20.524721,20.524721 0 0 1 -25.83407,11.20855"
+ sodipodi:open="true"
+ sodipodi:end="1.917446"
+ sodipodi:start="0.40543239"
+ sodipodi:ry="20.524721"
+ sodipodi:rx="20.524721"
+ sodipodi:cy="-313.05319"
+ sodipodi:cx="-420.58212"
+ sodipodi:type="arc"
+ id="path839-3"
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#c8c8c8;stroke-width:14.89931583;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
+ </g>
+ </g>
+ <path
+ inkscape:original-d="m 500.54332,620.98029 c -48.09424,-10e-4 -96.18948,-10e-4 -144.28572,0"
+ inkscape:path-effect="#path-effect906"
+ inkscape:connector-curvature="0"
+ id="path904"
+ d="m 500.54332,620.98029 c -48.09424,0 -96.18948,0 -144.28572,0"
+ style="fill:none;stroke:#c8c8c8;stroke-width:15;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:original-d="m 500.54332,567.766 c -48.09424,-10e-4 -96.18948,-10e-4 -144.28572,0"
+ inkscape:path-effect="#path-effect906-26"
+ inkscape:connector-curvature="0"
+ id="path904-18"
+ d="m 500.54332,567.766 c -48.09424,0 -96.18948,0 -144.28572,0"
+ style="fill:none;stroke:#c8c8c8;stroke-width:15;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:original-d="m 500.54332,514.55171 c -48.09424,-10e-4 -96.18948,-10e-4 -144.28572,0"
+ inkscape:path-effect="#path-effect906-20"
+ inkscape:connector-curvature="0"
+ id="path904-2"
+ d="m 500.54332,514.55171 c -48.09424,0 -96.18948,0 -144.28572,0"
+ style="fill:none;stroke:#c8c8c8;stroke-width:15;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>