rewrite work continued

This commit is contained in:
itsmattkc
2019-03-30 03:09:43 +11:00
parent 1fdac776d4
commit 114606c28e
25 changed files with 692 additions and 397 deletions
+6 -2
View File
@@ -174,7 +174,9 @@ SOURCES += \
rendering/shadergenerators.cpp \
global/timing.cpp \
rendering/pixelformats.cpp \
timeline/timelinefunctions.cpp
timeline/timelinefunctions.cpp \
timeline/track.cpp \
timeline/tracklist.cpp
HEADERS += \
ui/mainwindow.h \
@@ -308,7 +310,9 @@ HEADERS += \
global/timing.h \
rendering/pixelformats.h \
timeline/ghost.h \
timeline/timelinefunctions.h
timeline/timelinefunctions.h \
timeline/track.h \
timeline/tracklist.h
FORMS +=
+2 -2
View File
@@ -646,11 +646,11 @@ void EffectControls::Load() {
}
}
if (c->opening_transition != nullptr
&& (whole_clip_is_selected || c->sequence->IsTransitionSelected(c->opening_transition.get()))) {
&& (whole_clip_is_selected || c->track()->IsTransitionSelected(c->opening_transition.get()))) {
effects_to_open.append(c->opening_transition.get());
}
if (c->closing_transition != nullptr
&& (whole_clip_is_selected || c->sequence->IsTransitionSelected(c->closing_transition.get()))) {
&& (whole_clip_is_selected || c->track()->IsTransitionSelected(c->closing_transition.get()))) {
effects_to_open.append(c->closing_transition.get());
}
+27 -162
View File
@@ -492,21 +492,6 @@ MediaPtr Project::item_to_media_ptr(const QModelIndex &index) {
return raw_ptr->parentItem()->get_shared_ptr(raw_ptr);
}
void Project::get_all_media_from_table(QList<Media*>& items, QList<Media*>& list, int search_type) {
for (int i=0;i<items.size();i++) {
Media* item = items.at(i);
if (item->get_type() == MEDIA_TYPE_FOLDER) {
QList<Media*> children;
for (int j=0;j<item->childCount();j++) {
children.append(item->child(j));
}
get_all_media_from_table(children, list, search_type);
} else if (search_type == item->get_type() || search_type == -1) {
list.append(item);
}
}
}
bool Project::IsToolbarVisible()
{
return toolbar_widget->isVisible();
@@ -550,25 +535,22 @@ void Project::delete_selected_media() {
// check if media is in use
QVector<Media*> parents;
QList<Media*> sequence_items;
QList<Media*> all_top_level_items;
for (int i=0;i<olive::project_model.childCount();i++) {
all_top_level_items.append(olive::project_model.child(i));
}
get_all_media_from_table(all_top_level_items, sequence_items, MEDIA_TYPE_SEQUENCE); // find all sequences in project
if (sequence_items.size() > 0) {
QVector<Media*> all_sequences = olive::project_model.GetAllSequences();
if (all_sequences.size() > 0) {
QList<Media*> media_items;
get_all_media_from_table(items, media_items, MEDIA_TYPE_FOOTAGE);
QVector<Media*> all_footage = olive::project_model.GetAllFootage();
for (int i=0;i<media_items.size();i++) {
Media* item = media_items.at(i);
for (int i=0;i<all_footage.size();i++) {
Media* item = all_footage.at(i);
Footage* media = item->to_footage();
bool confirm_delete = false;
for (int j=0;j<sequence_items.size();j++) {
Sequence* s = sequence_items.at(j)->to_sequence().get();
for (int k=0;k<s->clips.size();k++) {
ClipPtr c = s->clips.at(k);
for (int j=0;j<all_sequences.size();j++) {
Sequence* s = all_sequences.at(j)->to_sequence().get();
QVector<Clip*> sequence_clips = s->GetAllClips();
for (int k=0;k<sequence_clips.size();k++) {
Clip* c = sequence_clips.at(k);
if (c != nullptr && c->media() == item) {
if (!confirm_delete) {
// we found a reference, so we know we'll need to ask if the user wants to delete it
@@ -608,13 +590,13 @@ void Project::delete_selected_media() {
parent = parent->parentItem();
}
j = sequence_items.size();
k = s->clips.size();
j = all_sequences.size();
k = sequence_clips.size();
} else if (confirm.clickedButton() == abort_button) {
// break out of loop
i = media_items.size();
j = sequence_items.size();
k = s->clips.size();
i = all_footage.size();
j = all_sequences.size();
k = sequence_clips.size();
remove = false;
}
@@ -636,7 +618,9 @@ void Project::delete_selected_media() {
panel_graph_editor->set_row(nullptr);
panel_effect_controls->Clear(true);
if (olive::ActiveSequence != nullptr) olive::ActiveSequence->selections.clear();
if (olive::ActiveSequence != nullptr) {
olive::ActiveSequence->ClearSelections();
}
// remove media and parents
for (int m=0;m<parents.size();m++) {
@@ -665,14 +649,8 @@ void Project::delete_selected_media() {
panel_footage_viewer->set_media(nullptr);
}
} else if (items.at(i)->get_type() == MEDIA_TYPE_FOOTAGE) {
if (panel_footage_viewer->seq != nullptr) {
for (int j=0;j<panel_footage_viewer->seq->clips.size();j++) {
ClipPtr c = panel_footage_viewer->seq->clips.at(j);
if (c != nullptr && c->media() == items.at(i)) {
panel_footage_viewer->set_media(nullptr);
break;
}
}
if (panel_footage_viewer->media == items.at(i)) {
panel_footage_viewer->set_media(nullptr);
}
}
}
@@ -1023,8 +1001,9 @@ void Project::delete_clips_using_selected_media() {
ComboAction* ca = new ComboAction();
bool deleted = false;
QModelIndexList items = get_current_selected();
for (int i=0;i<olive::ActiveSequence->clips.size();i++) {
const ClipPtr& c = olive::ActiveSequence->clips.at(i);
QVector<Clip*> sequence_clips = olive::ActiveSequence->GetAllClips();
for (int i=0;i<sequence_clips.size();i++) {
Clip* c = sequence_clips.at(i);
if (c != nullptr) {
for (int j=0;j<items.size();j++) {
Media* m = item_to_media(items.at(j));
@@ -1068,13 +1047,6 @@ void Project::clear() {
tree_view->update();
}
void save_marker(QXmlStreamWriter& stream, const Marker& m) {
stream.writeStartElement("marker");
stream.writeAttribute("frame", QString::number(m.frame));
stream.writeAttribute("name", m.name);
stream.writeEndElement();
}
void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex& parent) {
for (int i=0;i<olive::project_model.rowCount(parent);i++) {
const QModelIndex& item = olive::project_model.index(i, 0, parent);
@@ -1145,7 +1117,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only,
// save footage markers
for (int j=0;j<f->markers.size();j++) {
save_marker(stream, f->markers.at(j));
f->markers.at(j).Save(stream);
}
stream.writeEndElement(); // footage
@@ -1156,114 +1128,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only,
s->save_id = sequence_id;
sequence_id++;
} else {
stream.writeStartElement("sequence");
stream.writeAttribute("id", QString::number(s->save_id));
stream.writeAttribute("folder", QString::number(folder));
stream.writeAttribute("name", s->name);
stream.writeAttribute("width", QString::number(s->width));
stream.writeAttribute("height", QString::number(s->height));
stream.writeAttribute("framerate", QString::number(s->frame_rate, 'f', 10));
stream.writeAttribute("afreq", QString::number(s->audio_frequency));
stream.writeAttribute("alayout", QString::number(s->audio_layout));
if (s == olive::ActiveSequence.get()) {
stream.writeAttribute("open", "1");
}
stream.writeAttribute("workarea", QString::number(s->using_workarea));
stream.writeAttribute("workareaIn", QString::number(s->workarea_in));
stream.writeAttribute("workareaOut", QString::number(s->workarea_out));
QVector<TransitionPtr> transition_save_cache;
QVector<int> transition_clip_save_cache;
for (int j=0;j<s->clips.size();j++) {
const ClipPtr& c = s->clips.at(j);
if (c != nullptr) {
stream.writeStartElement("clip"); // clip
stream.writeAttribute("id", QString::number(j));
stream.writeAttribute("enabled", QString::number(c->enabled()));
stream.writeAttribute("name", c->name());
stream.writeAttribute("clipin", QString::number(c->clip_in()));
stream.writeAttribute("in", QString::number(c->timeline_in()));
stream.writeAttribute("out", QString::number(c->timeline_out()));
stream.writeAttribute("track", QString::number(c->track()));
stream.writeAttribute("r", QString::number(c->color().red()));
stream.writeAttribute("g", QString::number(c->color().green()));
stream.writeAttribute("b", QString::number(c->color().blue()));
stream.writeAttribute("autoscale", QString::number(c->autoscaled()));
stream.writeAttribute("speed", QString::number(c->speed().value, 'f', 10));
stream.writeAttribute("maintainpitch", QString::number(c->speed().maintain_audio_pitch));
stream.writeAttribute("reverse", QString::number(c->reversed()));
if (c->media() != nullptr) {
stream.writeAttribute("type", QString::number(c->media()->get_type()));
switch (c->media()->get_type()) {
case MEDIA_TYPE_FOOTAGE:
stream.writeAttribute("media", QString::number(c->media()->to_footage()->save_id));
stream.writeAttribute("stream", QString::number(c->media_stream_index()));
break;
case MEDIA_TYPE_SEQUENCE:
stream.writeAttribute("sequence", QString::number(c->media()->to_sequence()->save_id));
break;
}
}
// save markers
// only necessary for null media clips, since media has its own markers
if (c->media() == nullptr) {
for (int k=0;k<c->get_markers().size();k++) {
save_marker(stream, c->get_markers().at(k));
}
}
// save clip links
stream.writeStartElement("linked"); // linked
for (int k=0;k<c->linked.size();k++) {
stream.writeStartElement("link"); // link
stream.writeAttribute("id", QString::number(c->linked.at(k)));
stream.writeEndElement(); // link
}
stream.writeEndElement(); // linked
// save opening and closing transitions
for (int t=kTransitionOpening;t<=kTransitionClosing;t++) {
TransitionPtr transition = (t == kTransitionOpening) ? c->opening_transition : c->closing_transition;
if (transition != nullptr) {
stream.writeStartElement((t == kTransitionOpening) ? "opening" : "closing");
// check if this is a shared transition and the transition has already been saved
int transition_cache_index = transition_save_cache.indexOf(transition);
if (transition_cache_index > -1) {
// if so, just save a reference to the other clip
stream.writeAttribute("shared",
QString::number(transition_clip_save_cache.at(transition_cache_index)));
} else {
// otherwise save the whole transition
transition->save(stream);
transition_save_cache.append(transition);
transition_clip_save_cache.append(j);
}
stream.writeEndElement(); // opening
}
}
for (int k=0;k<c->effects.size();k++) {
stream.writeStartElement("effect"); // effect
c->effects.at(k)->save(stream);
stream.writeEndElement(); // effect
}
stream.writeEndElement(); // clip
}
}
for (int j=0;j<s->markers.size();j++) {
save_marker(stream, s->markers.at(j));
}
stream.writeEndElement();
s->Save(stream);
}
}
}
-2
View File
@@ -81,8 +81,6 @@ public:
QModelIndexList get_current_selected();
void get_all_media_from_table(QList<Media *> &items, QList<Media *> &list, int type = -1);
bool IsToolbarVisible();
bool IsProjectWidget(QObject *child);
+1 -7
View File
@@ -56,10 +56,6 @@
#include "global/timing.h"
#include "ui/menu.h"
int olive::timeline::kTrackDefaultHeight = 40;
int olive::timeline::kTrackMinHeight = 30;
int olive::timeline::kTrackHeightIncrement = 10;
Timeline::Timeline(QWidget *parent) :
Panel(parent),
cursor_frame(0),
@@ -119,8 +115,6 @@ Timeline::Timeline(QWidget *parent) :
Retranslate();
}
Timeline::~Timeline() {}
void Timeline::Retranslate() {
toolArrowButton->setToolTip(tr("Pointer Tool") + " (V)");
toolEditButton->setToolTip(tr("Edit Tool") + " (X)");
@@ -270,7 +264,7 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
break;
case MEDIA_TYPE_SEQUENCE:
s = medium->to_sequence().get();
sequence_length = s->getEndFrame();
sequence_length = s->GetEndFrame();
if (seq != nullptr) sequence_length = rescale_frame_number(sequence_length, s->frame_rate, seq->frame_rate);
can_import = (s != seq && sequence_length != 0);
if (s->using_workarea) {
-25
View File
@@ -38,28 +38,6 @@
#include "ui/panel.h"
namespace olive {
namespace timeline {
const int kGhostThickness = 2;
const int kClipTextPadding = 3;
/**
* @brief Set default track sizes
*
* Olive has a few default constants used for adjusting track heights in the Timeline. For HiDPI, it makes
* sense to multiply these by the current DPI scale. It uses a variable from QApplication to do this multiplication,
* which means the QApplication instance needs to be instantiated before these are calculated. Therefore, call this
* function ONCE after QApplication is created to multiply the track heights correctly.
*/
void MultiplyTrackSizesByDPI();
extern int kTrackDefaultHeight;
extern int kTrackMinHeight;
extern int kTrackHeightIncrement;
}
}
int getScreenPointFromFrame(double zoom, long frame);
long getFrameFromScreenPoint(double zoom, int x);
bool selection_contains_transition(const Selection& s, Clip *c, int type);
@@ -72,7 +50,6 @@ class Timeline : public Panel
Q_OBJECT
public:
explicit Timeline(QWidget *parent = nullptr);
virtual ~Timeline() override;
bool focused();
void multiply_zoom(double m);
@@ -255,8 +232,6 @@ private:
long rc_ripple_min;
long rc_ripple_max;
QVector<TimelineTrackHeight> track_heights;
QWidget* timeline_area;
TimelineWidget* video_area;
TimelineWidget* audio_area;
+25 -20
View File
@@ -127,12 +127,15 @@ void Viewer::reset_all_audio() {
// reset all clip audio
if (seq != nullptr) {
long last_frame = 0;
for (int i=0;i<seq->clips.size();i++) {
ClipPtr c = seq->clips.at(i);
if (c != nullptr) {
c->reset_audio();
last_frame = qMax(last_frame, c->timeline_out());
}
QVector<Clip*> all_clips = seq->GetAllClips();
for (int i=0;i<all_clips.size();i++) {
Clip* c = all_clips.at(i);
c->reset_audio();
last_frame = qMax(last_frame, c->timeline_out());
}
audio_ibuffer_frame = seq->playhead;
@@ -149,7 +152,7 @@ void Viewer::seek(long p) {
if (main_sequence) {
seq->playhead = p;
} else {
seq->playhead = qMin(seq->getEndFrame(), qMax(0L, p));
seq->playhead = qMin(seq->GetEndFrame(), qMax(0L, p));
}
bool update_fx = false;
if (main_sequence) {
@@ -171,7 +174,7 @@ void Viewer::go_to_start() {
}
void Viewer::go_to_end() {
if (seq != nullptr) seek(seq->getEndFrame());
if (seq != nullptr) seek(seq->GetEndFrame());
}
void Viewer::close_media() {
@@ -206,7 +209,7 @@ void Viewer::go_to_out() {
}
}
void Viewer::cue_recording(long start, long end, int track) {
void Viewer::cue_recording(long start, long end, Track* track) {
recording_start = start;
recording_end = end;
recording_track = track;
@@ -257,7 +260,7 @@ void Viewer::play(bool in_to_out) {
if (panel_sequence_viewer->playing) panel_sequence_viewer->pause();
if (panel_footage_viewer->playing) panel_footage_viewer->pause();
long sequence_end_frame = seq->getEndFrame();
long sequence_end_frame = seq->GetEndFrame();
if (sequence_end_frame == 0) {
return;
}
@@ -353,12 +356,12 @@ void Viewer::update_playhead_timecode(long p) {
}
void Viewer::update_end_timecode() {
end_timecode->setText((seq == nullptr) ? frame_to_timecode(0, olive::CurrentConfig.timecode_view, 30) : frame_to_timecode(seq->getEndFrame(), olive::CurrentConfig.timecode_view, seq->frame_rate));
end_timecode->setText((seq == nullptr) ? frame_to_timecode(0, olive::CurrentConfig.timecode_view, 30) : frame_to_timecode(seq->GetEndFrame(), olive::CurrentConfig.timecode_view, seq->frame_rate));
}
void Viewer::update_header_zoom() {
if (seq != nullptr) {
long sequenceEndFrame = seq->getEndFrame();
long sequenceEndFrame = seq->GetEndFrame();
if (cached_end_frame != sequenceEndFrame) {
minimum_zoom = (sequenceEndFrame > 0) ? ((double) headers->width() / (double) sequenceEndFrame) : 1;
headers->update_zoom(qMax(headers->get_zoom(), minimum_zoom));
@@ -431,7 +434,7 @@ void Viewer::clear_in() {
void Viewer::clear_out() {
if (seq != nullptr
&& seq->using_workarea) {
olive::UndoStack.push(new SetTimelineInOutCommand(seq.get(), true, seq->workarea_in, seq->getEndFrame()));
olive::UndoStack.push(new SetTimelineInOutCommand(seq.get(), true, seq->workarea_in, seq->GetEndFrame()));
update_parents();
}
}
@@ -497,7 +500,7 @@ void Viewer::set_zoom_value(double d) {
}
void Viewer::set_sb_max() {
headers->set_scrollbar_max(horizontal_bar, seq->getEndFrame(), headers->width());
headers->set_scrollbar_max(horizontal_bar, seq->GetEndFrame(), headers->width());
}
void Viewer::set_playback_speed(int s) {
@@ -517,7 +520,7 @@ long Viewer::get_seq_in() {
long Viewer::get_seq_out() {
return ((olive::CurrentConfig.loop || playing_in_to_out) && seq->using_workarea && previous_playhead < seq->workarea_out)
? seq->workarea_out
: seq->getEndFrame();
: seq->GetEndFrame();
}
void Viewer::setup_ui() {
@@ -689,10 +692,11 @@ void Viewer::set_media(Media* m) {
// FIXME: Move this magic number to Config
c->set_timeline_out(150);
}
c->set_track(-1);
Track* track = new_sequence->GetTrackList(Track::kTypeVideo)->First();
c->set_track(track);
c->set_clip_in(0);
c->refresh();
new_sequence->clips.append(c);
track->AddClip(c);
} else {
new_sequence->width = olive::CurrentConfig.default_sequence_width;
new_sequence->height = olive::CurrentConfig.default_sequence_height;
@@ -706,10 +710,11 @@ void Viewer::set_media(Media* m) {
c->set_media(media, audio_stream.file_index);
c->set_timeline_in(0);
c->set_timeline_out(footage->get_length_in_frames(new_sequence->frame_rate));
c->set_track(0);
Track* track = new_sequence->GetTrackList(Track::kTypeAudio)->First();
c->set_track(track);
c->set_clip_in(0);
c->refresh();
new_sequence->clips.append(c);
track->AddClip(c);
if (footage->video_tracks.size() == 0) {
viewer_widget_->waveform = true;
@@ -756,7 +761,7 @@ void Viewer::timer_update() {
pause();
}
} else if (playback_speed > 0) {
long end_frame = seq->getEndFrame();
long end_frame = seq->GetEndFrame();
if ((olive::CurrentConfig.auto_seek_to_beginning || previous_playhead < end_frame) && seq->playhead >= end_frame) {
pause();
}
+2 -2
View File
@@ -72,12 +72,12 @@ public:
QTimer playback_updater;
void cue_recording(long start, long end, int track);
void cue_recording(long start, long end, Track *track);
void uncue_recording();
bool is_recording_cued();
long recording_start;
long recording_end;
int recording_track;
Track* recording_track;
void reset_all_audio();
void update_parents(bool reload_fx = false);
+1 -1
View File
@@ -293,7 +293,7 @@ int Media::columnCount() const {
QString Media::GetStringDuration() {
if (get_type() == MEDIA_TYPE_SEQUENCE) {
Sequence* s = to_sequence().get();
return frame_to_timecode(s->getEndFrame(), olive::CurrentConfig.timecode_view, s->frame_rate);
return frame_to_timecode(s->GetEndFrame(), olive::CurrentConfig.timecode_view, s->frame_rate);
}
if (get_type() == MEDIA_TYPE_FOOTAGE) {
Footage* f = to_footage();
+39 -1
View File
@@ -50,7 +50,7 @@ void ProjectModel::destroy_root() {
panel_footage_viewer->set_media(nullptr);
}
root_item_ = std::make_shared<Media>();
root_item_ = nullptr;
}
void ProjectModel::clear() {
@@ -196,6 +196,44 @@ void ProjectModel::set_icon(Media* m, const QIcon &ico) {
emit dataChanged(index, index);
}
QVector<Media *> ProjectModel::GetAllSequences()
{
return GetAllMediaOfType(MEDIA_TYPE_SEQUENCE);
}
QVector<Media *> ProjectModel::GetAllFootage()
{
return GetAllMediaOfType(MEDIA_TYPE_FOOTAGE);
}
QVector<Media *> ProjectModel::GetAllFolders()
{
return GetAllMediaOfType(MEDIA_TYPE_FOLDER);
}
QVector<Media *> ProjectModel::GetAllMediaOfType(int search_type)
{
QVector<Media*> media_list;
RecurseTree(root_item_.get(), media_list, search_type);
return media_list;
}
void ProjectModel::RecurseTree(Media* parent, QVector<Media*>& list, int search_type)
{
for (int i=0;i<parent->childCount();i++) {
Media* child = parent->child(i);
if (child->get_type() == search_type) {
list.append(child);
}
if (child->childCount() > 0) {
RecurseTree(child, list, search_type);
}
}
}
void ProjectModel::appendChild(Media* parent, MediaPtr child) {
QModelIndex row_start;
+7
View File
@@ -58,8 +58,15 @@ public:
int childCount(Media* parent = nullptr);
void set_icon(Media* m, const QIcon &ico);
QVector<Media*> GetAllSequences();
QVector<Media*> GetAllFootage();
QVector<Media*> GetAllFolders();
private:
MediaPtr root_item_;
QVector<Media*> GetAllMediaOfType(int search_type);
void RecurseTree(Media* parent, QVector<Media *> &list, int search_type);
};
namespace olive {
+1 -1
View File
@@ -144,7 +144,7 @@ void Cacher::CacheAudioWorker() {
}
if (temp_reverse) {
long seq_end = olive::ActiveSequence->getEndFrame();
long seq_end = olive::ActiveSequence->GetEndFrame();
timeline_in = seq_end - timeline_in;
timeline_out = seq_end - timeline_out;
target_frame = seq_end - target_frame;
+113 -23
View File
@@ -37,14 +37,13 @@
#include "global/debug.h"
#include "global/timing.h"
Clip::Clip(Sequence* s) :
sequence(s),
Clip::Clip(Track *s) :
track_(s),
cacher(this),
enabled_(true),
clip_in_(0),
timeline_in_(0),
timeline_out_(0),
track_(0),
media_(nullptr),
reverse_(false),
autoscale_(olive::CurrentConfig.autoscale_by_default),
@@ -57,7 +56,7 @@ Clip::Clip(Sequence* s) :
{
}
ClipPtr Clip::copy(Sequence* s) {
ClipPtr Clip::copy(Track* s) {
ClipPtr copy = std::make_shared<Clip>(s);
copy->set_enabled(enabled());
@@ -76,7 +75,7 @@ ClipPtr Clip::copy(Sequence* s) {
copy->effects.append(effects.at(i)->copy(copy.get()));
}
copy->set_cached_frame_rate((this->sequence == nullptr) ? cached_frame_rate() : this->sequence->frame_rate);
copy->set_cached_frame_rate((this->track_ == nullptr) ? cached_frame_rate() : this->track_->frame_rate);
copy->refresh();
@@ -85,25 +84,36 @@ ClipPtr Clip::copy(Sequence* s) {
bool Clip::IsActiveAt(long timecode)
{
// these buffers allow clips to be opened and prepared well before they're displayed
// as well as closed a little after they're not needed anymore
int open_buffer = qCeil(this->sequence->frame_rate*2);
int close_buffer = qCeil(this->sequence->frame_rate);
return enabled()
&& timeline_in(true) < timecode + open_buffer
&& timeline_out(true) > timecode - close_buffer
&& timeline_in(true) < timecode
&& timeline_out(true) > timecode
&& timecode - timeline_in(true) + clip_in(true) < media_length();
}
bool Clip::IsSelected(bool containing)
{
if (this->sequence == nullptr) {
if (this->track_ == nullptr) {
return false;
}
return this->sequence->IsClipSelected(this, containing);
return this->track_->IsClipSelected(this, containing);
}
bool Clip::IsTransitionSelected(TransitionType type)
{
switch (type) {
case kTransitionOpening:
return track_->IsTransitionSelected(opening_transition.get());
case kTransitionClosing:
return track_->IsTransitionSelected(closing_transition.get());
default:
return false;
}
}
Track::Type Clip::type()
{
return track()->type();
}
const QColor &Clip::color()
@@ -132,7 +142,7 @@ FootageStream *Clip::media_stream()
{
if (media() != nullptr
&& media()->get_type() == MEDIA_TYPE_FOOTAGE) {
return media()->to_footage()->get_stream_from_file_index(track() < 0, media_stream_index());
return media()->to_footage()->get_stream_from_file_index(type() == Track::kTypeVideo, media_stream_index());
}
return nullptr;
@@ -212,9 +222,9 @@ void Clip::refresh() {
if (replaced && media() != nullptr && media()->get_type() == MEDIA_TYPE_FOOTAGE) {
Footage* m = media()->to_footage();
if (track() < 0 && m->video_tracks.size() > 0) {
if (type() == Track::kTypeVideo && m->video_tracks.size() > 0) {
set_media(media(), m->video_tracks.at(0).file_index);
} else if (track() >= 0 && m->audio_tracks.size() > 0) {
} else if (type() == Track::kTypeAudio && m->audio_tracks.size() > 0) {
set_media(media(), m->audio_tracks.at(0).file_index);
}
}
@@ -247,8 +257,88 @@ Clip::~Clip() {
if (IsOpen()) {
Close(true);
}
}
void Clip::Save(QXmlStreamWriter &stream)
{
stream.writeAttribute("enabled", QString::number(enabled()));
stream.writeAttribute("name", name());
stream.writeAttribute("clipin", QString::number(clip_in()));
stream.writeAttribute("in", QString::number(timeline_in()));
stream.writeAttribute("out", QString::number(timeline_out()));
stream.writeAttribute("track", QString::number(track()));
stream.writeAttribute("r", QString::number(color().red()));
stream.writeAttribute("g", QString::number(color().green()));
stream.writeAttribute("b", QString::number(color().blue()));
stream.writeAttribute("autoscale", QString::number(autoscaled()));
stream.writeAttribute("speed", QString::number(speed().value, 'f', 10));
stream.writeAttribute("maintainpitch", QString::number(speed().maintain_audio_pitch));
stream.writeAttribute("reverse", QString::number(reversed()));
if (c->media() != nullptr) {
stream.writeAttribute("type", QString::number(media()->get_type()));
switch (c->media()->get_type()) {
case MEDIA_TYPE_FOOTAGE:
stream.writeAttribute("media", QString::number(media()->to_footage()->save_id));
stream.writeAttribute("stream", QString::number(media_stream_index()));
break;
case MEDIA_TYPE_SEQUENCE:
stream.writeAttribute("sequence", QString::number(media()->to_sequence()->save_id));
break;
}
}
// save markers
// only necessary for null media clips, since media has its own markers
if (media() == nullptr) {
for (int k=0;k<get_markers().size();k++) {
get_markers().at(k).Save(stream);
}
}
// save clip links
stream.writeStartElement("linked"); // linked
for (int k=0;k<linked.size();k++) {
stream.writeStartElement("link"); // link
stream.writeAttribute("id", QString::number(linked.at(k)));
stream.writeEndElement(); // link
}
stream.writeEndElement(); // linked
// save opening and closing transitions
for (int t=kTransitionOpening;t<=kTransitionClosing;t++) {
TransitionPtr transition = (t == kTransitionOpening) ? opening_transition : closing_transition;
if (transition != nullptr) {
stream.writeStartElement((t == kTransitionOpening) ? "opening" : "closing");
// check if this is a shared transition and the transition has already been saved
int transition_cache_index = transition_save_cache.indexOf(transition);
if (transition_cache_index > -1) {
// if so, just save a reference to the other clip
stream.writeAttribute("shared",
QString::number(transition_clip_save_cache.at(transition_cache_index)));
} else {
// otherwise save the whole transition
transition->save(stream);
transition_save_cache.append(transition);
transition_clip_save_cache.append(j);
}
stream.writeEndElement(); // opening
}
}
for (int k=0;k<effects.size();k++) {
stream.writeStartElement("effect"); // effect
effects.at(k)->save(stream);
stream.writeEndElement(); // effect
}
effects.clear();
}
long Clip::clip_in(bool with_transition) {
@@ -346,12 +436,12 @@ AVRational Clip::time_base()
return cacher.media_time_base();
}
int Clip::track()
Track *Clip::track()
{
return track_;
}
void Clip::set_track(int t)
void Clip::set_track(Track *t)
{
track_ = t;
}
@@ -362,7 +452,7 @@ long Clip::length() {
}
double Clip::media_frame_rate() {
Q_ASSERT(track_ < 0);
Q_ASSERT(type() == Track::kTypeVideo);
if (media_ != nullptr) {
double rate = media_->get_frame_rate(media_stream_index());
if (!qIsNaN(rate)) return rate;
@@ -394,7 +484,7 @@ long Clip::media_length() {
case MEDIA_TYPE_SEQUENCE:
{
Sequence* s = media_->to_sequence().get();
return rescale_frame_number(s->getEndFrame(), s->frame_rate, fr);
return rescale_frame_number(s->GetEndFrame(), s->frame_rate, fr);
}
}
}
+12 -9
View File
@@ -36,8 +36,8 @@
#include "project/media.h"
#include "project/footage.h"
#include "rendering/framebufferobject.h"
#include "marker.h"
#include "track.h"
struct ClipSpeed {
ClipSpeed();
@@ -47,16 +47,19 @@ struct ClipSpeed {
using ClipPtr = std::shared_ptr<Clip>;
class Sequence;
class Clip {
public:
Clip(Sequence *s);
Clip(Track *s);
~Clip();
ClipPtr copy(Sequence *s);
ClipPtr copy(Track *s);
void Save(QXmlStreamWriter& stream);
bool IsActiveAt(long timecode);
bool IsSelected(bool containing = true);
bool IsTransitionSelected(TransitionType type);
Track::Type type();
const QColor& color();
void set_color(int r, int g, int b);
@@ -91,8 +94,8 @@ public:
long timeline_out(bool with_transition = false);
void set_timeline_out(long t);
int track();
void set_track(int t);
Track* track();
void set_track(Track* t);
bool reversed();
void set_reversed(bool r);
@@ -117,7 +120,7 @@ public:
long length();
void refactor_frame_rate(ComboAction* ca, double multiplier, bool change_timeline_points);
Sequence* sequence;
Track* parent_;
// markers
QVector<Marker>& get_markers();
@@ -159,11 +162,11 @@ public:
private:
// timeline variables (should be copied in copy())
Track* track_;
bool enabled_;
long clip_in_;
long timeline_in_;
long timeline_out_;
int track_;
QString name_;
Media* media_;
int media_stream_;
+9 -1
View File
@@ -32,7 +32,7 @@
#include <QInputDialog>
#include <QCoreApplication>
void draw_marker(QPainter &p, int x, int y, int bottom, bool selected) {
void Marker::Draw(QPainter &p, int x, int y, int bottom, bool selected) {
const QPoint points[5] = {
QPoint(x, bottom),
QPoint(x + MARKER_SIZE, bottom - MARKER_SIZE),
@@ -126,3 +126,11 @@ void set_marker_internal(Sequence *seq) {
set_marker_internal(seq, clips);
}
void Marker::Save(QXmlStreamWriter &stream) const
{
stream.writeStartElement("marker");
stream.writeAttribute("frame", QString::number(frame));
stream.writeAttribute("name", name);
stream.writeEndElement();
}
+4 -2
View File
@@ -25,6 +25,7 @@
#include <QString>
#include <QPainter>
#include <QXmlStreamWriter>
#include <memory>
class Sequence;
@@ -33,9 +34,10 @@ using SequencePtr = std::shared_ptr<Sequence>;
struct Marker {
long frame;
QString name;
};
void draw_marker(QPainter& p, int x, int y, int bottom, bool selected);
void Save(QXmlStreamWriter& stream) const;
static void Draw(QPainter& p, int x, int y, int bottom, bool selected);
};
void set_marker_internal(Sequence *seq, const QVector<int>& clips);
void set_marker_internal(Sequence* seq);
-2
View File
@@ -24,11 +24,9 @@
struct Selection {
long in;
long out;
int track;
long old_in;
long old_out;
int old_track;
bool trim_in;
};
+79 -101
View File
@@ -32,6 +32,12 @@ Sequence::Sequence() :
workarea_out(0),
wrapper_sequence(false)
{
// Set up tracks
track_lists.resize(Track::kTypeCount);
for (int i=0;i<track_lists.size();i++) {
track_lists[i] = std::make_shared<TrackList>(this, i);
}
}
SequencePtr Sequence::copy() {
@@ -44,16 +50,8 @@ SequencePtr Sequence::copy() {
s->audio_layout = audio_layout;
// deep copy all of the sequence's clips
s->clips.resize(clips.size());
for (int i=0;i<clips.size();i++) {
ClipPtr c = clips.at(i);
if (c == nullptr) {
s->clips[i] = nullptr;
} else {
ClipPtr copy = c->copy(s.get());
copy->linked = c->linked;
s->clips[i] = copy;
}
for (int i=0;i<track_lists.size();i++) {
s->track_lists[i] = track_lists.at(i).copy(s.get());
}
// copy all of the sequence's markers
@@ -62,41 +60,91 @@ SequencePtr Sequence::copy() {
return s;
}
long Sequence::getEndFrame() {
long end = 0;
for (int j=0;j<clips.size();j++) {
ClipPtr c = clips.at(j);
if (c != nullptr && c->timeline_out() > end) {
end = c->timeline_out();
}
void Sequence::Save(QXmlStreamWriter &stream)
{
stream.writeStartElement("sequence");
stream.writeAttribute("id", QString::number(save_id));
stream.writeAttribute("name", name);
stream.writeAttribute("width", QString::number(width));
stream.writeAttribute("height", QString::number(height));
stream.writeAttribute("framerate", QString::number(frame_rate, 'f', 10));
stream.writeAttribute("afreq", QString::number(audio_frequency));
stream.writeAttribute("alayout", QString::number(audio_layout));
if (this == olive::ActiveSequence.get()) {
stream.writeAttribute("open", "1");
}
return end;
stream.writeAttribute("workarea", QString::number(using_workarea));
stream.writeAttribute("workareaIn", QString::number(workarea_in));
stream.writeAttribute("workareaOut", QString::number(workarea_out));
QVector<TransitionPtr> transition_save_cache;
QVector<int> transition_clip_save_cache;
for (int j=0;j<tracks.size();j++) {
tracks.at(j)->Save(stream);
}
for (int j=0;j<markers.size();j++) {
markers.at(j).Save(stream);
}
stream.writeEndElement();
}
long Sequence::GetEndFrame() {
long end_frame = 0;
for (int i=0;i<tracks.size();i++) {
end_frame = qMax(tracks.at(i)->GetEndFrame(), end_frame);
}
return end_frame;
}
QVector<Clip *> Sequence::GetAllClips()
{
QVector<Clip*> all_clips;
for (int i=0;i<tracks.size();i++) {
all_clips.append(tracks.at(i)->GetAllClips());
}
return all_clips;
}
TrackList *Sequence::GetTrackList(Track::Type type)
{
return track_lists.at(type).get();
}
void Sequence::Close()
{
for (int i=0;i<clips.size();i++) {
Clip* c = clips.at(i).get();
if (c != nullptr) {
c->Close(true);
}
QVector<Clip*> all_clips = GetAllClips();
for (int i=0;i<all_clips.size();i++) {
all_clips.at(i)->Close(true);
}
}
void Sequence::RefreshClips(Media *m) {
for (int i=0;i<clips.size();i++) {
ClipPtr c = clips.at(i);
void Sequence::RefreshClipsUsingMedia(Media *m) {
if (c != nullptr
&& (m == nullptr || c->media() == m)) {
QVector<Clip*> all_clips = GetAllClips();
for (int i=0;i<all_clips.size();i++) {
Clip* c = all_clips.at(i);
if (m == nullptr || c->media() == m) {
c->Close(true);
c->refresh();
}
}
}
QVector<Clip *> Sequence::SelectedClips(bool containing)
{
QVector<Clip*> all_clips = GetAllClips();
QVector<Clip*> selected_clips;
for (int i=0;i<clips.size();i++) {
@@ -164,81 +212,11 @@ Effect *Sequence::GetSelectedGizmo()
return gizmo_ptr;
}
bool Sequence::IsClipSelected(int clip_index, bool containing)
void Sequence::ClearSelections()
{
return IsClipSelected(clips.at(clip_index).get(), containing);
}
bool Sequence::IsClipSelected(Clip *clip, bool containing)
{
for (int i=0;i<selections.size();i++) {
const Selection& s = selections.at(i);
if (clip->track() == s.track && ((clip->timeline_in() >= s.in && clip->timeline_out() <= s.out)
|| (!containing && !(clip->timeline_in() < s.in && clip->timeline_out() < s.in)
&& !(clip->timeline_in() > s.in && clip->timeline_out() > s.in)))) {
return true;
}
for (int i=0;i<tracks.size();i++) {
tracks.at(i)->ClearSelections();
}
return false;
}
bool Sequence::IsTransitionSelected(Transition *t)
{
if (t == nullptr) {
return false;
}
Clip* c = t->parent_clip;
int transition_track = t->parent_clip->track();
long transition_in_point;
long transition_out_point;
// Get positions of the transition on the timeline
if (t == c->opening_transition.get()) {
transition_in_point = c->timeline_in();
transition_out_point = c->timeline_in() + t->get_true_length();
if (t->secondary_clip != nullptr) {
transition_in_point -= t->get_true_length();
}
} else {
transition_in_point = c->timeline_out() - t->get_true_length();
transition_out_point = c->timeline_out();
if (t->secondary_clip != nullptr) {
transition_out_point += t->get_true_length();
}
}
// See if there's a selection matching this
for (int i=0;i<selections.size();i++) {
if (selections.at(i).in <= transition_in_point
&& selections.at(i).out >= transition_out_point
&& selections.at(i).track == transition_track) {
return true;
}
}
return false;
}
void Sequence::getTrackLimits(int* video_tracks, int* audio_tracks) {
int vt = 0;
int at = 0;
for (int j=0;j<clips.size();j++) {
ClipPtr c = clips.at(j);
if (c != nullptr) {
if (c->track() < 0 && c->track() < vt) { // video clip
vt = c->track();
} else if (c->track() > at) {
at = c->track();
}
}
}
if (video_tracks != nullptr) *video_tracks = vt;
if (audio_tracks != nullptr) *audio_tracks = at;
}
// static variable for the currently active sequence
+14 -7
View File
@@ -27,21 +27,27 @@
#include "clip.h"
#include "marker.h"
#include "selection.h"
#include "tracklist.h"
class Sequence {
class Sequence : public QObject {
Q_OBJECT
public:
Sequence();
SequencePtr copy();
void Save(QXmlStreamWriter& stream);
QString name;
void getTrackLimits(int* video_tracks, int* audio_tracks);
long getEndFrame();
int width;
int height;
double frame_rate;
int audio_frequency;
int audio_layout;
long GetEndFrame();
QVector<Clip*> GetAllClips();
TrackList* GetTrackList(Track::Type type);
/**
* @brief Close all open clips in a Sequence
*
@@ -55,17 +61,17 @@ public:
*/
void Close();
void RefreshClips(Media* m = nullptr);
void RefreshClipsUsingMedia(Media* m = nullptr);
QVector<Clip*> SelectedClips(bool containing = true);
QVector<int> SelectedClipIndexes();
Effect* GetSelectedGizmo();
bool IsClipSelected(int clip_index, bool containing = true);
bool IsClipSelected(Clip* clip, bool containing = true);
bool IsTransitionSelected(Transition* t);
QVector<Selection> selections;
void ClearSelections();
long playhead;
bool using_workarea;
@@ -77,7 +83,8 @@ public:
int save_id;
QVector<Marker> markers;
QVector<ClipPtr> clips;
private:
QVector<TrackList*> track_lists;
};
using SequencePtr = std::shared_ptr<Sequence>;
+174
View File
@@ -0,0 +1,174 @@
#include "track.h"
#include "timeline/clip.h"
int olive::timeline::kTrackDefaultHeight = 40;
int olive::timeline::kTrackMinHeight = 30;
int olive::timeline::kTrackHeightIncrement = 10;
Track::Track(TrackList* parent, Type type) :
parent_(parent),
type_(type)
{
}
Track *Track::copy(TrackList *parent)
{
Track* t = new Track(parent, type_);
t->ResizeClipArray(ClipCount());
for (int i=0;i<clips_.size();i++) {
ClipPtr c = clips_.at(i);
ClipPtr copy = c->copy(t);
copy->linked = c->linked;
t->clips_[i] = copy;
}
return t;
}
void Track::Save(QXmlStreamWriter &stream)
{
stream.writeStartElement("track");
for (int j=0;j<clips_.size();j++) {
Clip* c = clips_.at(j).get();
if (c != nullptr) {
stream.writeStartElement("clip");
stream.writeAttribute("id", QString::number(j));
c->Save(stream);
stream.writeEndElement(); // clip
}
}
stream.writeEndElement(); // track
}
Track::Type Track::type()
{
return type_;
}
int Track::height()
{
return height_;
}
void Track::set_height(int h)
{
height_ = h;
}
void Track::AddClip(ClipPtr clip)
{
clips_.append(clip);
if (clip->track() != nullptr) {
clip->track()->RemoveClip(clip.get());
}
clip->set_track(this);
}
void Track::RemoveClip(int i)
{
clips_.removeAt(i);
}
void Track::RemoveClip(Clip *c)
{
for (int i=0;i<clips_.size();i++) {
if (clips_.at(i).get() == c) {
clips_.removeAt(i);
return;
}
}
}
void Track::ResizeClipArray(int new_size)
{
clips_.resize(new_size);
}
QVector<ClipPtr> Track::GetAllClips()
{
return clips_;
}
bool Track::IsClipSelected(int clip_index, bool containing)
{
return IsClipSelected(clips_.at(clip_index).get(), containing);
}
bool Track::IsClipSelected(Clip *clip, bool containing)
{
for (int i=0;i<selections_.size();i++) {
const Selection& s = selections_.at(i);
if (((clip->timeline_in() >= s.in && clip->timeline_out() <= s.out)
|| (!containing && !(clip->timeline_in() < s.in && clip->timeline_out() < s.in)
&& !(clip->timeline_in() > s.in && clip->timeline_out() > s.in)))) {
return true;
}
}
return false;
}
bool Track::IsTransitionSelected(Transition *t)
{
if (t == nullptr) {
return false;
}
Clip* c = t->parent_clip;
long transition_in_point;
long transition_out_point;
// Get positions of the transition on the timeline
if (t == c->opening_transition.get()) {
transition_in_point = c->timeline_in();
transition_out_point = c->timeline_in() + t->get_true_length();
if (t->secondary_clip != nullptr) {
transition_in_point -= t->get_true_length();
}
} else {
transition_in_point = c->timeline_out() - t->get_true_length();
transition_out_point = c->timeline_out();
if (t->secondary_clip != nullptr) {
transition_out_point += t->get_true_length();
}
}
// See if there's a selection matching this
for (int i=0;i<selections_.size();i++) {
const Selection& s = selections_.at(i);
if (s.in <= transition_in_point
&& s.out >= transition_out_point) {
return true;
}
}
return false;
}
void Track::ClearSelections()
{
selections_.clear();
}
long Track::GetEndFrame()
{
long end_frame = 0;
for (int i=0;i<clips_.size();i++) {
Clip* c = clips_.at(i).get();
if (c != nullptr) {
end_frame = qMax(end_frame, c->timeline_out(true));
}
}
return end_frame;
}
+79
View File
@@ -0,0 +1,79 @@
#ifndef TRACK_H
#define TRACK_H
#include <QVector>
#include <memory>
#include "effects/effect.h"
namespace olive {
namespace timeline {
const int kGhostThickness = 2;
const int kClipTextPadding = 3;
/**
* @brief Set default track sizes
*
* Olive has a few default constants used for adjusting track heights in the Timeline. For HiDPI, it makes
* sense to multiply these by the current DPI scale. It uses a variable from QApplication to do this multiplication,
* which means the QApplication instance needs to be instantiated before these are calculated. Therefore, call this
* function ONCE after QApplication is created to multiply the track heights correctly.
*/
void MultiplyTrackSizesByDPI();
extern int kTrackDefaultHeight;
extern int kTrackMinHeight;
extern int kTrackHeightIncrement;
}
}
class TrackList;
class Track : public QObject
{
Q_OBJECT
public:
enum Type {
kTypeVideo,
kTypeAudio,
kTypeSubtitle,
kTypeCount
};
Track(TrackList* parent, Type type);
Track* copy(TrackList* parent);
void Save(QXmlStreamWriter& stream);
Type type();
int height();
void set_height(int h);
void AddClip(ClipPtr clip);
int ClipCount();
ClipPtr GetClip(int i);
void RemoveClip(int i);
void RemoveClip(Clip* c);
QVector<ClipPtr> GetAllClips();
QVector<Clip*> GetSelectedClips();
bool IsClipSelected(int clip_index, bool containing = true);
bool IsClipSelected(Clip* clip, bool containing = true);
bool IsTransitionSelected(Transition* t);
void ClearSelections();
long GetEndFrame();
private:
void ResizeClipArray(int new_size);
TrackList* parent_;
Type type_;
int height_;
QVector<ClipPtr> clips_;
QVector<EffectPtr> effects_;
QVector<Selection> selections_;
};
#endif // TRACK_H
+50
View File
@@ -0,0 +1,50 @@
#include "tracklist.h"
TrackList::TrackList(Sequence *parent, Track::Type type) :
QObject(parent),
type_(type)
{
// Ensure we have at least one track
AddTrack();
}
TrackListPtr TrackList::copy(Sequence *parent)
{
TrackListPtr t = std::make_shared<TrackList>(parent, type_);
t->ResizeTrackArray(tracks_.size());
for (int i=0;i<tracks_.size();i++) {
t->tracks_[i] = tracks_.at(i)->copy(t.get());
}
return t;
}
void TrackList::AddTrack()
{
TrackPtr track = std::make_shared<Track>(this, type_);
tracks_.append(track);
}
void TrackList::RemoveTrack(int i)
{
if (tracks_.size() == 1) {
return;
}
tracks_.removeAt(i);
}
Track *TrackList::First()
{
return tracks_.first().get();
}
QVector<TrackPtr> TrackList::tracks()
{
return tracks_;
}
Sequence *TrackList::GetParent()
{
return static_cast<Sequence*>(parent());
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef TRACKLIST_H
#define TRACKLIST_H
#include "track.h"
class TrackList : public QObject
{
Q_OBJECT
public:
TrackList(Sequence* parent, Track::Type type);
TrackList* copy(Sequence* parent);
void AddTrack();
void RemoveTrack(int i);
Track* First();
QVector<Track*> tracks();
Sequence* GetParent();
private:
void ResizeTrackArray(int i);
Track::Type type_;
QVector<Track*> tracks_;
};
#endif // TRACKLIST_H
+14 -20
View File
@@ -58,6 +58,7 @@
#include "global/debug.h"
#include "effects/effect.h"
#include "effects/internal/solideffect.h"
#include "timeline/track.h"
#define MAX_TEXT_WIDTH 20
#define TRANSITION_BETWEEN_RANGE 40
@@ -123,7 +124,7 @@ void TimelineWidget::show_context_menu(const QPoint& pos) {
bool audio_clips_are_selected = false;
for (int i=0;i<selected_clips.size();i++) {
if (selected_clips.at(i)->track() < 0) {
if (selected_clips.at(i)->type() == Track::kTypeVideo) {
video_clips_are_selected = true;
} else {
audio_clips_are_selected = true;
@@ -200,30 +201,22 @@ void TimelineWidget::toggle_autoscale() {
}
void TimelineWidget::tooltip_timer_timeout() {
if (olive::ActiveSequence != nullptr) {
if (tooltip_clip < olive::ActiveSequence->clips.size()) {
ClipPtr c = olive::ActiveSequence->clips.at(tooltip_clip);
if (c != nullptr) {
QToolTip::showText(QCursor::pos(),
tr("%1\nStart: %2\nEnd: %3\nDuration: %4").arg(
c->name(),
frame_to_timecode(c->timeline_in(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate),
frame_to_timecode(c->timeline_out(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate),
frame_to_timecode(c->length(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate)
));
}
}
if (tooltip_clip != nullptr) {
QToolTip::showText(QCursor::pos(),
tr("%1\nStart: %2\nEnd: %3\nDuration: %4").arg(
tooltip_clip->name(),
frame_to_timecode(tooltip_clip->timeline_in(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate),
frame_to_timecode(tooltip_clip->timeline_out(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate),
frame_to_timecode(tooltip_clip->length(), olive::CurrentConfig.timecode_view, olive::ActiveSequence->frame_rate)
));
}
tooltip_timer.stop();
}
void TimelineWidget::open_sequence_properties() {
QList<Media*> sequence_items;
QList<Media*> all_top_level_items;
for (int i=0;i<olive::project_model.childCount();i++) {
all_top_level_items.append(olive::project_model.child(i));
}
panel_project->get_all_media_from_table(all_top_level_items, sequence_items, MEDIA_TYPE_SEQUENCE); // find all sequences in project
QVector<Media*> sequence_items = olive::project_model.GetAllSequences();
for (int i=0;i<sequence_items.size();i++) {
if (sequence_items.at(i)->to_sequence() == olive::ActiveSequence) {
NewSequenceDialog nsd(this, sequence_items.at(i));
@@ -231,6 +224,7 @@ void TimelineWidget::open_sequence_properties() {
return;
}
}
QMessageBox::critical(this, tr("Error"), tr("Couldn't locate media wrapper for sequence."));
}
+5 -7
View File
@@ -37,18 +37,16 @@
class Timeline;
struct TimelineTrackHeight {
int index;
int height;
};
bool same_sign(int a, int b);
void draw_waveform(ClipPtr clip, const FootageStream *ms, long media_length, QPainter* p, const QRect& clip_rect, int waveform_start, int waveform_limit, double zoom);
class TimelineWidget : public QWidget {
Q_OBJECT
public:
explicit TimelineWidget(QWidget *parent = 0);
explicit TimelineWidget(QWidget *parent);
void SetTracks(QVector<Track>& tracks);
QScrollBar* scrollBar;
bool bottom_align;
@@ -92,7 +90,7 @@ private:
SequencePtr self_created_sequence;
QTimer tooltip_timer;
int tooltip_clip;
Clip* tooltip_clip;
int scroll;