Merge branch 'release/0.2.3'

This commit is contained in:
Ralph Wessel
2024-09-17 13:09:24 +01:00
73 changed files with 3534 additions and 246 deletions
+3 -1
View File
@@ -21,4 +21,6 @@ CMakeFiles/
XCBuildData/
**/*.xcsettings
*.log
.idea
.idea
*.mui
*.aps
+29 -4
View File
@@ -93,9 +93,10 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="Connector\Connector.cpp" />
<ClCompile Include="Connector\Database\Model\Card\ModelCardDatabase.cpp" />
<ClCompile Include="Connector\Database\ModelCardDatabase.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Account\AccountBridge.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Account\GetAccounts.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\AddModel.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\Arg\DocumentInfo.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\BaseBridge.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetConnectorVersion.cpp" />
@@ -103,12 +104,13 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetDocumentState.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationName.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationVersion.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\RemoveModel.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\Arg\ConnectorConfig.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\ConfigBridge.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\GetConfig.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\GetIsDevMode.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\UpdateConfig.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendFilter.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\GetSendFilters.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Send.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\SendBridge.cpp" />
@@ -120,14 +122,25 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Test\TriggerEvent.cpp" />
<ClCompile Include="Connector\Interface\ConnectorMenu.cpp" />
<ClCompile Include="Connector\Interface\ConnectorPalette.cpp" />
<ClCompile Include="Connector\Record\Model\CardMover.cpp" />
<ClCompile Include="Connector\Record\Model\CardSetting.cpp" />
<ClCompile Include="Connector\Record\Model\Filter\DirectSelectionSendFilter.cpp" />
<ClCompile Include="Connector\Record\Model\Filter\EverythingSendFilter.cpp" />
<ClCompile Include="Connector\Record\Model\Filter\FilterMover.cpp" />
<ClCompile Include="Connector\Record\Model\Filter\SendFilter.cpp" />
<ClCompile Include="Connector\Record\Model\ModelCard.cpp" />
<ClCompile Include="Connector\Record\Model\ReceiverModelCard.cpp" />
<ClCompile Include="Connector\Record\Model\SenderModelCard.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Connector\Connector.h" />
<ClInclude Include="Connector\ConnectorResource.h" />
<ClInclude Include="Connector\Database\Model\Card\ModelCardDatabase.h" />
<ClInclude Include="Connector\Database\Identity\RecordID.h" />
<ClInclude Include="Connector\Database\ModelCardDatabase.h" />
<ClInclude Include="Connector\Event\ConnectorEventID.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Account\AccountBridge.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Account\GetAccounts.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\AddModel.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\Arg\DocumentInfo.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\BaseBridge.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\GetConnectorVersion.h" />
@@ -135,12 +148,13 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\GetDocumentState.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationName.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationVersion.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\RemoveModel.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\Arg\ConnectorConfig.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\ConfigBridge.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\GetConfig.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\GetIsDevMode.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\UpdateConfig.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendFilter.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\GetSendFilters.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Send.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\SendBridge.h" />
@@ -152,6 +166,17 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Test\TriggerEvent.h" />
<ClInclude Include="Connector\Interface\ConnectorMenu.h" />
<ClInclude Include="Connector\Interface\ConnectorPalette.h" />
<ClInclude Include="Connector\Record\Model\CardMover.h" />
<ClInclude Include="Connector\Record\Model\CardSetting.h" />
<ClInclude Include="Connector\Record\Model\Filter\ArchicadEverythingFilter.h" />
<ClInclude Include="Connector\Record\Model\Filter\ArchicadSelectionFilter.h" />
<ClInclude Include="Connector\Record\Model\Filter\DirectSelectionSendFilter.h" />
<ClInclude Include="Connector\Record\Model\Filter\EverythingSendFilter.h" />
<ClInclude Include="Connector\Record\Model\Filter\FilterMover.h" />
<ClInclude Include="Connector\Record\Model\Filter\SendFilter.h" />
<ClInclude Include="Connector\Record\Model\ModelCard.h" />
<ClInclude Include="Connector\Record\Model\ReceiverModelCard.h" />
<ClInclude Include="Connector\Record\Model\SenderModelCard.h" />
<ClInclude Include="Connector\Version.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
+96 -18
View File
@@ -32,12 +32,6 @@
<Filter Include="Connector\Database">
<UniqueIdentifier>{2f459f56-86f0-4794-b4b7-1bd7b8ee5617}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Database\Model">
<UniqueIdentifier>{2820ad4f-60d9-436e-a7a2-d019d7e0ce0c}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Database\Model\Card">
<UniqueIdentifier>{85935d00-16ac-466a-a614-ad9ea802bffa}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Interface\Browser\Bridge\Config\Arg">
<UniqueIdentifier>{6a2f1f18-a554-4546-bba3-314d5f2ec9f9}</UniqueIdentifier>
</Filter>
@@ -53,8 +47,17 @@
<Filter Include="Connector\Interface\Browser\Bridge\Send">
<UniqueIdentifier>{2b87cf11-87cd-435f-ab24-42170c2e657e}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Interface\Browser\Bridge\Send\Arg">
<UniqueIdentifier>{3bc97363-0091-4f84-a5f7-085193bad850}</UniqueIdentifier>
<Filter Include="Connector\Database\Identity">
<UniqueIdentifier>{41395ee2-50f3-49c0-8859-23a3ad19a2fa}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Record">
<UniqueIdentifier>{a915e7ee-849f-48a9-aa7b-0ef6e358bee7}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Record\Model">
<UniqueIdentifier>{2b16c188-1d80-4d4d-830e-5c1e56ecf46e}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Record\Model\Filter">
<UniqueIdentifier>{b6d6326c-77f4-414a-bda6-e3e587c7ded2}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
@@ -122,9 +125,6 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\GetSourceApplicationVersion.cpp">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClCompile>
<ClCompile Include="Connector\Database\Model\Card\ModelCardDatabase.cpp">
<Filter>Connector\Database\Model\Card</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\Arg\ConnectorConfig.cpp">
<Filter>Connector\Interface\Browser\Bridge\Config\Arg</Filter>
</ClCompile>
@@ -159,8 +159,44 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\GetSendFilters.cpp">
<Filter>Connector\Interface\Browser\Bridge\Send</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendFilter.cpp">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
<ClCompile Include="Connector\Database\ModelCardDatabase.cpp">
<Filter>Connector\Database</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\CardMover.cpp">
<Filter>Connector\Record\Model</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\CardSetting.cpp">
<Filter>Connector\Record\Model</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\ModelCard.cpp">
<Filter>Connector\Record\Model</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\ReceiverModelCard.cpp">
<Filter>Connector\Record\Model</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\SenderModelCard.cpp">
<Filter>Connector\Record\Model</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\Filter\DirectSelectionSendFilter.cpp">
<Filter>Connector\Record\Model\Filter</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\Filter\EverythingSendFilter.cpp">
<Filter>Connector\Record\Model\Filter</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\Filter\FilterMover.cpp">
<Filter>Connector\Record\Model\Filter</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Model\Filter\SendFilter.cpp">
<Filter>Connector\Record\Model\Filter</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\AddModel.cpp">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\RemoveModel.cpp">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.cpp">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -215,9 +251,6 @@
<ClInclude Include="Connector\Version.h">
<Filter>Connector</Filter>
</ClInclude>
<ClInclude Include="Connector\Database\Model\Card\ModelCardDatabase.h">
<Filter>Connector\Database\Model\Card</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\Arg\ConnectorConfig.h">
<Filter>Connector\Interface\Browser\Bridge\Config\Arg</Filter>
</ClInclude>
@@ -252,8 +285,53 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\GetSendFilters.h">
<Filter>Connector\Interface\Browser\Bridge\Send</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendFilter.h">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
<ClInclude Include="Connector\Database\ModelCardDatabase.h">
<Filter>Connector\Database</Filter>
</ClInclude>
<ClInclude Include="Connector\Database\Identity\RecordID.h">
<Filter>Connector\Database\Identity</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\CardMover.h">
<Filter>Connector\Record\Model</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\CardSetting.h">
<Filter>Connector\Record\Model</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\ModelCard.h">
<Filter>Connector\Record\Model</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\ReceiverModelCard.h">
<Filter>Connector\Record\Model</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\SenderModelCard.h">
<Filter>Connector\Record\Model</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\Filter\ArchicadEverythingFilter.h">
<Filter>Connector\Record\Model\Filter</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\Filter\ArchicadSelectionFilter.h">
<Filter>Connector\Record\Model\Filter</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\Filter\DirectSelectionSendFilter.h">
<Filter>Connector\Record\Model\Filter</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\Filter\EverythingSendFilter.h">
<Filter>Connector\Record\Model\Filter</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\Filter\FilterMover.h">
<Filter>Connector\Record\Model\Filter</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Model\Filter\SendFilter.h">
<Filter>Connector\Record\Model\Filter</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\AddModel.h">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\RemoveModel.h">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.h">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -25,6 +25,10 @@
210CC8832C80E6A300610F58 /* TriggerEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 210CC8812C80E6A300610F58 /* TriggerEvent.cpp */; };
213CC39C2B1101F500088049 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2151077C2AEDB9070022CD24 /* Cocoa.framework */; };
214B7A372C764BCD00D586C1 /* UpdateConfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69FBD2C7630B3008B6A06 /* UpdateConfig.cpp */; };
215F082A2C947F4400CD343B /* CardMover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08262C947F4400CD343B /* CardMover.cpp */; };
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F082C2C94C5C000CD343B /* FilterMover.cpp */; };
215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08362C95808B00CD343B /* ReceiverModelCard.cpp */; };
215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08452C9633A800CD343B /* EverythingSendFilter.cpp */; };
219F30422C769283009834E9 /* ConfigTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219F30402C769282009834E9 /* ConfigTests.cpp */; };
21B67CA32C769CB400FD64FC /* libActiveLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69EF52C64FE91008B6A06 /* libActiveLib.a */; };
21B67CA42C769CB400FD64FC /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69ECD2C64C035008B6A06 /* libArchicad27.a */; };
@@ -47,7 +51,14 @@
21D0BD6A2C8A0DB40077E104 /* GetIsDevMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD682C8A0DB40077E104 /* GetIsDevMode.cpp */; };
21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD8D2C8EE4490077E104 /* Send.cpp */; };
21D0BD972C8F13F30077E104 /* GetSendFilters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */; };
21D0BD9B2C8F154B0077E104 /* SendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD982C8F154B0077E104 /* SendFilter.cpp */; };
21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */; };
21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */; };
21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDCB2C92DAC60077E104 /* AddModel.cpp */; };
21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDD22C935D1A0077E104 /* UpdateModel.cpp */; };
21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */; };
21D0BDDC2C93897B0077E104 /* SenderModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDDA2C93897B0077E104 /* SenderModelCard.cpp */; };
21D0BDE02C9393980077E104 /* SendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDDD2C9393980077E104 /* SendFilter.cpp */; };
21D0BDE32C943C630077E104 /* DirectSelectionSendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */; };
21D1E9AD2BF14AF200957EAA /* BIMData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9152BF14AEC00957EAA /* BIMData.framework */; };
21D1E9AE2BF14AF200957EAA /* TeamworkPortalServerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */; };
21D1E9AF2BF14AF200957EAA /* GDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21D1E9172BF14AEC00957EAA /* GDL.framework */; };
@@ -275,6 +286,17 @@
210CC8822C80E6A300610F58 /* TriggerEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TriggerEvent.h; sourceTree = "<group>"; };
213CC3A52B1101F500088049 /* Speckle Connector.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Speckle Connector.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
2151077C2AEDB9070022CD24 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
215F08262C947F4400CD343B /* CardMover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CardMover.cpp; sourceTree = "<group>"; };
215F08292C947F4400CD343B /* CardMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardMover.h; sourceTree = "<group>"; };
215F082C2C94C5C000CD343B /* FilterMover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilterMover.cpp; sourceTree = "<group>"; };
215F082D2C94C5C000CD343B /* FilterMover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterMover.h; sourceTree = "<group>"; };
215F08332C95808B00CD343B /* ReceiverModelCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReceiverModelCard.h; sourceTree = "<group>"; };
215F08362C95808B00CD343B /* ReceiverModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReceiverModelCard.cpp; sourceTree = "<group>"; };
215F083D2C96270100CD343B /* RecordID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RecordID.h; sourceTree = "<group>"; };
215F08412C962F5E00CD343B /* ArchicadSelectionFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadSelectionFilter.h; sourceTree = "<group>"; };
215F08442C9633A800CD343B /* EverythingSendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EverythingSendFilter.h; sourceTree = "<group>"; };
215F08452C9633A800CD343B /* EverythingSendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EverythingSendFilter.cpp; sourceTree = "<group>"; };
215F084A2C9782F100CD343B /* ArchicadEverythingFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ArchicadEverythingFilter.h; sourceTree = "<group>"; };
2161FD902BF2600C006D9527 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
219388682C4E5DE2002A0180 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
219F30352C768F0A009834E9 /* Connector-AC27-Test.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Connector-AC27-Test.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -319,8 +341,22 @@
21D0BD8D2C8EE4490077E104 /* Send.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Send.cpp; sourceTree = "<group>"; };
21D0BD952C8F13F30077E104 /* GetSendFilters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetSendFilters.h; sourceTree = "<group>"; };
21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSendFilters.cpp; sourceTree = "<group>"; };
21D0BD982C8F154B0077E104 /* SendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendFilter.cpp; sourceTree = "<group>"; };
21D0BD992C8F154B0077E104 /* SendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendFilter.h; sourceTree = "<group>"; };
21D0BDA42C8F33AC0077E104 /* ModelCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelCard.h; sourceTree = "<group>"; };
21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModelCard.cpp; sourceTree = "<group>"; };
21D0BDA92C8F363E0077E104 /* CardSetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CardSetting.h; sourceTree = "<group>"; };
21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CardSetting.cpp; sourceTree = "<group>"; };
21D0BDCB2C92DAC60077E104 /* AddModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AddModel.cpp; sourceTree = "<group>"; };
21D0BDCE2C92DAC60077E104 /* AddModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddModel.h; sourceTree = "<group>"; };
21D0BDD22C935D1A0077E104 /* UpdateModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UpdateModel.cpp; sourceTree = "<group>"; };
21D0BDD32C935D1A0077E104 /* UpdateModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateModel.h; sourceTree = "<group>"; };
21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveModel.cpp; sourceTree = "<group>"; };
21D0BDD62C935DAE0077E104 /* RemoveModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveModel.h; sourceTree = "<group>"; };
21D0BDDA2C93897B0077E104 /* SenderModelCard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SenderModelCard.cpp; sourceTree = "<group>"; };
21D0BDDB2C93897B0077E104 /* SenderModelCard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SenderModelCard.h; sourceTree = "<group>"; };
21D0BDDD2C9393980077E104 /* SendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendFilter.cpp; sourceTree = "<group>"; };
21D0BDDE2C9393980077E104 /* SendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendFilter.h; sourceTree = "<group>"; };
21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectSelectionSendFilter.cpp; sourceTree = "<group>"; };
21D0BDE22C943C630077E104 /* DirectSelectionSendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectSelectionSendFilter.h; sourceTree = "<group>"; };
21D1E9152BF14AEC00957EAA /* BIMData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BIMData.framework; path = "../Archicad 27/Support/Frameworks/BIMData.framework"; sourceTree = "<group>"; };
21D1E9162BF14AEC00957EAA /* TeamworkPortalServerClient.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TeamworkPortalServerClient.framework; path = "../Archicad 27/Support/Frameworks/TeamworkPortalServerClient.framework"; sourceTree = "<group>"; };
21D1E9172BF14AEC00957EAA /* GDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GDL.framework; path = "../Archicad 27/Support/Frameworks/GDL.framework"; sourceTree = "<group>"; };
@@ -885,6 +921,14 @@
name = Frameworks;
sourceTree = "<group>";
};
215F083E2C96270100CD343B /* Identity */ = {
isa = PBXGroup;
children = (
215F083D2C96270100CD343B /* RecordID.h */,
);
path = Identity;
sourceTree = "<group>";
};
219F30412C769282009834E9 /* ConnectorTests */ = {
isa = PBXGroup;
children = (
@@ -898,6 +942,8 @@
21B67CAB2C77329800FD64FC /* Base */ = {
isa = PBXGroup;
children = (
21D0BDCB2C92DAC60077E104 /* AddModel.cpp */,
21D0BDCE2C92DAC60077E104 /* AddModel.h */,
21B67CEA2C78D27200FD64FC /* Arg */,
21B67CA52C77329800FD64FC /* BaseBridge.cpp */,
21B67CA62C77329800FD64FC /* BaseBridge.h */,
@@ -911,31 +957,20 @@
21B67CA82C77329800FD64FC /* GetSourceApplicationName.h */,
21B67CA92C77329800FD64FC /* GetSourceApplicationVersion.cpp */,
21B67CAA2C77329800FD64FC /* GetSourceApplicationVersion.h */,
21D0BDD52C935DAE0077E104 /* RemoveModel.cpp */,
21D0BDD62C935DAE0077E104 /* RemoveModel.h */,
21D0BDD22C935D1A0077E104 /* UpdateModel.cpp */,
21D0BDD32C935D1A0077E104 /* UpdateModel.h */,
);
path = Base;
sourceTree = "<group>";
};
21B67CC92C77670400FD64FC /* Card */ = {
isa = PBXGroup;
children = (
21B67CC72C77670400FD64FC /* ModelCardDatabase.cpp */,
21B67CC82C77670400FD64FC /* ModelCardDatabase.h */,
);
path = Card;
sourceTree = "<group>";
};
21B67CCA2C77670400FD64FC /* Model */ = {
isa = PBXGroup;
children = (
21B67CC92C77670400FD64FC /* Card */,
);
path = Model;
sourceTree = "<group>";
};
21B67CCB2C77670400FD64FC /* Database */ = {
isa = PBXGroup;
children = (
21B67CCA2C77670400FD64FC /* Model */,
215F083E2C96270100CD343B /* Identity */,
21B67CC72C77670400FD64FC /* ModelCardDatabase.cpp */,
21B67CC82C77670400FD64FC /* ModelCardDatabase.h */,
);
path = Database;
sourceTree = "<group>";
@@ -988,7 +1023,6 @@
21D0BD5D2C89BFEA0077E104 /* Send */ = {
isa = PBXGroup;
children = (
21D0BD9A2C8F154B0077E104 /* Arg */,
21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */,
21D0BD952C8F13F30077E104 /* GetSendFilters.h */,
21D0BD8D2C8EE4490077E104 /* Send.cpp */,
@@ -999,13 +1033,47 @@
path = Send;
sourceTree = "<group>";
};
21D0BD9A2C8F154B0077E104 /* Arg */ = {
21D0BDD82C9387E60077E104 /* Record */ = {
isa = PBXGroup;
children = (
21D0BD982C8F154B0077E104 /* SendFilter.cpp */,
21D0BD992C8F154B0077E104 /* SendFilter.h */,
21D0BDD92C9387F70077E104 /* Model */,
);
path = Arg;
path = Record;
sourceTree = "<group>";
};
21D0BDD92C9387F70077E104 /* Model */ = {
isa = PBXGroup;
children = (
215F08262C947F4400CD343B /* CardMover.cpp */,
215F08292C947F4400CD343B /* CardMover.h */,
21D0BDAA2C8F363E0077E104 /* CardSetting.cpp */,
21D0BDA92C8F363E0077E104 /* CardSetting.h */,
21D0BDDF2C9393980077E104 /* Filter */,
21D0BDA72C8F33AC0077E104 /* ModelCard.cpp */,
21D0BDA42C8F33AC0077E104 /* ModelCard.h */,
215F08362C95808B00CD343B /* ReceiverModelCard.cpp */,
215F08332C95808B00CD343B /* ReceiverModelCard.h */,
21D0BDDA2C93897B0077E104 /* SenderModelCard.cpp */,
21D0BDDB2C93897B0077E104 /* SenderModelCard.h */,
);
path = Model;
sourceTree = "<group>";
};
21D0BDDF2C9393980077E104 /* Filter */ = {
isa = PBXGroup;
children = (
215F084A2C9782F100CD343B /* ArchicadEverythingFilter.h */,
215F08412C962F5E00CD343B /* ArchicadSelectionFilter.h */,
21D0BDE12C943C630077E104 /* DirectSelectionSendFilter.cpp */,
21D0BDE22C943C630077E104 /* DirectSelectionSendFilter.h */,
215F08452C9633A800CD343B /* EverythingSendFilter.cpp */,
215F08442C9633A800CD343B /* EverythingSendFilter.h */,
215F082C2C94C5C000CD343B /* FilterMover.cpp */,
215F082D2C94C5C000CD343B /* FilterMover.h */,
21D0BDDD2C9393980077E104 /* SendFilter.cpp */,
21D0BDDE2C9393980077E104 /* SendFilter.h */,
);
path = Filter;
sourceTree = "<group>";
};
21D1EA472BF14B6C00957EAA /* Archicad */ = {
@@ -1067,6 +1135,7 @@
21B67CCB2C77670400FD64FC /* Database */,
21F69F092C677BC0008B6A06 /* Event */,
21F69F0E2C677BC0008B6A06 /* Interface */,
21D0BDD82C9387E60077E104 /* Record */,
21B67CBA2C774C6500FD64FC /* Version.h */,
);
path = Connector;
@@ -1324,12 +1393,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */,
21B67CE32C78D1FB00FD64FC /* SayHiArg.cpp in Sources */,
215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */,
21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */,
21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */,
21D0BD9B2C8F154B0077E104 /* SendFilter.cpp in Sources */,
21D0BD8E2C8EE4490077E104 /* Send.cpp in Sources */,
21D0BDCF2C92DAC60077E104 /* AddModel.cpp in Sources */,
21B67CF72C78D4DE00FD64FC /* GetComplexType.cpp in Sources */,
21D0BDDC2C93897B0077E104 /* SenderModelCard.cpp in Sources */,
21B67CAE2C77329800FD64FC /* GetSourceApplicationVersion.cpp in Sources */,
21B67CC32C77649F00FD64FC /* GetDocumentState.cpp in Sources */,
21D0BD602C89BFEA0077E104 /* SendBridge.cpp in Sources */,
@@ -1342,14 +1414,22 @@
21B67CD92C78C83800FD64FC /* TestBridge.cpp in Sources */,
214B7A372C764BCD00D586C1 /* UpdateConfig.cpp in Sources */,
21B67CC02C775A0D00FD64FC /* GetDocumentInfo.cpp in Sources */,
21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */,
21B67CE72C78D23B00FD64FC /* ConnectorConfig.cpp in Sources */,
21B67CAD2C77329800FD64FC /* GetSourceApplicationName.cpp in Sources */,
21D0BDE02C9393980077E104 /* SendFilter.cpp in Sources */,
21D0BDA82C8F33AC0077E104 /* ModelCard.cpp in Sources */,
215F082A2C947F4400CD343B /* CardMover.cpp in Sources */,
215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */,
21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */,
21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */,
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */,
21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */,
21F69F8D2C70D7EE008B6A06 /* GetAccounts.cpp in Sources */,
21B67CCC2C77670400FD64FC /* ModelCardDatabase.cpp in Sources */,
21F69F132C677BC0008B6A06 /* ConnectorPalette.cpp in Sources */,
21F69FBC2C762EF0008B6A06 /* GetConfig.cpp in Sources */,
21D0BDE32C943C630077E104 /* DirectSelectionSendFilter.cpp in Sources */,
21B67CF12C78D38000FD64FC /* GoAway.cpp in Sources */,
21F69F142C677BC0008B6A06 /* Connector.cpp in Sources */,
);
+2 -1
View File
@@ -1,7 +1,7 @@
#include "Active/File/Directory.h"
#include "ConnectorResource.h"
#include "Connector/Connector.h"
#include "Connector/Database/Model/Card/ModelCardDatabase.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Interface/ConnectorMenu.h"
#include "Interface/ConnectorPalette.h"
#include "Speckle/Database/AccountDatabase.h"
@@ -29,6 +29,7 @@ namespace {
ConnectorInstance(const String& name) : ConnectorAddon{name} {
add<ConnectorMenu>();
add<ConnectorPalette>();
addWeak(m_modelCards.getSubscription());
}
// MARK: Functions (const)
@@ -0,0 +1,16 @@
#ifndef CONNECTOR_DATABASE_ID
#define CONNECTOR_DATABASE_ID
#include "Speckle/Utility/Guid.h"
namespace connector::database {
//BIM element record identifier
using ElementID = speckle::utility::Guid;
//A list of element IDs
using ElementIDList = std::vector<ElementID>;
}
#endif //CONNECTOR_DATABASE_ID
@@ -1,57 +0,0 @@
#ifndef CONNECTOR_DATABASE_MODEL_CARD_DATABASE
#define CONNECTOR_DATABASE_MODEL_CARD_DATABASE
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Utility/String.h"
namespace connector::database {
/*!
Database of model cards relating to a specific project
*/
class ModelCardDatabase : public active::serialise::Package {
public:
// MARK: - Types
using base = active::serialise::Package;
// MARK: - Constructors
/*!
Default constructor
*/
ModelCardDatabase() {}
// MARK: - Public variables (NB: Assuming to class invariants or overrides for this data, so making public for simplicity)
// MARK: Functions (const)
//Implement card access when necessary
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
//TODO: Model card array here - implement when necessary
};
}
#endif //CONNECTOR_DATABASE_MODEL_CARD_DATABASE
@@ -0,0 +1,121 @@
#include "Connector/Database/ModelCardDatabase.h"
#include "Active/Database/Storage/Storage.h"
#include "Active/Serialise/JSON/JSONTransport.h"
#include "Connector/Record/Model/CardMover.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Database/Storage/DocumentStore/DocumentStoreEngine.h"
#include <array>
using namespace active::container;
using namespace active::database;
using namespace active::event;
using namespace active::serialise;
using namespace active::serialise::json;
using namespace connector::database;
using namespace connector::record;
using namespace speckle::database;
using namespace speckle::utility;
namespace connector::database {
///ModelCard database engine declaration
class ModelCardDatabase::Engine : public DocumentStoreEngine<ModelCard, CardMover, JSONTransport, RecordID> {
using base = DocumentStoreEngine<ModelCard, CardMover, JSONTransport, RecordID>;
using base::base;
};
///ModelCard database storage declaration
class ModelCardDatabase::Store : public Storage<ModelCard, JSONTransport,
RecordID, RecordID, RecordID, RecordID> {
using base = Storage<ModelCard, JSONTransport,
RecordID, RecordID, RecordID, RecordID>;
using base::base;
};
}
namespace {
///The document storage identifier for model cards
const char* modelCardDBaseName = "connector::database::ModelModelCardDatabase";
///The document storage identifier for model cards
const char* modelCardTableName = "models";
}
/*--------------------------------------------------------------------
Constructor
--------------------------------------------------------------------*/
ModelCardDatabase::ModelCardDatabase() {
m_engine = std::make_shared<Engine>(modelCardDBaseName,
//Schema
DBaseSchema{active::utility::String{modelCardDBaseName},
//Tables
{
//Model card table
{
modelCardTableName, 0, 0, {} //The table specifics aren't relevant in this context
}
}
}
);
m_store = std::make_shared<Store>(m_engine);
} //ModelCardDatabase::ModelCardDatabase
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
ModelCardDatabase::~ModelCardDatabase() {}
/*--------------------------------------------------------------------
Get all model cards
return: All the cards
--------------------------------------------------------------------*/
Vector<ModelCard> ModelCardDatabase::getCards() const {
return m_store->getObjects();
} //ModelCardDatabase::getCards
/*--------------------------------------------------------------------
Write a card to storage
card: The card to write
--------------------------------------------------------------------*/
void ModelCardDatabase::write(const ModelCard& card) const {
m_store->write(card);
} //ModelCardDatabase::write
/*--------------------------------------------------------------------
Erase a card
cardID: The ID of the card to erase
--------------------------------------------------------------------*/
void ModelCardDatabase::erase(const String& cardID) const {
m_store->erase(cardID);
} //ModelCardDatabase::erase
/*--------------------------------------------------------------------
Get a serialisation wrapper for the database
return: A database wrapper
--------------------------------------------------------------------*/
std::unique_ptr<Cargo> ModelCardDatabase::wrapper() const {
return m_store->wrapper();
} //ModelCardDatabase::wrapper
/*--------------------------------------------------------------------
Get the database subscription (the content is document-based, and must react to document operations)
return: The database subscription (add weakly to publisher)
--------------------------------------------------------------------*/
std::shared_ptr<active::event::Subscriber> ModelCardDatabase::getSubscription() {
return std::dynamic_pointer_cast<Subscriber>(m_engine);
} //ModelCardDatabase::getSubscription
@@ -0,0 +1,71 @@
#ifndef CONNECTOR_DATABASE_MODEL_CARD_DATABASE
#define CONNECTOR_DATABASE_MODEL_CARD_DATABASE
#include "Connector/Record/Model/ModelCard.h"
namespace active::event {
class Subscriber;
}
namespace connector::database {
/*!
Database of model cards relating to a specific project
*/
class ModelCardDatabase {
public:
// MARK: - Constructors
/*!
Constructor
*/
ModelCardDatabase();
ModelCardDatabase(const ModelCardDatabase&) = delete;
/*!
Destructor
*/
~ModelCardDatabase();
// MARK: - Functions (const)
/*!
Get all model cards
@return All the cards
*/
active::container::Vector<record::ModelCard> getCards() const;
/*!
Write a card to storage
@param card The card to write
*/
void write(const record::ModelCard& card) const;
/*!
Erase a card
@param cardID The ID of the card to erase
*/
void erase(const speckle::utility::String& cardID) const;
/*!
Get a serialisation wrapper for the database
@return A database wrapper
*/
std::unique_ptr<active::serialise::Cargo> wrapper() const;
// MARK: - Functions (mutating)
/*!
Get the database subscription (the content is document-based, and must react to document operations)
@return The database subscription (add weakly to publisher)
*/
std::shared_ptr<active::event::Subscriber> getSubscription();
private:
class Engine;
class Store;
///Model card database storage
std::shared_ptr<Engine> m_engine;
std::shared_ptr<Store> m_store;
};
}
#endif //CONNECTOR_DATABASE_MODEL_CARD_DATABASE
@@ -14,7 +14,7 @@ using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<ContainerWrap<Vector, Account>, Vector<Account>>;
using WrappedValue = active::serialise::CargoHold<ContainerWrap<Vector<Account>>, Vector<Account>>;
}
@@ -0,0 +1,35 @@
#include "Connector/Interface/Browser/Bridge/Base/AddModel.h"
#include "Connector/Connector.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h"
using namespace active::container;
using namespace active::serialise;
using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<PackageWrap, DocumentInfo>;
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
AddModel::AddModel() : BridgeMethod{"AddModel", [&](const ModelCardEventWrapper& card) {
return run(card.get());
}} {}
/*--------------------------------------------------------------------
Add a model card to document storage
card: The card to add
--------------------------------------------------------------------*/
void AddModel::run(const ModelCard& card) const {
if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr)
modelCardDBase->write(card);
} //AddModel::run
@@ -0,0 +1,40 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_ADD_MODEL
#define CONNECTOR_INTERFACE_BRIDGE_ADD_MODEL
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Record/Model/ModelCard.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
///Argument parameter for a string
using CardHold = active::serialise::CargoHold<active::serialise::PackageWrap, connector::record::ModelCard>;
///Argument type for this method
using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType<CardHold>;
/*!
JS Function class to add a model card to the document storage
*/
class AddModel : public speckle::interfac::browser::bridge::BridgeMethod<ModelCardEventWrapper, void> {
public:
// MARK: - Constructors
/*!
Default constructor
*/
AddModel();
// MARK: - Functions (const)
/*!
Add a model card to document storage
@param card The card to add
*/
void run(const connector::record::ModelCard& card) const;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_ADD_MODEL
@@ -1,10 +1,13 @@
#include "Connector/Interface/Browser/Bridge/Base/BaseBridge.h"
#include "Connector/Interface/Browser/Bridge/Base/AddModel.h"
#include "Connector/Interface/Browser/Bridge/Base/GetConnectorVersion.h"
#include "Connector/Interface/Browser/Bridge/Base/GetDocumentInfo.h"
#include "Connector/Interface/Browser/Bridge/Base/GetDocumentState.h"
#include "Connector/Interface/Browser/Bridge/Base/GetSourceApplicationName.h"
#include "Connector/Interface/Browser/Bridge/Base/GetSourceApplicationVersion.h"
#include "Connector/Interface/Browser/Bridge/Base/RemoveModel.h"
#include "Connector/Interface/Browser/Bridge/Base/UpdateModel.h"
using namespace connector::interfac::browser::bridge;
@@ -13,9 +16,12 @@ using namespace connector::interfac::browser::bridge;
--------------------------------------------------------------------*/
BaseBridge::BaseBridge() : BrowserBridge{"baseBinding"} {
//Add bridge methods
addMethod<AddModel>();
addMethod<GetConnectorVersion>();
addMethod<GetDocumentInfo>();
addMethod<GetDocumentState>();
addMethod<GetSourceApplicationName>();
addMethod<GetSourceApplicationVersion>();
addMethod<RemoveModel>();
addMethod<UpdateModel>();
} //BaseBridge::BaseBridge
@@ -1,17 +1,21 @@
#include "Connector/Interface/Browser/Bridge/Base/GetDocumentState.h"
#include "Active/Serialise/CargoHold.h"
#include "Connector/Database/Model/Card/ModelCardDatabase.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Connector/Connector.h"
#include "Connector/Record/Model/ModelCard.h"
#include "Connector/Database/ModelCardDatabase.h"
using namespace active::container;
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace connector::database;
using namespace connector::record;
using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<PackageWrap, ModelCardDatabase>;
using WrappedValue = active::serialise::CargoHold<ContainerWrap<Vector<ModelCard>>, Vector<ModelCard>>;
}
@@ -29,7 +33,8 @@ GetDocumentState::GetDocumentState() : BridgeMethod{"GetDocumentState", [&]() {
return: The document info
--------------------------------------------------------------------*/
std::unique_ptr<Cargo> GetDocumentState::run() const {
///TODO: Retrieve the model card database from connector()->getModelCards() in future (when implemented)
ModelCardDatabase modelCards; //This is just a temp so something can be sent back to the JS for the interim
return std::make_unique<WrappedValue>(modelCards);
if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr) {
return modelCardDBase->wrapper();
}
return nullptr;
} //GetDocumentState::run
@@ -0,0 +1,36 @@
#include "Connector/Interface/Browser/Bridge/Base/RemoveModel.h"
#include "Connector/Connector.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h"
using namespace active::container;
using namespace active::serialise;
using namespace connector::database;
using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<PackageWrap, DocumentInfo>;
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
RemoveModel::RemoveModel() : BridgeMethod{"RemoveModel", [&](const ModelCardEventWrapper& card) {
return run(card.get());
}} {}
/*--------------------------------------------------------------------
Add a model card to document storage
card: The card to add
--------------------------------------------------------------------*/
void RemoveModel::run(const ModelCard& card) const {
if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr)
modelCardDBase->erase(card.getID());
} //RemoveModel::run
@@ -0,0 +1,40 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_REMOVE_MODEL
#define CONNECTOR_INTERFACE_BRIDGE_REMOVE_MODEL
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Record/Model/ModelCard.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
///Argument parameter for a string
using CardHold = active::serialise::CargoHold<active::serialise::PackageWrap, connector::record::ModelCard>;
///Argument type for this method
using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType<CardHold>;
/*!
JS Function class to add a model card to the document storage
*/
class RemoveModel : public speckle::interfac::browser::bridge::BridgeMethod<ModelCardEventWrapper, void> {
public:
// MARK: - Constructors
/*!
Default constructor
*/
RemoveModel();
// MARK: - Functions (const)
/*!
Add a model card to document storage
@param card The card to add
*/
void run(const connector::record::ModelCard& card) const;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_REMOVE_MODEL
@@ -0,0 +1,36 @@
#include "Connector/Interface/Browser/Bridge/Base/UpdateModel.h"
#include "Connector/Connector.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h"
using namespace active::container;
using namespace active::serialise;
using namespace connector::database;
using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<PackageWrap, DocumentInfo>;
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
UpdateModel::UpdateModel() : BridgeMethod{"UpdateModel", [&](const ModelCardEventWrapper& card) {
return run(card.get());
}} {}
/*--------------------------------------------------------------------
Add a model card to document storage
card: The card to add
--------------------------------------------------------------------*/
void UpdateModel::run(const ModelCard& card) const {
if (auto modelCardDBase = connector()->getModelCardDatabase(); modelCardDBase != nullptr)
modelCardDBase->write(card);
} //UpdateModel::run
@@ -0,0 +1,40 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_UPDATE_MODEL
#define CONNECTOR_INTERFACE_BRIDGE_UPDATE_MODEL
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Record/Model/ModelCard.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
///Argument parameter for a string
using CardHold = active::serialise::CargoHold<active::serialise::PackageWrap, connector::record::ModelCard>;
///Argument type for this method
using ModelCardEventWrapper = speckle::interfac::browser::bridge::JSArgType<CardHold>;
/*!
JS Function class to add a model card to the document storage
*/
class UpdateModel : public speckle::interfac::browser::bridge::BridgeMethod<ModelCardEventWrapper, void> {
public:
// MARK: - Constructors
/*!
Default constructor
*/
UpdateModel();
// MARK: - Functions (const)
/*!
Add a model card to document storage
@param card The card to add
*/
void run(const connector::record::ModelCard& card) const;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_UPDATE_MODEL
@@ -10,7 +10,7 @@ using namespace speckle::utility;
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
UpdateConfig::UpdateConfig() : BridgeMethod{"UpdateConfig", [&](UpdateArgs args) {
UpdateConfig::UpdateConfig() : BridgeMethod{"UpdateConfig", [&](const UpdateArgs& args) {
run(args);
}} {}
@@ -1,67 +0,0 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_FILTER
#define CONNECTOR_INTERFACE_BRIDGE_SEND_FILTER
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/Cloner.h"
#include "Speckle/Utility/String.h"
namespace connector::interfac::browser::bridge {
/*!
A connector send filter
*/
class SendFilter : public active::serialise::Package, public active::utility::Cloner {
public:
// MARK: - Types
using base = active::serialise::Package;
// MARK: - Constructors
/*!
Default constructor
@param nm The filter name
@param sum A summary
@param isDef True if this is the default filter
*/
SendFilter(const speckle::utility::String& nm = {}, const speckle::utility::String& sum = {}, bool isDef = false) :
name{nm}, summary{sum}, isDefault{isDef} {}
/*!
Record cloning
@return A clone of this record
*/
virtual SendFilter* clonePtr() const override { return new SendFilter(*this); };
// MARK: - Public variables (NB: Assuming to class invariants or overrides for this data, so making public for simplicity)
///The filter name
speckle::utility::String name;
///A summary
speckle::utility::String summary;
///True if this is the default filter
bool isDefault = false;
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_FILTER
@@ -4,16 +4,18 @@
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.h"
#include "Connector/Record/Model/Filter/ArchicadEverythingFilter.h"
#include "Connector/Record/Model/Filter/ArchicadSelectionFilter.h"
using namespace active::container;
using namespace active::serialise;
using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<ContainerWrap<Vector, SendFilter>, Vector<SendFilter>>;
using WrappedValue = active::serialise::CargoHold<ContainerWrap<Vector<SendFilter>>, Vector<SendFilter>>;
}
@@ -32,6 +34,7 @@ GetSendFilters::GetSendFilters() : BridgeMethod{"GetSendFilters", [&]() {
--------------------------------------------------------------------*/
std::unique_ptr<Cargo> GetSendFilters::run() const {
Vector<SendFilter> filters;
///TODO: Get real filters
//filters.emplace_back(ArchicadEverythingFilter{}); //TODO: Implement as required
filters.emplace_back(ArchicadSelectionFilter{});
return std::make_unique<WrappedValue>(filters);
} //GetSendFilters::run
@@ -85,7 +85,7 @@ namespace {
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
TriggerEvent::TriggerEvent() : BridgeMethod{"TriggerEvent", [&](TriggerEventWrapper arg) {
TriggerEvent::TriggerEvent() : BridgeMethod{"TriggerEvent", [&](const TriggerEventWrapper& arg) {
return run(arg);
}} {}
@@ -95,7 +95,7 @@ TriggerEvent::TriggerEvent() : BridgeMethod{"TriggerEvent", [&](TriggerEventWrap
eventName: The event name
--------------------------------------------------------------------*/
void TriggerEvent::run(speckle::utility::String eventName) const {
void TriggerEvent::run(const speckle::utility::String& eventName) const {
if (!hasBridge())
return;
if (eventName == "emptyTestEvent")
@@ -31,7 +31,7 @@ namespace connector::interfac::browser::bridge {
Trigger an event based on a specified name
@param eventName The event name
*/
void run(speckle::utility::String eventName) const;
void run(const speckle::utility::String& eventName) const;
};
}
@@ -0,0 +1,60 @@
/*!
Copyright 2024 Ralph Wessel and Hugh Wessel
Distributed under the MIT License (See accompanying file LICENSE.txt or copy at https://opensource.org/license/mit/)
*/
#include "Connector/Record/Model/CardMover.h"
#include "Connector/Record/Model/ReceiverModelCard.h"
#include "Connector/Record/Model/SenderModelCard.h"
using namespace active::serialise;
using namespace active::utility;
using namespace connector::record;
namespace {
///The tag used to identify a Speckle type name value
const char* attributeTag = "typeDiscriminator";
///Identity for a ReceiverModelCard
const char* receiverCardTypeName = "ReceiverModelCard";
///Identity for a SenderModelCard
const char* senderCardTypeName = "SenderModelCard";
/*--------------------------------------------------------------------
Ensure the handler is populated
handler: The card handler to validate
return: A reference to the handler
--------------------------------------------------------------------*/
std::shared_ptr<active::serialise::Handler>& validateHandler(std::shared_ptr<active::serialise::Handler>& handler) {
if (!handler->empty())
return handler;
handler->add<ReceiverModelCard>(receiverCardTypeName);
handler->add<SenderModelCard>(senderCardTypeName);
return handler;
} //CardMover::validateHandler
}
///The handler for model card packages
std::shared_ptr<active::serialise::Handler> CardMover::m_handler = std::make_shared<active::serialise::Handler>(attributeTag);
/*--------------------------------------------------------------------
Constructor (for deserialisation)
handler: A package handler to reconstruct incoming packages
--------------------------------------------------------------------*/
CardMover::CardMover() : Mover{validateHandler(m_handler)} {
} //CardMover::CardMover
/*--------------------------------------------------------------------
Constructor (for serialisation)
outgoing: An outgoing package
--------------------------------------------------------------------*/
CardMover::CardMover(const active::serialise::Package& outgoing) : Mover{outgoing, validateHandler(m_handler)} {
} //CardMover::CardMover
@@ -0,0 +1,36 @@
#ifndef CONNECTOR_MODEL_CARD_MOVER
#define CONNECTOR_MODEL_CARD_MOVER
#include "Active/Serialise/Package/Wrapper/Mover.h"
namespace connector::record {
/*!
Wrapper to box/unbox objects during (de)serialisation, including reading/writing a specified attribute to determine object type
Note that a derived class could also define the package handler, allowing the wrapper to be created via a default constructor that is
automatically bound to a set of internally defined object types
*/
class CardMover : public active::serialise::Mover {
public:
// MARK: - Constructors
/*!
Default constructor
*/
CardMover();
/*!
Constructor (for serialisation)
@param outgoing An outgoing package
*/
CardMover(const active::serialise::Package& outgoing);
private:
///The handler for model card packages
static std::shared_ptr<active::serialise::Handler> m_handler;
};
}
#endif //CONNECTOR_MODEL_CARD_MOVER
@@ -0,0 +1,94 @@
#include "Connector/Record/Model/CardSetting.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Item/Wrapper/AnyValueWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include <array>
using namespace active::serialise;
using namespace connector::record;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
idID,
titleID,
typeID,
valueID,
enumID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"id"},
Identity{"title"},
Identity{"type"},
Identity{"value"},
Identity{"enum"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool CardSetting::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[idID], idID, element },
{ fieldID[titleID], titleID, element },
{ fieldID[typeID], typeID, element },
{ fieldID[valueID], valueID, element },
{ fieldID[enumID], enumID, element },
},
}.withType(&typeid(CardSetting)));
return true;
} //CardSetting::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique CardSetting::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(CardSetting))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case idID:
return std::make_unique<ValueWrap<String>>(m_ID);
case titleID:
return std::make_unique<ValueWrap<String>>(m_title);
case typeID:
return std::make_unique<ValueWrap<String>>(m_type);
case valueID:
return std::make_unique<AnyValueWrap>(*m_value);
case enumID:
return std::make_unique<ContainerWrap<std::vector<speckle::utility::String>>>(m_enum);
default:
return nullptr; //Requested an unknown index
}
} //CardSetting::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void CardSetting::setDefault() {
m_ID.clear();
m_title.clear();
m_type.clear();
m_value->setDefault();
m_enum.clear();
} //CardSetting::setDefault
@@ -0,0 +1,107 @@
#ifndef CONNECTOR_RECORD_CARD_SETTING
#define CONNECTOR_RECORD_CARD_SETTING
#include "Active/Serialise/Package/Package.h"
#include "Active/Setting/ValueSetting.h"
#include "Active/Setting/Values/StringValue.h"
#include "Active/Utility/Cloner.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
namespace connector::record {
/*!
A setting attached to a model card, capturing rendering/view states of the model at the time of sending, e.g. level of detail (LoD)
*/
class CardSetting : public active::serialise::Package, public active::utility::Cloner {
public:
// MARK: - Types
using base = active::serialise::Package;
// MARK: - Constructors
/*!
Default constructor
*/
CardSetting() {}
/*!
Copy constructor
@param source The object to copy
*/
CardSetting(const CardSetting& source) :
m_title{source.m_title}, m_type{source.m_type}, m_value{clone(*source.m_value)}, m_enum{source.m_enum} {}
/*!
Destructor
*/
~CardSetting() {}
/*!
Record cloning
@return A clone of this record
*/
virtual CardSetting* clonePtr() const override { return new CardSetting(*this); };
// MARK: - Functions (const)
/*!
Get the setting ID
@return The setting ID
*/
const speckle::utility::String& getID() const { return m_ID; }
/*!
Get the setting title
@return The setting title
*/
const speckle::utility::String& getTitle() const { return m_title; }
/*!
Get the setting type
@return The setting type
*/
const speckle::utility::String& getType() const { return m_type; }
/*!
Get the setting value
@return The setting value
*/
const active::setting::Value& getValue() const { return *m_value; }
/*!
Get the options for the value, i.e. possible values it can hold
@return Possible setting values
*/
std::vector<speckle::utility::String> getEnum() const { return m_enum; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///A unique ID for the setting
speckle::utility::String m_ID = {active::utility::Guid{true}.operator active::utility::String()};
///The model ID
speckle::utility::String m_title;
///The project ID
speckle::utility::String m_type;
///The setting value
active::setting::Value::Unique m_value = std::make_unique<active::setting::StringValue>();
///Possible values for the setting (as strings)
std::vector<speckle::utility::String> m_enum;
};
}
#endif //CONNECTOR_RECORD_CARD_SETTING
@@ -0,0 +1,38 @@
#ifndef CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER
#define CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/EverythingSendFilter.h"
namespace connector::record {
/*!
A send filter consisting of a list of selected Archicad element IDs
*/
class ArchicadEverythingFilter : public EverythingSendFilter {
public:
// MARK: - Types
using base = EverythingSendFilter;
// MARK: - Constructors
/*!
Default constructor
@param sum A summary
@param isDef True if this is the default filter
*/
ArchicadEverythingFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{sum, isDef} {}
/*!
Record cloning
@return A clone of this record
*/
ArchicadEverythingFilter* clonePtr() const override { return new ArchicadEverythingFilter(*this); };
// MARK: - Functions (const)
};
}
#endif //CONNECTOR_RECORD_ARCHICAD_EVERYTHING_FILTER
@@ -0,0 +1,38 @@
#ifndef CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER
#define CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h"
namespace connector::record {
/*!
A send filter consisting of a list of selected Archicad element IDs
*/
class ArchicadSelectionFilter : public DirectSelectionSendFilter {
public:
// MARK: - Types
using base = DirectSelectionSendFilter;
// MARK: - Constructors
/*!
Default constructor
@param sum A summary
@param isDef True if this is the default filter
*/
ArchicadSelectionFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{sum, isDef} {}
/*!
Record cloning
@return A clone of this record
*/
ArchicadSelectionFilter* clonePtr() const override { return new ArchicadSelectionFilter(*this); };
// MARK: - Functions (const)
};
}
#endif //CONNECTOR_RECORD_ARCHICAD_SELECTION_FILTER
@@ -0,0 +1,71 @@
#include "Connector/Record/Model/Filter/DirectSelectionSendFilter.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include <algorithm>
#include <array>
using namespace active::serialise;
using namespace connector::database;
using namespace connector::record;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
selectedElemID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"selectedObjectIds"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool DirectSelectionSendFilter::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[selectedElemID], selectedElemID, element },
},
}.withType(&typeid(DirectSelectionSendFilter)));
return base::fillInventory(inventory);
} //DirectSelectionSendFilter::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique DirectSelectionSendFilter::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(DirectSelectionSendFilter))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case selectedElemID:
return std::make_unique<ContainerWrap<ElementIDList>>(m_selectedElements);
default:
return nullptr; //Requested an unknown index
}
} //DirectSelectionSendFilter::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void DirectSelectionSendFilter::setDefault() {
m_selectedElements.clear();
} //DirectSelectionSendFilter::setDefault
@@ -0,0 +1,67 @@
#ifndef CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER
#define CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
namespace connector::record {
/*!
A send filter consisting of a list of selected element IDs
*/
class DirectSelectionSendFilter : public SendFilter {
public:
// MARK: - Types
using base = SendFilter;
// MARK: - Constructors
/*!
Default constructor
@param sum A summary
@param isDef True if this is the default filter
*/
DirectSelectionSendFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{"Selection", sum, isDef} {}
/*!
Record cloning
@return A clone of this record
*/
DirectSelectionSendFilter* clonePtr() const override { return new DirectSelectionSendFilter(*this); };
// MARK: - Functions (const)
/*!
Get the filtered element IDs
@return The filter elements
*/
const database::ElementIDList& getElementIDs() const override { return m_selectedElements; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///A list of selected element IDs
database::ElementIDList m_selectedElements;
};
}
#endif //CONNECTOR_RECORD_DIRECT_SELECT_SEND_FILTER
@@ -1,27 +1,28 @@
#include "Connector/Database/Model/Card/ModelCardDatabase.h"
#include "Connector/Record/Model/Filter/EverythingSendFilter.h"
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/ValueSettingWrap.h"
#include "Active/Setting/ValueSetting.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Active/Utility/Concepts.h"
#include <algorithm>
#include <array>
using namespace active::serialise;
using namespace active::setting;
using namespace connector::database;
using namespace connector::record;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
model,
selectedElemID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"models"},
Identity{"selectedObjectIds"},
};
}
@@ -33,15 +34,15 @@ namespace {
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool ModelCardDatabase::fillInventory(Inventory& inventory) const {
bool EverythingSendFilter::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[model], model, element },
{ fieldID[selectedElemID], selectedElemID, element },
},
}.withType(&typeid(ModelCardDatabase)));
return true;
} //ModelCardDatabase::fillInventory
}.withType(&typeid(EverythingSendFilter)));
return base::fillInventory(inventory);
} //EverythingSendFilter::fillInventory
/*--------------------------------------------------------------------
@@ -51,21 +52,22 @@ bool ModelCardDatabase::fillInventory(Inventory& inventory) const {
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique ModelCardDatabase::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(ModelCardDatabase))
return nullptr;
Cargo::Unique EverythingSendFilter::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(EverythingSendFilter))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case model:
return std::make_unique<CargoHold<ValueSettingWrap, ValueSetting>>(); //NB: This is a placeholder until we define the content
case selectedElemID:
return std::make_unique<ContainerWrap<ElementIDList>>(m_emptyList);
default:
return nullptr; //Requested an unknown index
}
} //ModelCardDatabase::getCargo
} //EverythingSendFilter::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void ModelCardDatabase::setDefault() {
} //ModelCardDatabase::setDefault
void EverythingSendFilter::setDefault() {
m_emptyList.clear();
} //EverythingSendFilter::setDefault
@@ -0,0 +1,73 @@
#ifndef CONNECTOR_RECORD_EVERYTHING_SEND_FILTER
#define CONNECTOR_RECORD_EVERYTHING_SEND_FILTER
#include "Connector/Database/Identity/RecordID.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
namespace connector::record {
/*!
A send filter consisting of a list of selected element IDs
*/
class EverythingSendFilter : public SendFilter {
public:
// MARK: - Types
using base = SendFilter;
// MARK: - Constructors
/*!
Default constructor
@param sum A summary
@param isDef True if this is the default filter
*/
EverythingSendFilter(const speckle::utility::String& sum = {}, bool isDef = false) : base{"Everything", sum, isDef} {}
/*!
Record cloning
@return A clone of this record
*/
EverythingSendFilter* clonePtr() const override { return new EverythingSendFilter(*this); };
// MARK: - Functions (const)
/*!
Get the filtered element IDs
@return The filter elements
*/
const database::ElementIDList& getElementIDs() const override { return m_emptyList; }
/*!
Determine if the filter has expired because an element in the selection has changed
@param changed The list of changed element IDs
@return True if the one of the changed elements is in the selection
*/
virtual bool checkExpiry(const database::ElementIDList& changed) const override { return true; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///Enables a const empty list to be returned
database::ElementIDList m_emptyList;
};
}
#endif //CONNECTOR_RECORD_EVERYTHING_SEND_FILTER
@@ -0,0 +1,68 @@
/*!
Copyright 2024 Ralph Wessel and Hugh Wessel
Distributed under the MIT License (See accompanying file LICENSE.txt or copy at https://opensource.org/license/mit/)
*/
#include "Connector/Record/Model/Filter/FilterMover.h"
#include "Connector/Record/Model/Filter/ArchicadEverythingFilter.h"
#include "Connector/Record/Model/Filter/ArchicadSelectionFilter.h"
using namespace active::serialise;
using namespace active::utility;
using namespace connector::record;
namespace {
///The tag used to identify a Speckle type name value
const char* attributeTag = "typeDiscriminator";
///Identity for a SenderModelCard
const char* ArchicadSelectionTypeName = "ArchicadSelectionFilter";
///Identity for a SenderModelCard
const char* ArchicadEverythingTypeName = "ArchicadEverythingFilter";
}
///The handler for model card packages
std::shared_ptr<active::serialise::Handler> FilterMover::m_handler = std::make_shared<active::serialise::Handler>(attributeTag);
/*--------------------------------------------------------------------
Constructor (for deserialisation)
handler: A package handler to reconstruct incoming packages
--------------------------------------------------------------------*/
FilterMover::FilterMover() : Mover{m_handler} {
validateHandler();
} //FilterMover::FilterMover
/*--------------------------------------------------------------------
Constructor (for serialisation)
outgoing: An outgoing package
--------------------------------------------------------------------*/
FilterMover::FilterMover(const active::serialise::Package& outgoing) : Mover{outgoing, m_handler} {
validateHandler();
} //FilterMover::FilterMover
/*--------------------------------------------------------------------
Constructor (when it will be used for serialisation only on an existing object)
package: A reference to the member variable
--------------------------------------------------------------------*/
FilterMover::FilterMover(active::serialise::PackageUniqueWrap&& package) : Mover{std::move(package), m_handler} {
} //FilterMover::FilterMover
/*--------------------------------------------------------------------
Ensure the handler is populated
--------------------------------------------------------------------*/
void FilterMover::validateHandler() {
if (!m_handler->empty())
return;
m_handler->add<ArchicadEverythingFilter>(ArchicadEverythingTypeName);
m_handler->add<DirectSelectionSendFilter>(ArchicadSelectionTypeName);
} //FilterMover::validateHandler
@@ -0,0 +1,51 @@
#ifndef CONNECTOR_MODEL_SEND_FILTER_MOVER
#define CONNECTOR_MODEL_SEND_FILTER_MOVER
#include "Active/Serialise/Package/Wrapper/Mover.h"
namespace connector::record {
/*!
Wrapper to box/unbox objects during (de)serialisation, including reading/writing a specified attribute to determine object type
Note that a derived class could also define the package handler, allowing the wrapper to be created via a default constructor that is
automatically bound to a set of internally defined object types
*/
class FilterMover : public active::serialise::Mover {
public:
// MARK: - Constructors
/*!
Default constructor (primarily for a list of polymorphic objects)
*/
FilterMover();
/*!
Constructor (when it will be used for serialisation only on an existing object)
@param package A reference to the member variable
*/
FilterMover(const Package& package);
/*!
Constructor (for serialisation or deserialisation of a polymorphic member variable held in a unique pointer)
@param package A reference to the member variable
*/
FilterMover(const Package::Unique& package);
/*!
Constructor (when it will be used for serialisation only on an existing object)
@param package A reference to the member variable
*/
FilterMover(active::serialise::PackageUniqueWrap&& package);
private:
/*!
Ensure the handler is populated
*/
static void validateHandler();
///The handler for model card packages
static std::shared_ptr<active::serialise::Handler> m_handler;
};
}
#endif //CONNECTOR_MODEL_SEND_FILTER_MOVER
@@ -1,11 +1,12 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendFilter.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include <array>
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace connector::database;
using namespace connector::record;
using namespace speckle::utility;
namespace {
@@ -26,6 +27,23 @@ namespace {
}
/*--------------------------------------------------------------------
Determine if the filter has expired because an element in the selection has changed
changed: The list of changed element IDs
return: True if the one of the changed elements is in the selection
--------------------------------------------------------------------*/
bool SendFilter::checkExpiry(const ElementIDList& changed) const {
ElementIDList intersect;
ElementIDList mine{getElementIDs()}, theirs{changed};
std::sort(mine.begin(), mine.end());
std::sort(theirs.begin(), theirs.end());
std::set_intersection (mine.begin(), mine.end(), theirs.begin(), theirs.end(), std::back_inserter(intersect));
return !intersect.empty();
} //SendFilter::checkExpiry
/*--------------------------------------------------------------------
Fill an inventory with the package items
@@ -59,11 +77,11 @@ Cargo::Unique SendFilter::getCargo(const Inventory::Item& item) const {
using namespace active::serialise;
switch (item.index) {
case nameID:
return std::make_unique<ValueWrap<String>>(name);
return std::make_unique<ValueWrap<String>>(m_name);
case summaryID:
return std::make_unique<ValueWrap<String>>(summary);
return std::make_unique<ValueWrap<String>>(m_summary);
case defaultID:
return std::make_unique<ValueWrap<bool>>(isDefault);
return std::make_unique<ValueWrap<bool>>(m_isDefault);
default:
return nullptr; //Requested an unknown index
}
@@ -74,7 +92,7 @@ Cargo::Unique SendFilter::getCargo(const Inventory::Item& item) const {
Set to the default package content
--------------------------------------------------------------------*/
void SendFilter::setDefault() {
name.clear();
summary.clear();
isDefault = false;
m_name.clear();
m_summary.clear();
m_isDefault = false;
} //SendFilter::setDefault
@@ -0,0 +1,100 @@
#ifndef CONNECTOR_RECORD_SEND_FILTER
#define CONNECTOR_RECORD_SEND_FILTER
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/Cloner.h"
#include "Connector/Database/Identity/RecordID.h"
#include "Speckle/Utility/String.h"
namespace connector::record {
/*!
Base class for element filters applied when a model is sent to a Speckle server
*/
class SendFilter : public active::serialise::Package, public active::utility::Cloner {
public:
// MARK: - Types
using base = active::serialise::Package;
// MARK: - Constructors
/*!
Default constructor
@param nm The filter name
@param sum A summary
@param isDef True if this is the default filter
*/
SendFilter(const speckle::utility::String& nm = {}, const speckle::utility::String& sum = {}, bool isDef = false) :
m_name{nm}, m_summary{sum}, m_isDefault{isDef} {}
/*!
Destructor
*/
virtual ~SendFilter() {}
/*!
Object cloning
@return A clone of this object
*/
virtual SendFilter* clonePtr() const override = 0;
// MARK: - Functions (const)
/*!
Get the filter name
@return The filter name
*/
const speckle::utility::String& getName() const { return m_name; };
/*!
Get a summary description of the filter function, e.g. "All selected elements"
@return The filter summary description
*/
const speckle::utility::String& getSummary() const { return m_name; };
/*!
Determine if this is the default filter for model sends
@return True if this is the default filter
*/
bool isDefault() const { return m_isDefault; };
/*!
Get the filtered element IDs
@return The filter elements
*/
virtual const database::ElementIDList& getElementIDs() const = 0;
/*!
Determine if the filter has expired because an element in the selection has changed
@param changed The list of changed element IDs
@return True if the one of the changed elements is in the selection
*/
virtual bool checkExpiry(const database::ElementIDList& changed) const;
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///The filter name
speckle::utility::String m_name;
///A summary
speckle::utility::String m_summary;
///True if this is the default filter
bool m_isDefault = false;
};
}
#endif //CONNECTOR_RECORD_SEND_FILTER
@@ -0,0 +1,95 @@
#include "Connector/Record/Model/ModelCard.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include <array>
using namespace active::container;
using namespace active::serialise;
using namespace connector::record;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
modelID,
projectID,
accountID,
serverURLID,
settingsID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"modelId"},
Identity{"projectId"},
Identity{"accountId"},
Identity{"serverURL"},
Identity{"settings"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool ModelCard::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[modelID], modelID, element },
{ fieldID[projectID], projectID, element },
{ fieldID[accountID], accountID, element },
{ fieldID[serverURLID], serverURLID, element },
{ fieldID[settingsID], settingsID, element },
},
}.withType(&typeid(ModelCard)));
return base::fillInventory(inventory);
} //ModelCard::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique ModelCard::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(ModelCard))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case modelID:
return std::make_unique<ValueWrap<String>>(m_modelID);
case projectID:
return std::make_unique<ValueWrap<String>>(m_projectID);
case accountID:
return std::make_unique<ValueWrap<String>>(m_accountID);
case serverURLID:
return std::make_unique<ValueWrap<String>>(m_serverURL);
case settingsID:
return std::make_unique<ContainerWrap<Vector<CardSetting>>>(m_settings);
default:
return nullptr; //Requested an unknown index
}
} //ModelCard::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void ModelCard::setDefault() {
base::setDefault();
m_modelID.clear();
m_projectID.clear();
m_accountID.clear();
m_serverURL.clear();
m_settings.clear();
} //ModelCard::setDefault
@@ -0,0 +1,115 @@
#ifndef CONNECTOR_RECORD_MODEL_CARD
#define CONNECTOR_RECORD_MODEL_CARD
#include "Active/Container/Vector.h"
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/Cloner.h"
#include "Connector/Record/Model/CardSetting.h"
#include "Speckle/Utility/String.h"
#include "Speckle/Database/Content/Record.h"
namespace connector::record {
/*!
A connector send filter
*/
class ModelCard : public speckle::database::Record {
public:
// MARK: - Types
using base = speckle::database::Record;
//List of card settings
using SettingList = active::container::Vector<connector::record::CardSetting>;
// MARK: - Constructors
/*!
Default constructor
*/
ModelCard() {}
/*!
Constructor
@param modelID The model ID
@param projectID The project ID
@param accountID The account ID
@param serverURL The server URL
@param settings Any BIM host-related settings relevant to the appearance/rendering of the model, e.g. LoD, if properties included etc
*/
ModelCard(const speckle::database::RecordID& modelID, const speckle::database::RecordID& projectID,
const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL,
const SettingList& settings) :
m_modelID(modelID), m_projectID(projectID), m_accountID(accountID), m_serverURL(serverURL), m_settings(settings) {}
/*!
Destructor
*/
virtual ~ModelCard() {}
/*!
Record cloning
@return A clone of this record
*/
virtual ModelCard* clonePtr() const override { return new ModelCard(*this); };
// MARK: - Functions (const)
/*!
Get the model ID
@return The model ID
*/
const speckle::utility::String& getModelID() const { return m_modelID; }
/*!
Get the setting type
@return The setting type
*/
const speckle::utility::String& getProjectID() const { return m_projectID; }
/*!
Get the setting type
@return The setting type
*/
const speckle::utility::String& getAccountID() const { return m_accountID; }
/*!
Get the setting type
@return The setting type
*/
const speckle::utility::String& getServerURL() const { return m_serverURL; }
/*!
Get the card settings
@return The card settings
*/
const SettingList& getSettings() const { return m_settings; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///The model ID
speckle::database::RecordID m_modelID;
///The project ID
speckle::database::RecordID m_projectID;
///The user account ID
speckle::database::RecordID m_accountID;
///The server URL
speckle::utility::String m_serverURL;
///Settings for the model rendering, e.g. level of detail (LoD)
SettingList m_settings;
};
}
#endif //CONNECTOR_RECORD_MODEL_CARD
@@ -0,0 +1,102 @@
#include "Connector/Record/Model/ReceiverModelCard.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include <array>
using namespace active::serialise;
using namespace connector::database;
using namespace connector::record;
using namespace speckle::database;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
projectNameID,
modelNameID,
selectedVersionID,
latestVersionID,
warningDismissedID,
bakedObjectsID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"projectName"},
Identity{"modelName"},
Identity{"selectedVersionID"},
Identity{"latestVersionID"},
Identity{"hasDismissedUpdateWarning"},
Identity{"bakedObjectIds"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool ReceiverModelCard::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[projectNameID], projectNameID, element },
{ fieldID[modelNameID], modelNameID, element },
{ fieldID[selectedVersionID], selectedVersionID, element },
{ fieldID[latestVersionID], latestVersionID, element },
{ fieldID[warningDismissedID], warningDismissedID, element },
{ fieldID[bakedObjectsID], bakedObjectsID, element },
},
}.withType(&typeid(ReceiverModelCard)));
return base::fillInventory(inventory);
} //ReceiverModelCard::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique ReceiverModelCard::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(ReceiverModelCard))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case projectNameID:
return std::make_unique<StringWrap>(m_projectName);
case modelNameID:
return std::make_unique<StringWrap>(m_modelName);
case selectedVersionID:
return std::make_unique<ValueWrap<RecordID>>(m_selectedVersionID);
case latestVersionID:
return std::make_unique<ValueWrap<RecordID>>(m_latestVersionID);
case warningDismissedID:
return std::make_unique<BoolWrap>(m_hasDismissedUpdateWarning);
case bakedObjectsID:
return std::make_unique<ContainerWrap<ElementIDList>>(m_bakedObjectIDs);
default:
return nullptr; //Requested an unknown index
}
} //ReceiverModelCard::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void ReceiverModelCard::setDefault() {
base::setDefault();
m_projectName.clear();
m_modelName.clear();
m_selectedVersionID.clear();
m_latestVersionID.clear();
m_hasDismissedUpdateWarning = false;
m_bakedObjectIDs.clear();
} //ReceiverModelCard::setDefault
@@ -0,0 +1,119 @@
#ifndef CONNECTOR_RECORD_RECEIVER_MODEL_CARD
#define CONNECTOR_RECORD_RECEIVER_MODEL_CARD
#include "Connector/Database/Identity/RecordID.h"
#include "Connector/Record/Model/ModelCard.h"
namespace connector::record {
class SendFilter;
/*!
A connector model send card - carries information about what was sent with the model
*/
class ReceiverModelCard : public connector::record::ModelCard {
public:
// MARK: - Types
using base = connector::record::ModelCard;
// MARK: - Constructors
/*!
Default constructor
*/
ReceiverModelCard() {}
/*!
Constructor
@param projectName The project name
@param modelName The model name
@param selectedVersion The selected version ID
@param latestVersion The latest version ID
@param hasDimissedWarning True if the user has already dismissed an alert to update
@param bakedObjects The IDs of objects accepted in the receive
*/
ReceiverModelCard(const speckle::database::RecordID& projectID, const speckle::utility::String& projectName,
const speckle::database::RecordID& modelID, const speckle::utility::String& modelName,
const speckle::database::RecordID& selectedVersion, const speckle::database::RecordID& latestVersion,
const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL,
bool hasDimissedWarning, database::ElementIDList&& bakedObjects, const SettingList& settings) :
ModelCard{modelID, projectID, accountID, serverURL, settings},
m_projectName{projectName}, m_modelName{modelName}, m_selectedVersionID{selectedVersion}, m_latestVersionID{latestVersion},
m_hasDismissedUpdateWarning{hasDimissedWarning}, m_bakedObjectIDs{bakedObjects} {}
/*!
Record cloning
@return A clone of this record
*/
virtual ReceiverModelCard* clonePtr() const override { return new ReceiverModelCard(*this); };
// MARK: - Functions (const)
/*!
Get the project name
@return The project name
*/
const speckle::utility::String& getProjectName() const { return m_projectName; }
/*!
Get the model name
@return The model name
*/
const speckle::utility::String& getModelName() const { return m_modelName; }
/*!
Get the selected version ID
@return The selected version ID
*/
const speckle::database::RecordID& getSelectedVersionID() const { return m_selectedVersionID; }
/*!
Get the latest version ID
@return The latest version ID
*/
const speckle::database::RecordID& getLatestVersionID() const { return m_latestVersionID; }
/*!
Determine if the user has already dismissed an alert to update
@return True if the user has already dismissed an alert to update
*/
bool hasDismissedUpdateWarning() const { return m_hasDismissedUpdateWarning; }
/*!
Get the IDs of objects accepted in the receive
@return The accepted object IDs
*/
const database::ElementIDList& getBakedObjectIDs() const { return m_bakedObjectIDs; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///The received project name
speckle::utility::String m_projectName;
///The received model name
speckle::utility::String m_modelName;
///The ID of the version selected in the receive
speckle::database::RecordID m_selectedVersionID;
///The ID of the latest version
speckle::database::RecordID m_latestVersionID;
///True if the user has already dismissed an alert to update
bool m_hasDismissedUpdateWarning = false;
///IDs of objects accepted in the receive
database::ElementIDList m_bakedObjectIDs;
};
}
#endif //CONNECTOR_RECORD_RECEIVER_MODEL_CARD
@@ -0,0 +1,108 @@
#include "Connector/Record/Model/SenderModelCard.h"
#include "Active/Serialise/Package/Wrapper/PackageUniqueWrap.h"
#include "Connector/Record/Model/Filter/FilterMover.h"
#include "Connector/Record/Model/Filter/SendFilter.h"
#include <array>
using namespace active::serialise;
using namespace connector::record;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
sendFilterID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"sendFilter"},
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
SenderModelCard::SenderModelCard() {
} //SenderModelCard::SenderModelCard
/*--------------------------------------------------------------------
Constructor
filter: The filter applied when the model was sent
--------------------------------------------------------------------*/
SenderModelCard::SenderModelCard(const SendFilter& filter, const speckle::database::RecordID& modelID, const speckle::database::RecordID& projectID,
const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL, const SettingList& settings) :
ModelCard{modelID, projectID, accountID, serverURL, settings}, m_filter(clone(filter))
{
} //SenderModelCard::SenderModelCard
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
SenderModelCard::SenderModelCard(const SenderModelCard& source) : ModelCard{source} {
m_filter = (source.m_filter) ? clone(*source.m_filter) : nullptr;
} //SenderModelCard::SenderModelCard
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
SenderModelCard::~SenderModelCard() {
} //SenderModelCard::~SenderModelCard
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool SenderModelCard::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[sendFilterID], sendFilterID, element },
},
}.withType(&typeid(SenderModelCard)));
return base::fillInventory(inventory);
} //SenderModelCard::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SenderModelCard::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(SenderModelCard))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case sendFilterID:
return std::make_unique<FilterMover>(PackageUniqueWrap{m_filter});
default:
return nullptr; //Requested an unknown index
}
} //SenderModelCard::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void SenderModelCard::setDefault() {
base::setDefault();
m_filter->setDefault();
} //SenderModelCard::setDefault
@@ -0,0 +1,81 @@
#ifndef CONNECTOR_RECORD_SENDER_MODEL_CARD
#define CONNECTOR_RECORD_SENDER_MODEL_CARD
#include "Connector/Record/Model/ModelCard.h"
namespace connector::record {
class SendFilter;
/*!
A connector model send card - carries information about what was sent with the model
*/
class SenderModelCard : public connector::record::ModelCard {
public:
// MARK: - Types
using base = connector::record::ModelCard;
// MARK: - Constructors
/*!
Default constructor
*/
SenderModelCard();
/*!
Constructor
@param filter The filter applied when the model was sent
*/
SenderModelCard(const SendFilter& filter, const speckle::database::RecordID& modelID, const speckle::database::RecordID& projectID,
const speckle::database::RecordID& accountID, const speckle::utility::String& serverURL, const SettingList& settings);
/*!
Copy constructor
@param source The object to copy
*/
SenderModelCard(const SenderModelCard& source);
/*!
Destructor
*/
~SenderModelCard();
/*!
Record cloning
@return A clone of this record
*/
virtual SenderModelCard* clonePtr() const override { return new SenderModelCard(*this); };
// MARK: - Functions (const)
/*!
Get the filter applied when the model was sent
@return The model filter
*/
const SendFilter& getFilter() const { return *m_filter; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///The filter applied when the model was sent
std::unique_ptr<SendFilter> m_filter;
};
}
#endif //CONNECTOR_RECORD_SENDER_MODEL_CARD
+1 -1
View File
@@ -7,7 +7,7 @@ namespace connector {
static const unsigned int versionMinor = 2;
static const unsigned int versionPatch = 2;
static const unsigned int versionPatch = 3;
}
@@ -56,7 +56,7 @@ AccountDatabase::AccountDatabase(const active::file::Path& path) {
//Create accounts database storage (with schema)
m_store = std::make_unique<Store>(
//Engine
std::make_unique<AccountsEngine>(path,
std::make_shared<AccountsEngine>(path,
//Schema
DBaseSchema{active::utility::String{accountsDBaseName},
//Tables
+10 -3
View File
@@ -3,18 +3,19 @@
#include "Active/Database/Content/Record.h"
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Database/Identity/RecordID.h"
namespace speckle::database {
/*!
Base class for a database record
*/
class Record : public active::database::Record<speckle::utility::String, speckle::utility::String, speckle::utility::String> {
class Record : public active::database::Record<RecordID> {
public:
// MARK: - Types
using base = active::database::Record<speckle::utility::String, speckle::utility::String, speckle::utility::String>;
using base = active::database::Record<RecordID>;
///Unique pointer
using Unique = std::unique_ptr<Record>;
///Shared pointer
@@ -24,11 +25,17 @@ namespace speckle::database {
// MARK: - Constructors
/*!
Default constructor
*/
Record() : base{active::utility::Guid{true}.operator active::utility::String(),
active::utility::Guid{true}.operator active::utility::String()} {} //TODO: Implement a better default for the ID
/*!
Constructor
@param ID The record ID
*/
Record(speckle::utility::String ID) : base{ID} {}
Record(speckle::utility::String ID, speckle::utility::String::Option globID = std::nullopt) :
base{ID, globID.value_or(active::utility::Guid{true}.operator active::utility::String())} {}
/*!
Destructor
*/
+5 -2
View File
@@ -2,8 +2,11 @@
#define SPECKLE_DATABASE_INDEX
#include "Active/Database/Identity/Link.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Utility/String.h"
#include <any>
namespace speckle::database {
/*!
@@ -13,12 +16,12 @@ namespace speckle::database {
this is typically a guid, for Revit a string and for Vectorworks a handle. Note that this index is not necessarily persistent between
sessions.
*/
class Index : public active::database::Index<speckle::utility::String, speckle::utility::String, speckle::utility::String> {
class Index : public active::database::Index<RecordID> {
public:
// MARK: - Types
using base = active::database::Index<speckle::utility::String, speckle::utility::String, speckle::utility::String>;
using base = active::database::Index<RecordID>;
// MARK: - Constructors
+2 -2
View File
@@ -17,12 +17,12 @@ namespace speckle::database {
A link may optionally carry any number of settings. In the context of a user selection (for example) there might be settings describing where
the user made the selection (e.g. the hole in a floor slab), allowing a tool working on that selection to be more precise.
*/
class Link : public active::database::Link<speckle::utility::String, speckle::utility::String, speckle::utility::String> {
class Link : public active::database::Link<RecordID> {
public:
// MARK: - Types
using base = active::database::Link<speckle::utility::String, speckle::utility::String, speckle::utility::String>;
using base = active::database::Link<RecordID>;
// MARK: - Constructors
@@ -0,0 +1,20 @@
#ifndef SPECKLE_DATABASE_ID
#define SPECKLE_DATABASE_ID
#include "Speckle/Utility/String.h"
namespace speckle::database {
//Common Speckle record identifier type
using RecordID = speckle::utility::String;
//Common Speckle table identifier type
using TableID = speckle::utility::String;
//Common Speckle database identifier type
using DBaseID = speckle::utility::String;
//A list of record IDs
using RecordIDList = std::vector<RecordID>;
}
#endif //SPECKLE_DATABASE_ID
@@ -0,0 +1,297 @@
#include "Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h"
#include "Active/Utility/Defer.h"
#include "Active/Utility/Memory.h"
#include "Active/Utility/String.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Event/Type/DocStoreMergeEvent.h"
#include "Speckle/Event/Type/ProjectEvent.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#include <BM.hpp>
#endif
using namespace active::event;
using namespace active::setting;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
using namespace speckle::utility;
using enum DocumentStoreCore::Status;
namespace {
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Convert an Archicad API error code to a DocumentStoreCore status
acErrorCode: The API error code
return: An equivalent status code
--------------------------------------------------------------------*/
DocumentStoreCore::Status convertArchicadError(long acErrorCode) {
using enum DocumentStoreCore::Status;
switch (acErrorCode) {
case NoError:
return nominal;
case APIERR_BADPARS:
return badParameter;
case APIERR_BADID:
return badID;
default:
break;
}
return error;
} //convertArchicadError
/*--------------------------------------------------------------------
Determine if a specified data store exists
id: The store identity
return: True if the store exists
--------------------------------------------------------------------*/
bool isExistingStore(active::utility::NameID& storeID) {
if (storeID.id)
return true; //We must have a store if the ID is populated
GS::UniString storeName{String{storeID.name}};
API_Guid acID;
if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectGuidFromName(storeName, &acID)); statusCode != nominal)
throw std::system_error(DocumentStoreCore::makeError(statusCode));
storeID.id = Guid{acID};
if (!storeID.id) {
GS::Array<API_Guid> storedObjects;
ACAPI_AddOnObject_GetObjectList(&storedObjects);
for (auto iter = storedObjects.Enumerate(); iter != nullptr; ++iter) {
API_Guid objGuid = *iter;
GS::UniString objName;
GSHandle content = nullptr;
auto scope = active::utility::defer([&content](){ BMKillHandle(&content); });
if (ACAPI_AddOnObject_GetObjectContent(objGuid, &objName, &content) == NoError) {
if (objName == storeName) {
storeID.id = Guid{objGuid};
break;
}
}
}
}
return storeID.id.operator bool(); //Returns true if the store ID is non-null, i.e. the object exists
} //isExistingStore
/*--------------------------------------------------------------------
Copy a GS handle to a Memory object
handle: The GS handle
memory: The Memory object to receive the data
--------------------------------------------------------------------*/
void copyHandleToMemory(const GSHandle& handle, active::utility::Memory& memory) {
auto storeSize = BMGetHandleSize(handle);
memory.resize(storeSize);
active::utility::Memory::copy(memory.data(), *handle, storeSize, storeSize);
} //copyHandleToMemory
#endif
///Category for DocumentStore processing errors
class DocumentStoreCategory : public std::error_category {
public:
///Category name
const char* name() const noexcept override {
return "active::database::sqlite::category";
}
/*!
Get a message for a specified error code
@param errorCode A DocumentStore processing code
@return The error message for the specified code
*/
std::string message(int errorCode) const override {
//TODO: These error messages are ok for developers - but can we help users more?
switch (static_cast<DocumentStoreCore::Status>(errorCode)) {
case nominal:
return "";
case badParameter:
return "An internal function has been incorrectly used";
case badID:
return "Internal data has been requested using an invalid identity";
case error:
return "A non-specific error occurred";
default:
return "An unknown error occurred";
}
}
};
///DocumentStore processing category error instance
static DocumentStoreCategory instance;
}
/*--------------------------------------------------------------------
Make an error code for DocumentStore processing
return: An STL error code
--------------------------------------------------------------------*/
std::error_code DocumentStoreCore::makeError(DocumentStoreCore::Status code) {
return std::error_code(static_cast<int>(code), instance);
} //DocumentStoreCore::makeError
/*--------------------------------------------------------------------
Handle a document merge operation
event: The merge event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool DocumentStoreCore::handle(const DocStoreMergeEvent& event) {
#ifdef ARCHICAD
if (event.objects == nullptr)
return false;
for (const auto& object : *event.objects) {
if (*object.name != String{m_id.name})
continue;
active::utility::Memory toMerge;
copyHandleToMemory(object.data, toMerge);
mergeStore(toMerge);
writeStore();
}
#endif
return false;
} //DocumentStoreCore::handle
/*--------------------------------------------------------------------
Handle a project event
event: The project event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool DocumentStoreCore::handle(const event::ProjectEvent& event) {
#ifdef ARCHICAD
switch (event.getType()) {
case APINotify_Close:
resetStore(); //Wipe the cache, forcing a full reload when the data is requested again (after a project is opened)
break;
case APINotify_PreSave: case APINotify_SendChanges:
writeStore(); //Ensure the data is stored with the save/send
break;
default:
break;
}
#endif
return false;
} //DocumentStoreCore::handle
/*--------------------------------------------------------------------
Read the data stored in the document
return: The stored data (empty if the data doesn't exist)
--------------------------------------------------------------------*/
active::utility::Memory DocumentStoreCore::readStore() const {
active::utility::Memory result;
//First establish that we actually have stored data to read
if (!isExistingStore(m_id))
return result;
//Read the stored data
#ifdef ARCHICAD
GS::UniString storeName{String{m_id.name}};
GSHandle storedData;
auto scoped = active::utility::defer([&storedData](){ BMKillHandle(&storedData); });
if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_GetObjectContent(Guid{m_id.id}, &storeName, &storedData)); statusCode != nominal)
throw std::system_error(makeError(statusCode));
//Copy the stored data into the result
copyHandleToMemory(storedData, result);
#endif
return result;
} //DocumentStoreCore::readStore
/*--------------------------------------------------------------------
Write the data to document storage
toWrite: The data to write to storage
--------------------------------------------------------------------*/
void DocumentStoreCore::writeStore() {
#ifdef ARCHICAD
//Ensure a suitable data store exists
if (!isExistingStore(m_id)) {
//Create when missing
API_Guid acID;
if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_CreateUniqueObject(String{m_id.name}, &acID)); statusCode != nominal)
throw std::system_error(makeError(statusCode));
m_id.id = Guid{acID};
}
//Reserve the storage object in TW
if (addon()->isSharedDocument()) {
GS::HashTable<API_Guid, short> conflicts;
if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ReserveObjects({Guid{m_id.id}}, &conflicts)); statusCode != nominal)
throw std::system_error(makeError(statusCode));
//TODO: Implamenent handling for conflicts
}
auto toWrite = buildStore();
//Write the new data
GSHandle output = BMAllocateHandle(static_cast<GSSize>(toWrite.size()), ALLOCATE_CLEAR, 0);
auto scoped = active::utility::defer([&output](){ BMKillHandle(&output); });
active::utility::Memory::copy(*output, toWrite.data(), toWrite.size(), toWrite.size());
if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ModifyObject(Guid{m_id.id}, nullptr, &output)); statusCode != nominal)
throw std::system_error(makeError(statusCode));
//Release the storage object in TW
if (addon()->isSharedDocument()) {
if (auto statusCode = convertArchicadError(ACAPI_AddOnObject_ReleaseObjects({Guid{m_id.id}})); statusCode != nominal)
throw std::system_error(makeError(statusCode));
}
#endif
} //DocumentStoreCore::writeStore
/*--------------------------------------------------------------------
Get the event subscription list
return: The subscription list (an empty list will put the subscriber into a suspended state)
--------------------------------------------------------------------*/
Subscriber::Subscription DocumentStoreCore::subscription() const {
auto result = DocStoreSubscriber::subscription();
auto other = ProjectSubscriber::subscription();
result.insert(other.begin(), other.end());
return result;
} //DocumentStoreCore::subscription
/*--------------------------------------------------------------------
Receive a subscribed event
event: The incoming event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool DocumentStoreCore::receive(const active::event::Event& event) {
return DocStoreSubscriber::receive(event) || ProjectSubscriber::receive(event);
} //DocumentStoreCore::receive
/*--------------------------------------------------------------------
Attach participant components to the app (as required)
return: True if the participant is able to function
--------------------------------------------------------------------*/
bool DocumentStoreCore::attach() {
return DocStoreSubscriber::attach() && ProjectSubscriber::attach();
} //DocumentStoreCore::attach
/*--------------------------------------------------------------------
Start the participant operation
return: True if the participant is able to continue
--------------------------------------------------------------------*/
bool DocumentStoreCore::start() {
return DocStoreSubscriber::start() && ProjectSubscriber::start();
} //DocumentStoreCore::start
@@ -0,0 +1,142 @@
#ifndef SPECKLE_DATABASE_DOCUMENT_STORE_CORE
#define SPECKLE_DATABASE_DOCUMENT_STORE_CORE
#include "Active/File/Path.h"
#include "Active/Setting/SettingList.h"
#include "Active/Database/Storage/DBaseSchema.h"
#include "Active/Utility/NameID.h"
#include "Speckle/Event/Subscriber/DocStoreSubscriber.h"
#include "Speckle/Event/Subscriber/ProjectSubscriber.h"
namespace speckle::database {
using DocumentStoreSchema = active::database::DBaseSchema<>;
/*!
Core functionality and definitions for a mechanism to store data in a BIM (3rd-party) document/database
Currently implement for Archicad Add-On Objects
*/
class DocumentStoreCore : public event::DocStoreSubscriber, public event::ProjectSubscriber {
public:
// MARK: - Types
///Status of of the DocumentStore database
enum class Status {
nominal, ///<No errors logged
badParameter, ///<The data supplied to an SDK function call was invalid
badID, ///<The ID for the stored data is invalid
error, ///<An unidentified error occurred
};
// MARK: - Static functions
/*!
Make an error code for DocumentStore processing
@return An STL error code
*/
static std::error_code makeError(DocumentStoreCore::Status code);
// MARK: - Constructors
/*!
Default constructor
@param id The document storage identifier
@param schema The document storage schema
*/
DocumentStoreCore(const active::utility::NameID& id, DocumentStoreSchema&& schema) : m_id(id), m_schema{schema} {}
DocumentStoreCore(const DocumentStoreCore&) = default;
/*!
Destructor
*/
virtual ~DocumentStoreCore() {}
// MARK: - Function (const)
/*!
Get the database schema
@return The database schema
*/
const DocumentStoreSchema& getSchema() const { return m_schema; }
/*!
Get the database id
@return The database id
*/
const active::utility::NameID& getID() const { return m_id; }
// MARK: - Functions (mutating)
/*!
Handle a document merge operation
@param event The merge event
@return True if the event should be closed
*/
bool handle(const event::DocStoreMergeEvent& event) override;
/*!
Handle a project event
@param event The project event
@return True if the event should be closed
*/
bool handle(const event::ProjectEvent& event) override;
protected:
/*!
Read the data stored in the document (should be lazy-loading, only at the point where data is actually requested)
@return The stored data (empty if the data doesn't exist)
*/
active::utility::Memory readStore() const;
/*!
Write the data to document storage (currently happens at every change - could implement delayed storage until the point of send/save)
*/
void writeStore();
/*!
Build new store data from the latest records
@return Data to store from the latest records
*/
virtual active::utility::Memory buildStore() = 0;
/*!
Merge existing stored data with incoming stored data (from an external source)
@param toMerge The external stored data to merge
*/
virtual void mergeStore(const active::utility::Memory& toMerge) = 0;
/*!
Reset the stored data (some external change has invalidated previous data, e.g. the document was closed)
*/
virtual void resetStore() { m_id.id.clear(); }
// MARK: Subscriber functions
/*!
Get the event subscription list
@return The subscription list (an empty list will put the subscriber into a suspended state)
*/
Subscription subscription() const override;
/*!
Receive a subscribed event
@param event The incoming event
@return True if the event should be closed
*/
bool receive(const active::event::Event& event) override;
/*!
Attach participant components to the app (as required)
@return True if the participant is able to function
*/
bool attach() override;
/*!
Start the participant operation
@return True if the participant is able to continue
*/
bool start() override;
private:
///The database schema
DocumentStoreSchema m_schema;
///The database ID (mutable to allow lazy loading when data is accessed)
mutable active::utility::NameID m_id;
};
}
#endif //SPECKLE_DATABASE_DOCUMENT_STORE_CORE
@@ -0,0 +1,322 @@
#ifndef SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
#define SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
#include "Active/Database/Concepts.h"
#include "Active/Database/Storage/DBaseEngine.h"
#include "Active/Database/Storage/RecordCache.h"
#include "Active/File/Path.h"
#include "Active/Serialise/Cargo.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Active/Serialise/Transport.h"
#include "Active/Utility/BufferIn.h"
#include "Active/Utility/BufferOut.h"
#include "Speckle/Database/Storage/DocumentStore/DocumentStoreCore.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <algorithm>
#include <ranges>
namespace speckle::database {
///Concept for the ability to store objects in a document
template<typename Obj, typename ObjWrapper, typename Transport>
concept DocumentStorable = (active::database::CanWrap<Obj, ObjWrapper> || active::database::FlatType<Obj, ObjWrapper>) &&
std::is_base_of_v<active::serialise::Cargo, Obj> &&
std::is_base_of_v<active::serialise::Transport, Transport>;
/*!
A database engine to store records in a 3rd-party BIM document
Due to the fact that these records are intended to represent a single table and are stored in a document, the concepts of 'table' and
'document' aren't currently applicable (this could be extended in future if there is a use-case)
@tparam Obj Interface for the stored object. NB: This can be a base class for an object hierarchy, not necessarily a concrete class
@tparam ObjWrapper Wrapper type for (de)serialising objects
@tparam Transport The serialisation transport mechanism for objects
@tparam ObjID The object identifier type, e.g. Guid
*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID = RecordID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
class DocumentStoreEngine : public DocumentStoreCore, public active::database::DBaseEngine<Obj, ObjID, RecordID, RecordID> {
public:
// MARK: - Types
using base = active::database::DBaseEngine<Obj, ObjID, RecordID, RecordID>;
using Filter = base::Filter;
using Outline = base::Outline;
using Cache = active::database::RecordCache<Obj, ObjWrapper, ObjID, RecordID, RecordID>;
// MARK: - Constructors
/*!
Constructor
@param id The document storage identifier
*/
DocumentStoreEngine(const active::utility::NameID& id, DocumentStoreSchema&& schema) : DocumentStoreCore{id, std::move(schema)} {}
DocumentStoreEngine(const DocumentStoreEngine&) = delete;
// MARK: - Functions (const)
/*!
Get an object by index
@param ID The object ID
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested object (nullptr on failure)
*/
std::unique_ptr<Obj> getObject(const ObjID& objID, std::optional<RecordID> tableID = std::nullopt, std::optional<RecordID> documentID = std::nullopt) const override;
/*!
Get all objects
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The requested objects (nullptr on failure)
*/
active::container::Vector<Obj> getObjects(std::optional<RecordID> tableID = std::nullopt, std::optional<RecordID> documentID = std::nullopt) const override;
/*!
Get a filtered list of objects
@param filter The object filter
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The filtered objects (nullptr on failure)
*/
active::container::Vector<Obj> getObjects(const Filter& filter, std::optional<RecordID> tableID = std::nullopt,
std::optional<RecordID> documentID = std::nullopt) const override;
/*!
Write an object to the database
@param object The object to write
@param objID The object ID
@param objDocID The object document-specific ID (unique within a specific document - nullopt if not document-bound)
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
void write(const Obj& object, const ObjID& objID, std::optional<ObjID> objDocID = std::nullopt,
std::optional<RecordID> tableID = std::nullopt, std::optional<RecordID> documentID = std::nullopt) const override;
/*!
Erase an object by index
@param ID The object ID
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(const ObjID& ID, std::optional<RecordID> tableID = std::nullopt,
std::optional<RecordID> documentID = std::nullopt) const override;
/*!
Erase all objects
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(std::optional<RecordID> tableID = std::nullopt, std::optional<RecordID> documentID = std::nullopt) const override;
/*!
Get the database outline
@return The database outline
*/
Outline getOutline() const override;
protected:
/*!
Get the cache of records built from the data stored in the document
@return The cached records
*/
Cache* getCache() const;
/*!
Build new store data from the latest records
@return Data to store from the latest records
*/
active::utility::Memory buildStore() override;
/*!
Merge existing stored data with incoming stored data (from an external source)
@param toMerge The external stored data to merge
@return The merged data to be stored
*/
void mergeStore(const active::utility::Memory& toMerge) override;
/*!
Reset the stored data (some external change has invalidated previous data, e.g. the document was closed)
*/
void resetStore() override {
DocumentStoreCore::resetStore();
m_cache.reset();
}
private:
//Cached records from the document store
mutable std::unique_ptr<Cache> m_cache;
};
/*--------------------------------------------------------------------
Get the cache of records built from the data stored in the document
return: The cached records (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
typename DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::Cache* DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getCache() const {
if (m_cache)
return m_cache.get();
//Read the data stored in the document
auto storedData = readStore();
m_cache = std::make_unique<Cache>();
if (!storedData)
return m_cache.get(); //Return an empty container if there's no data
//Import the document data into the record cache
if constexpr (std::is_same_v<ObjWrapper, Obj>)
Transport().receive(std::forward<active::serialise::Cargo&&>(*m_cache), active::serialise::Identity{}, storedData);
else
Transport().receive(ObjWrapper{*m_cache}, active::serialise::Identity{}, storedData);
return m_cache.get();
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getCache
/*--------------------------------------------------------------------
Get an object by index
index: The object index
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (when the object is bound to a specific document)
return: The requested object (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
std::unique_ptr<Obj> DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObject(const ObjID& ID, std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
return getCache()->read(ID);
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObject
/*--------------------------------------------------------------------
Get all objects
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
active::container::Vector<Obj> DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObjects(std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
return getCache()->read();
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObjects
/*--------------------------------------------------------------------
Get all objects
filter: The object filter
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
active::container::Vector<Obj> DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObjects(const Filter& filter, std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
return getCache()->read(filter);
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getObjects
/*--------------------------------------------------------------------
Write an object to the database
object: The object to write
objID: The object ID
objDocID: The object document-specific ID (unique within a specific document - nullopt if not document-bound)
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (when the object is bound to a specific document)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::write(const Obj& object, const ObjID& objID, std::optional<ObjID> objDocID,
std::optional<RecordID> tableID, std::optional<RecordID> documentID) const {
getCache()->write(object); //NB: In future we might support duplicating records if objID != obj.id
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::write
/*--------------------------------------------------------------------
Erase an object by index
objID: The object ID
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (when the object is bound to a specific document)
return: True if the object was successfully erased
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::erase(const ObjID& ID, std::optional<RecordID> tableID,
std::optional<RecordID> documentID) const {
getCache()->erase(ID);
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::erase
/*--------------------------------------------------------------------
Erase all objects
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::erase(std::optional<RecordID> tableID, std::optional<RecordID> documentID) const {
getCache()->erase();
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::erase
/*--------------------------------------------------------------------
Get the database outline
return: The database outline
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::Outline DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getOutline() const {
Outline result;
if (getSchema().empty())
return result;
//NB: Currently implementing only a single table in a document store
result.emplace_back(std::make_pair(getSchema()[0].ID, getCache()->keys()));
return result;
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::getOutline
/*--------------------------------------------------------------------
Build new store data from the latest records
return: Data to store from the latest records
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
active::utility::Memory DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::buildStore() {
active::utility::Memory result;
Transport().send(std::forward<active::serialise::Cargo&&>(*getCache()), active::serialise::Identity{}, result);
return result;
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::buildStore
/*--------------------------------------------------------------------
Merge existing stored data with incoming stored data (from an external source)
toMerge: The external stored data to merge
return: The merged data to be stored
--------------------------------------------------------------------*/
template<typename Obj, typename ObjWrapper, typename Transport, typename ObjID>
requires DocumentStorable<Obj, ObjWrapper, Transport>
void DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::mergeStore(const active::utility::Memory& toMerge) {
//Import the incoming records from the data to merge
Cache incoming;
if constexpr (std::is_same_v<ObjWrapper, Obj>)
Transport().receive(std::forward<active::serialise::Cargo&&>(incoming), active::serialise::Identity{}, toMerge);
else
Transport().receive(ObjWrapper{incoming}, active::serialise::Identity{}, toMerge);
//Get the data currently stored in the document
getCache()->merge(std::forward<Cache&&>(incoming));
} //DocumentStoreEngine<Obj, ObjWrapper, Transport, ObjID>::mergeStore
}
#endif //SPECKLE_DATABASE_DOCUMENT_STORE_ENGINE
+17 -1
View File
@@ -46,11 +46,27 @@ String Addon::getLocalString(short itemIndex, short resourceIndex) const {
RSGetIndString(&string, itemIndex, resourceIndex, ACAPI_GetOwnResModule());
return string;
#else
return String{}
return String{};
#endif
} //Addon::getLocalString
/*--------------------------------------------------------------------
Determine if the active document is shared (in collaborative environments)
return: True if the active document is shared
--------------------------------------------------------------------*/
bool Addon::isSharedDocument() const {
#ifdef ARCHICAD
API_ProjectInfo pi{};
ACAPI_ProjectOperation_Project(&pi);
return pi.teamwork;
#else
return false;
#endif
} //Addon::isSharedDocument
/*--------------------------------------------------------------------
Publish an event from an external source to subscribers
+5
View File
@@ -38,6 +38,11 @@ namespace speckle::environment {
@return The localised string
*/
speckle::utility::String getLocalString(short itemIndex, short resourceIndex) const;
/*!
Determine if the active document is shared (in collaborative environments)
@return True if the active document is shared
*/
bool isSharedDocument() const;
// MARK: - Functions (mutating)
@@ -0,0 +1,88 @@
#include "Speckle/Event/Subscriber/DocStoreSubscriber.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Event/Type/DocStoreMergeEvent.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#endif
using namespace active::environment;
using namespace active::event;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
namespace {
#ifdef ARCHICAD
/*!
Callback for an Archicad document merge operation
@param sourceObjects The source document objects to merge
*/
GSErrCode __ACENV_CALL docMergeCallback(const GS::Array<API_AddonObject>& sourceObjects) {
if (addon() != nullptr)
addon()->publishExternal(DocStoreMergeEvent{sourceObjects});
return NoError;
}
#endif
}
//True if a doc merge subscriber has already started (only one is required - there are no variants)
bool speckle::event::DocStoreSubscriber::m_isStarted = false;
/*--------------------------------------------------------------------
Get the event subscription list
return: The subscription list (an empty list will put the subscriber into a suspended state)
--------------------------------------------------------------------*/
Subscriber::Subscription DocStoreSubscriber::subscription() const {
return { {DocStoreMergeEvent::ID} };
} //DocStoreSubscriber::subscription
/*--------------------------------------------------------------------
Receive a subscribed event
event: The incoming event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool DocStoreSubscriber::receive(const Event& event) {
//Pass a menu event to the specified handler function
if (auto docEvent = dynamic_cast<const DocStoreMergeEvent*>(&event); docEvent != nullptr)
return handle(*docEvent);
return false;
} //DocStoreSubscriber::receive
/*--------------------------------------------------------------------
Attach participant components to the app (as required)
return: True if the participant is able to function
--------------------------------------------------------------------*/
bool DocStoreSubscriber::attach() {
#ifdef ARCHICAD
ACAPI_AddOnObject_RegisterAddOnObjectHandler();
#endif
return true;
} //DocStoreSubscriber::attach
/*--------------------------------------------------------------------
Start the participant operation
return: True if the participant is able to continue
--------------------------------------------------------------------*/
bool DocStoreSubscriber::start() {
if (m_isStarted)
return true;
m_isStarted = true;
#ifdef ARCHICAD
return (ACAPI_AddOnObject_InstallAddOnObjectMergeHandler(docMergeCallback) == NoError);
#else
return false;
#endif
} //DocStoreSubscriber::start
@@ -0,0 +1,74 @@
#ifndef SPECKLE_EVENT_DOC_STORE_SUBSCRIBER
#define SPECKLE_EVENT_DOC_STORE_SUBSCRIBER
#include "Active/Event/Subscriber.h"
namespace speckle::event {
class DocStoreMergeEvent;
/*!
Base class for subscribers responding to document merge operations (notably those managing custom data in the document)
*/
class DocStoreSubscriber : public virtual active::event::Subscriber {
public:
// MARK: - Constructors
/*!
Default constructor
*/
DocStoreSubscriber() = default;
/*!
Copy constructor
@param source The object to copy
*/
DocStoreSubscriber(const DocStoreSubscriber& source) = default;
/*!
Destructor
*/
virtual ~DocStoreSubscriber() {}
// MARK: - Functions (const)
/*!
Get the event subscription list
@return The subscription list (an empty list will put the subscriber into a suspended state)
*/
Subscription subscription() const override;
// MARK: - Functions (mutating)
/*!
Receive a subscribed event
@param event The incoming event
@return True if the event should be closed
*/
bool receive(const active::event::Event& event) override;
protected:
/*!
Attach participant components to the app (as required)
@return True if the participant is able to function
*/
bool attach() override;
/*!
Start the participant operation
@return True if the participant is able to continue
*/
bool start() override;
/*!
Handle a document merge operation
@param event The merge event
@return True if the event should be closed
*/
virtual bool handle(const DocStoreMergeEvent& event) = 0;
private:
///True if a doc merge subscriber has already started (only one is required - there are no variants)
static bool m_isStarted;
};
}
#endif //SPECKLE_EVENT_DOC_STORE_SUBSCRIBER
@@ -25,7 +25,7 @@ namespace speckle::event {
/*!
Base class for subscribers handling a UI menu (from the app menu bar)
*/
class MenuSubscriber : public active::event::Subscriber {
class MenuSubscriber : public virtual active::event::Subscriber {
public:
// MARK: - Constructors
@@ -0,0 +1,76 @@
#include "Speckle/Event/Subscriber/ProjectSubscriber.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Event/Type/ProjectEvent.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#endif
using namespace active::environment;
using namespace active::event;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
namespace {
#ifdef ARCHICAD
/*!
Callback for an Archicad project event
@param notifyEvent The event notification type
@param param Parameter applicable to certain events (see API docs)
*/
GSErrCode __ACENV_CALL projectCallback(API_NotifyEventID notifyEvent, Int32 param) {
if (addon() != nullptr)
addon()->publishExternal(ProjectEvent{notifyEvent, param});
return NoError;
}
#endif
}
//True if a doc merge subscriber has already started (only one is required - there are no variants)
bool speckle::event::ProjectSubscriber::m_isStarted = false;
/*--------------------------------------------------------------------
Get the event subscription list
return: The subscription list (an empty list will put the subscriber into a suspended state)
--------------------------------------------------------------------*/
Subscriber::Subscription ProjectSubscriber::subscription() const {
return { {ProjectEvent::ID} };
} //ProjectSubscriber::subscription
/*--------------------------------------------------------------------
Receive a subscribed event
event: The incoming event
return: True if the event should be closed
--------------------------------------------------------------------*/
bool ProjectSubscriber::receive(const Event& event) {
//Pass a menu event to the specified handler function
if (auto projectEvent = dynamic_cast<const ProjectEvent*>(&event); projectEvent != nullptr)
return handle(*projectEvent);
return false;
} //ProjectSubscriber::receive
/*--------------------------------------------------------------------
Start the participant operation
return: True if the participant is able to continue
--------------------------------------------------------------------*/
bool ProjectSubscriber::start() {
if (m_isStarted)
return true;
m_isStarted = true;
#ifdef ARCHICAD
return (ACAPI_ProjectOperation_CatchProjectEvent(API_AllNotificationMask, projectCallback) == NoError);
#else
return false;
#endif
} //ProjectSubscriber::start
@@ -0,0 +1,69 @@
#ifndef SPECKLE_EVENT_PROJECT_SUBSCRIBER
#define SPECKLE_EVENT_PROJECT_SUBSCRIBER
#include "Active/Event/Subscriber.h"
namespace speckle::event {
class ProjectEvent;
/*!
Base class for subscribers responding to project events (open, close, quit etc)
*/
class ProjectSubscriber : public virtual active::event::Subscriber {
public:
// MARK: - Constructors
/*!
Default constructor
*/
ProjectSubscriber() = default;
/*!
Copy constructor
@param source The object to copy
*/
ProjectSubscriber(const ProjectSubscriber& source) = default;
/*!
Destructor
*/
virtual ~ProjectSubscriber() {}
// MARK: - Functions (const)
/*!
Get the event subscription list
@return The subscription list (an empty list will put the subscriber into a suspended state)
*/
Subscription subscription() const override;
// MARK: - Functions (mutating)
/*!
Receive a subscribed event
@param event The incoming event
@return True if the event should be closed
*/
bool receive(const active::event::Event& event) override;
protected:
/*!
Start the participant operation
@return True if the participant is able to continue
*/
bool start() override;
/*!
Handle a project event
@param event The project event
@return True if the event should be closed
*/
virtual bool handle(const ProjectEvent& event) = 0;
private:
///True if a doc merge subscriber has already started (only one is required - there are no variants)
static bool m_isStarted;
};
}
#endif //SPECKLE_EVENT_PROJECT_SUBSCRIBER
@@ -4,6 +4,10 @@
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Event/Type/SelectionEvent.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#endif
using namespace active::environment;
using namespace active::event;
using namespace speckle::database;
@@ -28,6 +32,9 @@ namespace {
}
//True if a selection change subscriber has already started (only one is required - there are no variants)
bool speckle::event::SelectionSubscriber::m_isStarted = false;
/*--------------------------------------------------------------------
Get the event subscription list
@@ -59,6 +66,9 @@ bool SelectionSubscriber::receive(const Event& event) {
return: True if the participant is able to continue
--------------------------------------------------------------------*/
bool SelectionSubscriber::start() {
if (m_isStarted)
return true;
m_isStarted = true;
#ifdef ARCHICAD
return (ACAPI_Notification_CatchSelectionChange(selectionCallback) == NoError);
#else
@@ -3,18 +3,14 @@
#include "Active/Event/Subscriber.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
#endif
namespace speckle::event {
class SelectionEvent;
/*!
Base class for subscribers responding to selectionm changes
Base class for subscribers responding to selection changes
*/
class SelectionSubscriber : public active::event::Subscriber {
class SelectionSubscriber : public virtual active::event::Subscriber {
public:
// MARK: - Constructors
@@ -65,7 +61,7 @@ namespace speckle::event {
private:
///True if a selection change subscriber has already started (only one is required - there are no variants)
int32_t m_isStarted = false;
static bool m_isStarted;
};
}
@@ -0,0 +1,42 @@
#ifndef SPECKLE_EVENT_DOC_STORE_MERGE_EVENT
#define SPECKLE_EVENT_DOC_STORE_MERGE_EVENT
#include "Active/Event/Event.h"
#include "Active/Utility/Guid.h"
#include "Active/Utility/String.h"
namespace speckle::event {
/*!
Class representing a document merge event, e.g. merging an external document
*/
class DocStoreMergeEvent : public active::event::Event {
public:
static const inline active::utility::NameID ID{active::utility::String{"document store merge"},
active::utility::Guid{active::utility::String{"c92e2c51-d47c-44e3-a54f-5068dccaa35a"}}};
// MARK: - Constructors
/*!
Default constructor
*/
DocStoreMergeEvent() : Event{ID} {}
#ifdef ARCHICAD
/*!
Constructor
@param incoming Incoming document objects to merge
*/
DocStoreMergeEvent(const GS::Array<API_AddonObject>& incoming) : Event{ID} { objects = &incoming; }
#endif
#ifdef ARCHICAD
//Incoming document objects to merge
const GS::Array<API_AddonObject>* objects = nullptr;
#endif
};
}
#endif //SPECKLE_EVENT_DOC_STORE_MERGE_EVENT
@@ -0,0 +1,58 @@
#ifndef SPECKLE_EVENT_PROJECT_EVENT
#define SPECKLE_EVENT_PROJECT_EVENT
#include "Active/Event/Event.h"
#include "Active/Utility/Guid.h"
#include "Active/Utility/String.h"
namespace speckle::event {
/*!
Class representing a selection change event
*/
class ProjectEvent : public active::event::Event {
public:
static const inline active::utility::NameID ID{active::utility::String{"project event"},
active::utility::Guid{active::utility::String{"0ffb9ec5-2164-4fc2-aa57-17b5a1f15355"}}};
// MARK: - Constructors
/*!
Default constructor
*/
ProjectEvent() : Event{ID} {}
#ifdef ARCHICAD
/*!
Constructor
@param notifyEvent The project event type
@param param An additional parameter relevant to some project events
*/
ProjectEvent(API_NotifyEventID notifyEvent, int32_t param) : Event{ID} {
m_eventID = notifyEvent;
m_param = param;
}
/*!
Get the event type
@return The event type
*/
API_NotifyEventID getType() const { return m_eventID; }
/*!
Get the event parameter
@return The event parameter
*/
int32_t getParam() const { return m_param; }
#endif
#ifdef ARCHICAD
//Incoming document objects to merge
API_NotifyEventID m_eventID;
int32_t m_param;
#endif
};
}
#endif //SPECKLE_EVENT_PROJECT_EVENT
@@ -21,7 +21,7 @@ using namespace speckle::utility;
/*--------------------------------------------------------------------
Constructor
--------------------------------------------------------------------*/
GetCallResult::GetCallResult() : JSFunction{"GetCallResult", [&](auto args) {
GetCallResult::GetCallResult() : JSFunction{"GetCallResult", [&](const auto& args) {
return getResult(args);
}} {
} //GetCallResult::GetCallResult
@@ -34,7 +34,7 @@ GetCallResult::GetCallResult() : JSFunction{"GetCallResult", [&](auto args) {
return: The requested result (nullptr on failure)
--------------------------------------------------------------------*/
std::unique_ptr<WrappedResultArg> GetCallResult::getResult(WrappedResultArg& argument) const {
std::unique_ptr<WrappedResultArg> GetCallResult::getResult(const WrappedResultArg& argument) const {
if (!hasBridge())
return nullptr;
//Retrieve the requested result
@@ -34,7 +34,7 @@ namespace speckle::interfac::browser::bridge {
@param argument The method arguments specifying the target bridge and requestID
@return The requested result (nullptr on failure)
*/
std::unique_ptr<WrappedResultArg> getResult(WrappedResultArg& argument) const;
std::unique_ptr<WrappedResultArg> getResult(const WrappedResultArg& argument) const;
};
}
@@ -102,8 +102,8 @@ namespace speckle::interfac::browser {
--------------------------------------------------------------------*/
template<typename FunctionBinding>
bool JSPortal<FunctionBinding>::install(std::shared_ptr<JSObject<FunctionBinding>> object) {
#ifdef ARCHICAD
try {
#ifdef ARCHICAD
auto engine = getJSEngine();
if (!engine)
return false;
@@ -127,10 +127,10 @@ namespace speckle::interfac::browser {
object->setPortal(*this);
return true;
}
#endif
} catch(...) {
///TODO: Need to discuss the best course of action to notify of a failure
}
#endif
return false;
} //JSPortal<FunctionBinding>::install
@@ -20,7 +20,7 @@ namespace speckle::interfac::browser {
struct FuncBase {};
template<typename Argument, typename Return>
struct FuncTypedef {
typedef std::function<std::unique_ptr<Return>(Argument)> type;
typedef std::function<std::unique_ptr<Return>(const Argument&)> type;
};
template<typename Return>
struct FuncTypedef<void, Return> {
@@ -28,7 +28,7 @@ namespace speckle::interfac::browser {
};
template<typename Argument>
struct FuncTypedef<Argument, void> {
typedef std::function<void(Argument)> type;
typedef std::function<void(const Argument&)> type;
};
template<>
struct FuncTypedef<void, void> {
@@ -99,6 +99,7 @@ Cargo::Unique Account::getCargo(const Inventory::Item& item) const {
Set to the default package content
--------------------------------------------------------------------*/
void Account::setDefault() {
base::setDefault();
m_token.clear();
m_refreshToken.clear();
m_isDefault = false;
@@ -1,7 +1,8 @@
#include "Speckle/Record/Credentials/ServerInfo.h"
#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageUnoWrap.h"
#include "Active/Serialise/Package/Wrapper/Mover.h"
#include "Active/Serialise/Package/Wrapper/PackageUniqueWrap.h"
#include "Speckle/Utility/Guid.h"
#include <array>
@@ -90,7 +91,7 @@ Cargo::Unique ServerInfo::getCargo(const Inventory::Item& item) const {
case urlID:
return std::make_unique<StringOptWrap>(m_url);
case migrationID:
return std::make_unique<PackageUnoWrap<ServerMigration>>(m_migration);
return std::make_unique<Mover>(PackageUniqueWrap{m_migration});
default:
return nullptr; //Requested an unknown index
}
+17
View File
@@ -2,6 +2,7 @@
#define SPECKLE_UTILITY_GUID
#include "Active/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#ifdef ARCHICAD
#include <ACAPinc.h>
@@ -22,6 +23,12 @@ namespace speckle::utility {
// MARK: - Constructors
using base::base;
/*!
Constructor
@param source The guid to copy
*/
Guid(const active::utility::Guid& source) : base{source} {}
#ifdef ARCHICAD
/*!
@@ -40,6 +47,16 @@ namespace speckle::utility {
using base::operator=;
/*!
Conversion operator
@return The guid as a string
*/
operator active::utility::String() const { return base::string(); }
/*!
Conversion operator
@return The guid as a string
*/
operator speckle::utility::String() const { return base::string(); }
#ifdef ARCHICAD
/*!
Conversion operator
@@ -16,7 +16,6 @@
210CC8A02C81E34400610F58 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 210CC89E2C81E34400610F58 /* Platform.h */; };
212A88132AE48821001EAFE7 /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21379E082AE47A6400A1584C /* libArchicad27.a */; platformFilters = (macos, ); };
2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351782C624FC100E5A69C /* MenuSubscriber.cpp */; };
2193518C2C62655700E5A69C /* MenuEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 219351892C62655700E5A69C /* MenuEvent.h */; };
2193519B2C6278D900E5A69C /* SelectionSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351992C6278D900E5A69C /* SelectionSubscriber.cpp */; };
219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351AC2C62CC1A00E5A69C /* Guid.cpp */; };
219351B32C62CC1A00E5A69C /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351AE2C62CC1A00E5A69C /* String.cpp */; };
@@ -37,6 +36,13 @@
21D0BD562C890B1C0077E104 /* ServerMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD542C890B1C0077E104 /* ServerMigration.h */; };
21D0BD592C8910400077E104 /* UserInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD572C8910400077E104 /* UserInfo.cpp */; };
21D0BD5A2C8910400077E104 /* UserInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD582C8910400077E104 /* UserInfo.h */; };
21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */; };
21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */; };
21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */; };
21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */; };
21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */; };
21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDC32C9241940077E104 /* ProjectSubscriber.h */; };
21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BDE42C943D3F0077E104 /* RecordID.h */; };
21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F382C6B880B008B6A06 /* JSBaseTransport.cpp */; };
21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F4A2C6CCC25008B6A06 /* BrowserBridge.cpp */; };
21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F602C6D0286008B6A06 /* GetBindingsMethodNames.cpp */; };
@@ -132,6 +138,16 @@
21D0BD542C890B1C0077E104 /* ServerMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerMigration.h; sourceTree = "<group>"; };
21D0BD572C8910400077E104 /* UserInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserInfo.cpp; sourceTree = "<group>"; };
21D0BD582C8910400077E104 /* UserInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInfo.h; sourceTree = "<group>"; };
21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentStoreCore.cpp; sourceTree = "<group>"; };
21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreCore.h; sourceTree = "<group>"; };
21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStoreEngine.h; sourceTree = "<group>"; };
21D0BDBA2C90F2830077E104 /* DocStoreSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocStoreSubscriber.h; sourceTree = "<group>"; };
21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocStoreSubscriber.cpp; sourceTree = "<group>"; };
21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocStoreMergeEvent.h; sourceTree = "<group>"; };
21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectSubscriber.cpp; sourceTree = "<group>"; };
21D0BDC32C9241940077E104 /* ProjectSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectSubscriber.h; sourceTree = "<group>"; };
21D0BDC62C9245E40077E104 /* ProjectEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectEvent.h; sourceTree = "<group>"; };
21D0BDE42C943D3F0077E104 /* RecordID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordID.h; sourceTree = "<group>"; };
21F69F012C66C229008B6A06 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Doxyfile; path = Documentation/Doxyfile; sourceTree = "<group>"; };
21F69F192C6A0FE2008B6A06 /* JSBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBinding.h; sourceTree = "<group>"; };
21F69F352C6AA9B3008B6A06 /* JSFunction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSFunction.h; sourceTree = "<group>"; };
@@ -248,8 +264,12 @@
2193517A2C624FC100E5A69C /* Subscriber */ = {
isa = PBXGroup;
children = (
21D0BDBB2C90F2830077E104 /* DocStoreSubscriber.cpp */,
21D0BDBA2C90F2830077E104 /* DocStoreSubscriber.h */,
219351782C624FC100E5A69C /* MenuSubscriber.cpp */,
219351792C624FC100E5A69C /* MenuSubscriber.h */,
21D0BDC22C9241940077E104 /* ProjectSubscriber.cpp */,
21D0BDC32C9241940077E104 /* ProjectSubscriber.h */,
219351992C6278D900E5A69C /* SelectionSubscriber.cpp */,
219351982C6278D900E5A69C /* SelectionSubscriber.h */,
);
@@ -259,7 +279,9 @@
2193518A2C62655700E5A69C /* Type */ = {
isa = PBXGroup;
children = (
21D0BDBE2C90F36B0077E104 /* DocStoreMergeEvent.h */,
219351892C62655700E5A69C /* MenuEvent.h */,
21D0BDC62C9245E40077E104 /* ProjectEvent.h */,
2193519C2C627E3100E5A69C /* SelectionEvent.h */,
);
path = Type;
@@ -293,8 +315,9 @@
children = (
21D0BD1D2C86F0280077E104 /* AccountDatabase.cpp */,
21D0BD1E2C86F0280077E104 /* AccountDatabase.h */,
21D0BD302C86FE090077E104 /* Identity */,
21D0BD272C86FC350077E104 /* Content */,
21D0BD302C86FE090077E104 /* Identity */,
21D0BDB02C8F8AB60077E104 /* Storage */,
);
path = Database;
sourceTree = "<group>";
@@ -314,10 +337,29 @@
21D0BD2D2C86FE090077E104 /* Index.h */,
21D0BD2E2C86FE090077E104 /* Link.cpp */,
21D0BD2F2C86FE090077E104 /* Link.h */,
21D0BDE42C943D3F0077E104 /* RecordID.h */,
);
path = Identity;
sourceTree = "<group>";
};
21D0BDAF2C8F8AB60077E104 /* DocumentStore */ = {
isa = PBXGroup;
children = (
21D0BDAC2C8F8AB60077E104 /* DocumentStoreCore.cpp */,
21D0BDAD2C8F8AB60077E104 /* DocumentStoreCore.h */,
21D0BDAE2C8F8AB60077E104 /* DocumentStoreEngine.h */,
);
path = DocumentStore;
sourceTree = "<group>";
};
21D0BDB02C8F8AB60077E104 /* Storage */ = {
isa = PBXGroup;
children = (
21D0BDAF2C8F8AB60077E104 /* DocumentStore */,
);
path = Storage;
sourceTree = "<group>";
};
21F69F1A2C6A0FE2008B6A06 /* Browser */ = {
isa = PBXGroup;
children = (
@@ -437,6 +479,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */,
21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */,
210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */,
210CC8A02C81E34400610F58 /* Platform.h in Headers */,
@@ -447,9 +490,11 @@
210CC88F2C81A98500610F58 /* Guid64.h in Headers */,
21B67D002C7CE15100FD64FC /* Exception.h in Headers */,
21D0BD2C2C86FC350077E104 /* Record.h in Headers */,
21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */,
210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */,
21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */,
2193518C2C62655700E5A69C /* MenuEvent.h in Headers */,
21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */,
21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */,
21D0BD312C86FE090077E104 /* Index.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -581,6 +626,8 @@
21F69F812C6FF3B0008B6A06 /* BridgeArgumentWrap.cpp in Sources */,
2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */,
21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */,
21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */,
21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */,
21F93AEC2B2F406E009A2C5B /* Addon.cpp in Sources */,
21D0BD4E2C8901A00077E104 /* ServerInfo.cpp in Sources */,
21B67D0E2C7E0E8D00FD64FC /* ErrorReport.cpp in Sources */,
@@ -589,6 +636,7 @@
21D0BD2B2C86FC350077E104 /* Record.cpp in Sources */,
21D0BD592C8910400077E104 /* UserInfo.cpp in Sources */,
210CC8902C81A98500610F58 /* Guid64.cpp in Sources */,
21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */,
21D0BD322C86FE090077E104 /* Link.cpp in Sources */,
219351B32C62CC1A00E5A69C /* String.cpp in Sources */,
219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */,
+9
View File
@@ -23,11 +23,17 @@
<ClInclude Include="Speckle\Database\Content\Record.h" />
<ClInclude Include="Speckle\Database\Identity\Index.h" />
<ClInclude Include="Speckle\Database\Identity\Link.h" />
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.h" />
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreEngine.h" />
<ClInclude Include="Speckle\Environment\Addon.h" />
<ClInclude Include="Speckle\Environment\Platform.h" />
<ClInclude Include="Speckle\Event\Subscriber\DocStoreSubscriber.h" />
<ClInclude Include="Speckle\Event\Subscriber\MenuSubscriber.h" />
<ClInclude Include="Speckle\Event\Subscriber\ProjectSubscriber.h" />
<ClInclude Include="Speckle\Event\Subscriber\SelectionSubscriber.h" />
<ClInclude Include="Speckle\Event\Type\DocStoreMergeEvent.h" />
<ClInclude Include="Speckle\Event\Type\MenuEvent.h" />
<ClInclude Include="Speckle\Event\Type\ProjectEvent.h" />
<ClInclude Include="Speckle\Event\Type\SelectionEvent.h" />
<ClInclude Include="Speckle\Interface\Browser\Bridge\BridgeArgument.h" />
<ClInclude Include="Speckle\Interface\Browser\Bridge\BridgeArgumentWrap.h" />
@@ -61,9 +67,12 @@
<ClCompile Include="Speckle\Database\AccountDatabase.cpp" />
<ClCompile Include="Speckle\Database\Content\Record.cpp" />
<ClCompile Include="Speckle\Database\Identity\Link.cpp" />
<ClCompile Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.cpp" />
<ClCompile Include="Speckle\Environment\Addon.cpp" />
<ClCompile Include="Speckle\Environment\Platform.cpp" />
<ClCompile Include="Speckle\Event\Subscriber\DocStoreSubscriber.cpp" />
<ClCompile Include="Speckle\Event\Subscriber\MenuSubscriber.cpp" />
<ClCompile Include="Speckle\Event\Subscriber\ProjectSubscriber.cpp" />
<ClCompile Include="Speckle\Event\Subscriber\SelectionSubscriber.cpp" />
<ClCompile Include="Speckle\Interface\Browser\Bridge\BridgeArgument.cpp" />
<ClCompile Include="Speckle\Interface\Browser\Bridge\BridgeArgumentWrap.cpp" />
+33
View File
@@ -56,6 +56,12 @@
<Filter Include="Speckle\Database\Identity">
<UniqueIdentifier>{ef1710f6-d890-4286-8fb2-f5c432a2c5ac}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Database\Storage">
<UniqueIdentifier>{afbc554e-df7d-4310-a967-4df8e9febcd0}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Database\Storage\DocumentStore">
<UniqueIdentifier>{c4146af8-d1a1-44cc-9810-cc8da1a705a8}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Speckle\Environment\Addon.h">
@@ -169,6 +175,24 @@
<ClInclude Include="Speckle\Environment\Platform.h">
<Filter>Speckle\Environment</Filter>
</ClInclude>
<ClInclude Include="Speckle\Event\Subscriber\DocStoreSubscriber.h">
<Filter>Speckle\Event\Subscriber</Filter>
</ClInclude>
<ClInclude Include="Speckle\Event\Subscriber\ProjectSubscriber.h">
<Filter>Speckle\Event\Subscriber</Filter>
</ClInclude>
<ClInclude Include="Speckle\Event\Type\DocStoreMergeEvent.h">
<Filter>Speckle\Event\Type</Filter>
</ClInclude>
<ClInclude Include="Speckle\Event\Type\ProjectEvent.h">
<Filter>Speckle\Event\Type</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.h">
<Filter>Speckle\Database\Storage\DocumentStore</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreEngine.h">
<Filter>Speckle\Database\Storage\DocumentStore</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Speckle\Environment\Addon.cpp">
@@ -237,6 +261,15 @@
<ClCompile Include="Speckle\Environment\Platform.cpp">
<Filter>Speckle\Environment</Filter>
</ClCompile>
<ClCompile Include="Speckle\Event\Subscriber\DocStoreSubscriber.cpp">
<Filter>Speckle\Event\Subscriber</Filter>
</ClCompile>
<ClCompile Include="Speckle\Event\Subscriber\ProjectSubscriber.cpp">
<Filter>Speckle\Event\Subscriber</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.cpp">
<Filter>Speckle\Database\Storage\DocumentStore</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="Speckle\CMakeLists.txt">