Expand role of CaptureRequest and add Accept tool (#1955)

This commit is contained in:
Haris Gušić
2021-10-12 22:49:41 +02:00
committed by GitHub
71 changed files with 453 additions and 342 deletions

View File

@@ -2,37 +2,14 @@
<node>
<interface name="org.flameshot.Flameshot">
<!--
graphicCapture:
@path: the path where the screenshot will be saved. When the argument is empty the program will ask for a path graphically.
@toClipboard: Whether to copy the screenshot to clipboard or not.
@delay: delay time in milliseconds.
@id: identificator of the call.
Open the user interface used to capture the screen. Sends a captureTaken signal with the raw image after closing the GUI
due to a capture taken. It could send a captureFailed signal if the screenshot can't be retrieved.
-->
<method name="graphicCapture">
<arg name="path" type="s" direction="in"/>
<arg name="toClipboard" type="b" direction="in"/>
<arg name="delay" type="i" direction="in"/>
<arg name="id" type="u" direction="in"/>
</method>
<!--
fullScreen:
@path: the path where the screenshot will be saved. When the argument is empty the program will ask for a path graphically.
@toClipboard: Whether to copy the screenshot to clipboard or not.
@delay: delay time in milliseconds, both return the @id defined in the call of this method.
@id: identificator of the call.
requestCapture:
@requestData: Serialized CaptureRequest object.
Takes a screenshot of the whole screen and sends a captureTaken signal with the raw image or a captureFailed signal.
Start a capture using a CaptureRequest.
-->
<method name="fullScreen">
<arg name="path" type="s" direction="in"/>
<arg name="toClipboard" type="b" direction="in"/>
<arg name="delay" type="i" direction="in"/>
<arg name="id" type="u" direction="in"/>
<method name="requestCapture">
<arg name="requestData" type="ay" direction="in"/>
</method>
<!--
@@ -44,24 +21,6 @@
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<!--
captureScreen:
@number: number of the screen to be captured.
@path: the path where the screenshot will be saved. When the argument is empty the program will ask for a path graphically.
@toClipboard: Whether to copy the screenshot to clipboard or not.
@delay: delay time in milliseconds, both return the @id defined in the call of this method.
@id: identificator of the call.
Takes a screenshot of the whole screen and sends a captureTaken signal with the raw image or a captureFailed signal.
-->
<method name="captureScreen">
<arg name="number" type="i" direction="in"/>
<arg name="path" type="s" direction="in"/>
<arg name="toClipboard" type="b" direction="in"/>
<arg name="delay" type="i" direction="in"/>
<arg name="id" type="u" direction="in"/>
</method>
<!--
openConfig:

View File

@@ -5,6 +5,7 @@
<file>img/app/org.flameshot.Flameshot.png</file>
<file>img/app/flameshot.png</file>
<file>img/app/keyboard.svg</file>
<file>img/material/black/accept.svg</file>
<file>img/material/black/arrow-bottom-left.svg</file>
<file>img/material/black/centeralign.svg</file>
<file>img/material/black/circle-outline.svg</file>
@@ -46,6 +47,7 @@
<file>img/material/black/minus.svg</file>
<file>img/material/black/plus.svg</file>
<file>img/material/black/shortcut.svg</file>
<file>img/material/white/accept.svg</file>
<file>img/material/white/arrow-bottom-left.svg</file>
<file>img/material/white/centeralign.svg</file>
<file>img/material/white/circle-outline.svg</file>

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>

After

Width:  |  Height:  |  Size: 209 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>

After

Width:  |  Height:  |  Size: 209 B

View File

@@ -5,15 +5,14 @@
#include "src/utils/screenshotsaver.h"
#include <QDateTime>
#include <QVector>
#include <stdexcept>
CaptureRequest::CaptureRequest(CaptureRequest::CaptureMode mode,
const uint delay,
const QString& path,
const QVariant& data,
CaptureRequest::ExportTask tasks)
: m_mode(mode)
, m_delay(delay)
, m_path(path)
, m_tasks(tasks)
, m_data(data)
, m_forcedID(false)
@@ -42,6 +41,36 @@ uint CaptureRequest::id() const
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;
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;
// Convert integers to enums
request.m_tasks = static_cast<ExportTask>(tasks);
request.m_mode = static_cast<CaptureMode>(mode);
return request;
}
CaptureRequest::CaptureMode CaptureRequest::captureMode() const
{
return m_mode;
@@ -62,14 +91,28 @@ QVariant CaptureRequest::data() const
return m_data;
}
CaptureRequest::ExportTask CaptureRequest::tasks() const
{
return m_tasks;
}
void CaptureRequest::addTask(CaptureRequest::ExportTask task)
{
if (task == SAVE_TASK) {
throw std::logic_error("SAVE_TASK must be added using addSaveTask");
}
m_tasks |= task;
}
void CaptureRequest::addSaveTask(const QString& path)
{
m_tasks |= SAVE_TASK;
m_path = path;
}
void CaptureRequest::exportCapture(const QPixmap& p)
{
if ((m_tasks & ExportTask::FILESYSTEM_SAVE_TASK) != ExportTask::NO_TASK) {
if ((m_tasks & ExportTask::SAVE_TASK) != ExportTask::NO_TASK) {
if (m_path.isEmpty()) {
ScreenshotSaver(m_id).saveToFilesystemGUI(p);
} else {
@@ -77,7 +120,7 @@ void CaptureRequest::exportCapture(const QPixmap& p)
}
}
if ((m_tasks & ExportTask::CLIPBOARD_SAVE_TASK) != ExportTask::NO_TASK) {
if ((m_tasks & ExportTask::COPY_TASK) != ExportTask::NO_TASK) {
ScreenshotSaver().saveToClipboard(p);
}
}

View File

@@ -20,25 +20,30 @@ public:
enum ExportTask
{
NO_TASK = 0,
CLIPBOARD_SAVE_TASK = 1,
FILESYSTEM_SAVE_TASK = 2,
COPY_TASK = 1,
SAVE_TASK = 2,
PRINT_RAW_TASK = 4,
PRINT_GEOMETRY_TASK = 8,
};
CaptureRequest(CaptureMode mode,
const uint delay = 0,
const QString& path = QLatin1String(""),
const QVariant& data = QVariant(),
ExportTask tasks = NO_TASK);
void setStaticID(uint id);
uint id() const;
QByteArray serialize() const;
static CaptureRequest deserialize(const QByteArray& data);
uint delay() const;
QString path() const;
QVariant data() const;
CaptureMode captureMode() const;
ExportTask tasks() const;
void addTask(ExportTask task);
void addSaveTask(const QString& path = QString());
void exportCapture(const QPixmap& p);
private:
@@ -50,6 +55,8 @@ private:
bool m_forcedID;
uint m_id;
CaptureRequest() {}
};
using eTask = CaptureRequest::ExportTask;

View File

@@ -28,30 +28,10 @@ FlameshotDBusAdapter::FlameshotDBusAdapter(QObject* parent)
FlameshotDBusAdapter::~FlameshotDBusAdapter() {}
void FlameshotDBusAdapter::graphicCapture(QString path,
bool toClipboard,
int delay,
uint id)
void FlameshotDBusAdapter::requestCapture(const QByteArray& requestData)
{
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
}
req.setStaticID(id);
Controller::getInstance()->requestCapture(req);
}
void FlameshotDBusAdapter::fullScreen(QString path,
bool toClipboard,
int delay,
uint id)
{
CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, path);
if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
}
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
req.setStaticID(id);
CaptureRequest req = CaptureRequest::deserialize(requestData);
req.setStaticID(req.id());
Controller::getInstance()->requestCapture(req);
}
@@ -60,21 +40,6 @@ void FlameshotDBusAdapter::openLauncher()
Controller::getInstance()->openLauncherWindow();
}
void FlameshotDBusAdapter::captureScreen(int number,
QString path,
bool toClipboard,
int delay,
uint id)
{
CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, path, number);
if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
}
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
req.setStaticID(id);
Controller::getInstance()->requestCapture(req);
}
void FlameshotDBusAdapter::openConfig()
{
Controller::getInstance()->openConfigWindow();

View File

@@ -21,19 +21,7 @@ signals:
void captureSaved(uint id, QString savePath);
public slots:
Q_NOREPLY void graphicCapture(QString path,
bool toClipboard,
int delay,
uint id);
Q_NOREPLY void fullScreen(QString path,
bool toClipboard,
int delay,
uint id);
Q_NOREPLY void captureScreen(int number,
QString path,
bool toClipboard,
int delay,
uint id);
Q_NOREPLY void requestCapture(const QByteArray& requestData);
Q_NOREPLY void openLauncher();
Q_NOREPLY void openConfig();
Q_NOREPLY void trayIconEnabled(bool enabled);

View File

@@ -307,7 +307,16 @@ int main(int argc, char* argv[])
DBusUtils dbusUtils;
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, pathValue);
if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
req.addTask(CaptureRequest::COPY_TASK);
}
if (isRaw) {
req.addTask(CaptureRequest::PRINT_RAW_TASK);
}
if (!pathValue.isEmpty()) {
req.addSaveTask(pathValue);
}
if (isSelection) {
req.addTask(CaptureRequest::PRINT_GEOMETRY_TASK);
}
uint id = req.id();
@@ -316,8 +325,8 @@ int main(int argc, char* argv[])
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("graphicCapture"));
m << pathValue << toClipboard << delay << id;
QStringLiteral("requestCapture"));
m << req.serialize();
QDBusConnection sessionBus = QDBusConnection::sessionBus();
dbusUtils.checkDBusConnection(sessionBus);
sessionBus.call(m);
@@ -352,12 +361,15 @@ int main(int argc, char* argv[])
goto finish;
}
CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay, pathValue);
CaptureRequest req(CaptureRequest::FULLSCREEN_MODE, delay);
if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
req.addTask(CaptureRequest::COPY_TASK);
}
if (isRaw) {
req.addTask(CaptureRequest::PRINT_RAW_TASK);
}
if (!pathValue.isEmpty()) {
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
req.addSaveTask(pathValue);
}
uint id = req.id();
DBusUtils dbusUtils;
@@ -367,8 +379,8 @@ int main(int argc, char* argv[])
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("fullScreen"));
m << pathValue << toClipboard << delay << id;
QStringLiteral("requestCapture"));
m << req.serialize();
QDBusConnection sessionBus = QDBusConnection::sessionBus();
dbusUtils.checkDBusConnection(sessionBus);
sessionBus.call(m);
@@ -410,13 +422,15 @@ int main(int argc, char* argv[])
goto finish;
}
CaptureRequest req(
CaptureRequest::SCREEN_MODE, delay, pathValue, number);
CaptureRequest req(CaptureRequest::SCREEN_MODE, delay, number);
if (toClipboard) {
req.addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
req.addTask(CaptureRequest::COPY_TASK);
}
if (isRaw) {
req.addTask(CaptureRequest::PRINT_RAW_TASK);
}
if (!pathValue.isEmpty()) {
req.addTask(CaptureRequest::FILESYSTEM_SAVE_TASK);
req.addSaveTask(pathValue);
}
uint id = req.id();
DBusUtils dbusUtils;
@@ -426,8 +440,8 @@ int main(int argc, char* argv[])
QStringLiteral("org.flameshot.Flameshot"),
QStringLiteral("/"),
QLatin1String(""),
QStringLiteral("captureScreen"));
m << number << pathValue << toClipboard << delay << id;
QStringLiteral("requestCapture"));
m << req.serialize();
QDBusConnection sessionBus = QDBusConnection::sessionBus();
dbusUtils.checkDBusConnection(sessionBus);
sessionBus.call(m);

View File

@@ -37,6 +37,7 @@ target_sources(
target_sources(flameshot PRIVATE rectangle/rectangletool.h rectangle/rectangletool.cpp)
target_sources(flameshot PRIVATE redo/redotool.h redo/redotool.cpp)
target_sources(flameshot PRIVATE save/savetool.h save/savetool.cpp)
target_sources(flameshot PRIVATE accept/accepttool.h accept/accepttool.cpp)
target_sources(flameshot PRIVATE invert/inverttool.h invert/inverttool.cpp)
target_sources(flameshot PRIVATE selection/selectiontool.h selection/selectiontool.cpp)
target_sources(flameshot PRIVATE sizeindicator/sizeindicatortool.h sizeindicator/sizeindicatortool.cpp)

View File

@@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "accepttool.h"
#include "src/utils/screenshotsaver.h"
#include <QApplication>
#include <QPainter>
#include <QStyle>
#if defined(Q_OS_MACOS)
#include "src/widgets/capture/capturewidget.h"
#include <QWidget>
#endif
AcceptTool::AcceptTool(QObject* parent)
: AbstractActionTool(parent)
{}
bool AcceptTool::closeOnButtonPressed() const
{
return true;
}
QIcon AcceptTool::icon(const QColor& background, bool inEditor) const
{
Q_UNUSED(inEditor)
return QIcon(iconPath(background) + "accept.svg");
}
QString AcceptTool::name() const
{
return tr("Accept");
}
CaptureTool::Type AcceptTool::type() const
{
return CaptureTool::TYPE_ACCEPT;
}
QString AcceptTool::description() const
{
return tr("Accept the capture");
}
CaptureTool* AcceptTool::copy(QObject* parent)
{
return new AcceptTool(parent);
}
void AcceptTool::pressed(CaptureContext&)
{
emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_CLOSE_GUI);
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#pragma once
#include "abstractactiontool.h"
class AcceptTool : public AbstractActionTool
{
Q_OBJECT
public:
explicit AcceptTool(QObject* parent = nullptr);
bool closeOnButtonPressed() const override;
QIcon icon(const QColor& background, bool inEditor) const override;
QString name() const override;
QString description() const override;
CaptureTool* copy(QObject* parent = nullptr) override;
protected:
CaptureTool::Type type() const override;
public slots:
void pressed(CaptureContext& context) override;
};

View File

@@ -153,7 +153,7 @@ void ArrowTool::process(QPainter& painter, const QPixmap& pixmap)
painter.fillPath(m_arrowPath, QBrush(color()));
}
void ArrowTool::pressed(const CaptureContext& context)
void ArrowTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -26,7 +26,7 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
private:
QPainterPath m_arrowPath;

View File

@@ -2,6 +2,8 @@
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "capturecontext.h"
#include "capturerequest.h"
#include "controller.h"
QPixmap CaptureContext::selectedScreenshotArea() const
{
@@ -11,3 +13,13 @@ QPixmap CaptureContext::selectedScreenshotArea() const
return screenshot.copy(selection);
}
}
CaptureRequest* CaptureContext::request()
{
return &*Controller::getInstance()->requests().find(requestId);
}
CaptureRequest* CaptureContext::request() const
{
return &*Controller::getInstance()->requests().find(requestId);
}

View File

@@ -3,6 +3,7 @@
#pragma once
#include "capturerequest.h"
#include <QPainter>
#include <QPixmap>
#include <QPoint>
@@ -28,6 +29,9 @@ struct CaptureContext
int thickness;
// Mode of the capture widget
bool fullscreen;
uint requestId;
QPixmap selectedScreenshotArea() const;
CaptureRequest* request();
CaptureRequest* request() const;
};

View File

@@ -47,6 +47,7 @@ public:
TYPE_SIZEINCREASE = 20,
TYPE_SIZEDECREASE = 21,
TYPE_INVERT = 22,
TYPE_ACCEPT = 23,
};
Q_ENUM(Type);
@@ -63,8 +64,6 @@ public:
REQ_REDO_MODIFICATION,
// Open the color picker under the mouse.
REQ_SHOW_COLOR_PICKER,
// Notify to redraw screenshot with tools without object selection.
REQ_CLEAR_SELECTION,
// Notify is the screenshot has been saved.
REQ_CAPTURE_DONE_OK,
// Instance this->widget()'s widget inside the editor under the mouse.
@@ -191,7 +190,7 @@ public slots:
// Called when the tool is activated.
virtual void drawStart(const CaptureContext& context) = 0;
// Called right after pressign the button which activates the tool.
virtual void pressed(const CaptureContext& context) = 0;
virtual void pressed(CaptureContext& context) = 0;
// Called when the color is changed in the editor.
virtual void onColorChanged(const QColor& c) = 0;
// Called when the thickness of the tool is updated in the editor.

View File

@@ -44,7 +44,7 @@ void CircleTool::process(QPainter& painter, const QPixmap& pixmap)
painter.drawEllipse(QRect(points().first, points().second));
}
void CircleTool::pressed(const CaptureContext& context)
void CircleTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -22,5 +22,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -166,7 +166,7 @@ void CircleCountTool::drawStart(const CaptureContext& context)
m_valid = true;
}
void CircleCountTool::pressed(const CaptureContext& context)
void CircleCountTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -31,7 +31,7 @@ protected:
public slots:
void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
private:
QString m_tempString;

View File

@@ -31,7 +31,7 @@ CaptureTool::Type CopyTool::type() const
QString CopyTool::description() const
{
return tr("Copy the selection into the clipboard");
return tr("Copy selection to clipboard");
}
CaptureTool* CopyTool::copy(QObject* parent)
@@ -39,9 +39,9 @@ CaptureTool* CopyTool::copy(QObject* parent)
return new CopyTool(parent);
}
void CopyTool::pressed(const CaptureContext& context)
void CopyTool::pressed(CaptureContext& context)
{
emit requestAction(REQ_CLEAR_SELECTION);
context.request()->addTask(CaptureRequest::COPY_TASK);
emit requestAction(REQ_CAPTURE_DONE_OK);
ScreenshotSaver().saveToClipboard(context.selectedScreenshotArea());
emit requestAction(REQ_CLOSE_GUI);
}

View File

@@ -23,5 +23,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -38,7 +38,7 @@ CaptureTool* ExitTool::copy(QObject* parent)
return new ExitTool(parent);
}
void ExitTool::pressed(const CaptureContext& context)
void ExitTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
emit requestAction(REQ_CLOSE_GUI);

View File

@@ -24,5 +24,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -44,10 +44,10 @@ CaptureTool* ImgurUploaderTool::copy(QObject* parent)
return new ImgurUploaderTool(parent);
}
void ImgurUploaderTool::pressed(const CaptureContext& context)
void ImgurUploaderTool::pressed(CaptureContext& context)
{
emit requestAction(REQ_CLEAR_SELECTION);
capture = context.selectedScreenshotArea();
emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_ADD_EXTERNAL_WIDGETS);
emit requestAction(REQ_CLOSE_GUI);
}

View File

@@ -25,7 +25,7 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
private:
QPixmap capture;

View File

@@ -72,7 +72,7 @@ void InvertTool::paintMousePreview(QPainter& painter,
Q_UNUSED(painter)
}
void InvertTool::pressed(const CaptureContext& context)
void InvertTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -26,5 +26,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -43,9 +43,10 @@ CaptureTool* AppLauncher::copy(QObject* parent)
return new AppLauncher(parent);
}
void AppLauncher::pressed(const CaptureContext& context)
void AppLauncher::pressed(CaptureContext& context)
{
capture = context.selectedScreenshotArea();
emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_ADD_EXTERNAL_WIDGETS);
emit requestAction(REQ_CLOSE_GUI);
}

View File

@@ -25,7 +25,7 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
private:
QPixmap capture;

View File

@@ -46,7 +46,7 @@ void LineTool::process(QPainter& painter, const QPixmap& pixmap)
painter.drawLine(points().first, points().second);
}
void LineTool::pressed(const CaptureContext& context)
void LineTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -22,5 +22,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -84,7 +84,7 @@ void MarkerTool::drawStart(const CaptureContext& context)
onThicknessChanged(context.thickness + PADDING_VALUE);
}
void MarkerTool::pressed(const CaptureContext& context)
void MarkerTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -26,5 +26,5 @@ protected:
public slots:
void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -38,7 +38,7 @@ CaptureTool* MoveTool::copy(QObject* parent)
return new MoveTool(parent);
}
void MoveTool::pressed(const CaptureContext& context)
void MoveTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -22,5 +22,5 @@ public:
CaptureTool* copy(QObject* parent = nullptr) override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -58,7 +58,7 @@ void PencilTool::drawStart(const CaptureContext& context)
m_pathArea.setBottomRight(context.mousePos);
}
void PencilTool::pressed(const CaptureContext& context)
void PencilTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -26,5 +26,5 @@ protected:
public slots:
void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -70,12 +70,12 @@ CaptureTool* PinTool::copy(QObject* parent)
return new PinTool(parent);
}
void PinTool::pressed(const CaptureContext& context)
void PinTool::pressed(CaptureContext& context)
{
emit requestAction(REQ_CLEAR_SELECTION);
emit requestAction(REQ_CAPTURE_DONE_OK);
m_geometry = context.selection;
m_geometry.setTopLeft(m_geometry.topLeft() + context.widgetOffset);
m_pixmap = context.selectedScreenshotArea();
emit requestAction(REQ_ADD_EXTERNAL_WIDGETS);
emit requestAction(REQ_CLOSE_GUI);
}

View File

@@ -25,7 +25,7 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
private:
QRect m_geometry;

View File

@@ -96,7 +96,7 @@ void PixelateTool::paintMousePreview(QPainter& painter,
Q_UNUSED(painter)
}
void PixelateTool::pressed(const CaptureContext& context)
void PixelateTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -26,5 +26,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -73,7 +73,7 @@ void RectangleTool::drawStart(const CaptureContext& context)
onThicknessChanged(context.thickness);
}
void RectangleTool::pressed(const CaptureContext& context)
void RectangleTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -23,5 +23,5 @@ protected:
public slots:
void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -38,7 +38,7 @@ CaptureTool* RedoTool::copy(QObject* parent)
return new RedoTool(parent);
}
void RedoTool::pressed(const CaptureContext& context)
void RedoTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
emit requestAction(REQ_REDO_MODIFICATION);

View File

@@ -23,5 +23,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -4,11 +4,6 @@
#include "savetool.h"
#include "src/utils/screenshotsaver.h"
#include <QPainter>
#if defined(Q_OS_MACOS)
#include "src/widgets/capture/capturewidget.h"
#include <QApplication>
#include <QWidget>
#endif
SaveTool::SaveTool(QObject* parent)
: AbstractActionTool(parent)
@@ -36,7 +31,7 @@ CaptureTool::Type SaveTool::type() const
QString SaveTool::description() const
{
return tr("Save the capture");
return tr("Save screenshot to a file");
}
CaptureTool* SaveTool::copy(QObject* parent)
@@ -44,32 +39,9 @@ CaptureTool* SaveTool::copy(QObject* parent)
return new SaveTool(parent);
}
void SaveTool::pressed(const CaptureContext& context)
void SaveTool::pressed(CaptureContext& context)
{
#if defined(Q_OS_MACOS)
for (QWidget* widget : qApp->topLevelWidgets()) {
QString className(widget->metaObject()->className());
if (0 ==
className.compare(CaptureWidget::staticMetaObject.className())) {
widget->showNormal();
widget->hide();
break;
}
}
#endif
emit requestAction(REQ_CLEAR_SELECTION);
if (context.savePath.isEmpty()) {
emit requestAction(REQ_HIDE_GUI);
bool ok = ScreenshotSaver().saveToFilesystemGUI(
context.selectedScreenshotArea());
if (ok) {
emit requestAction(REQ_CAPTURE_DONE_OK);
}
} else {
bool ok = ScreenshotSaver().saveToFilesystem(
context.selectedScreenshotArea(), context.savePath);
if (ok) {
emit requestAction(REQ_CAPTURE_DONE_OK);
}
}
context.request()->addSaveTask();
emit requestAction(REQ_CAPTURE_DONE_OK);
emit requestAction(REQ_CLOSE_GUI);
}

View File

@@ -23,5 +23,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -50,7 +50,7 @@ void SelectionTool::process(QPainter& painter, const QPixmap& pixmap)
painter.drawRect(QRect(points().first, points().second));
}
void SelectionTool::pressed(const CaptureContext& context)
void SelectionTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -24,5 +24,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -52,7 +52,7 @@ CaptureTool* SizeDecreaseTool::copy(QObject* parent)
return new SizeDecreaseTool(parent);
}
void SizeDecreaseTool::pressed(const CaptureContext& context)
void SizeDecreaseTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
emit requestAction(REQ_DECREASE_TOOL_SIZE);

View File

@@ -37,5 +37,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -52,7 +52,7 @@ CaptureTool* SizeIncreaseTool::copy(QObject* parent)
return new SizeIncreaseTool(parent);
}
void SizeIncreaseTool::pressed(const CaptureContext& context)
void SizeIncreaseTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
emit requestAction(REQ_INCREASE_TOOL_SIZE);

View File

@@ -37,5 +37,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -38,7 +38,7 @@ CaptureTool* SizeIndicatorTool::copy(QObject* parent)
return new SizeIndicatorTool(parent);
}
void SizeIndicatorTool::pressed(const CaptureContext& context)
void SizeIndicatorTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -23,5 +23,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -252,7 +252,7 @@ void TextTool::drawStart(const CaptureContext& context)
emit requestAction(REQ_ADD_CHILD_WIDGET);
}
void TextTool::pressed(const CaptureContext& context)
void TextTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
}

View File

@@ -50,7 +50,7 @@ public slots:
void drawEnd(const QPoint& p) override;
void drawMove(const QPoint& p) override;
void drawStart(const CaptureContext& context) override;
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
void onColorChanged(const QColor& c) override;
void onThicknessChanged(int th) override;
virtual int thickness() const override { return m_size; };

View File

@@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
#include "toolfactory.h"
#include "accept/accepttool.h"
#include "arrow/arrowtool.h"
#include "circle/circletool.h"
#include "circlecount/circlecounttool.h"
@@ -63,6 +64,7 @@ CaptureTool* ToolFactory::CreateTool(CaptureTool::Type t, QObject* parent)
if_TYPE_return_TOOL(TYPE_SIZEINCREASE, SizeIncreaseTool);
if_TYPE_return_TOOL(TYPE_SIZEDECREASE, SizeDecreaseTool);
if_TYPE_return_TOOL(TYPE_INVERT, InvertTool);
if_TYPE_return_TOOL(TYPE_ACCEPT, AcceptTool);
default:
return nullptr;
}

View File

@@ -38,7 +38,7 @@ CaptureTool* UndoTool::copy(QObject* parent)
return new UndoTool(parent);
}
void UndoTool::pressed(const CaptureContext& context)
void UndoTool::pressed(CaptureContext& context)
{
Q_UNUSED(context)
emit requestAction(REQ_UNDO_MODIFICATION);

View File

@@ -23,5 +23,5 @@ protected:
CaptureTool::Type type() const override;
public slots:
void pressed(const CaptureContext& context) override;
void pressed(CaptureContext& context) override;
};

View File

@@ -126,6 +126,7 @@ static QMap<QString, QSharedPointer<KeySequence>> recognizedShortcuts = {
SHORTCUT("TYPE_UNDO" , "Ctrl+Z" ),
SHORTCUT("TYPE_COPY" , "Ctrl+C" ),
SHORTCUT("TYPE_SAVE" , "Ctrl+S" ),
SHORTCUT("TYPE_ACCEPT" , "Return" ),
SHORTCUT("TYPE_EXIT" , "Ctrl+Q" ),
SHORTCUT("TYPE_IMAGEUPLOADER" , "Ctrl+U" ),
#if !defined(Q_OS_MACOS)

View File

@@ -68,6 +68,7 @@ void CaptureToolButton::initButton()
} else if (!shortcut.isEmpty()) {
tooltip += QStringLiteral(" (%1)").arg(shortcut);
}
tooltip.replace("Return", "Enter");
setToolTip(tooltip);
m_emergeAnimation = new QPropertyAnimation(this, "size", this);
@@ -142,15 +143,16 @@ static std::map<CaptureTool::Type, int> buttonTypeOrder
{ CaptureTool::TYPE_MOVESELECTION, 12 }, { CaptureTool::TYPE_UNDO, 13 },
{ CaptureTool::TYPE_REDO, 14 }, { CaptureTool::TYPE_COPY, 15 },
{ CaptureTool::TYPE_SAVE, 16 }, { CaptureTool::TYPE_IMAGEUPLOADER, 17 },
{ CaptureTool::TYPE_ACCEPT, 18 },
#if !defined(Q_OS_MACOS)
{ CaptureTool::TYPE_OPEN_APP, 18 }, { CaptureTool::TYPE_EXIT, 19 },
{ CaptureTool::TYPE_PIN, 20 },
{ CaptureTool::TYPE_OPEN_APP, 19 }, { CaptureTool::TYPE_EXIT, 20 },
{ CaptureTool::TYPE_PIN, 21 },
#else
{ CaptureTool::TYPE_EXIT, 18 }, { CaptureTool::TYPE_PIN, 19 },
{ CaptureTool::TYPE_EXIT, 19 }, { CaptureTool::TYPE_PIN, 20 },
#endif
{ CaptureTool::TYPE_SIZEINCREASE, 21 },
{ CaptureTool::TYPE_SIZEDECREASE, 22 },
{ CaptureTool::TYPE_SIZEINCREASE, 22 },
{ CaptureTool::TYPE_SIZEDECREASE, 23 },
};
int CaptureToolButton::getPriorityByButton(CaptureTool::Type b)
@@ -186,4 +188,5 @@ QList<CaptureTool::Type> CaptureToolButton::iterableButtonTypes = {
CaptureTool::TYPE_CIRCLECOUNT,
CaptureTool::TYPE_SIZEINCREASE,
CaptureTool::TYPE_SIZEDECREASE,
CaptureTool::TYPE_ACCEPT,
};

View File

@@ -10,6 +10,7 @@
// <http://www.gnu.org/licenses/old-licenses/library.txt>
#include "capturewidget.h"
#include "copytool.h"
#include "src/core/controller.h"
#include "src/core/qguiappcurrentscreen.h"
#include "src/tools/toolfactory.h"
@@ -62,7 +63,6 @@ CaptureWidget::CaptureWidget(uint id,
, m_activeTool(nullptr)
, m_toolWidget(nullptr)
, m_colorPicker(nullptr)
, m_id(id)
, m_lastMouseWheel(0)
, m_updateNotificationWidget(nullptr)
, m_activeToolIsMoved(false)
@@ -90,7 +90,7 @@ CaptureWidget::CaptureWidget(uint id,
m_uiColor = m_config.uiColor();
m_contrastUiColor = m_config.contrastUiColor();
setMouseTracking(true);
initContext(savePath, fullScreen);
initContext(fullScreen, id);
initSelection();
initShortcuts(); // must be called after initSelection
#if (defined(Q_OS_WIN) || defined(Q_OS_MACOS))
@@ -219,12 +219,8 @@ CaptureWidget::CaptureWidget(uint id,
QGuiAppCurrentScreen().currentScreen()->geometry());
if (m_config.showHelp()) {
OverlayMessage::push(
tr("Select an area with the mouse, or press Esc to exit."
"\nPress Enter to capture the screen."
"\nPress Right Click to show the color picker."
"\nUse the Mouse Wheel to change the thickness of your tool."
"\nPress Space to open the side panel."));
initHelpMessage();
OverlayMessage::push(m_helpMessage);
}
updateCursor();
@@ -232,10 +228,21 @@ CaptureWidget::CaptureWidget(uint id,
CaptureWidget::~CaptureWidget()
{
#if defined(Q_OS_MACOS)
for (QWidget* widget : qApp->topLevelWidgets()) {
QString className(widget->metaObject()->className());
if (0 ==
className.compare(CaptureWidget::staticMetaObject.className())) {
widget->showNormal();
widget->hide();
break;
}
}
#endif
if (m_captureDone) {
emit captureTaken(m_id, this->pixmap(), m_context.selection);
emit captureTaken(m_context.requestId, pixmap(), m_context.selection);
} else {
emit captureFailed(m_id);
emit captureFailed(m_context.requestId);
}
}
@@ -243,11 +250,24 @@ void CaptureWidget::initButtons()
{
auto allButtonTypes = CaptureToolButton::getIterableButtonTypes();
auto visibleButtonTypes = m_config.buttons();
if (m_context.request()->tasks() == CaptureRequest::NO_TASK) {
allButtonTypes.removeOne(CaptureTool::TYPE_ACCEPT);
visibleButtonTypes.removeOne(CaptureTool::TYPE_ACCEPT);
} else {
// Remove irrelevant buttons from both lists
for (auto* buttonList : { &allButtonTypes, &visibleButtonTypes }) {
buttonList->removeOne(CaptureTool::TYPE_SAVE);
buttonList->removeOne(CaptureTool::TYPE_COPY);
buttonList->removeOne(CaptureTool::TYPE_IMAGEUPLOADER);
buttonList->removeOne(CaptureTool::TYPE_OPEN_APP);
buttonList->removeOne(CaptureTool::TYPE_PIN);
}
}
QVector<CaptureToolButton*> vectorButtons;
// Add all buttons but hide those that were disabled in the Interface config
// This will allow keyboard shortcuts for those buttons to work
for (const CaptureTool::Type& t : allButtonTypes) {
for (CaptureTool::Type t : allButtonTypes) {
CaptureToolButton* b = new CaptureToolButton(t, this);
if (t == CaptureTool::TYPE_SELECTIONINDICATOR) {
m_sizeIndButton = b;
@@ -259,9 +279,6 @@ void CaptureWidget::initButtons()
makeChild(b);
switch (t) {
case CaptureTool::TYPE_EXIT:
case CaptureTool::TYPE_SAVE:
case CaptureTool::TYPE_COPY:
case CaptureTool::TYPE_UNDO:
case CaptureTool::TYPE_IMAGEUPLOADER:
case CaptureTool::TYPE_REDO:
@@ -283,6 +300,8 @@ void CaptureWidget::initButtons()
break;
}
m_tools[t] = b->tool();
connect(b->tool(),
&CaptureTool::requestAction,
this,
@@ -299,6 +318,34 @@ void CaptureWidget::initButtons()
m_buttonHandler->setButtons(vectorButtons);
}
void CaptureWidget::initHelpMessage()
{
QList<QPair<QString, QString>> keyMap;
if (keyMap.isEmpty()) {
keyMap << QPair(tr("Mouse"), tr("Select screenshot area"));
using CT = CaptureTool;
for (auto toolType :
{ CT::TYPE_ACCEPT, CT::TYPE_SAVE, CT::TYPE_COPY }) {
if (!m_tools.contains(toolType)) {
continue;
}
auto* tool = m_tools[toolType];
QString shortcut = ConfigHandler().shortcut(
QVariant::fromValue(toolType).toString());
shortcut.replace("Return", "Enter");
if (!shortcut.isEmpty()) {
keyMap << QPair(shortcut, tool->description());
}
}
keyMap << QPair(tr("Mouse Wheel"), tr("Change tool size"));
keyMap << QPair(tr("Right Click"), tr("Show color picker"));
keyMap << QPair(ConfigHandler().shortcut("TYPE_TOGGLE_PANEL"),
tr("Open side panel"));
keyMap << QPair(tr("Esc"), tr("Exit"));
}
m_helpMessage = OverlayMessage::compileFromKeyMap(keyMap);
}
QPixmap CaptureWidget::pixmap()
{
return m_context.selectedScreenshotArea();
@@ -309,6 +356,7 @@ QPixmap CaptureWidget::pixmap()
bool CaptureWidget::commitCurrentTool()
{
if (m_activeTool) {
processPixmapWithTool(&m_context.screenshot, m_activeTool);
if (m_activeTool->isValid() && !m_activeTool->editMode() &&
m_toolWidget) {
pushToolToStack();
@@ -528,7 +576,6 @@ void CaptureWidget::mousePressEvent(QMouseEvent* e)
showColorPicker(m_mousePressedPos);
return;
} else if (e->button() == Qt::LeftButton) {
OverlayMessage::pop();
m_mouseIsClicked = true;
// Click using a tool excluding tool MOVE
@@ -571,7 +618,13 @@ void CaptureWidget::mouseDoubleClickEvent(QMouseEvent* event)
m_panel->setToolWidget(m_activeTool->configurationWidget());
}
} else if (m_selection->geometry().contains(event->pos())) {
copyScreenshot();
CopyTool copyTool;
connect(&copyTool,
&CopyTool::requestAction,
this,
&CaptureWidget::handleToolSignal);
copyTool.pressed(m_context);
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
}
@@ -803,14 +856,24 @@ void CaptureWidget::changeEvent(QEvent* e)
}
}
void CaptureWidget::initContext(const QString& savePath, bool fullscreen)
void CaptureWidget::initContext(bool fullscreen, uint requestId)
{
m_context.color = m_config.drawColor();
m_context.savePath = savePath;
m_context.widgetOffset = mapToGlobal(QPoint(0, 0));
m_context.mousePos = mapFromGlobal(QCursor::pos());
m_context.thickness = m_config.drawThickness();
m_context.fullscreen = fullscreen;
// initialize m_context.request
if (requestId != 0) {
m_context.requestId = requestId;
} else {
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE);
uint id = req.id();
req.setStaticID(id);
Controller::getInstance()->requests().insert(id, req);
m_context.requestId = id;
}
}
void CaptureWidget::initPanel()
@@ -950,6 +1013,7 @@ void CaptureWidget::initSelection()
updateSizeIndicator();
m_buttonHandler->hide();
updateCursor();
OverlayMessage::pop();
});
connect(m_selection, &SelectionWidget::geometrySettled, this, [this]() {
if (m_selection->isVisible()) {
@@ -958,6 +1022,11 @@ void CaptureWidget::initSelection()
m_buttonHandler->hide();
}
});
connect(m_selection, &SelectionWidget::visibilityChanged, this, [this]() {
if (!m_selection->isVisible()) {
OverlayMessage::push(m_helpMessage);
}
});
}
void CaptureWidget::setState(CaptureToolButton* b)
@@ -966,6 +1035,7 @@ void CaptureWidget::setState(CaptureToolButton* b)
return;
}
commitCurrentTool();
if (m_toolWidget && m_activeTool) {
if (m_activeTool->isValid()) {
pushToolToStack();
@@ -982,11 +1052,6 @@ void CaptureWidget::setState(CaptureToolButton* b)
m_activeTool = backup;
}
// Only close activated from button
if (b->tool()->closeOnButtonPressed()) {
close();
}
if (b->tool()->isSelectable()) {
if (m_activeButton != b) {
QWidget* confW = b->tool()->configurationWidget();
@@ -1038,12 +1103,6 @@ void CaptureWidget::handleToolSignal(CaptureTool::Request r)
case CaptureTool::REQ_SHOW_COLOR_PICKER:
// TODO
break;
case CaptureTool::REQ_CLEAR_SELECTION:
if (m_panel->activeLayerIndex() >= 0) {
m_panel->setActiveLayer(-1);
drawToolsData();
}
break;
case CaptureTool::REQ_CAPTURE_DONE_OK:
m_captureDone = true;
break;
@@ -1190,17 +1249,6 @@ void CaptureWidget::setDrawThickness(int t)
void CaptureWidget::initShortcuts()
{
new QShortcut(
QKeySequence(ConfigHandler().shortcut("TYPE_EXIT")), this, SLOT(close()));
new QShortcut(QKeySequence(ConfigHandler().shortcut("TYPE_SAVE")),
this,
SLOT(saveScreenshot()));
new QShortcut(QKeySequence(ConfigHandler().shortcut("TYPE_COPY")),
this,
SLOT(copyScreenshot()));
new QShortcut(
QKeySequence(ConfigHandler().shortcut("TYPE_UNDO")), this, SLOT(undo()));
@@ -1456,37 +1504,6 @@ void CaptureWidget::childLeave()
updateTool(activeButtonTool());
}
void CaptureWidget::copyScreenshot()
{
m_captureDone = true;
if (m_activeTool != nullptr) {
processPixmapWithTool(&m_context.screenshot, m_activeTool);
}
auto req = Controller::getInstance()->requests().find(m_id);
req->addTask(CaptureRequest::CLIPBOARD_SAVE_TASK);
close();
}
void CaptureWidget::saveScreenshot()
{
#if defined(Q_OS_MACOS)
showNormal();
#endif
m_captureDone = true;
if (m_activeTool != nullptr) {
processPixmapWithTool(&m_context.screenshot, m_activeTool);
}
hide();
if (m_context.savePath.isEmpty()) {
ScreenshotSaver(m_id).saveToFilesystemGUI(pixmap());
} else {
ScreenshotSaver(m_id).saveToFilesystem(pixmap(), m_context.savePath);
}
close();
}
void CaptureWidget::setCaptureToolObjects(
const CaptureToolObjects& captureToolObjects)
{

View File

@@ -62,9 +62,6 @@ signals:
void thicknessChanged(int thickness);
private slots:
// TODO replace with tools
void copyScreenshot();
void saveScreenshot();
void undo();
void redo();
void togglePanel();
@@ -105,11 +102,12 @@ private:
void showColorPicker(const QPoint& pos);
bool startDrawObjectTool(const QPoint& pos);
QPointer<CaptureTool> activeToolObject();
void initContext(const QString& savePath, bool fullscreen);
void initContext(bool fullscreen, uint requestId);
void initPanel();
void initSelection();
void initShortcuts();
void initButtons();
void initHelpMessage();
void updateSizeIndicator();
void updateCursor();
void updateSelectionState();
@@ -175,10 +173,11 @@ private:
NotifierBox* m_notifierBox;
HoverEventFilter* m_eventFilter;
SelectionWidget* m_selection;
QString m_helpMessage;
SelectionWidget::SideType m_mouseOverHandle;
uint m_id;
QMap<CaptureTool::Type, CaptureTool*> m_tools;
CaptureToolObjects m_captureToolObjects;
CaptureToolObjects m_captureToolObjectsBackup;

View File

@@ -1,17 +1,16 @@
#include "overlaymessage.h"
#include "colorutils.h"
#include "confighandler.h"
#include "qguiappcurrentscreen.h"
#include <QApplication>
#include <QDebug>
#include <QLabel>
#include <QPainter>
#include <QPen>
#include <QScreen>
#include <QWidget>
OverlayMessage::OverlayMessage(QWidget* parent, const QRect& targetArea)
: QWidget(parent)
: QLabel(parent)
, m_targetArea(targetArea)
{
// NOTE: do not call the static functions from the constructor
@@ -19,6 +18,20 @@ OverlayMessage::OverlayMessage(QWidget* parent, const QRect& targetArea)
m_messageStack.push(QString()); // Default message is empty
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_AlwaysStackOnTop);
setAlignment(Qt::AlignCenter);
setTextFormat(Qt::RichText);
m_fillColor = ConfigHandler().uiColor();
int opacity = ConfigHandler().contrastOpacity();
m_textColor =
(ColorUtils::colorIsDark(m_fillColor) ? Qt::white : Qt::black);
// map a background opacity range 0-255 to a fill opacity range 190-160
// we do this because an opaque background makes the box look opaque too
m_fillColor.setAlpha(160 + (180 - 220) / (255.0 - 0) * (opacity - 255));
setStyleSheet(
QStringLiteral("QLabel { color: %1; }").arg(m_textColor.name()));
setMargin(QApplication::fontMetrics().height() / 2);
QWidget::hide();
}
@@ -27,9 +40,14 @@ void OverlayMessage::init(QWidget* parent, const QRect& targetArea)
new OverlayMessage(parent, targetArea);
}
/**
* @brief Push a message to the message stack.
* @param msg Message text formatted as rich text
*/
void OverlayMessage::push(const QString& msg)
{
m_instance->m_messageStack.push(msg);
m_instance->setText(m_instance->m_messageStack.top());
setVisibility(true);
}
@@ -39,13 +57,8 @@ void OverlayMessage::pop()
m_instance->m_messageStack.pop();
}
if (m_instance->m_messageStack.size() == 1) {
// Only empty message left (don't show it)
m_instance->QWidget::hide();
} else {
// Still visible, resize for new message
m_instance->updateGeometry();
}
m_instance->setText(m_instance->m_messageStack.top());
setVisibility(m_instance->m_messageStack.size() > 1);
}
void OverlayMessage::setVisibility(bool visible)
@@ -59,52 +72,56 @@ OverlayMessage* OverlayMessage::instance()
return m_instance;
}
void OverlayMessage::paintEvent(QPaintEvent*)
void OverlayMessage::pushKeyMap(const QList<QPair<QString, QString>>& map)
{
push(compileFromKeyMap(map));
}
/**
* @brief Compile a message from a set of shortcuts and descriptions.
* @param map List of (shortcut, description) pairs
*/
QString OverlayMessage::compileFromKeyMap(
const QList<QPair<QString, QString>>& map)
{
QString str = QStringLiteral("<table>");
for (const auto& pair : map) {
str += QStringLiteral("<tr>"
"<td align=\"right\"><b>%1 </b></td>"
"<td align=\"left\">&nbsp;&nbsp;%2</td>"
"</tr>")
.arg(pair.first)
.arg(pair.second);
}
str += QStringLiteral("</table>");
return str;
}
void OverlayMessage::paintEvent(QPaintEvent* e)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QRectF bRect = boundingRect();
bRect.moveTo(0, 0);
QColor rectColor(ConfigHandler().uiColor());
rectColor.setAlpha(180);
QColor textColor(
(ColorUtils::colorIsDark(rectColor) ? Qt::white : Qt::black));
painter.setBrush(QBrush(rectColor, Qt::SolidPattern));
painter.setPen(QPen(textColor));
painter.setBrush(QBrush(m_fillColor, Qt::SolidPattern));
painter.setPen(QPen(m_textColor, 1.5));
float margin = painter.pen().widthF();
painter.drawRect(bRect - QMarginsF(margin, margin, margin, margin));
painter.drawText(bRect, Qt::AlignCenter, m_messageStack.top());
painter.drawRoundedRect(
rect() - QMarginsF(margin, margin, margin, margin), 5, 5);
return QLabel::paintEvent(e);
}
void OverlayMessage::showEvent(QShowEvent*)
QRect OverlayMessage::boundingRect() const
{
update();
}
QRectF OverlayMessage::boundingRect() const
{
// We draw the white contrasting background for the text, using the
// same text and options to get the boundingRect that the text will
// have.
QRectF bRect = QApplication::fontMetrics().boundingRect(
m_targetArea, Qt::AlignCenter, m_messageStack.top());
// These four calls provide padding for the rect
const int margin = QApplication::fontMetrics().height() / 2;
bRect.setWidth(bRect.width() + margin);
bRect.setHeight(bRect.height() + margin);
bRect.setX(bRect.x() - margin);
bRect.setY(bRect.y() - margin);
return bRect;
QRect geom = QRect(QPoint(), sizeHint());
geom.moveCenter(m_targetArea.center());
return geom;
}
void OverlayMessage::updateGeometry()
{
m_instance->setGeometry(m_instance->boundingRect().toRect());
QWidget::updateGeometry();
setGeometry(boundingRect());
QLabel::updateGeometry();
}
OverlayMessage* OverlayMessage::m_instance = nullptr;

View File

@@ -1,7 +1,7 @@
#pragma once
#include <QLabel>
#include <QStack>
#include <QWidget>
/**
* @brief Overlay a message in capture mode.
@@ -17,7 +17,7 @@
* @note You have to make sure that widgets pop the messages they pushed when
* they are closed, to avoid potential bugs and resource leaks.
*/
class OverlayMessage : public QWidget
class OverlayMessage : public QLabel
{
public:
OverlayMessage() = delete;
@@ -28,16 +28,19 @@ public:
static void setVisibility(bool visible);
static OverlayMessage* instance();
static void pushKeyMap(const QList<QPair<QString, QString>>& map);
static QString compileFromKeyMap(const QList<QPair<QString, QString>>& map);
private:
QStack<QString> m_messageStack;
QRect m_targetArea;
QColor m_fillColor, m_textColor;
static OverlayMessage* m_instance;
OverlayMessage(QWidget* parent, const QRect& center);
void paintEvent(QPaintEvent*) override;
void showEvent(QShowEvent*) override;
QRectF boundingRect() const;
QRect boundingRect() const;
void updateGeometry();
};

View File

@@ -132,7 +132,9 @@ void SelectionWidget::setGeometry(const QRect& r)
{
QWidget::setGeometry(r + QMargins(MARGIN, MARGIN, MARGIN, MARGIN));
updateCursor();
emit geometryChanged();
if (isVisible()) {
emit geometryChanged();
}
}
QRect SelectionWidget::geometry() const
@@ -289,13 +291,27 @@ void SelectionWidget::paintEvent(QPaintEvent*)
void SelectionWidget::resizeEvent(QResizeEvent*)
{
updateAreas();
emit geometryChanged();
if (isVisible()) {
emit geometryChanged();
}
}
void SelectionWidget::moveEvent(QMoveEvent*)
{
updateAreas();
emit geometryChanged();
if (isVisible()) {
emit geometryChanged();
}
}
void SelectionWidget::showEvent(QShowEvent*)
{
emit visibilityChanged();
}
void SelectionWidget::hideEvent(QHideEvent*)
{
emit visibilityChanged();
}
void SelectionWidget::updateColor(const QColor& c)

View File

@@ -50,10 +50,14 @@ protected:
void resizeEvent(QResizeEvent*);
void moveEvent(QMoveEvent*);
void showEvent(QShowEvent*) override;
void hideEvent(QHideEvent*) override;
signals:
void animationEnded();
void geometryChanged();
void geometrySettled();
void visibilityChanged();
public slots:
void updateColor(const QColor& c);

View File

@@ -50,11 +50,11 @@ void ColorGrabWidget::startGrabbing()
// This is undone in the destructor.
qApp->setOverrideCursor(Qt::CrossCursor);
qApp->installEventFilter(this);
OverlayMessage::push(
"Press Enter or Left Mouse Button to accept color\n"
"Press and hold Left Mouse Button to precisely select color\n"
"Press Space or Right Mouse Button to toggle magnifier\n"
"Press ESC to cancel");
OverlayMessage::pushKeyMap(
{ { "Enter or Left Click", tr("Accept color") },
{ "Hold Left Click", tr("Precisely select color") },
{ "Space or Right Click", tr("Toggle magnifier") },
{ "Esc", tr("Cancel") } });
}
QColor ColorGrabWidget::color()