diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1cadbbd2cd..a49d96a7f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -69,6 +69,12 @@ option(USE_EXTERNAL_SINGLEAPPLICATION "Use external QtSingleApplication library"
option(USE_LAUNCHER_ABSOLUTE_PATH "Use absolute path for the desktop launcher" ON)
option(USE_WAYLAND_CLIPBOARD "USE KF Gui Wayland Clipboard" OFF)
option(DISABLE_UPDATE_CHECKER "Disable check for updates" OFF)
+option(USE_PLUGIN_MANAGER "Activate the Plugin Manager" ON)
+option(USE_WAYLAND_GRIM "Activate the Wayland GRIM screenshot adapter" OFF)
+
+if (USE_PLUGIN_MANAGER)
+ set(PLUGIN_DIRECTORY "app_plugins" CACHE PATH "Setting the Plugin Manager Plugin Directory")
+endif()
if (DISABLE_UPDATE_CHECKER)
add_compile_definitions(DISABLE_UPDATE_CHECKER)
endif ()
diff --git a/data/graphics.qrc b/data/graphics.qrc
index fd1d93d139..bed91511de 100644
--- a/data/graphics.qrc
+++ b/data/graphics.qrc
@@ -99,5 +99,9 @@
img/material/black/image.svg
img/material/white/apps.svg
img/material/white/image.svg
+ img/material/black/content-print.svg
+ img/material/black/save-to-pdf.svg
+ img/material/white/content-print.svg
+ img/material/white/save-to-pdf.svg
diff --git a/data/img/material/black/content-print.svg b/data/img/material/black/content-print.svg
new file mode 100644
index 0000000000..1409b5c0d0
--- /dev/null
+++ b/data/img/material/black/content-print.svg
@@ -0,0 +1,41 @@
+
+
diff --git a/data/img/material/black/save-to-pdf.svg b/data/img/material/black/save-to-pdf.svg
new file mode 100644
index 0000000000..98394b00b0
--- /dev/null
+++ b/data/img/material/black/save-to-pdf.svg
@@ -0,0 +1,24 @@
+
+
diff --git a/data/img/material/white/content-print.svg b/data/img/material/white/content-print.svg
new file mode 100644
index 0000000000..29a0cda4e1
--- /dev/null
+++ b/data/img/material/white/content-print.svg
@@ -0,0 +1,56 @@
+
+
diff --git a/data/img/material/white/save-to-pdf.svg b/data/img/material/white/save-to-pdf.svg
new file mode 100644
index 0000000000..45434f480e
--- /dev/null
+++ b/data/img/material/white/save-to-pdf.svg
@@ -0,0 +1,36 @@
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c29349a525..74bc2b45c1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,12 +8,18 @@ find_package(
Network
Svg
DBus
- LinguistTools)
+ LinguistTools
+ PrintSupport)
if (USE_WAYLAND_CLIPBOARD)
find_package(KF5GuiAddons)
endif()
+if (USE_PLUGIN_MANAGER)
+ find_package(yaml-cpp)
+endif()
+
+set(USE_PLUGIN_MANAGER ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
@@ -213,6 +219,7 @@ target_link_libraries(
Qt5::DBus
Qt5::Network
Qt5::Widgets
+ Qt5::PrintSupport
${QTSINGLEAPPLICATION_LIBRARY}
QtColorWidgets
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c933bdd6f1..5bb3cd5339 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -3,6 +3,8 @@ target_sources(flameshot PRIVATE
flameshotdaemon.h
flameshotdbusadapter.h
qguiappcurrentscreen.h
+ pluginmanager.h
+ corepluginInterface.h
)
target_sources(flameshot PRIVATE
@@ -11,6 +13,7 @@ target_sources(flameshot PRIVATE
flameshotdaemon.cpp
flameshotdbusadapter.cpp
qguiappcurrentscreen.cpp
+ pluginmanager.cpp
)
IF (WIN32)
diff --git a/src/core/capturerequest.h b/src/core/capturerequest.h
index ac8f885cec..ed90cc6ab1 100644
--- a/src/core/capturerequest.h
+++ b/src/core/capturerequest.h
@@ -27,6 +27,8 @@ class CaptureRequest
PIN = 16,
UPLOAD = 32,
ACCEPT_ON_SELECT = 64,
+ PRINT_SYSTEM = 128,
+ SAVE_TO_PDF = 256
};
CaptureRequest(CaptureMode mode,
diff --git a/src/core/corepluginInterface.h b/src/core/corepluginInterface.h
new file mode 100644
index 0000000000..54f48672e8
--- /dev/null
+++ b/src/core/corepluginInterface.h
@@ -0,0 +1,20 @@
+#ifndef COREPLUGININTERFACE_H
+#define COREPLUGININTERFACE_H
+
+#include
+
+class CorePluginInterface {
+public:
+ virtual ~CorePluginInterface() = 0;
+ virtual bool load(std::map &PluginConfig) = 0;
+ virtual void unload() = 0;
+ virtual bool ImagePost(QPixmap &pixmap) = 0;
+ virtual bool ImageToPDFPost(QPixmap &pixmap) = 0;
+ virtual bool PrintPre(QPixmap &pixmap) = 0;
+};
+
+#define FlameshotPlugin_iid "FlameshotPlugin.CorePluginInterface"
+
+Q_DECLARE_INTERFACE(CorePluginInterface, FlameshotPlugin_iid)
+
+#endif // COREPLUGININTERFACE_H
diff --git a/src/core/flameshot.cpp b/src/core/flameshot.cpp
index c7eadcadb6..af564b1774 100644
--- a/src/core/flameshot.cpp
+++ b/src/core/flameshot.cpp
@@ -31,7 +31,15 @@
#include
#include
#include
+#include
#include
+#include
+#include
+#include
+
+#ifdef USE_PLUGIN_MANAGER
+#include "core/pluginmanager.h"
+#endif
#if defined(Q_OS_MACOS)
#include
@@ -352,7 +360,12 @@ void Flameshot::exportCapture(const QPixmap& capture,
int tasks = req.tasks(), mode = req.captureMode();
QString path = req.path();
+ QPixmap PixmapOutputBuffer(capture);
+
if (tasks & CR::PRINT_GEOMETRY) {
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallImagePost(PixmapOutputBuffer);
+#endif
QByteArray byteArray;
QBuffer buffer(&byteArray);
QTextStream(stdout)
@@ -361,9 +374,12 @@ void Flameshot::exportCapture(const QPixmap& capture,
}
if (tasks & CR::PRINT_RAW) {
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallImagePost(PixmapOutputBuffer);
+#endif
QByteArray byteArray;
QBuffer buffer(&byteArray);
- capture.save(&buffer, "PNG");
+ PixmapOutputBuffer.save(&buffer, "PNG");
QFile file;
file.open(stdout, QIODevice::WriteOnly);
@@ -372,19 +388,35 @@ void Flameshot::exportCapture(const QPixmap& capture,
}
if (tasks & CR::SAVE) {
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallImagePost(PixmapOutputBuffer);
+#endif
if (req.path().isEmpty()) {
- saveToFilesystemGUI(capture);
+ saveToFilesystemGUI(PixmapOutputBuffer);
} else {
- saveToFilesystem(capture, path);
+ saveToFilesystem(PixmapOutputBuffer, path);
}
}
+ if (tasks & CR::SAVE_TO_PDF) {
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallImageToPDFPost(PixmapOutputBuffer);
+#endif
+ saveToPDF(PixmapOutputBuffer);
+ }
+
if (tasks & CR::COPY) {
- FlameshotDaemon::copyToClipboard(capture);
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallImagePost(PixmapOutputBuffer);
+#endif
+ FlameshotDaemon::copyToClipboard(PixmapOutputBuffer);
}
if (tasks & CR::PIN) {
- FlameshotDaemon::createPin(capture, selection);
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallImagePost(PixmapOutputBuffer);
+#endif
+ FlameshotDaemon::createPin(PixmapOutputBuffer, selection);
if (mode == CR::SCREEN_MODE || mode == CR::FULLSCREEN_MODE) {
AbstractLogger::info()
<< QObject::tr("Full screen screenshot pinned to screen");
@@ -392,6 +424,9 @@ void Flameshot::exportCapture(const QPixmap& capture,
}
if (tasks & CR::UPLOAD) {
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallImagePost(PixmapOutputBuffer);
+#endif
if (!ConfigHandler().uploadWithoutConfirmation()) {
auto* dialog = new ImgUploadDialog();
if (dialog->exec() == QDialog::Rejected) {
@@ -399,7 +434,7 @@ void Flameshot::exportCapture(const QPixmap& capture,
}
}
- ImgUploaderBase* widget = ImgUploaderManager().uploader(capture);
+ ImgUploaderBase* widget = ImgUploaderManager().uploader(PixmapOutputBuffer);
widget->show();
widget->activateWindow();
// NOTE: lambda can't capture 'this' because it might be destroyed later
@@ -416,8 +451,68 @@ void Flameshot::exportCapture(const QPixmap& capture,
});
}
+ if(tasks & CR::PRINT_SYSTEM) {
+ QPixmap pixmap = capture;
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->CallPrintPre(pixmap);
+#endif
+ QPrinter printer;
+ printer.setPageOrientation(QPageLayout::Orientation::Landscape);
+
+ QPrintPreviewDialog dialog(&printer);
+ dialog.setWindowFlag(Qt::WindowMinMaxButtonsHint);
+ dialog.setWindowTitle(tr("Print Document"));
+
+#if defined(Q_OS_WIN)
+ QToolBar *PrintPreviewToolbar = dialog.findChild();
+ QList List = PrintPreviewToolbar->actions();
+ int index = 0;
+ QSet RemoveIndex;
+ RemoveIndex.insert(0);
+ RemoveIndex.insert(1);
+ RemoveIndex.insert(16);
+ RemoveIndex.insert(17);
+ RemoveIndex.insert(18);
+ const int PrintAction = 21;
+ QSet RemoveList;
+ foreach(auto it, List) {
+ if(RemoveIndex.find(index) != RemoveIndex.end()) {
+ RemoveList.insert(it);
+ }
+ if(index == PrintAction) {
+ it->setIcon(QIcon(":/img/material/black/content-print.svg"));
+ }
+ index++;
+ }
+ foreach(auto it, List) {
+ if(RemoveList.find(it) != RemoveList.end()) {
+ PrintPreviewToolbar->removeAction(it);
+ }
+ }
+
+#endif
+ connect(&dialog, &QPrintPreviewDialog::paintRequested, [&](QPrinter *printer) {
+ QPainter painter(printer);
+ if((pixmap.size().width() >= printer->width()) ||
+ (pixmap.size().height() >= printer->height())) {
+ pixmap = pixmap.scaled(printer->width(), printer->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ } else if(pixmap.size().width() >= (printer->width()/2)) {
+ pixmap = pixmap.scaledToWidth(printer->width(), Qt::SmoothTransformation);
+ if(pixmap.size().height() >= printer->height()) {
+ pixmap = pixmap.scaledToHeight(printer->height(), Qt::SmoothTransformation);
+ }
+ }
+
+ QRect rect((printer->width() - pixmap.size().width()) /2,
+ (printer->height() - pixmap.size().height()) /2,
+ pixmap.size().width(), pixmap.size().height());
+ painter.drawPixmap(rect, pixmap);
+ });
+ dialog.exec();
+ }
+
if (!(tasks & CR::UPLOAD)) {
- emit captureTaken(capture);
+ emit captureTaken(PixmapOutputBuffer);
}
}
diff --git a/src/core/pluginmanager.cpp b/src/core/pluginmanager.cpp
new file mode 100644
index 0000000000..22aaf2e4bd
--- /dev/null
+++ b/src/core/pluginmanager.cpp
@@ -0,0 +1,157 @@
+#ifdef USE_PLUGIN_MANAGER
+
+#include "pluginmanager.h"
+#include
+#include
+#include
+#include "corepluginInterface.h"
+
+PluginManager::PluginManager() {
+
+}
+
+PluginManager *PluginManager::getInstance() {
+ static PluginManager pluginManager;
+ qDebug() << QObject::tr("Get the plugin manager interface: ").toStdString().c_str() << &pluginManager;
+ return &pluginManager;
+}
+
+void PluginManager::LoopDirsPlugins(QString Base, std::function Callback) {
+ QDir dirs(Base);
+ if(dirs.exists()) {
+ dirs.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);
+ QFileInfoList fileList = dirs.entryInfoList();
+ foreach(QFileInfo fileInfo, fileList) {
+ if (Base != pluginDir && fileInfo.isDir()) {
+ QFileInfo infocheck(fileInfo.absolutePath() + PluginDefineYaml);
+ if(!infocheck.exists()) {
+ LoopDirsPlugins(fileInfo.absoluteFilePath(), Callback);
+ }
+ } else if(Base == pluginDir && fileInfo.isDir()) {
+ LoopDirsPlugins(fileInfo.absoluteFilePath(), Callback);
+ } else if(fileInfo.isFile()) {
+ if(fileInfo.fileName() == PluginDefineYaml) {
+ Callback(fileInfo.absoluteFilePath());
+ }
+ }
+ }
+ }
+}
+
+int PluginManager::LoadPlugins() {
+ int count = 0;
+ LoopDirsPlugins(pluginDir, [&](QString PluginInfoDefaultYaml) {
+ qDebug() << QObject::tr("Get Plugin Definde: ").toStdString().c_str() << PluginInfoDefaultYaml;
+ YAML::Node config;
+ try {
+ config = YAML::LoadFile(PluginInfoDefaultYaml.toStdString());
+ } catch(std::exception &e) {
+ qDebug() << QObject::tr("Get Plugin Error: ").toStdString().c_str() << e.what() << PluginInfoDefaultYaml;
+ return;
+ }
+
+ PluginInfo Info;
+ Info.PluginInfoFullPath = PluginInfoDefaultYaml;
+ Info.PluginName = QString::fromStdString(config["plugin"]["name"].as());
+ if (config["plugin"]["type"].as() == "qt") {
+ Info.PluginType = PluginInfo::QTPlugin;
+ }
+
+ QString plugin = QFileInfo(PluginInfoDefaultYaml).absolutePath() + "/" + QString::fromStdString(config["plugin"]["file"].as());
+ Info.Pluginfile = plugin;
+
+ std::map PluginConfig = config["plugin"]["config"].as>();
+
+ QPluginLoader *Loader = new QPluginLoader(Info.Pluginfile);
+ if(Loader) {
+ if(Loader->load()) {
+ CorePluginInterface *Interface = qobject_cast(Loader->instance());
+ if(Interface->load(PluginConfig)) {
+ Info.PluginLoader = Loader;
+ }
+ }
+
+ this->PluginLists.append(Info);
+
+ count++;
+ }
+
+ });
+ qDebug() << QObject::tr("Get Plugin Count: ").toStdString().c_str() << count;
+ return count;
+}
+
+bool PluginManager::UnLoadPlugins() {
+ foreach(auto Info, this->PluginLists) {
+ if(Info.PluginType == PluginInfo::QTPlugin) {
+ QPluginLoader *Loader = reinterpret_cast(Info.PluginLoader);
+ if(Loader) {
+ delete Loader;
+ Info.PluginLoader = nullptr;
+ }
+ }
+ }
+ this->PluginLists.clear();
+ return false;
+}
+
+bool PluginManager::CallImagePost(QPixmap &pixmap) {
+ bool Result = false;
+ foreach(auto Info, this->PluginLists) {
+ if(Info.PluginType == PluginInfo::QTPlugin) {
+ qDebug() << QObject::tr("Call Plugin(ImagePost): ").toStdString().c_str() << Info.PluginName;
+ qDebug() << QObject::tr("Call Plugin(ImagePost) YAML FileName: ").toStdString().c_str() << Info.PluginInfoFullPath;
+ qDebug() << QObject::tr("Call Plugin(ImagePost) Qt Plugin: ").toStdString().c_str() << Info.Pluginfile;
+ if (Info.PluginType == PluginInfo::QTPlugin) {
+ QPluginLoader *Loader = reinterpret_cast(Info.PluginLoader);
+ if(Loader) {
+ CorePluginInterface *Interface = qobject_cast(Loader->instance());
+ Interface->ImagePost(pixmap);
+ Result = true;
+ }
+ }
+ }
+ }
+ return Result;
+}
+
+bool PluginManager::CallImageToPDFPost(QPixmap &pixmap) {
+ bool Result = false;
+ foreach(auto Info, this->PluginLists) {
+ if(Info.PluginType == PluginInfo::QTPlugin) {
+ qDebug() << QObject::tr("Call Plugin(ImageToPDFPost): ").toStdString().c_str() << Info.PluginName;
+ qDebug() << QObject::tr("Call Plugin(ImageToPDFPost) YAML FileName: ").toStdString().c_str() << Info.PluginInfoFullPath;
+ qDebug() << QObject::tr("Call Plugin(ImageToPDFPost) Qt Plugin: ").toStdString().c_str() << Info.Pluginfile;
+ if (Info.PluginType == PluginInfo::QTPlugin) {
+ QPluginLoader *Loader = reinterpret_cast(Info.PluginLoader);
+ if(Loader) {
+ CorePluginInterface *Interface = qobject_cast(Loader->instance());
+ Interface->ImageToPDFPost(pixmap);
+ Result = true;
+ }
+ }
+ }
+ }
+ return Result;
+}
+
+bool PluginManager::CallPrintPre(QPixmap &pixmap) {
+ bool Result = false;
+ foreach(auto Info, this->PluginLists) {
+ if(Info.PluginType == PluginInfo::QTPlugin) {
+ qDebug() << QObject::tr("Call Plugin(PrintPre): ").toStdString().c_str() << Info.PluginName;
+ qDebug() << QObject::tr("Call Plugin(PrintPre) YAML FileName: ").toStdString().c_str() << Info.PluginInfoFullPath;
+ qDebug() << QObject::tr("Call Plugin(PrintPre) Qt Plugin: ").toStdString().c_str() << Info.Pluginfile;
+ if (Info.PluginType == PluginInfo::QTPlugin) {
+ QPluginLoader *Loader = reinterpret_cast(Info.PluginLoader);
+ if(Loader) {
+ CorePluginInterface *Interface = qobject_cast(Loader->instance());
+ Interface->PrintPre(pixmap);
+ Result = true;
+ }
+ }
+ }
+ }
+ return Result;
+}
+#endif //USE_PLUGIN_MANAGER
diff --git a/src/core/pluginmanager.h b/src/core/pluginmanager.h
new file mode 100644
index 0000000000..4b32c21ef0
--- /dev/null
+++ b/src/core/pluginmanager.h
@@ -0,0 +1,50 @@
+#ifndef PLUGINMANAGER_H
+#define PLUGINMANAGER_H
+
+#ifdef USE_PLUGIN_MANAGER
+
+#define GET_BUILD_SET(x) #x
+#define BUILD_DEFINE_CONV_C_STRING(x) GET_BUILD_SET(x)
+
+#include
+#include
+#include
+#include
+
+const QString pluginDir = BUILD_DEFINE_CONV_C_STRING(PLUGIN_DIRECTORY);
+
+const QString PluginDefineYaml = "plugin.yaml";
+
+typedef struct _PluginInfo {
+ QString PluginName;
+ QString PluginInfoFullPath;
+ enum Type {
+ QTPlugin,
+ PyPlugin, /*no used*/
+ LuaPlugin /*no used*/
+ }PluginType;
+ QString Pluginfile;
+ void *PluginLoader;
+}PluginInfo;
+
+class PluginManager
+{
+ typedef void CallbackPluginLoads(QString PluginInfoDefaultYaml);
+private:
+ PluginManager();
+public:
+ static PluginManager *getInstance();
+ int LoadPlugins();
+ bool UnLoadPlugins();
+ bool CallImagePost(QPixmap &pixmap);
+ bool CallImageToPDFPost(QPixmap &pixmap);
+ bool CallPrintPre(QPixmap &pixmap);
+private:
+ static void LoopDirsPlugins(QString Base, std::function Callback);
+private:
+ QList PluginLists;
+};
+
+#endif //USE_PLUGIN_MANAGER
+
+#endif // PLUGINMANAGER_H
diff --git a/src/main.cpp b/src/main.cpp
index 23d3157e01..b5517313a0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -32,6 +32,9 @@
#include
#include
#endif
+#ifdef USE_PLUGIN_MANAGER
+#include "core/pluginmanager.h"
+#endif
#ifdef Q_OS_LINUX
// source: https://github.com/ksnip/ksnip/issues/416
@@ -126,6 +129,9 @@ void reinitializeAsQApplication(int& argc, char* argv[])
int main(int argc, char* argv[])
{
+#ifdef USE_PLUGIN_MANAGER
+ PluginManager::getInstance()->LoadPlugins();
+#endif
#ifdef Q_OS_LINUX
wayland_hacks();
#endif
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index d2a629242b..6712ca6ac2 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -3,9 +3,11 @@ target_sources(flameshot PRIVATE pixelate/pixelatetool.h pixelate/pixelatetool.c
target_sources(flameshot PRIVATE circle/circletool.h circle/circletool.cpp)
target_sources(flameshot PRIVATE circlecount/circlecounttool.h circlecount/circlecounttool.cpp)
target_sources(flameshot PRIVATE copy/copytool.h copy/copytool.cpp)
+target_sources(flameshot PRIVATE print/printtool.h print/printtool.cpp)
target_sources(flameshot PRIVATE exit/exittool.h exit/exittool.cpp)
target_sources(flameshot PRIVATE sizeincrease/sizeincreasetool.h sizeincrease/sizeincreasetool.cpp)
target_sources(flameshot PRIVATE sizedecrease/sizedecreasetool.h sizedecrease/sizedecreasetool.cpp)
+target_sources(flameshot PRIVATE save-to-pdf/save-to-pdf.h save-to-pdf/save-to-pdf.cpp)
target_sources(
flameshot
PRIVATE imgupload/storages/imgur/imguruploader.h
diff --git a/src/tools/capturetool.h b/src/tools/capturetool.h
index a095d61857..0783e3940b 100644
--- a/src/tools/capturetool.h
+++ b/src/tools/capturetool.h
@@ -41,13 +41,15 @@ class CaptureTool : public QObject
TYPE_OPEN_APP = 14,
TYPE_PIXELATE = 15,
TYPE_REDO = 16,
- TYPE_PIN = 17,
- TYPE_TEXT = 18,
- TYPE_CIRCLECOUNT = 19,
- TYPE_SIZEINCREASE = 20,
- TYPE_SIZEDECREASE = 21,
- TYPE_INVERT = 22,
- TYPE_ACCEPT = 23,
+ TYPE_PRINT = 17,
+ TYPE_PIN = 18,
+ TYPE_TEXT = 19,
+ TYPE_CIRCLECOUNT = 20,
+ TYPE_SIZEINCREASE = 21,
+ TYPE_SIZEDECREASE = 22,
+ TYPE_INVERT = 23,
+ TYPE_ACCEPT = 24,
+ TYPE_SAVE_TO_PDF = 25
};
Q_ENUM(Type);
diff --git a/src/tools/print/printtool.cpp b/src/tools/print/printtool.cpp
new file mode 100644
index 0000000000..b73cb23ab3
--- /dev/null
+++ b/src/tools/print/printtool.cpp
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// SPDX-FileCopyrightText: 2017-2019 Ouyang Chunhui & Contributor
+
+#include "printtool.h"
+#include "src/utils/screenshotsaver.h"
+#include
+
+PrintTool::PrintTool(QObject* parent)
+ : AbstractActionTool(parent)
+{}
+
+bool PrintTool::closeOnButtonPressed() const
+{
+ return true;
+}
+
+QIcon PrintTool::icon(const QColor& background, bool inEditor) const
+{
+ Q_UNUSED(inEditor)
+ return QIcon(iconPath(background) + "content-print.svg");
+}
+QString PrintTool::name() const
+{
+ return tr("Print");
+}
+
+CaptureTool::Type PrintTool::type() const
+{
+ return CaptureTool::TYPE_PRINT;
+}
+
+QString PrintTool::description() const
+{
+ return tr("Print");
+}
+
+CaptureTool* PrintTool::copy(QObject* parent)
+{
+ return new PrintTool(parent);
+}
+
+void PrintTool::pressed(CaptureContext& context)
+{
+ emit requestAction(REQ_CLEAR_SELECTION);
+ context.request.addTask(CaptureRequest::PRINT_SYSTEM);
+ emit requestAction(REQ_CAPTURE_DONE_OK);
+ emit requestAction(REQ_CLOSE_GUI);
+}
diff --git a/src/tools/print/printtool.h b/src/tools/print/printtool.h
new file mode 100644
index 0000000000..42ae384e7b
--- /dev/null
+++ b/src/tools/print/printtool.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// SPDX-FileCopyrightText: 2017-2019 Ouyang Chunhui & Contributor
+
+#pragma once
+
+#include "src/tools/abstractactiontool.h"
+
+class PrintTool : public AbstractActionTool
+{
+ Q_OBJECT
+public:
+ explicit PrintTool(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;
+};
diff --git a/src/tools/save-to-pdf/save-to-pdf.cpp b/src/tools/save-to-pdf/save-to-pdf.cpp
new file mode 100644
index 0000000000..46fbc7e639
--- /dev/null
+++ b/src/tools/save-to-pdf/save-to-pdf.cpp
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// SPDX-FileCopyrightText: 2017-2019 Ouyang Chunhui & Contributor
+
+#include "save-to-pdf.h"
+#include "src/utils/screenshotsaver.h"
+#include
+
+SaveToPDFTool::SaveToPDFTool(QObject* parent)
+ : AbstractActionTool(parent)
+{}
+
+bool SaveToPDFTool::closeOnButtonPressed() const
+{
+ return true;
+}
+
+QIcon SaveToPDFTool::icon(const QColor& background, bool inEditor) const
+{
+ Q_UNUSED(inEditor)
+ return QIcon(iconPath(background) + "save-to-pdf.svg");
+}
+QString SaveToPDFTool::name() const
+{
+ return tr("Save To PDF");
+}
+
+CaptureTool::Type SaveToPDFTool::type() const
+{
+ return CaptureTool::TYPE_PRINT;
+}
+
+QString SaveToPDFTool::description() const
+{
+ return tr("Save To PDF");
+}
+
+CaptureTool* SaveToPDFTool::copy(QObject* parent)
+{
+ return new SaveToPDFTool(parent);
+}
+
+void SaveToPDFTool::pressed(CaptureContext& context)
+{
+ emit requestAction(REQ_CLEAR_SELECTION);
+ context.request.addTask(CaptureRequest::SAVE_TO_PDF);
+ emit requestAction(REQ_CAPTURE_DONE_OK);
+ emit requestAction(REQ_CLOSE_GUI);
+}
diff --git a/src/tools/save-to-pdf/save-to-pdf.h b/src/tools/save-to-pdf/save-to-pdf.h
new file mode 100644
index 0000000000..97c35f5351
--- /dev/null
+++ b/src/tools/save-to-pdf/save-to-pdf.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// SPDX-FileCopyrightText: 2017-2019 Ouyang Chunhui & Contributor
+
+#pragma once
+
+#include "src/tools/abstractactiontool.h"
+
+class SaveToPDFTool : public AbstractActionTool
+{
+ Q_OBJECT
+public:
+ explicit SaveToPDFTool(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;
+};
diff --git a/src/tools/toolfactory.cpp b/src/tools/toolfactory.cpp
index 98ed0ab3d7..5910fd821f 100644
--- a/src/tools/toolfactory.cpp
+++ b/src/tools/toolfactory.cpp
@@ -20,9 +20,11 @@
#include "rectangle/rectangletool.h"
#include "redo/redotool.h"
#include "save/savetool.h"
+#include "save-to-pdf/save-to-pdf.h"
#include "selection/selectiontool.h"
#include "sizedecrease/sizedecreasetool.h"
#include "sizeincrease/sizeincreasetool.h"
+#include "print/printtool.h"
#include "text/texttool.h"
#include "undo/undotool.h"
@@ -48,6 +50,7 @@ CaptureTool* ToolFactory::CreateTool(CaptureTool::Type t, QObject* parent)
if_TYPE_return_TOOL(TYPE_UNDO, UndoTool);
if_TYPE_return_TOOL(TYPE_COPY, CopyTool);
if_TYPE_return_TOOL(TYPE_SAVE, SaveTool);
+ if_TYPE_return_TOOL(TYPE_SAVE_TO_PDF, SaveToPDFTool);
if_TYPE_return_TOOL(TYPE_EXIT, ExitTool);
if_TYPE_return_TOOL(TYPE_IMAGEUPLOADER, ImgUploaderTool);
#if !defined(Q_OS_MACOS)
@@ -55,6 +58,7 @@ CaptureTool* ToolFactory::CreateTool(CaptureTool::Type t, QObject* parent)
#endif
if_TYPE_return_TOOL(TYPE_PIXELATE, PixelateTool);
if_TYPE_return_TOOL(TYPE_REDO, RedoTool);
+ if_TYPE_return_TOOL(TYPE_PRINT, PrintTool);
if_TYPE_return_TOOL(TYPE_PIN, PinTool);
if_TYPE_return_TOOL(TYPE_TEXT, TextTool);
if_TYPE_return_TOOL(TYPE_CIRCLECOUNT, CircleCountTool);
diff --git a/src/utils/confighandler.cpp b/src/utils/confighandler.cpp
index 485fb26575..91a87007d0 100644
--- a/src/utils/confighandler.cpp
+++ b/src/utils/confighandler.cpp
@@ -142,6 +142,7 @@ static QMap> recognizedShortcuts = {
SHORTCUT("TYPE_UNDO" , "Ctrl+Z" ),
SHORTCUT("TYPE_COPY" , "Ctrl+C" ),
SHORTCUT("TYPE_SAVE" , "Ctrl+S" ),
+ SHORTCUT("TYPE_SAVE_TO_PDF" , ),
SHORTCUT("TYPE_ACCEPT" , "Return" ),
SHORTCUT("TYPE_EXIT" , "Ctrl+Q" ),
SHORTCUT("TYPE_IMAGEUPLOADER" , ),
@@ -179,6 +180,7 @@ static QMap> recognizedShortcuts = {
SHORTCUT("TYPE_SIZEINCREASE" , ),
SHORTCUT("TYPE_SIZEDECREASE" , ),
SHORTCUT("TYPE_CIRCLECOUNT" , ),
+ SHORTCUT("TYPE_PRINT", )
};
// clang-format on
diff --git a/src/utils/screenshotsaver.cpp b/src/utils/screenshotsaver.cpp
index f7f5a7102b..5932681583 100644
--- a/src/utils/screenshotsaver.cpp
+++ b/src/utils/screenshotsaver.cpp
@@ -23,6 +23,10 @@
#include
#include
#include
+#include
+#ifdef USE_PLUGIN_MANAGER
+#include "core/pluginmanager.h"
+#endif
#if defined(Q_OS_MACOS)
#include "src/widgets/capture/capturewidget.h"
#endif
@@ -101,6 +105,23 @@ QString ShowSaveFileDialog(const QString& title, const QString& directory)
}
}
+QString ShowSaveToPDFDialog(const QString& title, const QString& directory)
+{
+ QFileDialog dialog(nullptr, title, directory);
+ dialog.setAcceptMode(QFileDialog::AcceptSave);
+
+ // Build string list of supported image formats
+ QStringList mimeTypeList;
+ mimeTypeList.append("application/pdf");
+ dialog.setMimeTypeFilters(mimeTypeList);
+ if (dialog.exec() == QDialog::Accepted) {
+ return dialog.selectedFiles().constFirst();
+ } else {
+ return {};
+ }
+}
+
+
void saveToClipboardMime(const QPixmap& capture, const QString& imageType)
{
QByteArray array;
@@ -168,6 +189,49 @@ void saveToClipboard(const QPixmap& capture)
}
}
+bool saveToPDF(const QPixmap& capture) {
+ bool okay = false;
+ QString savePath;
+ ConfigHandler config;
+ savePath = QDir::toNativeSeparators(
+ ShowSaveToPDFDialog(QObject::tr("Save screenshot To PDF"), savePath));
+ if(savePath.endsWith(".pdf", Qt::CaseInsensitive)) {
+ QPrinter printer(QPrinter::HighResolution);
+ printer.setOutputFormat(QPrinter::PdfFormat);
+ printer.setPageOrientation(QPageLayout::Landscape);
+ printer.setPageSize(QPageSize::A4);
+ printer.setOutputFileName(savePath);
+ QPainter painter(&printer);
+ QPixmap new_capture = capture.scaled(printer.width(), printer.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ QRect rect(0, 0, new_capture.size().width(), new_capture.size().height());
+ painter.drawPixmap(rect, new_capture);
+ okay = true;
+ }
+
+ if(okay) {
+ QString pathNoFile =
+ savePath.left(savePath.lastIndexOf(QDir::separator()));
+
+ ConfigHandler().setSavePath(pathNoFile);
+
+ QString msg = QObject::tr("Capture saved as ") + savePath;
+ AbstractLogger().attachNotificationPath(savePath) << msg;
+
+ if (config.copyPathAfterSave()) {
+ FlameshotDaemon::copyToClipboard(
+ savePath, QObject::tr("Path copied to clipboard as ") + savePath);
+ }
+ } else {
+ QString msg = QObject::tr("Error trying to save as ") + savePath;
+ QMessageBox saveErrBox(
+ QMessageBox::Warning, QObject::tr("Save Error"), msg);
+ saveErrBox.setWindowIcon(QIcon(GlobalValues::iconPath()));
+ saveErrBox.exec();
+ }
+
+ return okay;
+}
+
bool saveToFilesystemGUI(const QPixmap& capture)
{
bool okay = false;
diff --git a/src/utils/screenshotsaver.h b/src/utils/screenshotsaver.h
index 9face3468b..a1675eadb9 100644
--- a/src/utils/screenshotsaver.h
+++ b/src/utils/screenshotsaver.h
@@ -11,6 +11,8 @@ bool saveToFilesystem(const QPixmap& capture,
const QString& path,
const QString& messagePrefix = "");
QString ShowSaveFileDialog(const QString& title, const QString& directory);
+QString ShowSaveToPDFDialog(const QString& title, const QString& directory);
void saveToClipboardMime(const QPixmap& capture, const QString& imageType);
void saveToClipboard(const QPixmap& capture);
bool saveToFilesystemGUI(const QPixmap& capture);
+bool saveToPDF(const QPixmap& capture);
diff --git a/src/widgets/capture/capturetoolbutton.cpp b/src/widgets/capture/capturetoolbutton.cpp
index bc51eb7272..be211d1db3 100644
--- a/src/widgets/capture/capturetoolbutton.cpp
+++ b/src/widgets/capture/capturetoolbutton.cpp
@@ -146,17 +146,18 @@ static std::map buttonTypeOrder
{ CaptureTool::TYPE_SELECTIONINDICATOR, 11 },
{ 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 },
+ { CaptureTool::TYPE_SAVE, 16 }, { CaptureTool::TYPE_SAVE_TO_PDF, 17},
+ { CaptureTool::TYPE_PRINT, 18}, { CaptureTool::TYPE_IMAGEUPLOADER, 29 },
+ { CaptureTool::TYPE_ACCEPT, 20 },
#if !defined(Q_OS_MACOS)
- { CaptureTool::TYPE_OPEN_APP, 19 }, { CaptureTool::TYPE_EXIT, 20 },
- { CaptureTool::TYPE_PIN, 21 },
+ { CaptureTool::TYPE_OPEN_APP, 21 }, { CaptureTool::TYPE_EXIT, 22 },
+ { CaptureTool::TYPE_PIN, 23 },
#else
- { CaptureTool::TYPE_EXIT, 19 }, { CaptureTool::TYPE_PIN, 20 },
+ { CaptureTool::TYPE_EXIT, 21 }, { CaptureTool::TYPE_PIN, 22 },
#endif
- { CaptureTool::TYPE_SIZEINCREASE, 22 },
- { CaptureTool::TYPE_SIZEDECREASE, 23 },
+ { CaptureTool::TYPE_SIZEINCREASE, 24 },
+ { CaptureTool::TYPE_SIZEDECREASE, 25 },
};
int CaptureToolButton::getPriorityByButton(CaptureTool::Type b)
@@ -174,7 +175,8 @@ QList CaptureToolButton::iterableButtonTypes = {
CaptureTool::TYPE_CIRCLECOUNT, CaptureTool::TYPE_PIXELATE,
CaptureTool::TYPE_MOVESELECTION, CaptureTool::TYPE_UNDO,
CaptureTool::TYPE_REDO, CaptureTool::TYPE_COPY,
- CaptureTool::TYPE_SAVE, CaptureTool::TYPE_EXIT,
+ CaptureTool::TYPE_SAVE, CaptureTool::TYPE_SAVE_TO_PDF,
+ CaptureTool::TYPE_PRINT, CaptureTool::TYPE_EXIT,
CaptureTool::TYPE_IMAGEUPLOADER,
#if !defined(Q_OS_MACOS)
CaptureTool::TYPE_OPEN_APP,
diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp
index 49ebff9720..9245694680 100644
--- a/src/widgets/capture/capturewidget.cpp
+++ b/src/widgets/capture/capturewidget.cpp
@@ -296,6 +296,7 @@ void CaptureWidget::initButtons()
// Remove irrelevant buttons from both lists
for (auto* buttonList : { &allButtonTypes, &visibleButtonTypes }) {
buttonList->removeOne(CaptureTool::TYPE_SAVE);
+ buttonList->removeOne(CaptureTool::TYPE_SAVE_TO_PDF);
buttonList->removeOne(CaptureTool::TYPE_COPY);
buttonList->removeOne(CaptureTool::TYPE_IMAGEUPLOADER);
buttonList->removeOne(CaptureTool::TYPE_OPEN_APP);