improved footage relink
Interface improvements and uses more heuristics to relink files faster.
This commit is contained in:
@@ -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_;
|
||||
|
||||
@@ -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_) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user