Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "propertyeditordialog.h"
- #include "./ui_propertyeditordialog.h"
- #include "colorpicker.h"
- #include <QWindow>
- #include <QMetaProperty>
- #include <QSpinBox>
- #include <QDoubleSpinBox>
- #include <QCheckBox>
- #include <QColorDialog>
- #include <QLineEdit>
- #include <QSize>
- #include <QTextStream>
- #include <QLocale>
- #include <QLineEdit>
- #include <QFileDialog>
- #include <limits>
- PropertyEditorDialog::PropertyEditorDialog(QObject * object, QWidget * parent)
- : QDialog(parent)
- , ui(new Ui::PropertyEditorDialog)
- {
- ui->setupUi(this);
- auto t = ui->tableWidget;
- t->setColumnCount(2);
- t->setHorizontalHeaderLabels({"Property name", "Property value"});
- t->resizeColumnToContents(0);
- t->horizontalHeader()->setStretchLastSection(true);
- t->verticalHeader()->setVisible(false);
- int propertyOffset = object->metaObject()->propertyOffset();
- int propertyCount = object->metaObject()->propertyCount();
- t->setRowCount(propertyCount - propertyOffset);
- for (int i = propertyOffset; i < propertyCount; ++i) {
- const auto & property = object->metaObject()->property(i);
- Q_ASSERT(property.hasNotifySignal());
- auto propertyName = property.name();
- // name
- auto nameItem = new QTableWidgetItem(propertyName);
- nameItem->setFlags(nameItem->flags() & ~Qt::ItemIsEditable);
- t->setItem(i - propertyOffset, 0, nameItem);
- // value
- auto value = object->property(property.name());
- switch (int(property.type())) {
- case QMetaType::QString : {
- auto valueItem = new QLineEdit{t};
- valueItem->setText(value.toString());
- t->setCellWidget(i - propertyOffset, 1, valueItem);
- QObject::connect(valueItem, &QLineEdit::textChanged, object, [object, propertyName] (QString value) { object->setProperty(propertyName, value); });
- break;
- }
- case QMetaType::Bool : {
- auto valueItem = new QCheckBox{t};
- valueItem->setCheckState(value.toBool() ? Qt::Checked : Qt::Unchecked);
- t->setCellWidget(i - propertyOffset, 1, valueItem);
- QObject::connect(valueItem, &QCheckBox::stateChanged, object, [object, propertyName] (int state) { object->setProperty(propertyName, (Qt::CheckState(state) == Qt::Checked)); });
- break;
- }
- case QMetaType::Float : {
- auto valueItem = new QDoubleSpinBox{t};
- valueItem->setRange(qreal(std::numeric_limits<float>::min()), qreal(std::numeric_limits<float>::max()));
- valueItem->setStepType(QDoubleSpinBox::AdaptiveDecimalStepType);
- valueItem->setValue(value.toDouble());
- t->setCellWidget(i - propertyOffset, 1, valueItem);
- QObject::connect(valueItem, qOverload<double>(&QDoubleSpinBox::valueChanged), object, [object, propertyName] (double value) { object->setProperty(propertyName, value); });
- break;
- }
- case QMetaType::Int : {
- auto valueItem = new QSpinBox{t};
- valueItem->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
- valueItem->setStepType(QSpinBox::AdaptiveDecimalStepType);
- valueItem->setValue(value.toInt());
- t->setCellWidget(i - propertyOffset, 1, valueItem);
- QObject::connect(valueItem, qOverload<int>(&QSpinBox::valueChanged), object, [object, propertyName] (int value) { object->setProperty(propertyName, value); });
- break;
- }
- case QVariant::Type::Color : {
- auto color = value.value<QColor>();
- auto valueItem = new ColorPicker{color, t};
- t->setCellWidget(i - propertyOffset, 1, valueItem);
- QObject::connect(valueItem, &ColorPicker::colorChanged, object, [object, propertyName] (QColor color) { object->setProperty(propertyName, color); });
- break;
- }
- case QMetaType::QSize : {
- auto valueItem = new QLineEdit{t};
- auto v = new SizeValidator;
- Q_CHECK_PTR(v);
- valueItem->setValidator(v);
- valueItem->setInputMask(QStringLiteral("00009x00009"));
- auto oldSize = value.toSize();
- valueItem->setText(QStringLiteral("%1x%2").arg(oldSize.width()).arg(oldSize.height()));
- t->setCellWidget(i - propertyOffset, 1, valueItem);
- auto onTextChanged = [object, propertyName, valueItem, oldSize]
- {
- auto size = SizeValidator::toSize(valueItem->text(), oldSize);
- object->setProperty(propertyName, size);
- };
- QObject::connect(valueItem, &QLineEdit::textChanged, object, onTextChanged);
- break;
- }
- }
- }
- auto onDoubleClicked = [t, this] (QModelIndex index)
- {
- if (index.column() != 0) {
- return;
- }
- auto valueIndex = index.siblingAtColumn(1);
- auto cellWidget = t->indexWidget(valueIndex);
- if (!cellWidget) {
- return;
- }
- if (auto colorPicker = qobject_cast<ColorPicker*>(cellWidget)) {
- auto oldColor = colorPicker->color();
- for (int i = 0; i < QColorDialog::customCount(); ++i) {
- QColorDialog::setCustomColor(i, oldColor);
- }
- auto color = QColorDialog::getColor(oldColor, this, t->model()->data(index, Qt::DisplayRole).toString(), QColorDialog::DontUseNativeDialog);
- if (!color.isValid() || (color == oldColor)) {
- return;
- }
- colorPicker->setColor(color);
- } else if (auto lineEdit = qobject_cast<QLineEdit*>(cellWidget)) {
- QFileInfo fileInfo{lineEdit->text()};
- auto filePath = QFileDialog::getOpenFileName(nullptr, QStringLiteral("Open filepath"), fileInfo.dir().path(), "All files (*.*)", nullptr, QFileDialog::DontUseNativeDialog);
- if (!filePath.isEmpty()) {
- lineEdit->setText(filePath);
- }
- }
- };
- QObject::connect(t, &QTableWidget::doubleClicked, this, onDoubleClicked);
- QObject::connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
- QObject::connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
- }
- PropertyEditorDialog::~PropertyEditorDialog()
- {
- delete ui;
- }
- int PropertyEditorDialog::exec(QString title, QWindow * window)
- {
- winId();
- windowHandle()->setTransientParent(window);
- setModal(false);
- setWindowTitle(title);
- return exec();
- }
- SizeValidator::SizeValidator()
- {
- setLocale(QLocale::c());
- }
- auto SizeValidator::validate(QString & input, int & pos) const -> State
- {
- Q_UNUSED(pos)
- QSize size;
- return toSize(input, &size);
- }
- auto SizeValidator::toSize(QString s, QSize * size) -> State
- {
- QTextStream ts{&s, QIODevice::ReadOnly};
- int width = -1, height = -1;
- auto x = QChar::fromLatin1('x');
- if ((ts >> width).status() != QTextStream::Ok) {
- return Intermediate;
- }
- ts.skipWhiteSpace();
- if ((ts >> x).status() != QTextStream::Ok) {
- return Intermediate;
- }
- if (x != 'x') {
- return Invalid;
- }
- if ((ts >> height).status() != QTextStream::Ok) {
- return Intermediate;
- }
- if ((width < (1 << 6)) || (height < (1 << 6))) {
- return Intermediate;
- }
- if ((width > (1 << 14)) || (height > (1 << 14))) {
- return Invalid;
- }
- size->setWidth(width);
- size->setHeight(height);
- if (!size->isValid()) {
- return Invalid;
- }
- return Acceptable;
- }
- QSize SizeValidator::toSize(QString s, const QSize oldSize)
- {
- QSize size;
- if (toSize(s, &size) != Acceptable) {
- return oldSize;
- }
- return size;
- }
Advertisement
Add Comment
Please, Sign In to add comment