mirror of
https://github.com/fergalmoran/flameshot.git
synced 2025-12-22 01:41:19 +00:00
Reduce dependence on D-Bus (#2003)
* Handle captures without sigslots Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Set {app,organization}Name and version consistently Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'full' dbus-free Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Move CaptureRequest::exportCapture to Controller We need to wait until the upload widget (or similar widgets) have finished before exiting. This must be done using a signal. The problem is that CaptureRequest can't be guaranteed to survive until the widget has finished what it's doing. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Use QApplication with the 'full' subcommand Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Do unto 'screen' as we did to 'full' Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add FlameshotDaemon singleton class Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Support clipboard hosting for both pixmaps and text * Fix upload handling Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Do not show tray icon if not daemon Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Clean up handling of pin task Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove annoying Qt warning messages The messages were caused by the color wheel. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix small bug in Controller::exportCapture * Fix --raw output * Make 'gui' dbus-independent Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix accept on select bug Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix compile error on Windows Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make it work on Windows * Remove obsolete function in main.cpp Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'launcher' work without dbus Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * clang-format, sigh Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Enable CLI parsing on MacOS Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'config' work without dbus Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Small refactor of capture request handling Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove obsolete DBusUtils Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove unused D-Bus sigslots Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove D-Bus methods openConfig, autostartEnabled and trayIconEnabled Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove D-Bus method requestCapture Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove CaptureRequest id mechanism Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix 'launcher' crash Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Handle clipboard notifications properly Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add 'autoCloseIdleDaemon' option Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Document FlameshotDaemon class Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'flameshot gui' run in single-application mode Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add `allowmultipleGuiInstances` config option Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix endless loop with multiple GUI instances Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Move upload confirmation dialog where it belongs Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add the new config options to the GUI as well Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix failing build on Windows Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Handle persistence on MacOS Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * fixed notifications on macos * Fixed display on macos * Reformat tests/action_options.sh Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix infinite recursion in tests/action_options.sh Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> Co-authored-by: Dearsh Oberoi <59907159+deo002@users.noreply.github.com> Co-authored-by: Jeremy Borgman <borgman.jeremy@pm.me>
This commit is contained in:
@@ -3,90 +3,38 @@
|
||||
<interface name="org.flameshot.Flameshot">
|
||||
|
||||
<!--
|
||||
requestCapture:
|
||||
@requestData: Serialized CaptureRequest object.
|
||||
attachPin:
|
||||
@data: Byte array containing the screenshot and geometry information.
|
||||
|
||||
Start a capture using a CaptureRequest.
|
||||
Attach a pinned screenshot widget to the daemon.
|
||||
-->
|
||||
<method name="requestCapture">
|
||||
<arg name="requestData" type="ay" direction="in"/>
|
||||
<method name="attachPin">
|
||||
<arg name="data" type="ay" direction="in"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
openLauncher:
|
||||
attachScreenshotToClipboard:
|
||||
@screenshot: Byte array containing the screenshot pixmap.
|
||||
|
||||
Opens the capture launcher.
|
||||
Copy the screenshot to the daemon's clipboard, to prevent losing the
|
||||
clipboard when a flameshot subcommand exits.
|
||||
-->
|
||||
<method name="openLauncher">
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
<method name="attachScreenshotToClipboard">
|
||||
<arg name="screenshot" type="ay" direction="in"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
openConfig:
|
||||
attachTextToClipboard:
|
||||
@text: Text to be copied to the clipboard.
|
||||
@notification: Optional notification to send.
|
||||
|
||||
Opens the configuration window.
|
||||
Copy the text to the daemon's clipboard, to prevent losing the
|
||||
clipboard when a flameshot subcommand exits.
|
||||
-->
|
||||
<method name="openConfig">
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
<method name="attachTextToClipboard">
|
||||
<arg name="text" type="s" direction="in"/>
|
||||
<arg name="notification" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
trayIconEnabled:
|
||||
@enabled: The new state for the trayIcon.
|
||||
|
||||
Enable or disable the trayIcon.
|
||||
-->
|
||||
<method name="trayIconEnabled">
|
||||
<arg name="enabled" type="b" direction="in"/>
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
autostartEnabled:
|
||||
@enabled: The new state for the autostart.
|
||||
|
||||
Enable or disable the autostart of the program.
|
||||
-->
|
||||
<method name="autostartEnabled">
|
||||
<arg name="enabled" type="b" direction="in"/>
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
captureTaken:
|
||||
@id: identificator of the call.
|
||||
@rawImage: raw image in PNG format.
|
||||
@selection: QRect selection geometry.
|
||||
|
||||
Successful capture signal returning the image.
|
||||
-->
|
||||
<signal name="captureTaken">
|
||||
<arg name="id" type="u" direction="out"/>
|
||||
<arg name="rawImage" type="ay" direction="out"/>
|
||||
<arg name="selection" type="(iiii)" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<!--
|
||||
captureFailed:
|
||||
@id: identificator of the call.
|
||||
|
||||
Whenever the capture fails.
|
||||
-->
|
||||
<signal name="captureFailed">
|
||||
<arg name="id" type="u" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<!--
|
||||
captureSaved:
|
||||
@id: identificator of the call.
|
||||
@savePath: canonical path of the newly created image file.
|
||||
|
||||
An image was written to disk after capture.
|
||||
-->
|
||||
<signal name="captureSaved">
|
||||
<arg name="id" type="u" direction="out"/>
|
||||
<arg name="savePath" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
|
||||
@@ -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
|
||||
;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<uint> 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<ExportTask>(tasks);
|
||||
request.m_mode = static_cast<CaptureMode>(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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {}
|
||||
};
|
||||
|
||||
|
||||
@@ -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 <QAction>
|
||||
#include <QApplication>
|
||||
#include <QBuffer>
|
||||
#include <QClipboard>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QMenu>
|
||||
@@ -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)
|
||||
|
||||
@@ -37,16 +37,14 @@ public:
|
||||
~Controller();
|
||||
void operator=(const Controller&) = delete;
|
||||
|
||||
void enableExports();
|
||||
|
||||
void setCheckForUpdatesEnabled(const bool enabled);
|
||||
|
||||
QMap<uint, CaptureRequest>& 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);
|
||||
|
||||
|
||||
262
src/core/flameshotdaemon.cpp
Normal file
262
src/core/flameshotdaemon.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
#include "flameshotdaemon.h"
|
||||
|
||||
#include "confighandler.h"
|
||||
#include "controller.h"
|
||||
#include "pinwidget.h"
|
||||
#include "screenshotsaver.h"
|
||||
#include "systemnotification.h"
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QPixmap>
|
||||
#include <QRect>
|
||||
|
||||
/**
|
||||
* @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;
|
||||
46
src/core/flameshotdaemon.h
Normal file
46
src/core/flameshotdaemon.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QObject>
|
||||
#include <QtDBus/QDBusAbstractAdaptor>
|
||||
|
||||
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<QWidget*> m_widgets;
|
||||
static FlameshotDaemon* m_instance;
|
||||
|
||||
friend class FlameshotDBusAdapter;
|
||||
};
|
||||
@@ -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 <QBuffer>
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "src/core/controller.h"
|
||||
#include <QtDBus/QDBusAbstractAdaptor>
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
266
src/main.cpp
266
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 <QApplication>
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
#include <QTextStream>
|
||||
#include <QSharedMemory>
|
||||
#include <QTimer>
|
||||
#include <QTranslator>
|
||||
|
||||
@@ -28,22 +29,12 @@
|
||||
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
|
||||
#include "src/core/flameshotdbusadapter.h"
|
||||
#include "src/utils/dbusutils.h"
|
||||
#include <QApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <desktopinfo.h>
|
||||
#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<int>>("QList<int>");
|
||||
qApp->setApplicationVersion(static_cast<QString>(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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 <QApplication>
|
||||
// FIXME #include <QBuffer>
|
||||
#include <QClipboard>
|
||||
#include <QCursor>
|
||||
#include <QDesktopServices>
|
||||
@@ -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."));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -81,6 +81,10 @@ static QMap<class QString, QSharedPointer<ValueHandler>>
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <QApplication>
|
||||
#include <QFile>
|
||||
#include <QRect>
|
||||
#include <QTextStream>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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 <QDBusConnection>
|
||||
#include <QObject>
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <QApplication>
|
||||
#include <QUrl>
|
||||
|
||||
#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
||||
#if !(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusMessage>
|
||||
@@ -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"),
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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<CaptureTool> activeToolObject();
|
||||
void initContext(bool fullscreen, uint requestId);
|
||||
void initContext(bool fullscreen, const CaptureRequest& req);
|
||||
void initPanel();
|
||||
void initSelection();
|
||||
void initShortcuts();
|
||||
|
||||
@@ -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<CaptureRequest::CaptureMode>(
|
||||
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();
|
||||
}
|
||||
|
||||
auto mode = static_cast<CaptureRequest::CaptureMode>(
|
||||
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();
|
||||
}
|
||||
m_launchButton->setEnabled(true);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QDateTime>
|
||||
#include <QDesktopServices>
|
||||
#include <QDesktopWidget>
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
#define HISTORYWIDGET_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
class QString;
|
||||
class QLayout;
|
||||
class QVBoxLayout;
|
||||
class NotificationWidget;
|
||||
|
||||
@@ -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 <QApplication>
|
||||
@@ -88,8 +89,7 @@ void InfoWindow::initLabels()
|
||||
|
||||
void InfoWindow::copyInfo()
|
||||
{
|
||||
QClipboard* clipboard = QApplication::clipboard();
|
||||
clipboard->setText(GlobalValues::versionInfo() + "\n" +
|
||||
FlameshotDaemon::copyToClipboard(GlobalValues::versionInfo() + "\n" +
|
||||
generateKernelString());
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,32 @@ cmd() {
|
||||
sleep 1
|
||||
}
|
||||
|
||||
notify() {
|
||||
if [ "$FLAMESHOT_PLATFORM" = "MAC" ]
|
||||
then
|
||||
osascript - "$1" <<EOF
|
||||
on run argv
|
||||
display notification (item 1 of argv) with title "Flameshot"
|
||||
end run
|
||||
EOF
|
||||
|
||||
else
|
||||
notify-send "GUI Test 1: --path" "Make a selection, then accept"
|
||||
fi
|
||||
}
|
||||
|
||||
display_img() {
|
||||
if [ "$FLAMESHOT_PLATFORM" = "MAC" ]
|
||||
then
|
||||
open -a Preview.app -f
|
||||
else
|
||||
display
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
wait_for_key() {
|
||||
echo "Press Enter to continue..." >&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.'
|
||||
|
||||
Reference in New Issue
Block a user