PIValueTreeEdit almost finish fullEditMode

This commit is contained in:
2022-12-15 13:05:53 +03:00
parent cdb02fc9be
commit 4bb4e87cc2
10 changed files with 622 additions and 173 deletions

View File

@@ -1,28 +1,27 @@
#include "pivaluetree_edit.h"
#include "piqt.h"
#include "pivaluetree_edit_parameters.h"
#include "pivariant_edit.h"
#include "qinputdialog.h"
#include "qmessagebox.h"
#include "qtoolbutton.h"
#include "ui_pivaluetree_edit_array.h"
#include "ui_pivaluetree_edit_parameters.h"
#include <QEvent>
#include <QFormLayout>
#include <QGroupBox>
using Attribute = PIValueTree::Attribute;
const char property_name[] = "__name__";
PIValueTreeEdit::PIValueTreeEdit(QWidget * parent): QWidget(parent) {
widget_params = new QDialog();
widget_params = new PIValueTreeEditParameters();
ui_array = new Ui::PIValueTreeEditArray();
ui_params = new Ui::PIValueTreeEditParameters();
ui_params->setupUi(widget_params);
grid = new GridWidgets(ui_params);
grid->parent = this;
auto * lay = new QBoxLayout(QBoxLayout::TopToBottom);
grid = new GridWidgets(this);
auto * lay = new QBoxLayout(QBoxLayout::TopToBottom);
lay->setContentsMargins(0, 0, 0, 0);
setLayout(lay);
}
@@ -30,7 +29,6 @@ PIValueTreeEdit::PIValueTreeEdit(QWidget * parent): QWidget(parent) {
PIValueTreeEdit::~PIValueTreeEdit() {
delete grid;
delete ui_params;
delete ui_array;
delete widget_params;
}
@@ -84,7 +82,9 @@ void PIValueTreeEdit::removeAll() {
value_edits.clear();
tree_edits.clear();
if (widget_array) {
ui_array->layoutArray->takeAt(0);
ui_array->layoutArray->removeWidget(grid);
grid->hide();
grid->setParent(this);
delete widget_array;
widget_array = nullptr;
}
@@ -97,18 +97,17 @@ void PIValueTreeEdit::removeAll() {
void PIValueTreeEdit::build() {
grid->create_edit_buttons = false;
removeAll();
// piCout << source.attributes().value(PIValueTree::attributeArrayType) << array_type;
// piCout << source.attributes().value(Attribute::arrayType) << array_type;
if (source.isArray()) {
grid->create_edit_buttons = false;
widget_array = new QWidget();
widget_array = new QWidget();
ui_array->setupUi(widget_array);
ui_array->spinCount->setRange(source.attribute(PIValueTree::attributeArrayMinCount, 0).toInt(),
source.attribute(PIValueTree::attributeArrayMaxCount, 65536).toInt());
ui_array->spinCount->setValue(source.children().size_s());
ui_array->widgetEdit->setVisible(source.attribute(PIValueTree::attributeArrayResize, false).toBool());
applyArrayAttributes();
ui_array->layoutArray->addWidget(grid);
uint array_type = PIVariant::typeIDFromName(source.attribute(PIValueTree::attributeArrayType).toString());
grid->button_add->hide();
grid->show();
uint array_type = PIVariant::typeIDFromName(source.attribute(Attribute::arrayType).toString());
int index = 0;
for (const auto & i: source.children()) {
auto * ve = new PIVariantEdit();
@@ -117,7 +116,7 @@ void PIValueTreeEdit::build() {
grid->add(PIValueTree(), QString::number(++index), ve, PI2QString(i.comment()));
array_edits << ve;
}
connect(ui_array->spinCount, QOverload<int>::of(&QSpinBox::valueChanged), this, [this, array_type](int value) {
connect(ui_array->spinCount, QOverload<int>::of(&QSpinBox::valueChanged), widget_array, [this, array_type](int value) {
value = piMaxi(value, 0);
for (int i = grid->rowCount() - 1; i >= value; --i)
grid->removeRow(i);
@@ -134,9 +133,10 @@ void PIValueTreeEdit::build() {
} else {
grid->create_edit_buttons = is_full_edit;
layout()->addWidget(grid);
if (!source.hasChildren()) grid->clear();
for (const auto & i: source.children()) {
if (i.attribute(PIValueTree::attributeHidden, false).toBool()) continue;
if (i.attribute(PIValueTree::attributeIsLabel, false).toBool()) {
if (i.attribute(Attribute::hidden, false).toBool()) continue;
if (i.attribute(Attribute::isLabel, false).toBool()) {
if (i.name().isEmpty()) continue;
auto * l = new QLabel(PI2QString(i.name()));
l->setAlignment(Qt::AlignCenter);
@@ -144,34 +144,9 @@ void PIValueTreeEdit::build() {
continue;
}
if (i.hasChildren() || i.isArray()) {
auto * ve = new PIValueTreeEdit();
PIStringList rp = root_path;
rp << i.name();
ve->root_path = rp;
ve->setGroupingEnabled(is_grouping);
ve->setFullEditMode(is_full_edit);
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(i, gb);
} else {
grid->add(i, PI2QString(i.name()), ve, PI2QString(i.comment()));
}
tree_edits[i.name()] = ve;
addTreeEdit(i);
} else {
auto * ve = new PIVariantEdit();
ve->setAttributes(i.attributes());
ve->setValue(i.value());
grid->add(i, PI2QString(i.name()), ve, PI2QString(i.comment()));
value_edits[i.name()] = ve;
addValueEdit(i);
}
}
}
@@ -180,7 +155,7 @@ void PIValueTreeEdit::build() {
void PIValueTreeEdit::applyValues() const {
if (source.isArray()) {
if (array_edits.isNotEmpty()) source.mergeAttributes(array_edits[0]->defaultAttributes());
if (array_edits.isNotEmpty()) source.mergeAttributes(array_edits[0]->attributes());
source.clearChildren();
for (int i = 0; i < array_edits.size_s(); ++i)
source.addChild({PIString::fromNumber(i), array_edits[i]->value()});
@@ -188,7 +163,7 @@ void PIValueTreeEdit::applyValues() const {
auto vit = value_edits.makeIterator();
while (vit.next()) {
auto & c(source.child(vit.key()));
c.mergeAttributes(vit.value()->defaultAttributes());
c.mergeAttributes(vit.value()->attributes());
c.setValue(vit.value()->value());
}
auto tit = tree_edits.makeIterator();
@@ -201,7 +176,7 @@ void PIValueTreeEdit::applyValues() const {
void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn, QAction * a) {
if (a == ui_params->actionRename) {
if (a == widget_params->actionRename) {
PIString nn = Q2PIString(QInputDialog::getText(nullptr, tr("Rename"), tr("Input new name:"), QLineEdit::Normal, PI2QString(vn)));
if (nn.isEmpty() || (nn == vn)) return;
for (const auto & c: source.children()) {
@@ -213,51 +188,140 @@ void PIValueTreeEdit::actionTriggered(QToolButton * button, const PIString & vn,
source[vn].setName(nn);
button->setProperty(property_name, PI2QString(nn));
grid->rename(PI2QString(vn), PI2QString(nn));
if (value_edits.contains(vn)) {
value_edits[nn] = value_edits[vn];
value_edits.remove(vn);
}
if (tree_edits.contains(vn)) {
tree_edits[nn] = tree_edits[vn];
tree_edits.remove(vn);
}
}
if (a == ui_params->actionRemove) {
if (a == widget_params->actionRemove) {
source.remove(vn);
grid->removeRow(grid->getRow(button));
value_edits.remove(vn);
tree_edits.remove(vn);
}
if (a == ui_params->actionChange) {
if (last_IDs_count != PIVariant::knownTypeIDsCount()) {
last_IDs_count = PIVariant::knownTypeIDsCount();
ui_params->comboType->clear();
auto ids = PIVariant::knownTypeIDs();
PIVector<PIPair<uint, QString>> types;
for (auto id: ids) {
if (!PIVariantEditorBase::editorExists(id)) continue;
PIString tn = PIVariant::typeNameFromID(id);
if (tn.startsWith("PI")) tn.remove(0, 2);
if (tn.startsWith("VariantTypes::")) tn.remove(0, 14);
types.append({id, PI2QString(tn)});
}
types.sort([](const PIPair<uint, QString> & a, const PIPair<uint, QString> & b) {
return QString::localeAwareCompare(a.second, b.second) < 0;
});
for (const auto & t: types)
ui_params->comboType->addItem(t.second, t.first);
if (a == widget_params->actionChange) {
auto & vt(source[vn]);
if (vt.isArray()) {
auto * ve = tree_edits.value(vn, nullptr);
if (!ve) return;
vt = ve->value();
if (!widget_params->showFor(vt)) return;
ve->setValue(vt);
// ve->applyArrayAttributes();
} else {
auto * ve = value_edits.value(vn, nullptr);
if (!ve) return;
vt.setValue(ve->value());
if (!widget_params->showFor(vt)) return;
ve->setAttributes(vt.attributes());
ve->setValue(vt.value());
}
auto old_vt = source.child(vn);
ui_params->comboType->setCurrentIndex(ui_params->comboType->findData(old_vt.value().typeID()));
ui_params->checkArray->setChecked(old_vt.isArray());
if (widget_params->exec() != QDialog::Accepted) return;
auto & el(source[vn]);
uint nid = ui_params->comboType->currentData().toUInt();
PIString vs = el.value().toString();
PIVariant var = PIVariant::fromType(nid);
var.setValueFromString(vs);
source[vn].setValue(var);
build();
}
}
PIValueTreeEdit * PIValueTreeEdit::addTreeEdit(const PIValueTree & vt) {
auto * ve = new PIValueTreeEdit();
PIStringList rp = root_path;
rp << vt.name();
ve->root_path = rp;
ve->setGroupingEnabled(is_grouping);
ve->setFullEditMode(is_full_edit);
ve->setValue(vt);
if (is_grouping) {
auto * gb = new QGroupBox();
gb->setLayout(new QBoxLayout(QBoxLayout::TopToBottom));
gb->layout()->addWidget(ve);
gb->setTitle(PI2QString(vt.name()));
gb->setToolTip(PI2QString(vt.comment()));
gb->setCheckable(true);
gb->setChecked(true);
gb->setAlignment(Qt::AlignCenter);
connect(gb, &QGroupBox::toggled, ve, &QWidget::setVisible);
grid->add(vt, gb, true);
} else {
grid->add(vt, PI2QString(vt.name()), ve, PI2QString(vt.comment()), true);
}
tree_edits[vt.name()] = ve;
return ve;
}
void PIValueTreeEdit::addValueEdit(const PIValueTree & vt) {
auto * ve = new PIVariantEdit();
ve->setAttributes(vt.attributes());
ve->setValue(vt.value());
grid->add(vt, PI2QString(vt.name()), ve, PI2QString(vt.comment()));
value_edits[vt.name()] = ve;
}
void PIValueTreeEdit::applyArrayAttributes() {
ui_array->spinCount->setRange(source.attribute(Attribute::arrayMinCount, 0).toInt(),
source.attribute(Attribute::arrayMaxCount, 65536).toInt());
ui_array->spinCount->setValue(source.children().size_s());
ui_array->widgetEdit->setVisible(source.attribute(Attribute::arrayResize, false).toBool());
uint array_type = PIVariant::typeIDFromName(source.attribute(Attribute::arrayType).toString());
for (int i = 0; i < array_edits.size_s(); ++i) {
auto * w = array_edits[i];
w->setAttributes(source.attributes());
w->setValue(i < source.children().size_s() ? source.children()[i].value() : PIVariant(), array_type);
}
}
void PIValueTreeEdit::newRequest(NewType type) {
PIString nn = Q2PIString(QInputDialog::getText(nullptr, tr("New item"), tr("Input new name:")));
if (nn.isEmpty()) return;
for (const auto & c: source.children()) {
if (c.name() == nn) {
QMessageBox::critical(nullptr, tr("New item"), tr("This name already exists!"));
return;
}
}
PIValueTree vt;
vt.setName(nn);
if (type == NewType::Value) {
if (!widget_params->showFor(vt)) return;
}
if (type == NewType::Array) {
vt.setAttribute(Attribute::arrayType, PIVariant::typeName<PIString>());
if (!widget_params->showFor(vt)) return;
}
source.addChild(vt);
switch (type) {
case NewType::Value: addValueEdit(vt); break;
case NewType::Group: addTreeEdit(vt); break;
case NewType::Array: addTreeEdit(vt); break;
}
}
// PIValueTreeEdit::GridWidgets
PIValueTreeEdit::GridWidgets::GridWidgets(Ui::PIValueTreeEditParameters * ui_) {
ui_params = ui_;
PIValueTreeEdit::GridWidgets::GridWidgets(PIValueTreeEdit * p) {
parent = p;
icon_conf = QIcon(":/icons/configure.png");
conf_menu.addActions({ui_params->actionRename, ui_params->actionChange, ui_params->actionRemove});
menu_group.addActions({p->widget_params->actionRename, p->widget_params->actionRemove});
menu_conf.addActions({p->widget_params->actionRename, p->widget_params->actionChange, p->widget_params->actionRemove});
menu_new.addActions({p->widget_params->actionValue, p->widget_params->actionGroup, p->widget_params->actionArray});
button_add = new QToolButton();
button_add->setIcon(QIcon(":/icons/list-add.png"));
button_add->setPopupMode(QToolButton::InstantPopup);
button_add->setMenu(&menu_new);
p->widget_params->actionValue->setData((int)NewType::Value);
p->widget_params->actionGroup->setData((int)NewType::Group);
p->widget_params->actionArray->setData((int)NewType::Array);
connect(button_add, &QToolButton::triggered, this, [this](QAction * a) { parent->newRequest((NewType)a->data().toInt()); });
}
PIValueTreeEdit::GridWidgets::~GridWidgets() {
delete button_add;
}
@@ -266,19 +330,16 @@ int PIValueTreeEdit::GridWidgets::getRow(QWidget * w) const {
for (int r = 0; r < lay->rowCount(); ++r) {
for (int c = 0; c < lay->columnCount(); ++c) {
auto * li = lay->itemAtPosition(r, c);
if (li) {
if (li->widget()) {
if (li->widget() == w) return r;
}
}
if (!li) continue;
if (li->widget() && (li->widget() == w)) return r;
}
}
return -1;
}
void PIValueTreeEdit::GridWidgets::add(const PIValueTree & vt, QString label, QWidget * w, const QString & comment) {
int col = beginRow(vt);
void PIValueTreeEdit::GridWidgets::add(const PIValueTree & vt, QString label, QWidget * w, const QString & comment, bool is_group) {
int col = beginRow(vt, is_group);
if (!label.isEmpty()) label += ':';
auto * l = new QLabel(label);
auto * c = new QLabel(comment);
@@ -291,24 +352,27 @@ void PIValueTreeEdit::GridWidgets::add(const PIValueTree & vt, QString label, QW
widgets << l << w << c;
labels << l;
++row_count;
changed();
}
void PIValueTreeEdit::GridWidgets::add(const PIValueTree & vt, QWidget * w) {
int col = beginRow(vt);
void PIValueTreeEdit::GridWidgets::add(const PIValueTree & vt, QWidget * w, bool is_group) {
int col = beginRow(vt, is_group);
lay->addWidget(w, row_count, col, 1, -1);
widgets << w;
++row_count;
changed();
}
int PIValueTreeEdit::GridWidgets::beginRow(const PIValueTree & vt) {
int PIValueTreeEdit::GridWidgets::beginRow(const PIValueTree & vt, bool is_group) {
if (!create_edit_buttons) return 0;
auto * b = new QToolButton();
b->setIcon(icon_conf);
b->setPopupMode(QToolButton::InstantPopup);
b->setMenu(&conf_menu);
b->setMenu((is_group && !vt.isArray()) ? &menu_group : &menu_conf);
b->setProperty(property_name, PI2QString(vt.name()));
b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
lay->addWidget(b, row_count, 0);
connect(b, &QToolButton::triggered, this, [this, b](QAction * a) {
parent->actionTriggered(b, Q2PIString(b->property(property_name).toString()), a);
@@ -319,13 +383,24 @@ int PIValueTreeEdit::GridWidgets::beginRow(const PIValueTree & vt) {
void PIValueTreeEdit::GridWidgets::rename(QString prev_name, QString new_name) {
if (!prev_name.isEmpty()) prev_name += ':';
if (!new_name.isEmpty()) new_name += ':';
for (auto * l: labels)
if (l->text() == prev_name) {
l->setText(new_name);
break;
if (parent->is_grouping) {
for (auto * w: widgets) {
auto * gb = qobject_cast<QGroupBox *>(w);
if (!gb) continue;
if (gb->title() == prev_name) {
gb->setTitle(new_name);
break;
}
}
} else {
if (!prev_name.isEmpty()) prev_name += ':';
if (!new_name.isEmpty()) new_name += ':';
for (auto * l: labels)
if (l->text() == prev_name) {
l->setText(new_name);
break;
}
}
}
@@ -337,25 +412,35 @@ void PIValueTreeEdit::GridWidgets::clear() {
lay->setContentsMargins(0, 0, 0, 0);
setLayout(lay);
row_count = 0;
changed();
}
void PIValueTreeEdit::GridWidgets::changed() {
if (!create_edit_buttons || !lay) return;
lay->addWidget(button_add, row_count, 0);
button_add->show();
}
void PIValueTreeEdit::GridWidgets::removeRow(int index) {
if (!lay || index < 0 || row_count <= index) return;
if (!lay) return;
if ((index < 0) || (index >= row_count) || (index >= lay->rowCount())) return;
for (int c = 0; c < lay->columnCount(); ++c) {
auto * li = lay->itemAtPosition(index, c);
if (li) {
if (li->widget()) {
widgets.removeOne(li->widget());
QLabel * lbl = qobject_cast<QLabel *>(li->widget());
QWidget * w = li->widget();
if (w) {
widgets.removeOne(w);
QLabel * lbl = qobject_cast<QLabel *>(w);
if (lbl) labels.removeOne(lbl);
delete li->widget();
delete w;
}
delete li;
}
}
--row_count;
simplify();
changed();
}