Skip to content

Commit

Permalink
DRAFT: add the ability to invoke QML functions
Browse files Browse the repository at this point in the history
  • Loading branch information
prototypicalpro committed Apr 26, 2022
1 parent 368793a commit b94d74c
Show file tree
Hide file tree
Showing 28 changed files with 755 additions and 179 deletions.
13 changes: 8 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ jobs:
matrix:
os: [ubuntu-latest, ubuntu-20.04, windows-latest, macos-latest, macos-10.15]
build_type: ['Release', 'Debug']
shared_libs: ['ON', 'OFF']
qt_version: [[5, 12, 12], [5, 15, 2], [6, 2, 3]]
shared_libs: ['ON', 'OFF']
tests: ['ON', 'OFF']
include:
- os: ubuntu-latest
triplet: 'x64-linux'
Expand All @@ -35,9 +36,11 @@ jobs:
triplet: 'x64-osx'
cmake_flags: ''
exclude:
# Disabled until https://github.com/sgieseking/anyrpc/pull/43 is in place
- os: windows-latest
shared_libs: 'ON'
# tests won't build with shared libs due to private symbols
- shared_libs: 'ON'
tests: 'ON'
- shared_libs: 'OFF'
tests: 'OFF'
steps:
- name: Check out repository code
uses: actions/checkout@v2
Expand Down Expand Up @@ -65,7 +68,7 @@ jobs:
- name: "Configure"
run: |
mkdir build
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DSPIX_BUILD_TESTS=ON -DSPIX_BUILD_EXAMPLES=ON ${{ matrix.cmake_flags}} -DBUILD_SHARED_LIBS=${{ matrix.shared_libs }} -DSPIX_QT_MAJOR=${{ matrix.qt_version[0] }} .
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DSPIX_BUILD_TESTS=${{ matrix.tests }} -DSPIX_BUILD_EXAMPLES=ON ${{ matrix.cmake_flags }} -DBUILD_SHARED_LIBS=${{ matrix.shared_libs }} -DSPIX_QT_MAJOR=${{ matrix.qt_version[0] }} .
- name: "Print cmake compile commands"
if: ${{ !contains(matrix.os, 'windows') }}
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ option(SPIX_BUILD_TESTS "Build Spix unit tests." OFF)
set(SPIX_QT_MAJOR "6" CACHE STRING "Major Qt version to build Spix against")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)

# Hide symbols unless explicitly flagged with SPIX_EXPORT
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
Expand Down
2 changes: 1 addition & 1 deletion examples/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt${SPIX_QT_MAJOR} COMPONENTS Core Quick REQUIRED)
Expand Down
2 changes: 1 addition & 1 deletion examples/BasicStandalone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../../cmake/modules")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

#
Expand Down
2 changes: 1 addition & 1 deletion examples/GTest/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(SPIX_QT_MAJOR "6" CACHE STRING "Major Qt version to build Spix against")
Expand Down
2 changes: 1 addition & 1 deletion examples/ListGridView/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(SPIX_QT_MAJOR "6" CACHE STRING "Major Qt version to build Spix against")
Expand Down
2 changes: 1 addition & 1 deletion examples/RemoteCtrl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(SPIX_QT_MAJOR "6" CACHE STRING "Major Qt version to build Spix against")
Expand Down
2 changes: 1 addition & 1 deletion examples/RepeaterLoader/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(SPIX_QT_MAJOR "6" CACHE STRING "Major Qt version to build Spix against")
Expand Down
6 changes: 5 additions & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ set(SOURCES
src/Commands/GetTestStatus.h
src/Commands/InputText.cpp
src/Commands/InputText.h
src/Commands/InvokeMethod.cpp
src/Commands/InvokeMethod.h
src/Commands/Quit.cpp
src/Commands/Quit.h
src/Commands/Screenshot.cpp
Expand Down Expand Up @@ -92,8 +94,10 @@ set(SOURCES
src/Scene/Qt/QtScene.cpp
src/Scene/Qt/QtScene.h
src/Scene/Scene.h


src/Utils/AnyRpcUtils.cpp
src/Utils/AnyRpcUtils.h
src/Utils/AnyRpcFunction.h
src/Utils/DebugDump.cpp
src/Utils/DebugDump.h
src/Utils/QtEventRecorder.cpp
Expand Down
55 changes: 55 additions & 0 deletions lib/include/Spix/Data/Variant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/***
* Copyright (C) Noah Koontz. All rights reserved.
* Licensed under the MIT license.
* See LICENSE.txt file in the project root for full license information.
****/

#pragma once

#include <chrono>
#include <map>
#include <string>
#include <variant>
#include <vector>

#include <Spix/spix_export.h>

namespace spix {

struct Variant;

namespace {
using VariantBaseType = std::variant<std::nullptr_t, bool, int64_t, uint64_t, double, std::string,
std::chrono::time_point<std::chrono::system_clock>, std::vector<Variant>, std::map<std::string, Variant>>;
}

// TODO: make this a block comment
// NOTE: std::visit is broken for this variant for GCC <= 11.2 and clang <= 14.0 . See
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2162r0.html for more info.
struct SPIX_EXPORT Variant : VariantBaseType {
using ListType = std::vector<Variant>;
using MapType = std::map<std::string, Variant>;
using VariantType = VariantBaseType;
using VariantBaseType::variant;
VariantBaseType const& base() const { return *this; }
VariantBaseType& base() { return *this; }

enum TypeIndex
{
Nullptr = 0,
Bool,
Int64,
Uint64,
Double,
String,
Time,
List,
Map,
TypeIndexCount
};
};

static_assert(
Variant::TypeIndexCount == std::variant_size_v<VariantBaseType>, "Variant enum does not cover all Variant types");

} // namespace spix
2 changes: 2 additions & 0 deletions lib/include/Spix/TestServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <Spix/Data/Geometry.h>
#include <Spix/Data/ItemPath.h>
#include <Spix/Data/Variant.h>
#include <Spix/Events/Identifiers.h>

#include <Spix/spix_export.h>
Expand Down Expand Up @@ -57,6 +58,7 @@ class SPIX_EXPORT TestServer {

std::string getStringProperty(ItemPath path, std::string propertyName);
void setStringProperty(ItemPath path, std::string propertyName, std::string propertyValue);
Variant invokeMethod(ItemPath path, std::string method, std::vector<Variant> args);
Rect getBoundingBox(ItemPath path);
bool existsAndVisible(ItemPath path);
std::vector<std::string> getErrors();
Expand Down
10 changes: 8 additions & 2 deletions lib/src/AnyRpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
****/

#include <Spix/AnyRpcServer.h>
#include <Utils/AnyRpcUtils.h>
#include <anyrpc/anyrpc.h>
#include <Spix/Data/Variant.h>
#include <Utils/AnyRpcFunction.h>
#include <atomic>

namespace spix {
Expand Down Expand Up @@ -70,6 +70,12 @@ AnyRpcServer::AnyRpcServer(int anyrpcPort)
setStringProperty(std::move(path), std::move(property), std::move(value));
});

utils::AddFunctionToAnyRpc<Variant(std::string, std::string, std::vector<Variant>)>(methodManager, "invokeMethod",
"Invoke a method on a QML object | invokeMethod(string path, string method, any[] args)",
[this](std::string path, std::string method, std::vector<Variant> args) {
return invokeMethod(std::move(path), std::move(method), std::move(args));
});

utils::AddFunctionToAnyRpc<std::vector<double>(std::string)>(methodManager, "getBoundingBox",
"Return the bounding box of an item in screen coordinates | getBoundingBox(string path) : (doubles) "
"[topLeft.x, topLeft.y , width, height]",
Expand Down
39 changes: 39 additions & 0 deletions lib/src/Commands/InvokeMethod.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/***
* 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 "InvokeMethod.h"

#include <Scene/Scene.h>

namespace spix {
namespace cmd {

InvokeMethod::InvokeMethod(ItemPath path, std::string method, std::vector<Variant> args, std::promise<Variant> promise)
: m_path(std::move(path))
, m_method(std::move(method))
, m_args(std::move(args))
, m_promise(std::move(promise))
{
}

void InvokeMethod::execute(CommandEnvironment& env)
{
auto item = env.scene().itemAtPath(m_path);

if (item) {
Variant ret;
bool success = item->invokeMethod(m_method, m_args, ret);
if (!success)
env.state().reportError("InvokeMethod: Failed to invoke method: " + m_method);
m_promise.set_value(ret);
} else {
env.state().reportError("InvokeMethod: Item not found: " + m_path.string());
m_promise.set_value(Variant(nullptr));
}
}

} // namespace cmd
} // namespace spix
34 changes: 34 additions & 0 deletions lib/src/Commands/InvokeMethod.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/***
* Copyright (C) Falko Axmann. All rights reserved.
* Licensed under the MIT license.
* See LICENSE.txt file in the project root for full license information.
****/

#pragma once

#include <Spix/spix_export.h>

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

#include <future>

namespace spix {
namespace cmd {

class SPIX_EXPORT InvokeMethod : public Command {
public:
InvokeMethod(ItemPath path, std::string method, std::vector<Variant> args, std::promise<Variant> promise);

void execute(CommandEnvironment& env) override;

private:
ItemPath m_path;
std::string m_method;
std::vector<Variant> m_args;
std::promise<Variant> m_promise;
};

} // namespace cmd
} // namespace spix
2 changes: 2 additions & 0 deletions lib/src/QtQmlBot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Spix/QtQmlBot.h>

#include <CommandExecuter/CommandExecuter.h>
#include <QtDebug>
#include <Scene/Qt/QtScene.h>
#include <Spix/TestServer.h>

Expand All @@ -24,6 +25,7 @@ QtQmlBot::~QtQmlBot() = default;

void QtQmlBot::runTestServer(TestServer& server)
{
qInfo() << "Spix server is enabled. Only use this in a safe environment.";
server.setCommandExecuter(m_cmdExec.get());
server.start();
}
Expand Down
2 changes: 2 additions & 0 deletions lib/src/Scene/Item.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include <Spix/Data/Geometry.h>
#include <Spix/Data/Variant.h>

#include <string>

Expand All @@ -29,6 +30,7 @@ class Item {
virtual Rect bounds() const = 0;
virtual std::string stringProperty(const std::string& name) const = 0;
virtual void setStringProperty(const std::string& name, const std::string& value) = 0;
virtual bool invokeMethod(const std::string& method, const std::vector<Variant>& args, Variant& ret) = 0;
virtual bool visible() const = 0;
};

Expand Down
6 changes: 6 additions & 0 deletions lib/src/Scene/Mock/MockItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ void MockItem::setStringProperty(const std::string& name, const std::string& val
{
}

bool MockItem::invokeMethod(const std::string& method, const std::vector<Variant>& args, Variant& ret)
{
ret = Variant(nullptr);
return true;
}

bool MockItem::visible() const
{
return true;
Expand Down
3 changes: 1 addition & 2 deletions lib/src/Scene/Mock/MockItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

#include <Scene/Item.h>

#include <map>

namespace spix {

class SPIX_EXPORT MockItem : public Item {
Expand All @@ -24,6 +22,7 @@ class SPIX_EXPORT MockItem : public Item {
Rect bounds() const override;
std::string stringProperty(const std::string& name) const override;
void setStringProperty(const std::string& name, const std::string& value) override;
bool invokeMethod(const std::string& method, const std::vector<Variant>& args, Variant& ret) override;
bool visible() const override;

// MockItem specials
Expand Down
Loading

0 comments on commit b94d74c

Please sign in to comment.