algorithm def
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include "Vtk/uLibVtkInterface.h"
|
||||
#include "Math/Units.h"
|
||||
#include "Math/Dense.h"
|
||||
#include "Settings.h"
|
||||
|
||||
namespace uLib {
|
||||
namespace Qt {
|
||||
@@ -15,8 +16,21 @@ PropertyWidgetBase::PropertyWidgetBase(PropertyBase* prop, QWidget* parent)
|
||||
: QWidget(parent), m_BaseProperty(prop) {
|
||||
m_Layout = new QHBoxLayout(this);
|
||||
m_Layout->setContentsMargins(4, 2, 4, 2);
|
||||
m_Label = new QLabel(QString::fromStdString(prop->GetName()), this);
|
||||
m_Label->setMinimumWidth(100);
|
||||
|
||||
std::string unit = prop->GetUnits();
|
||||
QString labelText = QString::fromStdString(prop->GetName());
|
||||
if (!unit.empty()) {
|
||||
auto dim = Settings::Instance().IdentifyDimension(unit);
|
||||
std::string pref = Settings::Instance().GetPreferredUnit(dim);
|
||||
if (!pref.empty()) {
|
||||
labelText += " [" + QString::fromStdString(pref) + "]";
|
||||
} else {
|
||||
labelText += " [" + QString::fromStdString(unit) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
m_Label = new QLabel(labelText, this);
|
||||
m_Label->setMinimumWidth(120);
|
||||
m_Layout->addWidget(m_Label);
|
||||
}
|
||||
PropertyWidgetBase::~PropertyWidgetBase() {
|
||||
@@ -115,9 +129,6 @@ void UnitLineEdit::updateText() {
|
||||
s += ".0";
|
||||
}
|
||||
}
|
||||
if (!m_Suffix.isEmpty()) {
|
||||
s += " " + m_Suffix;
|
||||
}
|
||||
setText(s);
|
||||
}
|
||||
|
||||
@@ -129,11 +140,12 @@ void UnitLineEdit::setIntegerOnly(bool integerOnly) {
|
||||
DoublePropertyWidget::DoublePropertyWidget(Property<double>* prop, QWidget* parent)
|
||||
: PropertyWidgetBase(prop, parent), m_Prop(prop) {
|
||||
m_Edit = new UnitLineEdit(this);
|
||||
QString units = QString::fromStdString(prop->GetUnits());
|
||||
if (!units.isEmpty()) {
|
||||
double factor = 1.0;
|
||||
parseWithUnits("1 " + units, &factor);
|
||||
m_Edit->setUnits(units, factor);
|
||||
std::string unit = prop->GetUnits();
|
||||
if (!unit.empty()) {
|
||||
auto dim = Settings::Instance().IdentifyDimension(unit);
|
||||
std::string pref = Settings::Instance().GetPreferredUnit(dim);
|
||||
double factor = Settings::Instance().GetUnitFactor(pref);
|
||||
m_Edit->setUnits(QString::fromStdString(pref), factor);
|
||||
}
|
||||
m_Edit->setValue(prop->Get());
|
||||
m_Layout->addWidget(m_Edit, 1);
|
||||
@@ -146,11 +158,12 @@ DoublePropertyWidget::DoublePropertyWidget(Property<double>* prop, QWidget* pare
|
||||
FloatPropertyWidget::FloatPropertyWidget(Property<float>* prop, QWidget* parent)
|
||||
: PropertyWidgetBase(prop, parent), m_Prop(prop) {
|
||||
m_Edit = new UnitLineEdit(this);
|
||||
QString units = QString::fromStdString(prop->GetUnits());
|
||||
if (!units.isEmpty()) {
|
||||
double factor = 1.0;
|
||||
parseWithUnits("1 " + units, &factor);
|
||||
m_Edit->setUnits(units, factor);
|
||||
std::string unit = prop->GetUnits();
|
||||
if (!unit.empty()) {
|
||||
auto dim = Settings::Instance().IdentifyDimension(unit);
|
||||
std::string pref = Settings::Instance().GetPreferredUnit(dim);
|
||||
double factor = Settings::Instance().GetUnitFactor(pref);
|
||||
m_Edit->setUnits(QString::fromStdString(pref), factor);
|
||||
}
|
||||
m_Edit->setValue(prop->Get());
|
||||
m_Layout->addWidget(m_Edit, 1);
|
||||
@@ -164,11 +177,12 @@ IntPropertyWidget::IntPropertyWidget(Property<int>* prop, QWidget* parent)
|
||||
: PropertyWidgetBase(prop, parent), m_Prop(prop) {
|
||||
m_Edit = new UnitLineEdit(this);
|
||||
m_Edit->setIntegerOnly(true);
|
||||
QString units = QString::fromStdString(prop->GetUnits());
|
||||
if (!units.isEmpty()) {
|
||||
double factor = 1.0;
|
||||
parseWithUnits("1 " + units, &factor);
|
||||
m_Edit->setUnits(units, factor);
|
||||
std::string unit = prop->GetUnits();
|
||||
if (!unit.empty()) {
|
||||
auto dim = Settings::Instance().IdentifyDimension(unit);
|
||||
std::string pref = Settings::Instance().GetPreferredUnit(dim);
|
||||
double factor = Settings::Instance().GetUnitFactor(pref);
|
||||
m_Edit->setUnits(QString::fromStdString(pref), factor);
|
||||
}
|
||||
m_Edit->setValue(prop->Get());
|
||||
m_Layout->addWidget(m_Edit, 1);
|
||||
@@ -211,6 +225,26 @@ StringPropertyWidget::StringPropertyWidget(Property<std::string>* prop, QWidget*
|
||||
}
|
||||
StringPropertyWidget::~StringPropertyWidget() {}
|
||||
|
||||
class GroupHeaderWidget : public QWidget {
|
||||
public:
|
||||
GroupHeaderWidget(const QString& name, QWidget* parent = nullptr) : QWidget(parent) {
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 8, 0, 4);
|
||||
auto* line = new QFrame(this);
|
||||
line->setFrameShape(QFrame::HLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
line->setStyleSheet("color: #555;");
|
||||
layout->addWidget(line);
|
||||
auto* label = new QLabel(name, this);
|
||||
QFont font = label->font();
|
||||
font.setBold(true);
|
||||
font.setPointSize(font.pointSize() + 1);
|
||||
label->setFont(font);
|
||||
label->setStyleSheet("color: #aaa; text-transform: uppercase;");
|
||||
layout->addWidget(label);
|
||||
}
|
||||
};
|
||||
|
||||
class EnumPropertyWidget : public PropertyWidgetBase {
|
||||
PropertyBase* m_Prop;
|
||||
QComboBox* m_Combo;
|
||||
@@ -305,26 +339,51 @@ void PropertyEditor::setObject(::uLib::Object* obj, bool displayOnly) {
|
||||
}
|
||||
}
|
||||
|
||||
// Group properties by their group string
|
||||
std::map<std::string, std::vector<::uLib::PropertyBase*>> groupedProps;
|
||||
std::vector<std::string> groupOrder;
|
||||
|
||||
for (auto* prop : *props) {
|
||||
// Priority 1: Check if it provides enum labels
|
||||
if (!prop->GetEnumLabels().empty()) {
|
||||
m_ContainerLayout->addWidget(new EnumPropertyWidget(prop, m_Container));
|
||||
continue;
|
||||
std::string group = prop->GetGroup();
|
||||
if (groupedProps.find(group) == groupedProps.end()) {
|
||||
groupOrder.push_back(group);
|
||||
}
|
||||
groupedProps[group].push_back(prop);
|
||||
}
|
||||
|
||||
for (const auto& groupName : groupOrder) {
|
||||
if (!groupName.empty()) {
|
||||
m_ContainerLayout->addWidget(new GroupHeaderWidget(QString::fromStdString(groupName), m_Container));
|
||||
}
|
||||
|
||||
// Priority 2: Standard factory lookup
|
||||
auto it = m_Factories.find(prop->GetTypeIndex());
|
||||
if (it != m_Factories.end()) {
|
||||
QWidget* widget = it->second(prop, m_Container);
|
||||
m_ContainerLayout->addWidget(widget);
|
||||
} else {
|
||||
// Debug info for unknown types
|
||||
std::cout << "PropertyEditor: No factory for " << prop->GetName()
|
||||
<< " (Type: " << prop->GetTypeName() << ")" << std::endl;
|
||||
for (auto* prop : groupedProps[groupName]) {
|
||||
QWidget* widget = nullptr;
|
||||
|
||||
// Priority 1: Check if it provides enum labels
|
||||
if (!prop->GetEnumLabels().empty()) {
|
||||
widget = new EnumPropertyWidget(prop, m_Container);
|
||||
} else {
|
||||
// Priority 2: Standard factory lookup
|
||||
auto it = m_Factories.find(prop->GetTypeIndex());
|
||||
if (it != m_Factories.end()) {
|
||||
widget = it->second(prop, m_Container);
|
||||
} else {
|
||||
// Debug info for unknown types
|
||||
std::cout << "PropertyEditor: No factory for " << prop->GetQualifiedName()
|
||||
<< " (Type: " << prop->GetTypeName() << ")" << std::endl;
|
||||
|
||||
QWidget* fallback = new PropertyWidgetBase(prop, m_Container);
|
||||
fallback->layout()->addWidget(new QLabel("(Read-only: " + QString::fromStdString(prop->GetValueAsString()) + ")"));
|
||||
m_ContainerLayout->addWidget(fallback);
|
||||
widget = new PropertyWidgetBase(prop, m_Container);
|
||||
widget->layout()->addWidget(new QLabel("(Read-only: " + QString::fromStdString(prop->GetValueAsString()) + ")"));
|
||||
}
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
if (!groupName.empty()) {
|
||||
// Indent grouped properties
|
||||
widget->setContentsMargins(16, 0, 0, 0);
|
||||
}
|
||||
m_ContainerLayout->addWidget(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_ContainerLayout->addStretch(1);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "Core/Object.h"
|
||||
#include "Core/Signal.h"
|
||||
#include "Math/Dense.h"
|
||||
#include "Settings.h"
|
||||
|
||||
namespace uLib {
|
||||
namespace Qt {
|
||||
@@ -93,18 +94,24 @@ class VectorPropertyWidget : public PropertyWidgetBase {
|
||||
public:
|
||||
VectorPropertyWidget(Property<VecT>* prop, QWidget* parent = nullptr)
|
||||
: PropertyWidgetBase(prop, parent), m_Prop(prop) {
|
||||
QString units = QString::fromStdString(prop->GetUnits());
|
||||
|
||||
std::string unit = prop->GetUnits();
|
||||
double factor = 1.0;
|
||||
if (!units.isEmpty()) {
|
||||
parseWithUnits("1 " + units, &factor);
|
||||
QString prefSuffix;
|
||||
if (!unit.empty()) {
|
||||
auto dim = Settings::Instance().IdentifyDimension(unit);
|
||||
std::string pref = Settings::Instance().GetPreferredUnit(dim);
|
||||
factor = Settings::Instance().GetUnitFactor(pref);
|
||||
prefSuffix = QString::fromStdString(pref);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Size; ++i) {
|
||||
m_Edits[i] = new UnitLineEdit(this);
|
||||
if (std::is_integral<typename VecT::Scalar>::value) {
|
||||
m_Edits[i]->setIntegerOnly(true);
|
||||
}
|
||||
if (!units.isEmpty()) {
|
||||
m_Edits[i]->setUnits(units, factor);
|
||||
if (!prefSuffix.isEmpty()) {
|
||||
m_Edits[i]->setUnits(prefSuffix, factor);
|
||||
}
|
||||
m_Layout->addWidget(m_Edits[i], 1);
|
||||
|
||||
|
||||
75
app/gcompose/src/Settings.h
Normal file
75
app/gcompose/src/Settings.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef GCOMPOSE_SETTINGS_H
|
||||
#define GCOMPOSE_SETTINGS_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "Math/Units.h"
|
||||
|
||||
namespace uLib {
|
||||
namespace Qt {
|
||||
|
||||
class Settings {
|
||||
public:
|
||||
static Settings& Instance() {
|
||||
static Settings instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
enum Dimension {
|
||||
Length,
|
||||
Angle,
|
||||
Energy,
|
||||
Time,
|
||||
Dimensionless
|
||||
};
|
||||
|
||||
void SetPreferredUnit(Dimension dim, const std::string& unit) {
|
||||
m_PreferredUnits[dim] = unit;
|
||||
}
|
||||
|
||||
std::string GetPreferredUnit(Dimension dim) const {
|
||||
auto it = m_PreferredUnits.find(dim);
|
||||
if (it != m_PreferredUnits.end()) return it->second;
|
||||
|
||||
switch(dim) {
|
||||
case Length: return "mm";
|
||||
case Angle: return "deg";
|
||||
case Energy: return "MeV";
|
||||
case Time: return "ns";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
double GetUnitFactor(const std::string& unit) const {
|
||||
if (unit == "m") return CLHEP::meter;
|
||||
if (unit == "cm") return CLHEP::centimeter;
|
||||
if (unit == "mm") return CLHEP::millimeter;
|
||||
if (unit == "um") return CLHEP::micrometer;
|
||||
if (unit == "deg") return CLHEP::degree;
|
||||
if (unit == "rad") return CLHEP::radian;
|
||||
if (unit == "ns") return CLHEP::nanosecond;
|
||||
if (unit == "s") return CLHEP::second;
|
||||
if (unit == "ms") return CLHEP::millisecond;
|
||||
if (unit == "MeV") return CLHEP::megaelectronvolt;
|
||||
if (unit == "GeV") return CLHEP::gigaelectronvolt;
|
||||
if (unit == "eV") return CLHEP::electronvolt;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
Dimension IdentifyDimension(const std::string& unit) const {
|
||||
if (unit == "m" || unit == "cm" || unit == "mm" || unit == "um" || unit == "nm") return Length;
|
||||
if (unit == "deg" || unit == "rad") return Angle;
|
||||
if (unit == "MeV" || unit == "GeV" || unit == "eV" || unit == "keV" || unit == "TeV") return Energy;
|
||||
if (unit == "ns" || unit == "s" || unit == "ms" || unit == "us") return Time;
|
||||
return Dimensionless;
|
||||
}
|
||||
|
||||
private:
|
||||
Settings() {}
|
||||
std::map<Dimension, std::string> m_PreferredUnits;
|
||||
};
|
||||
|
||||
} // namespace Qt
|
||||
} // namespace uLib
|
||||
|
||||
#endif
|
||||
@@ -46,23 +46,25 @@ ViewportPane::ViewportPane(QWidget* parent) : QWidget(parent), m_viewport(nullpt
|
||||
|
||||
m_layout->addWidget(m_titleBar);
|
||||
|
||||
// Main horizontal container for viewport and display panel
|
||||
QWidget* mainArea = new QWidget(this);
|
||||
QHBoxLayout* hLayout = new QHBoxLayout(mainArea);
|
||||
hLayout->setContentsMargins(0, 0, 0, 0);
|
||||
hLayout->setSpacing(0);
|
||||
m_layout->addWidget(mainArea);
|
||||
// Main area with splitter for viewport and display panel
|
||||
m_areaSplitter = new QSplitter(Qt::Horizontal, this);
|
||||
m_areaSplitter->setObjectName("ViewportAreaSplitter");
|
||||
m_layout->addWidget(m_areaSplitter, 1);
|
||||
|
||||
// Viewport will be added here via setViewport
|
||||
m_viewport = new uLib::Vtk::QViewport(mainArea);
|
||||
hLayout->addWidget(m_viewport);
|
||||
m_viewport = new uLib::Vtk::QViewport(m_areaSplitter);
|
||||
m_areaSplitter->addWidget(m_viewport);
|
||||
|
||||
// Display Panel (Overlay/Slide-out)
|
||||
m_displayPanel = new QFrame(mainArea);
|
||||
m_displayPanel = new QFrame(m_areaSplitter);
|
||||
m_displayPanel->setObjectName("DisplayPropertiesPanel");
|
||||
m_displayPanel->setFixedWidth(250);
|
||||
m_displayPanel->setMinimumWidth(150);
|
||||
m_displayPanel->hide();
|
||||
|
||||
m_areaSplitter->addWidget(m_displayPanel);
|
||||
m_areaSplitter->setStretchFactor(0, 1);
|
||||
m_areaSplitter->setStretchFactor(1, 0);
|
||||
|
||||
QVBoxLayout* panelLayout = new QVBoxLayout(m_displayPanel);
|
||||
panelLayout->setContentsMargins(5, 5, 5, 5);
|
||||
|
||||
@@ -72,8 +74,6 @@ ViewportPane::ViewportPane(QWidget* parent) : QWidget(parent), m_viewport(nullpt
|
||||
|
||||
m_displayEditor = new uLib::Qt::PropertyEditor(m_displayPanel);
|
||||
panelLayout->addWidget(m_displayEditor);
|
||||
|
||||
hLayout->addWidget(m_displayPanel);
|
||||
|
||||
connect(m_toggleBtn, &QPushButton::toggled, this, &ViewportPane::toggleDisplayPanel);
|
||||
connect(m_titleBar, &QWidget::customContextMenuRequested, this, &ViewportPane::showContextMenu);
|
||||
@@ -85,7 +85,15 @@ ViewportPane::ViewportPane(QWidget* parent) : QWidget(parent), m_viewport(nullpt
|
||||
ViewportPane::~ViewportPane() {}
|
||||
|
||||
void ViewportPane::toggleDisplayPanel() {
|
||||
m_displayPanel->setVisible(m_toggleBtn->isChecked());
|
||||
bool visible = m_toggleBtn->isChecked();
|
||||
m_displayPanel->setVisible(visible);
|
||||
if (visible && m_areaSplitter->sizes().value(1, 0) == 0) {
|
||||
QList<int> sizes = m_areaSplitter->sizes();
|
||||
int total = sizes[0] + sizes[1];
|
||||
sizes[1] = 250;
|
||||
sizes[0] = total - 250;
|
||||
m_areaSplitter->setSizes(sizes);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportPane::setObject(uLib::Object* obj) {
|
||||
@@ -107,15 +115,14 @@ void ViewportPane::setObject(uLib::Object* obj) {
|
||||
|
||||
void ViewportPane::setViewport(QWidget* viewport, const QString& title) {
|
||||
if (m_viewport) {
|
||||
m_viewport->parentWidget()->layout()->removeWidget(m_viewport);
|
||||
delete m_viewport;
|
||||
}
|
||||
m_viewport = viewport;
|
||||
m_titleLabel->setText(title);
|
||||
|
||||
m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
auto* mainAreaLayout = static_cast<QHBoxLayout*>(m_displayPanel->parentWidget()->layout());
|
||||
mainAreaLayout->insertWidget(0, m_viewport);
|
||||
m_areaSplitter->insertWidget(0, m_viewport);
|
||||
m_areaSplitter->setStretchFactor(0, 1);
|
||||
}
|
||||
|
||||
void ViewportPane::addVtkViewport() {
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace uLib {
|
||||
namespace Qt { class PropertyEditor; }
|
||||
}
|
||||
|
||||
class QSplitter;
|
||||
class QVBoxLayout;
|
||||
class QLabel;
|
||||
|
||||
@@ -39,6 +40,7 @@ private:
|
||||
QVBoxLayout* m_layout;
|
||||
QWidget* m_titleBar;
|
||||
QLabel* m_titleLabel;
|
||||
QSplitter* m_areaSplitter;
|
||||
QWidget* m_viewport;
|
||||
|
||||
// Display Properties Overlay
|
||||
|
||||
Reference in New Issue
Block a user