diff --git a/app/app.pro b/app/app.pro
index e1cf3eb823..5695aab33b 100644
--- a/app/app.pro
+++ b/app/app.pro
@@ -93,6 +93,7 @@ HEADERS += \
src/generalpage.h \
src/shortcutspage.h \
src/strokeoptionswidget.h \
+ src/timecodecontrolwidget.h \
src/timelinepage.h \
src/toolboxwidget.h \
src/toolspage.h \
@@ -151,6 +152,7 @@ SOURCES += \
src/generalpage.cpp \
src/shortcutspage.cpp \
src/strokeoptionswidget.cpp \
+ src/timecodecontrolwidget.cpp \
src/timelinepage.cpp \
src/toolboxwidget.cpp \
src/toolspage.cpp \
diff --git a/app/data/app.qrc b/app/data/app.qrc
index 5b9116dab2..2a144aa9db 100644
--- a/app/data/app.qrc
+++ b/app/data/app.qrc
@@ -100,6 +100,7 @@
icons/themes/playful/window/window-float-button-normal-darkm.svg
icons/themes/playful/window/window-float-button-normal.svg
icons/themes/playful/window/window-close-button-normal.svg
+ icons/themes/playful/controls/control-timecode.svg
pencil2d_quick_guide.pdf
diff --git a/app/data/icons/themes/playful/controls/control-timecode.svg b/app/data/icons/themes/playful/controls/control-timecode.svg
new file mode 100644
index 0000000000..2db7b5d2ff
--- /dev/null
+++ b/app/data/icons/themes/playful/controls/control-timecode.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/src/basedockwidget.cpp b/app/src/basedockwidget.cpp
index 3336b71706..057b0b6b16 100644
--- a/app/src/basedockwidget.cpp
+++ b/app/src/basedockwidget.cpp
@@ -63,9 +63,14 @@ void BaseDockWidget::lock(bool locked)
// nullptr means removing the custom title bar and restoring the default one
if (locked) {
- setTitleBarWidget(mNoTitleBarWidget);
+ if (mTitleBarWidget->hasChildWidget()) {
+ mTitleBarWidget->lock(locked);
+ } else {
+ setTitleBarWidget(mNoTitleBarWidget);
+ }
} else {
setTitleBarWidget(mTitleBarWidget);
+ mTitleBarWidget->lock(locked);
}
mLocked = locked;
@@ -77,6 +82,13 @@ void BaseDockWidget::setTitle(const QString& title)
mTitleBarWidget->setTitle(title);
}
+void BaseDockWidget::setWidgetInTitleBarArea(QWidget* widget)
+{
+ if (mTitleBarWidget) {
+ mTitleBarWidget->setChildWidget(widget);
+ }
+}
+
void BaseDockWidget::resizeEvent(QResizeEvent *event)
{
QDockWidget::resizeEvent(event);
diff --git a/app/src/basedockwidget.h b/app/src/basedockwidget.h
index fd4323c4a1..a509c3e78e 100644
--- a/app/src/basedockwidget.h
+++ b/app/src/basedockwidget.h
@@ -42,6 +42,10 @@ class BaseDockWidget : public QDockWidget
Editor* editor() const { return mEditor; }
void setEditor( Editor* e ) { mEditor = e; }
+ /// Sets a widget in addition to the normal titlebar buttons.
+ /// If the titlebar already has one widget, the previous one will be deleted.
+ void setWidgetInTitleBarArea(QWidget* widget);
+
protected:
void resizeEvent(QResizeEvent* event) override;
diff --git a/app/src/timecodecontrolwidget.cpp b/app/src/timecodecontrolwidget.cpp
new file mode 100644
index 0000000000..1d49f8b9e8
--- /dev/null
+++ b/app/src/timecodecontrolwidget.cpp
@@ -0,0 +1,118 @@
+/*
+
+Pencil2D - Traditional Animation Software
+Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
+Copyright (C) 2012-2020 Matthew Chiawen Chang
+
+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; version 2 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.
+
+*/
+#include "timecodecontrolwidget.h"
+
+#include "preferencemanager.h"
+#include "pencildef.h"
+#include "pencilsettings.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+TimeCodeControlWidget::TimeCodeControlWidget(TimeCodeControls* controls, QWidget* parent)
+ : QWidget(parent, Qt::Popup), mControls(controls)
+{
+ auto vboxLayout = new QVBoxLayout();
+ vboxLayout->setContentsMargins(4,4,4,4);
+ setLayout(vboxLayout);
+
+ auto titlelabel = new QLabel(tr("Timecode controls"));
+
+ vboxLayout->addWidget(titlelabel);
+
+ auto showTimeCodeCheckBox = new QCheckBox(this);
+ showTimeCodeCheckBox->setText(tr("Show"));
+ showTimeCodeCheckBox->setChecked(controls->enabled);
+
+ auto optionsGroupBox = new QGroupBox(this);
+ optionsGroupBox->setTitle(tr("Options"));
+ optionsGroupBox->setEnabled(controls->enabled);
+
+ auto showFramesCheckBox = new QCheckBox(this);
+ showFramesCheckBox->setText(tr("Frames"));
+ showFramesCheckBox->setChecked(controls->showFrames);
+
+ auto timecodeComboBox = new QComboBox(this);
+
+ auto groupBoxVBoxLayout = new QVBoxLayout();
+ groupBoxVBoxLayout->setContentsMargins(4,4,4,4);
+ optionsGroupBox->setLayout(groupBoxVBoxLayout);
+
+ groupBoxVBoxLayout->addWidget(showFramesCheckBox);
+ groupBoxVBoxLayout->addWidget(timecodeComboBox);
+
+ timecodeComboBox->addItem(tr("No Timecode"), timecodeKindToInt(TimecodeKind::NONE));
+ timecodeComboBox->addItem(tr("SMPTE Timecode"), timecodeKindToInt(TimecodeKind::SMPTE));
+ timecodeComboBox->addItem(tr("SFF Timecode"), timecodeKindToInt(TimecodeKind::SFF));
+ timecodeComboBox->setCurrentIndex(timecodeKindToInt(controls->kind));
+
+ vboxLayout->addWidget(showTimeCodeCheckBox);
+ vboxLayout->addWidget(optionsGroupBox);
+
+ connect(showTimeCodeCheckBox, &QCheckBox::toggled, this, [this, optionsGroupBox](bool toggled) {
+ showTimecode(toggled);
+ optionsGroupBox->setEnabled(toggled);
+ });
+
+ connect(showFramesCheckBox, &QCheckBox::toggled, this, [this](bool toggled) {
+ showFrames(toggled);
+ });
+
+ auto comboBoxValueChanged = static_cast(&QComboBox::currentIndexChanged);
+ connect(timecodeComboBox, comboBoxValueChanged, this, [this, controls](int index) {
+ auto timecodeKind = controls->timecodeKindFromInt(index);
+
+ setTimecodeTimerKind(timecodeKind);
+ });
+}
+
+void TimeCodeControlWidget::showFrames(bool shown)
+{
+ QSettings settings(PENCIL2D, PENCIL2D);
+ settings.setValue(SETTING_TIMECODE_FRAMES_ON, shown);
+
+ mControls->showFrames = shown;
+ emit timecodeUpdated();
+}
+
+int TimeCodeControlWidget::timecodeKindToInt(TimecodeKind kind) const
+{
+ return static_cast(kind);
+}
+
+void TimeCodeControlWidget::showTimecode(bool shown)
+{
+ QSettings settings(PENCIL2D, PENCIL2D);
+ settings.setValue(SETTING_TIMECODE_ON, shown);
+
+ mControls->enabled = shown;
+ emit timecodeUpdated();
+}
+
+void TimeCodeControlWidget::setTimecodeTimerKind(TimecodeKind kind)
+{
+ QSettings settings(PENCIL2D, PENCIL2D);
+ settings.setValue(SETTING_TIMECODE_KIND, timecodeKindToInt(kind));
+ settings.remove(SETTING_TIMECODE_TEXT);
+ mControls->kind = kind;
+
+ emit timecodeUpdated();
+}
diff --git a/app/src/timecodecontrolwidget.h b/app/src/timecodecontrolwidget.h
new file mode 100644
index 0000000000..670f845e67
--- /dev/null
+++ b/app/src/timecodecontrolwidget.h
@@ -0,0 +1,66 @@
+/*
+
+Pencil2D - Traditional Animation Software
+Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
+Copyright (C) 2012-2020 Matthew Chiawen Chang
+
+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; version 2 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.
+
+*/
+#ifndef TIMECODECONTROLWIDGET_H
+#define TIMECODECONTROLWIDGET_H
+
+#include
+#include "pencildef.h"
+
+struct TimeCodeControls {
+ bool enabled = false;
+ bool showFrames = false;
+
+ TimecodeKind kind = TimecodeKind::NONE;
+
+ TimecodeKind timecodeKindFromInt(int value) const
+ {
+ switch (value)
+ {
+ case 0:
+ return TimecodeKind::NONE;
+ case 1:
+ return TimecodeKind::SMPTE;
+ case 2:
+ return TimecodeKind::SFF;
+ default:
+ return TimecodeKind::NONE;
+ }
+ }
+};
+
+class TimeCodeControlWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit TimeCodeControlWidget(TimeCodeControls* controls, QWidget* parent = nullptr);
+
+signals:
+ void timecodeUpdated();
+
+private:
+
+ int timecodeKindToInt(TimecodeKind kind) const;
+
+ void setTimecodeTimerKind(TimecodeKind kind);
+ void showFrames(bool shown);
+ void showTimecode(bool shown);
+
+ TimeCodeControls* mControls = nullptr;
+};
+
+#endif // TIMECODECONTROLWIDGET_H
diff --git a/app/src/timecontrols.cpp b/app/src/timecontrols.cpp
index 2dc7748f15..a38bff1eef 100644
--- a/app/src/timecontrols.cpp
+++ b/app/src/timecontrols.cpp
@@ -21,6 +21,8 @@ GNU General Public License for more details.
#include
#include
#include
+#include
+#include
#include "editor.h"
#include "playbackmanager.h"
#include "layermanager.h"
@@ -30,7 +32,9 @@ GNU General Public License for more details.
#include "timeline.h"
#include "pencildef.h"
-TimeControls::TimeControls(TimeLine* parent) : QToolBar(parent)
+#include
+
+TimeControls::TimeControls(TimeLine* parent) : QWidget(parent)
{
mTimeline = parent;
}
@@ -39,8 +43,12 @@ void TimeControls::initUI()
{
QSettings settings(PENCIL2D, PENCIL2D);
+ QHBoxLayout* hBoxLayout = new QHBoxLayout();
+ hBoxLayout->setContentsMargins(0,0,0,0);
+
+ setLayout(hBoxLayout);
+
mFpsBox = new QSpinBox(this);
- mFpsBox->setFixedHeight(24);
mFpsBox->setValue(settings.value("Fps").toInt());
mFpsBox->setMinimum(1);
mFpsBox->setMaximum(90);
@@ -49,43 +57,26 @@ void TimeControls::initUI()
mFpsBox->setFocusPolicy(Qt::WheelFocus);
mFps = mFpsBox->value();
- mTimecodeSelect = new QToolButton(this);
-
- QMenu* timeSelectMenu = new QMenu(tr("Display timecode", "Timeline menu for choose a timecode"), this);
- mTimecodeSelect->setIcon(QIcon(":/icons/themes/playful/misc/more-options.svg"));
-
- timeSelectMenu->addAction(mNoTimecodeAction = new QAction(tr("No text"), this));
- timeSelectMenu->addAction(mOnlyFramesAction = new QAction(tr("Frames"), this));
- timeSelectMenu->addAction(mSmpteAction = new QAction(tr("SMPTE Timecode"), this));
- timeSelectMenu->addAction(mSffAction = new QAction(tr("SFF Timecode"), this));
- mTimecodeSelect->setMenu(timeSelectMenu);
- mTimecodeSelect->setPopupMode(QToolButton::InstantPopup);
- mTimecodeSelect->setStyleSheet("::menu-indicator{ image: none; }");
- mTimecodeLabelEnum = mEditor->preference()->getInt(SETTING::TIMECODE_TEXT);
+
+ mTimecodeButton = new QToolButton(this);
+ mTimecodeButton->setIconSize(QSize(22,22));
+ mTimecodeButton->setIcon(QIcon(":/icons/themes/playful/controls/control-timecode.svg"));
+
mTimecodeLabel = new QLabel(this);
+ QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+ // The default mono font is smaller, so we restore the font here
+ font.setPointSize(mTimecodeLabel->font().pointSize());
+ mTimecodeLabel->setFont(font);
mTimecodeLabel->setContentsMargins(2, 0, 0, 0);
- mTimecodeLabel->setText("");
+ mTimecodeLabel->setAlignment(Qt::AlignTrailing | Qt::AlignVCenter);
+ mTimecodeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+ mTimecodeLabel->setToolTip(tr("Shows the current time code"));
- switch (mTimecodeLabelEnum)
- {
- case NOTEXT:
- mTimecodeLabel->setToolTip("");
- break;
- case FRAMES:
- mTimecodeLabel->setToolTip(tr("Actual frame number"));
- break;
- case SMPTE:
- mTimecodeLabel->setToolTip(tr("Timecode format MM:SS:FF"));
- break;
- case SFF:
- mTimecodeLabel->setToolTip(tr("Timecode format S:FF"));
- break;
- default:
- mTimecodeLabel->setToolTip("");
- }
+ mTimecodeControls.enabled = mEditor->preference()->isOn(SETTING::TIMECODE_ON);
+ mTimecodeControls.kind = mTimecodeControls.timecodeKindFromInt(mEditor->preference()->getInt(SETTING::TIMECODE_KIND));
+ mTimecodeControls.showFrames = mEditor->preference()->isOn(SETTING::TIMECODE_FRAMES_ON);
mLoopStartSpinBox = new QSpinBox(this);
- mLoopStartSpinBox->setFixedHeight(24);
mLoopStartSpinBox->setValue(settings.value("loopStart").toInt());
mLoopStartSpinBox->setMinimum(1);
mLoopStartSpinBox->setEnabled(false);
@@ -93,7 +84,6 @@ void TimeControls::initUI()
mLoopStartSpinBox->setFocusPolicy(Qt::WheelFocus);
mLoopEndSpinBox = new QSpinBox(this);
- mLoopEndSpinBox->setFixedHeight(24);
mLoopEndSpinBox->setValue(settings.value("loopEnd").toInt());
mLoopEndSpinBox->setMinimum(2);
mLoopEndSpinBox->setEnabled(false);
@@ -101,20 +91,19 @@ void TimeControls::initUI()
mLoopEndSpinBox->setFocusPolicy(Qt::WheelFocus);
mPlaybackRangeCheckBox = new QCheckBox(tr("Range"));
- mPlaybackRangeCheckBox->setFixedHeight(24);
mPlaybackRangeCheckBox->setToolTip(tr("Playback range"));
- mPlayButton = new QPushButton(this);
+ mPlayButton = new QToolButton(this);
mPlayButton->setIconSize(QSize(22,22));
- mLoopButton = new QPushButton(this);
+ mLoopButton = new QToolButton(this);
mLoopButton->setIconSize(QSize(22,22));
- mSoundButton = new QPushButton(this);
+ mSoundButton = new QToolButton(this);
mSoundButton->setIconSize(QSize(22,22));
- mSoundScrubButton = new QPushButton(this);
+ mSoundScrubButton = new QToolButton(this);
mSoundScrubButton->setIconSize(QSize(22,22));
- mJumpToEndButton = new QPushButton(this);
+ mJumpToEndButton = new QToolButton(this);
mJumpToEndButton->setIconSize(QSize(22,22));
- mJumpToStartButton = new QPushButton(this);
+ mJumpToStartButton = new QToolButton(this);
mJumpToStartButton->setIconSize(QSize(22,22));
mLoopIcon = QIcon(":icons/themes/playful/controls/control-loop.svg");
@@ -144,25 +133,32 @@ void TimeControls::initUI()
mSoundScrubButton->setCheckable(true);
mSoundScrubButton->setChecked(mEditor->preference()->isOn(SETTING::SOUND_SCRUB_ACTIVE));
-
- addWidget(mJumpToStartButton);
- addWidget(mPlayButton);
- addWidget(mJumpToEndButton);
- addWidget(mLoopButton);
- addWidget(mFpsBox);
- addWidget(mPlaybackRangeCheckBox);
- addWidget(mLoopStartSpinBox);
- addWidget(mLoopEndSpinBox);
- addWidget(mSoundButton);
- addWidget(mSoundScrubButton);
- addWidget(mTimecodeSelect);
- mTimecodeLabelAction = addWidget(mTimecodeLabel);
+ layout()->addItem(new QSpacerItem(1,1, QSizePolicy::Expanding));
+ layout()->addWidget(mTimecodeLabel);
+ layout()->addWidget(mTimecodeButton);
+ layout()->addWidget(mJumpToStartButton);
+ layout()->addWidget(mPlayButton);
+ layout()->addWidget(mJumpToEndButton);
+ layout()->addWidget(mLoopButton);
+
+ layout()->addWidget(mFpsBox);
+ layout()->addWidget(mPlaybackRangeCheckBox);
+ layout()->addWidget(mLoopStartSpinBox);
+ layout()->addWidget(mLoopEndSpinBox);
+ layout()->addWidget(mSoundButton);
+ layout()->addWidget(mSoundScrubButton);
+ layout()->addItem(new QSpacerItem(1,1, QSizePolicy::Expanding));
makeConnections();
updateUI();
}
+void TimeControls::updateTimecode()
+{
+ updateTimecodeLabel(mEditor->currentFrame());
+}
+
void TimeControls::updateUI()
{
PlaybackManager* playback = mEditor->playback();
@@ -180,6 +176,8 @@ void TimeControls::updateUI()
QSignalBlocker b4(mLoopButton);
mLoopButton->setChecked(playback->isLooping());
+
+ updateTimecode();
}
void TimeControls::setEditor(Editor* editor)
@@ -188,6 +186,42 @@ void TimeControls::setEditor(Editor* editor)
mEditor = editor;
}
+void TimeControls::updateTimecodeLabel(int frame)
+{
+ mTimecodeLabel->setVisible(mTimecodeControls.enabled);
+
+ if (mTimecodeControls.enabled) {
+ const bool showFrames = mTimecodeControls.showFrames;
+ const QString frameSuffix = showFrames
+ ? QString(" | %1").arg(QString::number(frame).rightJustified(4, '0'))
+ : QString();
+
+ QString timecode;
+ switch (mTimecodeControls.kind)
+ {
+ case TimecodeKind::SMPTE: {
+ timecode = QString("%1:%2:%3")
+ .arg(frame / (60 * mFps) % 60, 2, 10, QLatin1Char('0'))
+ .arg(frame / mFps % 60, 2, 10, QLatin1Char('0'))
+ .arg(frame % mFps, 2, 10, QLatin1Char('0'));
+ mTimecodeLabel->setText(timecode + frameSuffix);
+ break;
+ }
+ case TimecodeKind::SFF: {
+ timecode = QString("%1:%2")
+ .arg(frame / mFps)
+ .arg(frame % mFps, 2, 10, QLatin1Char('0'));
+ mTimecodeLabel->setText(timecode + frameSuffix);
+ break;
+ }
+ default:
+ timecode = showFrames ? QString::number(frame).rightJustified(4, '0') : QString();
+ mTimecodeLabel->setText(timecode);
+ break;
+ }
+ }
+}
+
void TimeControls::setFps(int value)
{
QSignalBlocker blocker(mFpsBox);
@@ -234,10 +268,20 @@ void TimeControls::makeConnections()
connect(mFpsBox, spinBoxValueChanged, this, &TimeControls::setFps);
connect(mEditor, &Editor::fpsChanged, this, &TimeControls::setFps);
- connect(mNoTimecodeAction, &QAction::triggered, this, &TimeControls::noTimecodeText);
- connect(mOnlyFramesAction, &QAction::triggered, this, &TimeControls::onlyFramesText);
- connect(mSmpteAction, &QAction::triggered, this, &TimeControls::smpteText);
- connect(mSffAction, &QAction::triggered, this, &TimeControls::sffText);
+
+ connect(mTimecodeButton, &QToolButton::clicked, this, &TimeControls::showTimecodePanel);
+}
+
+void TimeControls::showTimecodePanel()
+{
+ mTimeCodeWidget = new TimeCodeControlWidget(&mTimecodeControls, this);
+ mTimeCodeWidget->setAttribute(Qt::WA_DeleteOnClose);
+ mTimeCodeWidget->show();
+ mTimeCodeWidget->move(QCursor::pos());
+
+ connect(mTimeCodeWidget, &TimeCodeControlWidget::timecodeUpdated, this, [this] {
+ updateTimecode();
+ });
}
void TimeControls::playButtonClicked()
@@ -319,42 +363,6 @@ void TimeControls::updateSoundScrubIcon(bool soundScrubEnabled)
mEditor->preference()->set(SETTING::SOUND_SCRUB_ACTIVE, soundScrubEnabled);
}
-void TimeControls::noTimecodeText()
-{
- QSettings settings(PENCIL2D, PENCIL2D);
- settings.setValue(SETTING_TIMECODE_TEXT, NOTEXT);
- mTimecodeLabelEnum = NOTEXT;
- mTimecodeLabel->setToolTip(tr(""));
- updateTimecodeLabel(mEditor->currentFrame());
-}
-
-void TimeControls::onlyFramesText()
-{
- QSettings settings(PENCIL2D, PENCIL2D);
- settings.setValue(SETTING_TIMECODE_TEXT, FRAMES);
- mTimecodeLabelEnum = FRAMES;
- mTimecodeLabel->setToolTip(tr("Actual frame number"));
- updateTimecodeLabel(mEditor->currentFrame());
-}
-
-void TimeControls::sffText()
-{
- QSettings settings(PENCIL2D, PENCIL2D);
- settings.setValue(SETTING_TIMECODE_TEXT, SFF);
- mTimecodeLabelEnum = SFF;
- mTimecodeLabel->setToolTip(tr("Timecode format S:FF"));
- updateTimecodeLabel(mEditor->currentFrame());
-}
-
-void TimeControls::smpteText()
-{
- QSettings settings(PENCIL2D, PENCIL2D);
- settings.setValue(SETTING_TIMECODE_TEXT, SMPTE);
- mTimecodeLabelEnum = SMPTE;
- mTimecodeLabel->setToolTip(tr("Timecode format MM:SS:FF"));
- updateTimecodeLabel(mEditor->currentFrame());
-}
-
void TimeControls::onFpsEditingFinished()
{
mFpsBox->clearFocus();
@@ -362,33 +370,6 @@ void TimeControls::onFpsEditingFinished()
mFps = mFpsBox->value();
}
-void TimeControls::updateTimecodeLabel(int frame)
-{
- mTimecodeLabelAction->setVisible(true);
-
- switch (mTimecodeLabelEnum)
- {
- case TimecodeTextLevel::SMPTE:
- mTimecodeLabel->setText(QString("%1:%2:%3")
- .arg(frame / (60 * mFps) % 60, 2, 10, QLatin1Char('0'))
- .arg(frame / mFps % 60, 2, 10, QLatin1Char('0'))
- .arg(frame % mFps, 2, 10, QLatin1Char('0')));
- break;
- case TimecodeTextLevel::SFF:
- mTimecodeLabel->setText(QString("%1:%2")
- .arg(frame / mFps)
- .arg(frame % mFps, 2, 10, QLatin1Char('0')));
- break;
- case TimecodeTextLevel::FRAMES:
- mTimecodeLabel->setText(QString::number(frame).rightJustified(4, '0'));
- break;
- case TimecodeTextLevel::NOTEXT:
- default:
- mTimecodeLabelAction->setVisible(false);
- break;
- }
-
-}
void TimeControls::updateLength(int frameLength)
{
diff --git a/app/src/timecontrols.h b/app/src/timecontrols.h
index d2901085c9..a612587e3d 100644
--- a/app/src/timecontrols.h
+++ b/app/src/timecontrols.h
@@ -25,11 +25,15 @@ GNU General Public License for more details.
#include
#include
+#include "pencildef.h"
+
+#include "timecodecontrolwidget.h"
+
class Editor;
class PreferenceManager;
class TimeLine;
-class TimeControls : public QToolBar
+class TimeControls : public QWidget
{
Q_OBJECT
@@ -60,8 +64,14 @@ public slots:
void updateTimecodeLabel(int frame);
private:
+ void showTimecodePanel();
+ void updateTimecode();
+
+ void showFramesInTimecode(bool shown);
+ void showTimecode(bool shown);
void makeConnections();
+ void setupTimeCodeMenu();
void playButtonClicked();
void jumpToStartButtonClicked();
void jumpToEndButtonClicked();
@@ -71,29 +81,23 @@ public slots:
void loopEndValueChanged(int);
void updateSoundScrubIcon(bool soundScrubEnabled);
- void noTimecodeText();
- void onlyFramesText();
- void sffText();
- void smpteText();
-
private:
- QPushButton* mPlayButton = nullptr;
- QPushButton* mJumpToEndButton = nullptr;
- QPushButton* mJumpToStartButton = nullptr;
- QPushButton* mLoopButton = nullptr;
- QPushButton* mSoundButton = nullptr;
- QPushButton* mSoundScrubButton = nullptr;
+ QToolButton* mPlayButton = nullptr;
+ QToolButton* mJumpToEndButton = nullptr;
+ QToolButton* mJumpToStartButton = nullptr;
+ QToolButton* mLoopButton = nullptr;
+ QToolButton* mSoundButton = nullptr;
+ QToolButton* mSoundScrubButton = nullptr;
QSpinBox* mFpsBox = nullptr;
QCheckBox* mPlaybackRangeCheckBox = nullptr;
QSpinBox* mLoopStartSpinBox = nullptr;
QSpinBox* mLoopEndSpinBox = nullptr;
- QToolButton* mTimecodeSelect = nullptr;
+
+ QToolButton* mTimecodeButton = nullptr;
QLabel* mTimecodeLabel = nullptr;
- QAction* mNoTimecodeAction = nullptr;
- QAction* mOnlyFramesAction = nullptr;
- QAction* mSmpteAction = nullptr;
- QAction* mSffAction = nullptr;
- QAction* mTimecodeLabelAction = nullptr;
+
+ TimeCodeControls mTimecodeControls;
+ TimeCodeControlWidget* mTimeCodeWidget = nullptr;
QIcon mStartIcon;
QIcon mStopIcon;
@@ -106,7 +110,6 @@ public slots:
TimeLine* mTimeline = nullptr;
Editor* mEditor = nullptr;
int mFps = 12;
- int mTimecodeLabelEnum;
};
#endif
diff --git a/app/src/timeline.cpp b/app/src/timeline.cpp
index 92a5544e9c..1acc9c325d 100644
--- a/app/src/timeline.cpp
+++ b/app/src/timeline.cpp
@@ -156,15 +156,17 @@ void TimeLine::initUI()
// --------- Time controls ---------
mTimeControls = new TimeControls(this);
- mTimeControls->setIconSize(QSize(22,22));
+ // Needs to be slightly larger than the titlebar to prevent the icons from becoming smaller.
+ mTimeControls->setFixedHeight(this->titleBarWidget()->height() + 1);
mTimeControls->setEditor(editor());
mTimeControls->initUI();
updateLength();
+ this->setWidgetInTitleBarArea(mTimeControls);
+
QHBoxLayout* rightToolBarLayout = new QHBoxLayout();
rightToolBarLayout->addWidget(timelineButtons);
rightToolBarLayout->setAlignment(Qt::AlignLeft);
- rightToolBarLayout->addWidget(mTimeControls);
rightToolBarLayout->setContentsMargins(0, 0, 0, 0);
rightToolBarLayout->setSpacing(0);
rightToolBar->setLayout(rightToolBarLayout);
diff --git a/app/src/titlebarwidget.cpp b/app/src/titlebarwidget.cpp
index d7aabb95da..b2ad1feeb1 100644
--- a/app/src/titlebarwidget.cpp
+++ b/app/src/titlebarwidget.cpp
@@ -33,12 +33,15 @@ TitleBarWidget::TitleBarWidget(QWidget* parent)
: QWidget(parent)
{
- QVBoxLayout* vLayout = new QVBoxLayout();
+ QHBoxLayout* vLayout = new QHBoxLayout();
- vLayout->setContentsMargins(3,4,3,4);
+ vLayout->setContentsMargins(2,0,2,0);
vLayout->setSpacing(0);
- vLayout->addWidget(createCustomTitleBarWidget(this));
+ QWidget* contentWidget = createCustomTitleBarWidget(this);
+ vLayout->addWidget(contentWidget);
+
+ contentWidget->setMinimumHeight(28);
setLayout(vLayout);
}
@@ -52,7 +55,7 @@ QWidget* TitleBarWidget::createCustomTitleBarWidget(QWidget* parent)
bool isDarkmode = PlatformHandler::isDarkMode();
QWidget* containerWidget = new QWidget(parent);
- QHBoxLayout* containerLayout = new QHBoxLayout(parent);
+ mContainerLayout = new QHBoxLayout(parent);
mCloseButton = new QToolButton(parent);
@@ -104,25 +107,34 @@ QWidget* TitleBarWidget::createCustomTitleBarWidget(QWidget* parent)
mTitleLabel->setAlignment(Qt::AlignVCenter);
#ifdef __APPLE__
- containerLayout->addWidget(mCloseButton);
- containerLayout->addWidget(mDockButton);
- containerLayout->addWidget(mTitleLabel);
+ mContainerLayout->addWidget(mCloseButton);
+ mContainerLayout->addWidget(mDockButton);
+ mContainerLayout->addWidget(mTitleLabel);
#else
- containerLayout->addWidget(mTitleLabel);
- containerLayout->addWidget(mDockButton);
- containerLayout->addWidget(mCloseButton);
+ mContainerLayout->addWidget(mTitleLabel);
+ mContainerLayout->addWidget(mDockButton);
+ mContainerLayout->addWidget(mCloseButton);
#endif
- containerLayout->setSpacing(3);
- containerLayout->setContentsMargins(0,0,0,0);
+ mContainerLayout->setSpacing(3);
+ mContainerLayout->setContentsMargins(0,0,0,0);
- containerWidget->setLayout(containerLayout);
+ containerWidget->setLayout(mContainerLayout);
containerWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
containerWidget->setMinimumSize(QSize(1,1));
return containerWidget;
}
+void TitleBarWidget::setChildWidget(QWidget* widget)
+{
+ if (mHasChildWidget) {
+ mContainerLayout->removeWidget(widget);
+ }
+ mContainerLayout->addWidget(widget);
+ mHasChildWidget = true;
+}
+
QString TitleBarWidget::flatButtonStylesheet() const
{
return "QToolButton { border: 0; }";
@@ -133,6 +145,16 @@ void TitleBarWidget::setTitle(const QString &title)
mTitleLabel->setText(title);
}
+void TitleBarWidget::lock(bool locked)
+{
+ if (locked) {
+ hideButtons(true);
+ } else {
+ hideButtonsIfNeeded(this->width());
+ }
+ mIsLocked = locked;
+}
+
void TitleBarWidget::hideButtons(bool hide)
{
mCloseButton->setHidden(hide);
@@ -150,7 +172,7 @@ void TitleBarWidget::hideButtonsIfNeeded(int width)
{
if (width <= mWidthOfFullLayout) {
hideButtons(true);
- } else {
+ } else if (!mIsLocked) {
hideButtons(false);
}
}
diff --git a/app/src/titlebarwidget.h b/app/src/titlebarwidget.h
index 70f1482725..4130d67277 100644
--- a/app/src/titlebarwidget.h
+++ b/app/src/titlebarwidget.h
@@ -23,6 +23,8 @@ GNU General Public License for more details.
class QLabel;
class QToolButton;
+class QToolBar;
+class QHBoxLayout;
class TitleBarWidget : public QWidget
{
@@ -37,14 +39,23 @@ class TitleBarWidget : public QWidget
void setIsFloating(bool floating) { mIsFloating = floating; }
+ /// Add a child widget next to the bar buttons
+ void setChildWidget(QWidget* widget);
+
+ /// Locking the title area hides the title bar buttons
+ void lock(bool locked);
+
+ /// Returns true if a custom child widget has been added, otherwise false
+ bool hasChildWidget() const { return mHasChildWidget; }
+
signals:
void closeButtonPressed();
void undockButtonPressed();
private:
+ void hideButtons(bool hide);
QString flatButtonStylesheet() const;
void showEvent(QShowEvent* event) override;
- void hideButtons(bool hide);
void hideButtonsIfNeeded(int width);
QWidget* createCustomTitleBarWidget(QWidget* parent);
@@ -53,7 +64,11 @@ class TitleBarWidget : public QWidget
QToolButton* mCloseButton = nullptr;
QToolButton* mDockButton = nullptr;
+ QHBoxLayout* mContainerLayout = nullptr;
+
+ bool mIsLocked = false;
bool mIsFloating = false;
+ bool mHasChildWidget = false;
int mWidthOfFullLayout = 0;
};
diff --git a/core_lib/src/managers/preferencemanager.cpp b/core_lib/src/managers/preferencemanager.cpp
index 8cb247aa63..08bc9b2413 100644
--- a/core_lib/src/managers/preferencemanager.cpp
+++ b/core_lib/src/managers/preferencemanager.cpp
@@ -98,7 +98,9 @@ void PreferenceManager::loadPrefs()
set(SETTING::FPS, settings.value(SETTING_FPS, 12).toInt());
set(SETTING::FIELD_W, settings.value(SETTING_FIELD_W, 800).toInt());
set(SETTING::FIELD_H, settings.value(SETTING_FIELD_H, 600).toInt());
- set(SETTING::TIMECODE_TEXT, settings.value(SETTING_TIMECODE_TEXT, 1).toInt());
+ set(SETTING::TIMECODE_ON, settings.value(SETTING_TIMECODE_ON, true).toBool());
+ set(SETTING::TIMECODE_FRAMES_ON, settings.value(SETTING_TIMECODE_FRAMES_ON, true).toBool());
+ set(SETTING::TIMECODE_KIND, settings.value(SETTING_TIMECODE_KIND, static_cast(TimecodeKind::SMPTE)).toInt());
// Files
set(SETTING::AUTO_SAVE, settings.value(SETTING_AUTO_SAVE, false).toBool());
@@ -298,8 +300,8 @@ void PreferenceManager::set(SETTING option, int value)
case SETTING::GRID_SIZE_W:
settings.setValue(SETTING_GRID_SIZE_W, value);
break;
- case SETTING::TIMECODE_TEXT:
- settings.setValue(SETTING_TIMECODE_TEXT, value);
+ case SETTING::TIMECODE_KIND:
+ settings.setValue(SETTING_TIMECODE_KIND, value);
break;
case SETTING::GRID_SIZE_H:
settings.setValue(SETTING_GRID_SIZE_H, value);
@@ -471,6 +473,12 @@ void PreferenceManager::set(SETTING option, bool value)
case SETTING::NEW_UNDO_REDO_SYSTEM_ON:
settings.setValue(SETTING_NEW_UNDO_REDO_ON, value);
break;
+ case SETTING::TIMECODE_ON:
+ settings.setValue(SETTING_TIMECODE_ON, value);
+ break;
+ case SETTING::TIMECODE_FRAMES_ON:
+ settings.setValue(SETTING_TIMECODE_FRAMES_ON, value);
+ break;
default:
Q_ASSERT(false);
break;
diff --git a/core_lib/src/util/pencildef.h b/core_lib/src/util/pencildef.h
index 00efcb73fd..9e907625d1 100644
--- a/core_lib/src/util/pencildef.h
+++ b/core_lib/src/util/pencildef.h
@@ -72,10 +72,9 @@ enum StabilizationLevel
STRONG
};
-enum TimecodeTextLevel
+enum class TimecodeKind
{
- NOTEXT,
- FRAMES, // FF
+ NONE,
SMPTE, // HH:MM:SS:FF
SFF // S:FF
};
@@ -288,7 +287,12 @@ const static int MaxFramesBound = 9999;
#define SETTING_ACTION_SAFE_ON "ActionSafeOn"
#define SETTING_ACTION_SAFE "ActionSafe"
#define SETTING_OVERLAY_SAFE_HELPER_TEXT_ON "OverlaySafeHelperTextOn"
-#define SETTING_TIMECODE_TEXT "TimecodeText"
+
+#define SETTING_TIMECODE_TEXT "TimecodeText"
+
+#define SETTING_TIMECODE_ON "TimecodeEnabled"
+#define SETTING_TIMECODE_KIND "TimecodeKind"
+#define SETTING_TIMECODE_FRAMES_ON "TimecodeFramesEnabled"
#define SETTING_ONION_MAX_OPACITY "OnionMaxOpacity"
#define SETTING_ONION_MIN_OPACITY "OnionMinOpacity"
diff --git a/core_lib/src/util/preferencesdef.h b/core_lib/src/util/preferencesdef.h
index 66683c2e5a..d60177b56d 100644
--- a/core_lib/src/util/preferencesdef.h
+++ b/core_lib/src/util/preferencesdef.h
@@ -73,7 +73,9 @@ enum class SETTING
OVERLAY_SAFE_HELPER_TEXT_ON,
ACTION_SAFE_ON,
ACTION_SAFE,
- TIMECODE_TEXT,
+ TIMECODE_ON,
+ TIMECODE_KIND,
+ TIMECODE_FRAMES_ON,
TITLE_SAFE_ON,
TITLE_SAFE,
NEW_UNDO_REDO_SYSTEM_ON,