ported seekablewidget to timebasedview
Cuts down on a lot of code duplication and opens up usage of the new TimelineViewSelectionManager framework
This commit is contained in:
+2
-11
@@ -80,18 +80,9 @@ NodeGraph *Node::parent() const
|
||||
return static_cast<NodeGraph*>(QObject::parent());
|
||||
}
|
||||
|
||||
Project* Node::project() const
|
||||
Project *Node::project() const
|
||||
{
|
||||
QObject *t = this->parent();
|
||||
|
||||
while (t) {
|
||||
if (Project *p = dynamic_cast<Project*>(t)) {
|
||||
return p;
|
||||
}
|
||||
t = t->parent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return Project::GetProjectFromObject(this);
|
||||
}
|
||||
|
||||
QString Node::ShortName() const
|
||||
|
||||
@@ -169,6 +169,20 @@ void Project::RegenerateUuid()
|
||||
uuid_ = QUuid::createUuid();
|
||||
}
|
||||
|
||||
Project *Project::GetProjectFromObject(const QObject *o)
|
||||
{
|
||||
QObject *t = o->parent();
|
||||
|
||||
while (t) {
|
||||
if (Project *p = dynamic_cast<Project*>(t)) {
|
||||
return p;
|
||||
}
|
||||
t = t->parent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Project::ColorManagerValueChanged(const NodeInput &input, const TimeRange &range)
|
||||
{
|
||||
Q_UNUSED(input)
|
||||
|
||||
@@ -109,6 +109,14 @@ public:
|
||||
saved_url_ = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find project parent from object
|
||||
*
|
||||
* If an object is expected to be a child of a project, this function will traverse its parent
|
||||
* tree until it finds it.
|
||||
*/
|
||||
static Project *GetProjectFromObject(const QObject *o);
|
||||
|
||||
signals:
|
||||
void NameChanged();
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "serializer210528.h"
|
||||
|
||||
#include "config/config.h"
|
||||
#include "node/factory.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -604,7 +605,7 @@ void ProjectSerializer210528::LoadMarkerList(QXmlStreamReader *reader, TimelineM
|
||||
}
|
||||
}
|
||||
|
||||
markers->AddMarker(TimeRange(in, out), name);
|
||||
new TimelineMarker(Config::Current()[QStringLiteral("MarkerColor")].toInt(), TimeRange(in, out), name, markers);
|
||||
}
|
||||
|
||||
reader->skipCurrentElement();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "serializer210907.h"
|
||||
|
||||
#include "config/config.h"
|
||||
#include "node/factory.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -596,7 +597,7 @@ void ProjectSerializer210907::LoadMarkerList(QXmlStreamReader *reader, TimelineM
|
||||
}
|
||||
}
|
||||
|
||||
markers->AddMarker(TimeRange(in, out), name);
|
||||
new TimelineMarker(Config::Current()[QStringLiteral("MarkerColor")].toInt(), TimeRange(in, out), name, markers);
|
||||
}
|
||||
|
||||
reader->skipCurrentElement();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "serializer211228.h"
|
||||
|
||||
#include "config/config.h"
|
||||
#include "node/factory.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -646,7 +647,7 @@ void ProjectSerializer211228::LoadMarkerList(QXmlStreamReader *reader, TimelineM
|
||||
}
|
||||
}
|
||||
|
||||
markers->AddMarker(TimeRange(in, out), name);
|
||||
new TimelineMarker(Config::Current()[QStringLiteral("MarkerColor")].toInt(), TimeRange(in, out), name, markers);
|
||||
}
|
||||
|
||||
reader->skipCurrentElement();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "serializer220403.h"
|
||||
|
||||
#include "config/config.h"
|
||||
#include "node/factory.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -1001,7 +1002,7 @@ void ProjectSerializer220403::LoadMarkerList(QXmlStreamReader *reader, TimelineM
|
||||
}
|
||||
}
|
||||
|
||||
markers->AddMarker(TimeRange(in, out), name);
|
||||
new TimelineMarker(Config::Current()[QStringLiteral("MarkerColor")].toInt(), TimeRange(in, out), name, markers);
|
||||
}
|
||||
|
||||
reader->skipCurrentElement();
|
||||
|
||||
+128
-75
@@ -23,21 +23,15 @@
|
||||
#include "common/xmlutils.h"
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "widget/marker/markerundo.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
TimelineMarker::TimelineMarker(const TimeRange &time, const QString &name, QObject *parent) :
|
||||
TimelineMarker::TimelineMarker(int color, const TimeRange &time, const QString &name, QObject *parent) :
|
||||
QObject(parent),
|
||||
time_(time),
|
||||
name_(name)
|
||||
name_(name),
|
||||
color_(color)
|
||||
{
|
||||
color_ = Config::Current()[QStringLiteral("MarkerColor")].toInt();
|
||||
}
|
||||
|
||||
const TimeRange &TimelineMarker::time() const
|
||||
{
|
||||
return time_;
|
||||
}
|
||||
|
||||
void TimelineMarker::set_time(const TimeRange &time)
|
||||
@@ -46,35 +40,12 @@ void TimelineMarker::set_time(const TimeRange &time)
|
||||
emit TimeChanged(time_);
|
||||
}
|
||||
|
||||
void TimelineMarker::set_time_undo(TimeRange time) {
|
||||
UndoCommand *command = new MarkerChangeTimeCommand(Core::instance()->GetActiveProject(), this, time);
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
const QString &TimelineMarker::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
void TimelineMarker::set_name(const QString &name)
|
||||
{
|
||||
name_ = name;
|
||||
emit NameChanged(name_);
|
||||
}
|
||||
|
||||
void TimelineMarker::set_name_undo(QString name)
|
||||
{
|
||||
UndoCommand *command = new MarkerChangeNameCommand(Core::instance()->GetActiveProject(), this, name);
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
int TimelineMarker::color()
|
||||
{
|
||||
return color_;
|
||||
}
|
||||
|
||||
void TimelineMarker::set_color(int c)
|
||||
{
|
||||
color_ = c;
|
||||
@@ -82,51 +53,133 @@ void TimelineMarker::set_color(int c)
|
||||
emit ColorChanged(color_);
|
||||
}
|
||||
|
||||
bool TimelineMarker::active()
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
void TimelineMarker::set_active(bool active)
|
||||
{
|
||||
active_ = active;
|
||||
|
||||
emit ActiveChanged(active_);
|
||||
}
|
||||
|
||||
TimelineMarkerList::~TimelineMarkerList()
|
||||
{
|
||||
qDeleteAll(markers_);
|
||||
}
|
||||
|
||||
TimelineMarker* TimelineMarkerList::AddMarker(const TimeRange &time, const QString &name, int color)
|
||||
{
|
||||
TimelineMarker* m = new TimelineMarker(time, name);
|
||||
if (color >= 0) {
|
||||
m->set_color(color);
|
||||
}
|
||||
markers_.append(m);
|
||||
emit MarkerAdded(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
void TimelineMarkerList::RemoveMarker(TimelineMarker *marker)
|
||||
{
|
||||
for (int i=0;i<markers_.size();i++) {
|
||||
TimelineMarker* m = markers_.at(i);
|
||||
|
||||
if (m == marker) {
|
||||
markers_.removeAt(i);
|
||||
emit MarkerRemoved(m);
|
||||
delete m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QList<TimelineMarker*> &TimelineMarkerList::list() const
|
||||
const std::vector<TimelineMarker*> &TimelineMarkerList::list() const
|
||||
{
|
||||
return markers_;
|
||||
}
|
||||
|
||||
void TimelineMarkerList::childEvent(QChildEvent *e)
|
||||
{
|
||||
QObject::childEvent(e);
|
||||
|
||||
if (TimelineMarker *marker = dynamic_cast<TimelineMarker *>(e->child())) {
|
||||
if (e->type() == QChildEvent::ChildAdded) {
|
||||
markers_.push_back(marker);
|
||||
} else if (e->type() == QChildEvent::ChildRemoved) {
|
||||
auto it = std::find(markers_.begin(), markers_.end(), marker);
|
||||
if (it != markers_.end()) {
|
||||
markers_.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MarkerAddCommand::MarkerAddCommand(TimelineMarkerList *marker_list, const TimeRange &range, const QString &name, int color) :
|
||||
marker_list_(marker_list)
|
||||
{
|
||||
added_marker_ = new TimelineMarker(color, range, name, &memory_manager_);
|
||||
}
|
||||
|
||||
Project* MarkerAddCommand::GetRelevantProject() const
|
||||
{
|
||||
return Project::GetProjectFromObject(marker_list_);
|
||||
}
|
||||
|
||||
void MarkerAddCommand::redo()
|
||||
{
|
||||
added_marker_->setParent(marker_list_);
|
||||
}
|
||||
|
||||
void MarkerAddCommand::undo()
|
||||
{
|
||||
added_marker_->setParent(&memory_manager_);
|
||||
}
|
||||
|
||||
MarkerRemoveCommand::MarkerRemoveCommand(TimelineMarker *marker) :
|
||||
marker_(marker)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerRemoveCommand::GetRelevantProject() const
|
||||
{
|
||||
return Project::GetProjectFromObject(marker_list_);
|
||||
}
|
||||
|
||||
void MarkerRemoveCommand::redo()
|
||||
{
|
||||
marker_list_ = marker_->parent();
|
||||
marker_->setParent(&memory_manager_);
|
||||
}
|
||||
|
||||
void MarkerRemoveCommand::undo()
|
||||
{
|
||||
marker_->setParent(marker_list_);
|
||||
}
|
||||
|
||||
MarkerChangeColorCommand::MarkerChangeColorCommand(TimelineMarker *marker, int new_color) :
|
||||
marker_(marker),
|
||||
new_color_(new_color)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerChangeColorCommand::GetRelevantProject() const
|
||||
{
|
||||
return Project::GetProjectFromObject(marker_);
|
||||
}
|
||||
|
||||
void MarkerChangeColorCommand::redo()
|
||||
{
|
||||
old_color_ = marker_->color();
|
||||
marker_->set_color(new_color_);
|
||||
}
|
||||
|
||||
void MarkerChangeColorCommand::undo()
|
||||
{
|
||||
marker_->set_color(old_color_);
|
||||
}
|
||||
|
||||
MarkerChangeNameCommand::MarkerChangeNameCommand(TimelineMarker *marker, QString new_name) :
|
||||
marker_(marker),
|
||||
new_name_(new_name)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerChangeNameCommand::GetRelevantProject() const
|
||||
{
|
||||
return Project::GetProjectFromObject(marker_);
|
||||
}
|
||||
|
||||
void MarkerChangeNameCommand::redo()
|
||||
{
|
||||
old_name_ = marker_->name();
|
||||
marker_->set_name(new_name_);
|
||||
}
|
||||
|
||||
void MarkerChangeNameCommand::undo()
|
||||
{
|
||||
marker_->set_name(old_name_);
|
||||
}
|
||||
|
||||
MarkerChangeTimeCommand::MarkerChangeTimeCommand(TimelineMarker* marker, TimeRange time) :
|
||||
marker_(marker),
|
||||
new_time_(time)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerChangeTimeCommand::GetRelevantProject() const
|
||||
{
|
||||
return Project::GetProjectFromObject(marker_);
|
||||
}
|
||||
|
||||
void MarkerChangeTimeCommand::redo()
|
||||
{
|
||||
old_time_ = marker_->time();
|
||||
marker_->set_time(new_time_);
|
||||
}
|
||||
|
||||
void MarkerChangeTimeCommand::undo()
|
||||
{
|
||||
marker_->set_time(old_time_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+106
-26
@@ -26,6 +26,7 @@
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include "common/timerange.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -33,26 +34,17 @@ class TimelineMarker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TimelineMarker(const TimeRange& time = TimeRange(), const QString& name = QString(), QObject* parent = nullptr);
|
||||
TimelineMarker(int color, const TimeRange& time, const QString& name = QString(), QObject* parent = nullptr);
|
||||
|
||||
const TimeRange &time() const;
|
||||
const TimeRange &time() const { return time_; }
|
||||
void set_time(const TimeRange& time);
|
||||
|
||||
const QString& name() const;
|
||||
const QString& name() const { return name_; }
|
||||
void set_name(const QString& name);
|
||||
|
||||
int color();
|
||||
int color() const { return color_; }
|
||||
void set_color(int c);
|
||||
|
||||
bool active();
|
||||
void set_active(bool active);
|
||||
|
||||
void Load(QXmlStreamReader* reader);
|
||||
|
||||
public slots:
|
||||
void set_name_undo(QString name);
|
||||
void set_time_undo(TimeRange time);
|
||||
|
||||
signals:
|
||||
void TimeChanged(const TimeRange& time);
|
||||
|
||||
@@ -60,8 +52,6 @@ signals:
|
||||
|
||||
void ColorChanged(int c);
|
||||
|
||||
void ActiveChanged(bool active);
|
||||
|
||||
private:
|
||||
TimeRange time_;
|
||||
|
||||
@@ -69,31 +59,121 @@ private:
|
||||
|
||||
int color_;
|
||||
|
||||
bool active_;
|
||||
|
||||
};
|
||||
|
||||
class TimelineMarkerList : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TimelineMarkerList() = default;
|
||||
TimelineMarkerList(QObject *parent = nullptr) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~TimelineMarkerList() override;
|
||||
|
||||
TimelineMarker* AddMarker(const TimeRange& time = TimeRange(), const QString& name = QString(), int color = -1);
|
||||
|
||||
void RemoveMarker(TimelineMarker* marker);
|
||||
|
||||
const QList<TimelineMarker *> &list() const;
|
||||
const std::vector<TimelineMarker *> &list() const;
|
||||
|
||||
signals:
|
||||
void MarkerAdded(TimelineMarker* marker);
|
||||
|
||||
void MarkerRemoved(TimelineMarker* marker);
|
||||
|
||||
protected:
|
||||
virtual void childEvent(QChildEvent *e) override;
|
||||
|
||||
private:
|
||||
QList<TimelineMarker*> markers_;
|
||||
std::vector<TimelineMarker*> markers_;
|
||||
|
||||
};
|
||||
|
||||
class MarkerAddCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerAddCommand(TimelineMarkerList* marker_list, const TimeRange& range, const QString& name, int color);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
TimelineMarkerList* marker_list_;
|
||||
TimeRange range_;
|
||||
QString name_;
|
||||
int color_;
|
||||
|
||||
TimelineMarker* added_marker_;
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
class MarkerRemoveCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerRemoveCommand(TimelineMarker* marker);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
TimelineMarker* marker_;
|
||||
QObject* marker_list_;
|
||||
TimeRange range_;
|
||||
QString name_;
|
||||
int color_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
class MarkerChangeColorCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerChangeColorCommand(TimelineMarker* marker, int new_color);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
TimelineMarker* marker_;
|
||||
int old_color_;
|
||||
int new_color_;
|
||||
|
||||
};
|
||||
|
||||
class MarkerChangeNameCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerChangeNameCommand(TimelineMarker* marker, QString name);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
TimelineMarker* marker_;
|
||||
QString old_name_;
|
||||
QString new_name_;
|
||||
};
|
||||
|
||||
class MarkerChangeTimeCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerChangeTimeCommand(TimelineMarker* marker, TimeRange time);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
TimelineMarker* marker_;
|
||||
TimeRange old_time_;
|
||||
TimeRange new_time_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -24,24 +24,31 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
TimelinePoints::TimelinePoints(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
markers_ = new TimelineMarkerList(this);
|
||||
workarea_ = new TimelineWorkArea(this);
|
||||
}
|
||||
|
||||
TimelineMarkerList *TimelinePoints::markers()
|
||||
{
|
||||
return &markers_;
|
||||
return markers_;
|
||||
}
|
||||
|
||||
const TimelineMarkerList *TimelinePoints::markers() const
|
||||
{
|
||||
return &markers_;
|
||||
return markers_;
|
||||
}
|
||||
|
||||
const TimelineWorkArea *TimelinePoints::workarea() const
|
||||
{
|
||||
return &workarea_;
|
||||
return workarea_;
|
||||
}
|
||||
|
||||
TimelineWorkArea *TimelinePoints::workarea()
|
||||
{
|
||||
return &workarea_;
|
||||
return workarea_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,10 +29,11 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TimelinePoints
|
||||
class TimelinePoints : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TimelinePoints() = default;
|
||||
TimelinePoints(QObject *parent = nullptr);
|
||||
|
||||
TimelineMarkerList* markers();
|
||||
const TimelineMarkerList* markers() const;
|
||||
@@ -41,9 +42,9 @@ public:
|
||||
const TimelineWorkArea* workarea() const;
|
||||
|
||||
private:
|
||||
TimelineMarkerList markers_;
|
||||
TimelineMarkerList *markers_;
|
||||
|
||||
TimelineWorkArea workarea_;
|
||||
TimelineWorkArea *workarea_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ add_subdirectory(focusablelineedit)
|
||||
add_subdirectory(handmovableview)
|
||||
add_subdirectory(keyframeview)
|
||||
add_subdirectory(manageddisplay)
|
||||
add_subdirectory(marker)
|
||||
add_subdirectory(menu)
|
||||
add_subdirectory(nodecombobox)
|
||||
add_subdirectory(nodeparamview)
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2021 Olive Team
|
||||
#
|
||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/marker/marker.h
|
||||
widget/marker/marker.cpp
|
||||
widget/marker/markercopypaste.h
|
||||
widget/marker/markercopypaste.cpp
|
||||
widget/marker/markerundo.h
|
||||
widget/marker/markerundo.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -1,263 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "marker.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QPainter>
|
||||
|
||||
#include "config/config.h"
|
||||
#include "common/qtutils.h"
|
||||
#include "panel/panelmanager.h"
|
||||
#include "panel/timeline/timeline.h"
|
||||
#include "ui/colorcoding.h"
|
||||
#include "widget/menu/menu.h"
|
||||
#include "widget/menu/menushared.h"
|
||||
#include "widget/timeruler/seekablewidget.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
Marker::Marker(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
active_(false),
|
||||
drag_allowed_(false),
|
||||
dragging_(false)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
|
||||
QFontMetrics fm = fontMetrics();
|
||||
marker_height_ = fm.height();
|
||||
marker_width_ = QtUtils::QFontMetricsWidth(fm, "H");
|
||||
resize(marker_width_, marker_height_);
|
||||
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
connect(this, &Marker::customContextMenuRequested, this, &Marker::ShowContextMenu);
|
||||
}
|
||||
|
||||
void Marker::SetActive(bool active)
|
||||
{
|
||||
active_ = active;
|
||||
|
||||
// Generaly the same functions delete both markers and timeline blocks. This helps ensure that
|
||||
// markers and timeline blocks can never be selected at the same time
|
||||
if (active) {
|
||||
TimelinePanel *timeline = PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
if (timeline) {
|
||||
timeline->timeline_widget()->DeselectAll();
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
bool Marker::active()
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
void Marker::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QFontMetrics fm = fontMetrics();
|
||||
|
||||
int y = marker_height_;
|
||||
|
||||
int half_width = marker_width_ / 2;
|
||||
|
||||
int x = half_width;
|
||||
|
||||
QPainter p(this);
|
||||
if (active_) {
|
||||
p.setPen(Qt::white);
|
||||
} else {
|
||||
p.setPen(Qt::black);
|
||||
}
|
||||
|
||||
QColor color = ColorCoding::GetColor(marker_color_).toQColor();
|
||||
p.setBrush(color);
|
||||
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
int half_marker_height = marker_height_ / 3;
|
||||
|
||||
QPoint points[] = {
|
||||
QPoint(x, y),
|
||||
QPoint(x - half_width, y - half_marker_height),
|
||||
QPoint(x - half_width, y - marker_height_),
|
||||
QPoint(x + 1 + half_width, y - marker_height_),
|
||||
QPoint(x + 1 + half_width, y - half_marker_height),
|
||||
QPoint(x + 1, y),
|
||||
};
|
||||
|
||||
p.drawPolygon(points, 6);
|
||||
|
||||
if (!name_.isEmpty()) {
|
||||
resize(marker_width_ + fm.horizontalAdvance(name_) + fm.horizontalAdvance(" "), marker_height_);
|
||||
|
||||
// Draw background rectangle
|
||||
color.setAlphaF(0.5);
|
||||
p.fillRect(x, y, fm.horizontalAdvance(name_) + fm.horizontalAdvance(" ") * 2 + half_width, -marker_height_, color);
|
||||
|
||||
// Draw text
|
||||
p.drawText(x + marker_width_, y - half_marker_height, name_);
|
||||
} else {
|
||||
resize(marker_width_, marker_height_);
|
||||
}
|
||||
|
||||
// In case this is a clip marker, redraw the timeline to update the clip marker
|
||||
TimelinePanel* timeline = PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
if (timeline) {
|
||||
timeline->timeline_widget()->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void Marker::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
// Only select if clicking on the icon and not the label
|
||||
if (e->pos().x() > marker_width_) {
|
||||
return;
|
||||
}
|
||||
if (e->button() == Qt::LeftButton || e->button() == Qt::RightButton) {
|
||||
SeekableParent()->SeekToScreenPoint(this->x() + 4);
|
||||
if (!active_) {
|
||||
if (e->modifiers() != Qt::ShiftModifier) {
|
||||
SeekableParent()->DeselectAllMarkers();
|
||||
}
|
||||
emit ActiveChanged(true);
|
||||
} else {
|
||||
if (e->modifiers() == Qt::ShiftModifier) {
|
||||
emit ActiveChanged(false);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
click_position_ = e->globalPos();
|
||||
marker_start_x_ = x();
|
||||
drag_allowed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Marker::mouseMoveEvent(QMouseEvent* e)
|
||||
{
|
||||
if (drag_allowed_) {
|
||||
dragging_ = true;
|
||||
|
||||
int new_position = marker_start_x_ + e->globalPos().x() - click_position_.x();
|
||||
|
||||
rational marker_time = SeekableParent()->ScreenToTime(new_position);
|
||||
|
||||
if (SeekableParent()->GetSnapService()) {
|
||||
if (Core::instance()->snapping()) {
|
||||
rational movement;
|
||||
SeekableParent()->GetSnapService()->SnapPoint({marker_time}, &movement);
|
||||
if (!movement.isNull()) {
|
||||
marker_time += movement;
|
||||
}
|
||||
|
||||
new_position = SeekableParent()->TimeToScene(marker_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_position > -marker_width_ / 2 && new_position < SeekableParent()->width() - marker_width_ / 2) {
|
||||
this->move(new_position-2, this->pos().y());
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Marker::mouseReleaseEvent(QMouseEvent* e)
|
||||
{
|
||||
if (dragging_) {
|
||||
rational time = SeekableParent()->SceneToTime(this->x() + 4);
|
||||
time = time < 0.0 ? 0.0 : time;
|
||||
emit TimeChanged(TimeRange(time, time));
|
||||
|
||||
dragging_ = false;
|
||||
}
|
||||
|
||||
drag_allowed_ = false;
|
||||
}
|
||||
|
||||
SeekableWidget* Marker::SeekableParent()
|
||||
{
|
||||
return dynamic_cast<SeekableWidget *>(parent());
|
||||
}
|
||||
|
||||
void Marker::ShowContextMenu()
|
||||
{
|
||||
// Only show context menu if we clicked on the icon and not the label
|
||||
QRect marker_icon(0, 0, marker_width_, marker_height_);
|
||||
if (!marker_icon.contains(this->mapFromGlobal(QCursor::pos()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Menu m(this);
|
||||
|
||||
// Color menu
|
||||
ColorLabelMenu color_coding_menu;
|
||||
connect(&color_coding_menu, &ColorLabelMenu::ColorSelected, this, &Marker::ColorChanged);
|
||||
m.addMenu(&color_coding_menu);
|
||||
|
||||
m.addSeparator();
|
||||
MenuShared::instance()->AddItemsForEditMenu(&m, false);
|
||||
|
||||
m.addSeparator();
|
||||
QAction rename;
|
||||
rename.setText(tr("Rename"));
|
||||
m.addAction(&rename);
|
||||
connect(&rename, &QAction::triggered, this, &Marker::Rename);
|
||||
|
||||
m.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void Marker::Rename()
|
||||
{
|
||||
bool ok;
|
||||
QString marker_name = QInputDialog::getText(this, tr("Set Marker"), tr("Marker name:"), QLineEdit::Normal, name_, &ok);
|
||||
if (ok) {
|
||||
emit NameChanged(marker_name);
|
||||
}
|
||||
}
|
||||
|
||||
void Marker::SetColor(int c)
|
||||
{
|
||||
marker_color_ = c;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void Marker::SetName(QString s)
|
||||
{
|
||||
name_ = s;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void Marker::SetTime(TimeRange time)
|
||||
{
|
||||
move(SeekableParent()->TimeToScene(time.in())-2, y());
|
||||
}
|
||||
|
||||
} // namespace olive
|
||||
@@ -1,92 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef MARKER_H
|
||||
#define MARKER_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "common/timerange.h"
|
||||
#include "widget/colorlabelmenu/colorlabelmenu.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SeekableWidget;
|
||||
|
||||
class Marker : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Marker(QWidget* parent = nullptr);
|
||||
|
||||
bool active();
|
||||
|
||||
void Rename();
|
||||
|
||||
SeekableWidget* SeekableParent();
|
||||
|
||||
public slots:
|
||||
void SetColor(int c);
|
||||
void SetActive(bool active);
|
||||
void SetName(QString s);
|
||||
void SetTime(TimeRange t);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent* event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
|
||||
signals:
|
||||
void ColorChanged(int c);
|
||||
void markerSelected(Marker* marker);
|
||||
void ActiveChanged(bool active);
|
||||
void NameChanged(QString name);
|
||||
void TimeChanged(TimeRange time);
|
||||
|
||||
private:
|
||||
|
||||
int marker_color_;
|
||||
|
||||
bool active_;
|
||||
|
||||
QString name_;
|
||||
|
||||
QPointF click_position_;
|
||||
|
||||
int marker_start_x_;
|
||||
|
||||
bool drag_allowed_;
|
||||
|
||||
bool dragging_;
|
||||
|
||||
int marker_height_;
|
||||
|
||||
int marker_width_;
|
||||
|
||||
private slots:
|
||||
void ShowContextMenu();
|
||||
};
|
||||
|
||||
} // namespace olive
|
||||
|
||||
#endif // MARKER_H
|
||||
@@ -1,136 +0,0 @@
|
||||
/***
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "markercopypaste.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "core.h"
|
||||
#include "markerundo.h"
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
void MarkerCopyPasteService::CopyMarkersToClipboard(const QVector<TimelineMarker*>& markers, void* userdata)
|
||||
{
|
||||
QString copy_str;
|
||||
|
||||
QXmlStreamWriter writer(©_str);
|
||||
writer.setAutoFormatting(true);
|
||||
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("olive"));
|
||||
|
||||
//writer.writeTextElement(QStringLiteral("version"), QString::number(Core::kProjectVersion));
|
||||
|
||||
writer.writeStartElement(QStringLiteral("markers"));
|
||||
|
||||
// Get earliest marker for offset
|
||||
rational min_start = RATIONAL_MAX;
|
||||
foreach (TimelineMarker* marker, markers) {
|
||||
if (marker->time().in() < min_start) {
|
||||
min_start = marker->time().in();
|
||||
}
|
||||
}
|
||||
|
||||
foreach(TimelineMarker * marker, markers) {
|
||||
// Cache marker in/out points
|
||||
rational in = marker->time().in();
|
||||
rational out = marker->time().out();
|
||||
|
||||
// Temporarily set in/out to be relative to the earliest selected marker
|
||||
marker->set_time(TimeRange(in - min_start, marker->time().out() - min_start));
|
||||
//marker->Save(&writer);
|
||||
|
||||
// Reset in/out
|
||||
marker->set_time(TimeRange(in, out));
|
||||
}
|
||||
|
||||
|
||||
writer.writeEndElement(); // markers
|
||||
writer.writeEndElement(); // olive
|
||||
writer.writeEndDocument();
|
||||
|
||||
Core::CopyStringToClipboard(copy_str);
|
||||
}
|
||||
|
||||
void MarkerCopyPasteService::PasteMarkersFromClipboard(TimelineMarkerList* list, MultiUndoCommand* command,
|
||||
rational offset) {
|
||||
QString clipboard = Core::PasteStringFromClipboard();
|
||||
|
||||
if (clipboard.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QXmlStreamReader reader(clipboard);
|
||||
uint data_version = 0;
|
||||
|
||||
while (XMLReadNextStartElement(&reader)) {
|
||||
if (reader.name() == QStringLiteral("olive")) {
|
||||
while (XMLReadNextStartElement(&reader)) {
|
||||
if (reader.name() == QStringLiteral("version")) {
|
||||
data_version = reader.readElementText().toUInt();
|
||||
} else if (reader.name() == QStringLiteral("markers")) {
|
||||
while (XMLReadNextStartElement(&reader)) {
|
||||
if (data_version == 0) {
|
||||
return;
|
||||
}
|
||||
QString name;
|
||||
int color = -1;
|
||||
rational in, out;
|
||||
|
||||
XMLAttributeLoop((&reader), attr) {
|
||||
if (attr.name() == QStringLiteral("name")) {
|
||||
name = attr.value().toString();
|
||||
}
|
||||
|
||||
if (attr.name() == QStringLiteral("color")) {
|
||||
color = attr.value().toInt();
|
||||
}
|
||||
|
||||
if (attr.name() == QStringLiteral("in")) {
|
||||
in = rational::fromString(attr.value().toString());
|
||||
}
|
||||
|
||||
if (attr.name() == QStringLiteral("out")) {
|
||||
out = rational::fromString(attr.value().toString());
|
||||
}
|
||||
}
|
||||
|
||||
command->add_child(new MarkerAddCommand(Core::instance()->GetActiveProject(),
|
||||
list,
|
||||
TimeRange(in + offset, out + offset),
|
||||
name,
|
||||
color));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.hasError()) {
|
||||
// If this was NOT an internal error, we assume it's an XML error that the user needs to know about
|
||||
QMessageBox::critical((QWidget*)Core::instance()->main_window(),
|
||||
QCoreApplication::translate("MarkerCopyPasteWidget", "Error pasting markers"),
|
||||
QCoreApplication::translate("MarkerCopyPasteWidget", "Failed to paste markers: %1").arg(reader.errorString()),
|
||||
QMessageBox::Ok);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
|
||||
}
|
||||
} //namespace olive
|
||||
@@ -1,42 +0,0 @@
|
||||
/***
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#ifndef MARKERCOPYPASTEWIDGET_H
|
||||
#define MARKERCOPYPASTEWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "widget/marker/marker.h"
|
||||
#include "node/project/serializer/serializer.h"
|
||||
#include "timeline/timelinemarker.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class MarkerCopyPasteService
|
||||
{
|
||||
public:
|
||||
MarkerCopyPasteService() = default;
|
||||
|
||||
protected:
|
||||
void CopyMarkersToClipboard(const QVector<TimelineMarker*> &markers, void* userdata = nullptr);
|
||||
|
||||
void PasteMarkersFromClipboard(TimelineMarkerList* list, MultiUndoCommand *command, rational offset);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MARKERCOPYPASTEWIDGET_H
|
||||
@@ -1,138 +0,0 @@
|
||||
/***
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "markerundo.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
MarkerAddCommand::MarkerAddCommand(Project *project, TimelineMarkerList *marker_list, const TimeRange &range, const QString &name, int color) :
|
||||
project_(project),
|
||||
marker_list_(marker_list),
|
||||
range_(range),
|
||||
name_(name),
|
||||
color_(color)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerAddCommand::GetRelevantProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
|
||||
void MarkerAddCommand::redo()
|
||||
{
|
||||
added_marker_ = marker_list_->AddMarker(range_, name_, color_);
|
||||
}
|
||||
|
||||
void MarkerAddCommand::undo()
|
||||
{
|
||||
marker_list_->RemoveMarker(added_marker_);
|
||||
}
|
||||
|
||||
MarkerRemoveCommand::MarkerRemoveCommand(Project *project, TimelineMarker *marker, TimelineMarkerList *marker_list) :
|
||||
project_(project),
|
||||
marker_(marker),
|
||||
marker_list_(marker_list),
|
||||
range_(marker->time()),
|
||||
name_(marker->name()),
|
||||
color_(marker->color())
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerRemoveCommand::GetRelevantProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
|
||||
void MarkerRemoveCommand::redo()
|
||||
{
|
||||
marker_list_->RemoveMarker(marker_);
|
||||
}
|
||||
|
||||
void MarkerRemoveCommand::undo()
|
||||
{
|
||||
marker_list_->AddMarker(range_, name_, color_);
|
||||
}
|
||||
|
||||
MarkerChangeColorCommand::MarkerChangeColorCommand(Project *project, TimelineMarker *marker, int new_color) :
|
||||
project_(project),
|
||||
marker_(marker),
|
||||
old_color_(marker->color()),
|
||||
new_color_(new_color)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerChangeColorCommand::GetRelevantProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
|
||||
void MarkerChangeColorCommand::redo()
|
||||
{
|
||||
marker_->set_color(new_color_);
|
||||
}
|
||||
|
||||
void MarkerChangeColorCommand::undo()
|
||||
{
|
||||
marker_->set_color(old_color_);
|
||||
}
|
||||
|
||||
MarkerChangeNameCommand::MarkerChangeNameCommand(Project *project, TimelineMarker *marker, QString new_name) :
|
||||
project_(project),
|
||||
marker_(marker),
|
||||
old_name_(marker->name()),
|
||||
new_name_(new_name)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerChangeNameCommand::GetRelevantProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
|
||||
void MarkerChangeNameCommand::redo()
|
||||
{
|
||||
marker_->set_name(new_name_);
|
||||
}
|
||||
|
||||
void MarkerChangeNameCommand::undo()
|
||||
{
|
||||
marker_->set_name(old_name_);
|
||||
}
|
||||
|
||||
MarkerChangeTimeCommand::MarkerChangeTimeCommand(Project* project, TimelineMarker* marker, TimeRange time) :
|
||||
project_(project),
|
||||
marker_(marker),
|
||||
old_time_(marker->time()),
|
||||
new_time_(time)
|
||||
{
|
||||
}
|
||||
|
||||
Project* MarkerChangeTimeCommand::GetRelevantProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
|
||||
void MarkerChangeTimeCommand::redo()
|
||||
{
|
||||
marker_->set_time(new_time_);
|
||||
}
|
||||
|
||||
void MarkerChangeTimeCommand::undo()
|
||||
{
|
||||
marker_->set_time(old_time_);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/***
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#ifndef MARKERUNDO_H
|
||||
#define MARKERUNDO_H
|
||||
|
||||
#include "undo/undocommand.h"
|
||||
#include "timeline/timelinemarker.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class MarkerAddCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerAddCommand(Project* project, TimelineMarkerList* marker_list, const TimeRange& range, const QString& name,
|
||||
int color = -1);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
TimelineMarkerList* marker_list_;
|
||||
TimeRange range_;
|
||||
QString name_;
|
||||
int color_;
|
||||
|
||||
TimelineMarker* added_marker_;
|
||||
};
|
||||
|
||||
class MarkerRemoveCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerRemoveCommand(Project* project, TimelineMarker* marker, TimelineMarkerList* marker_list);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
TimelineMarker* marker_;
|
||||
TimelineMarkerList* marker_list_;
|
||||
TimeRange range_;
|
||||
QString name_;
|
||||
int color_;
|
||||
};
|
||||
|
||||
class MarkerChangeColorCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerChangeColorCommand(Project* project, TimelineMarker* marker, int new_color);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
TimelineMarker* marker_;
|
||||
int old_color_;
|
||||
int new_color_;
|
||||
};
|
||||
|
||||
class MarkerChangeNameCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerChangeNameCommand(Project* project, TimelineMarker* marker, QString name);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
TimelineMarker* marker_;
|
||||
QString old_name_;
|
||||
QString new_name_;
|
||||
};
|
||||
|
||||
class MarkerChangeTimeCommand : public UndoCommand {
|
||||
public:
|
||||
MarkerChangeTimeCommand(Project* project, TimelineMarker* marker, TimeRange time);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
TimelineMarker* marker_;
|
||||
TimeRange old_time_;
|
||||
TimeRange new_time_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TIMELINEUNDOTRACK_H
|
||||
@@ -77,7 +77,7 @@ void ResizableTimelineScrollBar::paintEvent(QPaintEvent *event)
|
||||
|
||||
if (points_
|
||||
&& !timebase().isNull()
|
||||
&& (points_->workarea()->enabled() || !points_->markers()->list().isEmpty())) {
|
||||
&& (points_->workarea()->enabled() || !points_->markers()->list().empty())) {
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
@@ -110,7 +110,7 @@ void ResizableTimelineScrollBar::paintEvent(QPaintEvent *event)
|
||||
workarea_color);
|
||||
}
|
||||
|
||||
if (!points_->markers()->list().isEmpty()) {
|
||||
if (!points_->markers()->list().empty()) {
|
||||
foreach (TimelineMarker* marker, points_->markers()->list()) {
|
||||
QColor marker_color = ColorCoding::GetColor(marker->color()).toQColor();
|
||||
int64_t in = qRound64(ratio * TimeToScene(marker->time().in()));
|
||||
|
||||
@@ -43,6 +43,9 @@ public:
|
||||
return snapped_;
|
||||
}
|
||||
|
||||
const rational &GetTime() const { return playhead_; }
|
||||
|
||||
SnapService *GetSnapService() const { return snap_service_; }
|
||||
void SetSnapService(SnapService* service);
|
||||
|
||||
const double& GetYScale() const;
|
||||
@@ -85,11 +88,6 @@ protected:
|
||||
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier, const QPointF &cursor_pos) override;
|
||||
|
||||
const rational &GetPlayheadTime() const
|
||||
{
|
||||
return playhead_;
|
||||
}
|
||||
|
||||
bool PlayheadPress(QMouseEvent* event);
|
||||
bool PlayheadMove(QMouseEvent* event);
|
||||
bool PlayheadRelease(QMouseEvent* event);
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "node/project/sequence/sequence.h"
|
||||
#include "widget/marker/markerundo.h"
|
||||
#include "widget/timelinewidget/undo/timelineundoworkarea.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -40,7 +39,7 @@ TimeBasedWidget::TimeBasedWidget(bool ruler_text_visible, bool ruler_cache_statu
|
||||
auto_set_timebase_(true)
|
||||
{
|
||||
ruler_ = new TimeRuler(ruler_text_visible, ruler_cache_status_visible, this);
|
||||
connect(ruler_, &TimeRuler::TimeChanged, this, &TimeBasedWidget::SetTimeAndSignal);
|
||||
ConnectTimelineView(ruler_, true);
|
||||
|
||||
scrollbar_ = new ResizableTimelineScrollBar(Qt::Horizontal, this);
|
||||
connect(scrollbar_, &ResizableScrollBar::ResizeBegan, this, &TimeBasedWidget::ScrollBarResizeBegan);
|
||||
@@ -593,14 +592,25 @@ void TimeBasedWidget::SetMarker()
|
||||
QString marker_name;
|
||||
|
||||
if (Config::Current()[QStringLiteral("SetNameWithMarker")].toBool()) {
|
||||
marker_name = QInputDialog::getText(this, tr("Set Marker"), tr("Marker name:"), QLineEdit::Normal, QString(), &ok);
|
||||
marker_name = QInputDialog::getText(this, tr("Add Marker"), tr("Name:"), QLineEdit::Normal, QString(), &ok);
|
||||
} else {
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
Core::instance()->undo_stack()->push(new MarkerAddCommand(GetConnectedNode()->project(),
|
||||
GetConnectedNode()->GetTimelinePoints()->markers(), TimeRange(GetTime(), GetTime()), marker_name));
|
||||
int color;
|
||||
|
||||
TimelineMarkerList *markers = GetConnectedNode()->GetTimelinePoints()->markers();
|
||||
|
||||
if (!markers->list().empty()) {
|
||||
// Use last invoked color if applicable
|
||||
color = markers->list().back()->color();
|
||||
} else {
|
||||
// Fallback to default color in preferences
|
||||
color = Config::Current()[QStringLiteral("MarkerColor")].toInt();
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(new MarkerAddCommand(markers, TimeRange(GetTime(), GetTime()), marker_name, color));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -398,15 +398,6 @@ void TimelineWidget::DeselectAll()
|
||||
SignalDeselectedAllBlocks();
|
||||
}
|
||||
|
||||
bool TimelineWidget::MarkersActive()
|
||||
{
|
||||
if (ruler()->GetActiveTimelineMarkers().size() > 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::RippleToIn()
|
||||
{
|
||||
RippleTo(Timeline::kTrimIn);
|
||||
@@ -505,10 +496,11 @@ void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||
|
||||
void TimelineWidget::DeleteSelected(bool ripple)
|
||||
{
|
||||
if (MarkersActive()) {
|
||||
if (ruler()->hasFocus()) {
|
||||
ruler()->DeleteSelected();
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<Block*> selected_list = GetSelectedBlocks();
|
||||
QVector<Block*> blocks_to_delete;
|
||||
|
||||
@@ -641,11 +633,10 @@ void TimelineWidget::CopySelected(bool cut)
|
||||
return;
|
||||
}
|
||||
|
||||
if (MarkersActive()) {
|
||||
if (ruler()->hasFocus()) {
|
||||
ruler()->CopySelected(cut);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QVector<Block*> selected = GetSelectedBlocks();
|
||||
|
||||
|
||||
@@ -59,8 +59,6 @@ public:
|
||||
|
||||
void DeselectAll();
|
||||
|
||||
bool MarkersActive();
|
||||
|
||||
void RippleToIn();
|
||||
|
||||
void RippleToOut();
|
||||
|
||||
@@ -530,19 +530,19 @@ void TimelineView::DrawBlock(QPainter *painter, bool foreground, Block *block, q
|
||||
}
|
||||
|
||||
// Draw markers
|
||||
if (clip->connected_viewer() && !clip->connected_viewer()->GetLength().isNull()) {
|
||||
qDebug() << "MARKERS ON CLIP STUB";
|
||||
/*if (clip->connected_viewer() && !clip->connected_viewer()->GetLength().isNull()) {
|
||||
if (clip->connected_viewer()->GetTimelinePoints()->markers()->list().size() > 0) {
|
||||
QList<TimelineMarker *> marker_list = clip->connected_viewer()->GetTimelinePoints()->markers()->list();
|
||||
|
||||
std::vector<TimelineMarker *> marker_list = clip->connected_viewer()->GetTimelinePoints()->markers()->list();
|
||||
|
||||
int marker_width = QtUtils::QFontMetricsWidth(fm, "H");
|
||||
clip_marker_positions_.clear();
|
||||
|
||||
// Only draw markers if the block UI is large enough to draw all the markers
|
||||
if (marker_list.length() * marker_width < block_right - block_left) {
|
||||
if (marker_list.size() * marker_width < block_right - block_left) {
|
||||
|
||||
QListIterator<TimelineMarker*> iterator(marker_list);
|
||||
while(iterator.hasNext()) {
|
||||
TimelineMarker *marker = iterator.next();
|
||||
for (auto it=marker_list.cbegin(); it!=marker_list.cend(); it++) {
|
||||
TimelineMarker *marker = *it;
|
||||
// Make sure marker is within In/Out points of the clip
|
||||
if (marker->time().in() >= clip->media_in() && marker->time().out() <= clip->media_in() + clip->length()) {
|
||||
// Only draw names that we have room for
|
||||
@@ -561,7 +561,7 @@ void TimelineView::DrawBlock(QPainter *painter, bool foreground, Block *block, q
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// For transitions, show lines representing a transition
|
||||
|
||||
@@ -26,17 +26,17 @@
|
||||
|
||||
#include "common/qtutils.h"
|
||||
#include "core.h"
|
||||
#include "widget/marker/markerundo.h"
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
#define super TimeBasedView
|
||||
|
||||
SeekableWidget::SeekableWidget(QWidget* parent) :
|
||||
TimelineScaledWidget(parent),
|
||||
super(parent),
|
||||
timeline_points_(nullptr),
|
||||
scroll_(0),
|
||||
snap_service_(nullptr),
|
||||
dragging_(false)
|
||||
dragging_(false),
|
||||
selection_manager_(this)
|
||||
{
|
||||
QFontMetrics fm = fontMetrics();
|
||||
|
||||
@@ -46,19 +46,18 @@ SeekableWidget::SeekableWidget(QWidget* parent) :
|
||||
playhead_width_ = QtUtils::QFontMetricsWidth(fm, "H");
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
void SeekableWidget::ConnectTimelinePoints(TimelinePoints *points)
|
||||
{
|
||||
if (timeline_points_) {
|
||||
selection_manager_.ClearSelection();
|
||||
|
||||
disconnect(timeline_points_->workarea(), &TimelineWorkArea::RangeChanged, this, static_cast<void (SeekableWidget::*)()>(&SeekableWidget::update));
|
||||
disconnect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, static_cast<void (SeekableWidget::*)()>(&SeekableWidget::update));
|
||||
disconnect(timeline_points_->markers(), &TimelineMarkerList::MarkerAdded, this, static_cast<void (SeekableWidget::*)()>(&SeekableWidget::update));
|
||||
disconnect(timeline_points_->markers(), &TimelineMarkerList::MarkerRemoved, this, static_cast<void (SeekableWidget::*)()>(&SeekableWidget::update));
|
||||
|
||||
foreach(Marker* marker_widget, marker_map_.values()) {
|
||||
marker_widget->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
timeline_points_ = points;
|
||||
@@ -68,47 +67,26 @@ void SeekableWidget::ConnectTimelinePoints(TimelinePoints *points)
|
||||
connect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, static_cast<void (SeekableWidget::*)()>(&SeekableWidget::update));
|
||||
connect(timeline_points_->markers(), &TimelineMarkerList::MarkerAdded, this, static_cast<void (SeekableWidget::*)()>(&SeekableWidget::update));
|
||||
connect(timeline_points_->markers(), &TimelineMarkerList::MarkerRemoved, this, static_cast<void (SeekableWidget::*)()>(&SeekableWidget::update));
|
||||
|
||||
connect(timeline_points_->markers(), &TimelineMarkerList::MarkerAdded, this, &SeekableWidget::addMarker);
|
||||
connect(timeline_points_->markers(), &TimelineMarkerList::MarkerRemoved, this, &SeekableWidget::removeMarker);
|
||||
}
|
||||
|
||||
if (timeline_points() && !timeline_points()->markers()->list().isEmpty()) {
|
||||
foreach (TimelineMarker *marker, timeline_points()->markers()->list()) {
|
||||
if (!marker_map_.keys().contains(marker)) {
|
||||
addMarker(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateMarkerPositions();
|
||||
|
||||
update();
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void SeekableWidget::SetSnapService(SnapService *service)
|
||||
void SeekableWidget::DeleteSelected()
|
||||
{
|
||||
snap_service_ = service;
|
||||
}
|
||||
|
||||
void SeekableWidget::DeleteSelected() {
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
foreach (TimelineMarker *marker, GetActiveTimelineMarkers()) {
|
||||
command->add_child(new MarkerRemoveCommand(Core::instance()->GetActiveProject(), marker, timeline_points_->markers()));
|
||||
foreach (TimelineMarker *marker, selection_manager_.GetSelectedObjects()) {
|
||||
command->add_child(new MarkerRemoveCommand(marker));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
const int &SeekableWidget::GetScroll() const
|
||||
{
|
||||
return scroll_;
|
||||
}
|
||||
|
||||
void SeekableWidget::CopySelected(bool cut)
|
||||
{
|
||||
CopyMarkersToClipboard(GetActiveTimelineMarkers());
|
||||
qDebug() << "COPY IS STUB";
|
||||
//CopyMarkersToClipboard(selection_manager_.GetSelectedObjects());
|
||||
|
||||
if (cut) {
|
||||
DeleteSelected();
|
||||
@@ -117,14 +95,15 @@ void SeekableWidget::CopySelected(bool cut)
|
||||
|
||||
void SeekableWidget::PasteMarkers(bool insert, rational insert_time)
|
||||
{
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
PasteMarkersFromClipboard(timeline_points()->markers(), command, insert_time);
|
||||
//MultiUndoCommand *command = new MultiUndoCommand();
|
||||
//PasteMarkersFromClipboard(timeline_points()->markers(), command, insert_time);
|
||||
qDebug() << "PASTE IS STUB";
|
||||
}
|
||||
|
||||
void SeekableWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
SeekToScreenPoint(event->pos().x());
|
||||
SeekToScenePoint(mapToScene(event->pos()).x());
|
||||
dragging_ = true;
|
||||
|
||||
DeselectAllMarkers();
|
||||
@@ -134,7 +113,7 @@ void SeekableWidget::mousePressEvent(QMouseEvent *event)
|
||||
void SeekableWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
SeekToScreenPoint(event->pos().x());
|
||||
SeekToScenePoint(mapToScene(event->pos()).x());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,18 +121,19 @@ void SeekableWidget::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
if (snap_service_) {
|
||||
snap_service_->HideSnaps();
|
||||
if (GetSnapService()) {
|
||||
GetSnapService()->HideSnaps();
|
||||
}
|
||||
|
||||
dragging_ = false;
|
||||
}
|
||||
|
||||
void SeekableWidget::ScaleChangedEvent(const double &)
|
||||
void SeekableWidget::focusOutEvent(QFocusEvent *event)
|
||||
{
|
||||
updateMarkerPositions();
|
||||
super::focusOutEvent(event);
|
||||
|
||||
update();
|
||||
// Deselect everything when we lose focus
|
||||
DeselectAllMarkers();
|
||||
}
|
||||
|
||||
TimelinePoints *SeekableWidget::timeline_points() const
|
||||
@@ -161,131 +141,38 @@ TimelinePoints *SeekableWidget::timeline_points() const
|
||||
return timeline_points_;
|
||||
}
|
||||
|
||||
void SeekableWidget::SetTime(const rational &r)
|
||||
{
|
||||
time_ = r;
|
||||
|
||||
updateMarkerPositions();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void SeekableWidget::SetScroll(int s)
|
||||
{
|
||||
scroll_ = s;
|
||||
|
||||
updateMarkerPositions();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
QVector<TimelineMarker *> SeekableWidget::GetActiveTimelineMarkers() {
|
||||
QVector<TimelineMarker*> active_timelineMarkers;
|
||||
foreach (TimelineMarker *marker, timeline_points()->markers()->list()) {
|
||||
if (marker->active()) {
|
||||
active_timelineMarkers.append(marker);
|
||||
}
|
||||
}
|
||||
|
||||
return active_timelineMarkers;
|
||||
}
|
||||
|
||||
|
||||
void SeekableWidget::DeselectAllMarkers()
|
||||
{
|
||||
if (timebase().isNull()) {
|
||||
return;
|
||||
}
|
||||
if (!timeline_points()) {
|
||||
return;
|
||||
}
|
||||
foreach(TimelineMarker* marker, timeline_points()->markers()->list()) {
|
||||
marker->set_active(false);
|
||||
}
|
||||
}
|
||||
selection_manager_.ClearSelection();
|
||||
|
||||
void SeekableWidget::addMarker(TimelineMarker* marker)
|
||||
{
|
||||
if (!marker_map_.contains(marker)) {
|
||||
Marker *marker_widget = new Marker(this);
|
||||
marker_map_.insert(marker, marker_widget);
|
||||
|
||||
/*
|
||||
Markers are stored as TimelineMarkers and represented in the UI as Markers. As a single
|
||||
TimelineMarker can be represented in various views it is necessary to make sure all instances
|
||||
of the TimelineMarker's (UI) Markers are kept in sync. To do this, whenever a Marker is updated
|
||||
in some way, it signals that change to the relevant TimelineMarker which in turn broadcasts
|
||||
that update out to all the relevant Markers.
|
||||
*/
|
||||
|
||||
connect(marker_widget, &Marker::ColorChanged, this, &SeekableWidget::SetMarkerColor);
|
||||
connect(marker, &TimelineMarker::ColorChanged, marker_widget, &Marker::SetColor);
|
||||
|
||||
connect(marker_widget, &Marker::ActiveChanged, marker, &TimelineMarker::set_active);
|
||||
connect(marker, &TimelineMarker::ActiveChanged, marker_widget, &Marker::SetActive);
|
||||
|
||||
connect(marker_widget, &Marker::NameChanged, marker, &TimelineMarker::set_name_undo);
|
||||
connect(marker, &TimelineMarker::NameChanged, marker_widget, &Marker::SetName);
|
||||
|
||||
connect(marker_widget, &Marker::TimeChanged, marker, &TimelineMarker::set_time_undo);
|
||||
connect(marker, &TimelineMarker::TimeChanged, marker_widget, &Marker::SetTime);
|
||||
|
||||
marker_widget->move(TimeToScreen(marker->time().in())-2, text_height_);
|
||||
marker_widget->SetColor(marker->color());
|
||||
marker_widget->SetName(marker->name());
|
||||
marker_widget->show();
|
||||
}
|
||||
}
|
||||
|
||||
void SeekableWidget::removeMarker(TimelineMarker *marker)
|
||||
{
|
||||
marker_map_.value(marker)->deleteLater();
|
||||
marker_map_.take(marker);
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void SeekableWidget::SetMarkerColor(int c)
|
||||
{
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
foreach(TimelineMarker* marker, GetActiveTimelineMarkers()) {
|
||||
command->add_child(new MarkerChangeColorCommand(Core::instance()->GetActiveProject(), marker, c));
|
||||
foreach(TimelineMarker* marker, selection_manager_.GetSelectedObjects()) {
|
||||
command->add_child(new MarkerChangeColorCommand(marker, c));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
void SeekableWidget::updateMarkerPositions()
|
||||
{
|
||||
foreach (TimelineMarker* marker, marker_map_.keys()) {
|
||||
Marker *m = marker_map_.value(marker);
|
||||
m->move(TimeToScreen(marker->time().in())-2, text_height_);
|
||||
}
|
||||
}
|
||||
|
||||
int SeekableWidget::TimeToScreen(const rational &time) const
|
||||
{
|
||||
return qFloor(TimeToScene(time)) - scroll_;
|
||||
}
|
||||
|
||||
rational SeekableWidget::ScreenToTime(int x) const
|
||||
{
|
||||
return qMax(rational(0), SceneToTime(x + scroll_));
|
||||
}
|
||||
|
||||
void SeekableWidget::SeekToScreenPoint(int screen)
|
||||
void SeekableWidget::SeekToScenePoint(qreal scene)
|
||||
{
|
||||
if (timebase().isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
rational playhead_time = ScreenToTime(screen);
|
||||
rational playhead_time = SceneToTime(scene);
|
||||
|
||||
if (Core::instance()->snapping() && snap_service_) {
|
||||
if (Core::instance()->snapping() && GetSnapService()) {
|
||||
rational movement;
|
||||
|
||||
snap_service_->SnapPoint({playhead_time},
|
||||
&movement,
|
||||
SnapService::kSnapAll & ~SnapService::kSnapToPlayhead);
|
||||
GetSnapService()->SnapPoint({playhead_time},
|
||||
&movement,
|
||||
SnapService::kSnapAll & ~SnapService::kSnapToPlayhead);
|
||||
|
||||
playhead_time += movement;
|
||||
}
|
||||
@@ -305,20 +192,20 @@ void SeekableWidget::DrawTimelinePoints(QPainter* p, int marker_bottom)
|
||||
|
||||
// Draw in/out workarea
|
||||
if (timeline_points()->workarea()->enabled()) {
|
||||
int workarea_left = qMax(0, TimeToScreen(timeline_points()->workarea()->in()));
|
||||
int workarea_left = qMax(0.0, TimeToScene(timeline_points()->workarea()->in()));
|
||||
int workarea_right;
|
||||
|
||||
if (timeline_points()->workarea()->out() == TimelineWorkArea::kResetOut) {
|
||||
workarea_right = width();
|
||||
} else {
|
||||
workarea_right = qMin(width(), TimeToScreen(timeline_points()->workarea()->out()));
|
||||
workarea_right = qMin(qreal(width()), TimeToScene(timeline_points()->workarea()->out()));
|
||||
}
|
||||
|
||||
p->fillRect(workarea_left, 0, workarea_right - workarea_left, height(), palette().highlight());
|
||||
}
|
||||
|
||||
// Draw markers
|
||||
if (marker_bottom > 0 && !timeline_points()->markers()->list().isEmpty()) {
|
||||
if (marker_bottom > 0 && !timeline_points()->markers()->list().empty()) {
|
||||
|
||||
int marker_top = marker_bottom - text_height_;
|
||||
|
||||
@@ -327,8 +214,8 @@ void SeekableWidget::DrawTimelinePoints(QPainter* p, int marker_bottom)
|
||||
p->setBrush(Qt::green);
|
||||
|
||||
foreach (TimelineMarker* marker, timeline_points()->markers()->list()) {
|
||||
int marker_left = TimeToScreen(marker->time().in());
|
||||
int marker_right = TimeToScreen(marker->time().out());
|
||||
int marker_left = TimeToScene(marker->time().in());
|
||||
int marker_right = TimeToScene(marker->time().out());
|
||||
|
||||
if (marker_left >= width() || marker_right < 0) {
|
||||
continue;
|
||||
|
||||
@@ -22,35 +22,29 @@
|
||||
#define SEEKABLEWIDGET_H
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "timeline/timelinepoints.h"
|
||||
#include "widget/snapservice/snapservice.h"
|
||||
#include "widget/timebased/timescaledobject.h"
|
||||
#include "widget/marker/marker.h"
|
||||
#include "widget/marker/markercopypaste.h"
|
||||
#include "widget/timebased/timebasedviewselectionmanager.h"
|
||||
//#include "widget/marker/markercopypaste.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SeekableWidget : public TimelineScaledWidget, public MarkerCopyPasteService
|
||||
class SeekableWidget : public TimeBasedView//, public MarkerCopyPasteService
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SeekableWidget(QWidget *parent = nullptr);
|
||||
|
||||
const rational& GetTime() const
|
||||
int GetScroll() const
|
||||
{
|
||||
return time_;
|
||||
return horizontalScrollBar()->value();
|
||||
}
|
||||
|
||||
const int& GetScroll() const;
|
||||
|
||||
void ConnectTimelinePoints(TimelinePoints* points);
|
||||
|
||||
void SetSnapService(SnapService* service);
|
||||
|
||||
SnapService* GetSnapService() { return snap_service_; };
|
||||
|
||||
bool IsDraggingPlayhead() const
|
||||
{
|
||||
return dragging_;
|
||||
@@ -62,35 +56,28 @@ public:
|
||||
|
||||
void PasteMarkers(bool insert, rational insert_time);
|
||||
|
||||
QVector<TimelineMarker*> GetActiveTimelineMarkers();
|
||||
|
||||
void DeselectAllMarkers();
|
||||
|
||||
void SeekToScreenPoint(int screen);
|
||||
|
||||
int TimeToScreen(const rational& time) const;
|
||||
rational ScreenToTime(int x) const;
|
||||
void SeekToScenePoint(qreal scene);
|
||||
|
||||
public slots:
|
||||
void SetTime(const rational &r);
|
||||
|
||||
void SetScroll(int s);
|
||||
|
||||
void addMarker(TimelineMarker* marker);
|
||||
|
||||
void removeMarker(TimelineMarker* marker);
|
||||
|
||||
void updateMarkerPositions();
|
||||
void SetScroll(int i)
|
||||
{
|
||||
horizontalScrollBar()->setValue(i);
|
||||
}
|
||||
|
||||
void SetMarkerColor(int c);
|
||||
|
||||
protected:
|
||||
/*void SetMarkerTime();
|
||||
|
||||
void SetMarkerName();*/
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void ScaleChangedEvent(const double&) override;
|
||||
virtual void focusOutEvent(QFocusEvent *event) override;
|
||||
|
||||
void DrawTimelinePoints(QPainter *p, int marker_bottom = 0);
|
||||
|
||||
@@ -106,30 +93,16 @@ protected:
|
||||
return playhead_width_;
|
||||
}
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted whenever the time changes on this ruler, either by user or programmatically
|
||||
*/
|
||||
void TimeChanged(const rational &time);
|
||||
|
||||
private:
|
||||
rational time_;
|
||||
|
||||
TimelinePoints* timeline_points_;
|
||||
|
||||
int scroll_;
|
||||
|
||||
int text_height_;
|
||||
|
||||
int playhead_width_;
|
||||
|
||||
SnapService* snap_service_;
|
||||
|
||||
bool dragging_;
|
||||
|
||||
QMap<TimelineMarker*, Marker*> marker_map_;
|
||||
|
||||
QMap<TimelineMarker*, Marker*> active_markers_map_;
|
||||
TimeBasedViewSelectionManager<TimelineMarker> selection_manager_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -58,6 +58,17 @@ TimeRuler::TimeRuler(bool text_visible, bool cache_status_visible, QWidget* pare
|
||||
|
||||
// Connect context menu
|
||||
connect(this, &TimeRuler::customContextMenuRequested, this, &TimeRuler::ShowContextMenu);
|
||||
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
//horizontalScrollBar()->setVisible(false);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setBackgroundRole(QPalette::Window);
|
||||
setFrameShape(QFrame::NoFrame);
|
||||
|
||||
// NOTE: One day it might be preferable to use AlignBottom because the lines are anchored to
|
||||
// the bottom of the widget. However, for now this makes sense since we just ported this
|
||||
// from a QWidget's paintEvent.
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
}
|
||||
|
||||
void TimeRuler::SetPlaybackCache(PlaybackCache *cache)
|
||||
@@ -83,15 +94,13 @@ void TimeRuler::SetPlaybackCache(PlaybackCache *cache)
|
||||
update();
|
||||
}
|
||||
|
||||
void TimeRuler::paintEvent(QPaintEvent *)
|
||||
void TimeRuler::drawForeground(QPainter *p, const QRectF &rect)
|
||||
{
|
||||
// Nothing to paint if the timebase is invalid
|
||||
if (timebase().isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
// Draw timeline points if connected
|
||||
if (timeline_points()) {
|
||||
int marker_bottom = height() - text_height();
|
||||
@@ -104,7 +113,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
marker_bottom -= cache_status_height_;
|
||||
}
|
||||
|
||||
DrawTimelinePoints(&p, marker_bottom);
|
||||
DrawTimelinePoints(p, marker_bottom);
|
||||
}
|
||||
|
||||
double width_of_frame = timebase_dbl() * GetScale();
|
||||
@@ -173,11 +182,11 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
}
|
||||
|
||||
// Set line color to main text color
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(palette().text().color());
|
||||
p->setBrush(Qt::NoBrush);
|
||||
p->setPen(palette().text().color());
|
||||
|
||||
// Calculate line dimensions
|
||||
QFontMetrics fm = p.fontMetrics();
|
||||
QFontMetrics fm = p->fontMetrics();
|
||||
int line_bottom = height();
|
||||
|
||||
if (show_cache_status_) {
|
||||
@@ -197,8 +206,8 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
// FIXME: Hardcoded number
|
||||
const int kAverageTextWidth = 200;
|
||||
|
||||
for (int i=-kAverageTextWidth;i<width()+kAverageTextWidth;i++) {
|
||||
double screen_pt = static_cast<double>(i + GetScroll());
|
||||
for (int i=GetScroll()-kAverageTextWidth;i<GetScroll()+width()+kAverageTextWidth;i++) {
|
||||
double screen_pt = static_cast<double>(i);
|
||||
|
||||
if (long_interval > -1) {
|
||||
int this_long_unit = qFloor(screen_pt/long_interval);
|
||||
@@ -208,7 +217,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
if (text_visible_) {
|
||||
QRect text_rect;
|
||||
Qt::Alignment text_align;
|
||||
QString timecode_str = Timecode::time_to_timecode(ScreenToTime(i), timebase(), Core::instance()->GetTimecodeDisplay());
|
||||
QString timecode_str = Timecode::time_to_timecode(SceneToTime(i), timebase(), Core::instance()->GetTimecodeDisplay());
|
||||
int timecode_width = QtUtils::QFontMetricsWidth(fm, timecode_str);
|
||||
int timecode_left;
|
||||
|
||||
@@ -226,9 +235,9 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
}
|
||||
|
||||
if (timecode_left > last_text_draw) {
|
||||
p.drawText(text_rect,
|
||||
static_cast<int>(text_align),
|
||||
timecode_str);
|
||||
p->drawText(text_rect,
|
||||
static_cast<int>(text_align),
|
||||
timecode_str);
|
||||
|
||||
last_text_draw = timecode_left + timecode_width;
|
||||
|
||||
@@ -238,7 +247,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
}
|
||||
}
|
||||
|
||||
p.drawLine(i, line_y, i, line_bottom);
|
||||
p->drawLine(i, line_y, i, line_bottom);
|
||||
last_long_unit = this_long_unit;
|
||||
}
|
||||
}
|
||||
@@ -246,7 +255,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
if (short_interval > -1) {
|
||||
int this_short_unit = qFloor(screen_pt/short_interval);
|
||||
if (this_short_unit != last_short_unit) {
|
||||
p.drawLine(i, short_y, i, line_bottom);
|
||||
p->drawLine(i, short_y, i, line_bottom);
|
||||
last_short_unit = this_short_unit;
|
||||
}
|
||||
}
|
||||
@@ -257,40 +266,40 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
// FIXME: Hardcoded to get video length, if we ever need audio length, this will have to change
|
||||
rational len = playback_cache_->viewer_parent()->GetVideoLength();
|
||||
|
||||
int cache_screen_length = qMin(TimeToScreen(len), width());
|
||||
int cache_screen_length = qMin(TimeToScene(len), qreal(width()));
|
||||
|
||||
if (cache_screen_length > 0) {
|
||||
int cache_y = height() - cache_status_height_;
|
||||
|
||||
p.fillRect(0, cache_y, cache_screen_length , cache_status_height_, Qt::green);
|
||||
p->fillRect(0, cache_y, cache_screen_length , cache_status_height_, Qt::green);
|
||||
|
||||
foreach (const TimeRange& range, playback_cache_->GetInvalidatedRanges(len)) {
|
||||
int range_left = TimeToScreen(range.in());
|
||||
int range_left = TimeToScene(range.in());
|
||||
if (range_left >= width()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int range_right = TimeToScreen(range.out());
|
||||
int range_right = TimeToScene(range.out());
|
||||
if (range_right < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int adjusted_left = qMax(0, range_left);
|
||||
|
||||
p.fillRect(adjusted_left,
|
||||
cache_y,
|
||||
qMin(width(), range_right) - adjusted_left,
|
||||
cache_status_height_,
|
||||
Qt::red);
|
||||
p->fillRect(adjusted_left,
|
||||
cache_y,
|
||||
qMin(width(), range_right) - adjusted_left,
|
||||
cache_status_height_,
|
||||
Qt::red);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the playhead if it's on screen at the moment
|
||||
int playhead_pos = TimeToScreen(GetTime());
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(PLAYHEAD_COLOR);
|
||||
DrawPlayhead(&p, playhead_pos, line_bottom);
|
||||
int playhead_pos = TimeToScene(GetTime());
|
||||
p->setPen(Qt::NoPen);
|
||||
p->setBrush(PLAYHEAD_COLOR);
|
||||
DrawPlayhead(p, playhead_pos, line_bottom);
|
||||
}
|
||||
|
||||
void TimeRuler::TimebaseChangedEvent(const rational &tb)
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
void SetPlaybackCache(PlaybackCache* cache);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
virtual void TimebaseChangedEvent(const rational& tb) override;
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@ AudioWaveformView::AudioWaveformView(QWidget *parent) :
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
// NOTE: At some point it might make sense for this to be AlignCenter since the waveform
|
||||
// originates from the center. But we're leaving it top/left for now since it was just
|
||||
// ported from a QWidget's paintEvent.
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
}
|
||||
|
||||
void AudioWaveformView::SetViewer(AudioPlaybackCache *playback)
|
||||
@@ -60,9 +67,9 @@ void AudioWaveformView::SetViewer(AudioPlaybackCache *playback)
|
||||
}
|
||||
}
|
||||
|
||||
void AudioWaveformView::paintEvent(QPaintEvent *event)
|
||||
void AudioWaveformView::drawForeground(QPainter *p, const QRectF &rect)
|
||||
{
|
||||
super::paintEvent(event);
|
||||
super::drawForeground(p, rect);
|
||||
|
||||
if (!playback_) {
|
||||
return;
|
||||
@@ -74,20 +81,18 @@ void AudioWaveformView::paintEvent(QPaintEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
// Draw in/out points
|
||||
DrawTimelinePoints(&p);
|
||||
DrawTimelinePoints(p);
|
||||
|
||||
// Draw waveform
|
||||
p.setPen(QColor(64, 255, 160)); // FIXME: Hardcoded color
|
||||
AudioVisualWaveform::DrawWaveform(&p, rect(), GetScale(), playback_->visual(), SceneToTime(GetScroll()));
|
||||
p->setPen(QColor(64, 255, 160)); // FIXME: Hardcoded color
|
||||
AudioVisualWaveform::DrawWaveform(p, rect.toRect(), GetScale(), playback_->visual(), SceneToTime(GetScroll()));
|
||||
|
||||
// Draw playhead
|
||||
p.setPen(PLAYHEAD_COLOR);
|
||||
p->setPen(PLAYHEAD_COLOR);
|
||||
|
||||
int playhead_x = TimeToScreen(GetTime());
|
||||
p.drawLine(playhead_x, 0, playhead_x, height());
|
||||
int playhead_x = TimeToScene(GetTime());
|
||||
p->drawLine(playhead_x, 0, playhead_x, height());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
void SetViewer(AudioPlaybackCache *playback);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
private:
|
||||
QThreadPool pool_;
|
||||
|
||||
@@ -97,6 +97,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
|
||||
// Create waveform view when audio is connected and video isn't
|
||||
waveform_view_ = new AudioWaveformView();
|
||||
ConnectTimelineView(waveform_view_, true);
|
||||
PassWheelEventsToScrollBar(waveform_view_);
|
||||
stack_->addWidget(waveform_view_);
|
||||
|
||||
@@ -125,7 +126,6 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
SetScale(48.0);
|
||||
|
||||
// Ensures that seeking on the waveform view updates the time as expected
|
||||
connect(waveform_view_, &AudioWaveformView::TimeChanged, this, &ViewerWidget::SetTimeAndSignal);
|
||||
connect(waveform_view_, &AudioWaveformView::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
|
||||
|
||||
connect(&playback_backup_timer_, &QTimer::timeout, this, &ViewerWidget::PlaybackTimerUpdate);
|
||||
|
||||
Reference in New Issue
Block a user