Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37561323
en ru br
Репозитории ALT

Группа :: Обучение
Пакет: OpenBoard

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: 0009-vector_tool.patch
Скачать


From 9e627a85caeaa4bd8cebc2070b297e1ce6953262 Mon Sep 17 00:00:00 2001
From: thomas_lucky13 <mkoul@mail.ru>
Date: Thu, 24 Nov 2022 17:23:15 +0400
Subject: [PATCH] vector_tool
This is a new stylus tool which is vector. Vector consists of body and arrow at the end.
The directions of arrow can be on three ways:
1. From the beginning of the item.
2. At the end of item.
3. Both ways.
---
 resources/OpenBoard.qrc                     |   5 +
 resources/forms/mainWindow.ui               |  73 ++++++++
 resources/images/stylusPalette/vector.svg   | 142 +++++++++++++++
 resources/images/stylusPalette/vectorOn.svg | 173 ++++++++++++++++++
 resources/images/toolbar/vectorFrom.svg     | 182 +++++++++++++++++++
 resources/images/toolbar/vectorFromTo.svg   | 185 ++++++++++++++++++++
 resources/images/toolbar/vectorTo.svg       | 181 +++++++++++++++++++
 src/api/UBWidgetUniboardAPI.cpp             |   7 +-
 src/board/UBBoardController.cpp             |  35 ++++
 src/board/UBBoardController.h               |   1 +
 src/board/UBBoardView.cpp                   |   5 +-
 src/board/UBDrawingController.cpp           |  29 ++-
 src/board/UBDrawingController.h             |   2 +
 src/core/UB.h                               |  11 ++
 src/core/UBSettings.cpp                     |  33 ++++
 src/core/UBSettings.h                       |   5 +
 src/domain/UBGraphicsPolygonItem.cpp        |  12 ++
 src/domain/UBGraphicsPolygonItem.h          |   1 +
 src/domain/UBGraphicsScene.cpp              |  24 ++-
 src/domain/UBGraphicsScene.h                |   2 +
 src/frameworks/UBGeometryUtils.cpp          | 132 ++++++++++++++
 src/frameworks/UBGeometryUtils.h            |   6 +
 src/gui/UBStylusPalette.cpp                 |   1 +
 src/gui/UBToolbarButtonGroup.cpp            |   1 +
 src/tools/UBGraphicsCompass.cpp             |   6 +-
 25 files changed, 1239 insertions(+), 15 deletions(-)
 create mode 100644 resources/images/stylusPalette/vector.svg
 create mode 100644 resources/images/stylusPalette/vectorOn.svg
 create mode 100644 resources/images/toolbar/vectorFrom.svg
 create mode 100644 resources/images/toolbar/vectorFromTo.svg
 create mode 100644 resources/images/toolbar/vectorTo.svg
diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc
index d655e4ac..b82322ad 100644
--- a/resources/OpenBoard.qrc
+++ b/resources/OpenBoard.qrc
@@ -388,5 +388,10 @@
         <file>images/toolbar/solidLine.svg</file>
         <file>images/toolbar/dottedLine.svg</file>
         <file>images/toolbar/dashedLine.svg</file>
+        <file>images/toolbar/vectorTo.svg</file>
+        <file>images/toolbar/vectorFrom.svg</file>
+        <file>images/toolbar/vectorFromTo.svg</file>
+        <file>images/stylusPalette/vector.svg</file>
+        <file>images/stylusPalette/vectorOn.svg</file>
     </qresource>
 </RCC>
diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui
index 66ac731d..df43794f 100644
--- a/resources/forms/mainWindow.ui
+++ b/resources/forms/mainWindow.ui
@@ -1756,6 +1756,79 @@
     <string>Dotted Line</string>
    </property>
   </action>
+  <action name="actionVector">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../OpenBoard.qrc">
+     <normaloff>:/images/stylusPalette/vector.svg</normaloff>
+     <normalon>:/images/stylusPalette/vectorOn.svg</normalon>:/images/stylusPalette/vector.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Vector</string>
+   </property>
+   <property name="toolTip">
+    <string>Draw Vectors</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+J</string>
+   </property>
+  </action>
+  <action name="actionVectorTo">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../OpenBoard.qrc">
+     <normaloff>:/images/toolbar/vectorTo.svg</normaloff>:/images/toolbar/vectorTo.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Vector Style</string>
+   </property>
+   <property name="toolTip">
+    <string>Vector To</string>
+   </property>
+  </action>
+  <action name="actionVectorFrom">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../OpenBoard.qrc">
+     <normaloff>:/images/toolbar/vectorFrom.svg</normaloff>:/images/toolbar/vectorFrom.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Vector Style</string>
+   </property>
+   <property name="toolTip">
+    <string>Vector From</string>
+   </property>
+  </action>
+  <action name="actionVectorFromTo">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="../OpenBoard.qrc">
+     <normaloff>:/images/toolbar/vectorFromTo.svg</normaloff>:/images/toolbar/vectorFromTo.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Vector Style</string>
+   </property>
+   <property name="toolTip">
+    <string>Vector From To</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../OpenBoard.qrc"/>
diff --git a/resources/images/stylusPalette/vector.svg b/resources/images/stylusPalette/vector.svg
new file mode 100644
index 00000000..33d597fb
--- /dev/null
+++ b/resources/images/stylusPalette/vector.svg
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="42"
+   height="42"
+   viewBox="0 0 42 42"
+   version="1.1"
+   id="svg38508"
+   inkscape:version="1.2 (1:1.2.1+202207142221+cd75a1ee6d)"
+   sodipodi:docname="vector.svg"
+   inkscape:export-filename="/home/dmitry/git/OpenBoard/resources/images/stylusPalette/arrow_svg.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sodipodi:namedview
+     id="namedview38510"
+     pagecolor="#505050"
+     bordercolor="#eeeeee"
+     borderopacity="1"
+     inkscape:pageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="px"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="px"
+     inkscape:zoom="11.313708"
+     inkscape:cx="30.449787"
+     inkscape:cy="17.589282"
+     inkscape:window-width="1920"
+     inkscape:window-height="1007"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g965"
+     inkscape:document-rotation="0"
+     inkscape:snap-others="true"
+     inkscape:snap-global="false"
+     inkscape:showpageshadow="2"
+     inkscape:deskcolor="#505050">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7387"
+       dotted="false" />
+  </sodipodi:namedview>
+  <defs
+     id="defs38505">
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5-3"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2-7" />
+    </filter>
+  </defs>
+  <g
+     inkscape:label="icon"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-152.84748,-194.2822)">
+    <g
+       id="g965"
+       inkscape:label="vector">
+      <g
+         id="path1289"
+         style="display:inline"
+         transform="matrix(0.58714609,0,0,0.6676642,71.780858,71.552147)"
+         inkscape:label="vector">
+        <path
+           style="color:#000000;fill:#000000;stroke-linecap:round;-inkscape-stroke:none"
+           d="m 194.19531,194.88672 a 2,2 0 0 0 -2.82812,0.01 l -37.67774,37.91993 a 2,2 0 0 0 0.01,2.82812 2,2 0 0 0 2.82812,-0.008 l 37.67774,-37.92188 a 2,2 0 0 0 -0.01,-2.82812 z"
+           id="path1344" />
+        <g
+           id="g1330">
+          <path
+             style="color:#000000;fill:#000000;-inkscape-stroke:none"
+             d="m 194.83573,194.2705 -18.9707,0.0605 0.0137,4 14.96875,-0.0488 0.0488,14.97071 4,-0.0117 z"
+             id="path1338" />
+          <path
+             style="color:#000000;display:inline;fill:#000000;-inkscape-stroke:none"
+             d="m 152.83378,236.27045 0.0625,-18.9707 4,0.0137 -0.0488,14.96875 14.9707,0.0488 -0.0137,4 z"
+             id="path1332" />
+        </g>
+      </g>
+    </g>
+  </g>
+  <metadata
+     id="metadata854">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <cc:license
+           rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
+        <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>
+</svg>
diff --git a/resources/images/stylusPalette/vectorOn.svg b/resources/images/stylusPalette/vectorOn.svg
new file mode 100644
index 00000000..021a7652
--- /dev/null
+++ b/resources/images/stylusPalette/vectorOn.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="42"
+   height="42"
+   viewBox="0 0 42 42"
+   version="1.1"
+   id="svg38508"
+   inkscape:version="1.2 (1:1.2.1+202207142221+cd75a1ee6d)"
+   sodipodi:docname="vector.svg"
+   inkscape:export-filename="/home/dmitry/git/OpenBoard/resources/images/stylusPalette/arrow_svg.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sodipodi:namedview
+     id="namedview38510"
+     pagecolor="#505050"
+     bordercolor="#eeeeee"
+     borderopacity="1"
+     inkscape:pageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="px"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="px"
+     inkscape:zoom="11.313708"
+     inkscape:cx="30.361399"
+     inkscape:cy="17.500894"
+     inkscape:window-width="1920"
+     inkscape:window-height="1007"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g965"
+     inkscape:document-rotation="0"
+     inkscape:snap-others="true"
+     inkscape:snap-global="false"
+     inkscape:showpageshadow="2"
+     inkscape:deskcolor="#505050">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7387"
+       dotted="false" />
+  </sodipodi:namedview>
+  <defs
+     id="defs38505">
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5-3"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2-7" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient39514"
+       id="radialGradient39516"
+       cx="160.25581"
+       cy="201.69054"
+       fx="160.25581"
+       fy="201.69054"
+       r="7.2760415"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.8861847,0,0,2.8861847,-288.68039,-366.83393)" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient39514">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="0"
+         id="stop39510" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="1"
+         id="stop39512" />
+    </linearGradient>
+  </defs>
+  <g
+     inkscape:label="icon"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-152.84748,-194.2822)">
+    <g
+       id="g965"
+       inkscape:label="vectorOn">
+      <circle
+         style="display:inline;fill:url(#radialGradient39516);fill-opacity:1;stroke-width:0.0457296;stroke-linecap:round;stroke-linejoin:round"
+         id="path38960"
+         cx="173.84747"
+         cy="215.2822"
+         r="21"
+         inkscape:label="circleBackground" />
+      <g
+         id="path1289"
+         style="display:inline"
+         transform="matrix(0.58714609,0,0,0.6676642,71.780858,71.552147)"
+         inkscape:label="vector">
+        <path
+           style="color:#000000;fill:#000000;stroke-linecap:round;-inkscape-stroke:none"
+           d="m 194.19531,194.88672 a 2,2 0 0 0 -2.82812,0.01 l -37.67774,37.91993 a 2,2 0 0 0 0.01,2.82812 2,2 0 0 0 2.82812,-0.008 l 37.67774,-37.92188 a 2,2 0 0 0 -0.01,-2.82812 z"
+           id="path1344" />
+        <g
+           id="g1330">
+          <path
+             style="color:#000000;fill:#000000;-inkscape-stroke:none"
+             d="m 194.83573,194.2705 -18.9707,0.0605 0.0137,4 14.96875,-0.0488 0.0488,14.97071 4,-0.0117 z"
+             id="path1338" />
+          <path
+             style="color:#000000;display:inline;fill:#000000;-inkscape-stroke:none"
+             d="m 152.83378,236.27045 0.0625,-18.9707 4,0.0137 -0.0488,14.96875 14.9707,0.0488 -0.0137,4 z"
+             id="path1332" />
+        </g>
+      </g>
+    </g>
+  </g>
+  <metadata
+     id="metadata854">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <cc:license
+           rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
+        <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>
+</svg>
diff --git a/resources/images/toolbar/vectorFrom.svg b/resources/images/toolbar/vectorFrom.svg
new file mode 100644
index 00000000..494b7cb7
--- /dev/null
+++ b/resources/images/toolbar/vectorFrom.svg
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="42"
+   height="42"
+   viewBox="0 0 42 42"
+   version="1.1"
+   id="svg38508"
+   inkscape:version="1.2 (1:1.2.1+202207142221+cd75a1ee6d)"
+   sodipodi:docname="vectorDown.svg"
+   inkscape:export-filename="/home/dmitry/git/OpenBoard/resources/images/stylusPalette/arrow_svg.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sodipodi:namedview
+     id="namedview38510"
+     pagecolor="#505050"
+     bordercolor="#eeeeee"
+     borderopacity="1"
+     inkscape:pageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="px"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="px"
+     inkscape:zoom="5.656854"
+     inkscape:cx="-49.409089"
+     inkscape:cy="24.748738"
+     inkscape:window-width="1920"
+     inkscape:window-height="1007"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g1330"
+     inkscape:document-rotation="0"
+     inkscape:snap-others="true"
+     inkscape:snap-global="false"
+     inkscape:showpageshadow="2"
+     inkscape:deskcolor="#505050">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7387"
+       dotted="false" />
+  </sodipodi:namedview>
+  <defs
+     id="defs38505">
+    <marker
+       style="overflow:visible"
+       id="marker1157"
+       refX="0"
+       refY="0"
+       orient="auto-start-reverse"
+       inkscape:stockid="Arrow1"
+       markerWidth="4.0606604"
+       markerHeight="6.7071066"
+       viewBox="0 0 4.0606602 6.7071068"
+       inkscape:isstock="true"
+       inkscape:collect="always"
+       preserveAspectRatio="xMidYMid">
+      <path
+         style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
+         d="M 3,-3 0,0 3,3"
+         id="path1155"
+         transform="rotate(180,0.125,0)"
+         sodipodi:nodetypes="ccc" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1"
+       refX="0"
+       refY="0"
+       orient="auto-start-reverse"
+       inkscape:stockid="Arrow1"
+       markerWidth="4.0606604"
+       markerHeight="6.7071066"
+       viewBox="0 0 4.0606602 6.7071068"
+       inkscape:isstock="true"
+       inkscape:collect="always"
+       preserveAspectRatio="xMidYMid">
+      <path
+         style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
+         d="M 3,-3 0,0 3,3"
+         id="path5057"
+         transform="rotate(180,0.125,0)"
+         sodipodi:nodetypes="ccc" />
+    </marker>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5-3"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2-7" />
+    </filter>
+  </defs>
+  <g
+     inkscape:label="icon"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-152.84748,-194.2822)">
+    <g
+       id="g965"
+       inkscape:label="line">
+      <path
+         style="display:none;fill:none;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1);marker-end:url(#marker1157)"
+         d="M 155.10847,234.22611 192.7862,196.30525"
+         id="path963"
+         sodipodi:nodetypes="cc"
+         sodipodi:insensitive="true" />
+      <g
+         id="path1289">
+        <path
+           style="color:#000000;fill:#000000;stroke-linecap:round;-inkscape-stroke:none"
+           d="m 194.30563,194.88672 a 2,2 0 0 0 -2.82812,0.01 l -37.67774,37.91993 a 2,2 0 0 0 0.01,2.82812 2,2 0 0 0 2.82812,-0.008 l 37.67774,-37.92188 a 2,2 0 0 0 -0.01,-2.82812 z"
+           id="path1344" />
+        <g
+           id="g1330"
+           transform="matrix(-1,0,0,1,347.73006,0)">
+          <path
+             style="color:#000000;fill:#000000;-inkscape-stroke:none"
+             d="m 194.78596,236.27045 -0.0625,-18.9707 -4,0.0137 0.0488,14.96875 -14.9707,0.0488 0.0137,4 z"
+             id="path1332" />
+        </g>
+      </g>
+    </g>
+  </g>
+  <metadata
+     id="metadata854">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <cc:license
+           rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
+        <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>
+</svg>
diff --git a/resources/images/toolbar/vectorFromTo.svg b/resources/images/toolbar/vectorFromTo.svg
new file mode 100644
index 00000000..50ba0ba1
--- /dev/null
+++ b/resources/images/toolbar/vectorFromTo.svg
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="42"
+   height="42"
+   viewBox="0 0 42 42"
+   version="1.1"
+   id="svg38508"
+   inkscape:version="1.2 (1:1.2.1+202207142221+cd75a1ee6d)"
+   sodipodi:docname="verctor.svg"
+   inkscape:export-filename="/home/dmitry/git/OpenBoard/resources/images/stylusPalette/arrow_svg.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sodipodi:namedview
+     id="namedview38510"
+     pagecolor="#505050"
+     bordercolor="#eeeeee"
+     borderopacity="1"
+     inkscape:pageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="px"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="px"
+     inkscape:zoom="5.656854"
+     inkscape:cx="-7.8665633"
+     inkscape:cy="24.395185"
+     inkscape:window-width="1920"
+     inkscape:window-height="1007"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g965"
+     inkscape:document-rotation="0"
+     inkscape:snap-others="true"
+     inkscape:snap-global="false"
+     inkscape:showpageshadow="2"
+     inkscape:deskcolor="#505050">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7387"
+       dotted="false" />
+  </sodipodi:namedview>
+  <defs
+     id="defs38505">
+    <marker
+       style="overflow:visible"
+       id="marker1157"
+       refX="0"
+       refY="0"
+       orient="auto-start-reverse"
+       inkscape:stockid="Arrow1"
+       markerWidth="4.0606604"
+       markerHeight="6.7071066"
+       viewBox="0 0 4.0606602 6.7071068"
+       inkscape:isstock="true"
+       inkscape:collect="always"
+       preserveAspectRatio="xMidYMid">
+      <path
+         style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
+         d="M 3,-3 0,0 3,3"
+         id="path1155"
+         transform="rotate(180,0.125,0)"
+         sodipodi:nodetypes="ccc" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1"
+       refX="0"
+       refY="0"
+       orient="auto-start-reverse"
+       inkscape:stockid="Arrow1"
+       markerWidth="4.0606604"
+       markerHeight="6.7071066"
+       viewBox="0 0 4.0606602 6.7071068"
+       inkscape:isstock="true"
+       inkscape:collect="always"
+       preserveAspectRatio="xMidYMid">
+      <path
+         style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
+         d="M 3,-3 0,0 3,3"
+         id="path5057"
+         transform="rotate(180,0.125,0)"
+         sodipodi:nodetypes="ccc" />
+    </marker>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5-3"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2-7" />
+    </filter>
+  </defs>
+  <g
+     inkscape:label="icon"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-152.84748,-194.2822)">
+    <g
+       id="g965"
+       inkscape:label="line">
+      <path
+         style="display:none;fill:none;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1);marker-end:url(#marker1157)"
+         d="M 155.10847,234.22611 192.7862,196.30525"
+         id="path963"
+         sodipodi:nodetypes="cc"
+         sodipodi:insensitive="true" />
+      <g
+         id="path1289">
+        <path
+           style="color:#000000;fill:#000000;stroke-linecap:round;-inkscape-stroke:none"
+           d="m 194.19531,194.88672 a 2,2 0 0 0 -2.82812,0.01 l -37.67774,37.91993 a 2,2 0 0 0 0.01,2.82812 2,2 0 0 0 2.82812,-0.008 l 37.67774,-37.92188 a 2,2 0 0 0 -0.01,-2.82812 z"
+           id="path1344" />
+        <g
+           id="g1330">
+          <path
+             style="color:#000000;fill:#000000;-inkscape-stroke:none"
+             d="m 194.83573,194.2705 -18.9707,0.0605 0.0137,4 14.96875,-0.0488 0.0488,14.97071 4,-0.0117 z"
+             id="path1338" />
+          <path
+             style="color:#000000;fill:#000000;-inkscape-stroke:none"
+             d="m 152.83378,236.27045 0.0625,-18.9707 4,0.0137 -0.0488,14.96875 14.9707,0.0488 -0.0137,4 z"
+             id="path1332" />
+        </g>
+      </g>
+    </g>
+  </g>
+  <metadata
+     id="metadata854">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <cc:license
+           rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
+        <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>
+</svg>
diff --git a/resources/images/toolbar/vectorTo.svg b/resources/images/toolbar/vectorTo.svg
new file mode 100644
index 00000000..6c0e5bdc
--- /dev/null
+++ b/resources/images/toolbar/vectorTo.svg
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="42"
+   height="42"
+   viewBox="0 0 42 42"
+   version="1.1"
+   id="svg38508"
+   inkscape:version="1.2 (1:1.2.1+202207142221+cd75a1ee6d)"
+   sodipodi:docname="verctorUp.svg"
+   inkscape:export-filename="/home/dmitry/git/OpenBoard/resources/images/stylusPalette/arrow_svg.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sodipodi:namedview
+     id="namedview38510"
+     pagecolor="#505050"
+     bordercolor="#eeeeee"
+     borderopacity="1"
+     inkscape:pageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="px"
+     showgrid="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="px"
+     inkscape:zoom="5.656854"
+     inkscape:cx="-49.409089"
+     inkscape:cy="24.748738"
+     inkscape:window-width="1920"
+     inkscape:window-height="1007"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g1330"
+     inkscape:document-rotation="0"
+     inkscape:snap-others="true"
+     inkscape:snap-global="false"
+     inkscape:showpageshadow="2"
+     inkscape:deskcolor="#505050">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7387"
+       dotted="false" />
+  </sodipodi:namedview>
+  <defs
+     id="defs38505">
+    <marker
+       style="overflow:visible"
+       id="marker1157"
+       refX="0"
+       refY="0"
+       orient="auto-start-reverse"
+       inkscape:stockid="Arrow1"
+       markerWidth="4.0606604"
+       markerHeight="6.7071066"
+       viewBox="0 0 4.0606602 6.7071068"
+       inkscape:isstock="true"
+       inkscape:collect="always"
+       preserveAspectRatio="xMidYMid">
+      <path
+         style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
+         d="M 3,-3 0,0 3,3"
+         id="path1155"
+         transform="rotate(180,0.125,0)"
+         sodipodi:nodetypes="ccc" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1"
+       refX="0"
+       refY="0"
+       orient="auto-start-reverse"
+       inkscape:stockid="Arrow1"
+       markerWidth="4.0606604"
+       markerHeight="6.7071066"
+       viewBox="0 0 4.0606602 6.7071068"
+       inkscape:isstock="true"
+       inkscape:collect="always"
+       preserveAspectRatio="xMidYMid">
+      <path
+         style="fill:none;stroke:context-stroke;stroke-width:1;stroke-linecap:butt"
+         d="M 3,-3 0,0 3,3"
+         id="path5057"
+         transform="rotate(180,0.125,0)"
+         sodipodi:nodetypes="ccc" />
+    </marker>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2" />
+    </filter>
+    <filter
+       style="color-interpolation-filters:sRGB"
+       id="filter37990-9-5-3"
+       inkscape:label="shadowFilter"
+       x="-0.067811772"
+       y="-0.07751945"
+       width="1.1356235"
+       height="1.1873387">
+      <feGaussianBlur
+         stdDeviation="0.29999999999999999"
+         id="feGaussianBlur37992-3-6-6" />
+      <feOffset
+         dx="0"
+         dy="0.29999999999999999"
+         id="feOffset37994-2-2-7" />
+    </filter>
+  </defs>
+  <g
+     inkscape:label="icon"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-152.84748,-194.2822)">
+    <g
+       id="g965"
+       inkscape:label="line">
+      <path
+         style="display:none;fill:none;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1);marker-end:url(#marker1157)"
+         d="M 155.10847,234.22611 192.7862,196.30525"
+         id="path963"
+         sodipodi:nodetypes="cc"
+         sodipodi:insensitive="true" />
+      <g
+         id="path1289">
+        <path
+           style="color:#000000;fill:#000000;stroke-linecap:round;-inkscape-stroke:none"
+           d="m 194.19531,194.88672 a 2,2 0 0 0 -2.82812,0.01 l -37.67774,37.91993 a 2,2 0 0 0 0.01,2.82812 2,2 0 0 0 2.82812,-0.008 l 37.67774,-37.92188 a 2,2 0 0 0 -0.01,-2.82812 z"
+           id="path1344" />
+        <g
+           id="g1330">
+          <path
+             style="color:#000000;fill:#000000;-inkscape-stroke:none"
+             d="m 194.83573,194.2705 -18.9707,0.0605 0.0137,4 14.96875,-0.0488 0.0488,14.97071 4,-0.0117 z"
+             id="path1338" />
+        </g>
+      </g>
+    </g>
+  </g>
+  <metadata
+     id="metadata854">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <cc:license
+           rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
+        <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>
+</svg>
diff --git a/src/api/UBWidgetUniboardAPI.cpp b/src/api/UBWidgetUniboardAPI.cpp
index 14c04019..468c8c3b 100644
--- a/src/api/UBWidgetUniboardAPI.cpp
+++ b/src/api/UBWidgetUniboardAPI.cpp
@@ -145,6 +145,10 @@ void UBWidgetUniboardAPI::setTool(const QString& toolString)
     {
         UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Line);
     }
+    else if (lower == "vector")
+    {
+        UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Vector);
+    }
 }
 
 
@@ -251,7 +255,8 @@ void UBWidgetUniboardAPI::drawLineTo(const qreal x, const qreal y, const qreal p
 
     if (mScene)
     mScene->drawLineTo(QPointF(x, y), pWidth, 
-        UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line);
+        UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line
+                       || UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Vector);
 }
 
 
diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp
index 3c95cd4a..740f842c 100644
--- a/src/board/UBBoardController.cpp
+++ b/src/board/UBBoardController.cpp
@@ -396,6 +396,27 @@ void UBBoardController::setupToolbar()
     lineStyleChoice->setCurrentIndex(settings->lineStyleIndex());
     lineStyleActions.at(settings->lineStyleIndex())->setChecked(true);
     mPropertyPaletteWidgets.insert(lineStyle, newPropertyPaletteWidget);
+    //-----------------------------------------------------------//
+    // Setup vector style choice widget
+    QList<QAction *> vectorStyleActions;
+    vectorStyleActions.append(mMainWindow->actionVectorTo);
+    vectorStyleActions.append(mMainWindow->actionVectorFrom);
+    vectorStyleActions.append(mMainWindow->actionVectorFromTo);
+
+    UBToolbarButtonGroup *vectorStyleChoice =
+    new UBToolbarButtonGroup(mMainWindow->boardToolBar, vectorStyleActions);
+
+    connect(settings->appToolBarDisplayText, SIGNAL(changed(QVariant)), vectorStyleChoice, SLOT(displayText(QVariant)));
+
+    connect(vectorStyleChoice, SIGNAL(activated(int)),
+    UBDrawingController::drawingController(), SLOT(setVectorStyleIndex(int)));
+
+    vectorStyleChoice->displayText(QVariant(settings->appToolBarDisplayText->get().toBool()));
+    newPropertyPaletteWidget = mMainWindow->boardToolBar->insertWidget(mMainWindow->actionBackgrounds, vectorStyleChoice);
+    vectorStyleChoice->setCurrentIndex(settings->vectorStyleIndex());
+    vectorStyleActions.at(settings->vectorStyleIndex())->setChecked(true);
+    mPropertyPaletteWidgets.insert(vectorStyle, newPropertyPaletteWidget);
+
     //-----------------------------------------------------------//
 
     UBApplication::app()->insertSpaceToToolbarBeforeAction(mMainWindow->boardToolBar, mMainWindow->actionBackgrounds);
@@ -2005,6 +2026,7 @@ void UBBoardController::setColorIndex(int pColorIndex)
 
     if (UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Marker &&
             UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Line &&
+            UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Vector &&
             UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Text &&
             UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Selector)
     {
@@ -2013,6 +2035,7 @@ void UBBoardController::setColorIndex(int pColorIndex)
 
     if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Pen ||
             UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line ||
+            UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Vector ||
             UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Text ||
             UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Selector)
     {
@@ -2231,6 +2254,7 @@ void UBBoardController::stylusToolChanged(int tool)
             mPropertyPaletteWidgets[lineWidth]->setVisible(true);
             mPropertyPaletteWidgets[eraserWidth]->setVisible(false);
             mPropertyPaletteWidgets[lineStyle]->setVisible(false);
+            mPropertyPaletteWidgets[vectorStyle]->setVisible(false);
         } else
         if (eTool == UBStylusTool::Eraser)
         {
@@ -2238,6 +2262,7 @@ void UBBoardController::stylusToolChanged(int tool)
             mPropertyPaletteWidgets[lineWidth]->setVisible(false);
             mPropertyPaletteWidgets[eraserWidth]->setVisible(true);
             mPropertyPaletteWidgets[lineStyle]->setVisible(false);
+            mPropertyPaletteWidgets[vectorStyle]->setVisible(false);
         } else
         if (eTool == UBStylusTool::Line)
         {
@@ -2245,12 +2270,22 @@ void UBBoardController::stylusToolChanged(int tool)
             mPropertyPaletteWidgets[lineWidth]->setVisible(true);
             mPropertyPaletteWidgets[eraserWidth]->setVisible(false);
             mPropertyPaletteWidgets[lineStyle]->setVisible(true);
+            mPropertyPaletteWidgets[vectorStyle]->setVisible(false);
+        } else
+        if (eTool == UBStylusTool::Vector)
+        {
+            mPropertyPaletteWidgets[color]->setVisible(true);
+            mPropertyPaletteWidgets[lineWidth]->setVisible(true);
+            mPropertyPaletteWidgets[eraserWidth]->setVisible(false);
+            mPropertyPaletteWidgets[lineStyle]->setVisible(false);
+            mPropertyPaletteWidgets[vectorStyle]->setVisible(true);
         } else
         {
             mPropertyPaletteWidgets[color]->setVisible(false);
             mPropertyPaletteWidgets[lineWidth]->setVisible(false);
             mPropertyPaletteWidgets[eraserWidth]->setVisible(false);
             mPropertyPaletteWidgets[lineStyle]->setVisible(false);
+            mPropertyPaletteWidgets[vectorStyle]->setVisible(false);
         }
 
 }
diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h
index 8e6618f2..baa06fc4 100644
--- a/src/board/UBBoardController.h
+++ b/src/board/UBBoardController.h
@@ -327,6 +327,7 @@ class UBBoardController : public UBDocumentContainer
             color,
             lineWidth,
             lineStyle,
+            vectorStyle,
             eraserWidth
         };
         QMap<PropertyPalette, QAction*> mPropertyPaletteWidgets;
diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp
index 97c8e2af..366b74ae 100644
--- a/src/board/UBBoardView.cpp
+++ b/src/board/UBBoardView.cpp
@@ -367,7 +367,7 @@ void UBBoardView::tabletEvent (QTabletEvent * event)
     QPointF scenePos = viewportTransform ().inverted ().map (tabletPos);
 
     qreal pressure = 1.0;
-    if (((currentTool == UBStylusTool::Pen || currentTool == UBStylusTool::Line) && mPenPressureSensitive) ||
+    if (((currentTool == UBStylusTool::Pen || currentTool == UBStylusTool::Line || currentTool == UBStylusTool::Vector) && mPenPressureSensitive) ||
             (currentTool == UBStylusTool::Marker && mMarkerPressureSensitive))
         pressure = event->pressure ();
     else{
@@ -1821,6 +1821,9 @@ void UBBoardView::setToolCursor (int tool)
     case UBStylusTool::Line:
         controlViewport->setCursor (UBResources::resources ()->penCursor);
         break;
+    case UBStylusTool::Vector:
+        controlViewport->setCursor (UBResources::resources ()->penCursor);
+        break;
     case UBStylusTool::Text:
         controlViewport->setCursor (UBResources::resources ()->textCursor);
         break;
diff --git a/src/board/UBDrawingController.cpp b/src/board/UBDrawingController.cpp
index ab6b39d4..086ce13c 100644
--- a/src/board/UBDrawingController.cpp
+++ b/src/board/UBDrawingController.cpp
@@ -75,6 +75,7 @@ UBDrawingController::UBDrawingController(QObject * parent)
     connect(UBApplication::mainWindow->actionZoomOut, SIGNAL(triggered(bool)), this, SLOT(zoomOutToolSelected(bool)));
     connect(UBApplication::mainWindow->actionPointer, SIGNAL(triggered(bool)), this, SLOT(pointerToolSelected(bool)));
     connect(UBApplication::mainWindow->actionLine, SIGNAL(triggered(bool)), this, SLOT(lineToolSelected(bool)));
+    connect(UBApplication::mainWindow->actionVector, SIGNAL(triggered(bool)), this, SLOT(vectorToolSelected(bool)));
     connect(UBApplication::mainWindow->actionText, SIGNAL(triggered(bool)), this, SLOT(textToolSelected(bool)));
     connect(UBApplication::mainWindow->actionCapture, SIGNAL(triggered(bool)), this, SLOT(captureToolSelected(bool)));
 }
@@ -104,12 +105,12 @@ void UBDrawingController::setStylusTool(int tool)
     {
         UBApplication::boardController->activeScene()->deselectAllItems();
         if (mStylusTool == UBStylusTool::Pen || mStylusTool == UBStylusTool::Marker
-                || mStylusTool == UBStylusTool::Line)
+                || mStylusTool == UBStylusTool::Line || mStylusTool == UBStylusTool::Vector)
         {
             mLatestDrawingTool = mStylusTool;
         }
 
-        if (tool == UBStylusTool::Pen || tool == UBStylusTool::Line)
+        if (tool == UBStylusTool::Pen || tool == UBStylusTool::Line || tool == UBStylusTool::Vector)
         {
              emit lineWidthIndexChanged(UBSettings::settings()->penWidthIndex());
              emit colorIndexChanged(UBSettings::settings()->penColorIndex());
@@ -144,6 +145,8 @@ void UBDrawingController::setStylusTool(int tool)
             UBApplication::mainWindow->actionPointer->setChecked(true);
         else if (mStylusTool == UBStylusTool::Line)
             UBApplication::mainWindow->actionLine->setChecked(true);
+        else if (mStylusTool == UBStylusTool::Vector)
+            UBApplication::mainWindow->actionVector->setChecked(true);
         else if (mStylusTool == UBStylusTool::Text)
             UBApplication::mainWindow->actionText->setChecked(true);
         else if (mStylusTool == UBStylusTool::Capture)
@@ -160,13 +163,14 @@ bool UBDrawingController::isDrawingTool()
 {
     return (stylusTool() == UBStylusTool::Pen)
             || (stylusTool() == UBStylusTool::Marker)
+            || (stylusTool() == UBStylusTool::Vector)
             || (stylusTool() == UBStylusTool::Line);
 }
 
 
 int UBDrawingController::currentToolWidthIndex()
 {
-    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line)
+    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line || stylusTool() == UBStylusTool::Vector)
         return UBSettings::settings()->penWidthIndex();
     else if (stylusTool() == UBStylusTool::Marker)
         return UBSettings::settings()->markerWidthIndex();
@@ -177,7 +181,7 @@ int UBDrawingController::currentToolWidthIndex()
 
 qreal UBDrawingController::currentToolWidth()
 {
-    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line)
+    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line || stylusTool() == UBStylusTool::Vector)
         return UBSettings::settings()->currentPenWidth();
     else if (stylusTool() == UBStylusTool::Marker)
         return UBSettings::settings()->currentMarkerWidth();
@@ -198,6 +202,7 @@ void UBDrawingController::setLineWidthIndex(int index)
         UBSettings::settings()->setPenWidthIndex(index);
 
         if(stylusTool() != UBStylusTool::Line
+            && stylusTool() != UBStylusTool::Vector
             && stylusTool() != UBStylusTool::Selector)
         {
             setStylusTool(UBStylusTool::Pen);
@@ -210,7 +215,7 @@ void UBDrawingController::setLineWidthIndex(int index)
 
 int UBDrawingController::currentToolColorIndex()
 {
-    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line)
+    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line || stylusTool() == UBStylusTool::Vector)
     {
         return UBSettings::settings()->penColorIndex();
     }
@@ -233,7 +238,7 @@ QColor UBDrawingController::currentToolColor()
 
 QColor UBDrawingController::toolColor(bool onDarkBackground)
 {
-    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line)
+    if (stylusTool() == UBStylusTool::Pen || stylusTool() == UBStylusTool::Line || stylusTool() == UBStylusTool::Vector)
     {
         return UBSettings::settings()->penColor(onDarkBackground);
     }
@@ -284,6 +289,11 @@ void UBDrawingController::setLineStyleIndex(int index)
     UBSettings::settings()->setLineStyleIndex(index);
 }
 
+void UBDrawingController::setVectorStyleIndex(int index)
+{
+    UBSettings::settings()->setVectorStyleIndex(index);
+}
+
 void UBDrawingController::setPenColor(bool onDarkBackground, const QColor& color, int pIndex)
 {
     if (onDarkBackground)
@@ -396,6 +406,13 @@ void UBDrawingController::lineToolSelected(bool checked)
 }
 
 
+void UBDrawingController::vectorToolSelected(bool checked)
+{
+    if (checked)
+        setStylusTool(UBStylusTool::Vector);
+}
+
+
 void UBDrawingController::textToolSelected(bool checked)
 {
     if (checked)
diff --git a/src/board/UBDrawingController.h b/src/board/UBDrawingController.h
index 617bc824..b857caa9 100644
--- a/src/board/UBDrawingController.h
+++ b/src/board/UBDrawingController.h
@@ -81,6 +81,7 @@ class UBDrawingController : public QObject
         void setColorIndex(int index);
         void setEraserWidthIndex(int index);
         void setLineStyleIndex(int index);
+        void setVectorStyleIndex(int index);
 
     signals:
         void stylusToolChanged(int tool, int previousTool = -1);
@@ -108,6 +109,7 @@ class UBDrawingController : public QObject
         void zoomOutToolSelected(bool checked);
         void pointerToolSelected(bool checked);
         void lineToolSelected(bool checked);
+        void vectorToolSelected(bool checked);
         void textToolSelected(bool checked);
         void captureToolSelected(bool checked);
 };
diff --git a/src/core/UB.h b/src/core/UB.h
index 9c5552b4..a40ae4c1 100644
--- a/src/core/UB.h
+++ b/src/core/UB.h
@@ -71,6 +71,7 @@ struct UBStylusTool
         ZoomOut,
         Pointer,
         Line,
+        Vector,
         Text,
         Capture
     };
@@ -94,6 +95,16 @@ struct UBLineStyle
     };
 };
 
+struct UBVectorStyle
+{
+    enum Enum
+    {
+        To = 0,
+        From = 1,
+        FromTo = 2
+    };
+};
+
 struct UBZoom
 {
     enum Enum
diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp
index 994b51d8..b19235a2 100644
--- a/src/core/UBSettings.cpp
+++ b/src/core/UBSettings.cpp
@@ -817,6 +817,39 @@ UBLineStyle::Enum UBSettings::currentLineStyle()
 
     return UBLineStyle::Solid;
 }
+
+//----------------------------------------//
+// vector
+int UBSettings::vectorStyleIndex()
+{
+    return value("Board/VectorStyleIndex", 0).toInt();
+}
+
+void UBSettings::setVectorStyleIndex(int index)
+{
+    setValue("Board/VectorStyleIndex", index);
+}
+UBVectorStyle::Enum UBSettings::currentVectorStyle()
+{
+    switch (vectorStyleIndex())
+    {
+    case UBVectorStyle::To:
+        return UBVectorStyle::To;
+        break;
+    case UBVectorStyle::From:
+        return UBVectorStyle::From;
+        break;
+    case UBVectorStyle::FromTo:
+        return UBVectorStyle::FromTo;
+        break;
+    default:
+        Q_ASSERT(false);
+        return UBVectorStyle::To;
+        break;
+    }
+    return UBVectorStyle::To;
+}
+
 bool UBSettings::isDarkBackground()
 {
     return value("Board/DarkBackground", 0).toBool();
diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h
index 02a5366f..eec4f788 100644
--- a/src/core/UBSettings.h
+++ b/src/core/UBSettings.h
@@ -89,6 +89,10 @@ class UBSettings : public QObject
         int lineStyleIndex();
         UBLineStyle::Enum currentLineStyle();
 
+        // Vector related
+        int vectorStyleIndex();
+        UBVectorStyle::Enum currentVectorStyle();
+
         // Background related
         bool isDarkBackground();
         UBPageBackground pageBackground();
@@ -448,6 +452,7 @@ class UBSettings : public QObject
         void setEraserStrongWidth(qreal width);
 
         void setLineStyleIndex(int index);
+        void setVectorStyleIndex(int index);
 
          void setStylusPaletteVisible(bool visible);
 
diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp
index 65820f30..bd85b1ed 100644
--- a/src/domain/UBGraphicsPolygonItem.cpp
+++ b/src/domain/UBGraphicsPolygonItem.cpp
@@ -85,6 +85,18 @@ UBGraphicsPolygonItem::UBGraphicsPolygonItem (const QLineF& pLine, qreal pWidth,
     initialize();
 }
 
+UBGraphicsPolygonItem::UBGraphicsPolygonItem (const QLineF& pLine, UBVectorStyle::Enum style, qreal pWidth)
+    : QGraphicsPolygonItem(UBGeometryUtils::vectorToPolygon(pLine, pWidth, style))
+    , mOriginalLine(pLine)
+    , mOriginalWidth(pWidth)
+    , mIsNominalLine(true)
+    , mStroke(0)
+    , mpGroup(NULL)
+{
+    // NOOP
+    initialize();
+}
+
 UBGraphicsPolygonItem::UBGraphicsPolygonItem (const QLineF& pLine, qreal pStartWidth, qreal pEndWidth)
     : QGraphicsPolygonItem(UBGeometryUtils::lineToPolygon(pLine, pStartWidth, pEndWidth))
     , mOriginalLine(pLine)
diff --git a/src/domain/UBGraphicsPolygonItem.h b/src/domain/UBGraphicsPolygonItem.h
index fb7bdf9f..5236261c 100644
--- a/src/domain/UBGraphicsPolygonItem.h
+++ b/src/domain/UBGraphicsPolygonItem.h
@@ -46,6 +46,7 @@ class UBGraphicsPolygonItem : public QGraphicsPolygonItem, public UBItem
 
         UBGraphicsPolygonItem(QGraphicsItem * parent = 0 );
         UBGraphicsPolygonItem(const QLineF& line, qreal pWidth, UBLineStyle::Enum style);
+        UBGraphicsPolygonItem(const QLineF& line, UBVectorStyle::Enum style, qreal pWidth);
         UBGraphicsPolygonItem(const QLineF& line, qreal pWidth);
         UBGraphicsPolygonItem(const QLineF& pLine, qreal pStartWidth, qreal pEndWidth);
         UBGraphicsPolygonItem(const QPolygonF & polygon, QGraphicsItem * parent = 0);
diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp
index bccf4679..f01a2c46 100644
--- a/src/domain/UBGraphicsScene.cpp
+++ b/src/domain/UBGraphicsScene.cpp
@@ -436,7 +436,7 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre
             // ---------------------------------------------------------------
             mCurrentStroke = new UBGraphicsStroke(this);
 
-            if (currentTool != UBStylusTool::Line){
+            if (currentTool != UBStylusTool::Line && currentTool != UBStylusTool::Vector){
                 // Handle the pressure
                 width = UBDrawingController::drawingController()->currentToolWidth() * pressure;
             }
@@ -455,7 +455,8 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre
                 UBDrawingController::drawingController()->mActiveRuler->StartLine(scenePos, width);
             else {
                 moveTo(scenePos);
-                drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line);
+                drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line
+                           || UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Vector);
 
                 mCurrentStroke->addPoint(scenePos, width);
             }
@@ -528,7 +529,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres
         {
             qreal width = 0;
 
-            if (currentTool != UBStylusTool::Line){
+            if (currentTool != UBStylusTool::Line && currentTool != UBStylusTool::Vector){
                 // Handle the pressure
                 width = dc->currentToolWidth() * qMax(pressure, 0.2);
             }else{
@@ -539,7 +540,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres
             width /= UBApplication::boardController->systemScaleFactor();
             width /= UBApplication::boardController->currentZoom();
-            if (currentTool == UBStylusTool::Line || dc->activeRuler())
+            if (currentTool == UBStylusTool::Line || currentTool == UBStylusTool::Vector || dc->activeRuler())
             {
                 if (UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Marker)
                 if(NULL != mpLastPolygon && NULL != mCurrentStroke && mAddedItems.size() > 0){
@@ -577,7 +578,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres
                 dc->mActiveRuler->DrawLine(position, width);
             }
 
-            else if (currentTool == UBStylusTool::Line) {
+            else if (currentTool == UBStylusTool::Line || currentTool == UBStylusTool::Vector) {
                 drawLineTo(position, width, true);
             }
 
@@ -949,6 +950,10 @@ void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &startWid
     {
         polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), endWidth, UBSettings::settings()->currentLineStyle());
     } else
+    if(UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Vector)
+    {
+        polygonItem = vectorToPolygonItem(QLineF(mPreviousPoint, pEndPoint), endWidth, UBSettings::settings()->currentVectorStyle());
+    } else
     {
          polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), initialWidth, endWidth);
     }
@@ -1255,6 +1260,15 @@ UBGraphicsPolygonItem* UBGraphicsScene::lineToPolygonItem(const QLineF &pLine, c
     return polygonItem;
 }
 
+UBGraphicsPolygonItem* UBGraphicsScene::vectorToPolygonItem(const QLineF &pLine, const qreal &pWidth, UBVectorStyle::Enum style)
+{
+    UBGraphicsPolygonItem *polygonItem = new UBGraphicsPolygonItem(pLine, style, pWidth);
+
+    initPolygonItem(polygonItem);
+
+    return polygonItem;
+}
+
 void UBGraphicsScene::initPolygonItem(UBGraphicsPolygonItem* polygonItem)
 {
     QColor colorOnDarkBG;
diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h
index 3d934b53..c67ffbad 100644
--- a/src/domain/UBGraphicsScene.h
+++ b/src/domain/UBGraphicsScene.h
@@ -397,6 +397,8 @@ public slots:
         UBGraphicsPolygonItem* lineToPolygonItem(const QLineF &pLine, const qreal &pStartWidth, const qreal &pEndWidth);
         UBGraphicsPolygonItem* lineToPolygonItem(const QLineF &pLine, const qreal &pWidth, UBLineStyle::Enum style);
 
+        UBGraphicsPolygonItem* vectorToPolygonItem(const QLineF &pLine, const qreal &pWidth, UBVectorStyle::Enum style);
+
         UBGraphicsPolygonItem* arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth);
         UBGraphicsPolygonItem* curveToPolygonItem(const QList<QPair<QPointF, qreal> > &points);
         UBGraphicsPolygonItem* curveToPolygonItem(const QList<QPointF> &points, qreal startWidth, qreal endWidth);
diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp
index 53a6de2f..b30e258b 100644
--- a/src/frameworks/UBGeometryUtils.cpp
+++ b/src/frameworks/UBGeometryUtils.cpp
@@ -613,3 +613,135 @@ QPolygonF UBGeometryUtils::convertLineToPolygon(const QPolygonF& pLine)
     }
     return polygonRes;
 }
+
+QPolygonF UBGeometryUtils::vectorToPolygon(const QLineF& pLine, const qreal& pWidth, const UBVectorStyle::Enum vectorStyle)
+{
+
+    if (vectorStyle == UBVectorStyle::From)
+    {
+        return vectorFromToPolygon(pLine, pWidth);
+    }
+    if (vectorStyle == UBVectorStyle::FromTo)
+    {
+        return vectorFromToToPolygon(pLine, pWidth);
+    }
+    return vectorToToPolygon(pLine, pWidth);
+}
+
+QPainterPath UBGeometryUtils::getLinePainterPath(const QLineF& pLine, const qreal& pWidth)
+{
+    qreal x1 = pLine.x1();
+    qreal y1 = pLine.y1();
+
+    qreal x2 = pLine.x2();
+    qreal y2 = pLine.y2();
+
+    qreal alpha = (90.0 - pLine.angle()) * PI / 180.0;
+    qreal hypothenuse = pWidth / 2;
+
+    // TODO UB 4.x PERF cache sin/cos table
+    qreal opposite = sin(alpha) * hypothenuse;
+    qreal adjacent = cos(alpha) * hypothenuse;
+
+    QPointF p1a(x1 - adjacent, y1 - opposite);
+    QPointF p1b(x1 + adjacent, y1 + opposite);
+
+    QPointF p2a(x2 - adjacent, y2 - opposite);
+    QPointF p2b(x2 + adjacent, y2 + opposite);
+
+    QPainterPath painterPath;
+
+    painterPath.moveTo(p1a);
+    painterPath.lineTo(p2a);
+
+    painterPath.arcTo(x2 - hypothenuse, y2 - hypothenuse, pWidth, pWidth, (90.0 + pLine.angle()), -180.0);
+
+    //painterPath.lineTo(p2b);
+    painterPath.lineTo(p1b);
+
+    painterPath.arcTo(x1 - hypothenuse, y1 - hypothenuse, pWidth, pWidth, -1 * (90.0 - pLine.angle()), -180.0);
+
+    painterPath.closeSubpath();
+    return painterPath;
+}
+
+QPolygonF UBGeometryUtils::vectorToToPolygon(const QLineF& pLine, const qreal& pWidth)
+{
+    QPainterPath painterPath;
+    painterPath.addPath(getLinePainterPath(pLine, pWidth));
+
+    // To arrow
+    QPainterPath arrowLinePath;
+    qreal subLineLength = pLine.length()/10;
+    if (subLineLength > 38)
+        subLineLength = 38;
+    QLineF subLine = QLineF(pLine.p2().x(), pLine.p2().y(), pLine.p2().x()+subLineLength, pLine.p2().y());
+    subLine.setAngle(pLine.angle() - 160);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    subLine = QLineF(pLine.p2().x(), pLine.p2().y(),pLine.p2().x()+subLineLength, pLine.p2().y());
+    subLine.setAngle(pLine.angle() + 160);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    return painterPath.toFillPolygon();
+}
+
+QPolygonF UBGeometryUtils::vectorFromToPolygon(const QLineF& pLine, const qreal& pWidth)
+{
+    QPainterPath painterPath;
+    painterPath.addPath(getLinePainterPath(pLine, pWidth));
+
+    // From arrow
+    QPainterPath arrowLinePath;
+    qreal subLineLength = pLine.length()/10;
+    if (subLineLength > 38)
+        subLineLength = 38;
+    QLineF subLine = QLineF(pLine.p1().x(), pLine.p1().y(), pLine.p1().x()+subLineLength, pLine.p1().y());
+    subLine.setAngle(pLine.angle() - 20);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    subLine = QLineF(pLine.p1().x(), pLine.p1().y(),pLine.p1().x()+subLineLength, pLine.p1().y());
+    subLine.setAngle(pLine.angle() + 20);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    return painterPath.toFillPolygon();
+}
+
+QPolygonF UBGeometryUtils::vectorFromToToPolygon(const QLineF& pLine, const qreal& pWidth)
+{
+    QPainterPath painterPath;
+    painterPath.addPath(getLinePainterPath(pLine, pWidth));
+
+    // From arrow
+    QPainterPath arrowLinePath;
+    qreal subLineLength = pLine.length()/10;
+    if (subLineLength > 38)
+        subLineLength = 38;
+    QLineF subLine = QLineF(pLine.p1().x(), pLine.p1().y(), pLine.p1().x()+subLineLength, pLine.p1().y());
+    subLine.setAngle(pLine.angle() - 20);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    subLine = QLineF(pLine.p1().x(), pLine.p1().y(),pLine.p1().x()+subLineLength, pLine.p1().y());
+    subLine.setAngle(pLine.angle() + 20);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    // To arrow
+
+    subLine = QLineF(pLine.p2().x(), pLine.p2().y(), pLine.p2().x()+subLineLength, pLine.p2().y());
+    subLine.setAngle(pLine.angle() - 160);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    subLine = QLineF(pLine.p2().x(), pLine.p2().y(),pLine.p2().x()+subLineLength, pLine.p2().y());
+    subLine.setAngle(pLine.angle() + 160);
+    arrowLinePath = getLinePainterPath(subLine, pWidth);
+    painterPath+=arrowLinePath;
+
+    return painterPath.toFillPolygon();
+}
diff --git a/src/frameworks/UBGeometryUtils.h b/src/frameworks/UBGeometryUtils.h
index f2c70032..b4dc6cf5 100644
--- a/src/frameworks/UBGeometryUtils.h
+++ b/src/frameworks/UBGeometryUtils.h
@@ -65,6 +65,12 @@ class UBGeometryUtils
 
         static QList<QPointF> quadraticBezier(const QPointF& p0, const QPointF& p1, const QPointF& p2, unsigned int nPoints);
 
+        static QPolygonF vectorToPolygon(const QLineF& pLine, const qreal& pWidth, const UBVectorStyle::Enum vectorStyle);
+        static QPainterPath getLinePainterPath(const QLineF& pLine, const qreal& pWidth);
+        static QPolygonF vectorToToPolygon(const QLineF& pLine, const qreal& pWidth);
+        static QPolygonF vectorFromToPolygon(const QLineF& pLine, const qreal& pWidth);
+        static QPolygonF vectorFromToToPolygon(const QLineF& pLine, const qreal& pWidth);
+
         const static int centimeterGraduationHeight;
         const static int halfCentimeterGraduationHeight;
         const static int millimeterGraduationHeight;
diff --git a/src/gui/UBStylusPalette.cpp b/src/gui/UBStylusPalette.cpp
index 11190b92..cb039782 100644
--- a/src/gui/UBStylusPalette.cpp
+++ b/src/gui/UBStylusPalette.cpp
@@ -61,6 +61,7 @@ UBStylusPalette::UBStylusPalette(QWidget *parent, Qt::Orientation orient)
 
     actions << UBApplication::mainWindow->actionPointer;
     actions << UBApplication::mainWindow->actionLine;
+    actions << UBApplication::mainWindow->actionVector;
     actions << UBApplication::mainWindow->actionText;
     actions << UBApplication::mainWindow->actionCapture;
 
diff --git a/src/gui/UBToolbarButtonGroup.cpp b/src/gui/UBToolbarButtonGroup.cpp
index 30f697e5..2b73d31d 100644
--- a/src/gui/UBToolbarButtonGroup.cpp
+++ b/src/gui/UBToolbarButtonGroup.cpp
@@ -210,6 +210,7 @@ void UBToolbarButtonGroup::colorPaletteChanged()
     QList<QColor> colors;
 
     if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Pen 
+        || UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Vector
         || UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line)
     {
         colors = UBSettings::settings()->penColors(isDarkBackground);
diff --git a/src/tools/UBGraphicsCompass.cpp b/src/tools/UBGraphicsCompass.cpp
index 058d079e..4d17c3a1 100644
--- a/src/tools/UBGraphicsCompass.cpp
+++ b/src/tools/UBGraphicsCompass.cpp
@@ -584,10 +584,12 @@ void UBGraphicsCompass::paintCenterCross()
     QPointF needleCrossCenter = mapToScene(needlePosition());
     scene()->moveTo(QPointF(needleCrossCenter.x() - 5, needleCrossCenter.y()));
     scene()->drawLineTo(QPointF(needleCrossCenter.x() + 5, needleCrossCenter.y()), 1,
-        UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line);
+        UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line
+                        ||UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Vector);
     scene()->moveTo(QPointF(needleCrossCenter.x(), needleCrossCenter.y() - 5));
     scene()->drawLineTo(QPointF(needleCrossCenter.x(), needleCrossCenter.y() + 5), 1,
-        UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line);
+        UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line
+                        ||UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Vector);
 }
 
 QPointF UBGraphicsCompass::needlePosition() const
-- 
2.33.0
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin