diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 2f1e99e2ba..97a3c19af4 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -314,7 +314,7 @@ set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE};${CMAKE_INSTALL_RPATH}" ) -target_link_libraries( ${APPLICATION_EXECUTABLE} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml Qt5::Qml Qt5::Quick Qt5::QuickControls2 Qt5::WebEngineWidgets) +target_link_libraries( ${APPLICATION_EXECUTABLE} Qt5::Widgets Qt5::GuiPrivate Qt5::Svg Qt5::Network Qt5::Xml Qt5::Qml Qt5::Quick Qt5::QuickControls2 Qt5::WebEngineWidgets) target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} ) IF(BUILD_UPDATER) target_link_libraries( ${APPLICATION_EXECUTABLE} updater ) diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 9ac569cbc8..a408b392bf 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -408,7 +408,9 @@ void Application::setupLogging() // might be called from second instance auto logger = Logger::instance(); logger->setLogFile(_logFile); - logger->setLogDir(!_logDir.isEmpty() ? _logDir : ConfigFile().logDir()); + if (_logFile.isEmpty()) { + logger->setLogDir(_logDir.isEmpty() ? ConfigFile().logDir() : _logDir); + } logger->setLogExpire(_logExpire > 0 ? _logExpire : ConfigFile().logExpire()); logger->setLogFlush(_logFlush || ConfigFile().logFlush()); logger->setLogDebug(_logDebug || ConfigFile().logDebug()); diff --git a/src/gui/generalsettings.cpp b/src/gui/generalsettings.cpp index fff5c9076b..8e57eb8d1d 100644 --- a/src/gui/generalsettings.cpp +++ b/src/gui/generalsettings.cpp @@ -30,21 +30,107 @@ #include "ignorelisteditor.h" #include "common/utility.h" +#include "logger.h" #include "config.h" #include "legalnotice.h" +#include +#include #include #include #include +#include + #define QTLEGACY (QT_VERSION < QT_VERSION_CHECK(5,9,0)) #if !(QTLEGACY) #include #endif +namespace { +struct ZipEntry { + QString localFilename; + QString zipFilename; +}; + +ZipEntry fileInfoToZipEntry(const QFileInfo &info) +{ + return { + info.absoluteFilePath(), + info.fileName() + }; +} + +ZipEntry fileInfoToLogZipEntry(const QFileInfo &info) +{ + auto entry = fileInfoToZipEntry(info); + entry.zipFilename.prepend(QStringLiteral("logs/")); + return entry; +} + +ZipEntry syncFolderToZipEntry(OCC::Folder *f) +{ + const auto journalPath = f->journalDb()->databaseFilePath(); + const auto journalInfo = QFileInfo(journalPath); + return fileInfoToZipEntry(journalInfo); +} + +QVector createFileList() +{ + auto list = QVector(); + OCC::ConfigFile cfg; + + list.append(fileInfoToZipEntry(QFileInfo(cfg.configFile()))); + + const auto logger = OCC::Logger::instance(); + + if (!logger->logDir().isEmpty()) { + list.append({QString(), QStringLiteral("logs")}); + + QDir dir(logger->logDir()); + const auto infoList = dir.entryInfoList(QDir::Files); + std::transform(std::cbegin(infoList), std::cend(infoList), + std::back_inserter(list), + fileInfoToLogZipEntry); + } else if (!logger->logFile().isEmpty()) { + list.append(fileInfoToZipEntry(QFileInfo(logger->logFile()))); + } + + const auto folders = OCC::FolderMan::instance()->map().values(); + std::transform(std::cbegin(folders), std::cend(folders), + std::back_inserter(list), + syncFolderToZipEntry); + + return list; +} + +void createDebugArchive(const QString &filename) +{ + const auto entries = createFileList(); + + QZipWriter zip(filename); + for (const auto &entry : entries) { + if (entry.localFilename.isEmpty()) { + zip.addDirectory(entry.zipFilename); + } else { + QFile file(entry.localFilename); + if (!file.open(QFile::ReadOnly)) { + continue; + } + zip.addFile(entry.zipFilename, &file); + } + } + + zip.addFile("__nextcloud_client_parameters.txt", QCoreApplication::arguments().join(' ').toUtf8()); + + const auto buildInfo = QString(OCC::Theme::instance()->about() + "\n\n" + OCC::Theme::instance()->aboutDetails()); + zip.addFile("__nextcloud_client_buildinfo.txt", buildInfo.toUtf8()); +} +} + namespace OCC { GeneralSettings::GeneralSettings(QWidget *parent) @@ -122,6 +208,7 @@ GeneralSettings::GeneralSettings(QWidget *parent) _ui->monoIconsCheckBox->setVisible(Theme::instance()->monoIconsAvailable()); connect(_ui->ignoredFilesButton, &QAbstractButton::clicked, this, &GeneralSettings::slotIgnoreFilesEditor); + connect(_ui->debugArchiveButton, &QAbstractButton::clicked, this, &GeneralSettings::slotCreateDebugArchive); // accountAdded means the wizard was finished and the wizard might change some options. connect(AccountManager::instance(), &AccountManager::accountAdded, this, &GeneralSettings::loadMiscSettings); @@ -260,6 +347,17 @@ void GeneralSettings::slotIgnoreFilesEditor() } } +void GeneralSettings::slotCreateDebugArchive() +{ + const auto filename = QFileDialog::getSaveFileName(this, tr("Create Debug Archive"), QString(), tr("Zip Archives") + " (*.zip)"); + if (filename.isEmpty()) { + return; + } + + createDebugArchive(filename); + QMessageBox::information(this, tr("Debug Archive Created"), tr("Debug archive is created at %1").arg(filename)); +} + void GeneralSettings::slotShowLegalNotice() { auto notice = new LegalNotice(); diff --git a/src/gui/generalsettings.h b/src/gui/generalsettings.h index 4b5e6a538f..fa6fe11b9c 100644 --- a/src/gui/generalsettings.h +++ b/src/gui/generalsettings.h @@ -48,6 +48,7 @@ private slots: void slotToggleOptionalServerNotifications(bool); void slotShowInExplorerNavigationPane(bool); void slotIgnoreFilesEditor(); + void slotCreateDebugArchive(); void loadMiscSettings(); void slotShowLegalNotice(); #if defined(BUILD_UPDATER) diff --git a/src/gui/generalsettings.ui b/src/gui/generalsettings.ui index ebc69ebd66..67e9af6ee9 100644 --- a/src/gui/generalsettings.ui +++ b/src/gui/generalsettings.ui @@ -6,8 +6,8 @@ 0 0 - 516 - 523 + 553 + 558 @@ -219,6 +219,13 @@ + + + + Create Debug Archive... + + + diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index c4e81110cd..da4aca58e1 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -901,8 +901,9 @@ void ConfigFile::setAutomaticLogDir(bool enabled) QString ConfigFile::logDir() const { + const auto defaultLogDir = QString(configPath() + QStringLiteral("/logs")); QSettings settings(configFile(), QSettings::IniFormat); - return settings.value(QLatin1String(logDirC), QString()).toString(); + return settings.value(QLatin1String(logDirC), defaultLogDir).toString(); } void ConfigFile::setLogDir(const QString &dir) @@ -914,7 +915,7 @@ void ConfigFile::setLogDir(const QString &dir) bool ConfigFile::logDebug() const { QSettings settings(configFile(), QSettings::IniFormat); - return settings.value(QLatin1String(logDebugC), false).toBool(); + return settings.value(QLatin1String(logDebugC), true).toBool(); } void ConfigFile::setLogDebug(bool enabled) @@ -926,7 +927,7 @@ void ConfigFile::setLogDebug(bool enabled) int ConfigFile::logExpire() const { QSettings settings(configFile(), QSettings::IniFormat); - return settings.value(QLatin1String(logExpireC), 0).toBool(); + return settings.value(QLatin1String(logExpireC), 24).toBool(); } void ConfigFile::setLogExpire(int hours) diff --git a/src/libsync/logger.cpp b/src/libsync/logger.cpp index 6827308e1a..d5d2048314 100644 --- a/src/libsync/logger.cpp +++ b/src/libsync/logger.cpp @@ -167,6 +167,11 @@ void Logger::setLogWindowActivated(bool activated) _logWindowActivated = activated; } +QString Logger::logFile() const +{ + return _logFile.fileName(); +} + void Logger::setLogFile(const QString &name) { QMutexLocker locker(&_mutex); @@ -204,6 +209,11 @@ void Logger::setLogExpire(int expire) _logExpire = expire; } +QString Logger::logDir() const +{ + return _logDirectory; +} + void Logger::setLogDir(const QString &dir) { _logDirectory = dir; diff --git a/src/libsync/logger.h b/src/libsync/logger.h index 5f32a8a0d8..12973c71c1 100644 --- a/src/libsync/logger.h +++ b/src/libsync/logger.h @@ -60,9 +60,15 @@ public: void postGuiMessage(const QString &title, const QString &message); void setLogWindowActivated(bool activated); + + QString logFile() const; void setLogFile(const QString &name); + void setLogExpire(int expire); + + QString logDir() const; void setLogDir(const QString &dir); + void setLogFlush(bool flush); bool logDebug() const { return _logDebug; }