diff --git a/src/assets/view/widgets/dragvalue.h b/src/assets/view/widgets/dragvalue.h new file mode 100644 --- /dev/null +++ b/src/assets/view/widgets/dragvalue.h @@ -0,0 +1,169 @@ +/*************************************************************************** + * Copyright (C) 2011 by Till Theato (root@ttill.de) * + * This file is part of Kdenlive (www.kdenlive.org). * + * * + * Kdenlive is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * Kdenlive is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with Kdenlive. If not, see . * + ***************************************************************************/ + +#ifndef DRAGVALUE_H +#define DRAGVALUE_H + +#include +#include +#include +#include +#include + +class QAction; +class QMenu; +class KSelectAction; + +class CustomLabel : public QProgressBar +{ + Q_OBJECT +public: + explicit CustomLabel(const QString &label, bool showSlider = true, int range = 1000, QWidget *parent = nullptr); + void setProgressValue(double value); + void setStep(double step); + +protected: + // virtual void mouseDoubleClickEvent(QMouseEvent * event); + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + // virtual void paintEvent(QPaintEvent *event); + void wheelEvent(QWheelEvent *event) override; + void focusInEvent(QFocusEvent *e) override; + void focusOutEvent(QFocusEvent *e) override; + +private: + QPoint m_dragStartPosition; + QPoint m_dragLastPosition; + bool m_dragMode; + bool m_showSlider; + double m_step; + void slotValueInc(double factor = 1); + void slotValueDec(double factor = 1); + void setNewValue(double, bool); + +signals: + void valueChanged(double, bool); + void setInTimeline(); + void resetValue(); +}; + +/** + * @brief A widget for modifying numbers by dragging, using the mouse wheel or entering them with the keyboard. + */ + +class DragValue : public QWidget +{ + Q_OBJECT + +public: + /** + * @brief Default constructor. + * @param label The label that will be displayed in the progress bar + * @param defaultValue The default value + * @param decimals The number of decimals for the parameter. 0 means it is an integer + * @param min The minimum value + * @param max The maximum value + * @param id Used to identify this widget. If this parameter is set, "Show in Timeline" will be available in context menu. + * @param suffix The suffix that will be displayed in the spinbox (for example '%') + * @param showSlider If disabled, user can still drag on the label but no progress bar is shown + */ + explicit DragValue(const QString &label, double defaultValue, int decimals, double min = 0, double max = 100, int id = -1, + const QString &suffix = QString(), bool showSlider = true, QWidget *parent = nullptr); + virtual ~DragValue(); + + /** @brief Returns the precision = number of decimals */ + int precision() const; + /** @brief Returns the maximum value */ + qreal minimum() const; + /** @brief Returns the minimum value */ + qreal maximum() const; + + /** @brief Sets the minimum value. */ + void setMinimum(qreal min); + /** @brief Sets the maximum value. */ + void setMaximum(qreal max); + /** @brief Sets minimum and maximum value. */ + void setRange(qreal min, qreal max); + /** @brief Sets the size of a step (when dragging or using the mouse wheel). */ + void setStep(qreal step); + + /** @brief Returns the current value */ + qreal value() const; + /** @brief Change the "inTimeline" property to paint the intimeline widget differently. */ + void setInTimelineProperty(bool intimeline); + /** @brief Returns minimum size for QSpinBox, used to set all spinboxes to the same width. */ + int spinSize(); + /** @brief Sets the minimum size for QSpinBox, used to set all spinboxes to the same width. */ + void setSpinSize(int width); + /** @brief Returns true if widget is currently being edited */ + bool hasEditFocus() const; + +public slots: + /** @brief Sets the value (forced to be in the valid range) and emits valueChanged. */ + void setValue(double value, bool final = true); + void setValueFromProgress(double value, bool final); + /** @brief Resets to default value */ + void slotReset(); + +signals: + void valueChanged(double value, bool final = true); + void inTimeline(int); + + /* + * Private + */ + +protected: + /*virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseMoveEvent(QMouseEvent *e); + virtual void mouseReleaseEvent(QMouseEvent *e);*/ + /** @brief Forwards tab focus to lineedit since it is disabled. */ + void focusInEvent(QFocusEvent *e) override; + void focusOutEvent(QFocusEvent *e) override; + // virtual void keyPressEvent(QKeyEvent *e); + // virtual void wheelEvent(QWheelEvent *e); + // virtual void paintEvent( QPaintEvent * event ); + +private slots: + + void slotEditingFinished(); + + void slotSetScaleMode(int mode); + void slotSetDirectUpdate(bool directUpdate); + void slotShowContextMenu(const QPoint &pos); + void slotSetValue(int value); + void slotSetValue(double value); + void slotSetInTimeline(); + +private: + double m_maximum; + double m_minimum; + int m_decimals; + double m_default; + int m_id; + QSpinBox *m_intEdit; + QDoubleSpinBox *m_doubleEdit; + + QMenu *m_menu; + KSelectAction *m_scale; + QAction *m_directUpdate; + CustomLabel *m_label; +}; + +#endif diff --git a/src/assets/view/widgets/keyframewidget.hpp b/src/assets/view/widgets/keyframewidget.hpp --- a/src/assets/view/widgets/keyframewidget.hpp +++ b/src/assets/view/widgets/keyframewidget.hpp @@ -35,6 +35,7 @@ class QToolButton; class TimecodeDisplay; class KSelectAction; +class DragValue; class KeyframeWidget : public AbstractParamWidget { @@ -62,6 +63,7 @@ void slotAtKeyframe(bool atKeyframe, bool singleKeyframe); void monitorSeek(int pos); void slotEditKeyframeType(QAction *action); + void slotAdjustRectKeyframeValue(); private: QVBoxLayout *m_lay; @@ -73,7 +75,9 @@ QToolButton *m_buttonNext; KSelectAction *m_selectType; TimecodeDisplay *m_time; - + DragValue *m_rotation; + //const QString getValue() const; + std::unordered_map m_parameters; }; diff --git a/src/assets/view/widgets/keyframewidget.cpp b/src/assets/view/widgets/keyframewidget.cpp --- a/src/assets/view/widgets/keyframewidget.cpp +++ b/src/assets/view/widgets/keyframewidget.cpp @@ -22,6 +22,7 @@ #include "assets/keyframes/view/keyframeview.hpp" #include "assets/model/assetparametermodel.hpp" #include "core.h" +#include "dragvalue.h" #include "monitor/monitor.h" #include "timecode.h" #include "timecodedisplay.h" @@ -235,6 +236,13 @@ m_keyframes->refresh(); } +void KeyframeWidget::slotAdjustRectKeyframeValue() +{ + //QRect rect(m_spinX->value(), m_spinY->value(), m_spinWidth->value(), m_spinHeight->value()); + //m_monitor->setUpEffectGeometry(rect); + emit valueChanged(getValue()); +} + void KeyframeWidget::addParameter(const QPersistentModelIndex &index) { QLocale locale; @@ -268,6 +276,11 @@ double defaultValue = locale.toDouble(m_model->data(index, AssetParameterModel::DefaultRole).toString()); int decimals = m_model->data(index, AssetParameterModel::DecimalsRole).toInt(); double factor = m_model->data(index, AssetParameterModel::FactorRole).toDouble(); + QString name = m_model->data(index, AssetParameterModel::NameRole).toString(); + if (name == QLatin1String("Rotation")) { + m_rotation = new DragValue(i18n("Rotation"), 360, 0, 0, 360, -1, i18n("%"), true, this); + connect(m_rotation, &DragValue::valueChanged, this, &KeyframeWidget::slotAdjustRectKeyframeValue); + } auto doubleWidget = new DoubleWidget(name, value, min, max, defaultValue, comment, -1, suffix, decimals, this); doubleWidget->factor = factor; connect(doubleWidget, &DoubleWidget::valueChanged, diff --git a/src/monitor/monitor.h b/src/monitor/monitor.h --- a/src/monitor/monitor.h +++ b/src/monitor/monitor.h @@ -343,6 +343,8 @@ void extractZone(const QString &id); void effectChanged(const QRect &); void effectPointsChanged(const QVariantList &); + void opacityChanged(double); + void angleChanged(double); void addKeyframe(); void deleteKeyframe(); void seekToNextKeyframe(); diff --git a/src/monitor/monitor.cpp b/src/monitor/monitor.cpp --- a/src/monitor/monitor.cpp +++ b/src/monitor/monitor.cpp @@ -171,6 +171,8 @@ m_qmlManager = new QmlManager(m_glMonitor); connect(m_qmlManager, &QmlManager::effectChanged, this, &Monitor::effectChanged); connect(m_qmlManager, &QmlManager::effectPointsChanged, this, &Monitor::effectPointsChanged); + connect(m_qmlManager, &QmlManager::opacityChanged, this, &Monitor::opacityChanged); + connect(m_qmlManager, &QmlManager::angleChanged, this, &Monitor::angleChanged); auto *monitorEventEater = new QuickMonitorEventEater(this); m_glWidget->installEventFilter(monitorEventEater); diff --git a/src/monitor/qmlmanager.h b/src/monitor/qmlmanager.h --- a/src/monitor/qmlmanager.h +++ b/src/monitor/qmlmanager.h @@ -56,10 +56,14 @@ void effectRectChanged(); void effectPolygonChanged(); void effectRotoChanged(); + void effectOpacityChanged(); + void effectRotationChanged(); signals: void effectChanged(const QRect &); void effectPointsChanged(const QVariantList &); + void opacityChanged(const double &); + void angleChanged(const double &); }; #endif diff --git a/src/monitor/qmlmanager.cpp b/src/monitor/qmlmanager.cpp --- a/src/monitor/qmlmanager.cpp +++ b/src/monitor/qmlmanager.cpp @@ -66,6 +66,8 @@ root = m_view->rootObject(); QObject::connect(root, SIGNAL(effectChanged()), this, SLOT(effectRectChanged()), Qt::UniqueConnection); QObject::connect(root, SIGNAL(centersChanged()), this, SLOT(effectPolygonChanged()), Qt::UniqueConnection); + QObject::connect(root, SIGNAL(opacityChanged(double)), this, SIGNAL(opacityChanged(double)), Qt::UniqueConnection); + QObject::connect(root, SIGNAL(angleChanged(double)), this, SIGNAL(angleChanged(double)), Qt::UniqueConnection); root->setProperty("profile", QPoint(profile.width(), profile.height())); root->setProperty("framesize", QRect(0, 0, profile.width(), profile.height())); root->setProperty("scalex", (double)displayRect.width() / profile.width() * zoom); @@ -154,3 +156,21 @@ } emit effectPointsChanged(mix); } + +void QmlManager::effectOpacityChanged() +{ + if (!m_view->rootObject()) { + return; + } + const double opacityValue = m_view->rootObject()->property("opacity").toReal(); + emit opacityChanged(opacityValue); +} + +void QmlManager::effectRotationChanged() +{ + if (!m_view->rootObject()) { + return; + } + const double rotationValue = m_view->rootObject()->property("rotation").toReal(); + emit angleChanged(rotationValue); +} diff --git a/src/monitor/view/OpacitySlider.qml b/src/monitor/view/OpacitySlider.qml new file mode 100644 --- /dev/null +++ b/src/monitor/view/OpacitySlider.qml @@ -0,0 +1,22 @@ +import QtQuick.Controls 1.3 +import QtQuick.Controls.Styles 1.3 +import QtQuick 2.0 + +Item { + id: opacity + objectName: "opacity" + + Row { + Slider { + id: opacitySlider + objectName: "opacitySlider" + orientation: Qt.Horizontal + maximumValue: 100 + stepSize: 1 + value: 50 + onValueChanged: { + root.opacityChanged(value); + } + } + } +} diff --git a/src/monitor/view/RotationSlider.qml b/src/monitor/view/RotationSlider.qml new file mode 100644 --- /dev/null +++ b/src/monitor/view/RotationSlider.qml @@ -0,0 +1,22 @@ +import QtQuick.Controls 1.3 +import QtQuick.Controls.Styles 1.3 +import QtQuick 2.0 + +Item { + id: rotation + objectName: "rotation" + + Row { + Slider { + id: rotationSlider + objectName: "rotationSlider" + orientation: Qt.Horizontal + maximumValue: 359 + stepSize: 1 + value: 0 + onValueChanged: { + root.angleChanged(value); + } + } + } +} diff --git a/src/monitor/view/kdenlivemonitoreffectscene.qml b/src/monitor/view/kdenlivemonitoreffectscene.qml --- a/src/monitor/view/kdenlivemonitoreffectscene.qml +++ b/src/monitor/view/kdenlivemonitoreffectscene.qml @@ -36,11 +36,15 @@ property var centerPointsTypes: [] onCenterPointsChanged: canvas.requestPaint() property bool showToolbar: false + property bool showOpacity: false + property bool showRotation: false signal effectChanged() signal centersChanged() signal addKeyframe() signal seekToKeyframe() signal toolBarChanged(bool doAccept) + signal opacityChanged(double value) + signal angleChanged(double value) onZoomChanged: { effectToolBar.setZoom(root.zoom) } @@ -530,6 +534,27 @@ color: framerect.hoverColor } } + + OpacitySlider { + id: opacitySlider + anchors { + left: parent.left + top: parent.top + topMargin: 20 + leftMargin: 10 + } + } + + RotationSlider { + id: rotationSlider + anchors { + left: parent.left + top: parent.top + topMargin: 40 + leftMargin: 10 + } + } + MonitorRuler { id: clipMonitorRuler anchors { diff --git a/src/uiresources.qrc b/src/uiresources.qrc --- a/src/uiresources.qrc +++ b/src/uiresources.qrc @@ -13,6 +13,8 @@ monitor/view/SceneToolBar.qml monitor/view/EffectToolBar.qml monitor/view/MonitorRuler.qml + monitor/view/OpacitySlider.qml + monitor/view/RotationSlider.qml timeline2/view/qml/timeline.qml timeline2/view/qml/TrackHead.qml timeline2/view/qml/Track.qml diff --git a/src/widgets/geometrywidget.h b/src/widgets/geometrywidget.h --- a/src/widgets/geometrywidget.h +++ b/src/widgets/geometrywidget.h @@ -30,6 +30,7 @@ class KSelectAction; class DragValue; class Monitor; +class DoubleWidget; /** * @brief A widget for modifying numbers by dragging, using the mouse wheel or entering them with the keyboard. @@ -63,6 +64,7 @@ DragValue *m_spinHeight; DragValue *m_spinSize; DragValue *m_opacity; + DoubleWidget *m_rotationWidget; QSize m_defaultSize; QSize m_sourceSize; QAction *m_originalSize; @@ -73,6 +75,8 @@ public slots: void slotUpdateGeometryRect(const QRect r); void slotSetRange(QPair); + void slotUpdateOpacity(double); + void slotUpdateRotation(double); private slots: void slotAdjustRectKeyframeValue(); @@ -100,6 +104,8 @@ signals: void valueChanged(const QString val); + void opacityChanged(double opacity); + void angleChanged(double rotation); }; #endif diff --git a/src/widgets/geometrywidget.cpp b/src/widgets/geometrywidget.cpp --- a/src/widgets/geometrywidget.cpp +++ b/src/widgets/geometrywidget.cpp @@ -35,6 +35,7 @@ , m_max(range.second) , m_active(false) , m_monitor(monitor) + , m_rotationWidget(nullptr) { Q_UNUSED(useRatioLock) setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); @@ -389,19 +390,33 @@ m_spinWidth->blockSignals(true); m_spinHeight->blockSignals(true); m_opacity->blockSignals(true); + m_spinX->setValue(r.x()); m_spinY->setValue(r.y()); m_spinWidth->setValue(r.width()); m_spinHeight->setValue(r.height()); m_opacity->setValue((int) (opacity * 100)); + m_spinX->blockSignals(false); m_spinY->blockSignals(false); m_spinWidth->blockSignals(false); m_spinHeight->blockSignals(false); m_opacity->blockSignals(false); + m_monitor->setUpEffectGeometry(r); } +void GeometryWidget::slotUpdateOpacity(double value) +{ + m_opacity->setValue(value); +} + +void GeometryWidget::slotUpdateRotation(double value) +{ + if(m_rotationWidget) { + m_rotationWidget->setValue(value); + } +} const QString GeometryWidget::getValue() const { @@ -416,7 +431,11 @@ m_active = activate; if (activate) { m_monitor->slotShowEffectScene(MonitorSceneGeometry); + m_monitor->setEffectSceneProperty(QStringLiteral("showRotation"), true); + m_monitor->setEffectSceneProperty(QStringLiteral("showOpacity"), true); connect(m_monitor, &Monitor::effectChanged, this, &GeometryWidget::slotUpdateGeometryRect, Qt::UniqueConnection); + connect(m_monitor, &Monitor::opacityChanged, this, &GeometryWidget::slotUpdateOpacity, Qt::UniqueConnection); + connect(m_monitor, &Monitor::angleChanged, this, &GeometryWidget::slotUpdateRotation, Qt::UniqueConnection); QRect rect(m_spinX->value(), m_spinY->value(), m_spinWidth->value(), m_spinHeight->value()); m_monitor->setUpEffectGeometry(rect); /*double ratio = (double)m_spinWidth->value() / m_spinHeight->value(); @@ -433,6 +452,8 @@ } else { m_monitor->slotShowEffectScene(MonitorSceneDefault); disconnect(m_monitor, &Monitor::effectChanged, this, &GeometryWidget::slotUpdateGeometryRect); + disconnect(m_monitor, &Monitor::opacityChanged, this, &GeometryWidget::slotUpdateOpacity); + disconnect(m_monitor, &Monitor::angleChanged, this, &GeometryWidget::slotUpdateRotation); } }