diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -41,6 +41,7 @@
Gui/SettingsDialog/GeneralOptionsPage.cpp
Gui/SettingsDialog/ShortcutsOptionsPage.cpp
QuickEditor/QuickEditor.cpp
+ QuickEditor/BottomHelpTextWidget.cpp
)
ecm_qt_declare_logging_category(SPECTACLE_SRCS_DEFAULT HEADER spectacle_core_debug.h IDENTIFIER SPECTACLE_CORE_LOG CATEGORY_NAME org.kde.spectacle.core)
diff --git a/src/QuickEditor/BottomHelpTextWidget.h b/src/QuickEditor/BottomHelpTextWidget.h
new file mode 100644
--- /dev/null
+++ b/src/QuickEditor/BottomHelpTextWidget.h
@@ -0,0 +1,54 @@
+/* This file is part of Spectacle, the KDE screenshot utility
+ * Copyright (C) 2019 Leon De Andrade leondeandrade@hotmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see .
+ */
+
+#ifndef BOTTOM_HELP_TEXT_H
+#define BOTTOM_HELP_TEXT_H
+
+#include
+#include
+#include
+#include
+#include
+
+using BottomHelpTextModel = QVector>>;
+
+class BottomHelpTextWidget : public QFrame
+{
+ Q_OBJECT
+
+public:
+ explicit BottomHelpTextWidget(bool isSelectionEmpty, QWidget* parent = nullptr);
+ ~BottomHelpTextWidget() = default;
+
+public Q_SLOTS:
+ void updateStyle();
+
+Q_SIGNALS:
+ void textModelChanged();
+
+private:
+ void createTextModel(bool isSelectionEmpty);
+ void createLayout();
+
+ constexpr static int marginX = 12;
+ constexpr static int marginY = 8;
+ constexpr static int spacingX = 6;
+
+ BottomHelpTextModel mTextModel = BottomHelpTextModel();
+ QGridLayout* mLayout = new QGridLayout();
+};
+#endif //BOTTOM_HELP_TEXT_H
diff --git a/src/QuickEditor/BottomHelpTextWidget.cpp b/src/QuickEditor/BottomHelpTextWidget.cpp
new file mode 100644
--- /dev/null
+++ b/src/QuickEditor/BottomHelpTextWidget.cpp
@@ -0,0 +1,156 @@
+/* This file is part of Spectacle, the KDE screenshot utility
+ * Copyright (C) 2019 Leon De Andrade leondeandrade@hotmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see .
+ */
+
+#include "BottomHelpTextWidget.h"
+
+#include
+#include
+
+#include
+
+#include "SpectacleConfig.h"
+
+BottomHelpTextWidget::BottomHelpTextWidget(bool isSelectionEmpty, QWidget* parent) :
+ QFrame(parent)
+{
+ setFrameStyle(QFrame::Panel);
+ setAutoFillBackground(true);
+
+ updateStyle();
+
+ connect(this, &BottomHelpTextWidget::textModelChanged, this, &BottomHelpTextWidget::createLayout);
+ connect(qGuiApp, &QGuiApplication::paletteChanged, this, &BottomHelpTextWidget::updateStyle);
+
+ createTextModel(isSelectionEmpty);
+}
+
+void BottomHelpTextWidget::updateStyle() {
+ QPalette palette = this->palette();
+ QColor backgroundColor = palette.color(QPalette::Light);
+ backgroundColor.setAlpha(216);
+ palette.setColor(QPalette::Window, backgroundColor);
+ setPalette(palette);
+}
+
+void BottomHelpTextWidget::createTextModel(bool isSelectionEmpty)
+{
+ SpectacleConfig* config = SpectacleConfig::instance();
+ if(config->useReleaseToCapture()) {
+ if((config->alwaysRememberRegion() || config->rememberLastRectangularRegion()) && !isSelectionEmpty) {
+ //Release to capture enabled and saved region available
+ mTextModel.append({
+ QString(i18nc("Mouse action", "Click and drag,")),
+ { QString(i18n(" ")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Keyboard/mouse action", "Enter, double-click:")),
+ { QString(i18n("Take screenshot")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Shift:")),
+ { QString(i18nc("Shift key action first half", "Hold to toggle magnifier")),
+ QString(i18nc("Shift key action second half", "while dragging selection handles")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Arrow keys:")),
+ { QString(i18nc("Shift key action first line", "Move selection rectangle")),
+ QString(i18nc("Shift key action second line", "Hold Alt to resize, Shift to fine‑tune")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Mouse action", "Right-click:")),
+ { QString(i18n("Reset selection")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Esc:")),
+ { QString(i18n("Cancel")) }
+ });
+ } else {
+ //Release to capture enabled and NO saved region available
+ mTextModel.append({
+ QString(i18nc("Keyboard/mouse action", "Release left-click, Enter:")),
+ { QString(i18n("Take Screenshot")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Shift:")),
+ { QString(i18nc("Shift key action first half", "Hold to toggle magnifier")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Mouse action", "Right-click:")),
+ { QString(i18n("Reset selection")) }
+ });
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Esc:")),
+ { QString(i18n("Cancel")) }
+ });
+ }
+ } else {
+ //Default text, Release to capture option disabled
+ mTextModel.append({
+ QString(i18nc("Keyboard/mouse action", "Enter, double-click:")),
+ { QString(i18n("Take screenshot")) }
+ });
+
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Shift:")),
+ { QString(i18nc("Shift key action first half", "Hold to toggle magnifier")),
+ QString(i18nc("Shift key action second half", "while dragging selection handles")) }
+ });
+
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Arrow keys:")),
+ { QString(i18nc("Shift key action first line", "Move selection rectangle")),
+ QString(i18nc("Shift key action second line", "Hold Alt to resize, Shift to fine‑tune")) }
+ });
+
+ mTextModel.append({
+ QString(i18nc("Mouse action", "Right-click:")),
+ { QString(i18n("Reset selection")) }
+ });
+
+ mTextModel.append({
+ QString(i18nc("Keyboard action", "Esc:")),
+ { QString(i18n("Cancel")) }
+ });
+ }
+ emit textModelChanged();
+}
+
+void BottomHelpTextWidget::createLayout()
+{
+ mLayout->setHorizontalSpacing(spacingX);
+ mLayout->setVerticalSpacing(0);
+ mLayout->setContentsMargins(marginX, marginY, marginX, marginY);
+
+ //Create QLabels from the textModel and layout them in a Grid, j counts number of columns in the grid
+ for(int i = 0, j = 0; i < mTextModel.size(); ++i, ++j) {
+ const auto& helpTextRow = mTextModel[i];
+ const QString& leftHelpText = helpTextRow.first;
+ const QVector& rightHelpTexts = helpTextRow.second;
+
+ mLayout->addWidget(new QLabel(leftHelpText), j, 0, Qt::AlignRight);
+
+ for(const auto& rightHelpText: rightHelpTexts) {
+ mLayout->addWidget(new QLabel(rightHelpText), j, 2);
+ ++j;
+ }
+ //Add some vertical spacing only between the helpTextRows
+ if(i != mTextModel.size() - 1) {
+ mLayout->addItem(new QSpacerItem(0, 5), j, 0, 1, 3);
+ }
+ }
+ this->setLayout(mLayout);
+}
diff --git a/src/QuickEditor/QuickEditor.h b/src/QuickEditor/QuickEditor.h
--- a/src/QuickEditor/QuickEditor.h
+++ b/src/QuickEditor/QuickEditor.h
@@ -25,17 +25,19 @@
#include
#include
#include
-#include
+
+#include "BottomHelpTextWidget.h"
class QMouseEvent;
+class QScreen;
class QuickEditor: public QWidget
{
Q_OBJECT
public:
- explicit QuickEditor(const QPixmap &thePixmap, QWidget *parent = nullptr);
+ explicit QuickEditor(const QPixmap &thePixmap, const QScreen *activeScreen, QWidget *parent = nullptr);
virtual ~QuickEditor() = default;
private:
@@ -70,13 +72,10 @@
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
void paintEvent(QPaintEvent*) override;
- void drawBottomHelpText(QPainter& painter);
void drawDragHandles(QPainter& painter);
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);
@@ -89,12 +88,6 @@
static const int selectionBoxPaddingY;
static const int selectionBoxMarginY;
- static const int bottomHelpMaxLength = 6;
- static bool bottomHelpTextPrepared;
- static const int bottomHelpBoxPaddingX;
- static const int bottomHelpBoxPaddingY;
- static const int bottomHelpBoxPairSpacing;
- static const int bottomHelpBoxMarginBottom;
static const int midHelpTextFontSize;
static const int magnifierLargeStep;
@@ -113,11 +106,6 @@
QPointF mInitialTopLeft;
QString mMidHelpText;
QFont mMidHelpTextFont;
- std::pair> mBottomHelpText[bottomHelpMaxLength];
- QFont mBottomHelpTextFont;
- QRect mBottomHelpBorderBox;
- QPoint mBottomHelpContentPos;
- int mBottomHelpGridLeftWidth;
MouseState mMouseDragState;
QPixmap mPixmap;
qreal dprI;
@@ -128,8 +116,8 @@
bool mReleaseToCapture;
bool mRememberRegion;
bool mDisableArrowKeys;
- QRect mPrimaryScreenGeo;
- int mbottomHelpLength;
+
+ BottomHelpTextWidget* mBottomHelpText;
Q_SIGNALS:
diff --git a/src/QuickEditor/QuickEditor.cpp b/src/QuickEditor/QuickEditor.cpp
--- a/src/QuickEditor/QuickEditor.cpp
+++ b/src/QuickEditor/QuickEditor.cpp
@@ -33,20 +33,15 @@
const int QuickEditor::selectionBoxPaddingY = 4;
const int QuickEditor::selectionBoxMarginY = 2;
-bool QuickEditor::bottomHelpTextPrepared = false;
-const int QuickEditor::bottomHelpBoxPaddingX = 12;
-const int QuickEditor::bottomHelpBoxPaddingY = 8;
-const int QuickEditor::bottomHelpBoxPairSpacing = 6;
-const int QuickEditor::bottomHelpBoxMarginBottom = 5;
const int QuickEditor::midHelpTextFontSize = 12;
const int QuickEditor::magnifierLargeStep = 15;
const int QuickEditor::magZoom = 5;
const int QuickEditor::magPixels = 16;
const int QuickEditor::magOffset = 32;
-QuickEditor::QuickEditor(const QPixmap& thePixmap, QWidget *parent) :
+QuickEditor::QuickEditor(const QPixmap& thePixmap, const QScreen *activeScreen, QWidget *parent) :
QWidget(parent),
mMaskColor(QColor::fromRgbF(0, 0, 0, 0.15)),
mStrokeColor(palette().highlight().color()),
@@ -58,20 +53,16 @@
0.85
)),
mLabelForegroundColor(palette().windowText().color()),
+ mSelection(static_cast(QRect(activeScreen->geometry().topLeft(), QSize(0,0)))),
mMidHelpText(i18n("Click and drag to draw a selection rectangle,\nor press Esc to quit")),
mMidHelpTextFont(font()),
- mBottomHelpTextFont(font()),
- mBottomHelpGridLeftWidth(0),
mMouseDragState(MouseState::None),
mPixmap(thePixmap),
mMagnifierAllowed(false),
mShowMagnifier(SpectacleConfig::instance()->showMagnifierChecked()),
mToggleMagnifier(false),
- mReleaseToCapture(SpectacleConfig::instance()->useReleaseToCapture()),
mRememberRegion(SpectacleConfig::instance()->alwaysRememberRegion() || SpectacleConfig::instance()->rememberLastRectangularRegion()),
- mDisableArrowKeys(false),
- mPrimaryScreenGeo(QGuiApplication::primaryScreen()->geometry()),
- mbottomHelpLength(bottomHelpMaxLength)
+ mDisableArrowKeys(false)
{
SpectacleConfig *config = SpectacleConfig::instance();
if (config->useLightRegionMaskColour()) {
@@ -99,24 +90,8 @@
} else {
setCursor(Qt::CrossCursor);
}
-
- setBottomHelpText();
+ mBottomHelpText = new BottomHelpTextWidget(mSelection.size().isEmpty(), this);
mMidHelpTextFont.setPointSize(midHelpTextFontSize);
- if (!bottomHelpTextPrepared) {
- bottomHelpTextPrepared = true;
- const auto prepare = [this](QStaticText& item) {
- item.prepare(QTransform(), mBottomHelpTextFont);
- item.setPerformanceHint(QStaticText::AggressiveCaching);
- };
- for (auto& pair : mBottomHelpText) {
- prepare(pair.first);
- for (auto &item : pair.second) {
- prepare(item);
- }
- }
- }
- layoutBottomHelpText();
-
update();
}
@@ -288,7 +263,7 @@
void QuickEditor::mousePressEvent(QMouseEvent* event)
{
if (event->button() & Qt::LeftButton) {
- /* NOTE Workaround for Bug 407843
+ /* NOTE Workaround for Bug 407843
* If we show the selection Widget when a right click menu is open we lose focus on X.
* When the user clicks we get the mouse back. We can only grab the keyboard if we already
* have mouse focus. So just grab it undconditionally here.
@@ -436,7 +411,7 @@
if(mMouseDragState == MouseState::Inside) {
setCursor(Qt::OpenHandCursor);
}
- else if(mMouseDragState == MouseState::Outside && mReleaseToCapture) {
+ else if(mMouseDragState == MouseState::Outside && SpectacleConfig::instance()->useReleaseToCapture()) {
event->accept();
mMouseDragState = MouseState::None;
return acceptSelection();
@@ -490,120 +465,18 @@
} else if (mMagnifierAllowed && (mShowMagnifier ^ mToggleMagnifier)) {
drawMagnifier(painter);
}
- drawBottomHelpText(painter);
- } else {
- drawMidHelpText(painter);
- }
-}
-
-void QuickEditor::layoutBottomHelpText()
-{
- int maxRightWidth = 0;
- int contentWidth = 0;
- int contentHeight = 0;
- mBottomHelpGridLeftWidth = 0;
- 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();
- mBottomHelpGridLeftWidth = qMax(mBottomHelpGridLeftWidth, leftSize.width());
- for (const auto& item : right) {
- const auto rightItemSize = item.size().toSize();
- maxRightWidth = qMax(maxRightWidth, rightItemSize.width());
- contentHeight += rightItemSize.height();
- }
- contentWidth = qMax(contentWidth, mBottomHelpGridLeftWidth + maxRightWidth + bottomHelpBoxPairSpacing);
- contentHeight += (i != bottomHelpMaxLength ? bottomHelpBoxMarginBottom : 0);
- }
- mBottomHelpContentPos.setX((mPrimaryScreenGeo.width() - contentWidth) / 2 + mPrimaryScreenGeo.x());
- mBottomHelpContentPos.setY(height() - contentHeight - 8);
- mBottomHelpGridLeftWidth += mBottomHelpContentPos.x();
- mBottomHelpBorderBox.setRect(
- mBottomHelpContentPos.x() - bottomHelpBoxPaddingX,
- mBottomHelpContentPos.y() - bottomHelpBoxPaddingY,
- contentWidth + bottomHelpBoxPaddingX * 2,
- contentHeight + bottomHelpBoxPaddingY * 2 - 1
- );
-}
-
-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"))}};
-
+ QRect activeScreenGeo = QGuiApplication::screenAt(mSelection.center().toPoint())->geometry();
+ mBottomHelpText->move((activeScreenGeo.width() - mBottomHelpText->width())/2 + activeScreenGeo.x(),
+ height() - mBottomHelpText->height());
+ //Only draw bottom help text, if possible (no selection rectangle in that area)
+ if(!mSelection.intersects(mBottomHelpText->geometry())) {
+ mBottomHelpText->setVisible(true);
} 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)) {
- return;
- }
-
- painter.setBrush(mLabelBackgroundColor);
- painter.setPen(mLabelForegroundColor);
- painter.setFont(mBottomHelpTextFont);
- painter.setRenderHint(QPainter::Antialiasing, false);
- painter.drawRect(mBottomHelpBorderBox);
- painter.setRenderHint(QPainter::Antialiasing, true);
-
- int topOffset = mBottomHelpContentPos.y();
- 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();
- painter.drawStaticText(mBottomHelpGridLeftWidth - leftSize.width(), topOffset, left);
- for (const auto& item : right) {
- const auto rightItemSize = item.size().toSize();
- painter.drawStaticText(mBottomHelpGridLeftWidth + bottomHelpBoxPairSpacing, topOffset, item);
- topOffset += rightItemSize.height();
- }
- if (i != bottomHelpMaxLength) {
- topOffset += bottomHelpBoxMarginBottom;
+ mBottomHelpText->setVisible(false);
}
+ } else {
+ mBottomHelpText->setVisible(false);
+ drawMidHelpText(painter);
}
}
@@ -727,7 +600,8 @@
painter.fillRect(geometry(), mMaskColor);
painter.setFont(mMidHelpTextFont);
QRect textSize = painter.boundingRect(QRect(), Qt::AlignCenter, mMidHelpText);
- QPoint pos((mPrimaryScreenGeo.width() - textSize.width()) / 2 + mPrimaryScreenGeo.x(), (height() - textSize.height()) / 2);
+ QRect activeScreenGeo = QGuiApplication::screenAt(mSelection.center().toPoint())->geometry();
+ QPoint pos((activeScreenGeo.width() - textSize.width()) / 2 + activeScreenGeo.x(), (height() - textSize.height()) / 2);
painter.setBrush(mLabelBackgroundColor);
QPen pen(mLabelForegroundColor);
diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp
--- a/src/SpectacleCore.cpp
+++ b/src/SpectacleCore.cpp
@@ -37,6 +37,7 @@
#include
#include
#include
+#include
SpectacleCore::SpectacleCore(StartMode theStartMode,
Spectacle::CaptureMode theCaptureMode,
@@ -223,7 +224,7 @@
if (lExportManager->captureMode() == Spectacle::CaptureMode::RectangularRegion) {
if(!mQuickEditor) {
- mQuickEditor = std::make_unique(thePixmap);
+ mQuickEditor = std::make_unique(thePixmap, mMainWindow->window()->windowHandle()->screen());
connect(mQuickEditor.get(), &QuickEditor::grabDone, this, &SpectacleCore::screenshotUpdated);
connect(mQuickEditor.get(), &QuickEditor::grabCancelled, this, &SpectacleCore::screenshotFailed);
mQuickEditor->showFullScreen();