[graphics/okular/release/20.08] /: Add Constrain Angle action for annotation tools, alternative to pressing Shift

David Hurka null at kde.org
Thu Jul 16 23:32:44 BST 2020


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 ⪚ 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 (⪚ 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)


More information about the kde-doc-english mailing list