Files
qad/libs/widgets/qvariantedit.cpp
2022-12-14 14:14:33 +03:00

677 lines
16 KiB
C++

#include "qvariantedit.h"
#include <QDateTimeEdit>
#include <QFileDialog>
#include <QMessageBox>
QStringList StringListEdit::value() const {
QStringList l;
for (int i = 0; i < combo->count(); ++i)
l << combo->itemText(i);
return l;
}
void StringListEdit::setValue(const QStringList & v) {
int pi = combo->currentIndex();
combo->clear();
if (!v.isEmpty()) {
combo->addItems(v);
if (pi < combo->count() && pi >= 0) {
combo->setCurrentIndex(pi);
} else {
combo->setCurrentIndex(0);
}
}
}
void StringListEdit::addItem() {
combo->addItem(combo->currentText());
emit valueChanged();
}
void StringListEdit::delItem() {
if (combo->currentIndex() < 0) return;
combo->removeItem(combo->currentIndex());
emit valueChanged();
}
void StringListEdit::clear() {
if (combo->count() == 0) return;
combo->clear();
emit valueChanged();
}
StringListEdit::StringListEdit(QWidget * parent): QWidget(parent) {
lay = new QBoxLayout(QBoxLayout::LeftToRight);
combo = new EComboBox(this);
combo->setEditable(true);
combo->setLineEdit(new CLineEdit);
combo->setInsertPolicy(QComboBox::NoInsert);
butt_apply = new QPushButton(this);
butt_add = new QPushButton(this);
butt_del = new QPushButton(this);
butt_clear = new QPushButton(this);
butt_apply->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
butt_add->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
butt_del->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
butt_clear->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
butt_apply->setIcon(QIcon(":/icons/list-edit-apply.png"));
butt_add->setIcon(QIcon(":/icons/list-add.png"));
butt_del->setIcon(QIcon(":/icons/list-remove.png"));
butt_clear->setIcon(QIcon(":/icons/edit-clear.png"));
butt_apply->setToolTip(tr("Apply"));
butt_add->setToolTip(tr("Add"));
butt_del->setToolTip(tr("Remove"));
butt_clear->setToolTip(tr("Clear"));
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(2);
lay->addWidget(combo);
lay->addWidget(butt_apply);
lay->addWidget(butt_add);
lay->addWidget(butt_del);
lay->addWidget(butt_clear);
setLayout(lay);
connect(combo->lineEdit(), SIGNAL(returnPressed()), this, SLOT(editItem()));
connect(combo, SIGNAL(rowsChanged()), this, SIGNAL(valueChanged()));
connect(butt_apply, SIGNAL(clicked(bool)), this, SLOT(editItem()));
connect(butt_add, SIGNAL(clicked(bool)), this, SLOT(addItem()));
connect(butt_del, SIGNAL(clicked(bool)), this, SLOT(delItem()));
connect(butt_clear, &QPushButton::clicked, [this]() {
if (QMessageBox::question(this, tr("Clear All"), tr("Clear All?"), QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok)
clear();
});
}
void StringListEdit::changeEvent(QEvent * e) {
QWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
butt_add->setToolTip(tr("Add"));
butt_del->setToolTip(tr("Remove"));
butt_clear->setToolTip(tr("Clear"));
return;
}
}
void StringListEdit::editItem() {
int ci = combo->currentIndex();
if (ci < 0) return;
combo->setItemText(ci, combo->currentText());
emit valueChanged();
}
PathEdit::PathEdit(QWidget * parent): QWidget(parent), lay(QBoxLayout::LeftToRight, this) {
is_dir = is_abs = is_save = false;
filter = tr("All files(*)");
line = new CLineEdit(this);
butt_select = new QPushButton(this);
butt_select->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
butt_select->setIcon(QIcon(":/icons/document-open.png"));
butt_select->setToolTip(tr("Choose") + " ...");
lay.setContentsMargins(0, 0, 0, 0);
lay.addWidget(line);
lay.addWidget(butt_select);
connect(line, SIGNAL(textChanged(QString)), this, SIGNAL(valueChanged()));
connect(butt_select, SIGNAL(clicked(bool)), this, SLOT(select()));
}
void PathEdit::changeEvent(QEvent * e) {
QWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
butt_select->setToolTip(tr("Choose") + " ...");
return;
}
}
void PathEdit::resizeEvent(QResizeEvent *) {
butt_select->setMaximumHeight(line->height());
}
void PathEdit::setValue(const QString & v) {
line->setText(v);
if (!is_dir && is_save)
butt_select->setIcon(QIcon(":/icons/document-save.png"));
else
butt_select->setIcon(QIcon(":/icons/document-open.png"));
}
void PathEdit::select() {
QString ret;
if (is_dir)
ret = QFileDialog::getExistingDirectory(this, tr("Select directory"), value());
else {
if (is_save)
ret = QFileDialog::getSaveFileName(this, tr("Select file"), value(), filter);
else
ret = QFileDialog::getOpenFileName(this, tr("Select file"), value(), filter);
}
if (ret.isEmpty()) return;
if (!is_abs) ret = QDir::current().relativeFilePath(ret);
line->setText(ret);
emit valueChanged();
}
QVariantEdit::QVariantEdit(QWidget * parent): QWidget(parent) {
setLayout(new QBoxLayout(QBoxLayout::TopToBottom));
layout()->setContentsMargins(0, 0, 0, 0);
_empty = 0;
_line = 0;
_check = 0;
_color = 0;
_list = 0;
_date = 0;
_spin = 0;
_espin = 0;
_rect = 0;
_point = 0;
_path = 0;
_enum = 0;
_custom = _cur_edit = 0;
_recreate(QVariant());
}
QVariantEdit::~QVariantEdit() {
_delete();
}
void QVariantEdit::resizeEvent(QResizeEvent * e) {
QWidget::resizeEvent(e);
}
void QVariantEdit::_recreate(const QVariant & new_value) {
if (!new_value.isValid()) {
if (_cur_edit != _empty) _delete();
if (_empty == 0) {
_empty = new QLabel(tr("Invalid value"), this);
_empty->setAlignment(Qt::AlignCenter);
_cur_edit = _empty;
_resize();
}
_value = new_value;
return;
}
if (_value.userType() == new_value.userType()) {
_value = new_value;
return;
}
_delete();
#if QT_VERSION_MAJOR <= 5
switch (new_value.type()) {
#else
switch (new_value.metaType().id()) {
#endif
#if QT_VERSION_MAJOR <= 5
case QVariant::Bool:
#else
case QMetaType::Bool:
#endif
_check = new QCheckBox(this);
_check->setAutoFillBackground(true);
_cur_edit = _check;
connect(_check, SIGNAL(toggled(bool)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Int:
#else
case QMetaType::Int:
#endif
_spin = new QDoubleSpinBox(this);
_spin->setDecimals(0);
_spin->setRange(-0x7FFFFFFF, 0x7FFFFFFF);
_cur_edit = _spin;
connect(_spin, SIGNAL(valueChanged(double)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::UInt:
#else
case QMetaType::UInt:
#endif
_spin = new QDoubleSpinBox(this);
_spin->setDecimals(0);
_spin->setRange(0, 0xFFFFFFFF);
_cur_edit = _spin;
connect(_spin, SIGNAL(valueChanged(double)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::LongLong:
#else
case QMetaType::LongLong:
#endif
_spin = new QDoubleSpinBox(this);
_spin->setDecimals(0);
_spin->setRange(-0x7FFFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFFL);
_cur_edit = _spin;
connect(_spin, SIGNAL(valueChanged(double)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::ULongLong:
#else
case QMetaType::ULongLong:
#endif
_spin = new QDoubleSpinBox(this);
_spin->setDecimals(0);
_spin->setRange(0L, 0x7FFFFFFFFFFFFFFFL);
_cur_edit = _spin;
connect(_spin, SIGNAL(valueChanged(double)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Double:
#else
case QMetaType::Double:
#endif
_espin = new EvalSpinBox(this);
_cur_edit = _espin;
connect(_espin, SIGNAL(valueChanged(double)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Color:
#else
case QMetaType::QColor:
#endif
_color = new ColorButton(this);
_color->setUseAlphaChannel(true);
_cur_edit = _color;
connect(_color, SIGNAL(colorChanged(QColor)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::String:
#else
case QMetaType::QString:
#endif
_line = new CLineEdit(this);
_cur_edit = _line;
connect(_line, SIGNAL(textChanged(QString)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::StringList:
#else
case QMetaType::QStringList:
#endif
_list = new StringListEdit(this);
_cur_edit = _list;
connect(_list, SIGNAL(valueChanged()), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Rect:
#else
case QMetaType::QRect:
#endif
_rect = new QRectEdit(this);
_rect->setDecimals(0);
_cur_edit = _rect;
connect(_rect, SIGNAL(valueChanged(QRectF)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::RectF:
#else
case QMetaType::QRectF:
#endif
_rect = new QRectEdit(this);
_rect->setDecimals(3);
_cur_edit = _rect;
connect(_rect, SIGNAL(valueChanged(QRectF)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Point:
#else
case QMetaType::QPoint:
#endif
_point = new QPointEdit(this);
_point->setDecimals(0);
_cur_edit = _point;
connect(_point, SIGNAL(valueChanged(QPointF)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::PointF:
#else
case QMetaType::QPointF:
#endif
_point = new QPointEdit(this);
_point->setDecimals(3);
_cur_edit = _point;
connect(_point, SIGNAL(valueChanged(QPointF)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Date:
#else
case QMetaType::QDate:
#endif
_date = new QDateEdit(this);
_cur_edit = _date;
connect(_date, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Time:
#else
case QMetaType::QTime:
#endif
_date = new QTimeEdit(this);
_cur_edit = _date;
connect(_date, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(_changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::DateTime:
#else
case QMetaType::QDateTime:
#endif
_date = new QDateTimeEdit(this);
_cur_edit = _date;
connect(_date, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(_changed()));
break;
default: break;
}
if (!_cur_edit) {
if (new_value.canConvert<QAD::Enum>()) {
_enum = new EComboBox(this);
_setEnum(new_value.value<QAD::Enum>());
_cur_edit = _enum;
connect(_enum, SIGNAL(currentIndexChanged(int)), this, SLOT(_changed()));
}
if (new_value.canConvert<QAD::File>()) {
_path = new PathEdit(this);
_setFile(new_value.value<QAD::File>());
_cur_edit = _path;
connect(_path, SIGNAL(valueChanged()), this, SLOT(_changed()));
}
if (new_value.canConvert<QAD::Dir>()) {
_path = new PathEdit(this);
_setDir(new_value.value<QAD::Dir>());
_cur_edit = _path;
connect(_path, SIGNAL(valueChanged()), this, SLOT(_changed()));
}
if (!_cur_edit) { // try custom
QVariantEditorFactoryBase * f = QVariantEditorFactories::editorFactory(new_value.userType());
if (f) {
QWidget * fw = f->createEditor();
if (fw) {
fw->setParent(this);
_custom = fw;
_cur_edit = _custom;
connect(_custom, SIGNAL(valueChanged()), this, SLOT(_changed()));
}
}
}
}
if (_cur_edit) {
_resize();
}
_value = new_value;
}
QVariant QVariantEdit::value() const {
#if QT_VERSION_MAJOR <= 5
switch (_value.type()) {
#else
switch (_value.metaType().id()) {
#endif
#if QT_VERSION_MAJOR <= 5
case QVariant::Bool:
#else
case QMetaType::Bool:
#endif
return _check->isChecked();
#if QT_VERSION_MAJOR <= 5
case QVariant::Int:
#else
case QMetaType::Int:
#endif
return int(_spin->value());
#if QT_VERSION_MAJOR <= 5
case QVariant::UInt:
#else
case QMetaType::UInt:
#endif
return (unsigned int)(_spin->value());
#if QT_VERSION_MAJOR <= 5
case QVariant::LongLong:
#else
case QMetaType::LongLong:
#endif
return qlonglong(_spin->value());
#if QT_VERSION_MAJOR <= 5
case QVariant::ULongLong:
#else
case QMetaType::ULongLong:
#endif
return qulonglong(_spin->value());
#if QT_VERSION_MAJOR <= 5
case QVariant::Double:
#else
case QMetaType::Double:
#endif
return _espin->value();
#if QT_VERSION_MAJOR <= 5
case QVariant::Color:
#else
case QMetaType::QColor:
#endif
return _color->color();
#if QT_VERSION_MAJOR <= 5
case QVariant::String:
#else
case QMetaType::QString:
#endif
return _line->text();
#if QT_VERSION_MAJOR <= 5
case QVariant::StringList:
#else
case QMetaType::QStringList:
#endif
return _list->value();
#if QT_VERSION_MAJOR <= 5
case QVariant::Rect:
#else
case QMetaType::QRect:
#endif
return _rect->value().toRect();
#if QT_VERSION_MAJOR <= 5
case QVariant::RectF:
#else
case QMetaType::QRectF:
#endif
return _rect->value();
#if QT_VERSION_MAJOR <= 5
case QVariant::Point:
#else
case QMetaType::QPoint:
#endif
return _point->value().toPoint();
#if QT_VERSION_MAJOR <= 5
case QVariant::PointF:
#else
case QMetaType::QPointF:
#endif
return _point->value();
#if QT_VERSION_MAJOR <= 5
case QVariant::Date:
#else
case QMetaType::QDate:
#endif
return _date->date();
#if QT_VERSION_MAJOR <= 5
case QVariant::Time:
#else
case QMetaType::QTime:
#endif
return _date->time();
#if QT_VERSION_MAJOR <= 5
case QVariant::DateTime:
#else
case QMetaType::QDateTime:
#endif
return _date->dateTime();
default:
if (_value.canConvert<QAD::Enum>() && _enum) {
QAD::Enum ret;
for (int i = 0; i < _enum->count(); ++i)
ret.enum_list << QAD::Enumerator(_enum->itemData(i).toInt(), _enum->itemText(i));
ret.enum_name = _enum->property("enum_name").toString();
ret.selected = _enum->currentText();
return QVariant::fromValue<QAD::Enum>(ret);
}
if (_value.canConvert<QAD::File>() && _path) {
if (!_path->is_dir) {
QAD::File ret;
ret.file = _path->value();
ret.filter = _path->filter;
ret.is_abs = _path->is_abs;
ret.is_save = _path->is_save;
return QVariant::fromValue<QAD::File>(ret);
}
}
if (_value.canConvert<QAD::Dir>() && _path) {
if (_path->is_dir) {
QAD::Dir ret;
ret.dir = _path->value();
ret.is_abs = _path->is_abs;
return QVariant::fromValue<QAD::Dir>(ret);
}
}
if (_custom) {
return _custom->property("value");
}
}
return QVariant();
}
void QVariantEdit::setValue(const QVariant & v) {
_recreate(v);
if (_cur_edit) _cur_edit->blockSignals(true);
if (_line) {
_line->setText(v.toString());
}
if (_check) {
_check->setChecked(v.toBool());
_check->setText(v.toBool() ? "true" : "false");
}
if (_color) {
_color->setColor(v.value<QColor>());
}
if (_list) {
_list->setValue(v.toStringList());
}
if (_date) {
_date->setDateTime(v.toDateTime());
}
if (_spin) {
_spin->setValue(v.toDouble());
}
if (_espin) {
_espin->setValue(v.toDouble());
}
if (_rect) {
_rect->setValue(v.toRectF());
}
if (_point) {
_point->setValue(v.toPointF());
}
if (_path) {
if (_path->is_dir)
_setDir(v.value<QAD::Dir>());
else
_setFile(v.value<QAD::File>());
}
if (_enum) {
_setEnum(v.value<QAD::Enum>());
}
if (_custom) {
_setCustom(v);
}
if (_cur_edit) _cur_edit->blockSignals(false);
}
void QVariantEdit::_delete() {
if (_cur_edit) delete _cur_edit;
_cur_edit = 0;
_custom = 0;
_empty = 0;
_line = 0;
_check = 0;
_color = 0;
_list = 0;
_date = 0;
_spin = 0;
_espin = 0;
_rect = 0;
_point = 0;
_path = 0;
_enum = 0;
}
void QVariantEdit::_resize() {
if (!_cur_edit) return;
layout()->addWidget(_cur_edit);
}
void QVariantEdit::_newPath() {
_delete();
_path = new PathEdit(this);
_cur_edit = _path;
_value = _value.toString();
connect(_path, SIGNAL(valueChanged()), this, SLOT(_changed()));
_resize();
}
void QVariantEdit::_setEnum(const QAD::Enum & v) {
_enum->clear();
_enum->setProperty("enum_name", v.enum_name);
foreach(const QAD::Enumerator & e, v.enum_list)
_enum->addItem(e.name, QVariant(e.value));
int i(0);
for (i = 0; i < _enum->count(); ++i)
if (_enum->itemText(i) == v.selected) {
_enum->setCurrentIndex(i);
break;
}
if (i == _enum->count()) _enum->setCurrentIndex(-1);
}
void QVariantEdit::_setFile(const QAD::File & v) {
_path->is_dir = false;
_path->filter = v.filter;
_path->is_abs = v.is_abs;
_path->is_save = v.is_save;
_path->setValue(v.file);
}
void QVariantEdit::_setDir(const QAD::Dir & v) {
_path->is_dir = true;
_path->is_abs = v.is_abs;
_path->setValue(v.dir);
}
void QVariantEdit::_setCustom(const QVariant & v) {
_custom->setProperty("value", v);
}
void QVariantEdit::_changed() {
if (_check) _check->setText(_check->isChecked() ? "true" : "false");
emit valueChanged(value());
}