From a38e44f2ea890bf22289a4f550b40ce622fccb8c Mon Sep 17 00:00:00 2001 From: Ralph Wessel Date: Thu, 7 Nov 2024 17:36:39 +0000 Subject: [PATCH] Conversion report log added to send argument Added SendConversionResult --- .../Connector.xcodeproj/project.pbxproj | 2 + .../Connector/ConnectorResource.h | 1 + .../Bridge/Send/Arg/ConversionResult.cpp | 70 ++++++++++++-- .../Bridge/Send/Arg/ConversionResult.h | 91 ++++++++++++++----- .../Bridge/Send/Arg/SendConversionResult.h | 49 ++++++++++ .../Browser/Bridge/Send/Arg/SendError.cpp | 7 +- .../Browser/Bridge/Send/Arg/SendError.h | 4 +- .../Browser/Bridge/Send/Arg/SendObject.cpp | 20 +++- .../Browser/Bridge/Send/Arg/SendObject.h | 18 ++-- .../Bridge/Send/Arg/SendViaBrowserArgs.cpp | 9 +- .../Bridge/Send/Arg/SendViaBrowserArgs.h | 4 +- .../Interface/Browser/Bridge/Send/Send.cpp | 26 +++--- SpeckleLib/Speckle/Environment/Host.cpp | 21 +++++ SpeckleLib/Speckle/Environment/Host.h | 6 ++ SpeckleLib/Speckle/Record/Element/Element.cpp | 2 +- .../Collection/ConversionReporter.cpp | 6 +- .../Serialise/Collection/ConversionReporter.h | 29 ++++-- 17 files changed, 299 insertions(+), 66 deletions(-) create mode 100644 SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendConversionResult.h diff --git a/SpeckleConnector/Connector.xcodeproj/project.pbxproj b/SpeckleConnector/Connector.xcodeproj/project.pbxproj index c3709a9..53b4ff2 100644 --- a/SpeckleConnector/Connector.xcodeproj/project.pbxproj +++ b/SpeckleConnector/Connector.xcodeproj/project.pbxproj @@ -321,6 +321,7 @@ 2199BB522CDA4B1700A4BEEC /* ConnectorProject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConnectorProject.cpp; sourceTree = ""; }; 2199BB532CDA4B1700A4BEEC /* ConnectorProject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConnectorProject.h; sourceTree = ""; }; 2199BB5C2CDA93CE00A4BEEC /* ConnectorImagesFix.grc */ = {isa = PBXFileReference; lastKnownFileType = text; name = ConnectorImagesFix.grc; path = RFIX/ConnectorImagesFix.grc; sourceTree = ""; }; + 2199BB792CDCEA3900A4BEEC /* SendConversionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendConversionResult.h; sourceTree = ""; }; 219F30352C768F0A009834E9 /* Connector-AC27-Test.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Connector-AC27-Test.bundle"; sourceTree = BUILT_PRODUCTS_DIR; }; 219F30402C769282009834E9 /* ConfigTests.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = ConfigTests.cpp; sourceTree = ""; }; 219F30432C7693B6009834E9 /* Connector-AC27-Debug.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Connector-AC27-Debug.xctestplan"; sourceTree = SOURCE_ROOT; }; @@ -1026,6 +1027,7 @@ children = ( 21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */, 21AEF9F82CAC3897000B8681 /* ConversionResult.h */, + 2199BB792CDCEA3900A4BEEC /* SendConversionResult.h */, 21AEF9E32CAB56E5000B8681 /* SendError.cpp */, 21AEF9E42CAB56E5000B8681 /* SendError.h */, 21AEF9EE2CAB5720000B8681 /* SendObject.cpp */, diff --git a/SpeckleConnector/Connector/ConnectorResource.h b/SpeckleConnector/Connector/ConnectorResource.h index dbf6b2c..17e4482 100755 --- a/SpeckleConnector/Connector/ConnectorResource.h +++ b/SpeckleConnector/Connector/ConnectorResource.h @@ -58,6 +58,7 @@ enum ErrorString { modelCardNotFoundID, noProjectOpenID, accountNotFoundID, + elementTypeNotConvertedID, }; #endif //CONNECTOR_RESOURCE diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.cpp index afb3ac2..7566b21 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.cpp @@ -1,5 +1,6 @@ #include "Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h" +#include "Active/Serialise/CargoHold.h" #include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include @@ -12,14 +13,30 @@ namespace { ///Serialisation fields enum FieldIndex { + statusID, + srcID, + srcTypeID, + resID, + resTypeID, errorID, - cardID, }; ///Serialisation field IDs static std::array fieldID = { + Identity{"status"}, + Identity{"sourceId"}, + Identity{"sourceType"}, + Identity{"resultId"}, + Identity{"resultType"}, Identity{"error"}, - Identity{"modelCardId"}, + }; + + ///Conversion status enumerator names + std::array statusName{ + "success", + "warning", + "info", + "error", }; } @@ -35,8 +52,12 @@ bool ConversionResult::fillInventory(active::serialise::Inventory& inventory) co using enum Entry::Type; inventory.merge(Inventory{ { - { fieldID[errorID], errorID, element }, - { fieldID[cardID], cardID, element }, + { fieldID[statusID], statusID, element }, + { fieldID[srcID], srcID, element, !sourceID.empty() }, + { fieldID[srcTypeID], srcTypeID, element, !sourceType.empty() }, + { fieldID[resID], resID, element, !resultID.empty() }, + { fieldID[resTypeID], resTypeID, element, !resultType.empty() }, + { fieldID[errorID], errorID, element, error.operator bool() }, }, }.withType(&typeid(ConversionResult))); return true; @@ -55,11 +76,46 @@ Cargo::Unique ConversionResult::getCargo(const active::serialise::Inventory::Ite return nullptr; using namespace active::serialise; switch (item.index) { + case statusID: + return Cargo::Unique{new CargoHold, uint16_t>(static_cast(status))}; + case srcID: + return std::make_unique>(sourceID); + case srcTypeID: + return std::make_unique>(sourceType); + case resID: + return std::make_unique>(resultID); + case resTypeID: + return std::make_unique>(resultType); case errorID: - return std::make_unique>(message); - case cardID: - return std::make_unique>(modelCardID); + return std::make_unique(*error); default: return nullptr; //Requested an unknown index } } //ConversionResult::getCargo + + +/*-------------------------------------------------------------------- + Get a conversion status enumerator from text + + text; The incoming text + + return: The equivalent conversion status (nullopt on failure) + --------------------------------------------------------------------*/ +std::optional connector::interfac::browser::bridge::toConversionStatus(const String& text) { + for (auto i = 0; i < statusName.size(); ++i) + if (text == statusName[i]) + return static_cast(i + 1); + return std::nullopt; +} //active::geometry::toAnchor2D + + +/*-------------------------------------------------------------------- + Get the text for a conversion status value + + status: The incoming status + + return: The conversion status as text + --------------------------------------------------------------------*/ +String connector::interfac::browser::bridge::fromConversionStatus(ConversionResult::Status status) { + return statusName.at(static_cast(status) - 1); +} //active::geometry::fromAnchor2D diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h index 53146fa..5da3f33 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h @@ -1,47 +1,42 @@ -#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT -#define CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT +#ifndef CONNECTOR_INTERFACE_BRIDGE_CONVERSION_RESULT +#define CONNECTOR_INTERFACE_BRIDGE_CONVERSION_RESULT -#include "Active/Serialise/Package/Wrapper/PackageWrap.h" +#include "Active/Serialise/Package/Package.h" +#include "Active/Serialise/Item/Wrapper/ValueWrap.h" #include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h" #include "Speckle/Utility/String.h" namespace connector::interfac::browser::bridge { /*! - A send error to return to the JS in the event of an error + The result of a conversion process (BIM records to/from Speckle) */ - class ConversionResult final : public active::serialise::Package { + class ConversionResult : public active::serialise::Package { public: - enum class Status { - success = 1, - info, - warning, - error, + enum class Status : uint16_t { + success = 1, /// toConversionStatus(const speckle::utility::String& text); + /*! + Get the text for a conversion status value + @param status The incoming status + @return The conversion status as text + */ + speckle::utility::String fromConversionStatus(ConversionResult::Status status); } -#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT +namespace active::serialise { + + /*! + Import the object from the specified string (specialisation for bool) + @param source The string to read + @return True if the data was successfully read + */ + template<> inline + bool ValueWrap::read(const utility::String& source) { + auto converted = connector::interfac::browser::bridge::toConversionStatus(source); + if (!converted) + return false; + base::get() = *converted; + return true; + } //ValueWrap::read + + + /*! + Import the object from the specified string (specialisation for bool) + @param source The string to read + @return True if the data was successfully read + */ + template<> inline + bool ValueWrap>::read(const utility::String& source) { + auto converted = connector::interfac::browser::bridge::toConversionStatus(source); + base::get() = converted; + return converted.operator bool(); + } //ValueWrap::read + + + /*! + Export the object to the specified string (specialisation for bool) + @param dest The string to write the data to + @return True if the data was successfully written + */ + template<> inline + bool ValueWrap::write(utility::String& dest) const { + dest = connector::interfac::browser::bridge::fromConversionStatus(get()); + return true; + } //ValueWrap::write +} + +#endif //CONNECTOR_INTERFACE_BRIDGE_CONVERSION_RESULT diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendConversionResult.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendConversionResult.h new file mode 100644 index 0000000..c1168c5 --- /dev/null +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendConversionResult.h @@ -0,0 +1,49 @@ +#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT +#define CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT + +#include "Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h" +#include "Speckle/Serialise/Collection/ConversionReporter.h" + +namespace connector::interfac::browser::bridge { + + /*! + A result from converting a record to Speckle + */ + class SendConversionResult : public ConversionResult { + public: + + // MARK: - Constructors + + /*! + Constructor + @param stat The send/conversion status of the target record + @param srcID The record application ID + @param srcType The record application type name + @param err An optional error report + */ + SendConversionResult(Status stat, speckle::utility::String srcID, speckle::utility::String srcType, SendError::Option err = std::nullopt) { + status = stat; + sourceID = srcID; + sourceType = srcType; + error = err; + } + /*! + Constructor + @param stat The send/conversion status of the target record + @param srcID The record application ID + @param srcType The record application type name + @param err An optional error report + */ + SendConversionResult(const speckle::database::BIMRecordID& srcID, const speckle::serialise::ConversionReporter::Data& data) { + status = data.status == speckle::serialise::ConversionReporter::Data::Status::success ? + ConversionResult::Status::success : ConversionResult::Status::error; + sourceID = srcID.operator speckle::utility::String(); + sourceType = data.typeName; + if (!data.message.empty()) + error = SendError{data.message}; + } + }; + +} + +#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.cpp index 0b93763..ef96c41 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.cpp @@ -14,12 +14,14 @@ namespace { enum FieldIndex { errorID, cardID, + stackID, }; ///Serialisation field IDs static std::array fieldID = { Identity{"error"}, Identity{"modelCardId"}, + Identity{"stackTrace"}, }; } @@ -36,7 +38,8 @@ bool SendError::fillInventory(active::serialise::Inventory& inventory) const { inventory.merge(Inventory{ { { fieldID[errorID], errorID, element }, - { fieldID[cardID], cardID, element }, + { fieldID[cardID], cardID, element, !modelCardID.empty() }, + { fieldID[stackID], stackID, element, !stackTrace.empty() }, }, }.withType(&typeid(SendError))); return true; @@ -59,6 +62,8 @@ Cargo::Unique SendError::getCargo(const active::serialise::Inventory::Item& item return std::make_unique>(message); case cardID: return std::make_unique>(modelCardID); + case stackID: + return std::make_unique>(stackTrace); default: return nullptr; //Requested an unknown index } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.h index fd9a1c4..bbc5b2a 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendError.h @@ -24,7 +24,7 @@ namespace connector::interfac::browser::bridge { @param errMess The error message @param card The ID of the model card associated with the wrror */ - SendError(const speckle::utility::String& errMess, const speckle::utility::String& card) : message{errMess}, modelCardID{card} {} + SendError(const speckle::utility::String& errMess, const speckle::utility::String& card = {}) : message{errMess}, modelCardID{card} {} // MARK: - Public variables @@ -32,6 +32,8 @@ namespace connector::interfac::browser::bridge { speckle::utility::String message; ///The ID of the model card associated with the data speckle::utility::String modelCardID; + ///The error stack trace + speckle::utility::String stackTrace; // MARK: - Serialisation diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.cpp index 693b448..ef14dc0 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.cpp @@ -1,12 +1,14 @@ #include "Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h" -#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" #include "Active/Serialise/Item/Wrapper/ValueWrap.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" +#include "Connector/Record/Collection/ProjectCollection.h" #include using namespace active::serialise; using namespace connector::interfac::browser::bridge; +using namespace connector::record; using namespace speckle::serialise; using namespace speckle::utility; @@ -67,3 +69,19 @@ Cargo::Unique SendObject::getCargo(const active::serialise::Inventory::Item& ite return nullptr; //Requested an unknown index } } //SendObject::getCargo + + +/*-------------------------------------------------------------------- + Get the conversion results from the send object serialisation + + return: The serialisation conversion results + --------------------------------------------------------------------*/ +std::vector SendObject::getConversionResults() const { + std::vector convertResults; + auto collection = dynamic_cast(m_object.get()); + if (collection == nullptr) + return convertResults; + for (const auto& item : collection->getLog()) + convertResults.emplace_back(SendConversionResult{item.first, item.second}); + return convertResults; +} //SendObject::getConversionResults diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h index 662b2e3..cc385cc 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h @@ -3,6 +3,7 @@ #include "Active/Serialise/CargoHold.h" #include "Connector/Interface/Browser/Bridge/Config/Arg/ConnectorConfig.h" +#include "Connector/Interface/Browser/Bridge/Send/Arg/SendConversionResult.h" #include "Speckle/Database/Content/Record.h" #include "Speckle/Interface/Browser/Bridge/BridgeMethod.h" @@ -44,15 +45,20 @@ namespace connector::interfac::browser::bridge { */ Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override; /*! - Use a manager in (de)serialisation processes - @param management The management to use - */ + Use a manager in (de)serialisation processes + @param management The management to use + */ void useManagement(active::serialise::Management* management) const override { m_object->useManagement(management); } /*! - Get the cargo management - @return The active management - */ + Get the cargo management + @return The active management + */ active::serialise::Management* management() const override { return m_object->management(); } + /*! + Get the conversion results from the send object serialisation + @return The serialisation conversion results + */ + std::vector getConversionResults() const; private: ///The object to send diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.cpp index 3644285..7b91d43 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.cpp @@ -1,5 +1,6 @@ #include "Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h" +#include "Active/Serialise/Package/Wrapper/ContainerWrap.h" #include "Connector/Record/Model/ModelCard.h" #include "Speckle/Record/Credentials/Account.h" @@ -25,6 +26,7 @@ namespace { accID, messageID, sendObjectID, + convResultID, }; ///Serialisation field IDs @@ -37,6 +39,7 @@ namespace { Identity{"accountId"}, Identity{"message"}, Identity{"sendObject"}, + Identity{"sendConversionResults"}, }; } @@ -47,11 +50,11 @@ namespace { modelCard: The model card to populate into the send info for the browser account: The account linked to the send object: The object to be sent + results: The conversion results (reporting any conversion errors etc) --------------------------------------------------------------------*/ SendViaBrowserArgs::SendViaBrowserArgs(const ModelCard& modelCard, const Account& account, SendObject&& object) : modelCardID(modelCard.getID()), projectID(modelCard.getProjectID()), modelID(modelCard.getModelID()), token{account.getToken()}, serverURL{account.getServerURL()}, accountID{account.getID()}, sendObject{std::move(object)} { - } //SendViaBrowserArgs::SendViaBrowserArgs @@ -74,6 +77,7 @@ bool SendViaBrowserArgs::fillInventory(active::serialise::Inventory& inventory) { fieldID[accID], accID, element }, { fieldID[messageID], messageID, element }, { fieldID[sendObjectID], sendObjectID, element }, + { fieldID[convResultID], convResultID, element }, }, }.withType(&typeid(SendViaBrowserArgs))); return true; @@ -108,6 +112,9 @@ Cargo::Unique SendViaBrowserArgs::getCargo(const active::serialise::Inventory::I return std::make_unique(message); case sendObjectID: return std::make_unique(sendObject); + case convResultID: + sendConversionResults = sendObject.getConversionResults(); + return Cargo::Unique{new ContainerWrap{sendConversionResults}}; default: return nullptr; //Requested an unknown index } diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h index 71cef33..e0ea188 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h @@ -3,7 +3,7 @@ #include "Active/Serialise/Package/Package.h" #include "Active/Utility/String.h" -#include "Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h" +#include "Connector/Interface/Browser/Bridge/Send/Arg/SendConversionResult.h" #include "Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h" #include "Speckle/Database/Identity/RecordID.h" @@ -54,7 +54,7 @@ namespace connector::interfac::browser::bridge { ///The send message speckle::utility::String message; //TODO: Clarify what this is used for ///The conversion report (summarising the conversion results on an element-by-element basis) - std::vector sendConversionResults; + mutable std::vector sendConversionResults; ///The commit content SendObject sendObject; diff --git a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp index 9d6d407..e817a20 100644 --- a/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp +++ b/SpeckleConnector/Connector/Interface/Browser/Bridge/Send/Send.cpp @@ -6,27 +6,29 @@ #include "Connector/ConnectorResource.h" #include "Connector/Database/ModelCardDatabase.h" #include "Connector/Environment/ConnectorProject.h" -#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h" +#include "Connector/Interface/Browser/Bridge/Send/Arg/SendConversionResult.h" #include "Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h" #include "Connector/Record/Collection/ProjectCollection.h" #include "Connector/Record/Model/SenderModelCard.h" #include "Connector/Record/Model/Filter/SendFilter.h" #include "Speckle/Database/AccountDatabase.h" +#include "Speckle/Database/BIMElementDatabase.h" #include "Speckle/Database/Content/BIMRecord.h" +#include "Speckle/Environment/Project.h" +#include "Speckle/Environment/Host.h" #include "Speckle/Interface/Browser/Bridge/BrowserBridge.h" #include "Speckle/Record/Credentials/Account.h" +#include "Speckle/Record/Element/Element.h" #include "Speckle/Serialise/Detached/Storage/DetachedMemoryStore.h" #include "Speckle/Utility/Exception.h" -#include "Speckle/Database/BIMElementDatabase.h" -#include "Speckle/Environment/Project.h" -#include "Speckle/Record/Element/Element.h" -using namespace speckle::record::element; using namespace active::serialise; using namespace connector::environment; using namespace connector::interfac::browser::bridge; using namespace connector::record; using namespace speckle::database; +using namespace speckle::environment; +using namespace speckle::record::element; using namespace speckle::serialise; using namespace speckle::utility; @@ -44,13 +46,8 @@ Send::Send() : BridgeMethod{"Send", [&](const SendArgs& args) { modelCardID: The ID of the model card identifying the objects to send --------------------------------------------------------------------*/ void Send::run(const String& modelCardID) const { - -#ifdef ARCHICAD - // we currently rely on the ModelerAPI instead of the ModelAccessAPI - // we have to open a 3D window to get the Mesh data of the model elements - ACAPI_View_ShowAllIn3D(); -#endif - + //We can currently only send from the 3D model view + host()->makeModelViewActive(true); //Get the active project auto project = connector()->getActiveProject().lock(); if (!project) { @@ -89,8 +86,9 @@ void Send::run(const String& modelCardID) const { if (auto element = elementDatabase->getElement(link); element) collection->addElement(*element); else { - //Report these elements as failures for the report - collection->logRecord(link, ConversionReporter::Outcome::failure, false); + //Report failure to convert element + collection->logRecord(link, {ConversionReporter::Data::Status::failure, element->getTypeName(), element->getSpeckleType(), + connector()->getLocalString(errorString, elementTypeNotConvertedID)}, false); collection->incrementSkippedRecords(); } } diff --git a/SpeckleLib/Speckle/Environment/Host.cpp b/SpeckleLib/Speckle/Environment/Host.cpp index a3be8af..b4c2087 100644 --- a/SpeckleLib/Speckle/Environment/Host.cpp +++ b/SpeckleLib/Speckle/Environment/Host.cpp @@ -1,4 +1,5 @@ #include "Speckle/Environment/Host.h" +#include "Active/Utility/Memory.h" #ifdef ARCHICAD #include "DG.h" @@ -21,6 +22,26 @@ Host::Host() { } //Host::Host +/*-------------------------------------------------------------------- + Switch to the model view + + isSelectionOnly: True to display just the selected elements + + return: True if the model view is active + --------------------------------------------------------------------*/ +bool Host::makeModelViewActive(bool isSelectionOnly) const { +#ifdef ARCHICAD + API_WindowInfo windowInfo; + active::utility::Memory::erase(windowInfo); + if ((ACAPI_Window_GetCurrentWindow(&windowInfo) == NoError) && (windowInfo.typeID == APIWind_3DModelID)) + return true; + if (isSelectionOnly) + return (ACAPI_View_ShowSelectionIn3D() == NoError); + return (ACAPI_View_ShowAllIn3D() == NoError); +#endif +} //Host::makeModelViewActive + + /*-------------------------------------------------------------------- Display an alert dialog diff --git a/SpeckleLib/Speckle/Environment/Host.h b/SpeckleLib/Speckle/Environment/Host.h index bf355f9..8cb1712 100644 --- a/SpeckleLib/Speckle/Environment/Host.h +++ b/SpeckleLib/Speckle/Environment/Host.h @@ -20,6 +20,12 @@ namespace speckle::environment { // MARK: Functions (const) + /*! + Switch to the model view + @param isSelectionOnly True to display just the selected elements + @return True if the model view is active + */ + bool makeModelViewActive(bool isSelectionOnly = false) const; /*! Display an alert dialog @param message The alert message diff --git a/SpeckleLib/Speckle/Record/Element/Element.cpp b/SpeckleLib/Speckle/Record/Element/Element.cpp index 5a42037..ce22ad6 100644 --- a/SpeckleLib/Speckle/Record/Element/Element.cpp +++ b/SpeckleLib/Speckle/Record/Element/Element.cpp @@ -264,7 +264,7 @@ void Element::useManagement(Management* management) const { if (management != nullptr) { //If a conversion report is collected, add this record to the report (also updates progress display in the UI) if (auto reporter = management->get(); reporter != nullptr) - reporter->logRecord(getBIMID()); + reporter->logRecord(getBIMID(), {ConversionReporter::Data::Status::success, getTypeName(), getSpeckleType()}); } } //Element::useManagement diff --git a/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.cpp b/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.cpp index b49a2ae..a41ed5a 100644 --- a/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.cpp +++ b/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.cpp @@ -19,12 +19,12 @@ ConversionReporter::~ConversionReporter() {} Log the conversion/serialisation of a record recordID: The ID of the serialised record - outcome: The record serialisation outcome + @param data The record serialisation report data withUIFeedback: True if the UI progress feedback should be updated return: True if the serialisation should continue --------------------------------------------------------------------*/ -bool ConversionReporter::logRecord(const BIMRecordID& recordID, Outcome outcome, bool withUIFeedback) { +bool ConversionReporter::logRecord(const BIMRecordID& recordID, const Data& data, bool withUIFeedback) { //Initialise the progress UI component as required if (withUIFeedback && !m_progress) { if (m_progress = Progress::getInstance(addon()->getLocalString(titleStringLib, conversionProgressID)); m_progress) { @@ -35,7 +35,7 @@ bool ConversionReporter::logRecord(const BIMRecordID& recordID, Outcome outcome, } } //Log the conversion outcome for the record - m_log[recordID] = outcome; + m_log[recordID] = data; //Update the progress UI component if (withUIFeedback && m_progress) { ++(*m_progress); diff --git a/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.h b/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.h index 0cef9d1..921c7f6 100644 --- a/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.h +++ b/SpeckleLib/Speckle/Serialise/Collection/ConversionReporter.h @@ -16,13 +16,26 @@ namespace speckle::serialise { class ConversionReporter : public virtual active::serialise::Manager { public: - ///Record conversion status - enum class Outcome { - success, - failure, + ///Data collected from the conversion of a record + struct Data { + ///Record conversion status + enum class Status { + success, + failure, + }; + + ///The conversion status + Status status; + ///The name of the record type + utility::String typeName; + ///The name of the record type + utility::String speckleType; + ///Optional message from the conversion (particularly relevant when an error occurs) + utility::String message; }; + ///Reporter log pairing a record ID with the outcome of its conversion - using Log = std::unordered_map; + using Log = std::unordered_map; // MARK: Constructors @@ -55,11 +68,11 @@ namespace speckle::serialise { /*! Log the conversion/serialisation of a record @param recordID The ID of the serialised record - @param outcome The record serialisation outcome - @param withUIFeedback True if the UI progress feedback should be updated + @param data The record serialisation report data + @param withUIFeedback True if the UI progress feedback should be updated @return True if the serialisation should continue */ - bool logRecord(const speckle::database::BIMRecordID& recordID, Outcome outcome = Outcome::success, bool withUIFeedback = true); + bool logRecord(const speckle::database::BIMRecordID& recordID, const Data& data = {Data::Status::success}, bool withUIFeedback = true); private: ///The reporter log