summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp')
-rw-r--r--src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp1035
1 files changed, 0 insertions, 1035 deletions
diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
deleted file mode 100644
index 25b66911..00000000
--- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
+++ /dev/null
@@ -1,1035 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt 3D Studio.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "RowTimeline.h"
-#include "RowTimelinePropertyGraph.h"
-#include "RowTree.h"
-#include "RowManager.h"
-#include "Ruler.h"
-#include "TimelineConstants.h"
-#include "Keyframe.h"
-#include "KeyframeManager.h"
-#include "TimelineGraphicsScene.h"
-#include "Bindings/ITimelineItemBinding.h"
-#include "Bindings/ITimelineTimebar.h"
-#include "Bindings/Qt3DSDMTimelineItemProperty.h"
-#include "AppFonts.h"
-#include "StudioPreferences.h"
-#include "TimelineToolbar.h"
-#include "StudioUtils.h"
-
-#include <QtGui/qpainter.h>
-#include <QtGui/qbrush.h>
-#include <QtWidgets/qdesktopwidget.h>
-#include <QtWidgets/qapplication.h>
-#include <QtWidgets/qgraphicssceneevent.h>
-#include <QtWidgets/qwidget.h>
-#include <QtWidgets/qlabel.h>
-#include <QtCore/qdatetime.h>
-
-RowTimeline::RowTimeline()
- : InteractiveTimelineItem()
-{
- // 999999: theoretically big enough row width (~ 4.6 hrs of presentation length)
- setMinimumWidth(999999);
- setMaximumWidth(999999);
-}
-
-RowTimeline::~RowTimeline()
-{
- // remove keyframes
- if (!m_keyframes.empty()) {
- if (m_isProperty) // non-property rows use the same keyframes from property rows.
- qDeleteAll(m_keyframes);
-
- m_keyframes.clear();
- }
-}
-
-void RowTimeline::initialize()
-{
- // Called once m_rowTree exists
-
- m_commentItem = new RowTimelineCommentItem(this);
- m_commentItem->setParentRow(m_rowTree);
- updateCommentItemPos();
-
- TimelineToolbar *toolbar = m_rowTree->m_scene->widgetTimeline()->toolbar();
- connect(toolbar, &TimelineToolbar::showRowTextsToggled, this, [this]() {
- updateCommentItem();
- });
-
- connect(m_commentItem, &RowTimelineCommentItem::labelChanged, this,
- [this](const QString &label) {
- // Update label on timeline and on model
- ITimelineTimebar *timebar = m_rowTree->m_binding->GetTimelineItem()->GetTimebar();
- timebar->SetTimebarComment(label);
- });
-
- connect(m_rowTree->m_scene->ruler(), &Ruler::viewportXChanged, this,
- &RowTimeline::updateCommentItemPos);
-}
-
-void RowTimeline::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option)
-
- bool hiResIcons = StudioUtils::devicePixelRatio(widget->window()->windowHandle()) > 1.0;
-
- if (!y()) // prevents flickering when the row is just inserted to the layout
- return;
-
- const int currentHeight = size().height() - 1;
-
- if (isColorProperty() && !m_keyframes.empty()) {
- drawColorPropertyGradient(painter, widget->width());
- } else {
- // Background
- QColor bgColor;
- if (m_rowTree->isProperty())
- bgColor = CStudioPreferences::timelineRowColorNormalProp();
- else if (m_state == Selected)
- bgColor = CStudioPreferences::timelineRowColorSelected();
- else if (m_state == Hovered && !m_rowTree->m_locked)
- bgColor = CStudioPreferences::timelineRowColorOver();
- else
- bgColor = CStudioPreferences::timelineRowColorNormal();
- painter->fillRect(0, 0, size().width(), currentHeight, bgColor);
- }
-
- const double edgeOffset = TimelineConstants::RULER_EDGE_OFFSET;
-
- // Duration. Draw duration bar (for scene/component root) also if it has
- // datainput controller
- if (m_rowTree->hasDurationBar() || m_controllerDataInput.size()) {
- painter->save();
-
- // fully outside ancestors' limits, draw fully hashed
- if (m_minStartX > m_endX || m_maxEndX < m_startX) {
- painter->setBrush(QBrush(CStudioPreferences::timelineRowColorDurationOff1(),
- Qt::BDiagPattern));
- painter->setPen(Qt::NoPen);
- painter->fillRect(QRect(edgeOffset + m_startX, 0, m_endX - m_startX, currentHeight),
- CStudioPreferences::timelineRowColorDurationOff2());
- painter->drawRect(QRect(edgeOffset + m_startX, 0, m_endX - m_startX, currentHeight));
-
- painter->setPen(QPen(CStudioPreferences::timelineRowColorDurationEdge(), 2));
- painter->drawLine(edgeOffset + m_startX, 0, edgeOffset + m_startX, currentHeight);
- painter->drawLine(edgeOffset + m_endX, 0, edgeOffset + m_endX, currentHeight);
- } else {
- // draw main duration part
- double x = edgeOffset + qMax(m_startX, m_minStartX);
- double w = edgeOffset + qMin(m_endX, m_maxEndX) - x;
- static const int marginY = 3;
-
- painter->setPen(Qt::NoPen);
-
- if (m_controllerDataInput.size()) {
- painter->fillRect(QRect(x, 0, w, currentHeight),
- CStudioPreferences::dataInputColor());
- } else if (m_rowTree->indexInLayout() != 1) {
- painter->fillRect(QRect(x, 0, w, currentHeight), m_barColor);
- }
-
- if (m_state == Selected) {
- // draw selection overlay on bar
- painter->fillRect(QRect(x, marginY, w, currentHeight - marginY * 2),
- CStudioPreferences::timelineRowColorDurationSelected());
- }
-
- if (m_controllerDataInput.size()) {
- static const QPixmap pixDataInput = QPixmap(":/images/Objects-DataInput-White.png");
- static const QPixmap pixDataInput2x
- = QPixmap(":/images/Objects-DataInput-White@2x.png");
- static const QFontMetrics fm(painter->font());
-
- // need clip region to limit datainput icon visibility to the same rect as we use
- // for text
- painter->setClipRect(x, 0, w, currentHeight);
- painter->setClipping(true);
- painter->setPen(QPen(CStudioPreferences::textColor(), 2));
- // +5 added to text location to make margin comparable to other datainput controls
- painter->drawText(QRect(x + pixDataInput.width() + 5, 0, w, currentHeight),
- m_controllerDataInput, QTextOption(Qt::AlignCenter));
- // place the icon in front of the text
- int textwidth = fm.width(m_controllerDataInput);
- int iconx = x + (w - textwidth) / 2;
- if (iconx < x)
- iconx = x;
- painter->drawPixmap(iconx, marginY, hiResIcons ? pixDataInput2x : pixDataInput);
- painter->setPen(Qt::NoPen);
- painter->setClipping(false);
- }
-
- // draw hashed part before
- painter->setBrush(QBrush(CStudioPreferences::timelineRowColorDurationOff1(),
- Qt::BDiagPattern));
- if (m_startX < m_minStartX) {
- painter->setPen(Qt::NoPen);
- painter->fillRect(QRect(edgeOffset + m_startX, 0, m_minStartX - m_startX,
- currentHeight),
- CStudioPreferences::timelineRowColorDurationOff2());
- painter->drawRect(QRect(edgeOffset + m_startX, 0, m_minStartX - m_startX,
- currentHeight));
- painter->setPen(CStudioPreferences::timelineRowColorDurationEdge());
- painter->drawLine(edgeOffset + m_minStartX, 0, edgeOffset + m_minStartX,
- currentHeight);
- }
-
- // draw hashed part after
- if (m_endX > m_maxEndX) {
- painter->setPen(Qt::NoPen);
- painter->fillRect(QRect(edgeOffset + m_maxEndX, 0, m_endX - m_maxEndX,
- currentHeight),
- CStudioPreferences::timelineRowColorDurationOff2());
- painter->drawRect(QRect(edgeOffset + m_maxEndX, 0, m_endX - m_maxEndX,
- currentHeight));
- painter->setPen(CStudioPreferences::timelineRowColorDurationEdge());
- painter->drawLine(edgeOffset + m_maxEndX, 0, edgeOffset + m_maxEndX, currentHeight);
- }
-
- if (m_rowTree->indexInLayout() != 1) {
- painter->setPen(QPen(CStudioPreferences::timelineRowColorDurationEdge(), 2));
- painter->drawLine(edgeOffset + m_startX, 0, edgeOffset + m_startX, currentHeight);
- painter->drawLine(edgeOffset + m_endX, 0, edgeOffset + m_endX, currentHeight);
- }
- }
-
- painter->restore();
- }
-
- if (m_propertyGraph) { // Property graph
- QRectF graphRect(edgeOffset, 0, widget->width(), currentHeight);
- m_propertyGraph->paintGraphs(painter, graphRect);
- }
-
- // Keyframes
- const qreal keyFrameH = 16.0;
- const qreal keyFrameHalfH = keyFrameH / 2.0;
- const qreal keyFrameY = (qMin(currentHeight, TimelineConstants::ROW_H) / 2.0) - keyFrameHalfH;
- const qreal hiddenKeyFrameY = keyFrameY + (keyFrameH * 2.0 / 3.0) + 2.0;
- const qreal keyFrameOffset = hiResIcons ? 8 : 7.5;
-
- // Hidden descendant keyframe indicators
- if (!m_rowTree->expanded()) {
- static const QPixmap pixKeyframeHidden = QPixmap(":/images/keyframe-hidden-normal.png");
- static const QPixmap pixKeyframeHidden2x
- = QPixmap(":/images/keyframe-hidden-normal@2x.png");
- QVector<long> childKeyframeTimes;
- collectChildKeyframeTimes(childKeyframeTimes);
-
- const qreal oldOpacity = painter->opacity();
- painter->setOpacity(0.75);
- for (const auto time : qAsConst(childKeyframeTimes)) {
- const qreal xCoord = edgeOffset + m_rowTree->m_scene->ruler()->timeToDistance(time)
- - 2.5;
- painter->drawPixmap(QPointF(xCoord, hiddenKeyFrameY), hiResIcons ? pixKeyframeHidden2x
- : pixKeyframeHidden);
- }
- painter->setOpacity(oldOpacity);
- }
-
- if (m_rowTree->hasPropertyChildren()) { // object row keyframes
- static const QPixmap pixKeyframeMasterDisabled
- = QPixmap(":/images/Keyframe-Master-Disabled.png");
- static const QPixmap pixKeyframeMasterNormal
- = QPixmap(":/images/Keyframe-Master-Normal.png");
- static const QPixmap pixKeyframeMasterSelected
- = QPixmap(":/images/Keyframe-Master-Selected.png");
- static const QPixmap pixKeyframeMasterDynamicDisabled
- = QPixmap(":/images/Keyframe-MasterDynamic-Disabled.png");
- static const QPixmap pixKeyframeMasterDynamicNormal
- = QPixmap(":/images/Keyframe-MasterDynamic-Normal.png");
- static const QPixmap pixKeyframeMasterDynamicSelected
- = QPixmap(":/images/Keyframe-MasterDynamic-Selected.png");
- static const QPixmap pixKeyframeMasterDisabled2x
- = QPixmap(":/images/Keyframe-Master-Disabled@2x.png");
- static const QPixmap pixKeyframeMasterNormal2x
- = QPixmap(":/images/Keyframe-Master-Normal@2x.png");
- static const QPixmap pixKeyframeMasterSelected2x
- = QPixmap(":/images/Keyframe-Master-Selected@2x.png");
- static const QPixmap pixKeyframeMasterDynamicDisabled2x
- = QPixmap(":/images/Keyframe-MasterDynamic-Disabled@2x.png");
- static const QPixmap pixKeyframeMasterDynamicNormal2x
- = QPixmap(":/images/Keyframe-MasterDynamic-Normal@2x.png");
- static const QPixmap pixKeyframeMasterDynamicSelected2x
- = QPixmap(":/images/Keyframe-MasterDynamic-Selected@2x.png");
- for (auto keyframe : qAsConst(m_keyframes)) {
- QPixmap pixmap;
- if (m_rowTree->locked()) {
- if (keyframe->dynamic) {
- pixmap = hiResIcons ? pixKeyframeMasterDynamicDisabled2x
- : pixKeyframeMasterDynamicDisabled;
- } else {
- pixmap = hiResIcons ? pixKeyframeMasterDisabled2x
- : pixKeyframeMasterDisabled;
- }
- } else if (keyframe->selected()) {
- if (keyframe->dynamic) {
- pixmap = hiResIcons ? pixKeyframeMasterDynamicSelected2x
- : pixKeyframeMasterDynamicSelected;
- } else {
- pixmap = hiResIcons ? pixKeyframeMasterSelected2x
- : pixKeyframeMasterSelected;
- }
- } else {
- if (keyframe->dynamic) {
- pixmap = hiResIcons ? pixKeyframeMasterDynamicNormal2x
- : pixKeyframeMasterDynamicNormal;
- } else {
- pixmap = hiResIcons ? pixKeyframeMasterNormal2x
- : pixKeyframeMasterNormal;
- }
- }
- painter->drawPixmap(QPointF(edgeOffset + m_rowTree->m_scene->ruler()
- ->timeToDistance(keyframe->time) - keyFrameOffset,
- keyFrameY), pixmap);
-
- // highlight the pressed keyframe in a multi-selection (the keyframe that is affected
- // by snapping, and setting time dialog)
- if (m_rowTree->m_scene->keyframeManager()->selectedKeyframes().size() > 1
- && m_rowTree->m_scene->pressedKeyframe() == keyframe) {
- painter->setPen(QPen(CStudioPreferences::timelinePressedKeyframeColor(), 1));
- painter->drawArc(edgeOffset + m_rowTree->m_scene->ruler()
- ->timeToDistance(keyframe->time) - 4, keyFrameY + 4, 9, 9, 0,
- 5760);
- }
- }
- } else if (m_rowTree->isProperty()) { // property row keyframes
- static const QPixmap pixKeyframePropertyDisabled
- = QPixmap(":/images/Keyframe-Property-Disabled.png");
- static const QPixmap pixKeyframePropertyNormal
- = QPixmap(":/images/Keyframe-Property-Normal.png");
- static const QPixmap pixKeyframePropertySelected
- = QPixmap(":/images/Keyframe-Property-Selected.png");
- static const QPixmap pixKeyframePropertyDynamicDisabled
- = QPixmap(":/images/Keyframe-PropertyDynamic-Disabled.png");
- static const QPixmap pixKeyframePropertyDynamicNormal
- = QPixmap(":/images/Keyframe-PropertyDynamic-Normal.png");
- static const QPixmap pixKeyframePropertyDynamicSelected
- = QPixmap(":/images/Keyframe-PropertyDynamic-Selected.png");
- static const QPixmap pixKeyframePropertyDisabled2x
- = QPixmap(":/images/Keyframe-Property-Disabled@2x.png");
- static const QPixmap pixKeyframePropertyNormal2x
- = QPixmap(":/images/Keyframe-Property-Normal@2x.png");
- static const QPixmap pixKeyframePropertySelected2x
- = QPixmap(":/images/Keyframe-Property-Selected@2x.png");
- static const QPixmap pixKeyframePropertyDynamicDisabled2x
- = QPixmap(":/images/Keyframe-PropertyDynamic-Disabled@2x.png");
- static const QPixmap pixKeyframePropertyDynamicNormal2x
- = QPixmap(":/images/Keyframe-PropertyDynamic-Normal@2x.png");
- static const QPixmap pixKeyframePropertyDynamicSelected2x
- = QPixmap(":/images/Keyframe-PropertyDynamic-Selected@2x.png");
- for (auto keyframe : qAsConst(m_keyframes)) {
- QPixmap pixmap;
- if (m_rowTree->locked()) {
- if (keyframe->dynamic) {
- pixmap = hiResIcons ? pixKeyframePropertyDynamicDisabled2x
- : pixKeyframePropertyDynamicDisabled;
-
- } else {
- pixmap = hiResIcons ? pixKeyframePropertyDisabled2x
- : pixKeyframePropertyDisabled;
- }
- } else if (keyframe->selected()) {
- if (keyframe->dynamic) {
- pixmap = hiResIcons ? pixKeyframePropertyDynamicSelected2x
- : pixKeyframePropertyDynamicSelected;
-
- } else {
- pixmap = hiResIcons ? pixKeyframePropertySelected2x
- : pixKeyframePropertySelected;
- }
- } else {
- if (keyframe->dynamic) {
- pixmap = hiResIcons ? pixKeyframePropertyDynamicNormal2x
- : pixKeyframePropertyDynamicNormal;
-
- } else {
- pixmap = hiResIcons ? pixKeyframePropertyNormal2x
- : pixKeyframePropertyNormal;
- }
- }
- painter->drawPixmap(QPointF(edgeOffset + m_rowTree->m_scene->ruler()
- ->timeToDistance(keyframe->time) - keyFrameOffset,
- keyFrameY), pixmap);
- }
- }
-}
-
-bool RowTimeline::isColorProperty() const
-{
- ITimelineItemProperty *propBinding = m_rowTree->propBinding();
- if (propBinding) {
- qt3dsdm::TDataTypePair type = propBinding->GetType();
- if (m_rowTree->isProperty()
- && type.first == qt3dsdm::DataModelDataType::Float4
- && type.second == qt3dsdm::AdditionalMetaDataType::Color) {
- return true;
- }
- }
- return false;
-}
-
-void RowTimeline::drawColorPropertyGradient(QPainter *painter, int width)
-{
- // Gradient scaled width, or at least widget width
- double minWidth = width;
- double timelineScale = m_rowTree->m_scene->ruler()->timelineScale();
- double scaledWidth = width * (timelineScale / 2);
- width = qMax(minWidth, scaledWidth);
-
- ITimelineItemProperty *propBinding = m_rowTree->propBinding();
- QLinearGradient bgGradient(0, 0, width, 0);
-
- for (auto keyframe : qAsConst(m_keyframes)) {
- double xPos = m_rowTree->m_scene->ruler()->timeToDistance(keyframe->time);
- double gradPos = xPos / width;
- gradPos = qBound(0.0, gradPos, 1.0);
- QColor currentColor;
- // Get the color at the specified time.
- currentColor.setRed(propBinding->GetChannelValueAtTime(0, keyframe->time));
- currentColor.setGreen(propBinding->GetChannelValueAtTime(1, keyframe->time));
- currentColor.setBlue(propBinding->GetChannelValueAtTime(2, keyframe->time));
- bgGradient.setColorAt(gradPos, currentColor);
- }
- painter->fillRect(TimelineConstants::RULER_EDGE_OFFSET, 0,
- width, size().height() - 1, bgGradient);
-}
-
-Keyframe *RowTimeline::getClickedKeyframe(const QPointF &scenePos)
-{
- if (rowTree()->locked())
- return nullptr;
-
- QPointF p = mapFromScene(scenePos.x(), scenePos.y());
- double x;
-
- QList<Keyframe *> keyframes;
- if (m_rowTree->hasPropertyChildren()) {
- const auto childProps = m_rowTree->childProps();
- for (auto child : childProps)
- keyframes.append(child->rowTimeline()->m_keyframes);
- } else {
- keyframes = m_keyframes;
- }
-
- for (const auto keyframe : qAsConst(keyframes)) {
- x = TimelineConstants::RULER_EDGE_OFFSET
- + m_rowTree->m_scene->ruler()->timeToDistance(keyframe->time);
-
- if (p.x() > x - 5 && p.x() < x + 5 && p.y() > 3 && p.y() < 16)
- return keyframe;
- }
-
- return nullptr;
-}
-
-QList<Keyframe *> RowTimeline::getKeyframesInRange(const QRectF &rect) const
-{
- double x;
- QRectF localRect = mapFromScene(rect).boundingRect();
-
- QList<Keyframe *> result;
-
- static const int KF_CENTER_Y = 10;
- for (auto keyframe : qAsConst(m_keyframes)) {
- x = TimelineConstants::RULER_EDGE_OFFSET
- + m_rowTree->m_scene->ruler()->timeToDistance(keyframe->time);
-
- if (localRect.left() < x && localRect.right() > x
- && localRect.top() < KF_CENTER_Y && localRect.bottom() > KF_CENTER_Y) {
- result.append(keyframe);
- }
- }
-
- return result;
-}
-
-void RowTimeline::updateDurationFromBinding()
-{
- if (m_rowTree->isProperty()) // this method works for main rows only
- return;
-
- ITimelineTimebar *timebar = m_rowTree->m_binding->GetTimelineItem()->GetTimebar();
- clearBoundChildren();
- setStartTime(timebar->GetStartTime());
- setEndTime(timebar->GetEndTime());
-}
-
-void RowTimeline::updateKeyframesFromBinding(const QList<int> &properties)
-{
- if (m_rowTree->isProperty()) // this method works for main rows only
- return;
-
- const auto childProps = m_rowTree->childProps();
- for (auto child : childProps) {
- qt3dsdm::Qt3DSDMPropertyHandle propertyHandle =
- static_cast<Qt3DSDMTimelineItemProperty *>(child->m_PropBinding)
- ->getPropertyHandle();
- if (properties.contains(propertyHandle)) {
- m_rowTree->m_scene->keyframeManager()->deleteKeyframes(child->rowTimeline(), false);
-
- for (int i = 0; i < child->m_PropBinding->GetKeyframeCount(); i++) {
- Qt3DSDMTimelineKeyframe *kf = static_cast<Qt3DSDMTimelineKeyframe *>
- (child->m_PropBinding->GetKeyframeByIndex(i));
-
- Keyframe *kfUI = new Keyframe(kf->GetTime(), child->rowTimeline());
- kfUI->binding = kf;
- kfUI->dynamic = kf->IsDynamic();
- kf->setUI(kfUI);
- child->rowTimeline()->insertKeyframe(kfUI);
- child->parentRow()->rowTimeline()->insertKeyframe(kfUI);
- if (kf->IsSelected())
- m_rowTree->m_scene->keyframeManager()->selectKeyframe(kfUI);
- }
-
- if (isVisible()) {
- child->rowTimeline()->update();
- } else {
- // Find the first visible parent and update that to show hidden keyframes
- RowTree *updateRow = m_rowTree->parentRow();
- while (updateRow && !updateRow->isVisible())
- updateRow = updateRow->parentRow();
- if (updateRow)
- updateRow->rowTimeline()->update();
- }
- }
- }
- update();
-}
-
-void RowTimeline::insertKeyframe(Keyframe *keyframe)
-{
- if (!m_keyframes.contains(keyframe))
- m_keyframes.append(keyframe);
-}
-
-void RowTimeline::removeKeyframe(Keyframe *keyframe)
-{
- m_keyframes.removeAll(keyframe);
-}
-
-void RowTimeline::putSelectedKeyframesOnTop()
-{
- if (!m_keyframes.empty()) {
- std::partition(m_keyframes.begin(), m_keyframes.end(), [](Keyframe *kf) {
- return !kf->selected();
- });
- }
-
- if (m_rowTree->hasPropertyChildren()) { // has property rows
- const auto childProps = m_rowTree->childProps();
- for (auto child : childProps) {
- std::partition(child->rowTimeline()->m_keyframes.begin(),
- child->rowTimeline()->m_keyframes.end(), [](Keyframe *kf) {
- return !kf->selected();
- });
- }
- }
-}
-
-void RowTimeline::updateKeyframes()
-{
- update();
-
- if (m_rowTree->hasPropertyChildren()) { // master keyframes
- const auto childProps = m_rowTree->childProps();
- for (const auto child : childProps)
- child->rowTimeline()->update();
- }
-}
-
-TimelineControlType RowTimeline::getClickedControl(const QPointF &scenePos) const
-{
- if (!m_rowTree->hasDurationBar())
- return TimelineControlType::None;
-
- if (!m_rowTree->locked()) {
- QPointF p = mapFromScene(scenePos.x(), scenePos.y());
- p.setX(p.x() - TimelineConstants::RULER_EDGE_OFFSET);
-
- const int halfHandle = TimelineConstants::DURATION_HANDLE_W * .5;
- // Never choose start handle if end time is zero, as you cannot adjust it in that case
- bool startHandle = p.x() > m_startX - halfHandle && p.x() < m_startX + halfHandle
- && m_endTime > 0;
- bool endHandle = p.x() > m_endX - halfHandle && p.x() < m_endX + halfHandle;
- if (startHandle && endHandle) {
- // If handles overlap, choose the handle based on the side of the click relative to start
- startHandle = p.x() < m_startX;
- endHandle = !startHandle;
- }
- if (startHandle)
- return TimelineControlType::StartHandle;
- else if (endHandle)
- return TimelineControlType::EndHandle;
- else if (p.x() > m_startX && p.x() < m_endX && !rowTree()->locked())
- return TimelineControlType::Duration;
- }
-
- return TimelineControlType::None;
-}
-
-void RowTimeline::startDurationMove(double clickX)
-{
- // clickX is in ruler coordinate space
- m_startDurationMoveStartTime = m_startTime;
- m_startDurationMoveOffsetX = clickX - m_startX;
-}
-
-void RowTimeline::updateBoundChildren(bool start)
-{
- // Collect all bound children
- // Children are considered bound if the start/end time matches the parent time
- if (start)
- m_boundChildrenStart.clear();
- else
- m_boundChildrenEnd.clear();
- if (m_rowTree->hasDurationBar()) {
- const auto childRows = m_rowTree->childRows();
- for (auto child : childRows) {
- if (child->hasDurationBar() && !child->locked()) {
- RowTimeline *rowTimeline = child->rowTimeline();
- if (start && rowTimeline->m_startX == m_startX) {
- m_boundChildrenStart.append(rowTimeline);
- rowTimeline->updateBoundChildren(start);
- } else if (!start && rowTimeline->m_endX == m_endX) {
- m_boundChildrenEnd.append(rowTimeline);
- rowTimeline->updateBoundChildren(start);
- }
- }
- }
- }
-}
-
-void RowTimeline::clearBoundChildren()
-{
- m_boundChildrenStart.clear();
- m_boundChildrenEnd.clear();
-}
-
-// move the duration area (start/end x)
-void RowTimeline::moveDurationBy(double dx)
-{
- if (m_startX + dx < 0)
- dx = -m_startX;
-
- m_startX += dx;
- m_endX += dx;
-
- if (!m_rowTree->parentRow() || m_rowTree->objectType() == OBJTYPE_LAYER
- || m_rowTree->hasComponentAncestor()) {
- m_minStartX = m_startX;
- m_maxEndX = m_endX;
- }
-
- Ruler *ruler = m_rowTree->m_scene->ruler();
- m_startTime = ruler->distanceToTime(m_startX);
- m_endTime = ruler->distanceToTime(m_endX);
-
- // move keyframes with the row
- if (!m_rowTree->isProperty()) { // make sure we don't move the keyframes twice
- for (Keyframe *keyframe : qAsConst(m_keyframes))
- keyframe->time += rowTree()->m_scene->ruler()->distanceToTime(dx);
- }
-
- update();
-
- if (!m_rowTree->empty()) {
- updateChildrenMinStartXRecursive(m_rowTree);
- updateChildrenMaxEndXRecursive(m_rowTree);
-
- for (RowTree *child : qAsConst(m_rowTree->m_childRows)) {
- if (!child->locked())
- child->m_rowTimeline->moveDurationBy(dx);
- }
- }
-}
-
-void RowTimeline::moveDurationTo(double newX)
-{
- if (newX < 0)
- newX = 0;
-
- double dx = newX - m_startX;
- double durationX = m_endX - m_startX;
-
- m_startX = newX;
- m_endX = m_startX + durationX;
-
- if (!m_rowTree->parentRow() || m_rowTree->objectType() == OBJTYPE_LAYER
- || m_rowTree->hasComponentAncestor()) {
- m_minStartX = m_startX;
- m_maxEndX = m_endX;
- }
-
- Ruler *ruler = m_rowTree->m_scene->ruler();
- m_startTime = ruler->distanceToTime(m_startX);
- m_endTime = ruler->distanceToTime(m_endX);
-
- // move keyframes with the row
- if (!m_rowTree->isProperty()) { // make sure we don't move the keyframes twice
- for (Keyframe *keyframe : qAsConst(m_keyframes))
- keyframe->time += ruler->distanceToTime(dx);
- }
-
- update();
-
- if (!m_rowTree->empty()) {
- updateChildrenMinStartXRecursive(m_rowTree);
- updateChildrenMaxEndXRecursive(m_rowTree);
-
- for (RowTree *child : qAsConst(m_rowTree->m_childRows)) {
- if (!child->locked())
- child->m_rowTimeline->moveDurationBy(dx);
- }
- }
-}
-
-long RowTimeline::getDurationMoveTime() const
-{
- return m_startTime - m_startDurationMoveStartTime;
-}
-
-double RowTimeline::getDurationMoveOffsetX() const
-{
- return m_startDurationMoveOffsetX;
-}
-
-long RowTimeline::getDuration() const
-{
- return m_endTime - m_startTime;
-}
-
-void RowTimeline::collectChildKeyframeTimes(QVector<long> &childKeyframeTimes)
-{
- const auto childRows = m_rowTree->childRows();
- for (const auto row : childRows) {
- row->rowTimeline()->collectChildKeyframeTimes(childKeyframeTimes);
- const auto keyframes = row->rowTimeline()->keyframes();
- for (const auto kf : keyframes)
- childKeyframeTimes.append(kf->time);
- }
-}
-
-// called after timeline scale is changed to update duration star/end positions
-void RowTimeline::updatePosition()
-{
- clearBoundChildren();
- setStartTime(m_startTime);
- setEndTime(m_endTime);
-}
-
-// Set the position of the start of the row duration
-void RowTimeline::setStartX(double startX)
-{
- if (startX < 0)
- startX = 0;
- else if (startX > m_endX)
- startX = m_endX;
-
- m_startX = startX;
- m_startTime = m_rowTree->m_scene->ruler()->distanceToTime(startX);
-
- if (!m_rowTree->parentRow() || m_rowTree->parentRow()->objectType() == OBJTYPE_SCENE
- || m_rowTree->hasComponentAncestor()) {
- m_minStartX = 0;
- }
-
- updateChildrenStartRecursive();
- updateChildrenMinStartXRecursive(m_rowTree);
- update();
-}
-
-// Set the position of the end of the row duration
-void RowTimeline::setEndX(double endX)
-{
- if (endX < m_startX)
- endX = m_startX;
-
- m_endX = endX;
- m_endTime = m_rowTree->m_scene->ruler()->distanceToTime(endX);
-
- if (!m_rowTree->parentRow() || m_rowTree->parentRow()->objectType() == OBJTYPE_SCENE
- || m_rowTree->hasComponentAncestor()) {
- m_maxEndX = 999999;
- }
-
- updateChildrenEndRecursive();
- updateChildrenMaxEndXRecursive(m_rowTree);
- update();
-}
-
-QColor RowTimeline::barColor() const
-{
- return m_barColor;
-}
-
-void RowTimeline::setBarColor(const QColor &color)
-{
- m_barColor = color;
- update();
-}
-
-void RowTimeline::setControllerText(const QString &controller)
-{
- m_controllerDataInput = controller;
- update();
-}
-
-void RowTimeline::updateChildrenStartRecursive()
-{
- for (auto child : qAsConst(m_boundChildrenStart)) {
- if (!child.isNull()) {
- child->m_startX = m_startX;
- child->m_startTime = m_startTime;
- child->updateChildrenStartRecursive();
- child->update();
- }
- }
-}
-
-void RowTimeline::updateChildrenEndRecursive()
-{
- for (auto child : qAsConst(m_boundChildrenEnd)) {
- if (!child.isNull()) {
- child->m_endX = m_endX;
- child->m_endTime = m_endTime;
- child->updateChildrenEndRecursive();
- child->update();
- }
- }
-}
-
-void RowTimeline::updateChildrenMinStartXRecursive(RowTree *rowTree)
-{
- if (m_rowTree->objectType() != OBJTYPE_SCENE && !rowTree->empty()) {
- const auto childRows = rowTree->childRows();
- bool isComponentChild = m_rowTree->objectType() == OBJTYPE_COMPONENT
- || m_rowTree->hasComponentAncestor();
- for (auto child : childRows) {
- if (isComponentChild) {
- child->rowTimeline()->m_minStartX = 0;
- } else {
- child->rowTimeline()->m_minStartX = qMax(rowTree->rowTimeline()->m_startX,
- rowTree->rowTimeline()->m_minStartX);
- }
- child->rowTimeline()->update();
-
- updateChildrenMinStartXRecursive(child);
- }
- }
-}
-
-void RowTimeline::updateChildrenMaxEndXRecursive(RowTree *rowTree)
-{
- if (m_rowTree->objectType() != OBJTYPE_SCENE && !rowTree->empty()) {
- const auto childRows = rowTree->childRows();
- bool isComponentChild = m_rowTree->objectType() == OBJTYPE_COMPONENT
- || m_rowTree->hasComponentAncestor();
- for (auto child : childRows) {
- if (isComponentChild) {
- child->rowTimeline()->m_maxEndX = 999999;
- } else {
- child->rowTimeline()->m_maxEndX = qMin(rowTree->rowTimeline()->m_endX,
- rowTree->rowTimeline()->m_maxEndX);
- }
- child->rowTimeline()->update();
-
- updateChildrenMaxEndXRecursive(child);
- }
- }
-}
-
-void RowTimeline::updateCommentItem()
-{
- if (!m_commentItem)
- return;
- TimelineToolbar *toolbar = m_rowTree->m_scene->widgetTimeline()->toolbar();
- // Backend allows storing comments for rows with duration bar
- bool canHaveComment = m_rowTree->hasDurationBar();
- bool showComments = canHaveComment && toolbar->actionShowRowTexts()->isChecked();
- m_commentItem->setVisible(showComments);
- if (showComments && m_rowTree->m_binding) {
- ITimelineTimebar *timebar = m_rowTree->m_binding->GetTimelineItem()->GetTimebar();
- m_commentItem->setLabel(timebar->GetTimebarComment());
- }
-}
-
-void RowTimeline::updateCommentItemPos()
-{
- if (!m_commentItem)
- return;
-
- Ruler *ruler = m_rowTree->m_scene->ruler();
- m_commentItem->setPos(TimelineConstants::RULER_EDGE_OFFSET + ruler->viewportX(),
- -TimelineConstants::ROW_TEXT_OFFSET_Y);
-}
-
-void RowTimeline::setStartTime(long startTime)
-{
- m_startTime = startTime;
- m_startX = m_rowTree->m_scene->ruler()->timeToDistance(startTime);
-
- if (!m_rowTree->parentRow() || m_rowTree->parentRow()->objectType() == OBJTYPE_SCENE
- || m_rowTree->hasComponentAncestor()) {
- m_minStartX = 0;
- }
-
- updateChildrenStartRecursive();
- updateChildrenMinStartXRecursive(m_rowTree);
- update();
-}
-
-void RowTimeline::setEndTime(long endTime)
-{
- m_endTime = endTime;
- m_endX = m_rowTree->m_scene->ruler()->timeToDistance(endTime);
-
- if (!m_rowTree->parentRow() || m_rowTree->parentRow()->objectType() == OBJTYPE_SCENE
- || m_rowTree->hasComponentAncestor()) {
- m_maxEndX = 999999;
- }
-
- updateChildrenEndRecursive();
- updateChildrenMaxEndXRecursive(m_rowTree);
- update();
-}
-
-// duration start x in local space (x=0 at time=0)
-double RowTimeline::getStartX() const
-{
- return m_startX;
-}
-
-// duration end x in local space
-double RowTimeline::getEndX() const
-{
- return m_endX;
-}
-
-long RowTimeline::getStartTime() const
-{
- return m_startTime;
-}
-
-long RowTimeline::getEndTime() const
-{
- return m_endTime;
-}
-
-void RowTimeline::setState(State state)
-{
- m_state = state;
- m_rowTree->m_state = state;
-
- update();
- m_rowTree->update();
-}
-
-void RowTimeline::setRowTree(RowTree *rowTree)
-{
- m_rowTree = rowTree;
- if (m_rowTree->isProperty()) {
- if (m_propertyGraph)
- delete m_propertyGraph;
- m_propertyGraph = new RowTimelinePropertyGraph(this);
- }
- initialize();
-}
-
-RowTree *RowTimeline::rowTree() const
-{
- return m_rowTree;
-}
-
-QList<Keyframe *> RowTimeline::keyframes() const
-{
- return m_keyframes;
-}
-
-QString RowTimeline::formatTime(long millis) const
-{
- static const QString timeTemplate = tr("%1:%2.%3");
- static const QChar fillChar = tr("0").at(0);
-
- long mins = millis % 3600000 / 60000;
- long secs = millis % 60000 / 1000;
- long mils = millis % 1000;
-
- return timeTemplate.arg(mins).arg(secs, 2, 10, fillChar).arg(mils, 3, 10, fillChar);
-}
-
-void RowTimeline::showToolTip(const QPointF &pos)
-{
- QLabel *tooltip = m_rowTree->m_scene->timebarTooltip();
-
- tooltip->setText(formatTime(m_startTime) + " - " + formatTime(m_endTime)
- + " (" + formatTime(m_endTime - m_startTime) + ")");
-
- tooltip->adjustSize();
-
- QPoint newPos = pos.toPoint() + QPoint(-tooltip->width() / 2,
- -tooltip->height() - TimelineConstants::TIMEBAR_TOOLTIP_OFFSET_V);
-
- // Confine the tooltip to the current screen area to avoid artifacts from different pixel ratios
- static const int MARGIN = 5;
- const QRect screenGeometry = QApplication::desktop()->screenGeometry(
- m_rowTree->m_scene->widgetTimeline());
- int xMin = screenGeometry.x() + MARGIN;
- int xMax = screenGeometry.x() + screenGeometry.width() - tooltip->width() - MARGIN;
- if (newPos.x() < xMin)
- newPos.setX(xMin);
- else if (newPos.x() > xMax)
- newPos.setX(xMax);
-
- tooltip->move(newPos);
- tooltip->raise();
- tooltip->show();
-}
-
-RowTimeline *RowTimeline::parentRow() const
-{
- if (!m_rowTree->m_parentRow)
- return nullptr;
-
- return m_rowTree->m_parentRow->rowTimeline();
-}
-
-void RowTimeline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
-{
- InteractiveTimelineItem::hoverLeaveEvent(event);
- // Make sure mouse cursor is reseted when moving away from timeline row
- m_rowTree->m_scene->resetMouseCursor();
-}
-
-int RowTimeline::type() const
-{
- // Enable the use of qgraphicsitem_cast with this item.
- return TypeRowTimeline;
-}