Allow editing keyframe values for other types than double

Currently, the setKeyframeValue dialog only supports a
QDoubleSpinbox as value field. When using this dialog to
edit keyframe values of different type, they need to be
converted which fails for some types (QColor).
With this patch the dialog creates a dedicated control
for each value type. In case the type is not caught it falls
back to the old behavior.

Fixes: QDS-6949
Change-Id: Icbaa2af24f06418fa60648d23269f1a12c08f9de
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Knud Dollereder
2022-08-11 11:23:13 +02:00
parent 725c36e8d0
commit 9610698c66
4 changed files with 129 additions and 112 deletions

View File

@@ -497,7 +497,7 @@ extend_qtc_plugin(QmlDesigner
easingcurve.cpp easingcurve.h
easingcurvedialog.cpp easingcurvedialog.h
preseteditor.cpp preseteditor.h
setframevaluedialog.cpp setframevaluedialog.h setframevaluedialog.ui
setframevaluedialog.cpp setframevaluedialog.h
splineeditor.cpp splineeditor.h
timeline.qrc
timelineabstracttool.cpp timelineabstracttool.h

View File

@@ -24,47 +24,147 @@
****************************************************************************/
#include "setframevaluedialog.h"
#include "ui_setframevaluedialog.h"
#include "curveeditor/detail/colorcontrol.h"
#include <QtGui/qvalidator.h>
#include <QDoubleSpinBox>
#include <QSpinBox>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QMetaType>
#include <QDialogButtonBox>
#include <qnamespace.h>
#include <limits>
namespace QmlDesigner {
SetFrameValueDialog::SetFrameValueDialog(qreal frame, const QVariant &value,
const QString &propertyName, QWidget *parent)
: QDialog(parent)
, ui(new Ui::SetFrameValueDialog)
: QDialog(parent, Qt::Tool)
, m_valueGetter()
, m_valueType(value.metaType())
, m_frameControl(new QSpinBox)
{
ui->setupUi(this);
setWindowTitle(tr("Edit Keyframe"));
setFixedSize(size());
ui->lineEditFrame->setValidator(new QIntValidator(0, 99999, this));
auto dv = new QDoubleValidator(this);
dv->setDecimals(2);
ui->lineEditValue->setValidator(dv);
auto frameLabelString = QString(tr("Frame"));
auto labelWidth = fontMetrics().boundingRect(frameLabelString).width();
if (auto tmp = fontMetrics().boundingRect(propertyName).width(); tmp > labelWidth)
labelWidth = tmp;
QLocale l;
ui->lineEditFrame->setText(l.toString(qRound(frame)));
ui->lineEditValue->setText(l.toString(value.toDouble(), 'f', 2));
ui->labelValue->setText(propertyName);
auto *frameLabel = new QLabel(frameLabelString);
frameLabel->setAlignment(Qt::AlignRight);
frameLabel->setFixedWidth(labelWidth);
auto *valueLabel = new QLabel(propertyName);
valueLabel->setAlignment(Qt::AlignRight);
valueLabel->setFixedWidth(labelWidth);
m_frameControl->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
m_frameControl->setValue(static_cast<int>(frame));
m_frameControl->setAlignment(Qt::AlignRight);
auto* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto* frameRow = new QHBoxLayout;
frameRow->addWidget(frameLabel);
frameRow->addWidget(m_frameControl);
auto* valueRow = new QHBoxLayout;
valueRow->addWidget(valueLabel);
valueRow->addWidget(createValueControl(value));
auto* hbox = new QVBoxLayout;
hbox->addLayout(frameRow);
hbox->addLayout(valueRow);
hbox->addStretch();
hbox->addWidget(buttons);
setLayout(hbox);
}
SetFrameValueDialog::~SetFrameValueDialog()
{
delete ui;
}
{ }
qreal SetFrameValueDialog::frame() const
{
QLocale l;
return l.toDouble(ui->lineEditFrame->text());
return static_cast<qreal>(m_frameControl->value());
}
QVariant SetFrameValueDialog::value() const
{
QLocale l;
return QVariant(l.toDouble(ui->lineEditValue->text()));
if (m_valueGetter)
return m_valueGetter();
return QVariant(m_valueType);
}
QWidget* SetFrameValueDialog::createValueControl(const QVariant& value)
{
m_valueType = value.metaType();
switch (value.metaType().id())
{
case QMetaType::QColor: {
auto* widget = new StyleEditor::ColorControl(value.value<QColor>());
m_valueGetter = [widget]() { return widget->value(); };
return widget;
}
case QMetaType::Bool: {
auto* widget = new QCheckBox;
widget->setChecked(value.toBool());
m_valueGetter = [widget]() { return widget->isChecked(); };
return widget;
}
case QMetaType::Int: {
auto* widget = new QSpinBox;
widget->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toInt());
m_valueGetter = [widget]() { return widget->value(); };
return widget;
}
case QMetaType::UInt: {
auto* widget = new QSpinBox;
widget->setRange(0, std::numeric_limits<int>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toUInt());
m_valueGetter = [widget]() { return static_cast<unsigned int>(widget->value()); };
return widget;
}
case QMetaType::Float: {
auto* widget = new QDoubleSpinBox;
widget->setRange(std::numeric_limits<float>::min(), std::numeric_limits<float>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toFloat());
m_valueGetter = [widget]() { return static_cast<float>(widget->value()); };
return widget;
}
case QMetaType::Double:
[[fallthrough]];
default: {
auto* widget = new QDoubleSpinBox;
widget->setRange(std::numeric_limits<double>::min(), std::numeric_limits<double>::max());
widget->setAlignment(Qt::AlignRight);
widget->setValue(value.toDouble());
m_valueGetter = [widget]() { return widget->value(); };
return widget;
}
}
m_valueGetter = nullptr;
return nullptr;
}
} // namespace QmlDesigner

View File

@@ -27,14 +27,10 @@
#include <QDialog>
QT_FORWARD_DECLARE_CLASS(QLineEdit)
QT_FORWARD_DECLARE_CLASS(QSpinBox)
namespace QmlDesigner {
namespace Ui {
class SetFrameValueDialog;
}
class SetFrameValueDialog : public QDialog
{
Q_OBJECT
@@ -48,7 +44,12 @@ public:
QVariant value() const;
private:
Ui::SetFrameValueDialog *ui;
QWidget* createValueControl(const QVariant& value);
std::function<QVariant(void)> m_valueGetter;
QMetaType m_valueType;
QSpinBox *m_frameControl;
};
} // namespace QmlDesigner

View File

@@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmlDesigner::SetFrameValueDialog</class>
<widget class="QDialog" name="QmlDesigner::SetFrameValueDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>212</width>
<height>148</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelFrame">
<property name="text">
<string>Frame</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditFrame"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditValue"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelValue">
<property name="text">
<string>Value</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QmlDesigner::SetFrameValueDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QmlDesigner::SetFrameValueDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>