Skip to content

Commit

Permalink
Add ScreenshotRemote Function this create a screenshot like the norma…
Browse files Browse the repository at this point in the history
…l screenshot, except that it outputs the image as Base64 String
  • Loading branch information
Sebastian Feustel committed Mar 12, 2024
1 parent 1508416 commit 1df3ace
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ set(SOURCES
src/Commands/Quit.h
src/Commands/Screenshot.cpp
src/Commands/Screenshot.h
src/Commands/ScreenshotRemote.cpp
src/Commands/ScreenshotRemote.h
src/Commands/SetProperty.cpp
src/Commands/SetProperty.h
src/Commands/Wait.cpp
Expand Down
1 change: 1 addition & 0 deletions lib/include/Spix/TestServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class SPIX_EXPORT TestServer {
std::vector<std::string> getErrors();

void takeScreenshot(ItemPath targetItem, std::string filePath);
std::string takeScreenshotRemote(ItemPath targetItem);
void quit();

protected:
Expand Down
4 changes: 4 additions & 0 deletions lib/src/AnyRpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ AnyRpcServer::AnyRpcServer(int anyrpcPort)
return takeScreenshot(std::move(targetItem), std::move(filePath));
});

utils::AddFunctionToAnyRpc<std::string(std::string)>(methodManager, "takeScreenshotRemote",
"Take a screenshot of the object and send as base64 string | takeScreenshotRemote(string pathToTargetedItem)",
[this](std::string targetItem) { return takeScreenshotRemote(std::move(targetItem)); });

utils::AddFunctionToAnyRpc<void()>(methodManager, "quit", "Close the app | quit()", [this] { quit(); });

utils::AddFunctionToAnyRpc<void(std::string, std::string)>(methodManager, "command",
Expand Down
26 changes: 26 additions & 0 deletions lib/src/Commands/ScreenshotRemote.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/***
* Copyright (C) Falko Axmann. All rights reserved.
* Licensed under the MIT license.
* See LICENSE.txt file in the project root for full license information.
****/

#include "ScreenshotRemote.h"

#include <Scene/Scene.h>
namespace spix {
namespace cmd {

ScreenshotRemote::ScreenshotRemote(ItemPath targetItemPath, std::promise<std::string> promise)
: m_itemPath {std::move(targetItemPath)}
, m_promise(std::move(promise))
{
}

void ScreenshotRemote::execute(CommandEnvironment& env)
{
auto value = env.scene().takeScreenshotRemote(m_itemPath);
m_promise.set_value(value);
}

} // namespace cmd
} // namespace spix
23 changes: 23 additions & 0 deletions lib/src/Commands/ScreenshotRemote.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "Command.h"
#include <Spix/Data/ItemPath.h>

#include <future>

namespace spix {
namespace cmd {

class ScreenshotRemote : public Command {
public:
ScreenshotRemote(ItemPath targetItemPath, std::promise<std::string> promise);

void execute(CommandEnvironment& env) override;

private:
ItemPath m_itemPath;
std::promise<std::string> m_promise;
};

} // namespace cmd
} // namespace spix
5 changes: 5 additions & 0 deletions lib/src/Scene/Mock/MockScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ void MockScene::takeScreenshot(const ItemPath&, const std::string&)
{
}

std::string MockScene::takeScreenshotRemote(const ItemPath&)
{
return "Base64 String";
}

void MockScene::addItemAtPath(MockItem item, const ItemPath& path)
{
m_items.emplace(std::make_pair(path.string(), std::move(item)));
Expand Down
2 changes: 1 addition & 1 deletion lib/src/Scene/Mock/MockScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class SPIX_EXPORT MockScene : public Scene {

// Tasks
void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) override;

std::string takeScreenshotRemote(const ItemPath& targetItem);
// Mock stuff
void addItemAtPath(MockItem item, const ItemPath& path);
MockEvents& mockEvents();
Expand Down
30 changes: 30 additions & 0 deletions lib/src/Scene/Qt/QtScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <Scene/Qt/QtItemTools.h>
#include <Spix/Data/ItemPath.h>

#include <QBuffer>
#include <QByteArray>
#include <QGuiApplication>
#include <QObject>
#include <QQuickItem>
Expand Down Expand Up @@ -139,4 +141,32 @@ void QtScene::takeScreenshot(const ItemPath& targetItem, const std::string& file
image.save(QString::fromStdString(filePath));
}

std::string QtScene::takeScreenshotRemote(const ItemPath& targetItem)
{
auto item = getQQuickItemAtPath(targetItem);
if (!item) {
return "";
}

// take screenshot of the full window
auto windowImage = item->window()->grabWindow();

// get the rect of the item in window space in pixels, account for the device pixel ratio
QRectF imageCropRectItemSpace {0, 0, item->width(), item->height()};
auto imageCropRectF = item->mapRectToScene(imageCropRectItemSpace);
QRect imageCropRect(imageCropRectF.x() * windowImage.devicePixelRatio(),
imageCropRectF.y() * windowImage.devicePixelRatio(), imageCropRectF.width() * windowImage.devicePixelRatio(),
imageCropRectF.height() * windowImage.devicePixelRatio());

// crop the window image to the item rect
auto image = windowImage.copy(imageCropRect);
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
buffer.close();

return byteArray.toBase64().toStdString();
}

} // namespace spix
2 changes: 2 additions & 0 deletions lib/src/Scene/Qt/QtScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include <QByteArray>
#include <Scene/Qt/QtEvents.h>
#include <Scene/Scene.h>

Expand All @@ -28,6 +29,7 @@ class QtScene : public Scene {

// Tasks
void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) override;
std::string takeScreenshotRemote(const ItemPath& targetItem);

private:
QtEvents m_events;
Expand Down
1 change: 1 addition & 0 deletions lib/src/Scene/Scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Scene {

// Tasks
virtual void takeScreenshot(const ItemPath& targetItem, const std::string& filePath) = 0;
virtual std::string takeScreenshotRemote(const ItemPath& targetItem) = 0;
};

} // namespace spix
11 changes: 11 additions & 0 deletions lib/src/TestServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <Commands/InvokeMethod.h>
#include <Commands/Quit.h>
#include <Commands/Screenshot.h>
#include <Commands/ScreenshotRemote.h>
#include <Commands/SetProperty.h>
#include <Commands/Wait.h>

Expand Down Expand Up @@ -165,6 +166,16 @@ void TestServer::takeScreenshot(ItemPath targetItem, std::string filePath)
m_cmdExec->enqueueCommand<cmd::Screenshot>(targetItem, std::move(filePath));
}

std::string TestServer::takeScreenshotRemote(ItemPath targetItem)
{
std::promise<std::string> promise;
auto result = promise.get_future();
auto cmd = std::make_unique<cmd::ScreenshotRemote>(targetItem, std::move(promise));
m_cmdExec->enqueueCommand(std::move(cmd));

return result.get();
}

void TestServer::quit()
{
m_cmdExec->enqueueCommand<cmd::Quit>();
Expand Down

0 comments on commit 1df3ace

Please sign in to comment.