diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.h b/src/Gui/SettingsDialog/GeneralOptionsPage.h --- a/src/Gui/SettingsDialog/GeneralOptionsPage.h +++ b/src/Gui/SettingsDialog/GeneralOptionsPage.h @@ -50,6 +50,7 @@ QRadioButton* mRememberUntilClosed; QCheckBox *mUseLightBackground; QCheckBox *mShowMagnifier; + QCheckBox *mReleaseToCapture; }; #endif // GENERALOPTIONSPAGE_H diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp --- a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +++ b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp @@ -73,6 +73,11 @@ connect(mShowMagnifier, &QCheckBox::toggled, this, &GeneralOptionsPage::markDirty); mainLayout->addRow(QString(), mShowMagnifier); + // release mouse-button to capture + mReleaseToCapture = new QCheckBox(i18n("Accept on click-and-release"), this); + connect(mReleaseToCapture, &QCheckBox::toggled, this, &GeneralOptionsPage::markDirty); + mainLayout->addRow(QString(), mReleaseToCapture); + mainLayout->addItem(new QSpacerItem(0, 18, QSizePolicy::Fixed, QSizePolicy::Fixed)); // remember Rectangular Region box @@ -107,6 +112,7 @@ cfgManager->setRememberLastRectangularRegion(mRememberUntilClosed->isChecked() || mRememberAlways->isChecked()); cfgManager->setAlwaysRememberRegion (mRememberAlways->isChecked()); cfgManager->setShowMagnifierChecked(mShowMagnifier->checkState() == Qt::Checked); + cfgManager->setUseReleaseToCaptureChecked(mReleaseToCapture->checkState() == Qt::Checked); cfgManager->setPrintKeyActionRunning(static_cast(mPrintKeyActionGroup->checkedId())); mChangesMade = false; @@ -120,6 +126,7 @@ mRememberUntilClosed->setChecked(cfgManager->rememberLastRectangularRegion()); mRememberAlways->setChecked(cfgManager->alwaysRememberRegion()); mShowMagnifier->setChecked(cfgManager->showMagnifierChecked()); + mReleaseToCapture->setChecked(cfgManager->useReleaseToCapture()); mPrintKeyActionGroup->button(cfgManager->printKeyActionRunning())->setChecked(true); mChangesMade = false; diff --git a/src/QuickEditor/QuickEditor.h b/src/QuickEditor/QuickEditor.h --- a/src/QuickEditor/QuickEditor.h +++ b/src/QuickEditor/QuickEditor.h @@ -75,6 +75,7 @@ void drawMagnifier(QPainter& painter); void drawMidHelpText(QPainter& painter); void drawSelectionSizeTooltip(QPainter& painter); + void setBottomHelpText(); void layoutBottomHelpText(); void setMouseCursor(const QPointF& pos); MouseState mouseLocation(const QPointF& pos); @@ -88,7 +89,7 @@ static const int selectionBoxPaddingY; static const int selectionBoxMarginY; - static const int bottomHelpLength = 5; + static const int bottomHelpMaxLength = 6; static bool bottomHelpTextPrepared; static const int bottomHelpBoxPaddingX; static const int bottomHelpBoxPaddingY; @@ -112,7 +113,7 @@ QPointF mInitialTopLeft; QString mMidHelpText; QFont mMidHelpTextFont; - std::pair> mBottomHelpText[bottomHelpLength]; + std::pair> mBottomHelpText[bottomHelpMaxLength]; QFont mBottomHelpTextFont; QRect mBottomHelpBorderBox; QPoint mBottomHelpContentPos; @@ -124,7 +125,11 @@ bool mMagnifierAllowed; bool mShowMagnifier; bool mToggleMagnifier; + bool mReleaseToCapture; + bool mRememberRegion; + bool mDisableArrowKeys; QRect mPrimaryScreenGeo; + int mbottomHelpLength; Q_SIGNALS: void grabDone(const QPixmap &pixmap); diff --git a/src/QuickEditor/QuickEditor.cpp b/src/QuickEditor/QuickEditor.cpp --- a/src/QuickEditor/QuickEditor.cpp +++ b/src/QuickEditor/QuickEditor.cpp @@ -58,27 +58,18 @@ mLabelForegroundColor(palette().windowText().color()), mMidHelpText(i18n("Click and drag to draw a selection rectangle,\nor press Esc to quit")), mMidHelpTextFont(font()), - mBottomHelpText{ - {QStaticText(i18nc("Keyboard/mouse action", "Enter, double-click:")), {QStaticText(i18n("Take screenshot"))}}, - {QStaticText(i18nc("Keyboard action", "Shift:")), { - QStaticText(i18nc("Shift key action first half", "Hold to toggle magnifier")), - QStaticText(i18nc("Shift key action second half", "while dragging selection handles")) - }}, - {QStaticText(i18nc("Keyboard action", "Arrow keys:")), { - QStaticText(i18nc("Shift key action first line", "Move selection rectangle")), - QStaticText(i18nc("Shift key action second line", "Hold Alt to resize, Shift to fine‑tune")) - }}, - {QStaticText(i18nc("Mouse action", "Right-click:")), {QStaticText(i18n("Reset selection"))}}, - {QStaticText(i18nc("Keyboard action", "Esc:")), {QStaticText(i18n("Cancel"))}}, - }, mBottomHelpTextFont(font()), mBottomHelpGridLeftWidth(0), mMouseDragState(MouseState::None), mPixmap(pixmap), mMagnifierAllowed(false), mShowMagnifier(SpectacleConfig::instance()->showMagnifierChecked()), mToggleMagnifier(false), - mPrimaryScreenGeo(QGuiApplication::primaryScreen()->geometry()) + mReleaseToCapture(SpectacleConfig::instance()->useReleaseToCapture()), + mRememberRegion(SpectacleConfig::instance()->alwaysRememberRegion() || SpectacleConfig::instance()->rememberLastRectangularRegion()), + mDisableArrowKeys(false), + mPrimaryScreenGeo(QGuiApplication::primaryScreen()->geometry()), + mbottomHelpLength(bottomHelpMaxLength) { SpectacleConfig *config = SpectacleConfig::instance(); if (config->useLightRegionMaskColour()) { @@ -108,6 +99,7 @@ setCursor(Qt::CrossCursor); } + setBottomHelpText(); mMidHelpTextFont.setPointSize(midHelpTextFontSize); if (!bottomHelpTextPrepared) { bottomHelpTextPrepared = true; @@ -158,6 +150,10 @@ acceptSelection(); break; case Qt::Key_Up: { + if(mDisableArrowKeys) { + update(); + break; + } const qreal step = (shiftPressed ? 1 : magnifierLargeStep); const int newPos = boundsUp(qRound(mSelection.top() * devicePixelRatioF() - step), false); if (modifiers & Qt::AltModifier) { @@ -170,6 +166,10 @@ break; } case Qt::Key_Right: { + if(mDisableArrowKeys) { + update(); + break; + } const qreal step = (shiftPressed ? 1 : magnifierLargeStep); const int newPos = boundsRight(qRound(mSelection.left() * devicePixelRatioF() + step), false); if (modifiers & Qt::AltModifier) { @@ -181,6 +181,10 @@ break; } case Qt::Key_Down: { + if(mDisableArrowKeys) { + update(); + break; + } const qreal step = (shiftPressed ? 1 : magnifierLargeStep); const int newPos = boundsDown(qRound(mSelection.top() * devicePixelRatioF() + step), false); if (modifiers & Qt::AltModifier) { @@ -192,6 +196,10 @@ break; } case Qt::Key_Left: { + if(mDisableArrowKeys) { + update(); + break; + } const qreal step = (shiftPressed ? 1 : magnifierLargeStep); const int newPos = boundsLeft(qRound(mSelection.left() * devicePixelRatioF() - step), false); if (modifiers & Qt::AltModifier) { @@ -283,6 +291,7 @@ mMousePos = pos; mMagnifierAllowed = true; mMouseDragState = mouseLocation(pos); + mDisableArrowKeys = true; switch(mMouseDragState) { case MouseState::Outside: mStartPos = pos; @@ -415,8 +424,14 @@ void QuickEditor::mouseReleaseEvent(QMouseEvent* event) { const auto button = event->button(); - if (button == Qt::LeftButton && mMouseDragState == MouseState::Inside) { - setCursor(Qt::OpenHandCursor); + if (button == Qt::LeftButton) { + mDisableArrowKeys = false; + if(mMouseDragState == MouseState::Inside) { + setCursor(Qt::OpenHandCursor); + } + else if(mMouseDragState == MouseState::Outside && mReleaseToCapture) { + acceptSelection(); + } } else if (button == Qt::RightButton) { mSelection.setWidth(0); mSelection.setHeight(0); @@ -478,8 +493,8 @@ int contentWidth = 0; int contentHeight = 0; mBottomHelpGridLeftWidth = 0; - int i = 0; - for (const auto& item : mBottomHelpText) { + for (int i = 0; i < mbottomHelpLength; i++) { + const auto& item = mBottomHelpText[i]; const auto& left = item.first; const auto& right = item.second; const auto leftSize = left.size().toSize(); @@ -490,7 +505,7 @@ contentHeight += rightItemSize.height(); } contentWidth = qMax(contentWidth, mBottomHelpGridLeftWidth + maxRightWidth + bottomHelpBoxPairSpacing); - contentHeight += (++i != bottomHelpLength ? bottomHelpBoxMarginBottom : 0); + contentHeight += (i != bottomHelpMaxLength ? bottomHelpBoxMarginBottom : 0); } mBottomHelpContentPos.setX((mPrimaryScreenGeo.width() - contentWidth) / 2 + mPrimaryScreenGeo.x()); mBottomHelpContentPos.setY(height() - contentHeight - 8); @@ -503,6 +518,55 @@ ); } +void QuickEditor::setBottomHelpText() { + if (mReleaseToCapture) { + if(mRememberRegion && !mSelection.size().isEmpty()) { + //Release to capture enabled and saved region available + mBottomHelpText[0] = {QStaticText(i18nc("Mouse action", "Click and drag,")),{QStaticText(i18n(" "))}}; + mBottomHelpText[1] = {QStaticText(i18nc("Keyboard/mouse action", "Enter, double-click:")), + {QStaticText(i18n("Take screenshot"))}}; + mBottomHelpText[2] = {QStaticText(i18nc("Keyboard action", "Shift:")), { + QStaticText(i18nc("Shift key action first half", "Hold to toggle magnifier")), + QStaticText(i18nc("Shift key action second half", "while dragging selection handles")) + }}; + mBottomHelpText[3] = {QStaticText(i18nc("Keyboard action", "Arrow keys:")), { + QStaticText(i18nc("Shift key action first line", "Move selection rectangle")), + QStaticText(i18nc("Shift key action second line", "Hold Alt to resize, Shift to fine‑tune")) + }}; + mBottomHelpText[4] = {QStaticText(i18nc("Mouse action", "Right-click:")), + {QStaticText(i18n("Reset selection"))}}; + mBottomHelpText[5] = {QStaticText(i18nc("Keyboard action", "Esc:")), {QStaticText(i18n("Cancel"))}}; + + } else { + //Release to capture enabled and NO saved region available + mbottomHelpLength = 4; + mBottomHelpText[0] = {QStaticText(i18nc("Keyboard/mouse action", "Release left-click, Enter:")), + {QStaticText(i18n("Take Screenshot"))}}; + mBottomHelpText[1] = {QStaticText(i18nc("Keyboard action", "Shift:")), { + QStaticText(i18nc("Shift key action first half", "Hold to toggle magnifier"))}}; + mBottomHelpText[2] = {QStaticText(i18nc("Mouse action", "Right-click:")), + {QStaticText(i18n("Reset selection"))}}; + mBottomHelpText[3] = {QStaticText(i18nc("Keyboard action", "Esc:")), {QStaticText(i18n("Cancel"))}}; + } + }else { + //Default text, Release to capture option disabled + mbottomHelpLength = 5; + mBottomHelpText[0] = {QStaticText(i18nc("Keyboard/mouse action", "Enter, double-click:")), + {QStaticText(i18n("Take screenshot"))}}; + mBottomHelpText[1] = {QStaticText(i18nc("Keyboard action", "Shift:")), { + QStaticText(i18nc("Shift key action first half", "Hold to toggle magnifier")), + QStaticText(i18nc("Shift key action second half", "while dragging selection handles")) + }}; + mBottomHelpText[2] = {QStaticText(i18nc("Keyboard action", "Arrow keys:")), { + QStaticText(i18nc("Shift key action first line", "Move selection rectangle")), + QStaticText(i18nc("Shift key action second line", "Hold Alt to resize, Shift to fine‑tune")) + }}; + mBottomHelpText[3] = {QStaticText(i18nc("Mouse action", "Right-click:")), + {QStaticText(i18n("Reset selection"))}}; + mBottomHelpText[4] = {QStaticText(i18nc("Keyboard action", "Esc:")), {QStaticText(i18n("Cancel"))}}; + } +} + void QuickEditor::drawBottomHelpText(QPainter &painter) { if (mSelection.intersects(mBottomHelpBorderBox)) { @@ -517,8 +581,8 @@ painter.setRenderHint(QPainter::Antialiasing, true); int topOffset = mBottomHelpContentPos.y(); - int i = 0; - for (const auto& item : mBottomHelpText) { + for (int i = 0; i < mbottomHelpLength; i++) { + const auto& item = mBottomHelpText[i]; const auto& left = item.first; const auto& right = item.second; const auto leftSize = left.size().toSize(); @@ -528,7 +592,7 @@ painter.drawStaticText(mBottomHelpGridLeftWidth + bottomHelpBoxPairSpacing, topOffset, item); topOffset += rightItemSize.height(); } - if (++i != bottomHelpLength) { + if (i != bottomHelpMaxLength) { topOffset += bottomHelpBoxMarginBottom; } } diff --git a/src/SpectacleConfig.h b/src/SpectacleConfig.h --- a/src/SpectacleConfig.h +++ b/src/SpectacleConfig.h @@ -93,6 +93,9 @@ bool showMagnifierChecked() const; void setShowMagnifierChecked(bool enabled); + bool useReleaseToCapture() const; + void setUseReleaseToCaptureChecked(bool enabled); + qreal captureDelay() const; void setCaptureDelay(qreal delay); diff --git a/src/SpectacleConfig.cpp b/src/SpectacleConfig.cpp --- a/src/SpectacleConfig.cpp +++ b/src/SpectacleConfig.cpp @@ -178,6 +178,19 @@ mGuiConfig.sync(); } +// release mouse-button to capture + +bool SpectacleConfig::useReleaseToCapture() const +{ + return mGuiConfig.readEntry(QStringLiteral("useReleaseToCapture"), false); +} + +void SpectacleConfig::setUseReleaseToCaptureChecked(bool enabled) +{ + mGuiConfig.writeEntry(QStringLiteral("useReleaseToCapture"), enabled); + mGuiConfig.sync(); +} + // capture delay qreal SpectacleConfig::captureDelay() const