BIMElementDatabase::getTables and bringToFront added

BIMElementDatabase::getElements allows a target table to be specified
This commit is contained in:
Ralph Wessel
2024-11-06 18:03:26 +00:00
parent 4e60d95ce9
commit b62201cf95
11 changed files with 184 additions and 34 deletions
@@ -320,6 +320,7 @@
2199BB512CDA481A00A4BEEC /* ConnectorFix.grc */ = {isa = PBXFileReference; lastKnownFileType = text; name = ConnectorFix.grc; path = RFIX/ConnectorFix.grc; sourceTree = "<group>"; };
2199BB522CDA4B1700A4BEEC /* ConnectorProject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConnectorProject.cpp; sourceTree = "<group>"; };
2199BB532CDA4B1700A4BEEC /* ConnectorProject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConnectorProject.h; sourceTree = "<group>"; };
2199BB5C2CDA93CE00A4BEEC /* ConnectorImagesFix.grc */ = {isa = PBXFileReference; lastKnownFileType = text; name = ConnectorImagesFix.grc; path = RFIX/ConnectorImagesFix.grc; sourceTree = "<group>"; };
219F30352C768F0A009834E9 /* Connector-AC27-Test.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Connector-AC27-Test.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
219F30402C769282009834E9 /* ConfigTests.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = ConfigTests.cpp; sourceTree = "<group>"; };
219F30432C7693B6009834E9 /* Connector-AC27-Debug.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Connector-AC27-Debug.xctestplan"; sourceTree = SOURCE_ROOT; };
@@ -975,6 +976,7 @@
isa = PBXGroup;
children = (
2199BB512CDA481A00A4BEEC /* ConnectorFix.grc */,
2199BB5C2CDA93CE00A4BEEC /* ConnectorImagesFix.grc */,
);
name = Fixed;
sourceTree = "<group>";
@@ -33,8 +33,9 @@ namespace speckle::database {
};
///Element database storage declaration
class BIMElementDatabase::Store : public Storage<Element, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID> {
using base = Storage<Element, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID>;
class BIMElementDatabase::Store : public Storage<Element, UnboxedTransport, BIMRecordID, BIMRecordID,
BIMRecordID, BIMRecordID, ElementStorage::TableType> {
using base = Storage<Element, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID, ElementStorage::TableType>;
using base::base;
};
@@ -75,6 +76,28 @@ BIMElementDatabase::BIMElementDatabase() {
BIMElementDatabase::~BIMElementDatabase() {}
/*--------------------------------------------------------------------
Get the available element tables
targetType: An optional filtr for table type to retrieve, e.g. get all sections (nullopt = all table types)
return: A list of available tables
--------------------------------------------------------------------*/
BIMRecordIDList BIMElementDatabase::getTables(std::optional<TableType> targetType) const {
return m_engine->getTables(targetType);
} //BIMElementDatabase::getTables
/*--------------------------------------------------------------------
Bring the view of this database to the front (i.e. so the user sees it)
tableID: The ID of the table to bring to the front
--------------------------------------------------------------------*/
void BIMElementDatabase::bringViewToFront(BIMRecordID tableID) const {
m_engine->bringViewToFront(tableID);
} //BIMElementDatabase::bringViewToFront
/*--------------------------------------------------------------------
Get the current user element selection
@@ -110,7 +133,7 @@ void BIMElementDatabase::clearSelection() const {
return: A list containing IDs of found elements (empty if none found)
--------------------------------------------------------------------*/
std::vector<BIMRecordID> BIMElementDatabase::findElements(const Filter& filter, std::optional<BIMRecordID> tableID,
BIMRecordIDList BIMElementDatabase::findElements(const Filter& filter, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return m_engine->findObjects(filter, tableID, documentID);
} //BIMElementDatabase::findElements
@@ -120,6 +143,8 @@ std::vector<BIMRecordID> BIMElementDatabase::findElements(const Filter& filter,
Get a specified element
elementID: The ID of the target element
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested element (nullptr on failure)
--------------------------------------------------------------------*/
@@ -132,10 +157,14 @@ Element::Unique BIMElementDatabase::getElement(const BIMRecordID& elementID, std
/*--------------------------------------------------------------------
Get all elements
tableID: Optional table ID (defaults to the first table)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: All the elements
--------------------------------------------------------------------*/
Vector<Element> BIMElementDatabase::getElements() const {
return m_store->getObjects();
Vector<Element> BIMElementDatabase::getElements(std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return m_store->getObjects(tableID, documentID);
} //BIMElementDatabase::getElements
@@ -2,6 +2,7 @@
#define CONNECTOR_DATABASE_BIM_ELEMENT_DATABASE
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Database/Storage/Element/ElementStorage.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Record/Element/Interface/Part.h"
#include "Speckle/Utility/Guid.h"
@@ -19,13 +20,8 @@ namespace speckle::database {
/*!
Database of model elements relating to a specific project
*/
class BIMElementDatabase {
class BIMElementDatabase : public ElementStorage {
public:
// MARK: - Types
///Element filter (NB: expand in future to support optimised filtering)
using Filter = std::function<bool(const record::element::Element&)>;
// MARK: - Constructors
@@ -41,6 +37,17 @@ namespace speckle::database {
// MARK: - Functions (const)
/*!
Get the available element tables
@param targetType An optional filtr for table type to retrieve, e.g. get all sections (nullopt = all table types)
@return A set of available tables
*/
BIMRecordIDList getTables(std::optional<TableType> targetType) const;
/*!
Bring the view of this database to the front (i.e. so the user sees it)
@param tableID The ID of the table to bring to the front
*/
void bringViewToFront(BIMRecordID tableID) const;
/*!
Get the current user element selection
@return A list of selected element IDs
@@ -61,7 +68,7 @@ namespace speckle::database {
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
std::vector<BIMRecordID> findElements(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
BIMRecordIDList findElements(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const;
/*!
Get a specified element
@@ -80,9 +87,12 @@ namespace speckle::database {
std::unique_ptr<record::element::Element> getElement(const BIMLink& link) const { return getElement(link, link.tableID, link.docID); }
/*!
Get all model elements
@param tableID Optional table ID (defaults to the first table)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return All the elements
*/
active::container::Vector<record::element::Element> getElements() const;
active::container::Vector<record::element::Element> getElements(std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const;
/*!
Get memo memo (supplementary) data for a specified element
@param elementID The of the source element
@@ -34,6 +34,7 @@ namespace speckle::database {
using Attribute = record::attribute::Attribute;
using Filter = base::Filter;
using Outline = base::Outline;
using ObjIDList = base::ObjIDList;
// MARK: - Constructors
@@ -58,8 +59,8 @@ namespace speckle::database {
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
virtual std::vector<BIMRecordID> findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Get an object by ID
@param objID The object ID
@@ -41,14 +41,24 @@ using enum ArchicadDBaseCore::Status;
namespace {
//ID for the floor plan view
static const Guid primary2DViewID{String{"ddad27c0-c17b-4ad3-b76b-53d1e176d5ef"}};
//ID for the 3D view
static const Guid primary3DViewID{String{"ec368939-fb7d-4d8c-bc88-6d29806d9212"}};
/*!
Get information about a specified Archicad table
@param tableID The ID of the target table
@return The requested table info (nullopt on failure)
*/
std::optional<API_DatabaseInfo> getTableInfo(const BIMRecordID& tableID) {
API_DatabaseInfo dbaseInfo;
dbaseInfo.databaseUnId.elemSetId = tableID;
API_DatabaseInfo dbaseInfo{};
if (tableID == primary2DViewID)
dbaseInfo.typeID = APIWind_FloorPlanID;
else if (tableID == primary3DViewID)
dbaseInfo.typeID = APIWind_3DModelID;
else
dbaseInfo.databaseUnId.elemSetId = tableID;
if (auto err = ACAPI_Window_GetDatabaseInfo(&dbaseInfo); err == NoError)
return dbaseInfo;
return std::nullopt;
@@ -62,7 +72,7 @@ namespace {
*/
bool setActiveTable(const BIMRecordID& tableID) {
if (!tableID)
return false; //Null guid doens't point to anything
return false; //Null guid doesn't point to anything
if (auto activeTable = ArchicadElementDBaseEngine::getActiveTable(); activeTable && *activeTable == tableID)
return true;
auto dbaseInfo = getTableInfo(tableID);
@@ -114,12 +124,34 @@ namespace {
std::optional<BIMRecordID> ArchicadElementDBaseEngine::getActiveTable() {
API_WindowInfo dbaseInfo;
active::utility::Memory::erase(dbaseInfo);
if (auto err = ACAPI_Database_GetCurrentDatabase(&dbaseInfo); err == NoError)
if (auto err = ACAPI_Database_GetCurrentDatabase(&dbaseInfo); err == NoError) {
if (dbaseInfo.typeID == APIWind_FloorPlanID)
return primary2DViewID;
else if (dbaseInfo.typeID == APIWind_3DModelID)
return primary3DViewID;
return dbaseInfo.databaseUnId.elemSetId;
}
return std::nullopt;
} //ArchicadElementDBaseEngine::getActiveTable
/*--------------------------------------------------------------------
Bring the view of this database to the front (i.e. so the user sees it)
tableID: The ID of the table to bring to the front
--------------------------------------------------------------------*/
void ArchicadElementDBaseEngine::bringViewToFront(BIMRecordID tableID) const {
auto dbaseInfo = getTableInfo(tableID);
if (!dbaseInfo)
return;
API_WindowInfo windowInfo{};
windowInfo.typeID = dbaseInfo->typeID;
if ((windowInfo.typeID != APIWind_FloorPlanID) && (windowInfo.typeID != APIWind_3DModelID))
windowInfo.databaseUnId = dbaseInfo->databaseUnId;
ACAPI_Window_ChangeWindow(&windowInfo);
} //ArchicadElementDBaseEngine::bringViewToFront
/*--------------------------------------------------------------------
Get the current user element selection
@@ -162,6 +194,24 @@ void ArchicadElementDBaseEngine::clearSelection() const {
} //ArchicadElementDBaseEngine::clearSelection
/*--------------------------------------------------------------------
Get the available dbase tables
targetType: An optional filtr for table type/group to retrieve
return: A list of available tables
--------------------------------------------------------------------*/
ArchicadElementDBaseEngine::TableIDList ArchicadElementDBaseEngine::getTables(std::optional<TableType> targetType) const {
using enum ElementStorage::TableType;
TableIDList result;
if (!targetType || (targetType == primary2D))
result.insert(primary2DViewID);
if (!targetType || (targetType == primary3D))
result.insert(primary3DViewID);
return result;
} //ArchicadElementDBaseEngine::getTables
/*--------------------------------------------------------------------
Find a filtered list of objects
@@ -171,16 +221,19 @@ void ArchicadElementDBaseEngine::clearSelection() const {
return: A list containing IDs of found elements (empty if none found)
--------------------------------------------------------------------*/
std::vector<BIMRecordID> ArchicadElementDBaseEngine::findObjects(const Filter& filter, std::optional<BIMRecordID> tableID,
BIMRecordIDList ArchicadElementDBaseEngine::findObjects(const Filter& filter, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
//Switch to the target table (when specified). Otherwise the currently active table will be used
if (tableID)
setActiveTable(*tableID);
//First check for no filter (in which case we return all objects)
if (filter == nullptr) {
GS::Array<API_Guid> found;
if ((ACAPI_Element_GetElemList({}, &found) != NoError) || found.IsEmpty())
return {};
std::vector<BIMRecordID> result;
BIMRecordIDList result;
for (const auto& item : found)
result.emplace_back(item);
result.insert(item);
return result;
}
//Implement other filtering as required - ideally identify characteristics supported by API, e.g. filter by type/renovation etc
@@ -4,6 +4,7 @@
#include "Active/Database/Storage/DBaseEngine.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h"
#include "Speckle/Database/Storage/Element/ElementStorage.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Utility/Guid.h"
@@ -17,16 +18,17 @@ namespace speckle::database {
/*!
A database engine to read/write elements in an Archicad project database (local file or cloud-based)
*/
class ArchicadElementDBaseEngine : public ArchicadDBaseCore,
public active::database::DBaseEngine<record::element::Element, BIMRecordID, BIMRecordID, BIMRecordID> {
class ArchicadElementDBaseEngine : public ArchicadDBaseCore, public ElementStorage,
public active::database::DBaseEngine<record::element::Element, BIMRecordID, BIMRecordID, BIMRecordID, ElementStorage::TableType> {
public:
// MARK: - Types
using base = active::database::DBaseEngine<record::element::Element, BIMRecordID, BIMRecordID, BIMRecordID>;
using Element = record::element::Element;
using Filter = base::Filter;
using Filter = ElementStorage::Filter;
using Outline = base::Outline;
using ObjIDList = base::ObjIDList;
// MARK: - Constants
@@ -53,6 +55,11 @@ namespace speckle::database {
// MARK: - Functions (const)
/*!
Bring the view of this database to the front (i.e. so the user sees it)
@param tableID The ID of the table to bring to the front
*/
void bringViewToFront(BIMRecordID tableID) const;
/*!
Get the current user element selection
@return A list of selected element IDs
@@ -66,6 +73,12 @@ namespace speckle::database {
Clear the element selection
*/
void clearSelection() const;
/*!
Get the available dbase tables
@param targetType An optional filtr for table type/group to retrieve
@return A list of available tables
*/
TableIDList getTables(std::optional<TableType> targetType) const override;
/*!
Find a filtered list of objects
@param filter The object filter (nullptr = find all objects)
@@ -73,8 +86,8 @@ namespace speckle::database {
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
virtual std::vector<BIMRecordID> findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
virtual BIMRecordIDList findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get an object by index
@param objID The object ID
@@ -29,6 +29,7 @@ namespace speckle::database {
using Group = record::property::Group;
using Filter = base::Filter;
using Outline = base::Outline;
using ObjIDList = base::ObjIDList;
// MARK: - Constructors
@@ -53,8 +54,8 @@ namespace speckle::database {
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
virtual std::vector<BIMRecordID> findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Get an object by ID
@param objID The object ID
@@ -30,6 +30,7 @@ namespace speckle::database {
using Template = record::property::Template;
using Filter = base::Filter;
using Outline = base::Outline;
using ObjIDList = base::ObjIDList;
// MARK: - Constructors
@@ -54,8 +55,8 @@ namespace speckle::database {
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
virtual std::vector<BIMRecordID> findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Find all property templates linked to specified classifications
@param classifications The classifications
@@ -46,6 +46,7 @@ namespace speckle::database {
using base = active::database::DBaseEngine<Obj, ObjID, RecordID, RecordID>;
using Filter = base::Filter;
using Outline = base::Outline;
using ObjIDList = base::ObjIDList;
using Cache = active::database::RecordCache<Obj, ObjWrapper, ObjID, RecordID, RecordID>;
// MARK: - Constructors
@@ -66,8 +67,8 @@ namespace speckle::database {
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return A list containing IDs of found elements (empty if none found)
*/
virtual std::vector<RecordID> findObjects(const Filter& filter = nullptr, std::optional<RecordID> tableID = std::nullopt,
std::optional<RecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
virtual ObjIDList findObjects(const Filter& filter = nullptr, std::optional<RecordID> tableID = std::nullopt,
std::optional<RecordID> documentID = std::nullopt) const override { return {}; } //Implement when required
/*!
Get an object by index
@param ID The object ID
@@ -181,7 +182,7 @@ namespace speckle::database {
auto storedData = readStore();
m_cache = std::make_unique<Cache>();
if (!storedData) {
m_cache->setID(speckle::utility::Guid{true}.operator String()); //Needs an ID - used as substitute for the Speckle 'document ID'
m_cache->setID(speckle::utility::Guid{true}.operator speckle::utility::String()); //Needs an ID - substitute for the Speckle 'document ID'
return m_cache.get(); //Return an empty container if there's no data
}
//Import the document data into the record cache
@@ -0,0 +1,29 @@
#ifndef SPECKLE_DATABASE_ELEMENT_STORAGE
#define SPECKLE_DATABASE_ELEMENT_STORAGE
#include "Speckle/Record/Element/Element.h"
namespace speckle::database {
/*!
Fundamental concepts for element storage
*/
class ElementStorage {
public:
// MARK: - Types
///Element storage table types
enum class TableType {
primary2D,
primary3D,
section,
elevation,
};
///Element filter
using Filter = std::function<bool(const record::element::Element&)>;
};
}
#endif //SPECKLE_DATABASE_ELEMENT_STORAGE
@@ -303,6 +303,7 @@
2196F3022CB57E7F00450DFC /* Storey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Storey.h; sourceTree = "<group>"; };
2196F3032CB57E7F00450DFC /* Storey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Storey.cpp; sourceTree = "<group>"; };
219712682BE7E2D500D9EF7E /* Serialisation.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Serialisation.md; sourceTree = "<group>"; };
2199BB5F2CDB761B00A4BEEC /* ElementStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementStorage.h; sourceTree = "<group>"; };
21A0FB9F2CB880690023F24E /* FinishCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishCollector.h; sourceTree = "<group>"; };
21A0FBA92CB9324A0023F24E /* FinishProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinishProxy.h; sourceTree = "<group>"; };
21A0FBB42CBA5E380023F24E /* Str256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Str256.h; sourceTree = "<group>"; };
@@ -708,6 +709,14 @@
path = SpeckleLibDoctest;
sourceTree = "<group>";
};
2199BB602CDB761B00A4BEEC /* Element */ = {
isa = PBXGroup;
children = (
2199BB5F2CDB761B00A4BEEC /* ElementStorage.h */,
);
path = Element;
sourceTree = "<group>";
};
21A0FBA02CB880690023F24E /* Collection */ = {
isa = PBXGroup;
children = (
@@ -886,6 +895,7 @@
21D0BDB02C8F8AB60077E104 /* Storage */ = {
isa = PBXGroup;
children = (
2199BB602CDB761B00A4BEEC /* Element */,
215F088A2CA195EC00CD343B /* ArchicadDBase */,
21D0BDAF2C8F8AB60077E104 /* DocumentStore */,
);