diff --git a/src/monitor/qmlmanager.cpp b/src/monitor/qmlmanager.cpp
index ec6567bab..5abfae071 100644
--- a/src/monitor/qmlmanager.cpp
+++ b/src/monitor/qmlmanager.cpp
@@ -1,156 +1,160 @@
/***************************************************************************
* Copyright (C) 2016 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program 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) version 3 or any later version *
* accepted by the membership of KDE e.V. (or its successor approved *
* by the membership of KDE e.V.), which shall act as a proxy *
* defined in Section 14 of version 3 of the license. *
* *
* This program 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 this program. If not, see . *
***************************************************************************/
#include "qmlmanager.h"
#include "qml/qmlaudiothumb.h"
#include
+#include
+#include
QmlManager::QmlManager(QQuickView *view)
: QObject(view)
, m_view(view)
, m_sceneType(MonitorSceneNone)
{
}
void QmlManager::enableAudioThumbs(bool enable)
{
auto *audioThumbDisplay = m_view->rootObject()->findChild(QStringLiteral("audiothumb"));
if (audioThumbDisplay) {
audioThumbDisplay->setProperty("stateVisible", enable);
}
}
MonitorSceneType QmlManager::sceneType() const
{
return m_sceneType;
}
void QmlManager::setProperty(const QString &name, const QVariant &value)
{
m_view->rootObject()->setProperty(name.toUtf8().constData(), value);
}
void QmlManager::setScene(Kdenlive::MonitorId id, MonitorSceneType type, QSize profile, double profileStretch, QRect displayRect, double zoom, int duration)
{
if (type == m_sceneType) {
// Scene type already active
return;
}
if (id == Kdenlive::DvdMonitor) {
return;
}
m_sceneType = type;
- QQuickItem *root;
+ QQuickItem *root = nullptr;
switch (type) {
case MonitorSceneGeometry:
m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitoreffectscene.qml")));
root = m_view->rootObject();
QObject::connect(root, SIGNAL(effectChanged()), this, SLOT(effectRectChanged()), Qt::UniqueConnection);
QObject::connect(root, SIGNAL(centersChanged()), this, SLOT(effectPolygonChanged()), 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);
root->setProperty("scaley", (double)displayRect.width() / profileStretch / profile.width() * zoom);
root->setProperty("center", displayRect.center());
break;
case MonitorSceneCorners:
qDebug()<<"/// LOADING CORNERS SCENE\n\n+++++++++++++++++++++++++\n------------------\n+++++++++++++++++";
m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorcornerscene.qml")));
root = m_view->rootObject();
QObject::connect(root, SIGNAL(effectPolygonChanged()), this, SLOT(effectPolygonChanged()), 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);
root->setProperty("scaley", (double)displayRect.width() / profileStretch / profile.width() * zoom);
root->setProperty("stretch", profileStretch);
root->setProperty("center", displayRect.center());
break;
case MonitorSceneRoto:
// TODO
m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorrotoscene.qml")));
root = m_view->rootObject();
QObject::connect(root, SIGNAL(effectPolygonChanged()), this, SLOT(effectRotoChanged()), 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);
root->setProperty("scaley", (double)displayRect.width() / profileStretch / profile.width() * zoom);
root->setProperty("stretch", profileStretch);
root->setProperty("center", displayRect.center());
break;
case MonitorSceneSplit:
m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorsplit.qml")));
root = m_view->rootObject();
break;
case MonitorSceneRipple:
m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorripple.qml")));
root = m_view->rootObject();
break;
default:
m_view->setSource(
QUrl(id == Kdenlive::ClipMonitor ? QStringLiteral("qrc:/qml/kdenliveclipmonitor.qml") : QStringLiteral("qrc:/qml/kdenlivemonitor.qml")));
root = m_view->rootObject();
root->setProperty("profile", QPoint(profile.width(), profile.height()));
root->setProperty("scalex", (double)displayRect.width() / profile.width() * zoom);
root->setProperty("scaley", (double)displayRect.width() / profileStretch / profile.width() * zoom);
break;
}
- if (duration > 0) {
+ if (root && duration > 0) {
root->setProperty("duration", duration);
}
+ const QFont ft = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+ m_view->rootContext()->setContextProperty("fixedFont", ft);
}
void QmlManager::effectRectChanged()
{
if (!m_view->rootObject()) {
return;
}
const QRect rect = m_view->rootObject()->property("framesize").toRect();
emit effectChanged(rect);
}
void QmlManager::effectPolygonChanged()
{
if (!m_view->rootObject()) {
return;
}
QVariantList points = m_view->rootObject()->property("centerPoints").toList();
qDebug()<<"// GOT NEW POLYGON FROM QML: "<rootObject()) {
return;
}
QVariantList points = m_view->rootObject()->property("centerPoints").toList();
QVariantList controlPoints = m_view->rootObject()->property("centerPointsTypes").toList();
// rotoscoping effect needs a list of
QVariantList mix;
mix.reserve(points.count());
for (int i = 0; i < points.count(); i++) {
mix << controlPoints.at(2 * i);
mix << points.at(i);
mix << controlPoints.at(2 * i + 1);
}
emit effectPointsChanged(mix);
}
diff --git a/src/monitor/view/kdenliveclipmonitor.qml b/src/monitor/view/kdenliveclipmonitor.qml
index 85070ddbe..554cd38a7 100644
--- a/src/monitor/view/kdenliveclipmonitor.qml
+++ b/src/monitor/view/kdenliveclipmonitor.qml
@@ -1,263 +1,263 @@
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.2
import Kdenlive.Controls 1.0
import QtQuick 2.6
import AudioThumb 1.0
Item {
id: root
objectName: "root"
SystemPalette { id: activePalette }
// default size, but scalable by user
height: 300; width: 400
property string markerText
property point profile
property double zoom
property double scalex
property double scaley
property bool dropped
property string fps
property bool showMarkers
property bool showTimecode
property bool showFps
property bool showSafezone
property bool showAudiothumb
property bool showToolbar: false
property real baseUnit: fontMetrics.font.pixelSize * 0.8
property int duration: 300
property int mouseRulerPos: 0
property double frameSize: 10
property double timeScale: 1
property int overlayType: controller.overlayType
property color overlayColor: 'cyan'
property bool isClipMonitor: true
property int dragType: 0
FontMetrics {
id: fontMetrics
font.family: "Arial"
}
signal editCurrentMarker()
signal toolBarChanged(bool doAccept)
onDurationChanged: {
clipMonitorRuler.updateRuler()
}
onWidthChanged: {
clipMonitorRuler.updateRuler()
}
function updatePalette() {
clipMonitorRuler.forceRepaint()
}
function switchOverlay() {
if (controller.overlayType >= 5) {
controller.overlayType = 0
} else {
controller.overlayType = controller.overlayType + 1;
}
root.overlayType = controller.overlayType
}
MouseArea {
id: barOverArea
hoverEnabled: true
acceptedButtons: Qt.NoButton
anchors.fill: parent
}
SceneToolBar {
id: sceneToolBar
anchors {
right: parent.right
top: parent.top
topMargin: 4
rightMargin: 4
}
visible: barOverArea.mouseX >= x - 10
}
Item {
height: root.height - controller.rulerHeight
width: root.width
Item {
id: frame
objectName: "referenceframe"
width: root.profile.x * root.scalex
height: root.profile.y * root.scaley
anchors.centerIn: parent
Loader {
anchors.fill: parent
source: {
switch(root.overlayType)
{
case 0: {
return '';
}
case 1: {
return "OverlayStandard.qml";
}
case 2:{
return "OverlayMinimal.qml";
}
case 3:{
return "OverlayCenter.qml";
}
case 4:{
return "OverlayCenterDiagonal.qml";
}
case 5:{
return "OverlayThirds.qml";
}
}
}
}
}
Item {
id: monitorOverlay
anchors.fill: parent
QmlAudioThumb {
id: audioThumb
objectName: "audiothumb"
property bool stateVisible: true
anchors {
left: parent.left
bottom: parent.bottom
}
height: parent.height / 6
//font.pixelSize * 3
width: parent.width
visible: root.showAudiothumb
MouseArea {
id: mouseOverArea
hoverEnabled: true
onExited: audioThumb.stateVisible = false
onEntered: audioThumb.stateVisible = true
acceptedButtons: Qt.NoButton
anchors.fill: parent
}
states: [
State { when: audioThumb.stateVisible;
PropertyChanges { target: audioThumb; opacity: 1.0 } },
State { when: !audioThumb.stateVisible;
PropertyChanges { target: audioThumb; opacity: 0.0 } }
]
transitions: [ Transition {
NumberAnimation { property: "opacity"; duration: 500}
} ]
}
Text {
id: timecode
+ font: fixedFont
objectName: "timecode"
color: "white"
style: Text.Outline;
styleColor: "black"
text: controller.toTimecode(controller.position)
- font.pixelSize: root.baseUnit
visible: root.showTimecode
anchors {
right: parent.right
bottom: parent.bottom
rightMargin: 4
}
}
Text {
id: fpsdropped
+ font: fixedFont
objectName: "fpsdropped"
color: root.dropped ? "red" : "white"
style: Text.Outline;
styleColor: "black"
text: root.fps + "fps"
visible: root.showFps
- font.pixelSize: root.baseUnit
anchors {
right: timecode.visible ? timecode.left : parent.right
bottom: parent.bottom
rightMargin: 10
}
}
TextField {
id: marker
+ font: fixedFont
objectName: "markertext"
activeFocusOnPress: true
onEditingFinished: {
root.markerText = marker.displayText
marker.focus = false
root.editCurrentMarker()
}
anchors {
left: parent.left
bottom: parent.bottom
}
visible: root.showMarkers && text != ""
text: controller.markerComment
maximumLength: 20
style: TextFieldStyle {
textColor: "white"
background: Rectangle {
color: controller.position == controller.zoneIn ? "#9900ff00" : controller.position == controller.zoneOut ? "#99ff0000" : "#990000ff"
width: marker.width
}
}
- font.pixelSize: root.baseUnit
}
}
MouseArea {
id: dragOverArea
hoverEnabled: true
acceptedButtons: Qt.LeftButton
x: 0
width: 2 * audioDragButton.width
height: 2.5 * audioDragButton.height
y: parent.height - height
propagateComposedEvents: true
onPressed: {
// First found child is the Column
var clickedChild = childAt(mouseX,mouseY).childAt(mouseX,mouseY)
if (clickedChild == audioDragButton) {
dragType = 1
} else if (clickedChild == videoDragButton) {
dragType = 2
} else {
dragType = 0
}
mouse.accepted = false
}
Column {
ToolButton {
id: audioDragButton
iconName: "audio-volume-medium"
tooltip: "Audio only drag"
x: 10
enabled: false
visible: dragOverArea.containsMouse
}
ToolButton {
id: videoDragButton
iconName: "kdenlive-show-video"
tooltip: "Video only drag"
x: 10
enabled: false
visible: dragOverArea.containsMouse
}
}
}
}
MonitorRuler {
id: clipMonitorRuler
anchors {
left: root.left
right: root.right
bottom: root.bottom
}
height: controller.rulerHeight
}
}
diff --git a/src/monitor/view/kdenlivemonitor.qml b/src/monitor/view/kdenlivemonitor.qml
index 4680ce89b..c382ee552 100644
--- a/src/monitor/view/kdenlivemonitor.qml
+++ b/src/monitor/view/kdenlivemonitor.qml
@@ -1,188 +1,188 @@
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.2
import Kdenlive.Controls 1.0
import QtQuick 2.4
import AudioThumb 1.0
Item {
id: root
objectName: "root"
SystemPalette { id: activePalette }
// default size, but scalable by user
height: 300; width: 400
property string markerText
property point profile
property double zoom
property double scalex
property double scaley
property bool dropped
property string fps
property bool showMarkers
property bool showTimecode
property bool showFps
property bool showSafezone
property bool showAudiothumb
property real baseUnit: fontMetrics.font.pixelSize * 0.8
property int duration: 300
property int mouseRulerPos: 0
property double frameSize: 10
property double timeScale: 1
property int overlayType: controller.overlayType
property color overlayColor: 'cyan'
property bool isClipMonitor: false
FontMetrics {
id: fontMetrics
font.family: "Arial"
}
signal editCurrentMarker()
signal toolBarChanged(bool doAccept)
onDurationChanged: {
clipMonitorRuler.updateRuler()
}
onWidthChanged: {
clipMonitorRuler.updateRuler()
}
function updatePalette() {
clipMonitorRuler.forceRepaint()
}
function switchOverlay() {
if (controller.overlayType >= 5) {
controller.overlayType = 0
} else {
controller.overlayType = controller.overlayType + 1;
}
root.overlayType = controller.overlayType
}
MouseArea {
id: barOverArea
hoverEnabled: true
acceptedButtons: Qt.NoButton
anchors.fill: parent
}
SceneToolBar {
id: sceneToolBar
anchors {
right: parent.right
top: parent.top
topMargin: 4
rightMargin: 4
}
visible: barOverArea.mouseX >= x - 10
}
Item {
height: root.height - controller.rulerHeight
width: root.width
Item {
id: frame
objectName: "referenceframe"
width: root.profile.x * root.scalex
height: root.profile.y * root.scaley
anchors.centerIn: parent
Loader {
anchors.fill: parent
source: {
switch(root.overlayType)
{
case 0: {
return '';
}
case 1: {
return "OverlayStandard.qml";
}
case 2:{
return "OverlayMinimal.qml";
}
case 3:{
return "OverlayCenter.qml";
}
case 4:{
return "OverlayCenterDiagonal.qml";
}
case 5:{
return "OverlayThirds.qml";
}
}
}
}
}
Item {
id: monitorOverlay
anchors.fill: parent
Text {
id: timecode
+ font: fixedFont
objectName: "timecode"
color: "white"
style: Text.Outline;
styleColor: "black"
text: controller.toTimecode(controller.position)
- font.pixelSize: root.baseUnit
visible: root.showTimecode
anchors {
right: parent.right
bottom: parent.bottom
rightMargin: 4
}
}
Text {
id: fpsdropped
+ font: fixedFont
objectName: "fpsdropped"
color: root.dropped ? "red" : "white"
style: Text.Outline;
styleColor: "black"
text: root.fps + "fps"
visible: root.showFps
- font.pixelSize: root.baseUnit
anchors {
right: timecode.visible ? timecode.left : parent.right
bottom: parent.bottom
rightMargin: 10
}
}
TextField {
id: marker
+ font: fixedFont
objectName: "markertext"
activeFocusOnPress: true
onEditingFinished: {
root.markerText = marker.displayText
marker.focus = false
root.editCurrentMarker()
}
anchors {
left: parent.left
bottom: parent.bottom
}
visible: root.showMarkers && text != ""
text: controller.markerComment
maximumLength: 20
style: TextFieldStyle {
textColor: "white"
background: Rectangle {
color: controller.position == controller.zoneIn ? "#9900ff00" : controller.position == controller.zoneOut ? "#99ff0000" : "#990000ff"
width: marker.width
}
}
- font.pixelSize: root.baseUnit
}
}
}
MonitorRuler {
id: clipMonitorRuler
anchors {
left: root.left
right: root.right
bottom: root.bottom
}
height: controller.rulerHeight
}
}
diff --git a/src/timecodedisplay.cpp b/src/timecodedisplay.cpp
index 91ab571c4..2ba5ecf4d 100644
--- a/src/timecodedisplay.cpp
+++ b/src/timecodedisplay.cpp
@@ -1,241 +1,241 @@
/* This file is part of the KDE project
Copyright (c) 2010 Jean-Baptiste Mardelle
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "timecodedisplay.h"
#include "kdenlivesettings.h"
#include
#include
#include
#include
#include
MyValidator::MyValidator(QObject *parent)
: QValidator(parent)
{
}
void MyValidator::fixup(QString &str) const
{
str.replace(QLatin1Char(' '), QLatin1Char('0'));
}
QValidator::State MyValidator::validate(QString &str, int &) const
{
if (str.contains(QLatin1Char(' '))) {
fixup(str);
}
return QValidator::Acceptable;
}
TimecodeDisplay::TimecodeDisplay(const Timecode &t, QWidget *parent)
: QAbstractSpinBox(parent)
, m_timecode(t)
, m_frametimecode(false)
, m_minimum(0)
, m_maximum(-1)
, m_value(0)
{
- QFont ft = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+ const QFont ft = QFontDatabase::systemFont(QFontDatabase::FixedFont);
lineEdit()->setFont(ft);
setFont(ft);
lineEdit()->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
QFontMetrics fm(ft);
setFrame(false);
QPalette palette;
palette.setColor(QPalette::Base, Qt::transparent); // palette.window().color());
setPalette(palette);
setTimeCodeFormat(KdenliveSettings::frametimecode(), true);
setValue(m_minimum);
setMinimumWidth(fm.width(QStringLiteral("88:88:88:88")) + contentsMargins().right() + contentsMargins().left() + frameSize().width() -
lineEdit()->contentsRect().width() + (int)QStyle::PM_SpinBoxFrameWidth + 6);
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum);
setAccelerated(true);
connect(lineEdit(), &QLineEdit::editingFinished, this, &TimecodeDisplay::slotEditingFinished);
}
// virtual protected
QAbstractSpinBox::StepEnabled TimecodeDisplay::stepEnabled() const
{
QAbstractSpinBox::StepEnabled result = QAbstractSpinBox::StepNone;
if (m_value > m_minimum) {
result |= QAbstractSpinBox::StepDownEnabled;
}
if (m_maximum == -1 || m_value < m_maximum) {
result |= QAbstractSpinBox::StepUpEnabled;
}
return result;
}
// virtual
void TimecodeDisplay::stepBy(int steps)
{
int val = m_value + steps;
setValue(val);
}
void TimecodeDisplay::setTimeCodeFormat(bool frametimecode, bool init)
{
if (!init && m_frametimecode == frametimecode) {
return;
}
m_frametimecode = frametimecode;
lineEdit()->clear();
if (m_frametimecode) {
auto *valid = new QIntValidator(lineEdit());
valid->setBottom(0);
lineEdit()->setValidator(valid);
lineEdit()->setInputMask(QString());
} else {
lineEdit()->setInputMask(m_timecode.mask());
auto *valid = new MyValidator(lineEdit());
lineEdit()->setValidator(valid);
}
setValue(m_value);
}
void TimecodeDisplay::slotUpdateTimeCodeFormat()
{
setTimeCodeFormat(KdenliveSettings::frametimecode());
}
void TimecodeDisplay::updateTimeCode(const Timecode &t)
{
m_timecode = t;
setTimeCodeFormat(KdenliveSettings::frametimecode());
}
void TimecodeDisplay::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
e->setAccepted(true);
clearFocus();
} else {
QAbstractSpinBox::keyPressEvent(e);
}
}
void TimecodeDisplay::mouseReleaseEvent(QMouseEvent *e)
{
QAbstractSpinBox::mouseReleaseEvent(e);
if (!lineEdit()->underMouse()) {
clearFocus();
}
}
void TimecodeDisplay::wheelEvent(QWheelEvent *e)
{
QAbstractSpinBox::wheelEvent(e);
clearFocus();
}
void TimecodeDisplay::enterEvent(QEvent *e)
{
QAbstractSpinBox::enterEvent(e);
setFrame(true);
}
void TimecodeDisplay::leaveEvent(QEvent *e)
{
QAbstractSpinBox::leaveEvent(e);
setFrame(false);
}
int TimecodeDisplay::maximum() const
{
return m_maximum;
}
int TimecodeDisplay::minimum() const
{
return m_minimum;
}
int TimecodeDisplay::getValue() const
{
return m_value;
}
GenTime TimecodeDisplay::gentime() const
{
return GenTime(m_value, m_timecode.fps());
}
Timecode TimecodeDisplay::timecode() const
{
return m_timecode;
}
void TimecodeDisplay::setRange(int min, int max)
{
m_minimum = min;
m_maximum = max;
}
void TimecodeDisplay::setValue(const QString &value)
{
setValue(m_timecode.getFrameCount(value));
}
void TimecodeDisplay::setValue(int value)
{
if (m_maximum > 0) {
value = qBound(m_minimum, value, m_maximum);
} else {
value = qMax(m_minimum, value);
}
if (m_frametimecode) {
if (value == m_value && !lineEdit()->text().isEmpty()) {
return;
}
m_value = value;
lineEdit()->setText(QString::number(value - m_minimum));
} else {
if (value == m_value && lineEdit()->text() != QLatin1String(":::")) {
return;
}
m_value = value;
QString v = m_timecode.getTimecodeFromFrames(value - m_minimum);
lineEdit()->setText(v);
}
}
void TimecodeDisplay::setValue(const GenTime &value)
{
setValue((int)value.frames(m_timecode.fps()));
}
void TimecodeDisplay::slotEditingFinished()
{
lineEdit()->deselect();
if (m_frametimecode) {
setValue(lineEdit()->text().toInt() + m_minimum);
} else {
setValue(m_timecode.getFrameCount(lineEdit()->text()) + m_minimum);
}
emit timeCodeEditingFinished(m_value);
}
const QString TimecodeDisplay::displayText() const
{
return lineEdit()->displayText();
}