Skip to content

Commit

Permalink
fix Convert dialog hangs Windows Explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
ddennedy committed Jul 9, 2024
1 parent 0293ae6 commit 777dd62
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 157 deletions.
197 changes: 103 additions & 94 deletions src/docks/playlistdock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,104 @@ void PlaylistDock::moveClipDown()
}
}

void PlaylistDock::addFiles(int row, const QList<QUrl> &urls)
{
auto resetIndex = true;
ResourceDialog dialog(this);
LongUiTask longTask(tr("Add Files"));
int insertNextAt = row;
bool first = true;
QStringList fileNames = Util::sortedFileList(Util::expandDirectories(urls));
qsizetype i = 0, count = fileNames.size();
for (auto &path : fileNames) {
if (MAIN.isSourceClipMyProject(path)) continue;
longTask.reportProgress(Util::baseName(path), i++, count);
if (MLT.checkFile(path)) {
emit showStatusMessage(tr("Failed to open ").append(path));
continue;
}
Mlt::Producer p;
if (path.endsWith(".mlt") || path.endsWith(".xml")) {
if (Settings.playerGPU() && MLT.profile().is_explicit()) {
Mlt::Profile testProfile;
Mlt::Producer producer(testProfile, path.toUtf8().constData());
if (testProfile.width() != MLT.profile().width()
|| testProfile.height() != MLT.profile().height()
|| Util::isFpsDifferent(MLT.profile().fps(), testProfile.fps())) {
emit showStatusMessage(tr("Failed to open ").append(path));
continue;
}
}
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
if (p.is_valid()) {
// Convert MLT XML to a virtual clip.
p.set(kShotcutVirtualClip, 1);
p.set("resource", path.toUtf8().constData());
first = false;
}
} else {
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
}
if (p.is_valid()) {
Mlt::Producer *producer = &p;
if (first) {
first = false;
if (!MLT.producer() || !MLT.producer()->is_valid()) {
Mlt::Properties properties;
properties.set(kShotcutSkipConvertProperty, 1);
MAIN.open(path, &properties, false);
if (MLT.producer() && MLT.producer()->is_valid()) {
producer = MLT.producer();
first = true;
}
}
}
producer = MLT.setupNewProducer(producer);
producer->set(kShotcutSkipConvertProperty, 1);
if (!MLT.isLiveProducer(producer) || producer->get_int(kShotcutVirtualClip)) {
ProxyManager::generateIfNotExists(*producer);
if (row == -1)
MAIN.undoStack()->push(new Playlist::AppendCommand(m_model, MLT.XML(producer)));
else
MAIN.undoStack()->push(new Playlist::InsertCommand(m_model, MLT.XML(producer), insertNextAt++));
} else {
LongUiTask::cancel();
DurationDialog durationDialog(this);
durationDialog.setDuration(MLT.profile().fps() * 5);
if (durationDialog.exec() == QDialog::Accepted) {
producer->set_in_and_out(0, durationDialog.duration() - 1);
if (row == -1)
MAIN.undoStack()->push(new Playlist::AppendCommand(m_model, MLT.XML(producer)));
else
MAIN.undoStack()->push(new Playlist::InsertCommand(m_model, MLT.XML(producer), insertNextAt++));
}
}
if (first) {
first = false;
setIndex(0);
resetIndex = false;
}
dialog.add(producer);
delete producer;
}
}
if (Settings.showConvertClipDialog() && dialog.producerCount() > 1 && dialog.hasTroubleClips()) {
dialog.selectTroubleClips();
dialog.setWindowTitle(tr("Dropped Files"));
longTask.cancel();
dialog.exec();
} else if (Settings.showConvertClipDialog() && dialog.producerCount() == 1) {
Mlt::Producer producer = dialog.producer(0);
QString convertAdvice = Util::getConversionAdvice(&producer);
if (!convertAdvice.isEmpty()) {
longTask.cancel();
Util::offerSingleFileConversion(convertAdvice, &producer, this);
}
}
if (resetIndex)
resetPlaylistIndex();
}

void PlaylistDock::onInsertCutActionTriggered()
{
if (MLT.isClip() || MLT.savedProducer()) {
Expand Down Expand Up @@ -1158,99 +1256,12 @@ void PlaylistDock::onPlaylistCleared()

void PlaylistDock::onDropped(const QMimeData *data, int row)
{
bool resetIndex = true;
if (data && data->hasUrls()) {
ResourceDialog dialog(this);
LongUiTask longTask(tr("Add Files"));
int insertNextAt = row;
bool first = true;
QStringList fileNames = Util::sortedFileList(Util::expandDirectories(data->urls()));
qsizetype i = 0, count = fileNames.size();
for (auto &path : fileNames) {
if (MAIN.isSourceClipMyProject(path)) continue;
longTask.reportProgress(Util::baseName(path), i++, count);
if (MLT.checkFile(path)) {
emit showStatusMessage(tr("Failed to open ").append(path));
continue;
}
Mlt::Producer p;
if (path.endsWith(".mlt") || path.endsWith(".xml")) {
if (Settings.playerGPU() && MLT.profile().is_explicit()) {
Mlt::Profile testProfile;
Mlt::Producer producer(testProfile, path.toUtf8().constData());
if (testProfile.width() != MLT.profile().width()
|| testProfile.height() != MLT.profile().height()
|| Util::isFpsDifferent(MLT.profile().fps(), testProfile.fps())) {
emit showStatusMessage(tr("Failed to open ").append(path));
continue;
}
}
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
if (p.is_valid()) {
// Convert MLT XML to a virtual clip.
p.set(kShotcutVirtualClip, 1);
p.set("resource", path.toUtf8().constData());
first = false;
}
} else {
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
}
if (p.is_valid()) {
Mlt::Producer *producer = &p;
if (first) {
first = false;
if (!MLT.producer() || !MLT.producer()->is_valid()) {
Mlt::Properties properties;
properties.set(kShotcutSkipConvertProperty, 1);
MAIN.open(path, &properties, false);
if (MLT.producer() && MLT.producer()->is_valid()) {
producer = MLT.producer();
first = true;
}
}
}
producer = MLT.setupNewProducer(producer);
producer->set(kShotcutSkipConvertProperty, 1);
if (!MLT.isLiveProducer(producer) || producer->get_int(kShotcutVirtualClip)) {
ProxyManager::generateIfNotExists(*producer);
if (row == -1)
MAIN.undoStack()->push(new Playlist::AppendCommand(m_model, MLT.XML(producer)));
else
MAIN.undoStack()->push(new Playlist::InsertCommand(m_model, MLT.XML(producer), insertNextAt++));
} else {
LongUiTask::cancel();
DurationDialog durationDialog(this);
durationDialog.setDuration(MLT.profile().fps() * 5);
if (durationDialog.exec() == QDialog::Accepted) {
producer->set_in_and_out(0, durationDialog.duration() - 1);
if (row == -1)
MAIN.undoStack()->push(new Playlist::AppendCommand(m_model, MLT.XML(producer)));
else
MAIN.undoStack()->push(new Playlist::InsertCommand(m_model, MLT.XML(producer), insertNextAt++));
}
}
if (first) {
first = false;
setIndex(0);
resetIndex = false;
}
dialog.add(producer);
delete producer;
}
}
if (Settings.showConvertClipDialog() && dialog.producerCount() > 1 && dialog.hasTroubleClips()) {
dialog.selectTroubleClips();
dialog.setWindowTitle(tr("Dropped Files"));
longTask.cancel();
dialog.exec();
} else if (Settings.showConvertClipDialog() && dialog.producerCount() == 1) {
Mlt::Producer producer = dialog.producer(0);
QString convertAdvice = Util::getConversionAdvice(&producer);
if (!convertAdvice.isEmpty()) {
longTask.cancel();
Util::offerSingleFileConversion(convertAdvice, &producer, this);
}
}
// Use QTimer to workaround stupid drag from Windows Explorer bug
const auto &urls = data->urls();
QTimer::singleShot(0, this, [ = ]() {
addFiles(row, urls);
});
} else if (data && data->hasFormat(Mlt::XmlMimeType)) {
if (MLT.producer() && MLT.producer()->is_valid()) {
if (MLT.producer()->type() == mlt_service_playlist_type) {
Expand Down Expand Up @@ -1284,8 +1295,6 @@ void PlaylistDock::onDropped(const QMimeData *data, int row)
}
}
}
if (resetIndex)
resetPlaylistIndex();
}

void PlaylistDock::onMoveClip(int from, int to)
Expand Down
3 changes: 2 additions & 1 deletion src/docks/playlistdock.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2023 Meltytech, LLC
* Copyright (c) 2012-2024 Meltytech, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -107,6 +107,7 @@ private slots:
void setIndex(int row);
void moveClipUp();
void moveClipDown();
void addFiles(int row, const QList<QUrl> &urls);

Ui::PlaylistDock *ui;
QAbstractItemView *m_view;
Expand Down
133 changes: 72 additions & 61 deletions src/docks/timelinedock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2801,11 +2801,11 @@ void TimelineDock::initLoad()
load(false);
}

void TimelineDock::handleDrop(int trackIndex, int position, QString xml)
void TimelineDock::handleDrop(int trackIndex, int position, QString xmlOrUrls)
{
if (xml.startsWith(kFileUrlProtocol)) {
if (xmlOrUrls.startsWith(kFileUrlProtocol)) {
QList<QUrl> urls;
auto strings = xml.split(kFilesUrlDelimiter);
auto strings = xmlOrUrls.split(kFilesUrlDelimiter);
for (auto &s : strings) {
#ifdef Q_OS_WIN
if (!s.startsWith(kFileUrlProtocol)) {
Expand All @@ -2814,76 +2814,87 @@ void TimelineDock::handleDrop(int trackIndex, int position, QString xml)
#endif
urls << s;
}
int i = 0, count = urls.size();

// Handle drop from file manager to empty project.
if (!MLT.producer() || !MLT.producer()->is_valid()) {
QUrl url = xml.split(kFilesUrlDelimiter).first();
Mlt::Properties properties;
properties.set(kShotcutSkipConvertProperty, 1);
if (!MAIN.open(Util::removeFileScheme(url), &properties, false /* play */))
MAIN.open(Util::removeFileScheme(url, false), &properties, false /* play */);
}
// Use QTimer to workaround stupid drag from Windows Explorer bug
QTimer::singleShot(0, this, [ = ]() {
auto xml = xmlOrUrls;
int i = 0, count = urls.size();

LongUiTask longTask(QObject::tr("Drop Files"));
Mlt::Playlist playlist(MLT.profile());
ResourceDialog dialog(this);
for (const auto &path : Util::sortedFileList(urls)) {
if (MAIN.isSourceClipMyProject(path, /* withDialog */ false)) continue;
if (MLT.checkFile(path)) {
MAIN.showStatusMessage(QObject::tr("Failed to open ").append(path));
continue;
// Handle drop from file manager to empty project.
if (!MLT.producer() || !MLT.producer()->is_valid()) {
QUrl url = xml.split(kFilesUrlDelimiter).first();
Mlt::Properties properties;
properties.set(kShotcutSkipConvertProperty, 1);
if (!MAIN.open(Util::removeFileScheme(url), &properties, false /* play */))
MAIN.open(Util::removeFileScheme(url, false), &properties, false /* play */);
}
longTask.reportProgress(Util::baseName(path), i++, count);
Mlt::Producer p;
if (path.endsWith(".mlt") || path.endsWith(".xml")) {
if (Settings.playerGPU() && MLT.profile().is_explicit()) {
Mlt::Profile testProfile;
Mlt::Producer producer(testProfile, path.toUtf8().constData());
if (testProfile.width() != MLT.profile().width()
|| testProfile.height() != MLT.profile().height()
|| Util::isFpsDifferent(MLT.profile().fps(), testProfile.fps())) {
MAIN.showStatusMessage(QObject::tr("Failed to open ").append(path));
continue;

LongUiTask longTask(QObject::tr("Drop Files"));
Mlt::Playlist playlist(MLT.profile());
ResourceDialog dialog(this);
for (const auto &path : Util::sortedFileList(urls)) {
if (MAIN.isSourceClipMyProject(path, /* withDialog */ false)) continue;
if (MLT.checkFile(path)) {
MAIN.showStatusMessage(QObject::tr("Failed to open ").append(path));
continue;
}
longTask.reportProgress(Util::baseName(path), i++, count);
Mlt::Producer p;
if (path.endsWith(".mlt") || path.endsWith(".xml")) {
if (Settings.playerGPU() && MLT.profile().is_explicit()) {
Mlt::Profile testProfile;
Mlt::Producer producer(testProfile, path.toUtf8().constData());
if (testProfile.width() != MLT.profile().width()
|| testProfile.height() != MLT.profile().height()
|| Util::isFpsDifferent(MLT.profile().fps(), testProfile.fps())) {
MAIN.showStatusMessage(QObject::tr("Failed to open ").append(path));
continue;
}
}
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
if (p.is_valid()) {
p.set(kShotcutVirtualClip, 1);
p.set("resource", path.toUtf8().constData());
}
} else {
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
}
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
if (p.is_valid()) {
p.set(kShotcutVirtualClip, 1);
p.set("resource", path.toUtf8().constData());
}
} else {
p = Mlt::Producer(MLT.profile(), path.toUtf8().constData());
}
if (p.is_valid()) {
if (!qstrcmp(p.get("mlt_service"), "avformat") && !p.get_int("seekable")) {
MAIN.showStatusMessage(QObject::tr("Not adding non-seekable file: ") + Util::baseName(path));
continue;
if (!qstrcmp(p.get("mlt_service"), "avformat") && !p.get_int("seekable")) {
MAIN.showStatusMessage(QObject::tr("Not adding non-seekable file: ") + Util::baseName(path));
continue;
}
Mlt::Producer *producer = MLT.setupNewProducer(&p);
producer->set(kShotcutSkipConvertProperty, 1);
ProxyManager::generateIfNotExists(*producer);
playlist.append(*producer);
dialog.add(producer);
delete producer;
}
Mlt::Producer *producer = MLT.setupNewProducer(&p);
producer->set(kShotcutSkipConvertProperty, 1);
ProxyManager::generateIfNotExists(*producer);
playlist.append(*producer);
dialog.add(producer);
delete producer;
}
}
xml = MLT.XML(&playlist);
if (Settings.showConvertClipDialog() && dialog.producerCount() > 1 && dialog.hasTroubleClips()) {
dialog.selectTroubleClips();
dialog.setWindowTitle(tr("Dropped Files"));
longTask.cancel();
dialog.exec();
} else if (Settings.showConvertClipDialog() && dialog.producerCount() == 1) {
Mlt::Producer producer = dialog.producer(0);
QString convertAdvice = Util::getConversionAdvice(&producer);
if (!convertAdvice.isEmpty()) {
xml = MLT.XML(&playlist);
if (Settings.showConvertClipDialog() && dialog.producerCount() > 1 && dialog.hasTroubleClips()) {
dialog.selectTroubleClips();
dialog.setWindowTitle(tr("Dropped Files"));
longTask.cancel();
Util::offerSingleFileConversion(convertAdvice, &producer, this);
dialog.exec();
} else if (Settings.showConvertClipDialog() && dialog.producerCount() == 1) {
Mlt::Producer producer = dialog.producer(0);
QString convertAdvice = Util::getConversionAdvice(&producer);
if (!convertAdvice.isEmpty()) {
longTask.cancel();
Util::offerSingleFileConversion(convertAdvice, &producer, this);
}
}
}
insertOrOverwriteDrop(trackIndex, position, xml);
});
} else {
insertOrOverwriteDrop(trackIndex, position, xmlOrUrls);
}
}

void TimelineDock::insertOrOverwriteDrop(int trackIndex, int position, const QString &xml)
{
auto autoAddTracks = Settings.timelineAutoAddTracks();
Settings.setTimelineAutoAddTracks(false);
if (Settings.timelineRipple()) {
Expand Down
Loading

0 comments on commit 777dd62

Please sign in to comment.