Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kquickimageeditor for 
openSUSE:Factory checked in at 2021-10-08 00:05:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kquickimageeditor (Old)
 and      /work/SRC/openSUSE:Factory/.kquickimageeditor.new.2443 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kquickimageeditor"

Fri Oct  8 00:05:53 2021 rev:3 rq:923584 version:0.2.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kquickimageeditor/kquickimageeditor.changes      
2021-05-08 22:09:06.021305371 +0200
+++ 
/work/SRC/openSUSE:Factory/.kquickimageeditor.new.2443/kquickimageeditor.changes
    2021-10-08 00:06:51.405835329 +0200
@@ -1,0 +2,16 @@
+Wed Oct  6 19:50:10 UTC 2021 - Fabian Vogt <[email protected]>
+
+- Simplify %files section
+
+-------------------------------------------------------------------
+Wed Oct  6 19:14:19 UTC 2021 - Christophe Giboudeaux <[email protected]>
+
+- Update to 0.2.0
+  * ImageDocument: Add resize function
+  * Add SelectionTool, SelectionHandle, SelectionBackground,
+    CropBackground, RectangleCutout
+  * ResizeRectangle: Limit inside rect size and position to fit
+    own size
+  * Fix horizontalPadding not working
+
+-------------------------------------------------------------------

Old:
----
  kquickimageeditor-0.1.3.tar.xz
  kquickimageeditor-0.1.3.tar.xz.sig

New:
----
  kquickimageeditor-0.2.0.tar.xz
  kquickimageeditor-0.2.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kquickimageeditor.spec ++++++
--- /var/tmp/diff_new_pack.1YQ2ut/_old  2021-10-08 00:06:51.845836075 +0200
+++ /var/tmp/diff_new_pack.1YQ2ut/_new  2021-10-08 00:06:51.849836082 +0200
@@ -16,26 +16,25 @@
 #
 
 
-%define _kf5_version 5.70.0
-%define _tar_path 0.1
+%define _kf5_version 5.79.0
 %bcond_without  lang
 Name:           kquickimageeditor
-Version:        0.1.3
+Version:        0.2.0
 Release:        0
 Summary:        A set of QtQuick components for image editing
 License:        LGPL-2.1-or-later
 Group:          System/GUI/KDE
 URL:            https://www.kde.org
-Source0:        
https://download.kde.org/stable/kquickimageeditor/%{_tar_path}/%{name}-%{version}.tar.xz
+Source0:        
https://download.kde.org/stable/kquickimageeditor/%{name}-%{version}.tar.xz
+%if %{with lang}
+Source1:        
https://download.kde.org/stable/kquickimageeditor/%{name}-%{version}.tar.xz.sig
+Source2:        %{name}.keyring
+%endif
 BuildRequires:  cmake >= 3.5
 BuildRequires:  extra-cmake-modules >= %{_kf5_version}
 BuildRequires:  kf5-filesystem
 BuildRequires:  cmake(Qt5Core) >= 5.15.0
 BuildRequires:  cmake(Qt5Quick) >= 5.15.0
-%if %{with lang}
-Source1:        
https://download.kde.org/stable/kquickimageeditor/%{_tar_path}/%{name}-%{version}.tar.xz.sig
-Source2:        %{name}.keyring
-%endif
 
 %description
 KQuickImageEditor is a set of QtQuick components providing basic image editing
@@ -61,7 +60,7 @@
 basic image editing capabilities.
 
 %prep
-%autosetup
+%autosetup -p1
 
 %build
 %cmake_kf5 -d build
@@ -73,14 +72,9 @@
 %files imports
 %license LICENSES/*
 %doc README*
-%dir %{_kf5_qmldir}/org
+%dir %{_kf5_qmldir}/org/
 %dir %{_kf5_qmldir}/org/kde/
-%dir %{_kf5_qmldir}/org/kde/kquickimageeditor
-%{_kf5_qmldir}/org/kde/kquickimageeditor/libkquickimageeditorplugin.so
-%{_kf5_qmldir}/org/kde/kquickimageeditor/plugins.qmltypes
-%{_kf5_qmldir}/org/kde/kquickimageeditor/qmldir
-%{_kf5_qmldir}/org/kde/kquickimageeditor/qmldir.license
-%{_kf5_qmldir}/org/kde/kquickimageeditor/BasicResizeHandle.qml
+%{_kf5_qmldir}/org/kde/kquickimageeditor/
 
 %files devel
 %license LICENSES/*

++++++ kquickimageeditor-0.1.3.tar.xz -> kquickimageeditor-0.2.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/.gitignore 
new/kquickimageeditor-0.2.0/.gitignore
--- old/kquickimageeditor-0.1.3/.gitignore      2021-01-26 16:57:35.000000000 
+0100
+++ new/kquickimageeditor-0.2.0/.gitignore      2021-10-01 18:15:16.000000000 
+0200
@@ -6,3 +6,4 @@
 *.kate-swp
 *.swp
 build
+.clang-format
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/.gitlab-ci.yml 
new/kquickimageeditor-0.2.0/.gitlab-ci.yml
--- old/kquickimageeditor-0.1.3/.gitlab-ci.yml  1970-01-01 01:00:00.000000000 
+0100
+++ new/kquickimageeditor-0.2.0/.gitlab-ci.yml  2021-10-01 18:15:16.000000000 
+0200
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: None
+# SPDX-License-Identifier: CC0-1.0
+
+include:
+  - 
https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/.kde-ci.yml 
new/kquickimageeditor-0.2.0/.kde-ci.yml
--- old/kquickimageeditor-0.1.3/.kde-ci.yml     1970-01-01 01:00:00.000000000 
+0100
+++ new/kquickimageeditor-0.2.0/.kde-ci.yml     2021-10-01 18:15:16.000000000 
+0200
@@ -0,0 +1,7 @@
+# SPDX-FileCopyrightText: None
+# SPDX-License-Identifier: CC0-1.0
+
+Dependencies:
+- 'on': ['@all']
+  'require':
+    'frameworks/extra-cmake-modules': '@stable'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/CMakeLists.txt 
new/kquickimageeditor-0.2.0/CMakeLists.txt
--- old/kquickimageeditor-0.1.3/CMakeLists.txt  2021-01-26 16:57:35.000000000 
+0100
+++ new/kquickimageeditor-0.2.0/CMakeLists.txt  2021-10-01 18:15:16.000000000 
+0200
@@ -4,10 +4,10 @@
 
 cmake_minimum_required(VERSION 3.5)
 
-set(KF5_VERSION "5.70.0")
+set(KF5_VERSION "5.79.0")
 set(REQUIRED_QT_VERSION 5.15.0)
 
-project(KQuickImageEditor LANGUAGES CXX VERSION 0.1.2)
+project(KQuickImageEditor LANGUAGES CXX VERSION 0.2.0)
 
 find_package(ECM ${KF5_VERSION} NO_MODULE)
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
@@ -17,10 +17,11 @@
 include(KDECMakeSettings)
 include(KDECompilerSettings)
 include(FeatureSummary)
-include(ECMPoQmTools)
 include(ECMSetupVersion)
+include(KDEClangFormat)
+include(KDEGitCommitHooks)
+include(ECMGenerateQmlTypes)
 include(CMakePackageConfigHelpers)
-#include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
 include(KDEPackageAppTemplates)
 
 set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KQuickImageEditor")
@@ -52,3 +53,8 @@
 add_subdirectory(src)
 
 feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
+
+# add clang-format target for all our real source files
+file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES src/*.cpp src/*.h)
+kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
+kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/KQuickImageEditorConfig.cmake.in 
new/kquickimageeditor-0.2.0/KQuickImageEditorConfig.cmake.in
--- old/kquickimageeditor-0.1.3/KQuickImageEditorConfig.cmake.in        
2021-01-26 16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/KQuickImageEditorConfig.cmake.in        
2021-10-01 18:15:16.000000000 +0200
@@ -1,3 +1,6 @@
+# SPDX-FileCopyrightText: 2020 Carl Schwan <[email protected]>
+#
+# SPDX-License-Identifier: BSD-2-Clause
 @PACKAGE_INIT@
 
 include(CMakeFindDependencyMacro)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/examples/KirigamiExample.qml 
new/kquickimageeditor-0.2.0/examples/KirigamiExample.qml
--- old/kquickimageeditor-0.1.3/examples/KirigamiExample.qml    2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/examples/KirigamiExample.qml    2021-10-01 
18:15:16.000000000 +0200
@@ -135,7 +135,19 @@
                         Kirigami.Action {
                             iconName: rootEditorView.resizing ? 
"dialog-cancel" : "transform-crop"
                             text: rootEditorView.resizing ? i18n("Cancel") : 
i18nc("@action:button Crop an image", "Crop");
-                            onTriggered: rootEditorView.resizing = 
!rootEditorView.resizing;
+                            onTriggered: {
+                                console.log(editImage.verticalPadding);
+                                console.log(editImage.horizontalPadding);
+                                resizeRectangle.width = editImage.paintedWidth
+                                resizeRectangle.height = 
editImage.paintedHeight
+                                resizeRectangle.x = 0
+                                resizeRectangle.y = editImage.verticalPadding
+                                resizeRectangle.insideX = 100
+                                resizeRectangle.insideY = 100
+                                resizeRectangle.insideWidth = 100
+                                resizeRectangle.insideHeight = 100
+                                rootEditorView.resizing = 
!rootEditorView.resizing;
+                            }
                         },
                         Kirigami.Action {
                             iconName: "dialog-ok"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/CMakeLists.txt 
new/kquickimageeditor-0.2.0/src/CMakeLists.txt
--- old/kquickimageeditor-0.1.3/src/CMakeLists.txt      2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/CMakeLists.txt      2021-10-01 
18:15:16.000000000 +0200
@@ -2,14 +2,11 @@
 #
 # SPDX-License-Identifier: BSD-2-Clause
 
-include_directories(code)
-
-ecm_create_qm_loader(kquickimageeditor_QM_LOADER libkquickimageeditorplugin_qt)
-
 set(
     sources
     code/commands/undocommand.cpp
     code/commands/cropcommand.cpp
+    code/commands/resizecommand.cpp
     code/commands/mirrorcommand.cpp
     code/commands/rotatecommand.cpp
     code/kquickimageeditor_plugin.cpp
@@ -18,19 +15,17 @@
     code/imageitem.cpp
     code/imagedocument.cpp
     resources.qrc
+    controls/qmldir
     ${kquickimageeditor_QM_LOADER}
 )
-set(
-    pluginData
 
-    controls/qmldir
-)
+ecm_generate_qmltypes(org.kde.kquickimageeditor 1.0
+                      DESTINATION 
${KDE_INSTALL_QMLDIR}/org/kde/kquickimageeditor)
 
 add_library(
     kquickimageeditorplugin
     SHARED
-
-    ${sources} ${pluginData}
+    ${sources}
 )
 
 target_link_libraries(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/commands/cropcommand.h 
new/kquickimageeditor-0.2.0/src/code/commands/cropcommand.h
--- old/kquickimageeditor-0.1.3/src/code/commands/cropcommand.h 2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/commands/cropcommand.h 2021-10-01 
18:15:16.000000000 +0200
@@ -26,7 +26,7 @@
     virtual QImage redo(QImage image) override;
 
     virtual QImage undo(QImage image) override;
-    
+
 private:
     QImage m_image;
     QRect m_cropRect;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/commands/mirrorcommand.cpp 
new/kquickimageeditor-0.2.0/src/code/commands/mirrorcommand.cpp
--- old/kquickimageeditor-0.1.3/src/code/commands/mirrorcommand.cpp     
2021-01-26 16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/commands/mirrorcommand.cpp     
2021-10-01 18:15:16.000000000 +0200
@@ -6,8 +6,8 @@
 
 #include "mirrorcommand.h"
 
-MirrorCommand::MirrorCommand(bool horizonal, bool vertical)
-    : m_horizontal(horizonal)
+MirrorCommand::MirrorCommand(bool horizontal, bool vertical)
+    : m_horizontal(horizontal)
     , m_vertical(vertical)
 {
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/commands/mirrorcommand.h 
new/kquickimageeditor-0.2.0/src/code/commands/mirrorcommand.h
--- old/kquickimageeditor-0.1.3/src/code/commands/mirrorcommand.h       
2021-01-26 16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/commands/mirrorcommand.h       
2021-10-01 18:15:16.000000000 +0200
@@ -17,13 +17,13 @@
 class MirrorCommand : public UndoCommand
 {
 public:
-    MirrorCommand(bool horizonal, bool vertical);
+    MirrorCommand(bool horizontal, bool vertical);
     ~MirrorCommand() override = default;
 
     virtual QImage redo(QImage image) override;
 
     virtual QImage undo(QImage image) override;
-    
+
 private:
     bool m_horizontal;
     bool m_vertical;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/commands/resizecommand.cpp 
new/kquickimageeditor-0.2.0/src/code/commands/resizecommand.cpp
--- old/kquickimageeditor-0.1.3/src/code/commands/resizecommand.cpp     
1970-01-01 01:00:00.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/commands/resizecommand.cpp     
2021-10-01 18:15:16.000000000 +0200
@@ -0,0 +1,23 @@
+/* SPDX-FileCopyrightText: (C) 2020 Carl Schwan <[email protected]>
+ * SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "resizecommand.h"
+
+ResizeCommand::ResizeCommand(const QSize &resizeSize)
+    : m_resizeSize(resizeSize)
+{
+}
+
+QImage ResizeCommand::undo(QImage image)
+{
+    Q_UNUSED(image)
+    return m_image;
+}
+
+QImage ResizeCommand::redo(QImage image)
+{
+    m_image = image;
+    return m_image.scaled(m_resizeSize, Qt::IgnoreAspectRatio, 
Qt::SmoothTransformation);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/commands/resizecommand.h 
new/kquickimageeditor-0.2.0/src/code/commands/resizecommand.h
--- old/kquickimageeditor-0.1.3/src/code/commands/resizecommand.h       
1970-01-01 01:00:00.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/commands/resizecommand.h       
2021-10-01 18:15:16.000000000 +0200
@@ -0,0 +1,32 @@
+/* SPDX-FileCopyrightText: (C) 2020 Carl Schwan <[email protected]>
+ * SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include "undocommand.h"
+
+#include <QImage>
+#include <QRect>
+
+/**
+ * @brief ResizeCommand that resizes the current image.
+ */
+class ResizeCommand : public UndoCommand
+{
+public:
+    /**
+     * Contructor
+     */
+    ResizeCommand(const QSize &resizeSize);
+    ~ResizeCommand() override = default;
+
+    virtual QImage redo(QImage image) override;
+
+    virtual QImage undo(QImage image) override;
+
+private:
+    QImage m_image;
+    QSize m_resizeSize;
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/commands/rotatecommand.h 
new/kquickimageeditor-0.2.0/src/code/commands/rotatecommand.h
--- old/kquickimageeditor-0.1.3/src/code/commands/rotatecommand.h       
2021-01-26 16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/commands/rotatecommand.h       
2021-10-01 18:15:16.000000000 +0200
@@ -26,7 +26,7 @@
     virtual QImage redo(QImage image) override;
 
     virtual QImage undo(QImage image) override;
-    
+
 private:
     QTransform m_tranform;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/commands/undocommand.h 
new/kquickimageeditor-0.2.0/src/code/commands/undocommand.h
--- old/kquickimageeditor-0.1.3/src/code/commands/undocommand.h 2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/commands/undocommand.h 2021-10-01 
18:15:16.000000000 +0200
@@ -15,12 +15,12 @@
 {
 public:
     virtual ~UndoCommand() = 0;
-    
+
     /**
      * Applies the change to the document.
      */
     virtual QImage redo(QImage image) = 0;
-    
+
     /**
      * Revert a change to the document.
      */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/imagedocument.cpp 
new/kquickimageeditor-0.2.0/src/code/imagedocument.cpp
--- old/kquickimageeditor-0.1.3/src/code/imagedocument.cpp      2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/imagedocument.cpp      2021-10-01 
18:15:16.000000000 +0200
@@ -6,27 +6,27 @@
 
 #include "imagedocument.h"
 
-#include "commands/undocommand.h"
 #include "commands/cropcommand.h"
 #include "commands/mirrorcommand.h"
+#include "commands/resizecommand.h"
 #include "commands/rotatecommand.h"
+#include "commands/undocommand.h"
 
-#include <QUrl>
-#include <QString>
 #include <QDebug>
 #include <QFile>
 #include <QImage>
+#include <QString>
+#include <QUrl>
 
 ImageDocument::ImageDocument(QObject *parent)
     : QObject(parent)
 {
-    connect(this, &ImageDocument::pathChanged,
-            this, [this] (const QUrl &url) {
-                m_image = QImage(url.isLocalFile() ? url.toLocalFile() : 
url.toString());
-                m_edited = false;
-                Q_EMIT editedChanged();
-                Q_EMIT imageChanged();
-            });
+    connect(this, &ImageDocument::pathChanged, this, [this](const QUrl &url) {
+        m_image = QImage(url.isLocalFile() ? url.toLocalFile() : 
url.toString());
+        m_edited = false;
+        Q_EMIT editedChanged();
+        Q_EMIT imageChanged();
+    });
 }
 
 void ImageDocument::cancel()
@@ -71,6 +71,15 @@
     Q_EMIT imageChanged();
 }
 
+void ImageDocument::resize(int width, int height)
+{
+    const auto command = new ResizeCommand(QSize(width, height));
+    m_image = command->redo(m_image);
+    m_undos.append(command);
+    setEdited(true);
+    Q_EMIT imageChanged();
+}
+
 void ImageDocument::mirror(bool horizontal, bool vertical)
 {
     const auto command = new MirrorCommand(horizontal, vertical);
@@ -106,7 +115,7 @@
     return m_image.save(m_path.isLocalFile() ? m_path.toLocalFile() : 
m_path.toString());
 }
 
-bool ImageDocument::saveAs(const QUrl& location)
+bool ImageDocument::saveAs(const QUrl &location)
 {
     return m_image.save(location.isLocalFile() ? location.toLocalFile() : 
location.toString());
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/imagedocument.h 
new/kquickimageeditor-0.2.0/src/code/imagedocument.h
--- old/kquickimageeditor-0.1.3/src/code/imagedocument.h        2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/imagedocument.h        2021-10-01 
18:15:16.000000000 +0200
@@ -6,9 +6,9 @@
 
 #pragma once
 
+#include <QImage>
 #include <QObject>
 #include <QStack>
-#include <QImage>
 #include <QUrl>
 
 #include "commands/undocommand.h"
@@ -80,8 +80,8 @@
     Q_INVOKABLE void rotate(int angle);
 
     /**
-     * Mirrror the image.
-     * @param horizonal Mirror the image horizontally.
+     * Mirror the image.
+     * @param horizontal Mirror the image horizontally.
      * @param vertical Mirror the image vertically.
      */
     Q_INVOKABLE void mirror(bool horizontal, bool vertical);
@@ -96,6 +96,13 @@
     Q_INVOKABLE void crop(int x, int y, int width, int height);
 
     /**
+     * Resize the image.
+     * @param width The width of the new image.
+     * @param height The height of the new image.
+     */
+    Q_INVOKABLE void resize(int width, int height);
+
+    /**
      * Undo the last edit on the images.
      */
     Q_INVOKABLE void undo();
@@ -107,7 +114,7 @@
 
     /**
      * Save current edited image in place. This is a destructive operation and 
can't be reverted.
-     * @return true iff the file saving operattion was successful.
+     * @return true iff the file saving operation was successful.
      */
     Q_INVOKABLE bool save();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/imageitem.cpp 
new/kquickimageeditor-0.2.0/src/code/imageitem.cpp
--- old/kquickimageeditor-0.1.3/src/code/imageitem.cpp  2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/imageitem.cpp  2021-10-01 
18:15:16.000000000 +0200
@@ -8,13 +8,13 @@
 
 #include "imageitem.h"
 
+#include <QDebug>
 #include <QPainter>
 
-
 ImageItem::ImageItem(QQuickItem *parent)
-    : QQuickPaintedItem(parent),
-      m_smooth(false),
-      m_fillMode(ImageItem::Stretch)
+    : QQuickPaintedItem(parent)
+    , m_smooth(false)
+    , m_fillMode(ImageItem::Stretch)
 {
     setFlag(ItemHasContents, true);
 }
@@ -94,11 +94,11 @@
     painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth);
 
     if (m_fillMode == TileVertically) {
-        painter->scale(width()/(qreal)m_image.width(), 1);
+        painter->scale(width() / (qreal)m_image.width(), 1);
     }
 
     if (m_fillMode == TileHorizontally) {
-        painter->scale(1, height()/(qreal)m_image.height());
+        painter->scale(1, height() / (qreal)m_image.height());
     }
 
     if (m_fillMode >= Tile) {
@@ -142,9 +142,17 @@
     return (height() - m_paintedRect.height()) / 2;
 }
 
-void ImageItem::updatePaintedRect()
+int ImageItem::horizontalPadding() const
 {
+    if (m_image.isNull()) {
+        return 0;
+    }
 
+    return (width() - m_paintedRect.width()) / 2;
+}
+
+void ImageItem::updatePaintedRect()
+{
     if (m_image.isNull()) {
         return;
     }
@@ -172,12 +180,12 @@
     }
     case TileVertically: {
         destRect = boundingRect().toRect();
-        destRect.setWidth(destRect.width() / (width()/(qreal)m_image.width()));
+        destRect.setWidth(destRect.width() / (width() / 
(qreal)m_image.width()));
         break;
     }
     case TileHorizontally: {
         destRect = boundingRect().toRect();
-        destRect.setHeight(destRect.height() / 
(height()/(qreal)m_image.height()));
+        destRect.setHeight(destRect.height() / (height() / 
(qreal)m_image.height()));
         break;
     }
     case Stretch:
@@ -191,10 +199,11 @@
         Q_EMIT paintedHeightChanged();
         Q_EMIT paintedWidthChanged();
         Q_EMIT verticalPaddingChanged();
+        Q_EMIT horizontalPaddingChanged();
     }
 }
 
-void ImageItem::geometryChanged(const QRectF& newGeometry, const QRectF& 
oldGeometry)
+void ImageItem::geometryChanged(const QRectF &newGeometry, const QRectF 
&oldGeometry)
 {
     QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry);
     updatePaintedRect();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/imageitem.h 
new/kquickimageeditor-0.2.0/src/code/imageitem.h
--- old/kquickimageeditor-0.1.3/src/code/imageitem.h    2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/imageitem.h    2021-10-01 
18:15:16.000000000 +0200
@@ -7,8 +7,8 @@
 
 #pragma once
 
-#include <QQuickPaintedItem>
 #include <QImage>
+#include <QQuickPaintedItem>
 
 class ImageItem : public QQuickPaintedItem
 {
@@ -21,6 +21,7 @@
     Q_PROPERTY(int paintedWidth READ paintedWidth NOTIFY paintedWidthChanged)
     Q_PROPERTY(int paintedHeight READ paintedHeight NOTIFY 
paintedHeightChanged)
     Q_PROPERTY(int verticalPadding READ verticalPadding NOTIFY 
verticalPaddingChanged)
+    Q_PROPERTY(int horizontalPadding READ horizontalPadding NOTIFY 
horizontalPaddingChanged)
     Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY 
fillModeChanged)
     Q_PROPERTY(bool null READ isNull NOTIFY nullChanged)
 
@@ -31,11 +32,11 @@
         PreserveAspectCrop, // the image is scaled uniformly to fill, cropping 
if necessary
         Tile, // the image is duplicated horizontally and vertically
         TileVertically, // the image is stretched horizontally and tiled 
vertically
-        TileHorizontally //the image is stretched vertically and tiled 
horizontally
+        TileHorizontally // the image is stretched vertically and tiled 
horizontally
     };
     Q_ENUM(FillMode)
 
-    explicit ImageItem(QQuickItem *parent=nullptr);
+    explicit ImageItem(QQuickItem *parent = nullptr);
     ~ImageItem() override = default;
 
     void setImage(const QImage &image);
@@ -51,6 +52,7 @@
     int paintedWidth() const;
     int paintedHeight() const;
     int verticalPadding() const;
+    int horizontalPadding() const;
 
     FillMode fillMode() const;
     void setFillMode(FillMode mode);
@@ -68,9 +70,10 @@
     void paintedWidthChanged();
     void paintedHeightChanged();
     void verticalPaddingChanged();
+    void horizontalPaddingChanged();
 
 protected:
-    void geometryChanged(const QRectF & newGeometry, const QRectF & 
oldGeometry) override;
+    void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) 
override;
 
 private:
     QImage m_image;
@@ -80,5 +83,4 @@
 
 private Q_SLOTS:
     void updatePaintedRect();
-
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/kquickimageeditor_plugin.cpp 
new/kquickimageeditor-0.2.0/src/code/kquickimageeditor_plugin.cpp
--- old/kquickimageeditor-0.1.3/src/code/kquickimageeditor_plugin.cpp   
2021-01-26 16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/kquickimageeditor_plugin.cpp   
2021-10-01 18:15:16.000000000 +0200
@@ -7,10 +7,10 @@
 
 #include "kquickimageeditor_plugin.h"
 
-#include <resizehandle.h>
-#include <resizerectangle.h>
-#include <imageitem.h>
-#include <imagedocument.h>
+#include "imagedocument.h"
+#include "imageitem.h"
+#include "resizehandle.h"
+#include "resizerectangle.h"
 
 void KQuickImageEditorPlugin::registerTypes(const char *uri)
 {
@@ -23,4 +23,9 @@
     qmlRegisterType<ImageItem>(uri, 1, 0, "ImageItem");
     qmlRegisterType<ImageDocument>(uri, 1, 0, "ImageDocument");
     qmlRegisterType(resolveFileUrl(QStringLiteral("BasicResizeHandle.qml")), 
uri, 1, 0, "BasicResizeHandle");
+    qmlRegisterType(resolveFileUrl(QStringLiteral("SelectionTool.qml")), uri, 
1, 0, "SelectionTool");
+    qmlRegisterType(resolveFileUrl(QStringLiteral("SelectionHandle.qml")), 
uri, 1, 0, "SelectionHandle");
+    qmlRegisterType(resolveFileUrl(QStringLiteral("SelectionBackground.qml")), 
uri, 1, 0, "SelectionBackground");
+    qmlRegisterType(resolveFileUrl(QStringLiteral("CropBackground.qml")), uri, 
1, 0, "CropBackground");
+    qmlRegisterType(resolveFileUrl(QStringLiteral("RectangleCutout.qml")), 
uri, 1, 0, "RectangleCutout");
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/code/kquickimageeditor_plugin.h 
new/kquickimageeditor-0.2.0/src/code/kquickimageeditor_plugin.h
--- old/kquickimageeditor-0.1.3/src/code/kquickimageeditor_plugin.h     
2021-01-26 16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/kquickimageeditor_plugin.h     
2021-10-01 18:15:16.000000000 +0200
@@ -13,6 +13,7 @@
     Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
 public:
     void registerTypes(const char *uri) override;
+
 private:
     QString resolveFilePath(const QString &path) const
     {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/resizehandle.cpp 
new/kquickimageeditor-0.2.0/src/code/resizehandle.cpp
--- old/kquickimageeditor-0.1.3/src/code/resizehandle.cpp       2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/resizehandle.cpp       2021-10-01 
18:15:16.000000000 +0200
@@ -15,8 +15,8 @@
     : QQuickItem(parent)
 {
     setAcceptedMouseButtons(Qt::LeftButton);
-    
-    auto syncCursor = [this] () {
+
+    auto syncCursor = [this]() {
         switch (m_resizeCorner) {
         case Left:
         case Right:
@@ -36,10 +36,9 @@
             setCursor(Qt::SizeBDiagCursor);
         }
     };
-    
+
     syncCursor();
     connect(this, &ResizeHandle::resizeCornerChanged, this, syncCursor);
-    
 }
 
 QQuickItem *ResizeHandle::rectangle() const
@@ -63,12 +62,11 @@
     }
     m_rectangle = qobject_cast<ResizeRectangle *>(rectangle);
     Q_EMIT rectangleChanged();
-
 }
 
 bool ResizeHandle::resizeBlocked() const
 {
-    return false; //m_resizeWidthBlocked || m_resizeHeightBlocked;
+    return false; // m_resizeWidthBlocked || m_resizeHeightBlocked;
 }
 
 bool ResizeHandle::resizeLeft() const
@@ -99,11 +97,10 @@
 
     m_resizeWidthBlocked = width;
     m_resizeHeightBlocked = height;
-    
+
     Q_EMIT resizeBlockedChanged();
 }
 
-
 void ResizeHandle::mousePressEvent(QMouseEvent *event)
 {
     m_mouseDownPosition = event->windowPos();
@@ -114,11 +111,10 @@
 
 void ResizeHandle::mouseMoveEvent(QMouseEvent *event)
 {
-
     const QPointF difference = m_mouseDownPosition - event->windowPos();
-    
+
     const QSizeF minimumSize = QSize(20, 20);
-    
+
     // Horizontal resize
     if (resizeLeft()) {
         const qreal width = qMax(minimumSize.width(), 
m_mouseDownGeometry.width() + difference.x());
@@ -141,14 +137,12 @@
 
         m_rectangle->setInsideY(y);
         m_rectangle->setInsideHeight(height);
-        setResizeBlocked(m_resizeWidthBlocked,
-                            m_mouseDownGeometry.height() + difference.y() < 
minimumSize.height());
+        setResizeBlocked(m_resizeWidthBlocked, m_mouseDownGeometry.height() + 
difference.y() < minimumSize.height());
     } else if (resizeBottom()) {
         const qreal height = qMax(minimumSize.height(), 
m_mouseDownGeometry.height() - difference.y());
 
         m_rectangle->setInsideHeight(qMax(height, minimumSize.height()));
-        setResizeBlocked(m_resizeWidthBlocked,
-                            m_mouseDownGeometry.height() - difference.y() < 
minimumSize.height());
+        setResizeBlocked(m_resizeWidthBlocked, m_mouseDownGeometry.height() - 
difference.y() < minimumSize.height());
     }
 
     event->accept();
@@ -161,5 +155,3 @@
     setResizeBlocked(false, false);
     Q_EMIT resizeBlockedChanged();
 }
-
-#include "moc_resizehandle.cpp"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/resizehandle.h 
new/kquickimageeditor-0.2.0/src/code/resizehandle.h
--- old/kquickimageeditor-0.1.3/src/code/resizehandle.h 2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/resizehandle.h 2021-10-01 
18:15:16.000000000 +0200
@@ -11,7 +11,7 @@
 
 class ResizeRectangle;
 
-class ResizeHandle: public QQuickItem
+class ResizeHandle : public QQuickItem
 {
     Q_OBJECT
     Q_PROPERTY(bool resizeBlocked READ resizeBlocked NOTIFY 
resizeBlockedChanged)
@@ -37,7 +37,7 @@
     void setRectangle(QQuickItem *rectangle);
 
     bool resizeBlocked() const;
-    
+
     void setResizeCorner(Corner corner);
 
 protected:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/resizerectangle.cpp 
new/kquickimageeditor-0.2.0/src/code/resizerectangle.cpp
--- old/kquickimageeditor-0.1.3/src/code/resizerectangle.cpp    2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/resizerectangle.cpp    2021-10-01 
18:15:16.000000000 +0200
@@ -6,11 +6,10 @@
 
 #include "resizerectangle.h"
 
+#include <QDebug>
+#include <QSGFlatColorMaterial>
 #include <QSGGeometry>
 #include <QSGGeometryNode>
-#include <QSGFlatColorMaterial>
-#include <QDebug>
-
 
 ResizeRectangle::ResizeRectangle(QQuickItem *parent)
     : QQuickItem(parent)
@@ -82,8 +81,9 @@
     return m_insideX;
 }
 
-void ResizeRectangle::setInsideX(const qreal x)
+void ResizeRectangle::setInsideX(qreal x)
 {
+    x = qBound(0.0, x, this->width() - m_insideWidth);
     if (m_insideX == x) {
         return;
     }
@@ -98,8 +98,9 @@
     return m_insideY;
 }
 
-void ResizeRectangle::setInsideY(const qreal y)
+void ResizeRectangle::setInsideY(qreal y)
 {
+    y = qBound(0.0, y, this->height() - m_insideHeight);
     if (m_insideY == y) {
         return;
     }
@@ -114,8 +115,9 @@
     return m_insideWidth;
 }
 
-void ResizeRectangle::setInsideWidth(const qreal width)
+void ResizeRectangle::setInsideWidth(qreal width)
 {
+    width = qMin(width, this->width());
     if (m_insideWidth == width) {
         return;
     }
@@ -130,8 +132,9 @@
     return m_insideHeight;
 }
 
-void ResizeRectangle::setInsideHeight(const qreal height)
+void ResizeRectangle::setInsideHeight(qreal height)
 {
+    height = qMin(height, this->height());
     if (m_insideHeight == height) {
         return;
     }
@@ -141,7 +144,7 @@
     update();
 }
 
-QSGNode * ResizeRectangle::updatePaintNode(QSGNode *oldNode, 
QQuickItem::UpdatePaintNodeData *)
+QSGNode *ResizeRectangle::updatePaintNode(QSGNode *oldNode, 
QQuickItem::UpdatePaintNodeData *)
 {
     QSGGeometryNode *node = nullptr;
     QSGGeometry *geometry = nullptr;
@@ -150,8 +153,7 @@
     const int indexCount = 8 * 3;
     if (!oldNode) {
         node = new QSGGeometryNode;
-        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(),
-                                   vertexCount, indexCount);
+        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 
vertexCount, indexCount);
         geometry->setIndexDataPattern(QSGGeometry::StaticPattern);
         geometry->setDrawingMode(GL_TRIANGLES);
         node->setGeometry(geometry);
@@ -183,7 +185,7 @@
     points[10].set(m_insideX + m_insideWidth, m_insideY + m_insideHeight);
     points[11].set(m_insideX, m_insideY + m_insideHeight);
 
-    quint16* indices = geometry->indexDataAsUShort();
+    quint16 *indices = geometry->indexDataAsUShort();
     // left
     indices[0 + 0] = 0;
     indices[0 + 1] = 1;
@@ -226,7 +228,6 @@
     return node;
 }
 
-
 void ResizeRectangle::mouseReleaseEvent(QMouseEvent *event)
 {
     m_mouseClickedOnRectangle = false;
@@ -237,8 +238,8 @@
 {
     m_mouseDownPosition = event->pos();
     m_mouseDownGeometry = QPointF(m_insideX, m_insideY);
-    if (m_mouseDownPosition.x() >= m_insideX  && m_mouseDownPosition.x() <= 
m_insideX + m_insideWidth
-        && m_mouseDownPosition.y() >= m_insideY && m_mouseDownPosition.y() <= 
m_insideY + m_insideHeight) {
+    if (m_mouseDownPosition.x() >= m_insideX && m_mouseDownPosition.x() <= 
m_insideX + m_insideWidth && m_mouseDownPosition.y() >= m_insideY
+        && m_mouseDownPosition.y() <= m_insideY + m_insideHeight) {
         m_mouseClickedOnRectangle = true;
     }
     event->accept();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/code/resizerectangle.h 
new/kquickimageeditor-0.2.0/src/code/resizerectangle.h
--- old/kquickimageeditor-0.1.3/src/code/resizerectangle.h      2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/code/resizerectangle.h      2021-10-01 
18:15:16.000000000 +0200
@@ -8,40 +8,41 @@
 
 #include "resizehandle.h"
 
-#include <QQuickItem>
 #include <QQmlComponent>
+#include <QQuickItem>
 
+/// \deprecated
 class ResizeRectangle : public QQuickItem
 {
     Q_OBJECT
-    
+
     Q_PROPERTY(qreal insideX READ insideX WRITE setInsideX NOTIFY 
insideXChanged)
     Q_PROPERTY(qreal insideY READ insideY WRITE setInsideY NOTIFY 
insideYChanged)
     Q_PROPERTY(qreal insideWidth READ insideWidth WRITE setInsideWidth NOTIFY 
insideWidthChanged)
     Q_PROPERTY(qreal insideHeight READ insideHeight WRITE setInsideHeight 
NOTIFY insideHeightChanged)
-    
+
 public:
     ResizeRectangle(QQuickItem *parent = nullptr);
     ~ResizeRectangle() = default;
-    
+
     qreal insideX() const;
-    void setInsideX(const qreal x);
+    void setInsideX(qreal x);
     qreal insideY() const;
-    void setInsideY(const qreal y);
+    void setInsideY(qreal y);
     qreal insideWidth() const;
-    void setInsideWidth(const qreal width);
+    void setInsideWidth(qreal width);
     qreal insideHeight() const;
-    void setInsideHeight(const qreal height);
-    
+    void setInsideHeight(qreal height);
+
     virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) 
override;
-    
+
 protected:
     void mouseReleaseEvent(QMouseEvent *event) override;
-    void mousePressEvent(QMouseEvent * event) override;
+    void mousePressEvent(QMouseEvent *event) override;
     void mouseMoveEvent(QMouseEvent *event) override;
     void mouseDoubleClickEvent(QMouseEvent *event) override;
     virtual void componentComplete() override;
-    
+
 Q_SIGNALS:
     /// Double click event signal
     void acceptSize();
@@ -50,7 +51,7 @@
     void insideWidthChanged();
     void insideHeightChanged();
     void handleComponentChanged();
-    
+
 private:
     void updateHandles();
 
@@ -61,9 +62,9 @@
     QPointF m_mouseDownPosition;
     QPointF m_mouseDownGeometry;
     bool m_mouseClickedOnRectangle = false;
-    QQmlComponent *m_handleComponent;
-    ResizeHandle *m_handleBottomLeft;
-    ResizeHandle *m_handleBottomRight;
-    ResizeHandle *m_handleTopLeft;
-    ResizeHandle *m_handleTopRight;
+    QQmlComponent *m_handleComponent = nullptr;
+    ResizeHandle *m_handleBottomLeft = nullptr;
+    ResizeHandle *m_handleBottomRight = nullptr;
+    ResizeHandle *m_handleTopLeft = nullptr;
+    ResizeHandle *m_handleTopRight = nullptr;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/controls/CropBackground.qml 
new/kquickimageeditor-0.2.0/src/controls/CropBackground.qml
--- old/kquickimageeditor-0.1.3/src/controls/CropBackground.qml 1970-01-01 
01:00:00.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/controls/CropBackground.qml 2021-10-01 
18:15:16.000000000 +0200
@@ -0,0 +1,19 @@
+/* SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+ */
+
+import QtQuick 2.15
+import org.kde.kirigami 2.15 as Kirigami
+
+RectangleCutout {
+    id: root
+    Rectangle {
+        x: root.insideX - 1
+        y: root.insideY - 1
+        width: root.insideWidth + 2
+        height: root.insideHeight + 2
+        color: "transparent"
+        border.color: Kirigami.Theme.highlightColor
+        border.width: 1
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/controls/RectangleCutout.qml 
new/kquickimageeditor-0.2.0/src/controls/RectangleCutout.qml
--- old/kquickimageeditor-0.1.3/src/controls/RectangleCutout.qml        
1970-01-01 01:00:00.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/controls/RectangleCutout.qml        
2021-10-01 18:15:16.000000000 +0200
@@ -0,0 +1,54 @@
+/* SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+ */
+
+import QtQuick 2.15
+
+Item {
+    id: root
+    property color color: Qt.rgba(0,0,0,0.5)
+    property real insideX: 0
+    property real insideY: 0
+    property real insideWidth: width
+    property real insideHeight: height
+    // NOTE: Using 4 Rectangles is visibly smoother than using an OpacityMask 
effect
+    Rectangle {
+        id: topTintRect
+        LayoutMirroring.enabled: false
+        anchors.left: parent.left
+        anchors.right: parent.right
+        anchors.top: parent.top
+        height: root.insideY
+        color: root.color
+    }
+
+    Rectangle {
+        id: leftTintRect
+        LayoutMirroring.enabled: false
+        anchors.left: parent.left
+        anchors.top: topTintRect.bottom
+        anchors.bottom: bottomTintRect.top
+        width: root.insideX
+        color: root.color
+    }
+
+    Rectangle {
+        id: rightTintRect
+        LayoutMirroring.enabled: false
+        anchors.right: parent.right
+        anchors.top: topTintRect.bottom
+        anchors.bottom: bottomTintRect.top
+        width: root.width - root.insideX - root.insideWidth
+        color: root.color
+    }
+
+    Rectangle {
+        id: bottomTintRect
+        LayoutMirroring.enabled: false
+        anchors.left: parent.left
+        anchors.right: parent.right
+        anchors.bottom: parent.bottom
+        height: root.height - root.insideY - root.insideHeight
+        color: root.color
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/controls/SelectionBackground.qml 
new/kquickimageeditor-0.2.0/src/controls/SelectionBackground.qml
--- old/kquickimageeditor-0.1.3/src/controls/SelectionBackground.qml    
1970-01-01 01:00:00.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/controls/SelectionBackground.qml    
2021-10-01 18:15:16.000000000 +0200
@@ -0,0 +1,43 @@
+/* SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+ */
+
+import QtQuick 2.15
+import QtQuick.Shapes 1.15
+import org.kde.kirigami 2.15 as Kirigami
+
+Shape {
+    id: root
+    property bool enableAnimation: !(root.parent instanceof SelectionTool)
+        || !(parent.selectionArea.drag.active
+            || (parent.pressedHandle && parent.pressedHandle.drag.active))
+    Rectangle {
+        z: -1
+        anchors.fill: parent
+        anchors.margins: -1
+        color: "transparent"
+        border.color: Kirigami.Theme.highlightColor
+        border.width: 1
+    }
+    ShapePath {
+        id: shapePath
+        fillColor: "transparent"
+        strokeWidth: 1
+        strokeColor: "white"
+        strokeStyle: ShapePath.DashLine
+        // for some reason, +2 makes the spacing and dash lengths the same, no 
matter what the strokeWidth is.
+        dashPattern: [Kirigami.Units.smallSpacing / strokeWidth, 
Kirigami.Units.smallSpacing / strokeWidth + 2]
+        dashOffset: 0
+        startX: -strokeWidth/2; startY: startX
+        PathLine { x: root.width - shapePath.startX; y: shapePath.startY }
+        PathLine { x: root.width - shapePath.startX; y: root.height - 
shapePath.startY }
+        PathLine { x: shapePath.startX; y: root.height - shapePath.startY }
+        PathLine { x: shapePath.startX; y: shapePath.startY }
+        NumberAnimation on dashOffset {
+            running: root.enableAnimation
+            loops: Animation.Infinite
+            from: shapePath.dashOffset; to: shapePath.dashOffset + 
shapePath.dashPattern[0] + shapePath.dashPattern[1]
+            duration: 1000
+        }
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/controls/SelectionHandle.qml 
new/kquickimageeditor-0.2.0/src/controls/SelectionHandle.qml
--- old/kquickimageeditor-0.1.3/src/controls/SelectionHandle.qml        
1970-01-01 01:00:00.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/controls/SelectionHandle.qml        
2021-10-01 18:15:16.000000000 +0200
@@ -0,0 +1,120 @@
+/* SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+ */
+
+import QtQuick 2.15
+import QtGraphicalEffects 1.15
+import org.kde.kirigami 2.15 as Kirigami
+
+MouseArea {
+    id: root
+    enum Position {
+        TopLeft,    Top,    TopRight,
+        Left,               Right,
+        BottomLeft, Bottom, BottomRight,
+        NPositions
+    }
+    required property Item target
+    property int position: SelectionHandle.TopLeft
+
+    readonly property bool leftSide: position === SelectionHandle.TopLeft
+        || position === SelectionHandle.Left
+        || position === SelectionHandle.BottomLeft
+    readonly property bool rightSide: position === SelectionHandle.TopRight
+        || position === SelectionHandle.Right
+        || position === SelectionHandle.BottomRight
+    readonly property bool topSide: position === SelectionHandle.TopLeft
+        || position === SelectionHandle.Top
+        || position === SelectionHandle.TopRight
+    readonly property bool bottomSide: position === SelectionHandle.BottomLeft
+        || position === SelectionHandle.Bottom
+        || position === SelectionHandle.BottomRight
+    readonly property bool horizontalOnly: position === SelectionHandle.Left 
|| position === SelectionHandle.Right
+    readonly property bool verticalOnly: position === SelectionHandle.Top || 
position === SelectionHandle.Bottom
+    // Like forward slash
+    readonly property bool forwardDiagonal: position === 
SelectionHandle.TopRight || position === SelectionHandle.BottomLeft
+    // Like backward slash
+    readonly property bool backwardDiagonal: position === 
SelectionHandle.TopLeft || position === SelectionHandle.BottomRight
+
+    property bool lockX: false
+    property bool lockY: false
+
+    LayoutMirroring.enabled: false
+    LayoutMirroring.childrenInherit: true
+    anchors.horizontalCenter: if (!pressed && !lockX) {
+        if (leftSide) {
+            target.left
+        } else if (verticalOnly) {
+            target.horizontalCenter
+        } else {
+            target.right
+        }
+    }
+    anchors.verticalCenter: if (!pressed && !lockY) {
+        if (topSide) {
+            target.top
+        } else if (horizontalOnly) {
+            target.verticalCenter
+        } else {
+            target.bottom
+        }
+    }
+    implicitWidth: graphics.implicitWidth + Kirigami.Units.largeSpacing * 2
+    implicitHeight: graphics.implicitHeight + Kirigami.Units.largeSpacing * 2
+    width: verticalOnly ? target.width - implicitWidth : implicitWidth
+    height: horizontalOnly ? target.height - implicitHeight : implicitHeight
+    cursorShape: if (horizontalOnly) {
+        Qt.SizeHorCursor
+    } else if (verticalOnly) {
+        Qt.SizeVerCursor
+    } else if (forwardDiagonal) {
+        // actually oriented like forward slash
+        Qt.SizeBDiagCursor
+    } else {
+        // actually oriented like backward slash
+        Qt.SizeFDiagCursor
+    }
+    drag {
+        axis: if (horizontalOnly) {
+            Drag.XAxis
+        } else if (verticalOnly) {
+            Drag.YAxis
+        } else {
+            Drag.XAndYAxis
+        }
+        target: pressed ? root : null
+        minimumX: -width / 2
+        maximumX: parent.width - width / 2
+        minimumY: -height / 2
+        maximumY: parent.height - height / 2
+        threshold: 0
+    }
+    Rectangle {
+        id: graphics
+        visible: false
+        implicitWidth: Kirigami.Units.gridUnit + Kirigami.Units.gridUnit % 2
+        implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.gridUnit % 2
+        anchors.centerIn: parent
+        color: Kirigami.Theme.highlightColor
+        radius: height / 2
+    }
+    // Has to be the same size as source
+    Item {
+        id: maskSource
+        visible: false
+        anchors.fill: graphics
+        Rectangle {
+            x: root.leftSide ? parent.width - width : 0
+            y: root.topSide ? parent.height - height : 0
+            width: root.forwardDiagonal || root.backwardDiagonal || 
root.horizontalOnly ? parent.width / 2 : parent.width
+            height: root.forwardDiagonal || root.backwardDiagonal || 
root.verticalOnly ? parent.height / 2 : parent.height
+        }
+    }
+    OpacityMask {
+        anchors.fill: graphics
+        cached: true
+        invert: true
+        source: graphics
+        maskSource: maskSource
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/controls/SelectionTool.qml 
new/kquickimageeditor-0.2.0/src/controls/SelectionTool.qml
--- old/kquickimageeditor-0.1.3/src/controls/SelectionTool.qml  1970-01-01 
01:00:00.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/controls/SelectionTool.qml  2021-10-01 
18:15:16.000000000 +0200
@@ -0,0 +1,207 @@
+/* SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+ */
+
+import QtQuick 2.15
+import QtQml 2.15
+
+Item {
+    id: root
+    // make this readonly so it can be accessed without risking external 
modification
+    readonly property SelectionHandle pressedHandle: _private.pressedHandle
+    readonly property alias selectionArea: selectionArea
+    property alias selectionX: selectionArea.x
+    property alias selectionY: selectionArea.y
+    property alias selectionWidth: selectionArea.width
+    property alias selectionHeight: selectionArea.height
+
+    QtObject {
+        id: _private
+        property SelectionHandle pressedHandle: null
+    }
+
+    MouseArea {
+        id: selectionArea
+        x: 0
+        y: 0
+        z: 1
+        width: parent.width
+        height: parent.height
+        LayoutMirroring.enabled: false
+        anchors.left: if (_private.pressedHandle) {
+            if (_private.pressedHandle.backwardDiagonal) {
+                handleTopLeft.horizontalCenter
+            } else if (_private.pressedHandle.forwardDiagonal) {
+                handleBottomLeft.horizontalCenter
+            } else if (_private.pressedHandle.horizontalOnly) {
+                handleLeft.horizontalCenter
+            }
+        }
+        anchors.right: if (_private.pressedHandle) {
+            if (_private.pressedHandle.backwardDiagonal) {
+                handleBottomRight.horizontalCenter
+            } else if (_private.pressedHandle.forwardDiagonal) {
+                handleTopRight.horizontalCenter
+            } else if (_private.pressedHandle.horizontalOnly) {
+                handleRight.horizontalCenter
+            }
+        }
+        anchors.top: if (_private.pressedHandle) {
+            if (_private.pressedHandle.backwardDiagonal) {
+                handleTopLeft.verticalCenter
+            } else if (_private.pressedHandle.forwardDiagonal) {
+                handleTopRight.verticalCenter
+            } else if (_private.pressedHandle.verticalOnly) {
+                handleTop.verticalCenter
+            }
+        }
+        anchors.bottom: if (_private.pressedHandle) {
+            if (_private.pressedHandle.backwardDiagonal) {
+                handleBottomRight.verticalCenter
+            } else if (_private.pressedHandle.forwardDiagonal) {
+                handleBottomLeft.verticalCenter
+            } else if (_private.pressedHandle.verticalOnly) {
+                handleBottom.verticalCenter
+            }
+        }
+        enabled: drag.target
+        cursorShape: if (_private.pressedHandle || (pressed && enabled)) {
+            Qt.ClosedHandCursor
+        } else if (enabled) {
+            Qt.OpenHandCursor
+        } else {
+            Qt.ArrowCursor
+        }
+        drag {
+            axis: Drag.XAndYAxis
+            target: (selectionArea.width === root.width && 
selectionArea.height === root.height) || _private.pressedHandle ? null : 
selectionArea
+            minimumX: 0
+            maximumX: root.width - selectionArea.width
+            minimumY: 0
+            maximumY: root.height - selectionArea.height
+            threshold: 0
+        }
+    }
+
+    SelectionHandle {
+        id: handleTopLeft
+        target: selectionArea
+        position: SelectionHandle.TopLeft
+        lockX: _private.pressedHandle && 
_private.pressedHandle.backwardDiagonal
+        lockY: lockX
+        drag.maximumX: handleBottomRight.x - implicitWidth / 2
+        drag.maximumY: handleBottomRight.y - implicitHeight / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleTopLeft; when: handleTopLeft.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    SelectionHandle {
+        id: handleTop
+        visible: selectionArea.width >= implicitWidth
+        target: selectionArea
+        position: SelectionHandle.Top
+        lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
+        drag.maximumY: handleBottom.y - implicitHeight / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleTop; when: handleTop.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    SelectionHandle {
+        id: handleTopRight
+        target: selectionArea
+        position: SelectionHandle.TopRight
+        lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
+        lockY: lockX
+        drag.minimumX: handleBottomLeft.x + implicitWidth / 2
+        drag.maximumY: handleBottomLeft.y - implicitHeight / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleTopRight; when: handleTopRight.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    SelectionHandle {
+        id: handleLeft
+        visible: selectionArea.height >= implicitHeight
+        target: selectionArea
+        position: SelectionHandle.Left
+        lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
+        drag.maximumX: handleRight.x - implicitWidth / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleLeft; when: handleLeft.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    SelectionHandle {
+        id: handleRight
+        visible: selectionArea.height >= implicitHeight
+        target: selectionArea
+        position: SelectionHandle.Right
+        lockX: _private.pressedHandle && _private.pressedHandle.horizontalOnly
+        drag.minimumX: handleLeft.x + implicitWidth / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleRight; when: handleRight.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    SelectionHandle {
+        id: handleBottomLeft
+        target: selectionArea
+        position: SelectionHandle.BottomLeft
+        lockX: _private.pressedHandle && _private.pressedHandle.forwardDiagonal
+        lockY: lockX
+        drag.maximumX: handleTopRight.x - implicitWidth / 2
+        drag.minimumY: handleTopRight.y + implicitHeight / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleBottomLeft; when: handleBottomLeft.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    SelectionHandle {
+        id: handleBottom
+        visible: selectionArea.width >= implicitWidth
+        target: selectionArea
+        position: SelectionHandle.Bottom
+        lockY: _private.pressedHandle && _private.pressedHandle.verticalOnly
+        drag.minimumY: handleTop.y + implicitHeight / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleBottom; when: handleBottom.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    SelectionHandle {
+        id: handleBottomRight
+        target: selectionArea
+        position: SelectionHandle.BottomRight
+        lockX: _private.pressedHandle && 
_private.pressedHandle.backwardDiagonal
+        lockY: lockX
+        drag.minimumX: handleTopLeft.x + implicitWidth / 2
+        drag.minimumY: handleTopLeft.y + implicitHeight / 2
+        Binding {
+            target: _private; property: "pressedHandle"
+            value: handleBottomRight; when: handleBottomRight.pressed
+            restoreMode: Binding.RestoreBindingOrValue
+        }
+    }
+    // TODO: maybe scale proportions instead of just limiting size
+    onWidthChanged: if (selectionArea.x + selectionArea.width > root.width) {
+        selectionArea.width = Math.max(root.width - selectionArea.x, 
handleTopLeft.implicitWidth/2)
+        if (selectionArea.x > root.width) {
+            selectionArea.x = Math.max(root.width - selectionArea.width, 0)
+        }
+    }
+    onHeightChanged: if (selectionArea.y + selectionArea.height > root.height) 
{
+        selectionArea.height = Math.max(root.height - selectionArea.y, 
handleTopLeft.implicitHeight/2)
+        if (selectionArea.y > root.height) {
+            selectionArea.y = Math.max(root.height - selectionArea.height, 0)
+        }
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/src/controls/plugins.qmltypes 
new/kquickimageeditor-0.2.0/src/controls/plugins.qmltypes
--- old/kquickimageeditor-0.1.3/src/controls/plugins.qmltypes   2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/controls/plugins.qmltypes   2021-10-01 
18:15:16.000000000 +0200
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: 2020 Carl Schwan <[email protected]>
+//
+// SPDX-License-Identifier: BSD-2-Clause
 import QtQuick.tooling 1.2
 
 // This file describes the plugin-supplied types contained in the library.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kquickimageeditor-0.1.3/src/resources.qrc 
new/kquickimageeditor-0.2.0/src/resources.qrc
--- old/kquickimageeditor-0.1.3/src/resources.qrc       2021-01-26 
16:57:35.000000000 +0100
+++ new/kquickimageeditor-0.2.0/src/resources.qrc       2021-10-01 
18:15:16.000000000 +0200
@@ -6,5 +6,10 @@
 <RCC>
   <qresource prefix="/">
     <file alias="BasicResizeHandle.qml">controls/BasicResizeHandle.qml</file>
+    <file alias="SelectionTool.qml">controls/SelectionTool.qml</file>
+    <file alias="SelectionHandle.qml">controls/SelectionHandle.qml</file>
+    <file 
alias="SelectionBackground.qml">controls/SelectionBackground.qml</file>
+    <file alias="CropBackground.qml">controls/CropBackground.qml</file>
+    <file alias="RectangleCutout.qml">controls/RectangleCutout.qml</file>
   </qresource>
 </RCC>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/tests/manual/SelectionToolCropBackgroundTest.qml 
new/kquickimageeditor-0.2.0/tests/manual/SelectionToolCropBackgroundTest.qml
--- 
old/kquickimageeditor-0.1.3/tests/manual/SelectionToolCropBackgroundTest.qml    
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/kquickimageeditor-0.2.0/tests/manual/SelectionToolCropBackgroundTest.qml    
    2021-10-01 18:15:16.000000000 +0200
@@ -0,0 +1,31 @@
+/* SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+ */
+
+import QtQuick 2.15
+import org.kde.kquickimageeditor 1.0 as KQuickImageEditor
+
+Item {
+    id: root
+    width: 400
+    height: 400
+    Rectangle {
+        id: background
+        anchors.fill: parent
+        anchors.margins: 20
+        z: -1
+        gradient: Gradient.MeanFruit
+    }
+    KQuickImageEditor.SelectionTool {
+        id: selectionTool
+        anchors.fill: background
+        KQuickImageEditor.CropBackground {
+            anchors.fill: parent
+            z: -1
+            insideX: selectionTool.selectionX
+            insideY: selectionTool.selectionY
+            insideWidth: selectionTool.selectionWidth
+            insideHeight: selectionTool.selectionHeight
+        }
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kquickimageeditor-0.1.3/tests/manual/SelectionToolSelectionBackgroundTest.qml
 
new/kquickimageeditor-0.2.0/tests/manual/SelectionToolSelectionBackgroundTest.qml
--- 
old/kquickimageeditor-0.1.3/tests/manual/SelectionToolSelectionBackgroundTest.qml
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/kquickimageeditor-0.2.0/tests/manual/SelectionToolSelectionBackgroundTest.qml
   2021-10-01 18:15:16.000000000 +0200
@@ -0,0 +1,30 @@
+/* SPDX-FileCopyrightText: 2021 Noah Davis <[email protected]>
+ * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+ */
+
+import QtQuick 2.15
+import org.kde.kquickimageeditor 1.0 as KQuickImageEditor
+
+Item {
+    id: root
+    width: 400
+    height: 400
+    Rectangle {
+        id: background
+        anchors.fill: parent
+        anchors.margins: 20
+        z: -1
+        gradient: Gradient.MeanFruit
+    }
+    KQuickImageEditor.SelectionTool {
+        id: selectionTool
+        anchors.fill: background
+        KQuickImageEditor.SelectionBackground {
+            z: -1
+            x: selectionTool.selectionX
+            y: selectionTool.selectionY
+            width: selectionTool.selectionWidth
+            height: selectionTool.selectionHeight
+        }
+    }
+}

Reply via email to