mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 23:50:59 +00:00
Interface mockup 3
This commit is contained in:
@@ -25,8 +25,14 @@ find_package(Qt${QT_VERSION} COMPONENTS Core Gui Widgets Svg REQUIRED PATHS ${QT
|
|||||||
|
|
||||||
set(INTERFACE_FILES
|
set(INTERFACE_FILES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/MockMainWindow.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/MockMainWindow.h
|
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/components/SvgIcon.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/components/SvgIcon.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/components/CollapsibleSection.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/components/CollapsibleSection.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/components/PanelChrome.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/components/PanelChrome.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/panels/models/ModelsPanelTypes.h
|
${CMAKE_CURRENT_SOURCE_DIR}/panels/models/ModelsPanelTypes.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/panels/models/ModelsPanelWidget.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/panels/models/ModelsPanelWidget.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/panels/models/ModelsPanelWidget.h
|
${CMAKE_CURRENT_SOURCE_DIR}/panels/models/ModelsPanelWidget.h
|
||||||
|
|||||||
@@ -18,11 +18,13 @@
|
|||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
#include "MockMainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
|
||||||
#include "AppSettings.h"
|
#include "../ifcviewer/AppSettings.h"
|
||||||
#include "SceneLoader.h"
|
#include "../ifcviewer/SceneLoader.h"
|
||||||
#include "ViewportWindow.h"
|
#include "../ifcviewer/ViewportWindow.h"
|
||||||
|
#include "components/PanelChrome.h"
|
||||||
|
#include "components/SvgIcon.h"
|
||||||
#include "panels/models/ModelsPanelView.h"
|
#include "panels/models/ModelsPanelView.h"
|
||||||
#include "panels/models/ModelsPanelWidget.h"
|
#include "panels/models/ModelsPanelWidget.h"
|
||||||
#include "panels/properties/PropertiesPanelView.h"
|
#include "panels/properties/PropertiesPanelView.h"
|
||||||
@@ -32,154 +34,21 @@
|
|||||||
|
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QFile>
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPainter>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QSvgRenderer>
|
|
||||||
#include <QSignalBlocker>
|
#include <QSignalBlocker>
|
||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
#include <QTableWidget>
|
|
||||||
#include <QTabBar>
|
#include <QTabBar>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QTreeWidget>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
namespace {
|
namespace ifcinterface::shell {
|
||||||
|
|
||||||
QPixmap renderTintedSvgPixmap(const QString& icon_path, const QString& color, const QSize& size) {
|
MainWindow::MainWindow(QWidget* parent)
|
||||||
QFile file(icon_path);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
return QIcon(icon_path).pixmap(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString svg = QString::fromUtf8(file.readAll());
|
|
||||||
QString tinted = svg;
|
|
||||||
tinted.replace("currentColor", color, Qt::CaseSensitive);
|
|
||||||
tinted.replace(QRegularExpression(R"(stroke="[^"]*")"), QString("stroke=\"%1\"").arg(color));
|
|
||||||
tinted.replace(QRegularExpression(R"(fill="none")"), "fill=\"none\"");
|
|
||||||
QByteArray data = tinted.toUtf8();
|
|
||||||
QSvgRenderer renderer(data);
|
|
||||||
QPixmap pixmap(size);
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
renderer.render(&painter);
|
|
||||||
return pixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon makeTintedSvgIcon(const QString& icon_path, const QString& normal = "#39b54a",
|
|
||||||
const QString& active = "#53c763", const QString& disabled = "#6f7988") {
|
|
||||||
QFile file(icon_path);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
return QIcon(icon_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon icon;
|
|
||||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, normal, QSize(20, 20)), QIcon::Normal, QIcon::Off);
|
|
||||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, active, QSize(20, 20)), QIcon::Active, QIcon::Off);
|
|
||||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, active, QSize(20, 20)), QIcon::Selected, QIcon::Off);
|
|
||||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, disabled, QSize(20, 20)), QIcon::Disabled, QIcon::Off);
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon makePanelSvgIcon(const QString& icon_path) {
|
|
||||||
return makeTintedSvgIcon(icon_path, "#e7ebf2", "#ffffff", "#6f7988");
|
|
||||||
}
|
|
||||||
|
|
||||||
class DockTitleBar : public QWidget {
|
|
||||||
public:
|
|
||||||
explicit DockTitleBar(const QString& title, bool has_settings = false, QWidget* parent = nullptr)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
auto* layout = new QHBoxLayout(this);
|
|
||||||
layout->setContentsMargins(10, 6, 6, 6);
|
|
||||||
layout->setSpacing(6);
|
|
||||||
|
|
||||||
auto* text = new QLabel(title.toUpper(), this);
|
|
||||||
text->setObjectName("dockTitleText");
|
|
||||||
|
|
||||||
layout->addWidget(text);
|
|
||||||
layout->addStretch(1);
|
|
||||||
if (has_settings) {
|
|
||||||
auto* settings = new QToolButton(this);
|
|
||||||
settings->setIcon(makePanelSvgIcon(":/icons/settings.svg"));
|
|
||||||
settings->setAutoRaise(true);
|
|
||||||
settings->setCursor(Qt::ArrowCursor);
|
|
||||||
settings->setFixedSize(18, 18);
|
|
||||||
settings->setObjectName("dockTitleButton");
|
|
||||||
settings->setToolTip(QString("%1 settings").arg(title));
|
|
||||||
connect(settings, &QToolButton::clicked, this, [this, title]() {
|
|
||||||
auto* anchor = parentWidget();
|
|
||||||
QMenu menu(anchor);
|
|
||||||
menu.addAction(QString("%1 settings coming soon").arg(title));
|
|
||||||
menu.exec(QCursor::pos());
|
|
||||||
});
|
|
||||||
layout->addWidget(settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
QDockWidget* makeDock(const QString& title, QWidget* content, QWidget* parent, bool has_settings = false) {
|
|
||||||
auto* dock = new QDockWidget(title, parent);
|
|
||||||
dock->setObjectName(title);
|
|
||||||
dock->setFeatures(QDockWidget::DockWidgetMovable |
|
|
||||||
QDockWidget::DockWidgetFloatable |
|
|
||||||
QDockWidget::DockWidgetClosable);
|
|
||||||
dock->setTitleBarWidget(new DockTitleBar(title, has_settings, dock));
|
|
||||||
dock->setWidget(content);
|
|
||||||
return dock;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFrame* wrapPanel(QWidget* inner) {
|
|
||||||
auto* outer = new QFrame();
|
|
||||||
auto* outer_layout = new QVBoxLayout(outer);
|
|
||||||
outer_layout->setContentsMargins(6, 6, 6, 6);
|
|
||||||
outer_layout->setSpacing(0);
|
|
||||||
|
|
||||||
auto* frame = new QFrame(outer);
|
|
||||||
frame->setObjectName("panelFrame");
|
|
||||||
auto* layout = new QVBoxLayout(frame);
|
|
||||||
layout->setContentsMargins(8, 8, 8, 8);
|
|
||||||
layout->setSpacing(0);
|
|
||||||
layout->addWidget(inner);
|
|
||||||
|
|
||||||
outer_layout->addWidget(frame);
|
|
||||||
return outer;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFrame* wrapInspectorPanel(QWidget* inner) {
|
|
||||||
auto* outer = new QFrame();
|
|
||||||
auto* outer_layout = new QVBoxLayout(outer);
|
|
||||||
outer_layout->setContentsMargins(6, 6, 6, 6);
|
|
||||||
outer_layout->setSpacing(0);
|
|
||||||
|
|
||||||
auto* frame = new QFrame(outer);
|
|
||||||
frame->setObjectName("panelFrame");
|
|
||||||
auto* layout = new QVBoxLayout(frame);
|
|
||||||
layout->setContentsMargins(0, 8, 0, 8);
|
|
||||||
layout->setSpacing(0);
|
|
||||||
layout->addWidget(inner);
|
|
||||||
|
|
||||||
outer_layout->addWidget(frame);
|
|
||||||
return outer;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
MockMainWindow::MockMainWindow(QWidget* parent)
|
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
{
|
{
|
||||||
setupChrome();
|
setupChrome();
|
||||||
@@ -191,7 +60,7 @@ MockMainWindow::MockMainWindow(QWidget* parent)
|
|||||||
resize(1720, 980);
|
resize(1720, 980);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::setupChrome() {
|
void MainWindow::setupChrome() {
|
||||||
setWindowTitle("IfcOpenShell Interface");
|
setWindowTitle("IfcOpenShell Interface");
|
||||||
setDockOptions(QMainWindow::AllowNestedDocks |
|
setDockOptions(QMainWindow::AllowNestedDocks |
|
||||||
QMainWindow::AllowTabbedDocks |
|
QMainWindow::AllowTabbedDocks |
|
||||||
@@ -459,12 +328,12 @@ void MockMainWindow::setupChrome() {
|
|||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
QToolButton* MockMainWindow::makeRibbonAction(const QString& text, const QString& icon_path) {
|
QToolButton* MainWindow::makeRibbonAction(const QString& text, const QString& icon_path) {
|
||||||
auto* button = new QToolButton(this);
|
auto* button = new QToolButton(this);
|
||||||
button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
||||||
button->setIcon(icon_path.endsWith(".svg")
|
button->setIcon(icon_path.endsWith(".svg")
|
||||||
? makeTintedSvgIcon(icon_path)
|
? components::icons::makeTintedSvgIcon(icon_path)
|
||||||
: QIcon(icon_path));
|
: QIcon(icon_path));
|
||||||
button->setIconSize(QSize(20, 20));
|
button->setIconSize(QSize(20, 20));
|
||||||
button->setText(text);
|
button->setText(text);
|
||||||
button->setMinimumSize(QSize(68, 54));
|
button->setMinimumSize(QSize(68, 54));
|
||||||
@@ -473,7 +342,7 @@ QToolButton* MockMainWindow::makeRibbonAction(const QString& text, const QString
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* MockMainWindow::makeRibbonGroup(const QString& title, const QList<QToolButton*>& buttons) {
|
QWidget* MainWindow::makeRibbonGroup(const QString& title, const QList<QToolButton*>& buttons) {
|
||||||
auto* group = new QFrame(this);
|
auto* group = new QFrame(this);
|
||||||
group->setObjectName("ribbonGroup");
|
group->setObjectName("ribbonGroup");
|
||||||
auto* group_layout = new QVBoxLayout(group);
|
auto* group_layout = new QVBoxLayout(group);
|
||||||
@@ -493,7 +362,7 @@ QWidget* MockMainWindow::makeRibbonGroup(const QString& title, const QList<QTool
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* MockMainWindow::makeComingSoonPanel(const QString& title) {
|
QWidget* MainWindow::makeComingSoonPanel(const QString& title) {
|
||||||
auto* widget = new QWidget(this);
|
auto* widget = new QWidget(this);
|
||||||
auto* layout = new QVBoxLayout(widget);
|
auto* layout = new QVBoxLayout(widget);
|
||||||
layout->setContentsMargins(12, 12, 12, 12);
|
layout->setContentsMargins(12, 12, 12, 12);
|
||||||
@@ -509,12 +378,12 @@ QWidget* MockMainWindow::makeComingSoonPanel(const QString& title) {
|
|||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::setStatusMessage(const QString& mode, const QString& detail) {
|
void MainWindow::setStatusMessage(const QString& mode, const QString& detail) {
|
||||||
status_mode_label_->setText(mode);
|
status_mode_label_->setText(mode);
|
||||||
status_selection_label_->setText(detail);
|
status_selection_label_->setText(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
QToolButton* MockMainWindow::makePanelToggle(const QString& text, QDockWidget* dock) {
|
QToolButton* MainWindow::makePanelToggle(const QString& text, QDockWidget* dock) {
|
||||||
auto* button = makeRibbonAction(text, ":/icons/dm_toggle_openings.png");
|
auto* button = makeRibbonAction(text, ":/icons/dm_toggle_openings.png");
|
||||||
button->setCheckable(true);
|
button->setCheckable(true);
|
||||||
button->setChecked(dock->isVisible());
|
button->setChecked(dock->isVisible());
|
||||||
@@ -529,7 +398,7 @@ QToolButton* MockMainWindow::makePanelToggle(const QString& text, QDockWidget* d
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* MockMainWindow::buildHomeRibbonPage() {
|
QWidget* MainWindow::buildHomeRibbonPage() {
|
||||||
auto* page = new QFrame(this);
|
auto* page = new QFrame(this);
|
||||||
page->setObjectName("ribbonPage");
|
page->setObjectName("ribbonPage");
|
||||||
auto* row = new QHBoxLayout(page);
|
auto* row = new QHBoxLayout(page);
|
||||||
@@ -562,7 +431,7 @@ QWidget* MockMainWindow::buildHomeRibbonPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
auto* add_model = makeRibbonAction("Add Model", ":/icons/cube.svg");
|
auto* add_model = makeRibbonAction("Add Model", ":/icons/cube.svg");
|
||||||
connect(add_model, &QToolButton::clicked, this, &MockMainWindow::onAddFiles);
|
connect(add_model, &QToolButton::clicked, this, &MainWindow::onAddFiles);
|
||||||
auto* sync_models = makeRibbonAction("Sync Models", ":/icons/refresh-double.svg");
|
auto* sync_models = makeRibbonAction("Sync Models", ":/icons/refresh-double.svg");
|
||||||
connect(sync_models, &QToolButton::clicked, this, [this]() {
|
connect(sync_models, &QToolButton::clicked, this, [this]() {
|
||||||
setStatusMessage("Models", "Sync models coming soon");
|
setStatusMessage("Models", "Sync models coming soon");
|
||||||
@@ -580,7 +449,7 @@ QWidget* MockMainWindow::buildHomeRibbonPage() {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* MockMainWindow::buildNavigateRibbonPage() {
|
QWidget* MainWindow::buildNavigateRibbonPage() {
|
||||||
auto* page = new QFrame(this);
|
auto* page = new QFrame(this);
|
||||||
page->setObjectName("ribbonPage");
|
page->setObjectName("ribbonPage");
|
||||||
auto* row = new QHBoxLayout(page);
|
auto* row = new QHBoxLayout(page);
|
||||||
@@ -643,7 +512,7 @@ QWidget* MockMainWindow::buildNavigateRibbonPage() {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* MockMainWindow::buildInspectRibbonPage() {
|
QWidget* MainWindow::buildInspectRibbonPage() {
|
||||||
auto* page = new QFrame(this);
|
auto* page = new QFrame(this);
|
||||||
page->setObjectName("ribbonPage");
|
page->setObjectName("ribbonPage");
|
||||||
auto* row = new QHBoxLayout(page);
|
auto* row = new QHBoxLayout(page);
|
||||||
@@ -686,7 +555,7 @@ QWidget* MockMainWindow::buildInspectRibbonPage() {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* MockMainWindow::buildPanelsRibbonPage() {
|
QWidget* MainWindow::buildPanelsRibbonPage() {
|
||||||
auto* page = new QFrame(this);
|
auto* page = new QFrame(this);
|
||||||
page->setObjectName("ribbonPage");
|
page->setObjectName("ribbonPage");
|
||||||
auto* row = new QHBoxLayout(page);
|
auto* row = new QHBoxLayout(page);
|
||||||
@@ -712,7 +581,7 @@ QWidget* MockMainWindow::buildPanelsRibbonPage() {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::setupRibbon() {
|
void MainWindow::setupRibbon() {
|
||||||
auto* shell = new QFrame(this);
|
auto* shell = new QFrame(this);
|
||||||
shell->setObjectName("ribbonShell");
|
shell->setObjectName("ribbonShell");
|
||||||
|
|
||||||
@@ -751,7 +620,7 @@ void MockMainWindow::setupRibbon() {
|
|||||||
setMenuWidget(shell);
|
setMenuWidget(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::setupViewport() {
|
void MainWindow::setupViewport() {
|
||||||
viewport_ = new ViewportWindow();
|
viewport_ = new ViewportWindow();
|
||||||
viewport_container_ = QWidget::createWindowContainer(viewport_, this);
|
viewport_container_ = QWidget::createWindowContainer(viewport_, this);
|
||||||
viewport_container_->setMinimumSize(400, 300);
|
viewport_container_->setMinimumSize(400, 300);
|
||||||
@@ -773,29 +642,38 @@ void MockMainWindow::setupViewport() {
|
|||||||
setCentralWidget(shell);
|
setCentralWidget(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::setupDocks() {
|
void MainWindow::setupDocks() {
|
||||||
auto* models_panel = new ifcinterface::panels::models::ModelsPanelWidget(this);
|
auto* models_panel = new panels::models::ModelsPanelWidget(this);
|
||||||
auto* spatial_panel = new ifcinterface::panels::spatial_hierarchy::SpatialHierarchyPanelWidget(this);
|
auto* spatial_panel = new panels::spatial_hierarchy::SpatialHierarchyPanelWidget(this);
|
||||||
auto* properties_panel = new ifcinterface::panels::properties::PropertiesPanelWidget(this);
|
auto* properties_panel = new panels::properties::PropertiesPanelWidget(this);
|
||||||
|
|
||||||
models_panel_view_ = new ifcinterface::panels::models::ModelsPanelView(models_panel, this);
|
models_panel_view_ = new panels::models::ModelsPanelView(models_panel, this);
|
||||||
spatial_panel_view_ = new ifcinterface::panels::spatial_hierarchy::SpatialHierarchyPanelView(spatial_panel, this);
|
spatial_panel_view_ = new panels::spatial_hierarchy::SpatialHierarchyPanelView(spatial_panel, this);
|
||||||
properties_panel_view_ = new ifcinterface::panels::properties::PropertiesPanelView(properties_panel, this);
|
properties_panel_view_ = new panels::properties::PropertiesPanelView(properties_panel, this);
|
||||||
|
|
||||||
connect(models_panel_view_, &ifcinterface::panels::models::ModelsPanelView::statusMessageRequested,
|
connect(models_panel_view_, &panels::models::ModelsPanelView::statusMessageRequested,
|
||||||
this, &MockMainWindow::setStatusMessage);
|
this, &MainWindow::setStatusMessage);
|
||||||
connect(spatial_panel_view_, &ifcinterface::panels::spatial_hierarchy::SpatialHierarchyPanelView::statusMessageRequested,
|
connect(spatial_panel_view_, &panels::spatial_hierarchy::SpatialHierarchyPanelView::statusMessageRequested,
|
||||||
this, &MockMainWindow::setStatusMessage);
|
this, &MainWindow::setStatusMessage);
|
||||||
|
|
||||||
models_dock_ = makeDock("Models", wrapPanel(models_panel), this, true);
|
models_dock_ = components::panel::makeDock(
|
||||||
spatial_dock_ = makeDock("Spatial Hierarchy", wrapPanel(spatial_panel), this);
|
"Models", components::panel::wrapPanel(models_panel), this, true);
|
||||||
properties_dock_ = makeDock("Properties", wrapInspectorPanel(properties_panel), this);
|
spatial_dock_ = components::panel::makeDock(
|
||||||
layers_dock_ = makeDock("Layers", wrapPanel(makeComingSoonPanel("Layers")), this);
|
"Spatial Hierarchy", components::panel::wrapPanel(spatial_panel), this);
|
||||||
stored_views_dock_ = makeDock("Stored Views", wrapPanel(makeComingSoonPanel("Stored Views")), this);
|
properties_dock_ = components::panel::makeDock(
|
||||||
search_dock_ = makeDock("Search and Query", wrapPanel(makeComingSoonPanel("Search and Query")), this);
|
"Properties", components::panel::wrapInspectorPanel(properties_panel), this);
|
||||||
spreadsheet_dock_ = makeDock("Spreadsheet", wrapPanel(makeComingSoonPanel("Spreadsheet")), this);
|
layers_dock_ = components::panel::makeDock(
|
||||||
clash_dock_ = makeDock("Clash", wrapPanel(makeComingSoonPanel("Clash")), this);
|
"Layers", components::panel::wrapPanel(makeComingSoonPanel("Layers")), this);
|
||||||
issues_dock_ = makeDock("Issues", wrapPanel(makeComingSoonPanel("Issues")), this);
|
stored_views_dock_ = components::panel::makeDock(
|
||||||
|
"Stored Views", components::panel::wrapPanel(makeComingSoonPanel("Stored Views")), this);
|
||||||
|
search_dock_ = components::panel::makeDock(
|
||||||
|
"Search and Query", components::panel::wrapPanel(makeComingSoonPanel("Search and Query")), this);
|
||||||
|
spreadsheet_dock_ = components::panel::makeDock(
|
||||||
|
"Spreadsheet", components::panel::wrapPanel(makeComingSoonPanel("Spreadsheet")), this);
|
||||||
|
clash_dock_ = components::panel::makeDock(
|
||||||
|
"Clash", components::panel::wrapPanel(makeComingSoonPanel("Clash")), this);
|
||||||
|
issues_dock_ = components::panel::makeDock(
|
||||||
|
"Issues", components::panel::wrapPanel(makeComingSoonPanel("Issues")), this);
|
||||||
|
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, models_dock_);
|
addDockWidget(Qt::LeftDockWidgetArea, models_dock_);
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, spatial_dock_);
|
addDockWidget(Qt::LeftDockWidgetArea, spatial_dock_);
|
||||||
@@ -828,7 +706,7 @@ void MockMainWindow::setupDocks() {
|
|||||||
resizeDocks({models_dock_, spatial_dock_}, {280, 240}, Qt::Vertical);
|
resizeDocks({models_dock_, spatial_dock_}, {280, 240}, Qt::Vertical);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::setupStatus() {
|
void MainWindow::setupStatus() {
|
||||||
status_mode_label_ = new QLabel("Ready", this);
|
status_mode_label_ = new QLabel("Ready", this);
|
||||||
status_selection_label_ = new QLabel("No selection", this);
|
status_selection_label_ = new QLabel("No selection", this);
|
||||||
status_perf_label_ = new QLabel(this);
|
status_perf_label_ = new QLabel(this);
|
||||||
@@ -845,15 +723,15 @@ void MockMainWindow::setupStatus() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::setupLoader() {
|
void MainWindow::setupLoader() {
|
||||||
AppSettings::instance().setLoadDataSource(false);
|
AppSettings::instance().setLoadDataSource(false);
|
||||||
loader_ = new SceneLoader(viewport_, this);
|
loader_ = new SceneLoader(viewport_, this);
|
||||||
connect(loader_, &SceneLoader::loadStarted, this, &MockMainWindow::onLoadStarted);
|
connect(loader_, &SceneLoader::loadStarted, this, &MainWindow::onLoadStarted);
|
||||||
connect(loader_, &SceneLoader::loadedFromSidecar, this, &MockMainWindow::onLoadedFromSidecar);
|
connect(loader_, &SceneLoader::loadedFromSidecar, this, &MainWindow::onLoadedFromSidecar);
|
||||||
connect(loader_, &SceneLoader::loadedFromStream, this, &MockMainWindow::onLoadedFromStream);
|
connect(loader_, &SceneLoader::loadedFromStream, this, &MainWindow::onLoadedFromStream);
|
||||||
connect(loader_, &SceneLoader::loadCancelled, this, &MockMainWindow::onLoadCancelled);
|
connect(loader_, &SceneLoader::loadCancelled, this, &MainWindow::onLoadCancelled);
|
||||||
connect(loader_, &SceneLoader::loadError, this, &MockMainWindow::onLoadError);
|
connect(loader_, &SceneLoader::loadError, this, &MainWindow::onLoadError);
|
||||||
connect(loader_, &SceneLoader::allLoadsFinished, this, &MockMainWindow::onAllLoadsFinished);
|
connect(loader_, &SceneLoader::allLoadsFinished, this, &MainWindow::onAllLoadsFinished);
|
||||||
|
|
||||||
connect(viewport_, &ViewportWindow::frameStatsUpdated, this,
|
connect(viewport_, &ViewportWindow::frameStatsUpdated, this,
|
||||||
[this](const ViewportWindow::FrameStats& s) {
|
[this](const ViewportWindow::FrameStats& s) {
|
||||||
@@ -870,30 +748,30 @@ void MockMainWindow::setupLoader() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::addFiles(const QStringList& paths) {
|
void MainWindow::addFiles(const QStringList& paths) {
|
||||||
if (paths.isEmpty()) return;
|
if (paths.isEmpty()) return;
|
||||||
loader_->addFiles(paths);
|
loader_->addFiles(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MockMainWindow::formatElapsed(qint64 ms) const {
|
QString MainWindow::formatElapsed(qint64 ms) const {
|
||||||
return (ms >= 1000)
|
return (ms >= 1000)
|
||||||
? QString::number(ms / 1000.0, 'f', 2) + " s"
|
? QString::number(ms / 1000.0, 'f', 2) + " s"
|
||||||
: QString::number(ms) + " ms";
|
: QString::number(ms) + " ms";
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::onAddFiles() {
|
void MainWindow::onAddFiles() {
|
||||||
const QStringList paths = QFileDialog::getOpenFileNames(
|
const QStringList paths = QFileDialog::getOpenFileNames(
|
||||||
this, "Add IFC Files", QString(),
|
this, "Add IFC Files", QString(),
|
||||||
"IFC Viewer Cache (*.ifcview)");
|
"IFC Viewer Cache (*.ifcview)");
|
||||||
addFiles(paths);
|
addFiles(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::onLoadStarted(uint32_t /*mid*/, QString display_name) {
|
void MainWindow::onLoadStarted(uint32_t /*mid*/, QString display_name) {
|
||||||
status_mode_label_->setText("Loading");
|
status_mode_label_->setText("Loading");
|
||||||
status_selection_label_->setText(display_name);
|
status_selection_label_->setText(display_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::onLoadedFromSidecar(uint32_t mid, qint64 elapsed_ms) {
|
void MainWindow::onLoadedFromSidecar(uint32_t mid, qint64 elapsed_ms) {
|
||||||
status_mode_label_->setText("Loaded");
|
status_mode_label_->setText("Loaded");
|
||||||
status_selection_label_->setText(
|
status_selection_label_->setText(
|
||||||
QString("%1 from cache in %2")
|
QString("%1 from cache in %2")
|
||||||
@@ -901,7 +779,7 @@ void MockMainWindow::onLoadedFromSidecar(uint32_t mid, qint64 elapsed_ms) {
|
|||||||
.arg(formatElapsed(elapsed_ms)));
|
.arg(formatElapsed(elapsed_ms)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::onLoadedFromStream(uint32_t mid, qint64 elapsed_ms) {
|
void MainWindow::onLoadedFromStream(uint32_t mid, qint64 elapsed_ms) {
|
||||||
status_mode_label_->setText("Loaded");
|
status_mode_label_->setText("Loaded");
|
||||||
status_selection_label_->setText(
|
status_selection_label_->setText(
|
||||||
QString("%1 streamed in %2")
|
QString("%1 streamed in %2")
|
||||||
@@ -909,18 +787,20 @@ void MockMainWindow::onLoadedFromStream(uint32_t mid, qint64 elapsed_ms) {
|
|||||||
.arg(formatElapsed(elapsed_ms)));
|
.arg(formatElapsed(elapsed_ms)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::onLoadCancelled(uint32_t mid) {
|
void MainWindow::onLoadCancelled(uint32_t mid) {
|
||||||
status_mode_label_->setText("Cancelled");
|
status_mode_label_->setText("Cancelled");
|
||||||
status_selection_label_->setText(loader_->displayName(mid));
|
status_selection_label_->setText(loader_->displayName(mid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::onLoadError(uint32_t /*mid*/, QString message) {
|
void MainWindow::onLoadError(uint32_t /*mid*/, QString message) {
|
||||||
status_mode_label_->setText("Error");
|
status_mode_label_->setText("Error");
|
||||||
status_selection_label_->setText(message);
|
status_selection_label_->setText(message);
|
||||||
QMessageBox::warning(this, "IfcInterfaceMockup", message);
|
QMessageBox::warning(this, "IfcInterfaceMockup", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockMainWindow::onAllLoadsFinished() {
|
void MainWindow::onAllLoadsFinished() {
|
||||||
status_mode_label_->setText("Loaded");
|
status_mode_label_->setText("Loaded");
|
||||||
status_selection_label_->setText(QString("%1 model(s)").arg(loader_->modelCount()));
|
status_selection_label_->setText(QString("%1 model(s)").arg(loader_->modelCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace ifcinterface::shell
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
#ifndef IFCINTERFACE_MOCKMAINWINDOW_H
|
#ifndef IFCINTERFACE_SHELL_MAINWINDOW_H
|
||||||
#define IFCINTERFACE_MOCKMAINWINDOW_H
|
#define IFCINTERFACE_SHELL_MAINWINDOW_H
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@@ -35,10 +35,12 @@ namespace ifcinterface::panels::models { class ModelsPanelView; }
|
|||||||
namespace ifcinterface::panels::spatial_hierarchy { class SpatialHierarchyPanelView; }
|
namespace ifcinterface::panels::spatial_hierarchy { class SpatialHierarchyPanelView; }
|
||||||
namespace ifcinterface::panels::properties { class PropertiesPanelView; }
|
namespace ifcinterface::panels::properties { class PropertiesPanelView; }
|
||||||
|
|
||||||
class MockMainWindow : public QMainWindow {
|
namespace ifcinterface::shell {
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit MockMainWindow(QWidget* parent = nullptr);
|
explicit MainWindow(QWidget* parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupChrome();
|
void setupChrome();
|
||||||
@@ -91,4 +93,6 @@ private:
|
|||||||
ifcinterface::panels::properties::PropertiesPanelView* properties_panel_view_ = nullptr;
|
ifcinterface::panels::properties::PropertiesPanelView* properties_panel_view_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace ifcinterface::shell
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// This file was generated with the assistance of an AI coding tool.
|
||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "CollapsibleSection.h"
|
||||||
|
|
||||||
|
#include "SvgIcon.h"
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
namespace ifcinterface::components::inspector {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QWidget* makeInspectorFilterField(const QString& placeholder, QWidget* parent = nullptr) {
|
||||||
|
auto* field = new QLineEdit(parent);
|
||||||
|
field->setPlaceholderText(placeholder);
|
||||||
|
field->setClearButtonEnabled(true);
|
||||||
|
field->addAction(icons::makePanelSvgIcon(":/icons/filter.svg"), QLineEdit::LeadingPosition);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CollapsibleSection::CollapsibleSection(const QString& title, const QString& filter_placeholder, QWidget* parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
setObjectName("inspectorSection");
|
||||||
|
auto* layout = new QVBoxLayout(this);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
layout->setSpacing(6);
|
||||||
|
|
||||||
|
auto* header = new QFrame(this);
|
||||||
|
header->setObjectName("inspectorSectionHeader");
|
||||||
|
auto* header_layout = new QHBoxLayout(header);
|
||||||
|
header_layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
header_layout->setSpacing(6);
|
||||||
|
|
||||||
|
auto* toggle = new QToolButton(header);
|
||||||
|
toggle->setObjectName("inspectorSectionButton");
|
||||||
|
toggle->setText(title);
|
||||||
|
toggle->setCheckable(true);
|
||||||
|
toggle->setChecked(true);
|
||||||
|
toggle->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||||
|
toggle->setArrowType(Qt::DownArrow);
|
||||||
|
header_layout->addWidget(toggle);
|
||||||
|
header_layout->addStretch(1);
|
||||||
|
|
||||||
|
if (!filter_placeholder.isEmpty()) {
|
||||||
|
auto* filter_toggle = new QToolButton(header);
|
||||||
|
filter_toggle->setObjectName("inspectorFilterToggle");
|
||||||
|
filter_toggle->setCheckable(true);
|
||||||
|
filter_toggle->setIcon(icons::makePanelSvgIcon(":/icons/filter.svg"));
|
||||||
|
filter_toggle->setAutoRaise(true);
|
||||||
|
header_layout->addWidget(filter_toggle);
|
||||||
|
|
||||||
|
filter_field_ = qobject_cast<QLineEdit*>(makeInspectorFilterField(filter_placeholder, this));
|
||||||
|
filter_field_->setVisible(false);
|
||||||
|
connect(filter_toggle, &QToolButton::toggled, filter_field_, [this](bool visible) {
|
||||||
|
filter_field_->setVisible(visible);
|
||||||
|
if (visible) filter_field_->setFocus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
body_ = new QWidget(this);
|
||||||
|
body_->setObjectName("inspectorSectionBody");
|
||||||
|
body_layout_ = new QVBoxLayout(body_);
|
||||||
|
body_layout_->setContentsMargins(10, 6, 10, 0);
|
||||||
|
body_layout_->setSpacing(6);
|
||||||
|
|
||||||
|
connect(toggle, &QToolButton::toggled, body_, [toggle, this](bool expanded) {
|
||||||
|
toggle->setArrowType(expanded ? Qt::DownArrow : Qt::RightArrow);
|
||||||
|
body_->setVisible(expanded);
|
||||||
|
});
|
||||||
|
|
||||||
|
layout->addWidget(header);
|
||||||
|
if (filter_field_) {
|
||||||
|
auto* filter_wrapper = new QWidget(this);
|
||||||
|
filter_wrapper->setObjectName("inspectorFilterWrapper");
|
||||||
|
auto* filter_wrapper_layout = new QVBoxLayout(filter_wrapper);
|
||||||
|
filter_wrapper_layout->setContentsMargins(10, 0, 10, 0);
|
||||||
|
filter_wrapper_layout->setSpacing(0);
|
||||||
|
filter_wrapper_layout->addWidget(filter_field_);
|
||||||
|
layout->addWidget(filter_wrapper);
|
||||||
|
}
|
||||||
|
layout->addWidget(body_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollapsibleSection::addBodyWidget(QWidget* widget) {
|
||||||
|
body_layout_->addWidget(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ifcinterface::components::inspector
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// This file was generated with the assistance of an AI coding tool.
|
||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef IFCINTERFACE_COMPONENTS_INSPECTOR_COLLAPSIBLESECTION_H
|
||||||
|
#define IFCINTERFACE_COMPONENTS_INSPECTOR_COLLAPSIBLESECTION_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class QVBoxLayout;
|
||||||
|
|
||||||
|
namespace ifcinterface::components::inspector {
|
||||||
|
|
||||||
|
class CollapsibleSection : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit CollapsibleSection(const QString& title,
|
||||||
|
const QString& filter_placeholder = {},
|
||||||
|
QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
void addBodyWidget(QWidget* widget);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWidget* body_ = nullptr;
|
||||||
|
QVBoxLayout* body_layout_ = nullptr;
|
||||||
|
QLineEdit* filter_field_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ifcinterface::components::inspector
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
// This file was generated with the assistance of an AI coding tool.
|
||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "PanelChrome.h"
|
||||||
|
|
||||||
|
#include "SvgIcon.h"
|
||||||
|
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
namespace ifcinterface::components::panel {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class DockTitleBar : public QWidget {
|
||||||
|
public:
|
||||||
|
explicit DockTitleBar(const QString& title, bool has_settings = false, QWidget* parent = nullptr)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
auto* layout = new QHBoxLayout(this);
|
||||||
|
layout->setContentsMargins(10, 6, 6, 6);
|
||||||
|
layout->setSpacing(6);
|
||||||
|
|
||||||
|
auto* text = new QLabel(title.toUpper(), this);
|
||||||
|
text->setObjectName("dockTitleText");
|
||||||
|
|
||||||
|
layout->addWidget(text);
|
||||||
|
layout->addStretch(1);
|
||||||
|
if (has_settings) {
|
||||||
|
auto* settings = new QToolButton(this);
|
||||||
|
settings->setIcon(icons::makePanelSvgIcon(":/icons/settings.svg"));
|
||||||
|
settings->setAutoRaise(true);
|
||||||
|
settings->setCursor(Qt::ArrowCursor);
|
||||||
|
settings->setFixedSize(18, 18);
|
||||||
|
settings->setObjectName("dockTitleButton");
|
||||||
|
settings->setToolTip(QString("%1 settings").arg(title));
|
||||||
|
connect(settings, &QToolButton::clicked, this, [this, title]() {
|
||||||
|
auto* anchor = parentWidget();
|
||||||
|
QMenu menu(anchor);
|
||||||
|
menu.addAction(QString("%1 settings coming soon").arg(title));
|
||||||
|
menu.exec(QCursor::pos());
|
||||||
|
});
|
||||||
|
layout->addWidget(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
QDockWidget* makeDock(const QString& title, QWidget* content, QWidget* parent, bool has_settings) {
|
||||||
|
auto* dock = new QDockWidget(title, parent);
|
||||||
|
dock->setObjectName(title);
|
||||||
|
dock->setFeatures(QDockWidget::DockWidgetMovable |
|
||||||
|
QDockWidget::DockWidgetFloatable |
|
||||||
|
QDockWidget::DockWidgetClosable);
|
||||||
|
dock->setTitleBarWidget(new DockTitleBar(title, has_settings, dock));
|
||||||
|
dock->setWidget(content);
|
||||||
|
return dock;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFrame* wrapPanel(QWidget* inner) {
|
||||||
|
auto* outer = new QFrame();
|
||||||
|
auto* outer_layout = new QVBoxLayout(outer);
|
||||||
|
outer_layout->setContentsMargins(6, 6, 6, 6);
|
||||||
|
outer_layout->setSpacing(0);
|
||||||
|
|
||||||
|
auto* frame = new QFrame(outer);
|
||||||
|
frame->setObjectName("panelFrame");
|
||||||
|
auto* layout = new QVBoxLayout(frame);
|
||||||
|
layout->setContentsMargins(8, 8, 8, 8);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->addWidget(inner);
|
||||||
|
|
||||||
|
outer_layout->addWidget(frame);
|
||||||
|
return outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFrame* wrapInspectorPanel(QWidget* inner) {
|
||||||
|
auto* outer = new QFrame();
|
||||||
|
auto* outer_layout = new QVBoxLayout(outer);
|
||||||
|
outer_layout->setContentsMargins(6, 6, 6, 6);
|
||||||
|
outer_layout->setSpacing(0);
|
||||||
|
|
||||||
|
auto* frame = new QFrame(outer);
|
||||||
|
frame->setObjectName("panelFrame");
|
||||||
|
auto* layout = new QVBoxLayout(frame);
|
||||||
|
layout->setContentsMargins(0, 8, 0, 8);
|
||||||
|
layout->setSpacing(0);
|
||||||
|
layout->addWidget(inner);
|
||||||
|
|
||||||
|
outer_layout->addWidget(frame);
|
||||||
|
return outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ifcinterface::components::panel
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// This file was generated with the assistance of an AI coding tool.
|
||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef IFCINTERFACE_COMPONENTS_PANEL_PANELCHROME_H
|
||||||
|
#define IFCINTERFACE_COMPONENTS_PANEL_PANELCHROME_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class QDockWidget;
|
||||||
|
class QFrame;
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
|
namespace ifcinterface::components::panel {
|
||||||
|
|
||||||
|
QDockWidget* makeDock(const QString& title, QWidget* content, QWidget* parent, bool has_settings = false);
|
||||||
|
QFrame* wrapPanel(QWidget* inner);
|
||||||
|
QFrame* wrapInspectorPanel(QWidget* inner);
|
||||||
|
|
||||||
|
} // namespace ifcinterface::components::panel
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// This file was generated with the assistance of an AI coding tool.
|
||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "SvgIcon.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
|
||||||
|
namespace ifcinterface::components::icons {
|
||||||
|
|
||||||
|
QPixmap renderTintedSvgPixmap(const QString& icon_path, const QString& color, const QSize& size) {
|
||||||
|
QFile file(icon_path);
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
return QIcon(icon_path).pixmap(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString svg = QString::fromUtf8(file.readAll());
|
||||||
|
svg.replace("currentColor", color, Qt::CaseSensitive);
|
||||||
|
svg.replace(QRegularExpression(R"(stroke="[^"]*")"), QString("stroke=\"%1\"").arg(color));
|
||||||
|
svg.replace(QRegularExpression(R"(fill="none")"), "fill=\"none\"");
|
||||||
|
|
||||||
|
QSvgRenderer renderer(svg.toUtf8());
|
||||||
|
QPixmap pixmap(size);
|
||||||
|
pixmap.fill(Qt::transparent);
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
renderer.render(&painter);
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon makeTintedSvgIcon(const QString& icon_path, const QString& normal,
|
||||||
|
const QString& active, const QString& disabled) {
|
||||||
|
QFile file(icon_path);
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
return QIcon(icon_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon icon;
|
||||||
|
icon.addPixmap(renderTintedSvgPixmap(icon_path, normal, QSize(20, 20)), QIcon::Normal, QIcon::Off);
|
||||||
|
icon.addPixmap(renderTintedSvgPixmap(icon_path, active, QSize(20, 20)), QIcon::Active, QIcon::Off);
|
||||||
|
icon.addPixmap(renderTintedSvgPixmap(icon_path, active, QSize(20, 20)), QIcon::Selected, QIcon::Off);
|
||||||
|
icon.addPixmap(renderTintedSvgPixmap(icon_path, disabled, QSize(20, 20)), QIcon::Disabled, QIcon::Off);
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon makePanelSvgIcon(const QString& icon_path) {
|
||||||
|
return makeTintedSvgIcon(icon_path, "#e7ebf2", "#ffffff", "#6f7988");
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap makePanelSvgPixmap(const QString& icon_path, const QSize& size) {
|
||||||
|
return renderTintedSvgPixmap(icon_path, "#e7ebf2", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ifcinterface::components::icons
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// This file was generated with the assistance of an AI coding tool.
|
||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef IFCINTERFACE_COMPONENTS_ICONS_SVGICON_H
|
||||||
|
#define IFCINTERFACE_COMPONENTS_ICONS_SVGICON_H
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QString>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
|
namespace ifcinterface::components::icons {
|
||||||
|
|
||||||
|
QPixmap renderTintedSvgPixmap(const QString& icon_path, const QString& color, const QSize& size);
|
||||||
|
QIcon makeTintedSvgIcon(const QString& icon_path,
|
||||||
|
const QString& normal = "#39b54a",
|
||||||
|
const QString& active = "#53c763",
|
||||||
|
const QString& disabled = "#6f7988");
|
||||||
|
QIcon makePanelSvgIcon(const QString& icon_path);
|
||||||
|
QPixmap makePanelSvgPixmap(const QString& icon_path, const QSize& size);
|
||||||
|
|
||||||
|
} // namespace ifcinterface::components::icons
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
#include "MockMainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
@@ -71,7 +71,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
installUiFont();
|
installUiFont();
|
||||||
|
|
||||||
MockMainWindow window;
|
ifcinterface::shell::MainWindow window;
|
||||||
window.show();
|
window.show();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,63 +20,19 @@
|
|||||||
|
|
||||||
#include "PropertiesPanelWidget.h"
|
#include "PropertiesPanelWidget.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include "../../components/CollapsibleSection.h"
|
||||||
|
#include "../../components/SvgIcon.h"
|
||||||
|
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QSvgRenderer>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
QPixmap renderPanelSvgPixmap(const QString& icon_path, const QString& color, const QSize& size) {
|
|
||||||
QFile file(icon_path);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
return QIcon(icon_path).pixmap(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString svg = QString::fromUtf8(file.readAll());
|
|
||||||
svg.replace("currentColor", color, Qt::CaseSensitive);
|
|
||||||
svg.replace(QRegularExpression(R"(stroke="[^"]*")"), QString("stroke=\"%1\"").arg(color));
|
|
||||||
svg.replace(QRegularExpression(R"(fill="none")"), "fill=\"none\"");
|
|
||||||
|
|
||||||
QSvgRenderer renderer(svg.toUtf8());
|
|
||||||
QPixmap pixmap(size);
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
renderer.render(&painter);
|
|
||||||
return pixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon makePanelSvgIcon(const QString& icon_path) {
|
|
||||||
QIcon icon;
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#e7ebf2", QSize(20, 20)), QIcon::Normal, QIcon::Off);
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#ffffff", QSize(20, 20)), QIcon::Active, QIcon::Off);
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#ffffff", QSize(20, 20)), QIcon::Selected, QIcon::Off);
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#6f7988", QSize(20, 20)), QIcon::Disabled, QIcon::Off);
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap makePanelSvgPixmap(const QString& icon_path, const QSize& size) {
|
|
||||||
return renderPanelSvgPixmap(icon_path, "#e7ebf2", size);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* makeInspectorFilterField(const QString& placeholder, QWidget* parent = nullptr) {
|
|
||||||
auto* field = new QLineEdit(parent);
|
|
||||||
field->setPlaceholderText(placeholder);
|
|
||||||
field->setClearButtonEnabled(true);
|
|
||||||
field->addAction(makePanelSvgIcon(":/icons/filter.svg"), QLineEdit::LeadingPosition);
|
|
||||||
return field;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* makePropertySetPanel(const ifcinterface::panels::properties::PropertySet& property_set, QWidget* parent = nullptr) {
|
QWidget* makePropertySetPanel(const ifcinterface::panels::properties::PropertySet& property_set, QWidget* parent = nullptr) {
|
||||||
auto* group = new QGroupBox(property_set.title, parent);
|
auto* group = new QGroupBox(property_set.title, parent);
|
||||||
group->setObjectName("propertySetCard");
|
group->setObjectName("propertySetCard");
|
||||||
@@ -98,75 +54,6 @@ QWidget* makePropertySetPanel(const ifcinterface::panels::properties::PropertySe
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* makeInspectorSection(const QString& title,
|
|
||||||
const QString& filter_placeholder,
|
|
||||||
const QList<QWidget*>& groups,
|
|
||||||
QWidget* parent = nullptr) {
|
|
||||||
auto* section = new QWidget(parent);
|
|
||||||
section->setObjectName("inspectorSection");
|
|
||||||
auto* layout = new QVBoxLayout(section);
|
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
layout->setSpacing(6);
|
|
||||||
|
|
||||||
auto* header = new QFrame(section);
|
|
||||||
header->setObjectName("inspectorSectionHeader");
|
|
||||||
auto* header_layout = new QHBoxLayout(header);
|
|
||||||
header_layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
header_layout->setSpacing(6);
|
|
||||||
|
|
||||||
auto* toggle = new QToolButton(header);
|
|
||||||
toggle->setObjectName("inspectorSectionButton");
|
|
||||||
toggle->setText(title);
|
|
||||||
toggle->setCheckable(true);
|
|
||||||
toggle->setChecked(true);
|
|
||||||
toggle->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
|
||||||
toggle->setArrowType(Qt::DownArrow);
|
|
||||||
header_layout->addWidget(toggle);
|
|
||||||
header_layout->addStretch(1);
|
|
||||||
|
|
||||||
QLineEdit* filter_field = nullptr;
|
|
||||||
if (!filter_placeholder.isEmpty()) {
|
|
||||||
auto* filter_toggle = new QToolButton(header);
|
|
||||||
filter_toggle->setObjectName("inspectorFilterToggle");
|
|
||||||
filter_toggle->setCheckable(true);
|
|
||||||
filter_toggle->setIcon(makePanelSvgIcon(":/icons/filter.svg"));
|
|
||||||
filter_toggle->setAutoRaise(true);
|
|
||||||
header_layout->addWidget(filter_toggle);
|
|
||||||
|
|
||||||
filter_field = qobject_cast<QLineEdit*>(makeInspectorFilterField(filter_placeholder, section));
|
|
||||||
filter_field->setVisible(false);
|
|
||||||
QObject::connect(filter_toggle, &QToolButton::toggled, filter_field, [filter_field](bool visible) {
|
|
||||||
filter_field->setVisible(visible);
|
|
||||||
if (visible) filter_field->setFocus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* body = new QWidget(section);
|
|
||||||
body->setObjectName("inspectorSectionBody");
|
|
||||||
auto* body_layout = new QVBoxLayout(body);
|
|
||||||
body_layout->setContentsMargins(10, 6, 10, 0);
|
|
||||||
body_layout->setSpacing(6);
|
|
||||||
for (auto* group : groups) body_layout->addWidget(group);
|
|
||||||
|
|
||||||
QObject::connect(toggle, &QToolButton::toggled, body, [toggle, body](bool expanded) {
|
|
||||||
toggle->setArrowType(expanded ? Qt::DownArrow : Qt::RightArrow);
|
|
||||||
body->setVisible(expanded);
|
|
||||||
});
|
|
||||||
|
|
||||||
layout->addWidget(header);
|
|
||||||
if (filter_field) {
|
|
||||||
auto* filter_wrapper = new QWidget(section);
|
|
||||||
filter_wrapper->setObjectName("inspectorFilterWrapper");
|
|
||||||
auto* filter_wrapper_layout = new QVBoxLayout(filter_wrapper);
|
|
||||||
filter_wrapper_layout->setContentsMargins(10, 0, 10, 0);
|
|
||||||
filter_wrapper_layout->setSpacing(0);
|
|
||||||
filter_wrapper_layout->addWidget(filter_field);
|
|
||||||
layout->addWidget(filter_wrapper);
|
|
||||||
}
|
|
||||||
layout->addWidget(body);
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* makeAttributeList(const QList<ifcinterface::panels::properties::KeyValueRow>& rows, QWidget* parent = nullptr) {
|
QWidget* makeAttributeList(const QList<ifcinterface::panels::properties::KeyValueRow>& rows, QWidget* parent = nullptr) {
|
||||||
auto* panel = new QWidget(parent);
|
auto* panel = new QWidget(parent);
|
||||||
panel->setObjectName("attributeList");
|
panel->setObjectName("attributeList");
|
||||||
@@ -212,7 +99,7 @@ QWidget* makeRelationshipList(const QList<ifcinterface::panels::properties::Rela
|
|||||||
|
|
||||||
auto* icon = new QLabel(row);
|
auto* icon = new QLabel(row);
|
||||||
icon->setObjectName("relationshipIconLabel");
|
icon->setObjectName("relationshipIconLabel");
|
||||||
icon->setPixmap(makePanelSvgPixmap(":/icons/cursor-pointer.svg", QSize(14, 14)));
|
icon->setPixmap(ifcinterface::components::icons::makePanelSvgPixmap(":/icons/cursor-pointer.svg", QSize(14, 14)));
|
||||||
icon->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
icon->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
|
||||||
row_layout->addWidget(key);
|
row_layout->addWidget(key);
|
||||||
@@ -255,7 +142,7 @@ void PropertiesPanelWidget::setState(const PropertiesPanelState& state) {
|
|||||||
entity_layout->setContentsMargins(10, 8, 10, 8);
|
entity_layout->setContentsMargins(10, 8, 10, 8);
|
||||||
entity_layout->setSpacing(10);
|
entity_layout->setSpacing(10);
|
||||||
auto* entity_icon = new QLabel(entity_card);
|
auto* entity_icon = new QLabel(entity_card);
|
||||||
entity_icon->setPixmap(makePanelSvgPixmap(":/icons/cube-dots.svg", QSize(28, 28)));
|
entity_icon->setPixmap(components::icons::makePanelSvgPixmap(":/icons/cube-dots.svg", QSize(28, 28)));
|
||||||
entity_icon->setAlignment(Qt::AlignCenter);
|
entity_icon->setAlignment(Qt::AlignCenter);
|
||||||
auto* entity_text = new QWidget(entity_card);
|
auto* entity_text = new QWidget(entity_card);
|
||||||
auto* entity_text_layout = new QVBoxLayout(entity_text);
|
auto* entity_text_layout = new QVBoxLayout(entity_text);
|
||||||
@@ -287,14 +174,14 @@ void PropertiesPanelWidget::setState(const PropertiesPanelState& state) {
|
|||||||
quantity_set_widgets.append(makePropertySetPanel(property_set, content));
|
quantity_set_widgets.append(makePropertySetPanel(property_set, content));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* attributes_section = makeInspectorSection(
|
auto* attributes_section = new components::inspector::CollapsibleSection("Attributes", "", content);
|
||||||
"Attributes", "", {makeAttributeList(state.attributes, content)}, content);
|
attributes_section->addBodyWidget(makeAttributeList(state.attributes, content));
|
||||||
auto* relationships_section = makeInspectorSection(
|
auto* relationships_section = new components::inspector::CollapsibleSection("Relationships", "", content);
|
||||||
"Relationships", "", {makeRelationshipList(state.relationships, content)}, content);
|
relationships_section->addBodyWidget(makeRelationshipList(state.relationships, content));
|
||||||
auto* properties_section = makeInspectorSection(
|
auto* properties_section = new components::inspector::CollapsibleSection("Properties", "Filter properties or sets", content);
|
||||||
"Properties", "Filter properties or sets", property_set_widgets, content);
|
for (auto* widget : property_set_widgets) properties_section->addBodyWidget(widget);
|
||||||
auto* quantities_section = makeInspectorSection(
|
auto* quantities_section = new components::inspector::CollapsibleSection("Quantities", "Filter quantities or sets", content);
|
||||||
"Quantities", "Filter quantities or sets", quantity_set_widgets, content);
|
for (auto* widget : quantity_set_widgets) quantities_section->addBodyWidget(widget);
|
||||||
|
|
||||||
content_layout->addWidget(entity_wrapper);
|
content_layout->addWidget(entity_wrapper);
|
||||||
content_layout->addWidget(attributes_section);
|
content_layout->addWidget(attributes_section);
|
||||||
|
|||||||
@@ -20,48 +20,13 @@
|
|||||||
|
|
||||||
#include "SpatialHierarchyPanelWidget.h"
|
#include "SpatialHierarchyPanelWidget.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include "../../components/SvgIcon.h"
|
||||||
|
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QPainter>
|
|
||||||
#include <QPixmap>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QSvgRenderer>
|
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
QPixmap renderPanelSvgPixmap(const QString& icon_path, const QString& color, const QSize& size) {
|
|
||||||
QFile file(icon_path);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
return QIcon(icon_path).pixmap(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString svg = QString::fromUtf8(file.readAll());
|
|
||||||
svg.replace("currentColor", color, Qt::CaseSensitive);
|
|
||||||
svg.replace(QRegularExpression(R"(stroke="[^"]*")"), QString("stroke=\"%1\"").arg(color));
|
|
||||||
svg.replace(QRegularExpression(R"(fill="none")"), "fill=\"none\"");
|
|
||||||
|
|
||||||
QSvgRenderer renderer(svg.toUtf8());
|
|
||||||
QPixmap pixmap(size);
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
renderer.render(&painter);
|
|
||||||
return pixmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon makePanelSvgIcon(const QString& icon_path) {
|
|
||||||
QIcon icon;
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#e7ebf2", QSize(20, 20)), QIcon::Normal, QIcon::Off);
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#ffffff", QSize(20, 20)), QIcon::Active, QIcon::Off);
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#ffffff", QSize(20, 20)), QIcon::Selected, QIcon::Off);
|
|
||||||
icon.addPixmap(renderPanelSvgPixmap(icon_path, "#6f7988", QSize(20, 20)), QIcon::Disabled, QIcon::Off);
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace ifcinterface::panels::spatial_hierarchy {
|
namespace ifcinterface::panels::spatial_hierarchy {
|
||||||
|
|
||||||
SpatialHierarchyPanelWidget::SpatialHierarchyPanelWidget(QWidget* parent)
|
SpatialHierarchyPanelWidget::SpatialHierarchyPanelWidget(QWidget* parent)
|
||||||
@@ -102,8 +67,8 @@ void SpatialHierarchyPanelWidget::addNode(QTreeWidgetItem* parent, const TreeNod
|
|||||||
auto* item = new QTreeWidgetItem(parent, {node.name, ""});
|
auto* item = new QTreeWidgetItem(parent, {node.name, ""});
|
||||||
item->setData(1, Qt::UserRole, node.visible);
|
item->setData(1, Qt::UserRole, node.visible);
|
||||||
item->setSizeHint(0, QSize(0, 24));
|
item->setSizeHint(0, QSize(0, 24));
|
||||||
item->setIcon(0, makePanelSvgIcon(iconPath(node.kind)));
|
item->setIcon(0, components::icons::makePanelSvgIcon(iconPath(node.kind)));
|
||||||
item->setIcon(1, makePanelSvgIcon(node.visible ? ":/icons/eye.svg" : ":/icons/eye-closed.svg"));
|
item->setIcon(1, components::icons::makePanelSvgIcon(node.visible ? ":/icons/eye.svg" : ":/icons/eye-closed.svg"));
|
||||||
for (const auto& child : node.children) {
|
for (const auto& child : node.children) {
|
||||||
addNode(item, child);
|
addNode(item, child);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user