diff --git a/krita/krita.action b/krita/krita.action --- a/krita/krita.action +++ b/krita/krita.action @@ -2141,24 +2141,11 @@ - - - Insert Keyframe Right - - Insert keyframes to the right of selection moving the tail of animation to the right - - 100000 - 0 - - false - - - - + Insert Keyframe Left - Insert keyframes to the left of selection moving the tail of animation to the right + Insert keyframes to the left of selection, moving the tail of animation to the right. 100000 0 @@ -2167,11 +2154,11 @@ - + - Insert N Keyframes Right + Insert Keyframe Right - Insert several keyframes to the right of selection moving the tail of animation to the right + Insert keyframes to the right of selection, moving the tail of animation to the right. 100000 0 @@ -2180,11 +2167,11 @@ - + - Insert N Keyframes Left + Insert Multiple Keyframes - Insert several keyframes to the left of selection moving the tail of animation to the right + Insert several keyframes based on user parameters. 100000 0 @@ -2219,24 +2206,11 @@ - - - Insert Column Right - - Insert column to the right of selection moving the tail of animation to the right - - 100000 - 0 - - false - - - - + Insert Column Left - Insert column to the left of selection moving the tail of animation to the right + Insert column to the left of selection, moving the tail of animation to the right 100000 0 @@ -2245,11 +2219,11 @@ - + - Insert N Columns Right + Insert Column Right - Insert several columns to the right of selection moving the tail of animation to the right + Insert column to the right of selection, moving the tail of animation to the right 100000 0 @@ -2258,11 +2232,11 @@ - + - Insert N Columns Left + Insert Multiple Columns - Insert several columns to the left of selection moving the tail of animation to the right + Insert several columns based on user parameters. 100000 0 @@ -2310,9 +2284,9 @@ - + - Insert N Hold Frames + Insert Multiple Hold Frames Insert N hold frames after every keyframe @@ -2336,9 +2310,9 @@ - + - Remove N Hold Frames + Remove Multiple Hold Frames Remove N hold frames after every keyframe @@ -2362,9 +2336,9 @@ - + - Insert N Hold Columns + Insert Multiple Hold Columns Insert N hold columns into the frame at the current position @@ -2388,9 +2362,9 @@ - + - Remove N Hold Columns + Remove Multiple Hold Columns Remove N hold columns from the frame at the current position diff --git a/plugins/dockers/animation/kis_time_based_item_model.cpp b/plugins/dockers/animation/kis_time_based_item_model.cpp --- a/plugins/dockers/animation/kis_time_based_item_model.cpp +++ b/plugins/dockers/animation/kis_time_based_item_model.cpp @@ -304,7 +304,7 @@ } Q_FOREACH(KisKeyframeChannel *channel, channelsAt(srcIndex)) { - if (moveEmptyFrames || channel->keyframeAt(srcIndex.column())) { + if (moveEmptyFrames || channel->keyframeAt(srcIndex.column())) { srcFrameItems << KisAnimationUtils::FrameItem(srcNode, channel->id(), srcIndex.column()); dstFrameItems << KisAnimationUtils::FrameItem(dstNode, channel->id(), dstIndex.column()); } @@ -350,8 +350,8 @@ new KisSwitchCurrentTimeCommand(m_d->image->animationInterface(), oldTime, - newTime, parentCommand); - + newTime, + parentCommand); } KisProcessingApplicator::runSingleCommandStroke(m_d->image, parentCommand, KisStrokeJobData::BARRIER); diff --git a/plugins/dockers/animation/timeline_frames_model.h b/plugins/dockers/animation/timeline_frames_model.h --- a/plugins/dockers/animation/timeline_frames_model.h +++ b/plugins/dockers/animation/timeline_frames_model.h @@ -19,6 +19,7 @@ #ifndef __TIMELINE_FRAMES_MODEL_H #define __TIMELINE_FRAMES_MODEL_H + #include #include @@ -86,9 +87,9 @@ Qt::DropActions supportedDragActions() const override; Qt::DropActions supportedDropActions() const override; QStringList mimeTypes() const override; - QMimeData * mimeData(const QModelIndexList &indexes) const override; - QMimeData * mimeDataExtended(const QModelIndexList &indexes, const QModelIndex &baseIndex, MimeCopyPolicy copyPolicy) const; - bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent) override; + QMimeData *mimeData(const QModelIndexList &indexes) const override; + QMimeData *mimeDataExtended(const QModelIndexList &indexes, const QModelIndex &baseIndex, MimeCopyPolicy copyPolicy) const; + 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); diff --git a/plugins/dockers/animation/timeline_frames_view.h b/plugins/dockers/animation/timeline_frames_view.h --- a/plugins/dockers/animation/timeline_frames_view.h +++ b/plugins/dockers/animation/timeline_frames_view.h @@ -19,6 +19,7 @@ #ifndef __TIMELINE_FRAMES_VIEW_H #define __TIMELINE_FRAMES_VIEW_H + #include #include #include "kis_action_manager.h" @@ -27,9 +28,20 @@ class KisAction; class TimelineWidget; +enum TimelineDirection : short +{ + LEFT = -1, + BEFORE = -1, + + RIGHT = 1, + AFTER = 1 +}; + + class KRITAANIMATIONDOCKER_EXPORT TimelineFramesView : public QTableView { Q_OBJECT + public: TimelineFramesView(QWidget *parent); ~TimelineFramesView() override; @@ -40,7 +52,7 @@ void setShowInTimeline(KisAction *action); - void setActionManager( KisActionManager * actionManager); + void setActionManager(KisActionManager *actionManager); public Q_SLOTS: void slotSelectionChanged(); @@ -61,51 +73,49 @@ void slotRemoveLayer(); void slotLayerContextMenuRequested(const QPoint &globalPos); - // New, Copy, Insert and Remove Frames - void slotNewFrame(); - void slotCopyFrame(); - - void slotInsertKeyframesLeft(int count = 1, int timing = 1, bool forceEntireColumn = false); - void slotInsertKeyframesRight(int count = 1, int timing = 1, bool forceEntireColumn = false); + // New, Insert and Remove Frames + void slotAddBlankFrame(); + void slotAddDuplicateFrame(); - void slotInsertKeyframesLeftCustom(); - void slotInsertKeyframesRightCustom(); + void slotInsertKeyframeLeft() {insertKeyframes(-1, 1, TimelineDirection::LEFT, false);} + void slotInsertKeyframeRight() {insertKeyframes(-1, 1, TimelineDirection::RIGHT, false);} - void slotRemoveFrame(bool forceEntireColumn = false, bool needsOffset = false); - void slotRemoveFramesAndShift(bool forceEntireColumn = false); + void slotInsertKeyframeColumnLeft() {insertKeyframes(-1, 1, TimelineDirection::LEFT, true);} + void slotInsertKeyframeColumnRight() {insertKeyframes(-1, 1, TimelineDirection::RIGHT, true);} - void slotInsertColumnsLeft(int count = 1, int timing = 1); - void slotInsertColumnsLeftCustom(); + void slotInsertMultipleKeyframes() {insertMultipleKeyframes(false);} + void slotInsertMultipleKeyframeColumns() {insertMultipleKeyframes(true);} - void slotInsertColumnsRight(int count = 1, int timing = 1); - void slotInsertColumnsRightCustom(); + void slotRemoveSelectedFrames(bool entireColumn = false, bool needsOffset = false); + void slotRemoveSelectedFramesAndShift() {slotRemoveSelectedFrames(false, true);} - void slotRemoveColumns(); - void slotRemoveColumnsAndShift(); + void slotRemoveSelectedColumns() {slotRemoveSelectedFrames(true);} + void slotRemoveSelectedColumnsAndShift() {slotRemoveSelectedFrames(true, true);} - void slotInsertHoldFrames(int count = 1, bool forceEntireColumn = false); - void slotRemoveHoldFrames(int count = 1, bool forceEntireColumn = false); + void slotInsertHoldFrame() {insertOrRemoveHoldFrames(1);} + void slotRemoveHoldFrame() {insertOrRemoveHoldFrames(-1);} - void slotInsertHoldFramesCustom(); - void slotRemoveHoldFramesCustom(); + void slotInsertHoldFrameColumn() {insertOrRemoveHoldFrames(1,true);} + void slotRemoveHoldFrameColumn() {insertOrRemoveHoldFrames(-1,true);} - void slotInsertHoldColumns(int count = 1); - void slotRemoveHoldColumns(int count = 1); + void slotInsertMultipleHoldFrames() {insertOrRemoveMultipleHoldFrames(true);} + void slotRemoveMultipleHoldFrames() {insertOrRemoveMultipleHoldFrames(false);} - void slotInsertHoldColumnsCustom(); - void slotRemoveHoldColumnsCustom(); + void slotInsertMultipleHoldFrameColumns() {insertOrRemoveMultipleHoldFrames(true, true);} + void slotRemoveMultipleHoldFrameColumns() {insertOrRemoveMultipleHoldFrames(false, true);} - void slotMirrorFrames(bool forceEntireColumn = false); - void slotMirrorColumns(); + void slotMirrorFrames(bool entireColumn = false); + void slotMirrorColumns() {slotMirrorFrames(true);} // Copy-paste - void slotCopyFrames(bool forceEntireColumn = false); - void slotCutFrames(bool forceEntireColumn = false); - void slotPasteFrames(bool forceEntireColumn = false); + void slotCopyFrames() {cutCopyImpl(false, true);} + void slotCutFrames() {cutCopyImpl(false, false);} + + void slotCopyColumns() {cutCopyImpl(true, true);} + void slotCutColumns() {cutCopyImpl(true, false);} - void slotCopyColumns(); - void slotCutColumns(); - void slotPasteColumns(); + void slotPasteFrames(bool entireColumn = false); + void slotPasteColumns() {slotPasteFrames(true);} void slotReselectCurrentIndex(); @@ -128,14 +138,28 @@ private: void setFramesPerSecond(int fps); + void calculateSelectionMetrics(int &minColumn, int &maxColumn, QSet &rows) const; - void insertFramesImpl(int insertAtColumn, int count, int timing, QSet rows, bool forceEntireColumn); + /* Insert new keyframes/columns. + * + * count - Number of frames to add. If <0, use number of currently SELECTED frames. + * timing - Animation timing of frames to be added (on 1s, 2s, 3s, etc.) + * direction - Insert frames before (left) or after (right) selection scrubber. + * entireColumn - Create frames on all layers (rows) instead of just the active layer? + */ + void insertKeyframes(int count = 1, int timing = 1, + TimelineDirection direction = TimelineDirection::LEFT, bool entireColumn = false); + void insertMultipleKeyframes(bool entireColumn = false); + + void insertOrRemoveHoldFrames(int count, bool entireColumn = false); + void insertOrRemoveMultipleHoldFrames(bool insertion, bool entireColumn = false); + + void cutCopyImpl(bool entireColumn, bool copy); void createFrameEditingMenuActions(QMenu *menu, bool addFrameCreationActions); - QModelIndexList calculateSelectionSpan(bool forceEntireColumn, bool editableOnly = true) const; - void cutCopyImpl(bool forceEntireColumn, bool copy); + QModelIndexList calculateSelectionSpan(bool entireColumn, bool editableOnly = true) const; int defaultNumberOfFramesToAdd() const; void setDefaultNumberOfFramesToAdd(int value) const; @@ -163,7 +187,7 @@ void mouseMoveEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; void wheelEvent(QWheelEvent *e) override; - void rowsInserted(const QModelIndex& parent, int start, int end) override; + void rowsInserted(const QModelIndex &parent, int start, int end) override; bool viewportEvent(QEvent *event) override; private: diff --git a/plugins/dockers/animation/timeline_frames_view.cpp b/plugins/dockers/animation/timeline_frames_view.cpp --- a/plugins/dockers/animation/timeline_frames_view.cpp +++ b/plugins/dockers/animation/timeline_frames_view.cpp @@ -19,38 +19,25 @@ #include "timeline_frames_view.h" #include "timeline_frames_model.h" - #include "timeline_ruler_header.h" #include "timeline_layers_header.h" #include "timeline_insert_keyframe_dialog.h" - -#include -#include +#include "timeline_frames_item_delegate.h" #include - -#include #include -#include #include -#include #include #include -#include #include -#include -#include -#include +#include +#include +#include #include "KSharedConfig" -#include "kis_debug.h" -#include "timeline_frames_item_delegate.h" - #include "kis_zoom_button.h" - #include "kis_icon_utils.h" - #include "kis_animation_utils.h" #include "kis_custom_modifiers_catcher.h" #include "kis_action.h" @@ -59,17 +46,11 @@ #include "kis_color_label_selector_widget.h" #include "kis_slider_spin_box.h" #include +#include +#include #include #include -#include -#include -#include - -#include -#include - -#include "config-qtmultimedia.h" typedef QPair QItemViewPaintPair; typedef QList QItemViewPaintPairs; @@ -134,7 +115,7 @@ KoIconToolTip tip; - KisActionManager * actionMan = 0; + KisActionManager *actionMan = 0; }; TimelineFramesView::TimelineFramesView(QWidget *parent) @@ -160,20 +141,19 @@ m_d->horizontalRuler = new TimelineRulerHeader(this); this->setHorizontalHeader(m_d->horizontalRuler); - connect(m_d->horizontalRuler, SIGNAL(sigInsertColumnsLeft()), SLOT(slotInsertColumnsLeft())); - connect(m_d->horizontalRuler, SIGNAL(sigInsertColumnsRight()), SLOT(slotInsertColumnsRight())); + connect(m_d->horizontalRuler, SIGNAL(sigInsertColumnLeft()), SLOT(slotInsertKeyframeColumnLeft())); + connect(m_d->horizontalRuler, SIGNAL(sigInsertColumnRight()), SLOT(slotInsertKeyframeColumnRight())); - connect(m_d->horizontalRuler, SIGNAL(sigInsertColumnsLeftCustom()), SLOT(slotInsertColumnsLeftCustom())); - connect(m_d->horizontalRuler, SIGNAL(sigInsertColumnsRightCustom()), SLOT(slotInsertColumnsRightCustom())); + connect(m_d->horizontalRuler, SIGNAL(sigInsertMultipleColumns()), SLOT(slotInsertMultipleKeyframeColumns())); - connect(m_d->horizontalRuler, SIGNAL(sigRemoveColumns()), SLOT(slotRemoveColumns())); - connect(m_d->horizontalRuler, SIGNAL(sigRemoveColumnsAndShift()), SLOT(slotRemoveColumnsAndShift())); + connect(m_d->horizontalRuler, SIGNAL(sigRemoveColumns()), SLOT(slotRemoveSelectedColumns())); + connect(m_d->horizontalRuler, SIGNAL(sigRemoveColumnsAndShift()), SLOT(slotRemoveSelectedColumnsAndShift())); - connect(m_d->horizontalRuler, SIGNAL(sigInsertHoldColumns()), SLOT(slotInsertHoldColumns())); - connect(m_d->horizontalRuler, SIGNAL(sigRemoveHoldColumns()), SLOT(slotRemoveHoldColumns())); + connect(m_d->horizontalRuler, SIGNAL(sigInsertHoldColumns()), SLOT(slotInsertHoldFrameColumn())); + connect(m_d->horizontalRuler, SIGNAL(sigRemoveHoldColumns()), SLOT(slotRemoveHoldFrameColumn())); - connect(m_d->horizontalRuler, SIGNAL(sigInsertHoldColumnsCustom()), SLOT(slotInsertHoldColumnsCustom())); - connect(m_d->horizontalRuler, SIGNAL(sigRemoveHoldColumnsCustom()), SLOT(slotRemoveHoldColumnsCustom())); + connect(m_d->horizontalRuler, SIGNAL(sigInsertHoldColumnsCustom()), SLOT(slotInsertMultipleHoldFrameColumns())); + connect(m_d->horizontalRuler, SIGNAL(sigRemoveHoldColumnsCustom()), SLOT(slotRemoveMultipleHoldFrameColumns())); connect(m_d->horizontalRuler, SIGNAL(sigMirrorColumns()), SLOT(slotMirrorColumns())); @@ -305,13 +285,13 @@ { } -void TimelineFramesView::setShowInTimeline(KisAction* action) +void TimelineFramesView::setShowInTimeline(KisAction *action) { m_d->showHideLayerAction = action; m_d->layerEditingMenu->addAction(m_d->showHideLayerAction); } -void TimelineFramesView::setActionManager( KisActionManager * actionManager) +void TimelineFramesView::setActionManager(KisActionManager *actionManager) { m_d->actionMan = actionManager; m_d->horizontalRuler->setActionManager(actionManager); @@ -321,40 +301,37 @@ KisAction *action = 0; action = m_d->actionMan->createAction("add_blank_frame"); - connect(action, SIGNAL(triggered()), SLOT(slotNewFrame())); + connect(action, SIGNAL(triggered()), SLOT(slotAddBlankFrame())); action = m_d->actionMan->createAction("add_duplicate_frame"); - connect(action, SIGNAL(triggered()), SLOT(slotCopyFrame())); - - action = m_d->actionMan->createAction("insert_keyframes_right"); - connect(action, SIGNAL(triggered()), SLOT(slotInsertKeyframesRight())); + connect(action, SIGNAL(triggered()), SLOT(slotAddDuplicateFrame())); - action = m_d->actionMan->createAction("insert_n_keyframes_right"); - connect(action, SIGNAL(triggered()), SLOT(slotInsertKeyframesRightCustom())); + action = m_d->actionMan->createAction("insert_keyframe_left"); + connect(action, SIGNAL(triggered()), SLOT(slotInsertKeyframeLeft())); - action = m_d->actionMan->createAction("insert_keyframes_left"); - connect(action, SIGNAL(triggered()), SLOT(slotInsertKeyframesLeft())); + action = m_d->actionMan->createAction("insert_keyframe_right"); + connect(action, SIGNAL(triggered()), SLOT(slotInsertKeyframeRight())); - action = m_d->actionMan->createAction("insert_n_keyframes_left"); - connect(action, SIGNAL(triggered()), SLOT(slotInsertKeyframesLeftCustom())); + action = m_d->actionMan->createAction("insert_multiple_keyframes"); + connect(action, SIGNAL(triggered()), SLOT(slotInsertMultipleKeyframes())); action = m_d->actionMan->createAction("remove_frames_and_pull"); - connect(action, SIGNAL(triggered()), SLOT(slotRemoveFramesAndShift())); + connect(action, SIGNAL(triggered()), SLOT(slotRemoveSelectedFramesAndShift())); action = m_d->actionMan->createAction("remove_frames"); - connect(action, SIGNAL(triggered()), SLOT(slotRemoveFrame())); + connect(action, SIGNAL(triggered()), SLOT(slotRemoveSelectedFrames())); action = m_d->actionMan->createAction("insert_hold_frame"); - connect(action, SIGNAL(triggered()), SLOT(slotInsertHoldFrames())); + connect(action, SIGNAL(triggered()), SLOT(slotInsertHoldFrame())); - action = m_d->actionMan->createAction("insert_n_hold_frames"); - connect(action, SIGNAL(triggered()), SLOT(slotInsertHoldFramesCustom())); + action = m_d->actionMan->createAction("insert_multiple_hold_frames"); + connect(action, SIGNAL(triggered()), SLOT(slotInsertMultipleHoldFrames())); action = m_d->actionMan->createAction("remove_hold_frame"); - connect(action, SIGNAL(triggered()), SLOT(slotRemoveHoldFrames())); + connect(action, SIGNAL(triggered()), SLOT(slotRemoveHoldFrame())); - action = m_d->actionMan->createAction("remove_n_hold_frames"); - connect(action, SIGNAL(triggered()), SLOT(slotRemoveHoldFramesCustom())); + action = m_d->actionMan->createAction("remove_multiple_hold_frames"); + connect(action, SIGNAL(triggered()), SLOT(slotRemoveMultipleHoldFrames())); action = m_d->actionMan->createAction("mirror_frames"); connect(action, SIGNAL(triggered()), SLOT(slotMirrorFrames())); @@ -722,7 +699,6 @@ QTableView::rowsInserted(parent, start, end); } - inline bool isIndexDragEnabled(QAbstractItemModel *model, const QModelIndex &index) { return (model->flags(index) & Qt::ItemIsDragEnabled); } @@ -948,40 +924,44 @@ if (selectionExists) { - KisActionManager::safePopulateMenu(menu, "update_playback_range", m_d->actionMan); + KisActionManager::safePopulateMenu(menu, "update_playback_range", m_d->actionMan); } else { KisActionManager::safePopulateMenu(menu, "set_start_time", m_d->actionMan); KisActionManager::safePopulateMenu(menu, "set_end_time", m_d->actionMan); } - menu->addSeparator(); + menu->addSeparator(); KisActionManager::safePopulateMenu(menu, "cut_frames_to_clipboard", m_d->actionMan); KisActionManager::safePopulateMenu(menu, "copy_frames_to_clipboard", m_d->actionMan); KisActionManager::safePopulateMenu(menu, "paste_frames_from_clipboard", m_d->actionMan); menu->addSeparator(); - QMenu *frames = menu->addMenu(i18nc("@item:inmenu", "Keyframes")); - KisActionManager::safePopulateMenu(frames, "insert_keyframes_right", m_d->actionMan); - KisActionManager::safePopulateMenu(frames, "insert_keyframes_left", m_d->actionMan); - frames->addSeparator(); - KisActionManager::safePopulateMenu(frames, "insert_n_keyframes_right", m_d->actionMan); - KisActionManager::safePopulateMenu(frames, "insert_n_keyframes_left", m_d->actionMan); - - QMenu *hold = menu->addMenu(i18nc("@item:inmenu", "Hold Frames")); - KisActionManager::safePopulateMenu(hold, "insert_hold_frame", m_d->actionMan); - KisActionManager::safePopulateMenu(hold, "remove_hold_frame", m_d->actionMan); + { //Frames submenu. + QMenu *frames = menu->addMenu(i18nc("@item:inmenu", "Keyframes")); + KisActionManager::safePopulateMenu(frames, "insert_keyframe_left", m_d->actionMan); + KisActionManager::safePopulateMenu(frames, "insert_keyframe_right", m_d->actionMan); + frames->addSeparator(); + KisActionManager::safePopulateMenu(frames, "insert_multiple_keyframes", m_d->actionMan); + } - hold->addSeparator(); - KisActionManager::safePopulateMenu(hold, "insert_n_hold_frames", m_d->actionMan); - KisActionManager::safePopulateMenu(hold, "remove_n_hold_frames", m_d->actionMan); + { //Holds submenu. + QMenu *hold = menu->addMenu(i18nc("@item:inmenu", "Hold Frames")); + KisActionManager::safePopulateMenu(hold, "insert_hold_frame", m_d->actionMan); + KisActionManager::safePopulateMenu(hold, "remove_hold_frame", m_d->actionMan); + hold->addSeparator(); + KisActionManager::safePopulateMenu(hold, "insert_multiple_hold_frames", m_d->actionMan); + KisActionManager::safePopulateMenu(hold, "remove_multiple_hold_frames", m_d->actionMan); + } menu->addSeparator(); + KisActionManager::safePopulateMenu(menu, "remove_frames", m_d->actionMan); KisActionManager::safePopulateMenu(menu, "remove_frames_and_pull", m_d->actionMan); menu->addSeparator(); + if (addFrameCreationActions) { KisActionManager::safePopulateMenu(menu, "add_blank_frame", m_d->actionMan); KisActionManager::safePopulateMenu(menu, "add_duplicate_frame", m_d->actionMan); @@ -1202,20 +1182,18 @@ enableAction("add_blank_frame", hasEditableFrames); enableAction("add_duplicate_frame", hasEditableFrames); - enableAction("insert_keyframes_right", hasEditableFrames); - enableAction("insert_n_keyframes_right", hasEditableFrames); - - enableAction("insert_keyframes_left", hasEditableFrames); - enableAction("insert_n_keyframes_left", hasEditableFrames); + enableAction("insert_keyframe_left", hasEditableFrames); + enableAction("insert_keyframe_right", hasEditableFrames); + enableAction("insert_multiple_keyframes", hasEditableFrames); enableAction("remove_frames", hasEditableFrames && hasExistingFrames); enableAction("remove_frames_and_pull", hasEditableFrames); enableAction("insert_hold_frame", hasEditableFrames); - enableAction("insert_n_hold_frames", hasEditableFrames); + enableAction("insert_multiple_hold_frames", hasEditableFrames); enableAction("remove_hold_frame", hasEditableFrames); - enableAction("remove_n_hold_frames", hasEditableFrames); + enableAction("remove_multiple_hold_frames", hasEditableFrames); enableAction("mirror_frames", hasEditableFrames && editableIndexes.size() > 1); @@ -1284,7 +1262,7 @@ model()->removeRow(index.row()); } -void TimelineFramesView::slotNewFrame() +void TimelineFramesView::slotAddBlankFrame() { QModelIndex index = currentIndex(); if (!index.isValid() || @@ -1296,7 +1274,7 @@ m_d->model->createFrame(index); } -void TimelineFramesView::slotCopyFrame() +void TimelineFramesView::slotAddDuplicateFrame() { QModelIndex index = currentIndex(); if (!index.isValid() || @@ -1322,102 +1300,49 @@ } } -void TimelineFramesView::insertFramesImpl(int insertAtColumn, int count, int timing, QSet rows, bool forceEntireColumn) -{ - if (forceEntireColumn) { - rows.clear(); - for (int i = 0; i < m_d->model->rowCount(); i++) { - if (!m_d->model->data(m_d->model->index(i, insertAtColumn), TimelineFramesModel::FrameEditableRole).toBool()) continue; - rows.insert(i); - } - } - - if (!rows.isEmpty()) { - m_d->model->insertFrames(insertAtColumn, rows.toList(), count, timing); - } -} - -void TimelineFramesView::slotInsertKeyframesLeft(int count, int timing, bool forceEntireColumn) -{ - QSet rows; - int minColumn = 0; - int maxColumn = 0; - - calculateSelectionMetrics(minColumn, maxColumn, rows); - - if (count <= 0) { - count = qMax(1, maxColumn - minColumn + 1); - } - - insertFramesImpl(minColumn, count, timing, rows, forceEntireColumn); -} - -void TimelineFramesView::slotInsertKeyframesRight(int count, int timing, bool forceEntireColumn) +void TimelineFramesView::insertKeyframes(int count, int timing, TimelineDirection direction, bool entireColumn) { QSet rows; - int minColumn = 0; - int maxColumn = 0; + int minColumn = 0, maxColumn = 0; calculateSelectionMetrics(minColumn, maxColumn, rows); - if (count <= 0) { + if (count <= 0) { //Negative count? Use number of selected frames. count = qMax(1, maxColumn - minColumn + 1); } - insertFramesImpl(maxColumn + 1, count, timing, rows, forceEntireColumn); -} - -void TimelineFramesView::slotInsertColumnsLeft(int count, int timing) -{ - slotInsertKeyframesLeft(count, timing, true); -} - -void TimelineFramesView::slotInsertColumnsRight(int count, int timing) -{ - slotInsertKeyframesRight(count, timing, true); -} - -void TimelineFramesView::slotInsertKeyframesLeftCustom() -{ - int count, timing; + const int insertionColumn = + direction == TimelineDirection::RIGHT ? + maxColumn + 1 : minColumn; - if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { - slotInsertKeyframesLeft(count, timing, false); - } -} - -void TimelineFramesView::slotInsertKeyframesRightCustom() -{ - int count, timing; - - if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { - slotInsertKeyframesRight(count, timing, false); + if (entireColumn) { + rows.clear(); + for (int i = 0; i < m_d->model->rowCount(); i++) { + if (!m_d->model->data(m_d->model->index(i, insertionColumn), TimelineFramesModel::FrameEditableRole).toBool()) continue; + rows.insert(i); + } } -} - -void TimelineFramesView::slotInsertColumnsLeftCustom() -{ - int count, timing; - if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { - slotInsertColumnsLeft(count, timing); + if (!rows.isEmpty()) { + m_d->model->insertFrames(insertionColumn, rows.toList(), count, timing); } } -void TimelineFramesView::slotInsertColumnsRightCustom() +void TimelineFramesView::insertMultipleKeyframes(bool entireColumn) { int count, timing; + TimelineDirection direction; - if (m_d->insertKeyframeDialog->promptUserSettings(count, timing)) { - slotInsertColumnsRight(count, timing); + if (m_d->insertKeyframeDialog->promptUserSettings(count, timing, direction)) { + insertKeyframes(count, timing, direction, entireColumn); } } -QModelIndexList TimelineFramesView::calculateSelectionSpan(bool forceEntireColumn, bool editableOnly) const +QModelIndexList TimelineFramesView::calculateSelectionSpan(bool entireColumn, bool editableOnly) const { QModelIndexList indexes; - if (forceEntireColumn) { + if (entireColumn) { QSet rows; int minColumn = 0; int maxColumn = 0; @@ -1444,9 +1369,9 @@ return indexes; } -void TimelineFramesView::slotRemoveFrame(bool forceEntireColumn, bool needsOffset) +void TimelineFramesView::slotRemoveSelectedFrames(bool entireColumn, bool needsOffset) { - const QModelIndexList indexes = calculateSelectionSpan(forceEntireColumn); + const QModelIndexList indexes = calculateSelectionSpan(entireColumn); if (!indexes.isEmpty()) { if (needsOffset) { @@ -1457,26 +1382,11 @@ } } -void TimelineFramesView::slotRemoveColumns() -{ - slotRemoveFrame(true); -} - -void TimelineFramesView::slotRemoveFramesAndShift(bool forceEntireColumn) -{ - slotRemoveFrame(forceEntireColumn, true); -} - -void TimelineFramesView::slotRemoveColumnsAndShift() -{ - slotRemoveFramesAndShift(true); -} - -void TimelineFramesView::slotInsertHoldFrames(int count, bool forceEntireColumn) +void TimelineFramesView::insertOrRemoveHoldFrames(int count, bool entireColumn) { QModelIndexList indexes; - if (!forceEntireColumn) { + if (!entireColumn) { Q_FOREACH (const QModelIndex &index, selectionModel()->selectedIndexes()) { if (m_d->model->data(index, TimelineFramesModel::FrameEditableRole).toBool()) { indexes << index; @@ -1498,98 +1408,38 @@ } } -void TimelineFramesView::slotRemoveHoldFrames(int count, bool forceEntireColumn) -{ - slotInsertHoldFrames(-count, forceEntireColumn); -} - -void TimelineFramesView::slotInsertHoldFramesCustom() +void TimelineFramesView::insertOrRemoveMultipleHoldFrames(bool insertion, bool entireColumn) { bool ok = false; const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Insert hold frames"), + i18nc("@title:window", "Insert or Remove Hold Frames"), i18nc("@label:spinbox", "Enter number of frames"), defaultNumberOfFramesToAdd(), 1, 10000, 1, &ok); if (ok) { - setDefaultNumberOfFramesToAdd(count); - slotInsertHoldFrames(count); - } -} - -void TimelineFramesView::slotRemoveHoldFramesCustom() -{ - bool ok = false; - const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Remove hold frames"), - i18nc("@label:spinbox", "Enter number of frames"), - defaultNumberOfFramesToRemove(), - 1, 10000, 1, &ok); - - if (ok) { - setDefaultNumberOfFramesToRemove(count); - slotRemoveHoldFrames(count); - } -} - -void TimelineFramesView::slotInsertHoldColumns(int count) -{ - slotInsertHoldFrames(count, true); -} - -void TimelineFramesView::slotRemoveHoldColumns(int count) -{ - slotRemoveHoldFrames(count, true); -} - -void TimelineFramesView::slotInsertHoldColumnsCustom() -{ - bool ok = false; - const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Insert hold columns"), - i18nc("@label:spinbox", "Enter number of columns"), - defaultNumberOfColumnsToAdd(), - 1, 10000, 1, &ok); - - if (ok) { - setDefaultNumberOfColumnsToAdd(count); - slotInsertHoldColumns(count); - } -} - -void TimelineFramesView::slotRemoveHoldColumnsCustom() -{ - bool ok = false; - const int count = QInputDialog::getInt(this, - i18nc("@title:window", "Remove hold columns"), - i18nc("@label:spinbox", "Enter number of columns"), - defaultNumberOfColumnsToRemove(), - 1, 10000, 1, &ok); - - if (ok) { - setDefaultNumberOfColumnsToRemove(count); - slotRemoveHoldColumns(count); + if (insertion) { + setDefaultNumberOfFramesToAdd(count); + insertOrRemoveHoldFrames(count, entireColumn); + } else { + setDefaultNumberOfFramesToRemove(count); + insertOrRemoveHoldFrames(-count, entireColumn); + } } } -void TimelineFramesView::slotMirrorFrames(bool forceEntireColumn) +void TimelineFramesView::slotMirrorFrames(bool entireColumn) { - const QModelIndexList indexes = calculateSelectionSpan(forceEntireColumn); + const QModelIndexList indexes = calculateSelectionSpan(entireColumn); if (!indexes.isEmpty()) { m_d->model->mirrorFrames(indexes); } } -void TimelineFramesView::slotMirrorColumns() +void TimelineFramesView::cutCopyImpl(bool entireColumn, bool copy) { - slotMirrorFrames(true); -} - -void TimelineFramesView::cutCopyImpl(bool forceEntireColumn, bool copy) -{ - const QModelIndexList indexes = calculateSelectionSpan(forceEntireColumn, !copy); + const QModelIndexList indexes = calculateSelectionSpan(entireColumn, !copy); if (indexes.isEmpty()) return; int minColumn = std::numeric_limits::max(); @@ -1613,20 +1463,10 @@ } } -void TimelineFramesView::slotCopyFrames(bool forceEntireColumn) -{ - cutCopyImpl(forceEntireColumn, true); -} - -void TimelineFramesView::slotCutFrames(bool forceEntireColumn) -{ - cutCopyImpl(forceEntireColumn, false); -} - -void TimelineFramesView::slotPasteFrames(bool forceEntireColumn) +void TimelineFramesView::slotPasteFrames(bool entireColumn) { const QModelIndex currentIndex = - !forceEntireColumn ? this->currentIndex() : m_d->model->index(0, this->currentIndex().column()); + !entireColumn ? this->currentIndex() : m_d->model->index(0, this->currentIndex().column()); if (!currentIndex.isValid()) return; @@ -1644,21 +1484,6 @@ } } -void TimelineFramesView::slotCutColumns() -{ - slotCutFrames(true); -} - -void TimelineFramesView::slotPasteColumns() -{ - slotPasteFrames(true); -} - -void TimelineFramesView::slotCopyColumns() -{ - slotCopyFrames(true); -} - int TimelineFramesView::defaultNumberOfFramesToAdd() const { KConfigGroup cfg = KSharedConfig::openConfig()->group("FrameActionsDefaultValues"); diff --git a/plugins/dockers/animation/timeline_insert_keyframe_dialog.h b/plugins/dockers/animation/timeline_insert_keyframe_dialog.h --- a/plugins/dockers/animation/timeline_insert_keyframe_dialog.h +++ b/plugins/dockers/animation/timeline_insert_keyframe_dialog.h @@ -1,9 +1,31 @@ +/* + * Copyright (c) 2018 Emmet O'Neill + * Copyright (c) 2018 Eoin O'Neill + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + #ifndef __TIMELINE_INSERT_KEYFRAME_DIALOG_H #define __TIMELINE_INSERT_KEYFRAME_DIALOG_H #include "kritaanimationdocker_export.h" #include #include +#include + +enum TimelineDirection : short; class KRITAANIMATIONDOCKER_EXPORT TimelineInsertKeyframeDialog : QDialog { Q_OBJECT @@ -11,10 +33,13 @@ QSpinBox frameCountSpinbox; QSpinBox frameTimingSpinbox; + QRadioButton *leftBefore; + QRadioButton *rightAfter; + public: TimelineInsertKeyframeDialog(QWidget *parent = 0); - bool promptUserSettings(int &count, int &timing); + bool promptUserSettings(int &count, int &timing, TimelineDirection &out_direction); }; #endif // __TIMELINE_INSERT_KEYFRAME_DIALOG_H diff --git a/plugins/dockers/animation/timeline_insert_keyframe_dialog.cpp b/plugins/dockers/animation/timeline_insert_keyframe_dialog.cpp --- a/plugins/dockers/animation/timeline_insert_keyframe_dialog.cpp +++ b/plugins/dockers/animation/timeline_insert_keyframe_dialog.cpp @@ -1,7 +1,29 @@ +/* + * Copyright (c) 2018 Emmet O'Neill + * Copyright (c) 2018 Eoin O'Neill + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + #include "timeline_insert_keyframe_dialog.h" +#include "timeline_frames_view.h" #include +#include #include +#include #include #include #include @@ -14,31 +36,58 @@ setModal(true); setLayout(new QVBoxLayout(this)); - frameCountSpinbox.setMinimum(1); - frameCountSpinbox.setValue(1); + { // Count and Spacing Forms. + QWidget *forms = new QWidget(this); + layout()->addWidget(forms); + + frameCountSpinbox.setMinimum(1); + frameCountSpinbox.setValue(1); + + frameTimingSpinbox.setMinimum(1); + frameTimingSpinbox.setValue(1); + + QFormLayout *LO = new QFormLayout(this); + forms->setLayout(LO); + + LO->addRow(QString(i18nc("@label:spinbox", "Number of frames:")), &frameCountSpinbox); + LO->addRow(QString(i18nc("@label:spinbox", "Frame timing:")), &frameTimingSpinbox); + } + + { // Side Buttons. + QGroupBox *sideRadioButtons = new QGroupBox(i18nc("@label:group","Side:"), this); + layout()->addWidget(sideRadioButtons); - frameTimingSpinbox.setMinimum(1); - frameTimingSpinbox.setValue(1); + leftBefore = new QRadioButton(i18nc("@label:radio", "Left / Before"), sideRadioButtons); + rightAfter = new QRadioButton(i18nc("@label:radio", "Right / After"), sideRadioButtons); + leftBefore->setChecked(true); - QWidget *formsWidget = new QWidget(); - QFormLayout *formLayout = new QFormLayout(); - formsWidget->setLayout( formLayout ); - layout()->addWidget(formsWidget); + QVBoxLayout *LO = new QVBoxLayout(this); + sideRadioButtons->setLayout(LO); - QDialogButtonBox *buttonbox = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - layout()->addWidget(buttonbox); + LO->addWidget(leftBefore); + LO->addWidget(rightAfter); + } - formLayout->addRow(QString(i18nc("@label:spinbox", "Number of frames:")), &frameCountSpinbox); - formLayout->addRow(QString(i18nc("@label:spinbox", "Frame timing:")), &frameTimingSpinbox); + { // Cancel / OK Buttons. + QDialogButtonBox *buttonbox = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + layout()->addWidget(buttonbox); - connect(buttonbox, SIGNAL(accepted()), this, SLOT(accept())); - connect(buttonbox, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttonbox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonbox, SIGNAL(rejected()), this, SLOT(reject())); + } } -bool TimelineInsertKeyframeDialog::promptUserSettings(int &out_count, int &out_timing){ - if(exec() == QDialog::Accepted){ +bool TimelineInsertKeyframeDialog::promptUserSettings(int &out_count, int &out_timing, TimelineDirection &out_direction) +{ + if (exec() == QDialog::Accepted) { out_count = frameCountSpinbox.value(); out_timing = frameTimingSpinbox.value(); + + out_direction = TimelineDirection::LEFT; // Default + if (rightAfter && rightAfter->isChecked()) { + out_direction = TimelineDirection::RIGHT; + } + return true; } return false; diff --git a/plugins/dockers/animation/timeline_ruler_header.h b/plugins/dockers/animation/timeline_ruler_header.h --- a/plugins/dockers/animation/timeline_ruler_header.h +++ b/plugins/dockers/animation/timeline_ruler_header.h @@ -37,7 +37,7 @@ void setModel(QAbstractItemModel *model) override; - void setActionManager( KisActionManager * actionManager); + void setActionManager(KisActionManager *actionManager); protected: void mousePressEvent(QMouseEvent *e) override; @@ -61,10 +61,10 @@ const QPen &gridPen) const; Q_SIGNALS: - void sigInsertColumnsLeft(); - void sigInsertColumnsRight(); - void sigInsertColumnsLeftCustom(); - void sigInsertColumnsRightCustom(); + void sigInsertColumnLeft(); + void sigInsertColumnRight(); + void sigInsertMultipleColumns(); + void sigRemoveColumns(); void sigRemoveColumnsAndShift(); diff --git a/plugins/dockers/animation/timeline_ruler_header.cpp b/plugins/dockers/animation/timeline_ruler_header.cpp --- a/plugins/dockers/animation/timeline_ruler_header.cpp +++ b/plugins/dockers/animation/timeline_ruler_header.cpp @@ -55,10 +55,6 @@ { setSectionResizeMode(QHeaderView::Fixed); setDefaultSectionSize(18); - - - - } TimelineRulerHeader::~TimelineRulerHeader() @@ -66,24 +62,21 @@ } -void TimelineRulerHeader::setActionManager( KisActionManager * actionManager) +void TimelineRulerHeader::setActionManager(KisActionManager *actionManager) { m_d->actionMan = actionManager; if (actionManager) { KisAction *action; - action = actionManager->createAction("insert_columns_right"); - connect(action, SIGNAL(triggered()), SIGNAL(sigInsertColumnsRight())); - - action = actionManager->createAction("insert_n_columns_right"); - connect(action, SIGNAL(triggered()), SIGNAL(sigInsertColumnsRightCustom())); + action = actionManager->createAction("insert_column_left"); + connect(action, SIGNAL(triggered()), SIGNAL(sigInsertColumnLeft())); - action = actionManager->createAction("insert_columns_left"); - connect(action, SIGNAL(triggered()), SIGNAL(sigInsertColumnsLeft())); + action = actionManager->createAction("insert_column_right"); + connect(action, SIGNAL(triggered()), SIGNAL(sigInsertColumnRight())); - action = actionManager->createAction("insert_n_columns_left"); - connect(action, SIGNAL(triggered()), SIGNAL(sigInsertColumnsLeftCustom())); + action = actionManager->createAction("insert_multiple_columns"); + connect(action, SIGNAL(triggered()), SIGNAL(sigInsertMultipleColumns())); action = actionManager->createAction("remove_columns_and_pull"); connect(action, SIGNAL(triggered()), SIGNAL(sigRemoveColumnsAndShift())); @@ -94,13 +87,13 @@ action = actionManager->createAction("insert_hold_column"); connect(action, SIGNAL(triggered()), SIGNAL(sigInsertHoldColumns())); - action = actionManager->createAction("insert_n_hold_columns"); + action = actionManager->createAction("insert_multiple_hold_columns"); connect(action, SIGNAL(triggered()), SIGNAL(sigInsertHoldColumnsCustom())); action = actionManager->createAction("remove_hold_column"); connect(action, SIGNAL(triggered()), SIGNAL(sigRemoveHoldColumns())); - action = actionManager->createAction("remove_n_hold_columns"); + action = actionManager->createAction("remove_multiple_hold_columns"); connect(action, SIGNAL(triggered()), SIGNAL(sigRemoveHoldColumnsCustom())); action = actionManager->createAction("mirror_columns"); @@ -440,27 +433,31 @@ KisActionManager::safePopulateMenu(&menu, "cut_columns_to_clipboard", m_d->actionMan); KisActionManager::safePopulateMenu(&menu, "copy_columns_to_clipboard", m_d->actionMan); KisActionManager::safePopulateMenu(&menu, "paste_columns_from_clipboard", m_d->actionMan); - menu.addSeparator(); - QMenu *frames = menu.addMenu(i18nc("@item:inmenu", "Keyframe Columns")); - KisActionManager::safePopulateMenu(frames, "insert_columns_right", m_d->actionMan); - KisActionManager::safePopulateMenu(frames, "insert_columns_left", m_d->actionMan); menu.addSeparator(); - KisActionManager::safePopulateMenu(frames, "insert_n_columns_right", m_d->actionMan); - KisActionManager::safePopulateMenu(frames, "insert_n_columns_left", m_d->actionMan); - QMenu *hold = menu.addMenu(i18nc("@item:inmenu", "Hold Frame Columns")); - KisActionManager::safePopulateMenu(hold, "insert_hold_column", m_d->actionMan); - KisActionManager::safePopulateMenu(hold, "remove_hold_column", m_d->actionMan); - menu.addSeparator(); - KisActionManager::safePopulateMenu(hold, "insert_n_hold_columns", m_d->actionMan); - KisActionManager::safePopulateMenu(hold, "remove_n_hold_columns", m_d->actionMan); + { //Frame Columns Submenu + QMenu *frames = menu.addMenu(i18nc("@item:inmenu", "Keyframe Columns")); + KisActionManager::safePopulateMenu(frames, "insert_column_left", m_d->actionMan); + KisActionManager::safePopulateMenu(frames, "insert_column_right", m_d->actionMan); + frames->addSeparator(); + KisActionManager::safePopulateMenu(frames, "insert_multiple_columns", m_d->actionMan); + } + + { //Hold Columns Submenu + QMenu *hold = menu.addMenu(i18nc("@item:inmenu", "Hold Frame Columns")); + KisActionManager::safePopulateMenu(hold, "insert_hold_column", m_d->actionMan); + KisActionManager::safePopulateMenu(hold, "remove_hold_column", m_d->actionMan); + hold->addSeparator(); + KisActionManager::safePopulateMenu(hold, "insert_multiple_hold_columns", m_d->actionMan); + KisActionManager::safePopulateMenu(hold, "remove_multiple_hold_columns", m_d->actionMan); + } menu.addSeparator(); + KisActionManager::safePopulateMenu(&menu, "remove_columns", m_d->actionMan); KisActionManager::safePopulateMenu(&menu, "remove_columns_and_pull", m_d->actionMan); - if (numSelectedColumns > 1) { menu.addSeparator(); KisActionManager::safePopulateMenu(&menu, "mirror_columns", m_d->actionMan);