diff --git a/data/dbus/org.flameshot.Flameshot.xml b/data/dbus/org.flameshot.Flameshot.xml
index c2e94db8..2463d8f5 100644
--- a/data/dbus/org.flameshot.Flameshot.xml
+++ b/data/dbus/org.flameshot.Flameshot.xml
@@ -3,90 +3,38 @@
-
-
+
+
-
-
+
+
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/flameshot.example.ini b/flameshot.example.ini
index 97f330cc..65f1200f 100644
--- a/flameshot.example.ini
+++ b/flameshot.example.ini
@@ -48,6 +48,12 @@
;; Whether the tray icon is disabled (bool)
;disabledTrayIcon=false
;
+;; Automatically close daemon when it's not needed (not available on Windows)
+;autoCloseIdleDaemon=false
+;
+;; Allow multiple instances of `flameshot gui` to run at the same time
+;allowMultipleGuiInstances=false
+;
;; Last used tool thickness (int)
;drawThickness=1
;
diff --git a/src/config/generalconf.cpp b/src/config/generalconf.cpp
index 60e486ad..15cbf306 100644
--- a/src/config/generalconf.cpp
+++ b/src/config/generalconf.cpp
@@ -49,6 +49,10 @@ GeneralConf::GeneralConf(QWidget* parent)
initSaveAfterCopy();
inituploadHistoryMax();
initUndoLimit();
+ initAllowMultipleGuiInstances();
+#if !defined(Q_OS_WIN)
+ initAutoCloseIdleDaemon();
+#endif
m_layout->addStretch();
@@ -73,6 +77,8 @@ void GeneralConf::_updateComponents(bool allowEmptySavePath)
m_historyConfirmationToDelete->setChecked(
config.historyConfirmationToDelete());
m_checkForUpdates->setChecked(config.checkForUpdates());
+ m_allowMultipleGuiInstances->setChecked(config.allowMultipleGuiInstances());
+ m_autoCloseIdleDaemon->setChecked(config.autoCloseIdleDaemon());
m_showStartupLaunchMessage->setChecked(config.showStartupLaunchMessage());
m_screenshotPathFixedCheck->setChecked(config.savePathFixed());
m_uploadHistoryMax->setValue(config.uploadHistoryMax());
@@ -106,22 +112,22 @@ void GeneralConf::showDesktopNotificationChanged(bool checked)
ConfigHandler().setShowDesktopNotification(checked);
}
-void GeneralConf::showTrayIconChanged(bool checked)
-{
- auto controller = Controller::getInstance();
- if (checked) {
- controller->enableTrayIcon();
- } else {
- controller->disableTrayIcon();
- }
-}
-
void GeneralConf::checkForUpdatesChanged(bool checked)
{
ConfigHandler().setCheckForUpdates(checked);
Controller::getInstance()->setCheckForUpdatesEnabled(checked);
}
+void GeneralConf::allowMultipleGuiInstancesChanged(bool checked)
+{
+ ConfigHandler().setAllowMultipleGuiInstances(checked);
+}
+
+void GeneralConf::autoCloseIdleDaemonChanged(bool checked)
+{
+ ConfigHandler().setAutoCloseIdleDaemon(checked);
+}
+
void GeneralConf::autostartChanged(bool checked)
{
ConfigHandler().setStartupLaunch(checked);
@@ -250,10 +256,9 @@ void GeneralConf::initShowTrayIcon()
m_showTray->setToolTip(tr("Show the systemtray icon"));
m_scrollAreaLayout->addWidget(m_showTray);
- connect(m_showTray,
- &QCheckBox::stateChanged,
- this,
- &GeneralConf::showTrayIconChanged);
+ connect(m_showTray, &QCheckBox::clicked, this, [](bool checked) {
+ ConfigHandler().setDisabledTrayIcon(!checked);
+ });
#endif
}
@@ -314,6 +319,32 @@ void GeneralConf::initCheckForUpdates()
&GeneralConf::checkForUpdatesChanged);
}
+void GeneralConf::initAllowMultipleGuiInstances()
+{
+ m_allowMultipleGuiInstances = new QCheckBox(
+ tr("Allow multiple flameshot GUI instances simultaneously"), this);
+ m_allowMultipleGuiInstances->setToolTip(tr(
+ "This allows you to take screenshots of flameshot itself for example."));
+ m_scrollAreaLayout->addWidget(m_allowMultipleGuiInstances);
+ connect(m_allowMultipleGuiInstances,
+ &QCheckBox::clicked,
+ this,
+ &GeneralConf::allowMultipleGuiInstancesChanged);
+}
+
+void GeneralConf::initAutoCloseIdleDaemon()
+{
+ m_autoCloseIdleDaemon = new QCheckBox(
+ tr("Automatically close daemon when it is not needed"), this);
+ m_autoCloseIdleDaemon->setToolTip(
+ tr("Automatically close daemon when it is not needed"));
+ m_scrollAreaLayout->addWidget(m_autoCloseIdleDaemon);
+ connect(m_autoCloseIdleDaemon,
+ &QCheckBox::clicked,
+ this,
+ &GeneralConf::autoCloseIdleDaemonChanged);
+}
+
void GeneralConf::initAutostart()
{
m_autostart = new QCheckBox(tr("Launch at startup"), this);
diff --git a/src/config/generalconf.h b/src/config/generalconf.h
index 90abdb6c..05262744 100644
--- a/src/config/generalconf.h
+++ b/src/config/generalconf.h
@@ -27,8 +27,9 @@ private slots:
void showHelpChanged(bool checked);
void showSidePanelButtonChanged(bool checked);
void showDesktopNotificationChanged(bool checked);
- void showTrayIconChanged(bool checked);
void checkForUpdatesChanged(bool checked);
+ void allowMultipleGuiInstancesChanged(bool checked);
+ void autoCloseIdleDaemonChanged(bool checked);
void autostartChanged(bool checked);
void historyConfirmationToDelete(bool checked);
void uploadHistoryMaxChanged(int max);
@@ -55,6 +56,8 @@ private:
void initUndoLimit();
void initConfigButtons();
void initCheckForUpdates();
+ void initAllowMultipleGuiInstances();
+ void initAutoCloseIdleDaemon();
void initAutostart();
void initShowStartupLaunchMessage();
void initCopyAndCloseAfterUpload();
@@ -75,6 +78,8 @@ private:
QCheckBox* m_helpMessage;
QCheckBox* m_sidePanelButton;
QCheckBox* m_checkForUpdates;
+ QCheckBox* m_allowMultipleGuiInstances;
+ QCheckBox* m_autoCloseIdleDaemon;
QCheckBox* m_autostart;
QCheckBox* m_showStartupLaunchMessage;
QCheckBox* m_copyAndCloseAfterUpload;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8518184b..482d71ca 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,6 +1,17 @@
-target_sources(flameshot PRIVATE controller.h flameshotdbusadapter.h qguiappcurrentscreen.h)
+target_sources(flameshot PRIVATE
+ controller.h
+ flameshotdaemon.h
+ flameshotdbusadapter.h
+ qguiappcurrentscreen.h
+)
-target_sources(flameshot PRIVATE capturerequest.cpp controller.cpp flameshotdbusadapter.cpp qguiappcurrentscreen.cpp)
+target_sources(flameshot PRIVATE
+ capturerequest.cpp
+ controller.cpp
+ flameshotdaemon.cpp
+ flameshotdbusadapter.cpp
+ qguiappcurrentscreen.cpp
+)
IF (WIN32)
target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp)
diff --git a/src/core/capturerequest.cpp b/src/core/capturerequest.cpp
index 7a7250f6..07ba5308 100644
--- a/src/core/capturerequest.cpp
+++ b/src/core/capturerequest.cpp
@@ -23,63 +23,8 @@ CaptureRequest::CaptureRequest(CaptureRequest::CaptureMode mode,
, m_delay(delay)
, m_tasks(tasks)
, m_data(data)
- , m_forcedID(false)
- , m_id(0)
{}
-void CaptureRequest::setStaticID(uint id)
-{
- m_forcedID = true;
- m_id = id;
-}
-
-uint CaptureRequest::id() const
-{
- if (m_forcedID) {
- return m_id;
- }
-
- uint id = 0;
- QVector v;
- v << qHash(m_mode) << qHash(m_delay * QDateTime::currentMSecsSinceEpoch())
- << qHash(m_path) << qHash(m_tasks) << m_data.toInt();
- for (uint i : v) {
- id ^= i + 0x9e3779b9 + (id << 6) + (id >> 2);
- }
- return id;
-}
-
-QByteArray CaptureRequest::serialize() const
-{
- QByteArray data;
- QDataStream stream(&data, QIODevice::WriteOnly);
- // Convert enums to integers
- qint32 tasks = m_tasks, mode = m_mode;
- stream << mode << m_delay << tasks << m_data << m_forcedID << m_id << m_path
- << m_initialSelection;
- return data;
-}
-
-CaptureRequest CaptureRequest::deserialize(const QByteArray& data)
-{
- QDataStream stream(data);
- CaptureRequest request;
- qint32 tasks, mode;
- stream >> mode;
- stream >> request.m_delay;
- stream >> tasks;
- stream >> request.m_data;
- stream >> request.m_forcedID;
- stream >> request.m_id;
- stream >> request.m_path;
- stream >> request.m_initialSelection;
-
- // Convert integers to enums
- request.m_tasks = static_cast(tasks);
- request.m_mode = static_cast(mode);
- return request;
-}
-
CaptureRequest::CaptureMode CaptureRequest::captureMode() const
{
return m_mode;
@@ -118,7 +63,7 @@ void CaptureRequest::addTask(CaptureRequest::ExportTask task)
m_tasks |= task;
}
-void CaptureRequest::removeTask(CaptureRequest::ExportTask task)
+void CaptureRequest::removeTask(ExportTask task)
{
((int&)m_tasks) &= ~task;
}
@@ -139,59 +84,3 @@ void CaptureRequest::setInitialSelection(const QRect& selection)
{
m_initialSelection = selection;
}
-
-void CaptureRequest::exportCapture(const QPixmap& capture)
-{
- if (m_tasks & SAVE) {
- if (m_path.isEmpty()) {
- ScreenshotSaver(m_id).saveToFilesystemGUI(capture);
- } else {
- ScreenshotSaver(m_id).saveToFilesystem(capture, m_path);
- }
- }
-
- if (m_tasks & COPY) {
- ScreenshotSaver().saveToClipboard(capture);
- }
-
- if (m_tasks & PIN) {
- QWidget* widget = new PinWidget(capture, m_pinWindowGeometry);
- widget->show();
- widget->activateWindow();
- if (m_mode == SCREEN_MODE || m_mode == FULLSCREEN_MODE) {
- SystemNotification().sendMessage(
- QObject::tr("Full screen screenshot pinned to screen"));
- }
- }
-
- if (m_tasks & UPLOAD) {
- if (!ConfigHandler().uploadWithoutConfirmation()) {
- ImgUploadDialog* dialog = new ImgUploadDialog();
- if (dialog->exec() == QDialog::Rejected) {
- return;
- }
- }
-
- ImgUploaderBase* widget = ImgUploaderManager().uploader(capture);
- widget->show();
- widget->activateWindow();
- // NOTE: lambda can't capture 'this' because it might be destroyed later
- ExportTask tasks = m_tasks;
- QObject::connect(
- widget, &ImgUploaderBase::uploadOk, [widget, tasks](const QUrl& url) {
- if (ConfigHandler().copyAndCloseAfterUpload()) {
- if (!(tasks & COPY)) {
- SystemNotification().sendMessage(
- QObject::tr("URL copied to clipboard."));
-
- QApplication::clipboard()->setText(url.toString());
- widget->close();
- } else {
- widget->showPostUploadDialog();
- }
- } else {
- widget->showPostUploadDialog();
- }
- });
- }
-}
diff --git a/src/core/capturerequest.h b/src/core/capturerequest.h
index eda997b6..0cb79716 100644
--- a/src/core/capturerequest.h
+++ b/src/core/capturerequest.h
@@ -37,8 +37,6 @@ public:
void setStaticID(uint id);
uint id() const;
- QByteArray serialize() const;
- static CaptureRequest deserialize(const QByteArray& data);
uint delay() const;
QString path() const;
QVariant data() const;
@@ -51,7 +49,6 @@ public:
void addSaveTask(const QString& path = QString());
void addPinTask(const QRect& pinWindowGeometry);
void setInitialSelection(const QRect& selection);
- void exportCapture(const QPixmap& capture);
private:
CaptureMode m_mode;
@@ -61,9 +58,6 @@ private:
QVariant m_data;
QRect m_pinWindowGeometry, m_initialSelection;
- bool m_forcedID;
- uint m_id;
-
CaptureRequest() {}
};
diff --git a/src/core/controller.cpp b/src/core/controller.cpp
index 6ffb5d7f..487d8973 100644
--- a/src/core/controller.cpp
+++ b/src/core/controller.cpp
@@ -2,13 +2,18 @@
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "controller.h"
+#include "flameshotdaemon.h"
#if defined(Q_OS_MACOS)
#include "external/QHotkey/QHotkey"
#endif
+#include "pinwidget.h"
+#include "screenshotsaver.h"
#include "src/config/configwindow.h"
#include "src/core/qguiappcurrentscreen.h"
+#include "src/tools/imgupload/imguploadermanager.h"
+#include "src/tools/imgupload/storages/imguploaderbase.h"
#include "src/utils/confighandler.h"
#include "src/utils/globalvalues.h"
#include "src/utils/history.h"
@@ -18,14 +23,17 @@
#include "src/widgets/capture/capturewidget.h"
#include "src/widgets/capturelauncher.h"
#include "src/widgets/historywidget.h"
+#include "src/widgets/imguploaddialog.h"
#include "src/widgets/infowindow.h"
#include "src/widgets/notificationwidget.h"
#include
#include
+#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -64,21 +72,6 @@ Controller::Controller()
m_appLatestVersion = QStringLiteral(APP_VERSION).replace("v", "");
qApp->setQuitOnLastWindowClosed(false);
- // init tray icon
-#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
- if (!ConfigHandler().disabledTrayIcon()) {
- enableTrayIcon();
- }
-#elif defined(Q_OS_WIN)
- enableTrayIcon();
-
- GlobalShortcutFilter* nativeFilter = new GlobalShortcutFilter(this);
- qApp->installNativeEventFilter(nativeFilter);
- connect(nativeFilter, &GlobalShortcutFilter::printPressed, this, [this]() {
- this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
- });
-#endif
-
QString StyleSheet = CaptureButton::globalStyleSheet();
qApp->setStyleSheet(StyleSheet);
@@ -103,6 +96,18 @@ Controller::Controller()
qApp,
[&]() { this->showRecentUploads(); });
#endif
+ connect(ConfigHandler::getInstance(),
+ &ConfigHandler::fileChanged,
+ this,
+ [this]() {
+ ConfigHandler config;
+ if (config.disabledTrayIcon()) {
+ disableTrayIcon();
+ } else {
+ enableTrayIcon();
+ }
+ });
+
if (ConfigHandler().checkForUpdates()) {
getLatestAvailableVersion();
}
@@ -119,14 +124,6 @@ Controller* Controller::getInstance()
return &c;
}
-void Controller::enableExports()
-{
- connect(
- this, &Controller::captureTaken, this, &Controller::handleCaptureTaken);
- connect(
- this, &Controller::captureFailed, this, &Controller::handleCaptureFailed);
-}
-
void Controller::setCheckForUpdatesEnabled(const bool enabled)
{
if (m_appUpdates != nullptr) {
@@ -217,38 +214,33 @@ void Controller::appUpdates()
void Controller::requestCapture(const CaptureRequest& request)
{
- uint id = request.id();
- m_requestMap.insert(id, request);
-
switch (request.captureMode()) {
case CaptureRequest::FULLSCREEN_MODE:
- doLater(request.delay(), this, [this, id]() {
- this->startFullscreenCapture(id);
+ doLater(request.delay(), this, [this, request]() {
+ startFullscreenCapture(request);
});
break;
case CaptureRequest::SCREEN_MODE: {
int&& number = request.data().toInt();
- doLater(request.delay(), this, [this, id, number]() {
- this->startScreenGrab(id, number);
+ doLater(request.delay(), this, [this, request, number]() {
+ startScreenGrab(request, number);
});
break;
}
case CaptureRequest::GRAPHICAL_MODE: {
- QString&& path = request.path();
- doLater(request.delay(), this, [this, id, path]() {
- this->startVisualCapture(id, path);
+ doLater(request.delay(), this, [this, request]() {
+ startVisualCapture(request);
});
break;
}
default:
- emit captureFailed(id);
+ handleCaptureFailed();
break;
}
}
// creation of a new capture in GUI mode
-void Controller::startVisualCapture(const uint id,
- const QString& forcedSavePath)
+void Controller::startVisualCapture(const CaptureRequest& req)
{
#if defined(Q_OS_MACOS)
// This is required on MacOS because of Mission Control. If you'll switch to
@@ -263,6 +255,7 @@ void Controller::startVisualCapture(const uint id,
#endif
if (nullptr == m_captureWindow) {
+ // TODO is this unnecessary now?
int timeout = 5000; // 5 seconds
const int delay = 100;
QWidget* modalWidget = nullptr;
@@ -281,17 +274,9 @@ void Controller::startVisualCapture(const uint id,
return;
}
- m_captureWindow = new CaptureWidget(id, forcedSavePath);
- // m_captureWindow = new CaptureWidget(id, forcedSavePath, false); //
+ m_captureWindow = new CaptureWidget(req);
+ // m_captureWindow = new CaptureWidget(forcedSavePath, false); //
// debug
- connect(m_captureWindow,
- &CaptureWidget::captureFailed,
- this,
- &Controller::captureFailed);
- connect(m_captureWindow,
- &CaptureWidget::captureTaken,
- this,
- &Controller::captureTaken);
#ifdef Q_OS_WIN
m_captureWindow->show();
@@ -311,11 +296,11 @@ void Controller::startVisualCapture(const uint id,
m_appLatestUrl);
}
} else {
- emit captureFailed(id);
+ emit captureFailed();
}
}
-void Controller::startScreenGrab(const uint id, const int screenNumber)
+void Controller::startScreenGrab(CaptureRequest req, const int screenNumber)
{
bool ok = true;
QScreen* screen;
@@ -333,7 +318,7 @@ void Controller::startScreenGrab(const uint id, const int screenNumber)
}
QPixmap p(ScreenGrabber().grabScreen(screen, ok));
if (ok) {
- CaptureRequest& req = *requests().find(id);
+ QRect geometry = ScreenGrabber().screenGeometry(screen);
QRect region = req.initialSelection();
if (region.isNull()) {
region = ScreenGrabber().screenGeometry(screen);
@@ -347,9 +332,9 @@ void Controller::startScreenGrab(const uint id, const int screenNumber)
// change geometry for pin task
req.addPinTask(region);
}
- emit captureTaken(id, p, region);
+ exportCapture(p, geometry, req);
} else {
- emit captureFailed(id);
+ handleCaptureFailed();
}
}
@@ -390,6 +375,23 @@ void Controller::openLauncherWindow()
#endif
}
+void Controller::initTrayIcon()
+{
+#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
+ if (!ConfigHandler().disabledTrayIcon()) {
+ enableTrayIcon();
+ }
+#elif defined(Q_OS_WIN)
+ enableTrayIcon();
+
+ GlobalShortcutFilter* nativeFilter = new GlobalShortcutFilter(this);
+ qApp->installNativeEventFilter(nativeFilter);
+ connect(nativeFilter, &GlobalShortcutFilter::printPressed, this, [this]() {
+ this->requestCapture(CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
+ });
+#endif
+}
+
void Controller::enableTrayIcon()
{
ConfigHandler().setDisabledTrayIcon(false);
@@ -415,7 +417,7 @@ void Controller::enableTrayIcon()
}
#else
// Wait 400 ms to hide the QMenu
- doLater(400, this, [this]() { this->startVisualCapture(); });
+ doLater(400, this, [this]() { startVisualCapture(); });
#endif
});
QAction* launcherAction = new QAction(tr("&Open Launcher"), this);
@@ -560,40 +562,115 @@ void Controller::showRecentUploads()
#endif
}
-void Controller::sendCaptureSaved(uint id, const QString& savePath)
+void Controller::exportCapture(QPixmap capture,
+ QRect& selection,
+ const CaptureRequest& req)
{
- emit captureSaved(id, savePath);
+ using CR = CaptureRequest;
+ int tasks = req.tasks(), mode = req.captureMode();
+ QString path = req.path();
+
+ if (tasks & CR::PRINT_GEOMETRY) {
+ QByteArray byteArray;
+ QBuffer buffer(&byteArray);
+ QTextStream(stdout)
+ << selection.width() << "x" << selection.height() << "+"
+ << selection.x() << "+" << selection.y() << "\n";
+ }
+
+ if (tasks & CR::PRINT_RAW) {
+ QByteArray byteArray;
+ QBuffer buffer(&byteArray);
+ capture.save(&buffer, "PNG");
+ QFile file;
+ file.open(stdout, QIODevice::WriteOnly);
+
+ file.write(byteArray);
+ file.close();
+ }
+
+ if (tasks & CR::SAVE) {
+ if (req.path().isEmpty()) {
+ ScreenshotSaver().saveToFilesystemGUI(capture);
+ } else {
+ ScreenshotSaver().saveToFilesystem(capture, path);
+ }
+ }
+
+ if (tasks & CR::COPY) {
+ FlameshotDaemon::copyToClipboard(capture);
+ }
+
+ if (tasks & CR::PIN) {
+ FlameshotDaemon::createPin(capture, selection);
+ if (mode == CR::SCREEN_MODE || mode == CR::FULLSCREEN_MODE) {
+ SystemNotification().sendMessage(
+ QObject::tr("Full screen screenshot pinned to screen"));
+ }
+ }
+
+ if (tasks & CR::UPLOAD) {
+ if (!ConfigHandler().uploadWithoutConfirmation()) {
+ ImgUploadDialog* dialog = new ImgUploadDialog();
+ if (dialog->exec() == QDialog::Rejected) {
+ return;
+ }
+ }
+
+ ImgUploaderBase* widget = ImgUploaderManager().uploader(capture);
+ widget->show();
+ widget->activateWindow();
+ // NOTE: lambda can't capture 'this' because it might be destroyed later
+ CR::ExportTask tasks = tasks;
+ QObject::connect(
+ widget, &ImgUploaderBase::uploadOk, [=](const QUrl& url) {
+ if (ConfigHandler().copyAndCloseAfterUpload()) {
+ if (!(tasks & CR::COPY)) {
+ SystemNotification().sendMessage(
+ QObject::tr("URL copied to clipboard."));
+
+ QApplication::clipboard()->setText(url.toString());
+ widget->close();
+ } else {
+ widget->showPostUploadDialog();
+ }
+ } else {
+ widget->showPostUploadDialog();
+ }
+ });
+ }
+
+ if (!(tasks & CR::UPLOAD)) {
+ emit captureTaken(capture, selection);
+ }
}
-void Controller::startFullscreenCapture(const uint id)
+void Controller::startFullscreenCapture(const CaptureRequest& req)
{
bool ok = true;
QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
- CaptureRequest req(*requests().find(id));
QRect region = req.initialSelection();
if (!region.isNull()) {
p = p.copy(region);
}
if (ok) {
- // selection parameter is unused here
- emit captureTaken(id, p, {});
+ QRect selection; // `flameshot full` does not support --selection
+ exportCapture(p, selection, req);
} else {
- emit captureFailed(id);
+ handleCaptureFailed();
}
}
-void Controller::handleCaptureTaken(uint id, QPixmap p)
+void Controller::handleCaptureTaken(const CaptureRequest& req,
+ QPixmap p,
+ QRect selection)
{
- auto it = m_requestMap.find(id);
- if (it != m_requestMap.end()) {
- it.value().exportCapture(p);
- m_requestMap.erase(it);
- }
+ exportCapture(p, selection, req);
}
-void Controller::handleCaptureFailed(uint id)
+void Controller::handleCaptureFailed()
{
- m_requestMap.remove(id);
+ emit captureFailed();
}
void Controller::doLater(int msec, QObject* receiver, lambda func)
diff --git a/src/core/controller.h b/src/core/controller.h
index 9263aaa4..08ac0c1c 100644
--- a/src/core/controller.h
+++ b/src/core/controller.h
@@ -37,16 +37,14 @@ public:
~Controller();
void operator=(const Controller&) = delete;
- void enableExports();
-
void setCheckForUpdatesEnabled(const bool enabled);
QMap& requests();
signals:
- void captureTaken(uint id, QPixmap p, const QRect& selection);
- void captureFailed(uint id);
- void captureSaved(uint id, QString savePath);
+ // TODO remove all parameters from captureTaken and update dependencies
+ void captureTaken(QPixmap p, const QRect& selection);
+ void captureFailed();
public slots:
void requestCapture(const CaptureRequest& request);
@@ -55,6 +53,8 @@ public slots:
void openInfoWindow();
void appUpdates();
void openLauncherWindow();
+ // TODO move tray icon handling to FlameshotDaemon
+ void initTrayIcon();
void enableTrayIcon();
void disableTrayIcon();
void sendTrayNotification(
@@ -66,16 +66,19 @@ public slots:
void showRecentUploads();
- void sendCaptureSaved(uint id, const QString& savePath);
+ void exportCapture(QPixmap p, QRect& selection, const CaptureRequest& req);
private slots:
- void startFullscreenCapture(const uint id = 0);
- void startVisualCapture(const uint id = 0,
- const QString& forcedSavePath = QString());
- void startScreenGrab(const uint id = 0, const int screenNumber = -1);
+ void startFullscreenCapture(const CaptureRequest& req);
+ void startVisualCapture(
+ const CaptureRequest& req = CaptureRequest::GRAPHICAL_MODE);
+ void startScreenGrab(CaptureRequest req, const int screenNumber = -1);
- void handleCaptureTaken(uint id, QPixmap p);
- void handleCaptureFailed(uint id);
+public slots: // TODO move these up
+ void handleCaptureTaken(const CaptureRequest& req,
+ QPixmap p,
+ QRect selection);
+ void handleCaptureFailed();
void handleReplyCheckUpdates(QNetworkReply* reply);
diff --git a/src/core/flameshotdaemon.cpp b/src/core/flameshotdaemon.cpp
new file mode 100644
index 00000000..ba66210c
--- /dev/null
+++ b/src/core/flameshotdaemon.cpp
@@ -0,0 +1,262 @@
+#include "flameshotdaemon.h"
+
+#include "confighandler.h"
+#include "controller.h"
+#include "pinwidget.h"
+#include "screenshotsaver.h"
+#include "systemnotification.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * @brief A way of accessing the flameshot daemon both from the daemon itself,
+ * and from subcommands.
+ *
+ * The daemon is necessary in order to:
+ * - Host the system tray,
+ * - Listen for hotkey events that will trigger captures,
+ * - Host pinned screenshot widgets,
+ * - Host the clipboard on X11, where the clipboard gets lost once flameshot
+ * quits.
+ *
+ * If the `autoCloseIdleDaemon` option is true, the daemon will close as soon as
+ * it is not needed to host pinned screenshots and the clipboard. On Windows,
+ * this option is disabled and the daemon always persists, because the system
+ * tray is currently the only way to interact with flameshot.
+ *
+ * Both the daemon and non-daemon flameshot processes use the same public API,
+ * which is implemented as static methods. In the daemon process, this class is
+ * also instantiated as a singleton, so it can listen to D-Bus calls via the
+ * sigslot mechanism. The instantiation is done by calling `start` (this must be
+ * done only in the daemon process).
+ *
+ * @note The daemon will be automatically launched where necessary, via D-Bus.
+ * This applies only on Linux.
+ */
+FlameshotDaemon::FlameshotDaemon()
+ : m_persist(false)
+ , m_hostingClipboard(false)
+ , m_clipboardSignalBlocked(false)
+{
+ connect(
+ QApplication::clipboard(), &QClipboard::dataChanged, this, [this]() {
+ if (!m_hostingClipboard || m_clipboardSignalBlocked) {
+ m_clipboardSignalBlocked = false;
+ return;
+ }
+ m_hostingClipboard = false;
+ quitIfIdle();
+ });
+ // init tray icon
+ Controller::getInstance()->initTrayIcon();
+#ifdef Q_OS_WIN
+ m_persist = true;
+#else
+ m_persist = !ConfigHandler().autoCloseIdleDaemon();
+ connect(ConfigHandler::getInstance(),
+ &ConfigHandler::fileChanged,
+ this,
+ [this]() { m_persist = !ConfigHandler().autoCloseIdleDaemon(); });
+#endif
+}
+
+void FlameshotDaemon::start()
+{
+ if (!m_instance) {
+ m_instance = new FlameshotDaemon();
+ }
+}
+
+void FlameshotDaemon::createPin(QPixmap capture, QRect geometry)
+{
+ if (instance()) {
+ instance()->attachPin(capture, geometry);
+ return;
+ }
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream << capture;
+ stream << geometry;
+ QDBusMessage m = createMethodCall(QStringLiteral("attachPin"));
+ m << data;
+ call(m);
+}
+
+void FlameshotDaemon::copyToClipboard(QPixmap capture)
+{
+ if (instance()) {
+ instance()->attachScreenshotToClipboard(capture);
+ return;
+ }
+
+ QDBusMessage m =
+ createMethodCall(QStringLiteral("attachScreenshotToClipboard"));
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream << capture;
+
+ m << data;
+ call(m);
+}
+
+void FlameshotDaemon::copyToClipboard(QString text, QString notification)
+{
+ if (instance()) {
+ instance()->attachTextToClipboard(text, notification);
+ return;
+ }
+ auto m = createMethodCall(QStringLiteral("attachTextToClipboard"));
+
+ m << text << notification;
+
+ QDBusConnection sessionBus = QDBusConnection::sessionBus();
+ checkDBusConnection(sessionBus);
+ sessionBus.call(m);
+}
+
+void FlameshotDaemon::enableTrayIcon(bool enable)
+{
+#if !defined(Q_OS_WIN)
+ if (!instance()) {
+ return;
+ }
+ if (enable) {
+ Controller::getInstance()->enableTrayIcon();
+ } else {
+ Controller::getInstance()->disableTrayIcon();
+ }
+#endif
+}
+
+/**
+ * @brief Is this instance of flameshot hosting any windows as a daemon?
+ */
+bool FlameshotDaemon::isThisInstanceHostingWidgets()
+{
+ return instance() && !instance()->m_widgets.isEmpty();
+}
+
+FlameshotDaemon* FlameshotDaemon::instance()
+{
+ // Because we don't use DBus on MacOS, each instance of flameshot is its own
+ // mini-daemon, responsible for hosting its own persistent widgets (e.g.
+ // pins).
+#if defined(Q_OS_MACOS)
+ start();
+#endif
+ return m_instance;
+}
+
+/**
+ * @brief Quit the daemon if it has nothing to do and the 'persist' flag is not
+ * set.
+ */
+void FlameshotDaemon::quitIfIdle()
+{
+ if (m_persist && !instance()) {
+ return;
+ }
+ if (!m_hostingClipboard && m_widgets.isEmpty()) {
+ qApp->exit(0);
+ }
+}
+
+// SERVICE METHODS
+
+void FlameshotDaemon::attachPin(QPixmap pixmap, QRect geometry)
+{
+ PinWidget* pinWidget = new PinWidget(pixmap, geometry);
+ m_widgets.append(pinWidget);
+ connect(pinWidget, &QObject::destroyed, this, [=]() {
+ m_widgets.removeOne(pinWidget);
+ quitIfIdle();
+ });
+
+ pinWidget->show();
+ pinWidget->activateWindow();
+}
+
+void FlameshotDaemon::attachScreenshotToClipboard(QPixmap pixmap)
+{
+ m_hostingClipboard = true;
+ QClipboard* clipboard = QApplication::clipboard();
+ clipboard->blockSignals(true);
+ // This variable is necessary because the signal doesn't get blocked on
+ // windows for some reason
+ m_clipboardSignalBlocked = true;
+ ScreenshotSaver().saveToClipboard(pixmap);
+ clipboard->blockSignals(false);
+}
+
+// D-BUS ADAPTER METHODS
+
+void FlameshotDaemon::attachPin(const QByteArray& data)
+{
+ QDataStream stream(data);
+ QPixmap pixmap;
+ QRect geometry;
+
+ stream >> pixmap;
+ stream >> geometry;
+
+ attachPin(pixmap, geometry);
+}
+
+void FlameshotDaemon::attachScreenshotToClipboard(const QByteArray& screenshot)
+{
+ QDataStream stream(screenshot);
+ QPixmap p;
+ stream >> p;
+
+ attachScreenshotToClipboard(p);
+}
+
+void FlameshotDaemon::attachTextToClipboard(QString text, QString notification)
+{
+ m_hostingClipboard = true;
+ QClipboard* clipboard = QApplication::clipboard();
+
+ clipboard->blockSignals(true);
+ // This variable is necessary because the signal doesn't get blocked on
+ // windows for some reason
+ m_clipboardSignalBlocked = true;
+ clipboard->setText(text);
+ if (!notification.isEmpty()) {
+ SystemNotification().sendMessage(notification);
+ }
+ clipboard->blockSignals(false);
+}
+
+QDBusMessage FlameshotDaemon::createMethodCall(QString method)
+{
+ QDBusMessage m =
+ QDBusMessage::createMethodCall(QStringLiteral("org.flameshot.Flameshot"),
+ QStringLiteral("/"),
+ QLatin1String(""),
+ method);
+ return m;
+}
+
+void FlameshotDaemon::checkDBusConnection(const QDBusConnection& connection)
+{
+ if (!connection.isConnected()) {
+ SystemNotification().sendMessage(tr("Unable to connect via DBus"));
+ qApp->exit(1);
+ }
+}
+
+void FlameshotDaemon::call(const QDBusMessage& m)
+{
+ QDBusConnection sessionBus = QDBusConnection::sessionBus();
+ checkDBusConnection(sessionBus);
+ sessionBus.call(m);
+}
+
+// STATIC ATTRIBUTES
+FlameshotDaemon* FlameshotDaemon::m_instance = nullptr;
diff --git a/src/core/flameshotdaemon.h b/src/core/flameshotdaemon.h
new file mode 100644
index 00000000..25206066
--- /dev/null
+++ b/src/core/flameshotdaemon.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include
+#include
+#include
+
+class QPixmap;
+class QRect;
+class QDBusMessage;
+class QDBusConnection;
+
+class FlameshotDaemon : private QObject
+{
+ Q_OBJECT
+public:
+ static void start();
+ static FlameshotDaemon* instance();
+ static void createPin(QPixmap capture, QRect geometry);
+ static void copyToClipboard(QPixmap capture);
+ static void copyToClipboard(QString text, QString notification = "");
+ static void enableTrayIcon(bool enable);
+ static bool isThisInstanceHostingWidgets();
+
+private:
+ FlameshotDaemon();
+ void quitIfIdle();
+ void attachPin(QPixmap pixmap, QRect geometry);
+ void attachScreenshotToClipboard(QPixmap pixmap);
+
+ void attachPin(const QByteArray& data);
+ void attachScreenshotToClipboard(const QByteArray& screenshot);
+ void attachTextToClipboard(QString text, QString notification);
+
+private:
+ static QDBusMessage createMethodCall(QString method);
+ static void checkDBusConnection(const QDBusConnection& connection);
+ static void call(const QDBusMessage& m);
+
+ bool m_persist;
+ bool m_hostingClipboard;
+ bool m_clipboardSignalBlocked;
+ QList m_widgets;
+ static FlameshotDaemon* m_instance;
+
+ friend class FlameshotDBusAdapter;
+};
diff --git a/src/core/flameshotdbusadapter.cpp b/src/core/flameshotdbusadapter.cpp
index 9b66d13e..e6e5ee20 100644
--- a/src/core/flameshotdbusadapter.cpp
+++ b/src/core/flameshotdbusadapter.cpp
@@ -2,72 +2,26 @@
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "flameshotdbusadapter.h"
-#include "src/core/controller.h"
-#include "src/utils/confighandler.h"
-#include "src/utils/screengrabber.h"
-#include "src/utils/screenshotsaver.h"
-#include "src/utils/systemnotification.h"
-#include
+#include "src/core/flameshotdaemon.h"
+
FlameshotDBusAdapter::FlameshotDBusAdapter(QObject* parent)
: QDBusAbstractAdaptor(parent)
-{
- auto controller = Controller::getInstance();
- connect(controller,
- &Controller::captureFailed,
- this,
- &FlameshotDBusAdapter::captureFailed);
- connect(controller,
- &Controller::captureTaken,
- this,
- &FlameshotDBusAdapter::handleCaptureTaken);
- connect(controller,
- &Controller::captureSaved,
- this,
- &FlameshotDBusAdapter::captureSaved);
-}
+{}
FlameshotDBusAdapter::~FlameshotDBusAdapter() {}
-void FlameshotDBusAdapter::requestCapture(const QByteArray& requestData)
+void FlameshotDBusAdapter::attachScreenshotToClipboard(const QByteArray& data)
{
- CaptureRequest req = CaptureRequest::deserialize(requestData);
- Controller::getInstance()->requestCapture(req);
+ FlameshotDaemon::instance()->attachScreenshotToClipboard(data);
}
-void FlameshotDBusAdapter::openLauncher()
+void FlameshotDBusAdapter::attachTextToClipboard(QString text,
+ QString notification)
{
- Controller::getInstance()->openLauncherWindow();
+ FlameshotDaemon::instance()->attachTextToClipboard(text, notification);
}
-void FlameshotDBusAdapter::openConfig()
+void FlameshotDBusAdapter::attachPin(const QByteArray& data)
{
- Controller::getInstance()->openConfigWindow();
-}
-
-void FlameshotDBusAdapter::trayIconEnabled(bool enabled)
-{
- auto controller = Controller::getInstance();
- if (enabled) {
- controller->enableTrayIcon();
- } else {
- controller->disableTrayIcon();
- }
-}
-
-void FlameshotDBusAdapter::autostartEnabled(bool enabled)
-{
- ConfigHandler().setStartupLaunch(enabled);
- auto controller = Controller::getInstance();
- // Autostart is not saved in a .ini file, requires manual update
- controller->updateConfigComponents();
-}
-
-void FlameshotDBusAdapter::handleCaptureTaken(uint id,
- const QPixmap& p,
- const QRect& selection)
-{
- QByteArray byteArray;
- QBuffer buffer(&byteArray);
- p.save(&buffer, "PNG");
- emit captureTaken(id, byteArray, selection);
+ FlameshotDaemon::instance()->attachPin(data);
}
diff --git a/src/core/flameshotdbusadapter.h b/src/core/flameshotdbusadapter.h
index 655739a9..d9e96632 100644
--- a/src/core/flameshotdbusadapter.h
+++ b/src/core/flameshotdbusadapter.h
@@ -3,7 +3,6 @@
#pragma once
-#include "src/core/controller.h"
#include
class FlameshotDBusAdapter : public QDBusAbstractAdaptor
@@ -15,18 +14,8 @@ public:
explicit FlameshotDBusAdapter(QObject* parent = nullptr);
virtual ~FlameshotDBusAdapter();
-signals:
- void captureTaken(uint id, QByteArray rawImage, QRect selection);
- void captureFailed(uint id);
- void captureSaved(uint id, QString savePath);
-
public slots:
- Q_NOREPLY void requestCapture(const QByteArray& requestData);
- Q_NOREPLY void openLauncher();
- Q_NOREPLY void openConfig();
- Q_NOREPLY void trayIconEnabled(bool enabled);
- Q_NOREPLY void autostartEnabled(bool enabled);
-
-private slots:
- void handleCaptureTaken(uint id, const QPixmap& p, const QRect& selection);
+ Q_NOREPLY void attachScreenshotToClipboard(const QByteArray& data);
+ Q_NOREPLY void attachTextToClipboard(QString text, QString notification);
+ Q_NOREPLY void attachPin(const QByteArray& data);
};
diff --git a/src/main.cpp b/src/main.cpp
index 8b78c6f0..ec4fd0f1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,6 +11,7 @@
#include "src/config/styleoverride.h"
#include "src/core/capturerequest.h"
#include "src/core/controller.h"
+#include "src/core/flameshotdaemon.h"
#include "src/utils/confighandler.h"
#include "src/utils/filenamehandler.h"
#include "src/utils/pathinfo.h"
@@ -19,7 +20,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -28,22 +29,12 @@
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
#include "src/core/flameshotdbusadapter.h"
-#include "src/utils/dbusutils.h"
+#include
#include
#include
#include
#endif
-int waitAfterConnecting(int delay, QCoreApplication& app)
-{
- QTimer t;
- t.setInterval(delay + 1000 * 60 * 15); // 15 minutes timeout
- QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit);
- t.start();
- // wait
- return app.exec();
-}
-
#ifdef Q_OS_LINUX
// source: https://github.com/ksnip/ksnip/issues/416
void wayland_hacks()
@@ -56,6 +47,42 @@ void wayland_hacks()
}
#endif
+void requestCaptureAndWait(const CaptureRequest& req)
+{
+ Controller* controller = Controller::getInstance();
+ controller->requestCapture(req);
+ QObject::connect(
+ controller, &Controller::captureTaken, [&](QPixmap, QRect) {
+ // Only useful on MacOS because each instance hosts its own widgets
+ if (!FlameshotDaemon::isThisInstanceHostingWidgets()) {
+ qApp->exit(0);
+ }
+ });
+ QObject::connect(controller, &Controller::captureFailed, []() {
+ // TODO use abstract logger
+ // TODO do we have to do more stuff here?
+ QTextStream(stderr) << "screenshot aborted\n";
+ qApp->exit(1);
+ });
+ qApp->exec();
+}
+
+QSharedMemory* guiMutexLock()
+{
+ QString key = "org.flameshot.Flameshot-" APP_VERSION;
+ auto* shm = new QSharedMemory(key);
+#ifdef Q_OS_UNIX
+ // Destroy shared memory if the last instance crashed on Unix
+ shm->attach();
+ delete shm;
+ shm = new QSharedMemory(key);
+#endif
+ if (!shm->create(1)) {
+ return nullptr;
+ }
+ return shm;
+}
+
int main(int argc, char* argv[])
{
#ifdef Q_OS_LINUX
@@ -67,7 +94,9 @@ int main(int argc, char* argv[])
// required for the button serialization
// TODO: change to QVector in v1.0
qRegisterMetaTypeStreamOperators>("QList");
- qApp->setApplicationVersion(static_cast(APP_VERSION));
+ QCoreApplication::setApplicationVersion(APP_VERSION);
+ QCoreApplication::setApplicationName(QStringLiteral("flameshot"));
+ QCoreApplication::setOrganizationName(QStringLiteral("flameshot"));
// no arguments, just launch Flameshot
if (argc == 1) {
@@ -97,14 +126,14 @@ int main(int argc, char* argv[])
"_",
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
- app.installTranslator(&translator);
- app.installTranslator(&qtTranslator);
- app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
- app.setApplicationName(QStringLiteral("flameshot"));
- app.setOrganizationName(QStringLiteral("flameshot"));
+ qApp->installTranslator(&translator);
+ qApp->installTranslator(&qtTranslator);
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
auto c = Controller::getInstance();
-#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
+ FlameshotDaemon::start();
+
+#if !(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
new FlameshotDBusAdapter(c);
QDBusConnection dbus = QDBusConnection::sessionBus();
if (!dbus.isConnected()) {
@@ -114,20 +143,14 @@ int main(int argc, char* argv[])
dbus.registerObject(QStringLiteral("/"), c);
dbus.registerService(QStringLiteral("org.flameshot.Flameshot"));
#endif
- // Exporting captures must be connected after the dbus interface
- // or the dbus signal gets blocked until we end the exports.
- c->enableExports();
- return app.exec();
+ return qApp->exec();
}
-#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
+#if !defined(Q_OS_WIN)
/*--------------|
* CLI parsing |
* ------------*/
- QCoreApplication app(argc, argv);
- app.setApplicationName(QStringLiteral("flameshot"));
- app.setOrganizationName(QStringLiteral("flameshot"));
- app.setApplicationVersion(qApp->applicationVersion());
+ new QCoreApplication(argc, argv);
CommandLineParser parser;
// Add description
parser.setDescription(
@@ -305,7 +328,7 @@ int main(int argc, char* argv[])
checkOption },
configArgument);
// Parse
- if (!parser.parse(app.arguments())) {
+ if (!parser.parse(qApp->arguments())) {
goto finish;
}
@@ -313,18 +336,28 @@ int main(int argc, char* argv[])
//--------------
if (parser.isSet(helpOption) || parser.isSet(versionOption)) {
} else if (parser.isSet(launcherArgument)) { // LAUNCHER
- QDBusMessage m = QDBusMessage::createMethodCall(
- QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("openLauncher"));
- QDBusConnection sessionBus = QDBusConnection::sessionBus();
- if (!sessionBus.isConnected()) {
- SystemNotification().sendMessage(
- QObject::tr("Unable to connect via DBus"));
- }
- sessionBus.call(m);
+ delete qApp;
+ new QApplication(argc, argv);
+ Controller* controller = Controller::getInstance();
+ controller->openLauncherWindow();
+ qApp->exec();
} else if (parser.isSet(guiArgument)) { // GUI
+ delete qApp;
+ new QApplication(argc, argv);
+ // Prevent multiple instances of 'flameshot gui' from running if not
+ // configured to do so.
+ if (!ConfigHandler().allowMultipleGuiInstances()) {
+ auto* mutex = guiMutexLock();
+ if (!mutex) {
+ return 1;
+ }
+ QObject::connect(
+ qApp, &QCoreApplication::aboutToQuit, qApp, [mutex]() {
+ mutex->detach();
+ delete mutex;
+ });
+ }
+
// Option values
QString path = parser.value(pathOption);
if (!path.isEmpty()) {
@@ -338,7 +371,6 @@ int main(int argc, char* argv[])
bool pin = parser.isSet(pinOption);
bool upload = parser.isSet(uploadOption);
bool acceptOnSelect = parser.isSet(acceptOnSelectOption);
- DBusUtils dbusUtils;
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
if (!region.isEmpty()) {
req.setInitialSelection(Region().value(region).toRect());
@@ -368,28 +400,12 @@ int main(int argc, char* argv[])
req.addSaveTask();
}
}
- uint id = req.id();
- req.setStaticID(id);
-
- // Send message
- QDBusMessage m = QDBusMessage::createMethodCall(
- QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("requestCapture"));
- m << req.serialize();
- QDBusConnection sessionBus = QDBusConnection::sessionBus();
- dbusUtils.checkDBusConnection(sessionBus);
- sessionBus.call(m);
-
- if (raw) {
- dbusUtils.connectPrintCapture(sessionBus, id);
- return waitAfterConnecting(delay, app);
- } else if (printGeometry) {
- dbusUtils.connectSelectionCapture(sessionBus, id);
- return waitAfterConnecting(delay, app);
- }
+ requestCaptureAndWait(req);
} else if (parser.isSet(fullArgument)) { // FULL
+ // Recreate the application as a QApplication
+ // TODO find a way so we don't have to do this
+ delete qApp;
+ new QApplication(argc, argv);
// Option values
QString path = parser.value(pathOption);
if (!path.isEmpty()) {
@@ -421,33 +437,12 @@ int main(int argc, char* argv[])
if (!clipboard && path.isEmpty() && !raw && !upload) {
req.addSaveTask();
}
- uint id = req.id();
- req.setStaticID(id);
- DBusUtils dbusUtils;
-
- // Send message
- QDBusMessage m = QDBusMessage::createMethodCall(
- QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("requestCapture"));
- m << req.serialize();
- QDBusConnection sessionBus = QDBusConnection::sessionBus();
- dbusUtils.checkDBusConnection(sessionBus);
- sessionBus.call(m);
-
- if (raw) {
- dbusUtils.connectPrintCapture(sessionBus, id);
- // timeout just in case
- QTimer t;
- t.setInterval(delay + 2000);
- QObject::connect(
- &t, &QTimer::timeout, qApp, &QCoreApplication::quit);
- t.start();
- // wait
- return app.exec();
- }
+ requestCaptureAndWait(req);
} else if (parser.isSet(screenArgument)) { // SCREEN
+ // Recreate the application as a QApplication
+ // TODO find a way so we don't have to do this
+ delete qApp;
+ new QApplication(argc, argv);
QString numberStr = parser.value(screenNumberOption);
// Option values
int number =
@@ -494,47 +489,21 @@ int main(int argc, char* argv[])
req.addSaveTask();
}
- uint id = req.id();
- req.setStaticID(id);
- DBusUtils dbusUtils;
-
- // Send message
- QDBusMessage m = QDBusMessage::createMethodCall(
- QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("requestCapture"));
- m << req.serialize();
- QDBusConnection sessionBus = QDBusConnection::sessionBus();
- dbusUtils.checkDBusConnection(sessionBus);
- sessionBus.call(m);
-
- if (raw) {
- dbusUtils.connectPrintCapture(sessionBus, id);
- // timeout just in case
- QTimer t;
- t.setInterval(delay + 2000);
- QObject::connect(
- &t, &QTimer::timeout, qApp, &QCoreApplication::quit);
- t.start();
- // wait
- return app.exec();
- }
+ requestCaptureAndWait(req);
} else if (parser.isSet(configArgument)) { // CONFIG
bool autostart = parser.isSet(autostartOption);
bool filename = parser.isSet(filenameOption);
bool tray = parser.isSet(trayOption);
- bool help = parser.isSet(showHelpOption);
bool mainColor = parser.isSet(mainColorOption);
bool contrastColor = parser.isSet(contrastColorOption);
bool check = parser.isSet(checkOption);
bool someFlagSet =
- (filename || tray || help || mainColor || contrastColor || check);
+ (filename || tray || mainColor || contrastColor || check);
if (check) {
- QTextStream stream(stderr);
- bool ok = ConfigHandler(true).checkForErrors(&stream);
+ QTextStream err(stderr);
+ bool ok = ConfigHandler(true).checkForErrors(&err);
if (ok) {
- stream << QStringLiteral("No errors detected.\n");
+ err << QStringLiteral("No errors detected.\n");
goto finish;
} else {
return 1;
@@ -542,22 +511,7 @@ int main(int argc, char* argv[])
}
ConfigHandler config;
if (autostart) {
- QDBusMessage m = QDBusMessage::createMethodCall(
- QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("autostartEnabled"));
- if (parser.value(autostartOption) == QLatin1String("false")) {
- m << false;
- } else if (parser.value(autostartOption) == QLatin1String("true")) {
- m << true;
- }
- QDBusConnection sessionBus = QDBusConnection::sessionBus();
- if (!sessionBus.isConnected()) {
- SystemNotification().sendMessage(
- QObject::tr("Unable to connect via DBus"));
- }
- sessionBus.call(m);
+ config.setStartupLaunch(parser.value(autostartOption) == "true");
}
if (filename) {
QString newFilename(parser.value(filenameOption));
@@ -570,31 +524,10 @@ int main(int argc, char* argv[])
.arg(fh.parsedPattern());
}
if (tray) {
- QDBusMessage m = QDBusMessage::createMethodCall(
- QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("trayIconEnabled"));
- if (parser.value(trayOption) == QLatin1String("false")) {
- m << false;
- } else if (parser.value(trayOption) == QLatin1String("true")) {
- m << true;
- }
- QDBusConnection sessionBus = QDBusConnection::sessionBus();
- if (!sessionBus.isConnected()) {
- SystemNotification().sendMessage(
- QObject::tr("Unable to connect via DBus"));
- }
- sessionBus.call(m);
- }
- if (help) {
- if (parser.value(showHelpOption) == QLatin1String("false")) {
- config.setShowHelp(false);
- } else if (parser.value(showHelpOption) == QLatin1String("true")) {
- config.setShowHelp(true);
- }
+ config.setDisabledTrayIcon(parser.value(trayOption) == "false");
}
if (mainColor) {
+ // TODO use value handler
QString colorCode = parser.value(mainColorOption);
QColor parsedColor(colorCode);
config.setUiColor(parsedColor);
@@ -607,17 +540,12 @@ int main(int argc, char* argv[])
// Open gui when no options
if (!someFlagSet) {
- QDBusMessage m = QDBusMessage::createMethodCall(
- QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("openConfig"));
- QDBusConnection sessionBus = QDBusConnection::sessionBus();
- if (!sessionBus.isConnected()) {
- SystemNotification().sendMessage(
- QObject::tr("Unable to connect via DBus"));
- }
- sessionBus.call(m);
+ delete qApp;
+ new QApplication(argc, argv);
+ QObject::connect(
+ qApp, &QApplication::lastWindowClosed, qApp, &QApplication::quit);
+ Controller::getInstance()->openConfigWindow();
+ qApp->exec();
}
}
finish:
diff --git a/src/tools/accept/accepttool.cpp b/src/tools/accept/accepttool.cpp
index 3792a305..f636cd63 100644
--- a/src/tools/accept/accepttool.cpp
+++ b/src/tools/accept/accepttool.cpp
@@ -49,10 +49,10 @@ CaptureTool* AcceptTool::copy(QObject* parent)
void AcceptTool::pressed(CaptureContext& context)
{
emit requestAction(REQ_CAPTURE_DONE_OK);
- if (context.request()->tasks() & CaptureRequest::PIN) {
+ if (context.request.tasks() & CaptureRequest::PIN) {
QRect geometry = context.selection;
geometry.moveTopLeft(geometry.topLeft() + context.widgetOffset);
- context.request()->addPinTask(geometry);
+ context.request.addTask(CaptureRequest::PIN);
}
emit requestAction(REQ_CLOSE_GUI);
}
diff --git a/src/tools/capturecontext.cpp b/src/tools/capturecontext.cpp
index 6059e9a7..843a1dc0 100644
--- a/src/tools/capturecontext.cpp
+++ b/src/tools/capturecontext.cpp
@@ -14,13 +14,3 @@ QPixmap CaptureContext::selectedScreenshotArea() const
return screenshot.copy(selection);
}
}
-
-CaptureRequest* CaptureContext::request()
-{
- return &*Controller::getInstance()->requests().find(requestId);
-}
-
-CaptureRequest* CaptureContext::request() const
-{
- return &*Controller::getInstance()->requests().find(requestId);
-}
diff --git a/src/tools/capturecontext.h b/src/tools/capturecontext.h
index 23231d2e..1e9fc4b0 100644
--- a/src/tools/capturecontext.h
+++ b/src/tools/capturecontext.h
@@ -29,9 +29,7 @@ struct CaptureContext
int toolSize;
// Mode of the capture widget
bool fullscreen;
- uint requestId;
+ CaptureRequest request = CaptureRequest::GRAPHICAL_MODE;
QPixmap selectedScreenshotArea() const;
- CaptureRequest* request();
- CaptureRequest* request() const;
};
diff --git a/src/tools/copy/copytool.cpp b/src/tools/copy/copytool.cpp
index 2aa95efd..f9b02d3e 100644
--- a/src/tools/copy/copytool.cpp
+++ b/src/tools/copy/copytool.cpp
@@ -41,7 +41,7 @@ CaptureTool* CopyTool::copy(QObject* parent)
void CopyTool::pressed(CaptureContext& context)
{
- context.request()->addTask(CaptureRequest::COPY);
+ context.request.addTask(CaptureRequest::COPY);
emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_CLOSE_GUI);
}
diff --git a/src/tools/imgupload/imguploadertool.cpp b/src/tools/imgupload/imguploadertool.cpp
index 5623dc1b..f6057a49 100644
--- a/src/tools/imgupload/imguploadertool.cpp
+++ b/src/tools/imgupload/imguploadertool.cpp
@@ -41,6 +41,6 @@ CaptureTool* ImgUploaderTool::copy(QObject* parent)
void ImgUploaderTool::pressed(CaptureContext& context)
{
emit requestAction(REQ_CAPTURE_DONE_OK);
- context.request()->addTask(CaptureRequest::UPLOAD);
+ context.request.addTask(CaptureRequest::UPLOAD);
emit requestAction(REQ_CLOSE_GUI);
}
diff --git a/src/tools/imgupload/storages/imguploaderbase.cpp b/src/tools/imgupload/storages/imguploaderbase.cpp
index f9367dd2..6eee3c1a 100644
--- a/src/tools/imgupload/storages/imguploaderbase.cpp
+++ b/src/tools/imgupload/storages/imguploaderbase.cpp
@@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "imguploaderbase.h"
+#include "src/core/flameshotdaemon.h"
#include "src/utils/confighandler.h"
#include "src/utils/globalvalues.h"
#include "src/utils/history.h"
@@ -9,6 +10,7 @@
#include "src/widgets/loadspinner.h"
#include "src/widgets/notificationwidget.h"
#include
+// FIXME #include
#include
#include
#include
@@ -157,13 +159,13 @@ void ImgUploaderBase::openURL()
void ImgUploaderBase::copyURL()
{
- QApplication::clipboard()->setText(m_imageURL.toString());
+ FlameshotDaemon::copyToClipboard(m_imageURL.toString());
m_notification->showMessage(tr("URL copied to clipboard."));
}
void ImgUploaderBase::copyImage()
{
- QApplication::clipboard()->setPixmap(m_pixmap);
+ FlameshotDaemon::copyToClipboard(m_pixmap);
m_notification->showMessage(tr("Screenshot copied to clipboard."));
}
@@ -173,4 +175,4 @@ void ImgUploaderBase::deleteCurrentImage()
HISTORY_FILE_NAME unpackFileName =
history.unpackFileName(m_currentImageName);
deleteImage(unpackFileName.file, unpackFileName.token);
-}
\ No newline at end of file
+}
diff --git a/src/tools/pin/pintool.cpp b/src/tools/pin/pintool.cpp
index de53110e..a022e07f 100644
--- a/src/tools/pin/pintool.cpp
+++ b/src/tools/pin/pintool.cpp
@@ -43,8 +43,6 @@ CaptureTool* PinTool::copy(QObject* parent)
void PinTool::pressed(CaptureContext& context)
{
emit requestAction(REQ_CAPTURE_DONE_OK);
- QRect geometry = context.selection;
- geometry.setTopLeft(geometry.topLeft() + context.widgetOffset);
- context.request()->addPinTask(geometry);
+ context.request.addTask(CaptureRequest::PIN);
emit requestAction(REQ_CLOSE_GUI);
}
diff --git a/src/tools/save/savetool.cpp b/src/tools/save/savetool.cpp
index bc2460cf..95856660 100644
--- a/src/tools/save/savetool.cpp
+++ b/src/tools/save/savetool.cpp
@@ -41,7 +41,7 @@ CaptureTool* SaveTool::copy(QObject* parent)
void SaveTool::pressed(CaptureContext& context)
{
- context.request()->addSaveTask();
+ context.request.addSaveTask();
emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_CLOSE_GUI);
}
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
index afb3c29a..dae6ca46 100644
--- a/src/utils/CMakeLists.txt
+++ b/src/utils/CMakeLists.txt
@@ -1,8 +1,7 @@
# Required to generate MOC
target_sources(
flameshot
- PRIVATE dbusutils.h
- filenamehandler.h
+ PRIVATE filenamehandler.h
screengrabber.h
systemnotification.h
valuehandler.h
@@ -18,7 +17,6 @@ target_sources(
systemnotification.cpp
valuehandler.cpp
screenshotsaver.cpp
- dbusutils.cpp
globalvalues.cpp
desktopfileparse.cpp
desktopinfo.cpp
diff --git a/src/utils/confighandler.cpp b/src/utils/confighandler.cpp
index 91c5121c..b4741945 100644
--- a/src/utils/confighandler.cpp
+++ b/src/utils/confighandler.cpp
@@ -81,6 +81,10 @@ static QMap>
OPTION("disabledTrayIcon" ,Bool ( false )),
OPTION("historyConfirmationToDelete" ,Bool ( true )),
OPTION("checkForUpdates" ,Bool ( true )),
+ OPTION("allowMultipleGuiInstances" ,Bool ( false )),
+#if !defined(Q_OS_WIN)
+ OPTION("autoCloseIdleDaemon" ,Bool ( false )),
+#endif
#if defined(Q_OS_MACOS)
OPTION("startupLaunch" ,Bool ( false )),
#else
diff --git a/src/utils/confighandler.h b/src/utils/confighandler.h
index bc760a40..fc94ab1e 100644
--- a/src/utils/confighandler.h
+++ b/src/utils/confighandler.h
@@ -29,9 +29,14 @@ class QTextStream;
* and `TYPE` is the C++ type.
*/
#define CONFIG_SETTER(FUNC, KEY, TYPE) \
- void FUNC(const TYPE& value) \
+ void FUNC(const TYPE& val) \
{ \
- setValue(QStringLiteral(#KEY), QVariant::fromValue(value)); \
+ QString key = QStringLiteral(#KEY); \
+ /* Without this check, multiple `flameshot gui` instances running */ \
+ /* simultaneously would cause an endless loop of fileWatcher calls */ \
+ if (QVariant::fromValue(val) != value(key)) { \
+ setValue(key, QVariant::fromValue(val)); \
+ } \
}
/**
@@ -75,6 +80,10 @@ public:
CONFIG_GETTER_SETTER(drawFontSize, setDrawFontSize, int)
CONFIG_GETTER_SETTER(keepOpenAppLauncher, setKeepOpenAppLauncher, bool)
CONFIG_GETTER_SETTER(checkForUpdates, setCheckForUpdates, bool)
+ CONFIG_GETTER_SETTER(allowMultipleGuiInstances,
+ setAllowMultipleGuiInstances,
+ bool)
+ CONFIG_GETTER_SETTER(autoCloseIdleDaemon, setAutoCloseIdleDaemon, bool)
CONFIG_GETTER_SETTER(showStartupLaunchMessage,
setShowStartupLaunchMessage,
bool)
diff --git a/src/utils/dbusutils.cpp b/src/utils/dbusutils.cpp
deleted file mode 100644
index 1a19977c..00000000
--- a/src/utils/dbusutils.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-or-later
-// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
-
-#include "dbusutils.h"
-#include "src/utils/systemnotification.h"
-#include
-#include
-#include
-#include
-
-DBusUtils::DBusUtils(QObject* parent)
- : QObject(parent)
-{}
-
-void DBusUtils::connectPrintCapture(QDBusConnection& session, uint id)
-{
- m_id = id;
- // captureTaken
- session.connect(QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("captureTaken"),
- this,
- SLOT(captureTaken(uint, QByteArray, QRect)));
- // captureFailed
- session.connect(QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("captureFailed"),
- this,
- SLOT(captureFailed(uint)));
-}
-
-void DBusUtils::connectSelectionCapture(QDBusConnection& session, uint id)
-{
- m_id = id;
- // captureTaken
- session.connect(QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("captureTaken"),
- this,
- SLOT(selectionTaken(uint, QByteArray, QRect)));
- // captureFailed
- session.connect(QStringLiteral("org.flameshot.Flameshot"),
- QStringLiteral("/"),
- QLatin1String(""),
- QStringLiteral("captureFailed"),
- this,
- SLOT(captureFailed(uint)));
-}
-
-void DBusUtils::checkDBusConnection(const QDBusConnection& connection)
-{
- if (!connection.isConnected()) {
- SystemNotification().sendMessage(tr("Unable to connect via DBus"));
- qApp->exit(1);
- }
-}
-
-void DBusUtils::captureTaken(uint id, QByteArray rawImage, QRect selection)
-{
- if (m_id == id) {
- QFile file;
- file.open(stdout, QIODevice::WriteOnly);
-
- file.write(rawImage);
- file.close();
- qApp->exit();
- }
-}
-
-void DBusUtils::captureFailed(uint id)
-{
- if (m_id == id) {
- QTextStream(stdout) << "screenshot aborted\n";
- qApp->exit(1);
- }
-}
-
-void DBusUtils::selectionTaken(uint id, QByteArray rawImage, QRect selection)
-{
- if (m_id == id) {
- QFile file;
- file.open(stdout, QIODevice::WriteOnly);
-
- QTextStream out(&file);
- // TODO also make this change in D-Bus refactor branch
- out << selection.width() << "x" << selection.height() << "+"
- << selection.x() << "+" << selection.y() << "\n";
- file.close();
- qApp->exit();
- }
-}
diff --git a/src/utils/dbusutils.h b/src/utils/dbusutils.h
deleted file mode 100644
index 1000cb10..00000000
--- a/src/utils/dbusutils.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-or-later
-// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
-
-#pragma once
-
-#include "src/cli/commandlineparser.h"
-#include
-#include
-
-class DBusUtils : public QObject
-{
- Q_OBJECT
-public:
- explicit DBusUtils(QObject* parent = nullptr);
-
- void connectPrintCapture(QDBusConnection& session, uint id);
- void checkDBusConnection(const QDBusConnection& connection);
- void connectSelectionCapture(QDBusConnection& session, uint id);
-
-public slots:
- void selectionTaken(uint id, QByteArray rawImage, QRect selection);
- void captureTaken(uint id, QByteArray rawImage, QRect selection);
- void captureFailed(uint id);
-
-private:
- uint m_id;
-};
diff --git a/src/utils/screenshotsaver.cpp b/src/utils/screenshotsaver.cpp
index 02b488ba..b17f5c53 100644
--- a/src/utils/screenshotsaver.cpp
+++ b/src/utils/screenshotsaver.cpp
@@ -3,6 +3,7 @@
#include "screenshotsaver.h"
#include "src/core/controller.h"
+#include "src/core/flameshotdaemon.h"
#include "src/utils/confighandler.h"
#include "src/utils/filenamehandler.h"
#include "src/utils/globalvalues.h"
@@ -22,13 +23,7 @@
#include "src/widgets/capture/capturewidget.h"
#endif
-ScreenshotSaver::ScreenshotSaver()
- : m_id(0)
-{}
-
-ScreenshotSaver::ScreenshotSaver(const unsigned id)
- : m_id(id)
-{}
+ScreenshotSaver::ScreenshotSaver() {}
void ScreenshotSaver::saveToClipboardMime(const QPixmap& capture,
const QString& imageType)
@@ -102,8 +97,6 @@ bool ScreenshotSaver::saveToFilesystem(const QPixmap& capture,
if (ok) {
saveMessage += QObject::tr("Capture saved as ") + completePath;
- Controller::getInstance()->sendCaptureSaved(
- m_id, QFileInfo(completePath).canonicalFilePath());
} else {
saveMessage += QObject::tr("Error trying to save as ") + completePath;
if (file.error() != QFile::NoError) {
@@ -192,20 +185,11 @@ bool ScreenshotSaver::saveToFilesystemGUI(const QPixmap& capture)
ConfigHandler().setSavePath(pathNoFile);
QString msg = QObject::tr("Capture saved as ") + savePath;
-
- if (config.copyPathAfterSave()) {
- msg =
- QObject::tr("Capture is saved and copied to the clipboard as ") +
- savePath;
- }
-
SystemNotification().sendMessage(msg, savePath);
- Controller::getInstance()->sendCaptureSaved(
- m_id, QFileInfo(savePath).canonicalFilePath());
-
if (config.copyPathAfterSave()) {
- QApplication::clipboard()->setText(savePath);
+ FlameshotDaemon::copyToClipboard(
+ savePath, QObject::tr("Path copied to clipboard as ") + savePath);
}
} else {
diff --git a/src/utils/screenshotsaver.h b/src/utils/screenshotsaver.h
index 73413c1a..42e6edfe 100644
--- a/src/utils/screenshotsaver.h
+++ b/src/utils/screenshotsaver.h
@@ -12,7 +12,6 @@ class ScreenshotSaver
{
public:
ScreenshotSaver();
- ScreenshotSaver(const unsigned id);
void saveToClipboard(const QPixmap& capture);
void saveToClipboardMime(const QPixmap& capture, const QString& imageType);
@@ -22,7 +21,6 @@ public:
bool saveToFilesystemGUI(const QPixmap& capture);
private:
- unsigned m_id;
QString ShowSaveFileDialog(QWidget* parent,
const QString& title,
const QString& directory);
diff --git a/src/utils/systemnotification.cpp b/src/utils/systemnotification.cpp
index 2081c106..d1a5deb0 100644
--- a/src/utils/systemnotification.cpp
+++ b/src/utils/systemnotification.cpp
@@ -4,7 +4,7 @@
#include
#include
-#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
+#if !(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
#include
#include
#include
@@ -14,7 +14,7 @@ SystemNotification::SystemNotification(QObject* parent)
: QObject(parent)
, m_interface(nullptr)
{
-#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
+#if !(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
m_interface =
new QDBusInterface(QStringLiteral("org.freedesktop.Notifications"),
QStringLiteral("/org/freedesktop/Notifications"),
diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp
index 73fd33dd..af8b0d57 100644
--- a/src/widgets/capture/capturewidget.cpp
+++ b/src/widgets/capture/capturewidget.cpp
@@ -48,8 +48,8 @@
// an area of selection with its respective buttons.
// enableSaveWindow
-CaptureWidget::CaptureWidget(uint id,
- const QString& savePath,
+
+CaptureWidget::CaptureWidget(const CaptureRequest& req,
bool fullScreen,
QWidget* parent)
: QWidget(parent)
@@ -90,7 +90,7 @@ CaptureWidget::CaptureWidget(uint id,
m_uiColor = m_config.uiColor();
m_contrastUiColor = m_config.contrastUiColor();
setMouseTracking(true);
- initContext(fullScreen, id);
+ initContext(fullScreen, req);
#if (defined(Q_OS_WIN) || defined(Q_OS_MACOS))
// Top left of the whole set of screens
QPoint topLeft(0, 0);
@@ -251,9 +251,12 @@ CaptureWidget::~CaptureWidget()
}
#endif
if (m_captureDone) {
- emit captureTaken(m_context.requestId, pixmap(), m_context.selection);
+ QRect geometry(m_context.selection);
+ geometry.setTopLeft(geometry.topLeft() + m_context.widgetOffset);
+ Controller::getInstance()->exportCapture(
+ pixmap(), geometry, m_context.request);
} else {
- emit captureFailed(m_context.requestId);
+ Controller::getInstance()->handleCaptureFailed();
}
}
@@ -261,7 +264,7 @@ void CaptureWidget::initButtons()
{
auto allButtonTypes = CaptureToolButton::getIterableButtonTypes();
auto visibleButtonTypes = m_config.buttons();
- if (m_context.request()->tasks() == CaptureRequest::NO_TASK) {
+ if (m_context.request.tasks() == CaptureRequest::NO_TASK) {
allButtonTypes.removeOne(CaptureTool::TYPE_ACCEPT);
visibleButtonTypes.removeOne(CaptureTool::TYPE_ACCEPT);
} else {
@@ -891,7 +894,7 @@ void CaptureWidget::changeEvent(QEvent* e)
}
}
-void CaptureWidget::initContext(bool fullscreen, uint requestId)
+void CaptureWidget::initContext(bool fullscreen, const CaptureRequest& req)
{
m_context.color = m_config.drawColor();
m_context.widgetOffset = mapToGlobal(QPoint(0, 0));
@@ -900,15 +903,7 @@ void CaptureWidget::initContext(bool fullscreen, uint requestId)
m_context.fullscreen = fullscreen;
// initialize m_context.request
- if (requestId != 0) {
- m_context.requestId = requestId;
- } else {
- CaptureRequest req(CaptureRequest::GRAPHICAL_MODE);
- uint id = req.id();
- req.setStaticID(id);
- Controller::getInstance()->requests().insert(id, req);
- m_context.requestId = id;
- }
+ m_context.request = req;
}
void CaptureWidget::initPanel()
@@ -1040,7 +1035,7 @@ void CaptureWidget::initSelection()
{
// Be mindful of the order of statements, so that slots are called properly
m_selection = new SelectionWidget(m_uiColor, this);
- QRect initialSelection = m_context.request()->initialSelection();
+ QRect initialSelection = m_context.request.initialSelection();
connect(m_selection, &SelectionWidget::geometryChanged, this, [this]() {
QRect constrainedToCaptureArea =
m_selection->geometry().intersected(rect());
@@ -1052,16 +1047,10 @@ void CaptureWidget::initSelection()
});
connect(m_selection, &SelectionWidget::geometrySettled, this, [this]() {
if (m_selection->isVisibleTo(this)) {
- auto req = m_context.request();
- if (req->tasks() & CaptureRequest::ACCEPT_ON_SELECT) {
- req->removeTask(CaptureRequest::ACCEPT_ON_SELECT);
+ auto& req = m_context.request;
+ if (req.tasks() & CaptureRequest::ACCEPT_ON_SELECT) {
+ req.removeTask(CaptureRequest::ACCEPT_ON_SELECT);
m_captureDone = true;
- if (req->tasks() & CaptureRequest::PIN) {
- QRect geometry = m_context.selection;
- geometry.setTopLeft(geometry.topLeft() +
- m_context.widgetOffset);
- req->addPinTask(geometry);
- }
close();
}
m_buttonHandler->updatePosition(m_selection->geometry());
diff --git a/src/widgets/capture/capturewidget.h b/src/widgets/capture/capturewidget.h
index 959c8137..f213eac3 100644
--- a/src/widgets/capture/capturewidget.h
+++ b/src/widgets/capture/capturewidget.h
@@ -41,8 +41,7 @@ class CaptureWidget : public QWidget
Q_OBJECT
public:
- explicit CaptureWidget(uint id = 0,
- const QString& savePath = QString(),
+ explicit CaptureWidget(const CaptureRequest& req,
bool fullScreen = true,
QWidget* parent = nullptr);
~CaptureWidget();
@@ -57,8 +56,6 @@ public slots:
void deleteToolWidgetOrClose();
signals:
- void captureTaken(uint id, const QPixmap& capture, const QRect& selection);
- void captureFailed(uint id);
void colorChanged(const QColor& c);
void toolSizeChanged(int size);
@@ -105,7 +102,7 @@ private:
void showColorPicker(const QPoint& pos);
bool startDrawObjectTool(const QPoint& pos);
QPointer activeToolObject();
- void initContext(bool fullscreen, uint requestId);
+ void initContext(bool fullscreen, const CaptureRequest& req);
void initPanel();
void initSelection();
void initShortcuts();
diff --git a/src/widgets/capturelauncher.cpp b/src/widgets/capturelauncher.cpp
index 67ed3619..91e8ecab 100644
--- a/src/widgets/capturelauncher.cpp
+++ b/src/widgets/capturelauncher.cpp
@@ -21,7 +21,6 @@
CaptureLauncher::CaptureLauncher(QDialog* parent)
: QDialog(parent)
- , m_id(0)
{
setAttribute(Qt::WA_DeleteOnClose);
setWindowIcon(QIcon(GlobalValues::iconPath()));
@@ -108,7 +107,6 @@ void CaptureLauncher::startCapture()
auto mode = static_cast(
m_captureType->currentData().toInt());
CaptureRequest req(mode, 600 + m_delaySpinBox->value() * 1000);
- m_id = req.id();
connectCaptureSlots();
Controller::getInstance()->requestCapture(req);
}
@@ -166,16 +164,13 @@ void CaptureLauncher::disconnectCaptureSlots()
&CaptureLauncher::captureFailed);
}
-void CaptureLauncher::captureTaken(uint id, QPixmap p, const QRect& selection)
+void CaptureLauncher::captureTaken(QPixmap p, const QRect&)
{
// MacOS specific, more details in the function disconnectCaptureSlots()
disconnectCaptureSlots();
- if (id == m_id) {
- m_id = 0;
- m_imageLabel->setScreenshot(p);
- show();
- }
+ m_imageLabel->setScreenshot(p);
+ show();
auto mode = static_cast(
m_captureType->currentData().toInt());
@@ -186,14 +181,10 @@ void CaptureLauncher::captureTaken(uint id, QPixmap p, const QRect& selection)
m_launchButton->setEnabled(true);
}
-void CaptureLauncher::captureFailed(uint id)
+void CaptureLauncher::captureFailed()
{
// MacOS specific, more details in the function disconnectCaptureSlots()
disconnectCaptureSlots();
-
- if (id == m_id) {
- m_id = 0;
- show();
- }
+ show();
m_launchButton->setEnabled(true);
}
diff --git a/src/widgets/capturelauncher.h b/src/widgets/capturelauncher.h
index f8574c1e..a1340678 100644
--- a/src/widgets/capturelauncher.h
+++ b/src/widgets/capturelauncher.h
@@ -26,8 +26,8 @@ private:
private slots:
void startCapture();
void startDrag();
- void captureTaken(uint id, QPixmap p, const QRect& selection);
- void captureFailed(uint id);
+ void captureTaken(QPixmap p, const QRect& selection);
+ void captureFailed();
private:
QSpinBox* m_delaySpinBox;
@@ -36,5 +36,4 @@ private:
QPushButton* m_launchButton;
QLabel* m_CaptureModeLabel;
ImageLabel* m_imageLabel;
- uint m_id;
};
diff --git a/src/widgets/historywidget.cpp b/src/widgets/historywidget.cpp
index 84c05477..91c82860 100644
--- a/src/widgets/historywidget.cpp
+++ b/src/widgets/historywidget.cpp
@@ -1,11 +1,10 @@
#include "historywidget.h"
+#include "src/core/flameshotdaemon.h"
#include "src/tools/imgupload/imguploadermanager.h"
#include "src/utils/confighandler.h"
#include "src/utils/globalvalues.h"
#include "src/utils/history.h"
#include "src/widgets/notificationwidget.h"
-#include
-#include
#include
#include
#include
@@ -143,7 +142,7 @@ void HistoryWidget::addLine(const QString& path, const QString& fileName)
buttonCopyUrl->setText(tr("Copy URL"));
buttonCopyUrl->setMinimumHeight(HISTORYPIXMAP_MAX_PREVIEW_HEIGHT);
connect(buttonCopyUrl, &QPushButton::clicked, this, [=]() {
- QApplication::clipboard()->setText(url);
+ FlameshotDaemon::copyToClipboard(url);
m_notification->showMessage(tr("URL copied to clipboard."));
this->close();
});
diff --git a/src/widgets/historywidget.h b/src/widgets/historywidget.h
index 163342bc..c8ab1da5 100644
--- a/src/widgets/historywidget.h
+++ b/src/widgets/historywidget.h
@@ -2,10 +2,8 @@
#define HISTORYWIDGET_H
#include
-#include
-#include
-#include
+class QString;
class QLayout;
class QVBoxLayout;
class NotificationWidget;
diff --git a/src/widgets/infowindow.cpp b/src/widgets/infowindow.cpp
index 00a8916f..e1215bb7 100644
--- a/src/widgets/infowindow.cpp
+++ b/src/widgets/infowindow.cpp
@@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "infowindow.h"
+#include "src/core/flameshotdaemon.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/utils/globalvalues.h"
#include
@@ -88,9 +89,8 @@ void InfoWindow::initLabels()
void InfoWindow::copyInfo()
{
- QClipboard* clipboard = QApplication::clipboard();
- clipboard->setText(GlobalValues::versionInfo() + "\n" +
- generateKernelString());
+ FlameshotDaemon::copyToClipboard(GlobalValues::versionInfo() + "\n" +
+ generateKernelString());
}
void InfoWindow::keyPressEvent(QKeyEvent* e)
diff --git a/tests/action_options.sh b/tests/action_options.sh
index 0b3a33cc..93663fba 100644
--- a/tests/action_options.sh
+++ b/tests/action_options.sh
@@ -41,6 +41,32 @@ cmd() {
sleep 1
}
+notify() {
+ if [ "$FLAMESHOT_PLATFORM" = "MAC" ]
+ then
+osascript - "$1" <&2 && read ____
}
@@ -54,7 +80,7 @@ for subcommand in full screen
do
cmd flameshot "$subcommand" --path /tmp/
cmd flameshot "$subcommand" --clipboard
- cmd command "$FLAMESHOT" "$subcommand" --raw | display
+ cmd command "$FLAMESHOT" "$subcommand" --raw | display_img
[ "$subcommand" = "full" ] && sleep 1
echo
done
@@ -70,30 +96,30 @@ sleep 1
# ┗━━━━━━━━━━━━━━━┛
wait_for_key
-notify-send "GUI Test 1: --path" "Make a selection, then accept"
+notify "GUI Test 1: --path" #"Make a selection, then accept"
cmd flameshot gui --path /tmp/
wait_for_key
-notify-send "GUI Test 2: Clipboard" "Make a selection, then accept"
+notify "GUI Test 2: Clipboard" "Make a selection, then accept"
cmd flameshot gui --clipboard
wait_for_key
-notify-send "GUI Test 3: Print geometry" "Make a selection, then accept"
+notify "GUI Test 3: Print geometry" "Make a selection, then accept"
cmd command "$FLAMESHOT" gui --print-geometry
wait_for_key
-notify-send "GUI Test 4: Pin" "Make a selection, then accept"
+notify "GUI Test 4: Pin" "Make a selection, then accept"
cmd flameshot gui --pin
wait_for_key
-notify-send "GUI Test 5: Print raw" "Make a selection, then accept"
-cmd command "$FLAMESHOT" gui --raw | display
+notify "GUI Test 5: Print raw" "Make a selection, then accept"
+cmd command "$FLAMESHOT" gui --raw | display_img
wait_for_key
-notify-send "GUI Test 6: Copy on select" "Make a selection, flameshot will close automatically"
+notify "GUI Test 6: Copy on select" "Make a selection, flameshot will close automatically"
cmd flameshot gui --clipboard --accept-on-select
wait_for_key
-notify-send "GUI Test 7: File dialog on select" "After selecting, a file dialog will open"
+notify "GUI Test 7: File dialog on select" "After selecting, a file dialog will open"
cmd flameshot gui --accept-on-select
# All options except for --print-geometry (incompatible with --raw)
wait_for_key
-notify-send "GUI Test 8: All actions except print-geometry" "Just make a selection"
-cmd command "$FLAMESHOT" gui -p /tmp/ -c -r --pin | display
+notify "GUI Test 8: All actions except print-geometry" "Just make a selection"
+cmd command "$FLAMESHOT" gui -p /tmp/ -c -r --pin | display_img
echo '>> All tests done.'