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
 
void requestNodeChange (const QModelIndex &nodeIndex)
 
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 Member Functions

void emitRowDataChanged (int row)
 

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}
const QScopedPointer< Private > m_d

References 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 868 of file KisAnimTimelineFramesModel.cpp.

869{
870 return m_d->activeLayerIndex;
871}

References m_d.

◆ audioChannelFileName()

QString KisAnimTimelineFramesModel::audioChannelFileName ( ) const

Definition at line 1096 of file KisAnimTimelineFramesModel.cpp.

1097{
1098 if (document()) {
1100 if (files.count() > 0) {
1101 return files.first().baseName();
1102 }
1103 }
1104 return QString("");
1105}
QVector< QFileInfo > getAudioTracks() const
KisDocument * document() const

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

◆ audioVolume()

qreal KisAnimTimelineFramesModel::audioVolume ( ) const

Definition at line 1130 of file KisAnimTimelineFramesModel.cpp.

1131{
1132 if (document()) {
1133 return document()->getAudioLevel();
1134 } else {
1135 return 1.0;
1136 }
1137}
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 1155 of file KisAnimTimelineFramesModel.cpp.

1156{
1157 m_d->image->animationInterface()->invalidateFrames(KisTimeSpan::infinite(0), m_d->image->bounds());
1158}
static KisTimeSpan infinite(int start)

References KisTimeSpan::infinite(), and m_d.

◆ copyFrame()

bool KisAnimTimelineFramesModel::copyFrame ( const QModelIndex & dstIndex)

Definition at line 905 of file KisAnimTimelineFramesModel.cpp.

906{
907 if (!dstIndex.isValid()) return false;
908
909 return m_d->addKeyframe(dstIndex.row(), dstIndex.column(), true);
910}

References m_d.

◆ createFrame()

bool KisAnimTimelineFramesModel::createFrame ( const QModelIndexList & dstIndex)

Definition at line 873 of file KisAnimTimelineFramesModel.cpp.

874{
875 QList<QPair<int,int>> selectedCells;
876
877 Q_FOREACH(const QModelIndex &index, dstIndex){
878 if (!index.isValid()) continue;
879 selectedCells.append(QPair<int,int>(index.row(), index.column()));
880 }
881
882 if (selectedCells.size() == 0) {
883 return false;
884 }
885
886 KUndo2Command *parentCommand = new KUndo2Command(kundo2_i18np("Add blank frame", "Add %1 blank frames", selectedCells.size()));
887
888 Q_FOREACH (auto &cell, selectedCells) {
889 KisNodeDummy *dummy = m_d->converter->dummyFromRow(cell.first);
890 if (!dummy) continue;
891
892 KisNodeSP node = dummy->node();
893 if (!KisAnimUtils::supportsContentFrames(node)) continue;
894
895 KisAnimUtils::createKeyframeCommand(m_d->image, node, KisKeyframeChannel::Raster.id(), cell.second, false, parentCommand);
896 }
897
901
902 return true;
903}
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()->createPreferredThumbnailForFrame(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.
QImage createPreferredThumbnailForFrame(qint32 w, qint32 h, int time, Qt::AspectRatioMode aspectRatioMode=Qt::IgnoreAspectRatio)

References ActiveLayerRole, KisBaseNode::createPreferredThumbnailForFrame(), 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:459
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.

◆ emitRowDataChanged()

void KisAnimTimelineFramesModel::emitRowDataChanged ( int row)
private

Definition at line 1167 of file KisAnimTimelineFramesModel.cpp.

1168{
1169 int rows = rowCount();
1170 int cols = columnCount();
1171 if (row >= 0 && row < rows && cols > 0) {
1172 Q_EMIT dataChanged(index(row, 0), index(row, cols - 1));
1173 }
1174}
int rowCount(const QModelIndex &parent=QModelIndex()) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override

References KisTimeBasedItemModel::columnCount(), and rowCount().

◆ 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 926 of file KisAnimTimelineFramesModel.cpp.

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

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 975 of file KisAnimTimelineFramesModel.cpp.

976{
977 if (selectedIndexes.isEmpty() || insertCount == 0) return true;
978
979 QScopedPointer<KUndo2Command> parentCommand(new KUndo2Command(kundo2_i18np("Insert frame", "Insert %1 frames", insertCount)));
980
981 {
982 KisImageBarrierLock locker(m_d->image);
983
984 // Find Keyframes in selection...
985 QSet<TimelineSelectionEntry> uniqueKeyframesInSelection;
986 int earliestAffectedTime = std::numeric_limits<int>::max();
987
988 Q_FOREACH (const QModelIndex &index, selectedIndexes) {
989 KisNodeSP node = nodeAt(index);
990 KIS_SAFE_ASSERT_RECOVER(node) { continue; }
991
993 if (!channel) continue;
994
995 earliestAffectedTime = qMin(earliestAffectedTime, index.column()); // Earliest of selection... (to be continued.)
996
997 int time = channel->activeKeyframeTime(index.column());
998 KisRasterKeyframeSP keyframe = channel->activeKeyframeAt<KisRasterKeyframe>(index.column());
999
1000 if (keyframe) {
1001 uniqueKeyframesInSelection.insert(TimelineSelectionEntry{channel, time, keyframe});
1002 }
1003 }
1004
1005 // Determine which keyframes need to move and sort by time...
1006 QList<TimelineSelectionEntry> keyframesToMove;
1007
1008 for (auto it = uniqueKeyframesInSelection.begin(); it != uniqueKeyframesInSelection.end(); ++it) {
1009 TimelineSelectionEntry keyframeEntry = *it;
1010
1011 KisRasterKeyframeChannel *channel = keyframeEntry.channel;
1012 int nextKeyframeTime = channel->nextKeyframeTime(keyframeEntry.time);
1013 KisRasterKeyframeSP nextKeyframe = channel->keyframeAt<KisRasterKeyframe>(nextKeyframeTime);
1014
1015 if (nextKeyframe) {
1016 keyframesToMove << TimelineSelectionEntry{ channel, nextKeyframeTime, nextKeyframe };
1017 }
1018 }
1019
1020 std::sort(keyframesToMove.begin(), keyframesToMove.end(),
1022 return lhs.time > rhs.time;
1023 });
1024
1025 if (keyframesToMove.isEmpty()) return true;
1026
1027 const int oldTime = m_d->image->animationInterface()->currentUITime();
1028 const int maxColumn = columnCount();
1029
1030 // Store the original active keyframe, so we can switch to its new time at the end.
1031 // (This helps to keep artist drawing on the right keyframe even while adding and removing hold frames.)
1032 QModelIndex activeIndex = index(m_d->activeLayerIndex, oldTime);
1033 KisNodeSP activeNode = nodeAt(activeIndex);
1035
1036 KisRasterKeyframeSP originalActiveKeyframe = nullptr;
1037 if (activeChannel) {
1038 originalActiveKeyframe = activeChannel->activeKeyframeAt<KisRasterKeyframe>(oldTime);
1039 }
1040
1041 // Create keyframe movement commands...
1042 if (insertCount > 0) {
1043 setLastVisibleFrame(columnCount() + insertCount);
1044 }
1045
1046 Q_FOREACH (TimelineSelectionEntry entry, keyframesToMove) {
1047 int plannedFrameMove = insertCount;
1048
1049 if (insertCount < 0) {
1051
1052 int prevKeyframeTime = entry.channel->previousKeyframeTime(entry.time);
1053 KisRasterKeyframeSP prevFrame = entry.channel->keyframeAt<KisRasterKeyframe>(prevKeyframeTime);
1054 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(prevFrame, false);
1055
1056 // Clamp values so that they never exceed or overlap the previous frame
1057 plannedFrameMove = qMax(insertCount, prevKeyframeTime - entry.time + 1);
1058
1059 earliestAffectedTime = qMin(earliestAffectedTime, prevKeyframeTime); // No longer limited to selection.
1060 }
1061
1062 KisNodeDummy *dummy = m_d->dummiesFacade->dummyForNode(entry.channel->node());
1063 KIS_SAFE_ASSERT_RECOVER(dummy) { continue; }
1064
1065 const int row = m_d->converter->rowForDummy(dummy);
1066 KIS_SAFE_ASSERT_RECOVER(row >= 0) { continue; }
1067
1068 QModelIndexList indices;
1069 for (int column = entry.time; column < maxColumn; column++) {
1070 indices << index(row, column);
1071 }
1072
1074 QPoint(plannedFrameMove, 0),
1075 false,
1076 true,
1077 parentCommand.data());
1078 }
1079
1080 if (originalActiveKeyframe) {
1081 new KisSwitchCurrentTimeToKeyframeCommand(m_d->image->animationInterface(),
1082 oldTime,
1083 activeNode,
1085 originalActiveKeyframe,
1086 parentCommand.data());
1087 }
1088 }
1089
1090 KisProcessingApplicator::runSingleCommandStroke(m_d->image, parentCommand.take(),
1093 return true;
1094}
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 852 of file KisAnimTimelineFramesModel.cpp.

853{
854 Q_UNUSED(dstRow);
855
857 m_d->converter->otherLayersList();
858
859 if (index < 0 || index >= list.size()) return false;
860
861 list[index].dummy->node()->setPinnedToTimeline(true);
862 dstRow = m_d->converter->rowForDummy(list[index].dummy);
863 setData(this->index(dstRow, 0), true, ActiveLayerRole);
864
865 return true;
866}
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}
#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 1119 of file KisAnimTimelineFramesModel.cpp.

1120{
1121 return KisPart::instance()->playbackEngine()->isMute();
1122}
QScopedPointer< KisPlaybackEngine > playbackEngine
Definition KisPart.cpp:111

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

◆ makeClonesUnique()

void KisAnimTimelineFramesModel::makeClonesUnique ( const QModelIndexList & indices)

Definition at line 912 of file KisAnimTimelineFramesModel.cpp.

913{
915
916 Q_FOREACH (const QModelIndex &index, indices) {
917 const int time = index.column();
919 if (!channel) continue;
920 frameItems << KisAnimUtils::FrameItem(channel->node(), channel->id(), time);
921 }
922
923 KisAnimUtils::makeClonesUnique(m_d->image, frameItems);
924}
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 << int(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);
338 }
339 }
340 m_d->updateQueue.clear();
341}

References emitRowDataChanged(), 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

◆ requestNodeChange()

void KisAnimTimelineFramesModel::requestNodeChange ( const QModelIndex & nodeIndex)

Definition at line 846 of file KisAnimTimelineFramesModel.cpp.

847{
848 KisNodeSP node = nodeAt(nodeIndex);
849 Q_EMIT requestCurrentNodeChanged(node);
850}
void requestCurrentNodeChanged(KisNodeSP node)

References nodeAt(), and requestCurrentNodeChanged().

◆ 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 1160 of file KisAnimTimelineFramesModel.cpp.

1161{
1162 if (!m_d->image) return;
1163
1164 m_d->image->animationInterface()->setActiveLayerSelectedTimes(times);
1165}

References m_d.

◆ setAudioChannelFileName()

void KisAnimTimelineFramesModel::setAudioChannelFileName ( const QFileInfo & fileName)

Definition at line 1107 of file KisAnimTimelineFramesModel.cpp.

1108{
1110
1111 QVector<QFileInfo> tracks;
1112 if (fileName.exists()) {
1113 tracks << fileName;
1114 }
1115
1116 document()->setAudioTracks(tracks);
1117}
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 emitRowDataChanged(prevLayer);
450 emitRowDataChanged(m_d->activeLayerIndex);
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 sigEnsureRowVisible(int row)

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

◆ setDocumentClipRangeEnd()

void KisAnimTimelineFramesModel::setDocumentClipRangeEnd ( int column)

Definition at line 1150 of file KisAnimTimelineFramesModel.cpp.

1151{
1152 m_d->image->animationInterface()->setDocumentRangeEndFrame(column);
1153}

References m_d.

◆ setDocumentClipRangeStart()

void KisAnimTimelineFramesModel::setDocumentClipRangeStart ( int column)

Definition at line 1145 of file KisAnimTimelineFramesModel.cpp.

1146{
1147 m_d->image->animationInterface()->setDocumentRangeStartFrame(column);
1148}

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(), 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 169 of file KisAnimTimelineFramesModel.h.


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