diff --git a/dialogs/preferencesdialog.cpp b/dialogs/preferencesdialog.cpp index eb5ee4b3a..4703e0ae8 100644 --- a/dialogs/preferencesdialog.cpp +++ b/dialogs/preferencesdialog.cpp @@ -190,6 +190,7 @@ void PreferencesDialog::accept() { if (olive::CurrentConfig.use_software_fallback != use_software_fallbacks_checkbox->isChecked() || olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value() || olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value() + || olive::CurrentConfig.css_path != custom_css_fn->text() #ifdef Q_OS_WIN32 || olive::CurrentConfig.use_native_menu_styling != native_menus->isChecked() #endif @@ -233,11 +234,7 @@ void PreferencesDialog::accept() { } // save settings from UI to backend - if (olive::CurrentConfig.css_path != custom_css_fn->text()) { - olive::CurrentConfig.css_path = custom_css_fn->text(); - olive::MainWindow->Restyle(); - } - + olive::CurrentConfig.css_path = custom_css_fn->text(); olive::CurrentConfig.recording_mode = recordingComboBox->currentIndex() + 1; olive::CurrentConfig.img_seq_formats = imgSeqFormatEdit->text(); olive::CurrentConfig.upcoming_queue_size = upcoming_queue_spinbox->value(); diff --git a/global/config.cpp b/global/config.cpp index d4c548d03..14377d672 100644 --- a/global/config.cpp +++ b/global/config.cpp @@ -264,7 +264,7 @@ void Config::save(QString path) { stream.writeTextElement("HoverFocus", QString::number(hover_focus)); stream.writeTextElement("ProjectViewType", QString::number(project_view_type)); stream.writeTextElement("SetNameWithMarker", QString::number(set_name_with_marker)); - stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->toolbar_widget->isVisible())); + stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->IsToolbarVisible())); stream.writeTextElement("PreviousFrameQueueSize", QString::number(previous_queue_size)); stream.writeTextElement("PreviousFrameQueueType", QString::number(previous_queue_type)); stream.writeTextElement("UpcomingFrameQueueSize", QString::number(upcoming_queue_size)); diff --git a/global/global.cpp b/global/global.cpp index 171f2f34f..8980721d9 100644 --- a/global/global.cpp +++ b/global/global.cpp @@ -91,7 +91,12 @@ void OliveGlobal::check_for_autorecovery_file() { // detect auto-recovery file autorecovery_filename = data_dir + "/autorecovery.ove"; if (QFile::exists(autorecovery_filename)) { - if (QMessageBox::question(nullptr, tr("Auto-recovery"), tr("Olive didn't close properly and an autorecovery file was detected. Would you like to open it?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { + if (QMessageBox::question(nullptr, + tr("Auto-recovery"), + tr("Olive didn't close properly and an autorecovery file " + "was detected. Would you like to open it?"), + QMessageBox::Yes, + QMessageBox::No) == QMessageBox::Yes) { enable_load_project_on_init = false; OpenProjectWorker(autorecovery_filename, true); } @@ -168,6 +173,12 @@ void OliveGlobal::SetNativeStyling(QWidget *w) void OliveGlobal::LoadProject(const QString &fn, bool autorecovery) { + // QSortFilterProxyModels are not thread-safe, and as we'll be loading in another thread, leaving it connected + // can cause glitches in its presentation. Therefore for the duration of the loading process, we disconnect it, + // and reconnect it later once the loading is complete. + + panel_project->DisconnectFilterToModel(); + LoadDialog ld(olive::MainWindow); LoadThread* lt = new LoadThread(fn, autorecovery); @@ -179,6 +190,8 @@ void OliveGlobal::LoadProject(const QString &fn, bool autorecovery) lt->start(); ld.exec(); + + panel_project->ConnectFilterToModel(); } void OliveGlobal::ClearProject() diff --git a/panels/project.cpp b/panels/project.cpp index 3c762ff94..93e5005b3 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -78,7 +78,9 @@ QString autorecovery_filename; QStringList recent_projects; Project::Project(QWidget *parent) : - Panel(parent) + Panel(parent), + sorter(this), + sources_common(this, sorter) { QWidget* dockWidgetContents = new QWidget(this); @@ -88,10 +90,7 @@ Project::Project(QWidget *parent) : setWidget(dockWidgetContents); - sources_common = new SourcesCommon(this); - - sorter = new ProjectFilter(this); - sorter->setSourceModel(&olive::project_model); + ConnectFilterToModel(); // optional toolbar toolbar_widget = new QWidget(); @@ -134,7 +133,7 @@ Project::Project(QWidget *parent) : toolbar_search = new QLineEdit(); toolbar_search->setClearButtonEnabled(true); - connect(toolbar_search, SIGNAL(textChanged(QString)), sorter, SLOT(update_search_filter(const QString&))); + connect(toolbar_search, SIGNAL(textChanged(QString)), &sorter, SLOT(update_search_filter(const QString&))); toolbar->addWidget(toolbar_search); QPushButton* toolbar_tree_view = new QPushButton(); @@ -152,9 +151,9 @@ Project::Project(QWidget *parent) : verticalLayout->addWidget(toolbar_widget); // tree view - tree_view = new SourceTable(); + tree_view = new SourceTable(sources_common); tree_view->project_parent = this; - tree_view->setModel(sorter); + tree_view->setModel(&sorter); verticalLayout->addWidget(tree_view); // Set the first column width @@ -189,9 +188,9 @@ Project::Project(QWidget *parent) : icon_view_container_layout->addLayout(icon_view_controls); - icon_view = new SourceIconView(); + icon_view = new SourceIconView(sources_common); icon_view->project_parent = this; - icon_view->setModel(sorter); + icon_view->setModel(&sorter); icon_view->setIconSize(QSize(100, 100)); icon_view->setViewMode(QListView::IconMode); icon_view->setUniformItemSizes(true); @@ -212,8 +211,14 @@ Project::Project(QWidget *parent) : Retranslate(); } -Project::~Project() { - delete sorter; +void Project::ConnectFilterToModel() +{ + sorter.setSourceModel(&olive::project_model); +} + +void Project::DisconnectFilterToModel() +{ + sorter.setSourceModel(nullptr); } void Project::Retranslate() { @@ -418,10 +423,10 @@ void Project::new_folder() { QModelIndex index = olive::project_model.create_index(m->row(), 0, m.get()); switch (olive::CurrentConfig.project_view_type) { case olive::PROJECT_VIEW_TREE: - tree_view->edit(sorter->mapFromSource(index)); + tree_view->edit(sorter.mapFromSource(index)); break; case olive::PROJECT_VIEW_ICON: - icon_view->edit(sorter->mapFromSource(index)); + icon_view->edit(sorter.mapFromSource(index)); break; } } @@ -475,7 +480,7 @@ MediaPtr Project::create_folder_internal(QString name) { } Media* Project::item_to_media(const QModelIndex &index) { - return static_cast(sorter->mapToSource(index).internalPointer()); + return static_cast(sorter.mapToSource(index).internalPointer()); } MediaPtr Project::item_to_media_ptr(const QModelIndex &index) { @@ -503,6 +508,21 @@ void Project::get_all_media_from_table(QList& items, QList& list } } +bool Project::IsToolbarVisible() +{ + return toolbar_widget->isVisible(); +} + +void Project::SetToolbarVisible(bool visible) +{ + toolbar_widget->setVisible(visible); +} + +bool Project::IsProjectWidget(QObject *child) +{ + return (child == tree_view || child == icon_view); +} + bool delete_clips_in_clipboard_with_media(ComboAction* ca, Media* m) { int delete_count = 0; if (clipboard_type == CLIPBOARD_TYPE_CLIP) { @@ -939,7 +959,7 @@ bool Project::reveal_media(Media *media, QModelIndex parent) { // if m == media, then we found the media object we were looking for // get sorter proxy item (the item that's "visible") - QModelIndex sorted_index = sorter->mapFromSource(item); + QModelIndex sorted_index = sorter.mapFromSource(item); // retrieve its parent item QModelIndex hierarchy = sorted_index.parent(); @@ -954,8 +974,8 @@ bool Project::reveal_media(Media *media, QModelIndex parent) { // select item (requires a QItemSelection object to select the whole row) QItemSelection row_select( - sorter->index(sorted_index.row(), 0, sorted_index.parent()), - sorter->index(sorted_index.row(), sorter->columnCount()-1, sorted_index.parent()) + sorter.index(sorted_index.row(), 0, sorted_index.parent()), + sorter.index(sorted_index.row(), sorter.columnCount()-1, sorted_index.parent()) ); tree_view->selectionModel()->select(row_select, QItemSelectionModel::Select); @@ -1306,10 +1326,10 @@ void Project::update_view_type() { switch (olive::CurrentConfig.project_view_type) { case olive::PROJECT_VIEW_TREE: - sources_common->view = tree_view; + sources_common.view = tree_view; break; case olive::PROJECT_VIEW_ICON: - sources_common->view = icon_view; + sources_common.view = icon_view; break; } } diff --git a/panels/project.h b/panels/project.h index d2984b7d1..4cf77fe95 100644 --- a/panels/project.h +++ b/panels/project.h @@ -55,7 +55,9 @@ class Project : public Panel { Q_OBJECT public: explicit Project(QWidget *parent = nullptr); - ~Project(); + + void ConnectFilterToModel(); + void DisconnectFilterToModel(); bool is_focused(); void clear(); @@ -78,19 +80,14 @@ public: QVector list_all_project_sequences(); - SourceTable* tree_view; - SourceIconView* icon_view; - SourcesCommon* sources_common; - - ProjectFilter* sorter; - QVector last_imported_media; QModelIndexList get_current_selected(); void get_all_media_from_table(QList &items, QList &list, int type = -1); - QWidget* toolbar_widget; + bool IsToolbarVisible(); + bool IsProjectWidget(QObject *child); virtual void Retranslate() override; protected: @@ -104,6 +101,8 @@ public slots: void open_properties(); void new_folder(); void new_sequence(); + + void SetToolbarVisible(bool visible); private: void save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex &parent = QModelIndex()); int folder_id; @@ -115,6 +114,13 @@ private: QWidget* icon_view_container; QPushButton* directory_up; QLineEdit* toolbar_search; + + QWidget* toolbar_widget; + SourceTable* tree_view; + SourceIconView* icon_view; + + ProjectFilter sorter; + SourcesCommon sources_common; private slots: void update_view_type(); void set_icon_view(); diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 3a45fcd3c..510bc6263 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -875,7 +875,11 @@ void Viewer::timer_update() { previous_playhead = seq->playhead; seq->playhead = qMax(0, qRound(playhead_start + ((QDateTime::currentMSecsSinceEpoch()-start_msecs) * 0.001 * seq->frame_rate * playback_speed))); - if (olive::CurrentConfig.seek_also_selects) panel_timeline->select_from_playhead(); + + if (olive::CurrentConfig.seek_also_selects) { + panel_timeline->select_from_playhead(); + } + update_parents(olive::CurrentConfig.seek_also_selects); if (playing) { diff --git a/project/sourcescommon.cpp b/project/sourcescommon.cpp index d91850b3c..e0e80746c 100644 --- a/project/sourcescommon.cpp +++ b/project/sourcescommon.cpp @@ -47,9 +47,10 @@ #include "ui/menu.h" #include "undo/undostack.h" -SourcesCommon::SourcesCommon(Project* parent) : +SourcesCommon::SourcesCommon(Project* parent, ProjectFilter &sort_filter) : editing_item(nullptr), - project_parent(parent) + project_parent(parent), + sort_filter_(sort_filter) { rename_timer.setInterval(1000); connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval())); @@ -97,13 +98,13 @@ void SourcesCommon::show_context_menu(QWidget* parent, const QModelIndexList& it QAction* toolbar_action = view_menu->addAction(tr("Show Toolbar")); toolbar_action->setCheckable(true); - toolbar_action->setChecked(project_parent->toolbar_widget->isVisible()); - connect(toolbar_action, SIGNAL(triggered(bool)), project_parent->toolbar_widget, SLOT(setVisible(bool))); + toolbar_action->setChecked(project_parent->IsToolbarVisible()); + connect(toolbar_action, SIGNAL(triggered(bool)), project_parent, SLOT(SetToolbarVisible(bool))); QAction* show_sequences = view_menu->addAction(tr("Show Sequences")); show_sequences->setCheckable(true); - show_sequences->setChecked(panel_project->sorter->get_show_sequences()); - connect(show_sequences, SIGNAL(triggered(bool)), panel_project->sorter, SLOT(set_show_sequences(bool))); + show_sequences->setChecked(sort_filter_.get_show_sequences()); + connect(show_sequences, SIGNAL(triggered(bool)), &sort_filter_, SLOT(set_show_sequences(bool))); if (items.size() > 0) { if (items.size() == 1) { @@ -282,7 +283,7 @@ void SourcesCommon::dropEvent(QWidget* parent, bool replace = false; if (urls.size() == 1 && drop_item.isValid() - && (m != nullptr && m->get_type() == MEDIA_TYPE_FOOTAGE) + && m->get_type() == MEDIA_TYPE_FOOTAGE && !QFileInfo(paths.at(0)).isDir() && olive::CurrentConfig.drop_on_media_to_replace && QMessageBox::question( diff --git a/project/sourcescommon.h b/project/sourcescommon.h index 191b43fbb..506610ebc 100644 --- a/project/sourcescommon.h +++ b/project/sourcescommon.h @@ -26,6 +26,7 @@ #include #include "project/footage.h" +#include "project/projectfilter.h" class Project; class QMouseEvent; @@ -36,7 +37,7 @@ class QDropEvent; class SourcesCommon : public QObject { Q_OBJECT public: - SourcesCommon(Project *parent); + SourcesCommon(Project *parent, ProjectFilter& sort_filter); QAbstractItemView* view; void show_context_menu(QWidget* parent, const QModelIndexList &items); @@ -66,6 +67,8 @@ private: // we cache the selected footage items for open_create_proxy_dialog() QVector cached_selected_footage; + + ProjectFilter& sort_filter_; }; #endif // SOURCESCOMMON_H diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index 76fc7f584..f7955e319 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -391,16 +391,14 @@ bool MainWindow::load_css_from_file(const QString &fn) { void MainWindow::Restyle() { // Set up UI style - if (olive::styling::UseNativeUI()) { - qApp->setStyle(QStyleFactory::create("")); - } else { + if (!olive::styling::UseNativeUI()) { qApp->setStyle(QStyleFactory::create("Fusion")); // Set up whether to load custom CSS or default CSS+palette if (!olive::CurrentConfig.css_path.isEmpty() && load_css_from_file(olive::CurrentConfig.css_path)) { - setPalette(QPalette()); + qApp->setPalette(qApp->style()->standardPalette()); } else { diff --git a/ui/sourceiconview.cpp b/ui/sourceiconview.cpp index 66c62e6cf..4916a653a 100644 --- a/ui/sourceiconview.cpp +++ b/ui/sourceiconview.cpp @@ -27,7 +27,9 @@ #include "project/sourcescommon.h" #include "global/debug.h" -SourceIconView::SourceIconView(QWidget *parent) : QListView(parent) { +SourceIconView::SourceIconView(SourcesCommon &commons) : + commons_(commons) +{ setSelectionMode(QAbstractItemView::ExtendedSelection); setResizeMode(QListView::Adjust); setContextMenuPolicy(Qt::CustomContextMenu); @@ -36,17 +38,17 @@ SourceIconView::SourceIconView(QWidget *parent) : QListView(parent) { } void SourceIconView::show_context_menu() { - project_parent->sources_common->show_context_menu(this, selectedIndexes()); + commons_.show_context_menu(this, selectedIndexes()); } void SourceIconView::item_click(const QModelIndex& index) { if (selectedIndexes().size() == 1 && index.column() == 0) { - project_parent->sources_common->item_click(project_parent->item_to_media(index), index); + commons_.item_click(project_parent->item_to_media(index), index); } } void SourceIconView::mousePressEvent(QMouseEvent* event) { - project_parent->sources_common->mousePressEvent(event); + commons_.mousePressEvent(event); if (!indexAt(event->pos()).isValid()) selectionModel()->clear(); QListView::mousePressEvent(event); } @@ -70,7 +72,7 @@ void SourceIconView::dragMoveEvent(QDragMoveEvent *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()); + commons_.dropEvent(this, event, drop_item, selectedIndexes()); } void SourceIconView::mouseDoubleClickEvent(QMouseEvent *) { @@ -84,6 +86,6 @@ void SourceIconView::mouseDoubleClickEvent(QMouseEvent *) { } } if (default_behavior) { - project_parent->sources_common->mouseDoubleClickEvent(selectedIndexes()); + commons_.mouseDoubleClickEvent(selectedIndexes()); } } diff --git a/ui/sourceiconview.h b/ui/sourceiconview.h index e561a7a6f..a396aa938 100644 --- a/ui/sourceiconview.h +++ b/ui/sourceiconview.h @@ -23,24 +23,28 @@ #include +#include "project/sourcescommon.h" + class Project; class SourceIconView : public QListView { - Q_OBJECT + Q_OBJECT public: - SourceIconView(QWidget* parent = 0); - Project* project_parent; + SourceIconView(SourcesCommon& commons); + Project* project_parent; - void mousePressEvent(QMouseEvent* event); - void mouseDoubleClickEvent(QMouseEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseDoubleClickEvent(QMouseEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent* event); signals: - void changed_root(); + void changed_root(); private slots: - void show_context_menu(); - void item_click(const QModelIndex& index); + void show_context_menu(); + void item_click(const QModelIndex& index); +private: + SourcesCommon& commons_; }; #endif // SOURCEICONVIEW_H diff --git a/ui/sourcetable.cpp b/ui/sourcetable.cpp index a421cd80b..5a0d67ac0 100644 --- a/ui/sourcetable.cpp +++ b/ui/sourcetable.cpp @@ -45,7 +45,7 @@ #include #include -SourceTable::SourceTable(QWidget* parent) : QTreeView(parent) { +SourceTable::SourceTable(SourcesCommon& commons) : commons_(commons) { setSortingEnabled(true); setAcceptDrops(true); sortByColumn(0, Qt::AscendingOrder); @@ -58,22 +58,22 @@ SourceTable::SourceTable(QWidget* parent) : QTreeView(parent) { } void SourceTable::show_context_menu() { - project_parent->sources_common->show_context_menu(this, selectionModel()->selectedRows()); + commons_.show_context_menu(this, selectionModel()->selectedRows()); } void SourceTable::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); + commons_.item_click(project_parent->item_to_media(index), index); } } void SourceTable::mousePressEvent(QMouseEvent* event) { - project_parent->sources_common->mousePressEvent(event); + commons_.mousePressEvent(event); QTreeView::mousePressEvent(event); } void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) { - project_parent->sources_common->mouseDoubleClickEvent(selectionModel()->selectedRows()); + commons_.mouseDoubleClickEvent(selectionModel()->selectedRows()); } void SourceTable::dragEnterEvent(QDragEnterEvent *event) { @@ -93,5 +93,5 @@ void SourceTable::dragMoveEvent(QDragMoveEvent *event) { } void SourceTable::dropEvent(QDropEvent* event) { - project_parent->sources_common->dropEvent(this, event, indexAt(event->pos()), selectionModel()->selectedRows()); + commons_.dropEvent(this, event, indexAt(event->pos()), selectionModel()->selectedRows()); } diff --git a/ui/sourcetable.h b/ui/sourcetable.h index 251d87776..cc28ea48f 100644 --- a/ui/sourcetable.h +++ b/ui/sourcetable.h @@ -25,6 +25,8 @@ #include #include +#include "project/sourcescommon.h" + class Project; class Media; @@ -32,7 +34,7 @@ class SourceTable : public QTreeView { Q_OBJECT public: - SourceTable(QWidget* parent = 0); + SourceTable(SourcesCommon& commons); Project* project_parent; protected: void mousePressEvent(QMouseEvent*); @@ -43,6 +45,8 @@ protected: private slots: void item_click(const QModelIndex& index); void show_context_menu(); +private: + SourcesCommon& commons_; }; #endif // SOURCETABLE_H diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 684f93f47..30b07e443 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -240,7 +240,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { QVector media_list; panel_timeline->importing_files = false; - if (event->source() == panel_project->tree_view || event->source() == panel_project->icon_view) { + if (panel_project->IsProjectWidget(event->source())) { QModelIndexList items = panel_project->get_current_selected(); media_list.resize(items.size()); for (int i=0;i