255 lines
6.6 KiB
C++
255 lines
6.6 KiB
C++
#include "pivaluetree_edit.h"
|
|
#include "ui_pivaluetree_edit_array.h"
|
|
#include "pivariant_edit.h"
|
|
#include "piqt.h"
|
|
#include <QEvent>
|
|
#include <QFormLayout>
|
|
#include <QGroupBox>
|
|
|
|
|
|
PIValueTreeEdit::PIValueTreeEdit(QWidget * parent): QWidget(parent) {
|
|
ui = new Ui::PIValueTreeEditArray();
|
|
grid = new GridWidgets();
|
|
auto * lay = new QBoxLayout(QBoxLayout::TopToBottom);
|
|
lay->setContentsMargins(0, 0, 0, 0);
|
|
setLayout(lay);
|
|
}
|
|
|
|
|
|
PIValueTreeEdit::~PIValueTreeEdit() {
|
|
delete ui;
|
|
delete grid;
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::setValue(const PIValueTree & v) {
|
|
source = v;
|
|
build();
|
|
}
|
|
|
|
|
|
PIValueTree PIValueTreeEdit::value() const {
|
|
applyValues();
|
|
return source;
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::setGroupingEnabled(bool yes) {
|
|
is_grouping = yes;
|
|
build();
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::rollback() {
|
|
build();
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::clear() {
|
|
source = PIValueTree();
|
|
removeAll();
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::removeAll() {
|
|
array_edits.clear();
|
|
value_edits.clear();
|
|
tree_edits.clear();
|
|
if (ui_array) {
|
|
ui->layoutArray->takeAt(0);
|
|
delete ui_array;
|
|
ui_array = nullptr;
|
|
}
|
|
QLayoutItem * child = nullptr;
|
|
while ((child = layout()->takeAt(0)) != nullptr) {
|
|
delete child;
|
|
}
|
|
grid->clear();
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::build() {
|
|
removeAll();
|
|
//piCout << source.attributes().value(PIValueTree::attributeArrayType) << array_type;
|
|
if (source.isArray()) {
|
|
ui_array = new QWidget();
|
|
ui->setupUi(ui_array);
|
|
ui->spinCount->setRange(source.attribute(PIValueTree::attributeArrayMinCount, 0).toInt(),
|
|
source.attribute(PIValueTree::attributeArrayMaxCount, 65536).toInt());
|
|
ui->spinCount->setValue(source.children().size_s());
|
|
ui->widgetEdit->setVisible(source.attribute(PIValueTree::attributeArrayResize, false).toBool());
|
|
ui->layoutArray->addWidget(grid);
|
|
uint array_type = PIVariant::typeIDFromName(source.attribute(PIValueTree::attributeArrayType).toString());
|
|
int index = 0;
|
|
for (const auto & i: source.children()) {
|
|
auto * ve = new PIVariantEdit();
|
|
ve->setAttributes(source.attributes());
|
|
ve->setValue(i.value(), array_type);
|
|
grid->add(QString::number(++index), ve, PI2QString(i.comment()));
|
|
array_edits << ve;
|
|
}
|
|
connect(ui->spinCount, QOverload<int>::of(&QSpinBox::valueChanged), this, [this,array_type](int value){
|
|
value = piMaxi(value, 0);
|
|
for (int i = grid->rowCount() - 1; i >= value; --i)
|
|
grid->removeRow(i);
|
|
array_edits.resize(grid->rowCount());
|
|
for (int i = grid->rowCount(); i < value; ++i) {
|
|
auto * ve = new PIVariantEdit();
|
|
ve->setAttributes(source.attributes());
|
|
ve->setValue(PIVariant::fromType(array_type), array_type);
|
|
grid->add(QString::number(i + 1), ve, "");
|
|
array_edits << ve;
|
|
}
|
|
});
|
|
layout()->addWidget(ui_array);
|
|
} else {
|
|
layout()->addWidget(grid);
|
|
for (const auto & i: source.children()) {
|
|
if (i.attribute(PIValueTree::attributeHidden, false).toBool()) continue;
|
|
if (i.attribute(PIValueTree::attributeIsLabel, false).toBool()) {
|
|
if (i.name().isEmpty()) continue;
|
|
auto * l = new QLabel(PI2QString(i.name()));
|
|
l->setAlignment(Qt::AlignCenter);
|
|
grid->add(l);
|
|
continue;
|
|
}
|
|
if (i.hasChildren() || i.isArray()) {
|
|
auto * ve = new PIValueTreeEdit();
|
|
ve->setGroupingEnabled(is_grouping);
|
|
ve->setValue(i);
|
|
if (is_grouping) {
|
|
auto * gb = new QGroupBox();
|
|
gb->setLayout(new QBoxLayout(QBoxLayout::TopToBottom));
|
|
gb->layout()->addWidget(ve);
|
|
gb->setTitle(PI2QString(i.name()));
|
|
gb->setToolTip(PI2QString(i.comment()));
|
|
gb->setCheckable(true);
|
|
gb->setChecked(true);
|
|
gb->setAlignment(Qt::AlignCenter);
|
|
connect(gb, &QGroupBox::toggled, ve, &QWidget::setVisible);
|
|
grid->add(gb);
|
|
} else {
|
|
grid->add(PI2QString(i.name()), ve, PI2QString(i.comment()));
|
|
}
|
|
tree_edits[i.name()] = ve;
|
|
} else {
|
|
auto * ve = new PIVariantEdit();
|
|
ve->setAttributes(i.attributes());
|
|
ve->setValue(i.value());
|
|
grid->add(PI2QString(i.name()), ve, PI2QString(i.comment()));
|
|
value_edits[i.name()] = ve;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::applyValues() const {
|
|
if (source.isArray()) {
|
|
if (array_edits.isNotEmpty())
|
|
source.mergeAttributes(array_edits[0]->defaultAttributes());
|
|
source.clearChildren();
|
|
for (int i = 0; i < array_edits.size_s(); ++i)
|
|
source.addChild({PIString::fromNumber(i), array_edits[i]->value()});
|
|
} else {
|
|
auto vit = value_edits.makeIterator();
|
|
while (vit.next()) {
|
|
auto & c(source.child(vit.key()));
|
|
c.mergeAttributes(vit.value()->defaultAttributes());
|
|
c.setValue(vit.value()->value());
|
|
}
|
|
auto tit = tree_edits.makeIterator();
|
|
while (tit.next()) {
|
|
auto & c(source.child(tit.key()));
|
|
if (!c.isNull()) c = tit.value()->value();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void PIValueTreeEdit::GridWidgets::add(QString label, QWidget * w, const QString & comment) {
|
|
if (!label.isEmpty())
|
|
label += ':';
|
|
auto * l = new QLabel(label);
|
|
auto * c = new QLabel(comment);
|
|
l->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
c->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
w->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
|
lay->addWidget(l, row_count, 0, Qt::AlignVCenter | Qt::AlignRight);
|
|
lay->addWidget(w, row_count, 1);
|
|
lay->addWidget(c, row_count, 2, Qt::AlignVCenter | Qt::AlignLeft);
|
|
widgets << l << w << c;
|
|
++row_count;
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::GridWidgets::add(QWidget * w) {
|
|
lay->addWidget(w, row_count, 0, 1, -1);
|
|
widgets << w;
|
|
++row_count;
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::GridWidgets::clear() {
|
|
piDeleteAllAndClear(widgets);
|
|
if (lay)
|
|
delete lay;
|
|
lay = new QGridLayout();
|
|
lay->setContentsMargins(0, 0, 0, 0);
|
|
setLayout(lay);
|
|
row_count = 0;
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::GridWidgets::removeRow(int index) {
|
|
if (!lay) return;
|
|
if (row_count <= index) return;
|
|
for (int c = 0; c < lay->columnCount(); ++c) {
|
|
auto * li = lay->itemAtPosition(index, c);
|
|
if (li) {
|
|
if (li->widget()) {
|
|
widgets.removeOne(li->widget());
|
|
delete li->widget();
|
|
}
|
|
delete li;
|
|
}
|
|
}
|
|
--row_count;
|
|
simplify();
|
|
}
|
|
|
|
|
|
void PIValueTreeEdit::GridWidgets::simplify() {
|
|
if (!lay) return;
|
|
QVector<QMap<int, QWidget*>> wg;
|
|
QMap<QWidget*, Qt::Alignment> wa;
|
|
for (int r = 0; r < lay->rowCount(); ++r) {
|
|
QMap<int, QWidget*> row;
|
|
for (int c = 0; c < lay->columnCount(); ++c) {
|
|
auto * li = lay->itemAtPosition(r, c);
|
|
if (!li) continue;
|
|
if (li->widget()) {
|
|
row[c] = li->widget();
|
|
wa[li->widget()] = li->alignment();
|
|
}
|
|
}
|
|
if (!row.isEmpty())
|
|
wg << row;
|
|
}
|
|
delete lay;
|
|
lay = new QGridLayout();
|
|
lay->setContentsMargins(0, 0, 0, 0);
|
|
int rindex = 0;
|
|
for (const auto & row: wg) {
|
|
QMapIterator<int, QWidget*> it(row);
|
|
while (it.hasNext()) {
|
|
it.next();
|
|
lay->addWidget(it.value(), rindex, it.key(), wa.value(it.value()));
|
|
}
|
|
++rindex;
|
|
}
|
|
setLayout(lay);
|
|
}
|