From ceb0078b2e7b36d65fb9fb6505f72808219c7b64 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 24 Dec 2018 00:59:33 +1100 Subject: [PATCH 1/9] started work on icon/thumbnail view --- io/config.cpp | 7 +++- io/config.h | 4 +++ mainwindow.cpp | 2 +- mainwindow.ui | 3 +- panels/project.cpp | 81 +++++++++++++++++++++++++++++-------------- panels/project.h | 12 ++++--- project/media.cpp | 9 +++++ ui/sourcetable.h | 2 +- ui/timelinewidget.cpp | 4 +-- 9 files changed, 88 insertions(+), 36 deletions(-) diff --git a/io/config.cpp b/io/config.cpp index bd0882f68..2ecb744ba 100644 --- a/io/config.cpp +++ b/io/config.cpp @@ -32,7 +32,8 @@ Config::Config() autoscroll(AUTOSCROLL_PAGE_SCROLL), audio_rate(48000), fast_seeking(false), - hover_focus(false) + hover_focus(false), + project_view_type(PROJECT_VIEW_TREE) {} void Config::load(QString path) { @@ -115,6 +116,9 @@ void Config::load(QString path) { } else if (stream.name() == "HoverFocus") { stream.readNext(); hover_focus = (stream.text() == "1"); + } else if (stream.name() == "ProjectViewType") { + stream.readNext(); + project_view_type = stream.text().toInt(); } } } @@ -163,6 +167,7 @@ void Config::save(QString path) { stream.writeTextElement("AudioRate", QString::number(audio_rate)); stream.writeTextElement("FastSeeking", QString::number(fast_seeking)); stream.writeTextElement("HoverFocus", QString::number(hover_focus)); + stream.writeTextElement("ProjectViewType", QString::number(project_view_type)); stream.writeEndElement(); // configuration stream.writeEndDocument(); // doc diff --git a/io/config.h b/io/config.h index 4092204ff..4972c9dd3 100644 --- a/io/config.h +++ b/io/config.h @@ -18,6 +18,9 @@ #define AUTOSCROLL_PAGE_SCROLL 1 #define AUTOSCROLL_SMOOTH_SCROLL 2 +#define PROJECT_VIEW_TREE 0 +#define PROJECT_VIEW_ICON 1 + struct Config { Config(); bool saved_layout; @@ -44,6 +47,7 @@ struct Config { int audio_rate; bool fast_seeking; bool hover_focus; + int project_view_type; void load(QString path); void save(QString path); diff --git a/mainwindow.cpp b/mainwindow.cpp index 404a6dc9b..ee01aa846 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -439,7 +439,7 @@ void MainWindow::new_project() { panel_project->new_project(); updateTitle(""); update_ui(false); - panel_project->source_table->update(); + panel_project->tree_view->update(); } } diff --git a/mainwindow.ui b/mainwindow.ui index 61cc110c8..6533a2453 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -33,7 +33,7 @@ 0 0 653 - 25 + 16 @@ -148,6 +148,7 @@ + diff --git a/panels/project.cpp b/panels/project.cpp index dc391ae0b..7d52ac2c0 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -70,26 +70,40 @@ Project::Project(QWidget *parent) : QWidget* dockWidgetContents = new QWidget(); QVBoxLayout* verticalLayout = new QVBoxLayout(dockWidgetContents); verticalLayout->setContentsMargins(0, 0, 0, 0); + verticalLayout->setSpacing(0); setWidget(dockWidgetContents); - source_table = new SourceTable(dockWidgetContents); - source_table->project_parent = this; - source_table->setAcceptDrops(true); - source_table->setEditTriggers(QAbstractItemView::NoEditTriggers); - source_table->setDragDropMode(QAbstractItemView::DragDrop); - source_table->setSelectionMode(QAbstractItemView::ExtendedSelection); - verticalLayout->addWidget(source_table); - //setWidget(source_table); - - //layout->addWidget(source_table); - sorter = new QSortFilterProxyModel(this); sorter->setSourceModel(&project_model); - source_table->setModel(sorter); + + tree_view = new SourceTable(dockWidgetContents); + tree_view->project_parent = this; + tree_view->setAcceptDrops(true); + tree_view->setEditTriggers(QAbstractItemView::NoEditTriggers); + tree_view->setDragDropMode(QAbstractItemView::DragDrop); + tree_view->setSelectionMode(QAbstractItemView::ExtendedSelection); + tree_view->setModel(sorter); + verticalLayout->addWidget(tree_view); + + icon_view = new QListView(dockWidgetContents); + icon_view->setModel(sorter); + icon_view->setIconSize(QSize(100, 100)); + icon_view->setViewMode(QListView::IconMode); + icon_view->setUniformItemSizes(true); + verticalLayout->addWidget(icon_view); + + QPushButton* tree_view_button = new QPushButton("Tree View"); + verticalLayout->addWidget(tree_view_button); + connect(tree_view_button, SIGNAL(clicked(bool)), this, SLOT(set_tree_view())); + QPushButton* icon_view_button = new QPushButton("Icon View"); + verticalLayout->addWidget(icon_view_button); + connect(icon_view_button, SIGNAL(clicked(bool)), this, SLOT(set_icon_view())); //retranslateUi(Project); setWindowTitle(QApplication::translate("Project", "Project", nullptr)); + + update_view_type(); } Project::~Project() { @@ -189,7 +203,7 @@ Sequence* create_sequence_from_media(QVector& media_list) { } void Project::duplicate_selected() { - QModelIndexList items = source_table->selectionModel()->selectedRows(); + QModelIndexList items = tree_view->selectionModel()->selectedRows(); bool duped = false; ComboAction* ca = new ComboAction(); for (int j=0;jselectionModel()->selectedRows(); + QModelIndexList selected_items = tree_view->selectionModel()->selectedRows(); if (selected_items.size() == 1) { Media* item = item_to_media(selected_items.at(0)); if (item->get_type() == MEDIA_TYPE_FOOTAGE) { @@ -230,13 +244,13 @@ void Project::replace_clip_media() { if (sequence == NULL) { QMessageBox::critical(this, "No active sequence", "No sequence is active, please open the sequence you want to replace clips from.", QMessageBox::Ok); } else { - QModelIndexList selected_items = source_table->selectionModel()->selectedRows(); + QModelIndexList selected_items = tree_view->selectionModel()->selectedRows(); if (selected_items.size() == 1) { Media* item = item_to_media(selected_items.at(0)); if (item->get_type() == MEDIA_TYPE_SEQUENCE && sequence == item->to_sequence()) { QMessageBox::critical(this, "Active sequence selected", "You cannot insert a sequence into itself, so no clips of this media would be in this sequence.", QMessageBox::Ok); } else { - ReplaceClipMediaDialog dialog(this, source_table, item); + ReplaceClipMediaDialog dialog(this, tree_view, item); dialog.exec(); } } @@ -244,7 +258,7 @@ void Project::replace_clip_media() { } void Project::open_properties() { - QModelIndexList selected_items = source_table->selectionModel()->selectedRows(); + QModelIndexList selected_items = tree_view->selectionModel()->selectedRows(); if (selected_items.size() == 1) { Media* item = item_to_media(selected_items.at(0)); switch (item->get_type()) { @@ -302,7 +316,7 @@ QString Project::get_file_name_from_path(const QString& path) { }*/ bool Project::is_focused() { - return source_table->hasFocus(); + return tree_view->hasFocus(); } Media* Project::new_folder(QString name) { @@ -347,7 +361,7 @@ bool delete_clips_in_clipboard_with_media(ComboAction* ca, Media* m) { void Project::delete_selected_media() { ComboAction* ca = new ComboAction(); - QModelIndexList selected_items = source_table->selectionModel()->selectedRows(); + QModelIndexList selected_items = tree_view->selectionModel()->selectedRows(); QList items; for (int i=0;isetSortingEnabled(false); - source_table->setSortingEnabled(true); + tree_view->setSortingEnabled(false); + tree_view->setSortingEnabled(true); // check if media is in use QVector parents; @@ -666,7 +680,7 @@ void Project::process_file_list(QStringList& files, bool recursive, Media* repla Media* Project::get_selected_folder() { // if one item is selected and it's a folder, return it - QModelIndexList selected_items = source_table->selectionModel()->selectedRows(); + QModelIndexList selected_items = tree_view->selectionModel()->selectedRows(); if (selected_items.size() == 1) { Media* m = item_to_media(selected_items.at(0)); if (m->get_type() == MEDIA_TYPE_FOLDER) return m; @@ -685,12 +699,12 @@ bool Project::reveal_media(void *media, QModelIndex parent) { // expand all folders leading to this media QModelIndex hierarchy = item.parent(); while (hierarchy.isValid()) { - source_table->setExpanded(hierarchy, true); + tree_view->setExpanded(hierarchy, true); hierarchy = hierarchy.parent(); } // select item - source_table->selectionModel()->select(item, QItemSelectionModel::Select); + tree_view->selectionModel()->select(item, QItemSelectionModel::Select); return true; } @@ -715,7 +729,7 @@ void Project::delete_clips_using_selected_media() { } else { ComboAction* ca = new ComboAction(); bool deleted = false; - QModelIndexList items = source_table->selectionModel()->selectedRows(); + QModelIndexList items = tree_view->selectionModel()->selectedRows(); for (int i=0;iclips.size();i++) { Clip* c = sequence->clips.at(i); if (c != NULL) { @@ -984,6 +998,21 @@ void Project::save_project(bool autorecovery) { } } +void Project::update_view_type() { + tree_view->setVisible(config.project_view_type == PROJECT_VIEW_TREE); + icon_view->setVisible(config.project_view_type == PROJECT_VIEW_ICON); +} + +void Project::set_icon_view() { + config.project_view_type = PROJECT_VIEW_ICON; + update_view_type(); +} + +void Project::set_tree_view() { + config.project_view_type = PROJECT_VIEW_TREE; + update_view_type(); +} + void Project::save_recent_projects() { // save to file QFile f(recent_proj_file); @@ -1094,7 +1123,7 @@ void MediaThrobber::stop(int icon_type, bool replace) { // redraw clips update_ui(replace); - panel_project->source_table->viewport()->update(); + panel_project->tree_view->viewport()->update(); item->throbber = NULL; deleteLater(); } diff --git a/panels/project.h b/panels/project.h index 563ae5ac0..f027c4298 100644 --- a/panels/project.h +++ b/panels/project.h @@ -20,6 +20,7 @@ class QXmlStreamReader; class QFile; class QSortFilterProxyModel; class ComboAction; +class QListView; #define LOAD_TYPE_VERSION 69 #define LOAD_TYPE_URL 70 @@ -40,10 +41,8 @@ Sequence* create_sequence_from_media(QVector &media_list); QString get_channel_layout_name(int channels, uint64_t layout); QString get_interlacing_name(int interlacing); -class Project : public QDockWidget -{ +class Project : public QDockWidget { Q_OBJECT - public: explicit Project(QWidget *parent = 0); ~Project(); @@ -68,7 +67,9 @@ public: QVector list_all_project_sequences(); - SourceTable* source_table; + SourceTable* tree_view; + QListView* icon_view; + QSortFilterProxyModel* sorter; QVector last_imported_media; @@ -94,6 +95,9 @@ private: QString get_file_name_from_path(const QString &path); QDir proj_dir; private slots: + void update_view_type(); + void set_icon_view(); + void set_tree_view(); void clear_recent_projects(); }; diff --git a/project/media.cpp b/project/media.cpp index bb01dc72e..4be8add33 100644 --- a/project/media.cpp +++ b/project/media.cpp @@ -253,6 +253,15 @@ QVariant Media::data(int column, int role) { switch (role) { case Qt::DecorationRole: if (column == 0) { + if (config.project_view_type == PROJECT_VIEW_ICON + && get_type() == MEDIA_TYPE_FOOTAGE) { + Footage* f = to_footage(); + if (f->video_tracks.size() > 0 + && f->video_tracks.at(0)->preview_done) { + return QIcon(QPixmap::fromImage(f->video_tracks.at(0)->video_preview)); + } + } + return icon; } break; diff --git a/ui/sourcetable.h b/ui/sourcetable.h index c2a2637a7..0e3428152 100644 --- a/ui/sourcetable.h +++ b/ui/sourcetable.h @@ -12,7 +12,7 @@ class SourceTable : public QTreeView { Q_OBJECT public: - SourceTable(QWidget* parent = 0); + SourceTable(QWidget* parent = 0); Project* project_parent; protected: void mousePressEvent(QMouseEvent*); diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index ba4d42fcb..c05782bf8 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -265,8 +265,8 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { QVector media_list; panel_timeline->importing_files = false; - if (event->source() == panel_project->source_table) { - QModelIndexList items = panel_project->source_table->selectionModel()->selectedRows(); + if (event->source() == panel_project->tree_view) { + QModelIndexList items = panel_project->tree_view->selectionModel()->selectedRows(); media_list.resize(items.size()); for (int i=0;iitem_to_media(items.at(i)); From 4992b189f4ef11ff7439ab623ad3791f59407351 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 24 Dec 2018 17:31:40 +1100 Subject: [PATCH 2/9] make square version of thumb for icon view --- io/previewgenerator.cpp | 6 ++++-- mainwindow.cpp | 18 +++++++++--------- project/footage.cpp | 14 ++++++++++++++ project/footage.h | 3 +++ project/media.cpp | 7 ++++--- ui/otreeview.cpp | 9 +++++++++ ui/otreeview.h | 16 ++++++++++++++++ 7 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 ui/otreeview.cpp create mode 100644 ui/otreeview.h diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 696c7987a..40a8d9d3b 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -128,6 +128,7 @@ bool PreviewGenerator::retrieve_preview(const QString& hash) { QFile f(thumb_path); if (f.exists() && ms->video_preview.load(thumb_path)) { //dout << "loaded thumb" << ms->file_index << "from" << thumb_path; + ms->make_square_thumb(); ms->preview_done = true; } else { found = false; @@ -263,7 +264,7 @@ void PreviewGenerator::generate_waveform() { static_cast(temp_frame->format), dstW, dstH, - static_cast(AV_PIX_FMT_RGB24), + static_cast(AV_PIX_FMT_RGBA), SWS_FAST_BILINEAR, NULL, NULL, @@ -274,7 +275,8 @@ void PreviewGenerator::generate_waveform() { linesize[0] = dstW*3; sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize); - s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888); + s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGBA8888); + s->make_square_thumb(); // is video interlaced? s->video_auto_interlacing = (temp_frame->interlaced_frame) ? ((temp_frame->top_field_first) ? VIDEO_TOP_FIELD_FIRST : VIDEO_BOTTOM_FIELD_FIRST) : VIDEO_PROGRESSIVE; diff --git a/mainwindow.cpp b/mainwindow.cpp index ee01aa846..adc24850e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -130,15 +130,6 @@ MainWindow::MainWindow(QWidget *parent) : layout()->invalidate(); - // TODO maybe replace these with non-pointers later on? - panel_sequence_viewer = new Viewer(this); - panel_footage_viewer = new Viewer(this); - panel_project = new Project(this); - panel_effect_controls = new EffectControls(this); - panel_timeline = new Timeline(this); - - setup_layout(false); - connect(ui->menuWindow, SIGNAL(aboutToShow()), this, SLOT(windowMenu_About_To_Be_Shown())); connect(ui->menu_View, SIGNAL(aboutToShow()), this, SLOT(viewMenu_About_To_Be_Shown())); connect(ui->menu_Tools, SIGNAL(aboutToShow()), this, SLOT(toolMenu_About_To_Be_Shown())); @@ -215,6 +206,15 @@ MainWindow::MainWindow(QWidget *parent) : } } + // TODO maybe replace these with non-pointers later on? + panel_sequence_viewer = new Viewer(this); + panel_footage_viewer = new Viewer(this); + panel_project = new Project(this); + panel_effect_controls = new EffectControls(this); + panel_timeline = new Timeline(this); + + setup_layout(false); + init_audio(); connect(ui->action_Undo, SIGNAL(triggered(bool)), this, SLOT(undo())); diff --git a/project/footage.cpp b/project/footage.cpp index 6dc841eb7..b54f5a4a3 100644 --- a/project/footage.cpp +++ b/project/footage.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "io/previewgenerator.h" extern "C" { @@ -55,3 +56,16 @@ FootageStream* Footage::get_stream_from_file_index(bool video, int index) { } return NULL; } + +void FootageStream::make_square_thumb() { + // generate square version for QListView? + int square_size = qMax(video_preview.width(), video_preview.height()); + QPixmap pixmap(square_size, square_size); + pixmap.fill(Qt::transparent); + QPainter p(&pixmap); + int diff = (video_preview.width() - video_preview.height())>>1; + int sqx = (diff < 0) ? -diff : 0; + int sqy = (diff > 0) ? diff : 0; + p.drawImage(sqx, sqy, video_preview); + video_preview_square = QIcon(pixmap); +} diff --git a/project/footage.h b/project/footage.h index 55442e3ed..015253173 100644 --- a/project/footage.h +++ b/project/footage.h @@ -7,6 +7,7 @@ #include #include #include +#include #define VIDEO_PROGRESSIVE 0 #define VIDEO_TOP_FIELD_FIRST 1 @@ -32,7 +33,9 @@ struct FootageStream { // preview thumbnail/waveform bool preview_done; QImage video_preview; + QIcon video_preview_square; QVector audio_preview; + void make_square_thumb(); }; struct Footage { diff --git a/project/media.cpp b/project/media.cpp index 4be8add33..cec9c7f8f 100644 --- a/project/media.cpp +++ b/project/media.cpp @@ -8,6 +8,8 @@ #include "panels/project.h" #include "projectmodel.h" +#include + #include "debug.h" extern "C" { @@ -253,12 +255,11 @@ QVariant Media::data(int column, int role) { switch (role) { case Qt::DecorationRole: if (column == 0) { - if (config.project_view_type == PROJECT_VIEW_ICON - && get_type() == MEDIA_TYPE_FOOTAGE) { + if (get_type() == MEDIA_TYPE_FOOTAGE) { Footage* f = to_footage(); if (f->video_tracks.size() > 0 && f->video_tracks.at(0)->preview_done) { - return QIcon(QPixmap::fromImage(f->video_tracks.at(0)->video_preview)); + return f->video_tracks.at(0)->video_preview_square; } } diff --git a/ui/otreeview.cpp b/ui/otreeview.cpp new file mode 100644 index 000000000..9ea03a828 --- /dev/null +++ b/ui/otreeview.cpp @@ -0,0 +1,9 @@ +#include "otreeview.h" + +OTreeView::OTreeView(QWidget *parent) : QTreeView(parent) { + setSortingEnabled(true); + sortByColumn(0, Qt::AscendingOrder); + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu())); + connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&))); +} diff --git a/ui/otreeview.h b/ui/otreeview.h new file mode 100644 index 000000000..810f8b5ec --- /dev/null +++ b/ui/otreeview.h @@ -0,0 +1,16 @@ +#ifndef OTREEVIEW_H +#define OTREEVIEW_H + +#include + +#include "ui/sourcetable.h" + +class OTreeView : public QTreeView { + Q_OBJECT +public: + OTreeView(QWidget* parent = 0); +private: + +}; + +#endif // OTREEVIEW_H From 28bdda40233db9735209ab5320db0a5946181b96 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 24 Dec 2018 20:45:07 +1100 Subject: [PATCH 3/9] generate thumbs with alpha --- io/previewgenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 40a8d9d3b..bb24f3cbd 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -256,7 +256,7 @@ void PreviewGenerator::generate_waveform() { if (!s->preview_done) { int dstH = 120; int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height); - uint8_t* data = new uint8_t[dstW*dstH*3]; + uint8_t* data = new uint8_t[dstW*dstH*4]; sws_ctx = sws_getContext( temp_frame->width, @@ -272,7 +272,7 @@ void PreviewGenerator::generate_waveform() { ); int linesize[AV_NUM_DATA_POINTERS]; - linesize[0] = dstW*3; + linesize[0] = dstW*4; sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize); s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGBA8888); From abff5da67b766a941c9ccf33c2cb348561a80f59 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 24 Dec 2018 23:20:55 +1100 Subject: [PATCH 4/9] added directory browsing and icon size slider --- icons/dirup-disabled.png | Bin 0 -> 1933 bytes icons/dirup.png | Bin 0 -> 1926 bytes icons/icons.qrc | 2 ++ olive.pro | 6 ++-- panels/project.cpp | 63 +++++++++++++++++++++++++++++++++++---- panels/project.h | 10 +++++-- ui/sourceiconview.cpp | 17 +++++++++++ ui/sourceiconview.h | 18 +++++++++++ 8 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 icons/dirup-disabled.png create mode 100644 icons/dirup.png create mode 100644 ui/sourceiconview.cpp create mode 100644 ui/sourceiconview.h diff --git a/icons/dirup-disabled.png b/icons/dirup-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..f23fa3f683abe3a5f18474cbb18489b37d1820f4 GIT binary patch literal 1933 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 p(-o=R@{-Ztransition-tool.png transition-tool-disabled.png error.png + dirup.png + dirup-disabled.png diff --git a/olive.pro b/olive.pro index 78bd16870..ef37b525d 100644 --- a/olive.pro +++ b/olive.pro @@ -96,7 +96,8 @@ SOURCES += \ project/effectgizmo.cpp \ io/clipboard.cpp \ dialogs/stabilizerdialog.cpp \ - io/avtogl.cpp + io/avtogl.cpp \ + ui/sourceiconview.cpp HEADERS += \ mainwindow.h \ @@ -172,7 +173,8 @@ HEADERS += \ project/effectgizmo.h \ io/clipboard.h \ dialogs/stabilizerdialog.h \ - io/avtogl.h + io/avtogl.h \ + ui/sourceiconview.h FORMS += \ mainwindow.ui \ diff --git a/panels/project.cpp b/panels/project.cpp index 7d52ac2c0..70346b558 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -23,6 +23,7 @@ #include "io/clipboard.h" #include "project/media.h" #include "ui/sourcetable.h" +#include "ui/sourceiconview.h" #include "debug.h" #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include @@ -86,12 +86,47 @@ Project::Project(QWidget *parent) : tree_view->setModel(sorter); verticalLayout->addWidget(tree_view); - icon_view = new QListView(dockWidgetContents); + icon_view_container = new QWidget(); + + QVBoxLayout* icon_view_container_layout = new QVBoxLayout(); + icon_view_container_layout->setMargin(0); + icon_view_container_layout->setSpacing(0); + icon_view_container->setLayout(icon_view_container_layout); + + QHBoxLayout* icon_view_controls = new QHBoxLayout(); + icon_view_controls->setMargin(0); + icon_view_controls->setSpacing(0); + + QIcon directory_up_button; + directory_up_button.addFile(":/icons/dirup.png", QSize(), QIcon::Normal); + directory_up_button.addFile(":/icons/dirup-disabled.png", QSize(), QIcon::Disabled); + + directory_up = new QPushButton(); + directory_up->setIcon(directory_up_button); + directory_up->setEnabled(false); + icon_view_controls->addWidget(directory_up); + + icon_view_controls->addStretch(); + + QSlider* icon_size_slider = new QSlider(Qt::Horizontal); + icon_size_slider->setMinimum(16); + icon_size_slider->setMaximum(120); + icon_view_controls->addWidget(icon_size_slider); + connect(icon_size_slider, SIGNAL(valueChanged(int)), this, SLOT(set_icon_view_size(int))); + + icon_view_container_layout->addLayout(icon_view_controls); + + icon_view = new SourceIconView(dockWidgetContents); + icon_view->project_parent = this; icon_view->setModel(sorter); icon_view->setIconSize(QSize(100, 100)); icon_view->setViewMode(QListView::IconMode); icon_view->setUniformItemSizes(true); - verticalLayout->addWidget(icon_view); + icon_view_container_layout->addWidget(icon_view); + + icon_size_slider->setValue(icon_view->iconSize().height()); + + verticalLayout->addWidget(icon_view_container); QPushButton* tree_view_button = new QPushButton("Tree View"); verticalLayout->addWidget(tree_view_button); @@ -100,6 +135,9 @@ Project::Project(QWidget *parent) : verticalLayout->addWidget(icon_view_button); connect(icon_view_button, SIGNAL(clicked(bool)), this, SLOT(set_icon_view())); + connect(directory_up, SIGNAL(clicked(bool)), this, SLOT(go_up_dir())); + connect(icon_view, SIGNAL(changed_root()), this, SLOT(set_up_dir_enabled())); + //retranslateUi(Project); setWindowTitle(QApplication::translate("Project", "Project", nullptr)); @@ -1000,7 +1038,7 @@ void Project::save_project(bool autorecovery) { void Project::update_view_type() { tree_view->setVisible(config.project_view_type == PROJECT_VIEW_TREE); - icon_view->setVisible(config.project_view_type == PROJECT_VIEW_ICON); + icon_view_container->setVisible(config.project_view_type == PROJECT_VIEW_ICON); } void Project::set_icon_view() { @@ -1032,7 +1070,22 @@ void Project::save_recent_projects() { void Project::clear_recent_projects() { recent_projects.clear(); - save_recent_projects(); + save_recent_projects(); +} + +void Project::set_icon_view_size(int s) { + icon_view->setIconSize(QSize(s, s)); + // icon_view->setGridSize(QSize(s, s)); +} + +void Project::set_up_dir_enabled() { + dout << icon_view->rootIndex().isValid(); + directory_up->setEnabled(icon_view->rootIndex().isValid()); +} + +void Project::go_up_dir() { + icon_view->setRootIndex(icon_view->rootIndex().parent()); + set_up_dir_enabled(); } void Project::add_recent_project(QString url) { diff --git a/panels/project.h b/panels/project.h index f027c4298..b1e223855 100644 --- a/panels/project.h +++ b/panels/project.h @@ -20,7 +20,8 @@ class QXmlStreamReader; class QFile; class QSortFilterProxyModel; class ComboAction; -class QListView; +class SourceIconView; +class QPushButton; #define LOAD_TYPE_VERSION 69 #define LOAD_TYPE_URL 70 @@ -68,7 +69,7 @@ public: QVector list_all_project_sequences(); SourceTable* tree_view; - QListView* icon_view; + SourceIconView* icon_view; QSortFilterProxyModel* sorter; @@ -94,11 +95,16 @@ private: void list_all_sequences_worker(QVector *list, Media* parent); QString get_file_name_from_path(const QString &path); QDir proj_dir; + QWidget* icon_view_container; + QPushButton* directory_up; private slots: void update_view_type(); void set_icon_view(); void set_tree_view(); void clear_recent_projects(); + void set_icon_view_size(int); + void set_up_dir_enabled(); + void go_up_dir(); }; class MediaThrobber : public QObject { diff --git a/ui/sourceiconview.cpp b/ui/sourceiconview.cpp new file mode 100644 index 000000000..d1de9e4c2 --- /dev/null +++ b/ui/sourceiconview.cpp @@ -0,0 +1,17 @@ +#include "sourceiconview.h" + +#include "panels/project.h" +#include "project/media.h" +#include "debug.h" + +SourceIconView::SourceIconView(QWidget *parent) : QListView(parent) {} + +void SourceIconView::mouseDoubleClickEvent(QMouseEvent *event) { + if (selectedIndexes().size() == 1) { + Media* m = project_parent->item_to_media(selectedIndexes().at(0)); + if (m->get_type() == MEDIA_TYPE_FOLDER) { + setRootIndex(selectedIndexes().at(0)); + emit changed_root(); + } + } +} diff --git a/ui/sourceiconview.h b/ui/sourceiconview.h new file mode 100644 index 000000000..ea255d10d --- /dev/null +++ b/ui/sourceiconview.h @@ -0,0 +1,18 @@ +#ifndef SOURCEICONVIEW_H +#define SOURCEICONVIEW_H + +#include + +class Project; + +class SourceIconView : public QListView { + Q_OBJECT +public: + SourceIconView(QWidget* parent = 0); + Project* project_parent; + void mouseDoubleClickEvent(QMouseEvent *event); +signals: + void changed_root(); +}; + +#endif // SOURCEICONVIEW_H From 06ca2bdfcd1ad011666f3aa16e042aa42e0ec99e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 24 Dec 2018 23:33:23 +1100 Subject: [PATCH 5/9] fixed reveal in project --- panels/project.cpp | 12 ++++++------ panels/project.h | 2 +- ui/timelinewidget.h | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/panels/project.cpp b/panels/project.cpp index 70346b558..39f595d63 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -726,23 +726,25 @@ Media* Project::get_selected_folder() { return NULL; } -bool Project::reveal_media(void *media, QModelIndex parent) { +bool Project::reveal_media(Media *media, QModelIndex parent) { for (int i=0;iget_type() == MEDIA_TYPE_FOLDER) { if (reveal_media(media, item)) return true; - } else if (m->to_object() == media) { + } else if (m == media) { // expand all folders leading to this media - QModelIndex hierarchy = item.parent(); + QModelIndex sorted_index = sorter->mapFromSource(item); + + QModelIndex hierarchy = sorted_index.parent(); while (hierarchy.isValid()) { tree_view->setExpanded(hierarchy, true); hierarchy = hierarchy.parent(); } // select item - tree_view->selectionModel()->select(item, QItemSelectionModel::Select); + tree_view->selectionModel()->select(sorted_index, QItemSelectionModel::Select); return true; } @@ -1075,11 +1077,9 @@ void Project::clear_recent_projects() { void Project::set_icon_view_size(int s) { icon_view->setIconSize(QSize(s, s)); - // icon_view->setGridSize(QSize(s, s)); } void Project::set_up_dir_enabled() { - dout << icon_view->rootIndex().isValid(); directory_up->setEnabled(icon_view->rootIndex().isValid()); } diff --git a/panels/project.h b/panels/project.h index b1e223855..df36e5284 100644 --- a/panels/project.h +++ b/panels/project.h @@ -54,7 +54,7 @@ public: void process_file_list(QStringList& files, bool recursive = false, Media* replace = NULL, Media *parent = NULL); void replace_media(Media* item, QString filename); Media *get_selected_folder(); - bool reveal_media(void* media, QModelIndex parent = QModelIndex()); + bool reveal_media(Media *media, QModelIndex parent = QModelIndex()); void add_recent_project(QString url); void new_project(); diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h index 2ba01cab4..20e4bfea9 100644 --- a/ui/timelinewidget.h +++ b/ui/timelinewidget.h @@ -19,6 +19,7 @@ class TimelineAction; class QScrollBar; class SetSelectionsCommand; class QPainter; +class Media; bool same_sign(int a, int b); void draw_waveform(Clip* clip, FootageStream* ms, long media_length, QPainter* p, const QRect& clip_rect, int waveform_start, int waveform_limit, double zoom); @@ -65,7 +66,7 @@ private: // used for "right click ripple" long rc_ripple_min; long rc_ripple_max; - void* rc_reveal_media; + Media* rc_reveal_media; QTimer tooltip_timer; int tooltip_clip; From c159e598a7269108eb8c02a3a57a541a2c443fc0 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 25 Dec 2018 01:10:20 +1100 Subject: [PATCH 6/9] completion of icon view --- olive.pro | 6 +- panels/project.cpp | 19 ++- panels/project.h | 2 + project/clip.cpp | 7 +- project/sourcescommon.cpp | 279 ++++++++++++++++++++++++++++++++++++++ project/sourcescommon.h | 39 ++++++ project/undo.cpp | 3 +- project/undo.h | 3 +- ui/sourceiconview.cpp | 52 ++++++- ui/sourceiconview.h | 8 ++ ui/sourcetable.cpp | 250 +--------------------------------- ui/sourcetable.h | 13 +- 12 files changed, 413 insertions(+), 268 deletions(-) create mode 100644 project/sourcescommon.cpp create mode 100644 project/sourcescommon.h diff --git a/olive.pro b/olive.pro index ef37b525d..ad08b1454 100644 --- a/olive.pro +++ b/olive.pro @@ -97,7 +97,8 @@ SOURCES += \ io/clipboard.cpp \ dialogs/stabilizerdialog.cpp \ io/avtogl.cpp \ - ui/sourceiconview.cpp + ui/sourceiconview.cpp \ + project/sourcescommon.cpp HEADERS += \ mainwindow.h \ @@ -174,7 +175,8 @@ HEADERS += \ io/clipboard.h \ dialogs/stabilizerdialog.h \ io/avtogl.h \ - ui/sourceiconview.h + ui/sourceiconview.h \ + project/sourcescommon.h FORMS += \ mainwindow.ui \ diff --git a/panels/project.cpp b/panels/project.cpp index 39f595d63..cad3eaefe 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -24,6 +24,7 @@ #include "project/media.h" #include "ui/sourcetable.h" #include "ui/sourceiconview.h" +#include "project/sourcescommon.h" #include "debug.h" #include @@ -74,6 +75,8 @@ Project::Project(QWidget *parent) : setWidget(dockWidgetContents); + sources_common = new SourcesCommon(this); + sorter = new QSortFilterProxyModel(this); sorter->setSourceModel(&project_model); @@ -128,13 +131,6 @@ Project::Project(QWidget *parent) : verticalLayout->addWidget(icon_view_container); - QPushButton* tree_view_button = new QPushButton("Tree View"); - verticalLayout->addWidget(tree_view_button); - connect(tree_view_button, SIGNAL(clicked(bool)), this, SLOT(set_tree_view())); - QPushButton* icon_view_button = new QPushButton("Icon View"); - verticalLayout->addWidget(icon_view_button); - connect(icon_view_button, SIGNAL(clicked(bool)), this, SLOT(set_icon_view())); - connect(directory_up, SIGNAL(clicked(bool)), this, SLOT(go_up_dir())); connect(icon_view, SIGNAL(changed_root()), this, SLOT(set_up_dir_enabled())); @@ -1041,6 +1037,15 @@ void Project::save_project(bool autorecovery) { void Project::update_view_type() { tree_view->setVisible(config.project_view_type == PROJECT_VIEW_TREE); icon_view_container->setVisible(config.project_view_type == PROJECT_VIEW_ICON); + + switch (config.project_view_type) { + case PROJECT_VIEW_TREE: + sources_common->view = tree_view; + break; + case PROJECT_VIEW_ICON: + sources_common->view = icon_view; + break; + } } void Project::set_icon_view() { diff --git a/panels/project.h b/panels/project.h index df36e5284..71fdd0137 100644 --- a/panels/project.h +++ b/panels/project.h @@ -22,6 +22,7 @@ class QSortFilterProxyModel; class ComboAction; class SourceIconView; class QPushButton; +class SourcesCommon; #define LOAD_TYPE_VERSION 69 #define LOAD_TYPE_URL 70 @@ -70,6 +71,7 @@ public: SourceTable* tree_view; SourceIconView* icon_view; + SourcesCommon* sources_common; QSortFilterProxyModel* sorter; diff --git a/project/clip.cpp b/project/clip.cpp index df0927544..65fbdb50a 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -109,7 +109,12 @@ void Clip::refresh() { // validates media if it was replaced if (replaced && media != NULL && media->get_type() == MEDIA_TYPE_FOOTAGE) { Footage* m = media->to_footage(); - media_stream = (track < 0) ? m->video_tracks.at(0)->file_index : m->audio_tracks.at(0)->file_index; + + if (track < 0 && m->video_tracks.size() > 0) { + media_stream = m->video_tracks.at(0)->file_index; + } else if (track >= 0 && m->audio_tracks.size() > 0) { + media_stream = m->audio_tracks.at(0)->file_index; + } } replaced = false; diff --git a/project/sourcescommon.cpp b/project/sourcescommon.cpp new file mode 100644 index 000000000..510ff8a32 --- /dev/null +++ b/project/sourcescommon.cpp @@ -0,0 +1,279 @@ +#include "sourcescommon.h" + +#include "panels/panels.h" +#include "project/media.h" +#include "project/undo.h" +#include "panels/timeline.h" +#include "panels/project.h" +#include "project/footage.h" +#include "panels/viewer.h" +#include "io/config.h" +#include "mainwindow.h" + +#include +#include +#include +#include +#include + +SourcesCommon::SourcesCommon(Project* parent) : + project_parent(parent), + editing_item(NULL) +{ + rename_timer.setInterval(1000); + connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval())); +} + +void SourcesCommon::create_seq_from_selected() { + if (!selected_items.isEmpty()) { + QVector media_list; + for (int i=0;iitem_to_media(selected_items.at(i))); + } + + ComboAction* ca = new ComboAction(); + Sequence* s = create_sequence_from_media(media_list); + + // add clips to it + panel_timeline->create_ghosts_from_media(s, 0, media_list); + panel_timeline->add_clips_from_ghosts(ca, s); + + project_parent->new_sequence(ca, s, true, NULL); + undo_stack.push(ca); + } +} + +void SourcesCommon::show_context_menu(QWidget* parent, const QModelIndexList& items) { + QMenu menu(parent); + + selected_items = items; + + QAction* import_action = menu.addAction("Import..."); + QObject::connect(import_action, SIGNAL(triggered(bool)), project_parent, SLOT(import_dialog())); + + QAction* new_folder_action = menu.addAction("New Folder..."); + QObject::connect(new_folder_action, SIGNAL(triggered(bool)), mainWindow, SLOT(on_actionFolder_triggered())); + + if (items.size() > 0) { + Media* m = project_parent->item_to_media(items.at(0)); + + if (items.size() == 1) { + // replace footage + int type = m->get_type(); + if (type == MEDIA_TYPE_FOOTAGE) { + QAction* replace_action = menu.addAction("Replace/Relink Media"); + QObject::connect(replace_action, SIGNAL(triggered(bool)), project_parent, SLOT(replace_selected_file())); + +#if defined(Q_OS_WIN) + QAction* reveal_in_explorer = menu.addAction("Reveal in Explorer"); +#elif defined(Q_OS_MAC) + QAction* reveal_in_explorer = menu.addAction("Reveal in Finder"); +#else + QAction* reveal_in_explorer = menu.addAction("Reveal in File Manager"); +#endif + QObject::connect(reveal_in_explorer, SIGNAL(triggered(bool)), this, SLOT(reveal_in_browser())); + } + if (type != MEDIA_TYPE_FOLDER) { + QAction* replace_clip_media = menu.addAction("Replace Clips Using This Media"); + QObject::connect(replace_clip_media, SIGNAL(triggered(bool)), project_parent, SLOT(replace_clip_media())); + } + } + + // duplicate item + bool all_sequences = true; + bool all_footage = true; + for (int i=0;iget_type() != MEDIA_TYPE_SEQUENCE) { + all_sequences = false; + } + if (m->get_type() != MEDIA_TYPE_FOOTAGE) { + all_footage = false; + } + } + + // create sequence from + QAction* create_seq_from = menu.addAction("Create Sequence With This Media"); + QObject::connect(create_seq_from, SIGNAL(triggered(bool)), this, SLOT(create_seq_from_selected())); + + // ONLY sequences are selected + if (all_sequences) { + // ONLY sequences are selected + QAction* duplicate_action = menu.addAction("Duplicate"); + QObject::connect(duplicate_action, SIGNAL(triggered(bool)), project_parent, SLOT(duplicate_selected())); + } + + // ONLY footage is selected + if (all_footage) { + QAction* delete_footage_from_sequences = menu.addAction("Delete All Clips Using This Media"); + QObject::connect(delete_footage_from_sequences, SIGNAL(triggered(bool)), project_parent, SLOT(delete_clips_using_selected_media())); + } + + // delete media + QAction* delete_action = menu.addAction("Delete"); + QObject::connect(delete_action, SIGNAL(triggered(bool)), project_parent, SLOT(delete_selected_media())); + + if (items.size() == 1) { + QAction* properties_action = menu.addAction("Properties..."); + QObject::connect(properties_action, SIGNAL(triggered(bool)), project_parent, SLOT(open_properties())); + } + } + + menu.addSeparator(); + + QAction* tree_view_action = menu.addAction("Tree View"); + connect(tree_view_action, SIGNAL(triggered(bool)), project_parent, SLOT(set_tree_view())); + + QAction* icon_view_action = menu.addAction("Icon View"); + connect(icon_view_action, SIGNAL(triggered(bool)), project_parent, SLOT(set_icon_view())); + + menu.exec(QCursor::pos()); +} + +void SourcesCommon::mousePressEvent(QMouseEvent *) { + stop_rename_timer(); +} + +void SourcesCommon::item_click(Media *m, const QModelIndex& index) { + if (editing_item == m) { + rename_timer.start(); + } else { + editing_item = m; + editing_index = index; + } +} + +void SourcesCommon::mouseDoubleClickEvent(QMouseEvent *e, const QModelIndexList& selected_items) { + stop_rename_timer(); + if (selected_items.size() == 0) { + project_parent->import_dialog(); + } else if (selected_items.size() == 1) { + Media* item = project_parent->item_to_media(selected_items.at(0)); + switch (item->get_type()) { + case MEDIA_TYPE_FOOTAGE: + panel_footage_viewer->set_media(item); + panel_footage_viewer->setFocus(); + break; + case MEDIA_TYPE_SEQUENCE: + undo_stack.push(new ChangeSequenceAction(item->to_sequence())); + break; + } + } +} + +void SourcesCommon::dropEvent(QWidget* parent, QDropEvent *event, const QModelIndex& drop_item, const QModelIndexList& items) { + const QMimeData* mimeData = event->mimeData(); + Media* m = project_parent->item_to_media(drop_item); + if (mimeData->hasUrls()) { + // drag files in from outside + QList urls = mimeData->urls(); + if (!urls.isEmpty()) { + QStringList paths; + for (int i=0;iget_type() == MEDIA_TYPE_FOOTAGE + && !QFileInfo(paths.at(0)).isDir() + && config.drop_on_media_to_replace + && QMessageBox::question(parent, "Replace Media", "You dropped a file onto '" + m->get_name() + "'. Would you like to replace it with the dropped file?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { + replace = true; + project_parent->replace_media(m, paths.at(0)); + } + if (!replace) { + QModelIndex parent; + if (drop_item.isValid()) { + if (m->get_type() == MEDIA_TYPE_FOLDER) { + parent = drop_item; + } else { + parent = drop_item.parent(); + } + } + project_parent->process_file_list(paths, false, NULL, panel_project->item_to_media(parent)); + } + } + event->acceptProposedAction(); + } else { + event->ignore(); + + // dragging files within project + // if we dragged to the root OR dragged to a folder + if (!drop_item.isValid() || (drop_item.isValid() && m->get_type() == MEDIA_TYPE_FOLDER)) { + QVector move_items; + for (int i=0;iitem_to_media(item); + if (parent != drop_item && item != drop_item) { + bool ignore = false; + if (parent.isValid()) { + // if child belongs to a selected parent, assume the user is just moving the parent and ignore the child + QModelIndex par = parent; + while (par.isValid() && !ignore) { + for (int j=0;j 0) { + MediaMove* mm = new MediaMove(); + mm->to = m; + mm->items = move_items; + undo_stack.push(mm); + } + } + } +} + +void SourcesCommon::reveal_in_browser() { + Media* media = project_parent->item_to_media(selected_items.at(0)); + Footage* m = media->to_footage(); + +#if defined(Q_OS_WIN) + QStringList args; + args << "/select," << QDir::toNativeSeparators(m->url); + QProcess::startDetached("explorer", args); +#elif defined(Q_OS_MAC) + QStringList args; + args << "-e"; + args << "tell application \"Finder\""; + args << "-e"; + args << "activate"; + args << "-e"; + args << "select POSIX file \""+m->url+"\""; + args << "-e"; + args << "end tell"; + QProcess::startDetached("osascript", args); +#else + QDesktopServices::openUrl(QUrl::fromLocalFile(m->url.left(m->url.lastIndexOf('/')))); +#endif +} + +void SourcesCommon::stop_rename_timer() { + rename_timer.stop(); +} + +void SourcesCommon::rename_interval() { + stop_rename_timer(); + if (view->hasFocus() && editing_item != NULL) { + view->edit(editing_index); + } +} + +void SourcesCommon::item_renamed(Media* item) { + if (editing_item == item) { + MediaRename* mr = new MediaRename(item, "idk"); + undo_stack.push(mr); + editing_item = NULL; + } +} diff --git a/project/sourcescommon.h b/project/sourcescommon.h new file mode 100644 index 000000000..4522efdfa --- /dev/null +++ b/project/sourcescommon.h @@ -0,0 +1,39 @@ +#ifndef SOURCESCOMMON_H +#define SOURCESCOMMON_H + +#include +#include + +class Project; +class QMouseEvent; +class Media; +class QAbstractItemView; +class QDropEvent; + +class SourcesCommon : public QObject { + Q_OBJECT +public: + SourcesCommon(Project *parent); + QAbstractItemView* view; + void show_context_menu(QWidget* parent, const QModelIndexList &items); + + void mousePressEvent(QMouseEvent* e); + void mouseDoubleClickEvent(QMouseEvent* e, const QModelIndexList& selected_items); + void dropEvent(QWidget *parent, QDropEvent* e, const QModelIndex& drop_item, const QModelIndexList &items); + + void item_click(Media* m, const QModelIndex &index); +private slots: + void create_seq_from_selected(); + void reveal_in_browser(); + void rename_interval(); + void item_renamed(Media *item); +private: + Media* editing_item; + QModelIndex editing_index; + QModelIndexList selected_items; + Project* project_parent; + void stop_rename_timer(); + QTimer rename_timer; +}; + +#endif // SOURCESCOMMON_H diff --git a/project/undo.cpp b/project/undo.cpp index 17fe258d7..8e9132d82 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -592,6 +592,7 @@ void ReplaceMediaCommand::replace(QString& filename) { // replace media QStringList files; files.append(filename); + item->to_footage()->ready_lock.lock(); panel_project->process_file_list(files, false, item, NULL); } @@ -694,7 +695,7 @@ void EffectDeleteCommand::redo() { mainWindow->setWindowModified(true); } -MediaMove::MediaMove(SourceTable *s) : table(s), old_project_changed(mainWindow->isWindowModified()) {} +MediaMove::MediaMove() : old_project_changed(mainWindow->isWindowModified()) {} void MediaMove::undo() { for (int i=0;i items; Media* to; void undo(); void redo(); private: QVector froms; - SourceTable* table; bool old_project_changed; }; diff --git a/ui/sourceiconview.cpp b/ui/sourceiconview.cpp index d1de9e4c2..9617adc24 100644 --- a/ui/sourceiconview.cpp +++ b/ui/sourceiconview.cpp @@ -1,17 +1,67 @@ #include "sourceiconview.h" +#include + #include "panels/project.h" #include "project/media.h" +#include "project/sourcescommon.h" #include "debug.h" -SourceIconView::SourceIconView(QWidget *parent) : QListView(parent) {} +SourceIconView::SourceIconView(QWidget *parent) : QListView(parent) { + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&))); + connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu())); +} + +void SourceIconView::show_context_menu() { + project_parent->sources_common->show_context_menu(this, selectedIndexes()); +} + +void SourceIconView::item_click(const QModelIndex& index) { + if (selectionModel()->selectedRows().size() == 1 && index.column() == 0) { + project_parent->sources_common->item_click(project_parent->item_to_media(index), index); + } +} + +void SourceIconView::mousePressEvent(QMouseEvent* event) { + project_parent->sources_common->mousePressEvent(event); + if (!indexAt(event->pos()).isValid()) selectionModel()->clear(); + QListView::mousePressEvent(event); +} + +void SourceIconView::dragEnterEvent(QDragEnterEvent *event) { + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } else { + QListView::dragEnterEvent(event); + } +} + +void SourceIconView::dragMoveEvent(QDragMoveEvent *event) { + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } else { + QListView::dragMoveEvent(event); + } +} + +void SourceIconView::dropEvent(QDropEvent* event) { + QModelIndex drop_item = indexAt(event->pos()); + if (!drop_item.isValid()) drop_item = rootIndex(); + project_parent->sources_common->dropEvent(this, event, drop_item, selectedIndexes()); +} void SourceIconView::mouseDoubleClickEvent(QMouseEvent *event) { + bool default_behavior = true; if (selectedIndexes().size() == 1) { Media* m = project_parent->item_to_media(selectedIndexes().at(0)); if (m->get_type() == MEDIA_TYPE_FOLDER) { + default_behavior = false; setRootIndex(selectedIndexes().at(0)); emit changed_root(); } } + if (default_behavior) { + project_parent->sources_common->mouseDoubleClickEvent(event, selectedIndexes()); + } } diff --git a/ui/sourceiconview.h b/ui/sourceiconview.h index ea255d10d..9320a1628 100644 --- a/ui/sourceiconview.h +++ b/ui/sourceiconview.h @@ -10,9 +10,17 @@ class SourceIconView : public QListView { public: SourceIconView(QWidget* parent = 0); Project* project_parent; + + void mousePressEvent(QMouseEvent* event); void mouseDoubleClickEvent(QMouseEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent* event); signals: void changed_root(); +private slots: + void show_context_menu(); + void item_click(const QModelIndex& index); }; #endif // SOURCEICONVIEW_H diff --git a/ui/sourcetable.cpp b/ui/sourcetable.cpp index aa835f55d..75586e8b4 100644 --- a/ui/sourcetable.cpp +++ b/ui/sourcetable.cpp @@ -11,6 +11,7 @@ #include "mainwindow.h" #include "io/config.h" #include "project/media.h" +#include "project/sourcescommon.h" #include "debug.h" #include @@ -25,193 +26,30 @@ #include SourceTable::SourceTable(QWidget* parent) : QTreeView(parent) { - editing_item = NULL; setSortingEnabled(true); sortByColumn(0, Qt::AscendingOrder); - rename_timer.setInterval(1000); setContextMenuPolicy(Qt::CustomContextMenu); - connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval())); connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&))); connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu())); } void SourceTable::show_context_menu() { - QMenu menu(this); - - QAction* import_action = menu.addAction("Import..."); - connect(import_action, SIGNAL(triggered(bool)), project_parent, SLOT(import_dialog())); - - QAction* new_folder_action = menu.addAction("New Folder..."); - connect(new_folder_action, SIGNAL(triggered(bool)), mainWindow, SLOT(on_actionFolder_triggered())); - - QModelIndexList selected_items = selectionModel()->selectedRows(); - - if (selected_items.size() > 0) { - Media* m = project_parent->item_to_media(selected_items.at(0)); - - if (selected_items.size() == 1) { - // replace footage - int type = m->get_type(); - if (type == MEDIA_TYPE_FOOTAGE) { - QAction* replace_action = menu.addAction("Replace/Relink Media"); - connect(replace_action, SIGNAL(triggered(bool)), project_parent, SLOT(replace_selected_file())); - -#if defined(Q_OS_WIN) - QAction* reveal_in_explorer = menu.addAction("Reveal in Explorer"); -#elif defined(Q_OS_MAC) - QAction* reveal_in_explorer = menu.addAction("Reveal in Finder"); -#else - QAction* reveal_in_explorer = menu.addAction("Reveal in File Manager"); -#endif - connect(reveal_in_explorer, SIGNAL(triggered(bool)), this, SLOT(reveal_in_browser())); - } - if (type != MEDIA_TYPE_FOLDER) { - QAction* replace_clip_media = menu.addAction("Replace Clips Using This Media"); - connect(replace_clip_media, SIGNAL(triggered(bool)), project_parent, SLOT(replace_clip_media())); - } - } - - // duplicate item - bool all_sequences = true; - bool all_footage = true; - for (int i=0;iget_type() != MEDIA_TYPE_SEQUENCE) { - all_sequences = false; - } - if (m->get_type() != MEDIA_TYPE_FOOTAGE) { - all_footage = false; - } - } - - // create sequence from - QAction* create_seq_from = menu.addAction("Create Sequence With This Media"); - connect(create_seq_from, SIGNAL(triggered(bool)), this, SLOT(create_seq_from_selected())); - - // ONLY sequences are selected - if (all_sequences) { - // ONLY sequences are selected - QAction* duplicate_action = menu.addAction("Duplicate"); - connect(duplicate_action, SIGNAL(triggered(bool)), project_parent, SLOT(duplicate_selected())); - } - - // ONLY footage is selected - if (all_footage) { - QAction* delete_footage_from_sequences = menu.addAction("Delete All Clips Using This Media"); - connect(delete_footage_from_sequences, SIGNAL(triggered(bool)), project_parent, SLOT(delete_clips_using_selected_media())); - } - - // delete media - QAction* delete_action = menu.addAction("Delete"); - connect(delete_action, SIGNAL(triggered(bool)), project_parent, SLOT(delete_selected_media())); - - if (selected_items.size() == 1) { - QAction* properties_action = menu.addAction("Properties..."); - connect(properties_action, SIGNAL(triggered(bool)), project_parent, SLOT(open_properties())); - } - } - - menu.exec(QCursor::pos()); + project_parent->sources_common->show_context_menu(this, selectionModel()->selectedRows()); } -void SourceTable::create_seq_from_selected() { - QModelIndexList selected_items = selectionModel()->selectedRows(); - - if (!selected_items.isEmpty()) { - QVector media_list; - for (int i=0;iitem_to_media(selected_items.at(i))); - } - - ComboAction* ca = new ComboAction(); - Sequence* s = create_sequence_from_media(media_list); - - // add clips to it - panel_timeline->create_ghosts_from_media(s, 0, media_list); - panel_timeline->add_clips_from_ghosts(ca, s); - - project_parent->new_sequence(ca, s, true, NULL); - undo_stack.push(ca); - } -} - -void SourceTable::reveal_in_browser() { - QModelIndexList selected_items = selectionModel()->selectedRows(); - Media* media = project_parent->item_to_media(selected_items.at(0)); - Footage* m = media->to_footage(); - -#if defined(Q_OS_WIN) - QStringList args; - args << "/select," << QDir::toNativeSeparators(m->url); - QProcess::startDetached("explorer", args); -#elif defined(Q_OS_MAC) - QStringList args; - args << "-e"; - args << "tell application \"Finder\""; - args << "-e"; - args << "activate"; - args << "-e"; - args << "select POSIX file \""+m->url+"\""; - args << "-e"; - args << "end tell"; - QProcess::startDetached("osascript", args); -#else - QDesktopServices::openUrl(QUrl::fromLocalFile(m->url.left(m->url.lastIndexOf('/')))); -#endif -} - -void SourceTable::item_renamed(Media* item) { - if (editing_item == item) { - MediaRename* mr = new MediaRename(item, "idk"); - undo_stack.push(mr); - editing_item = NULL; - } -} - -void SourceTable::stop_rename_timer() { - rename_timer.stop(); -} - -void SourceTable::rename_interval() { - stop_rename_timer(); - if (hasFocus() && editing_item != NULL) { - edit(editing_index); - //editItem(editing_item, 0); - } -} void SourceTable::item_click(const QModelIndex& index) { if (selectionModel()->selectedRows().size() == 1 && index.column() == 0) { - Media* m = project_parent->item_to_media(index); - if (editing_item == m) { - rename_timer.start(); - } else { - editing_item = m; - editing_index = index; - } + project_parent->sources_common->item_click(project_parent->item_to_media(index), index); } } void SourceTable::mousePressEvent(QMouseEvent* event) { - stop_rename_timer(); + project_parent->sources_common->mousePressEvent(event); QTreeView::mousePressEvent(event); } -void SourceTable::mouseDoubleClickEvent(QMouseEvent* e) { - stop_rename_timer(); - QModelIndexList selected_items = selectionModel()->selectedRows(); - if (selected_items.size() == 0) { - project_parent->import_dialog(); - } else if (selected_items.size() == 1) { - Media* item = project_parent->item_to_media(selected_items.at(0)); - switch (item->get_type()) { - case MEDIA_TYPE_FOOTAGE: - panel_footage_viewer->set_media(item); - panel_footage_viewer->setFocus(); - break; - case MEDIA_TYPE_SEQUENCE: - undo_stack.push(new ChangeSequenceAction(item->to_sequence())); - break; - } - } +void SourceTable::mouseDoubleClickEvent(QMouseEvent* event) { + project_parent->sources_common->mouseDoubleClickEvent(event, selectionModel()->selectedRows()); } void SourceTable::dragEnterEvent(QDragEnterEvent *event) { @@ -231,79 +69,5 @@ void SourceTable::dragMoveEvent(QDragMoveEvent *event) { } void SourceTable::dropEvent(QDropEvent* event) { - const QMimeData* mimeData = event->mimeData(); - const QModelIndex& drop_item = indexAt(event->pos()); - Media* m = project_parent->item_to_media(drop_item); - if (mimeData->hasUrls()) { - // drag files in from outside - QList urls = mimeData->urls(); - if (!urls.isEmpty()) { - QStringList paths; - for (int i=0;iget_type() == MEDIA_TYPE_FOOTAGE - && !QFileInfo(paths.at(0)).isDir() - && config.drop_on_media_to_replace - && QMessageBox::question(this, "Replace Media", "You dropped a file onto '" + m->get_name() + "'. Would you like to replace it with the dropped file?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { - replace = true; - project_parent->replace_media(m, paths.at(0)); - } - if (!replace) { - QModelIndex parent; - if (drop_item.isValid()) { - if (m->get_type() == MEDIA_TYPE_FOLDER) { - parent = drop_item; - } else { - parent = drop_item.parent(); - } - } - if (parent.isValid()) setExpanded(parent, true); - project_parent->process_file_list(paths, false, NULL, panel_project->item_to_media(parent)); - } - } - event->acceptProposedAction(); - } else { - event->ignore(); - - // dragging files within project - // if we dragged to the root OR dragged to a folder - if (!drop_item.isValid() || (drop_item.isValid() && m->get_type() == MEDIA_TYPE_FOLDER)) { - QVector move_items; - QModelIndexList selected_items = selectionModel()->selectedRows(); - for (int i=0;iitem_to_media(item); - if (parent != drop_item && item != drop_item) { - bool ignore = false; - if (parent.isValid()) { - // if child belongs to a selected parent, assume the user is just moving the parent and ignore the child - QModelIndex par = parent; - while (par.isValid() && !ignore) { - for (int j=0;j 0) { - MediaMove* mm = new MediaMove(this); - mm->to = m; - mm->items = move_items; - undo_stack.push(mm); - } - } - } + project_parent->sources_common->dropEvent(this, event, indexAt(event->pos()), selectionModel()->selectedRows()); } diff --git a/ui/sourcetable.h b/ui/sourcetable.h index 0e3428152..aa19a5449 100644 --- a/ui/sourcetable.h +++ b/ui/sourcetable.h @@ -16,22 +16,13 @@ public: Project* project_parent; protected: void mousePressEvent(QMouseEvent*); - void mouseDoubleClickEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *); void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); -private: - QTimer rename_timer; - Media* editing_item; - QModelIndex editing_index; private slots: - void rename_interval(); void item_click(const QModelIndex& index); - void stop_rename_timer(); - void item_renamed(Media *item); - void show_context_menu(); - void create_seq_from_selected(); - void reveal_in_browser(); + void show_context_menu(); }; #endif // SOURCETABLE_H From aea2faedff26fe3efc3c2cf81c29411e1c5c4570 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 25 Dec 2018 01:15:08 +1100 Subject: [PATCH 7/9] timeline responds to icon view --- ui/timelinewidget.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index c05782bf8..0506995af 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -10,6 +10,7 @@ #include "panels/timeline.h" #include "project/footage.h" #include "ui/sourcetable.h" +#include "ui/sourceiconview.h" #include "panels/effectcontrols.h" #include "panels/viewer.h" #include "project/undo.h" @@ -265,8 +266,10 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { QVector media_list; panel_timeline->importing_files = false; - if (event->source() == panel_project->tree_view) { - QModelIndexList items = panel_project->tree_view->selectionModel()->selectedRows(); + if (event->source() == panel_project->tree_view || event->source() == panel_project->icon_view) { + QModelIndexList items = (event->source() == panel_project->tree_view) + ? panel_project->tree_view->selectionModel()->selectedRows() + : panel_project->icon_view->selectionModel()->selectedIndexes(); media_list.resize(items.size()); for (int i=0;iitem_to_media(items.at(i)); From 259fbf8542fa1dd246222b5eb61a3c71e7c69f79 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 25 Dec 2018 08:48:50 +1100 Subject: [PATCH 8/9] added missing include --- project/sourcescommon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/project/sourcescommon.cpp b/project/sourcescommon.cpp index 510ff8a32..dd1bd3da2 100644 --- a/project/sourcescommon.cpp +++ b/project/sourcescommon.cpp @@ -15,6 +15,7 @@ #include #include #include +#include SourcesCommon::SourcesCommon(Project* parent) : project_parent(parent), From 86f1ed813e2943d3ef9123af83da76c8b1bca427 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 25 Dec 2018 10:39:05 +1100 Subject: [PATCH 9/9] fixed various export issues --- io/exportthread.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/io/exportthread.cpp b/io/exportthread.cpp index 52e6e6999..5715ce9f0 100644 --- a/io/exportthread.cpp +++ b/io/exportthread.cpp @@ -97,8 +97,8 @@ bool ExportThread::setupVideo() { } // allocate context - vcodec_ctx = video_stream->codec; -// vcodec_ctx = avcodec_alloc_context3(vcodec); +// vcodec_ctx = video_stream->codec; + vcodec_ctx = avcodec_alloc_context3(vcodec); if (!vcodec_ctx) { dout << "[ERROR] Could not allocate video encoding context"; ed->export_error = "could not allocate video encoding context"; @@ -125,7 +125,7 @@ bool ExportThread::setupVideo() { itoa(vcodec_ctx, buffer, 10);*/ //av_opt_set(vcodec_ctx->priv_data, "preset", "fast", AV_OPT_SEARCH_CHILDREN); - av_opt_set(vcodec_ctx->priv_data, "x264opts", "opencl", AV_OPT_SEARCH_CHILDREN); + //av_opt_set(vcodec_ctx->priv_data, "x264opts", "opencl", AV_OPT_SEARCH_CHILDREN); switch (video_compression_type) { case COMPRESSION_TYPE_CFR: @@ -203,8 +203,8 @@ bool ExportThread::setupAudio() { } // allocate context - acodec_ctx = audio_stream->codec; -// acodec_ctx = avcodec_alloc_context3(acodec); +// acodec_ctx = audio_stream->codec; + acodec_ctx = avcodec_alloc_context3(acodec); if (!acodec_ctx) { dout << "[ERROR] Could not find allocate audio encoding context"; ed->export_error = "could not allocate audio encoding context"; @@ -448,14 +448,14 @@ void ExportThread::run() { avcodec_close(vcodec_ctx); av_packet_unref(&video_pkt); av_frame_free(&video_frame); -// avcodec_free_context(&vcodec_ctx); + avcodec_free_context(&vcodec_ctx); } if (audio_enabled) { avcodec_close(acodec_ctx); av_packet_unref(&audio_pkt); av_frame_free(&audio_frame); -// avcodec_free_context(&acodec_ctx); + avcodec_free_context(&acodec_ctx); } avformat_free_context(fmt_ctx);