Krita Source Code Documentation
Loading...
Searching...
No Matches
KisTimeBasedItemModel Class Referenceabstract

#include <KisTimeBasedItemModel.h>

+ Inheritance diagram for KisTimeBasedItemModel:

Classes

struct  Private
 

Public Types

enum  ItemDataRole {
  ActiveFrameRole = Qt::UserRole + 101 , ScrubToRole , CloneOfActiveFrame , CloneCount ,
  FrameExistsRole , SpecialKeyframeExists , FrameCachedRole , FrameEditableRole ,
  FramesPerSecondRole , FrameHasContent , WithinClipRange , UserRole
}
 

Public Member Functions

int columnCount (const QModelIndex &parent=QModelIndex()) const override
 
int currentTime () const
 
QVariant data (const QModelIndex &index, int role) const override
 
KisDocumentdocument () const
 
QVariant headerData (int section, Qt::Orientation orientation, int role) const override
 
bool isFrameCached (const int frame)
 
bool isPlaybackActive () const
 
bool isPlaybackPaused () const
 
bool isScrubbing ()
 
 KisTimeBasedItemModel (QObject *parent)
 
bool mirrorFrames (QModelIndexList indexes)
 
bool removeFrames (const QModelIndexList &indexes)
 
bool removeFramesAndOffset (QModelIndexList indicesToRemove)
 
void scrubHorizontalHeaderUpdate (int activeHeader)
 
void setAnimationPlayer (KisCanvasAnimationState *player)
 
bool setData (const QModelIndex &index, const QVariant &value, int role) override
 
void setDocument (class KisDocument *document)
 
void setFrameCache (KisAnimationFrameCacheSP cache)
 
bool setHeaderData (int section, Qt::Orientation orientation, const QVariant &value, int role) override
 
void setImage (KisImageWSP image)
 
void setLastVisibleFrame (int time)
 
void setPlaybackRange (const KisTimeSpan &range)
 
void setScrubState (bool active)
 
void stopPlayback () const
 
 ~KisTimeBasedItemModel () override
 

Protected Slots

void slotCurrentTimeChanged (int time)
 

Protected Member Functions

virtual KisKeyframeChannelchannelByID (QModelIndex index, const QString &id) const =0
 
virtual QMap< QString, KisKeyframeChannel * > channelsAt (QModelIndex index) const =0
 
int cloneCount (const QModelIndex &index) const
 
bool cloneOfActiveFrame (const QModelIndex &index) const
 
KUndo2CommandcreateOffsetFramesCommand (QModelIndexList srcIndexes, const QPoint &offset, bool copyFrames, bool moveEmptyFrames, KUndo2Command *parentCommand=0)
 
KisImageWSP image () const
 
virtual KisNodeSP nodeAt (QModelIndex index) const =0
 

Private Slots

void slotCacheChanged ()
 
void slotFramerateChanged ()
 
void slotPlaybackFrameChanged ()
 
void slotPlaybackRangeChanged ()
 
void slotPlaybackStateChanged (PlaybackState state)
 

Private Attributes

const QScopedPointer< Privatem_d
 

Detailed Description

Definition at line 22 of file KisTimeBasedItemModel.h.

Member Enumeration Documentation

◆ ItemDataRole

Enumerator
ActiveFrameRole 
ScrubToRole 
CloneOfActiveFrame 
CloneCount 
FrameExistsRole 
SpecialKeyframeExists 
FrameCachedRole 
FrameEditableRole 
FramesPerSecondRole 
FrameHasContent 
WithinClipRange 
UserRole 

Definition at line 63 of file KisTimeBasedItemModel.h.

Constructor & Destructor Documentation

◆ KisTimeBasedItemModel()

KisTimeBasedItemModel::KisTimeBasedItemModel ( QObject * parent)

Definition at line 93 of file KisTimeBasedItemModel.cpp.

94 : QAbstractTableModel(parent)
95 , m_d(new Private())
96{
97 KisConfig cfg(true);
98
99 using namespace std::placeholders;
100
101 std::function<void (int)> scrubHorizHeaderUpdateCallback(
103
104 m_d->scrubHeaderUpdateCompressor.reset(
105 new KisSignalCompressorWithParam<int>(100, scrubHorizHeaderUpdateCallback, KisSignalCompressor::FIRST_ACTIVE));
106}
void scrubHorizontalHeaderUpdate(int activeHeader)
const QScopedPointer< Private > m_d
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)

References KisSignalCompressor::FIRST_ACTIVE, m_d, scrubHorizontalHeaderUpdate(), and void().

◆ ~KisTimeBasedItemModel()

KisTimeBasedItemModel::~KisTimeBasedItemModel ( )
override

Definition at line 108 of file KisTimeBasedItemModel.cpp.

109{}

Member Function Documentation

◆ channelByID()

virtual KisKeyframeChannel * KisTimeBasedItemModel::channelByID ( QModelIndex index,
const QString & id ) const
protectedpure virtual

◆ channelsAt()

virtual QMap< QString, KisKeyframeChannel * > KisTimeBasedItemModel::channelsAt ( QModelIndex index) const
protectedpure virtual

◆ cloneCount()

int KisTimeBasedItemModel::cloneCount ( const QModelIndex & index) const
protected

Definition at line 649 of file KisTimeBasedItemModel.cpp.

649 {
651
652 if (!rasterChan) {
653 return 0;
654 }
655 return rasterChan->clonesOf(index.column()).count();
656}
static const KoID Raster
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
virtual KisKeyframeChannel * channelByID(QModelIndex index, const QString &id) const =0

References channelByID(), KisRasterKeyframeChannel::clonesOf(), and KisKeyframeChannel::Raster.

◆ cloneOfActiveFrame()

bool KisTimeBasedItemModel::cloneOfActiveFrame ( const QModelIndex & index) const
protected

Definition at line 641 of file KisTimeBasedItemModel.cpp.

641 {
643 if (!rasterChan) return false;
644
645 const int activeKeyframeTime = rasterChan->activeKeyframeTime(m_d->activeFrameIndex);
646 return rasterChan->areClones(activeKeyframeTime, index.column());
647}
int activeKeyframeTime(int time) const
Get the time of the active keyframe. Useful for snapping any time to that of the most recent keyframe...
bool areClones(int timeA, int timeB)

References KisKeyframeChannel::activeKeyframeTime(), KisRasterKeyframeChannel::areClones(), channelByID(), m_d, and KisKeyframeChannel::Raster.

◆ columnCount()

int KisTimeBasedItemModel::columnCount ( const QModelIndex & parent = QModelIndex()) const
override

Definition at line 213 of file KisTimeBasedItemModel.cpp.

214{
215 Q_UNUSED(parent);
216 return m_d->numFramesOverride;
217}

References m_d.

◆ createOffsetFramesCommand()

KUndo2Command * KisTimeBasedItemModel::createOffsetFramesCommand ( QModelIndexList srcIndexes,
const QPoint & offset,
bool copyFrames,
bool moveEmptyFrames,
KUndo2Command * parentCommand = 0 )
protected

Definition at line 372 of file KisTimeBasedItemModel.cpp.

377{
378 if (srcIndexes.isEmpty()) return 0;
379 if (offset.isNull()) return 0;
380
381 KisAnimUtils::sortPointsForSafeMove(&srcIndexes, offset);
382
383 KisAnimUtils::FrameItemList srcFrameItems;
384 KisAnimUtils::FrameItemList dstFrameItems;
385
386 Q_FOREACH (const QModelIndex &srcIndex, srcIndexes) {
387 QModelIndex dstIndex = index(
388 srcIndex.row() + offset.y(),
389 srcIndex.column() + offset.x());
390
391 KisNodeSP srcNode = nodeAt(srcIndex);
392 KisNodeSP dstNode = nodeAt(dstIndex);
393 if (!srcNode || !dstNode) return 0;
394
395 Q_FOREACH(KisKeyframeChannel *channel, channelsAt(srcIndex)) {
396 if (moveEmptyFrames || channel->keyframeAt(srcIndex.column())) {
397 srcFrameItems << KisAnimUtils::FrameItem(srcNode, channel->id(), srcIndex.column());
398 dstFrameItems << KisAnimUtils::FrameItem(dstNode, channel->id(), dstIndex.column());
399 }
400 }
401 }
402
403 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(srcFrameItems.size() == dstFrameItems.size(), 0);
404 if (srcFrameItems.isEmpty()) return 0;
405
406 return
408 dstFrameItems,
409 copyFrames,
410 moveEmptyFrames,
411 parentCommand);
412}
KisKeyframeChannel stores and manages KisKeyframes. Maps units of time to virtual keyframe values....
KisKeyframeSP keyframeAt(int time) const
Get a keyframe at specified time. Used primarily when the value of a given keyframe is needed.
virtual KisNodeSP nodeAt(QModelIndex index) const =0
virtual QMap< QString, KisKeyframeChannel * > channelsAt(QModelIndex index) const =0
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
void sortPointsForSafeMove(QModelIndexList *points, const QPoint &offset)
KUndo2Command * createMoveKeyframesCommand(const FrameItemList &srcFrames, const FrameItemList &dstFrames, bool copy, bool moveEmpty, KUndo2Command *parentCommand)

References channelsAt(), KisAnimUtils::createMoveKeyframesCommand(), KisKeyframeChannel::id(), KisKeyframeChannel::keyframeAt(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, nodeAt(), and KisAnimUtils::sortPointsForSafeMove().

◆ currentTime()

int KisTimeBasedItemModel::currentTime ( ) const

Definition at line 636 of file KisTimeBasedItemModel.cpp.

637{
638 return m_d->image->animationInterface()->currentUITime();
639}

References m_d.

◆ data()

QVariant KisTimeBasedItemModel::data ( const QModelIndex & index,
int role ) const
override

Definition at line 219 of file KisTimeBasedItemModel.cpp.

220{
221 switch (role) {
222 case ActiveFrameRole: {
223 return index.column() == m_d->activeFrameIndex;
224 }
225 case CloneOfActiveFrame: {
226 return cloneOfActiveFrame(index);
227 }
228 case CloneCount: {
229 return cloneCount(index);
230 }
231 case WithinClipRange:
232 return m_d->withinClipRange(index.column());
233 }
234
235 return QVariant();
236}
bool cloneOfActiveFrame(const QModelIndex &index) const
int cloneCount(const QModelIndex &index) const

References ActiveFrameRole, CloneCount, cloneCount(), CloneOfActiveFrame, cloneOfActiveFrame(), m_d, and WithinClipRange.

◆ document()

KisDocument * KisTimeBasedItemModel::document ( ) const

Definition at line 188 of file KisTimeBasedItemModel.cpp.

189{
190 return m_d->document;
191}

References m_d.

◆ headerData()

QVariant KisTimeBasedItemModel::headerData ( int section,
Qt::Orientation orientation,
int role ) const
override

Definition at line 254 of file KisTimeBasedItemModel.cpp.

255{
256 if (orientation == Qt::Horizontal) {
257 switch (role) {
258 case ActiveFrameRole:
259 return section == m_d->activeFrameIndex;
260 case FrameCachedRole:
261 return m_d->cachedFrames.size() > section ? m_d->cachedFrames[section] : false;
263 return m_d->framesPerSecond();
264 case WithinClipRange:
265 return m_d->withinClipRange(section);
266 }
267 }
268
269 return QVariant();
270}

References ActiveFrameRole, FrameCachedRole, FramesPerSecondRole, m_d, and WithinClipRange.

◆ image()

KisImageWSP KisTimeBasedItemModel::image ( ) const
protected

Definition at line 658 of file KisTimeBasedItemModel.cpp.

659{
660 return m_d->image;
661}

References m_d.

◆ isFrameCached()

bool KisTimeBasedItemModel::isFrameCached ( const int frame)

Definition at line 154 of file KisTimeBasedItemModel.cpp.

155{
156 return m_d->framesCache && m_d->framesCache->frameStatus(frame) == KisAnimationFrameCache::Cached;
157}

References KisAnimationFrameCache::Cached, and m_d.

◆ isPlaybackActive()

bool KisTimeBasedItemModel::isPlaybackActive ( ) const

Definition at line 622 of file KisTimeBasedItemModel.cpp.

623{
624 return m_d->animationPlayer && m_d->animationPlayer->playbackState() == PlaybackState::PLAYING;
625}

References m_d, and PLAYING.

◆ isPlaybackPaused()

bool KisTimeBasedItemModel::isPlaybackPaused ( ) const

Definition at line 627 of file KisTimeBasedItemModel.cpp.

628{
629 return m_d->animationPlayer && m_d->animationPlayer->playbackState() == PlaybackState::PAUSED;
630}

References m_d, and PAUSED.

◆ isScrubbing()

bool KisTimeBasedItemModel::isScrubbing ( )

Definition at line 554 of file KisTimeBasedItemModel.cpp.

555{
556 return m_d->scrubInProgress;
557}

References m_d.

◆ mirrorFrames()

bool KisTimeBasedItemModel::mirrorFrames ( QModelIndexList indexes)

Definition at line 453 of file KisTimeBasedItemModel.cpp.

454{
455 QScopedPointer<KUndo2Command> parentCommand(new KUndo2Command(kundo2_i18n("Mirror Frames")));
456
457 {
458 KisImageBarrierLock locker(m_d->image);
459
460 QMap<int, QModelIndexList> rowsList;
461
462 Q_FOREACH (const QModelIndex &index, indexes) {
463 rowsList[index.row()].append(index);
464 }
465
466
467 Q_FOREACH (int row, rowsList.keys()) {
468 QModelIndexList &list = rowsList[row];
469
470 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!list.isEmpty(), false);
471
472 std::sort(list.begin(), list.end(),
473 [] (const QModelIndex &lhs, const QModelIndex &rhs) {
474 return lhs.column() < rhs.column();
475 });
476
477 auto srcIt = list.begin();
478 auto dstIt = list.end();
479
480 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(srcIt != dstIt, false);
481 --dstIt;
482
483 QList<KisKeyframeChannel*> channels = channelsAt(*srcIt).values();
484
485 while (srcIt < dstIt) {
486 Q_FOREACH (KisKeyframeChannel *channel, channels) {
487 if (channel->keyframeAt(srcIt->column()) && channel->keyframeAt(dstIt->column())) {
488
489 channel->swapKeyframes(srcIt->column(),
490 dstIt->column(),
491 parentCommand.data());
492 }
493 else if (channel->keyframeAt(srcIt->column())) {
494
495 channel->insertKeyframe(dstIt->column(),
496 channel->keyframeAt(srcIt->column()),
497 parentCommand.data());
498
499 channel->removeKeyframe(srcIt->column(),
500 parentCommand.data());
501 }
502 else if (channel->keyframeAt(dstIt->column())) {
503
504 channel->insertKeyframe(srcIt->column(),
505 channel->keyframeAt(dstIt->column()),
506 parentCommand.data());
507
508 channel->removeKeyframe(dstIt->column(),
509 parentCommand.data());
510 }
511 }
512
513 srcIt++;
514 dstIt--;
515 }
516 }
517 }
518
520 parentCommand.take(),
523 return true;
524}
virtual void insertKeyframe(int time, KisKeyframeSP keyframe, KUndo2Command *parentUndoCmd=nullptr)
Insert an existing keyframe into the channel at the specified time.
virtual void removeKeyframe(int time, KUndo2Command *parentUndoCmd=nullptr)
Remove a keyframe from the channel at the specified time.
static void swapKeyframes(KisKeyframeChannel *channelA, int timeA, KisKeyframeChannel *channelB, int timeB, KUndo2Command *parentUndoCmd=nullptr)
Swap two keyframes across channel(s) at the specified times.
static void runSingleCommandStroke(KisImageSP image, KUndo2Command *cmd, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
runSingleCommandStroke creates a stroke and runs cmd in it. The text() field of cmd is used as a titl...
KUndo2MagicString kundo2_i18n(const char *text)

References KisStrokeJobData::BARRIER, channelsAt(), KisStrokeJobData::EXCLUSIVE, KisKeyframeChannel::insertKeyframe(), KisKeyframeChannel::keyframeAt(), KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, kundo2_i18n(), m_d, KisKeyframeChannel::removeKeyframe(), KisProcessingApplicator::runSingleCommandStroke(), and KisKeyframeChannel::swapKeyframes().

◆ nodeAt()

virtual KisNodeSP KisTimeBasedItemModel::nodeAt ( QModelIndex index) const
protectedpure virtual

◆ removeFrames()

bool KisTimeBasedItemModel::removeFrames ( const QModelIndexList & indexes)

Definition at line 348 of file KisTimeBasedItemModel.cpp.

349{
351
352 {
353 KisImageBarrierLock locker(m_d->image);
354
355 Q_FOREACH (const QModelIndex &index, indexes) {
356 int time = index.column();
357 Q_FOREACH(KisKeyframeChannel *channel, channelsAt(index)) {
358 if (channel->keyframeAt(time)) {
359 frameItems << KisAnimUtils::FrameItem(channel->node(), channel->id(), index.column());
360 }
361 }
362 }
363 }
364
365 if (frameItems.isEmpty()) return false;
366
367 KisAnimUtils::removeKeyframes(m_d->image, frameItems);
368
369 return true;
370}
void removeKeyframes(KisImageSP image, const FrameItemList &frames)

References channelsAt(), KisKeyframeChannel::id(), KisKeyframeChannel::keyframeAt(), m_d, KisKeyframeChannel::node(), and KisAnimUtils::removeKeyframes().

◆ removeFramesAndOffset()

bool KisTimeBasedItemModel::removeFramesAndOffset ( QModelIndexList indicesToRemove)

Definition at line 414 of file KisTimeBasedItemModel.cpp.

415{
416 if (indicesToRemove.isEmpty()) return true;
417
418 std::sort(indicesToRemove.begin(), indicesToRemove.end(),
419 [] (const QModelIndex &lhs, const QModelIndex &rhs) {
420 return lhs.column() > rhs.column();
421 });
422
423 const int minColumn = indicesToRemove.last().column();
424
425 KUndo2Command *parentCommand = new KUndo2Command(kundo2_i18np("Remove frame and shift", "Remove %1 frames and shift", indicesToRemove.size()));
426
427 {
428 KisImageBarrierLock locker(m_d->image);
429
430 Q_FOREACH (const QModelIndex &index, indicesToRemove) {
431 QModelIndexList indicesToOffset;
432 for (int column = index.column() + 1; column < columnCount(); column++) {
433 indicesToOffset << this->index(index.row(), column);
434 }
435 createOffsetFramesCommand(indicesToOffset, QPoint(-1, 0), false, true, parentCommand);
436 }
437
438 const int oldTime = m_d->image->animationInterface()->currentUITime();
439 const int newTime = minColumn;
440
441 new KisSwitchCurrentTimeCommand(m_d->image->animationInterface(),
442 oldTime,
443 newTime,
444 parentCommand);
445 }
446
450 return true;
451}
KUndo2Command * createOffsetFramesCommand(QModelIndexList srcIndexes, const QPoint &offset, bool copyFrames, bool moveEmptyFrames, KUndo2Command *parentCommand=0)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1)

References KisStrokeJobData::BARRIER, columnCount(), createOffsetFramesCommand(), KisStrokeJobData::EXCLUSIVE, kundo2_i18np(), m_d, and KisProcessingApplicator::runSingleCommandStroke().

◆ scrubHorizontalHeaderUpdate()

void KisTimeBasedItemModel::scrubHorizontalHeaderUpdate ( int activeHeader)

Definition at line 341 of file KisTimeBasedItemModel.cpp.

342{
343 Q_EMIT headerDataChanged (Qt::Horizontal, m_d->scrubHeaderMin, m_d->scrubHeaderMax);
344 m_d->scrubHeaderMin = activeColumn;
345 m_d->scrubHeaderMax = activeColumn;
346}

References m_d.

◆ setAnimationPlayer()

void KisTimeBasedItemModel::setAnimationPlayer ( KisCanvasAnimationState * player)

Definition at line 159 of file KisTimeBasedItemModel.cpp.

160{
161 if (m_d->animationPlayer == player) return;
162
163 if (m_d->animationPlayer) {
164 m_d->animationPlayer->disconnect(this);
165 }
166
167 m_d->animationPlayer = player;
168
169 if (m_d->animationPlayer) {
170 connect(m_d->animationPlayer, SIGNAL(sigPlaybackStateChanged(PlaybackState)), SLOT(slotPlaybackStateChanged(PlaybackState)));
171 connect(m_d->animationPlayer, SIGNAL(sigFrameChanged()), SLOT(slotPlaybackFrameChanged()));
172
173 const int frame = player ? player->displayProxy()->activeFrame() : m_d->image->animationInterface()->currentUITime();
174 setHeaderData(frame, Qt::Horizontal, true, ActiveFrameRole);
175
176 // only prioritize the cache, no seek operation to prevent audio from playing
177 setHeaderData(frame, Qt::Horizontal, QVariant(int(SEEK_NONE)), ScrubToRole);
178 }
179}
@ SEEK_NONE
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
class KisFrameDisplayProxy * displayProxy()
int activeFrame() const
Gets the active frame, the frame that is intended to be shown. This should always reflect the actual ...
void slotPlaybackStateChanged(PlaybackState state)
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) override

References KisFrameDisplayProxy::activeFrame(), ActiveFrameRole, connect(), KisCanvasAnimationState::displayProxy(), m_d, ScrubToRole, SEEK_NONE, setHeaderData(), slotPlaybackFrameChanged(), and slotPlaybackStateChanged().

◆ setData()

bool KisTimeBasedItemModel::setData ( const QModelIndex & index,
const QVariant & value,
int role )
override

Definition at line 238 of file KisTimeBasedItemModel.cpp.

239{
240 if (!index.isValid()) return false;
241
242 switch (role) {
243 case ActiveFrameRole:
244 setHeaderData(index.column(), Qt::Horizontal, value, role);
245 break;
246 case ScrubToRole:
247 setHeaderData(index.column(), Qt::Horizontal, value, role);
248 break;
249 }
250
251 return false;
252}
float value(const T *src, size_t ch)

References ActiveFrameRole, ScrubToRole, setHeaderData(), and value().

◆ setDocument()

void KisTimeBasedItemModel::setDocument ( class KisDocument * document)

Definition at line 181 of file KisTimeBasedItemModel.cpp.

182{
183 if (m_d->document == document) return;
184
185 m_d->document = document;
186}
KisDocument * document() const

References document(), and m_d.

◆ setFrameCache()

void KisTimeBasedItemModel::setFrameCache ( KisAnimationFrameCacheSP cache)

Definition at line 139 of file KisTimeBasedItemModel.cpp.

140{
141 if (KisAnimationFrameCacheSP(m_d->framesCache) == cache) return;
142
143 if (m_d->framesCache) {
144 m_d->framesCache->disconnect(this);
145 }
146
147 m_d->framesCache = cache;
148
149 if (m_d->framesCache) {
150 connect(m_d->framesCache, SIGNAL(changed()), SLOT(slotCacheChanged()));
151 }
152}
KisSharedPtr< KisAnimationFrameCache > KisAnimationFrameCacheSP
Definition kis_types.h:185

References connect(), m_d, and slotCacheChanged().

◆ setHeaderData()

bool KisTimeBasedItemModel::setHeaderData ( int section,
Qt::Orientation orientation,
const QVariant & value,
int role )
override

Optimization Hack Alert:

ideally, we should Q_EMIT all four signals, but... The point is this code is used in a tight loop during playback, so it should run as fast as possible. To tell the story short, commenting out these three lines makes playback run 15% faster ;)

Definition at line 272 of file KisTimeBasedItemModel.cpp.

273{
274 auto prioritizeCache = [this](int frame){
275 if (m_d->image) {
276 if(!isFrameCached(frame)) {
278 }
279 }
280 };
281
282
283 if (orientation == Qt::Horizontal) {
284 switch (role) {
285 case ActiveFrameRole:
286 if (value.toBool() &&
287 section != m_d->activeFrameIndex) {
288
289 int prevFrame = m_d->activeFrameIndex;
290 m_d->activeFrameIndex = section;
291
302 if (m_d->scrubInProgress) {
303 Q_EMIT dataChanged(this->index(0, m_d->activeFrameIndex), this->index(rowCount() - 1, m_d->activeFrameIndex));
304
305 /*
306 * In order to try to correct rendering issues while preserving performance, we will
307 * defer updates just long enough that visual artifacts aren't majorly noticeable.
308 * By using a signal compressor, we're going to update the range of columns between
309 * min / max. That min max is reset every time the update occurs. This should fix
310 * rendering issues to a configurable framerate.
311 */
312 m_d->scrubHeaderMin = qMin(m_d->activeFrameIndex, m_d->scrubHeaderMin);
313 m_d->scrubHeaderMax = qMax(m_d->activeFrameIndex, m_d->scrubHeaderMax);
314 m_d->scrubHeaderUpdateCompressor->start(m_d->activeFrameIndex);
315
316 // vvvvvvvvvvvvvvvvvvvvv Read above comment.. This fixes all timeline rendering issues, but at what cost???
317 //Q_EMIT dataChanged(this->index(0, prevFrame), this->index(rowCount() - 1, prevFrame));
318 //Q_EMIT headerDataChanged (Qt::Horizontal, m_d->activeFrameIndex, m_d->activeFrameIndex);
319 //Q_EMIT headerDataChanged (Qt::Horizontal, prevFrame, prevFrame);
320 } else {
321 Q_EMIT dataChanged(this->index(0, prevFrame), this->index(rowCount() - 1, prevFrame));
322 Q_EMIT dataChanged(this->index(0, m_d->activeFrameIndex), this->index(rowCount() - 1, m_d->activeFrameIndex));
323 Q_EMIT headerDataChanged (Qt::Horizontal, prevFrame, prevFrame);
324 Q_EMIT headerDataChanged (Qt::Horizontal, m_d->activeFrameIndex, m_d->activeFrameIndex);
325 }
326 }
327 break;
328 case ScrubToRole:
329 SeekOptionFlags seekFlags = SeekOptionFlags(value.toInt());
330 prioritizeCache(m_d->activeFrameIndex);
331 if (!m_d->image->hasUpdatesRunning()) {
332 KisPart::instance()->playbackEngine()->seek(m_d->activeFrameIndex, seekFlags);
333 }
334 break;
335 }
336 }
337
338 return false;
339}
static KisPart * instance()
Definition KisPart.cpp:131
QScopedPointer< KisPlaybackEngine > playbackEngine
Definition KisPart.cpp:111
void prioritizeFrameForCache(KisImageSP image, int frame)
Definition KisPart.cpp:530
bool isFrameCached(const int frame)

References ActiveFrameRole, KisPart::instance(), isFrameCached(), m_d, KisPart::playbackEngine, KisPart::prioritizeFrameForCache(), ScrubToRole, and value().

◆ setImage()

void KisTimeBasedItemModel::setImage ( KisImageWSP image)

Definition at line 111 of file KisTimeBasedItemModel.cpp.

112{
113 if (m_d->image == p_image ) {
114 return;
115 }
116
117 beginResetModel();
118
119 if (m_d->image) {
120 //Disconnect old image..
122 ai->disconnect(this);
123 }
124
125 m_d->image = p_image;
126 m_d->numFramesOverride = m_d->effectiveNumFrames();
127
128 if (m_d->image) {
130
131 connect(ai, SIGNAL(sigFramerateChanged()), this, SLOT(slotFramerateChanged()));
132 connect(ai, SIGNAL(sigUiTimeChanged(int)), this, SLOT(slotCurrentTimeChanged(int)));
133 connect(ai, SIGNAL(sigPlaybackRangeChanged()), this, SLOT(slotPlaybackRangeChanged()));
134 }
135
136 endResetModel();
137}
KisImageAnimationInterface * animationInterface() const

References KisImage::animationInterface(), connect(), KisImageAnimationInterface::image(), m_d, slotCurrentTimeChanged(), slotFramerateChanged(), and slotPlaybackRangeChanged().

◆ setLastVisibleFrame()

void KisTimeBasedItemModel::setLastVisibleFrame ( int time)

Definition at line 193 of file KisTimeBasedItemModel.cpp.

194{
195 const int growThreshold = m_d->effectiveNumFrames() - 1;
196 const int growValue = time + 8;
197
198 const int shrinkThreshold = m_d->effectiveNumFrames() - 3;
199 const int shrinkValue = qMax(m_d->baseNumFrames(), qMin(growValue, shrinkThreshold));
200 const bool canShrink = m_d->baseNumFrames() < m_d->effectiveNumFrames();
201
202 if (time >= growThreshold) {
203 beginInsertColumns(QModelIndex(), m_d->effectiveNumFrames(), growValue - 1);
204 m_d->numFramesOverride = growValue;
205 endInsertColumns();
206 } else if (time < shrinkThreshold && canShrink) {
207 beginRemoveColumns(QModelIndex(), shrinkValue, m_d->effectiveNumFrames() - 1);
208 m_d->numFramesOverride = shrinkValue;
209 endRemoveColumns();
210 }
211}

References m_d.

◆ setPlaybackRange()

void KisTimeBasedItemModel::setPlaybackRange ( const KisTimeSpan & range)

◆ setScrubState()

void KisTimeBasedItemModel::setScrubState ( bool active)

Definition at line 526 of file KisTimeBasedItemModel.cpp.

527{
528 if (!m_d->animationPlayer) {
529 return;
530 }
531
532 if (m_d->scrubInProgress != p_state) {
533 m_d->scrubInProgress = p_state;
534
535 if (m_d->scrubInProgress == true) {
536 m_d->scrubStartFrame = m_d->activeFrameIndex;
537
538 if (m_d->animationPlayer->playbackState() == PLAYING) {
539 m_d->shouldReturnToPlay = true;
540 m_d->animationPlayer->setPlaybackState(PAUSED);
541 }
542
543 } else {
544 if (m_d->shouldReturnToPlay) {
545 m_d->animationPlayer->setPlaybackState(PLAYING);
546 }
547
548 m_d->scrubStartFrame = -1;
549 m_d->shouldReturnToPlay = false;
550 }
551 }
552}

References m_d, PAUSED, and PLAYING.

◆ slotCacheChanged

void KisTimeBasedItemModel::slotCacheChanged ( )
privateslot

Definition at line 587 of file KisTimeBasedItemModel.cpp.

588{
589 const int numFrames = columnCount();
590 m_d->cachedFrames.resize(numFrames);
591
592 for (int i = 0; i < numFrames; i++) {
593 m_d->cachedFrames[i] =
594 m_d->framesCache->frameStatus(i) == KisAnimationFrameCache::Cached;
595 }
596
597 Q_EMIT headerDataChanged(Qt::Horizontal, 0, numFrames);
598}

References KisAnimationFrameCache::Cached, columnCount(), and m_d.

◆ slotCurrentTimeChanged

void KisTimeBasedItemModel::slotCurrentTimeChanged ( int time)
protectedslot

Definition at line 560 of file KisTimeBasedItemModel.cpp.

561{
562 if (time != m_d->activeFrameIndex) {
563 setHeaderData(time, Qt::Horizontal, true, ActiveFrameRole);
564 }
565}

References ActiveFrameRole, m_d, and setHeaderData().

◆ slotFramerateChanged

void KisTimeBasedItemModel::slotFramerateChanged ( )
privateslot

Definition at line 567 of file KisTimeBasedItemModel.cpp.

568{
569 Q_EMIT headerDataChanged(Qt::Horizontal, 0, columnCount() - 1);
570}

References columnCount().

◆ slotPlaybackFrameChanged

void KisTimeBasedItemModel::slotPlaybackFrameChanged ( )
privateslot

Definition at line 601 of file KisTimeBasedItemModel.cpp.

602{
603 if (m_d->animationPlayer->playbackState() != PlaybackState::PLAYING) return;
604 setHeaderData(m_d->animationPlayer->displayProxy()->activeFrame(), Qt::Horizontal, true, ActiveFrameRole);
605}

References ActiveFrameRole, m_d, PLAYING, and setHeaderData().

◆ slotPlaybackRangeChanged

void KisTimeBasedItemModel::slotPlaybackRangeChanged ( )
privateslot

Definition at line 572 of file KisTimeBasedItemModel.cpp.

573{
574 if (m_d->image && m_d->image->animationInterface() ) {
575 const KisImageAnimationInterface* const interface = m_d->image->animationInterface();
576 const int lastFrame = interface->activePlaybackRange().end();
577 if (lastFrame > m_d->numFramesOverride) {
578 beginInsertColumns(QModelIndex(), m_d->numFramesOverride, interface->activePlaybackRange().end());
579 m_d->numFramesOverride = interface->activePlaybackRange().end();
580 endInsertColumns();
581 }
582
583 dataChanged(index(0,0), index(rowCount(), columnCount()));
584 }
585}

References columnCount(), image(), and m_d.

◆ slotPlaybackStateChanged

void KisTimeBasedItemModel::slotPlaybackStateChanged ( PlaybackState state)
privateslot

Definition at line 607 of file KisTimeBasedItemModel.cpp.

608{
609 if (p_state == PlaybackState::STOPPED) {
610 setHeaderData(m_d->image->animationInterface()->currentUITime(), Qt::Horizontal, true, ActiveFrameRole);
611 }
612}

References ActiveFrameRole, m_d, setHeaderData(), and STOPPED.

◆ stopPlayback()

void KisTimeBasedItemModel::stopPlayback ( ) const

Definition at line 632 of file KisTimeBasedItemModel.cpp.

632 {
634}

References KisPart::instance(), and KisPart::playbackEngine.

Member Data Documentation

◆ m_d

const QScopedPointer<Private> KisTimeBasedItemModel::m_d
private

Definition at line 104 of file KisTimeBasedItemModel.h.


The documentation for this class was generated from the following files: