1 /*
2     SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
3     This file is part of Kdenlive. See www.kdenlive.org.
4 
5     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
6 */
7 
8 #include "qmlmanager.h"
9 #include "kdenlivesettings.h"
10 
11 #include <QFontDatabase>
12 #include <QQmlContext>
13 #include <QQuickView>
14 #include <QQuickItem>
15 
QmlManager(QQuickView * view)16 QmlManager::QmlManager(QQuickView *view)
17     : QObject(view)
18     , m_view(view)
19     , m_sceneType(MonitorSceneNone)
20 {
21 }
22 
sceneType() const23 MonitorSceneType QmlManager::sceneType() const
24 {
25     return m_sceneType;
26 }
27 
setProperty(const QString & name,const QVariant & value)28 void QmlManager::setProperty(const QString &name, const QVariant &value)
29 {
30     m_view->rootObject()->setProperty(name.toUtf8().constData(), value);
31 }
32 
setScene(Kdenlive::MonitorId id,MonitorSceneType type,QSize profile,double profileStretch,QRect displayRect,double zoom,int duration)33 void QmlManager::setScene(Kdenlive::MonitorId id, MonitorSceneType type, QSize profile, double profileStretch, QRect displayRect, double zoom, int duration)
34 {
35     if (type == m_sceneType) {
36         // Scene type already active
37         return;
38     }
39     m_sceneType = type;
40     QQuickItem *root = nullptr;
41     m_view->rootContext()->setContextProperty("fixedFont", QFontDatabase::systemFont(QFontDatabase::FixedFont));
42     double scalex = double(displayRect.width()) / profile.width() * zoom;
43     double scaley = double(displayRect.height()) / profile.height() * zoom;
44     switch (type) {
45     case MonitorSceneGeometry:
46         m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitoreffectscene.qml")));
47         root = m_view->rootObject();
48         QObject::connect(root, SIGNAL(effectChanged()), this, SLOT(effectRectChanged()), Qt::UniqueConnection);
49         QObject::connect(root, SIGNAL(centersChanged()), this, SLOT(effectPolygonChanged()), Qt::UniqueConnection);
50         root->setProperty("profile", QPoint(profile.width(), profile.height()));
51         root->setProperty("framesize", QRect(0, 0, profile.width(), profile.height()));
52         root->setProperty("scalex", scalex);
53         root->setProperty("scaley", scaley);
54         root->setProperty("center", displayRect.center());
55         break;
56     case MonitorSceneCorners:
57         m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorcornerscene.qml")));
58         root = m_view->rootObject();
59         QObject::connect(root, SIGNAL(effectPolygonChanged()), this, SLOT(effectPolygonChanged()), Qt::UniqueConnection);
60         root->setProperty("profile", QPoint(profile.width(), profile.height()));
61         root->setProperty("framesize", QRect(0, 0, profile.width(), profile.height()));
62         root->setProperty("scalex", scalex);
63         root->setProperty("scaley", scaley);
64         root->setProperty("stretch", profileStretch);
65         root->setProperty("center", displayRect.center());
66         break;
67     case MonitorSceneRoto:
68         m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorrotoscene.qml")));
69         root = m_view->rootObject();
70         QObject::connect(root, SIGNAL(effectPolygonChanged(QVariant,QVariant)), this, SLOT(effectRotoChanged(QVariant,QVariant)), Qt::UniqueConnection);
71         root->setProperty("profile", QPoint(profile.width(), profile.height()));
72         root->setProperty("framesize", QRect(0, 0, profile.width(), profile.height()));
73         root->setProperty("scalex", scalex);
74         root->setProperty("scaley", scaley);
75         root->setProperty("stretch", profileStretch);
76         root->setProperty("center", displayRect.center());
77         break;
78     case MonitorSplitTrack:
79         m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorsplittracks.qml")));
80         root = m_view->rootObject();
81         QObject::connect(root, SIGNAL(activateTrack(int)), this, SIGNAL(activateTrack(int)), Qt::UniqueConnection);
82         root->setProperty("profile", QPoint(profile.width(), profile.height()));
83         root->setProperty("framesize", QRect(0, 0, profile.width(), profile.height()));
84         root->setProperty("scalex", scalex);
85         root->setProperty("scaley", scaley);
86         root->setProperty("stretch", profileStretch);
87         root->setProperty("center", displayRect.center());
88         break;
89     case MonitorSceneSplit:
90         m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorsplit.qml")));
91         root = m_view->rootObject();
92         root->setProperty("profile", QPoint(profile.width(), profile.height()));
93         root->setProperty("scalex", scalex);
94         root->setProperty("scaley", scaley);
95         break;
96     case MonitorSceneTrimming:
97         m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitortrimming.qml")));
98         root = m_view->rootObject();
99         break;
100     default:
101         m_view->setSource(
102             QUrl(id == Kdenlive::ClipMonitor ? QStringLiteral("qrc:/qml/kdenliveclipmonitor.qml") : QStringLiteral("qrc:/qml/kdenlivemonitor.qml")));
103         root = m_view->rootObject();
104         root->setProperty("profile", QPoint(profile.width(), profile.height()));
105         root->setProperty("scalex", scalex);
106         root->setProperty("scaley", scaley);
107         if (id == Kdenlive::ClipMonitor) {
108             // Apply the always show audio setting
109             root->setProperty("permanentAudiothumb", KdenliveSettings::alwaysShowMonitorAudio());
110         }
111         break;
112     }
113     if (root && duration > 0) {
114         root->setProperty("duration", duration);
115     }
116 }
117 
effectRectChanged()118 void QmlManager::effectRectChanged()
119 {
120     if (!m_view->rootObject()) {
121         return;
122     }
123     const QRect rect = m_view->rootObject()->property("framesize").toRect();
124     emit effectChanged(rect);
125 }
126 
effectPolygonChanged()127 void QmlManager::effectPolygonChanged()
128 {
129     if (!m_view->rootObject()) {
130         return;
131     }
132     QVariantList points = m_view->rootObject()->property("centerPoints").toList();
133     emit effectPointsChanged(points);
134 }
135 
effectRotoChanged(QVariant pts,QVariant centers)136 void QmlManager::effectRotoChanged(QVariant pts, QVariant centers)
137 {
138     if (!m_view->rootObject()) {
139         return;
140     }
141     QVariantList points = pts.toList();
142     QVariantList controlPoints = centers.toList();
143     if (2 * points.size() != controlPoints.size()) {
144         // Mismatch, abort
145         return;
146     }
147     // rotoscoping effect needs a list of
148     QVariantList mix;
149     mix.reserve(points.count());
150     for (int i = 0; i < points.count(); i++) {
151         mix << controlPoints.at(2 * i);
152         mix << points.at(i);
153         mix << controlPoints.at(2 * i + 1);
154     }
155     emit effectPointsChanged(mix);
156 }
157