QmlDesigner: Inline timelineanimationform.ui

Change-Id: I0f41837cf51c09ca753aae0c68bdc9775f66beeb
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Alessandro Portale
2023-06-13 19:24:25 +02:00
parent ae83cc375b
commit 22d5807799
4 changed files with 132 additions and 408 deletions

View File

@@ -969,7 +969,7 @@ extend_qtc_plugin(QmlDesigner
timeline.qrc timeline.qrc
timelineabstracttool.cpp timelineabstracttool.h timelineabstracttool.cpp timelineabstracttool.h
timelineactions.cpp timelineactions.h timelineactions.cpp timelineactions.h
timelineanimationform.cpp timelineanimationform.h timelineanimationform.ui timelineanimationform.cpp timelineanimationform.h
timelineconstants.h timelineconstants.h
timelinecontext.cpp timelinecontext.h timelinecontext.cpp timelinecontext.h
timelinecontrols.cpp timelinecontrols.h timelinecontrols.cpp timelinecontrols.h

View File

@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "timelineanimationform.h" #include "timelineanimationform.h"
#include "ui_timelineanimationform.h"
#include <abstractview.h> #include <abstractview.h>
#include <bindingproperty.h> #include <bindingproperty.h>
@@ -18,42 +17,118 @@
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/layoutbuilder.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QCheckBox>
#include <QSpinBox>
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
namespace QmlDesigner { namespace QmlDesigner {
TimelineAnimationForm::TimelineAnimationForm(QWidget *parent) TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::TimelineAnimationForm)
{ {
ui->setupUi(this); constexpr int minimumLabelWidth = 160;
constexpr int spinBoxWidth = 80;
connectSpinBox(ui->duration, "duration"); auto mainL = new QLabel(tr("Animation Settings"));
connectSpinBox(ui->loops, "loops"); QFont f = mainL->font();
f.setBold(true);
mainL->setFont(f);
connectSpinBox(ui->startFrame, "from"); auto idL = new QLabel(tr("Animation ID:"));
connectSpinBox(ui->endFrame, "to"); idL->setToolTip(tr("Name for the animation."));
idL->setMinimumWidth(minimumLabelWidth);
m_idLineEdit = new QLineEdit;
connect(ui->loops, &QSpinBox::valueChanged, this, [this] { auto runningL = new QLabel(tr("Running in base state"));
ui->continuous->setChecked(ui->loops->value() == -1); runningL->setToolTip(
tr("Runs the animation automatically when the base state is active."));
m_running = new QCheckBox;
m_running->setEnabled(false);
auto startFrameL = new QLabel(tr("Start frame:"));
startFrameL->setToolTip(tr("First frame of the animation."));
m_startFrame = new QSpinBox;
m_startFrame->setFixedWidth(spinBoxWidth);
m_startFrame->setRange(-100000, 100000);
auto endFrameL = new QLabel(tr("End frame:"));
endFrameL->setToolTip(tr("Last frame of the animation."));
m_endFrame = new QSpinBox;
m_endFrame->setFixedWidth(spinBoxWidth);
m_endFrame->setRange(-100000, 100000);
auto durationL = new QLabel(tr("Duration:"));
durationL->setToolTip(tr("Length of the animation in milliseconds. If you set a shorter duration than the number of frames, frames are left out from the end of the animation."));
m_duration = new QSpinBox;
m_duration->setFixedWidth(spinBoxWidth);
m_duration->setRange(0, 100000);
auto continuousL = new QLabel(tr("Continuous"));
continuousL->setToolTip(tr("Sets the animation to loop indefinitely."));
m_continuous = new QCheckBox;
auto loopsL = new QLabel(tr("Loops:"));
loopsL->setToolTip(tr("Number of times the animation runs before it stops."));
m_loops = new QSpinBox;
m_loops->setFixedWidth(spinBoxWidth);
m_loops->setRange(-1, 1000);
auto pingPongL = new QLabel(tr("Ping pong"));
pingPongL->setToolTip(
tr("Runs the animation backwards to the beginning when it reaches the end."));
m_pingPong = new QCheckBox;
auto transitionToStateL = new QLabel(tr("Finished:"));
transitionToStateL->setToolTip(tr("State to activate when the animation finishes."));
m_transitionToState = new QComboBox;
m_transitionToState->addItem(tr("none"));
auto str = new QWidget;
QSizePolicy sp(QSizePolicy::MinimumExpanding, QSizePolicy::Ignored);
sp.setHorizontalStretch(2);
str->setSizePolicy(sp);
using namespace Layouting;
Grid {
Span(4, mainL), br,
empty(), br,
idL, Span(2, m_idLineEdit), Span(2, Row{ runningL, m_running }), br,
empty(), startFrameL, m_startFrame, endFrameL, m_endFrame, durationL, m_duration, br,
empty(), continuousL, m_continuous, loopsL, m_loops, pingPongL, m_pingPong, str, br,
tr("Transition to state:"), transitionToStateL, m_transitionToState, br,
}.attachTo(this);
connectSpinBox(m_duration, "duration");
connectSpinBox(m_loops, "loops");
connectSpinBox(m_startFrame, "from");
connectSpinBox(m_endFrame, "to");
connect(m_loops, &QSpinBox::valueChanged, this, [this] {
m_continuous->setChecked(m_loops->value() == -1);
}); });
connect(ui->continuous, &QCheckBox::toggled, this, [this](bool checked) { connect(m_continuous, &QCheckBox::toggled, this, [this](bool checked) {
if (checked) { if (checked) {
setProperty("loops", -1); setProperty("loops", -1);
ui->loops->setValue(-1); m_loops->setValue(-1);
} else { } else {
setProperty("loops", 1); setProperty("loops", 1);
ui->loops->setValue(1); m_loops->setValue(1);
} }
}); });
connect(ui->idLineEdit, &QLineEdit::editingFinished, this, [this] { connect(m_idLineEdit, &QLineEdit::editingFinished, this, [this] {
QTC_ASSERT(m_timeline.isValid(), return ); QTC_ASSERT(m_timeline.isValid(), return );
static QString lastString; static QString lastString;
const QString newId = ui->idLineEdit->text(); const QString newId = m_idLineEdit->text();
if (lastString == newId) if (lastString == newId)
return; return;
@@ -79,11 +154,11 @@ TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
if (error) { if (error) {
lastString.clear(); lastString.clear();
ui->idLineEdit->setText(animation().id()); m_idLineEdit->setText(animation().id());
} }
}); });
connect(ui->running, &QCheckBox::clicked, this, [this](bool checked) { connect(m_running, &QCheckBox::clicked, this, [this](bool checked) {
if (checked) { if (checked) {
setProperty("running", true); setProperty("running", true);
} else { } else {
@@ -91,7 +166,7 @@ TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
} }
}); });
connect(ui->pingPong, &QCheckBox::clicked, this, [this](bool checked) { connect(m_pingPong, &QCheckBox::clicked, this, [this](bool checked) {
if (checked) { if (checked) {
setProperty("pingPong", true); setProperty("pingPong", true);
} else { } else {
@@ -99,7 +174,7 @@ TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
} }
}); });
connect(ui->transitionToState, &QComboBox::activated, this, [this](int index) { connect(m_transitionToState, &QComboBox::activated, this, [this](int index) {
if (!m_animation.isValid()) if (!m_animation.isValid())
return; return;
if (!m_animation.view()->rootModelNode().hasId()) if (!m_animation.view()->rootModelNode().hasId())
@@ -116,16 +191,11 @@ TimelineAnimationForm::TimelineAnimationForm(QWidget *parent)
} else { } else {
m_animation.signalHandlerProperty("onFinished") m_animation.signalHandlerProperty("onFinished")
.setSource(rootNode.id() + ".state = \"" .setSource(rootNode.id() + ".state = \""
+ ui->transitionToState->currentText() + "\""); + m_transitionToState->currentText() + "\"");
} }
}); });
} }
TimelineAnimationForm::~TimelineAnimationForm()
{
delete ui;
}
void TimelineAnimationForm::setup(const ModelNode &animation) void TimelineAnimationForm::setup(const ModelNode &animation)
{ {
m_timeline = QmlTimeline(animation.parentProperty().parentModelNode()); m_timeline = QmlTimeline(animation.parentProperty().parentModelNode());
@@ -151,40 +221,40 @@ void TimelineAnimationForm::setupAnimation()
if (m_animation.isValid()) { if (m_animation.isValid()) {
setEnabled(true); setEnabled(true);
ui->idLineEdit->setText(m_animation.id()); m_idLineEdit->setText(m_animation.id());
if (m_animation.hasVariantProperty("duration")) if (m_animation.hasVariantProperty("duration"))
ui->duration->setValue(m_animation.variantProperty("duration").value().toInt()); m_duration->setValue(m_animation.variantProperty("duration").value().toInt());
else else
ui->duration->setValue(0); m_duration->setValue(0);
ui->startFrame->setValue(m_animation.variantProperty("from").value().toInt()); m_startFrame->setValue(m_animation.variantProperty("from").value().toInt());
ui->endFrame->setValue(m_animation.variantProperty("to").value().toInt()); m_endFrame->setValue(m_animation.variantProperty("to").value().toInt());
if (m_animation.hasVariantProperty("loops")) if (m_animation.hasVariantProperty("loops"))
ui->loops->setValue(m_animation.variantProperty("loops").value().toInt()); m_loops->setValue(m_animation.variantProperty("loops").value().toInt());
else else
ui->loops->setValue(0); m_loops->setValue(0);
if (m_animation.hasVariantProperty("running")) if (m_animation.hasVariantProperty("running"))
ui->running->setChecked(m_animation.variantProperty("running").value().toBool()); m_running->setChecked(m_animation.variantProperty("running").value().toBool());
else else
ui->running->setChecked(false); m_running->setChecked(false);
if (m_animation.hasVariantProperty("pingPong")) if (m_animation.hasVariantProperty("pingPong"))
ui->pingPong->setChecked(m_animation.variantProperty("pingPong").value().toBool()); m_pingPong->setChecked(m_animation.variantProperty("pingPong").value().toBool());
else else
ui->pingPong->setChecked(false); m_pingPong->setChecked(false);
ui->continuous->setChecked(ui->loops->value() == -1); m_continuous->setChecked(m_loops->value() == -1);
} }
populateStateComboBox(); populateStateComboBox();
ui->duration->setEnabled(m_animation.isValid()); m_duration->setEnabled(m_animation.isValid());
ui->running->setEnabled(m_animation.isValid()); m_running->setEnabled(m_animation.isValid());
ui->continuous->setEnabled(m_animation.isValid()); m_continuous->setEnabled(m_animation.isValid());
ui->loops->setEnabled(m_animation.isValid()); m_loops->setEnabled(m_animation.isValid());
} }
void TimelineAnimationForm::setProperty(const PropertyName &propertyName, const QVariant &value) void TimelineAnimationForm::setProperty(const PropertyName &propertyName, const QVariant &value)
@@ -207,15 +277,15 @@ void TimelineAnimationForm::connectSpinBox(QSpinBox *spinBox, const PropertyName
void TimelineAnimationForm::populateStateComboBox() void TimelineAnimationForm::populateStateComboBox()
{ {
ui->transitionToState->clear(); m_transitionToState->clear();
ui->transitionToState->addItem(tr("none")); m_transitionToState->addItem(tr("none"));
ui->transitionToState->addItem(tr("Base State")); m_transitionToState->addItem(tr("Base State"));
if (!m_animation.isValid()) if (!m_animation.isValid())
return; return;
QmlObjectNode rootNode = QmlObjectNode(m_animation.view()->rootModelNode()); QmlObjectNode rootNode = QmlObjectNode(m_animation.view()->rootModelNode());
if (rootNode.isValid() && rootNode.modelNode().hasId()) { if (rootNode.isValid() && rootNode.modelNode().hasId()) {
for (const QmlModelState &state : QmlVisualNode(rootNode).states().allStates()) { for (const QmlModelState &state : QmlVisualNode(rootNode).states().allStates()) {
ui->transitionToState m_transitionToState
->addItem(state.modelNode().variantProperty("name").value().toString(), ->addItem(state.modelNode().variantProperty("name").value().toString(),
QVariant::fromValue<ModelNode>(state.modelNode())); QVariant::fromValue<ModelNode>(state.modelNode()));
} }
@@ -227,9 +297,9 @@ void TimelineAnimationForm::populateStateComboBox()
name.chop(1); name.chop(1);
name.remove(0, 1); name.remove(0, 1);
if (name.isEmpty()) if (name.isEmpty())
ui->transitionToState->setCurrentIndex(1); m_transitionToState->setCurrentIndex(1);
else else
ui->transitionToState->setCurrentText(name); m_transitionToState->setCurrentText(name);
} }
} }
} }

View File

@@ -7,21 +7,21 @@
#include <QWidget> #include <QWidget>
QT_FORWARD_DECLARE_CLASS(QSpinBox) QT_BEGIN_NAMESPACE
class QCheckBox;
class QComboBox;
class QLineEdit;
class QSpinBox;
QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
namespace Ui {
class TimelineAnimationForm;
}
class TimelineAnimationForm : public QWidget class TimelineAnimationForm : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit TimelineAnimationForm(QWidget *parent); explicit TimelineAnimationForm(QWidget *parent);
~TimelineAnimationForm() override;
void setup(const ModelNode &animation); void setup(const ModelNode &animation);
ModelNode animation() const; ModelNode animation() const;
@@ -33,7 +33,15 @@ private:
void connectSpinBox(QSpinBox *spinBox, const PropertyName &propertyName); void connectSpinBox(QSpinBox *spinBox, const PropertyName &propertyName);
void populateStateComboBox(); void populateStateComboBox();
Ui::TimelineAnimationForm *ui; QLineEdit *m_idLineEdit;
QCheckBox *m_running;
QSpinBox *m_startFrame;
QSpinBox *m_endFrame;
QSpinBox *m_duration;
QCheckBox *m_continuous;
QSpinBox *m_loops;
QCheckBox *m_pingPong;
QComboBox *m_transitionToState;
QmlTimeline m_timeline; QmlTimeline m_timeline;
ModelNode m_animation; ModelNode m_animation;

View File

@@ -1,354 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmlDesigner::TimelineAnimationForm</class>
<widget class="QWidget" name="QmlDesigner::TimelineAnimationForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>641</width>
<height>176</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="3">
<widget class="QLabel" name="label_16">
<property name="toolTip">
<string>Number of times the animation runs before it stops.</string>
</property>
<property name="text">
<string>Loops:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="4" colspan="2">
<widget class="QSpinBox" name="loops">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_15">
<property name="toolTip">
<string>Sets the animation to loop indefinitely.</string>
</property>
<property name="text">
<string>Continuous</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="continuous">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QComboBox" name="transitionToState">
<item>
<property name="text">
<string>none</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>160</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Animation Settings</string>
</property>
</widget>
</item>
<item row="1" column="9">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>213</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Name for the animation.</string>
</property>
<property name="text">
<string>Animation ID:</string>
</property>
</widget>
</item>
<item row="3" column="9">
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>213</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="8">
<widget class="QSpinBox" name="duration">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_23">
<property name="toolTip">
<string>State to activate when the animation finishes.</string>
</property>
<property name="text">
<string>Finished:</string>
</property>
</widget>
</item>
<item row="4" column="7">
<widget class="QLabel" name="label_17">
<property name="toolTip">
<string>Runs the animation backwards to the beginning when it reaches the end.</string>
</property>
<property name="text">
<string>Ping pong</string>
</property>
</widget>
</item>
<item row="4" column="8">
<widget class="QCheckBox" name="pingPong">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="9">
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>213</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_20">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Transition to state:</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLineEdit" name="idLineEdit">
<property name="text">
<string>animation02</string>
</property>
</widget>
</item>
<item row="2" column="3" colspan="2">
<widget class="QLabel" name="label_18">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Runs the animation automatically when the base state is active.</string>
</property>
<property name="text">
<string>Running in base state</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="startFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_12">
<property name="toolTip">
<string>First frame of the animation.</string>
</property>
<property name="text">
<string>Start frame:</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QCheckBox" name="running">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="9">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>213</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="7">
<widget class="QLabel" name="label_14">
<property name="toolTip">
<string>Length of the animation in milliseconds. If you set a shorter duration than the number of frames, frames are left out from the end of the animation.</string>
</property>
<property name="text">
<string>Duration:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="label_13">
<property name="toolTip">
<string>Last frame of the animation.</string>
</property>
<property name="text">
<string>End frame:</string>
</property>
</widget>
</item>
<item row="3" column="4" colspan="3">
<widget class="QSpinBox" name="endFrame">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>