From df5760c15ae01eb508d199a63d0cbb6210d0744c Mon Sep 17 00:00:00 2001 From: Yurii Puchkov Date: Sun, 2 May 2021 20:48:22 +0300 Subject: [PATCH] NC/Optimisations and bug fixes for objects editing (#1600) * Optimise undo/redo for thickness, do not save every change on mouse wheel, save just the result (cherry picked from commit c0bd74790e086dcde1c242a31e27f992a04c07e2) * fix - In some cases undo/redo stack has excess steps (root cause is in the start move object event on a small not noticeable mouse move) (cherry picked from commit 912f39f38083e368979f34ef14821979c34482bb) * fix - It is impossible to remove an object using the "Undo the latest modification" button on second attempt (full undo, draw something, full undo again) (cherry picked from commit a7f77a130a497ac6fdecd59eb43c889dcc6cbe1a) * fix - Picked font family in the text editing tool is applied to the autoincrement tool (cherry picked from commit 11c5eb29b1078bd6aba91fe7a74c2682767ad47c) * Add git hash to version in the about dialog (cherry picked from commit b4dbf52b3217b51614100bd307046772a37dc484) * Add configuration option to limit undo steps (cherry picked from commit f13cbecabb172060b196a535348f145457ad2f0f) * Object delete operation is not registered on the undo stack (cherry picked from commit 5c966cb5d3702a4d735dd542ad03a80899250b4a) * fix - Unable to draw an object from second attempt after ColorPicker was called (cherry picked from commit 49a119886fec253376703e8aa2386e16bc23cbcf) * fix - App freezes and then crashes when changing object line thickness via Active thickness slider in the tool settings (cherry picked from commit 26fd64f1c333f70c67282630362cbc5fc8427a39) * fix - set min and max values for thickness slider to 1-100 (cherry picked from commit 6d8661666e4e199a3c29f991d52bef73ec36129c) * fix - Crash on Move Tool button with an active Text editor (cherry picked from commit 461f95da3afda56c0e9693e768e86b18d056eecc) * fix - Text is not modified when picking it as object in the list (cherry picked from commit 366bb0928b430d442dc67299353f7dc5ceb743b4) * fix - Text modification cannot be undone fix - Object that was created after the text object disappears after undo editing text (cherry picked from commit 79b2fb92aca65b177cffb386db141d30551a2b1c) * fix - Text is not saved if picking any object in the objects list without clicking at the empty space (cherry picked from commit 4679a744a3d2498fe27379f89d48b347a34ae0dc) * Last available undo step reset everything to the beginning (cherry picked from commit 4af7423d00cfaa9feabc905400aa3ac30fc4a3ea) * Missed changes (cherry-pick) for switching ColorPicker behaviour (right mouse click and hold to right mouse click and left click) Co-authored-by: Yuriy Puchkov --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 11 ++ src/config/generalconf.cpp | 34 ++++- src/config/generalconf.h | 3 + src/core/qguiappcurrentscreen.cpp | 2 - src/core/qguiappcurrentscreen.h | 2 - src/imgur.pri | 7 - src/tools/capturetool.h | 6 +- src/tools/text/texttool.cpp | 17 +++ src/tools/text/texttool.h | 4 + src/utils/confighandler.cpp | 15 +++ src/utils/confighandler.h | 3 + src/widgets/capture/capturetoolbutton.cpp | 4 + src/widgets/capture/capturewidget.cpp | 148 ++++++++++++++-------- src/widgets/capture/capturewidget.h | 7 + src/widgets/infowindow.cpp | 5 +- src/widgets/panel/sidepanelwidget.cpp | 1 + 17 files changed, 203 insertions(+), 68 deletions(-) delete mode 100644 src/imgur.pri diff --git a/CMakeLists.txt b/CMakeLists.txt index cda1da36..6eb1dde2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(GIT_API_URL "https://api.github.com/repos/flameshot-org/flameshot/releases/l # set(GIT_API_URL "https://api.github.com/repos/namecheap/flameshot/releases/latest") # TODO - fix it for all linux distros -# find_package (Git) +#find_package (Git) #if (GIT_FOUND) # message("git found: ${GIT_EXECUTABLE} in version ${GIT_VERSION_STRING}") # diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f738bfb..c34e9c52 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -197,6 +197,17 @@ if (WIN32) endif () endif () +find_package (Git) +if (GIT_FOUND) + message("git found: ${GIT_EXECUTABLE} in version ${GIT_VERSION_STRING}") + execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD OUTPUT_VARIABLE FLAMESHOT_GIT_HASH) + string(REGEX REPLACE "\r*\n$" "" FLAMESHOT_GIT_HASH "${FLAMESHOT_GIT_HASH}") + target_compile_definitions(flameshot PRIVATE FLAMESHOT_GIT_HASH="${FLAMESHOT_GIT_HASH}") + message("FLAMESHOT_GIT_HASH: ${FLAMESHOT_GIT_HASH}") +else() + target_compile_definitions(flameshot PRIVATE FLAMESHOT_GIT_HASH="-") + message("git command is not found") +endif () target_compile_definitions(flameshot PRIVATE APP_PREFIX="${CMAKE_INSTALL_PREFIX}") target_compile_definitions(flameshot PRIVATE APP_VERSION="v${PROJECT_VERSION}") target_compile_definitions(flameshot PRIVATE IMGUR_CLIENT_ID="313baf0c7b4d3ff") diff --git a/src/config/generalconf.cpp b/src/config/generalconf.cpp index 63eeac0a..538cdb3e 100644 --- a/src/config/generalconf.cpp +++ b/src/config/generalconf.cpp @@ -19,6 +19,7 @@ GeneralConf::GeneralConf(QWidget* parent) : QWidget(parent) , m_historyConfirmationToDelete(nullptr) + , m_undoLimit(nullptr) { m_layout = new QVBoxLayout(this); m_layout->setAlignment(Qt::AlignTop); @@ -35,6 +36,7 @@ GeneralConf::GeneralConf(QWidget* parent) initUseJpgForClipboard(); initSaveAfterCopy(); initUploadHistoryMaxSize(); + initUndoLimit(); // this has to be at the end initConfigButtons(); @@ -54,6 +56,7 @@ void GeneralConf::updateComponents() m_copyPathAfterSave->setChecked(config.copyPathAfterSaveEnabled()); m_useJpgForClipboard->setChecked(config.useJpgForClipboard()); m_uploadHistoryMaxSize->setValue(config.uploadHistoryMaxSizeValue()); + m_undoLimit->setValue(config.undoLimit()); if (!config.savePath().isEmpty()) { m_savePath->setText(config.savePath()); @@ -182,6 +185,7 @@ void GeneralConf::setActualFormData() m_historyConfirmationToDelete->setChecked( config.historyConfirmationToDelete()); m_uploadHistoryMaxSize->setValue(config.uploadHistoryMaxSizeValue()); + m_undoLimit->setValue(config.undoLimit()); m_useJpgForClipboard->setChecked(config.useJpgForClipboard()); } @@ -428,7 +432,6 @@ void GeneralConf::initUploadHistoryMaxSize() SIGNAL(valueChanged(int)), this, SLOT(uploadHistoryMaxSizeChanged(int))); - vboxLayout->addWidget(m_uploadHistoryMaxSize); } @@ -437,6 +440,35 @@ void GeneralConf::uploadHistoryMaxSizeChanged(int max) ConfigHandler().setUploadHistoryMaxSize(max); } +void GeneralConf::initUndoLimit() +{ + QGroupBox* box = new QGroupBox(tr("Undo limit")); + box->setFlat(true); + m_layout->addWidget(box); + m_layout->addStretch(); + + QVBoxLayout* vboxLayout = new QVBoxLayout(); + box->setLayout(vboxLayout); + + int limit = ConfigHandler().undoLimit(); + + m_undoLimit = new QSpinBox(this); + m_undoLimit->setMinimum(1); + m_undoLimit->setMaximum(999); + m_undoLimit->setValue(limit); + QString foreground = this->palette().windowText().color().name(); + m_undoLimit->setStyleSheet(QStringLiteral("color: %1").arg(foreground)); + + connect(m_undoLimit, SIGNAL(valueChanged(int)), this, SLOT(undoLimit(int))); + + vboxLayout->addWidget(m_undoLimit); +} + +void GeneralConf::undoLimit(int limit) +{ + ConfigHandler().setUndoLimit(limit); +} + void GeneralConf::initUseJpgForClipboard() { m_useJpgForClipboard = diff --git a/src/config/generalconf.h b/src/config/generalconf.h index 5e6fd0e1..54afc0e8 100644 --- a/src/config/generalconf.h +++ b/src/config/generalconf.h @@ -30,6 +30,7 @@ private slots: void autostartChanged(bool checked); void historyConfirmationToDelete(bool checked); void uploadHistoryMaxSizeChanged(int max); + void undoLimit(int limit); void saveAfterCopyChanged(bool checked); void changeSavePath(); void importConfiguration(); @@ -47,6 +48,7 @@ private: void initShowTrayIcon(); void initHistoryConfirmationToDelete(); void initUploadHistoryMaxSize(); + void initUndoLimit(); void initConfigButtons(); void initCheckForUpdates(); void initAutostart(); @@ -79,4 +81,5 @@ private: QCheckBox* m_historyConfirmationToDelete; QCheckBox* m_useJpgForClipboard; QSpinBox* m_uploadHistoryMaxSize; + QSpinBox* m_undoLimit; }; diff --git a/src/core/qguiappcurrentscreen.cpp b/src/core/qguiappcurrentscreen.cpp index ab9f196a..5d100b08 100644 --- a/src/core/qguiappcurrentscreen.cpp +++ b/src/core/qguiappcurrentscreen.cpp @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2021 Yuriy Puchkov -// -// Created by yuriypuchkov on 09.02.2021. #include "qguiappcurrentscreen.h" #include diff --git a/src/core/qguiappcurrentscreen.h b/src/core/qguiappcurrentscreen.h index 36b9ff6f..dc5e06aa 100644 --- a/src/core/qguiappcurrentscreen.h +++ b/src/core/qguiappcurrentscreen.h @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2021 Yuriy Puchkov -// -// Created by yuriypuchkov on 09.02.2021. #ifndef FLAMESHOT_QGUIAPPCURRENTSCREEN_H #define FLAMESHOT_QGUIAPPCURRENTSCREEN_H diff --git a/src/imgur.pri b/src/imgur.pri deleted file mode 100644 index 6e34b1e1..00000000 --- a/src/imgur.pri +++ /dev/null @@ -1,7 +0,0 @@ -# Use default Imgur client_id if user did not pass -# this variable to qmake -isEmpty(IMGUR_CLIENT_ID) { - IMGUR_CLIENT_ID = "313baf0c7b4d3ff" -} - -DEFINES += IMGUR_CLIENT_ID=\\\"$${IMGUR_CLIENT_ID}\\\" diff --git a/src/tools/capturetool.h b/src/tools/capturetool.h index 584f255f..23295549 100644 --- a/src/tools/capturetool.h +++ b/src/tools/capturetool.h @@ -72,9 +72,6 @@ public: REQ_CAPTURE_DONE_OK, // Instance this->widget()'s widget inside the editor under the mouse. REQ_ADD_CHILD_WIDGET, - // Instance this->widget()'s widget as a window which closes after - // closing the editor. - REQ_ADD_CHILD_WINDOW, // Instance this->widget()'s widget which handles its own lifetime. REQ_ADD_EXTERNAL_WIDGETS, // increase tool size for all tools @@ -129,6 +126,9 @@ public: virtual void setEditMode(bool b) { m_editMode = b; }; virtual bool editMode() { return m_editMode; }; + // return true if object was change after editMode + virtual bool isChanged() { return true; }; + // Counter for all object types (currently is used for the CircleCounter // only) virtual void setCount(int count) { m_count = count; }; diff --git a/src/tools/text/texttool.cpp b/src/tools/text/texttool.cpp index b33a36b8..5e562c66 100644 --- a/src/tools/text/texttool.cpp +++ b/src/tools/text/texttool.cpp @@ -174,6 +174,8 @@ void TextTool::process(QPainter& painter, const QPixmap& pixmap) return; } const int val = 5; + QFont orig_font = painter.font(); + QPen orig_pen = painter.pen(); QFontMetrics fm(m_font); QSize size(fm.boundingRect(QRect(), 0, m_text).size()); size.setWidth(size.width() + val * 2); @@ -185,6 +187,8 @@ void TextTool::process(QPainter& painter, const QPixmap& pixmap) if (!editMode()) { painter.drawText(m_textArea + QMargins(-val, -val, val, val), m_text); } + painter.setFont(orig_font); + painter.setPen(orig_pen); } void TextTool::drawObjectSelection(QPainter& painter) @@ -296,3 +300,16 @@ const QPoint* TextTool::pos() m_currentPos = m_textArea.topLeft(); return &m_currentPos; } + +void TextTool::setEditMode(bool b) +{ + if (b) { + m_textOld = m_text; + } + CaptureTool::setEditMode(b); +} + +bool TextTool::isChanged() +{ + return QString::compare(m_text, m_textOld, Qt::CaseInsensitive) != 0; +} \ No newline at end of file diff --git a/src/tools/text/texttool.h b/src/tools/text/texttool.h index 816596b7..70101166 100644 --- a/src/tools/text/texttool.h +++ b/src/tools/text/texttool.h @@ -38,6 +38,9 @@ public: const QPoint* pos() override; void drawObjectSelection(QPainter& painter) override; + void setEditMode(bool b) override; + bool isChanged() override; + protected: void copyParams(const TextTool* from, TextTool* to); ToolType nameID() const override; @@ -64,6 +67,7 @@ private: QFont m_font; QString m_text; + QString m_textOld; int m_size; QColor m_color; QRect m_textArea; diff --git a/src/utils/confighandler.cpp b/src/utils/confighandler.cpp index 95931f34..1d06e5f8 100644 --- a/src/utils/confighandler.cpp +++ b/src/utils/confighandler.cpp @@ -222,6 +222,21 @@ QString ConfigHandler::ignoreUpdateToVersion() return m_settings.value(QStringLiteral("ignoreUpdateToVersion")).toString(); } +void ConfigHandler::setUndoLimit(int value) +{ + m_settings.setValue(QStringLiteral("undoLimit"), value); +} + +int ConfigHandler::undoLimit() +{ + int limit = 100; + if (m_settings.contains(QStringLiteral("undoLimit"))) { + limit = m_settings.value(QStringLiteral("undoLimit")).toInt(); + limit = qBound(1, limit, 999); + } + return limit; +} + bool ConfigHandler::desktopNotificationValue() { bool res = true; diff --git a/src/utils/confighandler.h b/src/utils/confighandler.h index cf93540f..5e99d4fb 100644 --- a/src/utils/confighandler.h +++ b/src/utils/confighandler.h @@ -95,6 +95,9 @@ public: void setIgnoreUpdateToVersion(const QString& text); QString ignoreUpdateToVersion(); + void setUndoLimit(int value); + int undoLimit(); + QVector shortcuts(); void setShortcutsDefault(); bool setShortcut(const QString&, const QString&); diff --git a/src/widgets/capture/capturetoolbutton.cpp b/src/widgets/capture/capturetoolbutton.cpp index 6db5ffe5..bb4c8a25 100644 --- a/src/widgets/capture/capturetoolbutton.cpp +++ b/src/widgets/capture/capturetoolbutton.cpp @@ -45,6 +45,10 @@ CaptureToolButton::~CaptureToolButton() void CaptureToolButton::initButton() { + if (m_tool) { + delete m_tool; + m_tool = nullptr; + } m_tool = ToolFactory().CreateTool(m_buttonType, this); resize(GlobalValues::buttonBaseSize(), GlobalValues::buttonBaseSize()); diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp index a30eb5f7..86029a77 100644 --- a/src/widgets/capture/capturewidget.cpp +++ b/src/widgets/capture/capturewidget.cpp @@ -31,12 +31,13 @@ #include #include #include -#include #include #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #include "spdlog/spdlog.h" +#define MOUSE_DISTANCE_TO_START_MOVING 3 + // CaptureWidget is the main component used to capture the screen. It contains // an area of selection with its respective buttons. @@ -65,7 +66,11 @@ CaptureWidget::CaptureWidget(uint id, , m_lastPressedRedo(false) , m_panel(nullptr) , m_selection(nullptr) + , m_existingObjectIsChanged(false) + , m_startMove(false) { + m_undoStack.setUndoLimit(ConfigHandler().undoLimit() + 1); + // Base config of the widget m_eventFilter = new HoverEventFilter(this); connect(m_eventFilter, @@ -272,9 +277,6 @@ bool CaptureWidget::commitCurrentTool() m_toolWidget) { pushToolToStack(); } - if (m_activeTool) { - m_activeTool->setEditMode(false); - } releaseActiveTool(); return true; } @@ -297,6 +299,8 @@ void CaptureWidget::deleteToolWidgetOrClose() m_toolWidget->close(); delete m_toolWidget; m_toolWidget = nullptr; + } else if (m_colorPicker && m_colorPicker->isVisible()) { + m_colorPicker->hide(); } else { // close CaptureWidget close(); @@ -306,6 +310,12 @@ void CaptureWidget::deleteToolWidgetOrClose() void CaptureWidget::releaseActiveTool() { if (m_activeTool) { + if (m_activeTool->editMode()) { + m_activeTool->setEditMode(false); + if (m_activeTool->isChanged()) { + pushObjectsStateToUndoStack(); + } + } if (-1 == m_panel->activeLayerIndex() && m_activeButton) { // delete tool if no active selection, otherwise object shouldn't be // deleted, because it is in undo/redo stack @@ -400,8 +410,7 @@ bool CaptureWidget::startDrawObjectTool(const QPoint& pos) // 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)); + pushObjectsStateToUndoStack(); releaseActiveTool(); m_mouseIsClicked = false; } @@ -410,6 +419,16 @@ bool CaptureWidget::startDrawObjectTool(const QPoint& pos) return false; } +void CaptureWidget::pushObjectsStateToUndoStack() +{ + m_existingObjectIsChanged = false; + // push zero state to be able to do a complete undo + if (m_undoStack.count() == 0 || m_undoStack.index() == 0) { + m_undoStack.push(new ModificationCommand(this, m_captureToolObjects)); + } + m_undoStack.push(new ModificationCommand(this, m_captureToolObjects)); +} + int CaptureWidget::selectToolItemAtPos(const QPoint& pos) { // Try to select existing tool, "-1" - no active tool @@ -434,8 +453,14 @@ int CaptureWidget::selectToolItemAtPos(const QPoint& pos) void CaptureWidget::mousePressEvent(QMouseEvent* e) { + m_startMove = false; + m_startMovePos = QPoint(); m_dragStartPoint = m_mousePressedPos = e->pos(); m_activeToolOffsetToMouseOnStart = QPoint(); + if (m_colorPicker->isVisible()) { + updateCursor(); + return; + } // reset object selection if capture area selection is active if (m_selection->getMouseSide(e->pos()) != SelectionWidget::NO_SIDE) { @@ -443,6 +468,9 @@ void CaptureWidget::mousePressEvent(QMouseEvent* e) } if (e->button() == Qt::RightButton) { + if (m_activeTool && m_activeTool->editMode()) { + return; + } showColorPicker(m_mousePressedPos); } else if (e->button() == Qt::LeftButton) { m_showInitialMsg = false; @@ -471,8 +499,8 @@ void CaptureWidget::mousePressEvent(QMouseEvent* e) } } - // Commit current tool if it has edit widget and mouse click is outside of - // it + // Commit current tool if it has edit widget and mouse click is outside + // of it if (m_toolWidget && !m_toolWidget->geometry().contains(e->pos())) { commitCurrentTool(); m_panel->setToolWidget(nullptr); @@ -508,18 +536,34 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent* e) m_context.mousePos = e->pos(); bool symmetryMod = qApp->keyboardModifiers() & Qt::ShiftModifier; - int activeLayerIndex = m_panel->activeLayerIndex(); + int activeLayerIndex = -1; + if (m_mouseIsClicked) { + activeLayerIndex = m_panel->activeLayerIndex(); + } if (m_mouseIsClicked && !m_activeButton && activeLayerIndex >= 0) { // Move existing object - QPointer activeTool = - m_captureToolObjects.at(activeLayerIndex); - if (m_activeToolOffsetToMouseOnStart.isNull()) { - setCursor(Qt::OpenHandCursor); - m_activeToolOffsetToMouseOnStart = e->pos() - *activeTool->pos(); + if (!m_startMove) { + // Check for the minimal offset to start moving an object + if (m_startMovePos.isNull()) { + m_startMovePos = e->pos(); + } + if ((e->pos() - m_startMovePos).manhattanLength() > + MOUSE_DISTANCE_TO_START_MOVING) { + m_startMove = true; + } + } + if (m_startMove) { + QPointer 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); } - activeTool->move(e->pos() - m_activeToolOffsetToMouseOnStart); - m_activeToolIsMoved = true; - drawToolsData(false); } else if (m_mouseIsClicked && (!m_activeButton || (m_activeButton && m_activeButton->tool() && @@ -627,16 +671,14 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent* e) void CaptureWidget::mouseReleaseEvent(QMouseEvent* e) { - if (e->button() == Qt::RightButton || m_colorPicker->isVisible()) { + if (e->button() == Qt::LeftButton && m_colorPicker->isVisible()) { // Color picker m_colorPicker->hide(); 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)); + } else if (m_panel->activeLayerIndex() >= 0) { + pushObjectsStateToUndoStack(); } } else if (m_mouseIsClicked) { if (m_activeTool) { @@ -649,9 +691,7 @@ void CaptureWidget::mouseReleaseEvent(QMouseEvent* e) } } else { if (m_activeToolIsMoved) { - // push current state to the undo stack - m_undoStack.push( - new ModificationCommand(this, m_captureToolObjects)); + pushObjectsStateToUndoStack(); } // Try to select existing tool if it was in the selection area but @@ -786,17 +826,15 @@ void CaptureWidget::wheelEvent(QWheelEvent* e) m_activeButton->tool()->showMousePreview()) { 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)); + m_existingObjectIsChanged = true; } + emit thicknessChanged(m_context.thickness); } void CaptureWidget::resizeEvent(QResizeEvent* e) @@ -965,8 +1003,12 @@ void CaptureWidget::setState(CaptureToolButton* b) return; } - if (m_toolWidget && m_activeTool && m_activeTool->isValid()) { - pushToolToStack(); + if (m_toolWidget && m_activeTool) { + if (m_activeTool->isValid()) { + pushToolToStack(); + } else { + releaseActiveTool(); + } } if (m_activeButton != b) { processTool(b->tool()); @@ -1072,16 +1114,6 @@ void CaptureWidget::handleButtonSignal(CaptureTool::Request r) m_toolWidget->setFocus(); } break; - case CaptureTool::REQ_ADD_CHILD_WINDOW: - if (!m_activeTool) { - break; - } else { - QWidget* w = m_activeTool->widget(); - connect( - this, &CaptureWidget::destroyed, w, &QWidget::deleteLater); - w->show(); - } - break; case CaptureTool::REQ_ADD_EXTERNAL_WIDGETS: if (!m_activeTool) { break; @@ -1133,6 +1165,15 @@ void CaptureWidget::setDrawColor(const QColor& c) void CaptureWidget::updateActiveLayer(const int& layer) { + // TODO - refactor this part, make all objects to work with + // m_activeTool->isChanged() and remove m_existingObjectIsChanged + if (m_activeTool && m_activeTool->nameID() == ToolType::TEXT && + m_activeTool->isChanged()) { + commitCurrentTool(); + } + if (m_existingObjectIsChanged) { + pushObjectsStateToUndoStack(); + } drawToolsData(false, true); } @@ -1158,6 +1199,7 @@ void CaptureWidget::removeToolObject(int index) } m_context.circleCount = circleCount; } + pushObjectsStateToUndoStack(); drawToolsData(); } } @@ -1166,13 +1208,14 @@ void CaptureWidget::setDrawThickness(const int& t) { 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); + } else { + emit thicknessChanged(m_context.thickness); } } @@ -1375,12 +1418,12 @@ void CaptureWidget::updateCursor() void CaptureWidget::pushToolToStack() { - // push zero state to be able to do a complete undo - if (m_undoStack.count() == 0) { - m_undoStack.push(new ModificationCommand(this, m_captureToolObjects)); - } - // append current tool to the new state + bool isChanged = true; + if (m_activeTool && m_activeTool->editMode()) { + m_activeTool->setEditMode(false); + isChanged = m_activeTool->isChanged(); + } if (m_activeTool && m_activeButton) { disconnect(this, &CaptureWidget::colorChanged, @@ -1394,13 +1437,13 @@ void CaptureWidget::pushToolToStack() disconnect(m_panel->toolWidget(), nullptr, m_activeTool, nullptr); } - m_activeTool->setEditMode(false); m_captureToolObjects.append(m_activeTool); releaseActiveTool(); } - // push current state to the undo stack - m_undoStack.push(new ModificationCommand(this, m_captureToolObjects)); + if (isChanged) { + pushObjectsStateToUndoStack(); + } } void CaptureWidget::drawToolsData(bool updateLayersPanel, bool drawSelection) @@ -1530,6 +1573,11 @@ void CaptureWidget::undo() m_lastPressedUndo = true; m_lastPressedRedo = false; m_undoStack.undo(); + if (m_undoStack.index() == 0 && m_captureToolObjects.size() > 0) { + m_lastPressedUndo = false; + m_captureToolObjects.clear(); + drawToolsData(); + } } void CaptureWidget::redo() diff --git a/src/widgets/capture/capturewidget.h b/src/widgets/capture/capturewidget.h index 35700d64..999bb4e1 100644 --- a/src/widgets/capture/capturewidget.h +++ b/src/widgets/capture/capturewidget.h @@ -107,6 +107,7 @@ protected: void moveEvent(QMoveEvent* moveEvent) override; private: + void pushObjectsStateToUndoStack(); void releaseActiveTool(); void uncheckActiveTool(); int selectToolItemAtPos(const QPoint& pos); @@ -185,6 +186,12 @@ private: QUndoStack m_undoStack; + bool m_existingObjectIsChanged; + + // For start moving after more than X offset + QPoint m_startMovePos; + bool m_startMove; + // TODO - should be remove after fixing undo()/redo() functions bool m_lastPressedUndo; bool m_lastPressedRedo; diff --git a/src/widgets/infowindow.cpp b/src/widgets/infowindow.cpp index 7b2e844b..43eae3f2 100644 --- a/src/widgets/infowindow.cpp +++ b/src/widgets/infowindow.cpp @@ -55,8 +55,9 @@ void InfoWindow::initLabels() QLabel* versionTitleLabel = new QLabel(tr("Version"), this); versionTitleLabel->setAlignment(Qt::AlignHCenter); m_layout->addWidget(versionTitleLabel); - QString versionMsg = "Flameshot " + QStringLiteral(APP_VERSION) + - "\nCompiled with Qt " + QT_VERSION_STR; + QString versionMsg = "Flameshot " + QStringLiteral(APP_VERSION) + " (" + + QStringLiteral(FLAMESHOT_GIT_HASH) + + ")\nCompiled with Qt " + QT_VERSION_STR; QLabel* versionLabel = new QLabel(versionMsg, this); versionLabel->setAlignment(Qt::AlignHCenter); m_layout->addWidget(versionLabel); diff --git a/src/widgets/panel/sidepanelwidget.cpp b/src/widgets/panel/sidepanelwidget.cpp index c3ed01bb..b9e71edb 100644 --- a/src/widgets/panel/sidepanelwidget.cpp +++ b/src/widgets/panel/sidepanelwidget.cpp @@ -56,6 +56,7 @@ SidePanelWidget::SidePanelWidget(QPixmap* p, QWidget* parent) QFormLayout* colorForm = new QFormLayout(); m_thicknessSlider = new QSlider(Qt::Horizontal); + m_thicknessSlider->setRange(1, 100); m_thicknessSlider->setValue(m_thickness); m_colorLabel = new QLabel(); m_colorLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);