Commit 0027d885 authored by Dmitry Kazakov's avatar Dmitry Kazakov

[FEATURE] Allow deselection by clicking with a selection tool

1) Now you can deselect with *any* selection tool:
   rectangular, elliptical, outline.

2) Now you can also deselect with your tablet stylus,
   because there is a small tolerance level for
   considering your new selection as a click. If you made
   a selection that is smaller than 5 (view) pixels, then
   it is considered as a click and the tool deselects
   everything.

3) One can configure the click-tolerance level with a
   config option 'SelectionViewSizeMinimum'

CC:kimageshop@kde.org

# Conflicts:
#	libs/image/kis_algebra_2d.h
parent 86cadec8
......@@ -41,6 +41,7 @@ struct PointTypeTraits<QPoint>
{
typedef int value_type;
typedef qreal calculation_type;
typedef QRect rect_type;
};
template <>
......@@ -48,6 +49,7 @@ struct PointTypeTraits<QPointF>
{
typedef qreal value_type;
typedef qreal calculation_type;
typedef QRectF rect_type;
};
......@@ -201,6 +203,27 @@ inline void accumulateBounds(const Point &pt, Rect *bounds)
}
}
template <template <class T> class Container, class Point, class Rect>
inline void accumulateBounds(const Container<Point> &points, Rect *bounds)
{
Q_FOREACH (const Point &pt, points) {
accumulateBounds(pt, bounds);
}
}
template <template <class T> class Container, class Point>
inline typename PointTypeTraits<Point>::rect_type
accumulateBounds(const Container<Point> &points)
{
typename PointTypeTraits<Point>::rect_type result;
Q_FOREACH (const Point &pt, points) {
accumulateBounds(pt, &result);
}
return result;
}
template <class Point, class Rect>
inline Point clampPoint(Point pt, const Rect &bounds)
{
......@@ -223,7 +246,12 @@ inline Point clampPoint(Point pt, const Rect &bounds)
return pt;
}
QPainterPath KRITAIMAGE_EXPORT smallArrow();
template <class Size>
auto maxDimension(Size size) -> decltype(size.width()) {
return qMax(size.width(), size.height());
}
QPainterPath KRITAGLOBAL_EXPORT smallArrow();
/**
* Multiply width and height of \p rect by \p coeff keeping the
......
......@@ -918,6 +918,16 @@ void KisConfig::setOutlineSizeMinimum(qreal outlineSizeMinimum) const
m_cfg.writeEntry("OutlineSizeMinimum", outlineSizeMinimum);
}
qreal KisConfig::selectionViewSizeMinimum(bool defaultValue) const
{
return (defaultValue ? 5.0 : m_cfg.readEntry("SelectionViewSizeMinimum", 5.0));
}
void KisConfig::setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const
{
m_cfg.writeEntry("SelectionViewSizeMinimum", outlineSizeMinimum);
}
int KisConfig::autoSaveInterval(bool defaultValue) const
{
return (defaultValue ? 300 : m_cfg.readEntry("AutoSaveInterval", 300));
......
......@@ -239,6 +239,9 @@ public:
qreal outlineSizeMinimum(bool defaultValue = false) const;
void setOutlineSizeMinimum(qreal outlineSizeMinimum) const;
qreal selectionViewSizeMinimum(bool defaultValue = false) const;
void setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const;
int autoSaveInterval(bool defaultValue = false) const;
void setAutoSaveInterval(int seconds) const;
......
......@@ -41,6 +41,9 @@
#include "kis_command_utils.h"
#include "commands/kis_deselect_global_selection_command.h"
#include "kis_algebra_2d.h"
#include "kis_config.h"
KisSelectionToolHelper::KisSelectionToolHelper(KisCanvas2* canvas, const KUndo2MagicString& name)
: m_canvas(canvas)
......@@ -243,3 +246,18 @@ void KisSelectionToolHelper::cropPathIfNeeded(QPainterPath *path)
*path &= cropPath;
}
}
bool KisSelectionToolHelper::tryDeselectCurrentSelection(const QRectF selectionViewRect, SelectionAction action)
{
bool result = false;
if (KisAlgebra2D::maxDimension(selectionViewRect) < KisConfig().selectionViewSizeMinimum() &&
(action == SELECTION_INTERSECT || action == SELECTION_REPLACE)) {
// Queueing this action to ensure we avoid a race condition when unlocking the node system
QTimer::singleShot(0, m_canvas->viewManager()->selectionManager(), SLOT(deselect()));
result = true;
}
return result;
}
......@@ -46,9 +46,11 @@ public:
bool canShortcutToNoop(const QRect &rect, SelectionAction action);
void cropPathIfNeeded(QPainterPath *path);
bool tryDeselectCurrentSelection(const QRectF selectionViewRect, SelectionAction action);
private:
KisCanvas2* m_canvas;
KisImageWSP m_image;
KisImageSP m_image;
KisLayerSP m_layer;
KUndo2MagicString m_name;
};
......
......@@ -48,15 +48,12 @@ void __KisToolSelectEllipticalLocal::finishRect(const QRectF &rect)
KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
Q_ASSERT(kisCanvas);
// If the user just clicks on the canvas deselect
if (rect.isEmpty()) {
// Queueing this action to ensure we avoid a race condition when unlocking the node system
QTimer::singleShot(0, kisCanvas->viewManager()->selectionManager(), SLOT(deselect()));
KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select Ellipse"));
if (helper.tryDeselectCurrentSelection(pixelToView(rect), selectionAction())) {
return;
}
KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select Ellipse"));
if (selectionMode() == PIXEL_SELECTION) {
KisPixelSelectionSP tmpSel = new KisPixelSelection();
......
......@@ -52,6 +52,9 @@
#include "kis_pixel_selection.h"
#include "kis_selection_tool_helper.h"
#include "kis_algebra_2d.h"
#define FEEDBACK_LINE_WIDTH 2
......@@ -151,10 +154,17 @@ void KisToolSelectOutline::finishSelectionAction()
KIS_ASSERT_RECOVER_RETURN(kisCanvas);
kisCanvas->updateCanvas();
if (m_points.count() > 2) {
QRectF boundingViewRect =
pixelToView(KisAlgebra2D::accumulateBounds(m_points));
KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select by Outline"));
if (m_points.count() > 2 &&
!helper.tryDeselectCurrentSelection(boundingViewRect, selectionAction())) {
QApplication::setOverrideCursor(KisCursor::waitCursor());
KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select by Outline"));
if (selectionMode() == PIXEL_SELECTION) {
......
......@@ -55,10 +55,7 @@ void __KisToolSelectRectangularLocal::finishRect(const QRectF& rect)
QRect rc(rect.normalized().toRect());
helper.cropRectIfNeeded(&rc, selectionAction());
// If the user just clicks on the canvas deselect
if (helper.canShortcutToDeselect(rc, selectionAction())) {
// Queueing this action to ensure we avoid a race condition when unlocking the node system
QTimer::singleShot(0, kisCanvas->viewManager()->selectionManager(), SLOT(deselect()));
if (helper.tryDeselectCurrentSelection(pixelToView(rc), selectionAction())) {
return;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment