diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7cef987a..5b77edcf 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -39,6 +39,7 @@ qt_add_library(quickshell-core STATIC scriptmodel.cpp colorquantizer.cpp toolsupport.cpp + itemimagegrab.cpp ) qt_add_qml_module(quickshell-core diff --git a/src/core/itemimagegrab.cpp b/src/core/itemimagegrab.cpp new file mode 100644 index 00000000..06ee7b7e --- /dev/null +++ b/src/core/itemimagegrab.cpp @@ -0,0 +1,67 @@ +#include "itemimagegrab.hpp" + +#include +#include +#include +#include +#include +#include + +void ItemImageGrab::grab(QQuickItem* target, const QUrl& path) { + this->grab(target, path, QSize()); +} + +void ItemImageGrab::grab(QQuickItem* target, const QUrl& path, const QSize& targetSize) { + this->cropAndGrab(target, path, QRect(), targetSize); +} + +void ItemImageGrab::cropAndGrab(QQuickItem* target, const QUrl& path, const QRect& rect) { + this->cropAndGrab(target, path, rect, QSize()); +} + +void ItemImageGrab::cropAndGrab( + QQuickItem* target, + const QUrl& path, + const QRect& rect, + const QSize& targetSize +) { + if (!target) { + qWarning() << "ItemImageGrab: a target is required"; + return; + } + + if (!path.isLocalFile()) { + qWarning() << "ItemImageGrab: can only save to a file on the local filesystem"; + return; + } + + QSharedPointer grabResult; + if (targetSize.isEmpty()) { + grabResult = target->grabToImage(); + } else { + grabResult = target->grabToImage(targetSize); + } + + QObject::connect( + grabResult.data(), + &QQuickItemGrabResult::ready, + this, + [grabResult, rect, path, this]() { + QThreadPool::globalInstance()->start([grabResult, rect, path, this] { + QImage image = grabResult->image(); + + if (!rect.isEmpty()) { + image = image.copy(rect); + } + + const QString localFile = path.toLocalFile(); + + if (image.save(localFile)) { + emit this->saved(localFile, path); + } else { + emit this->failed(path); + } + }); + } + ); +} diff --git a/src/core/itemimagegrab.hpp b/src/core/itemimagegrab.hpp new file mode 100644 index 00000000..619c2fc7 --- /dev/null +++ b/src/core/itemimagegrab.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include + +/// Allows for saving an item grab to an file asynchronously. +class ItemImageGrab: public QObject { + Q_OBJECT; + QML_ELEMENT; + +public: + explicit ItemImageGrab(QObject* parent = nullptr): QObject(parent) {}; + + Q_INVOKABLE void grab(QQuickItem* target, const QUrl& path); + Q_INVOKABLE void grab(QQuickItem* target, const QUrl& path, const QSize& targetSize); + + Q_INVOKABLE void cropAndGrab(QQuickItem* target, const QUrl& path, const QRect& rect); + Q_INVOKABLE void + cropAndGrab(QQuickItem* target, const QUrl& path, const QRect& rect, const QSize& targetSize); + +signals: + void saved(const QString& file, const QUrl& path); + void failed(const QUrl& path); +}; diff --git a/src/core/module.md b/src/core/module.md index b9404ea9..541733c1 100644 --- a/src/core/module.md +++ b/src/core/module.md @@ -30,5 +30,6 @@ headers = [ "clock.hpp", "scriptmodel.hpp", "colorquantizer.hpp", + "itemimagegrab.hpp", ] -----