! * \brief Exports all settings (app-related and of Syncthing itself) to the specified \a url. * \remarks The \a url is passed by value so m_settingsExport can be passed despite being cleared by this function. */
| 1220 | * \remarks The \a url is passed by value so m_settingsExport can be passed despite being cleared by this function. |
| 1221 | */ |
| 1222 | bool App::exportSettings(QUrl url, const QJSValue &callback) |
| 1223 | { |
| 1224 | if (checkOngoingImportExport()) { |
| 1225 | return false; |
| 1226 | } |
| 1227 | |
| 1228 | if (m_isSyncthingRunning) { |
| 1229 | emit info(tr("Waiting for backend to terminate before exporting settings …")); |
| 1230 | m_settingsExport.url = url; |
| 1231 | m_settingsExport.callback = callback; |
| 1232 | terminateSyncthing(); |
| 1233 | return false; |
| 1234 | } |
| 1235 | |
| 1236 | setImportExportStatus(ImportExportStatus::Exporting); |
| 1237 | m_settingsExport.url.reset(); |
| 1238 | |
| 1239 | const auto tweaksSettings = m_settings.value(QLatin1String("tweaks")).toObject(); |
| 1240 | QtConcurrent::run([this, url, currentHomePath = currentSyncthingHomeDir(), |
| 1241 | asArchive = tweaksSettings.value(QLatin1String("importExportAsArchive")).toBool(), |
| 1242 | encryptionPassword = tweaksSettings.value(QLatin1String("importExportEncryptionPassword")).toString(), |
| 1243 | exportDir = tweaksSettings.value(QLatin1String("exportDir")).toString()] { |
| 1244 | if (!m_settingsDir.has_value()) { |
| 1245 | return std::make_pair(tr("settings directory was not located."), true); |
| 1246 | } |
| 1247 | |
| 1248 | auto path = QString(); |
| 1249 | if (url.isEmpty()) { |
| 1250 | if (exportDir.isEmpty()) { |
| 1251 | return std::make_pair(tr("no destination or file or directory specified/configured."), true); |
| 1252 | } |
| 1253 | path = makeExportPath(exportDir, QStringLiteral("syncthing-app-backup"), asArchive ? QStringLiteral(".zip") : QString()); |
| 1254 | } else { |
| 1255 | path = m_models.resolveUrl(url); |
| 1256 | } |
| 1257 | |
| 1258 | if (asArchive) { |
| 1259 | #ifdef Q_OS_ANDROID |
| 1260 | const auto error = QJniObject(QNativeInterface::QAndroidApplication::context()) |
| 1261 | .callMethod<jstring>("compressArchive", m_settingsDir->path(), currentHomePath, path, encryptionPassword) |
| 1262 | .toString(); |
| 1263 | return std::make_pair(error.isEmpty() ? tr("Settings have been archived to \"%1\".").arg(path) : error, !error.isEmpty()); |
| 1264 | #else |
| 1265 | return std::make_pair(tr("Archiving is only supported on Android."), true); |
| 1266 | #endif |
| 1267 | } |
| 1268 | |
| 1269 | const auto dir = QDir(path); |
| 1270 | if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) { |
| 1271 | return std::make_pair(tr("unable to create export directory under \"%1\"").arg(path), true); |
| 1272 | } |
| 1273 | try { |
| 1274 | std::filesystem::copy(SYNCTHING_APP_STRING_CONVERSION(m_settingsDir->path()), SYNCTHING_APP_STRING_CONVERSION(path), |
| 1275 | std::filesystem::copy_options::update_existing | std::filesystem::copy_options::recursive); |
| 1276 | if (!currentHomePath.isEmpty()) { |
| 1277 | std::filesystem::copy(SYNCTHING_APP_STRING_CONVERSION(currentHomePath), |
| 1278 | SYNCTHING_APP_STRING_CONVERSION(path + QStringLiteral("/syncthing")), |
| 1279 | std::filesystem::copy_options::update_existing | std::filesystem::copy_options::recursive); |
nothing calls this directly
no test coverage detected