Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAnimTimelineFramesModel Class Reference

#include <KisAnimTimelineFramesModel.h>

+ Inheritance diagram for KisAnimTimelineFramesModel:

Classes

struct  NodeManipulationInterface
 
struct  Private
 

Public Types

enum  ItemDataRole {
  ActiveLayerRole = KisTimeBasedItemModel::UserRole , TimelinePropertiesRole , OtherLayersRole , PinnedToTimelineRole ,
  FrameColorLabelIndexRole
}
 
enum  MimeCopyPolicy { UndefinedPolicy = 0 , MoveFramesPolicy , CopyFramesPolicy , CloneFramesPolicy }
 
typedef TimelineNodeListKeeper::OtherLayer OtherLayer
 
typedef TimelineNodeListKeeper::OtherLayersList OtherLayersList
 
typedef KisBaseNode::Property Property
 
typedef KisBaseNode::PropertyList PropertyList
 
- Public Types inherited from KisTimeBasedItemModel
enum  ItemDataRole {
  ActiveFrameRole = Qt::UserRole + 101 , ScrubToRole , CloneOfActiveFrame , CloneCount ,
  FrameExistsRole , SpecialKeyframeExists , FrameCachedRole , FrameEditableRole ,
  FramesPerSecondRole , FrameHasContent , WithinClipRange , UserRole
}
 

Public Slots

void slotCurrentNodeChanged (KisNodeSP node)
 

Signals

void requestCurrentNodeChanged (KisNodeSP node)
 
void requestTransferSelectionBetweenRows (int rowFrom, int rowTo)
 
void sigEnsureRowVisible (int row)
 
void sigFullClipRangeChanged ()
 
void sigInfiniteTimelineUpdateNeeded ()
 

Public Member Functions

int activeLayerRow () const
 
QString audioChannelFileName () const
 
qreal audioVolume () const
 
bool canDropFrameData (const QMimeData *data, const QModelIndex &index)
 
void clearEntireCache ()
 
bool copyFrame (const QModelIndex &dstIndex)
 
bool createFrame (const QModelIndexList &dstIndex)
 
QVariant data (const QModelIndex &index, int role) const override
 
bool dropMimeData (const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
 
bool dropMimeDataExtended (const QMimeData *data, Qt::DropAction action, const QModelIndex &parent, bool *dataMoved=0)
 
Qt::ItemFlags flags (const QModelIndex &index) const override
 
bool hasConnectionToCanvas () const
 
QVariant headerData (int section, Qt::Orientation orientation, int role) const override
 
bool insertFrames (int dstColumn, const QList< int > &dstRows, int count, int timing=1)
 
bool insertHoldFrames (const QModelIndexList &selectedIndexes, int insertCount)
 
bool insertOtherLayer (int index, int dstRow)
 
bool insertRows (int row, int count, const QModelIndex &parent) override
 
bool isAudioMuted () const
 
 KisAnimTimelineFramesModel (QObject *parent)
 
void makeClonesUnique (const QModelIndexList &indices)
 
QMimeData * mimeData (const QModelIndexList &indexes) const override
 
QMimeData * mimeDataExtended (const QModelIndexList &indexes, const QModelIndex &baseIndex, MimeCopyPolicy copyPolicy) const
 
QStringList mimeTypes () const override
 
KisNodeSP nodeAt (QModelIndex index) const override
 
bool removeRows (int row, int count, const QModelIndex &parent) override
 
int rowCount (const QModelIndex &parent=QModelIndex()) const override
 
void setActiveLayerSelectedTimes (const QSet< int > &times)
 
void setAudioChannelFileName (const QFileInfo &fileName)
 
void setAudioMuted (bool value)
 
void setAudioVolume (qreal value)
 
bool setData (const QModelIndex &index, const QVariant &value, int role) override
 
void setDocumentClipRangeEnd (int column)
 
void setDocumentClipRangeStart (int column)
 
void setDummiesFacade (KisDummiesFacadeBase *dummiesFacade, KisImageSP image, KisNodeDisplayModeAdapter *displayModeAdapter)
 
bool setHeaderData (int section, Qt::Orientation orientation, const QVariant &value, int role) override
 
void setLastClickedIndex (const QModelIndex &index)
 
void setNodeManipulationInterface (NodeManipulationInterface *iface)
 
Qt::DropActions supportedDragActions () const override
 
Qt::DropActions supportedDropActions () const override
 
 ~KisAnimTimelineFramesModel () override
 
- Public Member Functions inherited from TimelineNodeListKeeper::ModelWithExternalNotifications
void callBeginInsertRows (const QModelIndex &parent, int first, int last)
 
void callBeginRemoveRows (const QModelIndex &parent, int first, int last)
 
void callBeginResetModel ()
 
void callEndInsertRows ()
 
void callEndRemoveRows ()
 
void callEndResetModel ()
 
void callIndexChanged (const QModelIndex &index0, const QModelIndex &index1)
 
 ModelWithExternalNotifications (QObject *parent)
 
- Public Member Functions inherited from KisTimeBasedItemModel
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 Member Functions

KisKeyframeChannelchannelByID (QModelIndex index, const QString &id) const override
 
QMap< QString, KisKeyframeChannel * > channelsAt (QModelIndex index) const override
 
- Protected Member Functions inherited from KisTimeBasedItemModel
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
 

Private Slots

void processUpdateQueue ()
 
void slotDummyChanged (KisNodeDummy *dummy)
 
void slotImageContentChanged ()
 

Private Attributes

const QScopedPointer< Privatem_d
 

Additional Inherited Members

- Protected Slots inherited from KisTimeBasedItemModel
void slotCurrentTimeChanged (int time)
 

Detailed Description

Definition at line 45 of file KisAnimTimelineFramesModel.h.

Member Typedef Documentation

◆ OtherLayer

◆ OtherLayersList

◆ Property

◆ PropertyList

Member Enumeration Documentation

◆ ItemDataRole

◆ MimeCopyPolicy

Constructor & Destructor Documentation

◆ KisAnimTimelineFramesModel()

KisAnimTimelineFramesModel::KisAnimTimelineFramesModel ( QObject * parent)

Definition at line 220 of file KisAnimTimelineFramesModel.cpp.

222 m_d(new Private)
223{
224 connect(&m_d->updateTimer, SIGNAL(timeout()), SLOT(processUpdateQueue()));
225}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
const QScopedPointer< Private > m_d

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

◆ ~KisAnimTimelineFramesModel()

KisAnimTimelineFramesModel::~KisAnimTimelineFramesModel ( )
override

Definition at line 227 of file KisAnimTimelineFramesModel.cpp.

228{
229}

Member Function Documentation

◆ activeLayerRow()

int KisAnimTimelineFramesModel::activeLayerRow ( ) const

Definition at line 862 of file KisAnimTimelineFramesModel.cpp.

863{
864 return m_d->activeLayerIndex;
865}

References m_d.

◆ audioChannelFileName()

QString KisAnimTimelineFramesModel::audioChannelFileName ( ) const

Definition at line 1090 of file KisAnimTimelineFramesModel.cpp.

1091{
1092 if (document()) {
1094 if (files.count() > 0) {
1095 return files.first().baseName();
1096 }
1097 }
1098 return QString("");
1099}
QVector< QFileInfo > getAudioTracks() const
KisDocument * document() const

References KisTimeBasedItemModel::document(), and KisDocument::getAudioTracks().

◆ audioVolume()

qreal KisAnimTimelineFramesModel::audioVolume ( ) const

Definition at line 1124 of file KisAnimTimelineFramesModel.cpp.

1125{
1126 if (document()) {
1127 return document()->getAudioLevel();
1128 } else {
1129 return 1.0;
1130 }
1131}
qreal getAudioLevel()

References KisTimeBasedItemModel::document(), and KisDocument::getAudioLevel().

◆ canDropFrameData()

bool KisAnimTimelineFramesModel::canDropFrameData ( const QMimeData * data,
const QModelIndex & index )

Now we support D&D around any layer, so just return 'true' all the time.

Definition at line 647 of file KisAnimTimelineFramesModel.cpp.

648{
649 if (!index.isValid()) return false;
650
651 if ( !m_d->layerEditable(index.row()) ) return false;
652
657 return true;
658}

References m_d.

◆ channelByID()

KisKeyframeChannel * KisAnimTimelineFramesModel::channelByID ( QModelIndex index,
const QString & id ) const
overrideprotectedvirtual

Implements KisTimeBasedItemModel.

Definition at line 262 of file KisAnimTimelineFramesModel.cpp.

263{
264 KisNodeSP srcDummy = nodeAt(index);
265
266 if (!srcDummy) {
267 return nullptr;
268 }
269
270 return srcDummy->getKeyframeChannel(id);
271}
KisNodeSP nodeAt(QModelIndex index) const override
KisKeyframeChannel * getKeyframeChannel(const QString &id, bool create)

References KisBaseNode::getKeyframeChannel(), and nodeAt().

◆ channelsAt()

QMap< QString, KisKeyframeChannel * > KisAnimTimelineFramesModel::channelsAt ( QModelIndex index) const
overrideprotectedvirtual

Implements KisTimeBasedItemModel.

Definition at line 251 of file KisAnimTimelineFramesModel.cpp.

252{
253 KisNodeSP srcDummy = nodeAt(index);
254
255 if (!srcDummy) {
256 return {};
257 }
258
259 return srcDummy->keyframeChannels();
260}
QMap< QString, KisKeyframeChannel * > keyframeChannels

References KisBaseNode::keyframeChannels, and nodeAt().

◆ clearEntireCache()

void KisAnimTimelineFramesModel::clearEntireCache ( )

Definition at line 1149 of file KisAnimTimelineFramesModel.cpp.

1150{
1151 m_d->image->animationInterface()->invalidateFrames(KisTimeSpan::infinite(0), m_d->image->bounds());
1152}
static KisTimeSpan infinite(int start)

References KisTimeSpan::infinite(), and m_d.

◆ copyFrame()

bool KisAnimTimelineFramesModel::copyFrame ( const QModelIndex & dstIndex)

Definition at line 899 of file KisAnimTimelineFramesModel.cpp.

900{
901 if (!dstIndex.isValid()) return false;
902
903 return m_d->addKeyframe(dstIndex.row(), dstIndex.column(), true);
904}

References m_d.

◆ createFrame()

bool KisAnimTimelineFramesModel::createFrame ( const QModelIndexList & dstIndex)

Definition at line 867 of file KisAnimTimelineFramesModel.cpp.

868{
869 QList<QPair<int,int>> selectedCells;
870
871 Q_FOREACH(const QModelIndex &index, dstIndex){
872 if (!index.isValid()) continue;
873 selectedCells.append(QPair<int,int>(index.row(), index.column()));
874 }
875
876 if (selectedCells.size() == 0) {
877 return false;
878 }
879
880 KUndo2Command *parentCommand = new KUndo2Command(kundo2_i18np("Add blank frame", "Add %1 blank frames", selectedCells.size()));
881
882 Q_FOREACH (auto &cell, selectedCells) {
883 KisNodeDummy *dummy = m_d->converter->dummyFromRow(cell.first);
884 if (!dummy) continue;
885
886 KisNodeSP node = dummy->node();
887 if (!KisAnimUtils::supportsContentFrames(node)) continue;
888
889 KisAnimUtils::createKeyframeCommand(m_d->image, node, KisKeyframeChannel::Raster.id(), cell.second, false, parentCommand);
890 }
891
895
896 return true;
897}
static const KoID Raster
KisNodeSP node() const
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...
QString id() const
Definition KoID.cpp:63
KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1)
KUndo2Command * createKeyframeCommand(KisImageSP image, KisNodeSP node, const QString &channelId, int time, bool copy, KUndo2Command *parentCommand)
bool supportsContentFrames(KisNodeSP node)

References KisStrokeJobData::BARRIER, KisAnimUtils::createKeyframeCommand(), KisStrokeJobData::EXCLUSIVE, KoID::id(), kundo2_i18np(), m_d, KisNodeDummy::node(), KisKeyframeChannel::Raster, KisProcessingApplicator::runSingleCommandStroke(), and KisAnimUtils::supportsContentFrames().

◆ data()

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

Definition at line 393 of file KisAnimTimelineFramesModel.cpp.

394{
395 if(!m_d->dummiesFacade) return QVariant();
396
397 switch (role) {
398 case ActiveLayerRole: {
399 return index.row() == m_d->activeLayerIndex;
400 }
401 case FrameEditableRole: {
402 return m_d->layerEditable(index.row());
403 }
404 case FrameHasContent: {
405 return m_d->frameHasContent(index.row(), index.column());
406 }
407 case FrameExistsRole: {
408 return m_d->frameExists(index.row(), index.column());
409 }
411 return m_d->specialKeyframeExists(index.row(), index.column());
412 }
414 int label = m_d->frameColorLabel(index.row(), index.column());
415 return label > 0 ? label : QVariant();
416 }
417 case Qt::DisplayRole: {
418 return m_d->layerName(index.row());
419 }
420 case Qt::TextAlignmentRole: {
421 return QVariant(Qt::AlignHCenter | Qt::AlignVCenter);
422 }
423 case Qt::UserRole + KisAbstractResourceModel::LargeThumbnail: {
424 KisNodeDummy *dummy = m_d->converter->dummyFromRow(index.row());
425 if (!dummy) {
426 return QVariant();
427 }
428 const int maxSize = 200;
429
430 QImage image(dummy->node()->createThumbnailForFrame(maxSize, maxSize, index.column(), Qt::KeepAspectRatio));
431 return image;
432 }
433 }
434
435 return ModelWithExternalNotifications::data(index, role);
436}
@ LargeThumbnail
A larger thumbnail for displaying in a tooltip. 200x200 or so.
virtual QImage createThumbnailForFrame(qint32 w, qint32 h, int time, Qt::AspectRatioMode aspectRatioMode=Qt::IgnoreAspectRatio)

References ActiveLayerRole, KisBaseNode::createThumbnailForFrame(), FrameColorLabelIndexRole, KisTimeBasedItemModel::FrameEditableRole, KisTimeBasedItemModel::FrameExistsRole, KisTimeBasedItemModel::FrameHasContent, KisTimeBasedItemModel::image(), KisAbstractResourceModel::LargeThumbnail, m_d, KisNodeDummy::node(), and KisTimeBasedItemModel::SpecialKeyframeExists.

◆ dropMimeData()

bool KisAnimTimelineFramesModel::dropMimeData ( const QMimeData * data,
Qt::DropAction action,
int row,
int column,
const QModelIndex & parent )
override

Definition at line 660 of file KisAnimTimelineFramesModel.cpp.

661{
662 Q_UNUSED(row);
663 Q_UNUSED(column);
664
665 return dropMimeDataExtended(data, action, parent);
666}
QVariant data(const QModelIndex &index, int role) const override
bool dropMimeDataExtended(const QMimeData *data, Qt::DropAction action, const QModelIndex &parent, bool *dataMoved=0)

References data(), and dropMimeDataExtended().

◆ dropMimeDataExtended()

bool KisAnimTimelineFramesModel::dropMimeDataExtended ( const QMimeData * data,
Qt::DropAction action,
const QModelIndex & parent,
bool * dataMoved = 0 )

Definition at line 668 of file KisAnimTimelineFramesModel.cpp.

669{
670 bool result = false;
671
672 if ((action != Qt::MoveAction && action != Qt::CopyAction && action != Qt::LinkAction) ||
673 !parent.isValid()) return result;
674
675 QByteArray encoded = data->data("application/x-krita-frame");
676 QDataStream stream(&encoded, QIODevice::ReadOnly);
677
678 int uuidLenRoot = 0;
679 stream >> uuidLenRoot;
680 QByteArray uuidDataRoot(uuidLenRoot, '\0');
681 stream.readRawData(uuidDataRoot.data(), uuidLenRoot);
682 QUuid nodeUuidRoot = QUuid::fromRfc4122(uuidDataRoot);
683
684 KisPart *partInstance = KisPart::instance();
685 QList<QPointer<KisDocument>> documents = partInstance->documents();
686
687 KisImageSP srcImage = 0;
688 Q_FOREACH(KisDocument *doc, documents) {
689 KisImageSP tmpSrcImage = doc->image();
690 if (tmpSrcImage->root()->uuid() == nodeUuidRoot) {
691 srcImage = tmpSrcImage;
692 break;
693 }
694 }
695
696 if (!srcImage) {
697 KisPart *kisPartInstance = KisPart::instance();
699 i18n("Dropped frames are not available in this Krita instance")
700 , QIcon());
701 return false;
702 }
703
704 int size, baseRow, baseColumn;
705 stream >> size >> baseRow >> baseColumn;
706
707 const QPoint offset(parent.column() - baseColumn, parent.row() - baseRow);
709 int necessaryOffset = 0; //Necessary offset to keep move above 0, used later.
710
711 for (int i = 0; i < size; i++) {
712 int relRow, relColumn;
713 stream >> relRow >> relColumn;
714
715 const int srcRow = baseRow + relRow;
716 const int srcColumn = baseColumn + relColumn;
717
718 int uuidLen = 0;
719 stream >> uuidLen;
720 QByteArray uuidData(uuidLen, '\0');
721 stream.readRawData(uuidData.data(), uuidLen);
722 QUuid nodeUuid = QUuid::fromRfc4122(uuidData);
723
724 KisNodeSP srcNode;
725
726 if (!nodeUuid.isNull()) {
727 KisNodeUuidInfo nodeInfo(nodeUuid);
728 srcNode = nodeInfo.findNode(srcImage->root());
729 } else {
730 QModelIndex index = this->index(srcRow, srcColumn);
731 srcNode = nodeAt(index);
732 }
733
734 KIS_SAFE_ASSERT_RECOVER(srcNode) { continue; }
735
736 const QModelIndex dstRowIndex = this->index(srcRow + offset.y(), 0);
737 if (!dstRowIndex.isValid()) continue;
738
739 KisNodeSP dstNode = nodeAt(dstRowIndex);
740 KIS_SAFE_ASSERT_RECOVER(dstNode) { continue; }
741
742 Q_FOREACH (KisKeyframeChannel *channel, srcNode->keyframeChannels().values()) {
743 KisAnimUtils::FrameItem srcItem(srcNode, channel->id(), srcColumn);
744 KisAnimUtils::FrameItem dstItem(dstNode, channel->id(), srcColumn + offset.x());
745
746 if ((srcColumn + offset.x()) * -1 > necessaryOffset ) {
747 necessaryOffset = (srcColumn + offset.x()) * -1;
748 }
749
750 frameMoves << std::make_pair(srcItem, dstItem);
751 }
752 }
753
754 MimeCopyPolicy copyPolicy = UndefinedPolicy;
755
756 if (!stream.atEnd()) {
757 int value = 0;
758 stream >> value;
759 copyPolicy = MimeCopyPolicy(value);
760 }
761
762 const bool copyFrames = copyPolicy == UndefinedPolicy ?
763 action == Qt::CopyAction :
764 copyPolicy == CopyFramesPolicy;
765
766 const bool cloneFrames = action == Qt::LinkAction || copyPolicy == CloneFramesPolicy;
767
768 if (dataMoved) {
769 *dataMoved = !copyFrames;
770 }
771
772 KUndo2Command *cmd = 0;
773
774 if (!frameMoves.isEmpty()) {
775
776 // We need to make sure that no movement ever occurs into the negative values.
777 // TODO: Probably a better way to fix this, I'm not happy with this fix.
778 if (necessaryOffset > 0) {
779 for (int i = 0; i < frameMoves.count(); i++){
780 frameMoves[i].second.time += necessaryOffset;
781 }
782 }
783
784 KisImageBarrierLock lock(m_d->image);
785
786 if (cloneFrames) {
787 cmd = KisAnimUtils::createCloneKeyframesCommand(frameMoves, nullptr);
788 } else {
789 cmd = KisAnimUtils::createMoveKeyframesCommand(frameMoves, copyFrames, false, nullptr);
790 }
791 }
792
793 if (cmd) {
797 }
798
799 return cmd;
800}
float value(const T *src, size_t ch)
KisImageSP image
KisKeyframeChannel stores and manages KisKeyframes. Maps units of time to virtual keyframe values....
KisViewManager * viewManager
QList< QPointer< KisDocument > > documents
Definition KisPart.cpp:108
static KisPart * instance()
Definition KisPart.cpp:131
KisMainWindow * currentMainwindow() const
Definition KisPart.cpp:483
void showFloatingMessage(const QString &message, const QIcon &icon, int timeout=4500, KisFloatingMessage::Priority priority=KisFloatingMessage::Medium, int alignment=Qt::AlignCenter|Qt::TextWordWrap)
shows a floating message in the top right corner of the canvas
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
KUndo2Command * createMoveKeyframesCommand(const FrameItemList &srcFrames, const FrameItemList &dstFrames, bool copy, bool moveEmpty, KUndo2Command *parentCommand)
KUndo2Command * createCloneKeyframesCommand(const FrameMovePairList &srcDstPairs, KUndo2Command *parentCommand)
ChildIterator< value_type, is_const > parent(const ChildIterator< value_type, is_const > &it)
Definition KisForest.h:327
int size(const Forest< T > &forest)
Definition KisForest.h:1232
QUuid uuid() const

References KisStrokeJobData::BARRIER, CloneFramesPolicy, CopyFramesPolicy, KisAnimUtils::createCloneKeyframesCommand(), KisAnimUtils::createMoveKeyframesCommand(), KisPart::currentMainwindow(), data(), KisPart::documents, KisStrokeJobData::EXCLUSIVE, KisNodeUuidInfo::findNode(), KisKeyframeChannel::id(), KisDocument::image, KisPart::instance(), KisBaseNode::keyframeChannels, KIS_SAFE_ASSERT_RECOVER, m_d, nodeAt(), KisNodeFacade::root, KisProcessingApplicator::runSingleCommandStroke(), KisViewManager::showFloatingMessage(), UndefinedPolicy, KisBaseNode::uuid(), value(), and KisMainWindow::viewManager.

◆ flags()

Qt::ItemFlags KisAnimTimelineFramesModel::flags ( const QModelIndex & index) const
override

Basically we should forbid overrides only if we D&D a single frame and allow it when we D&D multiple frames. But we cannot distinguish it here... So allow all the time.

Definition at line 802 of file KisAnimTimelineFramesModel.cpp.

803{
804 Qt::ItemFlags flags = ModelWithExternalNotifications::flags(index);
805 if (!index.isValid()) return flags;
806
807 if (m_d->frameExists(index.row(), index.column()) || m_d->specialKeyframeExists(index.row(), index.column())) {
808 if (data(index, FrameEditableRole).toBool()) {
809 flags |= Qt::ItemIsDragEnabled;
810 }
811 }
812
818 flags |= Qt::ItemIsDropEnabled;
819
820 return flags;
821}
Qt::ItemFlags flags(const QModelIndex &index) const override

References data(), flags(), KisTimeBasedItemModel::FrameEditableRole, and m_d.

◆ hasConnectionToCanvas()

bool KisAnimTimelineFramesModel::hasConnectionToCanvas ( ) const

Definition at line 231 of file KisAnimTimelineFramesModel.cpp.

232{
233 return m_d->dummiesFacade;
234}

References m_d.

◆ headerData()

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

Definition at line 472 of file KisAnimTimelineFramesModel.cpp.

473{
474 if(!m_d->dummiesFacade) return QVariant();
475
476 if (orientation == Qt::Vertical) {
477 switch (role) {
478 case ActiveLayerRole:
479 return section == m_d->activeLayerIndex;
480 case Qt::DisplayRole: {
481 QVariant value = headerData(section, orientation, Qt::ToolTipRole);
482 if (!value.isValid()) return value;
483
484 QString name = value.toString();
485 const int maxNameSize = 13;
486
487 if (name.size() > maxNameSize) {
488 name = QString("%1...").arg(name.left(maxNameSize));
489 }
490
491 return name;
492 }
493 case Qt::ForegroundRole: {
494 // WARNING: this role doesn't work for header views! Use
495 // bold font to show isolated mode instead!
496 return QVariant();
497 }
498 case Qt::FontRole: {
499 KisNodeDummy *dummy = m_d->converter->dummyFromRow(section);
500 if (!dummy) return QVariant();
501 KisNodeSP node = dummy->node();
502
503 QFont baseFont;
504 if (node->projectionLeaf()->isDroppedNode()) {
505 baseFont.setStrikeOut(true);
506 } else if (m_d->image && m_d->image->isolationRootNode() &&
507 KisNodeModel::belongsToIsolatedGroup(m_d->image, node, m_d->dummiesFacade)) {
508 baseFont.setBold(true);
509 }
510 return baseFont;
511 }
512 case Qt::ToolTipRole: {
513 return m_d->layerName(section);
514 }
516 return QVariant::fromValue(m_d->layerProperties(section));
517 }
518 case OtherLayersRole: {
520 m_d->converter->otherLayersList();
521
522 return QVariant::fromValue(list);
523 }
525 KisNodeDummy *dummy = m_d->converter->dummyFromRow(section);
526 if (!dummy) return QVariant();
527 return dummy->node()->isPinnedToTimeline();
528 }
529 case Qt::BackgroundRole: {
530 int label = m_d->layerColorLabel(section);
531 if (label > 0) {
533 QColor color = scm.colorFromLabelIndex(label);
534 QPalette pal = qApp->palette();
535 color = KisPaintingTweaks::blendColors(color, pal.color(QPalette::Button), 0.3);
536 return QBrush(color);
537 } else {
538 return QVariant();
539 }
540 }
541 }
542 }
543
544 return ModelWithExternalNotifications::headerData(section, orientation, role);
545}
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
static bool belongsToIsolatedGroup(KisImageSP image, KisNodeSP node, KisDummiesFacadeBase *dummiesFacade)
QColor colorFromLabelIndex(int index) const
const char * name(StandardAction id)
QColor blendColors(const QColor &c1, const QColor &c2, qreal r1)
bool isPinnedToTimeline() const
KisProjectionLeafSP projectionLeaf
Definition kis_node.cpp:93

References ActiveLayerRole, KisNodeModel::belongsToIsolatedGroup(), KisPaintingTweaks::blendColors(), KisNodeViewColorScheme::colorFromLabelIndex(), headerData(), KisBaseNode::isPinnedToTimeline(), m_d, KisNodeDummy::node(), OtherLayersRole, PinnedToTimelineRole, KisNode::projectionLeaf, TimelinePropertiesRole, and value().

◆ insertFrames()

bool KisAnimTimelineFramesModel::insertFrames ( int dstColumn,
const QList< int > & dstRows,
int count,
int timing = 1 )

Definition at line 920 of file KisAnimTimelineFramesModel.cpp.

921{
922 if (dstRows.isEmpty() || count <= 0) return true;
923 timing = qMax(timing, 1);
924
925 KUndo2Command *parentCommand = new KUndo2Command(kundo2_i18np("Insert frame", "Insert %1 frames", count));
926
927 {
928 KisImageBarrierLock locker(m_d->image);
929
930 QModelIndexList indexes;
931
932 Q_FOREACH (int row, dstRows) {
933 for (int column = dstColumn; column < columnCount(); column++) {
934 indexes << index(row, column);
935 }
936 }
937
938 setLastVisibleFrame(columnCount() + (count * timing) - 1);
939
940 createOffsetFramesCommand(indexes, QPoint((count * timing), 0), false, false, parentCommand);
941
942 Q_FOREACH (int row, dstRows) {
943 KisNodeDummy *dummy = m_d->converter->dummyFromRow(row);
944 if (!dummy) continue;
945
946 KisNodeSP node = dummy->node();
947 if (!KisAnimUtils::supportsContentFrames(node)) continue;
948
949 for (int column = dstColumn; column < dstColumn + (count * timing); column += timing) {
950 KisAnimUtils::createKeyframeCommand(m_d->image, node, KisKeyframeChannel::Raster.id(), column, false, parentCommand);
951 }
952 }
953
954 const int oldTime = m_d->image->animationInterface()->currentUITime();
955 const int newTime = dstColumn > oldTime ? dstColumn : dstColumn + (count * timing) - 1;
956
957 new KisSwitchCurrentTimeCommand(m_d->image->animationInterface(),
958 oldTime,
959 newTime, parentCommand);
960 }
961
965
966 return true;
967}
KUndo2Command * createOffsetFramesCommand(QModelIndexList srcIndexes, const QPoint &offset, bool copyFrames, bool moveEmptyFrames, KUndo2Command *parentCommand=0)
int columnCount(const QModelIndex &parent=QModelIndex()) const override

References KisStrokeJobData::BARRIER, KisTimeBasedItemModel::columnCount(), KisAnimUtils::createKeyframeCommand(), KisTimeBasedItemModel::createOffsetFramesCommand(), KisStrokeJobData::EXCLUSIVE, KoID::id(), kundo2_i18np(), m_d, KisNodeDummy::node(), KisKeyframeChannel::Raster, KisProcessingApplicator::runSingleCommandStroke(), KisTimeBasedItemModel::setLastVisibleFrame(), and KisAnimUtils::supportsContentFrames().

◆ insertHoldFrames()

bool KisAnimTimelineFramesModel::insertHoldFrames ( const QModelIndexList & selectedIndexes,
int insertCount )

Definition at line 969 of file KisAnimTimelineFramesModel.cpp.

970{
971 if (selectedIndexes.isEmpty() || insertCount == 0) return true;
972
973 QScopedPointer<KUndo2Command> parentCommand(new KUndo2Command(kundo2_i18np("Insert frame", "Insert %1 frames", insertCount)));
974
975 {
976 KisImageBarrierLock locker(m_d->image);
977
978 // Find Keyframes in selection...
979 QSet<TimelineSelectionEntry> uniqueKeyframesInSelection;
980 int earliestAffectedTime = std::numeric_limits<int>::max();
981
982 Q_FOREACH (const QModelIndex &index, selectedIndexes) {
983 KisNodeSP node = nodeAt(index);
984 KIS_SAFE_ASSERT_RECOVER(node) { continue; }
985
987 if (!channel) continue;
988
989 earliestAffectedTime = qMin(earliestAffectedTime, index.column()); // Earliest of selection... (to be continued.)
990
991 int time = channel->activeKeyframeTime(index.column());
992 KisRasterKeyframeSP keyframe = channel->activeKeyframeAt<KisRasterKeyframe>(index.column());
993
994 if (keyframe) {
995 uniqueKeyframesInSelection.insert(TimelineSelectionEntry{channel, time, keyframe});
996 }
997 }
998
999 // Determine which keyframes need to move and sort by time...
1000 QList<TimelineSelectionEntry> keyframesToMove;
1001
1002 for (auto it = uniqueKeyframesInSelection.begin(); it != uniqueKeyframesInSelection.end(); ++it) {
1003 TimelineSelectionEntry keyframeEntry = *it;
1004
1005 KisRasterKeyframeChannel *channel = keyframeEntry.channel;
1006 int nextKeyframeTime = channel->nextKeyframeTime(keyframeEntry.time);
1007 KisRasterKeyframeSP nextKeyframe = channel->keyframeAt<KisRasterKeyframe>(nextKeyframeTime);
1008
1009 if (nextKeyframe) {
1010 keyframesToMove << TimelineSelectionEntry{ channel, nextKeyframeTime, nextKeyframe };
1011 }
1012 }
1013
1014 std::sort(keyframesToMove.begin(), keyframesToMove.end(),
1016 return lhs.time > rhs.time;
1017 });
1018
1019 if (keyframesToMove.isEmpty()) return true;
1020
1021 const int oldTime = m_d->image->animationInterface()->currentUITime();
1022 const int maxColumn = columnCount();
1023
1024 // Store the original active keyframe, so we can switch to its new time at the end.
1025 // (This helps to keep artist drawing on the right keyframe even while adding and removing hold frames.)
1026 QModelIndex activeIndex = index(m_d->activeLayerIndex, oldTime);
1027 KisNodeSP activeNode = nodeAt(activeIndex);
1029
1030 KisRasterKeyframeSP originalActiveKeyframe = nullptr;
1031 if (activeChannel) {
1032 originalActiveKeyframe = activeChannel->activeKeyframeAt<KisRasterKeyframe>(oldTime);
1033 }
1034
1035 // Create keyframe movement commands...
1036 if (insertCount > 0) {
1037 setLastVisibleFrame(columnCount() + insertCount);
1038 }
1039
1040 Q_FOREACH (TimelineSelectionEntry entry, keyframesToMove) {
1041 int plannedFrameMove = insertCount;
1042
1043 if (insertCount < 0) {
1045
1046 int prevKeyframeTime = entry.channel->previousKeyframeTime(entry.time);
1047 KisRasterKeyframeSP prevFrame = entry.channel->keyframeAt<KisRasterKeyframe>(prevKeyframeTime);
1048 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(prevFrame, false);
1049
1050 // Clamp values so that they never exceed or overlap the previous frame
1051 plannedFrameMove = qMax(insertCount, prevKeyframeTime - entry.time + 1);
1052
1053 earliestAffectedTime = qMin(earliestAffectedTime, prevKeyframeTime); // No longer limited to selection.
1054 }
1055
1056 KisNodeDummy *dummy = m_d->dummiesFacade->dummyForNode(entry.channel->node());
1057 KIS_SAFE_ASSERT_RECOVER(dummy) { continue; }
1058
1059 const int row = m_d->converter->rowForDummy(dummy);
1060 KIS_SAFE_ASSERT_RECOVER(row >= 0) { continue; }
1061
1062 QModelIndexList indices;
1063 for (int column = entry.time; column < maxColumn; column++) {
1064 indices << index(row, column);
1065 }
1066
1068 QPoint(plannedFrameMove, 0),
1069 false,
1070 true,
1071 parentCommand.data());
1072 }
1073
1074 if (originalActiveKeyframe) {
1075 new KisSwitchCurrentTimeToKeyframeCommand(m_d->image->animationInterface(),
1076 oldTime,
1077 activeNode,
1079 originalActiveKeyframe,
1080 parentCommand.data());
1081 }
1082 }
1083
1084 KisProcessingApplicator::runSingleCommandStroke(m_d->image, parentCommand.take(),
1087 return true;
1088}
int previousKeyframeTime(const int time) const
KisKeyframeSP keyframeAt(int time) const
Get a keyframe at specified time. Used primarily when the value of a given keyframe is needed.
KisKeyframeSP activeKeyframeAt(int time) const
int activeKeyframeTime(int time) const
Get the time of the active keyframe. Useful for snapping any time to that of the most recent keyframe...
int nextKeyframeTime(const int time) const
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
The KisRasterKeyframe class is a concrete subclass of KisKeyframe that wraps a physical raster image ...
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
KisRasterKeyframeChannel * channel

References KisKeyframeChannel::activeKeyframeAt(), KisKeyframeChannel::activeKeyframeTime(), KisStrokeJobData::BARRIER, TimelineSelectionEntry::channel, KisTimeBasedItemModel::columnCount(), KisTimeBasedItemModel::createOffsetFramesCommand(), KisStrokeJobData::EXCLUSIVE, KisBaseNode::getKeyframeChannel(), KisKeyframeChannel::keyframeAt(), KIS_SAFE_ASSERT_RECOVER, KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE, kundo2_i18np(), m_d, KisKeyframeChannel::nextKeyframeTime(), KisKeyframeChannel::node(), nodeAt(), KisKeyframeChannel::previousKeyframeTime(), KisKeyframeChannel::Raster, KisProcessingApplicator::runSingleCommandStroke(), KisTimeBasedItemModel::setLastVisibleFrame(), and TimelineSelectionEntry::time.

◆ insertOtherLayer()

bool KisAnimTimelineFramesModel::insertOtherLayer ( int index,
int dstRow )

Definition at line 846 of file KisAnimTimelineFramesModel.cpp.

847{
848 Q_UNUSED(dstRow);
849
851 m_d->converter->otherLayersList();
852
853 if (index < 0 || index >= list.size()) return false;
854
855 list[index].dummy->node()->setPinnedToTimeline(true);
856 dstRow = m_d->converter->rowForDummy(list[index].dummy);
857 setData(this->index(dstRow, 0), true, ActiveLayerRole);
858
859 return true;
860}
bool setData(const QModelIndex &index, const QVariant &value, int role) override

References ActiveLayerRole, m_d, and setData().

◆ insertRows()

bool KisAnimTimelineFramesModel::insertRows ( int row,
int count,
const QModelIndex & parent )
override

Definition at line 823 of file KisAnimTimelineFramesModel.cpp.

824{
825 Q_UNUSED(parent);
826
827 KIS_ASSERT_RECOVER(count == 1) { return false; }
828
829 if (row < 0 || row > rowCount()) return false;
830
831 bool result = m_d->addNewLayer(row);
832 return result;
833}
int rowCount(const QModelIndex &parent=QModelIndex()) const override
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55

References KIS_ASSERT_RECOVER, m_d, and rowCount().

◆ isAudioMuted()

bool KisAnimTimelineFramesModel::isAudioMuted ( ) const

Definition at line 1113 of file KisAnimTimelineFramesModel.cpp.

1114{
1115 return KisPart::instance()->playbackEngine()->isMute();
1116}
QScopedPointer< KisPlaybackEngine > playbackEngine
Definition KisPart.cpp:111

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

◆ makeClonesUnique()

void KisAnimTimelineFramesModel::makeClonesUnique ( const QModelIndexList & indices)

Definition at line 906 of file KisAnimTimelineFramesModel.cpp.

907{
909
910 Q_FOREACH (const QModelIndex &index, indices) {
911 const int time = index.column();
913 if (!channel) continue;
914 frameItems << KisAnimUtils::FrameItem(channel->node(), channel->id(), time);
915 }
916
917 KisAnimUtils::makeClonesUnique(m_d->image, frameItems);
918}
KisKeyframeChannel * channelByID(QModelIndex index, const QString &id) const override
void makeClonesUnique(KisImageSP image, const FrameItemList &frames)

References channelByID(), KisKeyframeChannel::id(), m_d, KisAnimUtils::makeClonesUnique(), KisKeyframeChannel::node(), and KisKeyframeChannel::Raster.

◆ mimeData()

QMimeData * KisAnimTimelineFramesModel::mimeData ( const QModelIndexList & indexes) const
override

Definition at line 598 of file KisAnimTimelineFramesModel.cpp.

599{
600 return mimeDataExtended(indexes, m_d->lastClickedIndex, UndefinedPolicy);
601}
QMimeData * mimeDataExtended(const QModelIndexList &indexes, const QModelIndex &baseIndex, MimeCopyPolicy copyPolicy) const

References m_d, mimeDataExtended(), and UndefinedPolicy.

◆ mimeDataExtended()

QMimeData * KisAnimTimelineFramesModel::mimeDataExtended ( const QModelIndexList & indexes,
const QModelIndex & baseIndex,
KisAnimTimelineFramesModel::MimeCopyPolicy copyPolicy ) const

Definition at line 603 of file KisAnimTimelineFramesModel.cpp.

606{
607 QMimeData *data = new QMimeData();
608
609 QByteArray encoded;
610 QDataStream stream(&encoded, QIODevice::WriteOnly);
611
612 const int baseRow = baseIndex.row();
613 const int baseColumn = baseIndex.column();
614
615 const QByteArray uuidDataRoot = m_d->image->root()->uuid().toRfc4122();
616 stream << int(uuidDataRoot.size());
617 stream.writeRawData(uuidDataRoot.data(), uuidDataRoot.size());
618
619 stream << indexes.size();
620 stream << baseRow << baseColumn;
621
622 Q_FOREACH (const QModelIndex &index, indexes) {
623 KisNodeSP node = nodeAt(index);
624 KIS_SAFE_ASSERT_RECOVER(node) { continue; }
625
626 stream << index.row() - baseRow << index.column() - baseColumn;
627
628 const QByteArray uuidData = node->uuid().toRfc4122();
629 stream << int(uuidData.size());
630 stream.writeRawData(uuidData.data(), uuidData.size());
631 }
632
633 stream << int(copyPolicy);
634 data->setData("application/x-krita-frame", encoded);
635
636 return data;
637}

References data(), KIS_SAFE_ASSERT_RECOVER, m_d, nodeAt(), and KisBaseNode::uuid().

◆ mimeTypes()

QStringList KisAnimTimelineFramesModel::mimeTypes ( ) const
override

Definition at line 586 of file KisAnimTimelineFramesModel.cpp.

587{
588 QStringList types;
589 types << QLatin1String("application/x-krita-frame");
590 return types;
591}

◆ nodeAt()

KisNodeSP KisAnimTimelineFramesModel::nodeAt ( QModelIndex index) const
overridevirtual

The dummy might not exist because the user could (quickly) change active layer and the list of the nodes in m_d->converter will change.

Implements KisTimeBasedItemModel.

Definition at line 241 of file KisAnimTimelineFramesModel.cpp.

242{
247 KisNodeDummy *dummy = m_d->converter->dummyFromRow(index.row());
248 return dummy ? dummy->node() : nullptr;
249}

References m_d, and KisNodeDummy::node().

◆ processUpdateQueue

void KisAnimTimelineFramesModel::processUpdateQueue ( )
privateslot

Definition at line 328 of file KisAnimTimelineFramesModel.cpp.

329{
330 if (!m_d->converter) return;
331
332 Q_FOREACH (KisNodeDummy *dummy, m_d->updateQueue) {
333 int row = m_d->converter->rowForDummy(dummy);
334
335 if (row >= 0) {
336 Q_EMIT headerDataChanged (Qt::Vertical, row, row);
337 Q_EMIT dataChanged(this->index(row, 0), this->index(row, columnCount() - 1));
338 }
339 }
340 m_d->updateQueue.clear();
341}

References KisTimeBasedItemModel::columnCount(), and m_d.

◆ removeRows()

bool KisAnimTimelineFramesModel::removeRows ( int row,
int count,
const QModelIndex & parent )
override

Definition at line 835 of file KisAnimTimelineFramesModel.cpp.

836{
837 Q_UNUSED(parent);
838 KIS_ASSERT_RECOVER(count == 1) { return false; }
839
840 if (row < 0 || row >= rowCount()) return false;
841
842 bool result = m_d->removeLayer(row);
843 return result;
844}

References KIS_ASSERT_RECOVER, m_d, and rowCount().

◆ requestCurrentNodeChanged

void KisAnimTimelineFramesModel::requestCurrentNodeChanged ( KisNodeSP node)
signal

◆ requestTransferSelectionBetweenRows

void KisAnimTimelineFramesModel::requestTransferSelectionBetweenRows ( int rowFrom,
int rowTo )
signal

◆ rowCount()

int KisAnimTimelineFramesModel::rowCount ( const QModelIndex & parent = QModelIndex()) const
override

Definition at line 385 of file KisAnimTimelineFramesModel.cpp.

386{
387 Q_UNUSED(parent);
388 if(!m_d->dummiesFacade) return 0;
389
390 return m_d->converter->rowCount();
391}

References m_d.

◆ setActiveLayerSelectedTimes()

void KisAnimTimelineFramesModel::setActiveLayerSelectedTimes ( const QSet< int > & times)

Definition at line 1154 of file KisAnimTimelineFramesModel.cpp.

1155{
1156 if (!m_d->image) return;
1157
1158 m_d->image->animationInterface()->setActiveLayerSelectedTimes(times);
1159}

References m_d.

◆ setAudioChannelFileName()

void KisAnimTimelineFramesModel::setAudioChannelFileName ( const QFileInfo & fileName)

Definition at line 1101 of file KisAnimTimelineFramesModel.cpp.

1102{
1104
1105 QVector<QFileInfo> tracks;
1106 if (fileName.exists()) {
1107 tracks << fileName;
1108 }
1109
1110 document()->setAudioTracks(tracks);
1111}
void setAudioTracks(QVector< QFileInfo > f)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KisTimeBasedItemModel::document(), KIS_SAFE_ASSERT_RECOVER_RETURN, and KisDocument::setAudioTracks().

◆ setAudioMuted()

void KisAnimTimelineFramesModel::setAudioMuted ( bool value)

◆ setAudioVolume()

void KisAnimTimelineFramesModel::setAudioVolume ( qreal value)

◆ setData()

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

Definition at line 438 of file KisAnimTimelineFramesModel.cpp.

439{
440 if (!index.isValid() || !m_d->dummiesFacade) return false;
441
442 switch (role) {
443 case ActiveLayerRole: {
444 if (value.toBool() &&
445 index.row() != m_d->activeLayerIndex) {
446 int prevLayer = m_d->activeLayerIndex;
447 m_d->activeLayerIndex = index.row();
448
449 Q_EMIT dataChanged(this->index(prevLayer, 0), this->index(prevLayer, columnCount() - 1));
450 Q_EMIT dataChanged(this->index(m_d->activeLayerIndex, 0), this->index(m_d->activeLayerIndex, columnCount() - 1));
451
452 Q_EMIT headerDataChanged(Qt::Vertical, prevLayer, prevLayer);
453 Q_EMIT headerDataChanged(Qt::Vertical, m_d->activeLayerIndex, m_d->activeLayerIndex);
454
455 KisNodeDummy *dummy = m_d->converter->dummyFromRow(m_d->activeLayerIndex);
456 KIS_ASSERT_RECOVER(dummy) { return true; }
457
458 Q_EMIT requestCurrentNodeChanged(dummy->node());
459 Q_EMIT sigEnsureRowVisible(m_d->activeLayerIndex);
460 }
461 break;
462 }
464 m_d->setFrameColorLabel(index.row(), index.column(), value.toInt());
465 }
466 break;
467 }
468
469 return ModelWithExternalNotifications::setData(index, value, role);
470}
void requestCurrentNodeChanged(KisNodeSP node)
void sigEnsureRowVisible(int row)

References ActiveLayerRole, KisTimeBasedItemModel::columnCount(), FrameColorLabelIndexRole, KIS_ASSERT_RECOVER, m_d, KisNodeDummy::node(), requestCurrentNodeChanged(), sigEnsureRowVisible(), and value().

◆ setDocumentClipRangeEnd()

void KisAnimTimelineFramesModel::setDocumentClipRangeEnd ( int column)

Definition at line 1144 of file KisAnimTimelineFramesModel.cpp.

1145{
1146 m_d->image->animationInterface()->setDocumentRangeEndFrame(column);
1147}

References m_d.

◆ setDocumentClipRangeStart()

void KisAnimTimelineFramesModel::setDocumentClipRangeStart ( int column)

Definition at line 1139 of file KisAnimTimelineFramesModel.cpp.

1140{
1141 m_d->image->animationInterface()->setDocumentRangeStartFrame(column);
1142}

References m_d.

◆ setDummiesFacade()

void KisAnimTimelineFramesModel::setDummiesFacade ( KisDummiesFacadeBase * dummiesFacade,
KisImageSP image,
KisNodeDisplayModeAdapter * displayModeAdapter )

Definition at line 273 of file KisAnimTimelineFramesModel.cpp.

276{
277 KisDummiesFacadeBase *oldDummiesFacade = m_d->dummiesFacade;
278
279 if (m_d->dummiesFacade && m_d->image) {
280 m_d->image->animationInterface()->disconnect(this);
281 m_d->image->disconnect(this);
282 m_d->dummiesFacade->disconnect(this);
283 }
284
285 m_d->image = image;
287
288 m_d->dummiesFacade = dummiesFacade;
289 m_d->converter.reset();
290
291 if (m_d->dummiesFacade) {
292 m_d->converter.reset(new TimelineNodeListKeeper(this, m_d->dummiesFacade, displayModeAdapter));
293 connect(m_d->dummiesFacade, SIGNAL(sigDummyChanged(KisNodeDummy*)), this, SLOT(slotDummyChanged(KisNodeDummy*)));
294 connect(m_d->image->animationInterface(), SIGNAL(sigPlaybackRangeChanged()), this, SIGNAL(sigInfiniteTimelineUpdateNeeded()));
295 connect(m_d->image, SIGNAL(sigImageModified()), this, SLOT(slotImageContentChanged()));
296 connect(m_d->image, SIGNAL(sigIsolatedModeChanged()), this, SLOT(slotImageContentChanged()));
297 }
298
299 if (m_d->dummiesFacade != oldDummiesFacade) {
300 beginResetModel();
301 endResetModel();
302 }
303
304 if (m_d->dummiesFacade) {
306 slotCurrentTimeChanged(m_d->image->animationInterface()->currentUITime());
307 }
308}
void slotDummyChanged(KisNodeDummy *dummy)
KisImageAnimationInterface * animationInterface() const
void setImage(KisImageWSP image)

References KisImage::animationInterface(), connect(), KisImageAnimationInterface::image(), KisDummiesFacadeBase::image(), KisTimeBasedItemModel::image(), m_d, KisTimeBasedItemModel::setImage(), sigInfiniteTimelineUpdateNeeded(), KisTimeBasedItemModel::slotCurrentTimeChanged(), slotDummyChanged(), and slotImageContentChanged().

◆ setHeaderData()

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

Definition at line 547 of file KisAnimTimelineFramesModel.cpp.

548{
549 if (!m_d->dummiesFacade) return false;
550
551 if (orientation == Qt::Vertical) {
552 switch (role) {
553 case ActiveLayerRole: {
554 setData(index(section, 0), value, role);
555 break;
556 }
559
560 int result = m_d->setLayerProperties(section, props);
561 Q_EMIT headerDataChanged (Qt::Vertical, section, section);
562 return result;
563 }
565 KisNodeDummy *dummy = m_d->converter->dummyFromRow(section);
566 if (!dummy) return false;
567 dummy->node()->setPinnedToTimeline(value.toBool());
568 return true;
569 }
570 }
571 }
572
573 return ModelWithExternalNotifications::setHeaderData(section, orientation, value, role);
574}
void setPinnedToTimeline(bool pinned)

References ActiveLayerRole, m_d, KisNodeDummy::node(), PinnedToTimelineRole, setData(), KisBaseNode::setPinnedToTimeline(), TimelinePropertiesRole, and value().

◆ setLastClickedIndex()

void KisAnimTimelineFramesModel::setLastClickedIndex ( const QModelIndex & index)

Definition at line 593 of file KisAnimTimelineFramesModel.cpp.

594{
595 m_d->lastClickedIndex = index;
596}

References m_d.

◆ setNodeManipulationInterface()

void KisAnimTimelineFramesModel::setNodeManipulationInterface ( NodeManipulationInterface * iface)

NOTE: the model has an ownership over the interface, that is it'll be deleted automatically later

Definition at line 236 of file KisAnimTimelineFramesModel.cpp.

237{
238 m_d->nodeInterface.reset(iface);
239}

References m_d.

◆ sigEnsureRowVisible

void KisAnimTimelineFramesModel::sigEnsureRowVisible ( int row)
signal

◆ sigFullClipRangeChanged

void KisAnimTimelineFramesModel::sigFullClipRangeChanged ( )
signal

◆ sigInfiniteTimelineUpdateNeeded

void KisAnimTimelineFramesModel::sigInfiniteTimelineUpdateNeeded ( )
signal

◆ slotCurrentNodeChanged

void KisAnimTimelineFramesModel::slotCurrentNodeChanged ( KisNodeSP node)
slot

Definition at line 343 of file KisAnimTimelineFramesModel.cpp.

344{
345 if (!node) {
346 m_d->activeLayerIndex = -1;
347 return;
348 }
349
350 KisNodeDummy *dummy = m_d->dummiesFacade->dummyForNode(node);
351 if (!dummy) {
352 // It's perfectly normal that dummyForNode returns 0; that happens
353 // when views get activated while Krita is closing down.
354 return;
355 }
356
357 int lastActiveLayerIndex = m_d->activeLayerIndex;
358 const bool prevActiveWasPinned = headerData(m_d->activeLayerIndex, Qt::Vertical, PinnedToTimelineRole).toBool();
359 m_d->converter->updateActiveDummy(dummy);
360
361 const int row = m_d->converter->rowForDummy(dummy);
362 if (row < 0) {
363 qWarning() << "WARNING: TimelineFramesModel::slotCurrentNodeChanged: node not found!";
364 }
365
366 if (row >= 0 && m_d->activeLayerIndex != row) {
367 setData(index(row, 0), true, ActiveLayerRole);
368 } else if (row >= 0 ){
370
371 // If the activeLayerIndex is considered to be the same "row", but the last one was pinned,
372 // it means that the previousActiveLayer has actually moved down the list because a new
373 // layer was inserted.
374 if (prevActiveWasPinned) {
375 lastActiveLayerIndex += 1;
376 }
377 }
378
379 // NOTE: Not in love with exposing 'selection' concepts to the model,
380 // but since this issue already existed, this is alright for now.
381 // Especially since it's just a signal...
382 requestTransferSelectionBetweenRows(lastActiveLayerIndex, m_d->activeLayerIndex);
383}
void requestTransferSelectionBetweenRows(int rowFrom, int rowTo)

References ActiveLayerRole, headerData(), m_d, PinnedToTimelineRole, requestTransferSelectionBetweenRows(), setData(), and sigEnsureRowVisible().

◆ slotDummyChanged

void KisAnimTimelineFramesModel::slotDummyChanged ( KisNodeDummy * dummy)
privateslot

Definition at line 310 of file KisAnimTimelineFramesModel.cpp.

311{
312 if (!m_d->updateQueue.contains(dummy)) {
313 m_d->updateQueue.append(dummy);
314 }
315 m_d->updateTimer.start();
316}

References m_d.

◆ slotImageContentChanged

void KisAnimTimelineFramesModel::slotImageContentChanged ( )
privateslot

Definition at line 318 of file KisAnimTimelineFramesModel.cpp.

319{
320 if (m_d->activeLayerIndex < 0) return;
321
322 KisNodeDummy *dummy = m_d->converter->dummyFromRow(m_d->activeLayerIndex);
323 if (!dummy) return;
324
325 slotDummyChanged(dummy);
326}

References m_d, and slotDummyChanged().

◆ supportedDragActions()

Qt::DropActions KisAnimTimelineFramesModel::supportedDragActions ( ) const
override

Definition at line 576 of file KisAnimTimelineFramesModel.cpp.

577{
578 return Qt::MoveAction | Qt::CopyAction | Qt::LinkAction;
579}

◆ supportedDropActions()

Qt::DropActions KisAnimTimelineFramesModel::supportedDropActions ( ) const
override

Definition at line 581 of file KisAnimTimelineFramesModel.cpp.

582{
583 return Qt::MoveAction | Qt::CopyAction | Qt::LinkAction;
584}

Member Data Documentation

◆ m_d

const QScopedPointer<Private> KisAnimTimelineFramesModel::m_d
private

Definition at line 165 of file KisAnimTimelineFramesModel.h.


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