From 1cc5a2629246d3c5cbfe135cdb5f375403aeb0c9 Mon Sep 17 00:00:00 2001 From: Affir Vega <60240851+affirVega@users.noreply.github.com> Date: Sun, 30 Jan 2022 00:32:09 +0300 Subject: [PATCH] Created basic layer movement functionality (up, down) (#2108) * Created basic layer movement functionality (up, down) * Replaced `and` and `or` with `&&` and `||`, added constructor initialization * Added move icons. Added that moving layers pushes state to undo stack. * Cleaned svgs. * Circle counter doesn't change nubmer when reordered anymore * Changed move arrow SVGs * Make down arrow in size with up arrow, fix white colors from #feffff to #fff * SVGs in unitilypanel for buttons now choose color depending on color theme * Refactor tool removing code, removed fixme, fixed bug with minimal circleCount * Set minimal width for buttons Co-authored-by: Feskow Vega --- data/graphics.qrc | 5 ++ data/img/material/black/move_down.svg | 3 + data/img/material/black/move_up.svg | 3 + data/img/material/white/move_down.svg | 3 + data/img/material/white/move_up.svg | 3 + src/tools/capturecontext.h | 2 + src/widgets/capture/capturetoolobjects.cpp | 11 ++++ src/widgets/capture/capturetoolobjects.h | 1 + src/widgets/capture/capturewidget.cpp | 70 ++++++++++++++++++---- src/widgets/capture/capturewidget.h | 3 + src/widgets/panel/utilitypanel.cpp | 63 ++++++++++++++++--- src/widgets/panel/utilitypanel.h | 8 +++ 12 files changed, 158 insertions(+), 17 deletions(-) create mode 100644 data/img/material/black/move_down.svg create mode 100644 data/img/material/black/move_up.svg create mode 100644 data/img/material/white/move_down.svg create mode 100644 data/img/material/white/move_up.svg diff --git a/data/graphics.qrc b/data/graphics.qrc index 565cab9c7d..06ef24f4db 100644 --- a/data/graphics.qrc +++ b/data/graphics.qrc @@ -90,5 +90,10 @@ img/material/white/square.svg img/material/white/text.svg img/material/white/undo-variant.svg + img/material/black/move_down.svg + img/material/black/move_up.svg + img/material/white/move_down.svg + img/material/white/move_up.svg + img/material/white/delete.svg diff --git a/data/img/material/black/move_down.svg b/data/img/material/black/move_down.svg new file mode 100644 index 0000000000..ce9932df37 --- /dev/null +++ b/data/img/material/black/move_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/data/img/material/black/move_up.svg b/data/img/material/black/move_up.svg new file mode 100644 index 0000000000..0a7cac10eb --- /dev/null +++ b/data/img/material/black/move_up.svg @@ -0,0 +1,3 @@ + + + diff --git a/data/img/material/white/move_down.svg b/data/img/material/white/move_down.svg new file mode 100644 index 0000000000..129faea72f --- /dev/null +++ b/data/img/material/white/move_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/data/img/material/white/move_up.svg b/data/img/material/white/move_up.svg new file mode 100644 index 0000000000..a1b8dff08a --- /dev/null +++ b/data/img/material/white/move_up.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/tools/capturecontext.h b/src/tools/capturecontext.h index 1e9fc4b0c7..7c9b139675 100644 --- a/src/tools/capturecontext.h +++ b/src/tools/capturecontext.h @@ -27,6 +27,8 @@ struct CaptureContext QPoint mousePos; // Size of the active tool int toolSize; + // Current circle count + int circleCount; // Mode of the capture widget bool fullscreen; CaptureRequest request = CaptureRequest::GRAPHICAL_MODE; diff --git a/src/widgets/capture/capturetoolobjects.cpp b/src/widgets/capture/capturetoolobjects.cpp index 6365710b77..b0159f22e3 100644 --- a/src/widgets/capture/capturetoolobjects.cpp +++ b/src/widgets/capture/capturetoolobjects.cpp @@ -19,6 +19,17 @@ void CaptureToolObjects::append(const QPointer& captureTool) } } +void CaptureToolObjects::insert(int index, + const QPointer& captureTool) +{ + if (!captureTool.isNull() && index >= 0 && + index <= m_captureToolObjects.size()) { + m_captureToolObjects.insert(index, + captureTool->copy(captureTool->parent())); + m_imageCache.clear(); + } +} + QPointer CaptureToolObjects::at(int index) { if (index >= 0 && index < m_captureToolObjects.size()) { diff --git a/src/widgets/capture/capturetoolobjects.h b/src/widgets/capture/capturetoolobjects.h index 26e1769086..296479af0f 100644 --- a/src/widgets/capture/capturetoolobjects.h +++ b/src/widgets/capture/capturetoolobjects.h @@ -14,6 +14,7 @@ class CaptureToolObjects : public QObject explicit CaptureToolObjects(QObject* parent = nullptr); QList> captureToolObjects(); void append(const QPointer& captureTool); + void insert(int index, const QPointer& captureTool); void removeAt(int index); void clear(); int size(); diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp index c34a5f1149..b66fe6cd30 100644 --- a/src/widgets/capture/capturewidget.cpp +++ b/src/widgets/capture/capturewidget.cpp @@ -73,6 +73,8 @@ CaptureWidget::CaptureWidget(const CaptureRequest& req, { m_undoStack.setUndoLimit(ConfigHandler().undoLimit()); + m_context.circleCount = 1; + // Base config of the widget m_eventFilter = new HoverEventFilter(this); connect(m_eventFilter, @@ -555,6 +557,8 @@ bool CaptureWidget::startDrawObjectTool(const QPoint& pos) // point and shouldn't wait for second point and move event m_activeTool->drawEnd(m_context.mousePos); + m_activeTool->setCount(m_context.circleCount++); + m_captureToolObjectsBackup = m_captureToolObjects; m_captureToolObjects.append(m_activeTool); pushObjectsStateToUndoStack(); @@ -967,6 +971,14 @@ void CaptureWidget::initPanel() &UtilityPanel::layerChanged, this, &CaptureWidget::updateActiveLayer); + connect(m_panel, + &UtilityPanel::moveUpClicked, + this, + &CaptureWidget::onMoveCaptureToolUp); + connect(m_panel, + &UtilityPanel::moveDownClicked, + this, + &CaptureWidget::onMoveCaptureToolDown); m_sidePanel = new SidePanelWidget(&m_context.screenshot, this); connect(m_sidePanel, @@ -1266,6 +1278,26 @@ void CaptureWidget::updateActiveLayer(int layer) updateSelectionState(); } +void CaptureWidget::onMoveCaptureToolUp(int captureToolIndex) +{ + m_captureToolObjectsBackup = m_captureToolObjects; + pushObjectsStateToUndoStack(); + auto tool = m_captureToolObjects.at(captureToolIndex); + m_captureToolObjects.removeAt(captureToolIndex); + m_captureToolObjects.insert(captureToolIndex - 1, tool); + updateLayersPanel(); +} + +void CaptureWidget::onMoveCaptureToolDown(int captureToolIndex) +{ + m_captureToolObjectsBackup = m_captureToolObjects; + pushObjectsStateToUndoStack(); + auto tool = m_captureToolObjects.at(captureToolIndex); + m_captureToolObjects.removeAt(captureToolIndex); + m_captureToolObjects.insert(captureToolIndex + 1, tool); + updateLayersPanel(); +} + void CaptureWidget::selectAll() { m_selection->show(); @@ -1279,26 +1311,30 @@ void CaptureWidget::removeToolObject(int index) { --index; if (index >= 0 && index < m_captureToolObjects.size()) { + // in case this tool is circle counter + int removedCircleCount = -1; + const CaptureTool::Type currentToolType = m_captureToolObjects.at(index)->type(); m_captureToolObjectsBackup = m_captureToolObjects; update( paddedUpdateRect(m_captureToolObjects.at(index)->boundingRect())); - m_captureToolObjects.removeAt(index); if (currentToolType == CaptureTool::TYPE_CIRCLECOUNT) { - // Do circle count reindex - int circleCount = 1; + removedCircleCount = m_captureToolObjects.at(index)->count(); + --m_context.circleCount; + // Decrement circle counter numbers starting from deleted circle for (int cnt = 0; cnt < m_captureToolObjects.size(); cnt++) { auto toolItem = m_captureToolObjects.at(cnt); if (toolItem->type() != CaptureTool::TYPE_CIRCLECOUNT) { continue; } - if (cnt >= index) { - m_captureToolObjects.at(cnt)->setCount(circleCount); + auto circleTool = m_captureToolObjects.at(cnt); + if (circleTool->count() >= removedCircleCount) { + circleTool->setCount(circleTool->count() - 1); } - circleCount++; } } + m_captureToolObjects.removeAt(index); pushObjectsStateToUndoStack(); drawToolsData(); updateLayersPanel(); @@ -1481,11 +1517,7 @@ void CaptureWidget::drawToolsData(bool drawSelection) // TODO refactor this for performance. The objects should not all be updated // at once every time QPixmap pixmapItem = m_context.origScreenshot; - int circleCount = 1; for (auto toolItem : m_captureToolObjects.captureToolObjects()) { - if (toolItem->type() == CaptureTool::TYPE_CIRCLECOUNT) { - toolItem->setCount(circleCount++); - } processPixmapWithTool(&pixmapItem, toolItem); update(paddedUpdateRect(toolItem->boundingRect())); } @@ -1547,6 +1579,20 @@ void CaptureWidget::makeChild(QWidget* w) w->installEventFilter(m_eventFilter); } +void CaptureWidget::restoreCircleCountState() +{ + int largest = 0; + for (int cnt = 0; cnt < m_captureToolObjects.size(); cnt++) { + auto toolItem = m_captureToolObjects.at(cnt); + if (toolItem->type() != CaptureTool::TYPE_CIRCLECOUNT) { + continue; + } + if (toolItem->count() > largest) + largest = toolItem->count(); + } + m_context.circleCount = largest + 1; +} + /** * @brief Wrapper around `new QShortcut`, properly handling Enter/Return. */ @@ -1609,6 +1655,8 @@ void CaptureWidget::undo() m_undoStack.undo(); drawToolsData(); updateLayersPanel(); + + restoreCircleCountState(); } void CaptureWidget::redo() @@ -1620,6 +1668,8 @@ void CaptureWidget::redo() drawToolsData(); update(); updateLayersPanel(); + + restoreCircleCountState(); } QRect CaptureWidget::extendedSelection() const diff --git a/src/widgets/capture/capturewidget.h b/src/widgets/capture/capturewidget.h index 93d51412bd..0c0ade5ddf 100644 --- a/src/widgets/capture/capturewidget.h +++ b/src/widgets/capture/capturewidget.h @@ -76,6 +76,8 @@ private slots: void onToolSizeChanged(int size); void onToolSizeSettled(int size); void updateActiveLayer(int layer); + void onMoveCaptureToolUp(int captureToolIndex); + void onMoveCaptureToolDown(int captureToolIndex); void selectAll(); public: @@ -115,6 +117,7 @@ private slots: void updateLayersPanel(); void pushToolToStack(); void makeChild(QWidget* w); + void restoreCircleCountState(); QList newShortcut(const QKeySequence& key, QWidget* parent, diff --git a/src/widgets/panel/utilitypanel.cpp b/src/widgets/panel/utilitypanel.cpp index acafcf0b7e..7760e90fe4 100644 --- a/src/widgets/panel/utilitypanel.cpp +++ b/src/widgets/panel/utilitypanel.cpp @@ -22,6 +22,8 @@ UtilityPanel::UtilityPanel(CaptureWidget* captureWidget) , m_layersLayout(nullptr) , m_captureTools(nullptr) , m_buttonDelete(nullptr) + , m_buttonMoveUp(nullptr) + , m_buttonMoveDown(nullptr) { initInternalPanel(); setAttribute(Qt::WA_TransparentForMouseEvents); @@ -141,12 +143,31 @@ void UtilityPanel::initInternalPanel() QHBoxLayout* layersButtons = new QHBoxLayout(); m_layersLayout->addLayout(layersButtons); + m_layersLayout->addWidget(m_captureTools); + bool isDark = ColorUtils::colorIsDark(bgColor); + QString coloredIconPath = + isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath(); + m_buttonDelete = new QPushButton(this); - m_buttonDelete->setIcon(QIcon(":/img/material/black/delete.svg")); + m_buttonDelete->setIcon(QIcon(coloredIconPath + "delete.svg")); + m_buttonDelete->setMinimumWidth(m_buttonDelete->height()); m_buttonDelete->setDisabled(true); + + m_buttonMoveUp = new QPushButton(this); + m_buttonMoveUp->setIcon(QIcon(coloredIconPath + "move_up.svg")); + m_buttonMoveUp->setMinimumWidth(m_buttonMoveUp->height()); + m_buttonMoveUp->setDisabled(true); + + m_buttonMoveDown = new QPushButton(this); + m_buttonMoveDown->setIcon(QIcon(coloredIconPath + "move_down.svg")); + m_buttonMoveDown->setMinimumWidth(m_buttonMoveDown->height()); + m_buttonMoveDown->setDisabled(true); + layersButtons->addWidget(m_buttonDelete); + layersButtons->addWidget(m_buttonMoveUp); + layersButtons->addWidget(m_buttonMoveDown); layersButtons->addStretch(); connect(m_buttonDelete, @@ -154,6 +175,16 @@ void UtilityPanel::initInternalPanel() this, SLOT(slotButtonDelete(bool))); + connect(m_buttonMoveUp, + &QPushButton::clicked, + this, + &UtilityPanel::slotUpClicked); + + connect(m_buttonMoveDown, + &QPushButton::clicked, + this, + &UtilityPanel::slotDownClicked); + // Bottom QPushButton* closeButton = new QPushButton(this); closeButton->setText(tr("Close")); @@ -192,14 +223,32 @@ int UtilityPanel::activeLayerIndex() void UtilityPanel::onCurrentRowChanged(int currentRow) { - if (currentRow > 0) { - m_buttonDelete->setDisabled(false); - } else { - m_buttonDelete->setDisabled(true); - } + m_buttonDelete->setDisabled(currentRow <= 0); + m_buttonMoveDown->setDisabled(currentRow == 0 || + currentRow + 1 == m_captureTools->count()); + m_buttonMoveUp->setDisabled(currentRow <= 1); + emit layerChanged(activeLayerIndex()); } +void UtilityPanel::slotUpClicked(bool clicked) +{ + Q_UNUSED(clicked); + // subtract 1 because there's in m_captureTools as [0] element + int toolRow = m_captureTools->currentRow() - 1; + m_captureTools->setCurrentRow(toolRow); + emit moveUpClicked(toolRow); +} + +void UtilityPanel::slotDownClicked(bool clicked) +{ + Q_UNUSED(clicked); + // subtract 1 because there's in m_captureTools as [0] element + int toolRow = m_captureTools->currentRow() - 1; + m_captureTools->setCurrentRow(toolRow + 2); + emit moveDownClicked(toolRow); +} + void UtilityPanel::slotButtonDelete(bool clicked) { Q_UNUSED(clicked) @@ -218,4 +267,4 @@ void UtilityPanel::slotButtonDelete(bool clicked) bool UtilityPanel::isVisible() const { return !m_internalPanel->isHidden(); -} \ No newline at end of file +} diff --git a/src/widgets/panel/utilitypanel.h b/src/widgets/panel/utilitypanel.h index ee8d4eee8f..020a627349 100644 --- a/src/widgets/panel/utilitypanel.h +++ b/src/widgets/panel/utilitypanel.h @@ -36,12 +36,18 @@ class UtilityPanel : public QWidget signals: void layerChanged(int layer); + void moveUpClicked(int currentRow); + void moveDownClicked(int currentRow); public slots: void toggle(); void slotButtonDelete(bool clicked); void onCurrentRowChanged(int currentRow); +private slots: + void slotUpClicked(bool clicked); + void slotDownClicked(bool clicked); + private: void initInternalPanel(); @@ -55,5 +61,7 @@ public slots: QVBoxLayout* m_layersLayout; QListWidget* m_captureTools; QPushButton* m_buttonDelete; + QPushButton* m_buttonMoveUp; + QPushButton* m_buttonMoveDown; CaptureWidget* m_captureWidget; };