Skip to content

Commit ce93338

Browse files
committedJul 8, 2018
Initial work on animation support
- new class to store animation configuration - new class for animation configuration GUI - animation implementation using Qt3D Animation framework
1 parent 059d0e2 commit ce93338

10 files changed

+489
-1
lines changed
 

‎CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ IF(WITH_CORE)
315315
FIND_PACKAGE(Qt53DInput REQUIRED)
316316
FIND_PACKAGE(Qt53DLogic REQUIRED)
317317
FIND_PACKAGE(Qt53DExtras REQUIRED)
318+
FIND_PACKAGE(Qt53DAnimation REQUIRED)
318319
SET(HAVE_3D TRUE) # used in qgsconfig.h
319320
ENDIF (WITH_3D)
320321
INCLUDE("cmake/modules/ECMQt4To5Porting.cmake")

‎src/3d/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ INCLUDE_DIRECTORIES(SYSTEM
135135

136136
ADD_LIBRARY(qgis_3d SHARED ${QGIS_3D_SRCS} ${QGIS_3D_MOC_SRCS} ${QGIS_3D_HDRS} ${QGIS_3D_RCC_SRCS})
137137

138-
TARGET_LINK_LIBRARIES(qgis_3d Qt5::3DCore Qt5::3DRender Qt5::3DInput Qt5::3DLogic Qt5::3DExtras)
138+
TARGET_LINK_LIBRARIES(qgis_3d Qt5::3DCore Qt5::3DRender Qt5::3DInput Qt5::3DLogic Qt5::3DExtras Qt5::3DAnimation)
139139

140140
GENERATE_EXPORT_HEADER(
141141
qgis_3d

‎src/app/3d/qgs3danimationsettings.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/***************************************************************************
2+
qgs3danimationsettings.cpp
3+
--------------------------------------
4+
Date : July 2018
5+
Copyright : (C) 2018 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgs3danimationsettings.h"
17+
18+
#include <Qt3DAnimation/QKeyframeAnimation>
19+
#include <Qt3DAnimation/QAnimationGroup>
20+
21+
Qgs3DAnimationSettings::Qgs3DAnimationSettings()
22+
{
23+
24+
}
25+
26+
float Qgs3DAnimationSettings::duration() const
27+
{
28+
return mKeyframes.isEmpty() ? 0 : mKeyframes.constLast().time;
29+
}
30+
31+
Qt3DAnimation::QKeyframeAnimation *Qgs3DAnimationSettings::createAnimation( Qt3DCore::QNode *parent ) const
32+
{
33+
Qt3DAnimation::QKeyframeAnimation *animation = new Qt3DAnimation::QKeyframeAnimation;
34+
35+
QVector<float> framePositions;
36+
QVector<Qt3DCore::QTransform *> transforms;
37+
for ( const Keyframe &keyframe : mKeyframes )
38+
{
39+
framePositions << keyframe.time;
40+
Qt3DCore::QTransform *t = new Qt3DCore::QTransform( parent );
41+
t->setTranslation( keyframe.position );
42+
t->setRotation( keyframe.rotation );
43+
transforms << t;
44+
}
45+
46+
animation->setKeyframes( transforms );
47+
animation->setFramePositions( framePositions );
48+
49+
//animation->setTarget(cam->transform());
50+
// animation->setEasing(QEasingCurve(QEasingCurve::InOutQuad));
51+
52+
return animation;
53+
}

‎src/app/3d/qgs3danimationsettings.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/***************************************************************************
2+
qgs3danimationsettings.h
3+
--------------------------------------
4+
Date : July 2018
5+
Copyright : (C) 2018 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGS3DANIMATIONSETTINGS_H
17+
#define QGS3DANIMATIONSETTINGS_H
18+
19+
#include <QVector3D>
20+
#include <QQuaternion>
21+
22+
namespace Qt3DCore
23+
{
24+
class QNode;
25+
}
26+
27+
namespace Qt3DAnimation
28+
{
29+
class QKeyframeAnimation;
30+
}
31+
32+
/**
33+
* Class that holds information about animation in 3D view. The animation is defined
34+
* as a series of keyframes
35+
*/
36+
class Qgs3DAnimationSettings
37+
{
38+
public:
39+
Qgs3DAnimationSettings();
40+
41+
//! keyframe definition
42+
struct Keyframe
43+
{
44+
float time; //!< Relative time of the keyframe in seconds
45+
QVector3D position; //!< Position of the camera
46+
QQuaternion rotation; //!< Rotation of the camera
47+
};
48+
49+
typedef QVector<Keyframe> Keyframes;
50+
51+
void setKeyframes( const Keyframes &keyframes ) { mKeyframes = keyframes; }
52+
Keyframes keyFrames() const { return mKeyframes; }
53+
54+
//! Returns duration of the whole animation in seconds
55+
float duration() const;
56+
57+
//! Returns a new object that contains Qt3D animation according to the keyframes
58+
Qt3DAnimation::QKeyframeAnimation *createAnimation( Qt3DCore::QNode *parent ) const;
59+
60+
// TODO: read/write routines
61+
62+
private:
63+
Keyframes mKeyframes;
64+
};
65+
66+
#endif // QGS3DANIMATIONSETTINGS_H

‎src/app/3d/qgs3danimationwidget.cpp

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/***************************************************************************
2+
qgs3danimationwidget.cpp
3+
--------------------------------------
4+
Date : July 2018
5+
Copyright : (C) 2018 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgs3danimationwidget.h"
17+
18+
#include "qgs3danimationsettings.h"
19+
#include "qgsapplication.h"
20+
21+
#include <Qt3DAnimation/QAnimationController>
22+
#include <Qt3DRender/QCamera>
23+
#include <QTimer>
24+
25+
Qgs3DAnimationWidget::Qgs3DAnimationWidget( QWidget *parent )
26+
: QWidget( parent )
27+
{
28+
setupUi( this );
29+
30+
btnAddKeyframe->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
31+
btnRemoveKeyframe->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
32+
btnEditKeyframe->setIcon( QIcon( QgsApplication::iconPath( "symbologyEdit.svg" ) ) );
33+
btnPlayPause->setIcon( QIcon( QgsApplication::iconPath( "mTaskRunning.svg" ) ) );
34+
35+
cboKeyframe->addItem( tr( "<none>" ) );
36+
37+
mAnimationTimer = new QTimer( this );
38+
mAnimationTimer->setInterval( 10 );
39+
connect( mAnimationTimer, &QTimer::timeout, this, &Qgs3DAnimationWidget::onAnimationTimer );
40+
41+
mAnimationController = new Qt3DAnimation::QAnimationController( this );
42+
43+
btnPlayPause->setCheckable( true );
44+
connect( btnPlayPause, &QToolButton::clicked, this, &Qgs3DAnimationWidget::onPlayPause );
45+
46+
connect( sliderTime, &QSlider::valueChanged, this, &Qgs3DAnimationWidget::onSliderValueChanged );
47+
48+
connect( cboKeyframe, qgis::overload<int>::of( &QComboBox::currentIndexChanged ), this, &Qgs3DAnimationWidget::onKeyframeChanged );
49+
}
50+
51+
void Qgs3DAnimationWidget::setCamera( Qt3DRender::QCamera *camera )
52+
{
53+
mCamera = camera;
54+
connect( mCamera, &Qt3DRender::QCamera::viewMatrixChanged, this, &Qgs3DAnimationWidget::onCameraViewMatrixChanged );
55+
}
56+
57+
void Qgs3DAnimationWidget::setAnimation( const Qgs3DAnimationSettings &animSettings )
58+
{
59+
// initialize GUI from the given animation
60+
cboKeyframe->clear();
61+
cboKeyframe->addItem( tr( "<none>" ) );
62+
for ( const Qgs3DAnimationSettings::Keyframe &keyframe : animSettings.keyFrames() )
63+
{
64+
cboKeyframe->addItem( QString( "%1 s" ).arg( keyframe.time ) );
65+
int lastIndex = cboKeyframe->count() - 1;
66+
cboKeyframe->setItemData( lastIndex, keyframe.time, Qt::UserRole + 1 );
67+
cboKeyframe->setItemData( lastIndex, keyframe.position, Qt::UserRole + 2 );
68+
cboKeyframe->setItemData( lastIndex, keyframe.rotation, Qt::UserRole + 3 );
69+
}
70+
71+
initializeController( animSettings );
72+
}
73+
74+
void Qgs3DAnimationWidget::initializeController( const Qgs3DAnimationSettings &animSettings )
75+
{
76+
// set up animation in the controller
77+
Qt3DAnimation::QAnimationGroup *group = new Qt3DAnimation::QAnimationGroup;
78+
Qt3DAnimation::QKeyframeAnimation *animation = animSettings.createAnimation( nullptr ); // TODO: who deletes transforms?
79+
animation->setParent( group );
80+
animation->setTarget( mCamera->transform() );
81+
group->addAnimation( animation ); // does not delete animations later
82+
83+
QVector<Qt3DAnimation::QAnimationGroup *> groups;
84+
groups << group;
85+
mAnimationController->setAnimationGroups( groups ); // does not delete groups later
86+
87+
sliderTime->setMaximum( animSettings.duration() * 100 );
88+
}
89+
90+
Qgs3DAnimationSettings Qgs3DAnimationWidget::animation() const
91+
{
92+
Qgs3DAnimationSettings animSettings;
93+
Qgs3DAnimationSettings::Keyframes keyframes;
94+
qDebug() << "---";
95+
for ( int i = 1; i < cboKeyframe->count(); ++i )
96+
{
97+
Qgs3DAnimationSettings::Keyframe kf;
98+
kf.time = cboKeyframe->itemData( i, Qt::UserRole + 1 ).toFloat();
99+
kf.position = cboKeyframe->itemData( i, Qt::UserRole + 2 ).value<QVector3D>();
100+
kf.rotation = cboKeyframe->itemData( i, Qt::UserRole + 3 ).value<QQuaternion>();
101+
keyframes << kf;
102+
qDebug() << "keyframe" << kf.time << kf.position << kf.rotation;
103+
}
104+
animSettings.setKeyframes( keyframes );
105+
return animSettings;
106+
}
107+
108+
void Qgs3DAnimationWidget::setDefaultAnimation()
109+
{
110+
Qgs3DAnimationSettings animSettings;
111+
Qgs3DAnimationSettings::Keyframes kf;
112+
Qgs3DAnimationSettings::Keyframe f1, f2;
113+
f1.time = 0;
114+
f1.position = mCamera->transform()->translation();
115+
f1.rotation = mCamera->transform()->rotation();
116+
f2.time = 5;
117+
f2.position = f1.position + QVector3D( 0, 0, f1.position.z() / 2 );
118+
f2.rotation = f1.rotation;
119+
kf << f1 << f2;
120+
animSettings.setKeyframes( kf );
121+
122+
setAnimation( animSettings );
123+
}
124+
125+
void Qgs3DAnimationWidget::onPlayPause()
126+
{
127+
if ( mAnimationTimer->isActive() )
128+
{
129+
mAnimationTimer->stop();
130+
cboKeyframe->setEnabled( true );
131+
}
132+
else
133+
{
134+
cboKeyframe->setCurrentIndex( 0 ); // unset active keyframe
135+
cboKeyframe->setEnabled( false );
136+
mAnimationTimer->start();
137+
}
138+
}
139+
140+
void Qgs3DAnimationWidget::onAnimationTimer()
141+
{
142+
float duration = sliderTime->maximum();
143+
sliderTime->setValue( sliderTime->value() >= duration ? 0 : sliderTime->value() + 1 );
144+
}
145+
146+
void Qgs3DAnimationWidget::onSliderValueChanged()
147+
{
148+
mAnimationController->setPosition( sliderTime->value() / 100. );
149+
}
150+
151+
void Qgs3DAnimationWidget::onCameraViewMatrixChanged()
152+
{
153+
if ( cboKeyframe->currentIndex() <= 0 )
154+
return;
155+
156+
// update keyframe's camera position/rotation
157+
int i = cboKeyframe->currentIndex();
158+
cboKeyframe->setItemData( i, mCamera->transform()->translation(), Qt::UserRole + 2 );
159+
cboKeyframe->setItemData( i, mCamera->transform()->rotation(), Qt::UserRole + 3 );
160+
161+
initializeController( animation() );
162+
}
163+
164+
void Qgs3DAnimationWidget::onKeyframeChanged()
165+
{
166+
if ( cboKeyframe->currentIndex() <= 0 )
167+
return;
168+
169+
// jump to the camera view of the keyframe
170+
float time = cboKeyframe->itemData( cboKeyframe->currentIndex(), Qt::UserRole + 1 ).toFloat();
171+
sliderTime->setValue( time * 100 );
172+
}

‎src/app/3d/qgs3danimationwidget.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/***************************************************************************
2+
qgs3danimationwidget.h
3+
--------------------------------------
4+
Date : July 2018
5+
Copyright : (C) 2018 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGS3DANIMATIONWIDGET_H
17+
#define QGS3DANIMATIONWIDGET_H
18+
19+
#include <QWidget>
20+
21+
#include "ui_animation3dwidget.h"
22+
23+
namespace Qt3DRender
24+
{
25+
class QCamera;
26+
}
27+
namespace Qt3DAnimation
28+
{
29+
class QAnimationController;
30+
}
31+
32+
class Qgs3DAnimationSettings;
33+
34+
class Qgs3DAnimationWidget : public QWidget, private Ui::Animation3DWidget
35+
{
36+
Q_OBJECT
37+
public:
38+
explicit Qgs3DAnimationWidget( QWidget *parent = nullptr );
39+
40+
void setCamera( Qt3DRender::QCamera *camera );
41+
42+
void setAnimation( const Qgs3DAnimationSettings &animation );
43+
Qgs3DAnimationSettings animation() const;
44+
45+
void setDefaultAnimation();
46+
47+
signals:
48+
49+
private slots:
50+
void onPlayPause();
51+
void onAnimationTimer();
52+
void onSliderValueChanged();
53+
void onCameraViewMatrixChanged();
54+
void onKeyframeChanged();
55+
56+
private:
57+
void initializeController( const Qgs3DAnimationSettings &animSettings );
58+
59+
private:
60+
QTimer *mAnimationTimer = nullptr;
61+
Qt3DAnimation::QAnimationController *mAnimationController = nullptr;
62+
Qt3DRender::QCamera *mCamera = nullptr; //!< Camera (not owned)
63+
};
64+
65+
#endif // QGS3DANIMATIONWIDGET_H

‎src/app/3d/qgs3dmapcanvasdockwidget.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgscameracontroller.h"
2323
#include "qgsmapcanvas.h"
2424

25+
#include "qgs3danimationsettings.h"
26+
#include "qgs3danimationwidget.h"
2527
#include "qgs3dmapsettings.h"
2628
#include "qgs3dutils.h"
2729

@@ -47,6 +49,9 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
4749
tr( "Save as Image…" ), this, &Qgs3DMapCanvasDockWidget::saveAsImage );
4850
toolBar->addAction( QgsApplication::getThemeIcon( QStringLiteral( "mIconProperties.svg" ) ),
4951
tr( "Configure…" ), this, &Qgs3DMapCanvasDockWidget::configure );
52+
QAction *actionAnim = toolBar->addAction( QIcon( QgsApplication::iconPath( "mTaskRunning.svg" ) ),
53+
tr( "Animations" ), this, &Qgs3DMapCanvasDockWidget::toggleAnimations );
54+
actionAnim->setCheckable( true );
5055

5156
mCanvas = new Qgs3DMapCanvas( contentsWidget );
5257
mCanvas->setMinimumSize( QSize( 200, 200 ) );
@@ -61,6 +66,9 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
6166
mProgressPendingJobs = new QProgressBar( this );
6267
mProgressPendingJobs->setRange( 0, 0 );
6368

69+
mAnimationWidget = new Qgs3DAnimationWidget( this );
70+
mAnimationWidget->setVisible( false );
71+
6472
QHBoxLayout *topLayout = new QHBoxLayout;
6573
topLayout->setContentsMargins( 0, 0, 0, 0 );
6674
topLayout->setSpacing( style()->pixelMetric( QStyle::PM_LayoutHorizontalSpacing ) );
@@ -74,6 +82,7 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
7482
layout->setSpacing( 0 );
7583
layout->addLayout( topLayout );
7684
layout->addWidget( mCanvas );
85+
layout->addWidget( mAnimationWidget );
7786

7887
contentsWidget->setLayout( layout );
7988

@@ -91,11 +100,30 @@ void Qgs3DMapCanvasDockWidget::saveAsImage()
91100
}
92101
}
93102

103+
void Qgs3DMapCanvasDockWidget::toggleAnimations()
104+
{
105+
if ( mAnimationWidget->isVisible() )
106+
{
107+
mAnimationWidget->setVisible( false );
108+
return;
109+
}
110+
111+
mAnimationWidget->setVisible( true );
112+
113+
// create a dummy animation when first started - better to have something than nothing...
114+
if ( mAnimationWidget->animation().duration() == 0 )
115+
{
116+
mAnimationWidget->setDefaultAnimation();
117+
}
118+
}
119+
94120
void Qgs3DMapCanvasDockWidget::setMapSettings( Qgs3DMapSettings *map )
95121
{
96122
mCanvas->setMap( map );
97123

98124
connect( mCanvas->scene(), &Qgs3DMapScene::terrainPendingJobsCountChanged, this, &Qgs3DMapCanvasDockWidget::onTerrainPendingJobsCountChanged );
125+
126+
mAnimationWidget->setCamera( mCanvas->scene()->cameraController()->camera() );
99127
}
100128

101129
void Qgs3DMapCanvasDockWidget::setMainCanvas( QgsMapCanvas *canvas )

‎src/app/3d/qgs3dmapcanvasdockwidget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
class QLabel;
2222
class QProgressBar;
2323

24+
class Qgs3DAnimationWidget;
2425
class Qgs3DMapCanvas;
2526
class Qgs3DMapSettings;
2627
class QgsMapCanvas;
@@ -43,13 +44,15 @@ class Qgs3DMapCanvasDockWidget : public QgsDockWidget
4344
void resetView();
4445
void configure();
4546
void saveAsImage();
47+
void toggleAnimations();
4648

4749
void onMainCanvasLayersChanged();
4850
void onMainCanvasColorChanged();
4951
void onTerrainPendingJobsCountChanged();
5052

5153
private:
5254
Qgs3DMapCanvas *mCanvas = nullptr;
55+
Qgs3DAnimationWidget *mAnimationWidget = nullptr;
5356
QgsMapCanvas *mMainCanvas = nullptr;
5457
QProgressBar *mProgressPendingJobs = nullptr;
5558
QLabel *mLabelPendingJobs = nullptr;

‎src/app/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ SET (QGIS_APP_MOC_HDRS
434434
IF (WITH_3D)
435435
SET(QGIS_APP_SRCS
436436
${QGIS_APP_SRCS}
437+
3d/qgs3danimationsettings.cpp
438+
3d/qgs3danimationwidget.cpp
437439
3d/qgs3dmapcanvas.cpp
438440
3d/qgs3dmapcanvasdockwidget.cpp
439441
3d/qgs3dmapconfigwidget.cpp
@@ -446,6 +448,7 @@ IF (WITH_3D)
446448

447449
SET (QGIS_APP_MOC_HDRS
448450
${QGIS_APP_MOC_HDRS}
451+
3d/qgs3danimationwidget.h
449452
3d/qgs3dmapcanvas.h
450453
3d/qgs3dmapcanvasdockwidget.h
451454
3d/qgs3dmapconfigwidget.h
@@ -760,6 +763,7 @@ ENDIF(ENABLE_MODELTEST)
760763
IF (WITH_3D)
761764
TARGET_LINK_LIBRARIES(qgis_app
762765
qgis_3d
766+
Qt5::3DAnimation
763767
)
764768
ENDIF (WITH_3D)
765769

‎src/ui/3d/animation3dwidget.ui

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>Animation3DWidget</class>
4+
<widget class="QWidget" name="Animation3DWidget">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>1301</width>
10+
<height>138</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Form</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout">
17+
<item>
18+
<layout class="QHBoxLayout" name="horizontalLayout">
19+
<item>
20+
<widget class="QLabel" name="label">
21+
<property name="text">
22+
<string>Keyframe</string>
23+
</property>
24+
</widget>
25+
</item>
26+
<item>
27+
<widget class="QComboBox" name="cboKeyframe"/>
28+
</item>
29+
<item>
30+
<widget class="QToolButton" name="btnAddKeyframe">
31+
<property name="text">
32+
<string> + </string>
33+
</property>
34+
</widget>
35+
</item>
36+
<item>
37+
<widget class="QToolButton" name="btnRemoveKeyframe">
38+
<property name="text">
39+
<string> - </string>
40+
</property>
41+
</widget>
42+
</item>
43+
<item>
44+
<widget class="QToolButton" name="btnEditKeyframe">
45+
<property name="text">
46+
<string>...</string>
47+
</property>
48+
</widget>
49+
</item>
50+
<item>
51+
<spacer name="horizontalSpacer">
52+
<property name="orientation">
53+
<enum>Qt::Horizontal</enum>
54+
</property>
55+
<property name="sizeHint" stdset="0">
56+
<size>
57+
<width>40</width>
58+
<height>20</height>
59+
</size>
60+
</property>
61+
</spacer>
62+
</item>
63+
</layout>
64+
</item>
65+
<item>
66+
<layout class="QHBoxLayout" name="horizontalLayout_2">
67+
<item>
68+
<widget class="QToolButton" name="btnPlayPause">
69+
<property name="text">
70+
<string>&gt;</string>
71+
</property>
72+
</widget>
73+
</item>
74+
<item>
75+
<widget class="QSlider" name="sliderTime">
76+
<property name="maximum">
77+
<number>100</number>
78+
</property>
79+
<property name="orientation">
80+
<enum>Qt::Horizontal</enum>
81+
</property>
82+
<property name="tickPosition">
83+
<enum>QSlider::TicksBothSides</enum>
84+
</property>
85+
<property name="tickInterval">
86+
<number>10</number>
87+
</property>
88+
</widget>
89+
</item>
90+
</layout>
91+
</item>
92+
</layout>
93+
</widget>
94+
<resources/>
95+
<connections/>
96+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.