Members of the KDE Community are recommended to subscribe to the kde-community mailing list at to allow them to participate in important discussions and receive other important announcements

Commit d76c59fc authored by Eoin O'Neill's avatar Eoin O'Neill 🍀

Fix: Properly Maintain Selection of Keyframes When Inserting / Removing Hold Frames.

Related Feature: Preserve multi-frame selection when active frame changes. Useful
for preserving the users selection on scrub, but also less error-prone when dealing
with modifying the user selection while concurrent "switch-time" operation is running.

Insert Keyframe Bug:

Maintain Multiframe Selection Wishlist:
parent cfa6d9f6
......@@ -878,7 +878,7 @@ bool TimelineFramesModel::insertFrames(int dstColumn, const QList<int> &dstRows,
return true;
bool TimelineFramesModel::insertHoldFrames(QModelIndexList selectedIndexes, int count)
bool TimelineFramesModel::insertHoldFrames(const QModelIndexList &selectedIndexes, int count)
if (selectedIndexes.isEmpty() || count == 0) return true;
......@@ -65,7 +65,7 @@ public:
bool insertFrames(int dstColumn, const QList<int> &dstRows, int count, int timing = 1);
bool insertHoldFrames(QModelIndexList selectedIndexes, int count);
bool insertHoldFrames(const QModelIndexList &selectedIndexes, int count);
QString audioChannelFileName() const;
void setAudioChannelFileName(const QString &fileName);
......@@ -69,7 +69,7 @@ struct TimelineFramesView::Private
selectionChangedCompressor(300, KisSignalCompressor::FIRST_INACTIVE)
selectionChangedCompressor(500, KisSignalCompressor::FIRST_INACTIVE)
TimelineFramesView *q;
......@@ -688,6 +688,7 @@ void TimelineFramesView::slotDataChanged(const QModelIndex &topLeft, const QMode
if (selectionModel()->selectedIndexes().count() > 1) return;
if (selectedColumn == -1) {
selectedColumn = index.column();
......@@ -1466,12 +1467,47 @@ void TimelineFramesView::insertOrRemoveHoldFrames(int count, bool entireColumn)
m_d->model->insertHoldFrames(indexes, count);
// Fan selection based on insertion or deletion.
// This should allow better UI/UX for insertion of keyframes or hold frames.
fanSelectedFrames(indexes, count);
// bulk adding frames can add too many
// trim timeline to clean up extra frames that might have been added
void TimelineFramesView::fanSelectedFrames(const QModelIndexList &selection, int count, bool ignoreKeyless) {
QMap<int, QList<int>> indexMap;
QList<QModelIndex> selectedIndices = selection;
foreach (const QModelIndex &index, selectedIndices) {
if (!indexMap.contains(index.row())) {
indexMap.insert(index.row(), QList<int>());
if (m_d->model->data(index, TimelineFramesModel::FrameExistsRole).value<bool>() || !ignoreKeyless) {
indexMap[index.row()] << index.column();
KisSignalsBlocker blockSig(selectionModel());
foreach (const int &layer, indexMap.keys()) {
QList<int>::const_iterator it;
int progressIndex = 0;
std::sort(indexMap[layer].begin(), indexMap[layer].end());
for (it = indexMap[layer].constBegin(); it != indexMap[layer].constEnd(); it++) {
const int offsetColumn = *it + (progressIndex * count);
selectionModel()->select(model()->index(layer, offsetColumn), QItemSelectionModel::Select);
void TimelineFramesView::insertOrRemoveMultipleHoldFrames(bool insertion, bool entireColumn)
bool ok = false;
......@@ -158,6 +158,7 @@ private:
void insertOrRemoveHoldFrames(int count, bool entireColumn = false);
void insertOrRemoveMultipleHoldFrames(bool insertion, bool entireColumn = false);
void fanSelectedFrames(const QModelIndexList &selection, int count, bool ignoreKeyless = true);
void cutCopyImpl(bool entireColumn, bool copy);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment