Commit 65829ff2 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Cleanup monitor toolbar, now shows up when mouse if on the right size of monitor

Replace toolbar zoom slider with buttons
Rewrite monitor guide overlay so that we can now have several layouts and switch between them using monitor toolbar button
parent 3569ac05
......@@ -598,3 +598,12 @@ void Core::clearSelection()
{
m_mainWindow->getCurrentTimeline()->controller()->clearSelection();
}
void Core::triggerAction(const QString &name)
{
QAction *action = m_mainWindow->actionCollection()->action(name);
if (action) {
action->trigger();
}
}
......@@ -193,6 +193,9 @@ private:
std::unique_ptr<Mlt::Profile> m_thumbProfile;
bool m_guiConstructed = false;
public slots:
void triggerAction(const QString &name);
signals:
void coreIsReady();
void updateLibraryPath();
......
......@@ -759,6 +759,15 @@
<default>0x05</default>
</entry>
<entry name="clipMonitorOverlayGuides" type="Int">
<label>index of current guides overlay for clip monitor.</label>
<default>0</default>
</entry>
<entry name="projectMonitorOverlayGuides" type="Int">
<label>index of current guides overlay for project monitor.</label>
<default>0</default>
</entry>
<entry name="displayAudioOverlay" type="Bool">
<label>Show audio overlay info on monitor.</label>
<default>false</default>
......
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui name="kdenlive" version="152" translationDomain="kdenlive">
<kpartgui name="kdenlive" version="153" translationDomain="kdenlive">
<MenuBar>
<Menu name="file" >
<Action name="dvd_wizard" />
......@@ -170,22 +170,25 @@
<Action name="monitor_seek_snap_forward" />
<Action name="seek_end" />
</Menu>
<Action name="monitor_seek_backward" />
<Action name="monitor_seek_backward-one-frame" />
<Action name="monitor_seek_backward-one-second" />
<Action name="monitor_seek_forward-one-second" />
<Action name="monitor_seek_forward-one-frame" />
<Action name="monitor_seek_forward" />
<Menu name="monitor_seek" ><text>Seek</text>
<Action name="monitor_seek_backward" />
<Action name="monitor_seek_backward-one-frame" />
<Action name="monitor_seek_backward-one-second" />
<Action name="monitor_seek_forward-one-second" />
<Action name="monitor_seek_forward-one-frame" />
<Action name="monitor_seek_forward" />
</Menu>
<Separator />
<Action name="mark_in" />
<Action name="mark_out" />
<Separator />
<Action name="monitor_fullscreen" />
<Action name="monitor_zoomin" />
<Action name="monitor_zoomout" />
<Menu name="monitor_config_overlay" ><text>Current Monitor Overlay</text>
<Action name="monitor_overlay" />
<Action name="monitor_overlay_tc" />
<Action name="monitor_overlay_fps" />
<Action name="monitor_overlay_safezone" />
<Action name="monitor_overlay_markers" />
<Action name="monitor_overlay_audiothumb" />
</Menu>
......
......@@ -291,7 +291,7 @@ void MainWindow::init()
m_projectMonitor = new Monitor(Kdenlive::ProjectMonitor, pCore->monitorManager(), this);
connect(m_projectMonitor, &Monitor::passKeyPress, this, &MainWindow::triggerKey);
connect(m_projectMonitor, &Monitor::addMarker, this, &MainWindow::slotAddMarkerGuideQuickly);
connect(m_projectMonitor, &Monitor::deleteMarker, this, &MainWindow::slotDeleteClipMarker);
connect(m_projectMonitor, &Monitor::deleteMarker, this, &MainWindow::slotDeleteGuide);
connect(m_projectMonitor, &Monitor::seekToPreviousSnap, this, &MainWindow::slotSnapRewind);
connect(m_projectMonitor, &Monitor::seekToNextSnap, this, &MainWindow::slotSnapForward);
connect(m_loopClip, &QAction::triggered, m_projectMonitor, &Monitor::slotLoopClip);
......@@ -1272,11 +1272,6 @@ void MainWindow::setupActions()
overlayMarkerInfo->setCheckable(true);
overlayMarkerInfo->setData(0x04);
QAction *overlaySafeInfo = new QAction(KoIconUtils::themedIcon(QStringLiteral("help-hint")), i18n("Monitor Overlay Safe Zones"), this);
addAction(QStringLiteral("monitor_overlay_safezone"), overlaySafeInfo);
overlaySafeInfo->setCheckable(true);
overlaySafeInfo->setData(0x08);
QAction *overlayAudioInfo = new QAction(KoIconUtils::themedIcon(QStringLiteral("help-hint")), i18n("Monitor Overlay Audio Waveform"), this);
addAction(QStringLiteral("monitor_overlay_audiothumb"), overlayAudioInfo);
overlayAudioInfo->setCheckable(true);
......
......@@ -554,40 +554,31 @@ void GLWidget::paintGL()
}
}
void GLWidget::slotZoomScene(double value)
void GLWidget::slotZoom(bool zoomIn)
{
int val = value;
if (val >= 3) {
setZoom(value - 2.0f);
} else if (val == 2) {
setZoom(0.5);
} else if (val == 1) {
setZoom(0.25);
} else if (val == 0) {
setZoom(0.125);
}
}
void GLWidget::wheelEvent(QWheelEvent *event)
{
if (((event->modifiers() & Qt::ControlModifier) != 0u) && ((event->modifiers() & Qt::ShiftModifier) != 0u)) {
if (event->delta() > 0) {
if (qFuzzyCompare(m_zoom, 1.0f)) {
if (zoomIn) {
if (qFuzzyCompare(m_zoom, 1.0f)) {
setZoom(2.0f);
} else if (qFuzzyCompare(m_zoom, 2.0f)) {
setZoom(3.0f);
} else if (m_zoom < 1.0f) {
setZoom(m_zoom * 2);
}
} else {
if (qFuzzyCompare(m_zoom, 3.0f)) {
setZoom(2.0);
} else if (qFuzzyCompare(m_zoom, 2.0f)) {
setZoom(1.0);
} else if (m_zoom > 0.2) {
setZoom(m_zoom / 2);
}
} else {
if (qFuzzyCompare(m_zoom, 3.0f)) {
setZoom(2.0);
} else if (qFuzzyCompare(m_zoom, 2.0f)) {
setZoom(1.0);
} else if (m_zoom > 0.2) {
setZoom(m_zoom / 2);
}
}
}
void GLWidget::wheelEvent(QWheelEvent *event)
{
if (((event->modifiers() & Qt::ControlModifier) != 0u) && ((event->modifiers() & Qt::ShiftModifier) != 0u)) {
slotZoom(event->delta() > 0);
return;
}
emit mouseSeek(event->delta(), (uint)event->modifiers());
......
......@@ -37,6 +37,7 @@
#include "bin/model/markerlistmodel.hpp"
#include "definitions.h"
#include "scopes/sharedframe.h"
#include "kdenlivesettings.h"
class QOpenGLFunctions_3_2_Core;
......@@ -63,6 +64,7 @@ class GLWidget : public QQuickView, protected QOpenGLFunctions
public:
friend class MonitorController;
friend class Monitor;
friend class MonitorProxy;
GLWidget(int id, QObject *parent = nullptr);
~GLWidget();
......@@ -142,7 +144,7 @@ public slots:
void setOffsetX(int x, int max);
void setOffsetY(int y, int max);
void slotSwitchAudioOverlay(bool enable);
void slotZoomScene(double value);
void slotZoom(bool zoomIn);
void initializeGL();
void releaseAnalyse();
void switchPlay(bool play, double speed = 1.0);
......@@ -178,9 +180,9 @@ protected:
Mlt::Producer *m_producer;
Mlt::Profile *m_monitorProfile;
QMutex m_mutex;
int m_id;
private:
int m_id;
QRect m_rect;
QRect m_effectRect;
GLuint m_texture[3];
......@@ -300,6 +302,7 @@ class MonitorProxy : public QObject
Q_PROPERTY(int zoneOut READ zoneOut WRITE setZoneOut NOTIFY zoneChanged)
Q_PROPERTY(int rulerHeight READ rulerHeight NOTIFY rulerHeightChanged)
Q_PROPERTY(QString markerComment READ markerComment NOTIFY markerCommentChanged)
Q_PROPERTY(int overlayType READ overlayType WRITE setOverlayType NOTIFY overlayTypeChanged)
public:
MonitorProxy(GLWidget *parent)
: QObject(parent)
......@@ -314,6 +317,14 @@ public:
int seekPosition() const { return m_seekPosition; }
int position() const { return m_position; }
int rulerHeight() const { return m_rulerHeight; }
int overlayType() const {return (q->m_id == (int)Kdenlive::ClipMonitor ? KdenliveSettings::clipMonitorOverlayGuides() : KdenliveSettings::projectMonitorOverlayGuides()); }
void setOverlayType(int ix) {
if (q->m_id == (int)Kdenlive::ClipMonitor) {
KdenliveSettings::setClipMonitorOverlayGuides(ix);
} else {
KdenliveSettings::setProjectMonitorOverlayGuides(ix);
}
}
QString markerComment() const { return m_markerComment; }
Q_INVOKABLE void requestSeekPosition(int pos)
{
......@@ -406,6 +417,8 @@ signals:
void rulerHeightChanged();
void addSnap(int);
void removeSnap(int);
Q_INVOKABLE void triggerAction(const QString &name);
void overlayTypeChanged();
private:
GLWidget *q;
......
......@@ -301,6 +301,7 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
} else {
connect(m_glMonitor->getControllerProxy(), &MonitorProxy::zoneChanged, this, &Monitor::updateClipZone);
}
connect(m_glMonitor->getControllerProxy(), &MonitorProxy::triggerAction, pCore.get(), &Core::triggerAction);
m_sceneVisibilityAction = new QAction(KoIconUtils::themedIcon(QStringLiteral("transform-crop")), i18n("Show/Hide edit mode"), this);
m_sceneVisibilityAction->setCheckable(true);
......@@ -308,10 +309,6 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
connect(m_sceneVisibilityAction, &QAction::triggered, this, &Monitor::slotEnableEffectScene);
m_toolbar->addAction(m_sceneVisibilityAction);
m_zoomVisibilityAction = new QAction(KoIconUtils::themedIcon(QStringLiteral("zoom-in")), i18n("Zoom"), this);
m_zoomVisibilityAction->setCheckable(true);
connect(m_zoomVisibilityAction, &QAction::triggered, this, &Monitor::slotEnableSceneZoom);
m_toolbar->addSeparator();
m_timePos = new TimecodeDisplay(m_monitorManager->timecode(), this);
m_toolbar->addWidget(m_timePos);
......@@ -505,8 +502,6 @@ void Monitor::setupMenu(QMenu *goMenu, QMenu *overlayMenu, QAction *playZone, QA
switchAudioMonitor->setCheckable(true);
switchAudioMonitor->setChecked((KdenliveSettings::monitoraudio() & m_id) != 0);
m_configMenu->addAction(overlayAudio);
m_configMenu->addAction(m_zoomVisibilityAction);
m_contextMenu->addAction(m_zoomVisibilityAction);
// For some reason, the frame in QAbstracSpinBox (base class of TimeCodeDisplay) needs to be displayed once, then hidden
// or it will never appear (supposed to appear on hover).
m_timePos->setFrame(false);
......@@ -1509,11 +1504,6 @@ QPoint Monitor::getZoneInfo() const
return m_controller->zone();
}
void Monitor::slotEnableSceneZoom(bool enable)
{
m_qmlManager->setProperty(QStringLiteral("showToolbar"), enable);
}
void Monitor::slotEnableEffectScene(bool enable)
{
KdenliveSettings::setShowOnMonitorScene(enable);
......@@ -1879,7 +1869,6 @@ void Monitor::loadQmlScene(MonitorSceneType type)
double ratio = (double)m_glMonitor->profileSize().width() / (int)(m_glMonitor->profileSize().height() * m_glMonitor->profile()->dar() + 0.5);
m_qmlManager->setScene(m_id, type, m_glMonitor->profileSize(), ratio, m_glMonitor->displayRect(), m_glMonitor->zoom(), m_timePos->maximum());
QQuickItem *root = m_glMonitor->rootObject();
root->setProperty("showToolbar", m_zoomVisibilityAction->isChecked());
connectQmlToolbar(root);
switch (type) {
case MonitorSceneSplit:
......@@ -1890,7 +1879,6 @@ void Monitor::loadQmlScene(MonitorSceneType type)
case MonitorSceneRoto:
QObject::connect(root, SIGNAL(addKeyframe()), this, SIGNAL(addKeyframe()), Qt::UniqueConnection);
QObject::connect(root, SIGNAL(seekToKeyframe()), this, SLOT(slotSeekToKeyFrame()), Qt::UniqueConnection);
QObject::connect(root, SIGNAL(toolBarChanged(bool)), m_zoomVisibilityAction, SLOT(setChecked(bool)), Qt::UniqueConnection);
break;
case MonitorSceneRipple:
QObject::connect(root, SIGNAL(doAcceptRipple(bool)), this, SIGNAL(acceptRipple(bool)), Qt::UniqueConnection);
......@@ -1913,30 +1901,9 @@ void Monitor::loadQmlScene(MonitorSceneType type)
void Monitor::connectQmlToolbar(QQuickItem *root)
{
QObject *button = root->findChild<QObject *>(QStringLiteral("fullScreen"));
if (button) {
QObject::connect(button, SIGNAL(clicked()), this, SLOT(slotSwitchFullScreen()), Qt::UniqueConnection);
}
// Normal monitor toolbar
button = root->findChild<QObject *>(QStringLiteral("nextSnap"));
if (button) {
QObject::connect(button, SIGNAL(clicked()), this, SIGNAL(seekToNextSnap()), Qt::UniqueConnection);
}
button = root->findChild<QObject *>(QStringLiteral("prevSnap"));
if (button) {
QObject::connect(button, SIGNAL(clicked()), this, SIGNAL(seekToPreviousSnap()), Qt::UniqueConnection);
}
button = root->findChild<QObject *>(QStringLiteral("addMarker"));
if (button) {
QObject::connect(button, SIGNAL(clicked()), this, SIGNAL(addMarker()), Qt::UniqueConnection);
}
button = root->findChild<QObject *>(QStringLiteral("removeMarker"));
if (button) {
QObject::connect(button, SIGNAL(clicked()), this, SIGNAL(deleteMarker()), Qt::UniqueConnection);
}
//TODO: get rid of this horrible hack and use triggerAction in qml
// Effect monitor toolbar
button = root->findChild<QObject *>(QStringLiteral("nextKeyframe"));
QObject *button = root->findChild<QObject *>(QStringLiteral("nextKeyframe"));
if (button) {
QObject::connect(button, SIGNAL(clicked()), this, SIGNAL(seekToNextKeyframe()), Qt::UniqueConnection);
}
......@@ -1952,10 +1919,6 @@ void Monitor::connectQmlToolbar(QQuickItem *root)
if (button) {
QObject::connect(button, SIGNAL(clicked()), this, SIGNAL(deleteKeyframe()), Qt::UniqueConnection);
}
button = root->findChild<QObject *>(QStringLiteral("zoomSlider"));
if (button) {
QObject::connect(button, SIGNAL(zoomChanged(double)), m_glMonitor, SLOT(slotZoomScene(double)), Qt::UniqueConnection);
}
}
void Monitor::setQmlProperty(const QString &name, const QVariant &value)
......@@ -2099,7 +2062,6 @@ void Monitor::updateQmlDisplay(int currentOverlay)
} else {
disconnect(m_timePos, &TimecodeDisplay::emitTimeCode, this, &Monitor::slotUpdateQmlTimecode);
}
m_glMonitor->rootObject()->setProperty("showSafezone", currentOverlay & 0x08);
m_glMonitor->rootObject()->setProperty("showAudiothumb", currentOverlay & 0x10);
}
......@@ -2165,3 +2127,12 @@ void Monitor::removeSnapPoint(int pos)
m_snaps->removePoint(pos);
}
void Monitor::slotZoomIn()
{
m_glMonitor->slotZoom(true);
}
void Monitor::slotZoomOut()
{
m_glMonitor->slotZoom(false);
}
......@@ -156,6 +156,10 @@ public:
void reconfigure();
/** @brief Saves current monitor frame to an image file, and add it to project if addToProject is set to true **/
void slotExtractCurrentFrame(QString frameName = QString(), bool addToProject = false);
/** @brief Zoom in active monitor */
void slotZoomIn();
/** @brief Zoom out active monitor */
void slotZoomOut();
protected:
void mousePressEvent(QMouseEvent *event) override;
......@@ -268,8 +272,6 @@ private slots:
void gpuError();
void setOffsetX(int x);
void setOffsetY(int y);
/** @brief Show/hide monitor zoom */
void slotEnableSceneZoom(bool enable);
/** @brief Pan monitor view */
void panView(QPoint diff);
/** @brief Project monitor zone changed, inform timeline */
......
......@@ -380,6 +380,16 @@ void MonitorManager::setupActions()
pCore->window()->addAction(QStringLiteral("monitor_fullscreen"), fullMonitor);
connect(fullMonitor, &QAction::triggered, this, &MonitorManager::slotSwitchFullscreen);
QAction *monitorZoomIn = new QAction(i18n("Zoom in monitor"), this);
monitorZoomIn->setIcon(KoIconUtils::themedIcon(QStringLiteral("zoom-in")));
pCore->window()->addAction(QStringLiteral("monitor_zoomin"), monitorZoomIn);
connect(monitorZoomIn, &QAction::triggered, this, &MonitorManager::slotZoomIn);
QAction *monitorZoomOut = new QAction(i18n("Zoom out monitor"), this);
monitorZoomOut->setIcon(KoIconUtils::themedIcon(QStringLiteral("zoom-out")));
pCore->window()->addAction(QStringLiteral("monitor_zoomout"), monitorZoomOut);
connect(monitorZoomOut, &QAction::triggered, this, &MonitorManager::slotZoomOut);
QAction *monitorSeekBackward = new QAction(KoIconUtils::themedIcon(QStringLiteral("media-seek-backward")), i18n("Rewind"), this);
monitorSeekBackward->setShortcut(Qt::Key_J);
pCore->window()->addAction(QStringLiteral("monitor_seek_backward"), monitorSeekBackward);
......@@ -612,3 +622,17 @@ void MonitorManager::slotExtractCurrentFrameToProject()
static_cast<Monitor *>(m_activeMonitor)->slotExtractCurrentFrame(QString(), true);
}
}
void MonitorManager::slotZoomIn()
{
if (m_activeMonitor) {
static_cast<Monitor *>(m_activeMonitor)->slotZoomIn();
}
}
void MonitorManager::slotZoomOut()
{
if (m_activeMonitor) {
static_cast<Monitor *>(m_activeMonitor)->slotZoomOut();
}
}
......@@ -117,6 +117,10 @@ private slots:
void slotSetInterpolation(int ix);
/** @brief Switch muting on/off */
void slotMuteCurrentMonitor(bool active);
/** @brief Zoom in active monitor */
void slotZoomIn();
/** @brief Zoom out active monitor */
void slotZoomOut();
private:
/** @brief Make sure 2 monitors cannot be activated simultaneously*/
......
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtQuick 2.0
Item {
id: overlay
Rectangle {
color: root.overlayColor
width: frame.width / 20
height: 1
anchors.centerIn: parent
}
Rectangle {
color: root.overlayColor
height: frame.width / 20
width: 1
anchors.centerIn: parent
}
}
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtQuick 2.0
Item {
id: overlay
//property color: 'cyan'
Rectangle {
id: safezone
objectName: "safezone"
color: "transparent"
border.color: root.overlayColor
width: parent.width * 0.9
height: parent.height * 0.9
anchors.centerIn: parent
Rectangle {
id: safetext
objectName: "safetext"
color: "transparent"
border.color: root.overlayColor
width: frame.width * 0.8
height: frame.height * 0.8
anchors.centerIn: parent
}
Rectangle {
color: root.overlayColor
width: frame.width / 20
height: 1
anchors.centerIn: parent
}
Rectangle {
color: root.overlayColor
height: frame.width / 20
width: 1
anchors.centerIn: parent
}
Rectangle {
color: root.overlayColor
height: frame.height / 11
width: 1
y: 0
x: parent.width / 2
}
Rectangle {
color: root.overlayColor
height: frame.height / 11
width: 1
y: parent.height -height
x: parent.width / 2
}
Rectangle {
color: root.overlayColor
width: frame.width / 11
height: 1
y: parent.height / 2
x: 0
}
Rectangle {
color: root.overlayColor
width: frame.width / 11
height: 1
y: parent.height / 2
x: parent.width -width
}
}
}
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.3
import QtQuick 2.0
Rectangle {
id: scenetoolbar
objectName: "scenetoolbar"
width: fullscreenButton.width
height: fullscreenButton.height * 5 + zoomSlider.height + 2
height: childrenRect.height
SystemPalette { id: myPalette; colorGroup: SystemPalette.Active }
color: Qt.rgba(myPalette.window.r, myPalette.window.g, myPalette.window.b, 0.7)
radius: 4
border.color : Qt.rgba(0, 0, 0, 0.3)
border.width: 1
function setZoom(zoom) {
if (zoom >= 1) {
zoomSlider.value = zoom + 2
} else if (zoom == 0.5) {
zoomSlider.value = 2
} else if (zoom == 0.25) {
zoomSlider.value = 1
} else if (zoom == 0.125) {
zoomSlider.value = 0
}
}
Column {
ToolButton {
id: fullscreenButton
objectName: "fullScreen"
iconName: "view-fullscreen"
tooltip: "Switch Full Screen"
onClicked: controller.triggerAction('monitor_fullscreen')
}
ToolButton {
objectName: "switchOverlay"
iconName: "view-grid"
tooltip: "Change Overlay"
onClicked: {
root.switchOverlay()
}
}
ToolButton {
objectName: "nextSnap"
iconName: "go-next"
tooltip: "Go to Next Snap Point"
iconName: "zoom-in"
tooltip: "Zoom in"
onClicked: controller.triggerAction('monitor_zoomin')
}
ToolButton {
objectName: "prevSnap"
iconName: "go-previous"
tooltip: "Go to Previous Snap Point"
iconName: "zoom-out"
tooltip: "Zoom out"
onClicked: controller.triggerAction('monitor_zoomout')
}
ToolButton {
objectName: "addMarker"
iconName: "list-add"
tooltip: "Add Marker"
tooltip: root.isClipMonitor ? "Add Marker" : "Add Guide"
onClicked: controller.triggerAction('add_marker_guide_quickly')
}
ToolButton {
objectName: "removeMarker"
iconName: "list-remove"
tooltip: "Remove Marker"
}
Slider {
id: zoomSlider
signal zoomChanged(real value)
anchors.horizontalCenter:parent.horizontalCenter
objectName: "zoomSlider"
orientation: Qt.Vertical
height: fullscreenButton.height * 3
maximumValue: 5.0
stepSize: 1.0
value: 3.0
onValueChanged: {
zoomSlider.zoomChanged(value);
}
tooltip: root.isClipMonitor ? "Remove Marker" : "Remove Guide"
onClicked: root.isClipMonitor ? controller.triggerAction('delete_clip_marker') : controller.triggerAction('delete_guide')
}
}
}
......@@ -33,15 +33,15 @@ Item {
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