Compare commits

...

18 Commits

Author SHA1 Message Date
Ralph Wessel 03e74e5195 Version bump 2024-09-17 13:09:07 +01:00
Ralph Wessel ce6306c1de CardMover should validate handler before constructing base Mover
ReceiverModelCar constructor should also construct base ModelCard
SenderModelCar didn't populate member filter
DocumentStoreCore now loads objects when project reopened
DocumentStoreCore uses defer for safer handle release
DocumentStoreCore::resetStore must reset object ID
DocumentStoreEngine must reset cache and DocumentStoreCore
2024-09-16 22:54:55 +01:00
Ralph Wessel 1f6bcbd947 Not using ArchicadEverythingFilter yet
DocumentCoreStore now records and applies document storage ID correctly
2024-09-16 16:32:03 +01:00
Ralph Wessel 220c9a5a40 ModelCard record and dbase fixes 2024-09-16 15:00:55 +01:00
Ralph Wessel 8ea4ced153 Updated VS projects 2024-09-16 08:54:18 +01:00
Ralph Wessel e92729e10f Added RecordID to express common ID types for Archicad
Added ArchicadEverythingFilter
Added ArchicadSelectionFilter
Added EverythingSendFilter
Updated SendFilter bridge method with defined filter types
Updated FilterMover with defined filter types
Implemented SendFilter::checkExpiry
Updated CardMover with ReceiverModelCard
Updated all bridge method args as const reference
2024-09-15 22:23:12 +01:00
Ralph Wessel e75ef3133d Clarified concepts for Storage and Engine types
Added FilterMover and CardMover to deal with polymorphic ModelCard and Sendfilter types
Implemented more of SenderModelCard (more needed)
2024-09-14 02:06:02 +01:00
Ralph Wessel 90211900e1 Interim commit - builds with some warnings
Simplication of record identifiers
Starting implementation of SenderModelCar
Implementation of SendFilters in progress
2024-09-13 11:51:40 +01:00
Ralph Wessel 850cd36d73 Added UpdateModel and RemoveModel
Linked new methods to baseBinding
2024-09-12 18:48:57 +01:00
Ralph Wessel 5dcab38086 Added "base.AddModel" method
Storage write methods
Subscriber implementations should be 'virtual Subscriber' to allow multiple inheritance
2024-09-12 18:00:22 +01:00
Ralph Wessel 461047f04a Updated VS projects
Updated gitignore for temp resource files
2024-09-12 00:10:03 +01:00
Ralph Wessel 8b765ec3d7 Added ModelCardDatabase::getSubscription 2024-09-11 23:18:03 +01:00
Ralph Wessel d00c20f0c6 ModelCardDatabase subscribes to project/merge events
ModelCardDatabase can be serialised as required for GetDocumentState method
Added ProjectSubscriber
Added ProjectEvent
2024-09-11 23:11:40 +01:00
Ralph Wessel 53dd72989a Added DocStoreSubscriber
Added DocStoreMergeEvent
DocumentStoreCore now handles merge events
Fixes to SelectionSubscriber
2024-09-10 23:35:12 +01:00
Ralph Wessel 7d9f939b8b Added DocumentStoreCore
Added DocumentStoreEngine
Added Addon::isSharedDocument
2024-09-10 22:28:29 +01:00
Ralph Wessel 7fe5ba6e9d Defined CardSetting and ModelCard classes 2024-09-09 16:45:41 +01:00
Ralph Wessel 47b2e0b513 Merge tag '0.2.2' into develop
0.2.2
2024-09-09 13:07:25 +01:00
Ralph Wessel 00d76dbe12 Merge branch 'release/0.2.2' 2024-09-09 13:07:25 +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">