Git commit 34708565caeb5d5fe9b8c14b9cd0af1a8ab8d5fe by David Hurka.
Committed on 16/07/2020 at 22:32.
Pushed by davidhurka into branch 'release/20.08'.

Add Constrain Angle action for annotation tools, alternative to pressing Shift

This adds a KToggleAction which sets annotation tools to constrain angle mode.
It provides an alternative user interface to the Shift button, which is used to 
constrain angles since MR !210.
The action and the Shift button are XOR-ed, i. e. if constrain angle mode is 
activated, pressing Shift temporarily disables it.

The action state is remembered accross sessions, for consistency with most 
other actions. It should be difficult to check this action without knowing of 
its existence, since it is not in any toolbar or menu, just in the action 
collection.

The meaning of AnnotatorEngine::Modifiers was generalized a bit, moving the 
responsibility about whether to constrain angles back to PageViewAnnotator, 
because AnnotatorEngine does not know about the action.

FEATURE: 353560
FIXED-IN: 1.11

M  +4    -7    doc/index.docbook
M  +23   -2    ui/annotationactionhandler.cpp
M  +2    -6    ui/annotationtools.cpp
M  +4    -3    ui/annotationtools.h
M  +23   -6    ui/pageviewannotator.cpp
M  +11   -0    ui/pageviewannotator.h
M  +1    -1    ui/presentationwidget.cpp

https://invent.kde.org/graphics/okular/commit/34708565caeb5d5fe9b8c14b9cd0af1a8ab8d5fe

diff --git a/doc/index.docbook b/doc/index.docbook
index 3f044804f..70996f35c 100644
--- a/doc/index.docbook
+++ b/doc/index.docbook
@@ -1171,13 +1171,10 @@ Context menu actions like Rename Bookmarks etc.)
                                    </tgroup>
                                  </informaltable>
                                  <para>
-                                   The contents of the annotating toolbar can 
be configured using the <link linkend="configannotations">Annotations page of 
&okular; configuration dialog</link>. This page can be opened with &RMB; 
clicking on the annotating toolbar then choosing <guimenuitem>Configure 
Annotations...</guimenuitem> from the context menu.
-                               </para>
-                               <para>
-                                        With a single &LMB; click on an 
annotation tool button you can use a tool once.
-                                       If you &eg; want to highlight all 
important parts of a text, activate that tool
-                                       permanently by double clicking on the 
tool button.
-                                       Press the <keycap>Esc</keycap> key or 
click the tool button again to leave the permanent mode.
+                                         By pressing <keycap>Shift</keycap> 
you can constrain the angle of line and polygon annotations to 15° steps, and 
the ratio of shape annotations (&eg; Rectangle, Ellipse) to 1:1. You can also 
get a toolbar button from <ulink 
url="help:/fundamentals/config.html#toolbars">Configure Toolbars...</ulink>.
+                                 </para>
+                                 <para>
+                                         The contents of the <guilabel>Quick 
Annotations</guilabel> menu can be configured using the <link 
linkend="configannotations">Annotations page of &okular; configuration 
dialog</link>. This page can be opened by clicking <guilabel>Quick 
Annotations</guilabel> button, then choosing <guimenuitem>Configure 
Annotations...</guimenuitem> from the pop-up menu.
                                </para>
                                <note>
                                        <para>
diff --git a/ui/annotationactionhandler.cpp b/ui/annotationactionhandler.cpp
index b49bed971..43569e717 100644
--- a/ui/annotationactionhandler.cpp
+++ b/ui/annotationactionhandler.cpp
@@ -52,6 +52,7 @@ public:
         , aStamp(nullptr)
         , aAddToQuickTools(nullptr)
         , aContinuousMode(nullptr)
+        , aConstrainRatioAndAngle(nullptr)
         , aWidth(nullptr)
         , aColor(nullptr)
         , aInnerColor(nullptr)
@@ -107,6 +108,7 @@ public:
     ToggleActionMenu *aStamp;
     QAction *aAddToQuickTools;
     KToggleAction *aContinuousMode;
+    KToggleAction *aConstrainRatioAndAngle;
     KSelectAction *aWidth;
     KSelectAction *aColor;
     KSelectAction *aInnerColor;
@@ -252,8 +254,10 @@ void 
AnnotationActionHandlerPrivate::updateConfigActions(const QString &annotTyp
     const bool isTypewriter = annotType == QStringLiteral("typewriter");
     const bool isInlineNote = annotType == QStringLiteral("note-inline");
     const bool isText = isInlineNote || isTypewriter;
-    const bool isShape = annotType == QStringLiteral("rectangle") || annotType 
== QStringLiteral("ellipse") || annotType == QStringLiteral("polygon");
-    const bool isLine = annotType == QStringLiteral("ink") || annotType == 
QStringLiteral("straight-line");
+    const bool isPolygon = annotType == QStringLiteral("polygon");
+    const bool isShape = annotType == QStringLiteral("rectangle") || annotType 
== QStringLiteral("ellipse") || isPolygon;
+    const bool isStraightLine = annotType == QStringLiteral("straight-line");
+    const bool isLine = annotType == QStringLiteral("ink") || isStraightLine;
     const bool isStamp = annotType == QStringLiteral("stamp");
 
     if (isTypewriter) {
@@ -269,6 +273,7 @@ void 
AnnotationActionHandlerPrivate::updateConfigActions(const QString &annotTyp
     aInnerColor->setEnabled(isShape);
     aOpacity->setEnabled(isAnnotationSelected);
     aFont->setEnabled(isText);
+    aConstrainRatioAndAngle->setEnabled(isStraightLine || isShape);
     aAdvancedSettings->setEnabled(isAnnotationSelected);
 
     // set tooltips
@@ -279,6 +284,7 @@ void 
AnnotationActionHandlerPrivate::updateConfigActions(const QString &annotTyp
         aOpacity->setToolTip(i18nc("@info:tooltip", "Annotation opacity (No 
annotation selected)"));
         aFont->setToolTip(i18nc("@info:tooltip", "Annotation font (No 
annotation selected)"));
         aAddToQuickTools->setToolTip(i18nc("@info:tooltip", "Add the current 
annotation to the quick annotations menu (No annotation selected)"));
+        aConstrainRatioAndAngle->setToolTip(i18nc("@info:tooltip", "Constrain 
shape ratio to 1:1 or line angle to 15° steps (No annotation selected)"));
         aAdvancedSettings->setToolTip(i18nc("@info:tooltip", "Advanced 
settings for the current annotation tool (No annotation selected)"));
         return;
     }
@@ -309,6 +315,14 @@ void 
AnnotationActionHandlerPrivate::updateConfigActions(const QString &annotTyp
         aFont->setToolTip(i18nc("@info:tooltip", "Annotation font (Current 
annotation has no font)"));
     }
 
+    if (isStraightLine || isPolygon) {
+        aConstrainRatioAndAngle->setToolTip(i18nc("@info:tooltip", "Constrain 
line angle to 15° steps"));
+    } else if (isShape) {
+        aConstrainRatioAndAngle->setToolTip(i18nc("@info:tooltip", "Constrain 
shape ratio to 1:1"));
+    } else {
+        aConstrainRatioAndAngle->setToolTip(i18nc("@info:tooltip", "Constrain 
shape ratio to 1:1 or line angle to 15° steps (Not supported by current 
annotation)"));
+    }
+
     aOpacity->setToolTip(i18nc("@info:tooltip", "Annotation opacity"));
     aAddToQuickTools->setToolTip(i18nc("@info:tooltip", "Add the current 
annotation to the quick annotations menu"));
     aAdvancedSettings->setToolTip(i18nc("@info:tooltip", "Advanced settings 
for the current annotation tool"));
@@ -612,6 +626,11 @@ 
AnnotationActionHandler::AnnotationActionHandler(PageViewAnnotator *parent, KAct
     d->aContinuousMode->setToolTip(i18nc("@info:tooltip", "Keep the annotation 
tool active after use"));
     d->aContinuousMode->setChecked(d->annotator->continuousMode());
 
+    // Constrain angle action
+    d->aConstrainRatioAndAngle =
+        new KToggleAction(QIcon::fromTheme(QStringLiteral("snap-angle")), 
i18nc("@action When checked, line annotations are constrained to 15° steps, 
shape annotations to 1:1 ratio", "Constrain Ratio and Angle of Annotation 
Tools"), this);
+    
d->aConstrainRatioAndAngle->setChecked(d->annotator->constrainRatioAndAngleActive());
+
     // Annotation settings actions
     d->aColor = 
d->colorPickerAction(AnnotationActionHandlerPrivate::AnnotationColor::Color);
     d->aInnerColor = 
d->colorPickerAction(AnnotationActionHandlerPrivate::AnnotationColor::InnerColor);
@@ -638,6 +657,7 @@ 
AnnotationActionHandler::AnnotationActionHandler(PageViewAnnotator *parent, KAct
 
     connect(d->aAddToQuickTools, &QAction::triggered, d->annotator, 
&PageViewAnnotator::addToQuickAnnotations);
     connect(d->aContinuousMode, &QAction::toggled, d->annotator, 
&PageViewAnnotator::setContinuousMode);
+    connect(d->aConstrainRatioAndAngle, &QAction::toggled, d->annotator, 
&PageViewAnnotator::setConstrainRatioAndAngle);
     connect(d->aAdvancedSettings, &QAction::triggered, d->annotator, 
&PageViewAnnotator::slotAdvancedSettings);
     connect(d->aFont, &QAction::triggered, 
std::bind(&AnnotationActionHandlerPrivate::slotSelectAnnotationFont, d));
 
@@ -675,6 +695,7 @@ 
AnnotationActionHandler::AnnotationActionHandler(PageViewAnnotator *parent, KAct
     ac->addAction(QStringLiteral("annotation_favorites"), d->aQuickTools);
     ac->addAction(QStringLiteral("annotation_bookmark"), d->aAddToQuickTools);
     ac->addAction(QStringLiteral("annotation_settings_pin"), 
d->aContinuousMode);
+    ac->addAction(QStringLiteral("annotation_constrain_ratio_angle"), 
d->aConstrainRatioAndAngle);
     ac->addAction(QStringLiteral("annotation_settings_width"), d->aWidth);
     ac->addAction(QStringLiteral("annotation_settings_color"), d->aColor);
     ac->addAction(QStringLiteral("annotation_settings_inner_color"), 
d->aInnerColor);
diff --git a/ui/annotationtools.cpp b/ui/annotationtools.cpp
index b32f5b31e..b4c5cf519 100644
--- a/ui/annotationtools.cpp
+++ b/ui/annotationtools.cpp
@@ -34,7 +34,7 @@ AnnotatorEngine::AnnotatorEngine(const QDomElement 
&engineElement)
         m_annotElement = annElement;
 }
 
-void AnnotatorEngine::decodeEvent(const QMouseEvent *mouseEvent, EventType 
*eventType, Button *button, Modifiers *modifiers)
+void AnnotatorEngine::decodeEvent(const QMouseEvent *mouseEvent, EventType 
*eventType, Button *button)
 {
     *eventType = AnnotatorEngine::Press;
     if (mouseEvent->type() == QEvent::MouseMove)
@@ -48,11 +48,9 @@ void AnnotatorEngine::decodeEvent(const QMouseEvent 
*mouseEvent, EventType *even
         *button = AnnotatorEngine::Left;
     else if (buttonState == Qt::RightButton)
         *button = AnnotatorEngine::Right;
-
-    modifiers->shift = mouseEvent->modifiers() & Qt::ShiftModifier;
 }
 
-void AnnotatorEngine::decodeEvent(const QTabletEvent *tabletEvent, EventType 
*eventType, Button *button, Modifiers *modifiers)
+void AnnotatorEngine::decodeEvent(const QTabletEvent *tabletEvent, EventType 
*eventType, Button *button)
 {
     switch (tabletEvent->type()) {
     case QEvent::TabletPress:
@@ -75,8 +73,6 @@ void AnnotatorEngine::decodeEvent(const QTabletEvent 
*tabletEvent, EventType *ev
         Q_ASSERT(false);
         break;
     }
-
-    modifiers->shift = tabletEvent->modifiers() & Qt::ShiftModifier;
 }
 
 AnnotatorEngine::~AnnotatorEngine()
diff --git a/ui/annotationtools.h b/ui/annotationtools.h
index 869e94bd6..54e0c3bbb 100644
--- a/ui/annotationtools.h
+++ b/ui/annotationtools.h
@@ -42,8 +42,9 @@ public:
     // enum definitions
     enum EventType { Press, Move, Release };
     enum Button { None, Left, Right };
+    /** To tell the annotator engine about modifier keys and other special 
wishes */
     struct Modifiers {
-        bool shift;
+        bool constrainRatioAndAngle; ///< Whether the engine shall snap to 
certain angles, if supported.
     };
 
     // perform operations
@@ -63,8 +64,8 @@ public:
         m_item = item;
     }
 
-    static void decodeEvent(const QMouseEvent *mouseEvent, EventType 
*eventType, Button *button, Modifiers *modifiers);
-    static void decodeEvent(const QTabletEvent *tabletEvent, EventType 
*eventType, Button *button, Modifiers *modifiers);
+    static void decodeEvent(const QMouseEvent *mouseEvent, EventType 
*eventType, Button *button);
+    static void decodeEvent(const QTabletEvent *tabletEvent, EventType 
*eventType, Button *button);
 
     virtual QCursor cursor() const;
 
diff --git a/ui/pageviewannotator.cpp b/ui/pageviewannotator.cpp
index 89ba44a9f..005fc7433 100644
--- a/ui/pageviewannotator.cpp
+++ b/ui/pageviewannotator.cpp
@@ -99,8 +99,8 @@ public:
         } else
             return QRect();
 
-        // shift button: enforce 1:1 form factor (e.g. circle or square)
-        if (modifiers.shift) {
+        // Constrain to 1:1 form factor (e.g. circle or square)
+        if (modifiers.constrainRatioAndAngle) {
             double side = qMin(qAbs(nX - startpoint.x) * xScale, qAbs(nY - 
startpoint.y) * yScale);
             nX = qBound(startpoint.x - side / xScale, nX, startpoint.x + side 
/ xScale);
             nY = qBound(startpoint.y - side / yScale, nY, startpoint.y + side 
/ yScale);
@@ -350,8 +350,8 @@ public:
         //            if ( button != Left )
         //                return rect;
 
-        // shift button: constrain to 15° steps
-        if (modifiers.shift && !points.isEmpty()) {
+        // Constrain to 15° steps, except first point of course.
+        if (modifiers.constrainRatioAndAngle && !points.isEmpty()) {
             const Okular::NormalizedPoint constrainedPoint = 
constrainAngle(points.constLast(), nX, nY, xScale, yScale, M_PI / 12.);
             nX = constrainedPoint.x;
             nY = constrainedPoint.y;
@@ -707,6 +707,7 @@ PageViewAnnotator::PageViewAnnotator(PageView *parent, 
Okular::Document *storage
     , m_toolsDefinition(nullptr)
     , m_quickToolsDefinition(nullptr)
     , m_continuousMode(true)
+    , m_constrainRatioAndAngle(false)
     , m_lastToolID(-1)
     , m_lockedItem(nullptr)
 {
@@ -840,7 +841,10 @@ QRect PageViewAnnotator::routeMouseEvent(QMouseEvent *e, 
PageViewItem *item)
     AnnotatorEngine::Modifiers modifiers;
 
     // figure out the event type and button
-    AnnotatorEngine::decodeEvent(e, &eventType, &button, &modifiers);
+    AnnotatorEngine::decodeEvent(e, &eventType, &button);
+
+    // Constrain angle if action checked XOR shift button pressed.
+    modifiers.constrainRatioAndAngle = (bool(constrainRatioAndAngleActive()) 
!= bool(e->modifiers() & Qt::ShiftModifier));
 
     return performRouteMouseOrTabletEvent(eventType, button, modifiers, 
e->localPos(), item);
 }
@@ -859,7 +863,10 @@ QRect PageViewAnnotator::routeTabletEvent(QTabletEvent *e, 
PageViewItem *item, c
     AnnotatorEngine::Modifiers modifiers;
 
     // figure out the event type and button
-    AnnotatorEngine::decodeEvent(e, &eventType, &button, &modifiers);
+    AnnotatorEngine::decodeEvent(e, &eventType, &button);
+
+    // Constrain angle if action checked XOR shift button pressed.
+    modifiers.constrainRatioAndAngle = (bool(constrainRatioAndAngleActive()) 
!= bool(e->modifiers() & Qt::ShiftModifier));
 
     const QPointF globalPosF = e->globalPosF();
     const QPointF localPosF = globalPosF - localOriginInGlobal;
@@ -1222,6 +1229,16 @@ void PageViewAnnotator::setContinuousMode(bool enabled)
     Okular::Settings::self()->save();
 }
 
+bool PageViewAnnotator::constrainRatioAndAngleActive()
+{
+    return m_constrainRatioAndAngle;
+}
+
+void PageViewAnnotator::setConstrainRatioAndAngle(bool enabled)
+{
+    m_constrainRatioAndAngle = enabled;
+}
+
 void PageViewAnnotator::setToolsEnabled(bool enabled)
 {
     if (m_actionHandler)
diff --git a/ui/pageviewannotator.h b/ui/pageviewannotator.h
index 7177d0f7d..3c1ebdda5 100644
--- a/ui/pageviewannotator.h
+++ b/ui/pageviewannotator.h
@@ -92,6 +92,11 @@ public:
     void setupActionsPostGUIActivated();
     // @return Is continuous mode active (pin annotation)?
     bool continuousMode();
+    /**
+     * State of constrain ratio and angle action.
+     * While annotating, this value is XOR-ed with the Shift modifier.
+     */
+    bool constrainRatioAndAngleActive();
     // enable/disable the annotation actions
     void setToolsEnabled(bool enabled);
     // enable/disable the text-selection annotation actions
@@ -120,6 +125,11 @@ public:
 
 public Q_SLOTS:
     void setContinuousMode(bool enabled);
+    /**
+     * State of constrain ratio and angle action.
+     * While annotating, this value is XOR-ed with the Shift modifier.
+     */
+    void setConstrainRatioAndAngle(bool enabled);
     void addToQuickAnnotations();
     void slotAdvancedSettings();
 
@@ -142,6 +152,7 @@ private:
     AnnotationTools *m_toolsDefinition;
     AnnotationTools *m_quickToolsDefinition;
     bool m_continuousMode;
+    bool m_constrainRatioAndAngle;
 
     // creation related variables
     int m_lastToolID;
diff --git a/ui/presentationwidget.cpp b/ui/presentationwidget.cpp
index 3f574031f..25ed5fdf2 100644
--- a/ui/presentationwidget.cpp
+++ b/ui/presentationwidget.cpp
@@ -1237,7 +1237,7 @@ QRect 
PresentationWidget::routeMouseDrawingEvent(QMouseEvent *e)
     AnnotatorEngine::Modifiers modifiers;
 
     // figure out the event type and button
-    AnnotatorEngine::decodeEvent(e, &eventType, &button, &modifiers);
+    AnnotatorEngine::decodeEvent(e, &eventType, &button);
 
     static bool hasclicked = false;
     if (eventType == AnnotatorEngine::Press)

Reply via email to