forked from qt-creator/qt-creator
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 <miikka.heikkinen@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -112,7 +112,7 @@ TimelineGraphicsScene::TimelineGraphicsScene(TimelineWidget *parent)
|
|||||||
if (auto *rview = rulerView())
|
if (auto *rview = rulerView())
|
||||||
rview->setSceneRect(rect);
|
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) {
|
auto moveFrameIndicator = [this](const QPointF &pos) {
|
||||||
|
|||||||
@@ -68,7 +68,12 @@ void TimelineMoveTool::mousePressEvent(TimelineMovableAbstractItem *item,
|
|||||||
QGraphicsSceneMouseEvent *event)
|
QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(item)
|
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,
|
void TimelineMoveTool::mouseMoveEvent(TimelineMovableAbstractItem *item,
|
||||||
@@ -80,34 +85,34 @@ void TimelineMoveTool::mouseMoveEvent(TimelineMovableAbstractItem *item,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (auto *current = currentItem()->asTimelineKeyframeItem()) {
|
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 sourceFrame = qRound(current->mapFromSceneToFrame(current->rect().center().x()));
|
||||||
const qreal targetFrame = qRound(current->mapFromSceneToFrame(event->scenePos().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 minFrame = scene()->startFrame();
|
||||||
const qreal maxFrame = scene()->endFrame();
|
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()));
|
if (lastFrame + deltaFrame > maxFrame)
|
||||||
double lastFrame = std::round(current->mapFromSceneToFrame(bbox.center().x()));
|
|
||||||
|
|
||||||
if ((lastFrame + deltaFrame) > maxFrame)
|
|
||||||
deltaFrame = maxFrame - lastFrame;
|
deltaFrame = maxFrame - lastFrame;
|
||||||
|
else if (firstFrame + deltaFrame < minFrame)
|
||||||
if ((firstFrame + deltaFrame) <= minFrame)
|
|
||||||
deltaFrame = minFrame - firstFrame;
|
deltaFrame = minFrame - firstFrame;
|
||||||
|
|
||||||
current->setPosition(sourceFrame + deltaFrame);
|
|
||||||
|
|
||||||
scene()->statusBarMessageChanged(tr(TimelineConstants::statusBarKeyframe)
|
scene()->statusBarMessageChanged(tr(TimelineConstants::statusBarKeyframe)
|
||||||
.arg(sourceFrame + deltaFrame));
|
.arg(sourceFrame + deltaFrame));
|
||||||
|
|
||||||
for (auto *keyframe : scene()->selectedKeyframes()) {
|
const QList<TimelineKeyframeItem *> selectedKeyframes = scene()->selectedKeyframes();
|
||||||
if (keyframe != current) {
|
for (auto *keyframe : selectedKeyframes) {
|
||||||
qreal pos = std::round(current->mapFromSceneToFrame(keyframe->rect().center().x()));
|
qreal pos = std::round(keyframe->mapFromSceneToFrame(keyframe->rect().center().x()));
|
||||||
keyframe->setPosition(pos + deltaFrame);
|
keyframe->setPosition(pos + deltaFrame);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ public:
|
|||||||
|
|
||||||
void keyPressEvent(QKeyEvent *keyEvent) override;
|
void keyPressEvent(QKeyEvent *keyEvent) override;
|
||||||
void keyReleaseEvent(QKeyEvent *keyEvent) override;
|
void keyReleaseEvent(QKeyEvent *keyEvent) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
qreal m_pressKeyframeDelta = 0.;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -517,10 +517,10 @@ void TimelineKeyframeItem::updateFrame()
|
|||||||
setPosition(m_frame.variantProperty("frame").value().toReal());
|
setPosition(m_frame.variantProperty("frame").value().toReal());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineKeyframeItem::setPosition(qreal position)
|
void TimelineKeyframeItem::setPosition(qreal frame)
|
||||||
{
|
{
|
||||||
int offset = (TimelineConstants::sectionHeight - TimelineConstants::keyFrameSize) / 2;
|
int offset = (TimelineConstants::sectionHeight - TimelineConstants::keyFrameSize) / 2;
|
||||||
const qreal scenePostion = mapFromFrameToScene(position);
|
const qreal scenePostion = mapFromFrameToScene(frame);
|
||||||
|
|
||||||
setRect(scenePostion - TimelineConstants::keyFrameSize / 2,
|
setRect(scenePostion - TimelineConstants::keyFrameSize / 2,
|
||||||
offset,
|
offset,
|
||||||
@@ -622,6 +622,11 @@ void TimelineKeyframeItem::setHighlighted(bool b)
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TimelineKeyframeItem::highlighted() const
|
||||||
|
{
|
||||||
|
return m_highlight;
|
||||||
|
}
|
||||||
|
|
||||||
TimelinePropertyItem *TimelineKeyframeItem::propertyItem() const
|
TimelinePropertyItem *TimelineKeyframeItem::propertyItem() const
|
||||||
{
|
{
|
||||||
/* The parentItem is always a TimelinePropertyItem. See constructor */
|
/* The parentItem is always a TimelinePropertyItem. See constructor */
|
||||||
|
|||||||
@@ -58,8 +58,9 @@ public:
|
|||||||
void updateFrame();
|
void updateFrame();
|
||||||
|
|
||||||
void setHighlighted(bool b);
|
void setHighlighted(bool b);
|
||||||
|
bool highlighted() const;
|
||||||
|
|
||||||
void setPosition(qreal position);
|
void setPosition(qreal frame);
|
||||||
|
|
||||||
void commitPosition(const QPointF &point) override;
|
void commitPosition(const QPointF &point) override;
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ void TimelineSelectionTool::mouseMoveEvent(TimelineMovableAbstractItem *item,
|
|||||||
m_selectionRect->show();
|
m_selectionRect->show();
|
||||||
|
|
||||||
aboutToSelect(selectionMode(event),
|
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, QList<QGraphicsIte
|
|||||||
|
|
||||||
for (auto *item : items) {
|
for (auto *item : items) {
|
||||||
if (auto *keyframe = TimelineMovableAbstractItem::asTimelineKeyframeItem(item)) {
|
if (auto *keyframe = TimelineMovableAbstractItem::asTimelineKeyframeItem(item)) {
|
||||||
|
// if keyframe's center isn't inside m_selectionRect, discard it
|
||||||
|
if (!m_selectionRect->rect().contains(keyframe->rect().center() + item->scenePos()))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (mode == SelectionMode::Remove)
|
if (mode == SelectionMode::Remove)
|
||||||
keyframe->setHighlighted(false);
|
keyframe->setHighlighted(false);
|
||||||
else if (mode == SelectionMode::Toggle)
|
else if (mode == SelectionMode::Toggle)
|
||||||
|
|||||||
Reference in New Issue
Block a user