[neon/backports-noble/kimageannotator-noble/Neon/release] /: New upstream version 0.7.1

Boyuan Yang null at kde.org
Wed Jul 3 14:54:16 BST 2024


Git commit 5ce38ad52dcb1c7257f4cee2a34347de60583d62 by Boyuan Yang.
Committed on 20/03/2024 at 19:19.
Pushed by jriddell into branch 'Neon/release'.

New upstream version 0.7.1

M  +15   -0    CHANGELOG.md
M  +26   -17   CMakeLists.txt
M  +6    -2    README.md
M  +1    -1    cmake/kImageAnnotatorConfig.cmake.in
M  +1    -1    example/CMakeLists.txt
M  +3    -1    src/CMakeLists.txt
M  +17   -10   src/annotations/core/AnnotationArea.cpp
M  +11   -5    src/annotations/core/AnnotationArea.h
M  +23   -2    src/annotations/items/AbstractAnnotationRect.cpp
M  +1    -0    src/annotations/items/AbstractAnnotationRect.h
M  +48   -54   src/annotations/items/AnnotationText.cpp
M  +8    -9    src/annotations/items/AnnotationText.h
M  +44   -30   src/annotations/items/text/AnnotationTextHandler.cpp
M  +8    -4    src/annotations/items/text/AnnotationTextHandler.h
M  +22   -10   src/annotations/items/text/KeyInputHelper.cpp
M  +6    -3    src/annotations/items/text/KeyInputHelper.h
M  +27   -155  src/annotations/items/text/TextCursor.cpp
M  +9    -18   src/annotations/items/text/TextCursor.h
A  +169  -0    src/annotations/items/text/TextHandlerItem.cpp     [License: GPL (v2+)]
A  +68   -0    src/annotations/items/text/TextHandlerItem.h     [License: GPL (v2+)]
M  +7    -8    src/annotations/misc/AnnotationItemClipboard.cpp
M  +3    -3    src/annotations/misc/AnnotationItemClipboard.h
M  +0    -1    src/annotations/undo/PasteCommand.cpp
M  +0    -1    src/annotations/undo/PasteCommand.h
C  +9    -16   src/common/filter/IKeyEventListener.h [from: src/annotations/items/text/TextPositions.h - 067% similarity]
R  +26   -9    src/common/filter/KeyEventFilter.cpp [from: src/common/filter/KeyEventListener.cpp - 067% similarity]
R  +12   -10   src/common/filter/KeyEventFilter.h [from: src/common/filter/KeyEventListener.h - 076% similarity]
M  +1    -1    src/common/helper/IconLoader.cpp
M  +1    -1    src/common/helper/ItemHelper.cpp
M  +1    -1    src/common/helper/PathHelper.cpp
C  +21   -19   src/common/helper/RectSizeHelper.cpp [from: src/common/helper/IconLoader.cpp - 050% similarity]
R  +15   -16   src/common/helper/RectSizeHelper.h [from: src/annotations/items/text/TextPositions.h - 062% similarity]
M  +25   -17   src/common/helper/ShapeHelper.cpp
M  +3    -2    src/common/provider/DevicePixelRatioScaler.cpp
M  +0    -1    src/common/provider/DevicePixelRatioScaler.h
M  +2    -2    src/gui/annotator/tabs/AnnotationTabContent.cpp
M  +1    -1    src/gui/annotator/tabs/AnnotationTabContent.h
M  +5    -3    src/gui/annotator/tabs/AnnotationTabWidget.cpp
M  +4    -0    src/gui/annotator/tabs/AnnotationTabWidget.h
M  +2    -2    src/gui/scrollAndZoomView/ScrollAndZoomView.cpp
M  +2    -2    src/gui/scrollAndZoomView/ViewZoomer.cpp
M  +1    -1    src/widgets/ToolPicker.cpp
M  +1    -1    src/widgets/menuButtons/ListMenuItem.cpp
M  +1    -1    src/widgets/settingsPicker/ColorPicker.h
M  +4    -4    tests/CMakeLists.txt
M  +12   -7    tests/annotations/core/AnnotationAreaTest.cpp
M  +1    -0    tests/annotations/core/AnnotationAreaTest.h
M  +1    -1    tests/annotations/core/AnnotationPropertiesFactoryTest.cpp
M  +32   -30   tests/annotations/items/helper/KeyInputHelperTest.cpp
M  +0    -1    tests/annotations/items/helper/KeyInputHelperTest.h
M  +87   -113  tests/annotations/items/helper/TextCursorTest.cpp
M  +0    -3    tests/annotations/items/helper/TextCursorTest.h
M  +4    -4    tests/annotations/misc/AnnotationItemClipboardTest.cpp
M  +2    -2    tests/annotations/undo/AddCommandTest.cpp
M  +4    -4    tests/annotations/undo/CropCommandTest.cpp
M  +2    -2    tests/annotations/undo/DeleteCommandTest.cpp
M  +8    -4    tests/annotations/undo/ModifyCanvasCommandTest.cpp
M  +1    -0    tests/annotations/undo/ModifyCanvasCommandTest.h
M  +2    -2    tests/annotations/undo/PasteCommandTest.cpp
M  +3    -3    tests/annotations/undo/RotateCommandTest.cpp
M  +4    -4    tests/annotations/undo/ScaleCommandTest.cpp
M  +3    -3    tests/gui/annotator/tabs/AnnotationTabContextMenuTest.cpp
M  +10   -10   tests/gui/selection/SelectionHandlerTest.cpp
M  +0    -8    tests/utils/TestRunner.h
M  +2    -2    tests/widgets/settingsPicker/StickerPickerTest.cpp
M  +3    -3    translations/CMakeLists.txt
M  +17   -17   translations/kImageAnnotator_de.ts
M  +73   -71   translations/kImageAnnotator_es.ts
M  +17   -17   translations/kImageAnnotator_pl.ts
M  +17   -17   translations/kImageAnnotator_pt.ts
M  +3    -3    translations/kImageAnnotator_sq.ts

https://invent.kde.org/neon/backports-noble/kimageannotator-noble/-/commit/5ce38ad52dcb1c7257f4cee2a34347de60583d62

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 221a444..74d298b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
 # Change log
 
+## Release 0.7.1
+* Fixed: Crash after pressing key when no tab exists or closing last tab. ([#334](https://github.com/ksnip/kImageAnnotator/issues/334))
+
+## Release 0.7.0
+* New: Allow copying items between tabs. ([#318](https://github.com/ksnip/kImageAnnotator/issues/318))
+* New: CTRL + A does not select all text typed. ([#198](https://github.com/ksnip/kImageAnnotator/issues/198))
+* New: Open text edit mode when double-click on textbox figure in Text tool. ([#180](https://github.com/ksnip/kImageAnnotator/issues/180))
+* New: Add reflowing capability to the text tool. ([#129](https://github.com/ksnip/kImageAnnotator/issues/129))
+* New: Editing text, no mouse cursor edit functions. ([#297](https://github.com/ksnip/kImageAnnotator/issues/297))
+* New: Mouse click within a text box for setting specific editing position and selecting text. ([#273](https://github.com/ksnip/kImageAnnotator/issues/273))
+* Fixed: Text isn't reflowed the next line within the box and text overlaps when resizing box. ([#271](https://github.com/ksnip/kImageAnnotator/issues/271))
+* Fixed: Can't wrap long text line when I resize Text box area. ([#211](https://github.com/ksnip/kImageAnnotator/issues/211))
+* Fixed: Key press operations affect items across different tabs. ([#319](https://github.com/ksnip/kImageAnnotator/issues/319))
+* Fixed: Clipboard cleared when new tab added. ([#321](https://github.com/ksnip/kImageAnnotator/issues/321))
+
 ## Release 0.6.1
 * Fixed: Fix for unnecessary scrollbars when a screenshot has a smaller size than the previous one. ([#303](https://github.com/ksnip/kImageAnnotator/issues/303))
 * Fixed: Add KDE support for scale factor. ([#302](https://github.com/ksnip/kImageAnnotator/issues/302))
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 99c89f5..8f3516e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.5)
-project(kImageAnnotator LANGUAGES CXX VERSION 0.6.1)
+project(kImageAnnotator LANGUAGES CXX VERSION 0.7.1)
 
-set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
 
@@ -25,8 +25,17 @@ elseif (UNIX)
 	string(REGEX REPLACE "//" "/" KIMAGEANNOTATOR_LANG_INSTALL_DIR "${KIMAGEANNOTATOR_LANG_INSTALL_DIR}")
 endif ()
 
-set(QT_MIN_VERSION 5.9.4)
-find_package(Qt5 ${QT_MIN_VERSION} REQUIRED Widgets Svg)
+set(QT_MIN_VERSION 5.15.2)
+
+option(BUILD_WITH_QT6 "Build against Qt6" OFF)
+
+if (BUILD_WITH_QT6)
+	set(QT_MAJOR_VERSION 6)
+else()
+	set(QT_MAJOR_VERSION 5)
+endif()
+
+find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} REQUIRED Widgets Svg)
 
 if (UNIX AND NOT APPLE)
 	find_package(X11 REQUIRED)
@@ -34,8 +43,8 @@ endif ()
 
 include(FeatureSummary)
 
-set(KCOLORPICKER_MIN_VERSION 0.2.0)
-find_package(kColorPicker ${KCOLORPICKER_MIN_VERSION} REQUIRED)
+set(KCOLORPICKER_MIN_VERSION 0.3.1)
+find_package(kColorPicker-Qt${QT_MAJOR_VERSION} ${KCOLORPICKER_MIN_VERSION} REQUIRED)
 
 include_directories(${CMAKE_CURRENT_SOURCE_DIR})
 
@@ -64,10 +73,10 @@ target_include_directories(kImageAnnotator
 						   PUBLIC
 						   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
 						   $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
-						   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+						   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/kImageAnnotator-Qt${QT_MAJOR_VERSION}>
 						   )
 
-target_link_libraries(kImageAnnotator PUBLIC Qt5::Widgets Qt5::Svg PRIVATE kColorPicker::kColorPicker)
+target_link_libraries(kImageAnnotator PUBLIC Qt${QT_MAJOR_VERSION}::Widgets Qt${QT_MAJOR_VERSION}::Svg PRIVATE kColorPicker::kColorPicker)
 
 if (UNIX AND NOT APPLE)
 	# X11::X11 imported target only available with sufficiently new CMake
@@ -98,30 +107,30 @@ install(TARGETS kImageAnnotator
 		)
 
 install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/kImageAnnotator
-		DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+		DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/kImageAnnotator-Qt${QT_MAJOR_VERSION}
 		)
 
 configure_package_config_file(
 		${CMAKE_CURRENT_SOURCE_DIR}/cmake/kImageAnnotatorConfig.cmake.in
-		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotatorConfig.cmake
-		INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator
+		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}Config.cmake
+		INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}
 )
 
 write_basic_package_version_file(
-		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotatorConfig-version.cmake
+		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}Config-version.cmake
 		VERSION ${PROJECT_VERSION}
 		COMPATIBILITY AnyNewerVersion
 )
 
 install(FILES
-		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotatorConfig.cmake
-		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotatorConfig-version.cmake
-		DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator
+		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}Config.cmake
+		${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}Config-version.cmake
+		DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}
 		)
 
 export(
 		EXPORT kImageAnnotator-targets
-		FILE ${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotator-targets.cmake
+		FILE ${CMAKE_CURRENT_BINARY_DIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}-targets.cmake
 		NAMESPACE kImageAnnotator::
 )
 
@@ -129,7 +138,7 @@ install(
 		EXPORT kImageAnnotator-targets
 		FILE kImageAnnotator-targets.cmake
 		NAMESPACE kImageAnnotator::
-		DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator
+		DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kImageAnnotator-Qt${QT_MAJOR_VERSION}
 )
 
 # uninstall target
diff --git a/README.md b/README.md
index 9bd3fad..a413b8b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # kImageAnnotator [![Linux Build Status][github-badge-linux]][github-url-linux] [![Windows Build Status][github-badge-windows]][github-url-windows] [![Translation status][weblate-badge]][weblate-url]
 Tool for annotating images
 
-Version 0.6.1
+Version 0.7.1
 
 ![kImageAnnotator](https://i.imgur.com/4vlPDUn.png "kImageAnnotator")
 
@@ -20,6 +20,7 @@ to be installed before building kImageAnnotator. Install instructions can be fou
     `$ mkdir build && cd build`  
 4. Create the makefile and build the project:  
     `$ cmake .. && make`  
+   to build with Qt6, pass `-DBUILD_WITH_QT6=true` to the `cmake` command
 5. Install shared library (not required when only using the example):  
     `$ sudo make install`
 6. Run the example application:  
@@ -35,7 +36,10 @@ static library is build. For windows, we currently only support building as stat
 
 1. Let cmake find the shared library, optionally with version  
     `set(KIMAGEANNOTATOR_MIN_VERSION "0.x.x")`  
-    `find_package(kImageAnnotator ${KIMAGEANNOTATOR_MIN_VERSION} REQUIRED)`  
+    to build with Qt5:  
+    `find_package(kImageAnnotator-Qt5 ${KIMAGEANNOTATOR_MIN_VERSION} REQUIRED)`  
+    to build with Qt6:  
+    `find_package(kImageAnnotator-Qt6 ${KIMAGEANNOTATOR_MIN_VERSION} REQUIRED)`
 
 2. Link the library with your application  
     `target_link_libraries(myApp kImageAnnotator)`  
diff --git a/cmake/kImageAnnotatorConfig.cmake.in b/cmake/kImageAnnotatorConfig.cmake.in
index 7bfc078..3b8d70b 100644
--- a/cmake/kImageAnnotatorConfig.cmake.in
+++ b/cmake/kImageAnnotatorConfig.cmake.in
@@ -2,7 +2,7 @@ include(CMakeFindDependencyMacro)
 
 @PACKAGE_INIT@
 
-find_dependency(Qt5 @QT_MIN_VERSION@ COMPONENTS Widgets)
+find_dependency(Qt at QT_MAJOR_VERSION@ @QT_MIN_VERSION@ COMPONENTS Widgets)
 if(NOT TARGET kImageAnnotator::kImageAnnotator)
   include("${CMAKE_CURRENT_LIST_DIR}/kImageAnnotator-targets.cmake")
 endif()
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index c96a353..f2b2aea 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -1,3 +1,3 @@
-add_executable(kImageAnnotator-example main.cpp)
+    add_executable(kImageAnnotator-example main.cpp)
 
 target_link_libraries(kImageAnnotator-example kImageAnnotator)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 12a48fc..61c5569 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -103,6 +103,7 @@ set(KIMAGEANNOTATOR_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/annotations/items/text/KeyInputHelper.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/annotations/items/text/TextCursor.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/annotations/items/text/CapsLockStatusChecker.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/annotations/items/text/TextHandlerItem.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/annotations/items/helper/NumberRectHelper.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/annotations/items/helper/AnnotationShapeCreator.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/annotations/undo/AddCommand.cpp
@@ -137,8 +138,9 @@ set(KIMAGEANNOTATOR_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/common/helper/ConfigNameHelper.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/common/helper/IconLoader.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/common/helper/PathHelper.cpp
+	${CMAKE_CURRENT_SOURCE_DIR}/common/helper/RectSizeHelper.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/common/filter/IgnoreShortcutsFilter.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/common/filter/KeyEventListener.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/common/filter/KeyEventFilter.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/common/platform/PlatformChecker.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/widgets/ToolPicker.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/widgets/Controls.cpp
diff --git a/src/annotations/core/AnnotationArea.cpp b/src/annotations/core/AnnotationArea.cpp
index ddafd0e..e701d48 100644
--- a/src/annotations/core/AnnotationArea.cpp
+++ b/src/annotations/core/AnnotationArea.cpp
@@ -26,6 +26,7 @@ AnnotationArea::AnnotationArea(
 		AbstractSettingsProvider *settingsProvider,
 		IDevicePixelRatioScaler *devicePixelRatioScaler,
 		ZoomValueProvider *zoomValueProvider,
+		AnnotationItemClipboard *itemClipboard,
 		QWidget *parent) :
 	QGraphicsScene(parent),
 	mUndoStack(new UndoStack),
@@ -40,7 +41,7 @@ AnnotationArea::AnnotationArea(
 	mPropertiesFactory(new AnnotationPropertiesFactory(config, mSettingsProvider)),
 	mItemFactory(new AnnotationItemFactory(mPropertiesFactory, mSettingsProvider, mConfig)),
 	mItems(new QList<AbstractAnnotationItem *>()),
-	mItemCopier(new AnnotationItemClipboard(mItemModifier)),
+	mItemClipboard(itemClipboard),
 	mDevicePixelRatioScaler(devicePixelRatioScaler),
 	mCanvasColor(config->canvasColor())
 {
@@ -59,9 +60,6 @@ AnnotationArea::AnnotationArea(
 
 	connect(mKeyHelper, &KeyHelper::undoPressed, mUndoStack, &UndoStack::undo);
 	connect(mKeyHelper, &KeyHelper::redoPressed, mUndoStack, &UndoStack::redo);
-
-	connect(&mKeyListener, &KeyEventListener::keyPressed, mKeyHelper, &KeyHelper::keyPress);
-	connect(&mKeyListener, &KeyEventListener::keyReleased, mKeyHelper, &KeyHelper::keyRelease);
 }
 
 AnnotationArea::~AnnotationArea()
@@ -72,7 +70,7 @@ AnnotationArea::~AnnotationArea()
 	delete mKeyHelper;
 	delete mUndoStack;
 	delete mItemModifier;
-	delete mItemCopier;
+	delete mItemClipboard;
 	delete mDevicePixelRatioScaler;
 }
 
@@ -103,7 +101,7 @@ void AnnotationArea::replaceBackgroundImage(const QPixmap &image)
 QImage AnnotationArea::image()
 {
 	if (mBackgroundImage == nullptr) {
-		return QImage();
+		return {};
 	}
 
 	mItemModifier->clear();
@@ -271,6 +269,16 @@ void AnnotationArea::cut(const QRectF &rect)
 	emit imageChanged();
 }
 
+void AnnotationArea::keyPressed(QKeyEvent *keyEvent)
+{
+	mKeyHelper->keyPress(keyEvent);
+}
+
+void AnnotationArea::keyReleased(QKeyEvent *keyEvent)
+{
+	mKeyHelper->keyRelease(keyEvent);
+}
+
 void AnnotationArea::update()
 {
 	mItemModifier->updateSelection();
@@ -358,7 +366,7 @@ void AnnotationArea::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
 	AnnotationContextMenu contextMenu;
 	auto isMenuOverItem = !selectedItems.isEmpty();
 	contextMenu.setOverItem(isMenuOverItem);
-	contextMenu.setPastEnabled(!mItemCopier->isEmpty());
+	contextMenu.setPastEnabled(mItemClipboard->isNotEmpty());
 	contextMenu.setEditVisible(selectedEditableItem() != nullptr);
 	AnnotationItemArranger itemArranger(selectedItems, mItems);
 	connect(&itemArranger, &AnnotationItemArranger::newCommand, mUndoStack, &UndoStack::push);
@@ -366,7 +374,7 @@ void AnnotationArea::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
 	connect(&contextMenu, &AnnotationContextMenu::bringForward, &itemArranger, &AnnotationItemArranger::bringForward);
 	connect(&contextMenu, &AnnotationContextMenu::sendBackward, &itemArranger, &AnnotationItemArranger::sendBackward);
 	connect(&contextMenu, &AnnotationContextMenu::sendToBack, &itemArranger, &AnnotationItemArranger::sendToBack);
-	connect(&contextMenu, &AnnotationContextMenu::copy, mItemCopier, &AnnotationItemClipboard::copyItems);
+	connect(&contextMenu, &AnnotationContextMenu::copy, [this](const QPointF &position) { mItemClipboard->copyItems(position, mItemModifier); } );
 	connect(&contextMenu, &AnnotationContextMenu::paste, this, &AnnotationArea::pasteCopiedItems);
 	connect(&contextMenu, &AnnotationContextMenu::erase, this, &AnnotationArea::deleteSelectedItems);
 	connect(&contextMenu, &AnnotationContextMenu::edit, this, &AnnotationArea::enableEditing);
@@ -406,7 +414,6 @@ void AnnotationArea::resetAnnotationArea()
 {
 	removeAllItems();
 	mItemModifier->clear();
-	mItemCopier->clear();
 	mUndoStack->clear();
 	mItemFactory->reset();
 	mKeyHelper->reset();
@@ -431,7 +438,7 @@ void AnnotationArea::deleteSelectedItems()
 
 void AnnotationArea::pasteCopiedItems(const QPointF &position)
 {
-	auto copiedItems = mItemCopier->copiedItemsWithOffset();
+	auto copiedItems = mItemClipboard->copiedItemsWithOffset();
 	mUndoStack->push(new PasteCommand(copiedItems, position, mItemFactory, this));
 }
 
diff --git a/src/annotations/core/AnnotationArea.h b/src/annotations/core/AnnotationArea.h
index c9f28d6..d9cc3bd 100644
--- a/src/annotations/core/AnnotationArea.h
+++ b/src/annotations/core/AnnotationArea.h
@@ -30,6 +30,7 @@
 #include "AnnotationItemFactory.h"
 #include "AbstractSettingsProvider.h"
 #include "ISettingsListener.h"
+#include "src/common/filter/IKeyEventListener.h"
 #include "src/annotations/modifiers/AnnotationItemModifier.h"
 #include "src/annotations/modifiers/AnnotationItemArranger.h"
 #include "src/annotations/misc/AnnotationItemClipboard.h"
@@ -40,7 +41,6 @@
 #include "src/common/helper/CursorHelper.h"
 #include "src/common/helper/KeyHelper.h"
 #include "src/common/provider/IDevicePixelRatioScaler.h"
-#include "src/common/filter/KeyEventListener.h"
 #include "src/annotations/undo/UndoStack.h"
 #include "src/annotations/undo/CropCommand.h"
 #include "src/annotations/undo/FlipCommand.h"
@@ -55,11 +55,16 @@
 
 namespace kImageAnnotator {
 
-class AnnotationArea : public QGraphicsScene, public ISettingsListener
+class AnnotationArea : public QGraphicsScene, public ISettingsListener, public IKeyEventListener
 {
     Q_OBJECT
 public:
-    explicit AnnotationArea(Config *config, AbstractSettingsProvider *settingsProvider, IDevicePixelRatioScaler *devicePixelRatioScaler, ZoomValueProvider *zoomValueProvider, QWidget *parent);
+    explicit AnnotationArea(
+			Config *config,
+			AbstractSettingsProvider *settingsProvider,
+			IDevicePixelRatioScaler *devicePixelRatioScaler,
+			ZoomValueProvider *zoomValueProvider,
+			AnnotationItemClipboard *itemClipboard, QWidget *parent);
     ~AnnotationArea() override;
     virtual void loadImage(const QPixmap &image);
     virtual void insertImageItem(const QPointF &position, const QPixmap &image);
@@ -86,6 +91,8 @@ public:
 	void modifyCanvas(const QRectF &canvasRect, const QColor &color);
 	QRectF backgroundImageRect() const;
 	void cut(const QRectF &rect);
+	void keyPressed(QKeyEvent *keyEvent) override;
+	void keyReleased(QKeyEvent *keyEvent) override;
 
 public slots:
     virtual void update();
@@ -112,11 +119,10 @@ private:
     QList<AbstractAnnotationItem*> *mItems;
     KeyHelper *mKeyHelper;
     UndoStack *mUndoStack;
-	AnnotationItemClipboard *mItemCopier;
+	AnnotationItemClipboard *mItemClipboard;
 	QAction *mUndoAction;
 	QAction *mRedoAction;
 	IDevicePixelRatioScaler *mDevicePixelRatioScaler;
-	KeyEventListener mKeyListener;
 	QRectF mCanvasRect;
 	QColor mCanvasColor;
 
diff --git a/src/annotations/items/AbstractAnnotationRect.cpp b/src/annotations/items/AbstractAnnotationRect.cpp
index ddb60e7..8ed05a7 100644
--- a/src/annotations/items/AbstractAnnotationRect.cpp
+++ b/src/annotations/items/AbstractAnnotationRect.cpp
@@ -45,6 +45,11 @@ void AbstractAnnotationRect::addPoint(const QPointF &position, bool modified)
 	prepareGeometryChange();
 	mRect->setBottomRight(position);
 	makeSymmetric(modified);
+
+	if (!minimumSize().isNull()) {
+		*mRect = RectSizeHelper::limitToSize(*mRect, minimumSize());
+	}
+
 	updateShape();
 }
 
@@ -62,10 +67,26 @@ QRectF AbstractAnnotationRect::rect() const
 
 void AbstractAnnotationRect::setPointAt(const QPointF &point, int index, bool keepAspectRatio)
 {
-	prepareGeometryChange();
 	auto newRect = ShapeHelper::setRectPointAtIndex(*mRect, index, point, keepAspectRatio);
-	mRect->setRect(newRect.x(), newRect.y(), newRect.width(), newRect.height());
+
+	prepareGeometryChange();
+
+	if(minimumSize().isNull()) {
+		mRect->setRect(newRect.x(), newRect.y(),newRect.width(), newRect.height());
+	} else {
+		if(qAbs(newRect.width()) >= minimumWidth()) {
+			mRect->setLeft(newRect.left());
+			mRect->setWidth(newRect.width());
+		}
+
+		if(qAbs(newRect.height()) >= minimumHeight()) {
+			mRect->setTop(newRect.top());
+			mRect->setHeight(newRect.height());
+		}
+	}
+
 	updateShape();
+
 }
 
 QPointF AbstractAnnotationRect::pointAt(int index) const
diff --git a/src/annotations/items/AbstractAnnotationRect.h b/src/annotations/items/AbstractAnnotationRect.h
index 7d62db9..9f06be3 100644
--- a/src/annotations/items/AbstractAnnotationRect.h
+++ b/src/annotations/items/AbstractAnnotationRect.h
@@ -24,6 +24,7 @@
 #include "src/common/helper/MathHelper.h"
 #include "src/common/helper/ShapeHelper.h"
 #include "src/common/constants/Constants.h"
+#include "src/common/helper/RectSizeHelper.h"
 
 namespace kImageAnnotator {
 
diff --git a/src/annotations/items/AnnotationText.cpp b/src/annotations/items/AnnotationText.cpp
index 8f0b1b9..51cb9e8 100644
--- a/src/annotations/items/AnnotationText.cpp
+++ b/src/annotations/items/AnnotationText.cpp
@@ -22,18 +22,30 @@
 namespace kImageAnnotator {
 
 AnnotationText::AnnotationText(const QPointF &startPosition, const TextPropertiesPtr &properties) :
-	AbstractAnnotationRect(startPosition, properties)
+	AbstractAnnotationRect(startPosition, properties),
+	mTextHandlerItem(new TextHandlerItem(this))
 {
-	setupFlags();
 	connectSlots();
+
+	mTextHandlerItem->setPos(startPosition);
+	setMinimumSize(mTextHandlerItem->minimumSize());
+
+	updateProperties();
+	refresh();
 }
 
 AnnotationText::AnnotationText(const AnnotationText &other) :
 	AbstractAnnotationRect(other),
-	mTextHandler(other.mTextHandler)
+	mTextHandlerItem(new TextHandlerItem(*other.mTextHandlerItem, this))
 {
-	setupFlags();
 	connectSlots();
+	setMinimumSize(mTextHandlerItem->minimumSize());
+	refresh();
+}
+
+AnnotationText::~AnnotationText()
+{
+	delete mTextHandlerItem;
 }
 
 void AnnotationText::updateShape()
@@ -43,35 +55,6 @@ void AnnotationText::updateShape()
 	setShape(path);
 }
 
-void AnnotationText::focusOutEvent(QFocusEvent *event)
-{
-	disableEditing();
-	QGraphicsWidget::focusOutEvent(event);
-}
-
-void AnnotationText::keyPressEvent(QKeyEvent *event)
-{
-	mTextHandler.handleKeyEvent(event);
-}
-
-void AnnotationText::inputMethodEvent(QInputMethodEvent *event)
-{
-	mTextHandler.insertText(event->commitString());
-}
-
-void AnnotationText::paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget)
-{
-	// Paint border
-	AbstractAnnotationRect::paint(painter, style, widget);
-
-	// Paint Text
-	auto font = textProperties()->font();
-	auto color = textProperties()->textColor();
-	auto margin = textProperties()->width();
-	auto isShadowEnabled = properties()->shadowEnabled();
-	mTextHandler.paintText(painter, mRect, font, color, margin, isShadowEnabled);
-}
-
 void AnnotationText::finish()
 {
 	enableEditing();
@@ -84,42 +67,36 @@ Tools AnnotationText::toolType() const
 
 QPainterPath AnnotationText::shape() const
 {
-	auto path = AbstractAnnotationItem::shape();
-	auto font = textProperties()->font();
-	auto margin = textProperties()->width();
-	path.addRect(mTextHandler.getTextRect(mRect, font, margin));
-	return path;
-}
-
-void AnnotationText::escape()
-{
-	clearFocus();
+	if(mTextHandlerItem->isEditing()) {
+		return {};
+	} else {
+		auto itemShape = AbstractAnnotationRect::shape();
+		itemShape.addRect(mTextHandlerItem->textRect());
+		return itemShape;
+	}
 }
 
 void AnnotationText::refresh()
 {
 	prepareGeometryChange();
-	auto font = textProperties()->font();
-	auto margin = textProperties()->width();
-	mTextHandler.updateRect(mRect, font, margin);
+	*mRect = RectSizeHelper::setSizeButKeepDirection(*mRect, mTextHandlerItem->boundingRect().size());
 	updateShape();
 }
 
 void AnnotationText::connectSlots()
 {
-	connect(&mTextHandler, &AnnotationTextHandler::changed, this, &AnnotationText::refresh);
-	connect(&mTextHandler, &AnnotationTextHandler::finished, this, &AnnotationText::escape);
+	connect(mTextHandlerItem, &TextHandlerItem::textRectChanged, this, &AnnotationText::refresh);
+	connect(this, &AnnotationText::propertiesChanged, this, &AnnotationText::updateProperties);
 }
 
 void AnnotationText::enableEditing()
 {
-    setFocus();
-	mTextHandler.enableEditing();
+	mTextHandlerItem->enableEditing();
 }
 
 void AnnotationText::disableEditing()
 {
-	mTextHandler.disableEditing();
+	mTextHandlerItem->disableEditing();
 }
 
 TextPropertiesPtr AnnotationText::textProperties() const
@@ -127,10 +104,27 @@ TextPropertiesPtr AnnotationText::textProperties() const
 	return AbstractAnnotationItem::properties().staticCast<AnnotationTextProperties>();
 }
 
-void AnnotationText::setupFlags()
+void AnnotationText::setPosition(const QPointF &newPosition)
+{
+	AbstractAnnotationRect::setPosition(newPosition);
+	mTextHandlerItem->setPos(newPosition);
+}
+
+void AnnotationText::addPoint(const QPointF &position, bool modified)
+{
+	AbstractAnnotationRect::addPoint(position, modified);
+	mTextHandlerItem->setTextRect(boundingRect().toRect());
+}
+
+void AnnotationText::setPointAt(const QPointF &point, int index, bool keepAspectRatio)
+{
+	AbstractAnnotationRect::setPointAt(point, index, keepAspectRatio);
+	mTextHandlerItem->setTextRect(boundingRect().toRect());
+}
+
+void AnnotationText::updateProperties()
 {
-	setFlag(ItemIsFocusable, true);
-	setFlag(ItemAcceptsInputMethod, true);
+	mTextHandlerItem->setTextProperties(textProperties());
 }
 
 } // namespace kImageAnnotator
diff --git a/src/annotations/items/AnnotationText.h b/src/annotations/items/AnnotationText.h
index daed720..d46fcbd 100644
--- a/src/annotations/items/AnnotationText.h
+++ b/src/annotations/items/AnnotationText.h
@@ -22,8 +22,9 @@
 
 #include "AbstractAnnotationRect.h"
 #include "src/annotations/items/interfaces/EditableItem.h"
-#include "src/annotations/items/text/AnnotationTextHandler.h"
+#include "src/annotations/items/text/TextHandlerItem.h"
 #include "src/annotations/properties/AnnotationTextProperties.h"
+#include "src/common/helper/RectSizeHelper.h"
 
 namespace kImageAnnotator {
 
@@ -33,30 +34,28 @@ Q_OBJECT
 public:
 	AnnotationText(const QPointF &startPosition, const TextPropertiesPtr &properties);
 	AnnotationText(const AnnotationText &other);
-	~AnnotationText() override = default;
+	~AnnotationText() override;
 	void finish() override;
 	Tools toolType() const override;
 	QPainterPath shape() const override;
 	void enableEditing() override;
 	void disableEditing() override;
 	TextPropertiesPtr textProperties() const;
+	void setPosition(const QPointF &newPosition) override;
+	void addPoint(const QPointF &position, bool modified) override;
+	void setPointAt(const QPointF &point, int index, bool keepAspectRatio) override;
 
 protected:
 	void updateShape() override;
-	void focusOutEvent(QFocusEvent *event) override;
-	void keyPressEvent(QKeyEvent *event) override;
-	void inputMethodEvent(QInputMethodEvent *event) override;
-	void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget) override;
 
 private:
-	AnnotationTextHandler mTextHandler;
+	TextHandlerItem *mTextHandlerItem;
 
 	void connectSlots();
-	void setupFlags();
 
 private slots:
-	void escape();
 	void refresh();
+	void updateProperties();
 };
 
 } // namespace kImageAnnotator
diff --git a/src/annotations/items/text/AnnotationTextHandler.cpp b/src/annotations/items/text/AnnotationTextHandler.cpp
index d5a33d9..6d9a48c 100644
--- a/src/annotations/items/text/AnnotationTextHandler.cpp
+++ b/src/annotations/items/text/AnnotationTextHandler.cpp
@@ -22,14 +22,16 @@
 namespace kImageAnnotator {
 
 AnnotationTextHandler::AnnotationTextHandler() :
-	mIsInEditMode(false)
+	mIsInEditMode(false),
+	mTextDocument(new QTextDocument),
+	mTextCursor(new TextCursor(mTextDocument))
 {
 	setupEditModeOutlinePen();
 	connectSlots();
 }
 
 AnnotationTextHandler::AnnotationTextHandler(const AnnotationTextHandler &other) :
-	mText(other.mText),
+	mTextDocument(other.mTextDocument),
 	mTextCursor(other.mTextCursor),
 	mIsInEditMode(false)
 {
@@ -39,31 +41,22 @@ AnnotationTextHandler::AnnotationTextHandler(const AnnotationTextHandler &other)
 
 void AnnotationTextHandler::insertText(const QString &text)
 {
-	mText.insert(mTextCursor.position(), text);
-	mTextCursor.moveForwardBy(mText, text.length());
+	mTextCursor->insertText(text);
 	emit changed();
 }
 
-void AnnotationTextHandler::removeText(TextPositions direction)
+void AnnotationTextHandler::removeText(QTextCursor::MoveOperation operation)
 {
-	auto currentCursorPos = mTextCursor.position();
-	if (direction == TextPositions::Previous) {
-		if (currentCursorPos == 0) {
-			return;
-		}
-		mText.remove(currentCursorPos - 1, 1);
-		moveCursor(TextPositions::Previous);
-	} else if (direction == TextPositions::Next) {
-		if (currentCursorPos >= mText.length()) {
-			return;
-		}
-		mText.remove(currentCursorPos, 1);
+	if (operation == QTextCursor::Left) {
+		mTextCursor->deletePreviousChar();
+	} else if (operation == QTextCursor::Right) {
+		mTextCursor->deleteChar();
 	}
 }
 
-void AnnotationTextHandler::moveCursor(TextPositions direction)
+void AnnotationTextHandler::moveCursor(QTextCursor::MoveOperation operation)
 {
-	mTextCursor.move(direction, mText);
+	mTextCursor->movePosition(operation);
 }
 
 void AnnotationTextHandler::pasteText()
@@ -72,13 +65,30 @@ void AnnotationTextHandler::pasteText()
 	if (clipboard->text().isEmpty()) {
 		return;
 	}
-	mText.insert(mTextCursor.position(), clipboard->text());
-	mTextCursor.setPosition(mTextCursor.position() + clipboard->text().length());
+
+	mTextCursor->insertText(clipboard->text());
+}
+
+void AnnotationTextHandler::cutText()
+{
+	copyText();
+	mTextCursor->removeSelectedText();
+}
+
+void AnnotationTextHandler::copyText()
+{
+	auto text = mTextCursor->selectedText();
+	QApplication::clipboard()->setText(text);
+}
+
+void AnnotationTextHandler::selectAllText()
+{
+	mTextCursor->select(QTextCursor::Document);
 }
 
 void AnnotationTextHandler::enableEditing()
 {
-	mTextCursor.start();
+	mTextCursor->start();
 	mIgnoreShortcutsFilter.apply();
 	mIsInEditMode = true;
 	emit changed();
@@ -86,7 +96,7 @@ void AnnotationTextHandler::enableEditing()
 
 void AnnotationTextHandler::disableEditing()
 {
-	mTextCursor.stop();
+	mTextCursor->stop();
 	mIgnoreShortcutsFilter.remove();
 	mIsInEditMode = false;
 	emit changed();
@@ -116,8 +126,7 @@ void AnnotationTextHandler::paintText(QPainter *painter, QRectF *rect, const QFo
 	QFontMetrics fontMetrics(font);
 	auto boxHeight = 0;
 
-	QTextDocument document(mText);
-	for (auto block = document.begin(); block != document.end(); block = block.next()) {
+	for (auto block = mTextDocument->begin(); block != mTextDocument->end(); block = block.next()) {
 		auto blockPosition = block.position();
 		auto blockLength = block.length();
 		QTextLayout textLayout(block);
@@ -142,8 +151,10 @@ void AnnotationTextHandler::paintText(QPainter *painter, QRectF *rect, const QFo
 
 		textLayout.draw(painter, QPoint(0, boxHeight));
 
-		if (mTextCursor.isVisible() && isCursorInBlock(blockPosition, blockLength)) {
-			textLayout.drawCursor(painter, QPointF(0, boxHeight), mTextCursor.position() - blockPosition, 1);
+//		textLayout.drawCursor(painter, QPointF(0, boxHeight), mTextCursor->position() - blockPosition, 1);
+
+		if (mTextCursor->isVisible() && isCursorInBlock(blockPosition, blockLength)) {
+			textLayout.drawCursor(painter, QPointF(0, boxHeight), mTextCursor->position() - blockPosition, 1);
 		}
 		boxHeight += blockHeight;
 	}
@@ -164,7 +175,7 @@ void AnnotationTextHandler::updateRect(QRectF *rect, const QFont &font, int marg
 
 bool AnnotationTextHandler::isCursorInBlock(int blockPosition, int blockLength) const
 {
-	return mTextCursor.position() >= blockPosition && mTextCursor.position() < blockPosition + blockLength;
+	return mTextCursor->position() >= blockPosition && mTextCursor->position() < blockPosition + blockLength;
 }
 
 void AnnotationTextHandler::setupEditModeOutlinePen()
@@ -177,7 +188,7 @@ void AnnotationTextHandler::setupEditModeOutlinePen()
 QRect AnnotationTextHandler::getTextRect(QRectF *rect, const QFont& font, int margin) const
 {
 	QFontMetrics fontMetrics(font);
-	auto newRect = fontMetrics.boundingRect(rect->toRect().normalized(), Qt::AlignLeft, mText);
+	auto newRect = fontMetrics.boundingRect(rect->toRect().normalized(), Qt::AlignLeft, mTextDocument->toPlainText());
 	newRect.adjust(0, 2, (margin * 2) + 2, margin * 2);
 	return newRect;
 }
@@ -194,8 +205,11 @@ void AnnotationTextHandler::connectSlots()
 	connect(&mKeyInputHelper, &KeyInputHelper::insert, this, &AnnotationTextHandler::insertText);
 	connect(&mKeyInputHelper, &KeyInputHelper::remove, this, &AnnotationTextHandler::removeText);
 	connect(&mKeyInputHelper, &KeyInputHelper::paste, this, &AnnotationTextHandler::pasteText);
+	connect(&mKeyInputHelper, &KeyInputHelper::cut, this, &AnnotationTextHandler::cutText);
+	connect(&mKeyInputHelper, &KeyInputHelper::copy, this, &AnnotationTextHandler::copyText);
 	connect(&mKeyInputHelper, &KeyInputHelper::escape, this, &AnnotationTextHandler::finished);
-	connect(&mTextCursor, &TextCursor::tick, this, &AnnotationTextHandler::changed);
+	connect(&mKeyInputHelper, &KeyInputHelper::selectAll, this, &AnnotationTextHandler::selectAllText);
+	connect(mTextCursor, &TextCursor::tick, this, &AnnotationTextHandler::changed);
 }
 
 } // namespace kImageAnnotator
diff --git a/src/annotations/items/text/AnnotationTextHandler.h b/src/annotations/items/text/AnnotationTextHandler.h
index 57748d7..eec7e1a 100644
--- a/src/annotations/items/text/AnnotationTextHandler.h
+++ b/src/annotations/items/text/AnnotationTextHandler.h
@@ -23,6 +23,7 @@
 #include <QPainter>
 #include <QApplication>
 #include <QClipboard>
+#include <QTextCursor>
 
 #include "src/annotations/items/text/TextCursor.h"
 #include "src/common/filter/IgnoreShortcutsFilter.h"
@@ -50,19 +51,22 @@ signals:
 	void finished() const;
 
 private:
-	QString mText;
-	TextCursor mTextCursor;
 	IgnoreShortcutsFilter mIgnoreShortcutsFilter;
 	bool mIsInEditMode;
 	QPen mEditModeOutlinePen;
 	KeyInputHelper mKeyInputHelper;
+	QTextDocument *mTextDocument;
+	TextCursor *mTextCursor;
 
 	bool isCursorInBlock(int blockPosition, int blockLength) const;
 	void setupEditModeOutlinePen();
 	void connectSlots();
-	void removeText(TextPositions direction);
-	void moveCursor(TextPositions direction);
+	void removeText(QTextCursor::MoveOperation operation);
+	void moveCursor(QTextCursor::MoveOperation operation);
 	void pasteText();
+	void cutText();
+	void copyText();
+	void selectAllText();
 };
 
 } // namespace kImageAnnotator
diff --git a/src/annotations/items/text/KeyInputHelper.cpp b/src/annotations/items/text/KeyInputHelper.cpp
index 5a92fdb..d7e9fe1 100644
--- a/src/annotations/items/text/KeyInputHelper.cpp
+++ b/src/annotations/items/text/KeyInputHelper.cpp
@@ -25,7 +25,7 @@ void KeyInputHelper::handleKeyPress(const QKeyEvent *event) const
 {
 	switch (event->key()) {
 		case Qt::Key_Backspace:
-			emit remove(TextPositions::Previous);
+			emit remove(QTextCursor::Left);
 			break;
 		case Qt::Key_Return:
 		case Qt::Key_Enter:
@@ -36,36 +36,36 @@ void KeyInputHelper::handleKeyPress(const QKeyEvent *event) const
 			}
 			break;
 		case Qt::Key_Delete:
-			emit remove(TextPositions::Next);
+			emit remove(QTextCursor::Right);
 			break;
 		case Qt::Key_Escape:
 			emit escape();
 			return;
 		case Qt::Key_Left:
 			if (isControlPressed(event)) {
-				emit move(TextPositions::PreviousWordBeginning);
+				emit move(QTextCursor::PreviousWord);
 			} else {
-				emit move(TextPositions::Previous);
+				emit move(QTextCursor::Left);
 			}
 			break;
 		case Qt::Key_Right:
 			if (isControlPressed(event)) {
-				emit move(TextPositions::NextWordBeginning);
+				emit move(QTextCursor::NextWord);
 			} else {
-				emit move(TextPositions::Next);
+				emit move(QTextCursor::Right);
 			}
 			break;
 		case Qt::Key_Up:
-			emit move(TextPositions::Up);
+			emit move(QTextCursor::Up);
 			break;
 		case Qt::Key_Down:
-			emit move(TextPositions::Down);
+			emit move(QTextCursor::Down);
 			break;
 		case Qt::Key::Key_Home:
-			emit move(TextPositions::Beginning);
+			emit move(QTextCursor::Start);
 			break;
 		case Qt::Key::Key_End:
-			emit move(TextPositions::End);
+			emit move(QTextCursor::End);
 			break;
 		case Qt::Key_Paste:
 			emit paste();
@@ -75,6 +75,18 @@ void KeyInputHelper::handleKeyPress(const QKeyEvent *event) const
 				emit paste();
 				break;
 			}
+			if (event->matches(QKeySequence::Cut)) {
+				emit cut();
+				break;
+			}
+			if (event->matches(QKeySequence::Copy)) {
+				emit copy();
+				break;
+			}
+			if (event->matches(QKeySequence::SelectAll)) {
+				emit selectAll();
+				break;
+			}
 			if (event->text().isEmpty()) {
 				return;
 			}
diff --git a/src/annotations/items/text/KeyInputHelper.h b/src/annotations/items/text/KeyInputHelper.h
index d619cee..2f7726f 100644
--- a/src/annotations/items/text/KeyInputHelper.h
+++ b/src/annotations/items/text/KeyInputHelper.h
@@ -21,8 +21,8 @@
 #define KIMAGEANNOTATOR_KEYINPUTHELPER_H
 
 #include <QKeyEvent>
+#include <QTextCursor>
 
-#include "TextPositions.h"
 #include "CapsLockStatusChecker.h"
 
 namespace kImageAnnotator {
@@ -39,11 +39,14 @@ public:
 	QString getTextWithCorrectCase(const QKeyEvent *event) const;
 
 signals:
-	void remove(TextPositions position) const;
+	void remove(QTextCursor::MoveOperation operation) const;
 	void insert(const QString &text) const;
-	void move(TextPositions position) const;
+	void move(QTextCursor::MoveOperation operation) const;
 	void paste() const;
+	void cut() const;
+	void copy() const;
 	void escape() const;
+	void selectAll() const;
 
 private:
 	bool isModifierPressed(const QKeyEvent *event, Qt::KeyboardModifier modifier) const;
diff --git a/src/annotations/items/text/TextCursor.cpp b/src/annotations/items/text/TextCursor.cpp
index f986ca7..e033336 100644
--- a/src/annotations/items/text/TextCursor.cpp
+++ b/src/annotations/items/text/TextCursor.cpp
@@ -21,63 +21,26 @@
 
 namespace kImageAnnotator {
 
-TextCursor::TextCursor() :
-	mBlinkTimer(new QTimer(this)),
-	mLineFeedChar(QChar::LineFeed)
+TextCursor::TextCursor(QTextDocument *document) :
+	mInnerTextCursor(new QTextCursor(document)),
+	mBlinkTimer(new QTimer(this))
 {
 	connectSlots();
 }
 
 TextCursor::TextCursor(const TextCursor &other) :
-	mBlinkTimer(new QTimer(this)),
-	mPosition(other.mPosition),
-	mLineFeedChar(QChar::LineFeed)
+	mInnerTextCursor(new QTextCursor(*other.mInnerTextCursor)),
+	mBlinkTimer(new QTimer(this))
 {
 	connectSlots();
 }
 
 TextCursor::~TextCursor()
 {
+	delete mInnerTextCursor;
     delete mBlinkTimer;
 }
 
-void TextCursor::move(TextPositions direction, const QString &text)
-{
-    switch (direction) {
-        case TextPositions::Beginning:
-            moveCursorToBeginning();
-            break;
-        case TextPositions::End:
-            moveCursorToEnd(text);
-            break;
-        case TextPositions::NextWordBeginning:
-            moveCursorToNextWordBeginning(text);
-            break;
-        case TextPositions::Next:
-            moveCursorForwardBy(text, 1);
-            break;
-        case TextPositions::PreviousWordBeginning:
-            moveCursorToPreviousWordBeginning(text);
-            break;
-        case TextPositions::Previous:
-            moveCursorBack(text);
-            break;
-        case TextPositions::Up:
-            moveCursorUp(text);
-            break;
-        case TextPositions::Down:
-            moveCursorDown(text);
-            break;
-    }
-    mIsVisible = true;
-}
-
-void TextCursor::moveForwardBy(const QString &text, int moveBy)
-{
-	moveCursorForwardBy(text, moveBy);
-	mIsVisible = true;
-}
-
 void TextCursor::start()
 {
 	mIsVisible = true;
@@ -92,12 +55,13 @@ void TextCursor::stop()
 
 int TextCursor::position() const
 {
-    return mPosition;
+    return mInnerTextCursor->position();
 }
 
 void TextCursor::setPosition(int newPosition)
 {
-    mPosition = newPosition;
+    mInnerTextCursor->setPosition(newPosition);
+	mIsVisible = true;
 }
 
 bool TextCursor::isVisible() const
@@ -105,135 +69,43 @@ bool TextCursor::isVisible() const
     return mIsVisible;
 }
 
-void TextCursor::moveCursorToBeginning()
-{
-    mPosition = 0;
-}
-
-void TextCursor::moveCursorToEnd(const QString &text)
-{
-    mPosition = text.length();
-}
-
-void TextCursor::moveCursorToNextWordBeginning(const QString &text)
-{
-    auto lastSpacePos = -1;
-    auto currentPos = mPosition;
-
-    while (currentPos < text.length()) {
-		auto currentChar = text.at(currentPos);
-
-		if (currentChar == mLineFeedChar && currentPos != mPosition) {
-            break;
-        }
-
-        if (currentChar.isSpace()) {
-            lastSpacePos = currentPos;
-        } else if (lastSpacePos >= 0) {
-            break;
-        }
-        currentPos++;
-    }
-
-    mPosition = currentPos;
-}
-
-void TextCursor::moveCursorForwardBy(const QString &text, int moveBy)
+void TextCursor::insertText(const QString &text)
 {
-    mPosition += moveBy;
-    if (mPosition > text.length()) {
-        mPosition = text.length();
-    }
-}
-
-void TextCursor::moveCursorToPreviousWordBeginning(const QString &text)
-{
-    auto lastNonSpacePos = -1;
-    auto currentPos = mPosition - 1;
-
-    while (currentPos >= 0) {
-		auto currentChar = text.at(currentPos);
-
-		if (currentChar == mLineFeedChar) {
-			lastNonSpacePos = currentPos;
-
-            if (lastNonSpacePos + 1 != mPosition) {
-                lastNonSpacePos++;
-            }
-            break;
-        }
-
-        if (currentChar.isSpace()) {
-            if (lastNonSpacePos >= 0) {
-                break;
-            }
-        } else {
-            lastNonSpacePos = currentPos;
-        }
-        currentPos--;
-    }
-
-    if (lastNonSpacePos >= 0) {
-        mPosition = lastNonSpacePos;
-    } else {
-        mPosition = 0;
-    }
+	mInnerTextCursor->insertText(text);
+	mIsVisible = true;
 }
 
-void TextCursor::moveCursorBack(const QString &text)
+void TextCursor::deleteChar()
 {
-    mPosition--;
-    if (mPosition < 0) {
-        mPosition = 0;
-    }
+	mInnerTextCursor->deleteChar();
+	mIsVisible = true;
 }
 
-void TextCursor::moveCursorUp(const QString &text)
+void TextCursor::deletePreviousChar()
 {
-    QTextDocument document(text);
-    auto currentBlock = document.findBlock(mPosition);
-
-    if (currentBlock == document.firstBlock()) {
-        return;
-    }
-
-    auto positionInBlock = currentBlock.position();
-    auto previousBlock = currentBlock.previous();
-
-    fitPositionToNewBlock(positionInBlock, previousBlock);
+	mInnerTextCursor->deletePreviousChar();
+	mIsVisible = true;
 }
 
-void TextCursor::moveCursorDown(const QString &text)
+void TextCursor::movePosition(QTextCursor::MoveOperation operation)
 {
-    QTextDocument document(text);
-    auto currentBlock = document.findBlock(mPosition);
-    if (currentBlock == document.lastBlock()) {
-        return;
-    }
-
-    auto positionInBlock = currentBlock.position();
-    auto nextBlock = currentBlock.next();
-
-    fitPositionToNewBlock(positionInBlock, nextBlock);
+	mInnerTextCursor->movePosition(operation);
+	mIsVisible = true;
 }
 
-void TextCursor::fitPositionToNewBlock(int positionInBlock, const QTextBlock &targetBlock)
+QString TextCursor::selectedText() const
 {
-    if ((mPosition - positionInBlock) < targetBlock.length()) {
-        moveToSamePositionInNewBlock(positionInBlock, targetBlock);
-    } else {
-        movePositionToEndOfBlock(targetBlock);
-    }
+	return mInnerTextCursor->selectedText();
 }
 
-void TextCursor::moveToSamePositionInNewBlock(int positionInBlock, const QTextBlock &targetBlock)
+void TextCursor::removeSelectedText()
 {
-    mPosition = targetBlock.position() + mPosition - positionInBlock;
+	mInnerTextCursor->removeSelectedText();
 }
 
-void TextCursor::movePositionToEndOfBlock(const QTextBlock &targetBlock)
+void TextCursor::select(QTextCursor::SelectionType selection)
 {
-    mPosition = targetBlock.position() + targetBlock.length() - 1;
+	mInnerTextCursor->select(selection);
 }
 
 void TextCursor::connectSlots()
diff --git a/src/annotations/items/text/TextCursor.h b/src/annotations/items/text/TextCursor.h
index f93f171..6d33a27 100644
--- a/src/annotations/items/text/TextCursor.h
+++ b/src/annotations/items/text/TextCursor.h
@@ -24,46 +24,37 @@
 #include <QTextDocument>
 #include <QTextBlock>
 
-#include "TextPositions.h"
-
 namespace kImageAnnotator {
 
 class TextCursor : public QObject
 {
 Q_OBJECT
 public:
-    explicit TextCursor();
+    explicit TextCursor(QTextDocument *document);
 	TextCursor(const TextCursor &other);
     ~TextCursor() override;
-    void move(TextPositions direction, const QString &text);
-    void moveForwardBy(const QString &text, int moveBy);
     void start();
     void stop();
     int position() const;
     void setPosition(int newPosition);
     bool isVisible() const;
+	void insertText(const QString &text);
+	void deleteChar();
+	void deletePreviousChar();
+	void movePosition(QTextCursor::MoveOperation operation);
+	QString	selectedText() const;
+	void removeSelectedText();
+	void select(QTextCursor::SelectionType selection);
 
 signals:
     void tick() const;
 
 private:
+	QTextCursor *mInnerTextCursor;
     int mBlinkIntervalInMs = 800;
     QTimer *mBlinkTimer;
-    int mPosition = 0;
     bool mIsVisible = false;
-    QChar mLineFeedChar;
 
-    void moveCursorToBeginning();
-    void moveCursorToEnd(const QString &text);
-    void moveCursorToNextWordBeginning(const QString &text);
-    void moveCursorForwardBy(const QString &text, int moveBy);
-    void moveCursorToPreviousWordBeginning(const QString &text);
-    void moveCursorBack(const QString &text);
-    void moveCursorUp(const QString &text);
-    void moveCursorDown(const QString &text);
-    void fitPositionToNewBlock(int positionInBlock, const QTextBlock &targetBlock);
-    void movePositionToEndOfBlock(const QTextBlock &targetBlock);
-    void moveToSamePositionInNewBlock(int positionInBlock, const QTextBlock &targetBlock);
 	void connectSlots();
 };
 
diff --git a/src/annotations/items/text/TextHandlerItem.cpp b/src/annotations/items/text/TextHandlerItem.cpp
new file mode 100644
index 0000000..207853b
--- /dev/null
+++ b/src/annotations/items/text/TextHandlerItem.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2023 Damir Porobic <damir.porobic at gmx.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "TextHandlerItem.h"
+
+namespace kImageAnnotator {
+
+TextHandlerItem::TextHandlerItem(AbstractAnnotationItem *parentItem) :
+	QGraphicsTextItem(parentItem),
+	mIsFixedTextRectSize(false)
+{
+	connectSlots();
+	enableEditing();
+}
+
+
+TextHandlerItem::TextHandlerItem(const TextHandlerItem &other, AbstractAnnotationItem *parentItem) :
+	QGraphicsTextItem(other.toPlainText(), parentItem),
+	mIsFixedTextRectSize(other.mIsFixedTextRectSize)
+{
+	connectSlots();
+
+	document()->setPageSize(other.document()->pageSize());
+
+	auto currentTextCursor = textCursor();
+	currentTextCursor.setPosition(other.textCursor().position());
+	setTextCursor(currentTextCursor);
+}
+
+void TextHandlerItem::enableEditing()
+{
+	setTextInteractionFlags(Qt::TextEditorInteraction);
+	setFocus();
+}
+
+void TextHandlerItem::disableEditing()
+{
+	clearSelection();
+	setTextInteractionFlags(Qt::NoTextInteraction);
+	clearFocus();
+}
+
+bool TextHandlerItem::isEditing() const
+{
+	return textInteractionFlags() == Qt::TextEditorInteraction;
+}
+
+QRect TextHandlerItem::textRect() const
+{
+	auto rect = boundingRect().toRect().normalized();
+	auto position = pos().toPoint();
+	return { position.x(), position.y(), rect.width(), rect.height() };
+}
+
+void TextHandlerItem::setTextRect(const QRect &rect)
+{
+	mIsFixedTextRectSize = true;
+	document()->setPageSize(rect.size());
+	setPos(rect.topLeft());
+}
+
+QRectF TextHandlerItem::boundingRect() const 
+{
+	if(mIsFixedTextRectSize) {
+		auto position = QGraphicsTextItem::boundingRect().topLeft();
+		return { position, document()->pageSize() };
+	} else {
+		return QGraphicsTextItem::boundingRect();
+	}
+}
+
+void TextHandlerItem::setTextProperties(const TextPropertiesPtr &properties)
+{
+	setFont(properties->font());
+	setDefaultTextColor(properties->textColor());
+
+	emit textRectChanged();
+}
+
+QSize TextHandlerItem::minimumSize() const
+{
+	return ScaledSizeProvider::scaledSize(QSize(10, 30));
+}
+
+void TextHandlerItem::focusOutEvent(QFocusEvent *event)
+{
+	disableEditing();
+	QGraphicsTextItem::focusOutEvent(event);
+}
+
+void TextHandlerItem::keyPressEvent(QKeyEvent *event)
+{
+	if(event->key() == Qt::Key_Escape) {
+		disableEditing();
+	} else {
+		QGraphicsTextItem::keyPressEvent(event);
+	}
+}
+
+void TextHandlerItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget)
+{
+	// Workaround for issue #70 / #184 -> Cursor not drawn with Qt 5.9
+	// https://bugreports.qt.io/browse/QTBUG-82022
+	if (isEditing()) {
+		painter->setBrush(QColor(255,255,255,50));
+		painter->drawRect(boundingRect());
+	}
+
+	if (isEditing()) {
+		QGraphicsTextItem::paint(painter, style, widget);
+	} else {
+		QStyleOptionGraphicsItem myOption(*style);
+		myOption.state &= ~QStyle::State_Selected;
+		QGraphicsTextItem::paint(painter, &myOption, widget);
+	}
+
+	if(isEditing() && isTextOutsideVisibleRect()) {
+		auto offset = 7;
+		auto size = QSizeF(14, 4);
+		auto position = QPointF(boundingRect().center().x() - (size.width() / 2), boundingRect().bottom() - offset);
+		auto rect = QRectF(position, size);
+
+		QPainterPath path;
+		path.moveTo(rect.left() + (rect.width() / 2), rect.bottom());
+		path.lineTo(rect.topLeft());
+		path.lineTo(rect.topRight());
+		path.lineTo(rect.left() + (rect.width() / 2), rect.bottom());
+
+		painter->setRenderHint(QPainter::Antialiasing, true);
+		painter->fillPath(path, QBrush(QColor (Qt::red))); // Draw fill
+		painter->setPen(Qt::black);
+		painter->drawPath(path);   // Draw Outline
+	}
+}
+
+void TextHandlerItem::clearSelection()
+{
+	auto currentTextCursor = textCursor();
+	currentTextCursor.clearSelection();
+	setTextCursor(currentTextCursor);
+}
+
+bool TextHandlerItem::isTextOutsideVisibleRect() const
+{
+	return document()->pageCount() > 1;
+}
+
+void TextHandlerItem::connectSlots() const
+{
+	connect(document(), &QTextDocument::contentsChanged, this, &TextHandlerItem::textRectChanged);
+}
+
+} // namespace kImageAnnotator
\ No newline at end of file
diff --git a/src/annotations/items/text/TextHandlerItem.h b/src/annotations/items/text/TextHandlerItem.h
new file mode 100644
index 0000000..43eb6b8
--- /dev/null
+++ b/src/annotations/items/text/TextHandlerItem.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 Damir Porobic <damir.porobic at gmx.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KIMAGEANNOTATOR_TEXTHANDLERITEM_H
+#define KIMAGEANNOTATOR_TEXTHANDLERITEM_H
+
+#include <QGraphicsTextItem>
+#include <QStyleOptionGraphicsItem>
+#include <QTextCursor>
+#include <QTextDocument>
+#include <QGraphicsSceneMouseEvent>
+
+#include "src/annotations/items/AbstractAnnotationItem.h"
+#include "src/annotations/properties/AnnotationTextProperties.h"
+#include "src/common/provider/ScaledSizeProvider.h"
+
+namespace kImageAnnotator {
+
+class TextHandlerItem : public QGraphicsTextItem
+{
+Q_OBJECT
+public:
+	explicit TextHandlerItem(AbstractAnnotationItem *parentItem);
+	TextHandlerItem(const TextHandlerItem &other, AbstractAnnotationItem *parentItem);
+	void enableEditing();
+	void disableEditing();
+	bool isEditing() const;
+	QRect textRect() const;
+	void setTextRect(const QRect &rect);
+	QRectF boundingRect() const override;
+	void setTextProperties(const TextPropertiesPtr &properties);
+	QSize minimumSize() const;
+
+signals:
+	void textRectChanged();
+
+protected:
+	void focusOutEvent(QFocusEvent *event) override;
+	void keyPressEvent(QKeyEvent *event) override;
+	void paint(QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget *widget) override;
+
+private:
+	bool mIsFixedTextRectSize;
+
+	void clearSelection();
+	bool isTextOutsideVisibleRect() const;
+	void connectSlots() const;
+};
+
+} // namespace kImageAnnotator
+
+#endif //KIMAGEANNOTATOR_TEXTHANDLERITEM_H
diff --git a/src/annotations/misc/AnnotationItemClipboard.cpp b/src/annotations/misc/AnnotationItemClipboard.cpp
index 9ea78e1..a6b3606 100644
--- a/src/annotations/misc/AnnotationItemClipboard.cpp
+++ b/src/annotations/misc/AnnotationItemClipboard.cpp
@@ -21,22 +21,21 @@
 
 namespace kImageAnnotator {
 
-AnnotationItemClipboard::AnnotationItemClipboard(const AnnotationItemModifier *itemModifier)
+bool AnnotationItemClipboard::isEmpty() const
 {
-	Q_ASSERT(itemModifier != nullptr);
-
-	mItemModifier = itemModifier;
+	return mCopiedItemsToOffset.count() == 0;
 }
 
-bool AnnotationItemClipboard::isEmpty() const
+bool AnnotationItemClipboard::isNotEmpty() const
 {
-	return mCopiedItemsToOffset.count() == 0;
+	return !isEmpty();
 }
 
-void AnnotationItemClipboard::copyItems(const QPointF &position)
+void AnnotationItemClipboard::copyItems(const QPointF &position, const AnnotationItemModifier *itemModifier)
 {
 	clear();
-	for (auto item : mItemModifier->selectedItems()) {
+
+	for (auto item : itemModifier->selectedItems()) {
 		mCopiedItemsToOffset[item] = item->position() - position;
 	}
 }
diff --git a/src/annotations/misc/AnnotationItemClipboard.h b/src/annotations/misc/AnnotationItemClipboard.h
index 37db9d0..49a427b 100644
--- a/src/annotations/misc/AnnotationItemClipboard.h
+++ b/src/annotations/misc/AnnotationItemClipboard.h
@@ -32,17 +32,17 @@ class AnnotationItemClipboard : public QObject
 Q_OBJECT
 
 public:
-	explicit AnnotationItemClipboard(const AnnotationItemModifier *itemModifier);
+	explicit AnnotationItemClipboard() = default;
 	~AnnotationItemClipboard() override = default;
 	bool isEmpty() const;
+	bool isNotEmpty() const;
 	QHash<AbstractAnnotationItem *, QPointF> copiedItemsWithOffset() const;
 
 public slots:
-	void copyItems(const QPointF &position);
+	void copyItems(const QPointF &position, const AnnotationItemModifier *itemModifier);
 	void clear();
 
 private:
-	const AnnotationItemModifier *mItemModifier;
 	QHash<AbstractAnnotationItem *, QPointF> mCopiedItemsToOffset;
 };
 
diff --git a/src/annotations/undo/PasteCommand.cpp b/src/annotations/undo/PasteCommand.cpp
index 5dc019e..e749d1f 100644
--- a/src/annotations/undo/PasteCommand.cpp
+++ b/src/annotations/undo/PasteCommand.cpp
@@ -30,7 +30,6 @@ PasteCommand::PasteCommand(const QHash<kImageAnnotator::AbstractAnnotationItem *
 	Q_ASSERT(itemFactory != nullptr);
 
 	mAnnotationArea = annotationArea;
-	mItemFactory = itemFactory;
 	for (auto item : itemsWithOffset.keys()) {
 		auto pastedItem = itemFactory->clone(item);
 		pastedItem->setPosition(position + itemsWithOffset[item]);
diff --git a/src/annotations/undo/PasteCommand.h b/src/annotations/undo/PasteCommand.h
index de868b0..33b37d2 100644
--- a/src/annotations/undo/PasteCommand.h
+++ b/src/annotations/undo/PasteCommand.h
@@ -36,7 +36,6 @@ public:
 
 private:
 	AnnotationArea *mAnnotationArea;
-	AnnotationItemFactory *mItemFactory;
 	QVector<AbstractAnnotationItem*> mPastedItems;
 };
 
diff --git a/src/annotations/items/text/TextPositions.h b/src/common/filter/IKeyEventListener.h
similarity index 67%
copy from src/annotations/items/text/TextPositions.h
copy to src/common/filter/IKeyEventListener.h
index 0cb60a6..6e3bbfc 100644
--- a/src/annotations/items/text/TextPositions.h
+++ b/src/common/filter/IKeyEventListener.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Damir Porobic <damir.porobic at gmx.com>
+ * Copyright (C) 2023 Damir Porobic <damir.porobic at gmx.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
@@ -17,27 +17,20 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef KIMAGEANNOTATOR_TEXTPOSITIONS_H
-#define KIMAGEANNOTATOR_TEXTPOSITIONS_H
+#ifndef KIMAGEANNOTATOR_IKEYEVENTLISTENER_H
+#define KIMAGEANNOTATOR_IKEYEVENTLISTENER_H
 
-#include <QMetaType>
+#include <QKeyEvent>
 
 namespace kImageAnnotator {
 
-enum class TextPositions
+class IKeyEventListener
 {
-    Beginning,
-    End,
-    PreviousWordBeginning,
-    NextWordBeginning,
-    Next,
-    Previous,
-    Up,
-    Down
+public:
+	virtual void keyPressed(QKeyEvent *keyEvent) = 0;
+	virtual void keyReleased(QKeyEvent *keyEvent) = 0;
 };
 
 } // namespace kImageAnnotator
 
-Q_DECLARE_METATYPE(kImageAnnotator::TextPositions)
-
-#endif //KIMAGEANNOTATOR_TEXTPOSITIONS_H
+#endif //KIMAGEANNOTATOR_IKEYEVENTLISTENER_H
diff --git a/src/common/filter/KeyEventListener.cpp b/src/common/filter/KeyEventFilter.cpp
similarity index 67%
rename from src/common/filter/KeyEventListener.cpp
rename to src/common/filter/KeyEventFilter.cpp
index a34ef22..ce1efbc 100644
--- a/src/common/filter/KeyEventListener.cpp
+++ b/src/common/filter/KeyEventFilter.cpp
@@ -17,21 +17,27 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#include "KeyEventListener.h"
+#include "KeyEventFilter.h"
 
 namespace kImageAnnotator {
 
-KeyEventListener::KeyEventListener()
+KeyEventFilter::KeyEventFilter():
+	mKeyEventListener(nullptr)
 {
 	QCoreApplication::instance()->installEventFilter(this);
 }
 
-KeyEventListener::~KeyEventListener()
+KeyEventFilter::~KeyEventFilter()
 {
 	QCoreApplication::instance()->removeEventFilter(this);
 }
 
-bool KeyEventListener::eventFilter(QObject *watched, QEvent *event)
+void KeyEventFilter::setListener(IKeyEventListener *listener)
+{
+	mKeyEventListener = listener;
+}
+
+bool KeyEventFilter::eventFilter(QObject *watched, QEvent *event)
 {
 	if (event->type() == QEvent::KeyPress) {
 		handleKeyPressed(event);
@@ -42,24 +48,35 @@ bool KeyEventListener::eventFilter(QObject *watched, QEvent *event)
 	return QObject::eventFilter(watched, event);
 }
 
-void KeyEventListener::handleKeyReleased(QEvent *event)
+void KeyEventFilter::handleKeyReleased(QEvent *event)
 {
 	auto keyEvent = dynamic_cast<QKeyEvent *>(event);
 
 	if(mPressedKeyCodes.contains(keyEvent->key())) {
 		mPressedKeyCodes.removeAll(keyEvent->key());
-		emit keyReleased(keyEvent);
+
+		if(isListenerSet()) {
+			mKeyEventListener->keyReleased(keyEvent);
+		}
 	}
 }
 
-void KeyEventListener::handleKeyPressed(QEvent *event)
+void KeyEventFilter::handleKeyPressed(QEvent *event)
 {
 	auto keyEvent = dynamic_cast<QKeyEvent *>(event);
 
-	if(!mPressedKeyCodes.contains(keyEvent->key())) {
+	if(isListenerSet() && !mPressedKeyCodes.contains(keyEvent->key())) {
 		mPressedKeyCodes.append(keyEvent->key());
-		emit keyPressed(keyEvent);
+
+		if(isListenerSet()) {
+			mKeyEventListener->keyPressed(keyEvent);
+		}
 	}
 }
 
+bool KeyEventFilter::isListenerSet()
+{
+	return mKeyEventListener != nullptr;
+}
+
 } // namespace kImageAnnotator
\ No newline at end of file
diff --git a/src/common/filter/KeyEventListener.h b/src/common/filter/KeyEventFilter.h
similarity index 76%
rename from src/common/filter/KeyEventListener.h
rename to src/common/filter/KeyEventFilter.h
index 10fb6d9..ba09a9f 100644
--- a/src/common/filter/KeyEventListener.h
+++ b/src/common/filter/KeyEventFilter.h
@@ -17,36 +17,38 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef KIMAGEANNOTATOR_KEYEVENTLISTENER_H
-#define KIMAGEANNOTATOR_KEYEVENTLISTENER_H
+#ifndef KIMAGEANNOTATOR_KEYEVENTFILTER_H
+#define KIMAGEANNOTATOR_KEYEVENTFILTER_H
 
 #include <QObject>
 #include <QKeyEvent>
 #include <QCoreApplication>
 #include <QList>
 
+#include "IKeyEventListener.h"
+
 namespace kImageAnnotator {
 
-class KeyEventListener : public QObject
+class KeyEventFilter : public QObject
 {
 	Q_OBJECT
 public:
-	explicit KeyEventListener();
-	~KeyEventListener() override;
-
-signals:
-	void keyPressed(QKeyEvent *event);
-	void keyReleased(QKeyEvent *event);
+	explicit KeyEventFilter();
+	~KeyEventFilter() override;
+	void setListener(IKeyEventListener *listener);
 
 protected:
 	bool eventFilter(QObject *watched, QEvent *event) override;
 
 private:
 	QList<int> mPressedKeyCodes;
+	IKeyEventListener *mKeyEventListener;
+
 	void handleKeyPressed(QEvent *event);
 	void handleKeyReleased(QEvent *event);
+	bool isListenerSet();
 };
 
 } // namespace kImageAnnotator
 
-#endif //KIMAGEANNOTATOR_KEYEVENTLISTENER_H
+#endif //KIMAGEANNOTATOR_KEYEVENTFILTER_H
diff --git a/src/common/helper/IconLoader.cpp b/src/common/helper/IconLoader.cpp
index 4170bf2..9154b14 100644
--- a/src/common/helper/IconLoader.cpp
+++ b/src/common/helper/IconLoader.cpp
@@ -40,7 +40,7 @@ QString IconLoader::getThemePrefix()
 
 double IconLoader::getThemeLuma()
 {
-	auto color = QApplication::palette().background().color();
+	auto color = QApplication::palette().window().color();
 	return 0.2126 * color.redF() + 0.7152 * color.greenF() + 0.0722 * color.blueF();
 }
 
diff --git a/src/common/helper/ItemHelper.cpp b/src/common/helper/ItemHelper.cpp
index b48261f..8ad3903 100644
--- a/src/common/helper/ItemHelper.cpp
+++ b/src/common/helper/ItemHelper.cpp
@@ -28,7 +28,7 @@ bool ItemHelper::zValueGreaterThen(const AbstractAnnotationItem *item1, const Ab
 
 void ItemHelper::sortItemsByZValueDesc(QList<AbstractAnnotationItem *> *items)
 {
-    qSort(items->begin(), items->end(), ItemHelper::zValueGreaterThen);
+    std::sort(items->begin(), items->end(), ItemHelper::zValueGreaterThen);
 }
 
 } // namespace kImageAnnotator
diff --git a/src/common/helper/PathHelper.cpp b/src/common/helper/PathHelper.cpp
index f039b36..492af46 100644
--- a/src/common/helper/PathHelper.cpp
+++ b/src/common/helper/PathHelper.cpp
@@ -38,7 +38,7 @@ QString PathHelper::extractFilenameWithFormat(const QString &path)
 
 QString PathHelper::prettyFilename(const QString &filename)
 {
-	auto parts = filename.split(QLatin1Char('_'), QString::SkipEmptyParts);
+	auto parts = filename.split(QLatin1Char('_'), Qt::SkipEmptyParts);
 
 	for (auto i = 0; i < parts.size() ; i++) {
 		parts[i].replace(0, 1, parts[i][0].toUpper());
diff --git a/src/common/helper/IconLoader.cpp b/src/common/helper/RectSizeHelper.cpp
similarity index 50%
copy from src/common/helper/IconLoader.cpp
copy to src/common/helper/RectSizeHelper.cpp
index 4170bf2..f41f349 100644
--- a/src/common/helper/IconLoader.cpp
+++ b/src/common/helper/RectSizeHelper.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 Damir Porobic <damir.porobic at gmx.com>
+ * Copyright (C) 2023 Damir Porobic <damir.porobic at gmx.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
@@ -17,36 +17,38 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#include "IconLoader.h"
+#include "RectSizeHelper.h"
 
 namespace kImageAnnotator {
 
-QIcon IconLoader::load(const QString &name)
+QRectF RectSizeHelper::setSizeButKeepDirection(const QRectF &rect, const QSizeF &newSize)
 {
-	auto type = getThemePrefix();
-	return QIcon(QLatin1String(":/icons/") + type + name);
-}
+	auto updatedRect = rect;
 
-QPixmap IconLoader::loadAsPixmap(const QString &name)
-{
-	auto type = getThemePrefix();
-	return QPixmap(QLatin1String(":/icons/") + type + name);
-}
+	updatedRect.setWidth(getSign(rect.width()) * newSize.width());
+	updatedRect.setHeight(getSign(rect.height()) * newSize.height());
 
-QString IconLoader::getThemePrefix()
-{
-	return isDarkTheme() ? QLatin1String("dark/") : QLatin1String("light/");
+	return updatedRect;
 }
 
-double IconLoader::getThemeLuma()
+QRectF RectSizeHelper::limitToSize(const QRectF &rect, const QSizeF &minSize)
 {
-	auto color = QApplication::palette().background().color();
-	return 0.2126 * color.redF() + 0.7152 * color.greenF() + 0.0722 * color.blueF();
+	auto updatedRect = rect;
+
+	if (qAbs(rect.width()) < minSize.width()) {
+		updatedRect.setWidth(getSign(rect.width()) * minSize.width());
+	}
+
+	if (qAbs(rect.height()) < minSize.height()) {
+		updatedRect.setHeight(getSign(rect.height()) * minSize.height());
+	}
+
+	return updatedRect;
 }
 
-bool IconLoader::isDarkTheme()
+qreal RectSizeHelper::getSign(const qreal &value)
 {
-	return getThemeLuma() > 0.4;
+	return value < 0 ? -1 : 1;
 }
 
 } // namespace kImageAnnotator
\ No newline at end of file
diff --git a/src/annotations/items/text/TextPositions.h b/src/common/helper/RectSizeHelper.h
similarity index 62%
rename from src/annotations/items/text/TextPositions.h
rename to src/common/helper/RectSizeHelper.h
index 0cb60a6..e9e14bc 100644
--- a/src/annotations/items/text/TextPositions.h
+++ b/src/common/helper/RectSizeHelper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Damir Porobic <damir.porobic at gmx.com>
+ * Copyright (C) 2023 Damir Porobic <damir.porobic at gmx.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
@@ -17,27 +17,26 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef KIMAGEANNOTATOR_TEXTPOSITIONS_H
-#define KIMAGEANNOTATOR_TEXTPOSITIONS_H
+#ifndef KIMAGEANNOTATOR_RECTSIZEHELPER_H
+#define KIMAGEANNOTATOR_RECTSIZEHELPER_H
 
-#include <QMetaType>
+#include <QRectF>
 
 namespace kImageAnnotator {
 
-enum class TextPositions
+class RectSizeHelper
 {
-    Beginning,
-    End,
-    PreviousWordBeginning,
-    NextWordBeginning,
-    Next,
-    Previous,
-    Up,
-    Down
+public:
+	static QRectF setSizeButKeepDirection(const QRectF &rect, const QSizeF &newSize);
+	static QRectF limitToSize(const QRectF &rect, const QSizeF &minSize);
+
+private:
+	RectSizeHelper() = default;
+	~RectSizeHelper() = default;
+
+	static qreal getSign(const qreal &value);
 };
 
 } // namespace kImageAnnotator
 
-Q_DECLARE_METATYPE(kImageAnnotator::TextPositions)
-
-#endif //KIMAGEANNOTATOR_TEXTPOSITIONS_H
+#endif //KIMAGEANNOTATOR_RECTSIZEHELPER_H
diff --git a/src/common/helper/ShapeHelper.cpp b/src/common/helper/ShapeHelper.cpp
index f86cc0b..39adf83 100644
--- a/src/common/helper/ShapeHelper.cpp
+++ b/src/common/helper/ShapeHelper.cpp
@@ -132,54 +132,62 @@ QRectF ShapeHelper::setRectPointAtIndex(const QRectF &rect, int index, const QPo
 {
 	auto updatedRect = rect;
 	if (index == 0) {
-		if (!keepAspectRatio) {
-			updatedRect.setTopLeft(pos);
-		} else {
+		if (keepAspectRatio) {
 			const auto xDif = updatedRect.topLeft().x() - pos.x();
 			const auto yDif = updatedRect.topLeft().y() - pos.y();
 			const auto min = qMin(xDif, yDif);
 			const auto newX = updatedRect.topLeft().x() - min;
 			const auto newY = updatedRect.topLeft().y() - min;
-			updatedRect.setTopLeft(QPointF(newX, newY));
+			auto newTopLeft = QPointF(newX, newY);
+			
+			updatedRect.setTopLeft(newTopLeft);
+		} else {
+			updatedRect.setTopLeft(pos);
 		}
 	} else if (index == 1) {
 		updatedRect.setTop(pos.y());
 	} else if (index == 2) {
-		if (!keepAspectRatio) {
-			updatedRect.setTopRight(pos);
-		} else {
+		if (keepAspectRatio) {
 			const auto xDif = pos.x() - updatedRect.topRight().x();
 			const auto yDif = updatedRect.topRight().y() - pos.y();
 			const auto min = qMin(xDif, yDif);
 			const auto newX = updatedRect.topRight().x() + min;
 			const auto newY = updatedRect.topRight().y() - min;
-			updatedRect.setTopRight(QPointF(newX, newY));
+			auto newTopRight = QPointF(newX, newY);
+			
+			updatedRect.setTopRight(newTopRight);
+		} else {
+			updatedRect.setTopRight(pos);
 		}
 	} else if (index == 3) {
 		updatedRect.setRight(pos.x());
 	} else if (index == 4) {
-		if (!keepAspectRatio) {
-			updatedRect.setBottomRight(pos);
-		} else {
+		if (keepAspectRatio) {
 			const auto xDif = pos.x() - updatedRect.bottomRight().x();
 			const auto yDif = pos.y() - updatedRect.bottomRight().y();
 			const auto min = qMin(xDif, yDif);
 			const auto newX = updatedRect.bottomRight().x() + min;
 			const auto newY = updatedRect.bottomRight().y() + min;
-			updatedRect.setBottomRight(QPointF(newX, newY));
+			auto newBottomRight = QPointF(newX, newY);
+			
+			updatedRect.setBottomRight(newBottomRight);
+		} else {
+			updatedRect.setBottomRight(pos);
 		}
 	} else if (index == 5) {
 		updatedRect.setBottom(pos.y());
 	} else if (index == 6) {
-		if (!keepAspectRatio) {
-			updatedRect.setBottomLeft(pos);
-		} else {
+		if (keepAspectRatio) {
 			const auto xDif = updatedRect.bottomLeft().x() - pos.x();
 			const auto yDif = pos.y() - updatedRect.bottomLeft().y();
 			const auto min = qMin(xDif, yDif);
 			const auto newX = updatedRect.bottomLeft().x() - min;
 			const auto newY = updatedRect.bottomLeft().y() + min;
-			updatedRect.setBottomLeft(QPointF(newX, newY));
+			auto newBottomLeft = QPointF(newX, newY);
+
+			updatedRect.setBottomLeft(newBottomLeft);
+		} else {
+			updatedRect.setBottomLeft(pos);
 		}
 	} else if (index == 7) {
 		updatedRect.setLeft(pos.x());
@@ -300,7 +308,7 @@ QPointF ShapeHelper::intersectionBetweenRectAndLineFromCenter(const QLineF &line
 
 bool ShapeHelper::linesIntersect(const QLineF &line1, const QLineF &line2, QPointF &intersection)
 {
-	return line1.intersect(line2, &intersection) == QLineF::BoundedIntersection;
+	return line1.intersects(line2, &intersection) == QLineF::BoundedIntersection;
 }
 
 } // namespace kImageAnnotator
diff --git a/src/common/provider/DevicePixelRatioScaler.cpp b/src/common/provider/DevicePixelRatioScaler.cpp
index 1e3f68c..2a88b0c 100644
--- a/src/common/provider/DevicePixelRatioScaler.cpp
+++ b/src/common/provider/DevicePixelRatioScaler.cpp
@@ -19,6 +19,8 @@
 
 #include "DevicePixelRatioScaler.h"
 
+#include <QRectF>
+
 namespace kImageAnnotator {
 
 QRectF DevicePixelRatioScaler::scale(const QRectF &rect) const
@@ -29,8 +31,7 @@ QRectF DevicePixelRatioScaler::scale(const QRectF &rect) const
 
 qreal DevicePixelRatioScaler::scaleFactor() const
 {
-	auto desktopWidget = QApplication::desktop();
-	return desktopWidget->devicePixelRatioF();
+	return qGuiApp->devicePixelRatio();
 }
 
 } // namespace kImageAnnotator
diff --git a/src/common/provider/DevicePixelRatioScaler.h b/src/common/provider/DevicePixelRatioScaler.h
index ef2686c..71d2335 100644
--- a/src/common/provider/DevicePixelRatioScaler.h
+++ b/src/common/provider/DevicePixelRatioScaler.h
@@ -21,7 +21,6 @@
 #define KIMAGEANNOTATOR_DEVICEPIXELRATIOSCALER_H
 
 #include <QApplication>
-#include <QDesktopWidget>
 
 #include "IDevicePixelRatioScaler.h"
 
diff --git a/src/gui/annotator/tabs/AnnotationTabContent.cpp b/src/gui/annotator/tabs/AnnotationTabContent.cpp
index 9a6b16f..8809361 100644
--- a/src/gui/annotator/tabs/AnnotationTabContent.cpp
+++ b/src/gui/annotator/tabs/AnnotationTabContent.cpp
@@ -21,10 +21,10 @@
 
 namespace kImageAnnotator {
 
-AnnotationTabContent::AnnotationTabContent(const QPixmap &pixmap, Config *config, AbstractSettingsProvider *settingsProvider) :
+AnnotationTabContent::AnnotationTabContent(const QPixmap &pixmap, Config *config, AbstractSettingsProvider *settingsProvider, AnnotationItemClipboard *itemClipboard) :
 	mAnnotationView(new AnnotationView(this)),
 	mZoomValueProvider(mAnnotationView->zoomValueProvider()),
-	mAnnotationArea(new AnnotationArea(config, settingsProvider, new DevicePixelRatioScaler, mZoomValueProvider, this)),
+	mAnnotationArea(new AnnotationArea(config, settingsProvider, new DevicePixelRatioScaler, mZoomValueProvider, itemClipboard, this)),
 	mMainLayout(new QHBoxLayout(this)),
 	mSettingsProvider(settingsProvider)
 {
diff --git a/src/gui/annotator/tabs/AnnotationTabContent.h b/src/gui/annotator/tabs/AnnotationTabContent.h
index a56fe20..89016b1 100644
--- a/src/gui/annotator/tabs/AnnotationTabContent.h
+++ b/src/gui/annotator/tabs/AnnotationTabContent.h
@@ -35,7 +35,7 @@ class AnnotationTabContent : public QWidget
 {
 	Q_OBJECT
 public:
-	AnnotationTabContent(const QPixmap &pixmap, Config *config, AbstractSettingsProvider *settingsProvider);
+	AnnotationTabContent(const QPixmap &pixmap, Config *config, AbstractSettingsProvider *settingsProvider, AnnotationItemClipboard *itemClipboard);
 	~AnnotationTabContent() override = default;
 	AnnotationArea* annotationArea() const;
 	ZoomValueProvider* zoomValueProvider() const;
diff --git a/src/gui/annotator/tabs/AnnotationTabWidget.cpp b/src/gui/annotator/tabs/AnnotationTabWidget.cpp
index edccaae..6db1180 100644
--- a/src/gui/annotator/tabs/AnnotationTabWidget.cpp
+++ b/src/gui/annotator/tabs/AnnotationTabWidget.cpp
@@ -29,7 +29,8 @@ AnnotationTabWidget::AnnotationTabWidget(Config *config, AbstractSettingsProvide
 	mRedoAction(new QAction(this)),
 	mTabContextMenu(new AnnotationTabContextMenu(this)),
 	mTabCloser(new AnnotationTabCloser(this)),
-	mTabClickFilter(new AnnotationTabClickEventFilter(mTabBar, this))
+	mTabClickFilter(new AnnotationTabClickEventFilter(mTabBar, this)),
+	mItemClipboard(new AnnotationItemClipboard())
 {
 	setTabBarAutoHide(true);
 	setMovable(true);
@@ -53,7 +54,7 @@ AnnotationTabWidget::AnnotationTabWidget(Config *config, AbstractSettingsProvide
 
 int AnnotationTabWidget::addTab(const QPixmap &image, const QString &title, const QString &toolTip)
 {
-	auto content = new AnnotationTabContent(image, mConfig, mSettingsProvider);
+	auto content = new AnnotationTabContent(image, mConfig, mSettingsProvider, mItemClipboard);
 	connect(content->annotationArea(), &AnnotationArea::imageChanged, this, &AnnotationTabWidget::imageChanged);
 
     auto newTabIndex = QTabWidget::addTab(content, title);
@@ -64,7 +65,7 @@ int AnnotationTabWidget::addTab(const QPixmap &image, const QString &title, cons
 
 int AnnotationTabWidget::insertTab(int index, const QPixmap &image, const QString &title, const QString &toolTip)
 {
-	auto content = new AnnotationTabContent(image, mConfig, mSettingsProvider);
+	auto content = new AnnotationTabContent(image, mConfig, mSettingsProvider, mItemClipboard);
     connect(content->annotationArea(), &AnnotationArea::imageChanged, this, &AnnotationTabWidget::imageChanged);
 
     auto newTabIndex = QTabWidget::insertTab(index, content, title);
@@ -155,6 +156,7 @@ void AnnotationTabWidget::tabChanged()
 {
 	mSettingsProvider->setActiveListener(currentAnnotationArea());
 	mSettingsProvider->setActiveZoomValueProvider(currentZoomValueProvider());
+	mKeyEventFilter.setListener(currentAnnotationArea());
 }
 
 void AnnotationTabWidget::addContextMenuActions(const QList<QAction *> &actions)
diff --git a/src/gui/annotator/tabs/AnnotationTabWidget.h b/src/gui/annotator/tabs/AnnotationTabWidget.h
index ab49945..34bd341 100644
--- a/src/gui/annotator/tabs/AnnotationTabWidget.h
+++ b/src/gui/annotator/tabs/AnnotationTabWidget.h
@@ -27,6 +27,8 @@
 #include "AnnotationTabContextMenu.h"
 #include "AnnotationTabCloser.h"
 #include "AnnotationTabClickEventFilter.h"
+#include "src/common/filter/KeyEventFilter.h"
+
 
 namespace kImageAnnotator {
 
@@ -69,6 +71,8 @@ private:
 	AnnotationTabContextMenu *mTabContextMenu;
 	AnnotationTabCloser *mTabCloser;
 	AnnotationTabClickEventFilter *mTabClickFilter;
+	AnnotationItemClipboard *mItemClipboard;
+	KeyEventFilter mKeyEventFilter;
 
 private slots:
 	void updateCurrentWidget(int index);
diff --git a/src/gui/scrollAndZoomView/ScrollAndZoomView.cpp b/src/gui/scrollAndZoomView/ScrollAndZoomView.cpp
index 66faab5..287aaa3 100644
--- a/src/gui/scrollAndZoomView/ScrollAndZoomView.cpp
+++ b/src/gui/scrollAndZoomView/ScrollAndZoomView.cpp
@@ -70,7 +70,7 @@ void ScrollAndZoomView::mouseMoveEvent(QMouseEvent *event)
 
 void ScrollAndZoomView::mousePressEvent(QMouseEvent *event)
 {
-	if (event->button() == Qt::MidButton) {
+	if (event->button() == Qt::MiddleButton) {
 		enableDragging(event->pos());
 	} else {
 		QGraphicsView::mousePressEvent(event);
@@ -79,7 +79,7 @@ void ScrollAndZoomView::mousePressEvent(QMouseEvent *event)
 
 void ScrollAndZoomView::mouseReleaseEvent(QMouseEvent *event)
 {
-	if (event->button() == Qt::MidButton) {
+	if (event->button() == Qt::MiddleButton) {
 		disableDragging();
 	} else {
 		QGraphicsView::mouseReleaseEvent(event);
diff --git a/src/gui/scrollAndZoomView/ViewZoomer.cpp b/src/gui/scrollAndZoomView/ViewZoomer.cpp
index 91a17da..72c7a2d 100644
--- a/src/gui/scrollAndZoomView/ViewZoomer.cpp
+++ b/src/gui/scrollAndZoomView/ViewZoomer.cpp
@@ -42,7 +42,7 @@ void ViewZoomer::zoom(double factor)
 	newZoomValue = QString::number(newZoomValue, 'f', 1).toDouble();
 
 	if(newZoomValue >= mMinScale && newZoomValue <= mMaxScale) {
-		mView->resetMatrix();
+		mView->resetTransform();
 		mView->scale(newZoomValue, newZoomValue);
 		emit zoomValueChanged(zoomValue());
 	}
@@ -61,7 +61,7 @@ void ViewZoomer::wheelZoom(QWheelEvent *event)
 	auto zoomInFactor = 0.1;
 
 	const auto factor = event->angleDelta().y() < 0.0 ? -zoomInFactor : zoomInFactor;
-	zoomToPoint(factor, event->pos());
+	zoomToPoint(factor, event->position().toPoint());
 	event->accept(); // supress scrolling
 }
 
diff --git a/src/widgets/ToolPicker.cpp b/src/widgets/ToolPicker.cpp
index 1f1e845..769d943 100644
--- a/src/widgets/ToolPicker.cpp
+++ b/src/widgets/ToolPicker.cpp
@@ -126,7 +126,7 @@ QAction *ToolPicker::createAction(const QString &tooltip, const QIcon &icon, Qt:
 	action->setCheckable(true);
 	action->setIcon(icon);
 	action->setShortcut(shortcut);
-	action->setToolTip(tooltip + QLatin1String(" (") + shortcut + QLatin1String(")"));
+	action->setToolTip(tooltip);
 	action->updateDefaultWidget();
 	mActionToTool[action] = toolType;
 	mActionGroup->addAction(action);
diff --git a/src/widgets/menuButtons/ListMenuItem.cpp b/src/widgets/menuButtons/ListMenuItem.cpp
index eb9cbf3..1ffa59b 100644
--- a/src/widgets/menuButtons/ListMenuItem.cpp
+++ b/src/widgets/menuButtons/ListMenuItem.cpp
@@ -35,7 +35,7 @@ ListMenuItem::ListMenuItem(const QIcon &icon, const QString &text, const QVarian
 
 	mIconSize = ScaledSizeProvider::menuItemIconSize();
 	auto offsetForTextWidth = 1.15; // Width not correct calculated on windows #117
-	mTextSize = QSize(fontMetrics().width(mText) * offsetForTextWidth, fontMetrics().height());
+	mTextSize = QSize(fontMetrics().horizontalAdvance(mText) * offsetForTextWidth, fontMetrics().height());
 	mIconOffset = QPoint(mMargin, mMargin);
 	mTextOffset = QPoint(mIconSize.width() + mIconOffset.x() + mSpacer, (mIconSize.height() - mTextSize.height()) / 2 + mIconOffset.y());
 	mSize = QSize(mIconSize.width() + mTextSize.width() + mMargin * 2 + mSpacer, mIconSize.height() + mMargin * 2);
diff --git a/src/widgets/settingsPicker/ColorPicker.h b/src/widgets/settingsPicker/ColorPicker.h
index 8a69698..8c31921 100644
--- a/src/widgets/settingsPicker/ColorPicker.h
+++ b/src/widgets/settingsPicker/ColorPicker.h
@@ -24,7 +24,7 @@
 #include <QHBoxLayout>
 #include <QLabel>
 
-#include <kColorPicker/KColorPicker.h>
+#include "kColorPicker/KColorPicker.h"
 
 #include "SettingsPickerWidget.h"
 #include "src/common/provider/ScaledSizeProvider.h"
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 55c7ef0..fe2d1da 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,4 +1,4 @@
-find_package(Qt5 ${QT_MIN_VERSION} REQUIRED Test)
+find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} REQUIRED Test)
 find_package(GTest CONFIG REQUIRED)
 
 enable_testing()
@@ -69,10 +69,10 @@ set(TESTUTILS_SRC
 add_library(KIMAGEANNOTATOR_STATIC STATIC ${KIMAGEANNOTATOR_SRCS})
 
 target_link_libraries(KIMAGEANNOTATOR_STATIC
-		Qt5::Widgets
+		Qt${QT_MAJOR_VERSION}::Widgets
 		kImageAnnotator::kImageAnnotator
 		kColorPicker::kColorPicker
-		Qt5::Svg)
+		Qt${QT_MAJOR_VERSION}::Svg)
 
 if (UNIX AND NOT APPLE)
 	# X11::X11 imported target only available with sufficiently new CMake
@@ -88,6 +88,6 @@ target_compile_definitions(KIMAGEANNOTATOR_STATIC PRIVATE KIMAGEANNOTATOR_LANG_I
 foreach (UnitTest ${UNITTEST_SRC})
 	get_filename_component(UnitTestName ${UnitTest} NAME_WE)
 	add_executable(${UnitTestName} ${UnitTest} ${TESTUTILS_SRC})
-	target_link_libraries(${UnitTestName} KIMAGEANNOTATOR_STATIC GTest::gmock Qt5::Test)
+	target_link_libraries(${UnitTestName} KIMAGEANNOTATOR_STATIC GTest::gmock Qt${QT_MAJOR_VERSION}::Test)
 	add_test(${UnitTestName} ${UnitTestName})
 endforeach (UnitTest)
diff --git a/tests/annotations/core/AnnotationAreaTest.cpp b/tests/annotations/core/AnnotationAreaTest.cpp
index e3a4541..c7b475b 100644
--- a/tests/annotations/core/AnnotationAreaTest.cpp
+++ b/tests/annotations/core/AnnotationAreaTest.cpp
@@ -25,7 +25,8 @@ void AnnotationAreaTest::ExportAsImage_Should_ExportImage_When_ImageSet()
 	pixmap.fill(QColor(Qt::green));
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, itemClipboard,nullptr);
 	annotationArea.loadImage(pixmap);
 
 	auto resultImage = annotationArea.image();
@@ -38,7 +39,8 @@ void AnnotationAreaTest::ExportAsImage_Should_ExportEmptyImage_When_NoImageSet()
 {
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, itemClipboard, nullptr);
 
 	auto resultImage = annotationArea.image();
 
@@ -53,7 +55,8 @@ void AnnotationAreaTest::ExportAsImage_Should_ExportScaledImage_When_ScalingEnab
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
 	scalerMock->setScaleFactor(scaleFactor);
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, itemClipboard, nullptr);
 	annotationArea.loadImage(pixmap);
 
 	auto resultImage = annotationArea.image();
@@ -72,7 +75,7 @@ void AnnotationAreaTest::AddAnnotationItem_Should_AddAnnotationItemToScene()
 	lineItem->addPoint(p2, false);
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 
 	annotationArea.addAnnotationItem(lineItem);
 
@@ -88,7 +91,7 @@ void AnnotationAreaTest::RemoveAnnotationItem_Should_RemoveAnnotationItemFromSce
 	lineItem->addPoint(p2, false);
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	annotationArea.addAnnotationItem(lineItem);
 	QCOMPARE(annotationArea.items().contains(lineItem), true);
 
@@ -104,7 +107,8 @@ void AnnotationAreaTest::CanvasRect_Should_ReturnRectUnionOfAllItems_When_NoCanv
 	pixmap.fill(QColor(Qt::green));
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, itemClipboard, nullptr);
 	annotationArea.loadImage(pixmap);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 2));
 	QPointF p1(10, 10);
@@ -126,7 +130,8 @@ void AnnotationAreaTest::CanvasRect_Should_ReturnUserDefinedRect_When_CanvasRect
 	pixmap.fill(QColor(Qt::green));
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, itemClipboard, nullptr);
 	annotationArea.loadImage(pixmap);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 2));
 	QPointF p1(10, 10);
diff --git a/tests/annotations/core/AnnotationAreaTest.h b/tests/annotations/core/AnnotationAreaTest.h
index 42cf466..7659720 100644
--- a/tests/annotations/core/AnnotationAreaTest.h
+++ b/tests/annotations/core/AnnotationAreaTest.h
@@ -34,6 +34,7 @@ using kImageAnnotator::AnnotationProperties;
 using kImageAnnotator::Config;
 using kImageAnnotator::PropertiesPtr;
 using kImageAnnotator::ResizeHandle;
+using kImageAnnotator::AnnotationItemClipboard;
 
 class AnnotationAreaTest : public QObject
 {
diff --git a/tests/annotations/core/AnnotationPropertiesFactoryTest.cpp b/tests/annotations/core/AnnotationPropertiesFactoryTest.cpp
index 77b4305..ce5047e 100644
--- a/tests/annotations/core/AnnotationPropertiesFactoryTest.cpp
+++ b/tests/annotations/core/AnnotationPropertiesFactoryTest.cpp
@@ -199,7 +199,7 @@ void AnnotationPropertiesFactoryTest::TestCreate_Should_SetToolFontBasedOnSettin
 void AnnotationPropertiesFactoryTest::TestCreate_Should_StickerPathBasedOnSettings()
 {
 	auto tool = Tools::Sticker;
-	auto path = QLatin1Literal("/my/path/to/sticker");
+	auto path = QStringLiteral("/my/path/to/sticker");
 	MockDefaultParameters parameters;
 	auto settingsProvider = new MockSettingsProvider();
 	settingsProvider->setSticker(path);
diff --git a/tests/annotations/items/helper/KeyInputHelperTest.cpp b/tests/annotations/items/helper/KeyInputHelperTest.cpp
index 8536ecb..fef79b4 100644
--- a/tests/annotations/items/helper/KeyInputHelperTest.cpp
+++ b/tests/annotations/items/helper/KeyInputHelperTest.cpp
@@ -20,9 +20,11 @@
 
 #include "KeyInputHelperTest.h"
 
+Q_DECLARE_METATYPE(QTextCursor::MoveOperation)
+
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitRemoveSignal_When_KeyIsBackspace()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::remove);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier);
@@ -30,13 +32,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitRemoveSignal_When_KeyIsBa
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::Previous);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::Left);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitRemoveSignal_When_KeyIsDelete()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::remove);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier);
@@ -44,8 +46,8 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitRemoveSignal_When_KeyIsDe
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::Next);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::Right);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitInsertSignalWithNewLine_When_KeyIsReturnAndModifierShift()
@@ -109,7 +111,7 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitEscapeSignal_When_KeyIsEs
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsHome()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Home, Qt::NoModifier);
@@ -117,13 +119,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsHome
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::Beginning);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::Start);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsEnd()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_End, Qt::NoModifier);
@@ -131,13 +133,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsEnd(
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::End);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::End);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArrowLeft()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier);
@@ -145,13 +147,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArro
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::Previous);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::Left);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArrowLeftAndModifierCtrl()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::ControlModifier);
@@ -159,13 +161,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArro
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::PreviousWordBeginning);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::PreviousWord);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArrowRight()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier);
@@ -173,13 +175,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArro
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::Next);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::Right);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArrowRightAndModifierCtrl()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::ControlModifier);
@@ -187,13 +189,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArro
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::NextWordBeginning);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::NextWord);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArrowUp()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
@@ -201,13 +203,13 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArro
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::Up);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::Up);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArrowDown()
 {
-	qRegisterMetaType<TextPositions>("TextPositions");
+	qRegisterMetaType<QTextCursor::MoveOperation>("MoveOperation");
 	KeyInputHelper keyInputHelper;
 	QSignalSpy spy(&keyInputHelper, &KeyInputHelper::move);
 	QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
@@ -215,8 +217,8 @@ void KeyInputHelperTest::TestHandleKeyPress_Should_EmitMoveSignal_When_KeyIsArro
 	keyInputHelper.handleKeyPress(&keyEvent);
 
 	QCOMPARE(spy.count(), 1);
-	auto resultDirection = qvariant_cast<TextPositions>(spy.at(0).at(0));
-	QCOMPARE(resultDirection, TextPositions::Down);
+	auto resultDirection = qvariant_cast<QTextCursor::MoveOperation>(spy.at(0).at(0));
+	QCOMPARE(resultDirection, QTextCursor::Down);
 }
 
 void KeyInputHelperTest::TestHandleKeyPress_Should_EmitPasteSignal_When_KeyIsPaste()
diff --git a/tests/annotations/items/helper/KeyInputHelperTest.h b/tests/annotations/items/helper/KeyInputHelperTest.h
index 849812b..90c67ef 100644
--- a/tests/annotations/items/helper/KeyInputHelperTest.h
+++ b/tests/annotations/items/helper/KeyInputHelperTest.h
@@ -26,7 +26,6 @@
 #include "src/annotations/items/text/KeyInputHelper.h"
 
 using kImageAnnotator::KeyInputHelper;
-using kImageAnnotator::TextPositions;
 
 class KeyInputHelperTest : public QObject
 {
diff --git a/tests/annotations/items/helper/TextCursorTest.cpp b/tests/annotations/items/helper/TextCursorTest.cpp
index 82af008..3c2d963 100644
--- a/tests/annotations/items/helper/TextCursorTest.cpp
+++ b/tests/annotations/items/helper/TextCursorTest.cpp
@@ -21,26 +21,26 @@
 
 void TextCursorTest::TestMove_Should_MoveCursorToBeginning_When_DirectionBeginning()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+    TextCursor textCursor(&textDocument);
     textCursor.setPosition(16);
 
-    textCursor.move(TextPositions::Beginning, text);
+    textCursor.movePosition(QTextCursor::Start);
 
     QCOMPARE(textCursor.position(), 0);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToEnd_When_DirectionEnd()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     QCOMPARE(textCursor.position(), 0);
 
-    textCursor.move(TextPositions::End, text);
+    textCursor.movePosition(QTextCursor::End);
 
     QCOMPARE(textCursor.position(), 16);
 
@@ -48,28 +48,28 @@ void TextCursorTest::TestMove_Should_MoveCursorToEnd_When_DirectionEnd()
 
 void TextCursorTest::TestMove_Should_MoveCursorByOnePointToRight_When_DirectionNext()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     QCOMPARE(textCursor.position(), 0);
 
-    textCursor.move(TextPositions::Next, text);
+    textCursor.movePosition(QTextCursor::Right);
 
     QCOMPARE(textCursor.position(), 1);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToNextWordBeginning_When_DirectionNextAndModifierCtrl()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String(" This is  a string\n"
-                                 "spanning multiple lines "
-                                 " 123 1  ");
+	QTextDocument textDocument(" This is  a string\n"
+							   "spanning multiple lines "
+							   " 123 1  ");
+	TextCursor textCursor(&textDocument);
     QCOMPARE(textCursor.position(), 0);
 	QVector<int> nextPositionList{ 1, 6, 10, 12, 18, 19, 28, 37, 44, 48, 51, 51 };
 
     for(int nextPosition : nextPositionList) {
-        textCursor.move(TextPositions::NextWordBeginning, text);
+        textCursor.movePosition(QTextCursor::NextWord);
 
         QCOMPARE(textCursor.position(), nextPosition);
     }
@@ -77,30 +77,30 @@ void TextCursorTest::TestMove_Should_MoveCursorToNextWordBeginning_When_Directio
 
 void TextCursorTest::TestMove_Should_MoveCursorByOnePointToLeft_When_DirectionPrevious()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
-    textCursor.move(TextPositions::Next, text);
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
+    textCursor.movePosition(QTextCursor::Right);
     QCOMPARE(textCursor.position(), 1);
 
-    textCursor.move(TextPositions::Previous, text);
+    textCursor.movePosition(QTextCursor::Left);
 
     QCOMPARE(textCursor.position(), 0);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToPreviousWordBeginning_When_DirectionPreviousAndModifierCtrl()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String(" This is  a string\n"
-                                 "spanning multiple lines "
-                                 " 123 1  ");
+	QTextDocument textDocument(" This is  a string\n"
+							   "spanning multiple lines "
+							   " 123 1  ");
+	TextCursor textCursor(&textDocument);
     textCursor.setPosition(51);
     QCOMPARE(textCursor.position(), 51);
     QVector<int> prevPositionList{ 48, 44, 37, 28, 19, 18, 12, 10, 6, 1, 0, 0 };
 
     for(int prevPosition : prevPositionList) {
-        textCursor.move(TextPositions::PreviousWordBeginning, text);
+        textCursor.movePosition(QTextCursor::PreviousWord);
 
         QCOMPARE(textCursor.position(), prevPosition);
     }
@@ -108,158 +108,132 @@ void TextCursorTest::TestMove_Should_MoveCursorToPreviousWordBeginning_When_Dire
 
 void TextCursorTest::TestMove_Should_MoveCursorToStart_When_DirectionPreviousAndCurrentPositionAtStart()
 {
-    TextCursor textCursor;
-	QString text = QLatin1String("Test\n"
-								 "123\n"
-								 "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     QCOMPARE(textCursor.position(), 0);
 
-    textCursor.move(TextPositions::Previous, text);
+    textCursor.movePosition(QTextCursor::Left);
 
     QCOMPARE(textCursor.position(), 0);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToEnd_When_DirectionNextAndCurrentPositionAtEnd()
 {
-    TextCursor textCursor;
-	QString text = QLatin1String("Test\n"
-								 "123\n"
-								 "test123");
-    textCursor.setPosition(text.length());
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
+    textCursor.setPosition(16);
 
-    textCursor.move(TextPositions::Next, text);
+    textCursor.movePosition(QTextCursor::Right);
 
-    QCOMPARE(textCursor.position(), text.length());
+    QCOMPARE(textCursor.position(), 16);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToNextLineSamePosition_When_DirectionDown()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     QCOMPARE(textCursor.position(), 0);
 
-    textCursor.move(TextPositions::Down, text);
+    textCursor.movePosition(QTextCursor::Down);
 
     QCOMPARE(textCursor.position(), 5);
 }
 
 void TextCursorTest::TestMove_Should_NotMoveCursor_When_DirectionDownAndInLastLine()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     textCursor.setPosition(9);
 
-    textCursor.move(TextPositions::Down, text);
+    textCursor.movePosition(QTextCursor::Down);
 
     QCOMPARE(textCursor.position(), 9);
 }
 
 void TextCursorTest::TestMove_Should_NotMoveCursor_When_DirectionUpAndInFirstLine()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     QCOMPARE(textCursor.position(), 0);
 
-    textCursor.move(TextPositions::Up, text);
+    textCursor.movePosition(QTextCursor::Up);
 
     QCOMPARE(textCursor.position(), 0);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToPreviousLineSamePosition_When_DirectionUpAndNotInFirstLine()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     textCursor.setPosition(9);
 
-    textCursor.move(TextPositions::Up, text);
+    textCursor.movePosition(QTextCursor::Up);
 
     QCOMPARE(textCursor.position(), 5);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToEndOfNextLine_When_DirectionDownAndPositionAtEndOfLineAndLineBelowIsSmaller()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     textCursor.setPosition(4);
 
-    textCursor.move(TextPositions::Down, text);
+    textCursor.movePosition(QTextCursor::Down);
 
-    QCOMPARE(textCursor.position(), 8);
+    QCOMPARE(textCursor.position(), 5);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToEndOfPreviousLine_When_DirectionUpAndPositionAtEndOfLineAndLineAboveIsSmaller()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     textCursor.setPosition(16);
 
-    textCursor.move(TextPositions::Up, text);
+    textCursor.movePosition(QTextCursor::Up);
 
-    QCOMPARE(textCursor.position(), 8);
+    QCOMPARE(textCursor.position(), 5);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToSamePositionOfPreviousLine_When_DirectionUpAndPositionAtEndOfLineAndLineAboveIsLarger()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     textCursor.setPosition(8);
 
-    textCursor.move(TextPositions::Up, text);
+    textCursor.movePosition(QTextCursor::Up);
 
-    QCOMPARE(textCursor.position(), 3);
+    QCOMPARE(textCursor.position(), 0);
 }
 
 void TextCursorTest::TestMove_Should_MoveCursorToSamePositionOfNextLine_When_DirectionDownAndPositionAtEndOfLineAndLineBelowIsLarger()
 {
-    TextCursor textCursor;
-    QString text = QLatin1String("Test\n"
-                                  "123\n"
-                                  "test123");
+	QTextDocument textDocument("Test\n"
+							   "123\n"
+							   "test123");
+	TextCursor textCursor(&textDocument);
     textCursor.setPosition(8);
 
-    textCursor.move(TextPositions::Down, text);
-
-    QCOMPARE(textCursor.position(), 12);
-}
-
-void TextCursorTest::TestMoveForwardBy_Should_MoveCursorForwardByRequestedSteps()
-{
-	TextCursor textCursor;
-	QString text = QLatin1String("Test\n"
-								 "123\n"
-								 "test123");
-	QCOMPARE(textCursor.position(), 0);
-
-	textCursor.moveForwardBy(text, 2);
-
-	QCOMPARE(textCursor.position(), 2);
-}
+    textCursor.movePosition(QTextCursor::Down);
 
-void TextCursorTest::TestMoveForwardBy_Should_MoveCursorToEnd_When_RequestedStepsLargerThenTextLength()
-{
-	TextCursor textCursor;
-	QString text = QLatin1String("Test\n"
-								 "123\n"
-								 "test123");
-	textCursor.setPosition(2);
-
-	textCursor.moveForwardBy(text, 20);
-
-	QCOMPARE(textCursor.position(), text.length());
+    QCOMPARE(textCursor.position(), 9);
 }
 
 TEST_MAIN(TextCursorTest);
diff --git a/tests/annotations/items/helper/TextCursorTest.h b/tests/annotations/items/helper/TextCursorTest.h
index 0898b65..39de2c8 100644
--- a/tests/annotations/items/helper/TextCursorTest.h
+++ b/tests/annotations/items/helper/TextCursorTest.h
@@ -26,7 +26,6 @@
 #include "src/annotations/items/text/TextCursor.h"
 
 using kImageAnnotator::TextCursor;
-using kImageAnnotator::TextPositions;
 
 class TextCursorTest : public QObject
 {
@@ -49,8 +48,6 @@ private slots:
 	void TestMove_Should_MoveCursorToEndOfPreviousLine_When_DirectionUpAndPositionAtEndOfLineAndLineAboveIsSmaller();
 	void TestMove_Should_MoveCursorToSamePositionOfPreviousLine_When_DirectionUpAndPositionAtEndOfLineAndLineAboveIsLarger();
 	void TestMove_Should_MoveCursorToSamePositionOfNextLine_When_DirectionDownAndPositionAtEndOfLineAndLineBelowIsLarger();
-	void TestMoveForwardBy_Should_MoveCursorForwardByRequestedSteps();
-	void TestMoveForwardBy_Should_MoveCursorToEnd_When_RequestedStepsLargerThenTextLength();
 };
 
 #endif // KIMAGEANNOTATOR_TEXTCURSORTEST_H
diff --git a/tests/annotations/misc/AnnotationItemClipboardTest.cpp b/tests/annotations/misc/AnnotationItemClipboardTest.cpp
index 8220a4c..d5f4e92 100644
--- a/tests/annotations/misc/AnnotationItemClipboardTest.cpp
+++ b/tests/annotations/misc/AnnotationItemClipboardTest.cpp
@@ -32,9 +32,9 @@ void AnnotationItemClipboardTest::TestCopyItems_Should_StoreSelectedItems()
 	MockZoomValueProvider zoomValueProvider;
 	AnnotationItemModifier modifier(&zoomValueProvider);
 	modifier.handleSelectionAt(position, &items, false);
-	AnnotationItemClipboard clipboard(&modifier);
+	AnnotationItemClipboard clipboard;
 
-	clipboard.copyItems(QPointF());
+	clipboard.copyItems(QPointF(), &modifier);
 
 	QCOMPARE(clipboard.copiedItemsWithOffset().count(), 1);
 	QCOMPARE(clipboard.copiedItemsWithOffset().keys().first(), &rect);
@@ -51,9 +51,9 @@ void AnnotationItemClipboardTest::TestCopyItems_Should_SetCorrectOffset()
 	MockZoomValueProvider zoomValueProvider;
 	AnnotationItemModifier modifier(&zoomValueProvider);
 	modifier.handleSelectionAt(position, &items, false);
-	AnnotationItemClipboard clipboard(&modifier);
+	AnnotationItemClipboard clipboard;
 
-	clipboard.copyItems(QPointF(20, 20));
+	clipboard.copyItems(QPointF(20, 20), &modifier);
 
 	QCOMPARE(clipboard.copiedItemsWithOffset()[&rect], QPointF(-20, -20));
 }
diff --git a/tests/annotations/undo/AddCommandTest.cpp b/tests/annotations/undo/AddCommandTest.cpp
index 2cb5d7b..da18302 100644
--- a/tests/annotations/undo/AddCommandTest.cpp
+++ b/tests/annotations/undo/AddCommandTest.cpp
@@ -26,7 +26,7 @@ void AddCommandTest::TestRedo_Should_ApplyOperation()
 	// arrange
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	QLineF line(10, 10, 20, 20);
 	auto item = new AnnotationLine(line.p1(), properties);
@@ -46,7 +46,7 @@ void AddCommandTest::TestUndo_Should_UndoOperation()
 	// arrange
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	QLineF line(10, 10, 20, 20);
 	auto item = new AnnotationLine(line.p1(), properties);
diff --git a/tests/annotations/undo/CropCommandTest.cpp b/tests/annotations/undo/CropCommandTest.cpp
index 247d577..1a9043d 100644
--- a/tests/annotations/undo/CropCommandTest.cpp
+++ b/tests/annotations/undo/CropCommandTest.cpp
@@ -24,7 +24,7 @@ void CropCommandTest::TestRedo_Should_CropImageAndScene()
 	// arrange
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	QPixmap image(400, 400);
 	QGraphicsPixmapItem graphicsPixmapItem(image);
 	QRectF cropRect(100, 100, 200, 200);
@@ -43,7 +43,7 @@ void CropCommandTest::TestRedo_Should_MoveItemToNewPosition()
 	// arrange
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	QPixmap image(400, 400);
 	QGraphicsPixmapItem graphicsPixmapItem(image);
 	QRectF cropRect(100, 100, 200, 200);
@@ -67,7 +67,7 @@ void CropCommandTest::TestUndo_Should_RestoreOriginalImageAndSceneSize()
 	// arrange
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	QPixmap image(400, 400);
 	QGraphicsPixmapItem graphicsPixmapItem(image);
 	QRectF cropRect(100, 100, 200, 200);
@@ -87,7 +87,7 @@ void CropCommandTest::TestUndo_Should_MoveItemBackToPreviousPosition()
 	// arrange
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	QPixmap image(400, 400);
 	QGraphicsPixmapItem graphicsPixmapItem(image);
 	QRectF cropRect(100, 100, 200, 200);
diff --git a/tests/annotations/undo/DeleteCommandTest.cpp b/tests/annotations/undo/DeleteCommandTest.cpp
index b17cd51..397b491 100644
--- a/tests/annotations/undo/DeleteCommandTest.cpp
+++ b/tests/annotations/undo/DeleteCommandTest.cpp
@@ -26,7 +26,7 @@ void DeleteCommandTest::TestRedo_Should_ApplyOperation()
 	// arrange
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	QLineF line(10, 10, 20, 20);
 	AnnotationLine item(line.p1(), properties);
@@ -48,7 +48,7 @@ void DeleteCommandTest::TestUndo_Should_UndoOperation()
 	// arrange
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	QLineF line(10, 10, 20, 20);
 	AnnotationLine item(line.p1(), properties);
diff --git a/tests/annotations/undo/ModifyCanvasCommandTest.cpp b/tests/annotations/undo/ModifyCanvasCommandTest.cpp
index f17e815..3ac54d0 100644
--- a/tests/annotations/undo/ModifyCanvasCommandTest.cpp
+++ b/tests/annotations/undo/ModifyCanvasCommandTest.cpp
@@ -23,7 +23,8 @@ void ModifyCanvasCommandTest::Redo_Should_ModifyCanvasSizeAndColor_When_SizeAndC
 {
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, itemClipboard, nullptr);
 	QPixmap image(400, 400);
 	annotationArea.loadImage(image);
 	QRectF newCanvasRect(100, 100, 200, 200);
@@ -41,7 +42,8 @@ void ModifyCanvasCommandTest::Redo_Should_OnlyModifyCanvasColor_When_OnlyColorCh
 {
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, itemClipboard, nullptr);
 	QPixmap image(400, 400);
 	annotationArea.loadImage(image);
 	QColor newCanvasColor(Qt::red);
@@ -59,7 +61,8 @@ void ModifyCanvasCommandTest::Undo_Should_RevertCanvasSizeAndColor_When_SizeAndC
 {
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, itemClipboard, nullptr);
 	QPixmap image(400, 400);
 	annotationArea.loadImage(image);
 	auto originalCanvasRect = annotationArea.canvasRect();
@@ -83,7 +86,8 @@ void ModifyCanvasCommandTest::Undo_Should_RevertOnlyColor_When_OnlyColorChanged(
 {
 	MockDefaultParameters parameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	auto itemClipboard = new AnnotationItemClipboard;
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, itemClipboard, nullptr);
 	QPixmap image(400, 400);
 	annotationArea.loadImage(image);
 	QColor newCanvasColor(Qt::red);
diff --git a/tests/annotations/undo/ModifyCanvasCommandTest.h b/tests/annotations/undo/ModifyCanvasCommandTest.h
index 08a527a..53aa9a6 100644
--- a/tests/annotations/undo/ModifyCanvasCommandTest.h
+++ b/tests/annotations/undo/ModifyCanvasCommandTest.h
@@ -33,6 +33,7 @@
 using kImageAnnotator::ModifyCanvasCommand;
 using kImageAnnotator::AnnotationArea;
 using kImageAnnotator::PropertiesPtr;
+using kImageAnnotator::AnnotationItemClipboard;
 
 class ModifyCanvasCommandTest : public QObject
 {
diff --git a/tests/annotations/undo/PasteCommandTest.cpp b/tests/annotations/undo/PasteCommandTest.cpp
index 10893d4..5afa6d0 100644
--- a/tests/annotations/undo/PasteCommandTest.cpp
+++ b/tests/annotations/undo/PasteCommandTest.cpp
@@ -43,7 +43,7 @@ void PasteCommandTest::TestRedo_Should_AddPastedItemsToAnnotationAreaAtGivenPosi
 	MockDefaultParameters mockParameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
 	AnnotationPropertiesFactory propertiesFactory(&mockParameters.config, &mockParameters.settingsProvider);
-	AnnotationArea annotationArea(&mockParameters.config, &mockParameters.settingsProvider, scalerMock, &mockParameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&mockParameters.config, &mockParameters.settingsProvider, scalerMock, &mockParameters.zoomValueProvider, nullptr, nullptr);
 	AnnotationItemFactory itemFactory(&propertiesFactory, &mockParameters.settingsProvider, &mockParameters.config);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	QLineF line(10, 10, 20, 20);
@@ -71,7 +71,7 @@ void PasteCommandTest::TestUndo_Should_RemovePastedItemsFromAnnotationArea()
 	MockDefaultParameters mockParameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
 	AnnotationPropertiesFactory propertiesFactory(&mockParameters.config, &mockParameters.settingsProvider);
-	AnnotationArea annotationArea(&mockParameters.config, &mockParameters.settingsProvider, scalerMock, &mockParameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&mockParameters.config, &mockParameters.settingsProvider, scalerMock, &mockParameters.zoomValueProvider, nullptr, nullptr);
 	AnnotationItemFactory itemFactory(&propertiesFactory, &mockParameters.settingsProvider, &mockParameters.config);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	QLineF line(10, 10, 20, 20);
diff --git a/tests/annotations/undo/RotateCommandTest.cpp b/tests/annotations/undo/RotateCommandTest.cpp
index b6bed2a..de88850 100644
--- a/tests/annotations/undo/RotateCommandTest.cpp
+++ b/tests/annotations/undo/RotateCommandTest.cpp
@@ -32,7 +32,7 @@ void RotateCommandTest::Redo_Should_RotatePixmapByProvidedAngel()
 
 	MockDefaultParameters defaultParameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&defaultParameters.config, &defaultParameters.settingsProvider, scalerMock, &defaultParameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&defaultParameters.config, &defaultParameters.settingsProvider, scalerMock, &defaultParameters.zoomValueProvider, nullptr, nullptr);
 	RotateCommand rotateCommand(&image, angel, &annotationArea);
 
 	// act
@@ -55,7 +55,7 @@ void RotateCommandTest::Redo_Should_TrimPixmapAndRemoveTransparentPart_WhenRotat
 
 	MockDefaultParameters defaultParameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&defaultParameters.config, &defaultParameters.settingsProvider, scalerMock, &defaultParameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&defaultParameters.config, &defaultParameters.settingsProvider, scalerMock, &defaultParameters.zoomValueProvider, nullptr, nullptr);
 	RotateCommand rotate1Command(&image, angel, &annotationArea);
 	rotate1Command.redo();
 	RotateCommand rotate2Command(&image, angel, &annotationArea);
@@ -78,7 +78,7 @@ void RotateCommandTest::Undo_Should_RevertBackToInitialImage()
 
 	MockDefaultParameters defaultParameters;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&defaultParameters.config, &defaultParameters.settingsProvider, scalerMock, &defaultParameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&defaultParameters.config, &defaultParameters.settingsProvider, scalerMock, &defaultParameters.zoomValueProvider, nullptr, nullptr);
 	RotateCommand rotateCommand(&image, angel, &annotationArea);
 	rotateCommand.redo();
 	QVERIFY(image.pixmap().toImage() != pixmap.toImage());
diff --git a/tests/annotations/undo/ScaleCommandTest.cpp b/tests/annotations/undo/ScaleCommandTest.cpp
index 0de6917..aba2f53 100644
--- a/tests/annotations/undo/ScaleCommandTest.cpp
+++ b/tests/annotations/undo/ScaleCommandTest.cpp
@@ -31,7 +31,7 @@ void ScaleCommandTest::TestRedo_Should_ScaleImageToNewSize()
 
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	ScaleCommand scaleCommand(&image, newSize, &annotationArea);
 
 	// act
@@ -50,7 +50,7 @@ void ScaleCommandTest::TestUndo_Should_ScaleImageBackToOldSize()
 	QGraphicsPixmapItem image(pixmap);
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	ScaleCommand scaleCommand(&image, newSize, &annotationArea);
 	scaleCommand.redo();
 	QCOMPARE(image.boundingRect().size().toSize(), newSize);
@@ -71,7 +71,7 @@ void ScaleCommandTest::TestRedo_Should_ScaleItemsBySameFactorAsImage()
 	QGraphicsPixmapItem image(pixmap);
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	auto rectItem = new AnnotationRect(QPointF(0, 0), properties);
 	rectItem->addPoint(QPointF(50, 50), false);
@@ -94,7 +94,7 @@ void ScaleCommandTest::TestUndo_Should_ScaleItemsBackToOriginalSize()
 	QGraphicsPixmapItem image(pixmap);
 	MockDefaultParameters p;
 	auto scalerMock = new MockDevicePixelRatioScaler();
-	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&p.config, &p.settingsProvider, scalerMock, &p.zoomValueProvider, nullptr, nullptr);
 	auto properties = PropertiesPtr(new AnnotationProperties(Qt::red, 1));
 	auto rectItem = new AnnotationRect(QPointF(0, 0), properties);
 	rectItem->addPoint(QPointF(50, 50), false);
diff --git a/tests/gui/annotator/tabs/AnnotationTabContextMenuTest.cpp b/tests/gui/annotator/tabs/AnnotationTabContextMenuTest.cpp
index 0c4904d..a5c86d7 100644
--- a/tests/gui/annotator/tabs/AnnotationTabContextMenuTest.cpp
+++ b/tests/gui/annotator/tabs/AnnotationTabContextMenuTest.cpp
@@ -40,8 +40,8 @@ void AnnotationTabContextMenuTest::TestCustomActionTriggered_Should_CallInnerAct
 void AnnotationTabContextMenuTest::TestAddCustomActions_Should_SetTextIconAndToolTipInOuterAction() 
 {
     QAction customAction;
-    customAction.setText(QLatin1Literal("LaLa"));
-    customAction.setToolTip(QLatin1Literal("Hello Hello"));
+    customAction.setText(QStringLiteral("LaLa"));
+    customAction.setToolTip(QStringLiteral("Hello Hello"));
     customAction.setIcon(QIcon());
     QWidget parent;
     AnnotationTabContextMenu menu(&parent);
@@ -68,4 +68,4 @@ void AnnotationTabContextMenuTest::TestCustomActionChanged_Should_UpdateEnabledS
     QCOMPARE(customAction.isEnabled(), outerAction->isEnabled());
 }
 
-TEST_MAIN(AnnotationTabContextMenuTest);
\ No newline at end of file
+TEST_MAIN(AnnotationTabContextMenuTest);
diff --git a/tests/gui/selection/SelectionHandlerTest.cpp b/tests/gui/selection/SelectionHandlerTest.cpp
index 80d22d5..70533ec 100644
--- a/tests/gui/selection/SelectionHandlerTest.cpp
+++ b/tests/gui/selection/SelectionHandlerTest.cpp
@@ -29,7 +29,7 @@ void SelectionHandlerTest::SetWidth_Should_EmitSelectionChangedSignal()
 
 	EXPECT_CALL(*selectionHandles, updateHandles(testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	SelectionHandler selectionHandler(selectionRestrictor, selectionHandles);
 	selectionHandler.init(&annotationArea);
 	QSignalSpy spy(&selectionHandler, &SelectionHandler::selectionChanged);
@@ -51,7 +51,7 @@ void SelectionHandlerTest::SetHeight_Should_EmitSelectionChangedSignal()
 
 	EXPECT_CALL(*selectionHandles, updateHandles(testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	SelectionHandler selectionHandler(selectionRestrictor, selectionHandles);
 	selectionHandler.init(&annotationArea);
 	QSignalSpy spy(&selectionHandler, &SelectionHandler::selectionChanged);
@@ -73,7 +73,7 @@ void SelectionHandlerTest::SetPositionX_Should_EmitSelectionChangedSignal()
 
 	EXPECT_CALL(*selectionHandles, updateHandles(testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	SelectionHandler selectionHandler(selectionRestrictor, selectionHandles);
 	selectionHandler.init(&annotationArea);
 	QSignalSpy spy(&selectionHandler, &SelectionHandler::selectionChanged);
@@ -95,7 +95,7 @@ void SelectionHandlerTest::SetPositionY_Should_EmitSelectionChangedSignal()
 
 	EXPECT_CALL(*selectionHandles, updateHandles(testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	SelectionHandler selectionHandler(selectionRestrictor, selectionHandles);
 	selectionHandler.init(&annotationArea);
 	QSignalSpy spy(&selectionHandler, &SelectionHandler::selectionChanged);
@@ -117,7 +117,7 @@ void SelectionHandlerTest::ResetSelection_Should_SetSelectionToProvidedRect()
 
 	EXPECT_CALL(*selectionHandles, updateHandles(testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	auto sceneRect = QRectF(0, 0, 500, 500);
 	annotationArea.setSceneRect(sceneRect);
 	SelectionHandler selectionHandler(selectionRestrictor, selectionHandles);
@@ -144,7 +144,7 @@ void SelectionHandlerTest::IsInMotion_Should_ReturnTrue_WhenClickedOnSelection()
 	EXPECT_CALL(*selectionHandles, grabHandle(testing::_, testing::_)).Times(testing::AnyNumber());
 	EXPECT_CALL(*selectionHandles, isHandleGrabbed()).WillRepeatedly(testing::Return(false));
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	auto sceneRect = QRectF(0, 0, 500, 500);
 	auto position = QPointF(150, 150);
 	annotationArea.setSceneRect(sceneRect);
@@ -172,7 +172,7 @@ void SelectionHandlerTest::IsInMotion_Should_ReturnTrue_WhenClickedOnHandle()
 	EXPECT_CALL(*selectionHandles, isHandleGrabbed()).WillRepeatedly(testing::Return(true));
 	EXPECT_CALL(*selectionHandles, grabHandle(testing::_, testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	auto sceneRect = QRectF(0, 0, 500, 500);
 	auto position = QPointF(2, 2);
 	annotationArea.setSceneRect(sceneRect);
@@ -199,7 +199,7 @@ void SelectionHandlerTest::IsInMotion_Should_ReturnFalse_WhenClickedOutsideSelec
 	EXPECT_CALL(*selectionHandles, grabHandle(testing::_, testing::_)).Times(testing::AnyNumber());
 	EXPECT_CALL(*selectionHandles, isHandleGrabbed()).WillRepeatedly(testing::Return(false));
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	auto sceneRect = QRectF(0, 0, 500, 500);
 	auto position = QPointF(400, 400);
 	annotationArea.setSceneRect(sceneRect);
@@ -225,7 +225,7 @@ void SelectionHandlerTest::RestrictResize_Should_KeepCurrentSelection_When_NewSe
 
 	EXPECT_CALL(*selectionHandles, updateHandles(testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	SelectionHandler selectionHandler(selectionRestrictor, selectionHandles);
 	selectionHandler.init(&annotationArea);
 	selectionHandler.setRestrictionEnabled(false);
@@ -250,7 +250,7 @@ void SelectionHandlerTest::RestrictResize_Should_KeepCurrentSelection_When_NewSe
 
 	EXPECT_CALL(*selectionHandles, updateHandles(testing::_)).Times(testing::AnyNumber());
 
-	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr);
+	AnnotationArea annotationArea(&parameters.config, &parameters.settingsProvider, scalerMock, &parameters.zoomValueProvider, nullptr, nullptr);
 	SelectionHandler selectionHandler(selectionRestrictor, selectionHandles);
 	selectionHandler.init(&annotationArea);
 	selectionHandler.setRestrictionEnabled(false);
diff --git a/tests/utils/TestRunner.h b/tests/utils/TestRunner.h
index 214b8b0..ff742f0 100644
--- a/tests/utils/TestRunner.h
+++ b/tests/utils/TestRunner.h
@@ -69,9 +69,6 @@ class GoogleTestEventListener : public ::testing::EmptyTestEventListener {
 #endif
 
 #define TEST_MAIN(TestObject) \
-QT_BEGIN_NAMESPACE \
-QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
-QT_END_NAMESPACE \
 int main(int argc, char *argv[]) \
 {   \
     INIT_GOOGLE_MOCKS (argc, argv); \
@@ -79,7 +76,6 @@ int main(int argc, char *argv[]) \
     QApplication app(argc, argv); \
     app.setAttribute(Qt::AA_Use96Dpi, true); \
     QTEST_DISABLE_KEYPAD_NAVIGATION \
-    QTEST_ADD_GPU_BLACKLIST_SUPPORT \
     TestObject tc; \
     QTEST_SET_MAIN_SOURCE_PATH \
     return QTest::qExec(&tc, argc, argv); \
@@ -90,16 +86,12 @@ int main(int argc, char *argv[]) \
 #include <QtTest/qtest_gui.h>
 
 #define TEST_MAIN(TestObject) \
-QT_BEGIN_NAMESPACE \
-QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
-QT_END_NAMESPACE \
 int main(int argc, char *argv[]) \
 {   \
     INIT_GOOGLE_MOCKS (argc, argv); \
     \
     QGuiApplication app(argc, argv); \
     app.setAttribute(Qt::AA_Use96Dpi, true); \
-    QTEST_ADD_GPU_BLACKLIST_SUPPORT \
     TestObject tc; \
     QTEST_SET_MAIN_SOURCE_PATH \
     return QTest::qExec(&tc, argc, argv); \
diff --git a/tests/widgets/settingsPicker/StickerPickerTest.cpp b/tests/widgets/settingsPicker/StickerPickerTest.cpp
index 94c2680..7c539fc 100644
--- a/tests/widgets/settingsPicker/StickerPickerTest.cpp
+++ b/tests/widgets/settingsPicker/StickerPickerTest.cpp
@@ -23,7 +23,7 @@ void StickerPickerTest::TestSelectSticker_Should_EmitSignal_When_StickerChanged(
 {
 	StickerPicker stickerPicker(nullptr);
 	QSignalSpy spy(&stickerPicker, &StickerPicker::stickerSelected);
-	auto expectedStickerPath = QLatin1Literal(":/stickers/nerd_face.svg");
+	auto expectedStickerPath = QStringLiteral(":/stickers/nerd_face.svg");
 
 	stickerPicker.setSticker(expectedStickerPath);
 
@@ -32,4 +32,4 @@ void StickerPickerTest::TestSelectSticker_Should_EmitSignal_When_StickerChanged(
 	QCOMPARE(resultSize, expectedStickerPath);
 }
 
-TEST_MAIN(StickerPickerTest);
\ No newline at end of file
+TEST_MAIN(StickerPickerTest);
diff --git a/translations/CMakeLists.txt b/translations/CMakeLists.txt
index 4dc5e88..75ff4d3 100644
--- a/translations/CMakeLists.txt
+++ b/translations/CMakeLists.txt
@@ -1,4 +1,4 @@
-find_package(Qt5LinguistTools)
+find_package(Qt${QT_MAJOR_VERSION}LinguistTools)
 
 set(KIMAGEANNOTATOR_LANG_TS
 	kImageAnnotator_ar.ts
@@ -34,9 +34,9 @@ set(KIMAGEANNOTATOR_LANG_TS
     kImageAnnotator_zh_CN.ts)
 
 if (DEFINED UPDATE_TS_FILES)
-	qt5_create_translation(KIMAGEANNOTATOR_LANG_QM ${CMAKE_SOURCE_DIR}/translations ${KIMAGEANNOTATOR_SRCS} ${KIMAGEANNOTATOR_LANG_TS} OPTIONS "-no-obsolete")
+	qt_create_translation(KIMAGEANNOTATOR_LANG_QM ${CMAKE_SOURCE_DIR}/translations ${KIMAGEANNOTATOR_SRCS} ${KIMAGEANNOTATOR_LANG_TS} OPTIONS "-no-obsolete")
 else ()
-	qt5_add_translation(KIMAGEANNOTATOR_LANG_QM ${KIMAGEANNOTATOR_LANG_TS})
+	qt_add_translation(KIMAGEANNOTATOR_LANG_QM ${KIMAGEANNOTATOR_LANG_TS})
 endif ()
 
 add_custom_target(translations ALL DEPENDS ${KIMAGEANNOTATOR_LANG_QM})
diff --git a/translations/kImageAnnotator_de.ts b/translations/kImageAnnotator_de.ts
index 917c9d9..33dec16 100644
--- a/translations/kImageAnnotator_de.ts
+++ b/translations/kImageAnnotator_de.ts
@@ -48,7 +48,7 @@
     <name>kImageAnnotator::AnnotationControlsWidget</name>
     <message>
         <source>Controls</source>
-        <translation type="unfinished"></translation>
+        <translation>Bedienelemente</translation>
     </message>
 </context>
 <context>
@@ -97,11 +97,11 @@
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Skala</translation>
     </message>
     <message>
         <source>Opacity</source>
-        <translation type="unfinished"></translation>
+        <translation>Deckkraft</translation>
     </message>
 </context>
 <context>
@@ -149,31 +149,31 @@
     <name>kImageAnnotator::Controls</name>
     <message>
         <source>Undo</source>
-        <translation type="unfinished"></translation>
+        <translation>Rückgängig</translation>
     </message>
     <message>
         <source>Redo</source>
-        <translation type="unfinished"></translation>
+        <translation>Wiederherstellen</translation>
     </message>
     <message>
         <source>Crop</source>
-        <translation type="unfinished"></translation>
+        <translation>Zuschneiden</translation>
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Skala</translation>
     </message>
     <message>
         <source>Rotate</source>
-        <translation type="unfinished">Drehen</translation>
+        <translation>Drehen</translation>
     </message>
     <message>
         <source>Modify canvas</source>
-        <translation type="unfinished"></translation>
+        <translation>Leinwand verändern</translation>
     </message>
     <message>
         <source>Cut</source>
-        <translation type="unfinished"></translation>
+        <translation>Ausschneiden</translation>
     </message>
 </context>
 <context>
@@ -207,19 +207,19 @@
     <name>kImageAnnotator::CutWidget</name>
     <message>
         <source>Vertical</source>
-        <translation type="unfinished">Vertikal</translation>
+        <translation>Vertikal</translation>
     </message>
     <message>
         <source>Horizontal</source>
-        <translation type="unfinished">Horizontal</translation>
+        <translation>Horizontal</translation>
     </message>
     <message>
         <source>Apply</source>
-        <translation type="unfinished">Anwenden</translation>
+        <translation>Anwenden</translation>
     </message>
     <message>
         <source>Cancel</source>
-        <translation type="unfinished">Abbrechen</translation>
+        <translation>Abbrechen</translation>
     </message>
 </context>
 <context>
@@ -526,15 +526,15 @@ Das Drehen um nicht 90°-Multiplikatoren kann zu Qualitätsverlusten führen.</t
     </message>
     <message>
         <source>Reset Zoom</source>
-        <translation type="unfinished"></translation>
+        <translation>Zoom zurücksetzen</translation>
     </message>
     <message>
         <source>Fit Image</source>
-        <translation type="unfinished"></translation>
+        <translation>Bild einpassen</translation>
     </message>
     <message>
         <source>Fit image to view (%1)</source>
-        <translation type="unfinished"></translation>
+        <translation>Bild in Ansicht einpassen (%1)</translation>
     </message>
 </context>
 </TS>
diff --git a/translations/kImageAnnotator_es.ts b/translations/kImageAnnotator_es.ts
index 3665310..10db618 100644
--- a/translations/kImageAnnotator_es.ts
+++ b/translations/kImageAnnotator_es.ts
@@ -48,60 +48,60 @@
     <name>kImageAnnotator::AnnotationControlsWidget</name>
     <message>
         <source>Controls</source>
-        <translation type="unfinished"></translation>
+        <translation>Controles</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::AnnotationGeneralSettings</name>
     <message>
         <source>General Settings</source>
-        <translation type="unfinished"></translation>
+        <translation>Parámetros generales</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::AnnotationImageSettings</name>
     <message>
         <source>Image Settings</source>
-        <translation type="unfinished"></translation>
+        <translation>Ajustes de la imagen</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::AnnotationItemSettings</name>
     <message>
         <source>Color</source>
-        <translation type="unfinished">Color</translation>
+        <translation>Color</translation>
     </message>
     <message>
         <source>Text Color</source>
-        <translation type="unfinished">Color de texto</translation>
+        <translation>Color del texto</translation>
     </message>
     <message>
         <source>Width</source>
-        <translation type="unfinished">Anchura</translation>
+        <translation>Ancho</translation>
     </message>
     <message>
         <source>Number Seed</source>
-        <translation type="unfinished"></translation>
+        <translation>Número de semillas</translation>
     </message>
     <message>
         <source>Obfuscation Factor</source>
-        <translation type="unfinished"></translation>
+        <translation>Factor de ofuscación</translation>
     </message>
     <message>
         <source>Item Shadow</source>
-        <translation type="unfinished"></translation>
+        <translation>Sombra del artículo</translation>
     </message>
     <message>
         <source>Item Settings</source>
-        <translation type="unfinished"></translation>
+        <translation>Ajustes del elemento</translation>
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Escala</translation>
     </message>
     <message>
         <source>Opacity</source>
-        <translation type="unfinished"></translation>
+        <translation>Opacidad</translation>
     </message>
 </context>
 <context>
@@ -131,49 +131,49 @@
     <name>kImageAnnotator::AnnotationToolSelection</name>
     <message>
         <source>Tool Selection</source>
-        <translation type="unfinished"></translation>
+        <translation>Selección de herramientas</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::BoolPicker</name>
     <message>
         <source>Enabled</source>
-        <translation type="unfinished"></translation>
+        <translation>Activado</translation>
     </message>
     <message>
         <source>Disabled</source>
-        <translation type="unfinished"></translation>
+        <translation>Desactivado</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::Controls</name>
     <message>
         <source>Undo</source>
-        <translation type="unfinished"></translation>
+        <translation>Deshacer</translation>
     </message>
     <message>
         <source>Redo</source>
-        <translation type="unfinished"></translation>
+        <translation>Rehacer</translation>
     </message>
     <message>
         <source>Crop</source>
-        <translation type="unfinished"></translation>
+        <translation>Cultivos</translation>
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Escala</translation>
     </message>
     <message>
         <source>Rotate</source>
-        <translation type="unfinished"></translation>
+        <translation>Girar</translation>
     </message>
     <message>
         <source>Modify canvas</source>
-        <translation type="unfinished"></translation>
+        <translation>Modificar el lienzo</translation>
     </message>
     <message>
         <source>Cut</source>
-        <translation type="unfinished"></translation>
+        <translation>Cortar</translation>
     </message>
 </context>
 <context>
@@ -200,26 +200,26 @@
     </message>
     <message>
         <source>Apply</source>
-        <translation type="unfinished"></translation>
+        <translation>Aplicar</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::CutWidget</name>
     <message>
         <source>Vertical</source>
-        <translation type="unfinished"></translation>
+        <translation>En vertical</translation>
     </message>
     <message>
         <source>Horizontal</source>
-        <translation type="unfinished"></translation>
+        <translation>En horizontal</translation>
     </message>
     <message>
         <source>Apply</source>
-        <translation type="unfinished"></translation>
+        <translation>Aplicar</translation>
     </message>
     <message>
         <source>Cancel</source>
-        <translation type="unfinished">Cancelar</translation>
+        <translation>Cancelar</translation>
     </message>
 </context>
 <context>
@@ -245,142 +245,144 @@
     <name>kImageAnnotator::FontPicker</name>
     <message>
         <source>Font Size</source>
-        <translation type="unfinished">Tamaño de letra</translation>
+        <translation>Tamaño de letra</translation>
     </message>
     <message>
         <source>Bold</source>
-        <translation type="unfinished"></translation>
+        <translation>Negrita</translation>
     </message>
     <message>
         <source>Italic</source>
-        <translation type="unfinished"></translation>
+        <translation>Cursiva</translation>
     </message>
     <message>
         <source>Underline</source>
-        <translation type="unfinished"></translation>
+        <translation>Subrayado</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::ImageEffectPicker</name>
     <message>
         <source>Image Effects</source>
-        <translation type="unfinished"></translation>
+        <translation>Efectos de la imagen</translation>
     </message>
     <message>
         <source>No Effect</source>
-        <translation type="unfinished"></translation>
+        <translation>Sin efectos</translation>
     </message>
     <message>
         <source>Drop Shadow</source>
-        <translation type="unfinished"></translation>
+        <translation>Sombra paralela</translation>
     </message>
     <message>
         <source>Grayscale</source>
-        <translation type="unfinished"></translation>
+        <translation>Escala de grises</translation>
     </message>
     <message>
         <source>Border</source>
-        <translation type="unfinished"></translation>
+        <translation>Borde</translation>
     </message>
     <message>
         <source>Invert Color</source>
-        <translation type="unfinished"></translation>
+        <translation>Invertir el color</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::ModifyCanvasWidget</name>
     <message>
         <source>Restricted</source>
-        <translation type="unfinished"></translation>
+        <translation>Restringido</translation>
     </message>
     <message>
         <source>When enabled enforces the canvas
 to include the background image.</source>
-        <translation type="unfinished"></translation>
+        <translation>Cuando se activa, obliga al lienzo
+a incluir la imagen de fondo.</translation>
     </message>
     <message>
         <source>X:</source>
-        <translation type="unfinished">X:</translation>
+        <translation>X:</translation>
     </message>
     <message>
         <source>Y:</source>
-        <translation type="unfinished">Y:</translation>
+        <translation>Y:</translation>
     </message>
     <message>
         <source>W:</source>
-        <translation type="unfinished">↔:</translation>
+        <translation>anch.:</translation>
     </message>
     <message>
         <source>H:</source>
-        <translation type="unfinished">↕:</translation>
+        <translation>alt.:</translation>
     </message>
     <message>
         <source>Apply</source>
-        <translation type="unfinished"></translation>
+        <translation>Aplicar</translation>
     </message>
     <message>
         <source>Cancel</source>
-        <translation type="unfinished">Cancelar</translation>
+        <translation>Cancelar</translation>
     </message>
     <message>
         <source>Color:</source>
-        <translation type="unfinished"></translation>
+        <translation>Color:</translation>
     </message>
     <message>
         <source>Canvas Background Color</source>
-        <translation type="unfinished"></translation>
+        <translation>Color del fondo del lienzo</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::RotateDialog</name>
     <message>
         <source>Rotate Image</source>
-        <translation type="unfinished"></translation>
+        <translation>Girar la imagen</translation>
     </message>
     <message>
         <source>180°</source>
-        <translation type="unfinished"></translation>
+        <translation>180°</translation>
     </message>
     <message>
         <source>90° Clockwise</source>
-        <translation type="unfinished"></translation>
+        <translation>90° en sentido horario</translation>
     </message>
     <message>
         <source>90° Counter Clockwise</source>
-        <translation type="unfinished"></translation>
+        <translation>90° en sentido antihorario</translation>
     </message>
     <message>
         <source>Arbitrary</source>
-        <translation type="unfinished"></translation>
+        <translation>Arbitrario</translation>
     </message>
     <message>
         <source>Positive values rotate clockwise, negative values counter clockwise.
 Rotating by non 90° multipliers might introduce loss of quality.</source>
-        <translation type="unfinished"></translation>
+        <translation>Los valores positivos giran en el sentido de las agujas del reloj, los negativos en sentido contrario.
+La rotación mediante multiplicadores que no sean de 90° puede introducir una pérdida de calidad.</translation>
     </message>
     <message>
         <source>Horizontal</source>
-        <translation type="unfinished"></translation>
+        <translation>En horizontal</translation>
     </message>
     <message>
         <source>Vertical</source>
-        <translation type="unfinished"></translation>
+        <translation>En vertical</translation>
     </message>
     <message>
         <source>OK</source>
-        <translation type="unfinished">Aceptar</translation>
+        <translation>DE ACUERDO</translation>
     </message>
     <message>
         <source>Cancel</source>
-        <translation type="unfinished">Cancelar</translation>
+        <translation>Cancelar</translation>
     </message>
     <message>
         <source>Rotate</source>
-        <translation type="unfinished"></translation>
+        <translation>Girar</translation>
     </message>
     <message>
         <source>Flip</source>
-        <translation type="unfinished"></translation>
+        <translation>Voltear</translation>
     </message>
 </context>
 <context>
@@ -422,7 +424,7 @@ Rotating by non 90° multipliers might introduce loss of quality.</source>
     <name>kImageAnnotator::StickerPicker</name>
     <message>
         <source>Sticker</source>
-        <translation type="unfinished">Adhesivo</translation>
+        <translation>Pegatina</translation>
     </message>
 </context>
 <context>
@@ -489,50 +491,50 @@ Rotating by non 90° multipliers might introduce loss of quality.</source>
     </message>
     <message>
         <source>Pixelate</source>
-        <translation type="unfinished"></translation>
+        <translation>Pixelar</translation>
     </message>
     <message>
         <source>Text Pointer</source>
-        <translation type="unfinished"></translation>
+        <translation>Indicador del texto</translation>
     </message>
     <message>
         <source>Text Arrow</source>
-        <translation type="unfinished"></translation>
+        <translation>Flecha de texto</translation>
     </message>
     <message>
         <source>Number Arrow</source>
-        <translation type="unfinished"></translation>
+        <translation>Flecha numérica</translation>
     </message>
     <message>
         <source>Duplicate</source>
-        <translation type="unfinished"></translation>
+        <translation>Duplicar</translation>
     </message>
 </context>
 <context>
     <name>kImageAnnotator::ZoomPicker</name>
     <message>
         <source>Zoom In (%1)</source>
-        <translation type="unfinished"></translation>
+        <translation>Acercar (%1)</translation>
     </message>
     <message>
         <source>Zoom Out (%1)</source>
-        <translation type="unfinished"></translation>
+        <translation>Alejar (%1)</translation>
     </message>
     <message>
         <source>Reset Zoom (%1)</source>
-        <translation type="unfinished"></translation>
+        <translation>Restaurar el zoom (%1)</translation>
     </message>
     <message>
         <source>Reset Zoom</source>
-        <translation type="unfinished"></translation>
+        <translation>Restaurar el zoom</translation>
     </message>
     <message>
         <source>Fit Image</source>
-        <translation type="unfinished"></translation>
+        <translation>Ajustar la imagen</translation>
     </message>
     <message>
         <source>Fit image to view (%1)</source>
-        <translation type="unfinished"></translation>
+        <translation>Ajustar la imagen a la vista (%1)</translation>
     </message>
 </context>
 </TS>
diff --git a/translations/kImageAnnotator_pl.ts b/translations/kImageAnnotator_pl.ts
index 8aefcab..a14a11e 100644
--- a/translations/kImageAnnotator_pl.ts
+++ b/translations/kImageAnnotator_pl.ts
@@ -48,7 +48,7 @@
     <name>kImageAnnotator::AnnotationControlsWidget</name>
     <message>
         <source>Controls</source>
-        <translation type="unfinished"></translation>
+        <translation>Sterowanie</translation>
     </message>
 </context>
 <context>
@@ -97,11 +97,11 @@
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Skala</translation>
     </message>
     <message>
         <source>Opacity</source>
-        <translation type="unfinished"></translation>
+        <translation>Nieprzezroczystość</translation>
     </message>
 </context>
 <context>
@@ -149,31 +149,31 @@
     <name>kImageAnnotator::Controls</name>
     <message>
         <source>Undo</source>
-        <translation type="unfinished"></translation>
+        <translation>Cofnij</translation>
     </message>
     <message>
         <source>Redo</source>
-        <translation type="unfinished"></translation>
+        <translation>Powtórz</translation>
     </message>
     <message>
         <source>Crop</source>
-        <translation type="unfinished"></translation>
+        <translation>Przytnij</translation>
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Skala</translation>
     </message>
     <message>
         <source>Rotate</source>
-        <translation type="unfinished">Obróć</translation>
+        <translation>Obróć</translation>
     </message>
     <message>
         <source>Modify canvas</source>
-        <translation type="unfinished"></translation>
+        <translation>Modyfikuj kanwę</translation>
     </message>
     <message>
         <source>Cut</source>
-        <translation type="unfinished"></translation>
+        <translation>Wytnij</translation>
     </message>
 </context>
 <context>
@@ -207,19 +207,19 @@
     <name>kImageAnnotator::CutWidget</name>
     <message>
         <source>Vertical</source>
-        <translation type="unfinished">Pionowo</translation>
+        <translation>Pionowo</translation>
     </message>
     <message>
         <source>Horizontal</source>
-        <translation type="unfinished">Poziomo</translation>
+        <translation>Poziomo</translation>
     </message>
     <message>
         <source>Apply</source>
-        <translation type="unfinished">Zastosuj</translation>
+        <translation>Zastosuj</translation>
     </message>
     <message>
         <source>Cancel</source>
-        <translation type="unfinished">Anuluj</translation>
+        <translation>Anuluj</translation>
     </message>
 </context>
 <context>
@@ -526,15 +526,15 @@ Obracanie przez mnożniki inne niż 90° może spowodować utratę jakości.</tr
     </message>
     <message>
         <source>Reset Zoom</source>
-        <translation type="unfinished"></translation>
+        <translation>Zresetuj powiększenie</translation>
     </message>
     <message>
         <source>Fit Image</source>
-        <translation type="unfinished"></translation>
+        <translation>Dopasuj obraz</translation>
     </message>
     <message>
         <source>Fit image to view (%1)</source>
-        <translation type="unfinished"></translation>
+        <translation>Dopasuj obraz do widoku (%1)</translation>
     </message>
 </context>
 </TS>
diff --git a/translations/kImageAnnotator_pt.ts b/translations/kImageAnnotator_pt.ts
index d91f5a7..0f22a23 100644
--- a/translations/kImageAnnotator_pt.ts
+++ b/translations/kImageAnnotator_pt.ts
@@ -48,7 +48,7 @@
     <name>kImageAnnotator::AnnotationControlsWidget</name>
     <message>
         <source>Controls</source>
-        <translation type="unfinished"></translation>
+        <translation>Controles</translation>
     </message>
 </context>
 <context>
@@ -97,11 +97,11 @@
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Escala</translation>
     </message>
     <message>
         <source>Opacity</source>
-        <translation type="unfinished"></translation>
+        <translation>Opacidade</translation>
     </message>
 </context>
 <context>
@@ -149,31 +149,31 @@
     <name>kImageAnnotator::Controls</name>
     <message>
         <source>Undo</source>
-        <translation type="unfinished"></translation>
+        <translation>Desfazer</translation>
     </message>
     <message>
         <source>Redo</source>
-        <translation type="unfinished"></translation>
+        <translation>Refazer</translation>
     </message>
     <message>
         <source>Crop</source>
-        <translation type="unfinished"></translation>
+        <translation>Recortar</translation>
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Escala</translation>
     </message>
     <message>
         <source>Rotate</source>
-        <translation type="unfinished">Rotacionar</translation>
+        <translation>Rotacionar</translation>
     </message>
     <message>
         <source>Modify canvas</source>
-        <translation type="unfinished"></translation>
+        <translation>Modificar tela</translation>
     </message>
     <message>
         <source>Cut</source>
-        <translation type="unfinished"></translation>
+        <translation>Cortar</translation>
     </message>
 </context>
 <context>
@@ -207,19 +207,19 @@
     <name>kImageAnnotator::CutWidget</name>
     <message>
         <source>Vertical</source>
-        <translation type="unfinished">Vertical</translation>
+        <translation>Vertical</translation>
     </message>
     <message>
         <source>Horizontal</source>
-        <translation type="unfinished">Horizontal</translation>
+        <translation>Horizontal</translation>
     </message>
     <message>
         <source>Apply</source>
-        <translation type="unfinished">Aplicar</translation>
+        <translation>Aplicar</translation>
     </message>
     <message>
         <source>Cancel</source>
-        <translation type="unfinished">Cancelar</translation>
+        <translation>Cancelar</translation>
     </message>
 </context>
 <context>
@@ -526,15 +526,15 @@ Rotacionar por multiplicadores diferentes de 90° pode causar perda de qualidade
     </message>
     <message>
         <source>Reset Zoom</source>
-        <translation type="unfinished"></translation>
+        <translation>Redefinir zoom</translation>
     </message>
     <message>
         <source>Fit Image</source>
-        <translation type="unfinished"></translation>
+        <translation>Ajustar a imagem</translation>
     </message>
     <message>
         <source>Fit image to view (%1)</source>
-        <translation type="unfinished"></translation>
+        <translation>Ajustar imagem para visualização (%1)</translation>
     </message>
 </context>
 </TS>
diff --git a/translations/kImageAnnotator_sq.ts b/translations/kImageAnnotator_sq.ts
index b2a6962..1811277 100644
--- a/translations/kImageAnnotator_sq.ts
+++ b/translations/kImageAnnotator_sq.ts
@@ -9,7 +9,7 @@
     </message>
     <message>
         <source>Bring to Front</source>
-        <translation>Sille Në Ballë</translation>
+        <translation>Sille Para</translation>
     </message>
     <message>
         <source>Bring Forward</source>
@@ -17,7 +17,7 @@
     </message>
     <message>
         <source>Send Backward</source>
-        <translation>Dërgoje Më Pas</translation>
+        <translation>Dërgoje Prapa</translation>
     </message>
     <message>
         <source>Send to Back</source>
@@ -97,7 +97,7 @@
     </message>
     <message>
         <source>Scale</source>
-        <translation type="unfinished"></translation>
+        <translation>Ripërmasojeni</translation>
     </message>
     <message>
         <source>Opacity</source>



More information about the Neon-commits mailing list