From 5db7b4d3a331e9ad67f5c68a0eee2f68abf71c75 Mon Sep 17 00:00:00 2001 From: Daniel Girardeau-Montaut Date: Fri, 30 Oct 2020 18:55:33 +0100 Subject: [PATCH 1/6] Fixing qrc name to match CC default plugin naming ('q' + plugin name) --- CMakeLists.txt | 15 +++++++-------- JsonRPCPlugin.qrc => qJsonRPCPlugin.qrc | 0 2 files changed, 7 insertions(+), 8 deletions(-) rename JsonRPCPlugin.qrc => qJsonRPCPlugin.qrc (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d1bf134..02eb614 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,16 +8,15 @@ if ( PLUGIN_JSONRPC ) AddPlugin( NAME ${PROJECT_NAME} ) - find_package(Qt5 COMPONENTS Network WebSockets REQUIRED) - target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Network Qt5::WebSockets) + find_package(Qt5 COMPONENTS Network WebSockets REQUIRED) + target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Network Qt5::WebSockets) add_subdirectory( include ) add_subdirectory( src ) - target_include_directories( ${PROJECT_NAME} - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ) - # set dependencies to necessary libraries - # target_link_libraries( ${PROJECT_NAME} LIB1 ) + target_include_directories( ${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ) + endif() diff --git a/JsonRPCPlugin.qrc b/qJsonRPCPlugin.qrc similarity index 100% rename from JsonRPCPlugin.qrc rename to qJsonRPCPlugin.qrc From e0307e55557a8cc0fa10afdcf5ce223f822b13d8 Mon Sep 17 00:00:00 2001 From: Daniel Girardeau-Montaut Date: Fri, 30 Oct 2020 19:20:14 +0100 Subject: [PATCH 2/6] Fix plugin name as well --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 02eb614..18d7b62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,10 @@ # CloudCompare Json RPC plugin based on example for standard plugins # Add an option to CMake to control whether we build this plugin or not -option( PLUGIN_JSONRPC "Install Json RPC plugin" ON ) +option( PLUGIN_STANDARD_QJSONRPC "Install Json RPC plugin" ON ) -if ( PLUGIN_JSONRPC ) - project( JsonRPCPlugin ) +if ( PLUGIN_STANDARD_QJSONRPC ) + project( QJSON_RPC_PLUGIN ) AddPlugin( NAME ${PROJECT_NAME} ) From 0c76203c43f2586a648d739d905a7f5e2ece8c0f Mon Sep 17 00:00:00 2001 From: Daniel Girardeau-Montaut Date: Fri, 30 Oct 2020 20:35:42 +0100 Subject: [PATCH 3/6] Syntax update to conform to CC coding standards + compilation with Visual Studio 2017 --- include/JsonRPCPlugin.h | 1 - include/jsonrpcserver.h | 35 ++++++++---- src/JsonRPCPlugin.cpp | 124 +++++++++++++++++----------------------- 3 files changed, 74 insertions(+), 86 deletions(-) diff --git a/include/JsonRPCPlugin.h b/include/JsonRPCPlugin.h index bf9d532..403ac4f 100644 --- a/include/JsonRPCPlugin.h +++ b/include/JsonRPCPlugin.h @@ -54,7 +54,6 @@ public: ~JsonRPCPlugin() override = default; // Inherited from ccStdPluginInterface - void onNewSelection( const ccHObject::Container &selectedEntities ) override; QList getActions() override; public slots: void triggered(bool checked); diff --git a/include/jsonrpcserver.h b/include/jsonrpcserver.h index 5839d6c..c23e36b 100644 --- a/include/jsonrpcserver.h +++ b/include/jsonrpcserver.h @@ -1,24 +1,37 @@ -#ifndef JSONRPCSERVER_H -#define JSONRPCSERVER_H +#pragma once +//Qt #include #include #include #include +//STL #include -#include "ccStdPluginInterface.h" -class JsonRPCResult { -public: - static JsonRPCResult error(int code, QString message) { - JsonRPCResult result = { .isError = true, .error_code = code, .error_message = message }; +struct JsonRPCResult +{ + static JsonRPCResult error(int code, QString message) + { + JsonRPCResult result; + { + result.isError = true; + result.error_code = code; + result.error_message = message; + } return result; } - static JsonRPCResult success(QVariant value) { - JsonRPCResult result = { .isError = false, .result = value }; + + static JsonRPCResult success(QVariant value) + { + JsonRPCResult result; + { + result.isError = false; + result.result = value; + } return result; } - bool isError{true}; + + bool isError{true}; int error_code{-32601}; QString error_message = "Method not found"; QVariant result; @@ -48,5 +61,3 @@ private: QWebSocketServer *ws_server{nullptr}; QList connections; }; - -#endif // JSONRPCSERVER_H diff --git a/src/JsonRPCPlugin.cpp b/src/JsonRPCPlugin.cpp index 395b015..dff7d6b 100644 --- a/src/JsonRPCPlugin.cpp +++ b/src/JsonRPCPlugin.cpp @@ -15,34 +15,21 @@ //# # //########################################################################## -// First: -// Replace all occurrences of 'ExamplePlugin' by your own plugin class name in this file. -// This includes the resource path to info.json in the constructor. - -// Second: -// Open ExamplePlugin.qrc, change the "prefix" and the icon filename for your plugin. -// Change the name of the file to .qrc - -// Third: -// Open the info.json file and fill in the information about the plugin. -// "type" should be one of: "Standard", "GL", or "I/O" (required) -// "name" is the name of the plugin (required) -// "icon" is the Qt resource path to the plugin's icon (from the .qrc file) -// "description" is used as a tootip if the plugin has actions and is displayed in the plugin dialog -// "authors", "maintainers", and "references" show up in the plugin dialog as well - +//Qt #include +//local #include "JsonRPCPlugin.h" -#include "ccGLWindow.h" -#include "ccMainAppInterface.h" -#include "FileIOFilter.h" -#include "ccGenericPointCloud.h" +//qCC_db +#include +//qCC_gl +#include +//qCC_io +#include +//CC plugins +#include -// Default constructor: -// - pass the Qt resource path to the info.json file (from .qrc file) -// - constructor should mainly be used to initialize actions and other members JsonRPCPlugin::JsonRPCPlugin( QObject *parent ) : QObject( parent ) , ccStdPluginInterface( ":/CC/plugin/JsonRPCPlugin/info.json" ) @@ -52,34 +39,6 @@ JsonRPCPlugin::JsonRPCPlugin( QObject *parent ) connect(&rpc_server, &JsonRPCServer::execute, this, &JsonRPCPlugin::execute); } - -// This method should enable or disable your plugin actions -// depending on the currently selected entities ('selectedEntities'). -void JsonRPCPlugin::onNewSelection( const ccHObject::Container &selectedEntities ) -{ - qDebug() << "JsonRPCPlugin::onNewSelection"; - if ( m_action == nullptr ) - { - return; - } - - // If you need to check for a specific type of object, you can use the methods - // in ccHObjectCaster.h or loop and check the objects' classIDs like this: - // - // for ( ccHObject *object : selectedEntities ) - // { - // if ( object->getClassID() == CC_TYPES::VIEWPORT_2D_OBJECT ) - // { - // // ... do something with the viewports - // } - // } - - // For example - only enable our action if something is selected. - m_action->setEnabled(true); -} - -// This method returns all the 'actions' your plugin can perform. -// getActions() will be called only once, when plugin is loaded. QList JsonRPCPlugin::getActions() { qDebug() << "JsonRPCPlugin::getActions"; @@ -87,13 +46,12 @@ QList JsonRPCPlugin::getActions() // default action (if it has not been already created, this is the moment to do it) if ( !m_action ) { - // Here we use the default plugin name, description, and icon, - // but each action should have its own. m_action = new QAction( getName(), this ); m_action->setToolTip( getDescription() ); m_action->setIcon( getIcon() ); m_action->setCheckable(true); m_action->setChecked(false); + m_action->setEnabled(true); // Connect appropriate signal connect( m_action, &QAction::triggered, this, &JsonRPCPlugin::triggered); @@ -106,9 +64,12 @@ void JsonRPCPlugin::triggered(bool checked) { qDebug() << "JsonRPCPlugin::triggered " << checked; - if(checked) { + if (checked) + { rpc_server.listen(6001); - } else { + } + else + { rpc_server.close(); } } @@ -116,17 +77,19 @@ void JsonRPCPlugin::triggered(bool checked) JsonRPCResult JsonRPCPlugin::execute(QString method, QMap params) { qDebug() << method << params; - if(m_app == nullptr) { + if (m_app == nullptr) + { return JsonRPCResult(); } JsonRPCResult result; bool need_redraw = false; - if(method == "open") { + if (method == "open") + { QString filename = params["filename"].toString(); // code copied from MainWindow::addToDB() //to use the same 'global shift' for multiple files - CCVector3d loadCoordinatesShift(0,0,0); + CCVector3d loadCoordinatesShift(0, 0, 0); bool loadCoordinatesTransEnabled = false; FileIOFilter::LoadParameters parameters; @@ -138,36 +101,44 @@ JsonRPCResult JsonRPCPlugin::execute(QString method, QMap par parameters.parentWidget = m_app->getActiveGLWindow(); } - if(params.contains("silent")) { + if(params.contains("silent")) + { parameters.alwaysDisplayLoadDialog = false; } CC_FILE_ERROR res = CC_FERR_NO_ERROR; ccHObject* newGroup = FileIOFilter::LoadFromFile(filename, parameters, res, params["filter"].toString()); - if(newGroup) { + if (newGroup) + { //disable the normals on all loaded clouds! ccHObject::Container clouds; newGroup->filterChildren(clouds, true, CC_TYPES::POINT_CLOUD); - for (ccHObject* cloud : clouds) { - if (cloud) { + for (ccHObject* cloud : clouds) + { + if (cloud) + { static_cast(cloud)->showNormals(false); } } // apply matrix if possible QList transformation = params["transformation"].toList(); - if(transformation.size() == 4*4) { + if (transformation.size() == 4*4) + { std::vector values(4*4); bool success; - for(unsigned i; i < 4*4; ++i) { + for (unsigned i = 0; i < 4 * 4; ++i) + { double d = transformation[i].toDouble(&success); qDebug() << transformation[i].toString() << transformation[i].toDouble(); - if(!success) { - break; + if (!success) + { + break; } - values[((i%4)*4)+(i/4)] = d; + values[((i % 4) * 4) + (i / 4)] = d; } - if(success) { + if (success) + { ccGLMatrix mat = ccGLMatrix(values.data()); qDebug() << "apply matrix: " << mat.toString(); newGroup->setGLTransformation(mat); @@ -177,22 +148,29 @@ JsonRPCResult JsonRPCPlugin::execute(QString method, QMap par m_app->addToDB(newGroup); need_redraw = true; result = JsonRPCResult::success(0); - } else { + } + else + { result = JsonRPCResult::error(1, "cancelled by user"); } - } else if(method == "clear") { + } + else if (method == "clear") + { // remove everything below root auto root = m_app->dbRootObject(); ccHObject* child; - while((child = root->getChild(0)) != nullptr) { + while ((child = root->getChild(0)) != nullptr) + { m_app->removeFromDB(child, true); } need_redraw = true; result = JsonRPCResult::success(0); } - // redraw - if(need_redraw) { + + // redraw + if (need_redraw) + { ccGLWindow* win = m_app->getActiveGLWindow(); if (win) win->redraw(); From 163ff0125361afb6522af29386cca97a04a0e7ce Mon Sep 17 00:00:00 2001 From: Daniel Girardeau-Montaut Date: Sat, 31 Oct 2020 18:34:36 +0100 Subject: [PATCH 4/6] Fixing case issue --- qJsonRPCPlugin.qrc => qJSonRPCPlugin.qrc | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename qJsonRPCPlugin.qrc => qJSonRPCPlugin.qrc (100%) diff --git a/qJsonRPCPlugin.qrc b/qJSonRPCPlugin.qrc similarity index 100% rename from qJsonRPCPlugin.qrc rename to qJSonRPCPlugin.qrc From 34f976da7e41527a01b83d6712eccae43f035f2d Mon Sep 17 00:00:00 2001 From: Daniel Girardeau-Montaut Date: Sat, 31 Oct 2020 19:15:52 +0100 Subject: [PATCH 5/6] Plugins should be OFF by default! --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d7b62..41ab609 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # CloudCompare Json RPC plugin based on example for standard plugins # Add an option to CMake to control whether we build this plugin or not -option( PLUGIN_STANDARD_QJSONRPC "Install Json RPC plugin" ON ) +option( PLUGIN_STANDARD_QJSONRPC "Install Json RPC plugin" OFF ) if ( PLUGIN_STANDARD_QJSONRPC ) project( QJSON_RPC_PLUGIN ) From 513f05ed7e2e330375a2cf9eacdd6c923179f30e Mon Sep 17 00:00:00 2001 From: Daniel Girardeau-Montaut Date: Sat, 31 Oct 2020 20:21:02 +0100 Subject: [PATCH 6/6] Compilation with Qt 5.9 --- src/jsonrpcserver.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/jsonrpcserver.cpp b/src/jsonrpcserver.cpp index bff222c..04fd451 100644 --- a/src/jsonrpcserver.cpp +++ b/src/jsonrpcserver.cpp @@ -73,13 +73,14 @@ void JsonRPCServer::processTextMessage(QString message) return; } QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8()); - auto method = doc["method"].toString(); - auto params = doc["params"].toVariant().toMap(); + QJsonObject obj = doc.object(); + auto method = obj.value("method").toString(); + auto params = obj.value("params").toVariant().toMap(); qDebug() << "method: " << method << ", params: " << params; // check invalid JSON RPC JsonRPCResult result; - if(!method.isEmpty() && !doc["jsonrpc"].toString().isEmpty()) { + if(!method.isEmpty() && !obj.value("jsonrpc").toString().isEmpty()) { // perform the RPC result = emit execute(method, params); } else { @@ -92,7 +93,7 @@ void JsonRPCServer::processTextMessage(QString message) } QJsonObject response; response["jsonrpc"] = "2.0"; - response["id"] = doc["id"]; + response["id"] = obj.value("id"); if(result.isError) { QJsonObject error; error["code"] = result.error_code;