Improve multitrack view (display clickable track names)

Related to #391
parent 4c7961e1
......@@ -903,3 +903,13 @@ std::unique_ptr<Mlt::Producer> Core::getTrackProducerInstance(int tid)
}
return nullptr;
}
bool Core::enableMultiTrack(bool enable)
{
bool isMultiTrack = pCore->monitorManager()->isMultiTrack();
if (isMultiTrack || enable) {
pCore->window()->getMainTimeline()->controller()->slotMultitrackView(enable, enable);
return true;
}
return false;
}
......@@ -219,6 +219,8 @@ public:
std::unique_ptr<Mlt::Producer> getTrackProducerInstance(int tid);
/** @brief Returns the undo stack index (position). */
int undoIndex() const;
/** @brief Enable / disable monitor multitrack view. Returns false if multitrack was not previously enabled */
bool enableMultiTrack(bool enable);
private:
explicit Core();
......
......@@ -132,7 +132,8 @@ enum MonitorSceneType {
MonitorSceneCorners,
MonitorSceneRoto,
MonitorSceneSplit,
MonitorSceneRipple
MonitorSceneRipple,
MonitorSplitTrack
};
enum MessageType { DefaultMessage, ProcessingJobMessage, OperationCompletedMessage, InformationMessage, ErrorMessage, MltError };
......
......@@ -2095,6 +2095,7 @@ void MainWindow::connectDocument()
KdenliveSettings::setProject_fps(pCore->getCurrentFps());
m_projectMonitor->slotLoadClipZone(project->zone());
connect(m_projectMonitor, &Monitor::multitrackView, getMainTimeline()->controller(), &TimelineController::slotMultitrackView, Qt::UniqueConnection);
connect(m_projectMonitor, &Monitor::activateTrack, getMainTimeline()->controller(), &TimelineController::activateTrackAndSelect, Qt::UniqueConnection);
connect(getMainTimeline()->controller(), &TimelineController::timelineClipSelected, pCore->library(), &LibraryWidget::enableAddSelection,
Qt::UniqueConnection);
connect(pCore->library(), &LibraryWidget::saveTimelineSelection, getMainTimeline()->controller(), &TimelineController::saveTimelineSelection,
......@@ -2546,7 +2547,7 @@ void MainWindow::slotAddMarkerGuideQuickly()
getMainTimeline()->controller()->switchGuide();
} else {
// Add marker to main clip
getMainTimeline()->controller()->addQuickMarker();
getMainTimeline()->controller()->addQuickMarker(selectedClip);
}
}
}
......
......@@ -172,6 +172,7 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
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::activateTrack, this, &Monitor::activateTrack);
auto *monitorEventEater = new QuickMonitorEventEater(this);
m_videoWidget->installEventFilter(monitorEventEater);
......@@ -1612,7 +1613,7 @@ void Monitor::slotEnableEffectScene(bool enable)
}
}
void Monitor::slotShowEffectScene(MonitorSceneType sceneType, bool temporary)
void Monitor::slotShowEffectScene(MonitorSceneType sceneType, bool temporary, QVariant sceneData)
{
if (sceneType == MonitorSceneNone) {
// We just want to revert to normal scene
......@@ -1621,11 +1622,15 @@ void Monitor::slotShowEffectScene(MonitorSceneType sceneType, bool temporary)
return;
}
sceneType = MonitorSceneDefault;
} else if (m_qmlManager->sceneType() == MonitorSplitTrack) {
// Don't show another scene type if multitrack mode is active
loadQmlScene(MonitorSplitTrack, sceneData);
return;
}
if (!temporary) {
m_lastMonitorSceneType = sceneType;
}
loadQmlScene(sceneType);
loadQmlScene(sceneType, sceneData);
}
void Monitor::slotSeekToKeyFrame()
......@@ -1951,7 +1956,7 @@ QSize Monitor::profileSize() const
return m_glMonitor->profileSize();
}
void Monitor::loadQmlScene(MonitorSceneType type)
void Monitor::loadQmlScene(MonitorSceneType type, QVariant sceneData)
{
if (m_id == Kdenlive::DvdMonitor || type == m_qmlManager->sceneType()) {
return;
......@@ -1985,6 +1990,9 @@ void Monitor::loadQmlScene(MonitorSceneType type)
updateQmlDisplay(KdenliveSettings::displayProjectMonitorInfo());
}
break;
case MonitorSplitTrack:
m_qmlManager->setProperty(QStringLiteral("tracks"), sceneData);
break;
default:
break;
}
......
......@@ -224,7 +224,7 @@ private:
int m_speedIndex;
void adjustScrollBars(float horizontal, float vertical);
void loadQmlScene(MonitorSceneType type);
void loadQmlScene(MonitorSceneType type, QVariant sceneData = QVariant());
void updateQmlDisplay(int currentOverlay);
/** @brief Create temporary Mlt::Tractor holding a clip and it's effectless clone */
void buildSplitEffect(Mlt::Producer *original);
......@@ -307,7 +307,7 @@ public slots:
void setTimePos(const QString &pos);
QPoint getZoneInfo() const;
/** @brief Display the on monitor effect scene (to adjust geometry over monitor). */
void slotShowEffectScene(MonitorSceneType sceneType, bool temporary = false);
void slotShowEffectScene(MonitorSceneType sceneType, bool temporary = false, QVariant sceneData = QVariant());
bool effectSceneDisplayed(MonitorSceneType effectType);
/** @brief split screen to compare clip with and without effect */
void slotSwitchCompare(bool enable);
......@@ -363,6 +363,7 @@ signals:
void removeSplitOverlay();
void acceptRipple(bool);
void switchTrimMode(int);
void activateTrack(int);
};
#endif
......@@ -91,6 +91,17 @@ void QmlManager::setScene(Kdenlive::MonitorId id, MonitorSceneType type, QSize p
root->setProperty("stretch", profileStretch);
root->setProperty("center", displayRect.center());
break;
case MonitorSplitTrack:
m_view->setSource(QUrl(QStringLiteral("qrc:/qml/kdenlivemonitorsplittracks.qml")));
root = m_view->rootObject();
QObject::connect(root, SIGNAL(activateTrack(int)), this, SIGNAL(activateTrack(int)), Qt::UniqueConnection);
root->setProperty("profile", QPoint(profile.width(), profile.height()));
root->setProperty("framesize", QRect(0, 0, profile.width(), profile.height()));
root->setProperty("scalex", scalex);
root->setProperty("scaley", scaley);
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();
......
......@@ -58,6 +58,7 @@ private slots:
signals:
void effectChanged(const QRect &);
void effectPointsChanged(const QVariantList &);
void activateTrack(int);
};
#endif
......@@ -43,7 +43,6 @@ Item {
}
signal editCurrentMarker()
signal toolBarChanged(bool doAccept)
onDurationChanged: {
clipMonitorRuler.updateRuler()
......
......@@ -38,7 +38,6 @@ Item {
}
signal editCurrentMarker()
signal toolBarChanged(bool doAccept)
onDurationChanged: {
clipMonitorRuler.updateRuler()
......
import QtQuick 2.11
import QtQuick.Controls 2.4
Item {
id: root
objectName: "root"
SystemPalette { id: activePalette }
// default size, but scalable by user
height: 300; width: 400
property string comment
property string framenum
property rect framesize
property point profile: controller.profile
property int overlayType: 0
property color overlayColor: 'cyan'
property point center
property double scalex
property double scaley
property double stretch : 1
property double sourcedar : 1
property double offsetx : 0
property double offsety : 0
onSourcedarChanged: refreshdar()
property bool iskeyframe
property int requestedKeyFrame
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 var tracks: []
signal activateTrack(int position)
onDurationChanged: {
clipMonitorRuler.updateRuler()
}
onWidthChanged: {
clipMonitorRuler.updateRuler()
}
FontMetrics {
id: fontMetrics
font.family: "Arial"
}
MouseArea {
id: barOverArea
hoverEnabled: true
acceptedButtons: Qt.NoButton
anchors.fill: parent
}
SceneToolBar {
id: sceneToolBar
barContainsMouse: sceneToolBar.rightSide ? barOverArea.mouseX >= x - 10 : barOverArea.mouseX < x + width + 10
onBarContainsMouseChanged: {
sceneToolBar.opacity = 1
sceneToolBar.visible = sceneToolBar.barContainsMouse
}
anchors {
right: parent.right
top: parent.top
topMargin: 4
rightMargin: 4
leftMargin: 4
}
}
Rectangle {
id: frame
objectName: "referenceframe"
property color hoverColor: "#ff0000"
width: root.profile.x * root.scalex
height: root.profile.y * root.scaley
x: root.center.x - width / 2 - root.offsetx
y: root.center.y - height / 2 - root.offsety
color: "transparent"
border.color: "#ffffff00"
Repeater {
id: trackSeparators
model: tracks
property int rows: trackSeparators.count < 5 ? 2 : 3
property int columns: trackSeparators.count < 3 ? 1 : trackSeparators.count < 5 ? 2 : 3
Rectangle {
width: parent.width / trackSeparators.rows
height: parent.height / trackSeparators.columns
x: width * (index % trackSeparators.rows)
y: height * (Math.floor(index / trackSeparators.rows))
color: "transparent"
border.color: root.overlayColor
Label {
text: modelData
color: "#ffffff"
padding :4
background: Rectangle {
color: "#66660000"
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: root.activateTrack(index);
}
}
}
}
}
MonitorRuler {
id: clipMonitorRuler
anchors {
left: root.left
right: root.right
bottom: root.bottom
}
height: controller.rulerHeight
}
}
......@@ -808,9 +808,10 @@ void TimelineFunctions::setCompositionATrack(const std::shared_ptr<TimelineItemM
pCore->pushUndo(undo, redo, i18n("Change Composition Track"));
}
void TimelineFunctions::enableMultitrackView(const std::shared_ptr<TimelineItemModel> &timeline, bool enable, bool refresh)
QStringList TimelineFunctions::enableMultitrackView(const std::shared_ptr<TimelineItemModel> &timeline, bool enable, bool refresh)
{
QList<int> videoTracks;
QStringList trackNames;
for (const auto &track : timeline->m_iteratorTable) {
if (timeline->getTrackById_const(track.first)->isAudioTrack() || timeline->getTrackById_const(track.first)->isHidden()) {
continue;
......@@ -849,6 +850,7 @@ void TimelineFunctions::enableMultitrackView(const std::shared_ptr<TimelineItemM
// 200 is an arbitrary number so we can easily remove these transition later
transition.set("internal_added", 200);
QString geometry;
trackNames << timeline->getTrackFullName(videoTracks.at(i));
switch (i) {
case 0:
switch (videoTracks.size()) {
......@@ -856,8 +858,6 @@ void TimelineFunctions::enableMultitrackView(const std::shared_ptr<TimelineItemM
geometry = QStringLiteral("0 0 50% 100%");
break;
case 3:
geometry = QStringLiteral("0 0 33% 100%");
break;
case 4:
geometry = QStringLiteral("0 0 50% 50%");
break;
......@@ -876,8 +876,6 @@ void TimelineFunctions::enableMultitrackView(const std::shared_ptr<TimelineItemM
geometry = QStringLiteral("50% 0 50% 100%");
break;
case 3:
geometry = QStringLiteral("33% 0 33% 100%");
break;
case 4:
geometry = QStringLiteral("50% 0 50% 50%");
break;
......@@ -893,8 +891,6 @@ void TimelineFunctions::enableMultitrackView(const std::shared_ptr<TimelineItemM
case 2:
switch (videoTracks.size()) {
case 3:
geometry = QStringLiteral("66% 0 33% 100%");
break;
case 4:
geometry = QStringLiteral("0 50% 50% 50%");
break;
......@@ -962,6 +958,7 @@ void TimelineFunctions::enableMultitrackView(const std::shared_ptr<TimelineItemM
if (refresh) {
timeline->requestMonitorRefresh();
}
return trackNames;
}
void TimelineFunctions::saveTimelineSelection(const std::shared_ptr<TimelineItemModel> &timeline, const std::unordered_set<int> &selection,
......
......@@ -112,7 +112,7 @@ struct TimelineFunctions
static bool requestSplitAudio(const std::shared_ptr<TimelineItemModel> &timeline, int clipId, int audioTarget);
static bool requestSplitVideo(const std::shared_ptr<TimelineItemModel> &timeline, int clipId, int videoTarget);
static void setCompositionATrack(const std::shared_ptr<TimelineItemModel> &timeline, int cid, int aTrack);
static void enableMultitrackView(const std::shared_ptr<TimelineItemModel> &timeline, bool enable, bool refresh);
static QStringList enableMultitrackView(const std::shared_ptr<TimelineItemModel> &timeline, bool enable, bool refresh);
static void saveTimelineSelection(const std::shared_ptr<TimelineItemModel> &timeline, const std::unordered_set<int> &selection, const QDir &targetDir);
/** @brief returns the number of same type tracks between 2 tracks
*/
......
......@@ -558,6 +558,7 @@ void TimelineItemModel::notifyChange(const QModelIndex &topleft, const QModelInd
void TimelineItemModel::buildTrackCompositing(bool rebuild)
{
bool isMultiTrack = pCore->enableMultiTrack(false);
auto it = m_allTracks.cbegin();
QScopedPointer<Mlt::Service> service(m_tractor->field());
QScopedPointer<Mlt::Field> field(m_tractor->field());
......@@ -607,6 +608,9 @@ void TimelineItemModel::buildTrackCompositing(bool rebuild)
++it;
}
field->unlock();
if (isMultiTrack) {
pCore->enableMultiTrack(true);
}
if (composite.isEmpty()) {
pCore->displayMessage(i18n("Could not setup track compositing, check your install"), MessageType::ErrorMessage);
}
......
......@@ -2872,7 +2872,28 @@ bool TimelineController::exists(int itemId)
void TimelineController::slotMultitrackView(bool enable, bool refresh)
{
TimelineFunctions::enableMultitrackView(m_model, enable, refresh);
QStringList trackNames = TimelineFunctions::enableMultitrackView(m_model, enable, refresh);
pCore->monitorManager()->projectMonitor()->slotShowEffectScene(enable ? MonitorSplitTrack : MonitorSceneNone, false, QVariant(trackNames));
}
void TimelineController::activateTrackAndSelect(int trackPosition)
{
int tid = -1;
for (const auto &track : m_model->m_iteratorTable) {
if (m_model->getTrackById_const(track.first)->isAudioTrack() || m_model->getTrackById_const(track.first)->isHidden()) {
continue;
}
if (trackPosition == 0) {
tid = track.first;
break;
}
trackPosition--;
}
if (tid > -1) {
m_activeTrack = tid;
emit activeTrackChanged();
selectCurrentItem(ObjectType::TimelineClip, true);
}
}
void TimelineController::saveTimelineSelection(const QDir &targetDir)
......
......@@ -542,6 +542,8 @@ public slots:
void checkDuration();
/** @brief Dis / enable multi track view. */
void slotMultitrackView(bool enable, bool refresh = true);
/** @brief Activate a video track by its position (0 = topmost). */
void activateTrackAndSelect(int trackPosition);
/** @brief Save timeline selected clips to target folder. */
void saveTimelineSelection(const QDir &targetDir);
/** @brief Restore timeline scroll pos on open. */
......
......@@ -9,6 +9,7 @@
<file alias="kdenlivemonitorcornerscene.qml">monitor/view/kdenlivemonitorcornerscene.qml</file>
<file alias="kdenlivemonitorrotoscene.qml">monitor/view/kdenlivemonitorrotoscene.qml</file>
<file alias="kdenlivemonitorsplit.qml">monitor/view/kdenlivemonitorsplit.qml</file>
<file alias="kdenlivemonitorsplittracks.qml">monitor/view/kdenlivemonitorsplittracks.qml</file>
<file alias="kdenlivemonitorripple.qml">monitor/view/kdenlivemonitorripple.qml</file>
<file alias="SceneToolBar.qml">monitor/view/SceneToolBar.qml</file>
<file alias="EffectToolBar.qml">monitor/view/EffectToolBar.qml</file>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment