From f9b225ae88b0e056efbc68d76dfb30f60d49eb22 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Tue, 1 Oct 2019 13:14:16 +0300 Subject: [PATCH] Some timeline visual updates and corrections - Selection rect selects keyframes based on center point rather than the whole keyframe. - Make playhead vertical line extend to the whole height of the timeline widget. - Prevent a jump when dragging a selection of keyframes. - Prevent dragging keyframes if the clicked keyframe is deselected (i.e. Ctrl+click a selected keyframe). - Correct timeline bounds checking while dragging multiple keyframes. Task-number: QDS-1073 Change-Id: Ibf118ecccfe86346f2d4e921c0958294a15c24f1 Reviewed-by: Miikka Heikkinen Reviewed-by: Thomas Hartmann --- .../timelineeditor/timelinegraphicsscene.cpp | 2 +- .../timelineeditor/timelinemovetool.cpp | 37 +++++++++++-------- .../timelineeditor/timelinemovetool.h | 3 ++ .../timelineeditor/timelinepropertyitem.cpp | 9 ++++- .../timelineeditor/timelinepropertyitem.h | 3 +- .../timelineeditor/timelineselectiontool.cpp | 6 ++- 6 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp index a7e080def7a..cce72207cd2 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp @@ -112,7 +112,7 @@ TimelineGraphicsScene::TimelineGraphicsScene(TimelineWidget *parent) if (auto *rview = rulerView()) rview->setSceneRect(rect); - m_currentFrameIndicator->setHeight(m_layout->geometry().height()); + m_currentFrameIndicator->setHeight(9999); // big enough number (> timeline widget height) }); auto moveFrameIndicator = [this](const QPointF &pos) { diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp index f9c3f4914a0..785b1bb2681 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp @@ -68,7 +68,12 @@ void TimelineMoveTool::mousePressEvent(TimelineMovableAbstractItem *item, QGraphicsSceneMouseEvent *event) { Q_UNUSED(item) - Q_UNUSED(event) + + if (auto *current = currentItem()->asTimelineKeyframeItem()) { + const qreal sourceFrame = qRound(current->mapFromSceneToFrame(current->rect().center().x())); + const qreal targetFrame = qRound(current->mapFromSceneToFrame(event->scenePos().x())); + m_pressKeyframeDelta = targetFrame - sourceFrame; + } } void TimelineMoveTool::mouseMoveEvent(TimelineMovableAbstractItem *item, @@ -80,34 +85,34 @@ void TimelineMoveTool::mouseMoveEvent(TimelineMovableAbstractItem *item, return; if (auto *current = currentItem()->asTimelineKeyframeItem()) { + // prevent dragging if deselecting a keyframe (Ctrl+click and drag a selected keyframe) + if (!current->highlighted()) + return; + const qreal sourceFrame = qRound(current->mapFromSceneToFrame(current->rect().center().x())); const qreal targetFrame = qRound(current->mapFromSceneToFrame(event->scenePos().x())); - qreal deltaFrame = targetFrame - sourceFrame; + qreal deltaFrame = targetFrame - sourceFrame - m_pressKeyframeDelta; const qreal minFrame = scene()->startFrame(); const qreal maxFrame = scene()->endFrame(); - auto bbox = scene()->selectionBounds().united(current->rect()); + auto bbox = scene()->selectionBounds().adjusted(TimelineConstants::keyFrameSize / 2, 0, + -TimelineConstants::keyFrameSize / 2, 0); + double firstFrame = std::round(current->mapFromSceneToFrame(bbox.left())); + double lastFrame = std::round(current->mapFromSceneToFrame(bbox.right())); - double firstFrame = std::round(current->mapFromSceneToFrame(bbox.center().x())); - double lastFrame = std::round(current->mapFromSceneToFrame(bbox.center().x())); - - if ((lastFrame + deltaFrame) > maxFrame) + if (lastFrame + deltaFrame > maxFrame) deltaFrame = maxFrame - lastFrame; - - if ((firstFrame + deltaFrame) <= minFrame) + else if (firstFrame + deltaFrame < minFrame) deltaFrame = minFrame - firstFrame; - current->setPosition(sourceFrame + deltaFrame); - scene()->statusBarMessageChanged(tr(TimelineConstants::statusBarKeyframe) .arg(sourceFrame + deltaFrame)); - for (auto *keyframe : scene()->selectedKeyframes()) { - if (keyframe != current) { - qreal pos = std::round(current->mapFromSceneToFrame(keyframe->rect().center().x())); - keyframe->setPosition(pos + deltaFrame); - } + const QList selectedKeyframes = scene()->selectedKeyframes(); + for (auto *keyframe : selectedKeyframes) { + qreal pos = std::round(keyframe->mapFromSceneToFrame(keyframe->rect().center().x())); + keyframe->setPosition(pos + deltaFrame); } } else { diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h index 20b9537af9a..c5c9702c44b 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h @@ -52,6 +52,9 @@ public: void keyPressEvent(QKeyEvent *keyEvent) override; void keyReleaseEvent(QKeyEvent *keyEvent) override; + +private: + qreal m_pressKeyframeDelta = 0.; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp index 920a8b35ca9..1159619dce0 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp @@ -517,10 +517,10 @@ void TimelineKeyframeItem::updateFrame() setPosition(m_frame.variantProperty("frame").value().toReal()); } -void TimelineKeyframeItem::setPosition(qreal position) +void TimelineKeyframeItem::setPosition(qreal frame) { int offset = (TimelineConstants::sectionHeight - TimelineConstants::keyFrameSize) / 2; - const qreal scenePostion = mapFromFrameToScene(position); + const qreal scenePostion = mapFromFrameToScene(frame); setRect(scenePostion - TimelineConstants::keyFrameSize / 2, offset, @@ -622,6 +622,11 @@ void TimelineKeyframeItem::setHighlighted(bool b) update(); } +bool TimelineKeyframeItem::highlighted() const +{ + return m_highlight; +} + TimelinePropertyItem *TimelineKeyframeItem::propertyItem() const { /* The parentItem is always a TimelinePropertyItem. See constructor */ diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h index 4544b403029..5d6666f4ed6 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h +++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h @@ -58,8 +58,9 @@ public: void updateFrame(); void setHighlighted(bool b); + bool highlighted() const; - void setPosition(qreal position); + void setPosition(qreal frame); void commitPosition(const QPointF &point) override; diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp index 78516d91b23..77f419fc393 100644 --- a/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp +++ b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp @@ -98,7 +98,7 @@ void TimelineSelectionTool::mouseMoveEvent(TimelineMovableAbstractItem *item, m_selectionRect->show(); aboutToSelect(selectionMode(event), - scene()->items(m_selectionRect->rect(), Qt::ContainsItemShape)); + scene()->items(m_selectionRect->rect(), Qt::IntersectsItemBoundingRect)); } } @@ -164,6 +164,10 @@ void TimelineSelectionTool::aboutToSelect(SelectionMode mode, QListrect().contains(keyframe->rect().center() + item->scenePos())) + continue; + if (mode == SelectionMode::Remove) keyframe->setHighlighted(false); else if (mode == SelectionMode::Toggle)