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

initial implementation of a time remap widget (not working yet)

parent c9ca7536
Pipeline #66817 failed with stage
in 7 minutes and 32 seconds
......@@ -642,7 +642,11 @@ void KeyframeView::paintEvent(QPaintEvent *event)
QStylePainter p(this);
int maxWidth = width() - 2 * m_offset;
m_scale = maxWidth / double(m_duration - 1);
if (m_duration > 1) {
m_scale = maxWidth / double(m_duration - 1);
} else {
m_scale = maxWidth;
}
int headOffset = m_lineHeight / 2;
int offset = pCore->getItemIn(m_model->getOwnerId());
m_zoomStart = m_zoomHandle.x() * maxWidth;
......
......@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "clipcreator.hpp"
#include "core.h"
#include "dialogs/clipcreationdialog.h"
#include "dialogs/timeremap.h"
#include "doc/documentchecker.h"
#include "doc/docundostack.hpp"
#include "doc/kdenlivedoc.h"
......@@ -2020,6 +2021,8 @@ void Bin::selectProxyModel(const QModelIndex &id)
showClipProperties(clip, false);
m_deleteAction->setText(i18n("Delete Clip"));
m_proxyAction->setText(i18n("Proxy Clip"));
//TODO: testing only, we should check clip type...
pCore->timeRemapWidget()->setClip(clip);
} else if (currentItem->itemType() == AbstractProjectItem::FolderItem) {
// A folder was selected, disable editing clip
m_tagsWidget->setTagData();
......
......@@ -31,6 +31,7 @@ the Free Software Foundation, either version 3 of the License, or
#include "timeline2/view/timelinewidget.h"
#include "dialogs/subtitleedit.h"
#include "dialogs/textbasededit.h"
#include "dialogs/timeremap.h"
#include <mlt++/MltRepository.h>
#include <KMessageBox>
......@@ -135,6 +136,7 @@ void Core::initGUI(bool isAppImage, const QString &MltPath, const QUrl &Url, con
m_subtitleWidget = new SubtitleEdit(m_mainWindow);
m_mixerWidget = new MixerManager(m_mainWindow);
m_textEditWidget = new TextBasedEdit(m_mainWindow);
m_timeRemapWidget = new TimeRemap(m_mainWindow);
connect(m_library, SIGNAL(addProjectClips(QList<QUrl>)), m_binWidget, SLOT(droppedUrls(QList<QUrl>)));
connect(this, &Core::updateLibraryPath, m_library, &LibraryWidget::slotUpdateLibraryPath);
connect(m_capture.get(), &MediaCapture::recordStateChanged, m_mixerWidget, &MixerManager::recordStateChanged);
......@@ -316,6 +318,11 @@ TextBasedEdit *Core::textEditWidget()
return m_textEditWidget;
}
TimeRemap *Core::timeRemapWidget()
{
return m_timeRemapWidget;
}
SubtitleEdit *Core::subtitleWidget()
{
return m_subtitleWidget;
......
......@@ -42,6 +42,7 @@ class ProjectManager;
class SubtitleEdit;
class SubtitleModel;
class TextBasedEdit;
class TimeRemap;
namespace Mlt {
class Repository;
......@@ -122,6 +123,8 @@ public:
SubtitleEdit *subtitleWidget();
/** @brief Returns a pointer to the text based editing widget. */
TextBasedEdit *textEditWidget();
/** @brief Returns a pointer to the time remapping widget. */
TimeRemap *timeRemapWidget();
/** @brief Returns a pointer to the audio mixer. */
MixerManager *mixer();
......@@ -264,6 +267,7 @@ private:
LibraryWidget *m_library{nullptr};
SubtitleEdit *m_subtitleWidget{nullptr};
TextBasedEdit *m_textEditWidget{nullptr};
TimeRemap *m_timeRemapWidget{nullptr};
MixerManager *m_mixerWidget{nullptr};
/** @brief Current project's profile path */
QString m_currentProfile;
......
......@@ -9,6 +9,7 @@ set(kdenlive_SRCS
dialogs/speechdialog.cpp
dialogs/subtitleedit.cpp
dialogs/textbasededit.cpp
dialogs/timeremap.cpp
dialogs/titletemplatedialog.cpp
dialogs/wizard.cpp
dialogs/splash.cpp
......
/***************************************************************************
* Copyright (C) 2021 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* *
* 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; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "timeremap.h"
#include "core.h"
#include "doc/kthumb.h"
#include "kdenlivesettings.h"
#include "bin/projectclip.h"
#include "project/projectmanager.h"
#include "kdenlive_debug.h"
#include <QFontDatabase>
#include <QWheelEvent>
#include <QStylePainter>
#include <KColorScheme>
#include "klocalizedstring.h"
RemapView::RemapView(QWidget *parent)
: QWidget(parent)
, m_duration(1)
, m_zoomFactor(1)
, m_zoomStart(0)
{
setMouseTracking(true);
setMinimumSize(QSize(150, 60));
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
int size = QFontInfo(font()).pixelSize() * 3;
m_lineHeight = int(size / 2.1);
setFixedHeight(size * 2);
setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed));
}
void RemapView::setDuration(int duration)
{
m_duration = duration;
update();
}
void RemapView::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPalette pal = palette();
KColorScheme scheme(pal.currentColorGroup(), KColorScheme::Window);
m_colSelected = palette().highlight().color();
m_colKeyframe = scheme.foreground(KColorScheme::NormalText).color();
QStylePainter p(this);
int maxWidth = width() - 2;
m_scale = maxWidth / double(qMax(1, m_duration - 1));
int headOffset = m_lineHeight / 2;
/*m_zoomStart = m_zoomHandle.x() * maxWidth;
m_zoomFactor = maxWidth / (m_zoomHandle.y() * maxWidth - m_zoomStart);
int zoomEnd = qCeil(m_zoomHandle.y() * maxWidth);*/
/* ticks */
double fps = pCore->getCurrentFps();
int displayedLength = int(m_duration / m_zoomFactor / fps);
double factor = 1;
if (displayedLength < 2) {
// 1 frame tick
} else if (displayedLength < 30 ) {
// 1 sec tick
factor = fps;
} else if (displayedLength < 150) {
// 5 sec tick
factor = 5 * fps;
} else if (displayedLength < 300) {
// 10 sec tick
factor = 10 * fps;
} else if (displayedLength < 900) {
// 30 sec tick
factor = 30 * fps;
} else if (displayedLength < 1800) {
// 1 min. tick
factor = 60 * fps;
} else if (displayedLength < 9000) {
// 5 min tick
factor = 300 * fps;
} else if (displayedLength < 18000) {
// 10 min tick
factor = 600 * fps;
} else {
// 30 min tick
factor = 1800 * fps;
}
// Position of left border in frames
double tickOffset = m_zoomStart * m_zoomFactor;
double frameSize = factor * m_scale * m_zoomFactor;
int base = int(tickOffset / frameSize);
tickOffset = frameSize - (tickOffset - (base * frameSize));
// Draw frame ticks
int scaledTick = 0;
for (int i = 0; i < maxWidth / frameSize; i++) {
scaledTick = int((i * frameSize) + tickOffset);
if (scaledTick >= maxWidth) {
break;
}
p.drawLine(QPointF(scaledTick , m_lineHeight + 1), QPointF(scaledTick, m_lineHeight - 3));
}
p.setPen(palette().dark().color());
/*
* Time-"line"
*/
p.setPen(m_colKeyframe);
p.drawLine(0, m_lineHeight, width(), m_lineHeight);
p.drawLine(0, m_lineHeight - headOffset / 2, 0, m_lineHeight + headOffset / 2);
p.drawLine(width(), m_lineHeight - headOffset / 2, width(), m_lineHeight + headOffset / 2);
/*
* current position cursor
*/
// Zoom bar
/*p.setPen(Qt::NoPen);
p.setBrush(palette().mid());
p.drawRoundedRect(0, m_zoomHeight + 3, width() - 2 * 0, m_size - m_zoomHeight - 3, m_lineHeight / 5, m_lineHeight / 5);
p.setBrush(palette().highlight());
p.drawRoundedRect(int((width()) * m_zoomHandle.x()),
m_zoomHeight + 3,
int((width()) * (m_zoomHandle.y() - m_zoomHandle.x())),
m_size - m_zoomHeight - 3,
m_lineHeight / 5, m_lineHeight / 5);
*/
}
TimeRemap::TimeRemap(QWidget *parent)
: QWidget(parent)
, m_clip(nullptr)
{
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
setupUi(this);
m_in = new TimecodeDisplay(pCore->timecode(), this);
inLayout->addWidget(m_in);
m_out = new TimecodeDisplay(pCore->timecode(), this);
outLayout->addWidget(m_out);
m_view = new RemapView(this);
remapLayout->addWidget(m_view);
}
void TimeRemap::setClip(std::shared_ptr<ProjectClip> clip, int in, int out)
{
m_clip = clip;
if (m_clip != nullptr) {
int min = in == -1 ? 0 : in;
int max = out == -1 ? m_clip->getFramePlaytime() : out;
m_in->setRange(min, max);
m_out->setRange(min, max);
m_view->setDuration(max - min);
setEnabled(true);
} else {
setEnabled(false);
}
}
TimeRemap::~TimeRemap()
{
//delete m_previewTimer;
}
/***************************************************************************
* Copyright (C) 2021 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* *
* 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; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#ifndef TIMEREMAP_H
#define TIMEREMAP_H
#include "ui_timeremap_ui.h"
#include "definitions.h"
#include "timecode.h"
#include "timecodedisplay.h"
#include <QWidget>
class ProjectClip;
/**
* @class RemapView
* @brief A widget to view remap keyframes.
* @author Jean-Baptiste Mardelle
*/
class RemapView : public QWidget
{
public:
explicit RemapView(QWidget *parent = nullptr);
void setDuration(int duration);
protected:
void paintEvent(QPaintEvent *event) override;
private:
int m_duration;
double m_scale;
QColor m_colSelected;
QColor m_colKeyframe;
int m_lineHeight;
double m_zoomFactor;
double m_zoomStart;
};
/**
* @class TimeRemap
* @brief A dialog for editing time remap effect.
* @author Jean-Baptiste Mardelle
*/
class TimeRemap : public QWidget, public Ui::TimeRemap_UI
{
Q_OBJECT
public:
explicit TimeRemap(QWidget *parent = nullptr);
~TimeRemap() override;
void setClip(std::shared_ptr<ProjectClip> clip, int in = -1, int out = -1);
private:
std::shared_ptr<ProjectClip> m_clip;
TimecodeDisplay *m_in;
TimecodeDisplay *m_out;
RemapView *m_view;
};
#endif
......@@ -74,6 +74,7 @@
#include "widgets/progressbutton.h"
#include <config-kdenlive.h>
#include "dialogs/textbasededit.h"
#include "dialogs/timeremap.h"
#include "project/dialogs/temporarydata.h"
#ifdef USE_JOGSHUTTLE
......@@ -269,6 +270,7 @@ void MainWindow::init(const QString &mltPath)
QDockWidget *libraryDock = addDock(i18n("Library"), QStringLiteral("library"), pCore->library());
QDockWidget *subtitlesDock = addDock(i18n("Subtitles"), QStringLiteral("Subtitles"), pCore->subtitleWidget());
QDockWidget *textEditingDock = addDock(i18n("Text Edit"), QStringLiteral("textedit"), pCore->textEditWidget());
QDockWidget *timeRemapDock = addDock(i18n("Time Remapping"), QStringLiteral("timeremap"), pCore->timeRemapWidget());
m_clipMonitor = new Monitor(Kdenlive::ClipMonitor, pCore->monitorManager(), this);
pCore->bin()->setMonitor(m_clipMonitor);
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TimeRemap_UI</class>
<widget class="QWidget" name="TimeRemap_UI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>375</width>
<height>140</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="8">
<layout class="QVBoxLayout" name="remapLayout"/>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>39</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Source time</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="inLayout"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Output time</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QToolButton" name="toolButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="go-previous"/>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="outLayout"/>
</item>
<item row="1" column="4">
<widget class="QToolButton" name="toolButton_2">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="go-next"/>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>28</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="5">
<widget class="QToolButton" name="button_add">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-add"/>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QToolButton" name="button_remove">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove"/>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
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