// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "transitioneditortoolbar.h" #include "transitioneditorgraphicsscene.h" #include "transitioneditorconstants.h" #include "timelineicons.h" #include "timelineview.h" #include "timelinewidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace QmlDesigner { static bool isSpacer(QObject *object) { return object->property("spacer_widget").toBool(); } static QWidget *createSpacer() { QWidget *spacer = new QWidget(); spacer->setProperty("spacer_widget", true); return spacer; } static int controlWidth(QToolBar *bar, QObject *control) { QWidget *widget = nullptr; if (auto *action = qobject_cast(control)) widget = bar->widgetForAction(action); if (widget == nullptr) widget = qobject_cast(control); if (widget) return widget->width(); return 0; } static QAction *createAction(const Utils::Id &id, const QIcon &icon, const QString &name, const QKeySequence &shortcut) { Core::Context context(TransitionEditorConstants::C_QMLTRANSITIONS); auto *action = new QAction(icon, name); auto *command = Core::ActionManager::registerAction(action, id, context); command->setDefaultKeySequence(shortcut); command->augmentActionWithShortcutToolTip(action); return action; } TransitionEditorToolBar::TransitionEditorToolBar(QWidget *parent) : QToolBar(parent) , m_grp() { setFixedHeight(Theme::toolbarSize()); setContentsMargins(0, 0, 0, 0); createLeftControls(); createCenterControls(); createRightControls(); } void TransitionEditorToolBar::reset() {} int TransitionEditorToolBar::scaleFactor() const { if (m_scale) return m_scale->value(); return 0; } QString TransitionEditorToolBar::currentTransitionId() const { return m_transitionComboBox->currentText(); } void TransitionEditorToolBar::updateComboBox(const ModelNode &root) { if (NodeAbstractProperty transitions = root.nodeAbstractProperty("transitions")) { for (const ModelNode &transition : transitions.directSubNodes()) m_transitionComboBox->addItem(transition.id()); } } void TransitionEditorToolBar::setCurrentTransition(const ModelNode &transition) { if (transition.isValid()) { m_transitionComboBox->clear(); const ModelNode root = transition.view()->rootModelNode(); updateComboBox(root); m_transitionComboBox->setCurrentText(transition.id()); } else { m_transitionComboBox->clear(); m_transitionComboBox->setCurrentText(""); } } void TransitionEditorToolBar::setDuration(qreal frame) { auto text = QString::number(frame, 'f', 0); m_duration->setText(text); } void TransitionEditorToolBar::setScaleFactor(int factor) { const QSignalBlocker blocker(m_scale); m_scale->setValue(factor); } void TransitionEditorToolBar::setActionEnabled(const QString &name, bool enabled) { for (auto *action : actions()) if (action->objectName() == name) action->setEnabled(enabled); } void TransitionEditorToolBar::createLeftControls() { auto addActionToGroup = [&](QAction *action) { addAction(action); m_grp << action; }; auto addWidgetToGroup = [&](QWidget *widget) { addWidget(widget); m_grp << widget; }; auto addSpacingToGroup = [&](int width) { auto *widget = new QWidget; widget->setFixedWidth(width); addWidget(widget); m_grp << widget; }; addSpacingToGroup(5); auto *settingsAction = createAction(TransitionEditorConstants::C_SETTINGS, Theme::iconFromName(Theme::Icon::settings_medium), tr("Transition Settings"), QKeySequence(Qt::Key_S)); connect(settingsAction, &QAction::triggered, this, &TransitionEditorToolBar::settingDialogClicked); addActionToGroup(settingsAction); addWidgetToGroup(createSpacer()); m_transitionComboBox = new QComboBox(this); addWidgetToGroup(m_transitionComboBox); connect(m_transitionComboBox, &QComboBox::currentTextChanged, this, [this]() { emit currentTransitionChanged(m_transitionComboBox->currentText()); }); } static QLineEdit *createToolBarLineEdit(QWidget *parent) { auto lineEdit = new QLineEdit(parent); lineEdit->setStyleSheet("* { background-color: rgba(0, 0, 0, 0); }"); lineEdit->setFixedWidth(48); lineEdit->setAlignment(Qt::AlignCenter); QPalette pal = parent->palette(); pal.setColor(QPalette::Text, Theme::instance()->color(Utils::Theme::PanelTextColorLight)); lineEdit->setPalette(pal); QValidator *validator = new QIntValidator(-100000, 100000, lineEdit); lineEdit->setValidator(validator); return lineEdit; } void TransitionEditorToolBar::createCenterControls() { addSpacing(10); auto *curvePicker = createAction(TransitionEditorConstants::C_CURVE_PICKER, Theme::iconFromName(Theme::Icon::curveDesigner_medium), tr("Easing Curve Editor"), QKeySequence(Qt::Key_C)); curvePicker->setObjectName("Easing Curve Editor"); connect(curvePicker, &QAction::triggered, this, &TransitionEditorToolBar::openEasingCurveEditor); addAction(curvePicker); addSpacing(10); #if 0 addSeparator(); addSpacing(10); auto *curveEditor = new QAction(TimelineIcons::CURVE_PICKER.icon(), tr("Curve Editor")); addAction(curveEditor); #endif } void TransitionEditorToolBar::createRightControls() { auto *spacer = createSpacer(); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); addWidget(spacer); addSeparator(); addSpacing(10); auto *zoomOut = createAction(TransitionEditorConstants::C_ZOOM_OUT, Theme::iconFromName(Theme::Icon::zoomOut_medium), tr("Zoom Out"), QKeySequence(QKeySequence::ZoomOut)); connect(zoomOut, &QAction::triggered, [this]() { m_scale->setValue(m_scale->value() - m_scale->pageStep()); }); addAction(zoomOut); addSpacing(10); m_scale = new QSlider(this); Utils::StyleHelper::setPanelWidget(m_scale); Utils::StyleHelper::setPanelWidgetSingleRow(m_scale); m_scale->setOrientation(Qt::Horizontal); m_scale->setMaximumWidth(200); m_scale->setMinimumWidth(100); m_scale->setMinimum(0); m_scale->setMaximum(100); m_scale->setValue(0); connect(m_scale, &QSlider::valueChanged, this, &TransitionEditorToolBar::scaleFactorChanged); addWidget(m_scale); addSpacing(10); auto *zoomIn = createAction(TransitionEditorConstants::C_ZOOM_IN, Theme::iconFromName(Theme::Icon::zoomIn_medium), tr("Zoom In"), QKeySequence(QKeySequence::ZoomIn)); connect(zoomIn, &QAction::triggered, [this]() { m_scale->setValue(m_scale->value() + m_scale->pageStep()); }); addAction(zoomIn); addSpacing(10); addSeparator(); m_duration = createToolBarLineEdit(this); addWidget(m_duration); auto emitEndChanged = [this]() { emit durationChanged(m_duration->text().toInt()); }; connect(m_duration, &QLineEdit::editingFinished, emitEndChanged); addSpacing(5); } void TransitionEditorToolBar::addSpacing(int width) { auto *widget = new QWidget; widget->setFixedWidth(width); addWidget(widget); } void TransitionEditorToolBar::resizeEvent([[maybe_unused]] QResizeEvent *event) { int width = 0; QWidget *spacer = nullptr; for (auto *object : std::as_const(m_grp)) { if (isSpacer(object)) spacer = qobject_cast(object); else width += controlWidth(this, object); } if (spacer) { int spacerWidth = TransitionEditorConstants::sectionWidth - width - 12; spacer->setFixedWidth(spacerWidth > 0 ? spacerWidth : 0); } } } // namespace QmlDesigner