Namecheap - Basic objects editing (move, remove, change color, change thickness) (#1539)
* Code refactoring - rename deleteToolwidgetOrClose to deleteToolWidgetOrClose (cherry picked from commit cc9d71c660fd335e484b8c2c5a4c9ac939a5b643) * Code refactoring - move part of code from CaptureWidget::paintEvent function into showInitialMessage (cherry picked from commit 377b716dc4cdc460e385e9a953850c377283db73) * Code refactoring - move part of code from CaptureWidget::paintEvent function into showInitialMessage (cherry picked from commit 377b716dc4cdc460e385e9a953850c377283db73) * Code refactoring - move part of code from CaptureWidget::paintEvent function into drawInactiveRegion, rename showInitialMessage -> drawInitialMessage (cherry picked from commit 39bf83588db52b9e5b40fddb2b7a9939a64bd19b) * Re-implement undo/redo feature with a future ability to work with it as with history with access by index (remove/edit not just for a last item) (cherry picked from commit d6c6cf51c38b8dd8f51f443f3dcb162e96796a66) * fix - No bubble border for CircleCountTool (cherry picked from commit 6ef81efd91d9d8d169c1dafd2801fffd2a722ee8) * fix - Restore Pen and Brush after the rectangle tool (effects Circle tool without it) (cherry picked from commit 5239925fa5cf69b6755004f3ab8443d091d731c1) * Tool objects history (undo) list on Utility Panel - added icon to the items (cherry picked from commit 4181990f2677a9c8b62c844546f4ac708ecac076) * Update Ukrainian and Russian translations (cherry picked from commit eae2fe0f5826eda4d44d1616bbd12ff53a9254dd) * Feature - remove any created object on CaptureWidget (cherry picked from commit ed2073fa7c2d4e9067668d5a262a067d3ccf9c9a) * Search tool object on CaptureWidget on mouse click and select it in UtilityPanel (cherry picked from commit 5a997dd5608d0bf72af1b50bcfa1779336b842ac) * Optimize tool object search on CaptureWidget (cherry picked from commit 7cd4872cb4adb29e847c5e3adfdb3a24a240982b) * Move selection with Ctrl modificator key only, set correct mouse cursor for dragging and selecting tool objects (cherry picked from commit bf8e47ccbef33bc765820fe64c12168587117ea6) * Move tool objects based on AbstractTwoPointTool class (cherry picked from commit 3f041b76d2da9326f099b7109984b75a4ce0df28) * Move Text tool objects on CaptureWidget (cherry picked from commit b71b6db9e1a4c64e19a045096bd7df0d5a3f4b8f) * Move Pencil tool objects on CaptureWidget (cherry picked from commit 3a269a57bb38bdfea0596f2a8310de6bd5bdb119) * Code refactoring - clean up unused and some refactoring (cherry picked from commit af667f1e25c7c363a42952b20580620c0e6d7925) * Remove - duplicate 'at' class member with int and uint types (cherry picked from commit 4b5b2f7a75ce568bd23d170b8d8731f630d1bf48) * Search for an active object BLUR/PIXELATE and activate it on mouse click (cherry picked from commit 04cbbdd352e41e23edb4ae596173a6d3971ecdb5) * Increase search radius for text objects (cherry picked from commit 4f189bc40b71b82d0e1e5d3ff06e6641616abb8c) * Code refactoring - remove old unused undo/redo backupPixmap (cherry picked from commit 1b15b9acf514fce854d5e0f467c10a6e14a333a0) * Add object selection arownd the object on select for tools based on AbstractTwoPointTool (cherry picked from commit 26fab8ff365ed0d7ff3eee1191d48248e8a05dcd) * Add object selection arownd the object on select for tools based on AbstractPathTool (cherry picked from commit bbf53e4c35a58d313d0cd94b24b86c15f5841483) * Add object selection arownd the object on select for the TextTool (cherry picked from commit ec5780b5c1ec59fd8924834f67563df36590c0a6) * Edit color for any selected object (cherry picked from commit 465a183978f8e8ff0df0e2c5cf77ec3d3115fccc) * Code refactoring - fix some missprints in MacOS CI (cherry picked from commit 99ef8a55d4ca812b6217bd15934c276a2ed5aa57) * Text object selection has wrong size (cherry picked from commit cd365060f1bc607ee53a77482af50f71d5ffe674) * Make more noticeable object selection for TwoPoints and Path tools (except arrows) (cherry picked from commit 67e304474fd116d95ae6138a50c719186b71bf9a) * Make more noticeable object selection for Arrows (cherry picked from commit 066ff0a425ebfc2c235ef756057c086cd75a863f) * Make more noticeable object selection for Text (cherry picked from commit e5e0afd5853ae2e8169209a0d9a3a6b1ce42f6e1) * fix - Make more noticeable object selection for Arrow tool (cherry picked from commit e1028c7c786d7d8b92b2bd7561193ed5be9066c8) * fix - add '#include <cmath>' for round function (cherry picked from commit a043036627587d78bbc916a4590e4e0cb9a6173d) * Add hotkey for removing objects (cherry picked from commit 13059461d550fbdd7f43d157c3a87fad43989742) * Add hotkey for removing objects (cherry picked from commit 13059461d550fbdd7f43d157c3a87fad43989742) * Code refactoring - remove outdated parts of undo/redo, some optimisation (cherry picked from commit 8e08cea690dcbadb61efbab4139b4bd43a9dd91a) * Add operator = for tool objects to be able to implement undo/redo stack based on the concept of full state saving for each step (just objects, not generated images and layers) (cherry picked from commit 7ffc850883ea97d807514a15d89ac5dd0e45c9f5) * Implement basic Undo/Redo step based on QUndoStack (without move and change color steps), some other fixes (cherry picked from commit 818f3d2939fbe5153787612824e40b3b1997297b) * Add undo/redo stack for changing color (cherry picked from commit 2b8a4ffc4f5e39d8531611f516a222288f54224b) * fix - save objects state before color update for undo/redo stack and do not save state until mouse release event (cherry picked from commit 4ba79d6b96d89a3010f14d0d9759ff98ae407fd1) * Add object movement to the undo/redo stack (cherry picked from commit 1eacc35a15487a815a68db6b7ad5daf8bac7adcf) * fix - undo/redo from first to the latest item (still with a brutal hack) (cherry picked from commit 421f43ff5361da1d215465e133b52b407829340c) * Do not close CaptureWidget if some tool object or selection is active (cherry picked from commit 17fc95e167dd7ac3c17c8ed39c4bbde03301ea9b) * Don't change color if right click is not in the object selection area (cherry picked from commit d8ecead647ca0804c5e7555c8ffa3117abc8f3d1) * Edit thickness for the existing objects (cherry picked from commit 9ab45497e60b1316bf50d67ca7d29b84cd70f515) * fix - restore CaptureWidget thickness on object select (cherry picked from commit 9ff9de5a915eec65bed66a74e3a5ec7f1bee2719) * Code refactoring - move repeated code to the function 'activeToolObject' (cherry picked from commit c388d8c8ec2844c2426148a437f6aaad2a1f7923) * Code refactoring - remove unused lines and many fixes based on Clang-Tidy (cherry picked from commit 7e19019dbaa185387b90fe9f45c8a65f057cd582) * Code refactoring - remove unused lines and many fixes based on Clang-Tidy (cherry picked from commit 7e19019dbaa185387b90fe9f45c8a65f057cd582) * fix - Circle Counter Bubble numeration can skip some items if CPU is high loaded at that moment (cherry picked from commit 6242fe8620bd5a46a7291de41ea8ce5465950664) * Code refactoring - make m_thickness variable in tool objects private and work with it as get/set methods (cherry picked from commit f36e823864c1af35aa94809515f786a45915e180) * fix - CircleTool doesn't place on CaptureWidget without mouse move Code refactoring - make number of variables private for AbstractTwoPointTool and work with them as get/set methods (cherry picked from commit 874ebc3afd3da77fcb954e83429e88016518cbca) * CircleCount - make circles more contrast and mouse preview opaque (cherry picked from commit cebf3b831cf5751cb0b4b9b83f6f63d60b18dc8c) * fix - CircleCount selection and changing color for existing object (cherry picked from commit 477c230194b57af9223a3d68c4ac4f5c1bf3566c) * fix - Move selection area tool cannot be selected (cherry picked from commit 38662ff86e6a858c02050de1caa37295bb25d574) * fix - Selection area disappears on click on existing tool out of area (cherry picked from commit e98c60e226c9883558718f1278879339dc528973) * Change MacOS hotkey Command+Backspace -> Backspace (cherry picked from commit aa96b956348a0192179f03a43a0ce5712ce1a965) * Make rectangle tool with rounded borders (not cut), Make selection tool without rounded edges (cherry picked from commit 2fd9c2ad9f5d00dcb9204b09989a66309b43f472) * fix - Thickness doesn't changed for existing object on changing it in side panel (cherry picked from commit 271731c89185b982a86bb27e3a7bc441a2942c10) * fix - Sync selection on CaptureWidget when clicking on tool in panel (cherry picked from commit 9db0c75ec0e92d5fad5bc3856f46f5ed87c6aefd) * Change selection on mouse down instead of mouse up event (cherry picked from commit 3e09778b701498498c144c5e5516f746f1c9088a) * Code refactoring - remove variable m_rightClick from CaptureWidget, use another existing trigger to detect it (cherry picked from commit 1abc595ce352b8445a943504a7c359cd0830a640) * fix - Rectangle preview and final objects are not the same (cherry picked from commit b31905892a60228cae5c8bcde1f71699eca63447) * fix - Doesn't save image if the 'use fixed path' checkbox is checked (cherry picked from commit 1470859aa2c4f28f2c45581891534f3fa4bd6f0a) * fix - Latest Uploads max size value doesn't restore after reset/import settings (cherry picked from commit fa72bacfc0bb12313dd351ee246dd567dfc3f3c8) * fix - impossible to disable the keyboard shortcut by clicking Delete button (cherry picked from commit 74d36e4b3a333cb81ffb4ad93a2bd5465e79cb94) * fix - MacOS - Increase and Decrease Size tool icon colors are not changed (dark/light) when changing main tool background color (cherry picked from commit e48b685c900540a9cd353f71290be04491621fc7) * fix - Selected region control points cannot be dragged on the screen corners (cherry picked from commit 08bf02b5ee096c14d10c15853543749d58c51ef4) * fix - Object selects if mouse pointer above any object when TextTool is active (cherry picked from commit b7a6a7efc8c3a77c55039721ab0cf388973c25d5) * fix - Test Tool doesn't close editor on next text item, you can see two editors and one of them will be never closed (cherry picked from commit eb12f76fd7121d1917659485673305684de523c8) * Code refactoring - remove function in the CaptureToolObjects class with the same functional (cherry picked from commit 1a108f7be48d5b4d89960ac4a5f4e82c03762cbc) * Code refactoring - CaptureWidget::mousePressEvent function is split into a few, code became more readable (cherry picked from commit dc850b3daa00fa173126d86403c35f3c67c448e6) * optimization - remove unnecessary calls of CaptureWidget::drawToolsData (cherry picked from commit c2432bd5602657233ee9506e84a7806bafeb6f68) * fix - Move tool doesn't work if any object is selected fix - Active tool stays active if existing object is selected in the Tool Settings panel (cherry picked from commit 6154feba575f79a06082f72b5c45a869c8d08f42) * fix - App freezes for a while when changing thickness of the pixelate to the minimal value (cherry picked from commit 3a1c519c8309b831e4cc4f11b9014b1a9599ba93) * fix - Text Tool doubles on press ESC when text editing field is active (cherry picked from commit 00bdebff75a0178a46f38606eec4921fdf2f5917) * fix - Image is pinned/saved with object selection frame if there is one (cherry picked from commit 81871860720fa0527f8dcabe1b274b3f03818b7c) * fix - Object line thickness changes according to previously modified object when switching between objects via object list (cherry picked from commit a4a367d30e18a743f0df849e7db1aa2dc20af2a6) * fix - Configuration: Filename doesn't set default value on clear (cherry picked from commit 289663c0c85f4bae98c1a19a7a05fb1029738c12) * Update README.md - Global shortcut for Ubuntu 20.04 (cherry picked from commit 3bee0aa0ac937c00113f2bcca818a9a57e6c5530) * fix - Saved screenshot has selection if some object is selected on Save (cherry picked from commit e53bb33e804cc7de1102a1ab3069bfb849174b73) * fix - Saved screenshot has selection if some object is selected on Upload * fix - Rename "Reset" to "Restore" in file settings for restoring saved file name rules in the configuration widget (cherry picked from commit d2ac5a330fca902b832fce163e4f5f138dbbcc6b) * Update Ukrainian and Russian translations * fix - Shapes are displayed as semi-empty at the very beginning of drawing if the line is thick (cherry picked from commit d8b09c5d5233fefe3181a69f5200198815bc3ec1) * fix - MacOS - Button "Tool Settings" is not visible on some displays if displays are vertically aligned (cherry picked from commit 6af590a859b2708177c34c3ff37725905f4c3bec) * fix - Incorrect selection border for Rectangle/Pixelate tool (cherry picked from commit c908d3b67c5d8e2188d2699ac11951110493b756) * Code refactoring - replace magic numbers (cherry picked from commit c8e1ce345adb1646659e4e90d314916532d5e67a) * fix merge conflicts for Internationalization files * fix - thickness shouldn't be less than one (cherry picked from commit d8ea8a0db7fffcec601dd3139c57198ba15b64b7) * Update copyright info Co-authored-by: Yuriy Puchkov <yuriy.puchkov@namecheap.com>
This commit is contained in:
@@ -40,14 +40,13 @@
|
||||
// CaptureWidget is the main component used to capture the screen. It contains
|
||||
// an area of selection with its respective buttons.
|
||||
|
||||
// enableSaveWIndow
|
||||
CaptureWidget::CaptureWidget(const uint id,
|
||||
// enableSaveWindow
|
||||
CaptureWidget::CaptureWidget(uint id,
|
||||
const QString& savePath,
|
||||
bool fullScreen,
|
||||
QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_mouseIsClicked(false)
|
||||
, m_rightClick(false)
|
||||
, m_newSelection(false)
|
||||
, m_grabbing(false)
|
||||
, m_captureDone(false)
|
||||
@@ -56,10 +55,16 @@ CaptureWidget::CaptureWidget(const uint id,
|
||||
, m_activeButton(nullptr)
|
||||
, m_activeTool(nullptr)
|
||||
, m_toolWidget(nullptr)
|
||||
, m_colorPicker(nullptr)
|
||||
, m_mouseOverHandle(SelectionWidget::NO_SIDE)
|
||||
, m_id(id)
|
||||
, m_lastMouseWheel(0)
|
||||
, m_updateNotificationWidget(nullptr)
|
||||
, m_activeToolIsMoved(false)
|
||||
, m_lastPressedUndo(false)
|
||||
, m_lastPressedRedo(false)
|
||||
, m_panel(nullptr)
|
||||
, m_selection(nullptr)
|
||||
{
|
||||
// Base config of the widget
|
||||
m_eventFilter = new HoverEventFilter(this);
|
||||
@@ -120,6 +125,7 @@ CaptureWidget::CaptureWidget(const uint id,
|
||||
move(currentScreen->geometry().x(), currentScreen->geometry().y());
|
||||
resize(currentScreen->size());
|
||||
#else
|
||||
// Comment For CaptureWidget Debugging under Linux
|
||||
setWindowFlags(Qt::BypassWindowManagerHint | Qt::WindowStaysOnTopHint |
|
||||
Qt::FramelessWindowHint | Qt::Tool);
|
||||
resize(pixmap().size());
|
||||
@@ -176,9 +182,6 @@ CaptureWidget::CaptureWidget(const uint id,
|
||||
m_notifierBox = new NotifierBox(this);
|
||||
m_notifierBox->hide();
|
||||
|
||||
connect(&m_undoStack, &QUndoStack::indexChanged, this, [this](int) {
|
||||
this->update();
|
||||
});
|
||||
initPanel();
|
||||
}
|
||||
|
||||
@@ -263,36 +266,56 @@ QPixmap CaptureWidget::pixmap()
|
||||
// tool.
|
||||
bool CaptureWidget::commitCurrentTool()
|
||||
{
|
||||
if (m_activeButton) {
|
||||
if (m_activeTool) {
|
||||
if (m_activeTool->isValid() && m_toolWidget) {
|
||||
pushToolToStack();
|
||||
} else {
|
||||
m_activeTool->deleteLater();
|
||||
}
|
||||
if (m_toolWidget) {
|
||||
m_toolWidget->deleteLater();
|
||||
return true;
|
||||
}
|
||||
if (m_activeButton && m_activeTool) {
|
||||
if (m_activeTool->isValid() && m_toolWidget) {
|
||||
pushToolToStack();
|
||||
} else {
|
||||
m_activeTool->deleteLater();
|
||||
m_activeTool = nullptr;
|
||||
}
|
||||
if (m_toolWidget) {
|
||||
m_toolWidget->deleteLater();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CaptureWidget::deleteToolwidgetOrClose()
|
||||
void CaptureWidget::deleteToolWidgetOrClose()
|
||||
{
|
||||
if (m_panel->isVisible()) {
|
||||
if (!m_activeButton.isNull()) {
|
||||
uncheckActiveTool();
|
||||
} else if (m_panel->activeLayerIndex() >= 0) {
|
||||
// remove active tool selection
|
||||
m_panel->setActiveLayer(-1);
|
||||
drawToolsData(false, true);
|
||||
} else if (m_panel->isVisible()) {
|
||||
// hide panel if visible
|
||||
m_panel->hide();
|
||||
} else if (m_toolWidget) {
|
||||
// delete toolWidget if exists
|
||||
m_toolWidget->deleteLater();
|
||||
m_toolWidget = nullptr;
|
||||
} else {
|
||||
// close CaptureWidget
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::paintEvent(QPaintEvent*)
|
||||
void CaptureWidget::uncheckActiveTool()
|
||||
{
|
||||
// uncheck active tool
|
||||
m_activeButton->setColor(m_uiColor);
|
||||
m_activeButton = nullptr;
|
||||
m_activeTool->deleteLater();
|
||||
m_activeTool = nullptr;
|
||||
updateCursor();
|
||||
update(); // clear mouse preview
|
||||
}
|
||||
|
||||
void CaptureWidget::paintEvent(QPaintEvent* paintEvent)
|
||||
{
|
||||
Q_UNUSED(paintEvent)
|
||||
QPainter painter(this);
|
||||
painter.drawPixmap(0, 0, m_context.screenshot);
|
||||
|
||||
@@ -307,125 +330,131 @@ void CaptureWidget::paintEvent(QPaintEvent*)
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
QColor overlayColor(0, 0, 0, m_opacity);
|
||||
painter.setBrush(overlayColor);
|
||||
QRect r;
|
||||
if (m_selection->isVisible()) {
|
||||
r = m_selection->geometry().normalized().adjusted(0, 0, -1, -1);
|
||||
}
|
||||
QRegion grey(rect());
|
||||
grey = grey.subtracted(r);
|
||||
|
||||
painter.setClipRegion(grey);
|
||||
painter.drawRect(-1, -1, rect().width() + 1, rect().height() + 1);
|
||||
painter.setClipRect(rect());
|
||||
// draw inactive region
|
||||
drawInactiveRegion(&painter);
|
||||
|
||||
// show initial message on screen capture call if required (before selecting
|
||||
// area)
|
||||
if (m_showInitialMsg) {
|
||||
#if defined(Q_OS_MACOS)
|
||||
QRect helpRect;
|
||||
QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
|
||||
if (currentScreen) {
|
||||
helpRect = currentScreen->geometry();
|
||||
} else {
|
||||
helpRect = QGuiApplication::primaryScreen()->geometry();
|
||||
}
|
||||
#else
|
||||
QRect helpRect = QGuiApplication::primaryScreen()->geometry();
|
||||
#endif
|
||||
drawInitialMessage(&painter);
|
||||
}
|
||||
}
|
||||
|
||||
helpRect.moveTo(mapFromGlobal(helpRect.topLeft()));
|
||||
|
||||
QString helpTxt =
|
||||
tr("Select an area with the mouse, or press Esc to exit."
|
||||
"\nPress Enter to capture the screen."
|
||||
"\nPress Right Click to show the color picker."
|
||||
"\nUse the Mouse Wheel to change the thickness of your tool."
|
||||
"\nPress Space to open the side panel.");
|
||||
|
||||
// We draw the white contrasting background for the text, using the
|
||||
// same text and options to get the boundingRect that the text will
|
||||
// have.
|
||||
QRectF bRect = painter.boundingRect(helpRect, Qt::AlignCenter, helpTxt);
|
||||
|
||||
// These four calls provide padding for the rect
|
||||
const int margin = QApplication::fontMetrics().height() / 2;
|
||||
bRect.setWidth(bRect.width() + margin);
|
||||
bRect.setHeight(bRect.height() + margin);
|
||||
bRect.setX(bRect.x() - margin);
|
||||
bRect.setY(bRect.y() - margin);
|
||||
|
||||
QColor rectColor(m_uiColor);
|
||||
rectColor.setAlpha(180);
|
||||
QColor textColor(
|
||||
(ColorUtils::colorIsDark(rectColor) ? Qt::white : Qt::black));
|
||||
|
||||
painter.setBrush(QBrush(rectColor, Qt::SolidPattern));
|
||||
painter.setPen(QPen(textColor));
|
||||
|
||||
painter.drawRect(bRect);
|
||||
painter.drawText(helpRect, Qt::AlignCenter, helpTxt);
|
||||
void CaptureWidget::showColorPicker(const QPoint& pos)
|
||||
{
|
||||
// Reset object selection if mouse pos is not in selection area
|
||||
auto toolItem = activeToolObject();
|
||||
if (toolItem && !toolItem->selectionRect().contains(pos)) {
|
||||
m_panel->setActiveLayer(-1);
|
||||
}
|
||||
|
||||
if (m_selection->isVisible()) {
|
||||
// paint handlers
|
||||
painter.setPen(m_uiColor);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setBrush(m_uiColor);
|
||||
for (auto r : m_selection->handlerAreas()) {
|
||||
painter.drawRoundedRect(r, 100, 100);
|
||||
// Call color picker
|
||||
m_colorPicker->move(pos.x() - m_colorPicker->width() / 2,
|
||||
pos.y() - m_colorPicker->height() / 2);
|
||||
m_colorPicker->raise();
|
||||
m_colorPicker->show();
|
||||
}
|
||||
|
||||
bool CaptureWidget::startDrawObjectTool(const QPoint& pos)
|
||||
{
|
||||
if (m_activeButton && m_activeButton->tool()->nameID() != ToolType::MOVE) {
|
||||
if (commitCurrentTool()) {
|
||||
return false;
|
||||
}
|
||||
m_activeTool = m_activeButton->tool()->copy(this);
|
||||
|
||||
connect(this,
|
||||
&CaptureWidget::colorChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::colorChanged);
|
||||
connect(this,
|
||||
&CaptureWidget::thicknessChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::thicknessChanged);
|
||||
connect(m_activeTool,
|
||||
&CaptureTool::requestAction,
|
||||
this,
|
||||
&CaptureWidget::handleButtonSignal);
|
||||
m_context.mousePos = pos;
|
||||
m_activeTool->drawStart(m_context);
|
||||
if (m_activeTool->nameID() == ToolType::CIRCLECOUNT) {
|
||||
// While it is based on AbstractTwoPointTool it has the only one
|
||||
// point and shouldn't wait for second point and move event
|
||||
m_activeTool->drawEnd(m_context.mousePos);
|
||||
m_captureToolObjects.append(m_activeTool);
|
||||
m_undoStack.push(
|
||||
new ModificationCommand(this, m_captureToolObjects));
|
||||
m_activeTool->deleteLater();
|
||||
m_activeTool = nullptr;
|
||||
m_mouseIsClicked = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CaptureWidget::selectToolItemAtPos(const QPoint& pos)
|
||||
{
|
||||
// Try to select existing tool
|
||||
if (m_activeButton.isNull() &&
|
||||
m_captureToolObjects.captureToolObjects().size() > 0 &&
|
||||
m_selection->getMouseSide(pos) == SelectionWidget::NO_SIDE) {
|
||||
auto toolItem = activeToolObject();
|
||||
if (!toolItem ||
|
||||
(toolItem && !toolItem->selectionRect().contains(pos))) {
|
||||
int activeLayerIndex = m_captureToolObjects.find(pos, size());
|
||||
int thickness_old = m_context.thickness;
|
||||
m_panel->setActiveLayer(activeLayerIndex);
|
||||
drawObjectSelection();
|
||||
if (thickness_old != m_context.thickness) {
|
||||
emit thicknessChanged(m_context.thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
m_dragStartPoint = m_mousePressedPos = e->pos();
|
||||
m_activeToolOffsetToMouseOnStart = QPoint();
|
||||
|
||||
// reset object selection if capture area selection is active
|
||||
if (m_selection->getMouseSide(e->pos()) != SelectionWidget::NO_SIDE) {
|
||||
m_panel->setActiveLayer(-1);
|
||||
}
|
||||
|
||||
if (e->button() == Qt::RightButton) {
|
||||
m_rightClick = true;
|
||||
m_colorPicker->move(e->pos().x() - m_colorPicker->width() / 2,
|
||||
e->pos().y() - m_colorPicker->height() / 2);
|
||||
m_colorPicker->raise();
|
||||
m_colorPicker->show();
|
||||
showColorPicker(m_mousePressedPos);
|
||||
} else if (e->button() == Qt::LeftButton) {
|
||||
m_showInitialMsg = false;
|
||||
m_mouseIsClicked = true;
|
||||
// Click using a tool
|
||||
if (m_activeButton) {
|
||||
if (commitCurrentTool()) {
|
||||
return;
|
||||
}
|
||||
m_activeTool = m_activeButton->tool()->copy(this);
|
||||
|
||||
connect(this,
|
||||
&CaptureWidget::colorChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::colorChanged);
|
||||
connect(this,
|
||||
&CaptureWidget::thicknessChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::thicknessChanged);
|
||||
connect(m_activeTool,
|
||||
&CaptureTool::requestAction,
|
||||
this,
|
||||
&CaptureWidget::handleButtonSignal);
|
||||
m_context.mousePos = e->pos();
|
||||
m_activeTool->drawStart(m_context);
|
||||
// Click using a tool excluding tool MOVE
|
||||
if (startDrawObjectTool(m_mousePressedPos)) {
|
||||
// return if success
|
||||
return;
|
||||
}
|
||||
|
||||
m_dragStartPoint = e->pos();
|
||||
m_selection->saveGeometry();
|
||||
// New selection
|
||||
if (!m_selection->geometry().contains(e->pos()) &&
|
||||
m_mouseOverHandle == SelectionWidget::NO_SIDE) {
|
||||
m_selection->setGeometry(QRect(e->pos(), e->pos()));
|
||||
m_selection->setVisible(false);
|
||||
m_newSelection = true;
|
||||
m_buttonHandler->hide();
|
||||
update();
|
||||
} else {
|
||||
m_grabbing = true;
|
||||
if (m_captureToolObjects.captureToolObjects().size() == 0) {
|
||||
if (!m_selection->geometry().contains(e->pos()) &&
|
||||
m_mouseOverHandle == SelectionWidget::NO_SIDE) {
|
||||
m_selection->setGeometry(
|
||||
QRect(m_mousePressedPos, m_mousePressedPos));
|
||||
m_selection->setVisible(false);
|
||||
m_newSelection = true;
|
||||
m_buttonHandler->hide();
|
||||
update();
|
||||
} else {
|
||||
m_grabbing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to select existing tool
|
||||
selectToolItemAtPos(m_mousePressedPos);
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
@@ -434,7 +463,22 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent* e)
|
||||
m_context.mousePos = e->pos();
|
||||
bool symmetryMod = qApp->keyboardModifiers() & Qt::ShiftModifier;
|
||||
|
||||
if (m_mouseIsClicked && !m_activeButton) {
|
||||
int activeLayerIndex = m_panel->activeLayerIndex();
|
||||
if (m_mouseIsClicked && !m_activeButton && activeLayerIndex >= 0) {
|
||||
// Move existing object
|
||||
QPointer<CaptureTool> activeTool =
|
||||
m_captureToolObjects.at(activeLayerIndex);
|
||||
if (m_activeToolOffsetToMouseOnStart.isNull()) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
m_activeToolOffsetToMouseOnStart = e->pos() - *activeTool->pos();
|
||||
}
|
||||
activeTool->move(e->pos() - m_activeToolOffsetToMouseOnStart);
|
||||
m_activeToolIsMoved = true;
|
||||
drawToolsData(false);
|
||||
} else if (m_mouseIsClicked &&
|
||||
(!m_activeButton ||
|
||||
(m_activeButton &&
|
||||
m_activeButton->tool()->nameID() == ToolType::MOVE))) {
|
||||
// Drawing, moving, or stretching a selection
|
||||
m_selection->setVisible(true);
|
||||
if (m_buttonHandler->isVisible()) {
|
||||
@@ -450,10 +494,15 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent* e)
|
||||
|
||||
} else if (m_mouseOverHandle == SelectionWidget::NO_SIDE) {
|
||||
// Moving the whole selection
|
||||
QRect initialRect = m_selection->savedGeometry().normalized();
|
||||
QPoint newTopLeft =
|
||||
initialRect.topLeft() + (e->pos() - m_dragStartPoint);
|
||||
inputRect = QRect(newTopLeft, initialRect.size());
|
||||
if (m_adjustmentButtonPressed || activeToolObject().isNull()) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
QRect initialRect = m_selection->savedGeometry().normalized();
|
||||
QPoint newTopLeft =
|
||||
initialRect.topLeft() + (e->pos() - m_dragStartPoint);
|
||||
inputRect = QRect(newTopLeft, initialRect.size());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Dragging a handle
|
||||
inputRect = m_selection->savedGeometry();
|
||||
@@ -534,20 +583,39 @@ void CaptureWidget::mouseReleaseEvent(QMouseEvent* e)
|
||||
{
|
||||
if (e->button() == Qt::RightButton || m_colorPicker->isVisible()) {
|
||||
m_colorPicker->hide();
|
||||
m_rightClick = false;
|
||||
if (!m_context.color.isValid()) {
|
||||
m_context.color = ConfigHandler().drawColorValue();
|
||||
m_panel->show();
|
||||
} else {
|
||||
// push current state to the undo stack
|
||||
m_undoStack.push(
|
||||
new ModificationCommand(this, m_captureToolObjects));
|
||||
}
|
||||
// when we end the drawing we have to register the last point and
|
||||
// add the temp modification to the list of modifications
|
||||
} else if (m_mouseIsClicked && m_activeTool) {
|
||||
m_activeTool->drawEnd(m_context.mousePos);
|
||||
if (m_activeTool->isValid()) {
|
||||
pushToolToStack();
|
||||
} else if (!m_toolWidget) {
|
||||
m_activeTool->deleteLater();
|
||||
m_activeTool = nullptr;
|
||||
} else if (m_mouseIsClicked) {
|
||||
if (m_activeTool) {
|
||||
// end draw/edit
|
||||
m_activeTool->drawEnd(m_context.mousePos);
|
||||
if (m_activeTool->isValid()) {
|
||||
pushToolToStack();
|
||||
} else if (!m_toolWidget) {
|
||||
m_activeTool->deleteLater();
|
||||
m_activeTool = nullptr;
|
||||
}
|
||||
} else {
|
||||
if (m_activeToolIsMoved) {
|
||||
// push current state to the undo stack
|
||||
m_undoStack.push(
|
||||
new ModificationCommand(this, m_captureToolObjects));
|
||||
}
|
||||
|
||||
// Try to select existing tool if it was in the selection area but
|
||||
// need to select another one
|
||||
if (e->pos() == m_mousePressedPos && !m_activeToolIsMoved &&
|
||||
m_activeButton.isNull()) {
|
||||
m_panel->setActiveLayer(
|
||||
m_captureToolObjects.find(e->pos(), size()));
|
||||
}
|
||||
drawToolsData(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,6 +642,7 @@ void CaptureWidget::mouseReleaseEvent(QMouseEvent* e)
|
||||
m_buttonHandler->show();
|
||||
}
|
||||
m_mouseIsClicked = false;
|
||||
m_activeToolIsMoved = false;
|
||||
m_newSelection = false;
|
||||
m_grabbing = false;
|
||||
|
||||
@@ -611,11 +680,12 @@ void CaptureWidget::keyPressEvent(QKeyEvent* e)
|
||||
return;
|
||||
} else if (e->key() == Qt::Key_Control) {
|
||||
m_adjustmentButtonPressed = true;
|
||||
updateCursor();
|
||||
} else if (e->key() == Qt::Key_Enter) {
|
||||
// Make no difference for Return and Enter keys
|
||||
QKeyEvent* keyReturn =
|
||||
new QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
|
||||
QCoreApplication::postEvent(this, keyReturn);
|
||||
QCoreApplication::postEvent(
|
||||
this,
|
||||
new QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,6 +693,7 @@ void CaptureWidget::keyReleaseEvent(QKeyEvent* e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Control) {
|
||||
m_adjustmentButtonPressed = false;
|
||||
updateCursor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,7 +729,7 @@ void CaptureWidget::wheelEvent(QWheelEvent* e)
|
||||
}
|
||||
|
||||
m_context.thickness += thicknessOffset;
|
||||
m_context.thickness = qBound(0, m_context.thickness, 100);
|
||||
m_context.thickness = qBound(1, m_context.thickness, 100);
|
||||
QPoint topLeft =
|
||||
QGuiAppCurrentScreen().currentScreen()->geometry().topLeft();
|
||||
int offset = m_notifierBox->width() / 4;
|
||||
@@ -668,6 +739,16 @@ void CaptureWidget::wheelEvent(QWheelEvent* e)
|
||||
update();
|
||||
}
|
||||
emit thicknessChanged(m_context.thickness);
|
||||
|
||||
// update selected object thickness
|
||||
// Reset selection if mouse pos is not in selection area
|
||||
auto toolItem = activeToolObject();
|
||||
if (toolItem) {
|
||||
toolItem->thicknessChanged(m_context.thickness);
|
||||
|
||||
// TODO - save thickness update, but not immediately
|
||||
m_undoStack.push(new ModificationCommand(this, m_captureToolObjects));
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::resizeEvent(QResizeEvent* e)
|
||||
@@ -706,8 +787,8 @@ void CaptureWidget::initPanel()
|
||||
QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
|
||||
panelRect = currentScreen->geometry();
|
||||
auto devicePixelRatio = currentScreen->devicePixelRatio();
|
||||
panelRect.moveTo(panelRect.x() / devicePixelRatio,
|
||||
panelRect.y() / devicePixelRatio);
|
||||
panelRect.moveTo(static_cast<int>(panelRect.x() / devicePixelRatio),
|
||||
static_cast<int>(panelRect.y() / devicePixelRatio));
|
||||
#else
|
||||
panelRect = QGuiApplication::primaryScreen()->geometry();
|
||||
auto devicePixelRatio =
|
||||
@@ -725,9 +806,10 @@ void CaptureWidget::initPanel()
|
||||
panelToggleButton->setOrientation(
|
||||
OrientablePushButton::VerticalBottomToTop);
|
||||
#if defined(Q_OS_MACOS)
|
||||
panelToggleButton->move(0,
|
||||
panelRect.y() + panelRect.height() / 2 -
|
||||
panelToggleButton->width() / 2);
|
||||
panelToggleButton->move(
|
||||
0,
|
||||
static_cast<int>(panelRect.height() / 2) -
|
||||
static_cast<int>(panelToggleButton->width() / 2));
|
||||
#else
|
||||
panelToggleButton->move(panelRect.x(),
|
||||
panelRect.y() + panelRect.height() / 2 -
|
||||
@@ -747,13 +829,17 @@ void CaptureWidget::initPanel()
|
||||
#if defined(Q_OS_MACOS)
|
||||
QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
|
||||
panelRect.moveTo(mapFromGlobal(panelRect.topLeft()));
|
||||
m_panel->setFixedWidth(m_colorPicker->width() * 1.5);
|
||||
m_panel->setFixedWidth(static_cast<int>(m_colorPicker->width() * 1.5));
|
||||
m_panel->setFixedHeight(currentScreen->geometry().height());
|
||||
#else
|
||||
panelRect.moveTo(mapFromGlobal(panelRect.topLeft()));
|
||||
panelRect.setWidth(m_colorPicker->width() * 1.5);
|
||||
m_panel->setGeometry(panelRect);
|
||||
#endif
|
||||
connect(m_panel,
|
||||
&UtilityPanel::layerChanged,
|
||||
this,
|
||||
&CaptureWidget::updateActiveLayer);
|
||||
|
||||
SidePanelWidget* sidePanel = new SidePanelWidget(&m_context.screenshot);
|
||||
connect(sidePanel,
|
||||
@@ -777,7 +863,9 @@ void CaptureWidget::initPanel()
|
||||
sidePanel->colorChanged(m_context.color);
|
||||
sidePanel->thicknessChanged(m_context.thickness);
|
||||
m_panel->pushWidget(sidePanel);
|
||||
m_panel->pushWidget(new QUndoView(&m_undoStack, this));
|
||||
|
||||
// Fill undo/redo/history list widget
|
||||
m_panel->fillCaptureTools(m_captureToolObjects.captureToolObjects());
|
||||
}
|
||||
|
||||
void CaptureWidget::showAppUpdateNotification(const QString& appLatestVersion,
|
||||
@@ -853,6 +941,7 @@ void CaptureWidget::setState(CaptureToolButton* b)
|
||||
}
|
||||
m_activeButton = b;
|
||||
m_activeButton->setColor(m_contrastUiColor);
|
||||
m_panel->setActiveLayer(-1);
|
||||
} else if (m_activeButton) {
|
||||
m_panel->clearToolWidget();
|
||||
m_activeButton->setColor(m_uiColor);
|
||||
@@ -876,18 +965,10 @@ void CaptureWidget::handleButtonSignal(CaptureTool::Request r)
|
||||
{
|
||||
switch (r) {
|
||||
case CaptureTool::REQ_CLEAR_MODIFICATIONS:
|
||||
m_captureToolObjects.clear();
|
||||
m_undoStack.setIndex(0);
|
||||
update();
|
||||
break;
|
||||
|
||||
case CaptureTool::REQ_INCREMENT_CIRCLE_COUNT:
|
||||
incrementCircleCount();
|
||||
break;
|
||||
|
||||
case CaptureTool::REQ_DECREMENT_CIRCLE_COUNT:
|
||||
decrementCircleCount();
|
||||
break;
|
||||
|
||||
case CaptureTool::REQ_CLOSE_GUI:
|
||||
close();
|
||||
break;
|
||||
@@ -903,10 +984,10 @@ void CaptureWidget::handleButtonSignal(CaptureTool::Request r)
|
||||
m_selection->setGeometryAnimated(rect());
|
||||
break;
|
||||
case CaptureTool::REQ_UNDO_MODIFICATION:
|
||||
m_undoStack.undo();
|
||||
undo();
|
||||
break;
|
||||
case CaptureTool::REQ_REDO_MODIFICATION:
|
||||
m_undoStack.redo();
|
||||
redo();
|
||||
break;
|
||||
case CaptureTool::REQ_REDRAW:
|
||||
update();
|
||||
@@ -920,6 +1001,12 @@ void CaptureWidget::handleButtonSignal(CaptureTool::Request r)
|
||||
case CaptureTool::REQ_MOVE_MODE:
|
||||
setState(m_activeButton); // Disable the actual button
|
||||
break;
|
||||
case CaptureTool::REQ_CLEAR_SELECTION:
|
||||
if (m_panel->activeLayerIndex() >= 0) {
|
||||
m_panel->setActiveLayer(-1);
|
||||
drawToolsData(false, false);
|
||||
}
|
||||
break;
|
||||
case CaptureTool::REQ_CAPTURE_DONE_OK:
|
||||
m_captureDone = true;
|
||||
break;
|
||||
@@ -958,9 +1045,8 @@ void CaptureWidget::handleButtonSignal(CaptureTool::Request r)
|
||||
}
|
||||
break;
|
||||
case CaptureTool::REQ_INCREASE_TOOL_SIZE:
|
||||
|
||||
// increase thickness
|
||||
m_context.thickness = qBound(0, m_context.thickness + 1, 100);
|
||||
m_context.thickness = qBound(1, m_context.thickness + 1, 100);
|
||||
|
||||
// show notifier circle
|
||||
m_notifierBox->showMessage(QString::number(m_context.thickness));
|
||||
@@ -968,9 +1054,8 @@ void CaptureWidget::handleButtonSignal(CaptureTool::Request r)
|
||||
emit thicknessChanged(m_context.thickness);
|
||||
break;
|
||||
case CaptureTool::REQ_DECREASE_TOOL_SIZE:
|
||||
|
||||
// decrease thickness
|
||||
m_context.thickness = qBound(0, m_context.thickness - 1, 100);
|
||||
m_context.thickness = qBound(1, m_context.thickness - 1, 100);
|
||||
|
||||
// show notifier circle
|
||||
m_notifierBox->showMessage(QString::number(m_context.thickness));
|
||||
@@ -989,26 +1074,57 @@ void CaptureWidget::setDrawColor(const QColor& c)
|
||||
ConfigHandler().setDrawColor(m_context.color);
|
||||
emit colorChanged(c);
|
||||
}
|
||||
auto toolItem = activeToolObject();
|
||||
if (toolItem) {
|
||||
// Change color
|
||||
emit toolItem->colorChanged(c);
|
||||
drawToolsData(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::incrementCircleCount()
|
||||
void CaptureWidget::updateActiveLayer(const int& layer)
|
||||
{
|
||||
m_context.circleCount++;
|
||||
SPDLOG_DEBUG("Incrementing Circle to {}.", m_context.circleCount);
|
||||
drawToolsData(false, true);
|
||||
}
|
||||
|
||||
void CaptureWidget::decrementCircleCount()
|
||||
void CaptureWidget::removeToolObject(int index)
|
||||
{
|
||||
|
||||
SPDLOG_DEBUG("Decrementing Circle.");
|
||||
m_context.circleCount--;
|
||||
--index;
|
||||
if (index >= 0 && index < m_captureToolObjects.size()) {
|
||||
const ToolType currentToolType =
|
||||
m_captureToolObjects.at(index)->nameID();
|
||||
m_captureToolObjects.removeAt(index);
|
||||
if (currentToolType == ToolType::CIRCLECOUNT) {
|
||||
// Do circle count reindex
|
||||
int circleCount = 1;
|
||||
for (int cnt = 0; cnt < m_captureToolObjects.size(); cnt++) {
|
||||
auto toolItem = m_captureToolObjects.at(cnt);
|
||||
if (toolItem->nameID() != ToolType::CIRCLECOUNT) {
|
||||
continue;
|
||||
}
|
||||
if (cnt >= index) {
|
||||
m_captureToolObjects.at(cnt)->setCount(circleCount);
|
||||
}
|
||||
circleCount++;
|
||||
}
|
||||
m_context.circleCount = circleCount;
|
||||
}
|
||||
drawToolsData();
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::setDrawThickness(const int& t)
|
||||
{
|
||||
m_context.thickness = qBound(0, t, 100);
|
||||
m_context.thickness = qBound(1, t, 100);
|
||||
ConfigHandler().setDrawThickness(m_context.thickness);
|
||||
emit thicknessChanged(m_context.thickness);
|
||||
|
||||
auto toolItem = activeToolObject();
|
||||
if (toolItem) {
|
||||
// Change thickness
|
||||
emit toolItem->thicknessChanged(t);
|
||||
drawToolsData(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::repositionSelection(QRect r)
|
||||
@@ -1115,6 +1231,10 @@ void CaptureWidget::initShortcuts()
|
||||
new QShortcut(QKeySequence(ConfigHandler().shortcut("TYPE_MOVE_DOWN")),
|
||||
this,
|
||||
SLOT(moveDown()));
|
||||
new QShortcut(
|
||||
QKeySequence(ConfigHandler().shortcut("TYPE_DELETE_CURRENT_TOOL")),
|
||||
this,
|
||||
SLOT(deleteCurrentTool()));
|
||||
|
||||
new QShortcut(
|
||||
QKeySequence(ConfigHandler().shortcut("TYPE_COMMIT_CURRENT_TOOL")),
|
||||
@@ -1125,7 +1245,17 @@ void CaptureWidget::initShortcuts()
|
||||
this,
|
||||
SLOT(selectAll()));
|
||||
|
||||
new QShortcut(Qt::Key_Escape, this, SLOT(deleteToolwidgetOrClose()));
|
||||
new QShortcut(Qt::Key_Escape, this, SLOT(deleteToolWidgetOrClose()));
|
||||
}
|
||||
|
||||
void CaptureWidget::deleteCurrentTool()
|
||||
{
|
||||
int thickness_old = m_context.thickness;
|
||||
emit m_panel->slotButtonDelete(true);
|
||||
drawObjectSelection();
|
||||
if (thickness_old != m_context.thickness) {
|
||||
emit thicknessChanged(m_context.thickness);
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::updateSizeIndicator()
|
||||
@@ -1140,10 +1270,17 @@ void CaptureWidget::updateSizeIndicator()
|
||||
|
||||
void CaptureWidget::updateCursor()
|
||||
{
|
||||
if (m_rightClick) {
|
||||
if (m_colorPicker && m_colorPicker->isVisible()) {
|
||||
setCursor(Qt::ArrowCursor);
|
||||
} else if (m_grabbing) {
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
if (m_adjustmentButtonPressed) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
} else {
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
} else if (m_activeButton &&
|
||||
m_activeButton->tool()->nameID() == ToolType::MOVE) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
} else if (!m_activeButton) {
|
||||
using sw = SelectionWidget;
|
||||
if (m_mouseOverHandle != sw::NO_SIDE) {
|
||||
@@ -1170,7 +1307,15 @@ void CaptureWidget::updateCursor()
|
||||
}
|
||||
} else if (m_selection->isVisible() &&
|
||||
m_selection->geometry().contains(m_context.mousePos)) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
if (m_adjustmentButtonPressed) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
} else {
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
} else if (m_selection->isVisible() &&
|
||||
m_captureToolObjects.captureToolObjects().size() > 0 &&
|
||||
m_activeTool.isNull()) {
|
||||
setCursor(Qt::ArrowCursor);
|
||||
} else {
|
||||
setCursor(Qt::CrossCursor);
|
||||
}
|
||||
@@ -1181,20 +1326,82 @@ void CaptureWidget::updateCursor()
|
||||
|
||||
void CaptureWidget::pushToolToStack()
|
||||
{
|
||||
auto mod = new ModificationCommand(&m_context.screenshot, m_activeTool);
|
||||
disconnect(this,
|
||||
&CaptureWidget::colorChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::colorChanged);
|
||||
disconnect(this,
|
||||
&CaptureWidget::thicknessChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::thicknessChanged);
|
||||
if (m_panel->toolWidget()) {
|
||||
disconnect(m_panel->toolWidget(), nullptr, m_activeTool, nullptr);
|
||||
// push zero state to be able to do a complete undo
|
||||
if (m_undoStack.count() == 0) {
|
||||
m_undoStack.push(new ModificationCommand(this, m_captureToolObjects));
|
||||
}
|
||||
m_undoStack.push(mod);
|
||||
m_activeTool = nullptr;
|
||||
|
||||
// append current tool to the new state
|
||||
if (m_activeTool && m_activeButton) {
|
||||
disconnect(this,
|
||||
&CaptureWidget::colorChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::colorChanged);
|
||||
disconnect(this,
|
||||
&CaptureWidget::thicknessChanged,
|
||||
m_activeTool,
|
||||
&CaptureTool::thicknessChanged);
|
||||
if (m_panel->toolWidget()) {
|
||||
disconnect(m_panel->toolWidget(), nullptr, m_activeTool, nullptr);
|
||||
}
|
||||
|
||||
m_captureToolObjects.append(m_activeTool);
|
||||
m_activeTool->deleteLater();
|
||||
m_activeTool = nullptr;
|
||||
}
|
||||
|
||||
// push current state to the undo stack
|
||||
m_undoStack.push(new ModificationCommand(this, m_captureToolObjects));
|
||||
}
|
||||
|
||||
void CaptureWidget::drawToolsData(bool updateLayersPanel, bool drawSelection)
|
||||
{
|
||||
QPixmap pixmapItem = m_context.origScreenshot.copy();
|
||||
QPainter painter(&pixmapItem);
|
||||
int index = 0;
|
||||
m_context.circleCount = 1;
|
||||
for (auto toolItem : m_captureToolObjects.captureToolObjects()) {
|
||||
if (toolItem->nameID() == ToolType::CIRCLECOUNT) {
|
||||
toolItem->setCount(m_context.circleCount);
|
||||
m_context.circleCount++;
|
||||
}
|
||||
toolItem->process(painter, pixmapItem);
|
||||
}
|
||||
|
||||
m_context.screenshot = pixmapItem.copy();
|
||||
update();
|
||||
if (updateLayersPanel) {
|
||||
m_panel->fillCaptureTools(m_captureToolObjects.captureToolObjects());
|
||||
}
|
||||
|
||||
if (drawSelection) {
|
||||
int thickness_old = m_context.thickness;
|
||||
drawObjectSelection();
|
||||
if (thickness_old != m_context.thickness) {
|
||||
emit thicknessChanged(m_context.thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureWidget::drawObjectSelection()
|
||||
{
|
||||
auto toolItem = activeToolObject();
|
||||
if (toolItem) {
|
||||
QPainter painter(&m_context.screenshot);
|
||||
toolItem->drawObjectSelection(painter);
|
||||
if (m_context.thickness != toolItem->thickness()) {
|
||||
m_context.thickness =
|
||||
toolItem->thickness() <= 0 ? 0 : toolItem->thickness();
|
||||
}
|
||||
if (activeToolObject() && m_activeButton) {
|
||||
uncheckActiveTool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPointer<CaptureTool> CaptureWidget::activeToolObject()
|
||||
{
|
||||
return m_captureToolObjects.at(m_panel->activeLayerIndex());
|
||||
}
|
||||
|
||||
void CaptureWidget::makeChild(QWidget* w)
|
||||
@@ -1225,7 +1432,7 @@ void CaptureWidget::copyScreenshot()
|
||||
m_captureDone = true;
|
||||
if (m_activeTool != nullptr) {
|
||||
QPainter painter(&m_context.screenshot);
|
||||
m_activeTool->process(painter, m_context.screenshot, true);
|
||||
m_activeTool->process(painter, m_context.screenshot);
|
||||
}
|
||||
|
||||
ScreenshotSaver().saveToClipboard(pixmap());
|
||||
@@ -1240,7 +1447,7 @@ void CaptureWidget::saveScreenshot()
|
||||
m_captureDone = true;
|
||||
if (m_activeTool != nullptr) {
|
||||
QPainter painter(&m_context.screenshot);
|
||||
m_activeTool->process(painter, m_context.screenshot, true);
|
||||
m_activeTool->process(painter, m_context.screenshot);
|
||||
}
|
||||
hide();
|
||||
if (m_context.savePath.isEmpty()) {
|
||||
@@ -1252,20 +1459,45 @@ void CaptureWidget::saveScreenshot()
|
||||
close();
|
||||
}
|
||||
|
||||
void CaptureWidget::setCaptureToolObjects(
|
||||
const CaptureToolObjects& captureToolObjects)
|
||||
{
|
||||
// Used for undo/redo
|
||||
m_captureToolObjects = captureToolObjects;
|
||||
drawToolsData(true, true);
|
||||
}
|
||||
|
||||
void CaptureWidget::undo()
|
||||
{
|
||||
// FIXME - m_lastPressedUndo and m_lastPressedRedo is a brutal hack, cannot
|
||||
// understand why first undo/redo has no effect so need to do it twice if it
|
||||
// is the firs operation
|
||||
if (!m_lastPressedUndo) {
|
||||
m_undoStack.undo();
|
||||
}
|
||||
m_lastPressedUndo = true;
|
||||
m_lastPressedRedo = false;
|
||||
m_undoStack.undo();
|
||||
}
|
||||
|
||||
void CaptureWidget::redo()
|
||||
{
|
||||
// FIXME - m_lastPressedUndo and m_lastPressedRedo is a brutal hack, cannot
|
||||
// understand why first undo/redo has no effect so need to do it twice if it
|
||||
// is the firs operation
|
||||
if (!m_lastPressedRedo) {
|
||||
m_undoStack.redo();
|
||||
}
|
||||
m_lastPressedUndo = false;
|
||||
m_lastPressedRedo = true;
|
||||
m_undoStack.redo();
|
||||
}
|
||||
|
||||
QRect CaptureWidget::extendedSelection() const
|
||||
{
|
||||
if (!m_selection->isVisible())
|
||||
if (!m_selection->isVisible()) {
|
||||
return QRect();
|
||||
}
|
||||
QRect r = m_selection->geometry();
|
||||
return extendedRect(&r);
|
||||
}
|
||||
@@ -1278,3 +1510,79 @@ QRect CaptureWidget::extendedRect(QRect* r) const
|
||||
r->width() * devicePixelRatio,
|
||||
r->height() * devicePixelRatio);
|
||||
}
|
||||
|
||||
void CaptureWidget::drawInitialMessage(QPainter* painter)
|
||||
{
|
||||
if (nullptr == painter) {
|
||||
return;
|
||||
}
|
||||
#if (defined(Q_OS_MACOS) || defined(Q_OS_LINUX))
|
||||
QRect helpRect;
|
||||
QScreen* currentScreen = QGuiAppCurrentScreen().currentScreen();
|
||||
if (currentScreen) {
|
||||
helpRect = currentScreen->geometry();
|
||||
} else {
|
||||
helpRect = QGuiApplication::primaryScreen()->geometry();
|
||||
}
|
||||
#else
|
||||
QRect helpRect = QGuiApplication::primaryScreen()->geometry();
|
||||
#endif
|
||||
|
||||
helpRect.moveTo(mapFromGlobal(helpRect.topLeft()));
|
||||
|
||||
QString helpTxt =
|
||||
tr("Select an area with the mouse, or press Esc to exit."
|
||||
"\nPress Enter to capture the screen."
|
||||
"\nPress Right Click to show the color picker."
|
||||
"\nUse the Mouse Wheel to change the thickness of your tool."
|
||||
"\nPress Space to open the side panel.");
|
||||
|
||||
// We draw the white contrasting background for the text, using the
|
||||
// same text and options to get the boundingRect that the text will
|
||||
// have.
|
||||
QRectF bRect = painter->boundingRect(helpRect, Qt::AlignCenter, helpTxt);
|
||||
|
||||
// These four calls provide padding for the rect
|
||||
const int margin = QApplication::fontMetrics().height() / 2;
|
||||
bRect.setWidth(bRect.width() + margin);
|
||||
bRect.setHeight(bRect.height() + margin);
|
||||
bRect.setX(bRect.x() - margin);
|
||||
bRect.setY(bRect.y() - margin);
|
||||
|
||||
QColor rectColor(m_uiColor);
|
||||
rectColor.setAlpha(180);
|
||||
QColor textColor(
|
||||
(ColorUtils::colorIsDark(rectColor) ? Qt::white : Qt::black));
|
||||
|
||||
painter->setBrush(QBrush(rectColor, Qt::SolidPattern));
|
||||
painter->setPen(QPen(textColor));
|
||||
|
||||
painter->drawRect(bRect);
|
||||
painter->drawText(helpRect, Qt::AlignCenter, helpTxt);
|
||||
}
|
||||
|
||||
void CaptureWidget::drawInactiveRegion(QPainter* painter)
|
||||
{
|
||||
QColor overlayColor(0, 0, 0, m_opacity);
|
||||
painter->setBrush(overlayColor);
|
||||
QRect r;
|
||||
if (m_selection->isVisible()) {
|
||||
r = m_selection->geometry().normalized().adjusted(0, 0, -1, -1);
|
||||
}
|
||||
QRegion grey(rect());
|
||||
grey = grey.subtracted(r);
|
||||
|
||||
painter->setClipRegion(grey);
|
||||
painter->drawRect(-1, -1, rect().width() + 1, rect().height() + 1);
|
||||
painter->setClipRect(rect());
|
||||
|
||||
if (m_selection->isVisible()) {
|
||||
// paint handlers
|
||||
painter->setPen(m_uiColor);
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->setBrush(m_uiColor);
|
||||
for (auto rect : m_selection->handlerAreas()) {
|
||||
painter->drawRoundedRect(rect, 100, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user