1 /*
2  *  SPDX-FileCopyrightText: 2018 Ambareesh "Amby" Balaji <ambareeshbalaji@gmail.com>
3  *
4  *  SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 #ifndef QUICKEDITOR_H
8 #define QUICKEDITOR_H
9 
10 #include <QMap>
11 #include <QStaticText>
12 #include <QWidget>
13 
14 class ComparableQPoint;
15 class QKeyEvent;
16 class QMouseEvent;
17 class QPainter;
18 
19 namespace KWayland::Client
20 {
21 class PlasmaShell;
22 }
23 
24 class QuickEditor : public QWidget
25 {
26     Q_OBJECT
27 
28 public:
29     QuickEditor(const QMap<const QScreen *, QImage> &images, KWayland::Client::PlasmaShell *plasmashell, QWidget *parent = nullptr);
30 
31 Q_SIGNALS:
32     void grabDone(const QPixmap &thePixmap);
33     void grabCancelled();
34 
35 private:
36     enum MouseState : short {
37         None = 0, // 0000
38         Inside = 1 << 0, // 0001
39         Outside = 1 << 1, // 0010
40         TopLeft = 5, // 101
41         Top = 17, // 10001
42         TopRight = 9, // 1001
43         Right = 33, // 100001
44         BottomRight = 6, // 110
45         Bottom = 18, // 10010
46         BottomLeft = 10, // 1010
47         Left = 34, // 100010
48         TopLeftOrBottomRight = TopLeft & BottomRight, // 100
49         TopRightOrBottomLeft = TopRight & BottomLeft, // 1000
50         TopOrBottom = Top & Bottom, // 10000
51         RightOrLeft = Right & Left, // 100000
52     };
53 
54     void acceptSelection();
55     int boundsLeft(int newTopLeftX, const bool mouse = true);
56     int boundsRight(int newTopLeftX, const bool mouse = true);
57     int boundsUp(int newTopLeftY, const bool mouse = true);
58     int boundsDown(int newTopLeftY, const bool mouse = true);
59     void keyPressEvent(QKeyEvent *event) override;
60     void keyReleaseEvent(QKeyEvent *event) override;
61     void mousePressEvent(QMouseEvent *event) override;
62     void mouseMoveEvent(QMouseEvent *event) override;
63     void mouseReleaseEvent(QMouseEvent *event) override;
64     void mouseDoubleClickEvent(QMouseEvent *event) override;
65     void paintEvent(QPaintEvent *) override;
66     void drawBottomHelpText(QPainter &painter);
67     void drawDragHandles(QPainter &painter);
68     void drawMagnifier(QPainter &painter);
69     void drawMidHelpText(QPainter &painter);
70     void preparePaint();
71     void createPixmapFromScreens();
72     void setGeometryToScreenPixmap(KWayland::Client::PlasmaShell *plasmashell);
73     void drawSelectionSizeTooltip(QPainter &painter, bool dragHandlesVisible);
74     void setBottomHelpText();
75     void layoutBottomHelpText();
76     void setMouseCursor(const QPointF &pos);
77     MouseState mouseLocation(const QPointF &pos);
78 
79     static QMap<ComparableQPoint, ComparableQPoint> computeCoordinatesAfterScaling(const QMap<ComparableQPoint, QPair<qreal, QSize>> &outputsRect);
80 
81     static const int handleRadiusMouse;
82     static const int handleRadiusTouch;
83     static const qreal increaseDragAreaFactor;
84     static const int minSpacingBetweenHandles;
85     static const int borderDragAreaSize;
86 
87     static const int selectionSizeThreshold;
88 
89     static const int selectionBoxPaddingX;
90     static const int selectionBoxPaddingY;
91     static const int selectionBoxMarginY;
92 
93     static const int bottomHelpMaxLength = 6;
94     static bool bottomHelpTextPrepared;
95     static const int bottomHelpBoxPaddingX;
96     static const int bottomHelpBoxPaddingY;
97     static const int bottomHelpBoxPairSpacing;
98     static const int bottomHelpBoxMarginBottom;
99     static const int midHelpTextFontSize;
100 
101     static const int magnifierLargeStep;
102 
103     static const int magZoom;
104     static const int magPixels;
105     static const int magOffset;
106 
107     QColor mMaskColor;
108     QColor mStrokeColor;
109     QColor mCrossColor;
110     QColor mLabelBackgroundColor;
111     QColor mLabelForegroundColor;
112     QRect mSelection;
113     QPointF mStartPos;
114     QPointF mInitialTopLeft;
115     QString mMidHelpText;
116     QFont mMidHelpTextFont;
117     std::pair<QStaticText, std::vector<QStaticText>> mBottomHelpText[bottomHelpMaxLength];
118     QFont mBottomHelpTextFont;
119     QRect mBottomHelpBorderBox;
120     QPoint mBottomHelpContentPos;
121     int mBottomHelpGridLeftWidth;
122     MouseState mMouseDragState;
123     QMap<const QScreen *, QImage> mImages;
124     QMap<const QScreen *, qreal> mScreenToDpr;
125     QPixmap mPixmap;
126     qreal devicePixelRatio;
127     qreal devicePixelRatioI;
128     QPointF mMousePos;
129     bool mMagnifierAllowed;
130     bool mShowMagnifier;
131     bool mToggleMagnifier;
132     bool mReleaseToCapture;
133     bool mDisableArrowKeys;
134     int mbottomHelpLength;
135     QRect mScreensRect;
136 
137     // Midpoints of handles
138     QVector<QPointF> mHandlePositions = QVector<QPointF>{8};
139     // Radius of handles is either handleRadiusMouse or handleRadiusTouch
140     int mHandleRadius;
141 };
142 
143 #endif // QUICKEDITOR_H
144