improved footage relink

Interface improvements and uses more heuristics to relink files faster.
This commit is contained in:
itsmattkc
2020-12-13 14:27:47 +11:00
parent 0699795c6f
commit 1cd07bc1f7
4 changed files with 80 additions and 6 deletions
@@ -23,8 +23,10 @@
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QFileInfo>
#include <QHeaderView>
#include <QLabel>
#include <QPushButton>
#include <QScrollBar>
#include <QVBoxLayout>
namespace olive {
@@ -43,6 +45,13 @@ FootageRelinkDialog::FootageRelinkDialog(const QList<FootagePtr>& 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.size(); i++) {
FootagePtr f = footage.at(i);
@@ -72,6 +81,16 @@ FootageRelinkDialog::FootageRelinkDialog(const QList<FootagePtr>& 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; it<footage_.size(); it++) {
FootagePtr other_footage = footage_.at(it);
// Ignore current footage file and footage that's already valid of course
if (index != it && !other_footage->IsValid()) {
// 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; i<footage_.size(); i++) {
if (!footage_.at(i)->IsValid()) {
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);
}
}
@@ -35,6 +35,8 @@ public:
FootageRelinkDialog(const QList<FootagePtr>& footage, QWidget* parent = nullptr);
private:
void UpdateFootageItem(int index);
QTreeWidget* table_;
QList<FootagePtr> footage_;
+8 -3
View File
@@ -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_) {
+1
View File
@@ -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: