From e393ac8d602a418f18c6bd05212d63920f1ad932 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Tue, 30 Jul 2024 20:44:45 +0200 Subject: [PATCH] GUI: mux: add progress dialog during file identification --- NEWS.md | 5 ++ .../merge/file_identification_pack.h | 2 +- .../merge/file_identification_thread.cpp | 57 ++++++++++++++----- .../merge/file_identification_thread.h | 7 ++- src/mkvtoolnix-gui/merge/tool.cpp | 52 ++++++++++++++--- src/mkvtoolnix-gui/merge/tool.h | 3 +- 6 files changed, 100 insertions(+), 26 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7419a850b..266186e36 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,10 @@ # Version ? +## New features and enhancements + +* MKVToolNix GUI: multiplexer: added a progress dialog that is shown during + file identification. + ## Bug fixes * mkvmerge: AAC parser: LOAS/LATM streams: if the first `AudioSpecificConfig` diff --git a/src/mkvtoolnix-gui/merge/file_identification_pack.h b/src/mkvtoolnix-gui/merge/file_identification_pack.h index 2f1f86bb4..dcc5a63c3 100644 --- a/src/mkvtoolnix-gui/merge/file_identification_pack.h +++ b/src/mkvtoolnix-gui/merge/file_identification_pack.h @@ -21,7 +21,7 @@ struct IdentificationPack { }; AddMode m_addMode{AddMode::UserChoice}; - uint64_t m_tabId{}; + uint64_t m_tabId{}, m_initialNumberOfFiles{}; QModelIndex m_sourceFileIdx{}; Qt::MouseButtons m_mouseButtons{}; QStringList m_fileNames; diff --git a/src/mkvtoolnix-gui/merge/file_identification_thread.cpp b/src/mkvtoolnix-gui/merge/file_identification_thread.cpp index 46d5ef16c..68b59da0d 100644 --- a/src/mkvtoolnix-gui/merge/file_identification_thread.cpp +++ b/src/mkvtoolnix-gui/merge/file_identification_thread.cpp @@ -25,8 +25,9 @@ class FileIdentificationWorkerPrivate { QVector m_toIdentify; QMutex m_mutex; - QAtomicInteger m_abortPlaylistScan; + QAtomicInteger m_abortPlaylistScan, m_abortIdentification; QRegularExpression m_simpleChaptersRE, m_ffmpegMetaChaptersRE, m_xmlChaptersRE, m_xmlSegmentInfoRE, m_xmlTagsRE; + QAtomicInteger m_numberOfIdentifiedFiles; explicit FileIdentificationWorkerPrivate() { @@ -51,15 +52,19 @@ FileIdentificationWorker::~FileIdentificationWorker() { } void -FileIdentificationWorker::addPackToIdentify(IdentificationPack const &pack) { +FileIdentificationWorker::addPackToIdentify(IdentificationPack &pack) { auto p = p_func(); qDebug() << "FileIdentificationWorker::addFilesToIdentify: adding" << pack.m_fileNames; QMutexLocker lock{&p->m_mutex}; + pack.m_initialNumberOfFiles = pack.m_fileNames.count(); + p->m_toIdentify.push_back(pack); + Q_EMIT queueProgressChanged(p->m_numberOfIdentifiedFiles, countNumberOfQueuedFiles()); + QTimer::singleShot(0, this, [this]() { identifyFiles(); }); } @@ -108,15 +113,25 @@ FileIdentificationWorker::identifyFiles() { qDebug() << "FileIdentificationWorker::identifyFiles: starting loop"; - Q_EMIT queueStarted(); + p->m_abortIdentification = false; + + { + QMutexLocker lock{&p->m_mutex}; + p->m_numberOfIdentifiedFiles = 0; + Q_EMIT queueStarted(countNumberOfQueuedFiles()); + } while (true) { QString fileName; { QMutexLocker lock{&p->m_mutex}; - if (p->m_toIdentify.isEmpty()) { - qDebug() << "FileIdentificationWorker::identifyFiles: exiting loop (nothing left to do)"; + + if (p->m_toIdentify.isEmpty() || p->m_abortIdentification) { + auto reason = p->m_abortIdentification ? "aborted" : "nothing left to do"; + qDebug() << "FileIdentificationWorker::identifyFiles: exiting loop (" << reason << ")"; + + p->m_toIdentify.clear(); Q_EMIT queueFinished(); @@ -140,6 +155,14 @@ FileIdentificationWorker::identifyFiles() { auto result = identifyThisFile(fileName); + // QThread::sleep(1); + + { + QMutexLocker lock{&p->m_mutex}; + p->m_numberOfIdentifiedFiles++; + Q_EMIT queueProgressChanged(p->m_numberOfIdentifiedFiles, countNumberOfQueuedFiles()); + } + if (result == Result::Wait) { qDebug() << "FileIdentificationWorker::identifyFiles: exiting loop (result was 'Wait')"; return; @@ -149,17 +172,9 @@ FileIdentificationWorker::identifyFiles() { void FileIdentificationWorker::abortIdentification() { - auto p = p_func(); - - QMutexLocker lock{&p->m_mutex}; - if (p->m_toIdentify.isEmpty()) - return; - qDebug() << "FileIdentificationWorker::abortIdentification: skipping remaining files"; - p->m_toIdentify.clear(); - - Q_EMIT queueFinished(); + p_func()->m_abortIdentification = true; } IdentificationPack::FileType @@ -345,6 +360,18 @@ FileIdentificationWorker::identifyThisFile(QString const &fileName) { return Result::Continue; } +unsigned int +FileIdentificationWorker::countNumberOfQueuedFiles() { + auto &p = *p_func(); + + auto numberOfQueuedFiles = 0u; + + for (auto const &pack : p.m_toIdentify) + numberOfQueuedFiles += pack.m_initialNumberOfFiles; + + return numberOfQueuedFiles; +} + // ---------------------------------------------------------------------- FileIdentificationThread::FileIdentificationThread(QObject *parent) @@ -374,7 +401,7 @@ FileIdentificationThread::continueIdentification() { void FileIdentificationThread::abortIdentification() { - QTimer::singleShot(0, &worker(), [this]() { worker().abortIdentification(); }); + worker().abortIdentification(); } void diff --git a/src/mkvtoolnix-gui/merge/file_identification_thread.h b/src/mkvtoolnix-gui/merge/file_identification_thread.h index 75bc7a18d..f32255df0 100644 --- a/src/mkvtoolnix-gui/merge/file_identification_thread.h +++ b/src/mkvtoolnix-gui/merge/file_identification_thread.h @@ -31,7 +31,7 @@ public: FileIdentificationWorker(QObject *parent = nullptr); virtual ~FileIdentificationWorker(); - void addPackToIdentify(IdentificationPack const &pack); + void addPackToIdentify(IdentificationPack &pack); void addIdentifiedFile(SourceFilePtr const &identifiedFile); void addIdentifiedFile(IdentificationPack::FileType type, QString const &fileName); @@ -45,8 +45,9 @@ public Q_SLOTS: void abortIdentification(); Q_SIGNALS: - void queueStarted(); + void queueStarted(unsigned int numberOfQueuedFiles); void queueFinished(); + void queueProgressChanged(unsigned int numFilesIdentified, unsigned int numberOfQueuedFiles); void playlistScanStarted(int numFilesToScan); void playlistScanFinished(); @@ -66,6 +67,8 @@ protected: Result identifyThisFile(QString const &fileName); Result scanPlaylists(QFileInfoList const &fileNames); + + unsigned int countNumberOfQueuedFiles(); }; class FileIdentificationThread : public QThread { diff --git a/src/mkvtoolnix-gui/merge/tool.cpp b/src/mkvtoolnix-gui/merge/tool.cpp index f61be0fd2..ab15c4d4c 100644 --- a/src/mkvtoolnix-gui/merge/tool.cpp +++ b/src/mkvtoolnix-gui/merge/tool.cpp @@ -108,7 +108,7 @@ class ToolPrivate { mtx::gui::Util::FilesDragDropHandler filesDDHandler{Util::FilesDragDropHandler::Mode::Remember}; FileIdentificationThread *identifier{}; - QProgressDialog *scanningDirectoryDialog{}; + QProgressDialog *scanningDirectoryDialog{}, *identifyingFilesDialog{}; QHash lastAddAppendFileNum; @@ -231,6 +231,7 @@ Tool::setupFileIdentificationThread() { connect(&worker, &FileIdentificationWorker::queueStarted, this, &Tool::fileIdentificationStarted); connect(&worker, &FileIdentificationWorker::queueFinished, this, &Tool::fileIdentificationFinished); + connect(&worker, &FileIdentificationWorker::queueProgressChanged, this, &Tool::updateFileIdentificationProgress); connect(&worker, &FileIdentificationWorker::packIdentified, this, &Tool::handleIdentifiedFiles); connect(&worker, &FileIdentificationWorker::identificationFailed, this, &Tool::showFileIdentificationError); connect(&worker, &FileIdentificationWorker::playlistScanStarted, this, &Tool::showScanningPlaylistDialog); @@ -947,13 +948,44 @@ Tool::identifyMultipleFiles(QStringList const &fileNamesToIdentify, } void -Tool::fileIdentificationStarted() { - p_func()->ui->overlordWidget->setEnabled(false); +Tool::fileIdentificationStarted(unsigned int numberOfQueuedFiles) { + auto &p = *p_func(); + + qDebug() << "Tool::fileIdentificationStarted with" << numberOfQueuedFiles; + + p.ui->overlordWidget->setEnabled(false); + + if (!p.identifyingFilesDialog) + p.identifyingFilesDialog = new QProgressDialog{ QY("Identifying files"), QY("Cancel"), 0, static_cast(numberOfQueuedFiles), this }; + p.identifyingFilesDialog->setWindowTitle(QY("Identifying files" )); + p.identifyingFilesDialog->show(); + + connect(p.identifyingFilesDialog, &QProgressDialog::canceled, p.identifier, &FileIdentificationThread::abortIdentification); } void Tool::fileIdentificationFinished() { - p_func()->ui->overlordWidget->setEnabled(true); + auto &p = *p_func(); + + qDebug() << "Tool::fileIdentificationFinished"; + + delete p.identifyingFilesDialog; + p.identifyingFilesDialog = nullptr; + + p.ui->overlordWidget->setEnabled(true); +} + +void +Tool::updateFileIdentificationProgress(unsigned int numberOfIdentifiedFiles, + unsigned int numberOfQueuedFiles) { + auto &p = *p_func(); + + qDebug() << "Tool::updateFileIdentificationProgress with " << numberOfIdentifiedFiles << "/" << numberOfQueuedFiles; + + if (p.identifyingFilesDialog) { + p.identifyingFilesDialog->setValue(static_cast(numberOfIdentifiedFiles)); + p.identifyingFilesDialog->setMaximum(static_cast(numberOfQueuedFiles)); + } } void @@ -1040,11 +1072,11 @@ void Tool::hideScanningDirectoryDialog() { auto &p = *p_func(); - if (!p.scanningDirectoryDialog) - return; - delete p.scanningDirectoryDialog; p.scanningDirectoryDialog = nullptr; + + if (p.identifyingFilesDialog) + p.identifyingFilesDialog->show(); } void @@ -1052,6 +1084,9 @@ Tool::showScanningPlaylistDialog(int numFilesToScan) { auto &p = *p_func(); auto &worker = p.identifier->worker(); + if (p.identifyingFilesDialog) + p.identifyingFilesDialog->hide(); + if (!p.scanningDirectoryDialog) p.scanningDirectoryDialog = new QProgressDialog{ QY("Scanning directory"), QY("Cancel"), 0, numFilesToScan, this }; @@ -1087,6 +1122,9 @@ Tool::selectPlaylistToAdd(QVector const &identifiedPlaylists) { for (auto const &playlist : playlists) p.identifier->worker().addIdentifiedFile(playlist); + if (p.identifyingFilesDialog) + p.identifyingFilesDialog->show(); + p.identifier->continueIdentification(); } diff --git a/src/mkvtoolnix-gui/merge/tool.h b/src/mkvtoolnix-gui/merge/tool.h index 94f7e4ca6..a2df26fcc 100644 --- a/src/mkvtoolnix-gui/merge/tool.h +++ b/src/mkvtoolnix-gui/merge/tool.h @@ -79,8 +79,9 @@ public Q_SLOTS: virtual void openMultipleConfigFilesFromCommandLine(QStringList const &fileNames); - virtual void fileIdentificationStarted(); + virtual void fileIdentificationStarted(unsigned int numberOfQueuedFiles); virtual void fileIdentificationFinished(); + virtual void updateFileIdentificationProgress(unsigned int numberOfIdentifiedFiles, unsigned int numberOfQueuedFiles); virtual void handleIdentifiedXmlOrSimpleChapters(QString const &fileName); virtual void handleIdentifiedXmlSegmentInfo(QString const &fileName); virtual void handleIdentifiedXmlTags(QString const &fileName);