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">
|
<interface name="org.flameshot.Flameshot">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
requestCapture:
|
attachPin:
|
||||||
@requestData: Serialized CaptureRequest object.
|
@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">
|
<method name="attachPin">
|
||||||
<arg name="requestData" type="ay" direction="in"/>
|
<arg name="data" type="ay" direction="in"/>
|
||||||
</method>
|
</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">
|
<method name="attachScreenshotToClipboard">
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
<arg name="screenshot" type="ay" direction="in"/>
|
||||||
</method>
|
</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">
|
<method name="attachTextToClipboard">
|
||||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
<arg name="text" type="s" direction="in"/>
|
||||||
|
<arg name="notification" type="s" direction="in"/>
|
||||||
</method>
|
</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>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
|
|||||||
@@ -48,6 +48,12 @@
|
|||||||
;; Whether the tray icon is disabled (bool)
|
;; Whether the tray icon is disabled (bool)
|
||||||
;disabledTrayIcon=false
|
;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)
|
;; Last used tool thickness (int)
|
||||||
;drawThickness=1
|
;drawThickness=1
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ GeneralConf::GeneralConf(QWidget* parent)
|
|||||||
initSaveAfterCopy();
|
initSaveAfterCopy();
|
||||||
inituploadHistoryMax();
|
inituploadHistoryMax();
|
||||||
initUndoLimit();
|
initUndoLimit();
|
||||||
|
initAllowMultipleGuiInstances();
|
||||||
|
#if !defined(Q_OS_WIN)
|
||||||
|
initAutoCloseIdleDaemon();
|
||||||
|
#endif
|
||||||
|
|
||||||
m_layout->addStretch();
|
m_layout->addStretch();
|
||||||
|
|
||||||
@@ -73,6 +77,8 @@ void GeneralConf::_updateComponents(bool allowEmptySavePath)
|
|||||||
m_historyConfirmationToDelete->setChecked(
|
m_historyConfirmationToDelete->setChecked(
|
||||||
config.historyConfirmationToDelete());
|
config.historyConfirmationToDelete());
|
||||||
m_checkForUpdates->setChecked(config.checkForUpdates());
|
m_checkForUpdates->setChecked(config.checkForUpdates());
|
||||||
|
m_allowMultipleGuiInstances->setChecked(config.allowMultipleGuiInstances());
|
||||||
|
m_autoCloseIdleDaemon->setChecked(config.autoCloseIdleDaemon());
|
||||||
m_showStartupLaunchMessage->setChecked(config.showStartupLaunchMessage());
|
m_showStartupLaunchMessage->setChecked(config.showStartupLaunchMessage());
|
||||||
m_screenshotPathFixedCheck->setChecked(config.savePathFixed());
|
m_screenshotPathFixedCheck->setChecked(config.savePathFixed());
|
||||||
m_uploadHistoryMax->setValue(config.uploadHistoryMax());
|
m_uploadHistoryMax->setValue(config.uploadHistoryMax());
|
||||||
@@ -106,22 +112,22 @@ void GeneralConf::showDesktopNotificationChanged(bool checked)
|
|||||||
ConfigHandler().setShowDesktopNotification(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)
|
void GeneralConf::checkForUpdatesChanged(bool checked)
|
||||||
{
|
{
|
||||||
ConfigHandler().setCheckForUpdates(checked);
|
ConfigHandler().setCheckForUpdates(checked);
|
||||||
Controller::getInstance()->setCheckForUpdatesEnabled(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)
|
void GeneralConf::autostartChanged(bool checked)
|
||||||
{
|
{
|
||||||
ConfigHandler().setStartupLaunch(checked);
|
ConfigHandler().setStartupLaunch(checked);
|
||||||
@@ -250,10 +256,9 @@ void GeneralConf::initShowTrayIcon()
|
|||||||
m_showTray->setToolTip(tr("Show the systemtray icon"));
|
m_showTray->setToolTip(tr("Show the systemtray icon"));
|
||||||
m_scrollAreaLayout->addWidget(m_showTray);
|
m_scrollAreaLayout->addWidget(m_showTray);
|
||||||
|
|
||||||
connect(m_showTray,
|
connect(m_showTray, &QCheckBox::clicked, this, [](bool checked) {
|
||||||
&QCheckBox::stateChanged,
|
ConfigHandler().setDisabledTrayIcon(!checked);
|
||||||
this,
|
});
|
||||||
&GeneralConf::showTrayIconChanged);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,6 +319,32 @@ void GeneralConf::initCheckForUpdates()
|
|||||||
&GeneralConf::checkForUpdatesChanged);
|
&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()
|
void GeneralConf::initAutostart()
|
||||||
{
|
{
|
||||||
m_autostart = new QCheckBox(tr("Launch at startup"), this);
|
m_autostart = new QCheckBox(tr("Launch at startup"), this);
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ private slots:
|
|||||||
void showHelpChanged(bool checked);
|
void showHelpChanged(bool checked);
|
||||||
void showSidePanelButtonChanged(bool checked);
|
void showSidePanelButtonChanged(bool checked);
|
||||||
void showDesktopNotificationChanged(bool checked);
|
void showDesktopNotificationChanged(bool checked);
|
||||||
void showTrayIconChanged(bool checked);
|
|
||||||
void checkForUpdatesChanged(bool checked);
|
void checkForUpdatesChanged(bool checked);
|
||||||
|
void allowMultipleGuiInstancesChanged(bool checked);
|
||||||
|
void autoCloseIdleDaemonChanged(bool checked);
|
||||||
void autostartChanged(bool checked);
|
void autostartChanged(bool checked);
|
||||||
void historyConfirmationToDelete(bool checked);
|
void historyConfirmationToDelete(bool checked);
|
||||||
void uploadHistoryMaxChanged(int max);
|
void uploadHistoryMaxChanged(int max);
|
||||||
@@ -55,6 +56,8 @@ private:
|
|||||||
void initUndoLimit();
|
void initUndoLimit();
|
||||||
void initConfigButtons();
|
void initConfigButtons();
|
||||||
void initCheckForUpdates();
|
void initCheckForUpdates();
|
||||||
|
void initAllowMultipleGuiInstances();
|
||||||
|
void initAutoCloseIdleDaemon();
|
||||||
void initAutostart();
|
void initAutostart();
|
||||||
void initShowStartupLaunchMessage();
|
void initShowStartupLaunchMessage();
|
||||||
void initCopyAndCloseAfterUpload();
|
void initCopyAndCloseAfterUpload();
|
||||||
@@ -75,6 +78,8 @@ private:
|
|||||||
QCheckBox* m_helpMessage;
|
QCheckBox* m_helpMessage;
|
||||||
QCheckBox* m_sidePanelButton;
|
QCheckBox* m_sidePanelButton;
|
||||||
QCheckBox* m_checkForUpdates;
|
QCheckBox* m_checkForUpdates;
|
||||||
|
QCheckBox* m_allowMultipleGuiInstances;
|
||||||
|
QCheckBox* m_autoCloseIdleDaemon;
|
||||||
QCheckBox* m_autostart;
|
QCheckBox* m_autostart;
|
||||||
QCheckBox* m_showStartupLaunchMessage;
|
QCheckBox* m_showStartupLaunchMessage;
|
||||||
QCheckBox* m_copyAndCloseAfterUpload;
|
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)
|
IF (WIN32)
|
||||||
target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp)
|
target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp)
|
||||||
|
|||||||
@@ -23,63 +23,8 @@ CaptureRequest::CaptureRequest(CaptureRequest::CaptureMode mode,
|
|||||||
, m_delay(delay)
|
, m_delay(delay)
|
||||||
, m_tasks(tasks)
|
, m_tasks(tasks)
|
||||||
, m_data(data)
|
, 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
|
CaptureRequest::CaptureMode CaptureRequest::captureMode() const
|
||||||
{
|
{
|
||||||
return m_mode;
|
return m_mode;
|
||||||
@@ -118,7 +63,7 @@ void CaptureRequest::addTask(CaptureRequest::ExportTask task)
|
|||||||
m_tasks |= task;
|
m_tasks |= task;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CaptureRequest::removeTask(CaptureRequest::ExportTask task)
|
void CaptureRequest::removeTask(ExportTask task)
|
||||||
{
|
{
|
||||||
((int&)m_tasks) &= ~task;
|
((int&)m_tasks) &= ~task;
|
||||||
}
|
}
|
||||||
@@ -139,59 +84,3 @@ void CaptureRequest::setInitialSelection(const QRect& selection)
|
|||||||
{
|
{
|
||||||
m_initialSelection = 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);
|
void setStaticID(uint id);
|
||||||
|
|
||||||
uint id() const;
|
uint id() const;
|
||||||
QByteArray serialize() const;
|
|
||||||
static CaptureRequest deserialize(const QByteArray& data);
|
|
||||||
uint delay() const;
|
uint delay() const;
|
||||||
QString path() const;
|
QString path() const;
|
||||||
QVariant data() const;
|
QVariant data() const;
|
||||||
@@ -51,7 +49,6 @@ public:
|
|||||||
void addSaveTask(const QString& path = QString());
|
void addSaveTask(const QString& path = QString());
|
||||||
void addPinTask(const QRect& pinWindowGeometry);
|
void addPinTask(const QRect& pinWindowGeometry);
|
||||||
void setInitialSelection(const QRect& selection);
|
void setInitialSelection(const QRect& selection);
|
||||||
void exportCapture(const QPixmap& capture);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CaptureMode m_mode;
|
CaptureMode m_mode;
|
||||||
@@ -61,9 +58,6 @@ private:
|
|||||||
QVariant m_data;
|
QVariant m_data;
|
||||||
QRect m_pinWindowGeometry, m_initialSelection;
|
QRect m_pinWindowGeometry, m_initialSelection;
|
||||||
|
|
||||||
bool m_forcedID;
|
|
||||||
uint m_id;
|
|
||||||
|
|
||||||
CaptureRequest() {}
|
CaptureRequest() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,18 @@
|
|||||||
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||||
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
|
#include "flameshotdaemon.h"
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS)
|
#if defined(Q_OS_MACOS)
|
||||||
#include "external/QHotkey/QHotkey"
|
#include "external/QHotkey/QHotkey"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pinwidget.h"
|
||||||
|
#include "screenshotsaver.h"
|
||||||
#include "src/config/configwindow.h"
|
#include "src/config/configwindow.h"
|
||||||
#include "src/core/qguiappcurrentscreen.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/confighandler.h"
|
||||||
#include "src/utils/globalvalues.h"
|
#include "src/utils/globalvalues.h"
|
||||||
#include "src/utils/history.h"
|
#include "src/utils/history.h"
|
||||||
@@ -18,14 +23,17 @@
|
|||||||
#include "src/widgets/capture/capturewidget.h"
|
#include "src/widgets/capture/capturewidget.h"
|
||||||
#include "src/widgets/capturelauncher.h"
|
#include "src/widgets/capturelauncher.h"
|
||||||
#include "src/widgets/historywidget.h"
|
#include "src/widgets/historywidget.h"
|
||||||
|
#include "src/widgets/imguploaddialog.h"
|
||||||
#include "src/widgets/infowindow.h"
|
#include "src/widgets/infowindow.h"
|
||||||
#include "src/widgets/notificationwidget.h"
|
#include "src/widgets/notificationwidget.h"
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QBuffer>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
|
#include <QFile>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
@@ -64,21 +72,6 @@ Controller::Controller()
|
|||||||
m_appLatestVersion = QStringLiteral(APP_VERSION).replace("v", "");
|
m_appLatestVersion = QStringLiteral(APP_VERSION).replace("v", "");
|
||||||
qApp->setQuitOnLastWindowClosed(false);
|
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();
|
QString StyleSheet = CaptureButton::globalStyleSheet();
|
||||||
qApp->setStyleSheet(StyleSheet);
|
qApp->setStyleSheet(StyleSheet);
|
||||||
|
|
||||||
@@ -103,6 +96,18 @@ Controller::Controller()
|
|||||||
qApp,
|
qApp,
|
||||||
[&]() { this->showRecentUploads(); });
|
[&]() { this->showRecentUploads(); });
|
||||||
#endif
|
#endif
|
||||||
|
connect(ConfigHandler::getInstance(),
|
||||||
|
&ConfigHandler::fileChanged,
|
||||||
|
this,
|
||||||
|
[this]() {
|
||||||
|
ConfigHandler config;
|
||||||
|
if (config.disabledTrayIcon()) {
|
||||||
|
disableTrayIcon();
|
||||||
|
} else {
|
||||||
|
enableTrayIcon();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (ConfigHandler().checkForUpdates()) {
|
if (ConfigHandler().checkForUpdates()) {
|
||||||
getLatestAvailableVersion();
|
getLatestAvailableVersion();
|
||||||
}
|
}
|
||||||
@@ -119,14 +124,6 @@ Controller* Controller::getInstance()
|
|||||||
return &c;
|
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)
|
void Controller::setCheckForUpdatesEnabled(const bool enabled)
|
||||||
{
|
{
|
||||||
if (m_appUpdates != nullptr) {
|
if (m_appUpdates != nullptr) {
|
||||||
@@ -217,38 +214,33 @@ void Controller::appUpdates()
|
|||||||
|
|
||||||
void Controller::requestCapture(const CaptureRequest& request)
|
void Controller::requestCapture(const CaptureRequest& request)
|
||||||
{
|
{
|
||||||
uint id = request.id();
|
|
||||||
m_requestMap.insert(id, request);
|
|
||||||
|
|
||||||
switch (request.captureMode()) {
|
switch (request.captureMode()) {
|
||||||
case CaptureRequest::FULLSCREEN_MODE:
|
case CaptureRequest::FULLSCREEN_MODE:
|
||||||
doLater(request.delay(), this, [this, id]() {
|
doLater(request.delay(), this, [this, request]() {
|
||||||
this->startFullscreenCapture(id);
|
startFullscreenCapture(request);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case CaptureRequest::SCREEN_MODE: {
|
case CaptureRequest::SCREEN_MODE: {
|
||||||
int&& number = request.data().toInt();
|
int&& number = request.data().toInt();
|
||||||
doLater(request.delay(), this, [this, id, number]() {
|
doLater(request.delay(), this, [this, request, number]() {
|
||||||
this->startScreenGrab(id, number);
|
startScreenGrab(request, number);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CaptureRequest::GRAPHICAL_MODE: {
|
case CaptureRequest::GRAPHICAL_MODE: {
|
||||||
QString&& path = request.path();
|
doLater(request.delay(), this, [this, request]() {
|
||||||
doLater(request.delay(), this, [this, id, path]() {
|
startVisualCapture(request);
|
||||||
this->startVisualCapture(id, path);
|
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
emit captureFailed(id);
|
handleCaptureFailed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// creation of a new capture in GUI mode
|
// creation of a new capture in GUI mode
|
||||||
void Controller::startVisualCapture(const uint id,
|
void Controller::startVisualCapture(const CaptureRequest& req)
|
||||||
const QString& forcedSavePath)
|
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_MACOS)
|
#if defined(Q_OS_MACOS)
|
||||||
// This is required on MacOS because of Mission Control. If you'll switch to
|
// 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
|
#endif
|
||||||
|
|
||||||
if (nullptr == m_captureWindow) {
|
if (nullptr == m_captureWindow) {
|
||||||
|
// TODO is this unnecessary now?
|
||||||
int timeout = 5000; // 5 seconds
|
int timeout = 5000; // 5 seconds
|
||||||
const int delay = 100;
|
const int delay = 100;
|
||||||
QWidget* modalWidget = nullptr;
|
QWidget* modalWidget = nullptr;
|
||||||
@@ -281,17 +274,9 @@ void Controller::startVisualCapture(const uint id,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_captureWindow = new CaptureWidget(id, forcedSavePath);
|
m_captureWindow = new CaptureWidget(req);
|
||||||
// m_captureWindow = new CaptureWidget(id, forcedSavePath, false); //
|
// m_captureWindow = new CaptureWidget(forcedSavePath, false); //
|
||||||
// debug
|
// debug
|
||||||
connect(m_captureWindow,
|
|
||||||
&CaptureWidget::captureFailed,
|
|
||||||
this,
|
|
||||||
&Controller::captureFailed);
|
|
||||||
connect(m_captureWindow,
|
|
||||||
&CaptureWidget::captureTaken,
|
|
||||||
this,
|
|
||||||
&Controller::captureTaken);
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
m_captureWindow->show();
|
m_captureWindow->show();
|
||||||
@@ -311,11 +296,11 @@ void Controller::startVisualCapture(const uint id,
|
|||||||
m_appLatestUrl);
|
m_appLatestUrl);
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
bool ok = true;
|
||||||
QScreen* screen;
|
QScreen* screen;
|
||||||
@@ -333,7 +318,7 @@ void Controller::startScreenGrab(const uint id, const int screenNumber)
|
|||||||
}
|
}
|
||||||
QPixmap p(ScreenGrabber().grabScreen(screen, ok));
|
QPixmap p(ScreenGrabber().grabScreen(screen, ok));
|
||||||
if (ok) {
|
if (ok) {
|
||||||
CaptureRequest& req = *requests().find(id);
|
QRect geometry = ScreenGrabber().screenGeometry(screen);
|
||||||
QRect region = req.initialSelection();
|
QRect region = req.initialSelection();
|
||||||
if (region.isNull()) {
|
if (region.isNull()) {
|
||||||
region = ScreenGrabber().screenGeometry(screen);
|
region = ScreenGrabber().screenGeometry(screen);
|
||||||
@@ -347,9 +332,9 @@ void Controller::startScreenGrab(const uint id, const int screenNumber)
|
|||||||
// change geometry for pin task
|
// change geometry for pin task
|
||||||
req.addPinTask(region);
|
req.addPinTask(region);
|
||||||
}
|
}
|
||||||
emit captureTaken(id, p, region);
|
exportCapture(p, geometry, req);
|
||||||
} else {
|
} else {
|
||||||
emit captureFailed(id);
|
handleCaptureFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,6 +375,23 @@ void Controller::openLauncherWindow()
|
|||||||
#endif
|
#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()
|
void Controller::enableTrayIcon()
|
||||||
{
|
{
|
||||||
ConfigHandler().setDisabledTrayIcon(false);
|
ConfigHandler().setDisabledTrayIcon(false);
|
||||||
@@ -415,7 +417,7 @@ void Controller::enableTrayIcon()
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Wait 400 ms to hide the QMenu
|
// Wait 400 ms to hide the QMenu
|
||||||
doLater(400, this, [this]() { this->startVisualCapture(); });
|
doLater(400, this, [this]() { startVisualCapture(); });
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
QAction* launcherAction = new QAction(tr("&Open Launcher"), this);
|
QAction* launcherAction = new QAction(tr("&Open Launcher"), this);
|
||||||
@@ -560,40 +562,115 @@ void Controller::showRecentUploads()
|
|||||||
#endif
|
#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;
|
bool ok = true;
|
||||||
QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
|
QPixmap p(ScreenGrabber().grabEntireDesktop(ok));
|
||||||
CaptureRequest req(*requests().find(id));
|
|
||||||
QRect region = req.initialSelection();
|
QRect region = req.initialSelection();
|
||||||
if (!region.isNull()) {
|
if (!region.isNull()) {
|
||||||
p = p.copy(region);
|
p = p.copy(region);
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
// selection parameter is unused here
|
QRect selection; // `flameshot full` does not support --selection
|
||||||
emit captureTaken(id, p, {});
|
exportCapture(p, selection, req);
|
||||||
} else {
|
} 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);
|
exportCapture(p, selection, req);
|
||||||
if (it != m_requestMap.end()) {
|
|
||||||
it.value().exportCapture(p);
|
|
||||||
m_requestMap.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::handleCaptureFailed(uint id)
|
void Controller::handleCaptureFailed()
|
||||||
{
|
{
|
||||||
m_requestMap.remove(id);
|
emit captureFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::doLater(int msec, QObject* receiver, lambda func)
|
void Controller::doLater(int msec, QObject* receiver, lambda func)
|
||||||
|
|||||||
@@ -37,16 +37,14 @@ public:
|
|||||||
~Controller();
|
~Controller();
|
||||||
void operator=(const Controller&) = delete;
|
void operator=(const Controller&) = delete;
|
||||||
|
|
||||||
void enableExports();
|
|
||||||
|
|
||||||
void setCheckForUpdatesEnabled(const bool enabled);
|
void setCheckForUpdatesEnabled(const bool enabled);
|
||||||
|
|
||||||
QMap<uint, CaptureRequest>& requests();
|
QMap<uint, CaptureRequest>& requests();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void captureTaken(uint id, QPixmap p, const QRect& selection);
|
// TODO remove all parameters from captureTaken and update dependencies
|
||||||
void captureFailed(uint id);
|
void captureTaken(QPixmap p, const QRect& selection);
|
||||||
void captureSaved(uint id, QString savePath);
|
void captureFailed();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void requestCapture(const CaptureRequest& request);
|
void requestCapture(const CaptureRequest& request);
|
||||||
@@ -55,6 +53,8 @@ public slots:
|
|||||||
void openInfoWindow();
|
void openInfoWindow();
|
||||||
void appUpdates();
|
void appUpdates();
|
||||||
void openLauncherWindow();
|
void openLauncherWindow();
|
||||||
|
// TODO move tray icon handling to FlameshotDaemon
|
||||||
|
void initTrayIcon();
|
||||||
void enableTrayIcon();
|
void enableTrayIcon();
|
||||||
void disableTrayIcon();
|
void disableTrayIcon();
|
||||||
void sendTrayNotification(
|
void sendTrayNotification(
|
||||||
@@ -66,16 +66,19 @@ public slots:
|
|||||||
|
|
||||||
void showRecentUploads();
|
void showRecentUploads();
|
||||||
|
|
||||||
void sendCaptureSaved(uint id, const QString& savePath);
|
void exportCapture(QPixmap p, QRect& selection, const CaptureRequest& req);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void startFullscreenCapture(const uint id = 0);
|
void startFullscreenCapture(const CaptureRequest& req);
|
||||||
void startVisualCapture(const uint id = 0,
|
void startVisualCapture(
|
||||||
const QString& forcedSavePath = QString());
|
const CaptureRequest& req = CaptureRequest::GRAPHICAL_MODE);
|
||||||
void startScreenGrab(const uint id = 0, const int screenNumber = -1);
|
void startScreenGrab(CaptureRequest req, const int screenNumber = -1);
|
||||||
|
|
||||||
void handleCaptureTaken(uint id, QPixmap p);
|
public slots: // TODO move these up
|
||||||
void handleCaptureFailed(uint id);
|
void handleCaptureTaken(const CaptureRequest& req,
|
||||||
|
QPixmap p,
|
||||||
|
QRect selection);
|
||||||
|
void handleCaptureFailed();
|
||||||
|
|
||||||
void handleReplyCheckUpdates(QNetworkReply* reply);
|
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
|
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||||
|
|
||||||
#include "flameshotdbusadapter.h"
|
#include "flameshotdbusadapter.h"
|
||||||
#include "src/core/controller.h"
|
#include "src/core/flameshotdaemon.h"
|
||||||
#include "src/utils/confighandler.h"
|
|
||||||
#include "src/utils/screengrabber.h"
|
|
||||||
#include "src/utils/screenshotsaver.h"
|
|
||||||
#include "src/utils/systemnotification.h"
|
|
||||||
#include <QBuffer>
|
|
||||||
FlameshotDBusAdapter::FlameshotDBusAdapter(QObject* parent)
|
FlameshotDBusAdapter::FlameshotDBusAdapter(QObject* parent)
|
||||||
: QDBusAbstractAdaptor(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() {}
|
FlameshotDBusAdapter::~FlameshotDBusAdapter() {}
|
||||||
|
|
||||||
void FlameshotDBusAdapter::requestCapture(const QByteArray& requestData)
|
void FlameshotDBusAdapter::attachScreenshotToClipboard(const QByteArray& data)
|
||||||
{
|
{
|
||||||
CaptureRequest req = CaptureRequest::deserialize(requestData);
|
FlameshotDaemon::instance()->attachScreenshotToClipboard(data);
|
||||||
Controller::getInstance()->requestCapture(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
FlameshotDaemon::instance()->attachPin(data);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/core/controller.h"
|
|
||||||
#include <QtDBus/QDBusAbstractAdaptor>
|
#include <QtDBus/QDBusAbstractAdaptor>
|
||||||
|
|
||||||
class FlameshotDBusAdapter : public QDBusAbstractAdaptor
|
class FlameshotDBusAdapter : public QDBusAbstractAdaptor
|
||||||
@@ -15,18 +14,8 @@ public:
|
|||||||
explicit FlameshotDBusAdapter(QObject* parent = nullptr);
|
explicit FlameshotDBusAdapter(QObject* parent = nullptr);
|
||||||
virtual ~FlameshotDBusAdapter();
|
virtual ~FlameshotDBusAdapter();
|
||||||
|
|
||||||
signals:
|
|
||||||
void captureTaken(uint id, QByteArray rawImage, QRect selection);
|
|
||||||
void captureFailed(uint id);
|
|
||||||
void captureSaved(uint id, QString savePath);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Q_NOREPLY void requestCapture(const QByteArray& requestData);
|
Q_NOREPLY void attachScreenshotToClipboard(const QByteArray& data);
|
||||||
Q_NOREPLY void openLauncher();
|
Q_NOREPLY void attachTextToClipboard(QString text, QString notification);
|
||||||
Q_NOREPLY void openConfig();
|
Q_NOREPLY void attachPin(const QByteArray& data);
|
||||||
Q_NOREPLY void trayIconEnabled(bool enabled);
|
|
||||||
Q_NOREPLY void autostartEnabled(bool enabled);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void handleCaptureTaken(uint id, const QPixmap& p, const QRect& selection);
|
|
||||||
};
|
};
|
||||||
|
|||||||
266
src/main.cpp
266
src/main.cpp
@@ -11,6 +11,7 @@
|
|||||||
#include "src/config/styleoverride.h"
|
#include "src/config/styleoverride.h"
|
||||||
#include "src/core/capturerequest.h"
|
#include "src/core/capturerequest.h"
|
||||||
#include "src/core/controller.h"
|
#include "src/core/controller.h"
|
||||||
|
#include "src/core/flameshotdaemon.h"
|
||||||
#include "src/utils/confighandler.h"
|
#include "src/utils/confighandler.h"
|
||||||
#include "src/utils/filenamehandler.h"
|
#include "src/utils/filenamehandler.h"
|
||||||
#include "src/utils/pathinfo.h"
|
#include "src/utils/pathinfo.h"
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QLibraryInfo>
|
#include <QLibraryInfo>
|
||||||
#include <QTextStream>
|
#include <QSharedMemory>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
|
||||||
@@ -28,22 +29,12 @@
|
|||||||
|
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
|
||||||
#include "src/core/flameshotdbusadapter.h"
|
#include "src/core/flameshotdbusadapter.h"
|
||||||
#include "src/utils/dbusutils.h"
|
#include <QApplication>
|
||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
#include <QDBusMessage>
|
#include <QDBusMessage>
|
||||||
#include <desktopinfo.h>
|
#include <desktopinfo.h>
|
||||||
#endif
|
#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
|
#ifdef Q_OS_LINUX
|
||||||
// source: https://github.com/ksnip/ksnip/issues/416
|
// source: https://github.com/ksnip/ksnip/issues/416
|
||||||
void wayland_hacks()
|
void wayland_hacks()
|
||||||
@@ -56,6 +47,42 @@ void wayland_hacks()
|
|||||||
}
|
}
|
||||||
#endif
|
#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[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
@@ -67,7 +94,9 @@ int main(int argc, char* argv[])
|
|||||||
// required for the button serialization
|
// required for the button serialization
|
||||||
// TODO: change to QVector in v1.0
|
// TODO: change to QVector in v1.0
|
||||||
qRegisterMetaTypeStreamOperators<QList<int>>("QList<int>");
|
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
|
// no arguments, just launch Flameshot
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
@@ -97,14 +126,14 @@ int main(int argc, char* argv[])
|
|||||||
"_",
|
"_",
|
||||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||||
|
|
||||||
app.installTranslator(&translator);
|
qApp->installTranslator(&translator);
|
||||||
app.installTranslator(&qtTranslator);
|
qApp->installTranslator(&qtTranslator);
|
||||||
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
|
qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
|
||||||
app.setApplicationName(QStringLiteral("flameshot"));
|
|
||||||
app.setOrganizationName(QStringLiteral("flameshot"));
|
|
||||||
|
|
||||||
auto c = Controller::getInstance();
|
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);
|
new FlameshotDBusAdapter(c);
|
||||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||||
if (!dbus.isConnected()) {
|
if (!dbus.isConnected()) {
|
||||||
@@ -114,20 +143,14 @@ int main(int argc, char* argv[])
|
|||||||
dbus.registerObject(QStringLiteral("/"), c);
|
dbus.registerObject(QStringLiteral("/"), c);
|
||||||
dbus.registerService(QStringLiteral("org.flameshot.Flameshot"));
|
dbus.registerService(QStringLiteral("org.flameshot.Flameshot"));
|
||||||
#endif
|
#endif
|
||||||
// Exporting captures must be connected after the dbus interface
|
return qApp->exec();
|
||||||
// or the dbus signal gets blocked until we end the exports.
|
|
||||||
c->enableExports();
|
|
||||||
return app.exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
#if !defined(Q_OS_WIN)
|
||||||
/*--------------|
|
/*--------------|
|
||||||
* CLI parsing |
|
* CLI parsing |
|
||||||
* ------------*/
|
* ------------*/
|
||||||
QCoreApplication app(argc, argv);
|
new QCoreApplication(argc, argv);
|
||||||
app.setApplicationName(QStringLiteral("flameshot"));
|
|
||||||
app.setOrganizationName(QStringLiteral("flameshot"));
|
|
||||||
app.setApplicationVersion(qApp->applicationVersion());
|
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
// Add description
|
// Add description
|
||||||
parser.setDescription(
|
parser.setDescription(
|
||||||
@@ -305,7 +328,7 @@ int main(int argc, char* argv[])
|
|||||||
checkOption },
|
checkOption },
|
||||||
configArgument);
|
configArgument);
|
||||||
// Parse
|
// Parse
|
||||||
if (!parser.parse(app.arguments())) {
|
if (!parser.parse(qApp->arguments())) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,18 +336,28 @@ int main(int argc, char* argv[])
|
|||||||
//--------------
|
//--------------
|
||||||
if (parser.isSet(helpOption) || parser.isSet(versionOption)) {
|
if (parser.isSet(helpOption) || parser.isSet(versionOption)) {
|
||||||
} else if (parser.isSet(launcherArgument)) { // LAUNCHER
|
} else if (parser.isSet(launcherArgument)) { // LAUNCHER
|
||||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
delete qApp;
|
||||||
QStringLiteral("org.flameshot.Flameshot"),
|
new QApplication(argc, argv);
|
||||||
QStringLiteral("/"),
|
Controller* controller = Controller::getInstance();
|
||||||
QLatin1String(""),
|
controller->openLauncherWindow();
|
||||||
QStringLiteral("openLauncher"));
|
qApp->exec();
|
||||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
|
||||||
if (!sessionBus.isConnected()) {
|
|
||||||
SystemNotification().sendMessage(
|
|
||||||
QObject::tr("Unable to connect via DBus"));
|
|
||||||
}
|
|
||||||
sessionBus.call(m);
|
|
||||||
} else if (parser.isSet(guiArgument)) { // GUI
|
} 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
|
// Option values
|
||||||
QString path = parser.value(pathOption);
|
QString path = parser.value(pathOption);
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
@@ -338,7 +371,6 @@ int main(int argc, char* argv[])
|
|||||||
bool pin = parser.isSet(pinOption);
|
bool pin = parser.isSet(pinOption);
|
||||||
bool upload = parser.isSet(uploadOption);
|
bool upload = parser.isSet(uploadOption);
|
||||||
bool acceptOnSelect = parser.isSet(acceptOnSelectOption);
|
bool acceptOnSelect = parser.isSet(acceptOnSelectOption);
|
||||||
DBusUtils dbusUtils;
|
|
||||||
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
|
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
|
||||||
if (!region.isEmpty()) {
|
if (!region.isEmpty()) {
|
||||||
req.setInitialSelection(Region().value(region).toRect());
|
req.setInitialSelection(Region().value(region).toRect());
|
||||||
@@ -368,28 +400,12 @@ int main(int argc, char* argv[])
|
|||||||
req.addSaveTask();
|
req.addSaveTask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint id = req.id();
|
requestCaptureAndWait(req);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else if (parser.isSet(fullArgument)) { // FULL
|
} 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
|
// Option values
|
||||||
QString path = parser.value(pathOption);
|
QString path = parser.value(pathOption);
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
@@ -421,33 +437,12 @@ int main(int argc, char* argv[])
|
|||||||
if (!clipboard && path.isEmpty() && !raw && !upload) {
|
if (!clipboard && path.isEmpty() && !raw && !upload) {
|
||||||
req.addSaveTask();
|
req.addSaveTask();
|
||||||
}
|
}
|
||||||
uint id = req.id();
|
requestCaptureAndWait(req);
|
||||||
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();
|
|
||||||
}
|
|
||||||
} else if (parser.isSet(screenArgument)) { // SCREEN
|
} 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);
|
QString numberStr = parser.value(screenNumberOption);
|
||||||
// Option values
|
// Option values
|
||||||
int number =
|
int number =
|
||||||
@@ -494,47 +489,21 @@ int main(int argc, char* argv[])
|
|||||||
req.addSaveTask();
|
req.addSaveTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint id = req.id();
|
requestCaptureAndWait(req);
|
||||||
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();
|
|
||||||
}
|
|
||||||
} else if (parser.isSet(configArgument)) { // CONFIG
|
} else if (parser.isSet(configArgument)) { // CONFIG
|
||||||
bool autostart = parser.isSet(autostartOption);
|
bool autostart = parser.isSet(autostartOption);
|
||||||
bool filename = parser.isSet(filenameOption);
|
bool filename = parser.isSet(filenameOption);
|
||||||
bool tray = parser.isSet(trayOption);
|
bool tray = parser.isSet(trayOption);
|
||||||
bool help = parser.isSet(showHelpOption);
|
|
||||||
bool mainColor = parser.isSet(mainColorOption);
|
bool mainColor = parser.isSet(mainColorOption);
|
||||||
bool contrastColor = parser.isSet(contrastColorOption);
|
bool contrastColor = parser.isSet(contrastColorOption);
|
||||||
bool check = parser.isSet(checkOption);
|
bool check = parser.isSet(checkOption);
|
||||||
bool someFlagSet =
|
bool someFlagSet =
|
||||||
(filename || tray || help || mainColor || contrastColor || check);
|
(filename || tray || mainColor || contrastColor || check);
|
||||||
if (check) {
|
if (check) {
|
||||||
QTextStream stream(stderr);
|
QTextStream err(stderr);
|
||||||
bool ok = ConfigHandler(true).checkForErrors(&stream);
|
bool ok = ConfigHandler(true).checkForErrors(&err);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
stream << QStringLiteral("No errors detected.\n");
|
err << QStringLiteral("No errors detected.\n");
|
||||||
goto finish;
|
goto finish;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -542,22 +511,7 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
ConfigHandler config;
|
ConfigHandler config;
|
||||||
if (autostart) {
|
if (autostart) {
|
||||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
config.setStartupLaunch(parser.value(autostartOption) == "true");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
if (filename) {
|
if (filename) {
|
||||||
QString newFilename(parser.value(filenameOption));
|
QString newFilename(parser.value(filenameOption));
|
||||||
@@ -570,31 +524,10 @@ int main(int argc, char* argv[])
|
|||||||
.arg(fh.parsedPattern());
|
.arg(fh.parsedPattern());
|
||||||
}
|
}
|
||||||
if (tray) {
|
if (tray) {
|
||||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
config.setDisabledTrayIcon(parser.value(trayOption) == "false");
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (mainColor) {
|
if (mainColor) {
|
||||||
|
// TODO use value handler
|
||||||
QString colorCode = parser.value(mainColorOption);
|
QString colorCode = parser.value(mainColorOption);
|
||||||
QColor parsedColor(colorCode);
|
QColor parsedColor(colorCode);
|
||||||
config.setUiColor(parsedColor);
|
config.setUiColor(parsedColor);
|
||||||
@@ -607,17 +540,12 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Open gui when no options
|
// Open gui when no options
|
||||||
if (!someFlagSet) {
|
if (!someFlagSet) {
|
||||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
delete qApp;
|
||||||
QStringLiteral("org.flameshot.Flameshot"),
|
new QApplication(argc, argv);
|
||||||
QStringLiteral("/"),
|
QObject::connect(
|
||||||
QLatin1String(""),
|
qApp, &QApplication::lastWindowClosed, qApp, &QApplication::quit);
|
||||||
QStringLiteral("openConfig"));
|
Controller::getInstance()->openConfigWindow();
|
||||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
qApp->exec();
|
||||||
if (!sessionBus.isConnected()) {
|
|
||||||
SystemNotification().sendMessage(
|
|
||||||
QObject::tr("Unable to connect via DBus"));
|
|
||||||
}
|
|
||||||
sessionBus.call(m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finish:
|
finish:
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ CaptureTool* AcceptTool::copy(QObject* parent)
|
|||||||
void AcceptTool::pressed(CaptureContext& context)
|
void AcceptTool::pressed(CaptureContext& context)
|
||||||
{
|
{
|
||||||
emit requestAction(REQ_CAPTURE_DONE_OK);
|
emit requestAction(REQ_CAPTURE_DONE_OK);
|
||||||
if (context.request()->tasks() & CaptureRequest::PIN) {
|
if (context.request.tasks() & CaptureRequest::PIN) {
|
||||||
QRect geometry = context.selection;
|
QRect geometry = context.selection;
|
||||||
geometry.moveTopLeft(geometry.topLeft() + context.widgetOffset);
|
geometry.moveTopLeft(geometry.topLeft() + context.widgetOffset);
|
||||||
context.request()->addPinTask(geometry);
|
context.request.addTask(CaptureRequest::PIN);
|
||||||
}
|
}
|
||||||
emit requestAction(REQ_CLOSE_GUI);
|
emit requestAction(REQ_CLOSE_GUI);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,3 @@ QPixmap CaptureContext::selectedScreenshotArea() const
|
|||||||
return screenshot.copy(selection);
|
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;
|
int toolSize;
|
||||||
// Mode of the capture widget
|
// Mode of the capture widget
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
uint requestId;
|
CaptureRequest request = CaptureRequest::GRAPHICAL_MODE;
|
||||||
|
|
||||||
QPixmap selectedScreenshotArea() const;
|
QPixmap selectedScreenshotArea() const;
|
||||||
CaptureRequest* request();
|
|
||||||
CaptureRequest* request() const;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ CaptureTool* CopyTool::copy(QObject* parent)
|
|||||||
|
|
||||||
void CopyTool::pressed(CaptureContext& context)
|
void CopyTool::pressed(CaptureContext& context)
|
||||||
{
|
{
|
||||||
context.request()->addTask(CaptureRequest::COPY);
|
context.request.addTask(CaptureRequest::COPY);
|
||||||
emit requestAction(REQ_CAPTURE_DONE_OK);
|
emit requestAction(REQ_CAPTURE_DONE_OK);
|
||||||
emit requestAction(REQ_CLOSE_GUI);
|
emit requestAction(REQ_CLOSE_GUI);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,6 @@ CaptureTool* ImgUploaderTool::copy(QObject* parent)
|
|||||||
void ImgUploaderTool::pressed(CaptureContext& context)
|
void ImgUploaderTool::pressed(CaptureContext& context)
|
||||||
{
|
{
|
||||||
emit requestAction(REQ_CAPTURE_DONE_OK);
|
emit requestAction(REQ_CAPTURE_DONE_OK);
|
||||||
context.request()->addTask(CaptureRequest::UPLOAD);
|
context.request.addTask(CaptureRequest::UPLOAD);
|
||||||
emit requestAction(REQ_CLOSE_GUI);
|
emit requestAction(REQ_CLOSE_GUI);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||||
|
|
||||||
#include "imguploaderbase.h"
|
#include "imguploaderbase.h"
|
||||||
|
#include "src/core/flameshotdaemon.h"
|
||||||
#include "src/utils/confighandler.h"
|
#include "src/utils/confighandler.h"
|
||||||
#include "src/utils/globalvalues.h"
|
#include "src/utils/globalvalues.h"
|
||||||
#include "src/utils/history.h"
|
#include "src/utils/history.h"
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include "src/widgets/loadspinner.h"
|
#include "src/widgets/loadspinner.h"
|
||||||
#include "src/widgets/notificationwidget.h"
|
#include "src/widgets/notificationwidget.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
// FIXME #include <QBuffer>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
@@ -157,13 +159,13 @@ void ImgUploaderBase::openURL()
|
|||||||
|
|
||||||
void ImgUploaderBase::copyURL()
|
void ImgUploaderBase::copyURL()
|
||||||
{
|
{
|
||||||
QApplication::clipboard()->setText(m_imageURL.toString());
|
FlameshotDaemon::copyToClipboard(m_imageURL.toString());
|
||||||
m_notification->showMessage(tr("URL copied to clipboard."));
|
m_notification->showMessage(tr("URL copied to clipboard."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImgUploaderBase::copyImage()
|
void ImgUploaderBase::copyImage()
|
||||||
{
|
{
|
||||||
QApplication::clipboard()->setPixmap(m_pixmap);
|
FlameshotDaemon::copyToClipboard(m_pixmap);
|
||||||
m_notification->showMessage(tr("Screenshot copied to clipboard."));
|
m_notification->showMessage(tr("Screenshot copied to clipboard."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,4 +175,4 @@ void ImgUploaderBase::deleteCurrentImage()
|
|||||||
HISTORY_FILE_NAME unpackFileName =
|
HISTORY_FILE_NAME unpackFileName =
|
||||||
history.unpackFileName(m_currentImageName);
|
history.unpackFileName(m_currentImageName);
|
||||||
deleteImage(unpackFileName.file, unpackFileName.token);
|
deleteImage(unpackFileName.file, unpackFileName.token);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ CaptureTool* PinTool::copy(QObject* parent)
|
|||||||
void PinTool::pressed(CaptureContext& context)
|
void PinTool::pressed(CaptureContext& context)
|
||||||
{
|
{
|
||||||
emit requestAction(REQ_CAPTURE_DONE_OK);
|
emit requestAction(REQ_CAPTURE_DONE_OK);
|
||||||
QRect geometry = context.selection;
|
context.request.addTask(CaptureRequest::PIN);
|
||||||
geometry.setTopLeft(geometry.topLeft() + context.widgetOffset);
|
|
||||||
context.request()->addPinTask(geometry);
|
|
||||||
emit requestAction(REQ_CLOSE_GUI);
|
emit requestAction(REQ_CLOSE_GUI);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ CaptureTool* SaveTool::copy(QObject* parent)
|
|||||||
|
|
||||||
void SaveTool::pressed(CaptureContext& context)
|
void SaveTool::pressed(CaptureContext& context)
|
||||||
{
|
{
|
||||||
context.request()->addSaveTask();
|
context.request.addSaveTask();
|
||||||
emit requestAction(REQ_CAPTURE_DONE_OK);
|
emit requestAction(REQ_CAPTURE_DONE_OK);
|
||||||
emit requestAction(REQ_CLOSE_GUI);
|
emit requestAction(REQ_CLOSE_GUI);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
# Required to generate MOC
|
# Required to generate MOC
|
||||||
target_sources(
|
target_sources(
|
||||||
flameshot
|
flameshot
|
||||||
PRIVATE dbusutils.h
|
PRIVATE filenamehandler.h
|
||||||
filenamehandler.h
|
|
||||||
screengrabber.h
|
screengrabber.h
|
||||||
systemnotification.h
|
systemnotification.h
|
||||||
valuehandler.h
|
valuehandler.h
|
||||||
@@ -18,7 +17,6 @@ target_sources(
|
|||||||
systemnotification.cpp
|
systemnotification.cpp
|
||||||
valuehandler.cpp
|
valuehandler.cpp
|
||||||
screenshotsaver.cpp
|
screenshotsaver.cpp
|
||||||
dbusutils.cpp
|
|
||||||
globalvalues.cpp
|
globalvalues.cpp
|
||||||
desktopfileparse.cpp
|
desktopfileparse.cpp
|
||||||
desktopinfo.cpp
|
desktopinfo.cpp
|
||||||
|
|||||||
@@ -81,6 +81,10 @@ static QMap<class QString, QSharedPointer<ValueHandler>>
|
|||||||
OPTION("disabledTrayIcon" ,Bool ( false )),
|
OPTION("disabledTrayIcon" ,Bool ( false )),
|
||||||
OPTION("historyConfirmationToDelete" ,Bool ( true )),
|
OPTION("historyConfirmationToDelete" ,Bool ( true )),
|
||||||
OPTION("checkForUpdates" ,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)
|
#if defined(Q_OS_MACOS)
|
||||||
OPTION("startupLaunch" ,Bool ( false )),
|
OPTION("startupLaunch" ,Bool ( false )),
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -29,9 +29,14 @@ class QTextStream;
|
|||||||
* and `TYPE` is the C++ type.
|
* and `TYPE` is the C++ type.
|
||||||
*/
|
*/
|
||||||
#define CONFIG_SETTER(FUNC, KEY, 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(drawFontSize, setDrawFontSize, int)
|
||||||
CONFIG_GETTER_SETTER(keepOpenAppLauncher, setKeepOpenAppLauncher, bool)
|
CONFIG_GETTER_SETTER(keepOpenAppLauncher, setKeepOpenAppLauncher, bool)
|
||||||
CONFIG_GETTER_SETTER(checkForUpdates, setCheckForUpdates, bool)
|
CONFIG_GETTER_SETTER(checkForUpdates, setCheckForUpdates, bool)
|
||||||
|
CONFIG_GETTER_SETTER(allowMultipleGuiInstances,
|
||||||
|
setAllowMultipleGuiInstances,
|
||||||
|
bool)
|
||||||
|
CONFIG_GETTER_SETTER(autoCloseIdleDaemon, setAutoCloseIdleDaemon, bool)
|
||||||
CONFIG_GETTER_SETTER(showStartupLaunchMessage,
|
CONFIG_GETTER_SETTER(showStartupLaunchMessage,
|
||||||
setShowStartupLaunchMessage,
|
setShowStartupLaunchMessage,
|
||||||
bool)
|
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 "screenshotsaver.h"
|
||||||
#include "src/core/controller.h"
|
#include "src/core/controller.h"
|
||||||
|
#include "src/core/flameshotdaemon.h"
|
||||||
#include "src/utils/confighandler.h"
|
#include "src/utils/confighandler.h"
|
||||||
#include "src/utils/filenamehandler.h"
|
#include "src/utils/filenamehandler.h"
|
||||||
#include "src/utils/globalvalues.h"
|
#include "src/utils/globalvalues.h"
|
||||||
@@ -22,13 +23,7 @@
|
|||||||
#include "src/widgets/capture/capturewidget.h"
|
#include "src/widgets/capture/capturewidget.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ScreenshotSaver::ScreenshotSaver()
|
ScreenshotSaver::ScreenshotSaver() {}
|
||||||
: m_id(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ScreenshotSaver::ScreenshotSaver(const unsigned id)
|
|
||||||
: m_id(id)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void ScreenshotSaver::saveToClipboardMime(const QPixmap& capture,
|
void ScreenshotSaver::saveToClipboardMime(const QPixmap& capture,
|
||||||
const QString& imageType)
|
const QString& imageType)
|
||||||
@@ -102,8 +97,6 @@ bool ScreenshotSaver::saveToFilesystem(const QPixmap& capture,
|
|||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
saveMessage += QObject::tr("Capture saved as ") + completePath;
|
saveMessage += QObject::tr("Capture saved as ") + completePath;
|
||||||
Controller::getInstance()->sendCaptureSaved(
|
|
||||||
m_id, QFileInfo(completePath).canonicalFilePath());
|
|
||||||
} else {
|
} else {
|
||||||
saveMessage += QObject::tr("Error trying to save as ") + completePath;
|
saveMessage += QObject::tr("Error trying to save as ") + completePath;
|
||||||
if (file.error() != QFile::NoError) {
|
if (file.error() != QFile::NoError) {
|
||||||
@@ -192,20 +185,11 @@ bool ScreenshotSaver::saveToFilesystemGUI(const QPixmap& capture)
|
|||||||
ConfigHandler().setSavePath(pathNoFile);
|
ConfigHandler().setSavePath(pathNoFile);
|
||||||
|
|
||||||
QString msg = QObject::tr("Capture saved as ") + savePath;
|
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);
|
SystemNotification().sendMessage(msg, savePath);
|
||||||
|
|
||||||
Controller::getInstance()->sendCaptureSaved(
|
|
||||||
m_id, QFileInfo(savePath).canonicalFilePath());
|
|
||||||
|
|
||||||
if (config.copyPathAfterSave()) {
|
if (config.copyPathAfterSave()) {
|
||||||
QApplication::clipboard()->setText(savePath);
|
FlameshotDaemon::copyToClipboard(
|
||||||
|
savePath, QObject::tr("Path copied to clipboard as ") + savePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ class ScreenshotSaver
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScreenshotSaver();
|
ScreenshotSaver();
|
||||||
ScreenshotSaver(const unsigned id);
|
|
||||||
|
|
||||||
void saveToClipboard(const QPixmap& capture);
|
void saveToClipboard(const QPixmap& capture);
|
||||||
void saveToClipboardMime(const QPixmap& capture, const QString& imageType);
|
void saveToClipboardMime(const QPixmap& capture, const QString& imageType);
|
||||||
@@ -22,7 +21,6 @@ public:
|
|||||||
bool saveToFilesystemGUI(const QPixmap& capture);
|
bool saveToFilesystemGUI(const QPixmap& capture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned m_id;
|
|
||||||
QString ShowSaveFileDialog(QWidget* parent,
|
QString ShowSaveFileDialog(QWidget* parent,
|
||||||
const QString& title,
|
const QString& title,
|
||||||
const QString& directory);
|
const QString& directory);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
#if !(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
#include <QDBusInterface>
|
#include <QDBusInterface>
|
||||||
#include <QDBusMessage>
|
#include <QDBusMessage>
|
||||||
@@ -14,7 +14,7 @@ SystemNotification::SystemNotification(QObject* parent)
|
|||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_interface(nullptr)
|
, m_interface(nullptr)
|
||||||
{
|
{
|
||||||
#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
#if !(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
||||||
m_interface =
|
m_interface =
|
||||||
new QDBusInterface(QStringLiteral("org.freedesktop.Notifications"),
|
new QDBusInterface(QStringLiteral("org.freedesktop.Notifications"),
|
||||||
QStringLiteral("/org/freedesktop/Notifications"),
|
QStringLiteral("/org/freedesktop/Notifications"),
|
||||||
|
|||||||
@@ -48,8 +48,8 @@
|
|||||||
// an area of selection with its respective buttons.
|
// an area of selection with its respective buttons.
|
||||||
|
|
||||||
// enableSaveWindow
|
// enableSaveWindow
|
||||||
CaptureWidget::CaptureWidget(uint id,
|
|
||||||
const QString& savePath,
|
CaptureWidget::CaptureWidget(const CaptureRequest& req,
|
||||||
bool fullScreen,
|
bool fullScreen,
|
||||||
QWidget* parent)
|
QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
@@ -90,7 +90,7 @@ CaptureWidget::CaptureWidget(uint id,
|
|||||||
m_uiColor = m_config.uiColor();
|
m_uiColor = m_config.uiColor();
|
||||||
m_contrastUiColor = m_config.contrastUiColor();
|
m_contrastUiColor = m_config.contrastUiColor();
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
initContext(fullScreen, id);
|
initContext(fullScreen, req);
|
||||||
#if (defined(Q_OS_WIN) || defined(Q_OS_MACOS))
|
#if (defined(Q_OS_WIN) || defined(Q_OS_MACOS))
|
||||||
// Top left of the whole set of screens
|
// Top left of the whole set of screens
|
||||||
QPoint topLeft(0, 0);
|
QPoint topLeft(0, 0);
|
||||||
@@ -251,9 +251,12 @@ CaptureWidget::~CaptureWidget()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (m_captureDone) {
|
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 {
|
} else {
|
||||||
emit captureFailed(m_context.requestId);
|
Controller::getInstance()->handleCaptureFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +264,7 @@ void CaptureWidget::initButtons()
|
|||||||
{
|
{
|
||||||
auto allButtonTypes = CaptureToolButton::getIterableButtonTypes();
|
auto allButtonTypes = CaptureToolButton::getIterableButtonTypes();
|
||||||
auto visibleButtonTypes = m_config.buttons();
|
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);
|
allButtonTypes.removeOne(CaptureTool::TYPE_ACCEPT);
|
||||||
visibleButtonTypes.removeOne(CaptureTool::TYPE_ACCEPT);
|
visibleButtonTypes.removeOne(CaptureTool::TYPE_ACCEPT);
|
||||||
} else {
|
} 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.color = m_config.drawColor();
|
||||||
m_context.widgetOffset = mapToGlobal(QPoint(0, 0));
|
m_context.widgetOffset = mapToGlobal(QPoint(0, 0));
|
||||||
@@ -900,15 +903,7 @@ void CaptureWidget::initContext(bool fullscreen, uint requestId)
|
|||||||
m_context.fullscreen = fullscreen;
|
m_context.fullscreen = fullscreen;
|
||||||
|
|
||||||
// initialize m_context.request
|
// initialize m_context.request
|
||||||
if (requestId != 0) {
|
m_context.request = req;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CaptureWidget::initPanel()
|
void CaptureWidget::initPanel()
|
||||||
@@ -1040,7 +1035,7 @@ void CaptureWidget::initSelection()
|
|||||||
{
|
{
|
||||||
// Be mindful of the order of statements, so that slots are called properly
|
// Be mindful of the order of statements, so that slots are called properly
|
||||||
m_selection = new SelectionWidget(m_uiColor, this);
|
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]() {
|
connect(m_selection, &SelectionWidget::geometryChanged, this, [this]() {
|
||||||
QRect constrainedToCaptureArea =
|
QRect constrainedToCaptureArea =
|
||||||
m_selection->geometry().intersected(rect());
|
m_selection->geometry().intersected(rect());
|
||||||
@@ -1052,16 +1047,10 @@ void CaptureWidget::initSelection()
|
|||||||
});
|
});
|
||||||
connect(m_selection, &SelectionWidget::geometrySettled, this, [this]() {
|
connect(m_selection, &SelectionWidget::geometrySettled, this, [this]() {
|
||||||
if (m_selection->isVisibleTo(this)) {
|
if (m_selection->isVisibleTo(this)) {
|
||||||
auto req = m_context.request();
|
auto& req = m_context.request;
|
||||||
if (req->tasks() & CaptureRequest::ACCEPT_ON_SELECT) {
|
if (req.tasks() & CaptureRequest::ACCEPT_ON_SELECT) {
|
||||||
req->removeTask(CaptureRequest::ACCEPT_ON_SELECT);
|
req.removeTask(CaptureRequest::ACCEPT_ON_SELECT);
|
||||||
m_captureDone = true;
|
m_captureDone = true;
|
||||||
if (req->tasks() & CaptureRequest::PIN) {
|
|
||||||
QRect geometry = m_context.selection;
|
|
||||||
geometry.setTopLeft(geometry.topLeft() +
|
|
||||||
m_context.widgetOffset);
|
|
||||||
req->addPinTask(geometry);
|
|
||||||
}
|
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
m_buttonHandler->updatePosition(m_selection->geometry());
|
m_buttonHandler->updatePosition(m_selection->geometry());
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ class CaptureWidget : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CaptureWidget(uint id = 0,
|
explicit CaptureWidget(const CaptureRequest& req,
|
||||||
const QString& savePath = QString(),
|
|
||||||
bool fullScreen = true,
|
bool fullScreen = true,
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
~CaptureWidget();
|
~CaptureWidget();
|
||||||
@@ -57,8 +56,6 @@ public slots:
|
|||||||
void deleteToolWidgetOrClose();
|
void deleteToolWidgetOrClose();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void captureTaken(uint id, const QPixmap& capture, const QRect& selection);
|
|
||||||
void captureFailed(uint id);
|
|
||||||
void colorChanged(const QColor& c);
|
void colorChanged(const QColor& c);
|
||||||
void toolSizeChanged(int size);
|
void toolSizeChanged(int size);
|
||||||
|
|
||||||
@@ -105,7 +102,7 @@ private:
|
|||||||
void showColorPicker(const QPoint& pos);
|
void showColorPicker(const QPoint& pos);
|
||||||
bool startDrawObjectTool(const QPoint& pos);
|
bool startDrawObjectTool(const QPoint& pos);
|
||||||
QPointer<CaptureTool> activeToolObject();
|
QPointer<CaptureTool> activeToolObject();
|
||||||
void initContext(bool fullscreen, uint requestId);
|
void initContext(bool fullscreen, const CaptureRequest& req);
|
||||||
void initPanel();
|
void initPanel();
|
||||||
void initSelection();
|
void initSelection();
|
||||||
void initShortcuts();
|
void initShortcuts();
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
CaptureLauncher::CaptureLauncher(QDialog* parent)
|
CaptureLauncher::CaptureLauncher(QDialog* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, m_id(0)
|
|
||||||
{
|
{
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
setWindowIcon(QIcon(GlobalValues::iconPath()));
|
setWindowIcon(QIcon(GlobalValues::iconPath()));
|
||||||
@@ -108,7 +107,6 @@ void CaptureLauncher::startCapture()
|
|||||||
auto mode = static_cast<CaptureRequest::CaptureMode>(
|
auto mode = static_cast<CaptureRequest::CaptureMode>(
|
||||||
m_captureType->currentData().toInt());
|
m_captureType->currentData().toInt());
|
||||||
CaptureRequest req(mode, 600 + m_delaySpinBox->value() * 1000);
|
CaptureRequest req(mode, 600 + m_delaySpinBox->value() * 1000);
|
||||||
m_id = req.id();
|
|
||||||
connectCaptureSlots();
|
connectCaptureSlots();
|
||||||
Controller::getInstance()->requestCapture(req);
|
Controller::getInstance()->requestCapture(req);
|
||||||
}
|
}
|
||||||
@@ -166,16 +164,13 @@ void CaptureLauncher::disconnectCaptureSlots()
|
|||||||
&CaptureLauncher::captureFailed);
|
&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()
|
// MacOS specific, more details in the function disconnectCaptureSlots()
|
||||||
disconnectCaptureSlots();
|
disconnectCaptureSlots();
|
||||||
|
|
||||||
if (id == m_id) {
|
m_imageLabel->setScreenshot(p);
|
||||||
m_id = 0;
|
show();
|
||||||
m_imageLabel->setScreenshot(p);
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto mode = static_cast<CaptureRequest::CaptureMode>(
|
auto mode = static_cast<CaptureRequest::CaptureMode>(
|
||||||
m_captureType->currentData().toInt());
|
m_captureType->currentData().toInt());
|
||||||
@@ -186,14 +181,10 @@ void CaptureLauncher::captureTaken(uint id, QPixmap p, const QRect& selection)
|
|||||||
m_launchButton->setEnabled(true);
|
m_launchButton->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CaptureLauncher::captureFailed(uint id)
|
void CaptureLauncher::captureFailed()
|
||||||
{
|
{
|
||||||
// MacOS specific, more details in the function disconnectCaptureSlots()
|
// MacOS specific, more details in the function disconnectCaptureSlots()
|
||||||
disconnectCaptureSlots();
|
disconnectCaptureSlots();
|
||||||
|
show();
|
||||||
if (id == m_id) {
|
|
||||||
m_id = 0;
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
m_launchButton->setEnabled(true);
|
m_launchButton->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ private:
|
|||||||
private slots:
|
private slots:
|
||||||
void startCapture();
|
void startCapture();
|
||||||
void startDrag();
|
void startDrag();
|
||||||
void captureTaken(uint id, QPixmap p, const QRect& selection);
|
void captureTaken(QPixmap p, const QRect& selection);
|
||||||
void captureFailed(uint id);
|
void captureFailed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSpinBox* m_delaySpinBox;
|
QSpinBox* m_delaySpinBox;
|
||||||
@@ -36,5 +36,4 @@ private:
|
|||||||
QPushButton* m_launchButton;
|
QPushButton* m_launchButton;
|
||||||
QLabel* m_CaptureModeLabel;
|
QLabel* m_CaptureModeLabel;
|
||||||
ImageLabel* m_imageLabel;
|
ImageLabel* m_imageLabel;
|
||||||
uint m_id;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#include "historywidget.h"
|
#include "historywidget.h"
|
||||||
|
#include "src/core/flameshotdaemon.h"
|
||||||
#include "src/tools/imgupload/imguploadermanager.h"
|
#include "src/tools/imgupload/imguploadermanager.h"
|
||||||
#include "src/utils/confighandler.h"
|
#include "src/utils/confighandler.h"
|
||||||
#include "src/utils/globalvalues.h"
|
#include "src/utils/globalvalues.h"
|
||||||
#include "src/utils/history.h"
|
#include "src/utils/history.h"
|
||||||
#include "src/widgets/notificationwidget.h"
|
#include "src/widgets/notificationwidget.h"
|
||||||
#include <QApplication>
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
@@ -143,7 +142,7 @@ void HistoryWidget::addLine(const QString& path, const QString& fileName)
|
|||||||
buttonCopyUrl->setText(tr("Copy URL"));
|
buttonCopyUrl->setText(tr("Copy URL"));
|
||||||
buttonCopyUrl->setMinimumHeight(HISTORYPIXMAP_MAX_PREVIEW_HEIGHT);
|
buttonCopyUrl->setMinimumHeight(HISTORYPIXMAP_MAX_PREVIEW_HEIGHT);
|
||||||
connect(buttonCopyUrl, &QPushButton::clicked, this, [=]() {
|
connect(buttonCopyUrl, &QPushButton::clicked, this, [=]() {
|
||||||
QApplication::clipboard()->setText(url);
|
FlameshotDaemon::copyToClipboard(url);
|
||||||
m_notification->showMessage(tr("URL copied to clipboard."));
|
m_notification->showMessage(tr("URL copied to clipboard."));
|
||||||
this->close();
|
this->close();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
#define HISTORYWIDGET_H
|
#define HISTORYWIDGET_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
|
class QString;
|
||||||
class QLayout;
|
class QLayout;
|
||||||
class QVBoxLayout;
|
class QVBoxLayout;
|
||||||
class NotificationWidget;
|
class NotificationWidget;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||||
|
|
||||||
#include "infowindow.h"
|
#include "infowindow.h"
|
||||||
|
#include "src/core/flameshotdaemon.h"
|
||||||
#include "src/core/qguiappcurrentscreen.h"
|
#include "src/core/qguiappcurrentscreen.h"
|
||||||
#include "src/utils/globalvalues.h"
|
#include "src/utils/globalvalues.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@@ -88,9 +89,8 @@ void InfoWindow::initLabels()
|
|||||||
|
|
||||||
void InfoWindow::copyInfo()
|
void InfoWindow::copyInfo()
|
||||||
{
|
{
|
||||||
QClipboard* clipboard = QApplication::clipboard();
|
FlameshotDaemon::copyToClipboard(GlobalValues::versionInfo() + "\n" +
|
||||||
clipboard->setText(GlobalValues::versionInfo() + "\n" +
|
generateKernelString());
|
||||||
generateKernelString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoWindow::keyPressEvent(QKeyEvent* e)
|
void InfoWindow::keyPressEvent(QKeyEvent* e)
|
||||||
|
|||||||
@@ -41,6 +41,32 @@ cmd() {
|
|||||||
sleep 1
|
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() {
|
wait_for_key() {
|
||||||
echo "Press Enter to continue..." >&2 && read ____
|
echo "Press Enter to continue..." >&2 && read ____
|
||||||
}
|
}
|
||||||
@@ -54,7 +80,7 @@ for subcommand in full screen
|
|||||||
do
|
do
|
||||||
cmd flameshot "$subcommand" --path /tmp/
|
cmd flameshot "$subcommand" --path /tmp/
|
||||||
cmd flameshot "$subcommand" --clipboard
|
cmd flameshot "$subcommand" --clipboard
|
||||||
cmd command "$FLAMESHOT" "$subcommand" --raw | display
|
cmd command "$FLAMESHOT" "$subcommand" --raw | display_img
|
||||||
[ "$subcommand" = "full" ] && sleep 1
|
[ "$subcommand" = "full" ] && sleep 1
|
||||||
echo
|
echo
|
||||||
done
|
done
|
||||||
@@ -70,30 +96,30 @@ sleep 1
|
|||||||
# ┗━━━━━━━━━━━━━━━┛
|
# ┗━━━━━━━━━━━━━━━┛
|
||||||
|
|
||||||
wait_for_key
|
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/
|
cmd flameshot gui --path /tmp/
|
||||||
wait_for_key
|
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
|
cmd flameshot gui --clipboard
|
||||||
wait_for_key
|
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
|
cmd command "$FLAMESHOT" gui --print-geometry
|
||||||
wait_for_key
|
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
|
cmd flameshot gui --pin
|
||||||
wait_for_key
|
wait_for_key
|
||||||
notify-send "GUI Test 5: Print raw" "Make a selection, then accept"
|
notify "GUI Test 5: Print raw" "Make a selection, then accept"
|
||||||
cmd command "$FLAMESHOT" gui --raw | display
|
cmd command "$FLAMESHOT" gui --raw | display_img
|
||||||
wait_for_key
|
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
|
cmd flameshot gui --clipboard --accept-on-select
|
||||||
wait_for_key
|
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
|
cmd flameshot gui --accept-on-select
|
||||||
|
|
||||||
# All options except for --print-geometry (incompatible with --raw)
|
# All options except for --print-geometry (incompatible with --raw)
|
||||||
wait_for_key
|
wait_for_key
|
||||||
notify-send "GUI Test 8: All actions except print-geometry" "Just make a selection"
|
notify "GUI Test 8: All actions except print-geometry" "Just make a selection"
|
||||||
cmd command "$FLAMESHOT" gui -p /tmp/ -c -r --pin | display
|
cmd command "$FLAMESHOT" gui -p /tmp/ -c -r --pin | display_img
|
||||||
|
|
||||||
echo '>> All tests done.'
|
echo '>> All tests done.'
|
||||||
|
|||||||
Reference in New Issue
Block a user