Commit fb8d5554 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

Status bar: add key binding info zone to display possible key combinations in timeline.

Related to #916
parent dc2c87bf
Pipeline #47341 passed with stage
in 10 minutes and 33 seconds
......@@ -3105,24 +3105,34 @@ void MainWindow::slotChangeEdit(QAction *action)
void MainWindow::slotSetTool(ProjectTool tool)
{
if (pCore->currentDoc()) {
// pCore->currentDoc()->setTool(tool);
QString message;
switch (tool) {
case SpacerTool:
message = i18n("Ctrl + click to use spacer on current track only, Shift + click to move guides too. You can combine both modifiers.");
break;
case RazorTool:
message = i18n("Click on a clip to cut it, Shift + move to preview cut frame");
break;
default:
message = i18n("Shift + click to create a selection rectangle, Ctrl + click to add an item to selection");
break;
}
m_messageLabel->setMessage(message, InformationMessage);
showToolMessage();
getMainTimeline()->setTool(tool);
}
}
void MainWindow::showToolMessage()
{
QString message;
if (m_buttonSelectTool->isChecked()) {
message = i18n("<b>Shift</b> to create a selection rectangle, <b>Ctrl</b> to add an item to selection");
} else if (m_buttonRazorTool->isChecked()) {
message = i18n("<b>Shift</b> to preview cut frame");
} else if (m_buttonSpacerTool->isChecked()) {
message = i18n("<b>Ctrl</b> to apply on current track only, <b>Shift</b> to also move guides. You can combine both modifiers.");
}
m_messageLabel->setKeyMap(message);
}
void MainWindow::clearToolMessage()
{
m_messageLabel->setKeyMap(QString());
}
void MainWindow::showKeyBinding(const QString &text)
{
m_messageLabel->setTmpKeyMap(text);
}
void MainWindow::slotCopy()
{
getMainTimeline()->controller()->copyItem();
......
......@@ -147,6 +147,13 @@ public:
/** @brief Restart the application and delete config files if clean is true */
void cleanRestart(bool clean);
/** @brief Show current tool key combination in status bar */
void showToolMessage();
/** @brief Hide the current tool key combination in status bar */
void clearToolMessage();
/** @brief Show a key binding in status bar */
void showKeyBinding(const QString &text);
protected:
/** @brief Closes the window.
* @return false if the user presses "Cancel" on a confirmation dialog or
......
......@@ -77,10 +77,20 @@ StatusBarMessageLabel::StatusBarMessageLabel(QWidget *parent)
m_label = new QLabel(this);
m_label->setAlignment(Qt::AlignLeft);
m_label->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
m_keyMap = new QLabel(this);
m_keyMap->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
m_keyMap->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
m_progress = new QProgressBar(this);
lay->addWidget(m_pixmap);
lay->addWidget(m_label);
lay->addWidget(m_progress);
QFrame* line = new QFrame(this);
line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
lay->addWidget(line);
lay->addWidget(m_keyMap);
setLayout(lay);
m_progress->setVisible(false);
lay->setContentsMargins(BorderGap, 0, 2 * BorderGap, 0);
......@@ -99,6 +109,21 @@ void StatusBarMessageLabel::mousePressEvent(QMouseEvent *event)
}
}
void StatusBarMessageLabel::setKeyMap(const QString &text)
{
m_keyMap->setText(text);
m_keymapText = text;
}
void StatusBarMessageLabel::setTmpKeyMap(const QString &text)
{
if (text.isEmpty()) {
m_keyMap->setText(m_keymapText);
} else {
m_keyMap->setText(text);
}
}
void StatusBarMessageLabel::setProgressMessage(const QString &text, MessageType type, int progress)
{
if (type == ProcessingJobMessage) {
......
......@@ -102,6 +102,10 @@ protected:
public slots:
void setProgressMessage(const QString &text, MessageType type = ProcessingJobMessage, int progress = 100);
void setMessage(const QString &text, MessageType type = DefaultMessage, int timeoutMS = 0);
/** @brief Display a key binding info in status bar */
void setKeyMap(const QString &text);
/** @brief Display a temporary key binding info in status bar, revert to defaut one if text is empty */
void setTmpKeyMap(const QString &text);
private slots:
......@@ -125,6 +129,8 @@ private:
int m_minTextHeight;
QLabel *m_pixmap;
QLabel *m_label;
QLabel *m_keyMap;
QString m_keymapText;
QProgressBar *m_progress;
QTimerWithTime m_queueTimer;
QSemaphore m_queueSemaphore;
......
......@@ -184,6 +184,15 @@ Rectangle {
var itemPos = mapToItem(tracksContainerArea, 0, 0, clipRoot.width, clipRoot.height)
initDrag(clipRoot, itemPos, clipRoot.clipId, clipRoot.modelStart, clipRoot.trackId, false)
}
function showClipInfo() {
var text = i18n("%1 (%2-%3), Position: %4, Duration: %5".arg(clipRoot.clipName)
.arg(timeline.simplifiedTC(clipRoot.inPoint))
.arg(timeline.simplifiedTC(clipRoot.outPoint))
.arg(timeline.simplifiedTC(clipRoot.modelStart))
.arg(timeline.simplifiedTC(clipRoot.clipDuration)))
timeline.showToolTip(text)
}
function getColor() {
if (clipRoot.clipState == ClipState.Disabled) {
......@@ -299,17 +308,14 @@ Rectangle {
onEntered: {
var itemPos = mapToItem(tracksContainerArea, 0, 0, width, height)
initDrag(clipRoot, itemPos, clipRoot.clipId, clipRoot.modelStart, clipRoot.trackId, false)
var text = i18n("%1 (%2-%3), Position: %4, Duration: %5".arg(clipRoot.clipName)
.arg(timeline.simplifiedTC(clipRoot.inPoint))
.arg(timeline.simplifiedTC(clipRoot.outPoint))
.arg(timeline.simplifiedTC(clipRoot.modelStart))
.arg(timeline.simplifiedTC(clipRoot.clipDuration)))
timeline.showToolTip(text)
showClipInfo()
}
onExited: {
endDrag()
timeline.showToolTip()
if (!trimInMouseArea.containsMouse && !trimOutMouseArea.containsMouse && !compInArea.containsMouse && !compOutArea.containsMouse) {
timeline.showToolTip()
}
}
onWheel: zoomByWheel(wheel)
......@@ -578,6 +584,7 @@ Rectangle {
initDrag(clipRoot, itemPos, clipRoot.clipId, clipRoot.modelStart, clipRoot.trackId, false)
var s = i18n("In:%1, Position:%2", timeline.simplifiedTC(clipRoot.inPoint),timeline.simplifiedTC(clipRoot.modelStart))
timeline.showToolTip(s)
timeline.showKeyBinding(i18n("<b>Ctrl</b> to change speed, <b>Double click</b> to mix with adjacent clip"))
}
}
onExited: {
......@@ -586,13 +593,9 @@ Rectangle {
if (!mouseArea.containsMouse) {
timeline.showToolTip()
} else {
var text = i18n("%1 (%2-%3), Position: %4, Duration: %5".arg(clipRoot.clipName)
.arg(timeline.simplifiedTC(clipRoot.inPoint))
.arg(timeline.simplifiedTC(clipRoot.outPoint))
.arg(timeline.simplifiedTC(clipRoot.modelStart))
.arg(timeline.simplifiedTC(clipRoot.clipDuration)))
timeline.showToolTip(text)
clipRoot.showClipInfo()
}
timeline.showKeyBinding()
}
}
Rectangle {
......@@ -684,6 +687,7 @@ Rectangle {
initDrag(clipRoot, itemPos, clipRoot.clipId, clipRoot.modelStart, clipRoot.trackId, false)
var s = i18n("Out:%1, Position:%2", timeline.simplifiedTC(clipRoot.outPoint),timeline.simplifiedTC(clipRoot.modelStart + clipRoot.clipDuration))
timeline.showToolTip(s)
timeline.showKeyBinding(i18n("<b>Ctrl</b> to change speed, <b>Double click</b> to mix with adjacent clip"))
}
}
onExited: {
......@@ -699,6 +703,7 @@ Rectangle {
.arg(timeline.simplifiedTC(clipRoot.clipDuration)))
timeline.showToolTip(text)
}
timeline.showKeyBinding()
}
}
/*ToolTip {
......@@ -933,19 +938,11 @@ Rectangle {
onPressed: {
timeline.addCompositionToClip('', clipRoot.clipId, 0)
}
ToolTip {
visible: compInArea.containsMouse && !dragProxyArea.pressed
delay: 1000
timeout: 5000
background: Rectangle {
color: activePalette.alternateBase
border.color: activePalette.light
}
contentItem: Label {
color: activePalette.text
font: miniFont
text: i18n("Click to add composition")
}
onEntered: {
timeline.showKeyBinding(i18n("<b>Click</b> to add composition"))
}
onExited: {
timeline.showKeyBinding()
}
Rectangle {
// Start composition box
......@@ -977,19 +974,11 @@ Rectangle {
onPressed: {
timeline.addCompositionToClip('', clipRoot.clipId, clipRoot.clipDuration - 1)
}
ToolTip {
visible: compOutArea.containsMouse && !dragProxyArea.pressed
delay: 1000
timeout: 5000
background: Rectangle {
color: activePalette.alternateBase
border.color: activePalette.light
}
contentItem: Label {
color: activePalette.text
font: miniFont
text: i18n("Click to add composition")
}
onEntered: {
timeline.showKeyBinding(i18n("<b>Click</b> to add composition"))
}
onExited: {
timeline.showKeyBinding()
}
Rectangle {
// End composition box
......@@ -1054,9 +1043,27 @@ Rectangle {
lastDuration = duration
timeline.adjustFade(clipRoot.clipId, 'fadeout', duration, -1)
// Show fade duration as time in a "bubble" help.
var s = timeline.simplifiedTC(clipRoot.fadeOut)
timeline.showToolTip(s)
//bubbleHelp.show(clipRoot.x + x, parentTrack.y + parentTrack.height, s)
timeline.showToolTip(i18n("Fade out: %1", timeline.simplifiedTC(clipRoot.fadeOut)))
}
}
}
onEntered: {
if (!pressed) {
if (clipRoot.fadeOut > 0) {
timeline.showToolTip(i18n("Fade out: %1", timeline.simplifiedTC(clipRoot.fadeOut)))
} else {
clipRoot.showClipInfo()
}
timeline.showKeyBinding(i18n("<b>Drag</b> to add a fade, <b>Double click</b> to add default duration fade"))
}
}
onExited: {
if (!pressed) {
timeline.showKeyBinding()
if (mouseArea.containsMouse) {
clipRoot.showClipInfo()
} else {
timeline.showToolTip()
}
}
}
......@@ -1083,21 +1090,6 @@ Rectangle {
width: 1
visible : clipRoot.fadeOut > 0 && (fadeOutMouseArea.containsMouse || fadeOutMouseArea.drag.active)
}
ToolTip {
visible: fadeOutMouseArea.containsMouse && !fadeOutMouseArea.drag.active
delay: 1000
timeout: 5000
background: Rectangle {
color: activePalette.alternateBase
border.color: activePalette.light
}
contentItem: Label {
color: activePalette.text
font: miniFont
text: clipRoot.fadeOut > 0 ? '%1: %2'.arg(i18n("Duration"))
.arg(timeline.simplifiedTC(clipRoot.fadeOut)) : i18n("Double click or drag to add a fade")
}
}
}
}
......@@ -1146,9 +1138,27 @@ Rectangle {
if (duration != clipRoot.fadeIn) {
timeline.adjustFade(clipRoot.clipId, 'fadein', duration, -1)
// Show fade duration as time in a "bubble" help.
var s = timeline.simplifiedTC(clipRoot.fadeIn)
timeline.showToolTip(s)
//bubbleHelp.show(clipRoot.x + x, parentTrack.y + parentTrack.height, s)
timeline.showToolTip(i18n("Fade in: %1", timeline.simplifiedTC(clipRoot.fadeIn)))
}
}
}
onEntered: {
if (!pressed) {
if (clipRoot.fadeIn > 0) {
timeline.showToolTip(i18n("Fade in: %1", timeline.simplifiedTC(clipRoot.fadeIn)))
} else {
clipRoot.showClipInfo()
}
timeline.showKeyBinding(i18n("<b>Drag</b> to add a fade, <b>Double click</b> to add default duration fade"))
}
}
onExited: {
if (!pressed) {
timeline.showKeyBinding()
if (mouseArea.containsMouse) {
clipRoot.showClipInfo()
} else {
timeline.showToolTip()
}
}
}
......@@ -1175,21 +1185,6 @@ Rectangle {
width: 1
visible : clipRoot.fadeIn > 0 && (fadeInMouseArea.containsMouse || fadeInMouseArea.drag.active)
}
ToolTip {
visible: fadeInMouseArea.containsMouse && !fadeInMouseArea.drag.active
delay: 1000
timeout: 5000
background: Rectangle {
color: activePalette.alternateBase
border.color: activePalette.light
}
contentItem: Label {
color: activePalette.text
font: miniFont
text: clipRoot.fadeIn > 0 ? '%1: %2'.arg(i18n("Duration"))
.arg(timeline.simplifiedTC(clipRoot.fadeIn)) : i18n("Double click or drag to add a fade")
}
}
}
}
}
......
......@@ -261,10 +261,17 @@ Rectangle {
// Used to pass modifier state to expand button
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true
onPressed: {
expandButton.modifier = mouse.modifiers
mouse.accepted = false
}
onEntered: {
timeline.showKeyBinding(i18n("<b>Shift</b> to collapse/expand all tracks of the same type (audio/video)"))
}
onExited: {
timeline.showKeyBinding()
}
}
anchors.left: parent.left
width: root.collapsedHeight
......
......@@ -1057,6 +1057,10 @@ Rectangle {
property bool scim: false
onExited: {
scim = false
timeline.showTimelineToolInfo(false)
}
onEntered: {
timeline.showTimelineToolInfo(true)
}
onDoubleClicked: {
if (mouse.buttons === Qt.LeftButton && root.showSubtitles && root.activeTool === 0 && mouse.y > ruler.height && mouse.y < (ruler.height + subtitleTrack.height)) {
......
......@@ -4063,3 +4063,20 @@ void TimelineController::showToolTip(const QString &info) const
{
pCore->displayMessage(info, DirectMessage);
}
void TimelineController::showKeyBinding(const QString &info) const
{
pCore->window()->showKeyBinding(info);
}
void TimelineController::showTimelineToolInfo(bool show) const
{
if (show) {
pCore->window()->showToolMessage();
} else {
pCore->window()->clearToolMessage();
}
}
......@@ -180,6 +180,8 @@ public:
Q_INVOKABLE QColor selectionColor() const;
Q_INVOKABLE QColor groupColor() const;
Q_INVOKABLE void showToolTip(const QString &info = QString()) const;
Q_INVOKABLE void showKeyBinding(const QString &info = QString()) const;
Q_INVOKABLE void showTimelineToolInfo(bool show) const;
void switchSubtitleDisable();
bool subtitlesDisabled() const;
void switchSubtitleLock();
......
......@@ -61,6 +61,7 @@ TimelineWidget::TimelineWidget(QWidget *parent)
kdeclarative.setupEngine(engine());
kdeclarative.setupContext();
setClearColor(palette().window().color());
setMouseTracking(true);
registerTimelineItems();
m_sortModel = std::make_unique<QSortFilterProxyModel>(this);
m_proxy = new TimelineController(this);
......
  • I'm still having major issues with custom shortcuts not working either at all, or stopping to work after a while (also affecting drag and dropping clips to the timeline), but can't find a way to fix it or why it happens. It sometimes starts working again, others goes on for a while... :-(

    Edited by Bruno Santos
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