mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 23:29:59 +00:00
spatial hierarchy from IFC + active-model concept
Build the spatial hierarchy panel from the loaded model's real IFC spatial structure instead of mock data: - helpers/element: add get_spatial_children (IsDecomposedBy -> RelatedObjects, filtered to spatial elements) to walk IfcProject -> IfcSite -> IfcBuilding -> IfcBuildingStorey -> IfcSpace. - SessionState: relay dataSourceReady as modelDataSourceReady (the .ifc for a sidecar hit loads asynchronously, so the tree can only build once it arrives). - spatial_hierarchy/View: walk the active model's IFC file into a TreeNode tree, naming nodes by Name (fallback to class), mapping site/building/storey kinds; siblings sorted with natural (numeric) collation. - spatial_hierarchy/Panel: tree now fills the panel height (setBodyExpanding + Expanding size policy); right-click menu for recursive Expand/Collapse Subtree and Expand/Collapse All. Add the concept of an active model: - SessionState: activeModelId / setActiveModelId / activeModelChanged; the first loaded model is active by default; reassigns/clears on removal. - Models panel: clicking a model makes it active; its cube icon is drawn with the accent colour (makeAccentSvgIcon) via FederationItemModel::setActiveModelId. - The spatial hierarchy reflects only the active model. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -94,6 +94,15 @@ void SessionState::createLoader(ViewportWindow* viewport) {
|
||||
connect(loader_, &SceneLoader::allLoadsFinished, this, [this]() {
|
||||
setStatusMessage("Loaded", QString("%1 model(s)").arg(loader_->modelCount()));
|
||||
});
|
||||
connect(loader_, &SceneLoader::dataSourceReady, this, [this](uint32_t session_model_id) {
|
||||
emit modelDataSourceReady(session_model_id);
|
||||
});
|
||||
// First model to load becomes the active model by default.
|
||||
connect(this, &SessionState::modelGeometryReady, this, [this](uint32_t session_model_id) {
|
||||
if (active_model_id_.isEmpty()) {
|
||||
setActiveModelId(modelIdForSessionModelId(session_model_id));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SessionState::setSelectedObjectId(uint32_t object_id) {
|
||||
@@ -129,12 +138,24 @@ void SessionState::removeModelMappingByModelId(const QString& model_id) {
|
||||
if (it == model_id_to_session_model_id_.end()) return;
|
||||
session_model_id_to_model_id_.remove(it.value());
|
||||
model_id_to_session_model_id_.erase(it);
|
||||
if (model_id == active_model_id_) {
|
||||
setActiveModelId(model_id_to_session_model_id_.isEmpty()
|
||||
? QString()
|
||||
: model_id_to_session_model_id_.keys().first());
|
||||
}
|
||||
}
|
||||
|
||||
void SessionState::clearModelMappings() {
|
||||
model_id_to_session_model_id_.clear();
|
||||
session_model_id_to_model_id_.clear();
|
||||
cloud_metadata_.clear();
|
||||
setActiveModelId(QString());
|
||||
}
|
||||
|
||||
void SessionState::setActiveModelId(const QString& model_id) {
|
||||
if (model_id == active_model_id_) return;
|
||||
active_model_id_ = model_id;
|
||||
emit activeModelChanged(active_model_id_);
|
||||
}
|
||||
|
||||
void SessionState::setCloudMetadata(const QString& model_id, const QVariantMap& metadata) {
|
||||
|
||||
Reference in New Issue
Block a user