From 0d5fa0c20c577b9b935be675939702caee9116a7 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 6 May 2026 12:36:28 +1000 Subject: [PATCH] Interface mockup 6 --- src/interface/ElementRegistry.cpp | 21 +++++++++- src/interface/ElementRegistry.h | 7 +++- src/interface/MainWindow.cpp | 2 +- src/interface/components/KeyValueTable.cpp | 4 +- src/interface/components/KeyValueTable.h | 2 +- src/interface/components/Panel.cpp | 22 +++++++++- src/interface/components/Panel.h | 6 ++- src/interface/components/Style.cpp | 20 ++------- .../panels/properties/PropertiesPanelView.cpp | 21 +++++++++- .../properties/PropertiesPanelWidget.cpp | 42 +++++++------------ .../panels/properties/PropertiesPanelWidget.h | 3 -- src/interface/panels/todo/TodoPanelWidget.cpp | 2 - 12 files changed, 90 insertions(+), 62 deletions(-) diff --git a/src/interface/ElementRegistry.cpp b/src/interface/ElementRegistry.cpp index 1e41385d33..7583ff3dd6 100644 --- a/src/interface/ElementRegistry.cpp +++ b/src/interface/ElementRegistry.cpp @@ -32,18 +32,37 @@ ElementRegistry::ElementRegistry(QObject* parent) } void ElementRegistry::bindLoader(SceneLoader* loader) { + loader_ = loader; connect(loader, &SceneLoader::sidecarElementsReady, this, &ElementRegistry::onSidecarElementsReady); connect(loader, &SceneLoader::streamedElementsReady, this, &ElementRegistry::onStreamedElementsReady); } -std::optional ElementRegistry::find(uint32_t object_id) const { +std::optional ElementRegistry::findBasicElementInfo(uint32_t object_id) const { auto it = elements_.find(object_id); if (it == elements_.end()) return std::nullopt; return it->second; } +std::optional ElementRegistry::findEntity(uint32_t object_id) const { + if (!loader_) return std::nullopt; + + auto info = findBasicElementInfo(object_id); + if (!info) return std::nullopt; + + auto* file = loader_->ifcFile(info->model_id); + if (!file) return std::nullopt; + + try { + auto instance = file->instance_by_id(info->ifc_id); + if (!instance) return std::nullopt; + return instance; + } catch (...) { + return std::nullopt; + } +} + void ElementRegistry::onSidecarElementsReady(uint32_t /*mid*/, std::vector elements, std::string string_table) { diff --git a/src/interface/ElementRegistry.h b/src/interface/ElementRegistry.h index 471e53f31f..b059c10c5d 100644 --- a/src/interface/ElementRegistry.h +++ b/src/interface/ElementRegistry.h @@ -23,10 +23,11 @@ #include #include +#include "../ifcparse/express.h" #include +#include #include #include -#include class SceneLoader; struct PackedElementInfo; @@ -50,7 +51,8 @@ public: explicit ElementRegistry(QObject* parent = nullptr); void bindLoader(SceneLoader* loader); - std::optional find(uint32_t object_id) const; + std::optional findBasicElementInfo(uint32_t object_id) const; + std::optional findEntity(uint32_t object_id) const; private: void onSidecarElementsReady(uint32_t mid, @@ -58,6 +60,7 @@ private: std::string string_table); void onStreamedElementsReady(uint32_t mid, std::vector elements); + SceneLoader* loader_ = nullptr; std::unordered_map elements_; }; diff --git a/src/interface/MainWindow.cpp b/src/interface/MainWindow.cpp index 28907cc495..5119a1fb6c 100644 --- a/src/interface/MainWindow.cpp +++ b/src/interface/MainWindow.cpp @@ -388,7 +388,7 @@ void MainWindow::setupPanels() { models_panel_ = new components::Panel("Models", models_widget, this, true); spatial_panel_ = new components::Panel("Spatial Hierarchy", spatial_widget, this); - properties_panel_ = new components::Panel("Properties", properties_widget, this); + properties_panel_ = new components::Panel("Properties", properties_widget, this, false, true); layers_panel_ = new components::Panel("Layers", new panels::todo::TodoPanelWidget("Layers", this), this); stored_views_panel_ = new components::Panel( "Stored Views", new panels::todo::TodoPanelWidget("Stored Views", this), this); diff --git a/src/interface/components/KeyValueTable.cpp b/src/interface/components/KeyValueTable.cpp index 0fbc436b3d..61937f7df4 100644 --- a/src/interface/components/KeyValueTable.cpp +++ b/src/interface/components/KeyValueTable.cpp @@ -31,7 +31,7 @@ namespace ifcinterface::components { KeyValueTable::KeyValueTable(const QList& rows, QWidget* parent) : QWidget(parent) { - setObjectName("attributeList"); + setObjectName("keyValueTable"); auto* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); @@ -57,7 +57,7 @@ KeyValueTable::KeyValueTable(const QList& rows, QWidget* paren auto* value = new QLabel(row_data.value, row); value->setObjectName(row_data.value_object_name.isEmpty() - ? "propertyValueLabel" + ? "keyValueValueLabel" : row_data.value_object_name); value->setWordWrap(true); value->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); diff --git a/src/interface/components/KeyValueTable.h b/src/interface/components/KeyValueTable.h index 3e1ba10f73..807376ce94 100644 --- a/src/interface/components/KeyValueTable.h +++ b/src/interface/components/KeyValueTable.h @@ -30,7 +30,7 @@ namespace ifcinterface::components { struct KeyValueTableRow { QString key; QString value; - QString value_object_name = "propertyValueLabel"; + QString value_object_name = "keyValueValueLabel"; QString trailing_icon_path; QString trailing_icon_object_name; int key_minimum_width = 0; diff --git a/src/interface/components/Panel.cpp b/src/interface/components/Panel.cpp index 3d73c98f6c..8356a4e739 100644 --- a/src/interface/components/Panel.cpp +++ b/src/interface/components/Panel.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -70,7 +71,7 @@ public: } // namespace -Panel::Panel(const QString& title, QWidget* content, QWidget* parent, bool has_settings) +Panel::Panel(const QString& title, QWidget* content, QWidget* parent, bool has_settings, bool scrollable) : QDockWidget(title, parent) { auto* outer = new QFrame(); @@ -86,7 +87,24 @@ Panel::Panel(const QString& title, QWidget* content, QWidget* parent, bool has_s auto* frame_layout = new QVBoxLayout(frame); frame_layout->setContentsMargins(0, style::metrics::padding, 0, style::metrics::padding); frame_layout->setSpacing(0); - frame_layout->addWidget(content); + + if (scrollable) { + auto* scroll = new QScrollArea(frame); + scroll->setWidgetResizable(true); + scroll->setFrameShape(QFrame::NoFrame); + + auto* scroll_body = new QWidget(scroll); + scroll_body->setObjectName("panelScrollBody"); + auto* scroll_body_layout = new QVBoxLayout(scroll_body); + scroll_body_layout->setContentsMargins(0, 0, 0, 0); + scroll_body_layout->setSpacing(0); + scroll_body_layout->addWidget(content); + + scroll->setWidget(scroll_body); + frame_layout->addWidget(scroll); + } else { + frame_layout->addWidget(content); + } outer_layout->addWidget(frame); setObjectName(title); diff --git a/src/interface/components/Panel.h b/src/interface/components/Panel.h index 9739d53552..b786f636e9 100644 --- a/src/interface/components/Panel.h +++ b/src/interface/components/Panel.h @@ -31,7 +31,11 @@ class Panel : public QDockWidget { Q_OBJECT public: - explicit Panel(const QString& title, QWidget* content, QWidget* parent = nullptr, bool has_settings = false); + explicit Panel(const QString& title, + QWidget* content, + QWidget* parent = nullptr, + bool has_settings = false, + bool scrollable = false); }; } // namespace ifcinterface::components diff --git a/src/interface/components/Style.cpp b/src/interface/components/Style.cpp index 9c0b14a924..25f4cc226c 100644 --- a/src/interface/components/Style.cpp +++ b/src/interface/components/Style.cpp @@ -164,7 +164,7 @@ QString buildAppStyleSheet() { color: #9aa4b3; background: transparent; } - QWidget#attributeList { + QWidget#keyValueTable { background: transparent; } QTreeView::item, QListView::item, QTableView::item { @@ -237,7 +237,7 @@ QString buildAppStyleSheet() { QLabel#relationshipIconLabel { background: transparent; } - QWidget#inspectorPanel { + QWidget#panelScrollBody { background: #2b2f36; } QFrame#panelSectionHeader { @@ -274,24 +274,10 @@ QString buildAppStyleSheet() { color: #9aa4b3; background: transparent; } - QLabel#propertyValueLabel { + QLabel#keyValueValueLabel { color: #dce2eb; background: transparent; } - QLabel#relationshipValueLabel { - color: #dce2eb; - background: transparent; - } - QLabel#todoPanelTitle { - font-size: 14px; - font-weight: 600; - color: #e1e6ee; - background: transparent; - } - QLabel#todoPanelBody { - color: #8f98a6; - background: transparent; - } )") .arg(metrics::panel_radius) .arg(metrics::control_padding_y) diff --git a/src/interface/panels/properties/PropertiesPanelView.cpp b/src/interface/panels/properties/PropertiesPanelView.cpp index 291589762a..82fcee6f57 100644 --- a/src/interface/panels/properties/PropertiesPanelView.cpp +++ b/src/interface/panels/properties/PropertiesPanelView.cpp @@ -23,6 +23,7 @@ #include "PropertiesPanelWidget.h" #include "../../ElementRegistry.h" +#include "../../../ifcviewer/AppSettings.h" #include "../../../ifcviewer/ViewportWindow.h" namespace ifcinterface::panels::properties { @@ -79,8 +80,13 @@ void PropertiesPanelView::refresh(uint32_t object_id) { {"Paint Coverage", "42.78 m2"}}}, }; - if (registry_) { - auto info = registry_->find(object_id); + if (!registry_) { + widget_->render(state); + return; + } + + if (!AppSettings::instance().loadDataSource()) { + auto info = registry_->findBasicElementInfo(object_id); if (info && !info->type.isEmpty()) { state.entity.entity_class = info->type; if (!state.property_sets.isEmpty() && !state.property_sets[1].rows.isEmpty()) { @@ -96,6 +102,17 @@ void PropertiesPanelView::refresh(uint32_t object_id) { if (info && !info->guid.isEmpty()) { state.attributes[0].value = info->guid; } + + widget_->render(state); + return; + } + + auto entity = registry_->findEntity(object_id); + if (entity) { + state.entity.entity_class = QString::fromStdString(entity->declaration().name()); + if (!state.property_sets.isEmpty() && !state.property_sets[1].rows.isEmpty()) { + state.property_sets[1].rows[0].value = state.entity.entity_class; + } } widget_->render(state); } diff --git a/src/interface/panels/properties/PropertiesPanelWidget.cpp b/src/interface/panels/properties/PropertiesPanelWidget.cpp index 33db92fbb4..fce0d5fec5 100644 --- a/src/interface/panels/properties/PropertiesPanelWidget.cpp +++ b/src/interface/panels/properties/PropertiesPanelWidget.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include namespace { @@ -42,7 +41,7 @@ QWidget* makePropertySetPanel(const ifcinterface::panels::properties::PropertySe QList rows; for (const auto& row : property_set.rows) { - rows.append({row.key, row.value, "propertyValueLabel", "", "", 0}); + rows.append({row.key, row.value, "keyValueValueLabel", "", "", 0}); } layout->addWidget(new ifcinterface::components::KeyValueTable(rows, group)); return group; @@ -51,7 +50,7 @@ QWidget* makePropertySetPanel(const ifcinterface::panels::properties::PropertySe QWidget* makeAttributeList(const QList& rows, QWidget* parent = nullptr) { QList table_rows; for (const auto& row : rows) { - table_rows.append({row.key, row.value, "propertyValueLabel", "", "", 0}); + table_rows.append({row.key, row.value, "keyValueValueLabel", "", "", 0}); } return new ifcinterface::components::KeyValueTable(table_rows, parent); } @@ -61,7 +60,7 @@ QWidget* makeRelationshipList(const QListsetContentsMargins(0, 0, 0, 0); - root->setSpacing(0); - - scroll_ = new QScrollArea(this); - scroll_->setWidgetResizable(true); - scroll_->setFrameShape(QFrame::NoFrame); - - content_ = new QWidget(scroll_); - content_->setObjectName("inspectorPanel"); - content_layout_ = new QVBoxLayout(content_); + content_layout_ = new QVBoxLayout(this); content_layout_->setContentsMargins(0, 0, 0, 0); content_layout_->setSpacing(12); - - scroll_->setWidget(content_); - root->addWidget(scroll_); } void PropertiesPanelWidget::render(const PropertiesPanelState& state) { @@ -100,7 +86,7 @@ void PropertiesPanelWidget::render(const PropertiesPanelState& state) { delete item; } - auto* entity_card = new QFrame(content_); + auto* entity_card = new QFrame(this); entity_card->setObjectName("entityClassCard"); auto* entity_layout = new QHBoxLayout(entity_card); entity_layout->setContentsMargins(10, 8, 10, 8); @@ -123,23 +109,23 @@ void PropertiesPanelWidget::render(const PropertiesPanelState& state) { QList property_set_widgets; for (const auto& property_set : state.property_sets) { - property_set_widgets.append(makePropertySetPanel(property_set, content_)); + property_set_widgets.append(makePropertySetPanel(property_set, this)); } QList quantity_set_widgets; for (const auto& property_set : state.quantity_sets) { - quantity_set_widgets.append(makePropertySetPanel(property_set, content_)); + quantity_set_widgets.append(makePropertySetPanel(property_set, this)); } - auto* entity_section = new components::Section("", components::SectionHeaderMode::Hidden, "", content_); + auto* entity_section = new components::Section("", components::SectionHeaderMode::Hidden, "", this); entity_section->addBodyWidget(entity_card); - auto* attributes_section = new components::Section("Attributes", components::SectionHeaderMode::Visible, "", content_); - attributes_section->addBodyWidget(makeAttributeList(state.attributes, content_)); - auto* relationships_section = new components::Section("Relationships", components::SectionHeaderMode::Visible, "", content_); - relationships_section->addBodyWidget(makeRelationshipList(state.relationships, content_)); - auto* properties_section = new components::Section("Properties", components::SectionHeaderMode::Visible, "Filter properties or sets", content_); + auto* attributes_section = new components::Section("Attributes", components::SectionHeaderMode::Visible, "", this); + attributes_section->addBodyWidget(makeAttributeList(state.attributes, this)); + auto* relationships_section = new components::Section("Relationships", components::SectionHeaderMode::Visible, "", this); + relationships_section->addBodyWidget(makeRelationshipList(state.relationships, this)); + auto* properties_section = new components::Section("Properties", components::SectionHeaderMode::Visible, "Filter properties or sets", this); for (auto* widget : property_set_widgets) properties_section->addBodyWidget(widget); - auto* quantities_section = new components::Section("Quantities", components::SectionHeaderMode::Visible, "Filter quantities or sets", content_); + auto* quantities_section = new components::Section("Quantities", components::SectionHeaderMode::Visible, "Filter quantities or sets", this); for (auto* widget : quantity_set_widgets) quantities_section->addBodyWidget(widget); content_layout_->addWidget(entity_section); diff --git a/src/interface/panels/properties/PropertiesPanelWidget.h b/src/interface/panels/properties/PropertiesPanelWidget.h index ea929c22de..95b584bd50 100644 --- a/src/interface/panels/properties/PropertiesPanelWidget.h +++ b/src/interface/panels/properties/PropertiesPanelWidget.h @@ -25,7 +25,6 @@ #include -class QScrollArea; class QVBoxLayout; namespace ifcinterface::panels::properties { @@ -38,8 +37,6 @@ public: void render(const PropertiesPanelState& state); private: - QScrollArea* scroll_ = nullptr; - QWidget* content_ = nullptr; QVBoxLayout* content_layout_ = nullptr; }; diff --git a/src/interface/panels/todo/TodoPanelWidget.cpp b/src/interface/panels/todo/TodoPanelWidget.cpp index 36104e7b6d..32befba591 100644 --- a/src/interface/panels/todo/TodoPanelWidget.cpp +++ b/src/interface/panels/todo/TodoPanelWidget.cpp @@ -42,10 +42,8 @@ TodoPanelWidget::TodoPanelWidget(const QString& title, QWidget* parent) body_layout->setSpacing(12); auto* heading = new QLabel(title, body); - heading->setObjectName("todoPanelTitle"); auto* content = new QLabel("Coming soon", body); - content->setObjectName("todoPanelBody"); content->setAlignment(Qt::AlignCenter); body_layout->addWidget(heading);