diff --git a/core/dive.h b/core/dive.h index f3143a6da..b4ed2af1d 100644 --- a/core/dive.h +++ b/core/dive.h @@ -207,8 +207,6 @@ extern void invalidate_dive_cache(struct dive *dc); extern int total_weight(const struct dive *); -extern const char *existing_filename; - extern bool has_planned(const struct dive *dive, bool planned); /* Get gasmixes at increasing timestamps. @@ -229,8 +227,11 @@ extern void update_setpoint_events(const struct dive *dive, struct divecomputer * QVariants and through QML. */ #include +#include Q_DECLARE_METATYPE(struct dive *); +extern std::string existing_filename; + #endif #endif // DIVE_H diff --git a/core/qthelper.cpp b/core/qthelper.cpp index 3eefd196f..6cf4fb345 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -44,7 +44,7 @@ #include -const char *existing_filename; +std::string existing_filename; static QLocale loc; static inline QString degreeSigns() @@ -521,12 +521,6 @@ QLocale getLocale() return loc; } -void set_filename(const char *filename) -{ - free((void *)existing_filename); - existing_filename = copy_string(filename); -} - QString get_depth_string(int mm, bool showunit, bool showdecimal) { if (prefs.units.length == units::METERS) { diff --git a/core/qthelper.h b/core/qthelper.h index a32bc8ebb..41364b9f8 100644 --- a/core/qthelper.h +++ b/core/qthelper.h @@ -125,7 +125,6 @@ bool canReachCloudServer(struct git_info *); void updateWindowTitle(); void subsurface_mkdir(const char *dir); char *get_file_name(const char *fileName); -void set_filename(const char *filename); void copy_image_and_overwrite(const char *cfileName, const char *path, const char *cnewName); char *move_away(const char *path); const char *local_file_path(struct picture *picture); diff --git a/core/save-git.cpp b/core/save-git.cpp index d93de9370..1fd0270c2 100644 --- a/core/save-git.cpp +++ b/core/save-git.cpp @@ -1192,12 +1192,12 @@ static int create_new_commit(struct git_info *info, git_oid *tree_id, bool creat return report_error("Unable to look up parent in branch '%s'", info->branch); if (!saved_git_id.empty()) { - if (existing_filename && verbose) - report_info("existing filename %s\n", existing_filename); + if (!existing_filename.empty() && verbose) + report_info("existing filename %s\n", existing_filename.c_str()); const git_oid *id = git_commit_id((const git_commit *) parent); /* if we are saving to the same git tree we got this from, let's make * sure there is no confusion */ - if (same_string(existing_filename, info->url) && git_oid_strcmp(id, saved_git_id.c_str())) + if (existing_filename == info->url && git_oid_strcmp(id, saved_git_id.c_str())) return report_error("The git branch does not match the git parent of the source"); } diff --git a/core/subsurface-string.h b/core/subsurface-string.h index 582f7622b..6f05063d5 100644 --- a/core/subsurface-string.h +++ b/core/subsurface-string.h @@ -76,5 +76,11 @@ std::string format_string_std(const char *fmt, Args&&... args) return res; } +// Sadly, starts_with only with C++20! +inline bool starts_with(const std::string &s, const char *s2) +{ + return s.rfind(s2, 0) == 0; +} + #endif #endif // SUBSURFACE_STRING_H diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index edad5d9e8..1a3ab6c12 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -512,22 +512,22 @@ void MainWindow::closeCurrentFile() clear_dive_file_data(); // this clears all the core data structures and resets the models setCurrentFile(nullptr); diveList->setSortOrder(DiveTripModelBase::NR, Qt::DescendingOrder); - if (!existing_filename) + if (existing_filename.empty()) setTitle(); disableShortcuts(); } void MainWindow::updateCloudOnlineStatus() { - bool is_cloud = existing_filename && prefs.cloud_verification_status == qPrefCloudStorage::CS_VERIFIED && - strstr(existing_filename, prefs.cloud_base_url); + bool is_cloud = !existing_filename.empty() && prefs.cloud_verification_status == qPrefCloudStorage::CS_VERIFIED && + existing_filename.find(prefs.cloud_base_url) != std::string::npos; ui.actionCloudOnline->setEnabled(is_cloud); ui.actionCloudOnline->setChecked(is_cloud && !git_local_only); } void MainWindow::setCurrentFile(const char *f) { - set_filename(f); + existing_filename = f; setTitle(); updateCloudOnlineStatus(); } @@ -545,13 +545,18 @@ void MainWindow::updateLastUsedDir(const QString &dir) qPrefDisplay::set_lastDir(dir); } +static QString get_current_filename() +{ + return existing_filename.empty() ? QString(prefs.default_filename) + : QString::fromStdString(existing_filename); +} void MainWindow::on_actionPrint_triggered() { #ifndef NO_PRINTING // When in planner, only print the planned dive. dive *singleDive = appState == ApplicationState::PlanDive ? plannerWidgets->getDive() : nullptr; - QString filename = existing_filename ?: prefs.default_filename; + QString filename = get_current_filename(); PrintDialog dlg(singleDive, filename, this); dlg.exec(); @@ -608,7 +613,7 @@ void MainWindow::on_actionQuit_triggered() void MainWindow::on_actionDownloadDC_triggered() { - QString filename = existing_filename ?: prefs.default_filename; + QString filename = get_current_filename(); DownloadFromDCWidget dlg(filename, this); dlg.exec(); } @@ -980,7 +985,7 @@ bool MainWindow::askSaveChanges() { QMessageBox response(this); - QString message = existing_filename ? + QString message = !existing_filename.empty() ? tr("Do you want to save the changes that you made in the file %1?").arg(displayedFilename(existing_filename)) : tr("Do you want to save the changes that you made in the data file?"); @@ -1157,23 +1162,23 @@ void MainWindow::recentFileTriggered(bool) int MainWindow::file_save_as(void) { QString filename; - const char *default_filename = existing_filename; + std::string default_filename = existing_filename; // if the default is to save to cloud storage, pick something that will work as local file: // simply extract the branch name which should be the users email address - if (default_filename && QString(default_filename).contains(QRegularExpression(CLOUD_HOST_PATTERN))) { - QString filename(default_filename); + if (!default_filename.empty() && QString::fromStdString(default_filename).contains(QRegularExpression(CLOUD_HOST_PATTERN))) { + QString filename = QString::fromStdString(default_filename); filename.remove(0, filename.indexOf("[") + 1); filename.replace("]", ".ssrf"); - default_filename = copy_qstring(filename); + default_filename = filename.toStdString(); } // create a file dialog that allows us to save to a new file - QFileDialog selection_dialog(this, tr("Save file as"), default_filename, + QFileDialog selection_dialog(this, tr("Save file as"), default_filename.c_str(), tr("Subsurface files") + " (*.ssrf *.xml)"); selection_dialog.setAcceptMode(QFileDialog::AcceptSave); selection_dialog.setFileMode(QFileDialog::AnyFile); selection_dialog.setDefaultSuffix(""); - if (empty_string(default_filename)) { + if (default_filename.empty()) { QFileInfo defaultFile(system_default_filename()); selection_dialog.setDirectory(qPrintable(defaultFile.absolutePath())); } @@ -1207,15 +1212,15 @@ int MainWindow::file_save(void) const char *current_default; bool is_cloud = false; - if (!existing_filename) + if (existing_filename.empty()) return file_save_as(); - is_cloud = (strncmp(existing_filename, "http", 4) == 0); + is_cloud = (starts_with(existing_filename, "http") == 0); if (is_cloud && !saveToCloudOK()) return -1; current_default = prefs.default_filename; - if (strcmp(existing_filename, current_default) == 0) { + if (existing_filename == current_default) { /* if we are using the default filename the directory * that we are creating the file in may not exist */ QDir current_def_dir = QFileInfo(current_default).absoluteDir(); @@ -1224,7 +1229,7 @@ int MainWindow::file_save(void) } if (is_cloud) showProgressBar(); - if (save_dives(existing_filename)) { + if (save_dives(existing_filename.c_str())) { if (is_cloud) hideProgressBar(); return -1; @@ -1232,7 +1237,7 @@ int MainWindow::file_save(void) if (is_cloud) hideProgressBar(); Command::setClean(); - addRecentFile(QString(existing_filename), true); + addRecentFile(QString::fromStdString(existing_filename), true); return 0; } @@ -1241,13 +1246,13 @@ NotificationWidget *MainWindow::getNotificationWidget() return ui.mainErrorMessage; } -QString MainWindow::displayedFilename(QString fullFilename) +QString MainWindow::displayedFilename(const std::string &fullFilename) { - QFile f(fullFilename); + QFile f(fullFilename.c_str()); QFileInfo fileInfo(f); QString fileName(fileInfo.fileName()); - if (fullFilename.contains(prefs.cloud_base_url)) { + if (fullFilename.find(prefs.cloud_base_url) != std::string::npos) { QString email = fileName.left(fileName.indexOf('[')); return git_local_only ? tr("[local cache for] %1").arg(email) : @@ -1265,7 +1270,7 @@ void MainWindow::setAutomaticTitle() void MainWindow::setTitle() { - if (empty_string(existing_filename)) { + if (existing_filename.empty()) { setWindowTitle("Subsurface"); return; } @@ -1397,7 +1402,7 @@ void MainWindow::on_actionExport_triggered() void MainWindow::on_actionConfigure_Dive_Computer_triggered() { - QString filename = existing_filename ?: prefs.default_filename; + QString filename = get_current_filename(); ConfigureDiveComputerDialog *dcConfig = new ConfigureDiveComputerDialog(filename, this); dcConfig->show(); } diff --git a/desktop-widgets/mainwindow.h b/desktop-widgets/mainwindow.h index 7df68750e..209e429c4 100644 --- a/desktop-widgets/mainwindow.h +++ b/desktop-widgets/mainwindow.h @@ -177,7 +177,7 @@ private: QString filter_import(); QString filter_import_dive_sites(); static MainWindow *m_Instance; - QString displayedFilename(QString fullFilename); + QString displayedFilename(const std::string &fullFilename); bool askSaveChanges(); bool okToClose(QString message); void closeCurrentFile(); diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index 7e7fe783a..ae9bbcfeb 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -430,7 +430,7 @@ void QMLManager::openLocalThenRemote(QString url) git_local_only = false; appendTextToLog(QStringLiteral("taking things online to be able to switch to cloud account")); } - set_filename(encodedFilename.constData()); + existing_filename = encodedFilename.toStdString(); if (git_local_only && qPrefCloudStorage::cloud_verification_status() != qPrefCloudStorage::CS_NOCLOUD) appendTextToLog(QStringLiteral("have cloud credentials, but user asked not to connect to network")); @@ -572,24 +572,24 @@ void QMLManager::finishSetup() !qPrefCloudStorage::cloud_storage_password().isEmpty() && getCloudURL(url) == 0) { openLocalThenRemote(url); - } else if (!empty_string(existing_filename) && + } else if (!existing_filename.empty() && qPrefCloudStorage::cloud_verification_status() != qPrefCloudStorage::CS_UNKNOWN) { rememberOldStatus(); - set_filename(qPrintable(nocloud_localstorage())); + existing_filename = nocloud_localstorage().toStdString(); qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NOCLOUD); emit passwordStateChanged(); saveCloudCredentials(qPrefCloudStorage::cloud_storage_email(), qPrefCloudStorage::cloud_storage_password(), qPrefCloudStorage::cloud_storage_pin()); appendTextToLog(tr("working in no-cloud mode")); - int error = parse_file(existing_filename, &divelog); + int error = parse_file(existing_filename.c_str(), &divelog); if (error) { // we got an error loading the local file setNotificationText(tr("Error parsing local storage, giving up")); - set_filename(NULL); + existing_filename.clear(); } else { // successfully opened the local file, now add thigs to the dive list consumeFinishedLoad(); updateHaveLocalChanges(true); - appendTextToLog(QString("working in no-cloud mode, finished loading %1 dives from %2").arg(divelog.dives->nr).arg(existing_filename)); + appendTextToLog(QString("working in no-cloud mode, finished loading %1 dives from %2").arg(divelog.dives->nr).arg(existing_filename.c_str())); } } else { qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_UNKNOWN); @@ -769,7 +769,7 @@ void QMLManager::deleteAccount() qPrefCloudStorage::set_cloud_storage_password(""); qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NOCLOUD); emit passwordStateChanged(); - set_filename(qPrintable(nocloud_localstorage())); + existing_filename = nocloud_localstorage().toStdString(); setStartPageText(tr("Cloud storage account deleted.")); return; } @@ -808,12 +808,12 @@ void QMLManager::loadDivesWithValidCredentials() setDiveListProcessing(false); if (!error) { report_error("filename is now %s", fileNamePrt.data()); - set_filename(fileNamePrt.data()); + existing_filename = fileNamePrt.toStdString(); } else { report_error("failed to open file %s", fileNamePrt.data()); setNotificationText(consumeError()); revertToNoCloudIfNeeded(); - set_filename(NULL); + existing_filename.clear(); return; } consumeFinishedLoad(); @@ -873,7 +873,7 @@ void QMLManager::revertToNoCloudIfNeeded() rememberOldStatus(); qPrefCloudStorage::set_cloud_verification_status(qPrefCloudStorage::CS_NOCLOUD); emit passwordStateChanged(); - set_filename(qPrintable(nocloud_localstorage())); + existing_filename = nocloud_localstorage().toStdString(); setStartPageText(RED_FONT + tr("Failed to connect to cloud server, reverting to no cloud status") + END_FONT); } } @@ -1477,7 +1477,7 @@ void QMLManager::openNoCloudRepo() // repo doesn't exist, create it and write the empty dive list to it git_create_local_repo(qPrintable(filename)); save_dives(qPrintable(filename)); - set_filename(qPrintable(filename)); + existing_filename = filename.toStdString(); auto s = qPrefLog::instance(); s->set_default_filename(qPrintable(filename)); s->set_default_file_behavior(LOCAL_DEFAULT_FILE); @@ -1489,10 +1489,10 @@ void QMLManager::saveChangesLocal(bool fromUndo) { if (unsavedChanges()) { if (qPrefCloudStorage::cloud_verification_status() == qPrefCloudStorage::CS_NOCLOUD) { - if (empty_string(existing_filename)) { + if (existing_filename.empty()) { QString filename = nocloud_localstorage(); git_create_local_repo(qPrintable(filename)); - set_filename(qPrintable(filename)); + existing_filename = filename.toStdString(); auto s = qPrefLog::instance(); s->set_default_filename(qPrintable(filename)); s->set_default_file_behavior(LOCAL_DEFAULT_FILE); @@ -1505,11 +1505,11 @@ void QMLManager::saveChangesLocal(bool fromUndo) } bool glo = git_local_only; git_local_only = true; - int error = save_dives(existing_filename); + int error = save_dives(existing_filename.c_str()); git_local_only = glo; if (error) { setNotificationText(consumeError()); - set_filename(NULL); + existing_filename.clear(); return; } mark_divelist_changed(false); diff --git a/subsurface-helper.cpp b/subsurface-helper.cpp index 351e3d19b..62ba125f8 100644 --- a/subsurface-helper.cpp +++ b/subsurface-helper.cpp @@ -67,7 +67,6 @@ void init_ui() void exit_ui() { free_globals(); - free((void *)existing_filename); } #ifdef SUBSURFACE_MOBILE diff --git a/subsurface-mobile-main.cpp b/subsurface-mobile-main.cpp index d090fd6b9..cc9f95a11 100644 --- a/subsurface-mobile-main.cpp +++ b/subsurface-mobile-main.cpp @@ -79,9 +79,9 @@ int main(int argc, char **argv) } init_ui(); if (prefs.default_file_behavior == LOCAL_DEFAULT_FILE) - set_filename(prefs.default_filename); + existing_filename = prefs.default_filename; else - set_filename(NULL); + existing_filename.clear(); // some hard coded settings qPrefCloudStorage::set_save_password_local(true);