diff --git a/icons/dirup-disabled.png b/icons/dirup-disabled.png new file mode 100644 index 000000000..f23fa3f68 Binary files /dev/null and b/icons/dirup-disabled.png differ diff --git a/icons/dirup.png b/icons/dirup.png new file mode 100644 index 000000000..f67b44672 Binary files /dev/null and b/icons/dirup.png differ diff --git a/icons/icons.qrc b/icons/icons.qrc index 711fdcdc0..ac37d6339 100644 --- a/icons/icons.qrc +++ b/icons/icons.qrc @@ -49,5 +49,7 @@ transition-tool.png transition-tool-disabled.png error.png + dirup.png + dirup-disabled.png 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/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); diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 696c7987a..bb24f3cbd 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; @@ -255,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, @@ -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, @@ -271,10 +272,11 @@ 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_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 404a6dc9b..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())); @@ -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/olive.pro b/olive.pro index 78bd16870..ad08b1454 100644 --- a/olive.pro +++ b/olive.pro @@ -96,7 +96,9 @@ SOURCES += \ project/effectgizmo.cpp \ io/clipboard.cpp \ dialogs/stabilizerdialog.cpp \ - io/avtogl.cpp + io/avtogl.cpp \ + ui/sourceiconview.cpp \ + project/sourcescommon.cpp HEADERS += \ mainwindow.h \ @@ -172,7 +174,9 @@ HEADERS += \ project/effectgizmo.h \ io/clipboard.h \ dialogs/stabilizerdialog.h \ - io/avtogl.h + io/avtogl.h \ + ui/sourceiconview.h \ + project/sourcescommon.h FORMS += \ mainwindow.ui \ diff --git a/panels/project.cpp b/panels/project.cpp index dc391ae0b..cad3eaefe 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -23,6 +23,8 @@ #include "io/clipboard.h" #include "project/media.h" #include "ui/sourcetable.h" +#include "ui/sourceiconview.h" +#include "project/sourcescommon.h" #include "debug.h" #include @@ -38,7 +40,6 @@ #include #include #include -#include #include #include @@ -70,26 +71,73 @@ 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); + sources_common = new SourcesCommon(this); 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_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); + icon_view_container_layout->addWidget(icon_view); + + icon_size_slider->setValue(icon_view->iconSize().height()); + + verticalLayout->addWidget(icon_view_container); + + 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)); + + update_view_type(); } Project::~Project() { @@ -189,7 +237,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 +278,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 +292,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 +350,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 +395,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 +714,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; @@ -674,23 +722,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()) { - 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(sorted_index, QItemSelectionModel::Select); return true; } @@ -715,7 +765,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 +1034,30 @@ 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() { + 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); @@ -1003,7 +1077,20 @@ 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)); +} + +void Project::set_up_dir_enabled() { + 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) { @@ -1094,7 +1181,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..71fdd0137 100644 --- a/panels/project.h +++ b/panels/project.h @@ -20,6 +20,9 @@ class QXmlStreamReader; class QFile; class QSortFilterProxyModel; class ComboAction; +class SourceIconView; +class QPushButton; +class SourcesCommon; #define LOAD_TYPE_VERSION 69 #define LOAD_TYPE_URL 70 @@ -40,10 +43,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(); @@ -54,7 +55,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(); @@ -68,7 +69,10 @@ public: QVector list_all_project_sequences(); - SourceTable* source_table; + SourceTable* tree_view; + SourceIconView* icon_view; + SourcesCommon* sources_common; + QSortFilterProxyModel* sorter; QVector last_imported_media; @@ -93,8 +97,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/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/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 bb01dc72e..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,6 +255,14 @@ QVariant Media::data(int column, int role) { switch (role) { case Qt::DecorationRole: if (column == 0) { + if (get_type() == MEDIA_TYPE_FOOTAGE) { + Footage* f = to_footage(); + if (f->video_tracks.size() > 0 + && f->video_tracks.at(0)->preview_done) { + return f->video_tracks.at(0)->video_preview_square; + } + } + return icon; } break; diff --git a/project/sourcescommon.cpp b/project/sourcescommon.cpp new file mode 100644 index 000000000..dd1bd3da2 --- /dev/null +++ b/project/sourcescommon.cpp @@ -0,0 +1,280 @@ +#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 +#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/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 diff --git a/ui/sourceiconview.cpp b/ui/sourceiconview.cpp new file mode 100644 index 000000000..9617adc24 --- /dev/null +++ b/ui/sourceiconview.cpp @@ -0,0 +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) { + 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 new file mode 100644 index 000000000..9320a1628 --- /dev/null +++ b/ui/sourceiconview.h @@ -0,0 +1,26 @@ +#ifndef SOURCEICONVIEW_H +#define SOURCEICONVIEW_H + +#include + +class Project; + +class SourceIconView : public QListView { + Q_OBJECT +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 c2a2637a7..aa19a5449 100644 --- a/ui/sourcetable.h +++ b/ui/sourcetable.h @@ -12,26 +12,17 @@ class SourceTable : public QTreeView { Q_OBJECT public: - SourceTable(QWidget* parent = 0); + SourceTable(QWidget* parent = 0); 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 diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index ba4d42fcb..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->source_table) { - QModelIndexList items = panel_project->source_table->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)); 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;