diff --git a/tools/chatgui/src/member_files/browser.cpp b/tools/chatgui/src/member_files/browser.cpp index dc80baa7..34d840fd 100644 --- a/tools/chatgui/src/member_files/browser.cpp +++ b/tools/chatgui/src/member_files/browser.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,7 @@ static bool copyPath(char* out, const QString& value) { } MemberFileBrowser::MemberFileBrowser(DbManager* db, QWidget* parent) : QDialog(parent), m_db(db) { + m_uploadPool.setMaxThreadCount(1); setAttribute(Qt::WA_DeleteOnClose); setWindowTitle(text("Group files")); resize(940, 600); auto* layout = new QVBoxLayout(this); auto* selectors = new QHBoxLayout; @@ -108,6 +110,7 @@ MemberFileBrowser::~MemberFileBrowser() { cancel(); cancelRequest(m_listId); cancelRequest(m_quotaId); for (auto id : m_actions.keys()) cancelRequest(id); + m_uploadPool.waitForDone(); } void MemberFileBrowser::setChannel(const QString& channel, quint64 selectedOwner) { @@ -411,7 +414,23 @@ void MemberFileBrowser::beginUploads(const QStringList& paths, bool chooseServer DEBUG_INFO(DEBUG_CATEGORY_MEDIA, "file browser: upload queue started batch=%llu group=%llu server=%llu owner=%llu path=%s files=%d", (unsigned long long)m_uploadBatchId, (unsigned long long)m_group, (unsigned long long)server(), (unsigned long long)owner(), qPrintable(m_path), m_uploadTotal); - nextUpload(); + m_uploadStatus->setText(text("Checking selected files…")); + quint64 batch = m_uploadBatchId; QStringList sources = m_uploadQueue; + m_uploadPool.start(QRunnable::create([this, batch, sources] { + QString invalid; + for (const auto& source : sources) { + QFileInfo info(source); + if (!info.isFile() || info.isSymLink() || !info.isReadable()) { invalid = source; break; } + } + QMetaObject::invokeMethod(this, [this, batch, invalid] { + if (m_uploadBatchId != batch) return; + if (!invalid.isEmpty()) { + DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "file browser: source rejected path=%s (not a readable regular file)", qPrintable(invalid)); + finishUploads(text("Cannot upload %1. Select readable files, not folders or links.").arg(invalid)); return; + } + nextUpload(); + }, Qt::QueuedConnection); + })); } void MemberFileBrowser::nextUpload() { diff --git a/tools/chatgui/src/member_files/browser.h b/tools/chatgui/src/member_files/browser.h index 0533bd2e..6f492d92 100644 --- a/tools/chatgui/src/member_files/browser.h +++ b/tools/chatgui/src/member_files/browser.h @@ -1,11 +1,12 @@ -/* Браузер серверных файлов группы. Виджет не выполняет файловое/сетевое I/O: - * запросы уходят в uasync, передачи — в общий дисковый поток member_files. +/* Браузер серверных файлов группы. GUI-поток не выполняет файловое/сетевое I/O: + * проверка локальных путей — QThreadPool, запросы — uasync, передачи — дисковый поток member_files. * Контекст и request_id защищают от поздних ответов после перехода в другой каталог. */ #pragma once #include #include #include #include +#include #include class DbManager; class QComboBox; @@ -55,6 +56,7 @@ private: bool m_openAfter = false; quint64 m_uploadBatchId = 0, m_uploadStatId = 0; QStringList m_uploadQueue; + QThreadPool m_uploadPool; int m_uploadDone = 0, m_uploadSkipped = 0, m_uploadTotal = 0; int m_staleRetries = 0; QHash m_actions;