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 647 of file KisTimeBasedItemModel.cpp.

647 {
649
650 if (!rasterChan) {
651 return 0;
652 }
653 return rasterChan->clonesOf(index.column()).count();
654}
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 639 of file KisTimeBasedItemModel.cpp.

639 {
641 if (!rasterChan) return false;
642
643 const int activeKeyframeTime = rasterChan->activeKeyframeTime(m_d->activeFrameIndex);
644 return rasterChan->areClones(activeKeyframeTime, index.column());
645}
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 370 of file KisTimeBasedItemModel.cpp.

375{
376 if (srcIndexes.isEmpty()) return 0;
377 if (offset.isNull()) return 0;
378
379 KisAnimUtils::sortPointsForSafeMove(&srcIndexes, offset);
380
381 KisAnimUtils::FrameItemList srcFrameItems;
382 KisAnimUtils::FrameItemList dstFrameItems;
383
384 Q_FOREACH (const QModelIndex &srcIndex, srcIndexes) {
385 QModelIndex dstIndex = index(
386 srcIndex.row() + offset.y(),
387 srcIndex.column() + offset.x());
388
389 KisNodeSP srcNode = nodeAt(srcIndex);
390 KisNodeSP dstNode = nodeAt(dstIndex);
391 if (!srcNode || !dstNode) return 0;
392
393 Q_FOREACH(KisKeyframeChannel *channel, channelsAt(srcIndex)) {
394 if (moveEmptyFrames || channel->keyframeAt(srcIndex.column())) {
395 srcFrameItems << KisAnimUtils::FrameItem(srcNode, channel->id(), srcIndex.column());
396 dstFrameItems << KisAnimUtils::FrameItem(dstNode, channel->id(), dstIndex.column());
397 }
398 }
399 }
400
401 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(srcFrameItems.size() == dstFrameItems.size(), 0);
402 if (srcFrameItems.isEmpty()) return 0;
403
404 return
406 dstFrameItems,
407 copyFrames,
408 moveEmptyFrames,
409 parentCommand);
410}
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 634 of file KisTimeBasedItemModel.cpp.

635{
636 return m_d->image->animationInterface()->currentUITime();
637}

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 656 of file KisTimeBasedItemModel.cpp.

657{
658 return m_d->image;
659}

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 620 of file KisTimeBasedItemModel.cpp.

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

References m_d, and PLAYING.

◆ isPlaybackPaused()

bool KisTimeBasedItemModel::isPlaybackPaused ( ) const

Definition at line 625 of file KisTimeBasedItemModel.cpp.

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

References m_d, and PAUSED.

◆ isScrubbing()

bool KisTimeBasedItemModel::isScrubbing ( )

Definition at line 552 of file KisTimeBasedItemModel.cpp.

553{
554 return m_d->scrubInProgress;
555}

References m_d.

◆ mirrorFrames()

bool KisTimeBasedItemModel::mirrorFrames ( QModelIndexList indexes)

Definition at line 451 of file KisTimeBasedItemModel.cpp.

452{
453 std::unique_ptr<KUndo2Command> parentCommand(new KUndo2Command(kundo2_i18n("Mirror Frames")));
454
455 {
456 KisImageBarrierLock locker(m_d->image);
457
458 QMap<int, QModelIndexList> rowsList;
459
460 Q_FOREACH (const QModelIndex &index, indexes) {
461 rowsList[index.row()].append(index);
462 }
463
464
465 Q_FOREACH (int row, rowsList.keys()) {
466 QModelIndexList &list = rowsList[row];
467
468 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!list.isEmpty(), false);
469
470 std::sort(list.begin(), list.end(),
471 [] (const QModelIndex &lhs, const QModelIndex &rhs) {
472 return lhs.column() < rhs.column();
473 });
474
475 auto srcIt = list.begin();
476 auto dstIt = list.end();
477
478 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(srcIt != dstIt, false);
479 --dstIt;
480
481 QList<KisKeyframeChannel*> channels = channelsAt(*srcIt).values();
482
483 while (srcIt < dstIt) {
484 Q_FOREACH (KisKeyframeChannel *channel, channels) {
485 if (channel->keyframeAt(srcIt->column()) && channel->keyframeAt(dstIt->column())) {
486
487 channel->swapKeyframes(srcIt->column(),
488 dstIt->column(),
489 parentCommand.get());
490 }
491 else if (channel->keyframeAt(srcIt->column())) {
492
493 channel->insertKeyframe(dstIt->column(),
494 channel->keyframeAt(srcIt->column()),
495 parentCommand.get());
496
497 channel->removeKeyframe(srcIt->column(),
498 parentCommand.get());
499 }
500 else if (channel->keyframeAt(dstIt->column())) {
501
502 channel->insertKeyframe(srcIt->column(),
503 channel->keyframeAt(dstIt->column()),
504 parentCommand.get());
505
506 channel->removeKeyframe(dstIt->column(),
507 parentCommand.get());
508 }
509 }
510
511 srcIt++;
512 dstIt--;
513 }
514 }
515 }
516
518 parentCommand.release(),
521 return true;
522}
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 346 of file KisTimeBasedItemModel.cpp.

347{
349
350 {
351 KisImageBarrierLock locker(m_d->image);
352
353 Q_FOREACH (const QModelIndex &index, indexes) {
354 int time = index.column();
355 Q_FOREACH(KisKeyframeChannel *channel, channelsAt(index)) {
356 if (channel->keyframeAt(time)) {
357 frameItems << KisAnimUtils::FrameItem(channel->node(), channel->id(), index.column());
358 }
359 }
360 }
361 }
362
363 if (frameItems.isEmpty()) return false;
364
365 KisAnimUtils::removeKeyframes(m_d->image, frameItems);
366
367 return true;
368}
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 412 of file KisTimeBasedItemModel.cpp.

413{
414 if (indicesToRemove.isEmpty()) return true;
415
416 std::sort(indicesToRemove.begin(), indicesToRemove.end(),
417 [] (const QModelIndex &lhs, const QModelIndex &rhs) {
418 return lhs.column() > rhs.column();
419 });
420
421 const int minColumn = indicesToRemove.last().column();
422
423 KUndo2Command *parentCommand = new KUndo2Command(kundo2_i18np("Remove frame and shift", "Remove %1 frames and shift", indicesToRemove.size()));
424
425 {
426 KisImageBarrierLock locker(m_d->image);
427
428 Q_FOREACH (const QModelIndex &index, indicesToRemove) {
429 QModelIndexList indicesToOffset;
430 for (int column = index.column() + 1; column < columnCount(); column++) {
431 indicesToOffset << this->index(index.row(), column);
432 }
433 createOffsetFramesCommand(indicesToOffset, QPoint(-1, 0), false, true, parentCommand);
434 }
435
436 const int oldTime = m_d->image->animationInterface()->currentUITime();
437 const int newTime = minColumn;
438
439 new KisSwitchCurrentTimeCommand(m_d->image->animationInterface(),
440 oldTime,
441 newTime,
442 parentCommand);
443 }
444
448 return true;
449}
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 339 of file KisTimeBasedItemModel.cpp.

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

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
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, 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 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 KisPart::instance()->playbackEngine()->seek(m_d->activeFrameIndex, seekFlags);
332 break;
333 }
334 }
335
336 return false;
337}
static KisPart * instance()
Definition KisPart.cpp:131
std::unique_ptr< KisPlaybackEngine > playbackEngine
Definition KisPart.cpp:111
void prioritizeFrameForCache(KisImageSP image, int frame)
Definition KisPart.cpp:506
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(), 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 524 of file KisTimeBasedItemModel.cpp.

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

References m_d, PAUSED, and PLAYING.

◆ slotCacheChanged

void KisTimeBasedItemModel::slotCacheChanged ( )
privateslot

Definition at line 585 of file KisTimeBasedItemModel.cpp.

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

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

◆ slotCurrentTimeChanged

void KisTimeBasedItemModel::slotCurrentTimeChanged ( int time)
protectedslot

Definition at line 558 of file KisTimeBasedItemModel.cpp.

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

References ActiveFrameRole, m_d, and setHeaderData().

◆ slotFramerateChanged

void KisTimeBasedItemModel::slotFramerateChanged ( )
privateslot

Definition at line 565 of file KisTimeBasedItemModel.cpp.

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

References columnCount().

◆ slotPlaybackFrameChanged

void KisTimeBasedItemModel::slotPlaybackFrameChanged ( )
privateslot

Definition at line 599 of file KisTimeBasedItemModel.cpp.

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

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

◆ slotPlaybackRangeChanged

void KisTimeBasedItemModel::slotPlaybackRangeChanged ( )
privateslot

Definition at line 570 of file KisTimeBasedItemModel.cpp.

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

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

◆ slotPlaybackStateChanged

void KisTimeBasedItemModel::slotPlaybackStateChanged ( PlaybackState state)
privateslot

Definition at line 605 of file KisTimeBasedItemModel.cpp.

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

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

◆ stopPlayback()

void KisTimeBasedItemModel::stopPlayback ( ) const

Definition at line 630 of file KisTimeBasedItemModel.cpp.

630 {
632}

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: