From 1cd07bc1f7e8d800ac1ec0bce8ea5db4203582cc Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 13 Dec 2020 14:27:47 +1100 Subject: [PATCH] improved footage relink Interface improvements and uses more heuristics to relink files faster. --- .../footagerelink/footagerelinkdialog.cpp | 72 ++++++++++++++++++- .../footagerelink/footagerelinkdialog.h | 2 + app/project/item/footage/footage.cpp | 11 ++- app/project/item/footage/footage.h | 1 + 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/app/dialog/footagerelink/footagerelinkdialog.cpp b/app/dialog/footagerelink/footagerelinkdialog.cpp index cfdde7fc5..cc8b149fb 100644 --- a/app/dialog/footagerelink/footagerelinkdialog.cpp +++ b/app/dialog/footagerelink/footagerelinkdialog.cpp @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include namespace olive { @@ -43,6 +45,13 @@ FootageRelinkDialog::FootageRelinkDialog(const QList& footage, QWidg table_->setColumnCount(3); table_->setHeaderLabels({tr("Footage"), tr("Filename"), tr("Actions")}); table_->setRootIsDecorated(false); + table_->setSelectionBehavior(QAbstractItemView::SelectRows); + table_->header()->setSectionsMovable(false); + + // Prefer stretching URL column (QHeaderView defaults to stretching the last column, which in + // our case is just a browse button) + table_->header()->setSectionResizeMode(1, QHeaderView::Stretch); + table_->header()->setStretchLastSection(false); for (int i=0; i& footage, QWidg layout->addWidget(buttons); setWindowTitle(tr("Relink Footage")); + + +} + +void FootageRelinkDialog::UpdateFootageItem(int index) +{ + FootagePtr f = footage_.at(index); + QTreeWidgetItem* item = table_->topLevelItem(index); + item->setIcon(0, f->icon()); + item->setText(1, f->filename()); } void FootageRelinkDialog::BrowseForFootage() @@ -86,17 +105,64 @@ void FootageRelinkDialog::BrowseForFootage() info.absolutePath(), QStringLiteral("%1;;%2 (**)").arg(info.fileName(), tr("All Files"))); + // We received a new filename if (!new_fn.isEmpty()) { + // Store original dir since we might be able to use this to find other files + QDir original_dir = info.dir(); + QDir new_dir = QFileInfo(new_fn).dir(); + + // Set new filename since this was set manually by the user f->set_filename(new_fn); if (Footage::CompareFootageToItsFilename(f)) { // Set footage to valid and update icon f->SetValid(); - QTreeWidgetItem* item = table_->topLevelItem(index); - item->setIcon(0, f->icon()); - item->setText(1, f->filename()); + // Update item visually + UpdateFootageItem(index); } + + // Check all other footage files for matches + for (int it=0; itIsValid()) { + // Get footage path relative to original directory + QString relative_to_original = original_dir.relativeFilePath(other_footage->filename()); + QString absolute_to_new = new_dir.filePath(relative_to_original); + + // Check if file exists + if (QFileInfo::exists(absolute_to_new) + && Footage::CompareFootageToFile(other_footage, absolute_to_new)) { + other_footage->set_filename(absolute_to_new); + other_footage->SetValid(); + UpdateFootageItem(it); + } + } + } + } + + // Check where the next invalid footage is. If there is none, accept automatically. Otherwise, + // jump to that footage so the user knows where it is. + int next_invalid = -1; + for (int i=0; iIsValid()) { + next_invalid = i; + break; + } + } + + if (next_invalid == -1) { + // No more invalid footage, just accept + this->accept(); + } else { + // Jump to next invalid footage + QModelIndex idx = table_->model()->index(next_invalid, 0); + table_->selectionModel()->select(idx, + QItemSelectionModel::Select | QItemSelectionModel::Rows); + table_->scrollTo(idx); + } } diff --git a/app/dialog/footagerelink/footagerelinkdialog.h b/app/dialog/footagerelink/footagerelinkdialog.h index b201b6762..91999ffc2 100644 --- a/app/dialog/footagerelink/footagerelinkdialog.h +++ b/app/dialog/footagerelink/footagerelinkdialog.h @@ -35,6 +35,8 @@ public: FootageRelinkDialog(const QList& footage, QWidget* parent = nullptr); private: + void UpdateFootageItem(int index); + QTreeWidget* table_; QList footage_; diff --git a/app/project/item/footage/footage.cpp b/app/project/item/footage/footage.cpp index c2d1b1c63..08c358208 100644 --- a/app/project/item/footage/footage.cpp +++ b/app/project/item/footage/footage.cpp @@ -299,10 +299,10 @@ StreamPtr Footage::get_first_stream_of_type(const Stream::Type &type) const return nullptr; } -bool Footage::CompareFootageToItsFilename(FootagePtr footage) +bool Footage::CompareFootageToFile(FootagePtr footage, const QString &filename) { // Heuristic to determine if file has changed - QFileInfo info(footage->filename()); + QFileInfo info(filename); if (info.exists()) { if (info.lastModified().toMSecsSinceEpoch() == footage->timestamp()) { @@ -311,7 +311,7 @@ bool Footage::CompareFootageToItsFilename(FootagePtr footage) } else { // Footage may have changed and we'll have to re-probe it. It also may not have, in which // case nothing needs to change. - ItemPtr item = Decoder::Probe(footage->project(), footage->filename(), nullptr); + ItemPtr item = Decoder::Probe(footage->project(), filename, nullptr); if (item && item->type() == footage->type()) { // Item is the same type, that's a good sign. Let's look for any differences. @@ -325,6 +325,11 @@ bool Footage::CompareFootageToItsFilename(FootagePtr footage) return false; } +bool Footage::CompareFootageToItsFilename(FootagePtr footage) +{ + return CompareFootageToFile(footage, footage->filename()); +} + void Footage::UpdateTooltip() { if (valid_) { diff --git a/app/project/item/footage/footage.h b/app/project/item/footage/footage.h index 2ffd9e272..a01c35600 100644 --- a/app/project/item/footage/footage.h +++ b/app/project/item/footage/footage.h @@ -202,6 +202,7 @@ public: StreamPtr get_first_stream_of_type(const Stream::Type& type) const; + static bool CompareFootageToFile(FootagePtr footage, const QString& filename); static bool CompareFootageToItsFilename(FootagePtr footage); private: