]> git.sven.stormbind.net Git - sven/vym.git/commitdiff
New upstream version 2.9.598 upstream upstream/2.9.598
authorSven Hoexter <sven@stormbind.net>
Fri, 26 Sep 2025 17:32:06 +0000 (19:32 +0200)
committerSven Hoexter <sven@stormbind.net>
Fri, 26 Sep 2025 17:32:06 +0000 (19:32 +0200)
92 files changed:
.gitignore [new file with mode: 0644]
CMakeLists.txt
config/io.github.insilmaril.vym.appdata.xml
demos/default-dark.vym
demos/default.vym
demos/lifeforms.vym
demos/math.vym
demos/task-management.vym
demos/time-management.vym
flags/system/applications-internet-new.svg [deleted file]
flags/system/applications-internet.svg [deleted file]
flags/system/flag-jira.svg [new file with mode: 0644]
flags/system/flag-url.svg [new file with mode: 0644]
flags/system/flag-urlnew.svg [new file with mode: 0644]
flags/system/jissue.svg [deleted file]
forms/jira-settings-dialog.ui
macros/macros.vys
src/aboutdialog.cpp
src/branch-container-base.cpp
src/branch-container.cpp
src/branch-container.h
src/branch-wrapper.cpp
src/branch-wrapper.h
src/branchitem.cpp
src/branchitem.h
src/command.cpp
src/command.h
src/container.cpp
src/export-ao.cpp
src/export-ao.h
src/export-ascii.cpp
src/export-ascii.h
src/export-confluence.cpp
src/export-html.cpp
src/export-html.h
src/export-markdown.cpp
src/export-markdown.h
src/findcontrolswidget.cpp [new file with mode: 0644]
src/findcontrolswidget.h [new file with mode: 0644]
src/findresulttreeview.cpp [new file with mode: 0644]
src/findresulttreeview.h [new file with mode: 0644]
src/findresultwidget.cpp
src/findresultwidget.h
src/findwidget.cpp [deleted file]
src/findwidget.h [deleted file]
src/flag.cpp
src/flag.h
src/flagrow-master.cpp
src/frame-container.cpp
src/historywindow.cpp
src/historywindow.h
src/image-container.cpp
src/jira-agent.cpp
src/jira-agent.h
src/jira-settings-dialog.cpp
src/main.cpp
src/mainwindow.cpp
src/mainwindow.h
src/mapdesign.cpp
src/mapeditor.cpp
src/mapeditor.h
src/misc.cpp
src/misc.h
src/noteeditor.cpp
src/shortcuts.cpp
src/shortcuts.h
src/slideeditor.cpp
src/slideeditor.h
src/task.cpp
src/task.h
src/taskeditor.cpp
src/taskmodel.cpp
src/texteditor.cpp
src/texteditor.h
src/treeeditor.cpp
src/treeeditor.h
src/treeitem.cpp
src/treeitem.h
src/version.h
src/vym-wrapper.cpp
src/vym-wrapper.h
src/vymmodel.cpp
src/vymmodel.h
src/vymmodelwrapper.cpp
src/vymmodelwrapper.h
src/vymview.cpp
src/vymview.h
src/zip-agent.cpp
src/zip-agent.h
test/vym-selftest.vys
tex/vym.tex
vym.qrc

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d2f186c
--- /dev/null
@@ -0,0 +1,16 @@
+# CMake files
+CMakeCache.txt
+CMakeFiles/
+cmake_install.cmake
+install_manifest.txt
+Makefile
+
+# Qt/CMake autogen and deploy
+vym_autogen/
+.qt/
+
+# Built binary
+vym
+
+# Qt translation artifacts
+translations/*.qm
index 800e4e1650514554ff9d0e48fb7f4028e98f4701..1d23a2aae9811a4efc866912dbb3daf009b4d366 100644 (file)
@@ -38,6 +38,7 @@ set(QtLibraries
 # or uncomment here:
 # set(CMAKE_BUILD_TYPE Debug)
 
+# No longer needed with qt_standard_project_setup() below...
 set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTOUIC ON)
 set(CMAKE_AUTORCC ON)
@@ -49,7 +50,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL Linux)
     find_package(DBus1)
 
     if(DBus1_FOUND)
-        message(STATUS "Deteced DBUS1 available, adding DBUS interfaces")
+        message(STATUS "Deteced Linux and DBUS1, adding DBUS interfaces")
 
         LIST(APPEND QtComponents DBus)
         LIST(APPEND QtLibraries Qt6::DBus)
@@ -75,6 +76,11 @@ if(WIN32)
     set(CMAKE_INSTALL_DATAROOTDIR ".")
  endif()
 
+
+# https://doc.qt.io/qt-6/qt-standard-project-setup.html
+find_package(Qt6 REQUIRED COMPONENTS Core)
+qt_standard_project_setup()
+
 include(GNUInstallDirs)
 
 find_package(Qt6 COMPONENTS ${QtComponents} REQUIRED)
index 55d378ab38c70b4796a6c3afb216d323bdd7916f..5d9a24ed4c2bbaa604e0269163e10723335e8721 100644 (file)
@@ -2,7 +2,7 @@
 <component type="desktop">
     <id>io.github.insilmaril.vym</id>
     <metadata_license>CC0-1.0</metadata_license>
-    <project_license>LGPL-2.1-or-later</project_license>
+    <project_license>GPL-2.0</project_license>
     <name>VYM</name>
     <summary>Tool for generating and manipulating mind maps</summary>
     <description>
@@ -26,7 +26,9 @@
     </categories>
     <url type="bugtracker">https://github.com/insilmaril/vym/issues</url>
     <url type="homepage">http://www.insilmaril.de/vym/</url>
-    <developer_name>vym</developer_name>
+    <developer id="io.github.insilmaril.vym">
+      <name>Uwe Drechsel</name>
+    </developer>
     <kudos>
         <kudo>HiDpiIcon</kudo>
         <kudo>HighContrast</kudo>
index 607343d9360fd482d34dd7a7bf4f39c631797aa1..2d5570045c1589a6c86e067649ab55bc0f39fca7 100644 (file)
Binary files a/demos/default-dark.vym and b/demos/default-dark.vym differ
index 4858026d6adf95af50f81891f84f91c99b1c15eb..545a3c99bb91552cab39d8eb0d79deb626d1fd72 100644 (file)
Binary files a/demos/default.vym and b/demos/default.vym differ
index 853932c7a0125d68661684f54015de5fa43129d4..9601d2b9c27a72d849160485fe56e0395fce1006 100644 (file)
Binary files a/demos/lifeforms.vym and b/demos/lifeforms.vym differ
index b8e2c639639048435830529398038b340971d78a..873206340938336e2392ed3e96e1792dda8b6684 100644 (file)
Binary files a/demos/math.vym and b/demos/math.vym differ
index 9057a9851dd4538b166bbeadcc32e27f7d039fb9..2023e8a17054d25e65c0306cdeb4f55988e77f2a 100644 (file)
Binary files a/demos/task-management.vym and b/demos/task-management.vym differ
index d0554f11e2863ea7c2bd0c744c0a96e5788db906..b9ec08f2cdfddad9b78d6ffbd79cec0af4e33df7 100644 (file)
Binary files a/demos/time-management.vym and b/demos/time-management.vym differ
diff --git a/flags/system/applications-internet-new.svg b/flags/system/applications-internet-new.svg
deleted file mode 100644 (file)
index 72532d0..0000000
+++ /dev/null
@@ -1,1084 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="48px"
-   height="48px"
-   id="svg3440"
-   sodipodi:version="0.32"
-   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
-   sodipodi:docname="applications-internet-new.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.1">
-  <defs
-     id="defs3">
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 24 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="48 : 24 : 1"
-       inkscape:persp3d-origin="24 : 16 : 1"
-       id="perspective95" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient6001">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop6003" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop6005" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4825">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop4827" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop4829" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient4126">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1.0000000;"
-         offset="0.0000000"
-         id="stop4128" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0.16494845;"
-         offset="1.0000000"
-         id="stop4130" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4114">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop4116" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop4118" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3962">
-      <stop
-         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
-         offset="0.0000000"
-         id="stop3964" />
-      <stop
-         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
-         offset="0.15517241"
-         id="stop4134" />
-      <stop
-         style="stop-color:#4074ae;stop-opacity:1.0000000;"
-         offset="0.75000000"
-         id="stop4346" />
-      <stop
-         style="stop-color:#36486c;stop-opacity:1.0000000;"
-         offset="1.0000000"
-         id="stop3966" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3962"
-       id="radialGradient3968"
-       gradientTransform="matrix(0.79959032,0,0,0.79960792,9.1985908,0.72047157)"
-       cx="18.247644"
-       cy="15.716079"
-       fx="18.247644"
-       fy="15.716079"
-       r="29.993349"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4114"
-       id="radialGradient4120"
-       gradientTransform="matrix(1.314533,0,0,0.60468523,9.1985908,-7.4933384)"
-       cx="15.115514"
-       cy="63.965388"
-       fx="15.115514"
-       fy="63.965388"
-       r="12.289036"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4126"
-       id="radialGradient4132"
-       gradientTransform="matrix(0.79959032,0,0,0.79960792,9.1985908,0.72047157)"
-       cx="15.601279"
-       cy="12.142302"
-       fx="15.601279"
-       fy="12.142302"
-       r="43.526714"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5983"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5985"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5987"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5989"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6007"
-       x1="-25.176178"
-       y1="30.057165"
-       x2="-22.252472"
-       y2="21.041553"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.0286978,0,0,0.79959904,52.56766,-13.083065)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6011"
-       gradientUnits="userSpaceOnUse"
-       x1="-25.176178"
-       y1="30.057165"
-       x2="-22.113543"
-       y2="22.661524"
-       gradientTransform="matrix(1.0286977,0,0,0.79959901,27.521423,21.868113)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6015"
-       gradientUnits="userSpaceOnUse"
-       x1="-22.822565"
-       y1="28.337734"
-       x2="-22.113543"
-       y2="22.661524"
-       gradientTransform="matrix(1.0286976,0,0,0.79959889,-10.488538,-32.250227)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6019"
-       gradientUnits="userSpaceOnUse"
-       x1="-21.658581"
-       y1="15.649428"
-       x2="-21.962101"
-       y2="21.336346"
-       gradientTransform="matrix(1.0051901,0,0,0.78132384,26.131093,17.875478)" />
-    <radialGradient
-       gradientUnits="userSpaceOnUse"
-       r="120"
-       cy="27.3013"
-       cx="232.5"
-       id="radialGradient4574">
-      <stop
-         id="stop4576"
-         style="stop-color:#ffee93;stop-opacity:1;"
-         offset="0" />
-      <stop
-         offset="0.3388288"
-         style="stop-color:#fff211;stop-opacity:1;"
-         id="stop4578" />
-      <stop
-         offset="0.59700626"
-         style="stop-color:#ffff32;stop-opacity:1"
-         id="stop4580" />
-      <stop
-         id="stop4582"
-         style="stop-color:#ffe171;stop-opacity:1;"
-         offset="1" />
-    </radialGradient>
-    <radialGradient
-       id="radialGradient24014"
-       cx="232.5"
-       cy="27.3013"
-       r="120"
-       gradientUnits="userSpaceOnUse">
-      <stop
-         offset="0"
-         style="stop-color:#ffee93;stop-opacity:1;"
-         id="stop24016" />
-      <stop
-         id="stop24018"
-         style="stop-color:#c57c00;stop-opacity:1"
-         offset="0.49229774" />
-      <stop
-         id="stop24020"
-         style="stop-color:#ffff7d;stop-opacity:1;"
-         offset="0.59700626" />
-      <stop
-         offset="1"
-         style="stop-color:#ffe171;stop-opacity:1;"
-         id="stop24022" />
-    </radialGradient>
-    <radialGradient
-       gradientUnits="userSpaceOnUse"
-       r="120"
-       cy="27.3013"
-       cx="232.5"
-       id="radialGradient2810-4">
-      <stop
-         id="stop2812-5"
-         style="stop-color:#ffee93;stop-opacity:1;"
-         offset="0" />
-      <stop
-         offset="0.3773585"
-         style="stop-color:#c57c00;stop-opacity:1;"
-         id="stop3686" />
-      <stop
-         offset="0.49483803"
-         style="stop-color:#ffff7d;stop-opacity:1;"
-         id="stop2816-0" />
-      <stop
-         id="stop2820-3"
-         style="stop-color:#ffe171;stop-opacity:1;"
-         offset="1" />
-    </radialGradient>
-    <clipPath
-       clipPathUnits="userSpaceOnUse"
-       id="clipPath24074">
-      <path
-         sodipodi:type="star"
-         style="opacity:0.39436622;fill:url(#linearGradient24078);fill-opacity:1;stroke:none"
-         id="path24076"
-         sodipodi:sides="11"
-         sodipodi:cx="90.156113"
-         sodipodi:cy="85.220039"
-         sodipodi:r1="19.827379"
-         sodipodi:r2="13.362659"
-         sodipodi:arg1="0.78539816"
-         sodipodi:arg2="1.0519012"
-         inkscape:flatsided="false"
-         inkscape:rounded="0"
-         inkscape:randomized="0"
-         d="m 104.17619,99.240114 -7.393254,-2.416374 -2.412211,7.77056 -4.913208,-6.029875 -6.230363,5.232875 -0.873257,-7.728938 -8.070419,1.033783 3.443947,-6.974112 -7.348174,-3.493525 6.667723,-4.005058 -4.292936,-6.911662 7.774544,0.235574 0.125279,-8.135397 6.413001,4.401413 4.50372,-6.7762 3.015376,7.169834 7.452262,-3.265607 -1.33961,7.661884 8.03476,1.281791 -5.26928,5.72134 6.06628,5.422232 -7.52598,1.964311 z"
-         transform="translate(80,-0.9385641)" />
-    </clipPath>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#radialGradient24014"
-       id="linearGradient24078"
-       gradientUnits="userSpaceOnUse"
-       x1="73.711586"
-       y1="71.214951"
-       x2="89.811958"
-       y2="99.101616" />
-    <radialGradient
-       gradientUnits="userSpaceOnUse"
-       r="120"
-       cy="27.3013"
-       cx="232.5"
-       id="radialGradient4574-6">
-      <stop
-         id="stop4576-7"
-         style="stop-color:#ffee93;stop-opacity:1;"
-         offset="0" />
-      <stop
-         offset="0.3388288"
-         style="stop-color:#fff211;stop-opacity:1;"
-         id="stop4578-5" />
-      <stop
-         offset="0.59700626"
-         style="stop-color:#ffff32;stop-opacity:1"
-         id="stop4580-3" />
-      <stop
-         id="stop4582-5"
-         style="stop-color:#ffe171;stop-opacity:1;"
-         offset="1" />
-    </radialGradient>
-    <linearGradient
-       y2="104.80668"
-       x2="-62.424866"
-       y1="76.708466"
-       x1="-13.757333"
-       gradientTransform="translate(148,19.999992)"
-       gradientUnits="userSpaceOnUse"
-       id="linearGradient4794"
-       xlink:href="#XMLID_4_"
-       inkscape:collect="always" />
-    <radialGradient
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.9792,0,0,0.9725,133.0002,20.8762)"
-       r="55.147999"
-       cy="-0.2148"
-       cx="48"
-       id="XMLID_4_">
-      <stop
-         id="stop3082"
-         style="stop-color:#72D13D"
-         offset="0" />
-      <stop
-         id="stop3084"
-         style="stop-color:#35AC1C"
-         offset="0.3553" />
-      <stop
-         id="stop3086"
-         style="stop-color:#0F9508"
-         offset="0.6194" />
-      <stop
-         id="stop3088"
-         style="stop-color:#008C00"
-         offset="0.7574" />
-      <stop
-         id="stop3090"
-         style="stop-color:#007A00"
-         offset="1" />
-    </radialGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient3571"
-       gradientUnits="userSpaceOnUse"
-       x1="73.742638"
-       y1="15.336544"
-       x2="80"
-       y2="19.281664"
-       spreadMethod="reflect" />
-    <filter
-       id="filter3387"
-       height="1.249912"
-       y="-0.12495601"
-       width="1.2041403"
-       x="-0.10207015"
-       inkscape:collect="always">
-      <feGaussianBlur
-         id="feGaussianBlur3389"
-         stdDeviation="0.44655691"
-         inkscape:collect="always" />
-    </filter>
-    <radialGradient
-       r="6.7806501"
-       fy="17.83758"
-       fx="73.656624"
-       cy="17.83758"
-       cx="73.656624"
-       gradientTransform="matrix(1,0,0,0.8708964,0,2.3028957)"
-       gradientUnits="userSpaceOnUse"
-       id="radialGradient4800"
-       xlink:href="#linearGradient5412"
-       inkscape:collect="always" />
-    <linearGradient
-       id="linearGradient5412"
-       gradientUnits="userSpaceOnUse"
-       x1="28"
-       y1="57.5"
-       x2="28"
-       y2="0">
-      <stop
-         offset="0"
-         style="stop-color:#fff14d;stop-opacity:1;"
-         id="stop5414" />
-      <stop
-         offset="1"
-         style="stop-color:#f8ffa0;stop-opacity:0;"
-         id="stop5416" />
-    </linearGradient>
-    <radialGradient
-       r="6.2063885"
-       fy="17.802542"
-       fx="73.082359"
-       cy="17.802542"
-       cx="73.082359"
-       gradientTransform="matrix(1,0,0,0.9256542,0,1.3235438)"
-       gradientUnits="userSpaceOnUse"
-       id="radialGradient4802"
-       xlink:href="#linearGradient4770"
-       inkscape:collect="always" />
-    <linearGradient
-       id="linearGradient4770"
-       gradientUnits="userSpaceOnUse"
-       x1="-84.002403"
-       y1="-383.9971"
-       x2="-12.0029"
-       y2="-383.9971"
-       gradientTransform="rotate(90,-90.0007,50.0022)">
-      <stop
-         offset="0"
-         style="stop-color:#e5ff00;stop-opacity:1"
-         id="stop4772" />
-      <stop
-         offset="1"
-         style="stop-color:#bff500;stop-opacity:0;"
-         id="stop4774" />
-    </linearGradient>
-    <radialGradient
-       r="24"
-       fy="104"
-       fx="104"
-       cy="104"
-       cx="104"
-       gradientTransform="translate(0,-1.3e-5)"
-       gradientUnits="userSpaceOnUse"
-       id="radialGradient4806"
-       xlink:href="#linearGradient3030"
-       inkscape:collect="always" />
-    <linearGradient
-       id="linearGradient3030"
-       inkscape:collect="always">
-      <stop
-         id="stop3032"
-         offset="0"
-         style="stop-color:#000000;stop-opacity:0.77902622" />
-      <stop
-         id="stop3034"
-         offset="1"
-         style="stop-color:#000000;stop-opacity:0;" />
-    </linearGradient>
-    <radialGradient
-       r="20"
-       fy="96"
-       fx="-40"
-       cy="84"
-       cx="-44"
-       gradientTransform="translate(148,19.999992)"
-       gradientUnits="userSpaceOnUse"
-       id="radialGradient4810"
-       xlink:href="#XMLID_4_"
-       inkscape:collect="always" />
-    <radialGradient
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.9792,0,0,0.9725,133.0002,20.8762)"
-       r="55.147999"
-       cy="-0.2148"
-       cx="48"
-       id="radialGradient1513">
-      <stop
-         id="stop1503"
-         style="stop-color:#72D13D"
-         offset="0" />
-      <stop
-         id="stop1505"
-         style="stop-color:#35AC1C"
-         offset="0.3553" />
-      <stop
-         id="stop1507"
-         style="stop-color:#0F9508"
-         offset="0.6194" />
-      <stop
-         id="stop1509"
-         style="stop-color:#008C00"
-         offset="0.7574" />
-      <stop
-         id="stop1511"
-         style="stop-color:#007A00"
-         offset="1" />
-    </radialGradient>
-    <linearGradient
-       y2="108.0104"
-       x2="11.68106"
-       y1="60.539303"
-       x1="11.68106"
-       gradientTransform="translate(85.3125,19.999992)"
-       gradientUnits="userSpaceOnUse"
-       id="linearGradient4812"
-       xlink:href="#linearGradient6001"
-       inkscape:collect="always" />
-    <linearGradient
-       y2="96.001434"
-       x2="11.68106"
-       y1="52"
-       x1="6.6976352"
-       gradientTransform="translate(85.30236,19.999992)"
-       gradientUnits="userSpaceOnUse"
-       id="linearGradient4814"
-       xlink:href="#linearGradient6001"
-       inkscape:collect="always" />
-    <linearGradient
-       y2="72"
-       x2="14.697635"
-       y1="96"
-       x1="26.697636"
-       gradientTransform="translate(85.30236,19.999992)"
-       gradientUnits="userSpaceOnUse"
-       id="linearGradient4816"
-       xlink:href="#linearGradient6001"
-       inkscape:collect="always" />
-    <linearGradient
-       y2="84"
-       x2="120.25"
-       y1="84"
-       x1="79.75"
-       gradientTransform="translate(3.99999,19.999992)"
-       gradientUnits="userSpaceOnUse"
-       id="linearGradient4818"
-       xlink:href="#linearGradient3225"
-       inkscape:collect="always" />
-    <linearGradient
-       id="linearGradient3225">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop3227" />
-      <stop
-         style="stop-color:#aeaeae;stop-opacity:1;"
-         offset="1"
-         id="stop3229" />
-    </linearGradient>
-    <filter
-       id="filter3191"
-       inkscape:collect="always">
-      <feGaussianBlur
-         id="feGaussianBlur3193"
-         stdDeviation="0.2025"
-         inkscape:collect="always" />
-    </filter>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient1937"
-       gradientUnits="userSpaceOnUse"
-       x1="73.742638"
-       y1="15.336544"
-       x2="80"
-       y2="19.281664"
-       spreadMethod="reflect" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient1939"
-       gradientUnits="userSpaceOnUse"
-       x1="73.742638"
-       y1="15.336544"
-       x2="80"
-       y2="19.281664"
-       spreadMethod="reflect" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient1941"
-       gradientUnits="userSpaceOnUse"
-       x1="73.742638"
-       y1="15.336544"
-       x2="80"
-       y2="19.281664"
-       spreadMethod="reflect" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="0.17254902"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="5.6568542"
-     inkscape:cx="5.0143305"
-     inkscape:cy="27.22336"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1920"
-     inkscape:window-height="1000"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:showpageshadow="false"
-     inkscape:document-rotation="0"
-     inkscape:window-maximized="1" />
-  <metadata
-     id="metadata4">
-    <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></dc:title>
-        <dc:creator>
-          <cc:Agent>
-            <dc:title>Jakub Steiner</dc:title>
-          </cc:Agent>
-        </dc:creator>
-        <dc:contributor>
-          <cc:Agent>
-            <dc:title>Tuomas Kuosmanen</dc:title>
-          </cc:Agent>
-        </dc:contributor>
-        <cc:license
-           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
-        <dc:source>http://jimmac.musichall.cz</dc:source>
-        <dc:subject>
-          <rdf:Bag>
-            <rdf:li>internet</rdf:li>
-            <rdf:li>tools</rdf:li>
-            <rdf:li>applications</rdf:li>
-            <rdf:li>category</rdf:li>
-          </rdf:Bag>
-        </dc:subject>
-      </cc:Work>
-      <cc:License
-         rdf:about="http://creativecommons.org/licenses/publicdomain/">
-        <cc:permits
-           rdf:resource="http://creativecommons.org/ns#Reproduction" />
-        <cc:permits
-           rdf:resource="http://creativecommons.org/ns#Distribution" />
-        <cc:permits
-           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
-      </cc:License>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     style="display:inline">
-    <ellipse
-       style="display:inline;fill:url(#radialGradient4120);fill-opacity:1;stroke:none;stroke-width:0.89156;stroke-opacity:1"
-       id="path4112"
-       cx="29.06843"
-       cy="31.185602"
-       rx="16.154341"
-       ry="7.4310017"
-       inkscape:label="shadow" />
-    <path
-       style="fill:url(#radialGradient3968);fill-opacity:1;fill-rule:nonzero;stroke:#39396c;stroke-width:0.799599;stroke-miterlimit:4;stroke-opacity:1"
-       d="m 44.34885,19.499456 c 0,8.563481 -6.942201,15.505604 -15.504505,15.505604 -8.563087,0 -15.504897,-6.942201 -15.504897,-15.505604 0,-8.563089 6.94181,-15.5045047 15.504897,-15.5045047 8.562304,0 15.504505,6.9414157 15.504505,15.5045047 z"
-       id="path3214" />
-    <g
-       id="g4136"
-       style="opacity:1;fill:#204a87;fill-opacity:0.71345;fill-rule:nonzero;stroke:none;stroke-miterlimit:4"
-       transform="matrix(0.78550298,0,0,0.78550298,9.2954054,0.9067094)">
-      <g
-         id="g4138"
-         style="fill:#204a87">
-        <g
-           id="g4142"
-           style="fill:#204a87">
-          <path
-             d="m 44.0713,20.7144 c 0,0.2627 0,0 0,0 l -0.5449,0.6172 c -0.334,-0.3936 -0.709,-0.7246 -1.0898,-1.0703 l -0.8359,0.123 -0.7637,-0.8633 v 1.0684 l 0.6543,0.4951 0.4355,0.4932 0.582,-0.6582 c 0.1465,0.2744 0.291,0.5488 0.4365,0.8232 v 0.8223 l -0.6553,0.7402 -1.1992,0.8232 -0.9082,0.9063 -0.582,-0.6602 0.291,-0.7402 -0.5811,-0.6582 -0.9814,-2.0977 -0.8359,-0.9453 -0.2188,0.2461 0.3281,1.1934 0.6172,0.6992 c 0.3525,1.0176 0.7012,1.9902 1.1641,2.9629 0.7178,0 1.3945,-0.0762 2.1074,-0.166 v 0.5762 l -0.8721,2.1392 -0.7998,0.9043 -0.6543,1.4004 c 0,0.7676 0,1.5352 0,2.3027 l 0.2188,0.9063 -0.3633,0.4102 -0.8008,0.4941 -0.8359,0.6992 0.6914,0.7813 -0.9453,0.8242 0.1816,0.5332 -1.418,1.6055 h -0.9443 l -0.7998,0.4941 H 33.6396 V 38.2814 L 33.4228,36.963 c -0.2813,-0.8262 -0.5742,-1.6465 -0.8721,-2.4668 0,-0.6055 0.0361,-1.2051 0.0723,-1.8105 l 0.3643,-0.8223 -0.5098,-0.9883 0.0371,-1.3574 -0.6914,-0.7813 0.3457,-1.1309 -0.5625,-0.6382 H 30.624 l -0.3271,-0.3701 -0.9814,0.6177 -0.3994,-0.4536 -0.9092,0.7817 c -0.6172,-0.6997 -1.2354,-1.3989 -1.8535,-2.0981 l -0.7266,-1.7285 0.6543,-0.9863 -0.3633,-0.4111 0.7988,-1.8936 c 0.6563,-0.8164 1.3418,-1.5996 2.0352,-2.3857 l 1.2363,-0.3291 1.3809,-0.1641 0.9453,0.2471 1.3447,1.3564 0.4727,-0.5342 0.6533,-0.082 1.2363,0.4111 h 0.9453 l 0.6543,-0.5762 0.291,-0.4111 -0.6553,-0.4111 -1.0908,-0.082 c -0.3027,-0.4199 -0.584,-0.8613 -0.9434,-1.2344 l -0.3643,0.1641 -0.1455,1.0703 -0.6543,-0.7402 -0.1445,-0.8242 -0.7266,-0.5742 h -0.292 l 0.7275,0.8223 -0.291,0.7402 -0.5811,0.1641 0.3633,-0.7402 -0.6553,-0.3281 -0.5801,-0.6582 -1.0918,0.2461 -0.1445,0.3281 -0.6543,0.4121 -0.3633,0.9053 -0.9082,0.4521 -0.4004,-0.4521 h -0.4355 v -1.4814 l 0.9453,-0.4941 h 0.7266 l -0.1465,-0.5752 -0.5801,-0.5762 0.9805,-0.2061 0.5449,-0.6162 0.4355,-0.7412 h 0.8008 l -0.2188,-0.5752 0.5098,-0.3291 v 0.6582 l 1.0898,0.2461 1.0898,-0.9043 0.0732,-0.4121 0.9443,-0.6577 c -0.3418,0.0425 -0.6836,0.0737 -1.0176,0.1646 V 9.9766 L 34.2213,9.1538 H 33.858 l -0.7984,0.7402 -0.2188,0.4116 0.2188,0.5767 -0.3643,0.9863 -0.5811,-0.3291 -0.5078,-0.5752 -0.8008,0.5752 -0.291,-1.3159 1.3809,-0.9048 V 8.8247 l 0.873,-0.5757 1.3809,-0.3296 0.9453,0.3296 1.7441,0.3291 -0.4355,0.4932 H 35.458 l 0.9453,0.9873 0.7266,-0.8223 0.2207,-0.3618 c 0,0 2.7871,2.498 4.3799,5.2305 1.5928,2.7334 2.3408,5.9551 2.3408,6.6094 z"
-             id="path4144"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4146"
-         style="fill:#204a87">
-        <g
-           id="g4150"
-           style="fill:#204a87">
-          <path
-             d="m 26.0703,9.2363 -0.0732,0.4932 0.5098,0.3291 0.8711,-0.5757 -0.4355,-0.4937 -0.582,0.3296 -0.29,-0.0825"
-             id="path4152"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4154"
-         style="fill:#204a87">
-        <g
-           id="g4158"
-           style="fill:#204a87">
-          <path
-             d="m 26.8701,5.8633 -1.8906,-0.7407 -2.1797,0.2466 -2.6904,0.7402 -0.5088,0.4941 1.6719,1.1514 v 0.6582 l -0.6543,0.6582 0.873,1.729 0.5801,-0.3301 0.7285,-1.1514 c 1.123,-0.3472 2.1299,-0.7407 3.1973,-1.2344 l 0.873,-2.2212"
-             id="path4160"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4162"
-         style="fill:#204a87">
-        <g
-           id="g4166"
-           style="fill:#204a87">
-          <path
-             d="m 28.833,12.7749 -0.291,-0.7412 -0.5098,0.165 0.1465,0.9043 0.6543,-0.3281"
-             id="path4168"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4170"
-         style="fill:#204a87">
-        <g
-           id="g4174"
-           style="fill:#204a87">
-          <path
-             d="m 29.123,12.6089 -0.1455,0.9883 0.7998,-0.165 0.5811,-0.5752 -0.5088,-0.4941 C 29.6787,11.9078 29.4824,11.483 29.2685,11.0465 H 28.833 v 0.4932 l 0.29,0.3291 v 0.7402"
-             id="path4176"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4178"
-         style="fill:#204a87">
-        <g
-           id="g4182"
-           style="fill:#204a87">
-          <path
-             d="m 18.3652,28.2422 -0.582,-1.1523 -1.0903,-0.2466 -0.5815,-1.5625 -1.4536,0.1641 -1.2354,-0.9043 -1.3091,1.1514 v 0.1816 c -0.396,-0.1143 -0.8828,-0.1299 -1.2354,-0.3467 l -0.291,-0.8223 v -0.9053 l -0.8721,0.082 c 0.0728,-0.5762 0.145,-1.1514 0.2183,-1.7275 H 9.4238 L 8.9155,22.812 8.4062,23.0581 7.6791,22.6479 7.6063,21.7426 7.7518,20.7553 8.8426,19.933 h 0.8721 l 0.145,-0.4941 1.0903,0.2461 0.7998,0.9883 0.1455,-1.6465 1.3813,-1.1514 0.5088,-1.2344 1.0176,-0.4111 0.5815,-0.8223 1.3081,-0.248 0.6548,-0.9863 c -0.6543,0 -1.3086,0 -1.9629,0 l 1.2358,-0.5762 h 0.8716 l 1.2363,-0.4121 0.1455,-0.4922 -0.4365,-0.4121 -0.5088,-0.165 0.1455,-0.4932 -0.3633,-0.7402 -0.8726,0.3281 0.1455,-0.6577 -1.0176,-0.5762 -0.7993,1.3979 0.0723,0.4941 -0.7993,0.3301 -0.5093,1.0693 -0.2178,-0.9873 -1.3813,-0.5762 -0.2183,-0.7402 1.8174,-1.0703 0.7998,-0.7402 0.0728,-0.9048 -0.436,-0.2471 -0.5815,-0.0825 -0.3633,0.9053 c 0,0 -0.6079,0.1191 -0.7642,0.1577 -1.9961,1.8394 -6.0293,5.8101 -6.9663,13.3062 0.0371,0.1738 0.6792,1.1816 0.6792,1.1816 l 1.5264,0.9043 1.5264,0.4121 0.6548,0.8232 1.0171,0.7402 0.5815,-0.082 0.436,0.1963 v 0.1328 l -0.5811,1.563 -0.4365,0.6582 0.1455,0.3301 -0.3633,1.2324 1.3086,2.3867 1.3081,1.1523 0.582,0.8223 -0.0732,1.7285 0.4365,0.9863 -0.4365,1.8926 c 0,0 -0.0342,-0.0117 0.0215,0.1777 0.0562,0.1895 2.3291,1.4512 2.4736,1.3438 0.144,-0.1094 0.2671,-0.2051 0.2671,-0.2051 l -0.145,-0.4102 0.5811,-0.5762 0.2183,-0.5762 0.9453,-0.3301 0.7266,-1.8105 -0.2178,-0.4922 0.5078,-0.7402 1.0908,-0.248 0.582,-1.3164 -0.1455,-1.6445 0.8721,-1.2344 0.1455,-1.2344 C 20.7331,29.4607 19.5495,28.8513 18.365,28.242"
-             id="path4184"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4186"
-         style="fill:#204a87">
-        <g
-           id="g4190"
-           style="fill:#204a87">
-          <path
-             d="m 16.7656,9.5649 0.7266,0.4937 h 0.582 V 9.4829 l -0.7266,-0.3291 -0.582,0.4111"
-             id="path4192"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4194"
-         style="fill:#204a87">
-        <g
-           id="g4198"
-           style="fill:#204a87">
-          <path
-             d="M 14.876,8.9072 14.5122,9.812 h 0.7271 L 15.6031,8.9892 C 15.9166,8.7675 16.2286,8.5444 16.5479,8.331 l 0.7271,0.2471 c 0.4844,0.3291 0.9688,0.6582 1.4536,0.9868 L 19.4561,8.9072 18.6558,8.5781 18.292,7.8374 16.9111,7.6728 16.8383,7.2612 16.184,7.4262 15.8936,8.002 15.5298,7.2613 l -0.145,0.3291 0.0728,0.8228 -0.5816,0.494"
-             id="path4200"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4202"
-         style="fill:#204a87">
-        <g
-           style="opacity:0.75;fill:#204a87"
-           id="g4204">
-          <path
-             id="path4206"
-             d=""
-             style="fill:#204a87" />
-        </g>
-        <g
-           id="g4208"
-           style="fill:#204a87">
-          <path
-             id="path4210"
-             d=""
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4212"
-         style="fill:#204a87">
-        <g
-           style="opacity:0.75;fill:#204a87"
-           id="g4214">
-          <path
-             id="path4216"
-             d=""
-             style="fill:#204a87" />
-        </g>
-        <g
-           id="g4218"
-           style="fill:#204a87">
-          <path
-             id="path4220"
-             d=""
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4222"
-         style="fill:#204a87">
-        <g
-           id="g4226"
-           style="fill:#204a87">
-          <path
-             d="M 17.4922,6.8496 17.856,6.521 18.5831,6.3564 c 0.498,-0.2422 0.998,-0.4053 1.5264,-0.5762 l -0.29,-0.4937 -0.9385,0.1348 -0.4434,0.4419 -0.731,0.106 -0.6499,0.3052 -0.3159,0.1528 -0.1929,0.2583 0.9443,0.1641"
-             id="path4228"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4230"
-         style="fill:#204a87">
-        <g
-           id="g4234"
-           style="fill:#204a87">
-          <path
-             d="m 18.7285,14.6665 0.4365,-0.6582 -0.6548,-0.4932 0.2183,1.1514"
-             id="path4236"
-             style="fill:#204a87" />
-        </g>
-      </g>
-    </g>
-    <path
-       style="opacity:0.395604;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient4132);stroke-width:0.799599;stroke-miterlimit:4;stroke-opacity:1"
-       d="m 43.561437,19.499484 c 0,8.128581 -6.589638,14.718146 -14.717101,14.718146 -8.128208,0 -14.717475,-6.58964 -14.717475,-14.718146 0,-8.128208 6.589267,-14.7171017 14.717475,-14.7171017 8.127463,0 14.717101,6.5888937 14.717101,14.7171017 z"
-       id="path4122" />
-    <ellipse
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6007);stroke-width:0.799599;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       id="path5991"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true"
-       transform="rotate(28.460691)"
-       cx="33.473431"
-       cy="3.7417412"
-       rx="16.184631"
-       ry="7.5622501" />
-    <ellipse
-       transform="rotate(-43.10261)"
-       inkscape:r_cy="true"
-       inkscape:r_cx="true"
-       id="path6009"
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6011);stroke-width:0.799599;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       cx="8.4271946"
-       cy="38.692917"
-       rx="16.184631"
-       ry="7.5622501" />
-    <g
-       inkscape:r_cy="true"
-       inkscape:r_cx="true"
-       transform="matrix(-0.83619837,0.61349322,0.61349322,0.83619837,37.677521,-16.985819)"
-       id="g4933">
-      <circle
-         transform="translate(14.95026,22.93047)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path4935"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5987);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path4937"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-    <ellipse
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6015);stroke-width:0.799599;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       id="path6013"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true"
-       transform="rotate(-174.37239)"
-       cx="-29.582764"
-       cy="-15.425425"
-       rx="16.184629"
-       ry="7.5622487" />
-    <ellipse
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6019);stroke-width:0.799598;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       id="path6017"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true"
-       transform="matrix(0.73014176,-0.6832957,0.68331862,0.7301203,0,0)"
-       cx="7.4732032"
-       cy="34.315746"
-       rx="15.814781"
-       ry="7.3894114" />
-    <g
-       id="g5075"
-       transform="matrix(-0.64469758,0.47299486,0.47299486,0.64469758,19.102138,-13.695669)"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true">
-      <circle
-         transform="translate(14.95026,22.93047)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path5077"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5983);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path5079"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-    <g
-       inkscape:r_cy="true"
-       inkscape:r_cx="true"
-       transform="matrix(-0.64469758,0.47299486,0.47299486,0.64469758,19.992459,-24.467077)"
-       id="g4945">
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path4947"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="translate(14.95026,22.93047)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path4949"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-    <g
-       style="opacity:1"
-       id="g4939"
-       transform="matrix(-0.69583274,0.51060161,0.51051045,0.69595588,29.35251,-27.515596)"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true">
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5989);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path4941"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="translate(14.95026,22.93047)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path4943"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-    <g
-       id="g4655"
-       transform="matrix(0.42965914,0,0,0.42965914,-32.525869,-7.5145594)"
-       inkscape:label="plus">
-      <path
-         inkscape:connector-curvature="0"
-         style="fill:url(#linearGradient4794);fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
-         d="m 102.0625,79.999994 c -3.31753,0 -6.0625,2.74498 -6.0625,6.0625 v 9.9375 h -9.9375 c -3.31753,0 -6.0625,2.74498 -6.0625,6.062496 v 3.875 c 0,3.31753 2.74497,6.0625 6.0625,6.0625 H 96 v 9.93751 c 0,3.31752 2.74497,6.0625 6.0625,6.0625 h 3.875 c 3.31752,0 6.0625,-2.74498 6.0625,-6.0625 v -9.93751 h 9.9375 c 3.31752,0 6.0625,-2.74497 6.0625,-6.0625 v -3.875 c 0,-3.317516 -2.74498,-6.062496 -6.0625,-6.062496 H 112 v -9.9375 c 0,-3.31752 -2.74498,-6.0625 -6.0625,-6.0625 z"
-         id="path3012"
-         sodipodi:nodetypes="ccccccccccccccccccccc"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         sodipodi:nodetypes="cccccc"
-         transform="matrix(-0.4770371,0,0,0.4770371,134.46434,74.913337)"
-         id="path3091"
-         d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 68.465655,24.133449 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
-         style="fill:url(#linearGradient1937);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         style="fill:url(#linearGradient1939);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
-         d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 68.172686,21.789699 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
-         id="path3095"
-         transform="matrix(0.4705955,0,0,0.4705955,74.322072,75.046467)"
-         sodipodi:nodetypes="cccccc"
-         clip-path="none" />
-      <g
-         id="g3201"
-         transform="matrix(1,0,0,-1,148,188.38795)"
-         clip-path="none">
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cccccc"
-           transform="matrix(-0.463084,0,0,0.463084,-14.468792,55.235658)"
-           id="path3197"
-           d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 l 2.175622,10.747436 11.133979,-0.114683 v -0.46875 C 81.92653,20.116546 74.219552,10.743294 69.875971,12.057888 Z"
-           style="opacity:0.643564;fill:url(#radialGradient4800);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)" />
-        <path
-           inkscape:connector-curvature="0"
-           style="opacity:0.643564;fill:url(#radialGradient4802);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
-           d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 67.782061,23.547512 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
-           id="path3199"
-           transform="matrix(0.4624565,0,0,0.4624565,-73.133616,55.243224)"
-           sodipodi:nodetypes="cccccc" />
-      </g>
-      <path
-         inkscape:connector-curvature="0"
-         sodipodi:nodetypes="cccccc"
-         transform="matrix(0.4793282,0,0,0.4793282,89.738069,90.470087)"
-         id="path3221"
-         d="M 69.719108,13.31279 C 68.64202,13.378073 67.34775,12.277052 66.875971,12.995388 L 68.465655,24.133449 79,23.37409 v -0.46875 c 1.740958,-2.57016 -4.937311,-9.65189 -9.280892,-9.59255 z"
-         style="opacity:0.550562;fill:url(#linearGradient1941);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         sodipodi:nodetypes="ccccccccccccccccccccc"
-         id="path3028"
-         d="m 102.0625,79.999994 c -3.31753,0 -6.0625,2.74498 -6.0625,6.0625 v 9.9375 h -9.9375 c -3.31753,0 -6.0625,2.74498 -6.0625,6.062496 v 3.875 c 0,3.31753 2.74497,6.0625 6.0625,6.0625 H 96 v 9.93751 c 0,3.31752 2.74497,6.0625 6.0625,6.0625 h 3.875 c 3.31752,0 6.0625,-2.74498 6.0625,-6.0625 v -9.93751 h 9.9375 c 3.31752,0 6.0625,-2.74497 6.0625,-6.0625 v -3.875 c 0,-3.317516 -2.74498,-6.062496 -6.0625,-6.062496 H 112 v -9.9375 c 0,-3.31752 -2.74498,-6.0625 -6.0625,-6.0625 z"
-         style="opacity:0.643564;fill:url(#radialGradient4806);fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         style="opacity:0.550562;fill:url(#linearGradient3571);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
-         d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 68.465655,24.133449 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
-         id="path3217"
-         transform="matrix(-0.4540742,0,0,0.4540742,116.57304,91.07955)"
-         sodipodi:nodetypes="cccccc"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         style="fill:url(#radialGradient4810);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
-         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 13.9375 H 86.0625 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 3.875 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 H 100 v 13.93751 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 h 3.875 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -13.93751 h 13.9375 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -3.875 c 0,-1.13397 -0.92853,-2.062496 -2.0625,-2.062496 H 108 v -13.9375 c 0,-1.13397 -0.92853,-2.0625 -2.0625,-2.0625 z"
-         id="rect2407"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         style="fill:url(#linearGradient4812);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
-         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 13.9375 H 86.0625 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 3.875 c 0,0.1098 0.04574,0.20722 0.0625,0.3125 3.25768,0.46957 6.69134,0.75 10.25,0.75 11.50157,0 21.80584,-2.62983 28.59375,-6.75 -0.28924,-0.15515 -0.61935,-0.249996 -0.96875,-0.249996 H 108 v -13.9375 c 0,-1.13397 -0.92853,-2.0625 -2.0625,-2.0625 z"
-         id="path3038"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         style="fill:url(#linearGradient4814);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
-         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 1 c 0,-1.13397 1.32853,-2.6625 2.4625,-2.6625 h 3.875 c 0.28349,0 0.56599,0.05148 0.8125,0.15625 0.11026,0.24952 0.4875,1.12458 0.4875,1.4125 l 0.3625,14.03125 0.0312,-13.9375 c 0,-0.57563 -0.24106,-1.09358 -0.625,-1.46875 -0.0878,-0.08777 -0.17903,-0.17902 -0.28125,-0.25 -0.008,-0.0052 -0.0235,0.0051 -0.0312,0 -0.10208,-0.06913 -0.19867,-0.13727 -0.3125,-0.1875 -0.009,-0.0037 -0.0225,0.0036 -0.0312,0 -0.1146,-0.0487 -0.25111,-0.09763 -0.375,-0.125 -0.0102,-0.0021 -0.021,0.002 -0.0312,0 -0.12367,-0.0255 -0.24455,-0.02921 -0.375,-0.03125 h -0.0312 -0.46875 z m -16,16 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 1 c 0,-1.13397 0.92853,-2.6625 2.0625,-2.6625 L 100,99.999994 Z m 21.9375,0 13.75977,0.511716 c -6.7592,3.6271 -17.82247,6.39454 -28.50977,6.39453 -1.77933,0 -3.53955,-0.09 -5.25,-0.21875 2.06039,0.18692 4.17941,0.3125 6.34375,0.3125 10.77006,0 20.48375,-2.32371 27.25,-6 0.008,-0.004 0.0233,0.004 0.0312,0 0.44256,-0.24123 0.86462,-0.49711 1.28125,-0.75 -0.13631,-0.0731 -0.2853,-0.14478 -0.4375,-0.1875 -0.01,-0.003 -0.0212,0.003 -0.0312,0 -0.15237,-0.0404 -0.30537,-0.0598 -0.46875,-0.0625 h -0.0312 -0.46875 z"
-         id="path3062"
-         sodipodi:nodetypes="cccccccccsssssssccccccccccccscssscsscccc"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         sodipodi:nodetypes="cccccccccsssssssccccccccccccscssscsscccc"
-         id="path3087"
-         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 1 c 0,-1.13397 1.32853,-2.6625 2.4625,-2.6625 h 3.875 c 0.28349,0 0.56599,0.05148 0.8125,0.15625 0.11026,0.24952 0.4875,1.12458 0.4875,1.4125 l 0.3625,14.03125 0.0312,-13.9375 c 0,-0.57563 -0.24106,-1.09358 -0.625,-1.46875 -0.0878,-0.08777 -0.17903,-0.17902 -0.28125,-0.25 -0.008,-0.0052 -0.0235,0.0051 -0.0312,0 -0.10208,-0.06913 -0.19867,-0.13727 -0.3125,-0.1875 -0.009,-0.0037 -0.0225,0.0036 -0.0312,0 -0.1146,-0.0487 -0.25111,-0.09763 -0.375,-0.125 -0.0102,-0.0021 -0.021,0.002 -0.0312,0 -0.12367,-0.0255 -0.24455,-0.02921 -0.375,-0.03125 h -0.0312 -0.46875 z m -16,16 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 1 c 0,-1.13397 0.92853,-2.6625 2.0625,-2.6625 L 100,99.999994 Z m 21.9375,0 13.85742,0.511716 c -6.75919,3.6271 -17.92012,6.39454 -28.60742,6.39453 -1.77933,0 -3.53955,-0.09 -5.25,-0.21875 2.06039,0.18692 4.17941,0.3125 6.34375,0.3125 10.77006,0 20.48375,-2.32371 27.25,-6 0.008,-0.004 0.0233,0.004 0.0312,0 0.44256,-0.24123 0.86462,-0.49711 1.28125,-0.75 -0.13631,-0.0731 -0.2853,-0.14478 -0.4375,-0.1875 -0.01,-0.003 -0.0212,0.003 -0.0312,0 -0.15237,-0.0404 -0.30537,-0.0598 -0.46875,-0.0625 h -0.0312 -0.46875 z"
-         style="fill:url(#linearGradient4816);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
-         clip-path="none" />
-      <path
-         inkscape:connector-curvature="0"
-         id="path3099"
-         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 13.9375 H 86.0625 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 3.875 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 H 100 v 13.93751 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 h 3.875 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -13.93751 h 13.9375 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -3.875 c 0,-1.13397 -0.92853,-2.062496 -2.0625,-2.062496 H 108 v -13.9375 c 0,-1.13397 -0.92853,-2.0625 -2.0625,-2.0625 z"
-         style="fill:none;fill-opacity:1;stroke:url(#linearGradient4818);stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1;filter:url(#filter3191)"
-         clip-path="none" />
-    </g>
-  </g>
-</svg>
diff --git a/flags/system/applications-internet.svg b/flags/system/applications-internet.svg
deleted file mode 100644 (file)
index 632865e..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="48px"
-   height="48px"
-   id="svg3440"
-   sodipodi:version="0.32"
-   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
-   sodipodi:docname="applications-internet.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.1">
-  <defs
-     id="defs3">
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 24 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="48 : 24 : 1"
-       inkscape:persp3d-origin="24 : 16 : 1"
-       id="perspective95" />
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient6001">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop6003" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop6005" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4825">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop4827" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop4829" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient4126">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1.0000000;"
-         offset="0.0000000"
-         id="stop4128" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0.16494845;"
-         offset="1.0000000"
-         id="stop4130" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient4114">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop4116" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop4118" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3962">
-      <stop
-         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
-         offset="0.0000000"
-         id="stop3964" />
-      <stop
-         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
-         offset="0.15517241"
-         id="stop4134" />
-      <stop
-         style="stop-color:#4074ae;stop-opacity:1.0000000;"
-         offset="0.75000000"
-         id="stop4346" />
-      <stop
-         style="stop-color:#36486c;stop-opacity:1.0000000;"
-         offset="1.0000000"
-         id="stop3966" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3962"
-       id="radialGradient3968"
-       gradientTransform="scale(0.999989,1.000011)"
-       cx="18.247644"
-       cy="15.716079"
-       fx="18.247644"
-       fy="15.716079"
-       r="29.993349"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4114"
-       id="radialGradient4120"
-       gradientTransform="scale(1.643990,0.608276)"
-       cx="15.115514"
-       cy="63.965388"
-       fx="15.115514"
-       fy="63.965388"
-       r="12.289036"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4126"
-       id="radialGradient4132"
-       gradientTransform="scale(0.999989,1.000011)"
-       cx="15.601279"
-       cy="12.142302"
-       fx="15.601279"
-       fy="12.142302"
-       r="43.526714"
-       gradientUnits="userSpaceOnUse" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5983"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5985"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5987"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient4825"
-       id="radialGradient5989"
-       gradientUnits="userSpaceOnUse"
-       cx="12.071323"
-       cy="12.493138"
-       fx="12.071323"
-       fy="12.493138"
-       r="6.7175145" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6007"
-       x1="-25.176178"
-       y1="30.057165"
-       x2="-22.252472"
-       y2="21.041553"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6011"
-       gradientUnits="userSpaceOnUse"
-       x1="-25.176178"
-       y1="30.057165"
-       x2="-22.113543"
-       y2="22.661524" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6015"
-       gradientUnits="userSpaceOnUse"
-       x1="-22.822565"
-       y1="28.337734"
-       x2="-22.113543"
-       y2="22.661524" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6001"
-       id="linearGradient6019"
-       gradientUnits="userSpaceOnUse"
-       x1="-21.658581"
-       y1="15.649428"
-       x2="-21.962101"
-       y2="21.336346" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="0.17254902"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="5.6568542"
-     inkscape:cx="-5.4339934"
-     inkscape:cy="25.586897"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1920"
-     inkscape:window-height="1000"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:showpageshadow="false"
-     inkscape:document-rotation="0"
-     inkscape:window-maximized="1" />
-  <metadata
-     id="metadata4">
-    <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></dc:title>
-        <dc:creator>
-          <cc:Agent>
-            <dc:title>Jakub Steiner</dc:title>
-          </cc:Agent>
-        </dc:creator>
-        <dc:contributor>
-          <cc:Agent>
-            <dc:title>Tuomas Kuosmanen</dc:title>
-          </cc:Agent>
-        </dc:contributor>
-        <cc:license
-           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
-        <dc:source>http://jimmac.musichall.cz</dc:source>
-        <dc:subject>
-          <rdf:Bag>
-            <rdf:li>internet</rdf:li>
-            <rdf:li>tools</rdf:li>
-            <rdf:li>applications</rdf:li>
-            <rdf:li>category</rdf:li>
-          </rdf:Bag>
-        </dc:subject>
-      </cc:Work>
-      <cc:License
-         rdf:about="http://creativecommons.org/licenses/publicdomain/">
-        <cc:permits
-           rdf:resource="http://creativecommons.org/ns#Reproduction" />
-        <cc:permits
-           rdf:resource="http://creativecommons.org/ns#Distribution" />
-        <cc:permits
-           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
-      </cc:License>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <ellipse
-       style="display:inline;fill:url(#radialGradient4120);fill-opacity:1;stroke:none;stroke-opacity:1"
-       id="path4112"
-       transform="matrix(1,0,0,1.243244,0,-10.27241)"
-       cx="24.849752"
-       cy="38.908627"
-       rx="20.203051"
-       ry="7.4751287"
-       inkscape:label="shadow" />
-    <path
-       style="fill:url(#radialGradient3968);fill-opacity:1;fill-rule:nonzero;stroke:#39396c;stroke-miterlimit:4;stroke-opacity:1"
-       d="m 43.959853,23.485499 c 0,10.709718 -8.682103,19.391723 -19.390348,19.391723 -10.709226,0 -19.3908387,-8.682103 -19.3908387,-19.391723 0,-10.709227 8.6816127,-19.3903473 19.3908387,-19.3903473 10.708245,0 19.390348,8.6811203 19.390348,19.3903473 z"
-       id="path3214" />
-    <g
-       id="g4136"
-       style="opacity:1;fill:#204a87;fill-opacity:0.71345;fill-rule:nonzero;stroke:none;stroke-miterlimit:4"
-       transform="matrix(0.982371,0,0,0.982371,0.121079,0.232914)">
-      <g
-         id="g4138"
-         style="fill:#204a87">
-        <g
-           id="g4142"
-           style="fill:#204a87">
-          <path
-             d="m 44.0713,20.7144 c 0,0.2627 0,0 0,0 l -0.5449,0.6172 c -0.334,-0.3936 -0.709,-0.7246 -1.0898,-1.0703 l -0.8359,0.123 -0.7637,-0.8633 v 1.0684 l 0.6543,0.4951 0.4355,0.4932 0.582,-0.6582 c 0.1465,0.2744 0.291,0.5488 0.4365,0.8232 v 0.8223 l -0.6553,0.7402 -1.1992,0.8232 -0.9082,0.9063 -0.582,-0.6602 0.291,-0.7402 -0.5811,-0.6582 -0.9814,-2.0977 -0.8359,-0.9453 -0.2188,0.2461 0.3281,1.1934 0.6172,0.6992 c 0.3525,1.0176 0.7012,1.9902 1.1641,2.9629 0.7178,0 1.3945,-0.0762 2.1074,-0.166 v 0.5762 l -0.8721,2.1392 -0.7998,0.9043 -0.6543,1.4004 c 0,0.7676 0,1.5352 0,2.3027 l 0.2188,0.9063 -0.3633,0.4102 -0.8008,0.4941 -0.8359,0.6992 0.6914,0.7813 -0.9453,0.8242 0.1816,0.5332 -1.418,1.6055 h -0.9443 l -0.7998,0.4941 H 33.6396 V 38.2814 L 33.4228,36.963 c -0.2813,-0.8262 -0.5742,-1.6465 -0.8721,-2.4668 0,-0.6055 0.0361,-1.2051 0.0723,-1.8105 l 0.3643,-0.8223 -0.5098,-0.9883 0.0371,-1.3574 -0.6914,-0.7813 0.3457,-1.1309 -0.5625,-0.6382 H 30.624 l -0.3271,-0.3701 -0.9814,0.6177 -0.3994,-0.4536 -0.9092,0.7817 c -0.6172,-0.6997 -1.2354,-1.3989 -1.8535,-2.0981 l -0.7266,-1.7285 0.6543,-0.9863 -0.3633,-0.4111 0.7988,-1.8936 c 0.6563,-0.8164 1.3418,-1.5996 2.0352,-2.3857 l 1.2363,-0.3291 1.3809,-0.1641 0.9453,0.2471 1.3447,1.3564 0.4727,-0.5342 0.6533,-0.082 1.2363,0.4111 h 0.9453 l 0.6543,-0.5762 0.291,-0.4111 -0.6553,-0.4111 -1.0908,-0.082 c -0.3027,-0.4199 -0.584,-0.8613 -0.9434,-1.2344 l -0.3643,0.1641 -0.1455,1.0703 -0.6543,-0.7402 -0.1445,-0.8242 -0.7266,-0.5742 h -0.292 l 0.7275,0.8223 -0.291,0.7402 -0.5811,0.1641 0.3633,-0.7402 -0.6553,-0.3281 -0.5801,-0.6582 -1.0918,0.2461 -0.1445,0.3281 -0.6543,0.4121 -0.3633,0.9053 -0.9082,0.4521 -0.4004,-0.4521 h -0.4355 v -1.4814 l 0.9453,-0.4941 h 0.7266 l -0.1465,-0.5752 -0.5801,-0.5762 0.9805,-0.2061 0.5449,-0.6162 0.4355,-0.7412 h 0.8008 l -0.2188,-0.5752 0.5098,-0.3291 v 0.6582 l 1.0898,0.2461 1.0898,-0.9043 0.0732,-0.4121 0.9443,-0.6577 c -0.3418,0.0425 -0.6836,0.0737 -1.0176,0.1646 V 9.9766 L 34.2213,9.1538 H 33.858 l -0.7984,0.7402 -0.2188,0.4116 0.2188,0.5767 -0.3643,0.9863 -0.5811,-0.3291 -0.5078,-0.5752 -0.8008,0.5752 -0.291,-1.3159 1.3809,-0.9048 V 8.8247 l 0.873,-0.5757 1.3809,-0.3296 0.9453,0.3296 1.7441,0.3291 -0.4355,0.4932 H 35.458 l 0.9453,0.9873 0.7266,-0.8223 0.2207,-0.3618 c 0,0 2.7871,2.498 4.3799,5.2305 1.5928,2.7334 2.3408,5.9551 2.3408,6.6094 z"
-             id="path4144"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4146"
-         style="fill:#204a87">
-        <g
-           id="g4150"
-           style="fill:#204a87">
-          <path
-             d="m 26.0703,9.2363 -0.0732,0.4932 0.5098,0.3291 0.8711,-0.5757 -0.4355,-0.4937 -0.582,0.3296 -0.29,-0.0825"
-             id="path4152"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4154"
-         style="fill:#204a87">
-        <g
-           id="g4158"
-           style="fill:#204a87">
-          <path
-             d="m 26.8701,5.8633 -1.8906,-0.7407 -2.1797,0.2466 -2.6904,0.7402 -0.5088,0.4941 1.6719,1.1514 v 0.6582 l -0.6543,0.6582 0.873,1.729 0.5801,-0.3301 0.7285,-1.1514 c 1.123,-0.3472 2.1299,-0.7407 3.1973,-1.2344 l 0.873,-2.2212"
-             id="path4160"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4162"
-         style="fill:#204a87">
-        <g
-           id="g4166"
-           style="fill:#204a87">
-          <path
-             d="m 28.833,12.7749 -0.291,-0.7412 -0.5098,0.165 0.1465,0.9043 0.6543,-0.3281"
-             id="path4168"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4170"
-         style="fill:#204a87">
-        <g
-           id="g4174"
-           style="fill:#204a87">
-          <path
-             d="m 29.123,12.6089 -0.1455,0.9883 0.7998,-0.165 0.5811,-0.5752 -0.5088,-0.4941 C 29.6787,11.9078 29.4824,11.483 29.2685,11.0465 H 28.833 v 0.4932 l 0.29,0.3291 v 0.7402"
-             id="path4176"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4178"
-         style="fill:#204a87">
-        <g
-           id="g4182"
-           style="fill:#204a87">
-          <path
-             d="m 18.3652,28.2422 -0.582,-1.1523 -1.0903,-0.2466 -0.5815,-1.5625 -1.4536,0.1641 -1.2354,-0.9043 -1.3091,1.1514 v 0.1816 c -0.396,-0.1143 -0.8828,-0.1299 -1.2354,-0.3467 l -0.291,-0.8223 v -0.9053 l -0.8721,0.082 c 0.0728,-0.5762 0.145,-1.1514 0.2183,-1.7275 H 9.4238 L 8.9155,22.812 8.4062,23.0581 7.6791,22.6479 7.6063,21.7426 7.7518,20.7553 8.8426,19.933 h 0.8721 l 0.145,-0.4941 1.0903,0.2461 0.7998,0.9883 0.1455,-1.6465 1.3813,-1.1514 0.5088,-1.2344 1.0176,-0.4111 0.5815,-0.8223 1.3081,-0.248 0.6548,-0.9863 c -0.6543,0 -1.3086,0 -1.9629,0 l 1.2358,-0.5762 h 0.8716 l 1.2363,-0.4121 0.1455,-0.4922 -0.4365,-0.4121 -0.5088,-0.165 0.1455,-0.4932 -0.3633,-0.7402 -0.8726,0.3281 0.1455,-0.6577 -1.0176,-0.5762 -0.7993,1.3979 0.0723,0.4941 -0.7993,0.3301 -0.5093,1.0693 -0.2178,-0.9873 -1.3813,-0.5762 -0.2183,-0.7402 1.8174,-1.0703 0.7998,-0.7402 0.0728,-0.9048 -0.436,-0.2471 -0.5815,-0.0825 -0.3633,0.9053 c 0,0 -0.6079,0.1191 -0.7642,0.1577 -1.9961,1.8394 -6.0293,5.8101 -6.9663,13.3062 0.0371,0.1738 0.6792,1.1816 0.6792,1.1816 l 1.5264,0.9043 1.5264,0.4121 0.6548,0.8232 1.0171,0.7402 0.5815,-0.082 0.436,0.1963 v 0.1328 l -0.5811,1.563 -0.4365,0.6582 0.1455,0.3301 -0.3633,1.2324 1.3086,2.3867 1.3081,1.1523 0.582,0.8223 -0.0732,1.7285 0.4365,0.9863 -0.4365,1.8926 c 0,0 -0.0342,-0.0117 0.0215,0.1777 0.0562,0.1895 2.3291,1.4512 2.4736,1.3438 0.144,-0.1094 0.2671,-0.2051 0.2671,-0.2051 l -0.145,-0.4102 0.5811,-0.5762 0.2183,-0.5762 0.9453,-0.3301 0.7266,-1.8105 -0.2178,-0.4922 0.5078,-0.7402 1.0908,-0.248 0.582,-1.3164 -0.1455,-1.6445 0.8721,-1.2344 0.1455,-1.2344 C 20.7331,29.4607 19.5495,28.8513 18.365,28.242"
-             id="path4184"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4186"
-         style="fill:#204a87">
-        <g
-           id="g4190"
-           style="fill:#204a87">
-          <path
-             d="m 16.7656,9.5649 0.7266,0.4937 h 0.582 V 9.4829 l -0.7266,-0.3291 -0.582,0.4111"
-             id="path4192"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4194"
-         style="fill:#204a87">
-        <g
-           id="g4198"
-           style="fill:#204a87">
-          <path
-             d="M 14.876,8.9072 14.5122,9.812 h 0.7271 L 15.6031,8.9892 C 15.9166,8.7675 16.2286,8.5444 16.5479,8.331 l 0.7271,0.2471 c 0.4844,0.3291 0.9688,0.6582 1.4536,0.9868 L 19.4561,8.9072 18.6558,8.5781 18.292,7.8374 16.9111,7.6728 16.8383,7.2612 16.184,7.4262 15.8936,8.002 15.5298,7.2613 l -0.145,0.3291 0.0728,0.8228 -0.5816,0.494"
-             id="path4200"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4202"
-         style="fill:#204a87">
-        <g
-           style="opacity:0.75;fill:#204a87"
-           id="g4204">
-          <path
-             id="path4206"
-             d=""
-             style="fill:#204a87" />
-        </g>
-        <g
-           id="g4208"
-           style="fill:#204a87">
-          <path
-             id="path4210"
-             d=""
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4212"
-         style="fill:#204a87">
-        <g
-           style="opacity:0.75;fill:#204a87"
-           id="g4214">
-          <path
-             id="path4216"
-             d=""
-             style="fill:#204a87" />
-        </g>
-        <g
-           id="g4218"
-           style="fill:#204a87">
-          <path
-             id="path4220"
-             d=""
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4222"
-         style="fill:#204a87">
-        <g
-           id="g4226"
-           style="fill:#204a87">
-          <path
-             d="M 17.4922,6.8496 17.856,6.521 18.5831,6.3564 c 0.498,-0.2422 0.998,-0.4053 1.5264,-0.5762 l -0.29,-0.4937 -0.9385,0.1348 -0.4434,0.4419 -0.731,0.106 -0.6499,0.3052 -0.3159,0.1528 -0.1929,0.2583 0.9443,0.1641"
-             id="path4228"
-             style="fill:#204a87" />
-        </g>
-      </g>
-      <g
-         id="g4230"
-         style="fill:#204a87">
-        <g
-           id="g4234"
-           style="fill:#204a87">
-          <path
-             d="m 18.7285,14.6665 0.4365,-0.6582 -0.6548,-0.4932 0.2183,1.1514"
-             id="path4236"
-             style="fill:#204a87" />
-        </g>
-      </g>
-    </g>
-    <path
-       style="opacity:0.395604;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient4132);stroke-miterlimit:4;stroke-opacity:1"
-       d="m 42.975093,23.485534 c 0,10.16582 -8.241178,18.406906 -18.4056,18.406906 -10.165354,0 -18.4060669,-8.241179 -18.4060669,-18.406906 0,-10.165354 8.2407129,-18.4056 18.4060669,-18.4056 10.164422,0 18.4056,8.240246 18.4056,18.4056 z"
-       id="path4122" />
-    <ellipse
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6007);stroke-width:0.881642;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       id="path5991"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true"
-       transform="matrix(1.131034,0.613097,-0.476556,0.879144,54.09058,16.04435)"
-       cx="-18.561554"
-       cy="21.041553"
-       rx="15.733126"
-       ry="9.4575529" />
-    <ellipse
-       transform="matrix(0.939326,-0.879086,0.683307,0.730131,32.31406,-4.451561)"
-       inkscape:r_cy="true"
-       inkscape:r_cx="true"
-       id="path6009"
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6011);stroke-width:0.881642;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       cx="-18.561554"
-       cy="21.041553"
-       rx="15.733126"
-       ry="9.4575529" />
-    <g
-       inkscape:r_cy="true"
-       inkscape:r_cx="true"
-       transform="matrix(-1.045772,0.767251,0.767251,1.045772,35.61651,-22.14396)"
-       id="g4933">
-      <circle
-         transform="translate(14.95026,22.93047)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path4935"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5987);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path4937"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-    <ellipse
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6015);stroke-width:0.881642;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       id="path6013"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true"
-       transform="matrix(-1.280316,-0.126159,0.09806226,-0.99518,-2.405125,40.52387)"
-       cx="-18.561554"
-       cy="21.041553"
-       rx="15.733126"
-       ry="9.4575529" />
-    <ellipse
-       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6019);stroke-width:0.902261;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-       id="path6017"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true"
-       transform="matrix(0.917874,-0.858983,0.667701,0.713433,27.63317,-6.909069)"
-       cx="-18.561554"
-       cy="21.041553"
-       rx="15.733126"
-       ry="9.4575529" />
-    <g
-       id="g5075"
-       transform="matrix(-0.806276,0.59154,0.59154,0.806276,12.38564,-18.02921)"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true">
-      <circle
-         transform="translate(14.95026,22.93047)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path5077"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5983);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path5079"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-    <g
-       inkscape:r_cy="true"
-       inkscape:r_cx="true"
-       transform="matrix(-0.806276,0.59154,0.59154,0.806276,13.4991,-31.50022)"
-       id="g4945">
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path4947"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="translate(14.95026,22.93047)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path4949"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-    <g
-       style="opacity:1"
-       id="g4939"
-       transform="matrix(-0.870227,0.638572,0.638458,0.870381,25.20503,-35.31278)"
-       inkscape:r_cx="true"
-       inkscape:r_cy="true">
-      <circle
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5989);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         id="path4941"
-         inkscape:r_cx="true"
-         inkscape:r_cy="true"
-         transform="translate(14.95026,22.93047)"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-      <circle
-         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
-         inkscape:r_cy="true"
-         inkscape:r_cx="true"
-         id="path4943"
-         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
-         cx="12.071323"
-         cy="12.493138"
-         r="6.7175145" />
-    </g>
-  </g>
-</svg>
diff --git a/flags/system/flag-jira.svg b/flags/system/flag-jira.svg
new file mode 100644 (file)
index 0000000..7f35cf2
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   height="128"
+   viewBox="2.59 0 11.606798 11.4688"
+   width="128"
+   version="1.1"
+   id="svg14"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs18">
+    <linearGradient
+       id="linearGradient1609">
+      <stop
+         style="stop-color:#0052cc;stop-opacity:1;"
+         offset="0"
+         id="stop1605" />
+      <stop
+         style="stop-color:#2684ff;stop-opacity:0;"
+         offset="1"
+         id="stop1607" />
+    </linearGradient>
+    <linearGradient
+       xlink:href="#a"
+       id="linearGradient855"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.05109566,0,0,-0.05132789,2.8787408,13.534242)"
+       x1="102.4"
+       y1="218.63"
+       x2="56.150002"
+       y2="172.39" />
+    <linearGradient
+       xlink:href="#linearGradient1609"
+       id="linearGradient1611"
+       x1="8.6326942"
+       y1="9.0570345"
+       x2="10.95546"
+       y2="6.6513"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <linearGradient
+     id="a"
+     gradientTransform="matrix(1,0,0,-1,0,264)"
+     gradientUnits="userSpaceOnUse"
+     x1="102.4"
+     x2="56.150002"
+     y1="218.63"
+     y2="172.39">
+    <stop
+       offset=".18"
+       stop-color="#0052cc"
+       id="stop2" />
+    <stop
+       offset="1"
+       stop-color="#2684ff"
+       id="stop4" />
+  </linearGradient>
+  <linearGradient
+     id="b"
+     x1="121.16464"
+     x2="160.81"
+     xlink:href="#a"
+     y1="171.41203"
+     y2="131.92"
+     gradientTransform="matrix(0.05109566,0,0,0.05132789,2.8787408,-0.01631941)" />
+  <path
+     d="M 13.816279,5.4105776 8.8911687,0.46308273 8.4139355,-0.01631955 4.7064346,3.7080318 3.0110802,5.4105776 a 0.45424045,0.45630485 0 0 0 0,0.6436518 l 3.3871316,3.4025248 2.0157237,2.0243718 3.7069905,-3.7243513 0.05774,-0.057487 1.637614,-1.6424918 a 0.45321853,0.45527832 0 0 0 0,-0.6462189 z M 8.4139355,7.4323824 6.7216472,5.7324032 8.4139355,4.0324238 10.105713,5.7324032 Z"
+     fill="#2684ff"
+     id="path8"
+     style="display:inline;stroke-width:0.0512116" />
+  <path
+     d="M 8.4139355,4.0324238 A 2.8485832,2.8615294 0 0 1 8.4016734,-0.0024621 L 4.6987706,3.7157308 6.7139836,5.7401027 Z"
+     fill="url(#a)"
+     id="path10"
+     style="display:inline;fill:url(#linearGradient855);stroke-width:0.0512116" />
+  <path
+     d="M 10.110311,5.7277836 8.4139355,7.4323824 a 2.8496051,2.8625559 0 0 1 0,4.0477176 L 12.127057,7.7521553 Z"
+     fill="url(#b)"
+     id="path12"
+     style="display:inline;fill:url(#linearGradient1611);stroke-width:0.0512116;fill-opacity:1" />
+</svg>
diff --git a/flags/system/flag-url.svg b/flags/system/flag-url.svg
new file mode 100644 (file)
index 0000000..632865e
--- /dev/null
@@ -0,0 +1,591 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48px"
+   height="48px"
+   id="svg3440"
+   sodipodi:version="0.32"
+   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
+   sodipodi:docname="applications-internet.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.1">
+  <defs
+     id="defs3">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective95" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6001">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop6003" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6005" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4825">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4827" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4829" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4126">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop4128" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.16494845;"
+         offset="1.0000000"
+         id="stop4130" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4114">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4116" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4118" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3962">
+      <stop
+         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop3964" />
+      <stop
+         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+         offset="0.15517241"
+         id="stop4134" />
+      <stop
+         style="stop-color:#4074ae;stop-opacity:1.0000000;"
+         offset="0.75000000"
+         id="stop4346" />
+      <stop
+         style="stop-color:#36486c;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop3966" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3962"
+       id="radialGradient3968"
+       gradientTransform="scale(0.999989,1.000011)"
+       cx="18.247644"
+       cy="15.716079"
+       fx="18.247644"
+       fy="15.716079"
+       r="29.993349"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4114"
+       id="radialGradient4120"
+       gradientTransform="scale(1.643990,0.608276)"
+       cx="15.115514"
+       cy="63.965388"
+       fx="15.115514"
+       fy="63.965388"
+       r="12.289036"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4126"
+       id="radialGradient4132"
+       gradientTransform="scale(0.999989,1.000011)"
+       cx="15.601279"
+       cy="12.142302"
+       fx="15.601279"
+       fy="12.142302"
+       r="43.526714"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5983"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5985"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5987"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5989"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6007"
+       x1="-25.176178"
+       y1="30.057165"
+       x2="-22.252472"
+       y2="21.041553"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6011"
+       gradientUnits="userSpaceOnUse"
+       x1="-25.176178"
+       y1="30.057165"
+       x2="-22.113543"
+       y2="22.661524" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6015"
+       gradientUnits="userSpaceOnUse"
+       x1="-22.822565"
+       y1="28.337734"
+       x2="-22.113543"
+       y2="22.661524" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6019"
+       gradientUnits="userSpaceOnUse"
+       x1="-21.658581"
+       y1="15.649428"
+       x2="-21.962101"
+       y2="21.336346" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.17254902"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.6568542"
+     inkscape:cx="-5.4339934"
+     inkscape:cy="25.586897"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1000"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:showpageshadow="false"
+     inkscape:document-rotation="0"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata4">
+    <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></dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>Tuomas Kuosmanen</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>internet</rdf:li>
+            <rdf:li>tools</rdf:li>
+            <rdf:li>applications</rdf:li>
+            <rdf:li>category</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <ellipse
+       style="display:inline;fill:url(#radialGradient4120);fill-opacity:1;stroke:none;stroke-opacity:1"
+       id="path4112"
+       transform="matrix(1,0,0,1.243244,0,-10.27241)"
+       cx="24.849752"
+       cy="38.908627"
+       rx="20.203051"
+       ry="7.4751287"
+       inkscape:label="shadow" />
+    <path
+       style="fill:url(#radialGradient3968);fill-opacity:1;fill-rule:nonzero;stroke:#39396c;stroke-miterlimit:4;stroke-opacity:1"
+       d="m 43.959853,23.485499 c 0,10.709718 -8.682103,19.391723 -19.390348,19.391723 -10.709226,0 -19.3908387,-8.682103 -19.3908387,-19.391723 0,-10.709227 8.6816127,-19.3903473 19.3908387,-19.3903473 10.708245,0 19.390348,8.6811203 19.390348,19.3903473 z"
+       id="path3214" />
+    <g
+       id="g4136"
+       style="opacity:1;fill:#204a87;fill-opacity:0.71345;fill-rule:nonzero;stroke:none;stroke-miterlimit:4"
+       transform="matrix(0.982371,0,0,0.982371,0.121079,0.232914)">
+      <g
+         id="g4138"
+         style="fill:#204a87">
+        <g
+           id="g4142"
+           style="fill:#204a87">
+          <path
+             d="m 44.0713,20.7144 c 0,0.2627 0,0 0,0 l -0.5449,0.6172 c -0.334,-0.3936 -0.709,-0.7246 -1.0898,-1.0703 l -0.8359,0.123 -0.7637,-0.8633 v 1.0684 l 0.6543,0.4951 0.4355,0.4932 0.582,-0.6582 c 0.1465,0.2744 0.291,0.5488 0.4365,0.8232 v 0.8223 l -0.6553,0.7402 -1.1992,0.8232 -0.9082,0.9063 -0.582,-0.6602 0.291,-0.7402 -0.5811,-0.6582 -0.9814,-2.0977 -0.8359,-0.9453 -0.2188,0.2461 0.3281,1.1934 0.6172,0.6992 c 0.3525,1.0176 0.7012,1.9902 1.1641,2.9629 0.7178,0 1.3945,-0.0762 2.1074,-0.166 v 0.5762 l -0.8721,2.1392 -0.7998,0.9043 -0.6543,1.4004 c 0,0.7676 0,1.5352 0,2.3027 l 0.2188,0.9063 -0.3633,0.4102 -0.8008,0.4941 -0.8359,0.6992 0.6914,0.7813 -0.9453,0.8242 0.1816,0.5332 -1.418,1.6055 h -0.9443 l -0.7998,0.4941 H 33.6396 V 38.2814 L 33.4228,36.963 c -0.2813,-0.8262 -0.5742,-1.6465 -0.8721,-2.4668 0,-0.6055 0.0361,-1.2051 0.0723,-1.8105 l 0.3643,-0.8223 -0.5098,-0.9883 0.0371,-1.3574 -0.6914,-0.7813 0.3457,-1.1309 -0.5625,-0.6382 H 30.624 l -0.3271,-0.3701 -0.9814,0.6177 -0.3994,-0.4536 -0.9092,0.7817 c -0.6172,-0.6997 -1.2354,-1.3989 -1.8535,-2.0981 l -0.7266,-1.7285 0.6543,-0.9863 -0.3633,-0.4111 0.7988,-1.8936 c 0.6563,-0.8164 1.3418,-1.5996 2.0352,-2.3857 l 1.2363,-0.3291 1.3809,-0.1641 0.9453,0.2471 1.3447,1.3564 0.4727,-0.5342 0.6533,-0.082 1.2363,0.4111 h 0.9453 l 0.6543,-0.5762 0.291,-0.4111 -0.6553,-0.4111 -1.0908,-0.082 c -0.3027,-0.4199 -0.584,-0.8613 -0.9434,-1.2344 l -0.3643,0.1641 -0.1455,1.0703 -0.6543,-0.7402 -0.1445,-0.8242 -0.7266,-0.5742 h -0.292 l 0.7275,0.8223 -0.291,0.7402 -0.5811,0.1641 0.3633,-0.7402 -0.6553,-0.3281 -0.5801,-0.6582 -1.0918,0.2461 -0.1445,0.3281 -0.6543,0.4121 -0.3633,0.9053 -0.9082,0.4521 -0.4004,-0.4521 h -0.4355 v -1.4814 l 0.9453,-0.4941 h 0.7266 l -0.1465,-0.5752 -0.5801,-0.5762 0.9805,-0.2061 0.5449,-0.6162 0.4355,-0.7412 h 0.8008 l -0.2188,-0.5752 0.5098,-0.3291 v 0.6582 l 1.0898,0.2461 1.0898,-0.9043 0.0732,-0.4121 0.9443,-0.6577 c -0.3418,0.0425 -0.6836,0.0737 -1.0176,0.1646 V 9.9766 L 34.2213,9.1538 H 33.858 l -0.7984,0.7402 -0.2188,0.4116 0.2188,0.5767 -0.3643,0.9863 -0.5811,-0.3291 -0.5078,-0.5752 -0.8008,0.5752 -0.291,-1.3159 1.3809,-0.9048 V 8.8247 l 0.873,-0.5757 1.3809,-0.3296 0.9453,0.3296 1.7441,0.3291 -0.4355,0.4932 H 35.458 l 0.9453,0.9873 0.7266,-0.8223 0.2207,-0.3618 c 0,0 2.7871,2.498 4.3799,5.2305 1.5928,2.7334 2.3408,5.9551 2.3408,6.6094 z"
+             id="path4144"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4146"
+         style="fill:#204a87">
+        <g
+           id="g4150"
+           style="fill:#204a87">
+          <path
+             d="m 26.0703,9.2363 -0.0732,0.4932 0.5098,0.3291 0.8711,-0.5757 -0.4355,-0.4937 -0.582,0.3296 -0.29,-0.0825"
+             id="path4152"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4154"
+         style="fill:#204a87">
+        <g
+           id="g4158"
+           style="fill:#204a87">
+          <path
+             d="m 26.8701,5.8633 -1.8906,-0.7407 -2.1797,0.2466 -2.6904,0.7402 -0.5088,0.4941 1.6719,1.1514 v 0.6582 l -0.6543,0.6582 0.873,1.729 0.5801,-0.3301 0.7285,-1.1514 c 1.123,-0.3472 2.1299,-0.7407 3.1973,-1.2344 l 0.873,-2.2212"
+             id="path4160"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4162"
+         style="fill:#204a87">
+        <g
+           id="g4166"
+           style="fill:#204a87">
+          <path
+             d="m 28.833,12.7749 -0.291,-0.7412 -0.5098,0.165 0.1465,0.9043 0.6543,-0.3281"
+             id="path4168"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4170"
+         style="fill:#204a87">
+        <g
+           id="g4174"
+           style="fill:#204a87">
+          <path
+             d="m 29.123,12.6089 -0.1455,0.9883 0.7998,-0.165 0.5811,-0.5752 -0.5088,-0.4941 C 29.6787,11.9078 29.4824,11.483 29.2685,11.0465 H 28.833 v 0.4932 l 0.29,0.3291 v 0.7402"
+             id="path4176"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4178"
+         style="fill:#204a87">
+        <g
+           id="g4182"
+           style="fill:#204a87">
+          <path
+             d="m 18.3652,28.2422 -0.582,-1.1523 -1.0903,-0.2466 -0.5815,-1.5625 -1.4536,0.1641 -1.2354,-0.9043 -1.3091,1.1514 v 0.1816 c -0.396,-0.1143 -0.8828,-0.1299 -1.2354,-0.3467 l -0.291,-0.8223 v -0.9053 l -0.8721,0.082 c 0.0728,-0.5762 0.145,-1.1514 0.2183,-1.7275 H 9.4238 L 8.9155,22.812 8.4062,23.0581 7.6791,22.6479 7.6063,21.7426 7.7518,20.7553 8.8426,19.933 h 0.8721 l 0.145,-0.4941 1.0903,0.2461 0.7998,0.9883 0.1455,-1.6465 1.3813,-1.1514 0.5088,-1.2344 1.0176,-0.4111 0.5815,-0.8223 1.3081,-0.248 0.6548,-0.9863 c -0.6543,0 -1.3086,0 -1.9629,0 l 1.2358,-0.5762 h 0.8716 l 1.2363,-0.4121 0.1455,-0.4922 -0.4365,-0.4121 -0.5088,-0.165 0.1455,-0.4932 -0.3633,-0.7402 -0.8726,0.3281 0.1455,-0.6577 -1.0176,-0.5762 -0.7993,1.3979 0.0723,0.4941 -0.7993,0.3301 -0.5093,1.0693 -0.2178,-0.9873 -1.3813,-0.5762 -0.2183,-0.7402 1.8174,-1.0703 0.7998,-0.7402 0.0728,-0.9048 -0.436,-0.2471 -0.5815,-0.0825 -0.3633,0.9053 c 0,0 -0.6079,0.1191 -0.7642,0.1577 -1.9961,1.8394 -6.0293,5.8101 -6.9663,13.3062 0.0371,0.1738 0.6792,1.1816 0.6792,1.1816 l 1.5264,0.9043 1.5264,0.4121 0.6548,0.8232 1.0171,0.7402 0.5815,-0.082 0.436,0.1963 v 0.1328 l -0.5811,1.563 -0.4365,0.6582 0.1455,0.3301 -0.3633,1.2324 1.3086,2.3867 1.3081,1.1523 0.582,0.8223 -0.0732,1.7285 0.4365,0.9863 -0.4365,1.8926 c 0,0 -0.0342,-0.0117 0.0215,0.1777 0.0562,0.1895 2.3291,1.4512 2.4736,1.3438 0.144,-0.1094 0.2671,-0.2051 0.2671,-0.2051 l -0.145,-0.4102 0.5811,-0.5762 0.2183,-0.5762 0.9453,-0.3301 0.7266,-1.8105 -0.2178,-0.4922 0.5078,-0.7402 1.0908,-0.248 0.582,-1.3164 -0.1455,-1.6445 0.8721,-1.2344 0.1455,-1.2344 C 20.7331,29.4607 19.5495,28.8513 18.365,28.242"
+             id="path4184"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4186"
+         style="fill:#204a87">
+        <g
+           id="g4190"
+           style="fill:#204a87">
+          <path
+             d="m 16.7656,9.5649 0.7266,0.4937 h 0.582 V 9.4829 l -0.7266,-0.3291 -0.582,0.4111"
+             id="path4192"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4194"
+         style="fill:#204a87">
+        <g
+           id="g4198"
+           style="fill:#204a87">
+          <path
+             d="M 14.876,8.9072 14.5122,9.812 h 0.7271 L 15.6031,8.9892 C 15.9166,8.7675 16.2286,8.5444 16.5479,8.331 l 0.7271,0.2471 c 0.4844,0.3291 0.9688,0.6582 1.4536,0.9868 L 19.4561,8.9072 18.6558,8.5781 18.292,7.8374 16.9111,7.6728 16.8383,7.2612 16.184,7.4262 15.8936,8.002 15.5298,7.2613 l -0.145,0.3291 0.0728,0.8228 -0.5816,0.494"
+             id="path4200"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4202"
+         style="fill:#204a87">
+        <g
+           style="opacity:0.75;fill:#204a87"
+           id="g4204">
+          <path
+             id="path4206"
+             d=""
+             style="fill:#204a87" />
+        </g>
+        <g
+           id="g4208"
+           style="fill:#204a87">
+          <path
+             id="path4210"
+             d=""
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4212"
+         style="fill:#204a87">
+        <g
+           style="opacity:0.75;fill:#204a87"
+           id="g4214">
+          <path
+             id="path4216"
+             d=""
+             style="fill:#204a87" />
+        </g>
+        <g
+           id="g4218"
+           style="fill:#204a87">
+          <path
+             id="path4220"
+             d=""
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4222"
+         style="fill:#204a87">
+        <g
+           id="g4226"
+           style="fill:#204a87">
+          <path
+             d="M 17.4922,6.8496 17.856,6.521 18.5831,6.3564 c 0.498,-0.2422 0.998,-0.4053 1.5264,-0.5762 l -0.29,-0.4937 -0.9385,0.1348 -0.4434,0.4419 -0.731,0.106 -0.6499,0.3052 -0.3159,0.1528 -0.1929,0.2583 0.9443,0.1641"
+             id="path4228"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4230"
+         style="fill:#204a87">
+        <g
+           id="g4234"
+           style="fill:#204a87">
+          <path
+             d="m 18.7285,14.6665 0.4365,-0.6582 -0.6548,-0.4932 0.2183,1.1514"
+             id="path4236"
+             style="fill:#204a87" />
+        </g>
+      </g>
+    </g>
+    <path
+       style="opacity:0.395604;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient4132);stroke-miterlimit:4;stroke-opacity:1"
+       d="m 42.975093,23.485534 c 0,10.16582 -8.241178,18.406906 -18.4056,18.406906 -10.165354,0 -18.4060669,-8.241179 -18.4060669,-18.406906 0,-10.165354 8.2407129,-18.4056 18.4060669,-18.4056 10.164422,0 18.4056,8.240246 18.4056,18.4056 z"
+       id="path4122" />
+    <ellipse
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6007);stroke-width:0.881642;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       id="path5991"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       transform="matrix(1.131034,0.613097,-0.476556,0.879144,54.09058,16.04435)"
+       cx="-18.561554"
+       cy="21.041553"
+       rx="15.733126"
+       ry="9.4575529" />
+    <ellipse
+       transform="matrix(0.939326,-0.879086,0.683307,0.730131,32.31406,-4.451561)"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       id="path6009"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6011);stroke-width:0.881642;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       cx="-18.561554"
+       cy="21.041553"
+       rx="15.733126"
+       ry="9.4575529" />
+    <g
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       transform="matrix(-1.045772,0.767251,0.767251,1.045772,35.61651,-22.14396)"
+       id="g4933">
+      <circle
+         transform="translate(14.95026,22.93047)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path4935"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5987);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path4937"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+    <ellipse
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6015);stroke-width:0.881642;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       id="path6013"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       transform="matrix(-1.280316,-0.126159,0.09806226,-0.99518,-2.405125,40.52387)"
+       cx="-18.561554"
+       cy="21.041553"
+       rx="15.733126"
+       ry="9.4575529" />
+    <ellipse
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6019);stroke-width:0.902261;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       id="path6017"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       transform="matrix(0.917874,-0.858983,0.667701,0.713433,27.63317,-6.909069)"
+       cx="-18.561554"
+       cy="21.041553"
+       rx="15.733126"
+       ry="9.4575529" />
+    <g
+       id="g5075"
+       transform="matrix(-0.806276,0.59154,0.59154,0.806276,12.38564,-18.02921)"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true">
+      <circle
+         transform="translate(14.95026,22.93047)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path5077"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5983);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path5079"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+    <g
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       transform="matrix(-0.806276,0.59154,0.59154,0.806276,13.4991,-31.50022)"
+       id="g4945">
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path4947"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="translate(14.95026,22.93047)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path4949"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+    <g
+       style="opacity:1"
+       id="g4939"
+       transform="matrix(-0.870227,0.638572,0.638458,0.870381,25.20503,-35.31278)"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true">
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5989);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path4941"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="translate(14.95026,22.93047)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path4943"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+  </g>
+</svg>
diff --git a/flags/system/flag-urlnew.svg b/flags/system/flag-urlnew.svg
new file mode 100644 (file)
index 0000000..72532d0
--- /dev/null
@@ -0,0 +1,1084 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48px"
+   height="48px"
+   id="svg3440"
+   sodipodi:version="0.32"
+   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
+   sodipodi:docname="applications-internet-new.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.1">
+  <defs
+     id="defs3">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective95" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6001">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop6003" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6005" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4825">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4827" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4829" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4126">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop4128" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.16494845;"
+         offset="1.0000000"
+         id="stop4130" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4114">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4116" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4118" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3962">
+      <stop
+         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop3964" />
+      <stop
+         style="stop-color:#d3e9ff;stop-opacity:1.0000000;"
+         offset="0.15517241"
+         id="stop4134" />
+      <stop
+         style="stop-color:#4074ae;stop-opacity:1.0000000;"
+         offset="0.75000000"
+         id="stop4346" />
+      <stop
+         style="stop-color:#36486c;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop3966" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3962"
+       id="radialGradient3968"
+       gradientTransform="matrix(0.79959032,0,0,0.79960792,9.1985908,0.72047157)"
+       cx="18.247644"
+       cy="15.716079"
+       fx="18.247644"
+       fy="15.716079"
+       r="29.993349"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4114"
+       id="radialGradient4120"
+       gradientTransform="matrix(1.314533,0,0,0.60468523,9.1985908,-7.4933384)"
+       cx="15.115514"
+       cy="63.965388"
+       fx="15.115514"
+       fy="63.965388"
+       r="12.289036"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4126"
+       id="radialGradient4132"
+       gradientTransform="matrix(0.79959032,0,0,0.79960792,9.1985908,0.72047157)"
+       cx="15.601279"
+       cy="12.142302"
+       fx="15.601279"
+       fy="12.142302"
+       r="43.526714"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5983"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5985"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5987"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4825"
+       id="radialGradient5989"
+       gradientUnits="userSpaceOnUse"
+       cx="12.071323"
+       cy="12.493138"
+       fx="12.071323"
+       fy="12.493138"
+       r="6.7175145" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6007"
+       x1="-25.176178"
+       y1="30.057165"
+       x2="-22.252472"
+       y2="21.041553"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.0286978,0,0,0.79959904,52.56766,-13.083065)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6011"
+       gradientUnits="userSpaceOnUse"
+       x1="-25.176178"
+       y1="30.057165"
+       x2="-22.113543"
+       y2="22.661524"
+       gradientTransform="matrix(1.0286977,0,0,0.79959901,27.521423,21.868113)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6015"
+       gradientUnits="userSpaceOnUse"
+       x1="-22.822565"
+       y1="28.337734"
+       x2="-22.113543"
+       y2="22.661524"
+       gradientTransform="matrix(1.0286976,0,0,0.79959889,-10.488538,-32.250227)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient6019"
+       gradientUnits="userSpaceOnUse"
+       x1="-21.658581"
+       y1="15.649428"
+       x2="-21.962101"
+       y2="21.336346"
+       gradientTransform="matrix(1.0051901,0,0,0.78132384,26.131093,17.875478)" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="120"
+       cy="27.3013"
+       cx="232.5"
+       id="radialGradient4574">
+      <stop
+         id="stop4576"
+         style="stop-color:#ffee93;stop-opacity:1;"
+         offset="0" />
+      <stop
+         offset="0.3388288"
+         style="stop-color:#fff211;stop-opacity:1;"
+         id="stop4578" />
+      <stop
+         offset="0.59700626"
+         style="stop-color:#ffff32;stop-opacity:1"
+         id="stop4580" />
+      <stop
+         id="stop4582"
+         style="stop-color:#ffe171;stop-opacity:1;"
+         offset="1" />
+    </radialGradient>
+    <radialGradient
+       id="radialGradient24014"
+       cx="232.5"
+       cy="27.3013"
+       r="120"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         offset="0"
+         style="stop-color:#ffee93;stop-opacity:1;"
+         id="stop24016" />
+      <stop
+         id="stop24018"
+         style="stop-color:#c57c00;stop-opacity:1"
+         offset="0.49229774" />
+      <stop
+         id="stop24020"
+         style="stop-color:#ffff7d;stop-opacity:1;"
+         offset="0.59700626" />
+      <stop
+         offset="1"
+         style="stop-color:#ffe171;stop-opacity:1;"
+         id="stop24022" />
+    </radialGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="120"
+       cy="27.3013"
+       cx="232.5"
+       id="radialGradient2810-4">
+      <stop
+         id="stop2812-5"
+         style="stop-color:#ffee93;stop-opacity:1;"
+         offset="0" />
+      <stop
+         offset="0.3773585"
+         style="stop-color:#c57c00;stop-opacity:1;"
+         id="stop3686" />
+      <stop
+         offset="0.49483803"
+         style="stop-color:#ffff7d;stop-opacity:1;"
+         id="stop2816-0" />
+      <stop
+         id="stop2820-3"
+         style="stop-color:#ffe171;stop-opacity:1;"
+         offset="1" />
+    </radialGradient>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath24074">
+      <path
+         sodipodi:type="star"
+         style="opacity:0.39436622;fill:url(#linearGradient24078);fill-opacity:1;stroke:none"
+         id="path24076"
+         sodipodi:sides="11"
+         sodipodi:cx="90.156113"
+         sodipodi:cy="85.220039"
+         sodipodi:r1="19.827379"
+         sodipodi:r2="13.362659"
+         sodipodi:arg1="0.78539816"
+         sodipodi:arg2="1.0519012"
+         inkscape:flatsided="false"
+         inkscape:rounded="0"
+         inkscape:randomized="0"
+         d="m 104.17619,99.240114 -7.393254,-2.416374 -2.412211,7.77056 -4.913208,-6.029875 -6.230363,5.232875 -0.873257,-7.728938 -8.070419,1.033783 3.443947,-6.974112 -7.348174,-3.493525 6.667723,-4.005058 -4.292936,-6.911662 7.774544,0.235574 0.125279,-8.135397 6.413001,4.401413 4.50372,-6.7762 3.015376,7.169834 7.452262,-3.265607 -1.33961,7.661884 8.03476,1.281791 -5.26928,5.72134 6.06628,5.422232 -7.52598,1.964311 z"
+         transform="translate(80,-0.9385641)" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient24014"
+       id="linearGradient24078"
+       gradientUnits="userSpaceOnUse"
+       x1="73.711586"
+       y1="71.214951"
+       x2="89.811958"
+       y2="99.101616" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="120"
+       cy="27.3013"
+       cx="232.5"
+       id="radialGradient4574-6">
+      <stop
+         id="stop4576-7"
+         style="stop-color:#ffee93;stop-opacity:1;"
+         offset="0" />
+      <stop
+         offset="0.3388288"
+         style="stop-color:#fff211;stop-opacity:1;"
+         id="stop4578-5" />
+      <stop
+         offset="0.59700626"
+         style="stop-color:#ffff32;stop-opacity:1"
+         id="stop4580-3" />
+      <stop
+         id="stop4582-5"
+         style="stop-color:#ffe171;stop-opacity:1;"
+         offset="1" />
+    </radialGradient>
+    <linearGradient
+       y2="104.80668"
+       x2="-62.424866"
+       y1="76.708466"
+       x1="-13.757333"
+       gradientTransform="translate(148,19.999992)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4794"
+       xlink:href="#XMLID_4_"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.9792,0,0,0.9725,133.0002,20.8762)"
+       r="55.147999"
+       cy="-0.2148"
+       cx="48"
+       id="XMLID_4_">
+      <stop
+         id="stop3082"
+         style="stop-color:#72D13D"
+         offset="0" />
+      <stop
+         id="stop3084"
+         style="stop-color:#35AC1C"
+         offset="0.3553" />
+      <stop
+         id="stop3086"
+         style="stop-color:#0F9508"
+         offset="0.6194" />
+      <stop
+         id="stop3088"
+         style="stop-color:#008C00"
+         offset="0.7574" />
+      <stop
+         id="stop3090"
+         style="stop-color:#007A00"
+         offset="1" />
+    </radialGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient3571"
+       gradientUnits="userSpaceOnUse"
+       x1="73.742638"
+       y1="15.336544"
+       x2="80"
+       y2="19.281664"
+       spreadMethod="reflect" />
+    <filter
+       id="filter3387"
+       height="1.249912"
+       y="-0.12495601"
+       width="1.2041403"
+       x="-0.10207015"
+       inkscape:collect="always">
+      <feGaussianBlur
+         id="feGaussianBlur3389"
+         stdDeviation="0.44655691"
+         inkscape:collect="always" />
+    </filter>
+    <radialGradient
+       r="6.7806501"
+       fy="17.83758"
+       fx="73.656624"
+       cy="17.83758"
+       cx="73.656624"
+       gradientTransform="matrix(1,0,0,0.8708964,0,2.3028957)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient4800"
+       xlink:href="#linearGradient5412"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5412"
+       gradientUnits="userSpaceOnUse"
+       x1="28"
+       y1="57.5"
+       x2="28"
+       y2="0">
+      <stop
+         offset="0"
+         style="stop-color:#fff14d;stop-opacity:1;"
+         id="stop5414" />
+      <stop
+         offset="1"
+         style="stop-color:#f8ffa0;stop-opacity:0;"
+         id="stop5416" />
+    </linearGradient>
+    <radialGradient
+       r="6.2063885"
+       fy="17.802542"
+       fx="73.082359"
+       cy="17.802542"
+       cx="73.082359"
+       gradientTransform="matrix(1,0,0,0.9256542,0,1.3235438)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient4802"
+       xlink:href="#linearGradient4770"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient4770"
+       gradientUnits="userSpaceOnUse"
+       x1="-84.002403"
+       y1="-383.9971"
+       x2="-12.0029"
+       y2="-383.9971"
+       gradientTransform="rotate(90,-90.0007,50.0022)">
+      <stop
+         offset="0"
+         style="stop-color:#e5ff00;stop-opacity:1"
+         id="stop4772" />
+      <stop
+         offset="1"
+         style="stop-color:#bff500;stop-opacity:0;"
+         id="stop4774" />
+    </linearGradient>
+    <radialGradient
+       r="24"
+       fy="104"
+       fx="104"
+       cy="104"
+       cx="104"
+       gradientTransform="translate(0,-1.3e-5)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient4806"
+       xlink:href="#linearGradient3030"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3030"
+       inkscape:collect="always">
+      <stop
+         id="stop3032"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:0.77902622" />
+      <stop
+         id="stop3034"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       r="20"
+       fy="96"
+       fx="-40"
+       cy="84"
+       cx="-44"
+       gradientTransform="translate(148,19.999992)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient4810"
+       xlink:href="#XMLID_4_"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.9792,0,0,0.9725,133.0002,20.8762)"
+       r="55.147999"
+       cy="-0.2148"
+       cx="48"
+       id="radialGradient1513">
+      <stop
+         id="stop1503"
+         style="stop-color:#72D13D"
+         offset="0" />
+      <stop
+         id="stop1505"
+         style="stop-color:#35AC1C"
+         offset="0.3553" />
+      <stop
+         id="stop1507"
+         style="stop-color:#0F9508"
+         offset="0.6194" />
+      <stop
+         id="stop1509"
+         style="stop-color:#008C00"
+         offset="0.7574" />
+      <stop
+         id="stop1511"
+         style="stop-color:#007A00"
+         offset="1" />
+    </radialGradient>
+    <linearGradient
+       y2="108.0104"
+       x2="11.68106"
+       y1="60.539303"
+       x1="11.68106"
+       gradientTransform="translate(85.3125,19.999992)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4812"
+       xlink:href="#linearGradient6001"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="96.001434"
+       x2="11.68106"
+       y1="52"
+       x1="6.6976352"
+       gradientTransform="translate(85.30236,19.999992)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4814"
+       xlink:href="#linearGradient6001"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="72"
+       x2="14.697635"
+       y1="96"
+       x1="26.697636"
+       gradientTransform="translate(85.30236,19.999992)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4816"
+       xlink:href="#linearGradient6001"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="84"
+       x2="120.25"
+       y1="84"
+       x1="79.75"
+       gradientTransform="translate(3.99999,19.999992)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4818"
+       xlink:href="#linearGradient3225"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3225">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3227" />
+      <stop
+         style="stop-color:#aeaeae;stop-opacity:1;"
+         offset="1"
+         id="stop3229" />
+    </linearGradient>
+    <filter
+       id="filter3191"
+       inkscape:collect="always">
+      <feGaussianBlur
+         id="feGaussianBlur3193"
+         stdDeviation="0.2025"
+         inkscape:collect="always" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient1937"
+       gradientUnits="userSpaceOnUse"
+       x1="73.742638"
+       y1="15.336544"
+       x2="80"
+       y2="19.281664"
+       spreadMethod="reflect" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient1939"
+       gradientUnits="userSpaceOnUse"
+       x1="73.742638"
+       y1="15.336544"
+       x2="80"
+       y2="19.281664"
+       spreadMethod="reflect" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6001"
+       id="linearGradient1941"
+       gradientUnits="userSpaceOnUse"
+       x1="73.742638"
+       y1="15.336544"
+       x2="80"
+       y2="19.281664"
+       spreadMethod="reflect" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.17254902"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.6568542"
+     inkscape:cx="5.0143305"
+     inkscape:cy="27.22336"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1000"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:showpageshadow="false"
+     inkscape:document-rotation="0"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata4">
+    <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></dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>Tuomas Kuosmanen</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>internet</rdf:li>
+            <rdf:li>tools</rdf:li>
+            <rdf:li>applications</rdf:li>
+            <rdf:li>category</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     style="display:inline">
+    <ellipse
+       style="display:inline;fill:url(#radialGradient4120);fill-opacity:1;stroke:none;stroke-width:0.89156;stroke-opacity:1"
+       id="path4112"
+       cx="29.06843"
+       cy="31.185602"
+       rx="16.154341"
+       ry="7.4310017"
+       inkscape:label="shadow" />
+    <path
+       style="fill:url(#radialGradient3968);fill-opacity:1;fill-rule:nonzero;stroke:#39396c;stroke-width:0.799599;stroke-miterlimit:4;stroke-opacity:1"
+       d="m 44.34885,19.499456 c 0,8.563481 -6.942201,15.505604 -15.504505,15.505604 -8.563087,0 -15.504897,-6.942201 -15.504897,-15.505604 0,-8.563089 6.94181,-15.5045047 15.504897,-15.5045047 8.562304,0 15.504505,6.9414157 15.504505,15.5045047 z"
+       id="path3214" />
+    <g
+       id="g4136"
+       style="opacity:1;fill:#204a87;fill-opacity:0.71345;fill-rule:nonzero;stroke:none;stroke-miterlimit:4"
+       transform="matrix(0.78550298,0,0,0.78550298,9.2954054,0.9067094)">
+      <g
+         id="g4138"
+         style="fill:#204a87">
+        <g
+           id="g4142"
+           style="fill:#204a87">
+          <path
+             d="m 44.0713,20.7144 c 0,0.2627 0,0 0,0 l -0.5449,0.6172 c -0.334,-0.3936 -0.709,-0.7246 -1.0898,-1.0703 l -0.8359,0.123 -0.7637,-0.8633 v 1.0684 l 0.6543,0.4951 0.4355,0.4932 0.582,-0.6582 c 0.1465,0.2744 0.291,0.5488 0.4365,0.8232 v 0.8223 l -0.6553,0.7402 -1.1992,0.8232 -0.9082,0.9063 -0.582,-0.6602 0.291,-0.7402 -0.5811,-0.6582 -0.9814,-2.0977 -0.8359,-0.9453 -0.2188,0.2461 0.3281,1.1934 0.6172,0.6992 c 0.3525,1.0176 0.7012,1.9902 1.1641,2.9629 0.7178,0 1.3945,-0.0762 2.1074,-0.166 v 0.5762 l -0.8721,2.1392 -0.7998,0.9043 -0.6543,1.4004 c 0,0.7676 0,1.5352 0,2.3027 l 0.2188,0.9063 -0.3633,0.4102 -0.8008,0.4941 -0.8359,0.6992 0.6914,0.7813 -0.9453,0.8242 0.1816,0.5332 -1.418,1.6055 h -0.9443 l -0.7998,0.4941 H 33.6396 V 38.2814 L 33.4228,36.963 c -0.2813,-0.8262 -0.5742,-1.6465 -0.8721,-2.4668 0,-0.6055 0.0361,-1.2051 0.0723,-1.8105 l 0.3643,-0.8223 -0.5098,-0.9883 0.0371,-1.3574 -0.6914,-0.7813 0.3457,-1.1309 -0.5625,-0.6382 H 30.624 l -0.3271,-0.3701 -0.9814,0.6177 -0.3994,-0.4536 -0.9092,0.7817 c -0.6172,-0.6997 -1.2354,-1.3989 -1.8535,-2.0981 l -0.7266,-1.7285 0.6543,-0.9863 -0.3633,-0.4111 0.7988,-1.8936 c 0.6563,-0.8164 1.3418,-1.5996 2.0352,-2.3857 l 1.2363,-0.3291 1.3809,-0.1641 0.9453,0.2471 1.3447,1.3564 0.4727,-0.5342 0.6533,-0.082 1.2363,0.4111 h 0.9453 l 0.6543,-0.5762 0.291,-0.4111 -0.6553,-0.4111 -1.0908,-0.082 c -0.3027,-0.4199 -0.584,-0.8613 -0.9434,-1.2344 l -0.3643,0.1641 -0.1455,1.0703 -0.6543,-0.7402 -0.1445,-0.8242 -0.7266,-0.5742 h -0.292 l 0.7275,0.8223 -0.291,0.7402 -0.5811,0.1641 0.3633,-0.7402 -0.6553,-0.3281 -0.5801,-0.6582 -1.0918,0.2461 -0.1445,0.3281 -0.6543,0.4121 -0.3633,0.9053 -0.9082,0.4521 -0.4004,-0.4521 h -0.4355 v -1.4814 l 0.9453,-0.4941 h 0.7266 l -0.1465,-0.5752 -0.5801,-0.5762 0.9805,-0.2061 0.5449,-0.6162 0.4355,-0.7412 h 0.8008 l -0.2188,-0.5752 0.5098,-0.3291 v 0.6582 l 1.0898,0.2461 1.0898,-0.9043 0.0732,-0.4121 0.9443,-0.6577 c -0.3418,0.0425 -0.6836,0.0737 -1.0176,0.1646 V 9.9766 L 34.2213,9.1538 H 33.858 l -0.7984,0.7402 -0.2188,0.4116 0.2188,0.5767 -0.3643,0.9863 -0.5811,-0.3291 -0.5078,-0.5752 -0.8008,0.5752 -0.291,-1.3159 1.3809,-0.9048 V 8.8247 l 0.873,-0.5757 1.3809,-0.3296 0.9453,0.3296 1.7441,0.3291 -0.4355,0.4932 H 35.458 l 0.9453,0.9873 0.7266,-0.8223 0.2207,-0.3618 c 0,0 2.7871,2.498 4.3799,5.2305 1.5928,2.7334 2.3408,5.9551 2.3408,6.6094 z"
+             id="path4144"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4146"
+         style="fill:#204a87">
+        <g
+           id="g4150"
+           style="fill:#204a87">
+          <path
+             d="m 26.0703,9.2363 -0.0732,0.4932 0.5098,0.3291 0.8711,-0.5757 -0.4355,-0.4937 -0.582,0.3296 -0.29,-0.0825"
+             id="path4152"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4154"
+         style="fill:#204a87">
+        <g
+           id="g4158"
+           style="fill:#204a87">
+          <path
+             d="m 26.8701,5.8633 -1.8906,-0.7407 -2.1797,0.2466 -2.6904,0.7402 -0.5088,0.4941 1.6719,1.1514 v 0.6582 l -0.6543,0.6582 0.873,1.729 0.5801,-0.3301 0.7285,-1.1514 c 1.123,-0.3472 2.1299,-0.7407 3.1973,-1.2344 l 0.873,-2.2212"
+             id="path4160"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4162"
+         style="fill:#204a87">
+        <g
+           id="g4166"
+           style="fill:#204a87">
+          <path
+             d="m 28.833,12.7749 -0.291,-0.7412 -0.5098,0.165 0.1465,0.9043 0.6543,-0.3281"
+             id="path4168"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4170"
+         style="fill:#204a87">
+        <g
+           id="g4174"
+           style="fill:#204a87">
+          <path
+             d="m 29.123,12.6089 -0.1455,0.9883 0.7998,-0.165 0.5811,-0.5752 -0.5088,-0.4941 C 29.6787,11.9078 29.4824,11.483 29.2685,11.0465 H 28.833 v 0.4932 l 0.29,0.3291 v 0.7402"
+             id="path4176"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4178"
+         style="fill:#204a87">
+        <g
+           id="g4182"
+           style="fill:#204a87">
+          <path
+             d="m 18.3652,28.2422 -0.582,-1.1523 -1.0903,-0.2466 -0.5815,-1.5625 -1.4536,0.1641 -1.2354,-0.9043 -1.3091,1.1514 v 0.1816 c -0.396,-0.1143 -0.8828,-0.1299 -1.2354,-0.3467 l -0.291,-0.8223 v -0.9053 l -0.8721,0.082 c 0.0728,-0.5762 0.145,-1.1514 0.2183,-1.7275 H 9.4238 L 8.9155,22.812 8.4062,23.0581 7.6791,22.6479 7.6063,21.7426 7.7518,20.7553 8.8426,19.933 h 0.8721 l 0.145,-0.4941 1.0903,0.2461 0.7998,0.9883 0.1455,-1.6465 1.3813,-1.1514 0.5088,-1.2344 1.0176,-0.4111 0.5815,-0.8223 1.3081,-0.248 0.6548,-0.9863 c -0.6543,0 -1.3086,0 -1.9629,0 l 1.2358,-0.5762 h 0.8716 l 1.2363,-0.4121 0.1455,-0.4922 -0.4365,-0.4121 -0.5088,-0.165 0.1455,-0.4932 -0.3633,-0.7402 -0.8726,0.3281 0.1455,-0.6577 -1.0176,-0.5762 -0.7993,1.3979 0.0723,0.4941 -0.7993,0.3301 -0.5093,1.0693 -0.2178,-0.9873 -1.3813,-0.5762 -0.2183,-0.7402 1.8174,-1.0703 0.7998,-0.7402 0.0728,-0.9048 -0.436,-0.2471 -0.5815,-0.0825 -0.3633,0.9053 c 0,0 -0.6079,0.1191 -0.7642,0.1577 -1.9961,1.8394 -6.0293,5.8101 -6.9663,13.3062 0.0371,0.1738 0.6792,1.1816 0.6792,1.1816 l 1.5264,0.9043 1.5264,0.4121 0.6548,0.8232 1.0171,0.7402 0.5815,-0.082 0.436,0.1963 v 0.1328 l -0.5811,1.563 -0.4365,0.6582 0.1455,0.3301 -0.3633,1.2324 1.3086,2.3867 1.3081,1.1523 0.582,0.8223 -0.0732,1.7285 0.4365,0.9863 -0.4365,1.8926 c 0,0 -0.0342,-0.0117 0.0215,0.1777 0.0562,0.1895 2.3291,1.4512 2.4736,1.3438 0.144,-0.1094 0.2671,-0.2051 0.2671,-0.2051 l -0.145,-0.4102 0.5811,-0.5762 0.2183,-0.5762 0.9453,-0.3301 0.7266,-1.8105 -0.2178,-0.4922 0.5078,-0.7402 1.0908,-0.248 0.582,-1.3164 -0.1455,-1.6445 0.8721,-1.2344 0.1455,-1.2344 C 20.7331,29.4607 19.5495,28.8513 18.365,28.242"
+             id="path4184"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4186"
+         style="fill:#204a87">
+        <g
+           id="g4190"
+           style="fill:#204a87">
+          <path
+             d="m 16.7656,9.5649 0.7266,0.4937 h 0.582 V 9.4829 l -0.7266,-0.3291 -0.582,0.4111"
+             id="path4192"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4194"
+         style="fill:#204a87">
+        <g
+           id="g4198"
+           style="fill:#204a87">
+          <path
+             d="M 14.876,8.9072 14.5122,9.812 h 0.7271 L 15.6031,8.9892 C 15.9166,8.7675 16.2286,8.5444 16.5479,8.331 l 0.7271,0.2471 c 0.4844,0.3291 0.9688,0.6582 1.4536,0.9868 L 19.4561,8.9072 18.6558,8.5781 18.292,7.8374 16.9111,7.6728 16.8383,7.2612 16.184,7.4262 15.8936,8.002 15.5298,7.2613 l -0.145,0.3291 0.0728,0.8228 -0.5816,0.494"
+             id="path4200"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4202"
+         style="fill:#204a87">
+        <g
+           style="opacity:0.75;fill:#204a87"
+           id="g4204">
+          <path
+             id="path4206"
+             d=""
+             style="fill:#204a87" />
+        </g>
+        <g
+           id="g4208"
+           style="fill:#204a87">
+          <path
+             id="path4210"
+             d=""
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4212"
+         style="fill:#204a87">
+        <g
+           style="opacity:0.75;fill:#204a87"
+           id="g4214">
+          <path
+             id="path4216"
+             d=""
+             style="fill:#204a87" />
+        </g>
+        <g
+           id="g4218"
+           style="fill:#204a87">
+          <path
+             id="path4220"
+             d=""
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4222"
+         style="fill:#204a87">
+        <g
+           id="g4226"
+           style="fill:#204a87">
+          <path
+             d="M 17.4922,6.8496 17.856,6.521 18.5831,6.3564 c 0.498,-0.2422 0.998,-0.4053 1.5264,-0.5762 l -0.29,-0.4937 -0.9385,0.1348 -0.4434,0.4419 -0.731,0.106 -0.6499,0.3052 -0.3159,0.1528 -0.1929,0.2583 0.9443,0.1641"
+             id="path4228"
+             style="fill:#204a87" />
+        </g>
+      </g>
+      <g
+         id="g4230"
+         style="fill:#204a87">
+        <g
+           id="g4234"
+           style="fill:#204a87">
+          <path
+             d="m 18.7285,14.6665 0.4365,-0.6582 -0.6548,-0.4932 0.2183,1.1514"
+             id="path4236"
+             style="fill:#204a87" />
+        </g>
+      </g>
+    </g>
+    <path
+       style="opacity:0.395604;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient4132);stroke-width:0.799599;stroke-miterlimit:4;stroke-opacity:1"
+       d="m 43.561437,19.499484 c 0,8.128581 -6.589638,14.718146 -14.717101,14.718146 -8.128208,0 -14.717475,-6.58964 -14.717475,-14.718146 0,-8.128208 6.589267,-14.7171017 14.717475,-14.7171017 8.127463,0 14.717101,6.5888937 14.717101,14.7171017 z"
+       id="path4122" />
+    <ellipse
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6007);stroke-width:0.799599;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       id="path5991"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       transform="rotate(28.460691)"
+       cx="33.473431"
+       cy="3.7417412"
+       rx="16.184631"
+       ry="7.5622501" />
+    <ellipse
+       transform="rotate(-43.10261)"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       id="path6009"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6011);stroke-width:0.799599;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       cx="8.4271946"
+       cy="38.692917"
+       rx="16.184631"
+       ry="7.5622501" />
+    <g
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       transform="matrix(-0.83619837,0.61349322,0.61349322,0.83619837,37.677521,-16.985819)"
+       id="g4933">
+      <circle
+         transform="translate(14.95026,22.93047)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path4935"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5987);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path4937"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+    <ellipse
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6015);stroke-width:0.799599;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       id="path6013"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       transform="rotate(-174.37239)"
+       cx="-29.582764"
+       cy="-15.425425"
+       rx="16.184629"
+       ry="7.5622487" />
+    <ellipse
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6019);stroke-width:0.799598;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+       id="path6017"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true"
+       transform="matrix(0.73014176,-0.6832957,0.68331862,0.7301203,0,0)"
+       cx="7.4732032"
+       cy="34.315746"
+       rx="15.814781"
+       ry="7.3894114" />
+    <g
+       id="g5075"
+       transform="matrix(-0.64469758,0.47299486,0.47299486,0.64469758,19.102138,-13.695669)"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true">
+      <circle
+         transform="translate(14.95026,22.93047)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path5077"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5983);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path5079"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+    <g
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       transform="matrix(-0.64469758,0.47299486,0.47299486,0.64469758,19.992459,-24.467077)"
+       id="g4945">
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path4947"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="translate(14.95026,22.93047)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path4949"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+    <g
+       style="opacity:1"
+       id="g4939"
+       transform="matrix(-0.69583274,0.51060161,0.51051045,0.69595588,29.35251,-27.515596)"
+       inkscape:r_cx="true"
+       inkscape:r_cy="true">
+      <circle
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient5989);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         id="path4941"
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         transform="translate(14.95026,22.93047)"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+      <circle
+         transform="matrix(0.308271,0,0,0.308271,23.30035,31.57234)"
+         inkscape:r_cy="true"
+         inkscape:r_cx="true"
+         id="path4943"
+         style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+         cx="12.071323"
+         cy="12.493138"
+         r="6.7175145" />
+    </g>
+    <g
+       id="g4655"
+       transform="matrix(0.42965914,0,0,0.42965914,-32.525869,-7.5145594)"
+       inkscape:label="plus">
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient4794);fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
+         d="m 102.0625,79.999994 c -3.31753,0 -6.0625,2.74498 -6.0625,6.0625 v 9.9375 h -9.9375 c -3.31753,0 -6.0625,2.74498 -6.0625,6.062496 v 3.875 c 0,3.31753 2.74497,6.0625 6.0625,6.0625 H 96 v 9.93751 c 0,3.31752 2.74497,6.0625 6.0625,6.0625 h 3.875 c 3.31752,0 6.0625,-2.74498 6.0625,-6.0625 v -9.93751 h 9.9375 c 3.31752,0 6.0625,-2.74497 6.0625,-6.0625 v -3.875 c 0,-3.317516 -2.74498,-6.062496 -6.0625,-6.062496 H 112 v -9.9375 c 0,-3.31752 -2.74498,-6.0625 -6.0625,-6.0625 z"
+         id="path3012"
+         sodipodi:nodetypes="ccccccccccccccccccccc"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cccccc"
+         transform="matrix(-0.4770371,0,0,0.4770371,134.46434,74.913337)"
+         id="path3091"
+         d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 68.465655,24.133449 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
+         style="fill:url(#linearGradient1937);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient1939);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
+         d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 68.172686,21.789699 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
+         id="path3095"
+         transform="matrix(0.4705955,0,0,0.4705955,74.322072,75.046467)"
+         sodipodi:nodetypes="cccccc"
+         clip-path="none" />
+      <g
+         id="g3201"
+         transform="matrix(1,0,0,-1,148,188.38795)"
+         clip-path="none">
+        <path
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccccc"
+           transform="matrix(-0.463084,0,0,0.463084,-14.468792,55.235658)"
+           id="path3197"
+           d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 l 2.175622,10.747436 11.133979,-0.114683 v -0.46875 C 81.92653,20.116546 74.219552,10.743294 69.875971,12.057888 Z"
+           style="opacity:0.643564;fill:url(#radialGradient4800);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="opacity:0.643564;fill:url(#radialGradient4802);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
+           d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 67.782061,23.547512 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
+           id="path3199"
+           transform="matrix(0.4624565,0,0,0.4624565,-73.133616,55.243224)"
+           sodipodi:nodetypes="cccccc" />
+      </g>
+      <path
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cccccc"
+         transform="matrix(0.4793282,0,0,0.4793282,89.738069,90.470087)"
+         id="path3221"
+         d="M 69.719108,13.31279 C 68.64202,13.378073 67.34775,12.277052 66.875971,12.995388 L 68.465655,24.133449 79,23.37409 v -0.46875 c 1.740958,-2.57016 -4.937311,-9.65189 -9.280892,-9.59255 z"
+         style="opacity:0.550562;fill:url(#linearGradient1941);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="ccccccccccccccccccccc"
+         id="path3028"
+         d="m 102.0625,79.999994 c -3.31753,0 -6.0625,2.74498 -6.0625,6.0625 v 9.9375 h -9.9375 c -3.31753,0 -6.0625,2.74498 -6.0625,6.062496 v 3.875 c 0,3.31753 2.74497,6.0625 6.0625,6.0625 H 96 v 9.93751 c 0,3.31752 2.74497,6.0625 6.0625,6.0625 h 3.875 c 3.31752,0 6.0625,-2.74498 6.0625,-6.0625 v -9.93751 h 9.9375 c 3.31752,0 6.0625,-2.74497 6.0625,-6.0625 v -3.875 c 0,-3.317516 -2.74498,-6.062496 -6.0625,-6.062496 H 112 v -9.9375 c 0,-3.31752 -2.74498,-6.0625 -6.0625,-6.0625 z"
+         style="opacity:0.643564;fill:url(#radialGradient4806);fill-opacity:1;stroke:none;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         style="opacity:0.550562;fill:url(#linearGradient3571);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3387)"
+         d="m 69.875971,12.057888 c -1.077088,0.06528 -2.528221,0.219164 -3,0.9375 L 68.465655,24.133449 79,23.37409 V 22.90534 C 80.740958,20.33518 74.219552,11.998548 69.875971,12.057888 Z"
+         id="path3217"
+         transform="matrix(-0.4540742,0,0,0.4540742,116.57304,91.07955)"
+         sodipodi:nodetypes="cccccc"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:url(#radialGradient4810);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
+         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 13.9375 H 86.0625 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 3.875 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 H 100 v 13.93751 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 h 3.875 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -13.93751 h 13.9375 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -3.875 c 0,-1.13397 -0.92853,-2.062496 -2.0625,-2.062496 H 108 v -13.9375 c 0,-1.13397 -0.92853,-2.0625 -2.0625,-2.0625 z"
+         id="rect2407"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient4812);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
+         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 13.9375 H 86.0625 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 3.875 c 0,0.1098 0.04574,0.20722 0.0625,0.3125 3.25768,0.46957 6.69134,0.75 10.25,0.75 11.50157,0 21.80584,-2.62983 28.59375,-6.75 -0.28924,-0.15515 -0.61935,-0.249996 -0.96875,-0.249996 H 108 v -13.9375 c 0,-1.13397 -0.92853,-2.0625 -2.0625,-2.0625 z"
+         id="path3038"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient4814);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
+         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 1 c 0,-1.13397 1.32853,-2.6625 2.4625,-2.6625 h 3.875 c 0.28349,0 0.56599,0.05148 0.8125,0.15625 0.11026,0.24952 0.4875,1.12458 0.4875,1.4125 l 0.3625,14.03125 0.0312,-13.9375 c 0,-0.57563 -0.24106,-1.09358 -0.625,-1.46875 -0.0878,-0.08777 -0.17903,-0.17902 -0.28125,-0.25 -0.008,-0.0052 -0.0235,0.0051 -0.0312,0 -0.10208,-0.06913 -0.19867,-0.13727 -0.3125,-0.1875 -0.009,-0.0037 -0.0225,0.0036 -0.0312,0 -0.1146,-0.0487 -0.25111,-0.09763 -0.375,-0.125 -0.0102,-0.0021 -0.021,0.002 -0.0312,0 -0.12367,-0.0255 -0.24455,-0.02921 -0.375,-0.03125 h -0.0312 -0.46875 z m -16,16 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 1 c 0,-1.13397 0.92853,-2.6625 2.0625,-2.6625 L 100,99.999994 Z m 21.9375,0 13.75977,0.511716 c -6.7592,3.6271 -17.82247,6.39454 -28.50977,6.39453 -1.77933,0 -3.53955,-0.09 -5.25,-0.21875 2.06039,0.18692 4.17941,0.3125 6.34375,0.3125 10.77006,0 20.48375,-2.32371 27.25,-6 0.008,-0.004 0.0233,0.004 0.0312,0 0.44256,-0.24123 0.86462,-0.49711 1.28125,-0.75 -0.13631,-0.0731 -0.2853,-0.14478 -0.4375,-0.1875 -0.01,-0.003 -0.0212,0.003 -0.0312,0 -0.15237,-0.0404 -0.30537,-0.0598 -0.46875,-0.0625 h -0.0312 -0.46875 z"
+         id="path3062"
+         sodipodi:nodetypes="cccccccccsssssssccccccccccccscssscsscccc"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cccccccccsssssssccccccccccccscssscsscccc"
+         id="path3087"
+         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 1 c 0,-1.13397 1.32853,-2.6625 2.4625,-2.6625 h 3.875 c 0.28349,0 0.56599,0.05148 0.8125,0.15625 0.11026,0.24952 0.4875,1.12458 0.4875,1.4125 l 0.3625,14.03125 0.0312,-13.9375 c 0,-0.57563 -0.24106,-1.09358 -0.625,-1.46875 -0.0878,-0.08777 -0.17903,-0.17902 -0.28125,-0.25 -0.008,-0.0052 -0.0235,0.0051 -0.0312,0 -0.10208,-0.06913 -0.19867,-0.13727 -0.3125,-0.1875 -0.009,-0.0037 -0.0225,0.0036 -0.0312,0 -0.1146,-0.0487 -0.25111,-0.09763 -0.375,-0.125 -0.0102,-0.0021 -0.021,0.002 -0.0312,0 -0.12367,-0.0255 -0.24455,-0.02921 -0.375,-0.03125 h -0.0312 -0.46875 z m -16,16 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 1 c 0,-1.13397 0.92853,-2.6625 2.0625,-2.6625 L 100,99.999994 Z m 21.9375,0 13.85742,0.511716 c -6.75919,3.6271 -17.92012,6.39454 -28.60742,6.39453 -1.77933,0 -3.53955,-0.09 -5.25,-0.21875 2.06039,0.18692 4.17941,0.3125 6.34375,0.3125 10.77006,0 20.48375,-2.32371 27.25,-6 0.008,-0.004 0.0233,0.004 0.0312,0 0.44256,-0.24123 0.86462,-0.49711 1.28125,-0.75 -0.13631,-0.0731 -0.2853,-0.14478 -0.4375,-0.1875 -0.01,-0.003 -0.0212,0.003 -0.0312,0 -0.15237,-0.0404 -0.30537,-0.0598 -0.46875,-0.0625 h -0.0312 -0.46875 z"
+         style="fill:url(#linearGradient4816);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1"
+         clip-path="none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3099"
+         d="m 102.0625,83.999994 c -1.13397,0 -2.0625,0.92853 -2.0625,2.0625 v 13.9375 H 86.0625 c -1.13397,0 -2.0625,0.928526 -2.0625,2.062496 v 3.875 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 H 100 v 13.93751 c 0,1.13397 0.92853,2.0625 2.0625,2.0625 h 3.875 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -13.93751 h 13.9375 c 1.13397,0 2.0625,-0.92853 2.0625,-2.0625 v -3.875 c 0,-1.13397 -0.92853,-2.062496 -2.0625,-2.062496 H 108 v -13.9375 c 0,-1.13397 -0.92853,-2.0625 -2.0625,-2.0625 z"
+         style="fill:none;fill-opacity:1;stroke:url(#linearGradient4818);stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.0878;stroke-opacity:1;filter:url(#filter3191)"
+         clip-path="none" />
+    </g>
+  </g>
+</svg>
diff --git a/flags/system/jissue.svg b/flags/system/jissue.svg
deleted file mode 100644 (file)
index 7f35cf2..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   height="128"
-   viewBox="2.59 0 11.606798 11.4688"
-   width="128"
-   version="1.1"
-   id="svg14"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg">
-  <defs
-     id="defs18">
-    <linearGradient
-       id="linearGradient1609">
-      <stop
-         style="stop-color:#0052cc;stop-opacity:1;"
-         offset="0"
-         id="stop1605" />
-      <stop
-         style="stop-color:#2684ff;stop-opacity:0;"
-         offset="1"
-         id="stop1607" />
-    </linearGradient>
-    <linearGradient
-       xlink:href="#a"
-       id="linearGradient855"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.05109566,0,0,-0.05132789,2.8787408,13.534242)"
-       x1="102.4"
-       y1="218.63"
-       x2="56.150002"
-       y2="172.39" />
-    <linearGradient
-       xlink:href="#linearGradient1609"
-       id="linearGradient1611"
-       x1="8.6326942"
-       y1="9.0570345"
-       x2="10.95546"
-       y2="6.6513"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <linearGradient
-     id="a"
-     gradientTransform="matrix(1,0,0,-1,0,264)"
-     gradientUnits="userSpaceOnUse"
-     x1="102.4"
-     x2="56.150002"
-     y1="218.63"
-     y2="172.39">
-    <stop
-       offset=".18"
-       stop-color="#0052cc"
-       id="stop2" />
-    <stop
-       offset="1"
-       stop-color="#2684ff"
-       id="stop4" />
-  </linearGradient>
-  <linearGradient
-     id="b"
-     x1="121.16464"
-     x2="160.81"
-     xlink:href="#a"
-     y1="171.41203"
-     y2="131.92"
-     gradientTransform="matrix(0.05109566,0,0,0.05132789,2.8787408,-0.01631941)" />
-  <path
-     d="M 13.816279,5.4105776 8.8911687,0.46308273 8.4139355,-0.01631955 4.7064346,3.7080318 3.0110802,5.4105776 a 0.45424045,0.45630485 0 0 0 0,0.6436518 l 3.3871316,3.4025248 2.0157237,2.0243718 3.7069905,-3.7243513 0.05774,-0.057487 1.637614,-1.6424918 a 0.45321853,0.45527832 0 0 0 0,-0.6462189 z M 8.4139355,7.4323824 6.7216472,5.7324032 8.4139355,4.0324238 10.105713,5.7324032 Z"
-     fill="#2684ff"
-     id="path8"
-     style="display:inline;stroke-width:0.0512116" />
-  <path
-     d="M 8.4139355,4.0324238 A 2.8485832,2.8615294 0 0 1 8.4016734,-0.0024621 L 4.6987706,3.7157308 6.7139836,5.7401027 Z"
-     fill="url(#a)"
-     id="path10"
-     style="display:inline;fill:url(#linearGradient855);stroke-width:0.0512116" />
-  <path
-     d="M 10.110311,5.7277836 8.4139355,7.4323824 a 2.8496051,2.8625559 0 0 1 0,4.0477176 L 12.127057,7.7521553 Z"
-     fill="url(#b)"
-     id="path12"
-     style="display:inline;fill:url(#linearGradient1611);stroke-width:0.0512116;fill-opacity:1" />
-</svg>
index cf3721ac63674116e15dde1065fb445f77733922..1a44e5a48a3f5b0968dd0fa7b73c8a1257d4089d 100644 (file)
     </widget>
    </item>
    <item>
-    <widget class="QCheckBox" name="usePATCheckBox">
+    <widget class="QLabel" name="authMethodLabel">
      <property name="text">
-      <string>Use Personal Access Token instead of username and password for authentication</string>
+      <string>Authentication method:</string>
      </property>
     </widget>
    </item>
    <item>
-    <widget class="QLabel" name="PATLabel">
-     <property name="text">
-      <string>Personal Access Token:</string>
-     </property>
+    <widget class="QComboBox" name="authMethodComboBox">
+     <item>
+      <property name="text">
+       <string>Username/Password</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>PAT</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Cloud</string>
+      </property>
+     </item>
     </widget>
    </item>
    <item>
-    <widget class="QLineEdit" name="PATLineEdit">
-     <property name="inputMethodHints">
-      <set>Qt::ImhNone</set>
-     </property>
-     <property name="echoMode">
-      <enum>QLineEdit::Password</enum>
-     </property>
-    </widget>
-   </item>
+   <widget class="QLabel" name="PATLabel">
+    <property name="text">
+     <string>Personal Access Token:</string>
+    </property>
+   </widget>
+  </item>
+  <item>
+   <widget class="QLineEdit" name="PATLineEdit">
+    <property name="inputMethodHints">
+     <set>Qt::ImhNone</set>
+    </property>
+    <property name="echoMode">
+     <enum>QLineEdit::Password</enum>
+    </property>
+   </widget>
+  </item>
+  <item>
+   <widget class="QLabel" name="apiTokenLabel">
+    <property name="text">
+     <string>API token:</string>
+    </property>
+   </widget>
+  </item>
+  <item>
+   <widget class="QLineEdit" name="apiTokenLineEdit">
+    <property name="inputMethodHints">
+     <set>Qt::ImhNone</set>
+    </property>
+    <property name="echoMode">
+     <enum>QLineEdit::Password</enum>
+    </property>
+   </widget>
+  </item>
    <item>
     <widget class="QLabel" name="userLabel">
      <property name="text">
index f97663837b04a087664ba00d0ad71c8690ce7b65..54ee4c7ba85c0ef360cc3de7af5a64901579fb8d 100644 (file)
@@ -43,8 +43,9 @@ function colorSubtreeWithQuickColor(n)
     vym.selectQuickColor(n);
     c = vym.currentColor();
 
-    b = map.selectedBranch();
-    b.colorSubtree (c);
+    branches = map.selectedBranches();
+    for (b of branches)
+        b.colorSubtree(c);
 }
 
 //! Macro F1: Color subtree red
@@ -112,11 +113,11 @@ function macro_f10()
     colorSubtreeWithQuickColor(9);
 }
 
-//! Macro F11: Repeat last command
+//! Macro F11:
 function macro_f11()
 {
     map = vym.currentMap();
-    map.repeatLastCommand();
+    // Unused
 }
 
 //! Macro F12: toggle high prio task
@@ -163,6 +164,7 @@ function macro_shift_f1()
     toggle_frame_branch ( map );
     b.setFrameBrushColor(true, "#ffb3b4");
     vym.statusMessage(status);
+
 }
 
 //! Macro Shift + F2: Frame background light green
index d3b765139e943ed1ead2bc9823c0ceffe8e9d154..bdcc605a9e7e5e689d274e6c38bc2e8ba043fc87 100644 (file)
@@ -87,6 +87,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent)
             "</li>"
             "<li> Patches"
             "  <ul>"
+            "    <li>Loric Brevet: Enabling Jira Cloud and usability discussions</li>"
             "    <li>Bleyddyn: &quot;Clear&quot; button in &quot;Recent files&quot; menu and improving remembering last directory</li>"
             "    <li>Sven H&ouml;xter: Various patches to fix typos and especiall for Debian packaging</li>"
             "    <li>Edward Wang: adding close tab buttons</li>"
index bbe0a2ad308b641325dde75245a81c1f09ac77fd..a9eebd5cc0a8a1f592ce7121dc0a021c3ecb8642 100644 (file)
@@ -21,6 +21,7 @@ void BranchContainerBase::init()
 
     setBrush(Qt::NoBrush);
     setPen(QPen(Qt::NoPen));
+    // setPen(QPen(Qt::blue));  // Testing only
 
     horizontalDirection = Container::LeftToRight;
 }
index ccc99b39e43baae83ae892f2c52f8d870e1fdfe4..dddaacfef511f56638e3d3e886d4887821f7ea60 100644 (file)
@@ -123,9 +123,9 @@ void BranchContainer::init()
     // Center of whole mainBranches should be the heading
     setCentralContainer(headingContainer);
 
-    // Elastic layout experiments FIXME-3
+    // Elastic layout experiments. v not really used currently  FIXME-3
     v_anim = QPointF(0, 0);
-    v.setParentItem(this);
+    v.setParentItem(this);  // Animation vector for animated layout
     v.setPen(QPen(Qt::red));
     v.setVisible(false);
 
@@ -865,7 +865,8 @@ void BranchContainer::updateUpLink()
     }
 
     // Create/delete bottomline, depends on frame and (List-)Layout
-    if (frameType(true) != FrameContainer::NoFrame ||
+    if (frameType(true)  != FrameContainer::NoFrame ||
+        frameType(false) != FrameContainer::NoFrame ||
         branchesContainerAndOrnamentsVerticalInt ||
         (pbc && pbc->branchesContainerLayoutInt == List)) {
         if (upLink->hasBottomLine())
@@ -975,14 +976,14 @@ void BranchContainer::setBranchesContainerAndOrnamentsVertical(bool b)
     branchesContainerAndOrnamentsVerticalInt = b;
 }
 
-QRectF BranchContainer::headingRect()
+QRectF BranchContainer::headingSceneRect()
 {
     // Returns scene coordinates of bounding rectanble
     return headingContainer->mapToScene(headingContainer->rect())
         .boundingRect();
 }
 
-QRectF BranchContainer::ornamentsRect()
+QRectF BranchContainer::ornamentsSceneRect()
 {
     // Returns scene coordinates of bounding rectanble
     return ornamentsContainer->mapToScene(headingContainer->rect())
@@ -1413,7 +1414,7 @@ void BranchContainer::reposition()
         // on MovingState
         if (pbc) {
             if (pbc->hasFloatingBranchesLayout()) {
-                if (scenePos().x() > pbc->scenePos().x())   // FIXME-2 problematic for rotated elements...
+                if (scenePos().x() > pbc->scenePos().x())   // FIXME-3 Potentially problematic for rotated elements...
                                                             // but OTOH using relative coord
                                                             // often pos.x() == 0
                     orientation = RightOfParent;
index da6683a86fd6503cf7c1da1fc554216ae72cff06..5e120c519636e2fb1159e5f7cd623a0b148729b2 100644 (file)
@@ -100,8 +100,8 @@ class BranchContainer : public BranchContainerBase, public LinkableContainer {
 
     void setBranchesContainerAndOrnamentsVertical(bool);
 
-    QRectF headingRect();    //! Return rectangle of HeadingContainer in absolute coordinates
-    QRectF ornamentsRect();  //! Return rectangle of ornamentsContainer in absolute coordinates
+    QRectF headingSceneRect();    //! Return rectangle of HeadingContainer in scene coordinates
+    QRectF ornamentsSceneRect();  //! Return rectangle of ornamentsContainer in scene coordinates
 
     void setColumnWidthAutoDesign(const bool &);
     bool columnWidthAutoDesign();
index 367c7de853e65ade3274dfc57df0e2ea18f2b973..aa9e72c58713d80c04dafa8f404a3fde3db59ccf 100644 (file)
@@ -306,6 +306,13 @@ QString BranchWrapper::getHeading()
     return r;
 }
 
+QString BranchWrapper::getHeadingColor()
+{
+    QString r = branchItemInt->headingColor().name();
+    mainWindow->setScriptResult(r);
+    return r;
+}
+
 QString BranchWrapper::getHeadingXML()
 {
     QString r = branchItemInt->heading().saveToDir();
index 394c7935950ecd6790d8fe125651cc04f101f4a2..a7a386ba51b4f826120b022325e54d66114e06f2 100644 (file)
@@ -46,6 +46,7 @@ class BranchWrapper : public QObject {
     int getFramePenWidth(const bool & useInnerFrame);
     QString getFrameType(const bool & useInnerFrame);
     QString getHeading();
+    QString getHeadingColor();
     QString getHeadingXML();
     QString getImagesLayout();
     void getJiraData(bool subtree);
index 797bd839657bf378fa80e2e21234e1df23620cf8..394b45f9397ab919b1e12fd43c29bd7d905edf04 100644 (file)
@@ -14,6 +14,8 @@
 
 extern TaskModel *taskModel;
 
+extern FlagRowMaster *systemFlagsMaster;
+
 BranchItem::BranchItem(TreeItem *parent)
     : MapItem(parent)
 {
@@ -247,7 +249,7 @@ void BranchItem::updateTaskFlag()
 {
     systemFlags.deactivateGroup("system-tasks");
     if (task) {
-        QString s = "system-" + task->getIconString();
+        QString s = "system-" + task->iconString();
         systemFlags.activate(s);
         model->emitDataChanged(this);
     }
@@ -263,6 +265,14 @@ void BranchItem::setTask(Task *t)
 
 Task *BranchItem::getTask() { return task; }
 
+Flag *BranchItem::taskFlag()
+{
+    if (!task)
+        return nullptr;
+
+    return systemFlagsMaster->findFlagByName("system-" + task->iconString());
+}
+
 void BranchItem::scroll()
 {
     if (tmpUnscrolled)
index 7d012812e9ed87e4ec9118f1f01154f263aaa632..6c0c103befd8b7672a0919f5faba55bf3e5e45ba 100644 (file)
@@ -42,6 +42,7 @@ class BranchItem : public MapItem {
     void updateTaskFlag();
     void setTask(Task *t);
     Task *getTask();
+    Flag *taskFlag();
 
   private:
     Task *task;
index 374514f4f5fbd7fdba543608c92b2952e8d2ca8b..fa706db59ac60a00bac613809d0c98be57cfcc68 100644 (file)
@@ -77,6 +77,8 @@ QString Command::typeToString(const ParameterType &type)
             return "Bool";
         case BranchPar:
             return "Branch";
+        case BranchListPar:
+            return "BranchesList";
         case ColorPar:
             return "Color";
         case DoublePar:
@@ -87,6 +89,8 @@ QString Command::typeToString(const ParameterType &type)
             return "Int";
         case StringPar:
             return "String";
+        case StringListPar:
+            return "StringsList";
         case UndefinedPar:
             return "Undefined";
         case VoidPar:
index e5deebf500340923e22bb020c2fb7d85308a9761..fce2f2a363af1ac894ce30cb007e4b9998db7ce1 100644 (file)
@@ -19,6 +19,7 @@ class Command {
         AttributePar,
         BoolPar,
         BranchPar,
+        BranchListPar,
         ColorPar,
         DoublePar,
         ImagePar,
@@ -28,6 +29,7 @@ class Command {
         StringListPar,
         UndefinedPar,
         VoidPar,
+        VymModelPar,
         XLinkPar
     };
     enum SelectionType {
index 700aa4b87bf00f63c457c60532b109efcd6c6421..ae2ec65828f48d1f694ae9bf2b6cf7984a12a2be 100644 (file)
@@ -45,7 +45,7 @@ void Container::init()
     // subcontainers usually may influence position
     // Only mapCenters will stay where they are
 
-    minimumWidth = 0;   // FIXME-3 currently unused, maybe for linkSpaceContainer
+    minimumWidth = 0;   // FIXME-3 currently unused, maybe for linkSpaceContainer or fixed dimensions
 
     horizontalDirection = LeftToRight;
     horizontalAlignmentInt = HorAlignedLeft;
index c2d9557e5d38ade46758f13268933a9df8d96626..8ae92652339c0cf94127f5ac41d095825e35a10c 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "branchitem.h"
 #include "mainwindow.h"
+#include "misc.h"
 #include "task.h"
 #include "vymmodel.h"
 
@@ -167,10 +168,3 @@ void ExportAO::doExport()
     completeExport();
 }
 
-QString ExportAO::underline(const QString &text, const QString &line)
-{
-    QString r = text + "\n";
-    for (int j = 0; j < text.length(); j++)
-        r += line;
-    return r;
-}
index 37f8d0f09bea4f31a802543d145188aaeea4b06e..1d19ad28720bf14f5f1da307429a3a763863004a 100644 (file)
@@ -7,7 +7,6 @@ class ExportAO : public ExportBase {
   public:
     ExportAO();
     virtual void doExport();
-    virtual QString underline(const QString &text, const QString &line);
 };
 
 #endif
index 4d56e9a6e199134d43486b41c540dbd7b4e2559c..467603e811a4be94cbab64b1e20f3a470671b96f 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "branchitem.h"
 #include "mainwindow.h"
+#include "misc.h"
 #include "task.h"
 #include "vymmodel.h"
 
@@ -158,14 +159,6 @@ void ExportASCII::doExport()
     completeExport(args);
 }
 
-QString ExportASCII::underline(const QString &text, const QString &line)
-{
-    QString r = text + "\n";
-    for (int j = 0; j < text.length(); j++)
-        r += line;
-    return r;
-}
-
 QString ExportASCII::ensureEmptyLines(QString &text, int n)
 {
     // Ensure at least n empty lines at the end of text
index 083ec89f816e0f6917bdeeaea1c49bfc4e769796..7bb5aa474ace5dda8620aae92bc1198ce83f1bb5 100644 (file)
@@ -7,7 +7,6 @@ class ExportASCII : public ExportBase {
   public:
     ExportASCII();
     virtual void doExport();
-    QString underline(const QString &text, const QString &line);
     QString ensureEmptyLines(QString &text, int n);
     QString ensureNewLine(QString &text);
 };
index ef534fcc1eb678b2105d6c871b09cd7bec732178..326729e03eb4d6ac617b169f4d512a5ab6afb3a7 100644 (file)
@@ -74,7 +74,7 @@ QString ExportConfluence::getBranchText(BranchItem *current)
             Task *task = current->getTask();
             if (task)
             {
-                QString taskName = task->getIconString();
+                QString taskName = task->iconString();
                 taskFlags += QString("<img src=\"flags/flag-%1.png\"
         alt=\"%2\">") .arg(taskName) .arg(QObject::tr("Flag: %1","Alt tag in
         HTML export").arg(taskName));
index e6c95c4ddce96aac6db1226f225c89996d2dd815..f2059dab35906e863e31ffcbcc8d2681f927a7a6 100644 (file)
@@ -19,6 +19,7 @@ extern QString vymHome;
 
 extern FlagRowMaster *standardFlagsMaster;
 extern FlagRowMaster *userFlagsMaster;
+extern FlagRowMaster *systemFlagsMaster;
 
 ExportHTML::ExportHTML() : ExportBase() { init(); }
 
@@ -29,6 +30,8 @@ void ExportHTML::init()
     exportName = "HTML";
     extension = ".html";
     frameURLs = true;
+
+    flagWidthInt = " width=\"32\" ";   // FIXME-3 use CSS instead
 }
 
 QString ExportHTML::getBranchText(BranchItem *current)
@@ -55,14 +58,31 @@ QString ExportHTML::getBranchText(BranchItem *current)
 
         // Task flags
         QString taskFlags;
+        QString flagName;;
+        QString flagPath;
         if (dia.useTaskFlags) {
             Task *task = current->getTask();
             if (task) {
-                QString taskName = task->getIconString();
-                taskFlags +=
-                    QString("<img style=\"vertical-align: middle\" src=\"flags/flag-%1.png\" alt=\"%2\">")
-                        .arg(taskName)
-                        .arg(QObject::tr("Flag: %1", "Alt tag in HTML export").arg(taskName));
+                QString taskName = task->iconString();
+                Flag *f = current->taskFlag();
+                if (f) {
+                    flagName = f->getName();
+                    ImageContainer *ic = f->getImageContainer();
+                    if (!ic) {
+                        qWarning() << __func__ << "ic == nullptr for task";
+                        return "Error...";
+                    }
+
+                    flagPath = flagsDir.path() + "/" + ic->originalFilename();
+
+                    if (!activeSystemFlagNames.contains(flagName)) {
+                        activeSystemFlagNames << flagName;
+                        ic->save(flagPath);
+                    }
+                    taskFlags +=
+                        QString("<img style=\"vertical-align: middle\" %1 src=\"flags/%2\" alt=\"%3\">")
+                            .arg(flagWidthInt, basename(flagPath), taskName);
+                }
             }
         }
 
@@ -80,7 +100,8 @@ QString ExportHTML::getBranchText(BranchItem *current)
                 if (f)
                     flags +=
                         QString(
-                            "<img style=\"vertical-align: middle\" width=\"32px\" alt=\"%1\" src=\"flags/%2\">")
+                            "<img style=\"vertical-align: middle\" %1 alt=\"%2\" src=\"flags/%3\">")
+                            .arg(flagWidthInt)
                             .arg(QObject::tr("Flag: %1", "Alt tag in HTML export").arg(f->getName()))
                             .arg(f->getImageContainer()->originalFilename());
             }
@@ -91,12 +112,30 @@ QString ExportHTML::getBranchText(BranchItem *current)
         if (dia.useNumbering)
             number = getSectionString(current) + " ";
 
-        // URL
+        // Url
         if (!url.isEmpty()) {
-            s += QString("<a href=\"%1\">%2<img style=\"vertical-align: middle\" src=\"flags/flag-url.png\" "
-                         "alt=\"%3\"></a>")
+            Flag *f = current->urlFlag();
+            if (f) {
+                flagName = f->getName();
+                ImageContainer *ic = f->getImageContainer();
+                if (!ic) {
+                    qWarning() << __func__ << "ic == nullptr for Url";
+                    return "Error...";
+                }
+
+                flagPath = flagsDir.path() + "/" + ic->originalFilename();
+
+                if (!activeSystemFlagNames.contains(flagName)) {
+                    activeSystemFlagNames << flagName;
+                    ic->save(flagPath);
+                }
+            }
+            s += QString("<a href=\"%1\">%2<img style=\"vertical-align: middle\" %3 src=\"flags/%4\" "
+                         "alt=\"%5\"></a>")
                      .arg(url)
                      .arg(number + taskFlags + heading + flags)
+                     .arg(flagWidthInt)
+                     .arg(basename(flagPath))
                      .arg(QObject::tr("Flag: url", "Alt tag in HTML export"));
 
             QRectF fbox = current->getBranchContainer()->getBBoxURLFlag();
@@ -109,6 +148,7 @@ QString ExportHTML::getBranchText(BranchItem *current)
                                 .arg(fbox.bottom() - offset.y())
                                 .arg(url)
                                 .arg(heading);
+
         }
         else
             s += number + taskFlags + heading + flags;
@@ -285,7 +325,7 @@ QString ExportHTML::createTOC()
     return toc;
 }
 
-void ExportHTML::doExport(bool useDialog) // FIXME-2 System flags not written. (URL, task, scrolled, ...)
+void ExportHTML::doExport(bool useDialog)
 {
     // Setup dialog and read settings
     dia.setMapName(model->getMapName());
@@ -398,7 +438,16 @@ void ExportHTML::doExport(bool useDialog) // FIXME-2 System flags not written. (
 
     // reset flags
     model->resetUsedFlags();
-
+    flagsDir.setPath(dia.getDir().absolutePath() + "/flags");
+    if (!flagsDir.exists()) {
+        if (!dia.getDir().mkdir("flags")) {
+            QMessageBox::critical(
+                0, QObject::tr("Critical"),
+                QObject::tr("Trying to create directory for flags:") + "\n\n" +
+                    QObject::tr("Could not create %1").arg(flagsDir.path()));
+            return;
+        }
+    }
     // Main loop over all mapcenters
     ts << buildList(model->getRootItem()) << "\n";
 
@@ -420,17 +469,8 @@ void ExportHTML::doExport(bool useDialog) // FIXME-2 System flags not written. (
     ts << "</body></html>";
     file.close();
 
-    QString flagsBasePath = dia.getDir().absolutePath() + "/flags";
-    QDir d(flagsBasePath);
-    if (!d.exists()) {
-        if (!dia.getDir().mkdir("flags")) {
-            QMessageBox::critical(
-                0, QObject::tr("Critical"),
-                QObject::tr("Trying to create directory for flags:") + "\n\n" +
-                    QObject::tr("Could not create %1").arg(flagsBasePath));
-            return;
-        }
-    }
+
+    // Copy standard flags
     Flag *f;
     foreach (QUuid uid, activeFlags) {
         f = standardFlagsMaster->findFlagByUid(uid);
@@ -440,7 +480,7 @@ void ExportHTML::doExport(bool useDialog) // FIXME-2 System flags not written. (
         if (f) {
             ImageContainer *ic = f->getImageContainer();
             if (ic)
-                ic->save(flagsBasePath + "/" + ic->originalFilename());
+                ic->save(flagsDir.path() + "/" + ic->originalFilename());
         }
     }
 
index d38b8abd720b5b073bb426ae1204351ceb2476aa..8c2c1995e04941e2dd5a2d5f5ddc59c5b73d47b3 100644 (file)
@@ -21,13 +21,18 @@ class ExportHTML : public ExportBase {
     QString cssSrc;
     QString cssDst;
 
+    QString flagWidthInt;
+
     bool frameURLs;
 
     QPointF offset;
 
     QSet<QUuid> activeFlags;
+    QStringList activeSystemFlagNames;
 
     ExportHTMLDialog dia;
+
+    QDir flagsDir;
 };
 
 #endif
index 478ff363e376b2243397a5ed5dd99cd2a87398ef..715958603f2ff73e36067cee0199ef4f01c86f45 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "branchitem.h"
 #include "mainwindow.h"
+#include "misc.h"
 #include "task.h"
 #include "vymmodel.h"
 
@@ -162,10 +163,3 @@ void ExportMarkdown::doExport()
     completeExport(args);
 }
 
-QString ExportMarkdown::underline(const QString &text, const QString &line)
-{
-    QString r = text + "\n";
-    for (int j = 0; j < text.length(); j++)
-        r += line;
-    return r;
-}
index 6b7f6a9c9c5d5659f8e1f9c5417f36743b5e8dec..d4c7331a80a52c68cae4ae15fcd95aa3fad032f0 100644 (file)
@@ -7,7 +7,6 @@ class ExportMarkdown : public ExportBase {
   public:
     ExportMarkdown();
     virtual void doExport();
-    virtual QString underline(const QString &text, const QString &line);
 };
 
 #endif
diff --git a/src/findcontrolswidget.cpp b/src/findcontrolswidget.cpp
new file mode 100644 (file)
index 0000000..02760b8
--- /dev/null
@@ -0,0 +1,126 @@
+#include <QAction>
+#include <QDebug>
+#include <QLabel>
+#include <QLineEdit>
+#include <QVBoxLayout>
+
+#include <QComboBox>
+#include <QGroupBox>
+#include <QLabel>
+#include <QPushButton>
+
+#include "findcontrolswidget.h"
+#include "mainwindow.h"
+
+extern Main *mainWindow;
+extern bool usingDarkTheme;
+extern QString iconTheme;
+
+FindControlsWidget::FindControlsWidget(QWidget *)
+{
+    QVBoxLayout *mainLayout = new QVBoxLayout;
+    QHBoxLayout *row2Layout = new QHBoxLayout;
+
+    QLabel *label = new QLabel;
+    label->setText(tr("Find:", "FindControlsWidget"));
+
+    // Create LineEdit (here QComboBox)
+    findcombo = new QComboBox;
+    findcombo->setMinimumWidth(250);
+    findcombo->setMaxCount(10);
+    findcombo->setEditable(true);
+
+    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+    findcombo->setSizePolicy(sizePolicy);
+    connect(findcombo, SIGNAL(editTextChanged(const QString &)), this,
+            SLOT(findTextChanged(const QString &)));
+    connect(findcombo, SIGNAL(currentIndexChanged(int)), this,
+            SLOT(indexChanged(int)));
+
+    nextButton = new QPushButton;
+    nextButton->setIcon(QPixmap(QString(":/edit-find-%1.svg").arg(iconTheme)));
+    // nextButton->setText (tr("Find","Find widget"));
+    connect(nextButton, SIGNAL(clicked()), this, SLOT(nextPressed()));
+
+    // QAction needed to only activate shortcut while FindControlsWidget has focus
+    QAction *a = new QAction(nextButton->text(), this);
+    a->setShortcut(Qt::Key_Return);     // Find in FindControlsWidget
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    connect(a, SIGNAL(triggered()), this, SLOT(nextPressed()));
+    addAction(a);
+
+    filterNotesButton = new QPushButton;
+    filterNotesButton->setIcon(QPixmap(":/flag-note.svg"));
+    filterNotesButton->setCheckable(true);
+    filterNotesButton->setChecked(true);
+    connect(filterNotesButton, SIGNAL(clicked()), this, SLOT(nextPressed()));
+
+    row2Layout->addWidget(label);
+    row2Layout->addWidget(findcombo);
+    row2Layout->addWidget(nextButton);
+    row2Layout->addWidget(filterNotesButton);
+
+    mainLayout->addLayout(row2Layout);
+
+    setLayout(mainLayout);
+    status = Undefined;
+}
+
+QString FindControlsWidget::getFindText() { return findcombo->currentText(); }
+
+void FindControlsWidget::nextPressed()
+{
+    if (findcombo->count() < findcombo->maxCount())
+        findcombo->insertItem(0, findcombo->currentText());
+    emit nextButtonPressed(findcombo->currentText(),
+                           filterNotesButton->isChecked());
+}
+
+void FindControlsWidget::findTextChanged(const QString &) { setStatus(Undefined); }
+
+void FindControlsWidget::indexChanged(int i)
+{
+    emit nextButtonPressed(findcombo->currentText(),
+                           filterNotesButton->isChecked());
+}
+
+void FindControlsWidget::setFocus()
+{
+    findcombo->lineEdit()->selectAll();
+    findcombo->lineEdit()->setFocus();
+}
+
+void FindControlsWidget::setStatus(Status st)
+{
+    if (st == status)
+        return;
+
+    status = st;
+    QPalette p = palette();
+    QColor c;
+    if (usingDarkTheme)
+        switch (st) {
+            case Success:
+                c = QColor(0, 170, 0);
+                break;
+            case Failed:
+                c = QColor(170, 0, 0);
+                break;
+            default:
+                c = p.color(QPalette::Base);
+        }
+    else
+        switch (st) {
+            case Success:
+                c = QColor(120, 255, 120);
+                break;
+            case Failed:
+                c = QColor(255, 120, 120);
+                break;
+            default:
+                c = p.color(QPalette::Base);
+        }
+    p.setColor(QPalette::Active, static_cast<QPalette::ColorRole>(9), c);
+    p.setColor(QPalette::Inactive, static_cast<QPalette::ColorRole>(9), c);
+    findcombo->setPalette(p);
+}
diff --git a/src/findcontrolswidget.h b/src/findcontrolswidget.h
new file mode 100644 (file)
index 0000000..9a500e7
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef FindControlsWidget_H
+#define FindControlsWidget_H
+
+#include <QWidget>
+
+class QAction;
+class QGroupBox;
+class QComboBox;
+class QPushButton;
+
+class FindControlsWidget : public QWidget {
+    Q_OBJECT
+
+  public:
+    enum Status { Undefined, Success, Failed };
+
+    FindControlsWidget(QWidget *parent = nullptr);
+    QString getFindText();
+
+  public slots:
+    void nextPressed();
+    void findTextChanged(const QString &);
+    void indexChanged(int);
+    void setFocus();
+    void setStatus(Status st);
+
+  private:
+    Status status;
+
+  signals:
+    void nextButtonPressed(QString, bool);
+
+  private:
+    QComboBox *findcombo;
+    QGroupBox *findbox;
+    QPushButton *nextButton;
+    QPushButton *filterNotesButton;
+};
+
+#endif
diff --git a/src/findresulttreeview.cpp b/src/findresulttreeview.cpp
new file mode 100644 (file)
index 0000000..c5b615b
--- /dev/null
@@ -0,0 +1,74 @@
+#include "findresulttreeview.h"
+
+#include <QAction>
+#include <QContextMenuEvent>
+#include <QHeaderView>
+#include <QMenu>
+
+extern QString editorFocusInStyle;
+extern QString editorFocusOutStyle;
+
+///////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+FindResultTreeView::FindResultTreeView()
+{
+    init();
+}
+
+void FindResultTreeView::init()
+{
+    setSelectionMode(QAbstractItemView::ExtendedSelection);
+    header()->hide();
+
+    QAction *a;
+
+    a = new QAction(this);
+    a->setShortcut(Qt::Key_Return);
+    a->setShortcutContext(Qt::WidgetShortcut);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(startEdit()));
+
+
+    // FIXME-3 Set borders when in focus to editorFocusStyle
+}
+
+FindResultTreeView::~FindResultTreeView()
+{
+    // qDebug()<<"Destructor FindResultTreeView for "<<model->getMapName();
+}
+
+QModelIndex FindResultTreeView::getSelectedIndex()
+{
+    QModelIndexList list = selectionModel()->selectedIndexes();
+    if (list.isEmpty())
+        return QModelIndex();
+    else
+        return list.first();
+}
+
+void FindResultTreeView::contextMenuEvent(QContextMenuEvent *e) {
+    /*
+    if (model->getSelectedBranch())
+        branchContextMenu->popup(e->globalPos());
+    else if (model->getSelectedImage())
+        floatimageContextMenu->popup(e->globalPos());
+    else if (model->getSelectedXLink())
+        model->editXLink();
+    else
+        canvasContextMenu->exec(e->globalPos());
+
+    e->accept();
+    */
+}
+
+void FindResultTreeView::closeEvent(QCloseEvent *event)
+{
+    qDebug() << "FRTV::close";
+    //mainWindow->windowSetFindResultTreeViewsVisibility(false);
+}
+
+void FindResultTreeView::startEdit()
+{
+    QModelIndex ix = getSelectedIndex();
+    emit searchFinished();
+}
diff --git a/src/findresulttreeview.h b/src/findresulttreeview.h
new file mode 100644 (file)
index 0000000..92d2c39
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef FindResultTreeView_H
+#define FindResultTreeView_H
+
+#include <QTreeView>
+
+class VymModel;
+
+/*! \brief TreeView widget in vym to display and edit a map, based on
+ * QTreeView */
+
+class FindResultTreeView : public QTreeView {
+    Q_OBJECT
+
+  public:
+    FindResultTreeView();
+    ~FindResultTreeView();
+    void init();
+    QModelIndex getSelectedIndex();
+
+  protected:
+    virtual void contextMenuEvent(QContextMenuEvent *e);
+    virtual void closeEvent(QCloseEvent *event);
+
+  signals:
+    void searchFinished();
+
+  private slots:
+    void startEdit();
+
+  private:
+    VymModel *model;
+};
+
+#endif
index 1e0e3c1018d0878c2161e93627ae17d0617f0fe4..7dc3a566ce984f1c2ab28a7ae8e123d966066300 100644 (file)
@@ -5,26 +5,42 @@
 
 #include "findresultitem.h"
 #include "findresultmodel.h"
+#include "findresulttreeview.h"
+#include "mainwindow.h"
 #include "vymmodel.h"
 
+extern Main *mainWindow;
+
 FindResultWidget::FindResultWidget(QWidget *)
 {
     // Create results model
     resultsModel = new FindResultModel;
 
     // Create TreeView
-    view = new QTreeView(this);
+    view = new FindResultTreeView();
     view->setModel(resultsModel);
 
-    // Create FindWidget
-    findWidget = new FindWidget(this);
-    connect(findWidget, SIGNAL(nextButtonPressed(QString, bool)), this,
+    // Create FindControlsWidget
+    findControlsWidget = new FindControlsWidget(this);
+    connect(findControlsWidget, SIGNAL(nextButtonPressed(QString, bool)), this,
             SLOT(nextButtonPressed(QString, bool)));
 
+    QAction *a = new QAction("Cancel", findControlsWidget);
+    a->setShortcut(Qt::Key_Escape);             // Escape in findControlsWidget
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    connect(a, SIGNAL(triggered()), this, SLOT(cancelPressed()));
+    addAction(a);
+
+    a = new QAction("Close", findControlsWidget);
+    a->setShortcut(Qt::CTRL | Qt::Key_D);       // Close window in findControlsWidget
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    connect(a, SIGNAL(triggered()), this, SLOT(closeWindow()));
+    addAction(a);
+
     QVBoxLayout *mainLayout = new QVBoxLayout;
 
     mainLayout->addWidget(view);
-    mainLayout->addWidget(findWidget);
+    mainLayout->addWidget(findControlsWidget);
 
     setLayout(mainLayout);
 
@@ -33,6 +49,8 @@ FindResultWidget::FindResultWidget(QWidget *)
             SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
             SLOT(updateSelection(QItemSelection, QItemSelection)));
 
+    connect(view, SIGNAL(searchFinished()), this, SLOT(searchFinished()));
+
     connect(resultsModel, SIGNAL(layoutChanged()), view, SLOT(expandAll()));
 }
 
@@ -40,7 +58,6 @@ void FindResultWidget::addItem(TreeItem *ti)
 {
     if (ti) {
         QModelIndex index = view->selectionModel()->currentIndex();
-        // QAbstractItemModel *resultsModel = view->model();
 
         if (!resultsModel->insertRow(index.row() + 1, index.parent()))
             return;
@@ -73,7 +90,7 @@ void FindResultWidget::addItem(const QString &s)
     }
 }
 
-QString FindResultWidget::getFindText() { return findWidget->getFindText(); }
+QString FindResultWidget::getFindText() { return findControlsWidget->getFindText(); }
 
 FindResultModel *FindResultWidget::getResultModel() { return resultsModel; }
 
@@ -81,13 +98,22 @@ void FindResultWidget::popup()
 {
     show();
     parentWidget()->show();
-    findWidget->setFocus();
+    findControlsWidget->setFocus();
+}
+
+void FindResultWidget::cancelPressed()
+{
+    mainWindow->escapePressed();
 }
 
-void FindResultWidget::cancelPressed() { emit hideFindResultWidget(); }
+void FindResultWidget::closeWindow()
+{
+    parentWidget()->hide();
+}
 
 void FindResultWidget::nextButtonPressed(QString s, bool searchNotesFlag)
 {
+    view->setFocus();
     emit findPressed(s, searchNotesFlag);
 }
 
@@ -109,7 +135,26 @@ void FindResultWidget::updateSelection(QItemSelection newsel, QItemSelection)
     }
 }
 
-void FindResultWidget::setStatus(FindWidget::Status st)
+void FindResultWidget::setStatus(FindControlsWidget::Status st)
+{
+    findControlsWidget->setStatus(st);
+}
+
+void FindResultWidget::searchFinished()
 {
-    findWidget->setStatus(st);
+    QModelIndexList sl = view->selectionModel()->selectedIndexes();
+    if (!sl.isEmpty() && sl.first().isValid()) {
+        FindResultItem *fri =
+            static_cast<FindResultItem *>(sl.first().internalPointer());
+        if (fri->getOrgModel() && fri->getOriginalID() > 0) {
+            TreeItem *ti = fri->getOrgModel()->findID(fri->getOriginalID());
+            if (ti) {
+                fri->getOrgModel()->select(ti);
+                int i = fri->getOriginalIndex();
+                if (i >= 0)
+                    emit noteSelected(resultsModel->getSearchString(), i);
+                parentWidget()->hide();
+            }
+        }
+    }
 }
index e4e1eae9add0587b14fe1691fa446769e37a6190..fa7cc0d81dbb8a077218b52574f1d60de5e32b05 100644 (file)
@@ -4,14 +4,15 @@
 #include <QItemSelection>
 #include <QWidget>
 
-#include "findwidget.h"
+#include "findcontrolswidget.h"
 
 class FindResultModel;
 class TreeItem;
 class VymModel;
 class QTreeView;
 class QPushButton;
-class FindWidget;
+class FindResultTreeView;
+class FindControlsWidget;
 
 class FindResultWidget : public QWidget {
     Q_OBJECT
@@ -26,9 +27,11 @@ class FindResultWidget : public QWidget {
   public slots:
     void popup();
     void cancelPressed();
+    void closeWindow();
     void nextButtonPressed(QString, bool);
     void updateSelection(QItemSelection, QItemSelection);
-    void setStatus(FindWidget::Status st);
+    void setStatus(FindControlsWidget::Status st);
+    void searchFinished();
 
   signals:
     void hideFindResultWidget();
@@ -36,11 +39,11 @@ class FindResultWidget : public QWidget {
     void findPressed(QString, bool);
 
   public:
-    FindWidget *findWidget;
+    FindControlsWidget *findControlsWidget;
 
   private:
     FindResultModel *resultsModel;
-    QTreeView *view;
+    FindResultTreeView *view;
 };
 
 #endif
diff --git a/src/findwidget.cpp b/src/findwidget.cpp
deleted file mode 100644 (file)
index d983644..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-#include <QAction>
-#include <QDebug>
-#include <QLabel>
-#include <QLineEdit>
-#include <QVBoxLayout>
-
-#include <QComboBox>
-#include <QGroupBox>
-#include <QLabel>
-#include <QPushButton>
-
-#include "findwidget.h"
-#include "mainwindow.h"
-
-extern Main *mainWindow;
-extern bool usingDarkTheme;
-extern QString iconTheme;
-
-FindWidget::FindWidget(QWidget *)
-{
-    QVBoxLayout *mainLayout = new QVBoxLayout;
-    QHBoxLayout *row2Layout = new QHBoxLayout;
-
-    QLabel *label = new QLabel;
-    label->setText(tr("Find:", "FindWidget"));
-
-    // Create LineEdit (here QComboBox)
-    findcombo = new QComboBox;
-    findcombo->setMinimumWidth(250);
-    findcombo->setEditable(true);
-
-    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-    findcombo->setSizePolicy(sizePolicy);
-    connect(findcombo, SIGNAL(highlighted(int)), this, SLOT(nextPressed()));
-    connect(findcombo, SIGNAL(editTextChanged(const QString &)), this,
-            SLOT(findTextChanged(const QString &)));
-
-    nextButton = new QPushButton;
-    nextButton->setIcon(QPixmap(QString(":/edit-find-%1.svg").arg(iconTheme)));
-    // nextButton->setText (tr("Find","Find widget"));
-    connect(nextButton, SIGNAL(clicked()), this, SLOT(nextPressed()));
-
-    // QAction needed to only activate shortcut while FindWidget has focus
-    QAction *a = new QAction(nextButton->text(), this);
-    a->setShortcut(Qt::Key_Return);
-    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    connect(a, SIGNAL(triggered()), this, SLOT(nextPressed()));
-    addAction(a);
-
-    filterNotesButton = new QPushButton;
-    filterNotesButton->setIcon(QPixmap(":/flag-note.svg"));
-    filterNotesButton->setCheckable(true);
-    filterNotesButton->setChecked(true);
-    connect(filterNotesButton, SIGNAL(clicked()), this, SLOT(nextPressed()));
-
-    row2Layout->addWidget(label);
-    row2Layout->addWidget(findcombo);
-    row2Layout->addWidget(nextButton);
-    row2Layout->addWidget(filterNotesButton);
-
-    mainLayout->addLayout(row2Layout);
-
-    setLayout(mainLayout);
-    status = Undefined;
-}
-
-QString FindWidget::getFindText() { return findcombo->currentText(); }
-
-void FindWidget::cancelPressed()
-{
-    hide();
-    emit hideFindWidget(); // Restore focus
-}
-
-void FindWidget::nextPressed()
-{
-    emit nextButtonPressed(findcombo->currentText(),
-                           filterNotesButton->isChecked());
-}
-
-void FindWidget::findTextChanged(const QString &) { setStatus(Undefined); }
-
-void FindWidget::setFocus()
-{
-    findcombo->lineEdit()->selectAll();
-    findcombo->lineEdit()->setFocus();
-}
-
-void FindWidget::setStatus(Status st)
-{
-    if (st == status)
-        return;
-
-    status = st;
-    QPalette p = palette();
-    QColor c;
-    if (usingDarkTheme)
-        switch (st) {
-            case Success:
-                c = QColor(0, 170, 0);
-                break;
-            case Failed:
-                c = QColor(170, 0, 0);
-                break;
-            default:
-                c = p.color(QPalette::Base);
-        }
-    else
-        switch (st) {
-            case Success:
-                c = QColor(120, 255, 120);
-                break;
-            case Failed:
-                c = QColor(255, 120, 120);
-                break;
-            default:
-                c = p.color(QPalette::Base);
-        }
-    p.setColor(QPalette::Active, static_cast<QPalette::ColorRole>(9), c);
-    p.setColor(QPalette::Inactive, static_cast<QPalette::ColorRole>(9), c);
-    findcombo->setPalette(p);
-}
diff --git a/src/findwidget.h b/src/findwidget.h
deleted file mode 100644 (file)
index be58ba2..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef FINDWIDGET_H
-#define FINDWIDGET_H
-
-#include <QWidget>
-
-class QAction;
-class QGroupBox;
-class QComboBox;
-class QPushButton;
-
-class FindWidget : public QWidget {
-    Q_OBJECT
-
-  public:
-    enum Status { Undefined, Success, Failed };
-
-    FindWidget(QWidget *parent = nullptr);
-    QString getFindText();
-
-  public slots:
-    void cancelPressed();
-    void nextPressed();
-    void findTextChanged(const QString &);
-    void setFocus();
-    void setStatus(Status st);
-
-  private:
-    Status status;
-
-  signals:
-    void hideFindWidget();
-    void nextButtonPressed(QString, bool);
-
-  private:
-    QComboBox *findcombo;
-    QGroupBox *findbox;
-    QPushButton *nextButton;
-    QPushButton *filterNotesButton;
-};
-
-#endif
index 246bea11f31e4381d569e1275f079a8413101a48..0a99419c92a5aa42e62abec24b2e91eb0a74ce3e 100644 (file)
@@ -74,8 +74,6 @@ void Flag::setName(const QString &n)
 
 const QString Flag::getName() { return name; }
 
-const QString Flag::getPath() { return path; }
-
 void Flag::setVisible(bool b) { visible = b; }
 
 bool Flag::isVisible() { return visible; }
index e36262b3df4db78610dd6ea2f5ec525ca56a334b..0062699653bed2b984468589a6e06cfbb41292c9 100644 (file)
@@ -32,7 +32,6 @@ class Flag : public XMLObj {
     bool load(const QString &);
     void setName(const QString &);
     const QString getName();
-    const QString getPath();
     void setVisible(bool b);
     bool isVisible();
     void setGroup(const QString &);
index 545ef1636a5bfdad93b938244327e019f47b20ac..a6e6e4f8f3c95175aa0d87e4918f340e44c14768 100644 (file)
@@ -73,7 +73,7 @@ Flag *FlagRowMaster::findFlagByUid(const QUuid &uid)
     return nullptr;
 }
 
-Flag *FlagRowMaster::findFlagByName(const QString &name)
+Flag *FlagRowMaster::findFlagByName(const QString &name)    // FIXME-3 called quite often. From taskEditor?
 {
     int i = 0;
     while (i <= flags.size() - 1) {
index 8e5f354107b0cb78debea4c91e52cd0b664f1377..69692b8b092fa56d08b40837b681c08b185fc10c 100644 (file)
@@ -256,22 +256,24 @@ void FrameContainer::updateGeometry(const QRectF &childRect)
 
     qreal pad = framePaddingInt + (framePen.width() - 1) / 2; // "Inner" padding and pen width
 
+    qreal wp = framePen.width();
+
     switch (frameTypeInt) {
         case NoFrame:
             break;
 
         case Rectangle:
             rectFrame->setRect(
-                childRect.left() - pad,
-                childRect.top() - pad,
-                childRect.width() + pad * 2,
-                childRect.height() + pad * 2);
+                childRect.left() - pad - wp,
+                childRect.top() - pad - wp,
+                childRect.width() + pad * 2 + wp * 2,
+                childRect.height() + pad * 2 + wp * 2);
 
             r.setRect(
-                    childRect.left() - pad * 2,
-                    childRect.top() - pad * 2,
-                    childRect.width() + pad * 4,
-                    childRect.height() + pad * 4);
+                    childRect.left() - pad * 2 - wp,
+                    childRect.top() - pad * 2 - wp,
+                    childRect.width() + pad * 4 + wp * 2,
+                    childRect.height() + pad * 4 + wp * 2);
             break;
 
         case RoundedRectangle: {
@@ -330,7 +332,7 @@ void FrameContainer::updateGeometry(const QRectF &childRect)
             path.cubicTo(bl + QPointF( - h, 0), tl + QPointF( - h, 0), tl);
  
             pathFrame->setPath(path);
-            QRectF r = path.boundingRect();
+            r = path.boundingRect();
 
             // center of pathFrame might be outside of origin, due to cloud not completely symmetrical
             // Correct position of pathFrame and child
@@ -383,7 +385,7 @@ void FrameContainer::updateGeometry(const QRectF &childRect)
             }
             break;
 
-        case Cloud: {
+        case Cloud: {   // FIXME-3 penWidth not considered? Compare other (working) types...
             QPointF tl = childRect.topLeft() + QPointF( - pad, - pad);
             QPointF tr = childRect.topRight() + QPointF(  pad, - pad);
             QPointF bl = childRect.bottomLeft() + QPointF( - pad, + pad);
@@ -449,10 +451,10 @@ void FrameContainer::updateGeometry(const QRectF &childRect)
             childContainers().first()->setPos(- br.center() + p);
 
             r.setRect(
-                    - (br.width() + pad) / 2,
-                    - (br.height() + pad) / 2,  // Vertically centered anyway later...
-                    br.width() + 2 * pad,
-                    br.height() + 2 * pad);
+                    - (br.width() + pad + wp) / 2,
+                    - (br.height() + pad + wp) / 2,  // Vertically centered anyway later...
+                    br.width() + 2 * pad + wp,
+                    br.height() + 2 * pad + wp);
             }
             break;
 
index fedfecc5caefa2b28655203a216e32fee8cd96b7..2d41b9d91b1dfad04bf89af2fe2a846e1c0a466b 100644 (file)
@@ -7,6 +7,9 @@
 extern Settings settings;
 extern Main *mainWindow;
 
+extern QString editorFocusInStyle;
+extern QString editorFocusOutStyle;
+
 HistoryWindow::HistoryWindow(QWidget *parent) : QDialog(parent)
 {
     ui.setupUi(this);
@@ -35,6 +38,18 @@ HistoryWindow::HistoryWindow(QWidget *parent) : QDialog(parent)
     connect(ui.historyTable, SIGNAL(itemSelectionChanged()), this,
             SLOT(select()));
 
+    QAction *a = new QAction(this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    a->setShortcut(Qt::CTRL | Qt::Key_D);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(closeWindow()));
+
+    a = new QAction(this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    a->setShortcut(Qt::Key_Escape);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), mainWindow, SLOT(escapePressed()));
+
     // Load Settings
 
     resize(
@@ -56,6 +71,8 @@ HistoryWindow::HistoryWindow(QWidget *parent) : QDialog(parent)
         2,
         settings.value("/satellite/historywindow/geometry/columnWidth/2", 250)
             .toInt());
+
+    ui.historyTable->setStyleSheet("QTableView:focus {" + editorFocusInStyle + "}");
 }
 
 HistoryWindow::~HistoryWindow()
@@ -179,8 +196,12 @@ void HistoryWindow::setStepsTotal(int st)
 
 void HistoryWindow::closeEvent(QCloseEvent *ce)
 {
-    ce->accept();
-    hide();
+    closeWindow();
+}
+
+void HistoryWindow::closeWindow()
+{
+    parentWidget()->hide();
     emit windowClosed();
 }
 
index e838712e200af73eeb915ea2a9814cf1002a7a9e..639fd510dba80b78e1f6397bdcfbb44ae440d449 100644 (file)
@@ -20,6 +20,7 @@ class HistoryWindow : public QDialog {
     void closeEvent(QCloseEvent *);
 
   private slots:
+    void closeWindow();
     void undo();
     void redo();
     void select();
index ca58c5ea3bf695bc1e0cdea321b6a71856360398..e8dbaf19495726cfaf4f5af7debb350767d9b565 100644 (file)
@@ -134,7 +134,8 @@ void ImageContainer::select()
 
 bool ImageContainer::load(const QString &fn)
 {
-    //qDebug() << "IC::load " << fn;
+    QFile file (fn);
+    // qDebug() << "IC::load " << fn << file.fileName(); 
     if (imageType != ImageContainer::Undefined) {
         qWarning() << "ImageContainer::load (" << fn
                    << ") into existing image of type " << imageType;
index 97ceb1e87ef025d055ad54d8df1f765a7ffc7cab..a44ec6861fed57092f44f5d3c0a607f4e0e0f775 100644 (file)
@@ -60,8 +60,9 @@ void JiraAgent::init()
     QObject::connect(killTimer, SIGNAL(timeout()), this, SLOT(timeout()));
 
     // Reset credentials, these are server specific beginning in 2.9.18
-    authUsingPATInt = true;
-    personalAccessTokenInt = QString();
+    authMethodInt.clear();
+    patTokenInt = QString();
+    apiTokenInt = QString();
     userNameInt = QString();
     passwordInt = QString();
     serverNameInt = QString();
@@ -77,30 +78,31 @@ bool JiraAgent::setJiraServer(int n)
 {
     bool foundServer = false;
 
-    bool usePAT = settings.value("authUsingPAT", true).toBool();
+    QString method = settings.value("method", "userpass").toString();
     QString url = settings.value("baseUrl", "").toString();
     if (!url.isEmpty()) {
         baseUrlInt = url;
         serverNameInt = settings.value("name","-").toString();
-        QString pat = settings.value("PAT", "").toString();
-        if (!pat.isEmpty()) {
-            authUsingPATInt = true;
-            personalAccessTokenInt = pat;
-            foundServer = true;
-        }
-
-        // Looking for username and password
-        QString user = settings.value("username", "").toString();
-        if (!user.isEmpty()) {
+        authMethodInt = method;
+        if (method == "userpass") {
+            userNameInt = settings.value("username", "").toString();
             QString pass = settings.value("password", "").toString();
-            if (!pass.isEmpty()) {
-                userNameInt = user;
+            if (!userNameInt.isEmpty() && !pass.isEmpty()) {
                 passwordInt = pass;
                 foundServer = true;
             }
+        } else if (method == "pat") {
+            patTokenInt = settings.value("PAT", "").toString();
+            if (!patTokenInt.isEmpty())
+                foundServer = true;
+        } else { // cloud
+            userNameInt = settings.value("email", "").toString();
+            apiTokenInt = settings.value("apiToken", "").toString();
+            if (!userNameInt.isEmpty() && !apiTokenInt.isEmpty())
+                foundServer = true;
         }
     }
-    qDebug() << __func__ << " n=" << n << "usePAT=" << authUsingPATInt << " userName=" << userNameInt;
+    qDebug() << __func__ << " n=" << n << " method=" << authMethodInt << " userName=" << userNameInt;
 
     return foundServer;
 }
@@ -195,26 +197,27 @@ bool JiraAgent::setQuery(const QString &s)  // FIXME-3 only works for first serv
                               // Search for project = PATTERN and use resulting server
 
     settings.beginGroup("/atlassian/jira/servers/1");
-    bool usePAT = settings.value("authUsingPAT", true).toBool();    // FIXME-3 should be done in setJiraServer
+    QString method = settings.value("method", "userpass").toString();
     QString url = settings.value("baseUrl", "").toString();
     if (!url.isEmpty()) {
         baseUrlInt = url;
-        //qDebug() << "JA::setQuery  url=" <<url;
-        QString pat = settings.value("PAT", "").toString();
-        if (!pat.isEmpty()) {
-            // Use PAT
-            personalAccessTokenInt = pat;
-            foundServer = true;
-        }
-
-        QString user = settings.value("username", "").toString();
-        if (!user.isEmpty()) {
+        authMethodInt = method;
+        if (method == "userpass") {
+            userNameInt = settings.value("username", "").toString();
             QString pass = settings.value("password", "").toString();
-            if (!pass.isEmpty()) {
-                userNameInt = user;
+            if (!userNameInt.isEmpty() && !pass.isEmpty()) {
                 passwordInt = pass;
                 foundServer = true;
             }
+        } else if (method == "pat") {
+            patTokenInt = settings.value("PAT", "").toString();
+            if (!patTokenInt.isEmpty())
+                foundServer = true;
+        } else { // cloud
+            userNameInt = settings.value("email", "").toString();
+            apiTokenInt = settings.value("apiToken", "").toString();
+            if (!userNameInt.isEmpty() && !apiTokenInt.isEmpty())
+                foundServer = true;
         }
     }
     settings.endGroup();
@@ -332,27 +335,24 @@ void JiraAgent::startGetTicketRequest()
 
     QNetworkRequest request = QNetworkRequest(u);
 
-    // Basic authentication in header
     QString headerData;
-
-    if (authUsingPATInt) {
-        //headerData = QString("Bearer %1").arg(personalAccessTokenInt);
-        QString concatenated = userNameInt + ":" + personalAccessTokenInt;
+    if (authMethodInt == "pat") {
+        headerData = QString("Bearer %1").arg(patTokenInt);
+    } else if (authMethodInt == "cloud") {
+        QString concatenated = userNameInt + ":" + apiTokenInt;
         QByteArray data = concatenated.toLocal8Bit().toBase64();
         headerData = "Basic " + data;
-        // qDebug() << " - UN + PAT: " << concatenated;
-    } else {
+    } else { // userpass
         QString concatenated = userNameInt + ":" + passwordInt;
         QByteArray data = concatenated.toLocal8Bit().toBase64();
         headerData = "Basic " + data;
-        // qDebug() << " - UN + PW: " << concatenated;
     }
 
     request.setRawHeader("Authorization", headerData.toLocal8Bit());
 
     if (debug) {
         qDebug() << "JA::startGetTicketRequest: url = " + request.url().toString();
-        qDebug() << "                  authUsingPAT = " << authUsingPATInt;
+        qDebug() << "                  method = " << authMethodInt;
     }
 
     killTimer->start();
@@ -402,19 +402,17 @@ void JiraAgent::startQueryRequest()
 
     QNetworkRequest request = QNetworkRequest(u);
 
-    // Basic authentication in header
     QString headerData;
-    if (authUsingPATInt) {
-        //headerData = QString("Bearer %1").arg(personalAccessTokenInt);
-        QString concatenated = userNameInt + ":" + personalAccessTokenInt;
+    if (authMethodInt == "pat") {
+        headerData = QString("Bearer %1").arg(patTokenInt);
+    } else if (authMethodInt == "cloud") {
+        QString concatenated = userNameInt + ":" + apiTokenInt;
         QByteArray data = concatenated.toLocal8Bit().toBase64();
         headerData = "Basic " + data;
-        // qDebug() << " - UN + PAT: " << concatenated;
-    } else {
+    } else { // userpass
         QString concatenated = userNameInt + ":" + passwordInt;
         QByteArray data = concatenated.toLocal8Bit().toBase64();
         headerData = "Basic " + data;
-        // qDebug() << " - UN + PW: " << concatenated;
     }
     request.setRawHeader("Authorization", headerData.toLocal8Bit());
 
index ef5c80559c66b8ea155ca60ee41f8c70e964f7e1..73d6e42f67d18b7f06a3b7cc1cb0b9f221605c91 100644 (file)
@@ -71,8 +71,9 @@ class JiraAgent : public QObject {
     QJsonObject jsobj;
 
     // Settings: Credentials to access JIRA
-    bool authUsingPATInt;
-    QString personalAccessTokenInt;
+    QString authMethodInt; // userpass | pat | cloud
+    QString patTokenInt;
+    QString apiTokenInt;
     QString userNameInt;
     QString passwordInt;
 
index adb6f401ad48cf6219a401aac36f72aad3a72896..d2d93278eaccb3cada21c0bddd9a26b1d8150b44 100644 (file)
@@ -1,6 +1,7 @@
 #include "jira-settings-dialog.h"
 
 #include <QDebug>
+#include <QSignalBlocker>
 
 #include "settings.h"
 
@@ -13,7 +14,7 @@ JiraSettingsDialog::JiraSettingsDialog(QWidget *parent) : QDialog(parent)
     QDialog::setWindowTitle("VYM - " +
                             tr("Jira settings", "Jira settings dialog title"));
 
-    ui.tableWidget->setColumnCount(5);
+    ui.tableWidget->setColumnCount(4);
 
         settings.beginGroup("/atlassian/jira");
         QTableWidgetItem *newItem;
@@ -23,7 +24,6 @@ JiraSettingsDialog::JiraSettingsDialog(QWidget *parent) : QDialog(parent)
         headers << "URL";
         headers << "Pattern";
         headers << "Method";
-        headers << "User";
         ui.tableWidget->setHorizontalHeaderLabels(headers);
 
         int size = settings.beginReadArray("servers");
@@ -41,14 +41,14 @@ JiraSettingsDialog::JiraSettingsDialog(QWidget *parent) : QDialog(parent)
                 newItem = new QTableWidgetItem(settings.value("pattern").toString());
                 ui.tableWidget->setItem(0, 2, newItem);
 
-                if (settings.value("authUsingPAT").toString() == "true")
+                QString method = settings.value("method", "userpass").toString();
+                if (method == "userpass")
+                    newItem = new QTableWidgetItem("Username/Password");
+                else if (method == "pat")
                     newItem = new QTableWidgetItem("PAT");
                 else
-                    newItem = new QTableWidgetItem("Username/Password");
+                    newItem = new QTableWidgetItem("Cloud");
                 ui.tableWidget->setItem(0, 3, newItem);
-
-                newItem = new QTableWidgetItem(settings.value("username","-").toString());
-                ui.tableWidget->setItem(0, 4, newItem);
             }
         }
         settings.endArray();
@@ -71,7 +71,11 @@ JiraSettingsDialog::JiraSettingsDialog(QWidget *parent) : QDialog(parent)
             this, SLOT(fieldsChanged()));
     connect(ui.PATLineEdit, SIGNAL(editingFinished()), 
             this, SLOT(fieldsChanged()));
-    connect(ui.usePATCheckBox, SIGNAL(clicked()), 
+    connect(ui.apiTokenLineEdit, SIGNAL(editingFinished()), 
+            this, SLOT(fieldsChanged()));
+    connect(ui.authMethodComboBox, SIGNAL(currentIndexChanged(int)),
+            this, SLOT(updateAuthenticationFields()));
+    connect(ui.authMethodComboBox, SIGNAL(currentIndexChanged(int)),
             this, SLOT(fieldsChanged()));
     connect(ui.tableWidget, SIGNAL(cellChanged(int, int)),
             this, SLOT(fieldsChanged()));
@@ -91,29 +95,35 @@ void JiraSettingsDialog::deleteServer()
 
 void JiraSettingsDialog::updateAuthenticationFields()
 {
-    QModelIndexList ixl = ui.tableWidget->selectionModel()->selectedIndexes();
-
-    int row;
-    if (ixl.isEmpty() || ixl.count() > 1)
-        row = -1;
-    else
-        row = ixl.first().row();
+    int rowCount = ui.tableWidget->rowCount();
+    int row = -1;
+    if (ui.tableWidget->selectionModel()) {
+        QModelIndexList sel = ui.tableWidget->selectionModel()->selectedIndexes();
+        if (!sel.isEmpty()) row = sel.first().row();
+    }
 
     if (row < 0) {
-        // No server selected, disable fields
         ui.selectedServerLineEdit->setText("");
-        ui.usePATCheckBox->setEnabled(false);
+        ui.authMethodComboBox->setEnabled(false);
+        ui.authMethodComboBox->hide();
+        ui.authMethodLabel->hide();
         ui.PATLineEdit->setEnabled(false);
-        ui.PATLabel->setEnabled(false);
-        ui.userLabel->setEnabled(false);
+        ui.PATLineEdit->hide();
+        ui.PATLabel->hide();
+        ui.apiTokenLineEdit->setEnabled(false);
+        ui.apiTokenLineEdit->hide();
+        ui.apiTokenLabel->hide();
         ui.userLineEdit->setEnabled(false);
-        ui.passwordLabel->setEnabled(false);
+        ui.userLineEdit->hide();
+        ui.userLabel->hide();
         ui.passwordLineEdit->setEnabled(false);
+        ui.passwordLineEdit->hide();
+        ui.passwordLabel->hide();
 
-        // Empty unused fields
         ui.userLineEdit->setText("");
         ui.passwordLineEdit->setText("");
         ui.PATLineEdit->setText("");
+        ui.apiTokenLineEdit->setText("");
 
     } else {
         // Index of selected server in settings
@@ -125,57 +135,75 @@ void JiraSettingsDialog::updateAuthenticationFields()
             ui.selectedServerLineEdit->setText( ui.tableWidget->item(row, 0)->text());
         else
             ui.selectedServerLineEdit->setText("");
-        ui.usePATCheckBox->setEnabled(true);
-        ui.usePATCheckBox->setChecked(
-            settings.value(selectedServer + "authUsingPAT", true).toBool());
+        // Block signal emissions while updating widgets to avoid re-entrancy
+        QSignalBlocker blockCombo(ui.authMethodComboBox);
+        QSignalBlocker blockUser(ui.userLineEdit);
+        QSignalBlocker blockPass(ui.passwordLineEdit);
+        QSignalBlocker blockPat(ui.PATLineEdit);
+
+        ui.authMethodComboBox->setEnabled(true);
+        ui.authMethodComboBox->show();
+        ui.authMethodLabel->show();
         ui.PATLineEdit->setEnabled(true);
         ui.PATLabel->setEnabled(true);
+        ui.apiTokenLineEdit->setEnabled(true);
+        ui.apiTokenLabel->setEnabled(true);
         ui.userLabel->setEnabled(true);
         ui.userLineEdit->setEnabled(true);
         ui.passwordLabel->setEnabled(true);
         ui.passwordLineEdit->setEnabled(true);
 
-        // Show and prefill fields depending on usage of PAT
-        if (ui.usePATCheckBox->isChecked()) {
+        int methodIdx = ui.authMethodComboBox->currentIndex();
+        if (methodIdx == 2) { // cloud
+            ui.apiTokenLineEdit->show();
+            ui.apiTokenLineEdit->setText(
+                settings.value(selectedServer + "apiToken","").toString());
+            ui.apiTokenLabel->show();
+            ui.PATLineEdit->hide();
+            ui.PATLabel->hide();
+            ui.userLabel->show();
+            ui.userLabel->setText(tr("Email:"));
+            ui.userLineEdit->show();
+            ui.userLineEdit->setText(
+                settings.value(QString("/atlassian/jira/servers/%1/email").arg(n_server), "").toString());
+            ui.passwordLabel->hide();
+            ui.passwordLineEdit->hide();
+        } else if (methodIdx == 1) { // PAT
             ui.PATLineEdit->show();
             ui.PATLineEdit->setText(
                 settings.value(selectedServer + "PAT","").toString());
-                settings.value(selectedServer + "PAT","").toString();
             ui.PATLabel->show();
+            ui.apiTokenLineEdit->hide();
+            ui.apiTokenLabel->hide();
             ui.userLabel->hide();
             ui.userLineEdit->hide();
             ui.passwordLabel->hide();
             ui.passwordLineEdit->hide();
-        } else {
+        } else { // user/pass
             ui.PATLineEdit->hide();
             ui.PATLabel->hide();
+            ui.apiTokenLineEdit->hide();
+            ui.apiTokenLabel->hide();
             ui.userLabel->show();
+            ui.userLabel->setText(tr("Username:"));
             ui.userLineEdit->show();
             ui.userLineEdit->setText(
-                settings.value(QString("/atlassian/jira/servers/%1/username").arg(n_server), "-").toString());
+                settings.value(QString("/atlassian/jira/servers/%1/username").arg(n_server), "").toString());
             ui.passwordLabel->show();
             ui.passwordLineEdit->show();
             ui.passwordLineEdit->setText(
                 settings.value(QString("/atlassian/jira/servers/%1/password").arg(n_server), "").toString());
         }
     }
-
-    // Update layout
-    adjustSize();
 }
 
 
 void JiraSettingsDialog::fieldsChanged()
 {
     int rowCount = ui.tableWidget->rowCount();
-
     if (rowCount < 1) return;
-
-    QModelIndexList ixl = ui.tableWidget->selectionModel()->selectedIndexes();
-
-    if (ixl.isEmpty() || ixl.count() > 1) return;
-
-    int row = ixl.first().row();
+    int row = ui.tableWidget->currentRow();
+    if (row < 0 || row >= rowCount) return;
     int n_server = rowCount - 1 - row;
 
     if (n_server < 0) return;
@@ -196,24 +224,63 @@ void JiraSettingsDialog::fieldsChanged()
         settings.setValue("pattern", ui.tableWidget->item(row, 2)->text());
     else
         settings.setValue("pattern", "");
-    settings.setValue("authUsingPAT", ui.usePATCheckBox->isChecked());
-    if (ui.usePATCheckBox->isChecked()) {
-        // Don't save password if PAT is used
-        settings.remove("password");
-        settings.setValue("PAT", ui.PATLineEdit->text());
-    } else {
+
+    int methodIdx = ui.authMethodComboBox->currentIndex();
+    QString method = (methodIdx == 0) ? "userpass" : (methodIdx == 1) ? "pat" : "cloud";
+    settings.setValue("method", method);
+    if (method == "userpass") {
         settings.setValue("username", ui.userLineEdit->text());
         settings.setValue("password", ui.passwordLineEdit->text());
-        settings.remove("PAT");
+    } else if (method == "pat") {
+        settings.setValue("PAT", ui.PATLineEdit->text());
+    } else { // cloud
+        settings.setValue("email", ui.userLineEdit->text());
+        settings.setValue("apiToken", ui.apiTokenLineEdit->text());
     }
     settings.setValue("servers/size", rowCount);
 
     settings.endArray();
     settings.endGroup();
+
+    // Reflect method in table overview without re-triggering cellChanged
+    {
+        QSignalBlocker blockTable(ui.tableWidget);
+        QString methodText = (method == "userpass") ? "Username/Password" : (method == "pat") ? "PAT" : "Cloud";
+        QTableWidgetItem *methodItem = new QTableWidgetItem(methodText);
+        ui.tableWidget->setItem(row, 3, methodItem);
+    }
 }
 
 void JiraSettingsDialog::selectionChanged(const QItemSelection &selected, const QItemSelection &)
 {
+    Q_UNUSED(selected);
+
+    // If nothing selected, just refresh to the hidden state
+    if (!ui.tableWidget->selectionModel() ||
+        ui.tableWidget->selectionModel()->selectedIndexes().isEmpty()) {
+        updateAuthenticationFields();
+        return;
+    }
+
+    int row = ui.tableWidget->selectionModel()->selectedIndexes().first().row();
+    int rowCount = ui.tableWidget->rowCount();
+    if (row < 0 || row >= rowCount) {
+        updateAuthenticationFields();
+        return;
+    }
+
+    int n_server = rowCount - row; // absolute numbering used in settings path
+    QString selectedServer = QString("/atlassian/jira/servers/%1/").arg(n_server);
+
+    // Load and set method for selected server without triggering save yet
+    QString method = settings.value(selectedServer + "method", "userpass").toString();
+    int methodIndex = 0; // 0=userpass,1=pat,2=cloud
+    if (method == "pat") methodIndex = 1;
+    else if (method == "cloud") methodIndex = 2;
+    {
+        QSignalBlocker blockCombo(ui.authMethodComboBox);
+        ui.authMethodComboBox->setCurrentIndex(methodIndex);
+    }
+
     updateAuthenticationFields();
 }
-
index 94e14885ef16d0088c710285906c1da45cad5a45..88949f74ef093f2d0907234b1bc98d2e7a9c0f70 100644 (file)
@@ -11,7 +11,6 @@
 #include "command.h"
 #include "debuginfo.h"
 #include "findresultwidget.h"
-#include "findwidget.h"
 #include "flagrow-master.h"
 #include "headingeditor.h"
 #include "macros.h"
@@ -59,7 +58,7 @@ BranchPropertyEditor *branchPropertyEditor;
 Main *mainWindow;
 ScriptEditor *scriptEditor;
 ScriptOutput *scriptOutput;
-FindWidget *findWidget;
+FindControlsWidget *findControlsWidget;
 FindResultWidget *findResultWidget;
 TaskEditor *taskEditor;
 
@@ -138,9 +137,11 @@ int warningCount = 0;
 int criticalCount = 0;
 int fatalCount = 0;
 
-QString editorFocusStyle =
-    QString(" border-color: #3daee9; border-style:outset; border-width:3px; "
-            "color:black;");
+// Some styles used in various widgets
+QString editorFocusInStyle =
+    QString(" border-color: #3daee9; border-style:outset; border-width:1px; ");// "color:black;");
+QString editorFocusOutStyle = QString("border-width:0px;");
+QString toolBarStyle;
 
 void msgHandler(QtMsgType type, const QMessageLogContext &context,
                 const QString &msg)
@@ -433,9 +434,14 @@ int main(int argc, char *argv[])
             iconTheme = "dark";
         }
     }
+    /*
+    qDebug() << "dark settings: " << settingsDarkTheme
+        << " systemDark=" << systemSeemsDark
+        << " useDark" << usingDarkTheme;
+    */
 
     QPalette palette;
-    if (usingDarkTheme && settingsDarkTheme == "always") {
+    if (usingDarkTheme) {
         qApp->setStyle(QStyleFactory::create("fusion"));
         //qApp->setStyle(QStyleFactory::create("Windows"));
         //qApp->setStyle(QStyleFactory::create("windowsvista"));
@@ -447,7 +453,6 @@ int main(int argc, char *argv[])
         palette.setColor(QPalette::AlternateBase, QColor(53,53,53));
         palette.setColor(QPalette::ToolTipBase, QColor(53,53,53));
         palette.setColor(QPalette::ToolTipText, Qt::white);
-        // Unused: QPalette::PlaceHolderText
         palette.setColor(QPalette::Text, Qt::white);
         palette.setColor(QPalette::Button, QColor(53,53,53));
         palette.setColor(QPalette::ButtonText, Qt::white);
@@ -461,9 +466,49 @@ int main(int argc, char *argv[])
         qApp->setPalette(palette);
 
         vymBlueColor =QColor::fromString("#00aaff");
-    } else
+    } else {
+        if (systemSeemsDark) {
+            qApp->setStyle(QStyleFactory::create("macOS"));
+            palette.setColor(QPalette::Window, QColor("#ececec"));          // 10
+            palette.setColor(QPalette::WindowText, Qt::black);              //  0
+            palette.setColor(QPalette::Base, QColor("#ffffff"));            //  9
+            palette.setColor(QPalette::AlternateBase, QColor(253,53,53));   // 16
+            palette.setColor(QPalette::ToolTipBase, Qt::white);             // 18
+            palette.setColor(QPalette::ToolTipText, Qt::black);             // 19
+            palette.setColor(QPalette::Text, Qt::black);                    //  6
+            palette.setColor(QPalette::Button, QColor("#ececec"));          //  1
+            palette.setColor(QPalette::ButtonText, Qt::black);              //  8
+            palette.setColor(QPalette::BrightText, Qt::white);              //  7
+
+            /*
+            QPalette::Light    2       Lighter than Button color.
+            QPalette::Midlight 3       Between Button and Light.
+            QPalette::Dark     4       Darker than Button.
+            QPalette::Mid      5       Between Button and Dark.
+            QPalette::Shadow   11      A very dark color. By default, shadow color is Qt::black.
+            */
+            palette.setColor(QPalette::Light, QColor("#ffffff"));           //  2
+            palette.setColor(QPalette::Midlight, QColor("#f5f5f5"));        //  3
+            palette.setColor(QPalette::Dark, QColor("#bfbfbf"));            //  4
+            palette.setColor(QPalette::Mid, QColor("#a9a9a9"));             //  5
+            palette.setColor(QPalette::Shadow, Qt::black);                  // 11
+
+            // Roles of seleced items
+            palette.setColor(QPalette::Highlight, QColor("#a5cdff"));       // 12
+            palette.setColor(QPalette::HighlightedText, Qt::black);         // 13
+
+            // Links
+            /*
+            QPalette::Link     14
+            QPalette::LinkVisited      15
+             */
+            qApp->setPalette(palette);
+        }
+
         vymBlueColor =QColor::fromString("#0000ff");
+    }
 
+    //  toolBarStyle = "background-color: " + palette.color(QPalette::Button).name() + "; border: None;";   // FIXME-3  Checked buttons no longer visible, introduced for forced bright theme
     vymForegroundColor = palette.color(QPalette::WindowText);
     vymBaseColor = palette.color(QPalette::Base);
 
@@ -531,6 +576,7 @@ int main(int argc, char *argv[])
 
     // Initialize editors
     noteEditor = new NoteEditor(QObject::tr("Note Editor", "Name of editor shown as window title"));
+
     headingEditor = new HeadingEditor(QObject::tr("Heading Editor", "Name of editor shown as window title"));
     branchPropertyEditor = new BranchPropertyEditor();
 
@@ -538,14 +584,27 @@ int main(int argc, char *argv[])
     // overwritten during loading of maps
     lastSessionFiles = settings.value("/mainwindow/sessionFileList", QStringList()).toStringList();
 
-
     // Logfiles (no GUI yet for settings)
     useActionLog = settings.value("/logfile/enabled", false).toBool();
     actionLogPath = settings.value("/logfile/path", QDir::homePath() + "/vym.log").toString();
 
-    // Create MainWindow
+    // Create MainWindow (after creating editors)
     Main m;
 
+    // Add Escape-keys to editors (after creating MainWindow)
+    QAction *a = new QAction("Cancel", noteEditor);
+    a->setShortcut(Qt::Key_Escape);     // Escape in NoteEditor
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    noteEditor->connect(a, SIGNAL(triggered()), mainWindow, SLOT(escapePressed()));
+    noteEditor->addAction(a);
+
+    a = new QAction("Cancel", headingEditor);
+    a->setShortcut(Qt::Key_Escape);     // Escape in HeadingEditor
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    headingEditor->connect(a, SIGNAL(triggered()), mainWindow, SLOT(escapePressed()));
+    headingEditor->addAction(a);
+
+
     // Check for zip tools
     zipToolAvailable = ZipAgent::checkZipTool();
     unzipToolAvailable = ZipAgent::checkUnzipTool();
@@ -647,8 +706,9 @@ int main(int argc, char *argv[])
     // Enable some last minute cleanup
     QObject::connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
 
-    // For benchmarking we may want to quit instead of entering event loop
-    if (options.isActive("quit"))
+    // For benchmarking or if test script is done
+    // we may want to quit instead of entering event loop
+    if (options.isActive("quit") || m.exitAfterScript())
         m.fileExitVYM();
     else
         app.exec();
index b46a4d3961b937d7f48a091b3db9e7ea06e6054b..c5006f5f7a9e1aa1a1d0bfbdaeeb9cc9183ac6cc 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <iostream>
 
-#define ADD_SHORTCUT a->setToolTip(a->toolTip() + QString(" (%1)").arg(a->shortcut().toString())); a->setShortcutVisibleInContextMenu(true);
 #if defined(VYM_DBUS)
 #include "adaptorvym.h"
 #endif
@@ -119,19 +118,10 @@ extern QString iconTheme;
 extern bool useActionLog;
 extern QString actionLogPath;
 
-QMenu *branchAddContextMenu;
 QMenu *branchContextMenu;
-QMenu *branchLinksContextMenu;
-QMenu *branchRemoveContextMenu;
-QMenu *branchXLinksContextMenuEdit;
-QMenu *branchXLinksContextMenuFollow;
 QMenu *canvasContextMenu;
 QMenu *floatimageContextMenu;
-QMenu *targetsContextMenu;
 QMenu *taskContextMenu;
-QMenu *fileLastMapsMenu;
-QMenu *fileImportMenu;
-QMenu *fileExportMenu;
 
 extern Settings settings;
 extern Options options;
@@ -148,6 +138,8 @@ extern QDir vymInstallDir;
 
 extern QColor vymBlueColor;
 
+extern QString toolBarStyle;
+
 Main::Main(QWidget *parent) : QMainWindow(parent)
 {
     // qDebug() << "Constr. MainWindow";
@@ -213,9 +205,25 @@ Main::Main(QWidget *parent) : QMainWindow(parent)
 
     layout->addWidget(tabWidget);
 
-    switchboard.addGroup("MainWindow", tr("Main window", "Shortcut group"));
-    switchboard.addGroup("MapEditor", tr("Map Editors", "Shortcut group"));
-    switchboard.addGroup("TextEditor", tr("Text Editors", "Shortcut group"));
+    switchboard.addScope("MainWindow", tr("Main window", "Shortcut group"));
+    switchboard.addScope("MapEditor", tr("Map Editors", "Shortcut group"));
+    switchboard.addScope("TextEditor", tr("Text Editors", "Shortcut group"));
+
+    // Create main menus
+
+    fileMenu = menuBar()->addMenu(tr("&Map", "Map menu"));
+    editMenu = menuBar()->addMenu(tr("E&dit", "Edit menu"));
+    selectMenu = menuBar()->addMenu(tr("Select", "Select menu"));
+    formatMenu = menuBar()->addMenu(tr("F&ormat", "Format menu"));
+    viewMenu = menuBar()->addMenu(tr("&View"));
+    toolbarsMenu =
+        viewMenu->addMenu(tr("Toolbars", "Toolbars overview in view menu"));
+    windowsMenu =
+        viewMenu->addMenu(tr("Windows", "Editor windows overview in view menu"));
+
+    viewMenu->addSeparator();
+
+    connectMenu = menuBar()->addMenu(tr("&Connect"));
 
     // Setup actions
     setupFileActions();
@@ -232,12 +240,14 @@ Main::Main(QWidget *parent) : QMainWindow(parent)
     setupToolbars();
     setupFlagActions();
 
+    // Populate menus
+    setupEditMenu();
+
     // Dock widgets ///////////////////////////////////////////////
     QDockWidget *dw;
     dw = new QDockWidget();
     dw->setWidget(noteEditor);
     dw->setObjectName("NoteEditor");
-    dw->setWindowTitle(noteEditor->getEditorTitle());
     dw->hide();
     noteEditorDW = dw;
     addDockWidget(Qt::LeftDockWidgetArea, dw);
@@ -245,7 +255,6 @@ Main::Main(QWidget *parent) : QMainWindow(parent)
     dw = new QDockWidget();
     dw->setWidget(headingEditor);
     dw->setObjectName("HeadingEditor");
-    dw->setWindowTitle(headingEditor->getEditorTitle());
     dw->hide();
     headingEditorDW = dw;
     addDockWidget(Qt::BottomDockWidgetArea, dw);
@@ -294,7 +303,7 @@ Main::Main(QWidget *parent) : QMainWindow(parent)
     // Connect NoteEditor, so that we can update flags if text changes
     connect(noteEditor, SIGNAL(textHasChanged(VymText)), this,
             SLOT(updateNoteText(VymText)));
-    connect(noteEditor, SIGNAL(windowClosed()), this, SLOT(updateActions()));
+    connect(noteEditor, SIGNAL(windowClosed()), this, SLOT(updateActions()));   // FIXME-2 windowCLosed needed after all?
 
     // Connect heading editor
     connect(headingEditor, SIGNAL(textHasChanged(const VymText &)), this,
@@ -303,15 +312,6 @@ Main::Main(QWidget *parent) : QMainWindow(parent)
     connect(scriptEditor, SIGNAL(runScript(QString)), this,
             SLOT(runScript(QString)));
 
-    // Switch back  to MapEditor using Esc  or end presentation mode
-    QAction *a = new QAction(this);
-    a->setShortcut(Qt::Key_Escape);
-    a->setShortcutContext(Qt::ApplicationShortcut);
-    a->setCheckable(false);
-    a->setEnabled(true);
-    addAction(a);
-    connect(a, SIGNAL(triggered()), this, SLOT(escapePressed()));
-
     // Create TaskEditor after setting up above actions, allow cloning
     taskEditor = new TaskEditor();
     dw = new QDockWidget(tr("Task list", "TaskEditor"));
@@ -342,13 +342,13 @@ Main::Main(QWidget *parent) : QMainWindow(parent)
     progressDialog.setCancelButton(nullptr);
 
     // Load window settings
-    restoreState(settings.value("/mainwindow/state", 0).toByteArray());
+    restoreState(settings.value("/mainwindow/state").toByteArray());
     restoreGeometry(settings.value("/mainwindow/geometry").toByteArray());
 
     updateGeometry();
 
-    actionViewToggleTreeEditor->setChecked(settings.value("/mainwindow/view/showTreeEditors", true).toBool());
-    actionViewToggleSlideEditor->setChecked(settings.value("/mainwindow/view/showSlideEditors", false).toBool());
+    windowSetTreeEditorsVisibility(settings.value("/mainwindow/view/showTreeEditors", true).toBool());
+    windowSetSlideEditorsVisibility(settings.value("/mainwindow/view/showSlideEditors", false).toBool());
 
     // After startup, schedule looking for updates AFTER
     // release notes have been downloaded
@@ -361,11 +361,17 @@ Main::Main(QWidget *parent) : QMainWindow(parent)
     if (!QDBusConnection::sessionBus().registerObject("/vym", this))
         qWarning("MainWindow: Couldn't register DBUS object!");
 #endif
+
+    // Allows a (test-)script to make vym quit after script execution
+    exitAfterScriptInt = false;
+
+    backgroundZipProcesses = 0;
+    closeAfterLastZipProcess = false;
 }
 
 Main::~Main()
 {
-    // qDebug() << "Destr Mainwindow";
+    //qDebug() << "Destr Mainwindow begin";
 
     // Make sure there is no focus elsewhere, e.g. in BranchPropertyEditor
     // which could cause a crash.  (Qt bug?)
@@ -375,13 +381,8 @@ Main::~Main()
 
     if (!testmode) {
         settings.setValue("/mainwindow/geometry", saveGeometry());
-        settings.setValue("/mainwindow/state", saveState(0)); // FIXME-3 use saveState and saveGeometry
-                                                              // https://doc.qt.io/qt-6/qmainwindow.html#saveState
-
-        settings.setValue("/mainwindow/view/showTreeEditors",
-                actionViewToggleTreeEditor->isChecked());
-        settings.setValue("/mainwindow/view/showSlideEditors",
-                actionViewToggleSlideEditor->isChecked());
+        settings.setValue("/mainwindow/state", saveState()); // FIXME-3 use restoreDockWidget
+                                                             // https://doc.qt.io/qt-6/qmainwindow.html#saveState
 
         settings.setValue("/mainwindow/view/AntiAlias",
                           actionViewToggleAntiAlias->isChecked());
@@ -407,8 +408,6 @@ Main::~Main()
             settings.setValue("/system/printerFileName",
                               printer->outputFileName());
         }
-        settings.setValue("/mapeditor/editmode/autoSelectText",
-                          actionSettingsAutoSelectText->isChecked());
         settings.setValue("/mapeditor/editmode/useFlagGroups",
                           actionSettingsUseFlagGroups->isChecked());
         settings.setValue("/export/useHideExport",
@@ -425,6 +424,8 @@ Main::~Main()
     delete standardFlagsMaster;
     delete userFlagsMaster;
     delete systemFlagsMaster;
+
+    //qDebug() << "Destr Mainwindow end";
 }
 
 void Main::loadCmdLine()
@@ -536,7 +537,11 @@ void Main::setupAPI()
     // Below are the commands for vym itself
     //
 
-    Command *c = new Command("clearConsole", Command::AnySel);
+    Command *c = new Command("callMacro", Command::AnySel);
+    c->addParameter(Command::StringPar, false, "Include macros and run script");
+    vymCommands.append(c);
+
+    c = new Command("clearConsole", Command::AnySel);
     vymCommands.append(c);
 
     c = new Command("closeMapWithID", Command::AnySel);
@@ -546,7 +551,7 @@ void Main::setupAPI()
     c = new Command("currentColor", Command::AnySel);
     vymCommands.append(c);
 
-    c = new Command("currentMap", Command::AnySel);
+    c = new Command("currentMap", Command::AnySel, Command::VymModelPar);
     vymCommands.append(c);
 
     c = new Command("currentMapIndex", Command::AnySel);
@@ -555,6 +560,10 @@ void Main::setupAPI()
     c = new Command("editHeading", Command::BranchSel);
     vymCommands.append(c);
 
+    c = new Command("exit", Command::AnySel);
+    c->setComment("Exit vym after script execution");
+    vymCommands.append(c);
+
     c = new Command("gotoMap", Command::AnySel);
     c->addParameter(Command::IntPar, false, "Index of map");
     vymCommands.append(c);
@@ -566,6 +575,10 @@ void Main::setupAPI()
     c = new Command("mapCount", Command::AnySel);
     vymCommands.append(c);
 
+    c = new Command("mapWithId", Command::AnySel, Command::VymModelPar);
+    c->addParameter(Command::IntPar, false, "unique id of map");
+    vymCommands.append(c);
+
     c = new Command("print", Command::AnySel);
     c->setComment("Print string to console");
     c->addParameter(Command::StringPar, false, "String to print");
@@ -581,9 +594,6 @@ void Main::setupAPI()
     c->addParameter(Command::IntPar, false, "Index of quick color [0..6]");
     vymCommands.append(c);
 
-    c = new Command("toggleTreeEditor", Command::AnySel);
-    vymCommands.append(c);
-
     c = new Command("usesDarkTheme", Command::AnySel, Command::BoolPar);
     vymCommands.append(c);
 
@@ -781,7 +791,7 @@ void Main::setupAPI()
     c->addParameter(Command::IntPar, false, "Index of slide to remove");
     modelCommands.append(c);
 
-    c = new Command("repeatLastCommand", Command::AnySel);
+    c = new Command("repeatLastAction", Command::AnySel);
     modelCommands.append(c);
 
     c = new Command("resetBranchIterator", Command::BranchSel, Command::BoolPar);
@@ -800,6 +810,9 @@ void Main::setupAPI()
     c = new Command("selectedBranch", Command::AnySel, Command::BranchPar);
     modelCommands.append(c);
 
+    c = new Command("selectedBranches", Command::AnySel, Command::BranchListPar);
+    modelCommands.append(c);
+
     c = new Command("selectLatestAdded", Command::AnySel, Command::BoolPar);
     modelCommands.append(c);
 
@@ -848,14 +861,8 @@ void Main::setupAPI()
     c->addParameter(Command::DoublePar, false, "Rotation of view of map");
     modelCommands.append(c);
 
-    c = new Command("setTitle", Command::AnySel);
-    c->addParameter(Command::StringPar, false, "");
-    modelCommands.append(c);
-
-    c = new Command("setZoom", Command::AnySel);
-    c->addParameter(Command::DoublePar, false, "Zoomfactor of map");
-    modelCommands.append(c);
-
+    c = new Command("setSelectionBrushColor", Command::AnySel);
+    c->addParameter(Command::ColorPar, false, "Color of selection box background");
     modelCommands.append(c);
 
     c = new Command("setSelectionColor", Command::AnySel);
@@ -870,8 +877,14 @@ void Main::setupAPI()
     c->addParameter(Command::IntPar, false, "Selection box border width ");
     modelCommands.append(c);
 
-    c = new Command("setSelectionBrushColor", Command::AnySel);
-    c->addParameter(Command::ColorPar, false, "Color of selection box background");
+    c = new Command("setTitle", Command::AnySel);
+    c->addParameter(Command::StringPar, false, "");
+    modelCommands.append(c);
+
+    c = new Command("setZoom", Command::AnySel);
+    c->addParameter(Command::DoublePar, false, "Zoomfactor of map");
+    modelCommands.append(c);
+
     modelCommands.append(c);
 
     c = new Command("sleep", Command::AnySel);
@@ -998,6 +1011,10 @@ void Main::setupAPI()
     c->addParameter(Command::BoolPar, false, "Use setting for heading if true, for subtree if false");
     branchCommands.append(c);
 
+    c = new Command("getHeadingColor", Command::BranchSel, Command::StringPar);
+    c->setComment("Get color of heading as text");
+    branchCommands.append(c);
+
     c = new Command("getHeadingXML", Command::BranchSel, Command::StringPar);
     c->setComment("Get heading of branch as XML");
     branchCommands.append(c);
@@ -1545,51 +1562,48 @@ void Main::setupAPI()
 
 }
 
-void Main::cloneActionMapEditor(QAction *a, QKeySequence ks)
+void Main::cloneActionMapEditor(QAction *a) // FIXME-2 obsolete by mapEditorActions.append(...)  ?
 {
-    a->setShortcut(ks);
     a->setShortcutContext(Qt::WidgetShortcut);
     mapEditorActions.append(a);
 }
 
+
 // File Actions
 void Main::setupFileActions()
 {
-    QString tag = tr("&Map", "Menu for file actions");
-    QMenu *fileMenu = menuBar()->addMenu(tag);
-
     QAction *a;
+    QString tag = tr("File actions", "MainWindow shortcut groups");
     a = new QAction(QPixmap(QString(":/document-new-%1.svg").arg(iconTheme)), tr("&New map", "File menu"),
                     this);
-    switchboard.addSwitch("fileMapNew", shortcutScope, a, tag);
+    switchboard.addAction(a, "fileMapNew", Qt::CTRL | Qt::Key_N, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(fileNew()));
-    cloneActionMapEditor(a, Qt::CTRL | Qt::Key_N);
+    cloneActionMapEditor(a);
     fileMenu->addAction(a);
     actionFileNew = a;
 
     a = new QAction(QPixmap(":/filenewcopy.svg"),
                     tr("&Copy to new map", "File menu"), this);
-    switchboard.addSwitch("fileMapNewCopy", shortcutScope, a, tag);
+    switchboard.addAction(a, "fileMapNewCopy", Qt::CTRL | Qt::SHIFT | Qt::Key_C, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(fileNewCopy()));
-    cloneActionMapEditor(a, Qt::CTRL | Qt::SHIFT | Qt::Key_C);
+    cloneActionMapEditor(a);
     fileMenu->addAction(a);
     actionFileNewCopy = a;
 
     a = new QAction(QPixmap(QString(":/document-open-%1").arg(iconTheme)), tr("&Open...", "File menu"),
                     this);
-    switchboard.addSwitch("fileMapOpen", shortcutScope, a, tag);
+    switchboard.addAction(a, "fileMapOpen", Qt::CTRL | Qt::Key_L, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(fileLoad()));
-    cloneActionMapEditor(a, Qt::CTRL | Qt::Key_L);
+    cloneActionMapEditor(a);
     fileMenu->addAction(a);
     actionFileOpen = a;
 
     a = new QAction(tr("&Restore last session", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_R);
-    switchboard.addSwitch("fileMapRestore", shortcutScope, a, tag);
+    switchboard.addAction(a, "fileMapRestore", Qt::CTRL | Qt::Key_S, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(fileRestoreSession()));
     fileMenu->addAction(a);
-    actionListFiles.append(a);
-    actionCopy = a;
+    a->setEnabled(true);
+    actionFileRestoreSession = a;
 
     fileLastMapsMenu = fileMenu->addMenu(tr("Open Recent", "File menu"));
     fileMenu->addSeparator();
@@ -1601,8 +1615,8 @@ void Main::setupFileActions()
     actionClearRecent = a;
 
     a = new QAction(QPixmap(QString(":/document-save-%1.svg").arg(iconTheme)), tr("&Save...", "File menu"), this);
-    switchboard.addSwitch("fileMapSave", shortcutScope, a, tag);
-    cloneActionMapEditor(a, Qt::CTRL | Qt::Key_S);
+    switchboard.addAction(a, "fileMapSave", Qt::CTRL | Qt::Key_S, shortcutScope, tag);
+    cloneActionMapEditor(a);
     fileMenu->addAction(a);
     restrictedMapActions.append(a);
     connect(a, SIGNAL(triggered()), this, SLOT(fileSave()));
@@ -1665,11 +1679,12 @@ void Main::setupFileActions()
 
     fileExportMenu = fileMenu->addMenu(tr("Export", "File menu"));
 
+    tag = tr("Exports", "MainWindow shortcut groups");
     a = new QAction(QPixmap(QString(":/document-export-%1.svg").arg(iconTheme)),
-                    tr("Repeat last export (%1)").arg("-"), this);
-    switchboard.addSwitch("fileExportLast", shortcutScope, a, tag);
+                    tr("Repeat last export"), this);
+    switchboard.addAction(a, "fileExportLast", Qt::CTRL | Qt::Key_E, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(fileExportLast()));
-    cloneActionMapEditor(a, Qt::CTRL | Qt::Key_E);
+    cloneActionMapEditor(a);
     fileExportMenu->addAction(a);
     actionFileExportLast = a;
     actionListFiles.append(a);
@@ -1767,7 +1782,7 @@ void Main::setupFileActions()
     fileMenu->addSeparator();
 
     a = new QAction(tr("Map properties"), this);
-    switchboard.addSwitch("editMapProperties", shortcutScope, a, tag);
+    switchboard.addAction(a, "editMapProperties", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editMapProperties()));
     fileMenu->addAction(a);
     actionListFiles.append(a);
@@ -1777,8 +1792,7 @@ void Main::setupFileActions()
 
     a = new QAction(QPixmap(QString(":/document-print-%1.svg").arg(iconTheme)), tr("&Print") + QString("..."),
                     this);
-    a->setShortcut(Qt::CTRL | Qt::Key_P);
-    switchboard.addSwitch("fileMapPrint", shortcutScope, a, tag);
+    switchboard.addAction(a, "fileMapPrint", Qt::CTRL | Qt::Key_P, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(filePrint()));
     fileMenu->addAction(a);
     unrestrictedMapActions.append(a);
@@ -1786,27 +1800,26 @@ void Main::setupFileActions()
 
     a = new QAction(QPixmap(QString(":/document-close-%1.svg").arg(iconTheme)), tr("&Close Map", "File menu"),
                     this);
-    a->setShortcut(Qt::CTRL | Qt::Key_W);
-    switchboard.addSwitch("fileMapClose", shortcutScope, a, tag);
+    switchboard.addAction(a, "fileMapClose", Qt::CTRL | Qt::Key_W, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(fileCloseMap()));
     fileMenu->addAction(a);
     actionFileClose = a;
 
+    tag = tr("Exit", "MainWindow shortcut groups");
     a = new QAction(QPixmap(QString(":/application-exit-%1.svg").arg(iconTheme)), tr("E&xit", "File menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Q);
-    switchboard.addSwitch("fileExit", shortcutScope, a, tag);
+    switchboard.addAction(a, "fileExit", Qt::CTRL | Qt::Key_Q, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(fileExitVYM()));
     fileMenu->addAction(a);
     actionFileExitVym = a;
 
+    tag = tr("Miscellaneous", "MainWindow shortcut groups");
     a = new QAction("Toggle winter mode", this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Asterisk);
     a->setShortcutContext(Qt::WidgetShortcut);
 
     if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
         addAction(a);
         mapEditorActions.append(a);
-        switchboard.addSwitch("mapWinterMode", shortcutScope, a, tag);
+        switchboard.addAction(a, "mapWinterMode", Qt::CTRL | Qt::Key_Asterisk, shortcutScope, tag);
     }
     connect(a, SIGNAL(triggered()), this, SLOT(toggleWinter()));
     actionToggleWinter = a;
@@ -1815,281 +1828,248 @@ void Main::setupFileActions()
 // Edit Actions
 void Main::setupEditActions()
 {
-    QString tag = tr("E&dit", "Edit menu");
-    QMenu *editMenu = menuBar()->addMenu(tag);
-
     QAction *a;
+    QString tag = tr("Undo/Redo", "MainWindow shortcut groups");
     a = new QAction(QPixmap(":/undo.png"), tr("&Undo", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Z);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     a->setEnabled(false);
-    editMenu->addAction(a);
     mapEditorActions.append(a);
     restrictedMapActions.append(a);
-    switchboard.addSwitch("mapUndo", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapUndo",Qt::CTRL | Qt::Key_Z, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editUndo()));
     actionUndo = a;
 
+    a = new QAction(QPixmap(":/undo.png"), tr("&Undo", "Edit menu"), this);
+    a->setShortcutContext(Qt::WidgetShortcut);
+    a->setEnabled(false);
+    mapEditorActions.append(a);
+    restrictedMapActions.append(a);
+    switchboard.addAction(a, "mapUndo", Qt::Key_U, shortcutScope, tag); // Vim Alternative
+    connect(a, SIGNAL(triggered()), this, SLOT(editUndo()));
+    actionUndoVim = a;
+
     a = new QAction(QPixmap(":/redo.png"), tr("&Redo", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Y);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
-    editMenu->addAction(a);
     restrictedMapActions.append(a);
     mapEditorActions.append(a);
-    switchboard.addSwitch("mapRedo", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapRedo", Qt::CTRL | Qt::Key_Y, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editRedo()));
     actionRedo = a;
 
+    a = new QAction(tr("Repeat last action", "Edit menu") + " (experimental)", this);
+    switchboard.addAction(a, "repeatLastAction", Qt::Key_Period, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(editRepeatLastAction()));
+    //actionListBranches.append(a);
+    actionRepeatCommand = a;
+
     editMenu->addSeparator();
+
     a = new QAction(QPixmap(QString(":/edit-copy-%1.svg").arg(iconTheme)), tr("&Copy", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_C);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     a->setEnabled(false);
-    editMenu->addAction(a);
     unrestrictedMapActions.append(a);
     mapEditorActions.append(a);
-    switchboard.addSwitch("mapCopy", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapCopy", Qt::CTRL | Qt::Key_C, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editCopy()));
     actionCopy = a;
 
+    a = new QAction(QPixmap(QString(":/edit-copy-%1.svg").arg(iconTheme)), tr("&Copy", "Edit menu"), this);
+    a->setShortcutContext(Qt::WidgetShortcut);
+    a->setEnabled(false);
+    unrestrictedMapActions.append(a);
+    mapEditorActions.append(a);
+    switchboard.addAction(a, "mapCopyVim", Qt::Key_Y, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(editCopy()));
+    actionCopyVim = a;
+
     a = new QAction(QPixmap(QString(":/edit-cut-%1.svg").arg(iconTheme)), tr("Cu&t", "Edit menu"), this);
     // Multi key shortcuts https://bugreports.qt.io/browse/QTBUG-39127
-    a->setShortcut(Qt::CTRL | Qt::Key_X);
-    ADD_SHORTCUT
     a->setEnabled(false);
     a->setShortcutContext(Qt::WidgetShortcut);
-    editMenu->addAction(a);
     restrictedMapActions.append(a);
     mapEditorActions.append(a);
     restrictedMapActions.append(a);
-    switchboard.addSwitch("mapCut", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapCut", Qt::CTRL | Qt::Key_X, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editCut()));
     addAction(a);
     actionCut = a;
 
+    a = new QAction(QPixmap(QString(":/edit-cut-%1.svg").arg(iconTheme)), tr("Cu&t", "Edit menu"), this);
+    switchboard.addAction(a, "mapCutVim", Qt::Key_D, shortcutScope, tag);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
+    actionListItems.append(a);
+    actionCutVim = a;
+
     a = new QAction(QPixmap(QString(":/edit-paste-%1.svg").arg(iconTheme)), tr("&Paste", "Edit menu"),
                     this);
     connect(a, SIGNAL(triggered()), this, SLOT(editPaste()));
-    a->setShortcut(Qt::CTRL | Qt::Key_V);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     a->setEnabled(false);
-    editMenu->addAction(a);
     restrictedMapActions.append(a);
     mapEditorActions.append(a);
-    switchboard.addSwitch("mapPaste", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapPaste", Qt::CTRL | Qt::Key_V, shortcutScope, tag);
     actionPaste = a;
 
+    a = new QAction(QPixmap(QString(":/edit-paste-%1.svg").arg(iconTheme)), tr("&Paste", "Edit menu"),
+                    this);
+    connect(a, SIGNAL(triggered()), this, SLOT(editPaste()));
+    a->setShortcutContext(Qt::WidgetShortcut);
+    a->setEnabled(false);
+    restrictedMapActions.append(a);
+    mapEditorActions.append(a);
+    switchboard.addAction(a, "mapPasteVim", Qt::Key_P, shortcutScope, tag);
+    actionPasteVim = a;
+
     // Shortcut to delete selection
     a = new QAction(tr("Delete Selection", "Edit menu"), this);
 #if defined(Q_OS_MACOS)
-    a->setShortcut(Qt::Key_Backspace);
+    switchboard.addAction(a, "mapDelete", Qt::Key_Backspace, shortcutScope, tag);
 #else
-    a->setShortcut(Qt::Key_Delete);
+    switchboard.addAction(a, "mapDelete", Qt::Key_Delete, shortcutScope, tag);
 #endif
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
-    editMenu->addAction(a);
     actionListItems.append(a);
     actionDelete = a;
 
-    a = new QAction(tr("Delete Selection", "Edit menu"), this);
-    a->setShortcut(Qt::Key_D);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
-    addAction(a);
-    connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
-    editMenu->addAction(a);
-    actionListItems.append(a);
-    actionDeleteAlt = a;
-
+    tag = tr("Add", "MainWindow shortcut groups");
     // Shortcut to add mapcenter
     a = new QAction(QPixmap(":/newmapcenter.png"),
                     tr("Add mapcenter", "Canvas context menu"), this);
-    a->setShortcut(Qt::Key_C);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapAddCenter", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapAddCenter", Qt::Key_C, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddMapCenter()));
-    editMenu->addAction(a);
     actionListFiles.append(a);
     actionAddMapCenter = a;
 
     // Shortcut to add branch
     a = new QAction(QPixmap(":/newbranch.png"),
                     tr("Add branch as child", "Edit menu"), this);
-    switchboard.addSwitch("mapeditAddBranch", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapeditAddBranch", Qt::Key_A, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddBranch()));
-    cloneActionMapEditor(a, Qt::Key_A);
-    ADD_SHORTCUT
+    cloneActionMapEditor(a);
     taskEditorActions.append(a);
     actionListBranches.append(a);
     actionAddBranch = a;
 
     // Add branch by inserting it at selection
     a = new QAction(tr("Add branch (insert)", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::CTRL | Qt::Key_A);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapEditAddBranchBefore", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditAddBranchBefore", Qt::SHIFT | Qt::CTRL | Qt::Key_A, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddBranchBefore()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     actionAddBranchBefore = a;
 
     // Add branch above
     a = new QAction(tr("Add branch above", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_A);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapEditAddBranchAbove", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditAddBranchAbove", Qt::SHIFT | Qt::Key_A, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddBranchAbove()));
     a->setEnabled(false);
     actionListBranches.append(a);
-    editMenu->addAction(a);
     actionAddBranchAbove = a;
 
     a = new QAction(tr("Add branch above", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_Insert);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapEditAddBranchAboveAlt", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditAddBranchAboveAlt", Qt::SHIFT | Qt::Key_Insert, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddBranchAbove()));
     actionListBranches.append(a);
 
     // Add branch below
     a = new QAction(tr("Add branch below", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Insert);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapEditAddBranchBelow", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditAddBranchBelow", Qt::CTRL | Qt::Key_Insert, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddBranchBelow()));
     a->setEnabled(false);
     actionListBranches.append(a);
 
     a = new QAction(tr("Add branch below", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_A);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapEditAddBranchBelowAlt", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditAddBranchBelowAlt", Qt::CTRL | Qt::Key_A, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddBranchBelow()));
     actionListBranches.append(a);
-    editMenu->addAction(a);
     actionAddBranchBelow = a;
 
+    tag = tr("Move", "MainWindow shortcut groups");
     a = new QAction(QPixmap(":/up.png"), tr("Move branch up", "Edit menu"),
                     this);
-    a->setShortcut(Qt::Key_PageUp);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     mapEditorActions.append(a);
     taskEditorActions.append(a);
     restrictedMapActions.append(a);
     actionListBranches.append(a);
     actionListImages.append(a);
-    editMenu->addAction(a);
-    switchboard.addSwitch("mapEditMoveBranchUp", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditMoveBranchUp", Qt::Key_PageUp, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editMoveUp()));
     actionMoveUp = a;
 
     a = new QAction(QPixmap(":/down.png"), tr("Move branch down", "Edit menu"),
                     this);
-    a->setShortcut(Qt::Key_PageDown);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     mapEditorActions.append(a);
     taskEditorActions.append(a);
     restrictedMapActions.append(a);
     actionListBranches.append(a);
     actionListImages.append(a);
-    editMenu->addAction(a);
-    switchboard.addSwitch("mapEditMoveBranchDown", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditMoveBranchDown", Qt::Key_PageDown, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editMoveDown()));
     actionMoveDown = a;
 
     a = new QAction(QPixmap(":up-diagonal-right.png"), tr("Move branch diagonally up", "Edit menu"),
                     this);
-#if defined(Q_OS_MACOS)
-    a->setShortcut(Qt::SHIFT | Qt::Key_PageUp);
-#else
-    a->setShortcut(Qt::CTRL | Qt::Key_PageUp);
-#endif
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     mapEditorActions.append(a);
     taskEditorActions.append(a);
     restrictedMapActions.append(a);
     actionListBranches.append(a);
-    editMenu->addAction(a);
-    switchboard.addSwitch("mapEditMoveBranchUpDiagonally", shortcutScope, a, tag);
+#if defined(Q_OS_MACOS)
+    switchboard.addAction(a, "mapEditMoveBranchUpDiagonally", Qt::SHIFT | Qt::Key_PageUp, shortcutScope, tag);
+#else
+    switchboard.addAction(a, "mapEditMoveBranchUpDiagonally", Qt::CTRL | Qt::Key_PageUp, shortcutScope, tag);
+#endif
     connect(a, SIGNAL(triggered()), this, SLOT(editMoveUpDiagonally()));
     actionMoveUpDiagonally = a;
 
     a = new QAction(QPixmap(":down-diagonal-left.png"), tr("Move branch diagonally down", "Edit menu"),
                     this);
-#if defined(Q_OS_MACOS)
-    a->setShortcut(Qt::SHIFT | Qt::Key_PageDown);
-#else
-    a->setShortcut(Qt::CTRL | Qt::Key_PageDown);
-#endif 
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     mapEditorActions.append(a);
     taskEditorActions.append(a);
     restrictedMapActions.append(a);
     actionListBranches.append(a);
-    editMenu->addAction(a);
-    switchboard.addSwitch("mapEditMoveBranchDownDiagonally", shortcutScope, a, tag);
+#if defined(Q_OS_MACOS)
+    switchboard.addAction(a, "mapEditMoveBranchDownDiagonally", Qt::SHIFT | Qt::Key_PageDown, shortcutScope, tag);
+#else
+    switchboard.addAction(a, "mapEditMoveBranchDownDiagonally", Qt::CTRL | Qt::Key_PageDown, shortcutScope, tag);
+#endif 
     connect(a, SIGNAL(triggered()), this, SLOT(editMoveDownDiagonally()));
     actionMoveDownDiagonally = a;
 
     a = new QAction(QPixmap(), tr("&Detach", "Context menu"), this);
     a->setStatusTip(tr("Detach branch and use as mapcenter", "Context menu"));
-    a->setShortcut(Qt::Key_D | Qt::SHIFT);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapDetachBranch", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapDetachBranch", Qt::Key_D | Qt::SHIFT, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editDetach()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     actionDetach = a;
 
+    QString sortDisplayTag = tr("Sort and display", "MainWindow shortcut groups");
     a = new QAction(QPixmap(QString(":/view-sort-ascending-name-%1.svg").arg(iconTheme)), tr("Sort children", "Edit menu"), this);
     a->setEnabled(true);
-    a->setShortcut(Qt::Key_O);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapSortBranches", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapSortBranches", Qt::Key_O, shortcutScope, sortDisplayTag);
     connect(a, SIGNAL(triggered()), this, SLOT(editSortChildren()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     actionSortChildren = a;
 
     a = new QAction(QPixmap(QString(":/view-sort-descending-name-%1.svg").arg(iconTheme)), tr("Sort children backwards", "Edit menu"), this);
     a->setEnabled(true);
-    a->setShortcut(Qt::SHIFT | Qt::Key_O);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapSortBranchesReverse", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapSortBranchesReverse", Qt::SHIFT | Qt::Key_O, shortcutScope, sortDisplayTag);
     connect(a, SIGNAL(triggered()), this, SLOT(editSortBackChildren()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     actionSortBackChildren = a;
 
     a = new QAction(QPixmap(":/flag-scrolled-right.png"),
                     tr("Scroll branch", "Edit menu"), this);
-    a->setShortcut(Qt::Key_S);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapToggleScroll", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleScroll", Qt::Key_S, shortcutScope, sortDisplayTag);
     connect(a, SIGNAL(triggered()), this, SLOT(editToggleScroll()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     a->setEnabled(false);
     a->setCheckable(true);
@@ -2098,108 +2078,64 @@ void Main::setupEditActions()
     actionToggleScroll = a;
 
     a = new QAction(tr("Unscroll branch and subtree", "Edit menu"), this);
-    editMenu->addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editUnscrollSubtree()));
     actionListBranches.append(a);
+    actionUnscrollSubtree = a;
 
+    QString geometryTag = tr("Geometry of items", "MainWindow shortcut groups");
     a = new QAction(tr("Grow selection", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Plus);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapGrowSelection", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapGrowSelection", Qt::CTRL | Qt::Key_Plus, shortcutScope, geometryTag);
     connect(a, SIGNAL(triggered()), this, SLOT(editGrowSelectionSize()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     actionListImages.append(a);
     actionGrowSelectionSize = a;
 
     a = new QAction(tr("Shrink selection", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Minus);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapShrinkSelection", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapShrinkSelection", Qt::CTRL | Qt::Key_Minus, shortcutScope, geometryTag);
     connect(a, SIGNAL(triggered()), this, SLOT(editShrinkSelectionSize()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     actionListImages.append(a);
     actionShrinkSelectionSize = a;
 
     a = new QAction(tr("Reset selection size", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_0);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapResetSelectionSize", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapResetSelectionSize", Qt::CTRL | Qt::Key_0, shortcutScope, geometryTag);
     connect(a, SIGNAL(triggered()), this, SLOT(editResetSelectionSize()));
-    editMenu->addAction(a);
     actionListBranches.append(a);
     actionListImages.append(a);
     actionResetSelectionSize = a;
 
-    editMenu->addSeparator();
-
-    a = new QAction(QPixmap(), "TE: " + tr("Collapse one level", "Edit menu"),
-                    this);
-    a->setShortcut(Qt::Key_Less | Qt::CTRL);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapCollapseOneLevel", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(editCollapseOneLevel()));
-    editMenu->addAction(a);
-    a->setEnabled(false);
-    a->setCheckable(false);
+    a = new QAction(tr("Rotate subtree clockwise", "Edit menu"), this);
+    switchboard.addAction(a, "mapRotateSubtreeCW", Qt::CTRL | Qt::Key_R, shortcutScope, geometryTag);
+    connect(a, SIGNAL(triggered()), this, SLOT(editRotateSubtreeCW()));
     actionListBranches.append(a);
-    addAction(a);
-    actionCollapseOneLevel = a;
+    actionRotateSubtreeCW = a;
 
-    a = new QAction(QPixmap(),
-                    "TE: " + tr("Collapse unselected levels", "Edit menu"),
-                    this);
-    a->setShortcut(Qt::Key_Less);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapCollapseUnselectedLevels", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(editCollapseUnselected()));
-    editMenu->addAction(a);
-    a->setEnabled(false);
-    a->setCheckable(false);
+    a = new QAction(tr("Rotate subtree counter-clockwise", "Edit menu"), this);
+    switchboard.addAction(a, "mapRotateSubtreeCCW", Qt::CTRL | Qt::SHIFT | Qt::Key_R, shortcutScope, geometryTag);
+    connect(a, SIGNAL(triggered()), this, SLOT(editRotateSubtreeCCW()));
     actionListBranches.append(a);
-    addAction(a);
-    actionCollapseUnselected = a;
-
-    a = new QAction(QPixmap(), tr("Expand all branches", "Edit menu"), this);
-    connect(a, SIGNAL(triggered()), this, SLOT(editExpandAll()));
-    actionExpandAll = a;
-    actionExpandAll->setEnabled(false);
-    actionExpandAll->setCheckable(false);
-    actionListBranches.append(actionExpandAll);
-    addAction(a);
+    actionRotateSubtreeCCW = a;
 
-    a = new QAction(QPixmap(), tr("Expand one level", "Edit menu"), this);
-    a->setShortcut(Qt::Key_Greater);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapExpandOneLevel", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(editExpandOneLevel()));
-    a->setEnabled(false);
-    a->setCheckable(false);
-    addAction(a);
-    actionListBranches.append(a);
-    actionExpandOneLevel = a;
+    editMenu->addSeparator();
 
-    tag = tr("References Context menu", "Shortcuts");
+    tag = tr("URLs", "Shortcuts in references context menu");
     a = new QAction(QPixmap(":/flag-url.svg"), tr("Open URL", "Edit menu"),
                     this);
-    a->setShortcut(Qt::CTRL | Qt::Key_U);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapOpenUrl", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapOpenUrl", shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(openUrl()));
     actionListBranches.append(a);
     actionOpenUrl = a;
 
     a = new QAction(tr("Open all visible URLs in subtree", "Edit menu"), this);
-    switchboard.addSwitch("mapOpenUrlsSubTree", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapOpenUrlsSubTree", shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVisUrls()));
     actionListBranches.append(a);
     actionOpenMultipleVisUrls = a;
 
     a = new QAction(tr("Open all URLs in subtree", "Edit menu"), this);
-    switchboard.addSwitch("mapOpenMultipleUrls", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapOpenMultipleUrls", shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleUrls()));
     actionListBranches.append(a);
@@ -2207,7 +2143,7 @@ void Main::setupEditActions()
 
     a = new QAction(tr("Open all URLs in subtree in private mode", "Edit menu"), this);
     if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
-        switchboard.addSwitch("mapOpenMultipleUrls", shortcutScope, a, tag);
+        switchboard.addAction(a, "mapOpenMultipleUrls", shortcutScope, tag);
         addAction(a);
         connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleUrlsPrivate()));
         actionListBranches.append(a);
@@ -2215,10 +2151,7 @@ void Main::setupEditActions()
     actionOpenMultipleUrlsPrivate = a;
 
     a = new QAction(QPixmap(), tr("Extract URLs from note", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_N);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapUrlsFromNote", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapUrlsFromNote", Qt::SHIFT | Qt::Key_N, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editNote2URLs()));
     actionListBranches.append(a);
@@ -2226,44 +2159,33 @@ void Main::setupEditActions()
 
     a = new QAction(QPixmap(":/flag-urlnew.svg"),
                     tr("Edit URL...", "Edit menu"), this);
-    a->setShortcut(Qt::Key_U);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapEditURL", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditURL", Qt::SHIFT | Qt::Key_U, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editURL()));
     actionListBranches.append(a);
     actionURLNew = a;
 
     a = new QAction(QPixmap(), tr("Edit local URL...", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_U);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapEditLocalURL", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditLocalURL", Qt::CTRL | Qt::Key_U, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editLocalURL()));
     actionListBranches.append(a);
     actionLocalURL = a;
 
     a = new QAction(tr("Use heading for URL", "Edit menu"), this);
-    //a->setShortcut(Qt::ALT | Qt::Key_U);
-    a->setShortcutContext(Qt::ApplicationShortcut);
     a->setEnabled(false);
-    switchboard.addSwitch("mapHeading2URL", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapHeading2URL", shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editHeading2URL()));
     actionListBranches.append(a);
     actionHeading2URL = a;
 
-    tag = "Jira";
+    tag = tr("Connect", "Connection shortcuts in MainWindow");
     a = new QAction(
             QPixmap(":/flag-jira.svg"), 
             tr("Get data from Jira for subtree", "Edit menu"),
             this);
-    a->setShortcut(Qt::Key_J | Qt::SHIFT);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapUpdateSubTreeFromJira", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapUpdateSubTreeFromJira", Qt::Key_J | Qt::SHIFT, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(getJiraDataSubtree()));
     actionGetJiraDataSubtree = a;
@@ -2272,20 +2194,14 @@ void Main::setupEditActions()
             QPixmap(":/flag-jira.svg"),
             tr("Set Jira query", "Edit menu"),
             this);
-    a->setShortcut(Qt::Key_J | Qt::CTRL);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
-    switchboard.addSwitch("mapSetJiraQuery", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapSetJiraQuery", Qt::Key_J | Qt::CTRL, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(setJiraQuery()));
-    actionGetJiraDataSubtree = a;
+    actionSetJiraQuery = a;
 
-    tag = "Confluence";
     a = new QAction(tr("Get page name and details from Confluence", "Edit menu"),
                     this);
-    //    a->setShortcut ( Qt::Key_J | Qt::CTRL);
-    //    a->setShortcutContext (Qt::WindowShortcut);
-    //    switchboard.addSwitch ("mapUpdateSubTreeFromJira", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapGetConfluencePageDetails", shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(getConfluencePageDetails()));
     actionListBranches.append(a);
@@ -2293,21 +2209,17 @@ void Main::setupEditActions()
 
     a = new QAction(tr("Get page name and details from Confluence for child pages", "Edit menu"),
                     this);
-    //    a->setShortcut ( Qt::Key_J | Qt::CTRL);
-    //    a->setShortcutContext (Qt::WindowShortcut);
-    //    switchboard.addSwitch ("mapUpdateSubTreeFromJira", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapGetConfluencePagesDetails", shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(getConfluencePageDetailsRecursively()));
     actionListBranches.append(a);
     actionGetConfluencePageDetailsRecursively = a;
 
-    tag = tr("vymlinks - linking maps", "Shortcuts");
+    tag = tr("vymlinks - linking maps", "Shortcuts for vymLinks in MainWindow");
     a = new QAction(QPixmap(":/flag-vymlink.png"),
                     tr("Open linked map", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_V);
-    ADD_SHORTCUT
     a->setEnabled(false);
-    switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapOpenVymLink", Qt::SHIFT | Qt::Key_V, shortcutScope, tag);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLink()));
     actionListBranches.append(a);
@@ -2316,7 +2228,7 @@ void Main::setupEditActions()
     a = new QAction(QPixmap(":/flag-vymlink.png"),
                     tr("Open linked map in background tab", "Edit menu"), this);
     a->setEnabled(false);
-    switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapOpenVymLink", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLinkBackground()));
     actionListBranches.append(a);
     actionOpenVymLinkBackground = a;
@@ -2324,189 +2236,163 @@ void Main::setupEditActions()
     a = new QAction(QPixmap(), tr("Open all vym links in subtree", "Edit menu"),
                     this);
     a->setEnabled(false);
-    switchboard.addSwitch("mapOpenMultipleVymLinks", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapOpenMultipleVymLinks", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVymLinks()));
     actionListBranches.append(a);
     actionOpenMultipleVymLinks = a;
 
     a = new QAction(QPixmap(":/flag-vymlinknew.png"),
                     tr("Edit vym link...", "Edit menu"), this);
-    a->setShortcut(Qt::Key_V);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setEnabled(false);
-    switchboard.addSwitch("mapEditVymLink", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapEditVymLink", Qt::Key_V, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editVymLink()));
     actionListBranches.append(a);
     actionEditVymLink = a;
 
     a = new QAction(tr("Delete vym link", "Edit menu"), this);
     a->setEnabled(false);
-    switchboard.addSwitch("mapDeleteVymLink", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapDeleteVymLink", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteVymLink()));
     actionListBranches.append(a);
     actionDeleteVymLink = a;
 
-    tag = tr("Exports", "Shortcuts");
     a = new QAction(QPixmap(":/flag-hideexport.png"),
                     tr("Hide in exports", "Edit menu"), this);
-    a->setShortcut(Qt::Key_H);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(true);
     a->setEnabled(false);
     addAction(a);
-    switchboard.addSwitch("mapToggleHideExport", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleHideExport", Qt::Key_H, shortcutScope, sortDisplayTag);
     connect(a, SIGNAL(triggered()), this, SLOT(editToggleHideExport()));
     actionListBranches.append(a);
     actionListImages.append(a);
     actionToggleHideExport = a;
 
-    tag = tr("Tasks", "Shortcuts");
+    tag = tr("Tasks", "Shortcuts for tasks in MainWindow");
     a = new QAction(QPixmap(":/taskeditor.png"), tr("Toggle task", "Edit menu"),
                     this);
-    a->setShortcut(Qt::Key_W | Qt::SHIFT);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(true);
     a->setEnabled(false);
     addAction(a);
-    switchboard.addSwitch("mapToggleTask", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleTask", Qt::Key_W | Qt::SHIFT, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editToggleTask()));
     actionListBranches.append(a);
     actionToggleTask = a;
 
     a = new QAction(QPixmap(), tr("Cycle task status", "Edit menu"), this);
-    a->setShortcut(Qt::Key_W);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     addAction(a);
-    switchboard.addSwitch("mapCycleTaskStatus", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapCycleTaskStatus", Qt::Key_W, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editCycleTaskStatus()));
     actionListBranches.append(a);
     actionCycleTaskStatus = a;
 
     a = new QAction(QPixmap(), tr("Reset delta priority for visible tasks", "Reset delta"), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     addAction(a);
-    switchboard.addSwitch("mapResetTaskDeltaPrio", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapResetTaskDeltaPrio", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskResetDeltaPrio()));
     actionListBranches.append(a);
     actionTaskResetDeltaPrio = a;
 
     a = new QAction(QPixmap(), tr("Reset sleep", "Task sleep"), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(0);
     addAction(a);
-    switchboard.addSwitch("mapResetSleep", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapResetSleep", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep0 = a;
 
     a = new QAction(QPixmap(),
                     tr("Sleep %1 days", "Task sleep").arg("n") + "...", this);
-    a->setShortcutContext(Qt::WindowShortcut);
-    a->setShortcut(Qt::Key_Q | Qt::SHIFT);
-    ADD_SHORTCUT
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(-1);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleepN", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleepN", Qt::Key_Q | Qt::SHIFT, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleepN = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 day", "Task sleep").arg(1), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(1);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep1", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep1", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep1 = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(2), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(2);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep2", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep2", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep2 = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(3), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(3);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep3", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep3", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep3 = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(4), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(4);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep4", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep4", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep4 = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(5), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(5);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep5", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep5", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep5 = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(7), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(7);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep7", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep7", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep7 = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(2), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(14);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep14", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep14", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep14 = a;
 
     a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(4), this);
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(false);
     a->setEnabled(false);
     a->setData(28);
     addAction(a);
-    switchboard.addSwitch("mapTaskSleep28", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTaskSleep28", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
     actionListBranches.append(a);
     actionTaskSleep28 = a;
@@ -2523,21 +2409,17 @@ void Main::setupEditActions()
     // Only remove branch, not its children
     a = new QAction(
         tr("Remove only branch and keep its children ", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_X);
-    ADD_SHORTCUT
     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteKeepChildren()));
     a->setEnabled(false);
     addAction(a);
-    switchboard.addSwitch("mapDeleteKeepChildren", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapDeleteKeepChildren", Qt::CTRL | Qt::SHIFT | Qt::Key_X, shortcutScope, tag);
     actionListBranches.append(a);
     actionDeleteKeepChildren = a;
 
     // Only remove children of a branch
     a = new QAction(tr("Remove children", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_X);
-    ADD_SHORTCUT
     addAction(a);
-    switchboard.addSwitch("mapDeleteChildren", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapDeleteChildren", Qt::SHIFT | Qt::Key_X, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteChildren()));
     a->setEnabled(false);
     addAction(a);
@@ -2548,11 +2430,8 @@ void Main::setupEditActions()
     a = new QAction(tr("Add timestamp", "Edit menu"), this);
     a->setEnabled(false);
     actionListBranches.append(a);
-    a->setShortcut(Qt::Key_T);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
     addAction(a);
-    switchboard.addSwitch("mapAddTimestamp", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapAddTimestamp", Qt::Key_T, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editAddTimestamp()));
     actionListBranches.append(a);
     actionAddTimestamp = a;
@@ -2564,11 +2443,8 @@ void Main::setupEditActions()
     actionMapInfo = a;
 
     a = new QAction(QPixmap(QString(":/insert-image-%1.svg").arg(iconTheme)), tr("Add image", "Edit and context menus") + "...", this);
-    a->setShortcutContext(Qt::WindowShortcut);
-    a->setShortcut(Qt::Key_I | Qt::SHIFT);
-    ADD_SHORTCUT
     addAction(a);
-    switchboard.addSwitch("mapLoadImage", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapLoadImage", Qt::Key_I | Qt::SHIFT, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editLoadImage()));
     actionListBranches.append(a);
     actionLoadImage = a;
@@ -2577,65 +2453,113 @@ void Main::setupEditActions()
         tr("Item property window", "Dialog to edit properties of selected item") +
             QString("..."),
         this);
-    a->setShortcut(Qt::Key_P);
-    ADD_SHORTCUT
-    a->setShortcutContext(Qt::WindowShortcut);
     a->setCheckable(true);
     addAction(a);
-    switchboard.addSwitch("mapTogglePropertyEditor", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTogglePropertyEditor", Qt::Key_B, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleProperty()));
     actionViewTogglePropertyEditor = a;
 }
 
+void Main::setupEditMenu()
+{
+    editMenu->addAction(actionUndo);
+    editMenu->addAction(actionUndoVim);
+    editMenu->addAction(actionRedo);
+    editMenu->addAction(actionRepeatCommand);
+
+    editMenu->addSeparator();
+
+    editMenu->addAction(actionCopy);
+    editMenu->addAction(actionCopyVim);
+    editMenu->addAction(actionCut);
+    editMenu->addAction(actionPaste);
+    editMenu->addAction(actionPasteVim);
+    editMenu->addAction(actionDelete);
+
+    editMenu->addSeparator();
+
+    editMenu->addMenu(branchAddContextMenu);
+    editMenu->addMenu(branchRemoveContextMenu);
+    editMenu->addMenu(branchHierarchyContextMenu);
+    editMenu->addMenu(branchGeometryContextMenu);
+
+    editMenu->addSeparator();
+
+    editMenu->addAction(actionToggleScroll);
+    editMenu->addAction(actionUnscrollSubtree);
+
+}
+
 // Select Actions
 void Main::setupSelectActions()
 {
     QString tag = tr("Selections", "Shortcuts");
-    QMenu *selectMenu = menuBar()->addMenu(tr("Select", "Select menu"));
     QAction *a;
 
     tag = tr("Search functions", "Shortcuts");
     a = new QAction(QPixmap(QString(":/edit-find-%1.svg").arg(iconTheme)), tr("Find...", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_F);
-    ADD_SHORTCUT
     selectMenu->addAction(a);
-    switchboard.addSwitch("mapFind", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapFind", Qt::CTRL | Qt::Key_F, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
     actionListFiles.append(a);
     actionFind = a;
 
     a = new QAction(QPixmap(QString(":/edit-find-%1.svg").arg(iconTheme)), tr("Find...", "Edit menu"), this);
-    a->setShortcut(Qt::Key_Slash);
-    ADD_SHORTCUT
     selectMenu->addAction(a);
-    switchboard.addSwitch("mapFindAlt", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapFindAlt", Qt::Key_Slash, shortcutScope, tag); // Alternative: VIM Find
     connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
     actionListFiles.append(a);
+    actionFindVim = a;
+
+    a = new QAction(tr("Follow reference", "Context menu"), this);
+    addAction(a);
+    actionListBranches.append(a);
+    selectMenu->addAction(a);
+    switchboard.addAction(a, "mapFollowXLink", Qt::Key_F, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(popupFollowReference()));
+    actionFollowReference = a;
+
+    a = new QAction("Select first branch in siblings", this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    selectMenu->addAction(a);
+    switchboard.addAction(a, "Select first branch in siblings", Qt::Key_Home, shortcutScope, tag);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(editSelectFirstSibling()));
+
+    a = new QAction("Select first branch in siblings", this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    selectMenu->addAction(a);
+    switchboard.addAction(a, "Select first branch in siblings", Qt::Key_0, shortcutScope, tag);              // Alternative: VIM Select first
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(editSelectFirstSibling()));
+
+    a = new QAction("Select last branch in siblings", this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    selectMenu->addAction(a);
+    switchboard.addAction(a, "Select last branch in siblings", Qt::Key_End, shortcutScope, tag);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(editSelectLastSibling()));
+
+    a = new QAction("Select last branch in siblings", this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    selectMenu->addAction(a);
+    switchboard.addAction(a, "Select last branch in siblings", Qt::Key_Dollar, shortcutScope, tag);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(editSelectLastSibling()));
 
-    a = new QAction(tr("Find duplicate URLs", "Edit menu") + " (test)", this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_F);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapFindDuplicates", shortcutScope, a, tag);
-    if (settings.value("/mainwindow/showTestMenu", false).toBool())
-        selectMenu->addAction(a);
-    connect(a, SIGNAL(triggered()), this, SLOT(editFindDuplicateURLs()));
     a = new QAction(QPixmap(":/flag-target.svg"),
                     tr("Toggle target...", "Edit menu"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_T);
-    ADD_SHORTCUT
     a->setCheckable(true);
     selectMenu->addAction(a);
-    switchboard.addSwitch("mapToggleTarget", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleTarget", Qt::SHIFT | Qt::Key_T, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editToggleTarget()));
     actionListBranches.append(a);
     actionToggleTarget = a;
 
     a = new QAction(QPixmap(":/flag-target.svg"),
                     tr("Goto target...", "Edit menu"), this);
-    a->setShortcut(Qt::Key_G);
-    ADD_SHORTCUT
     selectMenu->addAction(a);
-    switchboard.addSwitch("mapGotoTarget", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapGotoTarget", Qt::Key_G, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editGoToTarget()));
     actionListBranches.append(a);
     actionListImages.append(a);
@@ -2643,52 +2567,49 @@ void Main::setupSelectActions()
 
     a = new QAction(QPixmap(":/flag-target.svg"),
                     tr("Move to target...", "Edit menu"), this);
-    a->setShortcut(Qt::Key_M);
-    ADD_SHORTCUT
     selectMenu->addAction(a);
-    switchboard.addSwitch("mapMoveToTarget", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapMoveToTarget", Qt::Key_M, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editMoveToTarget()));
     actionListBranches.append(a);
     actionMoveToTarget = a;
 
     a = new QAction(QPixmap(":/flag-vymlink.png"),
                     tr("Goto linked map...", "Edit menu"), this);
-    a->setShortcut(Qt::Key_G | Qt::SHIFT);
-    ADD_SHORTCUT
     selectMenu->addAction(a);
-    switchboard.addSwitch("gotoLinkedMap", shortcutScope, a, tag);
+    switchboard.addAction(a, "gotoLinkedMap", Qt::Key_G | Qt::SHIFT, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editGoToLinkedMap()));
     actionListBranches.append(a);
     actionGoToTargetLinkedMap = a;
 
+    a = new QAction(tr("Find duplicate URLs", "Edit menu") + " (test)", this);
+    switchboard.addAction(a, "mapFindDuplicates", shortcutScope, tag);
+    if (settings.value("/mainwindow/showTestMenu", false).toBool())
+        selectMenu->addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(editFindDuplicateURLs()));
+
     a = new QAction(QPixmap(QString(":/go-previous-%1.svg").arg(iconTheme)),
                     tr("Select previous", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_O);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     selectMenu->addAction(a);
     actionListFiles.append(a);
     mapEditorActions.append(a);
-    switchboard.addSwitch("mapSelectPrevious", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapSelectPrevious", Qt::CTRL | Qt::Key_O, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editSelectPrevious()));
     actionSelectPrevious = a;
 
     a = new QAction(QPixmap(QString(":/go-next-%1.svg").arg(iconTheme)), tr("Select next", "Edit menu"),
                     this);
-    a->setShortcut(Qt::CTRL | Qt::Key_I);
-    ADD_SHORTCUT
     a->setShortcutContext(Qt::WidgetShortcut);
     selectMenu->addAction(a);
     actionListFiles.append(a);
     mapEditorActions.append(a);
-    switchboard.addSwitch("mapSelectNext", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapSelectNext", Qt::CTRL | Qt::Key_I, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editSelectNext()));
     actionSelectNext = a;
 
     a = new QAction(tr("Unselect all", "Edit menu"), this);
-    // a->setShortcut (Qt::CTRL | Qt::Key_I );
     selectMenu->addAction(a);
-    switchboard.addSwitch("mapSelectNothing", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapSelectNothing", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editSelectNothing()));
     actionListFiles.append(a);
     actionSelectNothing = a;
@@ -2698,17 +2619,14 @@ void Main::setupSelectActions()
 // Format Actions
 void Main::setupFormatActions()
 {
-    QMenu *formatMenu = menuBar()->addMenu(tr("F&ormat", "Format menu"));
-
     QString tag = tr("Formatting", "Shortcuts");
 
     QAction* a;
 
     a = new QAction(QPixmap(":/formatcolorpicker.png"),
                     tr("Pic&k color", "Edit menu"), this);
-    // a->setShortcut (Qt::CTRL | Qt::Key_K );
     formatMenu->addAction(a);
-    switchboard.addSwitch("mapFormatColorPicker", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapFormatColorPicker", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(formatPickColor()));
     a->setEnabled(false);
     actionListBranches.append(a);
@@ -2716,9 +2634,8 @@ void Main::setupFormatActions()
 
     a = new QAction(QPixmap(":/formatcolorbranch.png"),
                     tr("Color &branch", "Edit menu"), this);
-    // a->setShortcut (Qt::CTRL | Qt::Key_B | Qt::SHIFT);
     formatMenu->addAction(a);
-    switchboard.addSwitch("mapFormatColorBranch", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapFormatColorBranch", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(formatColorBranch()));
     a->setEnabled(false);
     actionListBranches.append(a);
@@ -2726,9 +2643,8 @@ void Main::setupFormatActions()
 
     a = new QAction(QPixmap(":/formatcolorsubtree.png"),
                     tr("Color sub&tree", "Edit menu"), this);
-    // a->setShortcut (Qt::CTRL | Qt::Key_B);  // Color subtree
     formatMenu->addAction(a);
-    switchboard.addSwitch("mapFormatColorSubtree", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapFormatColorSubtree", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(formatColorSubtree()));
     a->setEnabled(false);
     actionListBranches.append(a);
@@ -2813,193 +2729,187 @@ void Main::setupFormatActions()
 // View Actions
 void Main::setupViewActions()
 {
-    QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
-    toolbarsMenu =
-        viewMenu->addMenu(tr("Toolbars", "Toolbars overview in view menu"));
-    windowsMenu =
-        viewMenu->addMenu(tr("Windows", "Editor windows overview in view menu"));
-
-    viewMenu->addSeparator();
-
     QAction *a;
 
-    QString tag = tr("Views", "Shortcuts");
-
-    a = new QAction(QPixmap(":view-video-projector.png"), 
-            tr("Toggle Presentation mode", "View action") + " " +
-            tr("(still experimental)"),
-            this);
-    a->setShortcut(Qt::Key_Asterisk || Qt::SHIFT);
-    ADD_SHORTCUT
-    viewMenu->addAction(a);
-    switchboard.addSwitch ("presentationMode", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(togglePresentationMode()));
-    actionTogglePresentationMode = a;
+    QString tag = tr("Views", "Mainwindow view shortcut groups");
 
     a = new QAction(QPixmap(QString(":/folder-cloud-%1.svg").arg(iconTheme)),
             tr("Toggle mode to temporary hide parts", "View action"),
             this);
-    a->setShortcut(Qt::Key_H | Qt::SHIFT);
-    ADD_SHORTCUT
-    viewMenu->addAction(a);
     viewMenu->addAction(a);
-    switchboard.addSwitch ("tmpHideMode", shortcutScope, a, tag);
+    switchboard.addAction (a, "tmpHideMode", Qt::Key_H | Qt::SHIFT, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(toggleHideTmpMode()));
     actionToggleHideTmpMode = a;
 
     a = new QAction(QPixmap(QString(":/zoom-in-%1.svg").arg(iconTheme)), tr("Zoom in", "View action"),
                     this);
-    a->setShortcut(Qt::Key_Plus);
-    ADD_SHORTCUT
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapZoomIn", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapZoomIn", Qt::Key_Plus, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomIn()));
     actionZoomIn = a;
 
     a = new QAction(QPixmap(QString(":/zoom-out-%1.svg").arg(iconTheme)), tr("Zoom out", "View action"), this);
-    a->setShortcut(Qt::Key_Minus);
-    ADD_SHORTCUT
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapZoomOut", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapZoomOut", Qt::Key_Minus, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomOut()));
     actionZoomOut = a;
 
     a = new QAction(QPixmap(QString(":/transform-rotate-ccw-%1.svg").arg(iconTheme)),
                     tr("Rotate counterclockwise", "View action"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_R);
-    ADD_SHORTCUT
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapRotateCounterClockwise", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapRotateCounterClockwise", Qt::SHIFT | Qt::Key_R, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(viewRotateCounterClockwise()));
     actionRotateCounterClockwise = a;
 
     a = new QAction(QPixmap(QString(":/transform-rotate-cw-%1.svg").arg(iconTheme)),
                     tr("Rotate clockwise", "View action"), this);
-    a->setShortcut(Qt::Key_R);
-    ADD_SHORTCUT
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapRotateClockwise", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapRotateClockwise", Qt::Key_R, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(viewRotateClockwise()));
     actionRotateClockwise = a;
 
     a = new QAction(QPixmap(QString(":/zoom-original-%1").arg(iconTheme)),
                     tr("reset Zoom", "View action"), this);
-    a->setShortcut(Qt::Key_Comma);
-    ADD_SHORTCUT
-    switchboard.addSwitch("mapZoomReset", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapZoomReset", Qt::Key_Comma, shortcutScope, tag);
     viewMenu->addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomReset()));
     actionZoomReset = a;
 
     a = new QAction(QPixmap(QString(":/zoom-fit-best-%1.svg").arg(iconTheme)),
                     tr("Center on selection", "View action"), this);
-    a->setShortcut(Qt::Key_Period);
-    ADD_SHORTCUT
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapCenterOn", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapCenterOn", Qt::Key_NumberSign, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(viewCenter()));
     actionCenterOn = a;
 
     a = new QAction(tr("Fit view to selection", "View action"), this);
-    a->setShortcut(Qt::Key_Period | Qt::SHIFT);
-    ADD_SHORTCUT
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapCenterAndFitView", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapCenterAndFitView", Qt::Key_Semicolon, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(viewCenterScaled()));
     actionCenterOnScaled = a;
 
     a = new QAction( tr("Rotate view to selection", "View action"), this);
-    a->setShortcut(Qt::Key_NumberSign);
-    ADD_SHORTCUT
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapCenterAndRotateView", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapCenterAndRotateView", Qt::Key_NumberSign | Qt::SHIFT, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(viewCenterRotated()));
     actionCenterOnRotated = a;
 
+    tag = tr("Tree editor expand/collapse", "Mainwindow view shortcut groups");
+
+    a = new QAction(QPixmap(), tr("Expand all branches", "Edit menu"), this);
+    connect(a, SIGNAL(triggered()), this, SLOT(editExpandAll()));
+    actionExpandAll = a;
+    actionExpandAll->setEnabled(false);
+    actionExpandAll->setCheckable(false);
+    actionListBranches.append(actionExpandAll);
+    addAction(a);
+
+    a = new QAction(tr("Expand one level", "Edit menu"), this);
+    switchboard.addAction(a, "mapExpandOneLevel", Qt::Key_Greater, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(editExpandOneLevel()));
+    a->setEnabled(false);
+    a->setCheckable(false);
+    addAction(a);
+    actionListBranches.append(a);
+    actionExpandOneLevel = a;
+
+    a = new QAction("TE: " + tr("Collapse one level", "Edit menu"), this);
+    switchboard.addAction(a, "mapCollapseOneLevel", Qt::Key_Less | Qt::CTRL, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(editCollapseOneLevel()));
+    viewMenu->addAction(a);
+    a->setEnabled(false);
+    a->setCheckable(false);
+    actionListBranches.append(a);
+    addAction(a);
+    actionCollapseOneLevel = a;
+
+    a = new QAction("TE: " + tr("Collapse unselected levels", "Edit menu"), this);
+    switchboard.addAction(a, "mapCollapseUnselectedLevels", Qt::Key_Less, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(editCollapseUnselected()));
+    viewMenu->addAction(a);
+    a->setEnabled(false);
+    a->setCheckable(false);
+    actionListBranches.append(a);
+    addAction(a);
+    actionCollapseUnselected = a;
 
     viewMenu->addSeparator();
 
     // Editor and other windows
 
+    tag = tr("Windows", "Mainwindow view shortcut groups");
     // a=noteEditorDW->toggleViewAction();
     a = new QAction(QPixmap(":/flag-note.svg"),
                     tr("Note editor", "View action"), this);
-    a->setShortcut(Qt::Key_N);
     a->setShortcutContext(Qt::WidgetShortcut);
     a->setCheckable(true);
     windowsMenu->addAction(a);
     mapEditorActions.append(a);
-    switchboard.addSwitch("mapToggleNoteEditor", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleNoteEditor()));
-    actionViewToggleNoteEditor = a;
+    switchboard.addAction(a, "mapShowNoteEditor", Qt::Key_N, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(windowShowNoteEditor()));
+    actionViewToggleNoteEditor = a; // FIXME-3 rename action to show
 
     // a=headingEditorDW->toggleViewAction();
     a = new QAction(QPixmap(":/headingeditor.png"),
                     tr("Heading editor", "View action"), this);
     a->setCheckable(true);
     a->setIcon(QPixmap(":/headingeditor.png"));
-    a->setShortcut(Qt::Key_E);
     a->setShortcutContext(Qt::WidgetShortcut);
     mapEditorActions.append(a);
     windowsMenu->addAction(a);
-    switchboard.addSwitch("mapToggleHeadingEditor", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHeadingEditor()));
-    actionViewToggleHeadingEditor = a;
+    switchboard.addAction(a, "mapShowHeadingEditor", Qt::Key_E, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(windowShowHeadingEditor()));
+    actionViewToggleHeadingEditor = a;  // FIXME-3 rename action to show
 
     // Original icon is "category" from KDE
     a = new QAction(QPixmap(":/treeeditor.png"),
-                    tr("Tree editor", "View action"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_T);
+           tr("Switch between Map editor and Tree editor", "View action"), this);
     a->setCheckable(true);
     windowsMenu->addAction(a);
-    switchboard.addSwitch("mapToggleTreeEditor", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTreeEditors()));
-    actionViewToggleTreeEditor = a;
+    switchboard.addAction(a, "switchTreeEditorAndMapEditor", Qt::Key_Tab, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(switchEditors()));
+    actionViewSwitchEditors = a;
 
     a = new QAction(QPixmap(":/taskeditor.png"),
                     tr("Task editor", "View action"), this);
     a->setCheckable(true);
-    a->setShortcut(Qt::Key_Q);
     a->setShortcutContext(Qt::WidgetShortcut);
     mapEditorActions.append(a);
     windowsMenu->addAction(a);
-    switchboard.addSwitch("mapToggleTaskEditor", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleTaskEditor", Qt::Key_Q, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTaskEditor()));
-    actionViewToggleTaskEditor = a;
+    actionViewToggleTaskEditor = a; // FIXME-3 rename action to show
 
     a = new QAction(QPixmap(":/slideeditor.png"),
                     tr("Slide editor", "View action"), this);
     a->setCheckable(true);
     windowsMenu->addAction(a);
-    switchboard.addSwitch("mapToggleSlideEditor", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(windowToggleSlideEditors()));
-    actionViewToggleSlideEditor = a;
+    switchboard.addAction(a, "mapShowSlideEditor", shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(windowShowSlideEditors()));
+    actionViewShowSlideEditors = a;
 
     a = new QAction(QPixmap(":/scripteditor.png"),
                     tr("Script editor", "View action"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_S);
     a->setCheckable(true);
     windowsMenu->addAction(a);
-    switchboard.addSwitch("mapToggleScriptEditor", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleScriptEditor", Qt::SHIFT | Qt::Key_S, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptEditor()));
-    actionViewToggleScriptEditor = a;
+    actionViewToggleScriptEditor = a; // FIXME-3 show
 
     a = new QAction(QPixmap(), tr("Script output window", "View action"), this);
-    a->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_S);
     a->setCheckable(true);
     windowsMenu->addAction(a);
-    switchboard.addSwitch("mapToggleScriptOutput", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleScriptOutput", Qt::CTRL | Qt::SHIFT | Qt::Key_S, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptOutput()));
-    actionViewToggleScriptOutput = a;
+    actionViewToggleScriptOutput = a; // FIXME-3 show
 
     a = new QAction(QPixmap(":/history.png"),
                     tr("History Window", "View action"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_H);
     a->setShortcutContext(Qt::WidgetShortcut);
     a->setCheckable(true);
     windowsMenu->addAction(a);
     mapEditorActions.append(a);
-    switchboard.addSwitch("mapToggleHistoryWindow", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapToggleHistoryWindow", Qt::CTRL | Qt::Key_H, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHistory()));
     actionViewToggleHistoryWindow = a;
 
@@ -3027,54 +2937,61 @@ void Main::setupViewActions()
 
     viewMenu->addSeparator();
 
-    // Map and slides
-    a = new QAction(tr("Next Map", "View action"), this);
-    a->setStatusTip(a->text());
-    a->setShortcut(Qt::SHIFT | Qt::Key_Right);
-    viewMenu->addAction(a);
-    switchboard.addSwitch("mapPrevious", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(windowNextEditor()));
-
-    a = new QAction(tr("Previous Map", "View action"), this);
-    a->setStatusTip(a->text());
-    a->setShortcut(Qt::SHIFT | Qt::Key_Left);
+    // Slides and presentation
+    tag = tr("Presentation mode", "Mainwindow presentation shortcut groups");
+    a = new QAction(QPixmap(":view-video-projector.png"), 
+            tr("Toggle Presentation mode", "View action") + " " +
+            tr("(still experimental)"),
+            this);
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapNext", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(windowPreviousEditor()));
+    switchboard.addAction (a, "presentationMode", Qt::Key_Asterisk | Qt::SHIFT, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(togglePresentationMode()));
+    actionTogglePresentationMode = a;
 
     a = new QAction(tr("Next slide", "View action"), this);
     a->setStatusTip(a->text());
-    a->setShortcut(Qt::Key_Space);
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapNextSlide", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapNextSlide", Qt::Key_Space, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(nextSlide()));
 
     a = new QAction(tr("Previous slide", "View action"), this); //FIXME-3 no shortcut yet
     a->setStatusTip(a->text());
-    //a->setShortcut(Qt::Key_Backspace);
     viewMenu->addAction(a);
-    switchboard.addSwitch("mapPreviousSlide", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapPreviousSlide", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(previousSlide()));
+
+    // Map navigation
+    tag = tr("Navigation between maps", "Mainwindow view shortcut groups");
+    a = new QAction(tr("Next Map", "View action"), this);
+    a->setStatusTip(a->text());
+    viewMenu->addAction(a);
+    switchboard.addAction(a, "mapPrevious", Qt::SHIFT | Qt::Key_Right, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(windowNextEditor()));
+
+    a = new QAction(tr("Previous Map", "View action"), this);
+    a->setStatusTip(a->text());
+    viewMenu->addAction(a);
+    switchboard.addAction(a, "mapNext", Qt::SHIFT | Qt::Key_Left, shortcutScope, tag);
+    connect(a, SIGNAL(triggered()), this, SLOT(windowPreviousEditor()));
 }
 
 // Connect Actions
 void Main::setupConnectActions()
 {
-    QMenu *connectMenu = menuBar()->addMenu(tr("&Connect"));
     QString tag = tr("Connect", "Shortcuts");
 
     QAction *a;
 
     a = new QAction( tr("Get Confluence user data", "Connect action"), this);
-    a->setShortcut(Qt::SHIFT | Qt::Key_C);
     connectMenu->addAction(a);
-    switchboard.addSwitch ("confluenceUser", shortcutScope, a, tag);
+    switchboard.addAction(a, "confluenceUser", Qt::SHIFT | Qt::Key_C, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(getConfluenceUser()));
     actionConnectGetConfluenceUser = a;
 
     connectMenu->addAction(actionGetConfluencePageDetails);
     connectMenu->addAction(actionGetConfluencePageDetailsRecursively);
     connectMenu->addAction(actionGetJiraDataSubtree);
+    connectMenu->addAction(actionSetJiraQuery);
 
     connectMenu->addSeparator();
 
@@ -3097,10 +3014,8 @@ void Main::setupModeActions()
         QIcon(":/mode-select.svg"),
         tr("Use modifier to select and reorder objects", "Mode modifier"),
         actionGroupModModes);
-    a->setShortcut(Qt::Key_J);
-    ADD_SHORTCUT
     addAction(a);
-    switchboard.addSwitch("mapModModePoint", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapModModePoint", Qt::Key_J, shortcutScope, tag);
     a->setCheckable(true);
     a->setChecked(true);
     actionListFiles.append(a);
@@ -3111,10 +3026,8 @@ void Main::setupModeActions()
         tr("Use modifier to pick color from another branch",
            "Mode modifier"),
         actionGroupModModes);
-    a->setShortcut(Qt::Key_K);
-    ADD_SHORTCUT
     addAction(a);
-    switchboard.addSwitch("mapModModeColor", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapModModeColor", Qt::Key_K, shortcutScope, tag);
     a->setCheckable(true);
     actionListFiles.append(a);
     actionModModeColor = a;
@@ -3122,10 +3035,8 @@ void Main::setupModeActions()
     a = new QAction(QPixmap(":/mode-xlink.png"),
                     tr("Use modifier to draw xLinks", "Mode modifier"),
                     actionGroupModModes);
-    a->setShortcut(Qt::Key_L);
-    ADD_SHORTCUT
     addAction(a);
-    switchboard.addSwitch("mapModModeXLink", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapModModeXLink", Qt::Key_L, shortcutScope, tag);
     a->setCheckable(true);
     actionListFiles.append(a);
     actionModModeXLink = a;
@@ -3134,10 +3045,8 @@ void Main::setupModeActions()
         QPixmap(":/mode-move-object.svg"),
         tr("Use modifier to move branches without linking", "Mode modifier"),
         actionGroupModModes);
-    a->setShortcut(Qt::Key_Odiaeresis);
-    ADD_SHORTCUT
     addAction(a);
-    switchboard.addSwitch("mapModModeMoveObject", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapModModeMoveObject", Qt::Key_Odiaeresis, shortcutScope, tag);
     a->setCheckable(true);
     actionListFiles.append(a);
     actionModModeMoveObject = a;
@@ -3146,10 +3055,8 @@ void Main::setupModeActions()
         QPixmap(":/mode-move-view.png"),
         tr("Use modifier to move view without selecting", "Mode modifier"),
         actionGroupModModes);
-    a->setShortcut(Qt::Key_Adiaeresis);
-    ADD_SHORTCUT
     addAction(a);
-    switchboard.addSwitch("mapModModeMoveView", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapModModeMoveView", Qt::Key_Adiaeresis, shortcutScope, tag);
     a->setCheckable(true);
     actionListFiles.append(a);
     actionModModeMoveView = a;
@@ -3446,7 +3353,7 @@ Flag *Main::setupFlag(const QString &path, Flag::FlagType type,
     }
 
     if (!flag)
-        return flag;
+        return nullptr;
 
     flag->setName(name);
     flag->setToolTip(tooltip);
@@ -3571,6 +3478,8 @@ void Main::setupSettingsActions()
     settingsMenu->addAction(a);
     actionSettingsJIRA = a;
 
+    settingsMenu->addSeparator();
+
     a = new QAction(tr("Set path for new maps", "Settings action") + "...",
                     this);
     connect(a, SIGNAL(triggered()), this, SLOT(settingsDefaultMapPath()));
@@ -3628,13 +3537,6 @@ void Main::setupSettingsActions()
     settingsMenu->addAction(a);
     actionSettingsAutoSelectNewBranch = a;
 
-    a = new QAction(tr("Select existing heading", "Settings action"), this);
-    a->setCheckable(true);
-    a->setChecked(
-        settings.value("/mapeditor/editmode/autoSelectText", true).toBool());
-    settingsMenu->addAction(a);
-    actionSettingsAutoSelectText = a;
-
     a = new QAction(tr("Exclusive flags", "Settings action"), this);
     a->setCheckable(true);
     a->setChecked(
@@ -3697,13 +3599,11 @@ void Main::setupTestActions()
     QString tag = "Testing";
     QAction *a;
     a = new QAction("Test function 1", this);
-    a->setShortcut(Qt::ALT | Qt::Key_T);
     testMenu->addAction(a);
-    switchboard.addSwitch("mapTest1", shortcutScope, a, tag);
+    switchboard.addAction(a, "mapTest1", Qt::ALT | Qt::Key_T, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(testFunction1()));
 
     a = new QAction("Test function 2", this);
-    // a->setShortcut (Qt::ALT | Qt::Key_T);
     testMenu->addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(testFunction2()));
 
@@ -3767,7 +3667,7 @@ void Main::setupHelpActions()
 }
 
 // Context Menus
-void Main::setupContextMenus()
+void Main::setupContextMenus()  // FIXME-2 Use context menus add/remove also in Edit menu for better readability
 {
     // Context menu for goto/move targets  (populated on demand)
     targetsContextMenu = new QMenu(this);
@@ -3787,6 +3687,8 @@ void Main::setupContextMenus()
     branchAddContextMenu->addSeparator();
     branchAddContextMenu->addAction(actionImportAdd);
     branchAddContextMenu->addAction(actionImportReplace);
+    foreach (auto a, branchAddContextMenu->actions())
+        a->setShortcutVisibleInContextMenu(true);
 
     // Submenu "Remove"
     branchRemoveContextMenu =
@@ -3795,10 +3697,30 @@ void Main::setupContextMenus()
     branchRemoveContextMenu->addAction(actionDelete);
     branchRemoveContextMenu->addAction(actionDeleteKeepChildren);
     branchRemoveContextMenu->addAction(actionDeleteChildren);
-
-    branchContextMenu->addAction(actionSaveBranch);
-    branchContextMenu->addAction(actionFileNewCopy);
-    branchContextMenu->addAction(actionDetach);
+    foreach (auto a, branchRemoveContextMenu->actions())
+        a->setShortcutVisibleInContextMenu(true);
+
+    // Submenu "Hierarchy"
+    branchHierarchyContextMenu =
+        branchContextMenu->addMenu(tr("Hierarchy", "Context menu name"));
+    branchHierarchyContextMenu->addAction(actionMoveUp);
+    branchHierarchyContextMenu->addAction(actionMoveDown);
+    branchHierarchyContextMenu->addAction(actionMoveDownDiagonally);
+    branchHierarchyContextMenu->addAction(actionMoveUpDiagonally);
+    branchHierarchyContextMenu->addAction(actionDetach);
+    branchHierarchyContextMenu->addAction(actionSortChildren);
+    branchHierarchyContextMenu->addAction(actionSortBackChildren);
+    //foreach (auto a, branchRemoveContextMenu->actions())
+    //   a->setShortcutVisibleInContextMenu(true);
+
+    // Submenu "Geometry"
+    branchGeometryContextMenu =
+        branchContextMenu->addMenu(tr("Geometry", "Context menu name"));
+    branchGeometryContextMenu->addAction(actionGrowSelectionSize);
+    branchGeometryContextMenu->addAction(actionShrinkSelectionSize);
+    branchGeometryContextMenu->addAction(actionResetSelectionSize);
+    branchGeometryContextMenu->addAction(actionRotateSubtreeCW);
+    branchGeometryContextMenu->addAction(actionRotateSubtreeCCW);
 
     branchContextMenu->addSeparator();
     branchContextMenu->addAction(actionLoadImage);
@@ -3821,6 +3743,8 @@ void Main::setupContextMenus()
     taskContextMenu->addAction(actionTaskSleep7);
     taskContextMenu->addAction(actionTaskSleep14);
     taskContextMenu->addAction(actionTaskSleep28);
+    foreach (auto a, taskContextMenu->actions())
+        a->setShortcutVisibleInContextMenu(true);
 
     // Submenu for Links (URLs, vymLinks)
     branchLinksContextMenu = new QMenu(this);
@@ -3844,6 +3768,8 @@ void Main::setupContextMenus()
     branchLinksContextMenu->addAction(actionOpenMultipleVymLinks);
     branchLinksContextMenu->addAction(actionEditVymLink);
     branchLinksContextMenu->addAction(actionDeleteVymLink);
+    foreach (auto a, branchLinksContextMenu->actions())
+        a->setShortcutVisibleInContextMenu(true);
 
     // Context Menu for XLinks in a branch menu
     // This will be populated "on demand" in updateActions
@@ -3854,16 +3780,10 @@ void Main::setupContextMenus()
     connect(branchXLinksContextMenuEdit, SIGNAL(triggered(QAction *)), this,
             SLOT(editEditXLink(QAction *)));
     QAction *a;
-    a = new QAction(tr("Follow XLink", "Context menu"), this);
-    a->setShortcut(Qt::Key_F);
-    addAction(a);
-    switchboard.addSwitch("mapFollowXLink", shortcutScope, a, tag);
-    connect(a, SIGNAL(triggered()), this, SLOT(popupFollowXLink()));
-
     branchXLinksContextMenuFollow =
         branchContextMenu->addMenu(tr("Follow XLink", "Context menu name"));
     connect(branchXLinksContextMenuFollow, SIGNAL(triggered(QAction *)), this,
-            SLOT(editFollowXLink(QAction *)));
+            SLOT(followReference(QAction *)));
 
     branchContextMenu->addSeparator();
     branchContextMenu->addAction(actionViewTogglePropertyEditor);
@@ -3883,6 +3803,9 @@ void Main::setupContextMenus()
     floatimageContextMenu->addAction(actionShrinkSelectionSize);
     floatimageContextMenu->addAction(actionFormatHideLinkUnselected);
 
+    foreach (auto a, floatimageContextMenu->actions())
+        a->setShortcutVisibleInContextMenu(true);
+
     // Context menu for canvas
     canvasContextMenu = new QMenu(this);
 
@@ -3908,6 +3831,8 @@ void Main::setupContextMenus()
 
     canvasContextMenu->addSeparator();
     canvasContextMenu->addAction(actionMapProperties);
+    foreach (auto a, canvasContextMenu->actions())
+        a->setShortcutVisibleInContextMenu(true);
 
     // Menu for last opened files
     // Create actions
@@ -4009,9 +3934,12 @@ void Main::setupMacros()
 
 void Main::setupToolbars()
 {
+    QList <QToolBar*> toolbars;
     // File actions
     fileToolbar =
         addToolBar(tr("File actions toolbar", "Toolbar for file actions"));
+    toolbars << fileToolbar;
+
     fileToolbar->setObjectName("fileTB");
     fileToolbar->addAction(actionFileNew);
     fileToolbar->addAction(actionFileOpen);
@@ -4022,6 +3950,7 @@ void Main::setupToolbars()
     // Undo/Redo and clipboard
     clipboardToolbar = addToolBar(tr("Undo and clipboard toolbar",
                                      "Toolbar for redo/undo and clipboard"));
+    toolbars << clipboardToolbar;
     clipboardToolbar->setObjectName("clipboard toolbar");
     clipboardToolbar->addAction(actionUndo);
     clipboardToolbar->addAction(actionRedo);
@@ -4031,6 +3960,7 @@ void Main::setupToolbars()
 
     // Basic edits
     editActionsToolbar = addToolBar(tr("Edit actions toolbar", "Toolbar name"));
+    toolbars << editActionsToolbar;
     editActionsToolbar->setObjectName("basic edit actions TB");
     editActionsToolbar->addAction(actionAddMapCenter);
     editActionsToolbar->addAction(actionAddBranch);
@@ -4051,6 +3981,7 @@ void Main::setupToolbars()
 
     // Selections
     selectionToolbar = addToolBar(tr("Selection toolbar", "Toolbar name"));
+    toolbars << selectionToolbar;
     selectionToolbar->setObjectName("toolbar for selecting items");
     selectionToolbar->addAction(actionFind);
     selectionToolbar->addAction(actionSelectPrevious);
@@ -4059,12 +3990,14 @@ void Main::setupToolbars()
     // URLs and vymLinks
     referencesToolbar = addToolBar(
         tr("URLs and vymLinks toolbar", "Toolbar for URLs and vymlinks"));
+    toolbars << referencesToolbar;
     referencesToolbar->setObjectName("URLs and vymlinks toolbar");
     referencesToolbar->addAction(actionURLNew);
     referencesToolbar->addAction(actionEditVymLink);
 
     // Format and colors
     colorsToolbar = new QToolBar(tr("Colors toolbar", "Colors toolbar name"));
+    toolbars << colorsToolbar;
     colorsToolbar->setObjectName("colorsTB");
 
     actionGroupQuickColors = new QActionGroup(this);
@@ -4095,7 +4028,7 @@ void Main::setupToolbars()
         a->setCheckable(true);
         a->setData(n);
         //formatMenu->addAction(a);
-        // switchboard.addSwitch("mapFormatColor", shortcutScope, a, tag);
+        // switchboard.addAction(a, "mapFormatColor", shortcutScope, tag);
         connect(a, SIGNAL(triggered()), this, SLOT(quickColorPressed()));
         colorsToolbar->addAction(a);
         n++;
@@ -4111,8 +4044,9 @@ void Main::setupToolbars()
     else
         addToolBar (colorsToolbar);
 
-    // View transformations (shrink/grow/rotate)
+    // View transformations (shrink/grow/rotate)    // FIXME-3 add shortcut to rotate selected subtree/item   Fn-key maybe and macro?
     viewTransformationsToolbar = addToolBar(tr("View toolbar", "View Toolbar name"));
+    toolbars << viewTransformationsToolbar;
     viewTransformationsToolbar->setObjectName("viewTB");
     viewTransformationsToolbar->addAction(actionZoomIn);
     viewTransformationsToolbar->addAction(actionZoomOut);
@@ -4123,24 +4057,27 @@ void Main::setupToolbars()
 
     // Modified special view, e.g. presentation mode or temporary hiding of branches
     limitedViewToolbar = addToolBar(tr("Limited view toolbar", "View Toolbar name"));
+    toolbars << limitedViewToolbar ;
     limitedViewToolbar->setObjectName("limitedViewTB");
     limitedViewToolbar->addAction(actionTogglePresentationMode);
     limitedViewToolbar->addAction(actionToggleHideTmpMode);
 
     // Editors
     editorsToolbar = addToolBar(tr("Editors toolbar", "Editor Toolbar name"));
+    toolbars << editorsToolbar ;
     editorsToolbar->setObjectName("editorsTB");
     editorsToolbar->addAction(actionViewToggleNoteEditor);
     editorsToolbar->addAction(actionViewToggleHeadingEditor);
-    editorsToolbar->addAction(actionViewToggleTreeEditor);
+    editorsToolbar->addAction(actionViewSwitchEditors);
     editorsToolbar->addAction(actionViewToggleTaskEditor);
-    editorsToolbar->addAction(actionViewToggleSlideEditor);
+    editorsToolbar->addAction(actionViewShowSlideEditors);
     editorsToolbar->addAction(actionViewToggleScriptEditor);
     editorsToolbar->addAction(actionViewToggleHistoryWindow);
 
     // Modifier modes
     modModesToolbar =
         addToolBar(tr("Modifier modes toolbar", "Modifier Toolbar name"));
+    toolbars << modModesToolbar ;
     modModesToolbar->setObjectName("modesTB");
     modModesToolbar->addAction(actionModModePoint);
     modModesToolbar->addAction(actionModModeColor);
@@ -4152,28 +4089,25 @@ void Main::setupToolbars()
     addToolBarBreak();
     standardFlagsToolbar =
         addToolBar(tr("Standard Flags toolbar", "Standard Flag Toolbar"));
+    toolbars << standardFlagsToolbar ;
     standardFlagsToolbar->setObjectName("standardFlagTB");
     standardFlagsMaster->setToolBar(standardFlagsToolbar);
 
     userFlagsToolbar =
         addToolBar(tr("User Flags toolbar", "user Flags Toolbar"));
+    toolbars << userFlagsToolbar ;
     userFlagsToolbar->setObjectName("userFlagsTB");
+
     userFlagsMaster->setToolBar(userFlagsToolbar);
     userFlagsMaster->createConfigureAction();
 
-    // Add all toolbars to View menu
-    toolbarsMenu->addAction(fileToolbar->toggleViewAction());
-    toolbarsMenu->addAction(clipboardToolbar->toggleViewAction());
-    toolbarsMenu->addAction(editActionsToolbar->toggleViewAction());
-    toolbarsMenu->addAction(selectionToolbar->toggleViewAction());
-    toolbarsMenu->addAction(colorsToolbar->toggleViewAction());
-    toolbarsMenu->addAction(viewTransformationsToolbar->toggleViewAction());
-    toolbarsMenu->addAction(limitedViewToolbar->toggleViewAction());
-    toolbarsMenu->addAction(modModesToolbar->toggleViewAction());
-    toolbarsMenu->addAction(referencesToolbar->toggleViewAction());
-    toolbarsMenu->addAction(editorsToolbar->toggleViewAction());
-    toolbarsMenu->addAction(userFlagsToolbar->toggleViewAction());
-    toolbarsMenu->addAction(standardFlagsToolbar->toggleViewAction());
+    foreach (auto tb, toolbars) {
+        // Add View menu
+        toolbarsMenu->addAction(tb->toggleViewAction());
+
+        // Set backgrounds
+        tb->setStyleSheet(toolBarStyle);
+    }
 
     // Initialize toolbarStates for presentation mode
     toolbarStates[fileToolbar] = true;
@@ -4372,6 +4306,18 @@ void Main::fileNewCopy()
     }
 }
 
+void Main::backgroundZipStarted()
+{
+    backgroundZipProcesses++;
+}
+
+void Main::backgroundZipFinished()
+{
+    backgroundZipProcesses--;
+    if (closeAfterLastZipProcess)
+        fileExitVYM();
+}
+
 bool Main::fileLoad(QString fn, const File::LoadMode &lmode,
                                const File::FileType &ftype)
 {
@@ -5118,7 +5064,7 @@ void Main::fileExportLast()
 
 bool Main::fileCloseMap(int i)
 {
-
+    //qDebug() << __func__ << "i=" << i << " currentInd=" << tabWidget->currentIndex();
     VymModel *m;
     VymView *vv;
     if (i < 0)
@@ -5128,11 +5074,6 @@ bool Main::fileCloseMap(int i)
     m = vv->getModel();
 
     if (m) {
-        if (m->isSaving()) {
-            //qDebug() << "MW::fileCloseMap ignoring request to close because of running zip process";
-            return false;
-        }
-
         if (m->hasChanged()) {
             QMessageBox mb(
                 QMessageBox::Warning,
@@ -5177,8 +5118,25 @@ void Main::filePrint()
         currentMapEditor()->print();
 }
 
+bool Main::exitAfterScript()
+{
+    return exitAfterScriptInt;
+}
+
+void Main::setRepeatAction(const QString &script)
+{
+    repeatActionInt = script;
+}
+
+void Main::setExitAfterScript(bool b)
+{
+    exitAfterScriptInt = b;
+}
+
 bool Main::fileExitVYM()
 {
+    closeAfterLastZipProcess = true;
+
     // Only save session if there still are tabs open
     if (tabWidget->count() > 0)
         fileSaveSession();
@@ -5191,7 +5149,10 @@ bool Main::fileExitVYM()
         // Update widgets to show progress
         qApp->processEvents();
     }
-    qApp->quit();
+    if (backgroundZipProcesses > 0)
+        qDebug() << __func__ << " has still running bg zips...";
+    else
+        qApp->quit();
     return false;
 }
 
@@ -5838,6 +5799,25 @@ void Main::editResetSelectionSize()
         m->resetSelectionSize();
 }
 
+void Main::editRotateSubtreeCW()
+{
+    VymModel *m = currentModel();
+    if (m)
+        m->rotateSubtree(5);
+}
+
+void Main::editRotateSubtreeCCW()
+{
+    VymModel *m = currentModel();
+    if (m)
+        m->rotateSubtree(-5);
+}
+
+void Main::editRepeatLastAction()
+{
+    runScriptWithMacros(repeatActionInt);
+}
+
 void Main::editAddMapCenter()
 {
     VymModel *m = currentModel();
@@ -5925,7 +5905,7 @@ void Main::editDeleteSelection()
 {
     VymModel *m = currentModel();
     if (m)
-        m->deleteSelection();
+        m->cut();
 }
 
 void Main::editLoadImage()
@@ -5962,17 +5942,34 @@ void Main::editEditXLink(QAction *a)
     }
 }
 
-void Main::popupFollowXLink()
+void Main::popupFollowReference()
 {
-    branchXLinksContextMenuFollow->exec(QCursor::pos());
+    if (branchXLinksContextMenuFollow->actions().count() == 1)
+        // If only one reference (XLink, Url, VymLink) is available,
+        // just follow it
+        followReference(branchXLinksContextMenuFollow->actions().at(0));
+    else
+        // Popup menu
+        branchXLinksContextMenuFollow->exec(QCursor::pos());
 }
 
-void Main::editFollowXLink(QAction *a)
+void Main::followReference(QAction *a)
 {
     VymModel *m = currentModel();
 
-    if (m)
-        m->followXLink(branchXLinksContextMenuFollow->actions().indexOf(a));
+    if (m) {
+        QString d = a->data().toString();
+        if (d.startsWith("XLink:"))
+            m->select(QUuid(d.section(':', 1)));
+        else if (d.startsWith("Url:"))
+            openUrl(d.section(':', 1));
+        else if (d.startsWith("VymLink:")) {
+            QStringList vymLinks;
+            vymLinks << d.section(':', 1);
+            openVymLinks(vymLinks);
+        } else
+            qWarning() << __func__ << "Unknown reference in d=" << d;
+    }
 }
 
 bool Main::initLinkedMapsMenu(VymModel *model, QMenu *menu)
@@ -6133,6 +6130,20 @@ void Main::editMoveToTarget()
     }
 }
 
+void Main::editSelectFirstSibling()
+{
+    VymModel *m = currentModel();
+    if (m)
+        m->selectFirstBranch();
+}
+
+void Main::editSelectLastSibling()
+{
+    VymModel *m = currentModel();
+    if (m)
+        m->selectLastBranch();
+}
+
 void Main::editSelectPrevious()
 {
     VymModel *m = currentModel();
@@ -6156,15 +6167,9 @@ void Main::editSelectNothing()
 
 void Main::editOpenFindResultWidget()
 {
-    if (!findResultWidget->parentWidget()->isVisible()) {
-        //     findResultWidget->parentWidget()->show();
-        findResultWidget->popup();
-    }
-    else
-        findResultWidget->parentWidget()->hide();
+    findResultWidget->popup();
 }
 
-#include "findwidget.h" // FIXME-4 Integrated FRW and FW
 void Main::editFindNext(QString s, bool searchNotesFlag)
 {
     Qt::CaseSensitivity cs = Qt::CaseInsensitive;
@@ -6172,9 +6177,9 @@ void Main::editFindNext(QString s, bool searchNotesFlag)
     if (m) {
         if (m->findAll(findResultWidget->getResultModel(), s, cs,
                        searchNotesFlag))
-            findResultWidget->setStatus(FindWidget::Success);
+            findResultWidget->setStatus(FindControlsWidget::Success);
         else
-            findResultWidget->setStatus(FindWidget::Failed);
+            findResultWidget->setStatus(FindControlsWidget::Failed);
     }
 }
 
@@ -6186,8 +6191,7 @@ void Main::editFindDuplicateURLs() // FIXME-4 feature: use FindResultWidget for
         m->findDuplicateURLs();
 }
 
-void Main::updateQueries(
-    VymModel *) // FIXME-4 disabled for now to avoid selection in FRW
+void Main::updateQueries( VymModel *) // FIXME-4 disabled for now to avoid selection in FRW
 {
     return;
     /*
@@ -6336,7 +6340,6 @@ void Main::formatSelectLinkColor()
     if (m) {
         QColor col = QColorDialog::getColor(m->mapDesign()->defaultLinkColor(), this);
         m->setDefaultLinkColor(col);
-        updateActions();
     }
 }
 
@@ -6404,14 +6407,14 @@ void Main::viewRotateCounterClockwise()
 {
     MapEditor *me = currentMapEditor();
     if (me)
-        me->setRotationTarget(me->rotationTarget() - 10);
+        me->setRotationTarget(me->rotationTarget() - 5);
 }
 
 void Main::viewRotateClockwise()
 {
     MapEditor *me = currentMapEditor();
     if (me)
-        me->setRotationTarget(me->rotationTarget() + 10);
+        me->setRotationTarget(me->rotationTarget() + 5);
 }
 
 void Main::viewCenter()
@@ -6703,24 +6706,32 @@ bool Main::settingsJIRA()
         return false;
 }
 
-void Main::windowToggleNoteEditor()
+void Main::windowShowNoteEditor()
 {
-    if (noteEditor->parentWidget()->isVisible())
-        noteEditor->parentWidget()->hide();
-    else {
+    if (!noteEditor->parentWidget()->isVisible())
         noteEditor->parentWidget()->show();
-        noteEditor->setFocus();
-    }
+    noteEditor->setFocus();
 }
 
-void Main::windowToggleTreeEditors()
+void Main::switchEditors()
 {
-    windowSetTreeEditorsVisibility(actionViewToggleTreeEditor->isChecked());
+    VymView *vv = currentView();
+    if (vv) {
+        MapEditor *me = vv->getMapEditor();
+        if (me) {
+            if (me->hasFocus()) {
+                windowSetTreeEditorsVisibility(true);
+                vv->setFocusTreeEditor();
+            } else
+                vv->setFocusMapEditor();
+        }
+    }
 }
 
 void Main::windowSetTreeEditorsVisibility(bool b)
 {
-    actionViewToggleTreeEditor->setChecked(b);
+    // Close *all* TreeEditors in each VymView and update vym settings
+    settings.setValue("/mainwindow/view/showTreeEditors", b);
     for (int i = 0; i < tabWidget->count(); i++)
         ((VymView*)tabWidget->widget(i))->setTreeEditorVisibility(b);
 }
@@ -6737,14 +6748,14 @@ void Main::windowToggleTaskEditor()
     }
 }
 
-void Main::windowToggleSlideEditors()
+void Main::windowShowSlideEditors()
 {
-    windowSetSlideEditorsVisibility(actionViewToggleSlideEditor->isChecked());
+    windowSetSlideEditorsVisibility(true);
 }
 
 void Main::windowSetSlideEditorsVisibility(bool b)
 {
-    actionViewToggleSlideEditor->setChecked(b);
+    settings.setValue("/mainwindow/view/showSlideEditors", b);
     for (int i = 0; i < tabWidget->count(); i++)
         ((VymView*)tabWidget->widget(i))->setSlideEditorVisibility(b);
 }
@@ -6790,16 +6801,11 @@ void Main::windowToggleProperty()
     branchPropertyEditor->setModel(currentModel());
 }
 
-void Main::windowShowHeadingEditor() { headingEditorDW->show(); }
-
-void Main::windowToggleHeadingEditor()
+void Main::windowShowHeadingEditor()
 {
-    if (headingEditor->parentWidget()->isVisible())
-        headingEditor->parentWidget()->hide();
-    else {
+    if (!headingEditor->parentWidget()->isVisible())
         headingEditor->parentWidget()->show();
-        headingEditor->setFocus();
-    }
+    headingEditor->setFocus();
 }
 
 void Main::windowToggleAntiAlias()
@@ -6861,9 +6867,9 @@ void Main::updateNoteEditor(TreeItem *ti)
             noteEditor->setNote(ti->getNote());
         else
             noteEditor->clear(); // Also sets empty state
-        return;
-    }
-    noteEditor->setInactive();
+    } else
+        noteEditor->setInactive();
+    noteEditor->setEditorTitle();
 }
 
 void Main::updateHeadingEditor(TreeItem *ti)
@@ -7102,23 +7108,37 @@ void Main::updateActions()
         if (m->isSaving()) {
             actionFileSave->setEnabled(false);
             actionFileClose->setEnabled(false);
-            actionFileExitVym->setEnabled(false);
         } else {
             if (!m->hasChanged())
                 actionFileSave->setEnabled(false);
-            else
+            else {
                 actionFileSave->setEnabled(true);
+                actionFileRestoreSession->setEnabled(false);
+                // qDebug() << __func__ << "disabling restoreSession";
+            }
             actionFileClose->setEnabled(true);
-            actionFileExitVym->setEnabled(true);
         }
         
 
         // Undo/Redo
-        if (!m->isUndoAvailable())
+        QWidget *w = clipboardToolbar->widgetForAction(actionUndo);
+        if (!m->isUndoAvailable()) {
             actionUndo->setEnabled(false);
+            actionUndoVim->setEnabled(false);
+            w->setToolTip(tr("Undo (%1)").arg(actionUndo->shortcut().toString()));
+        } else {
+            actionUndo->setToolTip(m->lastUndoComment());
+            w->setToolTip(tr("Undo: %1 (%2)").arg(m->lastUndoComment(), actionUndo->shortcut().toString()));
+        }
 
-        if (!m->isRedoAvailable())
+        w = clipboardToolbar->widgetForAction(actionRedo);
+        if (!m->isRedoAvailable()) {
             actionRedo->setEnabled(false);
+            w->setToolTip(tr("Redo (%1)").arg(actionRedo->shortcut().toString()));
+        } else
+            w->setToolTip(tr("Redo: %1 (%2)").arg(m->lastRedoComment(), actionRedo->shortcut().toString()));
+
+        actionRepeatCommand->setEnabled(!repeatActionInt.isEmpty());
 
         // History window
         historyWindow->setWindowTitle(
@@ -7145,10 +7165,17 @@ void Main::updateActions()
             com = dest = "";
             desc = " - ";
         }
-        actionFileExportLast->setText(
-            tr("Export in last used format: %1\n%2", "status tip")
-                .arg(desc, dest));
+        QString sc = actionFileExportLast->shortcut().toString();
+        if (!sc.isEmpty()) {
+#if defined(Q_OS_MACOS)
+            sc.replace("Ctrl","Cmd");
+#endif
+            sc = " (" + sc + ")";
+        }
 
+        actionFileExportLast->setToolTip(
+            tr("Repeat last Export %1\nFormat: %2 to\n%3", "status tip")
+                .arg(sc, desc, dest));
 
         if (seltis.count() > 0) { // Tree Item selected
             if (selti) 
@@ -7178,26 +7205,51 @@ void Main::updateActions()
                 // Take care of xlinks
                 // FIXME-5 similar code in mapeditor mousePressEvent
                 bool b = false;
-                if (selbi && selbi->xlinkCount() > 0)
+                if (selbi && selbi->hasReference())
                     b = true;
 
                 branchXLinksContextMenuEdit->setEnabled(b);
                 branchXLinksContextMenuFollow->setEnabled(b);
                 branchXLinksContextMenuEdit->clear();
                 branchXLinksContextMenuFollow->clear();
+                actionFollowReference->setEnabled(b);
                 if (b) {
                     BranchItem *bi;
                     QString s;
+
+                    // Add XLinks
                     for (int i = 0; i < selbi->xlinkCount(); ++i) {
                         bi = selbi->getXLinkItemNum(i)->getPartnerBranch();
                         if (bi) {
+                            QString uid = (bi->getUuid()).toString();
                             s = bi->headingPlain();
                             if (s.length() > xLinkMenuWidth)
                                 s = s.left(xLinkMenuWidth) + "...";
                             branchXLinksContextMenuEdit->addAction(s);
-                            branchXLinksContextMenuFollow->addAction(s);
+                            branchXLinksContextMenuFollow->addAction(
+                                    tr("Branch", "Context menu to follow links") + ": " + s);
+                            branchXLinksContextMenuFollow->actions().last()->setData(
+                                    QString("XLink:%1").arg(uid));
                         }
                     }
+
+                    // Add URL
+                    s = selbi->url();
+                    if (!s.isEmpty()) {
+                        branchXLinksContextMenuFollow->addAction(
+                                tr("Url", "Context menu to follow links") + ": " + s);
+                        branchXLinksContextMenuFollow->actions().last()->setData(
+                                QString("Url:%1").arg(s));
+                    }
+
+                    // Add VymLink
+                    s = selbi->vymLink();
+                    if (!s.isEmpty()) {
+                        branchXLinksContextMenuFollow->addAction(
+                                tr("Map", "Context menu to follow links") + ": " + s);
+                        branchXLinksContextMenuFollow->actions().last()->setData(
+                                QString("VymLink:%1").arg(s));
+                    }
                 }
                 // Standard and user flags
                 if (selbi)
@@ -7273,10 +7325,12 @@ void Main::updateActions()
                 const QClipboard *clipboard = QApplication::clipboard();
                 const QMimeData *mimeData = clipboard->mimeData();
                 if (mimeData->formats().contains("application/x-vym") ||
-                    mimeData->hasImage())
-                    actionPaste->setEnabled(true);
-                else
+                    mimeData->hasImage()) {
+                    actionPasteVim->setEnabled(true);
+                } else {
                     actionPaste->setEnabled(false);
+                    actionPasteVim->setEnabled(false);
+                }
 
                 actionToggleTarget->setEnabled(true);
             } // end of BranchItem
@@ -7433,7 +7487,6 @@ QVariant Main::runScript(const QString &script)
     QJSValue vwrapper = scriptEngine->newQObject(vymWrapper);
 
     scriptEngine->globalObject().setProperty("vym", vwrapper);
-
     QJSEngine *scriptEngineOrg = scriptEngine;
     QJSValue result = scriptEngine->evaluate(script);
 
@@ -7468,9 +7521,17 @@ QVariant Main::runScript(const QString &script)
     scriptEngine->deleteLater();
     scriptEngine = nullptr;
 
+    if (exitAfterScriptInt)
+        fileExitVYM();
+
     return scriptResult;
 }
 
+QVariant Main::runScriptWithMacros(const QString &script)
+{
+    return runScript(macros.get() + script);
+}
+
 void Main::abortScript(const QJSValue::ErrorType &err, const QString &msg)
 {
     if (!scriptEngine)
@@ -7543,7 +7604,6 @@ void Main::flagChanged()
     if (me && m && me->state() != MapEditor::EditingHeading) {
         m->toggleFlagByUid(QUuid(sender()->objectName()), nullptr,
                            actionSettingsUseFlagGroups->isChecked());
-        updateActions();
     }
 }
 
@@ -7566,8 +7626,7 @@ void Main::testFunction2()
 {
     VymModel *m = currentModel();
     if (m) {
-        //m->repeatLastCommand();
-        currentMapEditor()->testFunction2();
+        //currentMapEditor()->testFunction2();
     }
 }
 
@@ -7794,11 +7853,11 @@ void Main::callMacro()
         // Function keys start at "1", not "0"
         i++;
 
-        QString s = QString("macro_%1f%2();\n").arg(modifiers).arg(i);
+        QString macro = QString("macro_%1f%2();\n").arg(modifiers).arg(i);
 
-        s += macros.get();
 
-        runScript(s);
+        runScript(macros.get() + macro);
+        setRepeatAction(macro);
     }
 }
 
@@ -8106,4 +8165,3 @@ void Main::toggleHideTmpMode()
     if (m)
         m->toggleHideTmpMode();
 }
-
index 15eee3a53479efa6c84d63b1ba5d899760ea88ab..c51bc0067aca162613cfae8a9d2ac4b882015447 100644 (file)
@@ -70,10 +70,11 @@ class Main : public QMainWindow {
     void setupAPI();
 
     /*! Helper method to clone actions later in MapEditor */
-    void cloneActionMapEditor(QAction *a, QKeySequence ks);
+    void cloneActionMapEditor(QAction *a);
 
     void setupFileActions();
     void setupEditActions();
+    void setupEditMenu();
     void setupSelectActions();
     void setupFormatActions();
     void setupViewActions();
@@ -117,7 +118,13 @@ class Main : public QMainWindow {
   private slots:
     void editorChanged();
 
+  private:
+    int backgroundZipProcesses;
+    bool closeAfterLastZipProcess;
+
   public slots:
+    void backgroundZipStarted();
+    void backgroundZipFinished();
     bool fileLoad(QString, const File::LoadMode &, const File::FileType &ftype);
     void fileLoad(const File::LoadMode &);
   private slots:
@@ -162,11 +169,23 @@ class Main : public QMainWindow {
     bool fileCloseMap(int i = -1); // Optionally pass number of tab
     void filePrint();
 
+  public:
+    bool exitAfterScript();
+    void setExitAfterScript(bool b);
+
+  private:
+    bool exitAfterScriptInt;
+    QString repeatActionInt;
+
+  public:
+    void setRepeatAction(const QString &script);
+
   public slots:
     bool fileExitVYM();
     void editUndo();
     void editRedo();
     void gotoHistoryStep(int);
+
   private slots:
     void editCopy();
     void editPaste();
@@ -222,7 +241,10 @@ class Main : public QMainWindow {
     void editUnscrollSubtree();
     void editGrowSelectionSize();
     void editShrinkSelectionSize();
+    void editRotateSubtreeCW();
+    void editRotateSubtreeCCW();
     void editResetSelectionSize();
+    void editRepeatLastAction();
     void editAddMapCenter();
     void editAddBranch();
     void editAddBranchBefore();
@@ -236,9 +258,9 @@ class Main : public QMainWindow {
     void editDeleteSelection();
     void editLoadImage();
     void editSaveImage();
-    void popupFollowXLink();
-    void editFollowXLink(QAction *);
     void editEditXLink(QAction *);
+    void popupFollowReference();
+    void followReference(QAction *);
 
   private slots:
     bool initLinkedMapsMenu(VymModel *model, QMenu *menu);
@@ -251,6 +273,8 @@ class Main : public QMainWindow {
     bool initTargetsMenu(VymModel *model, QMenu *menu);
     void editGoToTarget();
     void editMoveToTarget();
+    void editSelectFirstSibling();
+    void editSelectLastSibling();
     void editSelectPrevious();
     void editSelectNext();
     void editSelectNothing();
@@ -321,18 +345,17 @@ class Main : public QMainWindow {
     bool settingsConfluence();
     bool settingsJIRA();
 
-    void windowToggleNoteEditor();
-    void windowToggleTreeEditors();
+    void windowShowNoteEditor();
+    void switchEditors();
     void windowSetTreeEditorsVisibility(bool);
     void windowToggleTaskEditor();
-    void windowToggleSlideEditors();
+    void windowShowSlideEditors();
     void windowSetSlideEditorsVisibility(bool);
     void windowToggleScriptEditor();
     void windowToggleScriptOutput();
     void windowToggleHistory();
     void windowToggleProperty();
     void windowShowHeadingEditor();
-    void windowToggleHeadingEditor();
     void updateHistory(SimpleSettings &);
     void windowToggleAntiAlias();
     bool isAliased();
@@ -355,6 +378,7 @@ class Main : public QMainWindow {
 
     void scriptPrint(const QString &, const QString &color = "");
     QVariant runScript(const QString &);
+    QVariant runScriptWithMacros(const QString &);
     void abortScript(const QJSValue::ErrorType &err, const QString &msg);
     void abortScript(const QString &msg);
     QVariant setScriptResult(const QVariant &r);
@@ -459,6 +483,26 @@ class Main : public QMainWindow {
 
     QMenu *toolbarsMenu;
     QMenu *windowsMenu;
+
+    QMenu *branchAddContextMenu;
+    QMenu *branchGeometryContextMenu;
+    QMenu *branchHierarchyContextMenu;
+    QMenu *branchLinksContextMenu;
+    QMenu *branchRemoveContextMenu;
+    QMenu *branchXLinksContextMenuEdit;
+    QMenu *branchXLinksContextMenuFollow;   // Can also have Urls and VymLinks since 2.9.592
+    QMenu *targetsContextMenu;
+    QMenu *fileLastMapsMenu;
+    QMenu *fileImportMenu;
+    QMenu *fileExportMenu;
+
+    QMenu *fileMenu;
+    QMenu *editMenu;
+    QMenu *selectMenu;
+    QMenu *formatMenu;
+    QMenu *viewMenu;
+    QMenu *connectMenu;
+
     QToolBar *fileToolbar;
     QToolBar *clipboardToolbar;
     QToolBar *editActionsToolbar;
@@ -489,10 +533,14 @@ class Main : public QMainWindow {
     QAction *actionFileExportLast;
     QAction *actionFileExportConfluence;
     QAction *actionUndo;
+    QAction *actionUndoVim;
     QAction *actionRedo;
+    QAction *actionRepeatCommand;
     QAction *actionCopy;
+    QAction *actionCopyVim;
     QAction *actionCut;
     QAction *actionPaste;
+    QAction *actionPasteVim;
     QAction *actionMoveUp;
     QAction *actionMoveDown;
     QAction *actionMoveDownDiagonally;
@@ -501,6 +549,7 @@ class Main : public QMainWindow {
     QAction *actionSortChildren;
     QAction *actionSortBackChildren;
     QAction *actionToggleScroll;
+    QAction *actionUnscrollSubtree;
     QAction *actionExpandAll;
     QAction *actionExpandOneLevel;
     QAction *actionCollapseOneLevel;
@@ -514,6 +563,7 @@ class Main : public QMainWindow {
     QAction *actionLocalURL;
     QAction *actionHeading2URL;
     QAction *actionGetJiraDataSubtree;
+    QAction *actionSetJiraQuery;
     QAction *actionGetConfluencePageDetails;
     QAction *actionGetConfluencePageDetailsRecursively;
     QAction *actionOpenVymLink;
@@ -541,7 +591,7 @@ class Main : public QMainWindow {
     QAction *actionMapInfo;
     QAction *actionHeading;
     QAction *actionDelete;
-    QAction *actionDeleteAlt;
+    QAction *actionCutVim;
 
   public:
     QAction *actionAddMapCenter;
@@ -562,14 +612,23 @@ class Main : public QMainWindow {
     QAction *actionShrinkSelectionSize;
     QAction *actionResetSelectionSize;
 
+    QAction *actionRotateSubtreeCW;
+    QAction *actionRotateSubtreeCCW;
+
     QAction *actionToggleTarget;
     QAction *actionGoToTargetLinkedMap;
     QAction *actionGoToTarget;
     QAction *actionMoveToTarget;
+    QAction *actionSelectFirstSibling;
+    QAction *actionSelectFirstSiblingVim;
+    QAction *actionSelectLastSibling;
+    QAction *actionSelectLastSiblingVim;
     QAction *actionSelectPrevious;
     QAction *actionSelectNext;
     QAction *actionSelectNothing;
     QAction *actionFind;
+    QAction *actionFindVim;
+    QAction *actionFollowReference;
 
     QActionGroup *actionGroupQuickColors;
     QAction *actionFormatQuickColor;
@@ -615,12 +674,8 @@ class Main : public QMainWindow {
     QAction *actionViewToggleNoteEditor;
     QAction *actionViewToggleHeadingEditor;
     QAction *actionViewToggleTaskEditor;
-  
-  public: // Allow VymView class to check visibility  
-    QAction *actionViewToggleTreeEditor;
-    QAction *actionViewToggleSlideEditor;
-
-  private:  
+    QAction *actionViewSwitchEditors;
+    QAction *actionViewShowSlideEditors;
     QAction *actionViewToggleScriptEditor;
     QAction *actionViewToggleScriptOutput;
     QAction *actionViewToggleHistoryWindow;
@@ -631,7 +686,6 @@ class Main : public QMainWindow {
 
     QAction *actionConnectGetConfluenceUser;
     QAction *actionSettingsAutoSelectNewBranch;
-    QAction *actionSettingsAutoSelectText;
     QAction *actionSettingsUseFlagGroups;
     QAction *actionSettingsUseHideExport;
     QAction *actionSettingsToggleAutosave;
index e47317938cc19ac918336e24811598c7c6ef2e47..26e7c99f8334c109ef294f6295ecaab74636498b 100644 (file)
@@ -22,6 +22,12 @@ template <typename T> T & ConfigList<T>::operator[](int i) {
 }
 
 template <typename T> T ConfigList<T>::tryAt(int i) {
+    if (qlist.isEmpty()) {
+        qWarning() << "Empty ConfigList in MapDesign!";
+        T t;
+        return t;
+    }
+
     if (i >= qlist.count())
         return qlist.last();
     else
@@ -139,26 +145,29 @@ void MapDesign::init()
         QPalette palette = qApp->palette();
         backgroundColorInt = QColor(palette.color(QPalette::Base));
 
+        headingColors << QColor(Qt::white);
+
         innerFramePenColors << QColor(Qt::white);
         innerFrameBrushColors << QColor(85, 85, 127);
 
         innerFramePenColors << QColor(Qt::blue);
         innerFrameBrushColors << QColor(25, 25, 127);
 
-        outerFramePenColors << QColor(Qt::green);
-        outerFramePenColors << QColor(Qt::red);
-        outerFramePenColors << QColor(Qt::green);
-        outerFramePenColors << QColor(Qt::red);
-        outerFrameBrushColors << QColor(85, 85, 127);
-        outerFrameBrushColors << QColor(25, 25, 117);
-        outerFrameBrushColors << QColor(85, 85, 127);
-        outerFrameBrushColors << QColor(25, 25, 117);
+        outerFramePenColors << QColor(Qt::blue);
+        outerFrameBrushColors << QColor(25, 25, 127);
     } else {
         backgroundColorInt = QColor(Qt::white);
+
+        headingColors << QColor(Qt::black);
+
         innerFramePenColors << QColor(Qt::black);
         innerFrameBrushColors << QColor(Qt::white);
-        outerFramePenColors << QColor(Qt::green);
-        outerFrameBrushColors << QColor(85, 85, 127);
+
+        innerFramePenColors << QColor(Qt::black);
+        innerFrameBrushColors << QColor("#dadada");
+
+        outerFramePenColors << QColor(Qt::black);
+        outerFrameBrushColors << QColor(Qt::white);
     }
 
     // Font
@@ -203,9 +212,6 @@ void MapDesign::init()
     headingColorHints << MapDesign::InheritedColor;        // Use color of parent
     headingColorUpdateWhenRelinking << false;
 
-    headingColors << QColor(Qt::white);
-    headingColors << QColor(Qt::green);
-
     // Frames
     innerFrameTypes << FrameContainer::RoundedRectangle;
     innerFrameTypes << FrameContainer::Rectangle;
index e2ef231fba58840fea31c6c9c4fa61d06a136113..ee3993c726d6758601fbbddb8d17fc2534923a69 100644 (file)
@@ -37,7 +37,7 @@ extern Settings settings;
 
 extern QTextStream vout;
 
-extern QString editorFocusStyle;
+extern QString editorFocusInStyle;
 
 extern FlagRowMaster *systemFlagsMaster;
 
@@ -50,7 +50,7 @@ MapEditor::MapEditor(VymModel *vm)
     QString shortcutScope = tr("Map Editor", "Shortcut scope");
     mapScene = new QGraphicsScene(nullptr);
     mapScene->setBackgroundBrush(QBrush(Qt::white, Qt::SolidPattern));
-    //mapScene->setItemIndexMethod(QGraphicsScene::NoIndex);  // FIXME-3 Avoiding crashes...
+    //mapScene->setItemIndexMethod(QGraphicsScene::NoIndex);  // FIXME-4 Avoiding crashes...
                                                             // Alternatively call removeFromIndex() in destructor
                                                             // or maybe also prepareGeometryChange()
 
@@ -103,7 +103,7 @@ MapEditor::MapEditor(VymModel *vm)
 
     selectionMode = AutoSelection;
 
-    setStyleSheet("QGraphicsView:focus {" + editorFocusStyle + "}");
+    setStyleSheet("QGraphicsView:focus {" + editorFocusInStyle + "}");
 
     // Create bitmap cursors, platform dependant
     HandOpenCursor = QCursor(QPixmap(":/mode-move-view.png"), 1, 1);
@@ -158,26 +158,24 @@ MapEditor::MapEditor(VymModel *vm)
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(cursorLeft()));
 
-    a = new QAction("Select child branch", this);
+    a = new QAction("Select child or parent branch", this);
     a->setShortcut(Qt::Key_Right);
     //  a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(cursorRight()));
 
-    a = new QAction("Select first branch", this);
-    a->setShortcut(Qt::Key_Home);
-    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    addAction(a);
-    connect(a, SIGNAL(triggered()), this, SLOT(cursorFirst()));
-
-    a = new QAction("Select last branch", this);
-    a->setShortcut(Qt::Key_End);
-    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    addAction(a);
-    connect(a, SIGNAL(triggered()), this, SLOT(cursorLast()));
-
     // Action to embed LineEdit for heading in Scene
-    lineEdit = nullptr;
+    lineEdit = new QLineEdit;
+    lineEdit->setCursor(Qt::IBeamCursor);
+    editHeadingCancelAction = new QAction("editHeadingCancelAction", lineEdit);
+    editHeadingCancelAction->setShortcut(Qt::Key_Escape);
+    //editHeadingCancelAction->setShortcutContext(Qt::ApplicationShortcut);
+    lineEdit->addAction(editHeadingCancelAction);
+    proxyWidget = mapScene->addWidget(lineEdit);
+    connect( editHeadingCancelAction, SIGNAL(triggered()), this, SLOT(editHeadingCanceled()));
+    lineEdit->show();
+    lineEdit->hide();
+
 
     a = new QAction(tr("Edit heading", "MapEditor"), this);
     a->setShortcut(Qt::Key_Return); // Edit heading
@@ -195,12 +193,16 @@ MapEditor::MapEditor(VymModel *vm)
     vPan = QPointF();
     connect(panningTimer, SIGNAL(timeout()), this, SLOT(panView()));
 
-    // Clone actions defined in MainWindow
-    foreach (QAction *qa, mainWindow->mapEditorActions) {
+    // Clone global actions defined in MainWindow   // FIXME-3 Problematic, if shortcuts could change later
+                                                    // Maybe control "duplicate" actions from switchboard
+                                                    // using scopes?
+                                                    // Use scope like "MapEditors" for TreeEditor,
+                                                    // MainWindow and MapEditor?
+    foreach (auto a_org, mainWindow->mapEditorActions) {
         a = new QAction(this);
-        a->setShortcut(qa->shortcut());
-        a->setShortcutContext(qa->shortcutContext());
-        connect(a, SIGNAL(triggered()), qa, SLOT(trigger()));
+        a->setShortcut(a_org->shortcut());
+        a->setShortcutContext(a_org->shortcutContext());
+        connect(a, SIGNAL(triggered()), a_org, SLOT(trigger()));
         addAction(a);
     }
 
@@ -703,18 +705,24 @@ void MapEditor::setViewCenterTarget(const QPointF &p, const qreal &zft,
 
 void MapEditor::setViewCenterTarget()
 {
-    qDebug() << __func__;
-    MapItem *selti = (MapItem *)(model->getSelectedItem());
-    if (selti) {
+    // qDebug() << __func__;
+    QList <TreeItem*> seltis = model->getSelectedItems();
+    QPointF p;
+    int n = 0;
+    foreach (TreeItem *selti, seltis) {
         Container *c = nullptr;
         if (selti->hasTypeBranch()) 
             c = ((BranchItem*)selti)->getBranchContainer()->getHeadingContainer();
         else if (selti->hasTypeImage())
             c = ((ImageItem*)selti)->getImageContainer();
-        else
-            return;
-        setViewCenterTarget(c->mapToScene(c->rect().center()), 1, 0);
+        if (c) {
+            n++;
+            p = p + c->mapToScene(c->rect().center());
+        }
     }
+
+    if (n > 0)
+        setViewCenterTarget( p / n, 1, 0);
 }
 
 QPointF MapEditor::getViewCenterTarget() { return viewCenterTarget; }
@@ -1172,18 +1180,18 @@ bool MapEditor::isContainerCloserInDirection(Container *c1, Container *c2, const
     return false;
 }
 
-TreeItem* MapEditor::getItemInDirection(TreeItem *ti, RadarDirection radarDir)
+TreeItem* MapEditor::getItemInDirection(TreeItem *ti, RadarDirection radarDir)  // FIXME-2 setting to enforce hirarchical mode... #161
 {
     SelectionMode selMode = currentSelectionMode(ti);
 
-    //qDebug() << "ME::getItemInDir  selMode=" << selMode;
+    // qDebug() << "ME::getItemInDir  selMode=" << selMode;
     if (selMode == GeometricSelection)
         return getItemFromGeometry(ti, radarDir);
 
     if (selMode == OrgChartSelection)
         return getItemFromOrgChart(ti, radarDir);
 
-    return getItemFromClassicMap(ti, radarDir);
+    return getItemFromHirarchy(ti, radarDir);
 }
 
 TreeItem* MapEditor::getItemFromGeometry(TreeItem *ti, RadarDirection radarDir) // FIXME-3 does not really work
@@ -1259,14 +1267,14 @@ TreeItem* MapEditor::getItemFromOrgChart(TreeItem *ti, RadarDirection radarDir)
     else if (radarDir == DownDirection)
         return bi->getLastSelectedBranch();
     else if (radarDir == LeftDirection)
-        return getItemFromClassicMap(ti, UpDirection);
+        return getItemFromHirarchy(ti, UpDirection);
     else if (radarDir == RightDirection)
-        return getItemFromClassicMap(ti, DownDirection);
+        return getItemFromHirarchy(ti, DownDirection);
 
     return nullptr;
 }
 
-TreeItem* MapEditor::getItemFromClassicMap(TreeItem *selti, RadarDirection radarDir)
+TreeItem* MapEditor::getItemFromHirarchy(TreeItem *selti, RadarDirection radarDir)
 {
     if (!selti)
         return nullptr;
@@ -1553,10 +1561,6 @@ void MapEditor::cursorRight()
     }
 }
 
-void MapEditor::cursorFirst() { model->selectFirstBranch(); }  // FIXME-3 adapt for images and container layouts
-
-void MapEditor::cursorLast() { model->selectLastBranch(); }  // FIXME-3 adapt for images and container layouts
-
 void MapEditor::editHeading(BranchItem *selbi)
 {
     if (editorState == EditingHeading) {
@@ -1568,17 +1572,21 @@ void MapEditor::editHeading(BranchItem *selbi)
     if (selbi) {
         VymText heading = selbi->heading();
         if (heading.isRichText() || selbi->headingPlain().contains("\n")) {
+            // RichText heading is edited in its own editor, continue there
             mainWindow->windowShowHeadingEditor();
             ensureSelectionVisibleAnimated();
             return;
         }
         model->setSelectionBlocked(true);
 
-        lineEdit = new QLineEdit;
-        QGraphicsProxyWidget *proxyWidget = mapScene->addWidget(lineEdit);
-        // FIXME-3-FT get total rotation XXX for BC in scene and do "proxyWidget->setRotation(XXX);
-        lineEdit->setCursor(Qt::IBeamCursor);
+        // FIXME-3-FT get total rotation a for BC in scene and do "proxyWidget->setRotation(a);
+
+        // Make sure lineEdit is above everything else, including selection box
+        mapScene->removeItem(proxyWidget);
+        mapScene->addItem(proxyWidget);
+
         lineEdit->setCursorPosition(1);
+        lineEdit->show();
         lineEdit->grabKeyboard();
 
 #if defined(Q_OS_WINDOWS)
@@ -1594,11 +1602,11 @@ void MapEditor::editHeading(BranchItem *selbi)
 
         BranchContainer *bc = selbi->getBranchContainer();
         if (bc->getOrientation() == BranchContainer::RightOfParent) {
-            tl = bc->headingRect().topLeft();
+            tl = bc->headingSceneRect().topLeft();
             br = tl + QPointF(w, h);
         }
         else {
-            br = bc->headingRect().bottomRight();
+            br = bc->headingSceneRect().bottomRight();
             tl = br - QPointF(w, h);
         }
         // Qt bug when using QProxyWdiget in scaled QGraphicsView
@@ -1627,29 +1635,40 @@ void MapEditor::editHeading(BranchItem *selbi)
     }
 }
 
+void MapEditor::editHeadingCanceled()
+{
+    hideLineEdit();
+    model->saveStateCancelScript();
+}
+
 void MapEditor::editHeadingFinished()
 {
     if (editorState != EditingHeading || !lineEdit ) {
         qWarning() << "ME::editHeadingFinished not editing heading!";
     } else {
-        lineEdit->clearFocus();
-        lineEdit->releaseKeyboard();
         QString s = lineEdit->text();
         s.replace(QRegularExpression("\\n"), " "); // Don't paste newline chars
         if (s.length() == 0)
             s = " "; // Don't allow empty lines, which would screw up drawing
         model->setHeadingPlainText(s);
-        delete (lineEdit);
-        lineEdit = nullptr;
-
-        // Maybe reselect previous branch
-        mainWindow->editHeadingFinished(model);
 
         // Autolayout to avoid overlapping branches with longer headings
         if (settings.value("/mainwindow/autoLayout/use", "true") == "true")
             autoLayout();
     }
 
+    hideLineEdit();
+}
+
+void MapEditor::hideLineEdit()
+{
+    lineEdit->clearFocus();
+    lineEdit->releaseKeyboard();
+    lineEdit->hide();
+
+    // Maybe reselect previous branch
+    mainWindow->editHeadingFinished(model);
+
     model->setSelectionBlocked(false);
     setState(Neutral);
 }
@@ -1924,7 +1943,7 @@ void MapEditor::mousePressEvent(QMouseEvent *e) // FIXME-3  Drop down dialog, if
                         model->getUrl(),
                         e->modifiers() & Qt::AltModifier);
             } else if (sysFlagName == "system-note")
-                mainWindow->windowToggleNoteEditor();
+                mainWindow->windowShowNoteEditor();
             else if (sysFlagName == "hideInExport")
                 model->toggleHideExport();
             else if (sysFlagName.startsWith("system-task-"))
@@ -2217,7 +2236,7 @@ void MapEditor::moveObject(QMouseEvent *e, const QPointF &p_event)
             // When temporary linking e.g. to MapCenter, position on a circle
             // bigger than ornamensContainer
 
-            qreal radius = 100 + targetBranchContainer->ornamentsRect().width();
+            qreal radius = 100 + targetBranchContainer->ornamentsSceneRect().width();
 
             QPointF center_sp = targetBranchContainer->getHeadingContainer()->mapToScene(QPointF(0,0));
             qreal a = getAngle(p_event - center_sp);
@@ -2620,9 +2639,16 @@ void MapEditor::wheelEvent(QWheelEvent *e)
     }
 }
 
-void MapEditor::focusOutEvent(QFocusEvent *)
+void MapEditor::focusInEvent(QFocusEvent *e)
+{
+    //qDebug() << "ME::focusInEvent" << e->reason();
+    setFrameStyle(QFrame::Box);
+}
+
+void MapEditor::focusOutEvent(QFocusEvent *e)
 {
-    // qDebug()<<"ME::focusOutEvent"<<e->reason();
+    //qDebug() << "ME::focusOutEvent" << e->reason();
+    setFrameStyle(QFrame::NoFrame);
     if (editorState == EditingHeading)
         editHeadingFinished();
 }
@@ -2812,44 +2838,35 @@ MapEditor::SelectionMode MapEditor::currentSelectionMode(TreeItem *selti)
     // Selections should consider logical relations, e.g. siblings and parents
     // but also geometric. Return the most appropriate mode depending on 
     // rotation of view and layout of selected item.
-    if (!selti) {
-        // qDebug() << "ME::selectionMode: Classic";
-        return ClassicSelection;
-    }
-
-    if (rotationInt != 0) {
-        // qDebug() << "ME::selectionMode: Geometric";
-        return GeometricSelection;
-    }
 
-    Container *c = nullptr;
-    if (selti->hasTypeBranch()) {
-        BranchContainer *bc = ((BranchItem*)selti)->getBranchContainer();
-        if (bc->branchesContainerLayout() == Container::Horizontal) {
-            // qDebug() << "ME::selectionMode: OrgChart";
-            return OrgChartSelection;
-        }
-        if (bc->isFloating()) {
-            // qDebug() << "ME::selectionMode: Geometric";
-            return GeometricSelection;
-        }
-    } else if (selti->hasTypeImage()) {
-        // qDebug() << "ME::selectionMode: Geometric";
-        return GeometricSelection;
-    }
+    SelectionMode sm = HirarchicalSelection;
+    if (selti) {
 
-    if (!c) {
-        // qDebug() << "ME::selectionMode: Classic";
-        return ClassicSelection;
-    }
+        if (rotationInt != 0) {
+            // qDebug() << "ME::selectionMode: rotated";
+            sm = GeometricSelection;
+        } else {
+            if (selti->hasTypeBranch()) {
+                BranchContainer *bc = ((BranchItem*)selti)->getBranchContainer();
+                if (bc->branchesContainerLayout() == Container::Horizontal) {
+                    // qDebug() << "ME::selectionMode: OrgChart";
+                    sm = OrgChartSelection;
+                } else if (bc->isFloating()) {
+                    // qDebug() << "ME::selectionMode: Geometric";
+                    sm =  GeometricSelection;
+                }
 
-    if (c->isFloating()) {
-        // qDebug() << "ME::selectionMode: Geometric";
-        return GeometricSelection;
-    }
+                // Missing: !Horizontal and !floating
+            } else if (selti->hasTypeImage()) {
+                // qDebug() << "ME::selectionMode: Geometric";
+                sm = GeometricSelection;
+            }
+        } // view not rotated
+    } // selti != nullptr
 
-    qDebug() << "ME::selectionMode: Classic";
-    return ClassicSelection;
+    if (debug)
+        qDebug() << "ME::currentSelectionMode: " << sm;
+    return sm;
 }
 
 void MapEditor::updateData(const QModelIndex &sel)
index 24f8bfc6ad2fbe706cd7d92a6ab80a90a4c2f261..a94f78636854367c1d9302efda11e9bd9302169f 100644 (file)
@@ -177,7 +177,7 @@ class MapEditor : public QGraphicsView {
     TreeItem* getItemInDirection(TreeItem *ti, RadarDirection);
     TreeItem* getItemFromGeometry(TreeItem *ti, RadarDirection);
     TreeItem* getItemFromOrgChart(TreeItem *ti, RadarDirection);
-    TreeItem* getItemFromClassicMap(TreeItem *ti, RadarDirection);
+    TreeItem* getItemFromHirarchy(TreeItem *ti, RadarDirection);
 
     TreeItem* getItemDirectAbove(TreeItem *ti);
     TreeItem* getItemDirectBelow( TreeItem *ti);
@@ -195,13 +195,15 @@ class MapEditor : public QGraphicsView {
     void cursorDownToggleSelection();
     void cursorLeft();
     void cursorRight();
-    void cursorFirst();
-    void cursorLast();
     void editHeading(BranchItem *selbi = nullptr);
+    void editHeadingCanceled();
     void editHeadingFinished();
 
   private:
+    void hideLineEdit();
     QLineEdit *lineEdit;
+    QAction *editHeadingCancelAction;
+    QGraphicsProxyWidget *proxyWidget;
 
   private:
     void contextMenuEvent(QContextMenuEvent *e);
@@ -214,6 +216,7 @@ class MapEditor : public QGraphicsView {
     void mouseReleaseEvent(QMouseEvent *);
     void mouseDoubleClickEvent(QMouseEvent *);
     void wheelEvent(QWheelEvent *);
+    void focusInEvent(QFocusEvent *);
     void focusOutEvent(QFocusEvent *);
     void resizeEvent(QResizeEvent *);
 
@@ -269,7 +272,7 @@ class MapEditor : public QGraphicsView {
   public:
     enum SelectionMode {
         AutoSelection,
-        ClassicSelection,
+        HirarchicalSelection,   // legacy selection type (default)
         OrgChartSelection,
         GeometricSelection
     };
index 07e65daec271e7cab5a071a214086553fd9d81ec..cc229adad4c816be3917f14039d47bfd76a135fb 100644 (file)
@@ -247,6 +247,14 @@ bool versionLowerThanVym(const QString &v)
         return versionLowerOrEqualThanVym(v);
 }
 
+QString underline(const QString &text, const QString &line)
+{
+    QString r = text + "\n";
+    for (int j = 0; j < text.length(); j++)
+        r += line;
+    return r + "\n\n";
+}
+
 bool versionLowerOrEqualThanVym(const QString &v)
 {
     // returns true, if Version v <=  VYM_VERSION
index e2c15b54d76362f958cfdf11ffbd98101d28bef5..c22dbe1e2f3cbf41c1352fd5d3b6c585256b2cab 100644 (file)
@@ -42,6 +42,8 @@ QString pointToString(const QPointF &p);
 
 void centerDialog(QDialog *dia);
 
+QString underline(const QString &text, const QString &line);
+
 bool versionLowerThanVym(const QString &);
 bool versionLowerOrEqualThanVym(const QString &);
 bool versionLowerOrEqual(const QString &, const QString &);
index b4f070fbf17bd92921642645688efd743e3e51aa..4b9318c1bffa22b55ccf14ca73b6e04e7e3300e3 100644 (file)
@@ -10,6 +10,8 @@ extern QString vymName;
 
 NoteEditor::NoteEditor(const QString &eName) : TextEditor(eName)
 {
+    editorName = eName;
+
     setWindowTitle("");
 
     menuBar()->show();
index 63f5d94a5d13dadae5ca032907ab2f2dcc212f34..45a61513908d60eb917d025abb39813a49b0c0e2 100644 (file)
@@ -5,18 +5,20 @@
 
 #include "shortcuts.h"
 
+#include "misc.h"
+
 /////////////////////////////////////////////////////////////////
 // KeySwitch
 /////////////////////////////////////////////////////////////////
-KeySwitch::KeySwitch(const QString &kIdentifier, const QString &kName,
-                     const QString &kGroup, const QString &kTag,
-                     const QKeySequence &kseq)
+KeySwitch::KeySwitch(const QString &identifier,
+                     const QString &scope,
+                     const QString &tag,
+                     QAction* action)
 {
-    identifier = kIdentifier;
-    name = kName;
-    group = kGroup;
-    tag = kTag;
-    keySequence = kseq;
+    identifierInt = identifier;
+    scopeInt = scope;
+    tagInt = tag;
+    actionInt = action;
 }
 
 /////////////////////////////////////////////////////////////////
@@ -24,64 +26,85 @@ KeySwitch::KeySwitch(const QString &kIdentifier, const QString &kName,
 /////////////////////////////////////////////////////////////////
 Switchboard::Switchboard() {}
 
-void Switchboard::addGroup(QString gIdentifier, QString gName)
+void Switchboard::addScope(QString scopeIdentifier, QString scopeName)
 {
-    if (groups.contains(gIdentifier)) {
-        qDebug() << "Warning switchboard: Shortcut group " << gIdentifier
+    if (scopesMap.contains(scopeIdentifier)) {
+        qDebug() << "Warning switchboard: Shortcut scope " << scopeIdentifier
                  << " already exists";
         return;
     }
-    groups.insert(gIdentifier, gName);
+    scopesMap.insert(scopeIdentifier, scopeName);
 }
 
-void Switchboard::addSwitch(QString identifier, QString scope, QAction *action,
-                            QString tag)
+void Switchboard::addAction(QAction *action,
+        const QString &identifier,
+        const QString &scope,
+        const QString &tag)
 {
-    if (!switches.contains(identifier)) {
-        KeySwitch ksw(identifier, action->text(), scope, tag,
-                      action->shortcut());
-        switches.insert(scope, ksw);
+    addAction(action, identifier, QKeySequence(), scope, tag);
+}
+
+void Switchboard::addAction(QAction *action,
+        const QString &identifier,
+        QKeySequence ks,
+        const QString &scope,
+        const QString &tag)
+{
+    action->setShortcut(ks);
+    action->setShortcutVisibleInContextMenu(true); // FIXME-3 should obsolete setting in MainWindow::setupContextMenus()
+
+    if (!switchesMap.contains(identifier)) {
+        if (!action->shortcut().toString().isEmpty()) {
+            // Add shortcut to tooltip
+            action->setToolTip(action->toolTip() + 
+                    QString(" (%1)").arg(action->shortcut().toString()));
+        }
+        KeySwitch ksw(identifier, scope, tag, action);
+        switchesMap.insert(scope, ksw);
     }
     else
         qDebug()
-            << "Warning switchboard::addSwitch warning: Existing idenifier "
+            << "Warning switchboard::addAction warning: Existing idenifier "
             << identifier;
 }
 
+
 QString Switchboard::getASCII()
 {
     QString s;
-    QString g;
-    foreach (g, switches.uniqueKeys()) {
-        s += "Scope " + g + ":\n";
-        QList<KeySwitch> values = switches.values(g);
-        for (int i = 0; i < values.size(); ++i) {
-            QString desc = values.at(i).name;
-            QString sc = values.at(i).keySequence.toString();
-            if (!sc.isEmpty()) {
-                desc = desc.remove('&');
-                desc = desc.remove("...");
-                s += QString(" %1: %2\n").arg(sc, 12).arg(desc);
-            }
+    QString scope;
+    foreach (scope, switchesMap.uniqueKeys()) {
+        s += underline(scope, "=");
+
+        QStringList tagsInScope;
+        foreach (auto ksw, switchesMap.values(scope)) {
+            if (!tagsInScope.contains(ksw.tagInt))
+                tagsInScope << ksw.tagInt;
         }
-        s += "\n";
-    }
 
-    /*
-    foreach (g, actions.uniqueKeys())
-    {
-        s += g +"\n";
-        QList <QAction*> values=actions.values(g);
-        for (int i=0;i<values.size();++i)
-        {
-            QString desc=values.at(i)->text();
-            QString   sc=values.at(i)->shortcut().toString();
-            desc=desc.remove('&');
-            desc=desc.remove("...");
-            s+= QString(" %1: %2\n").arg(sc,12).arg(desc);
+        foreach (auto tag, tagsInScope) {
+            s += underline(tag, "-");
+            foreach (auto ksw, switchesMap.values(scope)) {
+                if (ksw.tagInt == tag) {
+                    QString desc = ksw.actionInt->text();
+                    QString sc = ksw.actionInt->shortcut().toString();
+                    if (!sc.isEmpty()) {
+#if defined(Q_OS_MACOS)
+                        sc.replace("Ctrl","Cmd");
+#endif
+                    
+                        desc = desc.remove('&');
+                        desc = desc.remove("...");
+                        s += QString(" %1: %2\n").arg(sc, 12).arg(desc);
+                    }
+                }
+            }
+            if (tag != tagsInScope.last())
+                s += "\n";
         }
+        if (scope != switchesMap.uniqueKeys().last())
+            s += "\n";
     }
-    */
     return s;
 }
 
@@ -89,10 +112,11 @@ void Switchboard::printASCII() { std::cout << qPrintable(getASCII()); }
 
 void Switchboard::printLaTeX()
 {
+    /*
     QString g;
-    foreach (g, actions.uniqueKeys()) {
+    foreach (g, actionsMap.uniqueKeys()) {
         std::cout << "Group: " << qPrintable(g) << "\\\\ \\hline" << std::endl;
-        QList<QAction *> values = actions.values(g);
+        QList<QAction *> values = actionsMap.values(g);
         for (int i = 0; i < values.size(); ++i)
             if (!values.at(i)->shortcut().toString().isEmpty()) {
                 QString desc = values.at(i)->text();
@@ -104,4 +128,5 @@ void Switchboard::printLaTeX()
             }
         std::cout << std::endl;
     }
+    */
 }
index 32f9d0d1c50dc997cae782d47e8348bf273af96d..c10b2acf8316e28b34c6ff5efae6c412f2d020a7 100644 (file)
@@ -8,32 +8,31 @@
 class KeySwitch {
   public:
     KeySwitch(
-        const QString &kIdentifier, //! Unique identifier (still unused)
-        const QString &kName,      //! text saved in related action (translated)
-        const QString &kGroup,     //! Scope
-        const QString &kTag,       //! Tag, used for listing related shortcuts
-        const QKeySequence &kseq); //! Keysequence from action
-    QString group;
-    QString name;
-    QString identifier;
-    QString tag;
+        const QString &identifier,  //! Unique identifier (still unused)
+        const QString &scope,       //! Scope
+        const QString &tag,         //! Tag, used for listing related shortcuts
+        QAction* action);     //! Action 
+    QString scopeInt;
+    QString nameInt;
+    QString identifierInt;
+    QString tagInt;
     QKeySequence keySequence;
+    QAction *actionInt;
 };
 
 class Switchboard {
   public:
     Switchboard();
-    void addGroup(QString gIdentifier, QString gName);
-    void addSwitch(QString identifier, QString scope, QAction *a, QString tag);
+    void addScope(QString gIdentifier, QString gName);
+    void addAction(QAction *a, const QString &identifier, const QString &scope, const QString &tag);
+    void addAction(QAction *a, const QString &identifier, QKeySequence, const QString &scope, const QString &tag);
     QString getASCII();
     void printASCII();
     void printLaTeX();
 
   protected:
-    QMultiMap<QString, QAction *> actions;
-    QMultiMap<QString, KeySwitch> switches;
-    QMap<QString, QString> groups;
-    QStringList tags;
+    QMultiMap<QString, KeySwitch> switchesMap;  // Switches grouped by scope
+    QMap<QString, QString> scopesMap;           // Hash with translated names of scopes
 };
 
 #endif
index f6798ceadac3e17352bcb1ac8425c847b43a4898..c761b84e87a989c40988cae4235cf05c2837fadf 100644 (file)
@@ -12,7 +12,7 @@
 extern Main *mainWindow;
 extern SlideEditor *slideEditor;
 
-extern QString editorFocusStyle;
+extern QString editorFocusInStyle;
 
 SlideEditor::SlideEditor(VymModel *m)
 {
@@ -27,7 +27,7 @@ SlideEditor::SlideEditor(VymModel *m)
 
     slideModel->setSelectionModel(view->selectionModel());
 
-    view->setStyleSheet("QTreeView:focus {" + editorFocusStyle + "}");
+    view->setStyleSheet("QTreeView:focus {" + editorFocusInStyle + "}");
 
     // Create ControlWidget
     slideControl = new SlideControlWidget(this);
@@ -58,11 +58,28 @@ SlideEditor::SlideEditor(VymModel *m)
             SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
             SLOT(updateSelection(QItemSelection, QItemSelection)));
 
+    QAction *a = new QAction(this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    a->setShortcut(Qt::CTRL | Qt::Key_D);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(closeWindow()));
+
+    a = new QAction(this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    a->setShortcut(Qt::Key_Escape);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), mainWindow, SLOT(escapePressed()));
+
     //    connect (resultsModel, SIGNAL(layoutChanged() ), view, SLOT
     //    (expandAll() ));
 }
 
 void SlideEditor::closeEvent(QCloseEvent *event)
+{
+    closeWindow();
+}
+
+void SlideEditor::closeWindow()
 {
     mainWindow->windowSetSlideEditorsVisibility(false);
 }
index 110ce036b7c3767357a16df530217f2dbb6b7505..c8e87e662d75e36b53bbae2623bf7f33ab131d32 100644 (file)
@@ -19,6 +19,7 @@ class SlideEditor : public QWidget {
     virtual void closeEvent(QCloseEvent *event);
 
   public slots:
+    void closeWindow();  
     void previousSlide();
     void nextSlide();
     void addSlide();
index 18b1caafa22acefb579661ce6a05a9dd0fec1ae8..f9051866d3048fb68d4a21946a455e641e2cb9c8 100644 (file)
@@ -6,6 +6,8 @@
 #include "taskmodel.h"
 #include "vymmodel.h"
 
+extern QString flagsPath;
+
 Task::Task(TaskModel *tm)
 {
     //    qDebug()<<"Constr. Task";
@@ -82,7 +84,7 @@ QString Task::getStatusString()
     return "Undefined";
 }
 
-QString Task::getIconString()
+QString Task::iconString()
 {
     QString s;
     switch (status) {
index 49e4184a0ab84fc1c10283d2e35c944f9a988227..f7c16f14a50fbec13f15926cbf4aba1a47363641 100644 (file)
@@ -24,8 +24,7 @@ class Task : public XMLObj {
     void setStatus(Status ts);
     Status getStatus();
     QString getStatusString();
-    QString
-    getIconString(); //! Used to create icons in task list and flags in mapview
+    QString iconString();   //! Used to create icons in task list and flags in mapview
     void setAwake(const QString &s);
     void setAwake(Awake a);
     Awake getAwake();
index 1e4cc8ef129804be65549b4a28fefe64af8a37e8..4d30d31182df7548b30d3a3bde15e94f4187a613 100644 (file)
@@ -24,7 +24,7 @@ extern Settings settings;
 extern QMenu *taskContextMenu;
 extern TaskModel *taskModel;
 
-extern QString editorFocusStyle;
+extern QString editorFocusInStyle;
 
 TaskEditor::TaskEditor(QWidget *)
 {
@@ -188,7 +188,8 @@ TaskEditor::TaskEditor(QWidget *)
 
     view->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
 
-    view->setStyleSheet("QTableView:focus {" + editorFocusStyle + "}");
+    QString selected = "QTableView::item:selected {border-color: #00ff00; border-width: 3px; background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #CCCC0A, stop: 1 #96960A);}";
+    view->setStyleSheet("QTableView:focus {" + editorFocusInStyle + "}" + selected);
 
     updateColumnLayout();
 }
@@ -424,12 +425,6 @@ void TaskEditor::selectionChanged(const QItemSelection &selected,
                 m->select(bi);
             if (m != mainWindow->currentModel())
                 mainWindow->gotoModel(m);
-            /* view->setStyleSheet( // FIXME-5 this resets column widths on Windows...
-                "QTableView {selection-background-color: " +
-                m->getSelectionBrushColor().name() +
-                "; selection-color:" + bi->headingColor().name() + "}" +
-                "QTableView:focus {" + editorFocusStyle + "}");
-            */
         }
     }
 }
index 0f2bfc80d10386d6dc9aa3d24a3815ff1d4673b0..c5b6b9f34a9e84016d2d7b4a438c4ab4ec5343c5 100644 (file)
@@ -133,7 +133,7 @@ QVariant TaskModel::data(const QModelIndex &index, int role) const
         }
     }
     else if (role == Qt::DecorationRole && index.column() == 2) {
-        QString s = t->getIconString();
+        QString s = t->iconString();
         if (s == "task-new")
             return task_new_icon;
         else if (s == "task-new-morning")
index bfa2aa4d7f50b8ddb65d5848aa1e53a2899b2503..196be3112ce7f15e53edd2513bdc99198a72c75d 100644 (file)
@@ -30,6 +30,10 @@ extern QColor vymForegroundColor;
 extern QColor vymBaseColor;
 extern QAction *actionViewToggleNoteEditor;
 
+extern QString editorFocusInStyle;
+extern QString editorFocusOutStyle;
+extern QString toolBarStyle;
+
 extern QString vymName;
 
 extern Switchboard switchboard;
@@ -57,6 +61,14 @@ TextEditor::TextEditor(const QString eName)   // FEATURE #137 insert images with
     connect(editor, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)), this,
             SLOT(formatChanged(const QTextCharFormat &)));
 
+
+    QAction *a = new QAction("Close window", this);
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    a->setShortcut(Qt::CTRL | Qt::Key_D);
+    connect(a, SIGNAL(triggered()), this, SLOT(closeWindow()));
+    //fileMenu->addAction(a);
+    editor->addAction(a);
+
     // Load settings
     init (eName);
     setWindowIcon(QPixmap(":/vym-editor.png"));
@@ -318,15 +330,15 @@ void TextEditor::setFocus() { editor->setFocus(); }
 void TextEditor::setupFileActions()
 {
     QToolBar *tb = addToolBar(tr("Note Actions"));
+    tb->setStyleSheet(toolBarStyle);
     tb->setObjectName("noteEditorFileActions");
     QMenu *fileMenu = menuBar()->addMenu(tr("&Note", "Menubar"));
 
-    QString tag = tr("Texteditor", "Shortcuts");
+    QString tag = tr("File actions", "TextEditor shortcut groups");
     QAction *a;
     a = new QAction(QPixmap(QString(":/document-open-%1").arg(iconTheme)), tr("&Import..."), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_O);
     a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textLoad", shortcutScope, a, tag);
+    switchboard.addAction(a, "textLoad", Qt::CTRL | Qt::Key_O, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textLoad()));
     tb->addAction(a);
     fileMenu->addAction(a);
@@ -334,9 +346,8 @@ void TextEditor::setupFileActions()
 
     fileMenu->addSeparator();
     a = new QAction(QPixmap(QString(":/document-export-%1").arg(iconTheme)), tr("&Export..."), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_S);
     a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textSave", shortcutScope, a, tag);
+    switchboard.addAction(a, "textSave", Qt::CTRL | Qt::Key_S, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textExport()));
     tb->addAction(a);
     fileMenu->addAction(a);
@@ -345,7 +356,7 @@ void TextEditor::setupFileActions()
     actionFileExport = a;
 
     a = new QAction(tr("Export &As...(ASCII)"), this);
-    switchboard.addSwitch("textExportAsASCII", shortcutScope, a, tag);
+    switchboard.addAction(a, "textExportAsASCII", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textExportText()));
     fileMenu->addAction(a);
     addAction(a);
@@ -354,8 +365,7 @@ void TextEditor::setupFileActions()
 
     fileMenu->addSeparator();
     a = new QAction(QPixmap(QString(":/document-print-%1.svg").arg(iconTheme)), tr("&Print..."), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_P);
-    switchboard.addSwitch("textPrint", shortcutScope, a, tag);
+    switchboard.addAction(a, "textPrint", Qt::CTRL | Qt::Key_P, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textPrint()));
     tb->addAction(a);
     fileMenu->addAction(a);
@@ -372,17 +382,17 @@ void TextEditor::setupFileActions()
 
 void TextEditor::setupEditActions()
 {
-    QString tag = tr("Texteditor", "Shortcuts");
+    QString tag = tr("Edit actions", "TextEditor shortcut groups");
     QToolBar *editToolBar = addToolBar(tr("Edit Actions"));
+    editToolBar->setStyleSheet(toolBarStyle);
     editToolBar->setObjectName("noteEditorEditActions");
     editToolBar->hide();
     QMenu *editMenu = menuBar()->addMenu(tr("Edi&t"));
 
     QAction *a;
     a = new QAction(QPixmap(":/undo.png"), tr("&Undo"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Z);
     a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textUndo", shortcutScope, a, tag);
+    switchboard.addAction(a, "textUndo", Qt::CTRL | Qt::Key_Z, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), editor, SLOT(undo()));
     editMenu->addAction(a);
     editToolBar->addAction(a);
@@ -390,9 +400,8 @@ void TextEditor::setupEditActions()
     actionEditUndo = a;
 
     a = new QAction(QPixmap(":/redo.png"), tr("&Redo"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_Y);
     a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textRedo", shortcutScope, a, tag);
+    switchboard.addAction(a, "textRedo", Qt::CTRL | Qt::Key_Y, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), editor, SLOT(redo()));
     editMenu->addAction(a);
     editToolBar->addAction(a);
@@ -402,8 +411,7 @@ void TextEditor::setupEditActions()
     editMenu->addSeparator();
     a = new QAction(QPixmap(), tr("Select and copy &all"), this);
     a->setShortcutContext(Qt::WidgetShortcut);
-    a->setShortcut(Qt::CTRL | Qt::Key_A);
-    switchboard.addSwitch("textCopyAll", shortcutScope, a, tag);
+    switchboard.addAction(a, "textCopyAll", Qt::CTRL | Qt::Key_A, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(editCopyAll()));
     editMenu->addAction(a);
     filledEditorActions << a;
@@ -411,9 +419,8 @@ void TextEditor::setupEditActions()
 
     editMenu->addSeparator();
     a = new QAction(QPixmap(QString(":/edit-copy-%1.svg").arg(iconTheme)), tr("&Copy", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_C);
     a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textCopy", shortcutScope, a, tag);
+    switchboard.addAction(a, "textCopy", Qt::CTRL | Qt::Key_C, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), editor, SLOT(copy()));
     editMenu->addAction(a);
     editToolBar->addAction(a);
@@ -421,9 +428,8 @@ void TextEditor::setupEditActions()
     actionEditCopy = a;
 
     a = new QAction(QPixmap(QString(":/edit-cut-%1.svg").arg(iconTheme)), tr("Cu&t", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_X);
     a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textCut", shortcutScope, a, tag);
+    switchboard.addAction(a, "textCut", Qt::CTRL | Qt::Key_X, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), editor, SLOT(cut()));
     editMenu->addAction(a);
     editToolBar->addAction(a);
@@ -431,9 +437,8 @@ void TextEditor::setupEditActions()
     actionEditCut = a;
 
     a = new QAction(QPixmap(QString(":/edit-paste-%1.svg").arg(iconTheme)), tr("&Paste", "Edit menu"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_V);
     a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textPaste", shortcutScope, a, tag);
+    switchboard.addAction(a, "textPaste", Qt::CTRL | Qt::Key_V, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), editor, SLOT(paste()));
     editMenu->addAction(a);
     editToolBar->addAction(a);
@@ -451,20 +456,20 @@ void TextEditor::setupEditActions()
 
 void TextEditor::setupFormatActions()
 {
-    QString tag = tr("Texteditor", "Shortcuts");
+    QString tag = tr("Format actions", "TextEditor shortcut groups");
     fontHintsToolBar =
         addToolBar(tr("Font hints", "toolbar in texteditor"));
+    fontHintsToolBar->setStyleSheet(toolBarStyle);
     fontHintsToolBar->setObjectName("noteEditorFontToolBar");
     QMenu *formatMenu = menuBar()->addMenu(tr("F&ormat"));
 
     QAction *a;
 
     a = new QAction(QPixmap(":/formatfixedfont.png"), tr("&Font hint"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_H);
     a->setCheckable(true);
     a->setChecked(
         settings.value("/noteeditor/fonts/useFixedByDefault", false).toBool());
-    switchboard.addSwitch("textToggleFonthint", shortcutScope, a, tag);
+    switchboard.addAction(a, "textToggleFonthint", Qt::CTRL | Qt::Key_H, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(toggleFonthint()));
     formatMenu->addAction(a);
     fontHintsToolBar->addAction(a);
@@ -473,10 +478,8 @@ void TextEditor::setupFormatActions()
 
     // Original icon: ./share/icons/oxygen/22x22/actions/format-text-color.png
     a = new QAction(QPixmap(":/formatrichtext.svg"), tr("&Richtext"), this);
-    //  a->setShortcut(Qt::CTRL | Qt::Key_R);
-    //  a->setShortcutContext (Qt::WidgetShortcut);
     a->setCheckable(true);
-    switchboard.addSwitch("textToggleRichText", shortcutScope, a, tag);
+    switchboard.addAction(a, "textToggleRichText", shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(toggleRichText()));
     formatMenu->addAction(a);
     fontHintsToolBar->addAction(a);
@@ -486,6 +489,7 @@ void TextEditor::setupFormatActions()
     addToolBarBreak();
 
     fontToolBar = addToolBar(tr("Fonts", "toolbar in texteditor"));
+    fontToolBar->setStyleSheet(toolBarStyle);
     fontToolBar->setObjectName("noteEditorFontToolBar");
 
     comboFont = new QComboBox;
@@ -512,6 +516,7 @@ void TextEditor::setupFormatActions()
     addToolBarBreak();
 
     formatToolBar = addToolBar(tr("Format", "toolbar in texteditor"));
+    formatToolBar->setStyleSheet(toolBarStyle);
     formatToolBar->setObjectName("noteEditorFormatToolBar");
 
     //QPixmap pix(16, 16);
@@ -534,9 +539,8 @@ void TextEditor::setupFormatActions()
     actionTextBGColor = a;
 
     a = new QAction(QPixmap(QString(":/format-text-bold-%1.svg").arg(iconTheme)), tr("&Bold"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_B);
 //    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textToggleBold", shortcutScope, a, tag);
+    switchboard.addAction(a, "textToggleBold", Qt::CTRL | Qt::Key_B, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textBold()));
     formatToolBar->addAction(a);
     formatMenu->addAction(a);
@@ -545,9 +549,8 @@ void TextEditor::setupFormatActions()
     actionTextBold = a;
 
     a = new QAction(QPixmap(QString(":/format-text-italic-%1.svg").arg(iconTheme)), tr("&Italic"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_I);
 //    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textToggleItalic", shortcutScope, a, tag);
+    switchboard.addAction(a, "textToggleItalic", Qt::CTRL | Qt::Key_I, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textItalic()));
     formatToolBar->addAction(a);
     formatMenu->addAction(a);
@@ -556,9 +559,8 @@ void TextEditor::setupFormatActions()
     actionTextItalic = a;
 
     a = new QAction(QPixmap(QString(":/text-format-underline-%1.svg").arg(iconTheme)), tr("&Underline"), this);
-    a->setShortcut(Qt::CTRL | Qt::Key_U);
 //    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
-    switchboard.addSwitch("textToggleUnderline", shortcutScope, a, tag);
+    switchboard.addAction(a, "textToggleUnderline", Qt::CTRL | Qt::Key_U, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textUnderline()));
     formatToolBar->addAction(a);
     formatMenu->addAction(a);
@@ -571,23 +573,19 @@ void TextEditor::setupFormatActions()
     QActionGroup *actGrp2 = new QActionGroup(this);
     actGrp2->setExclusive(true);
     a = new QAction(QPixmap(QString(":/text-format-subscript-%1.svg").arg(iconTheme)), tr("Subs&cript"), actGrp2);
-    a->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_B);
-//    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
     a->setCheckable(true);
     formatToolBar->addAction(a);
     formatMenu->addAction(a);
-    switchboard.addSwitch("textToggleSub", shortcutScope, a, tag);
+    switchboard.addAction(a, "textToggleSub", Qt::CTRL | Qt::SHIFT | Qt::Key_B, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textVAlign()));
     filledEditorRichTextActions << a;
     actionAlignSubScript = a;
 
     a = new QAction(QPixmap(QString(":/text-format-superscript-%1.svg").arg(iconTheme)), tr("Su&perscript"), actGrp2);
-    a->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_P);
-//    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
     a->setCheckable(true);
     formatToolBar->addAction(a);
     formatMenu->addAction(a);
-    switchboard.addSwitch("textToggleSuper", shortcutScope, a, tag);
+    switchboard.addAction(a, "textToggleSuper", Qt::CTRL | Qt::SHIFT | Qt::Key_P, shortcutScope, tag);
     connect(a, SIGNAL(triggered()), this, SLOT(textVAlign()));
     filledEditorRichTextActions << a;
     actionAlignSuperScript = a;
@@ -709,14 +707,22 @@ void TextEditor::textLoad()
 void TextEditor::closeEvent(QCloseEvent *ce)
 {
     ce->accept(); // TextEditor can be reopened with show()
-    hide();
-    emit windowClosed();
-    return;
+    closeWindow();
 }
 
 bool TextEditor::eventFilter(QObject *obj, QEvent *ev)
 {
     if (obj == editor) {
+        // qDebug() << "TE::eventFilter   ev=" << ev;
+        if (ev->type() == QEvent::FocusIn) {
+            //editor->setFrameStyle(QFrame::Box);
+            editor->setStyleSheet("QTextEdit {" + editorFocusInStyle + "}");
+        }
+        if (ev->type() == QEvent::FocusOut) {
+            editor->setFrameStyle(QFrame::NoFrame);
+            editor->setStyleSheet("QTextEdit {" + editorFocusOutStyle + "}");
+
+        }
         if (ev->type() == QEvent::KeyPress) {
             QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
             if (keyEvent == QKeySequence::Paste) {
@@ -839,6 +845,13 @@ void TextEditor::clear()
     blockChangedSignal = blockChangedOrg;
 }
 
+void TextEditor::closeWindow()
+{
+    parentWidget()->hide();
+    emit windowClosed();
+    return;
+}
+
 void TextEditor::deleteAll()
 {
     editor->clear();
index 0c13457fba2a565307f4f050876d995747039ece..9ef3d500de21d17aa2c4098c368a0016a50d4211 100644 (file)
@@ -55,6 +55,7 @@ class TextEditor : public QMainWindow {
     void setInactive(); // Nothing can be entered
     void editCopyAll();
     void clear();
+    void closeWindow();
 
   protected slots:
     void deleteAll();
index d8bc48de6b4cec7451227e04fbaef5bd6256d87f..79a4751c48241c35de2e02e29800ae1b9498bbd6 100644 (file)
@@ -10,7 +10,6 @@
 #include "vymmodel.h"
 
 extern Main *mainWindow;
-extern QString editorFocusStyle;
 
 extern QMenu *branchContextMenu;
 extern QMenu *canvasContextMenu;
@@ -63,6 +62,12 @@ void TreeEditor::init()
     addAction(a);
     connect(a, SIGNAL(triggered()), this, SLOT(startEdit()));
 
+    a = new QAction(this);
+    a->setShortcutContext(Qt::WidgetShortcut);
+    a->setShortcut(Qt::CTRL | Qt::Key_D);
+    addAction(a);
+    connect(a, SIGNAL(triggered()), this, SLOT(closeWindow()));
+
     // Clone actions defined in MainWindow  // FIXME-3 PageUp/Down not working in TreeEditor
     foreach (QAction *qa, mainWindow->mapEditorActions) {
         a = new QAction(this);
@@ -71,8 +76,6 @@ void TreeEditor::init()
         connect(a, SIGNAL(triggered()), qa, SLOT(trigger()));
         addAction(a);
     }
-
-    setStyleSheet("QTreeView:focus {" + editorFocusStyle + "}");
 }
 
 TreeEditor::~TreeEditor()
@@ -104,6 +107,12 @@ void TreeEditor::contextMenuEvent(QContextMenuEvent *e) {
 
 void TreeEditor::closeEvent(QCloseEvent *event)
 {
+    closeWindow();
+}
+
+void TreeEditor::closeWindow()
+{
+    // Close *all* TreeEditors in each VymView and update vym settings
     mainWindow->windowSetTreeEditorsVisibility(false);
 }
 
index 73b4c7e73d49480456a7383518f504799d5c6c4b..9f38a8e7062d0b9a62076f1f4a460b3bb02ae0e2 100644 (file)
@@ -21,6 +21,9 @@ class TreeEditor : public QTreeView {
     virtual void contextMenuEvent(QContextMenuEvent *e);
     virtual void closeEvent(QCloseEvent *event);
 
+  public slots:
+    void closeWindow();
+
   private slots:
     void cursorUp();
     void cursorDown();
index e885a6d8714fb2e7c767c9127e1b4aba98d0d751..b62f5a5f3490b8a0c31223a7ebce223b37b31e8b 100644 (file)
@@ -395,9 +395,9 @@ void TreeItem::setUrl(const QString &u)
 {
     urlInt = u;
     if (!urlInt.isEmpty())
-        systemFlags.activate(QString("system-url"));
+        setUrlType(UrlType::GeneralUrl);
     else
-        systemFlags.deactivate(QString("system-url"));
+        setUrlType(UrlType::NoUrl);
 }
 
 QString TreeItem::url() { return urlInt; }
@@ -407,6 +407,16 @@ bool TreeItem::hasUrl() { return !urlInt.isEmpty();}
 void TreeItem::setUrlType(UrlType ut)
 {
     urlTypeInt = ut;
+    if (urlTypeInt == TreeItem::JiraUrl) {
+        systemFlags.activate("system-jira");
+        systemFlags.deactivate("system-url");
+    } else {
+        systemFlags.deactivate("system-jira");
+        if (urlTypeInt == TreeItem::GeneralUrl)
+            systemFlags.activate("system-url");
+        else
+            systemFlags.deactivate("system-url");
+    }
 }
 
 TreeItem::UrlType TreeItem::urlType()
@@ -414,6 +424,20 @@ TreeItem::UrlType TreeItem::urlType()
     return urlTypeInt;
 }
 
+Flag* TreeItem::urlFlag()
+{
+    if (!hasUrl())
+        return nullptr;
+
+    if (urlTypeInt == UrlType::GeneralUrl)
+        return systemFlagsMaster->findFlagByName("system-url");
+
+    if (urlTypeInt == UrlType::JiraUrl)
+        return systemFlagsMaster->findFlagByName("system-jira");
+
+    return nullptr;
+}
+
 void TreeItem::setVymLink(const QString &vl)
 {
     if (!vl.isEmpty()) {
@@ -444,6 +468,11 @@ QString TreeItem::vymLink() { return vymLinkInt; }
 
 bool TreeItem::hasVymLink() { return !vymLinkInt.isEmpty();}
 
+bool TreeItem::hasReference()
+{
+    return (xlinkCounter > 0) || hasUrl() || hasVymLink();
+}
+
 void TreeItem::toggleTarget()
 {
     systemFlags.toggle(QString("system-target"));
index 5072248109446c40726e411ea1c44a85c46cde55..bf5dbaf5f273af8f6639ead1785d3286e08c9226 100644 (file)
@@ -111,6 +111,7 @@ class TreeItem : public XMLObj {
     bool hasUrl();
     void setUrlType(UrlType);
     UrlType urlType();
+    Flag *urlFlag();
 
   protected:
     QString vymLinkInt;
@@ -119,6 +120,7 @@ class TreeItem : public XMLObj {
     void setVymLink(const QString &s);  //! Set vymLink
     QString vymLink();                  //! Get vymLink
     bool hasVymLink();
+    bool hasReference();                //! True if vymLink, XLink, or Url are availalble
 
   protected:
     bool target;
index c7f56e2d8fe662ac1c557bb209008b83a964e0ad..187f02762aefe9561daf41b0b953b6a87c83c211 100644 (file)
@@ -1,8 +1,8 @@
 #ifndef VERSION_H
 #define VERSION_H
 
-#define __VYM_VERSION "2.9.588"
-#define __VYM_BUILD_DATE "2025-08-07"
+#define __VYM_VERSION "2.9.598"
+#define __VYM_BUILD_DATE "2025-09-25"
 
 #define __VYM_NAME "VYMng"     // FIXME "next generation" in in window title
 #define __VYM_HOME "http://www.insilmaril.de/vym"
index a7bf6d73c592caf54bcccd31e8dc97a3cf1e0a7f..ce99df6a06017f8dd65aa059d563b932fa0adf6d 100644 (file)
@@ -64,6 +64,17 @@ QObject *VymWrapper::currentMap()
     return mw;
 }
 
+QObject *VymWrapper::mapWithId(uint n)
+{
+    VymModel *m = mainWindow->getModel(n);
+    if (!m) {
+        mainWindow->abortScript(
+                QJSValue::ReferenceError,
+                QString("No model available with id=%1").arg(n));
+    }
+    return (QObject*)(m->getWrapper());
+}
+
 void VymWrapper::editHeading()
 {
     MapEditor *me = mainWindow->currentMapEditor();
@@ -82,6 +93,11 @@ bool VymWrapper::directoryExists(const QString &directoryName)
     return d.exists();
 }
 
+void VymWrapper::exit()
+{
+    mainWindow->setExitAfterScript(true);
+}
+
 bool VymWrapper::fileCopy(const QString &srcPath, QString dstPath)
 {
     QFile file(srcPath);
@@ -218,8 +234,6 @@ uint VymWrapper::currentMapID()
     return r;
 }
 
-void VymWrapper::toggleTreeEditor() { mainWindow->windowToggleTreeEditors(); }
-
 void VymWrapper::saveFile(
     const QString &filename,
     const QString &s) // FIXME-3 error handling missing (in vymmodel and here)
index 46540c6359e601c59de66f71557b9e6a67bf1f9c..26fc176ea741ef098cb78930e050c14d575ca7b2 100644 (file)
@@ -9,6 +9,7 @@ class VymModelWrapper;
 ///////////////////////////////////////////////////////////////////////////
 class VymWrapper : public QObject {
     Q_OBJECT
+
   public:
     VymWrapper();
     ~VymWrapper();
@@ -18,10 +19,12 @@ class VymWrapper : public QObject {
     bool closeMapWithID(uint n);
     QString currentColor();
     Q_INVOKABLE QObject *currentMap();
+    Q_INVOKABLE QObject *mapWithId(uint n);
     uint currentMapID();
     void editHeading();
     bool directoryIsEmpty(const QString &dirName);
     bool directoryExists(const QString &dirName);
+    void exit();
     bool fileCopy(const QString &srcPath, QString dstPath);
     bool fileExists(const QString &fileName);
     bool fileRemove(const QString &fileName);
@@ -38,7 +41,6 @@ class VymWrapper : public QObject {
     void selectQuickColor(int n);
     void statusMessage(const QString &s);
     void saveFile(const QString &filename, const QString &s);
-    void toggleTreeEditor();
     bool usesDarkTheme();
     QString version();
     QString vymBaseDir();
index 59e08190fe7b1258c56f9ec16312e2067ea7abe5..41b14bd88a9fbc6e61fef24eca30779c9d3a8ad2 100644 (file)
@@ -121,6 +121,7 @@ VymModel::VymModel()
 VymModel::~VymModel()
 {
     //qDebug() << "Destr VymModel begin this=" << this << "  " << mapName << "zipAgent=" << zipAgent;
+    //logInfo("VymModel about to be destroyed", __func__);
 
     mapEditor = nullptr;
     repositionBlocked = true;
@@ -128,28 +129,6 @@ VymModel::~VymModel()
     filePath.clear();
     fileChangedTimer->stop();
 
-    if (zipAgent) {
-        mainWindow->statusMessage(tr("Waiting until map is completely saved and compressed..."));
-        zipAgent->waitForFinished();
-        
-        // zipAgent might be set to nullptr already in VymModel::zipFinished
-        if (zipAgent) {
-            if (zipAgent->exitStatus() != QProcess::NormalExit) {
-                QMessageBox::critical(0, QObject::tr("Critical Error"),
-                                      QObject::tr("zip didn't exit normally"));
-            }
-            else {
-                if (zipAgent->exitCode() > 0) {
-                    QMessageBox::critical(
-                        0, QObject::tr("Critical Error"),
-                        QString("zip exit code:  %1").arg(zipAgent->exitCode()));
-                }
-            }
-            zipAgent->deleteLater();
-            zipAgent = nullptr;
-        }
-    }
-
     vymLock.releaseLock();
 
     // Delete rootItem already now, while VymModel is still around
@@ -162,9 +141,10 @@ VymModel::~VymModel()
     delete (wrapper);
     delete mapDesignInt;
 
-    // qDebug() << "Destr VymModel end this=" << this;
+    // VymModel can be destroyed now, zipProcess for saving is handled in MainWindow
 
-    logInfo("VymModel destroyed", __func__);
+    //qDebug() << "Destr VymModel end this=" << this;
+    //logInfo("VymModel destroyed", __func__);
 }
 
 void VymModel::clear()
@@ -185,6 +165,7 @@ void VymModel::init()
     // No ZipAgent yet and not saving
     zipAgent = nullptr;
     isSavingInt = false;
+    isLoadingInt = false;
 
     // Use default author
     authorInt = settings
@@ -341,10 +322,12 @@ QString VymModel::saveToDir(const QString &tmpdir, const QString &prefix,
             mapAttr += xml.attribute("comment", commentInt) + "\n";
 
         mapAttr += xml.attribute("branchCount", QString().number(branchCount()));
+        if (mapEditor) {
         mapAttr += xml.attribute("mapZoomFactor",
                      QString().setNum(mapEditor->zoomFactorTarget()));
         mapAttr += xml.attribute("mapRotation",
                      QString().setNum(mapEditor->rotationTarget()));
+        }
     }
     header += xml.beginElement("vymmap", mapAttr);
 
@@ -528,6 +511,9 @@ bool VymModel::loadMap(QString fname, const File::LoadMode &lmode,
         return false;
     }
 
+    // No returns now befor end of function
+    isLoadingInt = true;
+
     QString xmlfile;
     if (fname.right(4) == ".xml" || fname.right(3) == ".mm") {
         xmlfile = fname;
@@ -628,7 +614,8 @@ bool VymModel::loadMap(QString fname, const File::LoadMode &lmode,
         bool saveStateBlockedOrg = saveStateBlocked;
         repositionBlocked = true;
         saveStateBlocked = true;
-        mapEditor->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
+        if (mapEditor)
+            mapEditor->setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
 
         // We need to set the tmpDir in order  to load files with rel. path
         QString tmpdir;
@@ -666,7 +653,8 @@ bool VymModel::loadMap(QString fname, const File::LoadMode &lmode,
         // Aftermath
         repositionBlocked = false;
         saveStateBlocked = saveStateBlockedOrg;
-        mapEditor->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
+        if (mapEditor)
+            mapEditor->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
 
         if (noError) {
             if (parsedWell) {
@@ -708,7 +696,7 @@ bool VymModel::loadMap(QString fname, const File::LoadMode &lmode,
         foreach (BranchItem *center, rootItem->getBranches()) {
             foreach (BranchItem *mainBranch, center->getBranches()) {
                 BranchContainer *bc = mainBranch->getBranchContainer();
-                QRectF rb = bc->ornamentsRect();
+                QRectF rb = bc->ornamentsSceneRect();
                 QPointF offset;
                 offset.setX(rb.width() / 2);
                 offset.setY(rb.height() / 2);
@@ -737,6 +725,8 @@ bool VymModel::loadMap(QString fname, const File::LoadMode &lmode,
     }
 
     qApp->processEvents(); // Update view (scene()->update() is not enough)
+
+    isLoadingInt = false;
     return noError;
 }
 
@@ -917,14 +907,33 @@ bool VymModel::isSaving()
     return isSavingInt;
 }
 
+bool VymModel::isLoading()
+{
+    return isLoadingInt;
+}
+
+bool VymModel::isBusy()
+{
+    return isLoadingInt || isSavingInt;
+}
+
 void VymModel::zipFinished()
 {
     // Cleanup
-    QString log = QString("Finished zipping %1 to %2").arg(zipAgent->zipDir().path(), zipAgent->zipName());
-    logInfo(log, __func__);
+    QString path = "unknown";
+    QString name = "unknown";
+    if (zipAgent) {
+        path = zipAgent->zipDir().path();
+        name = zipAgent->zipName();
+
+        QString log = QString("Finished zipping %1 to %2").arg(path, name);
+        logInfo(log, __func__);
+
+        zipAgent->deleteLater();
+        zipAgent = nullptr;
+    } else
+        logWarning("zipAgent == nullptr", __func__);
 
-    zipAgent->deleteLater();
-    zipAgent = nullptr;
     isSavingInt = false;
 
     mainWindow->statusMessage(tr("Saved %1").arg(filePath));
@@ -1536,25 +1545,37 @@ QString VymModel::lastRedoSelection()
 }
 
 QString VymModel::lastRedoCommand()
+{
+    if (isRedoAvailable())
+        return undoSet.value(
+            QString("/history/step-%1/redoCommand").arg(curStep + 1));
+    else
+        return QString();
+}
+
+QString VymModel::lastRedoComment()
+{
+    if (isRedoAvailable())
+        return undoSet.value(QString("/history/step-%1/comment").arg(curStep + 1));
+    else
+        return QString();
+}
+
+QString VymModel::lastUndoCommand()
 {
     if (isUndoAvailable())
         return undoSet.value(
-            QString("/history/step-%1/redoCommand").arg(curStep));
+            QString("/history/step-%1/undoCommand").arg(curStep));
     else
         return QString();
 }
 
-QVariant VymModel::repeatLastCommand()
+QString VymModel::lastUndoComment()
 {
-    QString command = QString("vym.gotoMap(%1); m = vym.currentMap();").arg(modelIdInt);
-    QString redoCommand = undoSet.value(
-       QString("/history/step-%1/redoCommand").arg(curStep));
-    if (isUndoAvailable() && !redoCommand.startsWith("model."))
-        // Only repeat command, if not a set of commands
-        command += "m." + redoCommand + ";";
+    if (isUndoAvailable())
+        return undoSet.value(QString("/history/step-%1/comment").arg(curStep));
     else
-        return false;
-    return mainWindow->runScript(command);
+        return QString();
 }
 
 void VymModel::undo()
@@ -1758,36 +1779,6 @@ QString VymModel::saveState(
     else
         logInfo("saveState: " + comment + " " + redoCommand, __func__);
 
-    // Increase undo steps, but check for repeated actions
-    // like editing a vymNote - then do not increase but replace last command
-    //
-    bool repeatedCommand = false;
-
-    /* FIXME-3 Repeated command not supported yet in saveState
-    // Undo Scripts start with "model.select" - do not consider these for repeated actions
-    if (!undoCommand.startsWith("{")) {
-        if (curStep > 0 && redoSelection == lastRedoSelection()) {
-            int i = redoCommand.indexOf("(");
-            QString rcl = redoCommand.left(i-1);
-            if (i > 0 && rcl == lastRedoCommand().left(i-1)) {
-
-                // Current command is a repeated one. We only want to "squash" some of these
-                QRegularExpression re("<vymnote");
-                if (rcl.startsWith("model.parseVymText") && re.match(redoCommand).hasMatch()) {
-                    if (debug)
-                        qDebug() << "VM::saveState repeated command: " << redoCommand;
-
-                    // Do not increase undoCommand counter
-                    repeatedCommand = true;
-                    undoCommand = undoSet.value(
-                        QString("/history/step-%1/undoCommand").arg(curStep), undoCommand);
-                } else
-                    if (debug)
-                        qDebug() << "VM::saveState not repeated command: " << redoCommand;
-            }
-        }
-    }
-    */
     QString historyPath = getHistoryPath();
 
     // Create historyPath if not available and required
@@ -1842,14 +1833,12 @@ QString VymModel::saveState(
         return historyPath + "/";
     }
 
-    if (!repeatedCommand) {
-        if (undosAvail < stepsTotal)
-            undosAvail++;
+    if (undosAvail < stepsTotal)
+        undosAvail++;
 
-        curStep++;
-        if (curStep > stepsTotal)
-            curStep = 1;
-    }
+    curStep++;
+    if (curStep > stepsTotal)
+        curStep = 1;
 
     // We would have to save all actions in a tree, to keep track of
     // possible redos after an action. Possible, but we are too lazy: forget
@@ -1899,6 +1888,11 @@ QString VymModel::saveStateBranch(
         const QString &comment)
 {
     QString prefix = setBranchVar(bi) + "b.";
+
+    QString repeatAction = QString("m = vym.currentMap();");
+    repeatAction += " branches = m.selectedBranches(); for (b of branches) {b." + rc + "}";
+    mainWindow->setRepeatAction(repeatAction);
+
     return saveState(prefix + uc, prefix + rc, comment);
 }
 
@@ -1921,7 +1915,7 @@ void VymModel::saveStateEndScript()
     if (debug)
         std::cout << "VM::saveStateEndScript" << endl 
             << "  buildingScript=" << buildingUndoScript << endl
-            << "  undoScript=" << undoScript.toStdString() << endl;
+            << "      undoScript=" << undoScript.toStdString() << endl;
 
     if (buildingUndoScript) {
         buildingUndoScript = false;
@@ -1938,6 +1932,32 @@ void VymModel::saveStateEndScript()
     }
 }
 
+void VymModel::saveStateCancelScript()
+{
+    if (debug)
+        std::cout << "VM::saveStateCancelScript" << endl 
+            << "  buildingScript=" << buildingUndoScript << endl
+            << "      undoScript=" << undoScript.toStdString() << endl;
+
+    if (buildingUndoScript) {
+        buildingUndoScript = false;
+
+        logDebug("Canceling building saveStateScript: '" + undoScriptComment + "'", __func__);
+
+        // Drop whole Script, if empty
+        if (undoScript.isEmpty() && redoScript.isEmpty()) return;
+
+        // Prepare undo of actions so far
+        saveState(
+                QString("{%1}").arg(undoScript),
+                QString("{%1}").arg(redoScript),
+                undoScriptComment, nullptr);
+
+        // Undo
+        undo();
+    }
+}
+
 QGraphicsScene *VymModel::getScene() { return mapEditor->getScene(); }
 
 TreeItem *VymModel::findBySelectString(QString s)
@@ -2644,7 +2664,7 @@ void VymModel::setFrameAutoDesign(const bool &useInnerFrame, const bool &b, Bran
 
         logAction(rc, comment, __func__);
 
-        saveStateBeginScript(comment);
+        saveStateBeginScript(comment);  // setFrameAD, calls setFrame* functions
 
         bc = selbi->getBranchContainer();
         bc->setFrameAutoDesign(useInnerFrame, b);
@@ -2688,7 +2708,7 @@ void VymModel::setFrameType(const bool &useInnerFrame, const FrameContainer::Fra
             // Save also penWidth, colors, etc. to restore frame on undo
             saveCompleteFrame = true;
 
-            saveStateBeginScript("Set frame parameters");
+            saveStateBeginScript("Set frame parameters");   // setFrameType, calls setFrame* functions
             QString colorName = bc->framePenColor(useInnerFrame).name();
             saveStateBranch(selbi,
                     QString("setFramePenColor (%1, \"%2\");").arg(uif, colorName),
@@ -2908,7 +2928,7 @@ void VymModel::setRotationAutoDesign(const bool &b, BranchItem *bi)
 
             logAction(rc, comment, __func__);
 
-            saveStateBeginScript(comment);
+            saveStateBeginScript(comment); // setRotationsAD, calls setRotation* functions
             if (b) {
                 setRotationHeading(mapDesignInt->rotationHeading(selbi->depth()));
                 setRotationSubtree(mapDesignInt->rotationSubtree(selbi->depth()));
@@ -2981,6 +3001,32 @@ void VymModel::setRotationSubtree (const int &i, BranchItem *bi)
     }
 }
 
+void VymModel::rotateSubtree(qreal a)
+{
+    QList<BranchItem *> selbis = getSelectedBranches();
+
+    foreach (BranchItem *selbi, selbis) {
+        BranchContainer *bc = selbi->getBranchContainer();
+        qreal a_old = bc->rotationSubtree();
+        qreal a_new = a_old + a;
+        QString uc = QString("setRotationSubtree(\"%1\");").arg(toS(a_old, 1));
+        QString rc = QString("setRotationSubtree(\"%1\");").arg(a_new);
+        QString comment = QString("Set rotation angle of subtree to %1").arg(a_new);
+
+        logAction(rc, comment, __func__);
+
+        saveStateBranch(selbi, uc, rc, comment);
+
+        bc->setRotationSubtree(a_new);
+        emitDataChanged(selbi);
+    }
+
+    if (!selbis.isEmpty()) {
+        branchPropertyEditor->updateControls();
+        reposition();
+    }
+}
+
 void VymModel::setScaleAutoDesign (const bool & b, BranchItem *bi)
 {
     QList<BranchItem *> selbis = getSelectedBranches(bi);
@@ -2996,7 +3042,7 @@ void VymModel::setScaleAutoDesign (const bool & b, BranchItem *bi)
 
             logAction(rc, c, __func__);
 
-            saveStateBeginScript(c);
+            saveStateBeginScript(c);    // setScaleAD, calls setScale* functions
             if (b) {
                 setScaleHeading(mapDesignInt->scaleHeading(selbi->depth()));
                 setScaleSubtree(mapDesignInt->scaleSubtree(selbi->depth()));
@@ -3542,7 +3588,7 @@ BranchItem *VymModel::addTimestamp()
                        .arg(today.day(), 2, 10, c);
         QString comment = "Add branch with current date as heading: " + s;
 
-        saveStateBeginScript(comment);
+        saveStateBeginScript(comment);  // addTimeStamp, calls setHeadingPlain and indirect setUrl
         BranchItem *newbi = addNewBranch(selbi);
         setHeadingPlainText(s, newbi);
         saveStateEndScript();
@@ -3598,8 +3644,6 @@ void VymModel::copy()
         saveState("", rc, comment);
 
     }
-
-    mainWindow->updateActions();
 }
 
 void VymModel::paste()
@@ -4248,7 +4292,7 @@ BranchItem *VymModel::addMapCenter(bool interactive)
         // Start to build undo/redo scripts
         // These script will be finished later when setHeading() is called
         if (hasContextPos)
-            saveStateBeginScript(
+            saveStateBeginScript(   // addMC
                     QString("Add new MapCenter at (%1)").arg(toS(contextPos)));
         else
             saveStateBeginScript("Add new MapCenter");
@@ -4273,10 +4317,9 @@ BranchItem *VymModel::addMapCenter(bool interactive)
 
     BranchItem *newbi = addMapCenterAtPos(contextPos, interactive);
 
-    if (interactive)
+    if (interactive && mapEditor)
         mapEditor->editHeading(newbi);
 
-    updateActions();
     emitShowSelection();
 
     emitUpdateLayout();
@@ -4390,7 +4433,7 @@ BranchItem *VymModel::addNewBranch(BranchItem *bi, int pos, bool interactive)
             comment = QString("Add new branch below %1").arg(getObjectName(selbi));
 
         logAction("", comment, __func__);
-        saveStateBeginScript(comment);
+        saveStateBeginScript(comment);  // addNewBranch: edit new heading if interactive
     }
 
     BranchItem *newbi = addNewBranchInt(selbi, pos);
@@ -4422,7 +4465,7 @@ BranchItem *VymModel::addNewBranch(BranchItem *bi, int pos, bool interactive)
            */
     }
 
-    if (interactive) {
+    if (interactive && mapEditor) {
         select(newbi);
         mapEditor->editHeading();
     }
@@ -4442,7 +4485,7 @@ BranchItem *VymModel::addNewBranchBefore(BranchItem *bi, bool interactive)    //
             // saveStateEndScript will be called in VymModel::setHeading()
             comment = QString("Add new branch before %1").arg(getObjectName(selbi));
             logAction("", comment, __func__);
-            saveStateBeginScript(comment);
+            saveStateBeginScript(comment); // addNewBranchBefore (incl. relinking)
         }
 
         // add below selection
@@ -4470,7 +4513,7 @@ BranchItem *VymModel::addNewBranchBefore(BranchItem *bi, bool interactive)    //
             emitDataChanged(newbi);
         }
 
-        if (interactive) {
+        if (interactive && mapEditor) {
             select(newbi);
             mapEditor->editHeading();
         }
@@ -4507,7 +4550,7 @@ bool VymModel::relinkBranches(QList <BranchItem*> branches, BranchItem *dst, int
     if (!saveStateBlocked)
         // When ordering branches, we already saveState there and not for 
         // each branch individually
-        saveStateBeginScript(
+        saveStateBeginScript(   // relinkBranches: also save position if required
             QString("Relink %1 objects to \"%2\"")
                 .arg(branches.count())
                 .arg(dst->headingPlain()));
@@ -4554,8 +4597,10 @@ bool VymModel::relinkBranches(QList <BranchItem*> branches, BranchItem *dst, int
         if (dst == rootItem) {
             detaching = true;
             preDetachPos = bc->getHeadingContainer()->scenePos();
-        } else
-            detaching = false;
+        } else {
+            // Save position, so // that it can be used // for undo command // later
+            detaching = false; bc->setOriginalPos();
+        }
 
         BranchItem *branchpi = bi->parentBranch();
 
@@ -4670,7 +4715,7 @@ bool VymModel::relinkImage(ImageItem* image, TreeItem *dst_ti, int num_new) {
     return relinkImages(images, dst_ti, num_new);
 }
 
-bool VymModel::relinkImages(QList <ImageItem*> images, TreeItem *dst_ti, int num_new) // FIXME-2 Check relinking, if attributes are in dst_ti (*before) image rows
+bool VymModel::relinkImages(QList <ImageItem*> images, TreeItem *dst_ti, int num_new)
 {
     // Selection is lost when removing rows from model
     QList <TreeItem*> selectedItems = getSelectedItems();
@@ -4701,7 +4746,7 @@ bool VymModel::relinkImages(QList <ImageItem*> images, TreeItem *dst_ti, int num
     if (!saveStateBlocked)
         // When ordering branches, we already saveState there and not for 
         // each branch individually
-        saveStateBeginScript(
+        saveStateBeginScript(   // FIXME-3 relink images: script used for multiselection
             QString("Relink %1 objects to \"%2\"")
                 .arg(images.count())
                 .arg(dst->headingPlain()));
@@ -4738,7 +4783,7 @@ bool VymModel::relinkImages(QList <ImageItem*> images, TreeItem *dst_ti, int num
         // - What about updating links of images (later)?
         // - What about updating design (later)?
         // - in ImageWrapper: num_new missing
-        // - does not save positions
+        // - does not save positions currently
 
         QString iv = setImageVar(ii);
         QString uc = setBranchVar(pi) + iv + "i.relinkToBranch(b);";
@@ -4795,7 +4840,8 @@ void VymModel::deleteSelection(ulong selID)
 
     unselectAll();
 
-    mapEditor->stopContainerAnimations();  // FIXME-5 better tell ME about deleted items, so that ME can take care of race conditions, e.g. also deleting while moving objects
+    if (mapEditor)
+        mapEditor->stopContainerAnimations();  // FIXME-5 better tell ME about deleted items, so that ME can take care of race conditions, e.g. also deleting while moving objects
 
     foreach (ulong id, selectedIDs) {
         TreeItem *ti = findID(id);
@@ -5412,7 +5458,8 @@ void VymModel::colorBranch(QColor c, BranchItem *bi)
         emitDataChanged(selbi);
         taskEditor->showSelection();
     }
-    mapEditor->getScene()->update();
+    if (mapEditor)
+        mapEditor->getScene()->update();
 }
 
 void VymModel::colorSubtree(QColor c, BranchItem *bi)
@@ -5439,7 +5486,8 @@ void VymModel::colorSubtree(QColor c, BranchItem *bi)
         }
     }
     taskEditor->showSelection();
-    mapEditor->getScene()->update();
+    if (mapEditor)
+        mapEditor->getScene()->update();
 }
 
 QColor VymModel::getCurrentHeadingColor()
@@ -5603,17 +5651,6 @@ void VymModel::updateJiraFlag(TreeItem *ti)
         }
     }
 
-    // Update UrlType
-    if (ti->urlType() == TreeItem::JiraUrl) {
-        ti->activateSystemFlagByName("system-jira");
-        ti->deactivateSystemFlagByName("system-url");
-    } else {
-        ti->deactivateSystemFlagByName("system-jira");
-        if (ti->urlType() == TreeItem::GeneralUrl)
-            ti->activateSystemFlagByName("system-url");
-        else
-            ti->deactivateSystemFlagByName("system-url");
-    }
     emitDataChanged(ti);
 }
 
@@ -5778,16 +5815,6 @@ QStringList VymModel::getVymLinks()
     return links;
 }
 
-void VymModel::followXLink(int i)
-{
-    BranchItem *selbi = getSelectedBranch();
-    if (selbi) {
-        selbi = selbi->getXLinkItemNum(i)->getPartnerBranch();
-        if (selbi)
-            select(selbi);
-    }
-}
-
 void VymModel::editXLink()
 {
     XLink *xlink = getSelectedXLink();
@@ -5913,6 +5940,11 @@ void VymModel::setExportMode(bool b)
 
 QPointF VymModel::exportImage(QString fname, bool askName, QString format)
 {
+    if (!mapEditor) {
+        qWarning() << __func__ << "mapEditor == nullptr";
+        return QPointF();
+    }
+
     QPointF offset; // set later, when getting image from MapEditor
 
     if (fname == "") {
@@ -5945,8 +5977,6 @@ QPointF VymModel::exportImage(QString fname, bool askName, QString format)
 
     setExportMode(true);
 
-    mapEditor->minimizeView();  // Export minimal image
-
     QImage img(mapEditor->getImage(offset));
     if (!img.save(fname, format.toLocal8Bit())) {
         QMessageBox::critical(
@@ -5965,6 +5995,11 @@ QPointF VymModel::exportImage(QString fname, bool askName, QString format)
 
 void VymModel::exportPDF(QString fname, bool askName)
 {
+    if (!mapEditor) {
+        qWarning() << __func__ << "mapEditor == nullptr";
+        return;
+    }
+    
     if (fname == "") {
         if (!askName) {
             qWarning("VymModel::exportPDF called without filename (and "
@@ -6497,12 +6532,22 @@ void VymModel::registerMapEditor(QWidget *e) { mapEditor = (MapEditor *)e; }
 
 void VymModel::setMapZoomFactor(const double &d)
 {
+    if (!mapEditor) {
+        qWarning() << __func__ << "mapEditor == nullptr";
+        return;
+    }
+
     zoomFactor = d;
     mapEditor->setZoomFactorTarget(d);
 }
 
 void VymModel::setMapRotation(const double &a)
 {
+    if (!mapEditor) {
+        qWarning() << __func__ << "mapEditor == nullptr";
+        return;
+    }
+
     if (a < 1)
         // Round to zero, otherwise selectionMode in MapEditor might be 
         // "Geometric" when it should be "Classic"
@@ -6518,6 +6563,11 @@ void VymModel::setMapAnimCurve(const QEasingCurve &c) { animCurve = c; }
 
 bool VymModel::centerOnID(const QString &id)
 {
+    if (!mapEditor) {
+        qWarning() << __func__ << "mapEditor == nullptr";
+        return false;
+    }
+
     TreeItem *ti = findUuid(QUuid(id));
     if (ti && (ti->hasTypeBranch() || ti->hasTypeImage())) {
         Container *c = ((MapItem*)ti)->getContainer();
@@ -6559,7 +6609,8 @@ void VymModel::reposition(bool force)
 
     repositionXLinks();
 
-    mapEditor->minimizeView();  // Optimize view when geometry changes in reposition()
+    if (mapEditor)
+        mapEditor->minimizeView();  // Optimize view when geometry changes in reposition()
 
     //qDebug() << "VM::reposition end";
     if (force)
@@ -6844,7 +6895,7 @@ void VymModel::setBackgroundColor(QColor col)
 {
     QColor oldcol = mapDesignInt->backgroundColor();
 
-    saveStateBeginScript("Set background color");
+    saveStateBeginScript("Set background color");   // Save background image in script
 
     if (hasBackgroundImage())
         unsetBackgroundImage();
@@ -6873,7 +6924,7 @@ bool VymModel::loadBackgroundImage( const QString &imagePath)
 
         logAction(rc, comment, __func__);
 
-        saveStateBeginScript(comment);
+        saveStateBeginScript(comment);  // load BG img, save previous img if used
 
         bool saveOldImage = false;
 
@@ -6996,26 +7047,24 @@ void VymModel::setPos(const QPointF &pos_new, TreeItem *selti)
         selItems = getSelectedItems();
 
     QString com = "Move items (non-interactive";
-    saveStateBeginScript("Move items (non-interactive)");
+    QString uc, rc, itemVar;
     foreach (TreeItem *ti, selItems) {
         if (ti->hasTypeBranch() || ti->hasTypeImage())
         {
             Container *c = ((MapItem*)ti)->getContainer();
             QString pos_new_str = toS(pos_new);
 
-            QString uc, rc, itemVar;
             if (ti->hasTypeBranch())
                 itemVar = setBranchVar((BranchItem*)ti) + "b.";
             else 
                 itemVar = setImageVar((ImageItem*)ti) + "i.";
-            uc = QString("%1.setPos%2;").arg(itemVar, toS(c->getOriginalPos(), 5));
-            rc = QString("%1.setPos%2;").arg(itemVar, toS(c->pos(), 5));
-            logAction(rc, com, __func__);
-            saveState(uc, rc); 
+            uc += QString("%1.setPos%2;").arg(itemVar, toS(c->getOriginalPos(), 5));
+            rc += QString("%1.setPos%2;").arg(itemVar, toS(c->pos(), 5));
             c->setPos(pos_new);
         }
     }
-    saveStateEndScript();
+    logAction(rc, com, __func__);
+    saveState(uc, rc); 
     reposition();
 }
 
@@ -7959,11 +8008,13 @@ SlideItem *VymModel::addSlide()     // FIXME-3 missing saveState
                 return nullptr;
             }
 
-            inScript.replace(
-                "CURRENT_ZOOM",
-                QString().setNum(getMapEditor()->zoomFactorTarget()));
-            inScript.replace("CURRENT_ANGLE",
-                             QString().setNum(getMapEditor()->rotationTarget()));
+            if (mapEditor) {
+                inScript.replace(
+                    "CURRENT_ZOOM",
+                    QString().setNum(mapEditor->zoomFactorTarget()));
+                inScript.replace("CURRENT_ANGLE",
+                                 QString().setNum(mapEditor->rotationTarget()));
+            }
             inScript.replace("CURRENT_ID",
                              "\"" + seli->getUuid().toString() + "\"");
 
index c779737500c1c2515ebecee49e39fe778c72cfc1..2364bfd574010af5d2ba34648e8a519a22224e73 100644 (file)
@@ -172,16 +172,17 @@ class VymModel : public TreeModel {
   public:
     /*! \brief Save the map to file */
     bool saveMap(const File::SaveMode &);
+    bool isLoading();
     bool isSaving();
+    bool isBusy();
 
   private slots:
     void zipFinished ();
 
   private:
-
-
     ZipAgent *zipAgent;
     bool isSavingInt;
+    bool isLoadingInt;
 
   public:
     ImageItem* loadImage(
@@ -262,14 +263,16 @@ class VymModel : public TreeModel {
     bool isRedoAvailable(); //!< True, if redo is available
     QString lastRedoSelection();
     QString lastRedoCommand();
-    QVariant repeatLastCommand(); //!< Repeat last command on current selection
+    QString lastRedoComment();
+    QString lastUndoCommand();
+    QString lastUndoComment();
 
-    void undo();               //!< Undo last action
-    bool isUndoAvailable();    //!< True, if undo is available
-    void gotoHistoryStep(int); //!< Goto a specifig step in history
+    void undo();                    //!< Undo last action
+    bool isUndoAvailable();         //!< True, if undo is available
+    void gotoHistoryStep(int);      //!< Goto a specifig step in history
 
-    QString getHistoryPath(); //!< Path to directory containing the history
-    void resetHistory();      //!< Initialize history
+    QString getHistoryPath();       //!< Path to directory containing the history
+    void resetHistory();            //!< Initialize history
 
     QString setAttributeVar(AttributeItem*, QString varName ="b");  //!< Returns command to set AttributeItem in scripts for undo/redo
     QString setBranchVar(BranchItem*, QString varName ="b");  //!< Returns command to set BranchItem in scripts for undo/redo
@@ -308,6 +311,7 @@ class VymModel : public TreeModel {
     /*! Put several states into one Script for a single undo step */
     void saveStateBeginScript(const QString &comment);
     void saveStateEndScript();
+    void saveStateCancelScript();
 
     ////////////////////////////////////////////
     // unsorted so far
@@ -392,6 +396,7 @@ class VymModel : public TreeModel {
     void setRotationAutoDesign(const bool &, BranchItem *bi = nullptr);
     void setRotationHeading(const int &, BranchItem *bi = nullptr);
     void setRotationSubtree(const int &, BranchItem *bi = nullptr);
+    void rotateSubtree(qreal a);
     void setScaleAutoDesign(const bool &, BranchItem *bi = nullptr);
     void setScaleHeading(const qreal &, const bool relative = false, BranchItem *bi = nullptr);
     qreal getScaleHeading();
@@ -595,7 +600,6 @@ class VymModel : public TreeModel {
     void deleteVymLink();                // delete link to another map
     QString getVymLink();                // return path to map
     QStringList getVymLinks();           // return paths in subtree
-    void followXLink(int);
     void editXLink();
     void setXLinkColor(const QString &, XLink *xl = nullptr);
     void setXLinkStyle(const QString &, XLink *xl = nullptr);
index 40222087eb35987d41154450b4a136b918eb50d5..4b53c01a1158da7cedc321cea39ac8d1b04898c1 100644 (file)
@@ -481,11 +481,6 @@ void VymModelWrapper::removeXLink(XLinkWrapper *xlw)
     modelInt->deleteXLink(xlw->xlink());
 }
 
-QVariant VymModelWrapper::repeatLastCommand()
-{
-    return modelInt->repeatLastCommand();
-}
-
 bool VymModelWrapper::saveSelection(const QString &filename)
 {
     QString filename_org = modelInt->getFilePath(); // Restore filename later
@@ -541,6 +536,17 @@ BranchWrapper* VymModelWrapper::selectedBranch()
         return nullptr; // caught by QJSEngine
 }
 
+QList <BranchWrapper*> VymModelWrapper::selectedBranches()
+{
+    QList <BranchItem*> selbis = modelInt->getSelectedBranches();
+
+    QList <BranchWrapper*> rlist;
+    foreach (BranchItem *selbi, selbis)
+        rlist << selbi->branchWrapper();
+
+    return rlist;
+}
+
 XLinkWrapper* VymModelWrapper::selectedXLink()
 {
     XLinkItem *xli = modelInt->getSelectedXLinkItem();
index 21f9061041c8e08b11b792b6a4266ae753043b1d..137a2e04eccaf475430be857b6422537883e29eb 100644 (file)
@@ -64,11 +64,11 @@ class VymModelWrapper : public QObject {
     void removeKeepChildren(BranchWrapper *bw);
     void removeSlide(int n);
     void removeXLink(XLinkWrapper *xlw);
-    QVariant repeatLastCommand();
     bool saveSelection(const QString &filename);
     bool select(const QString &s);
     Q_INVOKABLE AttributeWrapper* selectedAttribute();
     Q_INVOKABLE BranchWrapper* selectedBranch();
+    QList <BranchWrapper*> selectedBranches();
     Q_INVOKABLE XLinkWrapper* selectedXLink();
     bool selectUids(QJSValueList args);
     bool selectLatestAdded();
index 4c0e6eb506f35588aa85d6ecdd3faae5d8d4a49e..3e24b455035c5fca5196775690d2d2c43944267e 100644 (file)
@@ -11,6 +11,8 @@
 extern Main *mainWindow;
 extern Settings settings;
 
+extern QString editorFocusInStyle;
+
 VymView::VymView(VymModel *m)
 {
     model = m;
@@ -30,12 +32,19 @@ VymView::VymView(VymModel *m)
     TreeDelegate *delegate = new TreeDelegate(this);
     treeEditor->setItemDelegate(delegate);
 
+    // Add Escape-keys to editors
+    QAction *a = new QAction("Cancel", treeEditor);
+    a->setShortcut(Qt::Key_Escape);     // Escape in NoteEditor
+    a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+    treeEditor->connect(a, SIGNAL(triggered()), mainWindow, SLOT(escapePressed()));
+    treeEditor->addAction(a);
+
     DockEditor *de;
     de = new DockEditor(tr("Tree Editor", "Title of dockable editor widget"),
                         this, model);
     de->setWidget(treeEditor);
     de->setAllowedAreas(Qt::AllDockWidgetAreas);
-    de->setVisible(mainWindow->actionViewToggleTreeEditor->isChecked());
+    de->setVisible(settings.value("/mainwindow/view/showTreeEditors", true).toBool());
     addDockWidget(Qt::LeftDockWidgetArea, de);
     treeEditorDE = de;
 
@@ -52,7 +61,7 @@ VymView::VymView(VymModel *m)
                         this, model);
     de->setWidget(slideEditor);
     de->setAllowedAreas(Qt::AllDockWidgetAreas);
-    de->setVisible(mainWindow->actionViewToggleSlideEditor->isChecked());
+    de->setVisible(settings.value("/mainwindow/view/showSlideEditors", false).toBool());
     addDockWidget(Qt::RightDockWidgetArea, de);
     slideEditorDE = de;
     connect(slideEditorDE, SIGNAL(visibilityChanged(bool)), mainWindow,
@@ -118,12 +127,6 @@ void VymView::updateColors()
     // TreeEditor, HeadingEditor and MapEditor
 
     QString s;
-    // Selection
-    /*
-    treeEditor->setStyleSheet(
-        "selection-background-color: " + brush.color().name(QColor::HexArgb) + ";" +
-        "background-color: " + mapEditor->getScene()->backgroundBrush().color().name());
-        */
 
     MapDesign *mapDesign = model->mapDesign();
 
@@ -157,7 +160,7 @@ void VymView::updateColors()
     treeEditor->setPalette(palette);
 
     // s += "QTreeView::branch {color: red; background: palette(base);}";
-    treeEditor->setStyleSheet(s);
+    treeEditor->setStyleSheet("QTreeView{" + s + "} QTreeView:focus{" + editorFocusInStyle + "}");
 }
 
 void VymView::changeSelection(const QItemSelection &newsel,
@@ -300,3 +303,4 @@ void VymView::setSlideEditorVisibility(bool b)
 }
 
 void VymView::setFocusMapEditor() { mapEditor->setFocus(); }
+void VymView::setFocusTreeEditor() { treeEditor->setFocus(); }
index d71fe81a7ad5426804ebfc97119591571fa1072a..06a144298c778cc1d9a51b68b6eeb2b889c997a8 100644 (file)
@@ -35,6 +35,7 @@ class VymView : public QMainWindow {
     void setTreeEditorVisibility(bool);
     void setSlideEditorVisibility(bool);
     void setFocusMapEditor();
+    void setFocusTreeEditor();
 
   private:
     VymModel *model;
index 3dbca91ee3db4c72f325ab7f4f66791929397fb4..f7ad8bd5f5e15e09cb7fbc4da6809a06d03082d1 100644 (file)
@@ -15,12 +15,11 @@ ZipAgent::ZipAgent(QDir zipDir, QString zipName)   // FIXME-4 Does not support d
     zipNameInt = QDir::toNativeSeparators(zipName);
     zipDirInt = zipDir;
     isBackgroundProcessInt = true;
-
 }
 
 ZipAgent::~ZipAgent()
 {
-    //qDebug() << "Destr ZipAgent";
+    // qDebug() << "Destr ZipAgent";
 }
 
 bool ZipAgent::checkZipTool()
@@ -74,7 +73,7 @@ void ZipAgent::startZip()
     args << ".";
 #endif
     setArguments(args);
-    mainWindow->logInfo("Starting compressing " + zipDirInt.path() + " : " + zipToolPath + " " + args.join(" "));
+    mainWindow->logInfo("ZipAgent: Starting compressing " + zipDirInt.path() + " : " + zipToolPath + " " + args.join(" ") + QString("  Background=%1").arg(isBackgroundProcessInt));
 
     start();
 
@@ -103,11 +102,17 @@ void ZipAgent::startZip()
                 }
             }
         }
-    }
+    } else {
+        connect (this, SIGNAL(backgroundZipStarted()), mainWindow, SLOT(backgroundZipStarted()));
+        connect (this, SIGNAL(backgroundZipFinished()), mainWindow, SLOT(backgroundZipFinished()));
+        emit backgroundZipStarted();
+    }    
+
 }
 
 void ZipAgent::zipProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
 {
+    //qDebug() << __func__ << "starting.";
     mainWindow->logInfo(QString("ZA::zipProcessFinished  exitCode=%1 exitStatus=%2").arg(exitCode).arg(exitStatus), __func__);
 
 #if defined(Q_OS_WINDOWS)
@@ -166,6 +171,10 @@ void ZipAgent::zipProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
     }
 #endif
     emit zipFinished();
+    if (isBackgroundProcessInt)
+        emit backgroundZipFinished();
+
+    // qDebug() << __func__ << "done.";
 }
 
 void ZipAgent::startUnzip()
index a5ea86e45b985db55c4264a5fc729f6996c9349c..312af1a3feb3ce7713fc67429b0f30393c53aa18 100644 (file)
@@ -25,6 +25,8 @@ class ZipAgent : public QProcess {
     QString zipName();
 
   signals:
+    void backgroundZipStarted();
+    void backgroundZipFinished();
     void zipFinished();
     void zipError();
 
index a26e83f416a222b9b51526439b6edc18cb2eb15c..b65dcab982fcb3cbdd5d13f3bf36432e9ab0bc37 100644 (file)
@@ -36,7 +36,7 @@ not_yet_ported_tests = [
 ];
 
 tests = all_tests;
-//tests = ["layouts"];
+// tests = ["modify_branches"];
 
 
 var verbosity = 0;
@@ -1109,6 +1109,29 @@ function test_modify_branches()
   expect("After undo of inverse sorting first child of \"Main A\" is \"" + ha + "\"", branch_0Aa.headingText(), ha);
   expect("After undo of inverse sorting last child of \"Main A\" is \"" + hc + "\"", branch_0Ac.headingText(), hc);
   closeCurrentMap();
+
+  // Coloring
+  map = initMap(testMapDefault);
+
+  b = map.findBranchBySelection(main_A_string);
+  col = b.getHeadingColor();
+  b.colorBranch("#ff0000");
+  expect("colorBranch", b.getHeadingColor(), "#ff0000");
+  map.undo();
+  expect("Undo: colorBranch", b.getHeadingColor(), col);
+
+  b2 = map.findBranchBySelection(branch_0Aa_string);
+  col = b2.getHeadingColor();
+  b.colorSubtree("#00ff00");
+  expect("colorSubtree", b2.getHeadingColor(), "#00ff00");
+
+  map.undo();
+  b = map.findBranchBySelection(main_A_string);
+  b2 = map.findBranchBySelection(branch_0Aa_string);
+  expect("Undo: colorSubtree a) in tree", b2.getHeadingColor(), col);
+  expect("Undo: colorSubtree b) branch", b.getHeadingColor(), col);
+
+  closeCurrentMap();
 }
 
 function test_modify_images()
@@ -1811,3 +1834,4 @@ if (tests.includes("tasks"))          { test_tasks(); }
 if (tests.includes("xlinks"))         { test_xlinks(); }
 
 summary();
+vym.exit();
index 392a61957ae7b2b7c4d87279aca8bed8c0653c6a..2e64f811cd16184d5262eaf589f93db185097ed2 100644 (file)
@@ -1451,7 +1451,8 @@ To hide the link between a branch and its parent open the
 
 
 \subsection{XLinks} \label{xlinks}
-So far all the data in the \vym map has been treelike. Using xLinks you
+So far all the data in the \vym map has been treelike. Using xLinks
+("crosslinks") you
 can link one branch to any other, just like attaching a rope between two
 branches in a real tree. This is especially useful in complex maps,
 where you want to have crossreferences which can not be displayed on the
@@ -1487,12 +1488,12 @@ the control points:
 
 \subsubsection*{Follow a xLink}
 In a complex \vym map it sometimes comes in handy to be able to jump to
-the other end of a xLink. You can do this by opening the context menu of
-the branch and clicking on "Goto xLink" and selecting the xLink you
-want to follow. Even easier is to click on the lower right end of a
-branch -- a popup menu will show up with all xLinked branches. Click one
-of them to jump to it.
+the other end of a xLink. There are several ways to do so:
 
+If the current branch has exactly one outgoing xLink and no
+other reference (Url or vymLink), the linked branch will be
+selected. If multiple xLinks or other references are available,
+a popup menu will ask you to select the reference.
 
 \subsection{Adding and removing branches}
 The context menu of a branch shows some more ways to add and delete data
@@ -1509,30 +1510,11 @@ between {\em Add Map (Insert)} and {\em Add Map (Replace)}: The imported
 data will be added after the selected branch.
 
 \section{\vym on Mac OS X}
-%FIXME-3 Currently not yet supported on Mac OS X in 1.13.x
-
-%\subsection{Overview}
-%Sorry, currently (\vym 2.2.2) there is no Mac port available. Please
-%contact the author\footnote{
-%    Email Uwe Drechsel: \href{mailto:vym@insilmaril.de}{vym@insilmaril.de}} if
-%you are interested in a Mac version.
-
-%Basically there are two ways to run \vym on Macs:
-%\subsubsection*{Qt Mac Edition:}
-%    \vym here provides the well known Mac look and feel.  \vym is
-%    available as Mac OS X application package in contained in a disk
-%    image ({\tt vym.dmg}). It has been compiled and tested in
-%    Mac~OS~10.4.  This package includes  runtime libraries of Qt by
-%    Trolltech.
-    
-%\subsubsection*{X11 version} \vym can also be run using the Linux
-%version, but then menus and handling will also be those of the Linux
-%version e.g. The menu bar will look different. 
 
 \subsection {Contextmenu and special keys}
 Most Macs unfortunatly just have a single mouse button. In order to show
 the context menu which usually would be opened with the right mouse
-button, you can click while pressing the \key{kommand}-key.
+button, you can click while pressing the \key{command}-key.
 
 Especially on Laptops some of the keys usually used on PC keyboards seem
 to be missing. The Qt-Mac Edition of \vym has its own keyboard
diff --git a/vym.qrc b/vym.qrc
index 0296628366dfd0ee0b1ff416e9e506353a1d6710..b59051eeb261ba36ab3094a39a091bec3faeec24 100644 (file)
--- a/vym.qrc
+++ b/vym.qrc
     <file alias="flag-thumb-down.png">flags/flag-thumb-down.png</file>
     <file alias="flag-thumb-up.png">flags/flag-thumb-up.png</file>
     <file alias="flag-tmpUnscrolled-right.png">flags/flag-tmpUnscrolled-right.png</file>
-    <file alias="flag-url.svg">flags/system/applications-internet.svg</file>
-    <file alias="flag-urlnew.svg">flags/system/applications-internet-new.svg</file>
+    <file alias="flag-url.svg">flags/system/flag-url.svg</file>
+    <file alias="flag-urlnew.svg">flags/system/flag-urlnew.svg</file>
     <file alias="flag-vymlink.png">flags/flag-vymlink.png</file>
     <file alias="flag-vymlinknew.png">flags/flag-vymlinknew.png</file>
-    <file alias="flag-jira.svg">flags/system/jissue.svg</file>
+    <file alias="flag-jira.svg">flags/system/flag-jira.svg</file>
     <file alias="flag-wip.svg">flags/standard/edit-undo.svg</file>
 
     <file alias="freemind/attach.png">flags/freemind/attach.png</file>