summaryrefslogtreecommitdiffstats
path: root/tests/manual/examples/widgets/tools/settingseditor/variantdelegate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/examples/widgets/tools/settingseditor/variantdelegate.cpp')
-rw-r--r--tests/manual/examples/widgets/tools/settingseditor/variantdelegate.cpp377
1 files changed, 377 insertions, 0 deletions
diff --git a/tests/manual/examples/widgets/tools/settingseditor/variantdelegate.cpp b/tests/manual/examples/widgets/tools/settingseditor/variantdelegate.cpp
new file mode 100644
index 0000000000..ed51a1645b
--- /dev/null
+++ b/tests/manual/examples/widgets/tools/settingseditor/variantdelegate.cpp
@@ -0,0 +1,377 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "variantdelegate.h"
+
+#include <QCheckBox>
+#include <QDateTime>
+#include <QLineEdit>
+#include <QSpinBox>
+#include <QRegularExpressionValidator>
+#include <QTextStream>
+
+#include <algorithm>
+
+static bool isPrintableChar(char c)
+{
+ return uchar(c) >= 32 && uchar(c) < 128;
+}
+
+static bool isPrintable(const QByteArray &ba)
+{
+ return std::all_of(ba.cbegin(), ba.cend(), isPrintableChar);
+}
+
+static QString byteArrayToString(const QByteArray &ba)
+{
+ if (isPrintable(ba))
+ return QString::fromLatin1(ba);
+ QString result;
+ for (char c : ba) {
+ if (isPrintableChar(c)) {
+ if (c == '\\')
+ result += QLatin1Char(c);
+ result += QLatin1Char(c);
+ } else {
+ const uint uc = uchar(c);
+ result += "\\x";
+ if (uc < 16)
+ result += '0';
+ result += QString::number(uc, 16);
+ }
+ }
+ return result;
+}
+
+TypeChecker::TypeChecker()
+{
+ boolExp.setPattern("^(true)|(false)$");
+ boolExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+ Q_ASSERT(boolExp.isValid());
+
+ byteArrayExp.setPattern(R"RX(^[\x00-\xff]*$)RX");
+ charExp.setPattern("^.$");
+ Q_ASSERT(charExp.isValid());
+ colorExp.setPattern(R"RX(^\(([0-9]*),([0-9]*),([0-9]*),([0-9]*)\)$)RX");
+ Q_ASSERT(colorExp.isValid());
+ doubleExp.setPattern("");
+ pointExp.setPattern(R"RX(^\((-?[0-9]*),(-?[0-9]*)\)$)RX");
+ Q_ASSERT(pointExp.isValid());
+ rectExp.setPattern(R"RX(^\((-?[0-9]*),(-?[0-9]*),(-?[0-9]*),(-?[0-9]*)\)$)RX");
+ Q_ASSERT(rectExp.isValid());
+ signedIntegerExp.setPattern("^-?[0-9]*$");
+ Q_ASSERT(signedIntegerExp.isValid());
+ sizeExp = pointExp;
+ unsignedIntegerExp.setPattern("^[0-9]+$");
+ Q_ASSERT(unsignedIntegerExp.isValid());
+
+ const QString datePattern = "([0-9]{,4})-([0-9]{,2})-([0-9]{,2})";
+ dateExp.setPattern('^' + datePattern + '$');
+ Q_ASSERT(dateExp.isValid());
+ const QString timePattern = "([0-9]{,2}):([0-9]{,2}):([0-9]{,2})";
+ timeExp.setPattern('^' + timePattern + '$');
+ Q_ASSERT(timeExp.isValid());
+ dateTimeExp.setPattern('^' + datePattern + 'T' + timePattern + '$');
+ Q_ASSERT(dateTimeExp.isValid());
+}
+
+VariantDelegate::VariantDelegate(const QSharedPointer<TypeChecker> &typeChecker,
+ QObject *parent)
+ : QStyledItemDelegate(parent),
+ m_typeChecker(typeChecker)
+{
+}
+
+void VariantDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (index.column() == 2) {
+ QVariant value = index.model()->data(index, Qt::UserRole);
+ if (!isSupportedType(value.userType())) {
+ QStyleOptionViewItem myOption = option;
+ myOption.state &= ~QStyle::State_Enabled;
+ QStyledItemDelegate::paint(painter, myOption, index);
+ return;
+ }
+ }
+
+ QStyledItemDelegate::paint(painter, option, index);
+}
+
+QWidget *VariantDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem & /* option */,
+ const QModelIndex &index) const
+{
+ if (index.column() != 2)
+ return nullptr;
+
+ QVariant originalValue = index.model()->data(index, Qt::UserRole);
+ if (!isSupportedType(originalValue.userType()))
+ return nullptr;
+
+ switch (originalValue.userType()) {
+ case QMetaType::Bool:
+ return new QCheckBox(parent);
+ break;
+ case QMetaType::Int:
+ case QMetaType::LongLong: {
+ auto spinBox = new QSpinBox(parent);
+ spinBox->setRange(-32767, 32767);
+ return spinBox;
+ }
+ case QMetaType::UInt:
+ case QMetaType::ULongLong: {
+ auto spinBox = new QSpinBox(parent);
+ spinBox->setRange(0, 63335);
+ return spinBox;
+ }
+ default:
+ break;
+ }
+
+ QLineEdit *lineEdit = new QLineEdit(parent);
+ lineEdit->setFrame(false);
+
+ QRegularExpression regExp;
+
+ switch (originalValue.userType()) {
+ case QMetaType::Bool:
+ regExp = m_typeChecker->boolExp;
+ break;
+ case QMetaType::QByteArray:
+ regExp = m_typeChecker->byteArrayExp;
+ break;
+ case QMetaType::QChar:
+ regExp = m_typeChecker->charExp;
+ break;
+ case QMetaType::QColor:
+ regExp = m_typeChecker->colorExp;
+ break;
+ case QMetaType::QDate:
+ regExp = m_typeChecker->dateExp;
+ break;
+ case QMetaType::QDateTime:
+ regExp = m_typeChecker->dateTimeExp;
+ break;
+ case QMetaType::Double:
+ regExp = m_typeChecker->doubleExp;
+ break;
+ case QMetaType::Int:
+ case QMetaType::LongLong:
+ regExp = m_typeChecker->signedIntegerExp;
+ break;
+ case QMetaType::QPoint:
+ regExp = m_typeChecker->pointExp;
+ break;
+ case QMetaType::QRect:
+ regExp = m_typeChecker->rectExp;
+ break;
+ case QMetaType::QSize:
+ regExp = m_typeChecker->sizeExp;
+ break;
+ case QMetaType::QTime:
+ regExp = m_typeChecker->timeExp;
+ break;
+ case QMetaType::UInt:
+ case QMetaType::ULongLong:
+ regExp = m_typeChecker->unsignedIntegerExp;
+ break;
+ default:
+ break;
+ }
+
+ if (regExp.isValid()) {
+ QValidator *validator = new QRegularExpressionValidator(regExp, lineEdit);
+ lineEdit->setValidator(validator);
+ }
+
+ return lineEdit;
+}
+
+void VariantDelegate::setEditorData(QWidget *editor,
+ const QModelIndex &index) const
+{
+ QVariant value = index.model()->data(index, Qt::UserRole);
+ if (auto spinBox = qobject_cast<QSpinBox *>(editor)) {
+ const auto userType = value.userType();
+ if (userType == QMetaType::UInt || userType == QMetaType::ULongLong)
+ spinBox->setValue(value.toUInt());
+ else
+ spinBox->setValue(value.toInt());
+ } else if (auto checkBox = qobject_cast<QCheckBox *>(editor)) {
+ checkBox->setChecked(value.toBool());
+ } else if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor)) {
+ if (value.userType() == QMetaType::QByteArray
+ && !isPrintable(value.toByteArray())) {
+ lineEdit->setReadOnly(true);
+ }
+ lineEdit->setText(displayText(value));
+ }
+}
+
+void VariantDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
+ const QModelIndex &index) const
+{
+ const QVariant originalValue = index.model()->data(index, Qt::UserRole);
+ QVariant value;
+
+ if (auto spinBox = qobject_cast<QSpinBox *>(editor)) {
+ value.setValue(spinBox->value());
+ } else if (auto checkBox = qobject_cast<QCheckBox *>(editor)) {
+ value.setValue(checkBox->isChecked());
+ } else if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor)) {
+ if (!lineEdit->isModified())
+ return;
+
+ QString text = lineEdit->text();
+ const QValidator *validator = lineEdit->validator();
+ if (validator) {
+ int pos;
+ if (validator->validate(text, pos) != QValidator::Acceptable)
+ return;
+ }
+
+ QRegularExpressionMatch match;
+
+ switch (originalValue.userType()) {
+ case QMetaType::QChar:
+ value = text.at(0);
+ break;
+ case QMetaType::QColor:
+ match = m_typeChecker->colorExp.match(text);
+ value = QColor(qMin(match.captured(1).toInt(), 255),
+ qMin(match.captured(2).toInt(), 255),
+ qMin(match.captured(3).toInt(), 255),
+ qMin(match.captured(4).toInt(), 255));
+ break;
+ case QMetaType::QDate:
+ {
+ QDate date = QDate::fromString(text, Qt::ISODate);
+ if (!date.isValid())
+ return;
+ value = date;
+ }
+ break;
+ case QMetaType::QDateTime:
+ {
+ QDateTime dateTime = QDateTime::fromString(text, Qt::ISODate);
+ if (!dateTime.isValid())
+ return;
+ value = dateTime;
+ }
+ break;
+ case QMetaType::QPoint:
+ match = m_typeChecker->pointExp.match(text);
+ value = QPoint(match.captured(1).toInt(), match.captured(2).toInt());
+ break;
+ case QMetaType::QRect:
+ match = m_typeChecker->rectExp.match(text);
+ value = QRect(match.captured(1).toInt(), match.captured(2).toInt(),
+ match.captured(3).toInt(), match.captured(4).toInt());
+ break;
+ case QMetaType::QSize:
+ match = m_typeChecker->sizeExp.match(text);
+ value = QSize(match.captured(1).toInt(), match.captured(2).toInt());
+ break;
+ case QMetaType::QStringList:
+ value = text.split(',');
+ break;
+ case QMetaType::QTime:
+ {
+ QTime time = QTime::fromString(text, Qt::ISODate);
+ if (!time.isValid())
+ return;
+ value = time;
+ }
+ break;
+ default:
+ value = text;
+ value.convert(originalValue.metaType());
+ }
+ }
+
+ model->setData(index, displayText(value), Qt::DisplayRole);
+ model->setData(index, value, Qt::UserRole);
+}
+
+bool VariantDelegate::isSupportedType(int type)
+{
+ switch (type) {
+ case QMetaType::Bool:
+ case QMetaType::QByteArray:
+ case QMetaType::QChar:
+ case QMetaType::QColor:
+ case QMetaType::QDate:
+ case QMetaType::QDateTime:
+ case QMetaType::Double:
+ case QMetaType::Int:
+ case QMetaType::LongLong:
+ case QMetaType::QPoint:
+ case QMetaType::QRect:
+ case QMetaType::QSize:
+ case QMetaType::QString:
+ case QMetaType::QStringList:
+ case QMetaType::QTime:
+ case QMetaType::UInt:
+ case QMetaType::ULongLong:
+ return true;
+ default:
+ return false;
+ }
+}
+
+QString VariantDelegate::displayText(const QVariant &value)
+{
+ switch (value.userType()) {
+ case QMetaType::Bool:
+ return value.toBool() ? "✓" : "☐";
+ case QMetaType::QByteArray:
+ return byteArrayToString(value.toByteArray());
+ case QMetaType::QChar:
+ case QMetaType::Double:
+ case QMetaType::Int:
+ case QMetaType::LongLong:
+ case QMetaType::QString:
+ case QMetaType::UInt:
+ case QMetaType::ULongLong:
+ return value.toString();
+ case QMetaType::QColor:
+ {
+ QColor color = qvariant_cast<QColor>(value);
+ return QString("(%1,%2,%3,%4)")
+ .arg(color.red()).arg(color.green())
+ .arg(color.blue()).arg(color.alpha());
+ }
+ case QMetaType::QDate:
+ return value.toDate().toString(Qt::ISODate);
+ case QMetaType::QDateTime:
+ return value.toDateTime().toString(Qt::ISODate);
+ case QMetaType::UnknownType:
+ return "<Invalid>";
+ case QMetaType::QPoint:
+ {
+ QPoint point = value.toPoint();
+ return QString("(%1,%2)").arg(point.x()).arg(point.y());
+ }
+ case QMetaType::QRect:
+ {
+ QRect rect = value.toRect();
+ return QString("(%1,%2,%3,%4)")
+ .arg(rect.x()).arg(rect.y())
+ .arg(rect.width()).arg(rect.height());
+ }
+ case QMetaType::QSize:
+ {
+ QSize size = value.toSize();
+ return QString("(%1,%2)").arg(size.width()).arg(size.height());
+ }
+ case QMetaType::QStringList:
+ return value.toStringList().join(',');
+ case QMetaType::QTime:
+ return value.toTime().toString(Qt::ISODate);
+ default:
+ break;
+ }
+ return QString("<%1>").arg(value.typeName());
+}