#include "MainPanel.h" #include "ViewportPane.h" #include "ContextPanel.h" #include "PropertiesPanel.h" #include "Core/ObjectFactory.h" #include "Core/ObjectsContext.h" #include "Vtk/vtkObjectsContext.h" #include "Vtk/vtkQViewport.h" #include #include #include #include #include #include #include #include #include #include #include "StyleManager.h" #include "Math/VoxImage.h" MainPanel::MainPanel(QWidget* parent) : QWidget(parent), m_context(nullptr), m_mainVtkContext(nullptr) { this->setObjectName("MainPanel"); this->setAttribute(Qt::WA_StyledBackground); auto* mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); // 1. Top Menu Panel auto* menuPanel = new QWidget(this); menuPanel->setObjectName("MenuPanel"); menuPanel->setFixedHeight(36); auto* menuLayout = new QHBoxLayout(menuPanel); menuLayout->setContentsMargins(10, 0, 10, 0); menuLayout->setSpacing(15); auto* logo = new QLabel("G-COMPOSE", menuPanel); logo->setObjectName("LogoLabel"); // File Menu Button auto* btnFile = new QPushButton("File", menuPanel); btnFile->setObjectName("MenuButton"); auto* fileMenu = new QMenu(btnFile); fileMenu->addAction("Open", this, &MainPanel::onOpen); fileMenu->addAction("Save", this, &MainPanel::onSave); fileMenu->addAction("Save As", this, &MainPanel::onSaveAs); fileMenu->addAction("Exit", this, &MainPanel::onExit); btnFile->setMenu(fileMenu); // Theme Menu Button auto* btnTheme = new QPushButton("Theme", menuPanel); btnTheme->setObjectName("MenuButton"); auto* themeMenu = new QMenu(btnTheme); themeMenu->addAction("Dark", this, &MainPanel::onDarkTheme); themeMenu->addAction("Bright", this, &MainPanel::onBrightTheme); btnTheme->setMenu(themeMenu); // New Menu Button auto* btnNew = new QPushButton("Add", menuPanel); btnNew->setObjectName("MenuButton"); auto* newMenu = new QMenu(btnNew); auto classes = uLib::ObjectFactory::Instance().GetRegisteredClasses(); for (const auto& className : classes) { auto* action = newMenu->addAction(QString::fromStdString(className)); connect(action, &QAction::triggered, [this, className]() { this->onCreateObject(className); }); } btnNew->setMenu(newMenu); menuLayout->addWidget(logo); menuLayout->addWidget(btnFile); menuLayout->addWidget(btnNew); menuLayout->addWidget(btnTheme); menuLayout->addStretch(); mainLayout->addWidget(menuPanel); // 2. Central Splitter Area m_rootSplitter = new QSplitter(Qt::Horizontal, this); m_contextPanel = new ContextPanel(m_rootSplitter); m_rootSplitter->addWidget(m_contextPanel); m_rootSplitter->setStretchFactor(0, 0); m_firstPane = new ViewportPane(m_rootSplitter); m_rootSplitter->addWidget(m_firstPane); m_rootSplitter->setStretchFactor(1, 1); connect(m_contextPanel, &ContextPanel::objectSelected, [this](uLib::Object* obj) { if (auto* viewport = qobject_cast(m_firstPane->currentViewport())) { uLib::Vtk::Prop3D* prop3d = nullptr; if (m_mainVtkContext) { prop3d = m_mainVtkContext->GetProp3D(obj); } viewport->SelectProp3D(prop3d); // Update the display properties in the viewport pane itself - use the prop3d proxy if possible m_firstPane->setObject(prop3d ? (uLib::Object*)prop3d : obj); } else { m_firstPane->setObject(obj); } }); // Set initial sizes: Context(250), Viewport(600), Properties(250) QList sizes; sizes << 250 << 600 << 250; m_rootSplitter->setSizes(sizes); mainLayout->addWidget(m_rootSplitter, 1); } void MainPanel::setContext(uLib::ObjectsContext* context) { m_context = context; m_contextPanel->setContext(context); if (m_mainVtkContext) { if (auto* viewport = qobject_cast(m_firstPane->currentViewport())) { viewport->RemoveProp3D(*m_mainVtkContext); } delete m_mainVtkContext; m_mainVtkContext = nullptr; } if (context) { if (auto* viewport = qobject_cast(m_firstPane->currentViewport())) { m_mainVtkContext = new uLib::Vtk::ObjectsContext(context); // viewport->AddProp3D(*m_mainVtkContext); // redundant auto syncSelection = [this](uLib::Vtk::Prop3D* p) { if (!p) { m_contextPanel->clearSelection(); m_firstPane->setObject(nullptr); } else { m_contextPanel->selectObject(p->GetContent()); m_firstPane->setObject(p); } }; connect(viewport, &uLib::Vtk::QViewport::prop3dSelected, syncSelection); uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::ObjectsContext::Prop3DAdded, [this](uLib::Vtk::Prop3D* p) { if (p) { auto panes = this->findChildren(); for (auto* pane : panes) { if (auto* vp = qobject_cast(pane->currentViewport())) { vp->AddProp3D(*p); vp->ZoomAuto(); vp->Render(); } } } }); uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::ObjectsContext::Prop3DRemoved, [this](uLib::Vtk::Prop3D* p) { if (p) { auto panes = this->findChildren(); for (auto* pane : panes) { if (auto* vp = qobject_cast(pane->currentViewport())) { vp->RemoveProp3D(*p); vp->Render(); } } } }); // Add any prop3ds that were created during m_mainVtkContext's construction to all panes auto panes = this->findChildren(); for (auto* obj : context->GetObjects()) { if (auto* p = m_mainVtkContext->GetProp3D(obj)) { for (auto* pane : panes) { if (auto* vp = qobject_cast(pane->currentViewport())) { vp->AddProp3D(*p); } } } } uLib::Object::connect(context, &uLib::Object::Updated, [viewport]() { viewport->Render(); }); viewport->ZoomAuto(); viewport->Render(); } } } void MainPanel::onCreateObject(const std::string& className) { if (!m_context) return; auto* obj = uLib::ObjectFactory::Instance().Create(className); if (obj) { m_context->AddObject(obj); } } void MainPanel::onOpen() { QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "VTK/VTI Images (*.vtk *.vti);;All Files (*.*)"); if (fileName.isEmpty()) return; QFileInfo info(fileName); QString ext = info.suffix().toLower(); if (ext == "vti" || ext == "vtk") { auto* obj = uLib::ObjectFactory::Instance().Create("VoxImage"); auto* vox = dynamic_cast(obj); if (vox) { bool success = false; if (ext == "vti") { success = vox->ImportFromVti(fileName.toStdString().c_str()); } else { success = vox->ImportFromVtk(fileName.toStdString().c_str()); } if (success) { obj->SetInstanceName(info.fileName().toStdString()); m_context->AddObject(obj); } else { delete obj; } } else { delete obj; } } } void MainPanel::onSave() { // Placeholder for save logic } void MainPanel::onSaveAs() { // Placeholder for save as logic } void MainPanel::onExit() { qApp->quit(); } void MainPanel::onDarkTheme() { StyleManager::applyStyle(qApp, "dark"); } void MainPanel::onBrightTheme() { StyleManager::applyStyle(qApp, "bright"); } MainPanel::~MainPanel() {}