1
/* This file is part of the KDE project
2
* Copyright (C) 2012 Paul Mendez <paulestebanms@gmail.com>
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Library General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or ( at your option ) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Library General Public License for more details.
14
* You should have received a copy of the GNU Library General Public License
15
* along with this library; see the file COPYING.LIB. If not, write to
16
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
* Boston, MA 02110-1301, USA.
20
#include "KPrAnimationsTimeLineView.h"
23
#include "KPrTimeLineHeader.h"
24
#include "KPrTimeLineView.h"
25
#include "KPrShapeAnimations.h"
26
#include "animations/KPrShapeAnimation.h"
27
#include "tools/animationtool/KPrAnimationGroupProxyModel.h"
33
#include <QVBoxLayout>
34
#include <QHBoxLayout>
35
#include <QAbstractTableModel>
36
#include <QScrollArea>
38
#include <QFontMetrics>
43
//default value for invalid columns and rows index
44
const int INVALID = -1;
46
//Max value for time scale
47
const int SCALE_LIMIT = 1000;
48
const int START_COLUMN = (int)KPrShapeAnimations::ShapeThumbnail;
49
const int END_COLUMN = (int)KPrShapeAnimations::StartTime;
51
KPrAnimationsTimeLineView::KPrAnimationsTimeLineView(QWidget *parent)
55
, m_selectedRow(INVALID)
56
, m_selectedColumn(INVALID)
63
m_view = new KPrTimeLineView(this);
64
m_header = new KPrTimeLineHeader(this);
65
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
66
m_scrollArea = new QScrollArea;
67
m_scrollArea->setBackgroundRole(QPalette::Light);
68
m_scrollArea->setWidget(m_view);
69
m_scrollArea->installEventFilter(m_view);
70
m_scrollArea->installEventFilter(m_header);
71
QVBoxLayout *layout = new QVBoxLayout;
72
layout->addWidget(m_header);
73
layout->addWidget(m_scrollArea);
74
layout->setContentsMargins(0, 0, 0, 0);
75
layout->setSpacing(0);
79
connect(m_view, SIGNAL(clicked(const QModelIndex&)), this, SIGNAL(clicked(const QModelIndex&)));
80
connect(m_view, SIGNAL(timeValuesChanged(QModelIndex)), this, SIGNAL(timeValuesChanged(QModelIndex)));
81
connect(m_view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestContextMenu(QPoint)));
84
void KPrAnimationsTimeLineView::setModel(KPrAnimationGroupProxyModel *model)
87
m_shapeModel = dynamic_cast<KPrShapeAnimations *>(model->sourceModel());
88
Q_ASSERT(m_shapeModel);
90
connect(m_shapeModel, SIGNAL(layoutChanged()), this, SLOT(updateColumnsWidth()));
91
connect(m_shapeModel, SIGNAL(layoutChanged()), this, SLOT(resetData()));
92
connect(m_shapeModel, SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged()));
93
connect(m_shapeModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(update()));
94
//It works only if one item could be selected each time
95
connect(m_shapeModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(notifyTimeValuesChanged(QModelIndex)));
96
connect(m_shapeModel, SIGNAL(timeScaleModified()), this, SLOT(adjustScale()));
102
void KPrAnimationsTimeLineView::resizeEvent(QResizeEvent *event)
104
if (m_scrollArea->horizontalScrollBar()) {
105
connect(m_scrollArea->horizontalScrollBar(), SIGNAL(valueChanged(int)), m_header, SLOT(repaint()));
107
QWidget::resizeEvent(event);
110
KPrAnimationGroupProxyModel *KPrAnimationsTimeLineView::model()
115
KPrShapeAnimations *KPrAnimationsTimeLineView::animationsModel()
120
int KPrAnimationsTimeLineView::widthOfColumn(int column) const
123
case KPrShapeAnimations::ShapeThumbnail:
124
return rowsHeigth() * 3 / 2;
125
case KPrShapeAnimations::AnimationIcon:
126
return rowsHeigth() * 5 / 4;
127
case KPrShapeAnimations::StartTime:
128
return 2 * (rowsHeigth() * 2 / 3 + rowsHeigth() * 10 / 4 + 10);
135
void KPrAnimationsTimeLineView::setSelectedRow(int row)
141
void KPrAnimationsTimeLineView::setSelectedColumn(int column)
143
m_selectedColumn = column;
146
QModelIndex KPrAnimationsTimeLineView::currentIndex()
148
return m_model->index(m_selectedRow, m_selectedColumn, QModelIndex());
151
void KPrAnimationsTimeLineView::setCurrentIndex(const QModelIndex &index)
153
setSelectedRow(index.row());
154
setSelectedColumn(index.column());
155
m_scrollArea->ensureVisible(widthOfColumn(index.row()),
156
rowsHeigth() * index.row());
159
int KPrAnimationsTimeLineView::rowsHeigth() const
164
int KPrAnimationsTimeLineView::totalWidth() const
167
for (int i = 0; i < KPrShapeAnimations::Duration; i++){
168
width = width + widthOfColumn(i);
173
void KPrAnimationsTimeLineView::paintItemBorder(QPainter *painter, const QPalette &palette, const QRect &rect)
175
painter->setPen(QPen(palette.button().color().darker(), 0.33));
176
painter->drawLine(rect.bottomLeft(), rect.bottomRight());
177
painter->drawLine(rect.bottomRight(), rect.topRight());
180
QScrollArea *KPrAnimationsTimeLineView::scrollArea() const
185
int KPrAnimationsTimeLineView::numberOfSteps() const
187
return m_stepsNumber;
190
void KPrAnimationsTimeLineView::setNumberOfSteps(int steps)
192
m_stepsNumber = steps;
195
void KPrAnimationsTimeLineView::incrementScale(int step)
197
if ((numberOfSteps() + step) < SCALE_LIMIT) {
198
setNumberOfSteps(numberOfSteps() + step);
204
void KPrAnimationsTimeLineView::changeStartLimit(const int row)
206
// If user wants a after_previous animation start before previous animation switch to with_previous
207
QModelIndex index = m_model->index(row, 0);
208
if (index.isValid()) {
209
QModelIndex sourceIndex = m_model->mapToSource(index);
210
m_shapeModel->recalculateStart(sourceIndex);
214
void KPrAnimationsTimeLineView::adjustScale()
217
for (int row = 0; row < m_model->rowCount(); ++ row){
218
int startOffSet = calculateStartOffset(row);
219
qreal length = m_model->data(m_model->index(row, KPrShapeAnimations::StartTime)).toInt() +
220
m_model->data(m_model->index(row,KPrShapeAnimations:: Duration)).toInt() + startOffSet;
221
length = length / 1000;
222
if (length > m_maxLength) {
223
m_maxLength = length;
226
const int spacing = 2;
227
// Increment Scale if maxLength is out of range
228
if ((m_maxLength + spacing * stepsScale()) > (numberOfSteps())) {
229
incrementScale(m_maxLength + spacing * stepsScale() - numberOfSteps());
232
// Decrement scale if maxLength is too short
233
if ((m_maxLength - spacing * stepsScale()) < (numberOfSteps())) {
234
incrementScale(m_maxLength + spacing * stepsScale() - numberOfSteps());
239
void KPrAnimationsTimeLineView::notifyTimeValuesChanged(const QModelIndex &index)
241
QModelIndex newIndex = m_model->mapFromSource(index);
242
emit timeValuesChanged(newIndex);
245
void KPrAnimationsTimeLineView::requestContextMenu(QPoint pos)
247
emit customContextMenuRequested(m_view->mapToParent(pos));
250
int KPrAnimationsTimeLineView::stepsScale()
252
// Set step size depending on the scale length
253
int stepsNumber = numberOfSteps();
254
if (stepsNumber < 15)
256
else if (stepsNumber < 50)
258
else if (stepsNumber < 100)
260
else if (stepsNumber < 200)
262
else if (stepsNumber < 300)
264
else if (stepsNumber < 500)
270
qreal KPrAnimationsTimeLineView::maxLineLength() const
275
void KPrAnimationsTimeLineView::setMaxLineLength(qreal length)
278
m_maxLength = length;
282
QColor KPrAnimationsTimeLineView::barColor(int row)
285
KPrShapeAnimation::PresetClass type =
286
static_cast<KPrShapeAnimation::PresetClass>(m_model->data(m_model->index(row, KPrShapeAnimations::AnimationClass)).toInt());
288
case KPrShapeAnimation::Entrance: return Qt::darkGreen;
289
case KPrShapeAnimation::Emphasis: return Qt::blue;
290
case KPrShapeAnimation::Custom: return Qt::gray;
291
case KPrShapeAnimation::Exit: return Qt::red;
292
default: return Qt::gray;
296
int KPrAnimationsTimeLineView::calculateStartOffset(int row) const
298
//calculate real start
299
KPrShapeAnimation::NodeType triggerEvent = static_cast<KPrShapeAnimation::NodeType>(
300
m_model->data(m_model->index(row, KPrShapeAnimations::NodeType)).toInt());
304
if (triggerEvent == KPrShapeAnimation::AfterPrevious) {
305
QModelIndex sourceIndex = m_model->mapToSource(m_model->index(row - 1, KPrShapeAnimations::NodeType));
306
return m_shapeModel->animationEnd(sourceIndex);
308
if (triggerEvent == KPrShapeAnimation::WithPrevious) {
309
QModelIndex sourceIndex = m_model->mapToSource(m_model->index(row - 1, KPrShapeAnimations::NodeType));
310
return m_shapeModel->animationStart(sourceIndex);
315
int KPrAnimationsTimeLineView::rowCount() const
318
return m_model->rowCount();
323
QSize KPrAnimationsTimeLineView::sizeHint() const
325
return QSize(m_view->sizeHint().width(), m_view->sizeHint().height() + m_header->sizeHint().height());
328
int KPrAnimationsTimeLineView::startColumn() const
333
int KPrAnimationsTimeLineView::endColumn() const
338
void KPrAnimationsTimeLineView::update()
341
m_view->updateGeometry();
342
this->updateGeometry();
347
void KPrAnimationsTimeLineView::updateColumnsWidth()
349
for (int row = 0; row < m_model->rowCount(); ++ row){
350
qreal length = m_model->data(m_model->index(row, KPrShapeAnimations::StartTime)).toDouble() +
351
m_model->data(m_model->index(row, KPrShapeAnimations::Duration)).toDouble();
352
if (length > m_maxLength) {
353
m_maxLength = length;
356
m_view->setMinimumSize(m_view->minimumSizeHint());
359
void KPrAnimationsTimeLineView::resetData()
361
m_selectedRow = INVALID;
362
m_selectedColumn = INVALID;