Commit 958fdc0a authored by Ambareesh  Balaji's avatar Ambareesh Balaji Committed by Nate Graham

Port QML Rectangle cropper to QWidget + QPainter

1. Port QML canvas based screenshot cropper to QWidget + QPainter based cropper
2. Fix minor bugs with cropper while porting, like system font not being set for size indicator
3. "Include mouse pointer" setting now blends the cursor into the screenshot right away, letting the user see it while cropping, rather than blending it in after cropping


BUG: 394503
BUG: 374009

Test Plan: Compare with original cropper and check if I missed something

Reviewers: #spectacle, broulik, ngraham, alexeymin

Reviewed By: #spectacle, broulik, ngraham, alexeymin

Subscribers: alexeymin, kpiwowarski, broulik, sharvey, guotao, ngraham, rkflx, #spectacle

Tags: #spectacle

Differential Revision:
parent e5a22132
......@@ -25,7 +25,6 @@ set(
ecm_qt_declare_logging_category(SPECTACLE_SRCS_DEFAULT HEADER spectacle_core_debug.h IDENTIFIER SPECTACLE_CORE_LOG CATEGORY_NAME org.kde.spectacle.core)
......@@ -299,15 +299,15 @@ void KSMainWindow::showPrintDialog()
void KSMainWindow::openScreenshotsFolder()
// Highlight last screenshot in file manager if user saved at least once ever
// (since last save and saveas file names are stored in spectaclerc), otherwise,
// Highlight last screenshot in file manager if user saved at least once ever
// (since last save and saveas file names are stored in spectaclerc), otherwise,
// if in save mode, open default save location from configure > save > location
// if in save as mode, open last save as files location
// failsafe for either option is default save location from configure > save > location
SpectacleConfig *cfgManager = SpectacleConfig::instance();
ExportManager *exportManager = ExportManager::instance();
QUrl location;
switch(cfgManager->lastUsedSaveMode()) {
case SaveMode::Save:
location = cfgManager->lastSaveFile();
......@@ -416,17 +416,13 @@ void X11ImageGrabber::rectangleSelectionCancelled()
emit imageGrabFailed();
void X11ImageGrabber::rectangleSelectionConfirmed(const QPixmap &pixmap, const QRect &region)
void X11ImageGrabber::rectangleSelectionConfirmed(const QPixmap &pixmap)
QObject *sender = QObject::sender();
if (mCapturePointer) {
mPixmap = blendCursorImage(pixmap, region.x(), region.y(), region.width(), region.height());
} else {
mPixmap = pixmap;
mPixmap = pixmap;
emit pixmapChanged(mPixmap);
......@@ -664,7 +660,7 @@ void X11ImageGrabber::grabCurrentScreen()
void X11ImageGrabber::grabRectangularRegion()
const auto pixmap = getToplevelPixmap(QRect(), false);
const auto pixmap = getToplevelPixmap(QRect(), mCapturePointer);
if (!pixmap.isNull()) {
QuickEditor *editor = new QuickEditor(pixmap);
......@@ -66,7 +66,7 @@ class X11ImageGrabber : public ImageGrabber
private Q_SLOTS:
void KWinDBusScreenshotHelper(quint64 window);
void rectangleSelectionConfirmed(const QPixmap &pixmap, const QRect &region);
void rectangleSelectionConfirmed(const QPixmap &pixmap);
void rectangleSelectionCancelled();
public Q_SLOTS:
This diff is collapsed.
<qresource prefix="/QuickEditor">
This diff is collapsed.
* Copyright (C) 2016 Boudhayan Gupta <>
* Copyright (C) 2018 Ambareesh "Amby" Balaji <>
* 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
......@@ -20,34 +21,111 @@
#include <QObject>
#include <QKeyEvent>
#include <QPainter>
#include <QStaticText>
#include <QWidget>
#include <utility>
#include <vector>
class QuickEditor : public QObject
class QMouseEvent;
class QuickEditor : public QWidget
explicit QuickEditor(const QPixmap &pixmap);
explicit QuickEditor(const QPixmap &pixmap, QObject *parent = nullptr);
virtual ~QuickEditor();
enum MouseState : short {
None = 0, // 0000
Inside = 1 << 0, // 0001
Outside = 1 << 1, // 0010
TopLeft = 5, //101
Top = 17, // 10001
TopRight = 9, // 1001
Right = 33, // 100001
BottomRight = 6, // 110
Bottom = 18, // 10010
BottomLeft = 10, // 1010
Left = 34, // 100010
TopLeftOrBottomRight = TopLeft & BottomRight, // 100
TopRightOrBottomLeft = TopRight & BottomLeft, // 1000
TopOrBottom = Top & Bottom, // 10000
RightOrLeft = Right & Left, // 100000
void acceptSelection();
int boundsLeft(int newTopLeftX, const bool mouse = true);
int boundsRight(int newTopLeftX, const bool mouse = true);
int boundsUp(int newTopLeftY, const bool mouse = true);
int boundsDown(int newTopLeftY, const bool mouse = true);
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
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 layoutBottomHelpText();
void setMouseCursor(const QPointF& pos);
MouseState mouseLocation(const QPointF& pos);
void grabDone(const QPixmap &pixmap, const QRect &cropRegion);
void grabCancelled();
static const qreal mouseAreaSize;
static const qreal cornerHandleRadius;
static const qreal midHandleRadius;
static const int selectionSizeThreshold;
private Q_SLOTS:
static const int selectionBoxPaddingX;
static const int selectionBoxPaddingY;
static const int selectionBoxMarginY;
void acceptImageHandler(int x, int y, int width, int height);
static const int bottomHelpLength = 5;
static std::pair<QStaticText, std::vector<QStaticText>> bottomHelpText[bottomHelpLength];
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;
struct ImageStore;
ImageStore *mImageStore;
static const int magZoom;
static const int magPixels;
static const int magOffset;
class QuickEditorPrivate;
QuickEditorPrivate *d_ptr;
QColor mMaskColor;
QColor mStrokeColor;
QColor mCrossColor;
QColor mLabelBackgroundColor;
QColor mLabelForegroundColor;
QRectF mSelection;
QPointF mStartPos;
QPointF mInitialTopLeft;
QString mMidHelpText;
QFont mMidHelpTextFont;
QFont mBottomHelpTextFont;
QRect mBottomHelpBorderBox;
QPoint mBottomHelpContentPos;
int mBottomHelpGridLeftWidth;
MouseState mMouseDragState;
QPixmap mPixmap;
qreal dprI;
QPointF mMousePos;
bool mMagnifierAllowed;
bool mShowMagnifier;
bool mToggleMagnifier;
void grabDone(const QPixmap &pixmap);
void grabCancelled();
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment