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.) - The contents of the annotating toolbar can be configured using the Annotations page of &okular; configuration dialog. This page can be opened with &RMB; clicking on the annotating toolbar then choosing Configure Annotations... from the context menu. - - - 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 Esc key or click the tool button again to leave the permanent mode. + By pressing Shift 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 Configure Toolbars.... + + + The contents of the Quick Annotations menu can be configured using the Annotations page of &okular; configuration dialog. This page can be opened by clicking Quick Annotations button, then choosing Configure Annotations... from the pop-up menu. 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)