From 9228e46588c7bcc2ae6d49875db8855f2bee6d78 Mon Sep 17 00:00:00 2001 From: toofar Date: Wed, 27 Dec 2023 18:29:44 +1300 Subject: [PATCH] Add method of editing a pinned screenshot Add a method to allow editing a pinned screenshot by initiating a new screenshot over top of the pinned image, and then closing the old pinned image on success. This adds a new context menu to pinned screenshots. When selected the PinWidget will call the daemon to do the work. Thus this functionality only works when flameshot is running in daemon mode. The context menu options don't show up when not running in daemon mode (I don't know why they don't show up, other ones like the rotate and opacity ones also don't show up). This is not the ideal method of doing this, it doesn't actually edit the screenshot at all. I call it the "bait and switch" method of editing. The only previous attempt that I've soon to do this got caught up in dealing with screens with different DPI (pull/1565). While it would be amazing to be able to limit the whole "grab" region to be less than a screen, or even just one screen, I think this method of editing a pin in the full desktop cature mode is a step forward. It sure is for my workflow anyhow. I'm not familiar with c++ or this codebase so if there looks to be anything weird in this PR it's probably due to ignorance. I'm calling FlameshotDaemon from PinWidget, I'm not sure if I should be doing that or trying to access the Flameshot singleton directly, I just copied off of another tool which called `FlameshotDaemon::copyToClipboard()`. I'm not sure if doing `.geometry() - .layout()->contentsMargins()` is the correct way to get the image geometry, I was guided by what attributes I could see in GammaRay while inspecting a running flameshot. The method of disconnecting from the signals from within the lambdas is from here: https://stackoverflow.com/questions/14828678/disconnecting-lambda-functions-in-qt5 I contemplated calling the method in Flameshot "replacePin" or "captureFromPin" or something more technically accurate. But I figured the signature could stay a bit optimistic and if people would like the behaviour to be firmed up to match the goal in the future that could be done. Eg add functionality to the CaptureWidget to make it so you can't modify the capture region, change the grab region to be less than the whole desktop etc. Known issues: * you can move/resize the selection region, eg not just edit a pin but create a completely different one of a different region of the screen Relates to: https://github.com/flameshot-org/flameshot/issues/954 --- src/core/flameshotdaemon.cpp | 40 ++++++++++++++++++++++++++++++++++++ src/core/flameshotdaemon.h | 2 ++ src/tools/pin/pinwidget.cpp | 11 ++++++++++ src/tools/pin/pinwidget.h | 1 + 4 files changed, 54 insertions(+) diff --git a/src/core/flameshotdaemon.cpp b/src/core/flameshotdaemon.cpp index b8fdf3cdd3..8a9d2fba7d 100644 --- a/src/core/flameshotdaemon.cpp +++ b/src/core/flameshotdaemon.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -269,6 +270,45 @@ void FlameshotDaemon::attachPin(const QPixmap& pixmap, QRect geometry) pinWidget->activateWindow(); } +/** + * @brief Initiate a new pin capture to replace `existing`. + * + * Starts a new screenshot capture with the selection region initialized to be + * the same as `existing`. When it is completed the selection will be pinned and + * the previous pin (the `existing` argument) will be closed. + */ +void FlameshotDaemon::editPin(PinWidget& existing) +{ + CaptureRequest req(CaptureRequest::GRAPHICAL_MODE); + req.addTask(CaptureRequest::PIN); + QRect contentsRect = + existing.geometry() - existing.layout()->contentsMargins(); + req.setInitialSelection(contentsRect); + + Flameshot* flameshot = Flameshot::instance(); + flameshot->gui(req); + + // Connect to signals emitted when a capture (hopefully the one we just + // initiated!) is finished, both when it succeeds and when it is aborted. + auto successConn = std::make_shared(); + auto failureConn = std::make_shared(); + *successConn = QObject::connect(flameshot, + &Flameshot::captureTaken, + [&existing, successConn, failureConn]() { + // Only close the old pin on success. + existing.close(); + + QObject::disconnect(*successConn); + QObject::disconnect(*failureConn); + }); + *failureConn = QObject::connect(flameshot, + &Flameshot::captureTaken, + [&existing, successConn, failureConn]() { + QObject::disconnect(*successConn); + QObject::disconnect(*failureConn); + }); +} + void FlameshotDaemon::attachScreenshotToClipboard(const QPixmap& pixmap) { m_hostingClipboard = true; diff --git a/src/core/flameshotdaemon.h b/src/core/flameshotdaemon.h index e49c815e3c..f4f203b1ad 100644 --- a/src/core/flameshotdaemon.h +++ b/src/core/flameshotdaemon.h @@ -1,5 +1,6 @@ #pragma once +#include "pinwidget.h" #include #include #include @@ -27,6 +28,7 @@ class FlameshotDaemon : public QObject static void copyToClipboard(const QPixmap& capture); static void copyToClipboard(const QString& text, const QString& notification = ""); + static void editPin(PinWidget& pinned); static bool isThisInstanceHostingWidgets(); void sendTrayNotification( diff --git a/src/tools/pin/pinwidget.cpp b/src/tools/pin/pinwidget.cpp index 8baa19e783..f642d0cc31 100644 --- a/src/tools/pin/pinwidget.cpp +++ b/src/tools/pin/pinwidget.cpp @@ -7,6 +7,7 @@ #include "pinwidget.h" #include "qguiappcurrentscreen.h" #include "screenshotsaver.h" +#include "src/core/flameshotdaemon.h" #include "src/utils/confighandler.h" #include "src/utils/globalvalues.h" @@ -328,6 +329,10 @@ void PinWidget::showContextMenu(const QPoint& pos) &PinWidget::decreaseOpacity); contextMenu.addAction(&decreaseOpacityAction); + QAction editAction(tr("Edit Pin"), this); + connect(&editAction, &QAction::triggered, this, &PinWidget::edit); + contextMenu.addAction(&editAction); + QAction closePinAction(tr("Close"), this); connect(&closePinAction, &QAction::triggered, this, &PinWidget::closePin); contextMenu.addSeparator(); @@ -340,9 +345,15 @@ void PinWidget::copyToClipboard() { saveToClipboard(m_pixmap); } + void PinWidget::saveToFile() { hide(); saveToFilesystemGUI(m_pixmap); show(); } + +void PinWidget::edit() +{ + FlameshotDaemon::editPin(*this); +} diff --git a/src/tools/pin/pinwidget.h b/src/tools/pin/pinwidget.h index 1e26baff75..deb5f4dc67 100644 --- a/src/tools/pin/pinwidget.h +++ b/src/tools/pin/pinwidget.h @@ -61,4 +61,5 @@ private slots: void showContextMenu(const QPoint& pos); void copyToClipboard(); void saveToFile(); + void edit(); };