From 4af2ec88bdef9daba28211dce2a0a7e45fe731f9 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Mon, 25 Mar 2024 10:58:27 +0100 Subject: [PATCH] Use std::vector instead of QStringList in main() In an effort to convert core to C++ structures. Signed-off-by: Berthold Stoeger --- Subsurface-mobile.pro | 1 + core/CMakeLists.txt | 1 + core/subsurface-string.cpp | 17 ++++++++++++++ core/subsurface-string.h | 3 +++ desktop-widgets/mainwindow.cpp | 42 +++++++++++++++++++--------------- desktop-widgets/mainwindow.h | 4 ++-- subsurface-desktop-main.cpp | 31 ++++++++++++------------- subsurface-downloader-main.cpp | 39 +++++++++++++++---------------- 8 files changed, 80 insertions(+), 58 deletions(-) create mode 100644 core/subsurface-string.cpp diff --git a/Subsurface-mobile.pro b/Subsurface-mobile.pro index 36538c618..c64dacf4f 100644 --- a/Subsurface-mobile.pro +++ b/Subsurface-mobile.pro @@ -44,6 +44,7 @@ SOURCES += subsurface-mobile-main.cpp \ core/file.cpp \ core/fulltext.cpp \ core/subsurfacestartup.cpp \ + core/subsurface-string.cpp \ core/pref.c \ core/profile.cpp \ core/device.cpp \ diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index e6f373da7..7a38d82d8 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -172,6 +172,7 @@ set(SUBSURFACE_CORE_LIB_SRCS string-format.cpp strtod.c subsurface-float.h + subsurface-string.cpp subsurface-string.h subsurfacestartup.cpp subsurfacestartup.h diff --git a/core/subsurface-string.cpp b/core/subsurface-string.cpp new file mode 100644 index 000000000..2d90943b0 --- /dev/null +++ b/core/subsurface-string.cpp @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "subsurface-string.h" + +std::string join(const std::vector &l, const std::string &separator, bool skip_empty) +{ + std::string res; + bool first = true; + for (const std::string &s: l) { + if (skip_empty && l.empty()) + continue; + if (!first) + res += separator; + res += s; + first = false; + } + return res; +} diff --git a/core/subsurface-string.h b/core/subsurface-string.h index 4a17b2653..55559809d 100644 --- a/core/subsurface-string.h +++ b/core/subsurface-string.h @@ -66,6 +66,7 @@ extern double strtod_flags(const char *str, const char **ptr, unsigned int flags } #include +#include // Sadly, starts_with only with C++20! inline bool starts_with(const std::string &s, const char *s2) @@ -73,6 +74,8 @@ inline bool starts_with(const std::string &s, const char *s2) return s.rfind(s2, 0) == 0; } +std::string join(const std::vector &l, const std::string &separator, bool skip_empty = false); + #endif #endif // SUBSURFACE_STRING_H diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index 6a42ab49f..71320738e 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -376,13 +376,13 @@ void MainWindow::on_actionOpen_triggered() // some file dialogs decide to add the default extension to a filename without extension // so we would get dir[branch].ssrf when trying to select dir[branch]. // let's detect that and remove the incorrect extension - QStringList cleanFilenames; + std::vector cleanFilenames; QRegularExpression reg(".*\\[[^]]+]\\.ssrf", QRegularExpression::CaseInsensitiveOption); for (QString filename: filenames) { if (reg.match(filename).hasMatch()) filename.remove(QRegularExpression("\\.ssrf$", QRegularExpression::CaseInsensitiveOption)); - cleanFilenames << filename; + cleanFilenames.push_back(filename.toStdString()); } loadFiles(cleanFilenames); } @@ -399,6 +399,11 @@ void MainWindow::on_actionSaveAs_triggered() file_save_as(); } +static std::string encodeFileName(const std::string &fn) +{ + return QFile::encodeName(QString::fromStdString(fn)).toStdString(); +} + void MainWindow::on_actionCloudstorageopen_triggered() { if (!okToClose(tr("Please save or cancel the current dive edit before opening a new file."))) @@ -414,9 +419,9 @@ void MainWindow::on_actionCloudstorageopen_triggered() closeCurrentFile(); showProgressBar(); - QByteArray fileNamePtr = QFile::encodeName(QString::fromStdString(*filename)); - if (!parse_file(fileNamePtr.data(), &divelog)) - setCurrentFile(fileNamePtr.toStdString()); + std::string encoded = encodeFileName(*filename); + if (!parse_file(encoded.c_str(), &divelog)) + setCurrentFile(encoded); process_loaded_dives(); hideProgressBar(); refreshDisplay(); @@ -1156,7 +1161,7 @@ void MainWindow::recentFileTriggered(bool) updateLastUsedDir(QFileInfo(filename).dir().path()); closeCurrentFile(); - loadFiles(QStringList() << filename); + loadFiles(std::vector { filename.toStdString() }); } int MainWindow::file_save_as(void) @@ -1280,33 +1285,32 @@ void MainWindow::setTitle() setWindowTitle("Subsurface: " + displayedFilename(existing_filename) + unsaved + shown); } -void MainWindow::importFiles(const QStringList &fileNames) +void MainWindow::importFiles(const std::vector &fileNames) { - if (fileNames.isEmpty()) + if (fileNames.empty()) return; - QByteArray fileNamePtr; struct divelog log; - for (int i = 0; i < fileNames.size(); ++i) { - fileNamePtr = QFile::encodeName(fileNames.at(i)); - parse_file(fileNamePtr.data(), &log); + for (const std::string &fn: fileNames) { + std::string encoded = encodeFileName(fn); + parse_file(encoded.c_str(), &log); } - QString source = fileNames.size() == 1 ? fileNames[0] : tr("multiple files"); + QString source = fileNames.size() == 1 ? QString::fromStdString(fileNames[0]) : tr("multiple files"); Command::importDives(&log, IMPORT_MERGE_ALL_TRIPS, source); } -void MainWindow::loadFiles(const QStringList &fileNames) +void MainWindow::loadFiles(const std::vector &fileNames) { - if (fileNames.isEmpty()) { + if (fileNames.empty()) { refreshDisplay(); return; } QByteArray fileNamePtr; showProgressBar(); - for (int i = 0; i < fileNames.size(); ++i) { - fileNamePtr = QFile::encodeName(fileNames.at(i)); + for (const std::string &fn: fileNames) { + fileNamePtr = QFile::encodeName(QString::fromStdString(fn)); if (!parse_file(fileNamePtr.data(), &divelog)) { setCurrentFile(fileNamePtr.toStdString()); addRecentFile(fileNamePtr, false); @@ -1352,13 +1356,13 @@ void MainWindow::on_actionImportDiveLog_triggered() return; updateLastUsedDir(QFileInfo(fileNames[0]).dir().path()); - QStringList logFiles; + std::vector logFiles; QStringList csvFiles; for (const QString &fn: fileNames) { if (isCsvFile(fn)) csvFiles.append(fn); else - logFiles.append(fn); + logFiles.push_back(fn.toStdString()); } if (logFiles.size()) diff --git a/desktop-widgets/mainwindow.h b/desktop-widgets/mainwindow.h index 9b397a219..d156fbfd9 100644 --- a/desktop-widgets/mainwindow.h +++ b/desktop-widgets/mainwindow.h @@ -67,8 +67,8 @@ public: Count }; - void loadFiles(const QStringList &files); - void importFiles(const QStringList &importFiles); + void loadFiles(const std::vector &files); + void importFiles(const std::vector &importFiles); void setToolButtonsEnabled(bool enabled); void setApplicationState(ApplicationState state); void enterPreviousState(); diff --git a/subsurface-desktop-main.cpp b/subsurface-desktop-main.cpp index d15f946f5..835258b74 100644 --- a/subsurface-desktop-main.cpp +++ b/subsurface-desktop-main.cpp @@ -13,6 +13,7 @@ #include "core/qt-gui.h" #include "core/qthelper.h" #include "core/subsurfacestartup.h" +#include "core/subsurface-string.h" #include "core/settings/qPref.h" #include "core/tag.h" #include "desktop-widgets/mainwindow.h" @@ -37,23 +38,22 @@ int main(int argc, char **argv) if (verbose) /* print the version if the Win32 console_init() code enabled verbose. */ print_version(); - int i; bool no_filenames = true; QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); std::unique_ptr app(new QApplication(argc, argv)); - QStringList files; - QStringList importedFiles; + std::vector files; + std::vector importedFiles; QStringList arguments = QCoreApplication::arguments(); const char *default_directory = system_default_directory(); subsurface_mkdir(default_directory); - for (i = 1; i < arguments.length(); i++) { - QString a = arguments.at(i); - if (a.isEmpty()) + for (int i = 1; i < arguments.length(); i++) { + std::string a = arguments[i].toStdString(); + if (a.empty()) continue; - if (a.at(0) == '-') { - parse_argument(qPrintable(a)); + if (a[0] == '-') { + parse_argument(a.c_str()); continue; } if (imported) { @@ -85,21 +85,20 @@ int main(int argc, char **argv) init_ui(); if (no_filenames) { if (prefs.default_file_behavior == LOCAL_DEFAULT_FILE) { - QString defaultFile(prefs.default_filename); - if (!defaultFile.isEmpty()) - files.push_back(QString(prefs.default_filename)); + if (!empty_string(prefs.default_filename)) + files.emplace_back(prefs.default_filename ? prefs.default_filename : ""); } else if (prefs.default_file_behavior == CLOUD_DEFAULT_FILE) { auto cloudURL = getCloudURL(); if (cloudURL) - files.push_back(QString::fromStdString(*cloudURL)); + files.push_back(*cloudURL); } } MainWindow *m = MainWindow::instance(); - if (verbose && !files.isEmpty()) - qDebug() << "loading dive data from" << files; + if (verbose && !files.empty()) + report_info("loading dive data from: %s", join(files, std::string(", ")).c_str()); m->loadFiles(files); - if (verbose && !importedFiles.isEmpty()) - qDebug() << "importing dive data from" << importedFiles; + if (verbose && !importedFiles.empty()) + report_info("importing dive data from %s", join(importedFiles, std::string(", ")).c_str()); m->importFiles(importedFiles); if (verbose > 0) diff --git a/subsurface-downloader-main.cpp b/subsurface-downloader-main.cpp index f5f131941..2b4cea1e7 100644 --- a/subsurface-downloader-main.cpp +++ b/subsurface-downloader-main.cpp @@ -36,11 +36,10 @@ int main(int argc, char **argv) // supporting BT makes sense when used with an iPhone and an rfcomm BT device? QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); - int i; bool no_filenames = true; std::unique_ptr app(new QCoreApplication(argc, argv)); - QStringList files; - QStringList importedFiles; + std::vector files; + std::vector importedFiles; QStringList arguments = QCoreApplication::arguments(); // set a default logfile name for libdivecomputer so we always get a logfile @@ -60,12 +59,12 @@ int main(int argc, char **argv) // now handle the arguments fill_computer_list(); - for (i = 1; i < arguments.length(); i++) { - QString a = arguments.at(i); - if (a.isEmpty()) + for (int i = 1; i < arguments.length(); i++) { + std::string a = arguments[i].toStdString(); + if (a.empty()) continue; - if (a.at(0) == '-') { - parse_argument(qPrintable(a)); + if (a[0] == '-') { + parse_argument(a.c_str()); continue; } if (imported) { @@ -80,19 +79,18 @@ int main(int argc, char **argv) if (no_filenames) { if (prefs.default_file_behavior == LOCAL_DEFAULT_FILE) { - QString defaultFile(prefs.default_filename); - if (!defaultFile.isEmpty()) - files.push_back(QString(prefs.default_filename)); + if (!empty_string(prefs.default_filename)) + files.emplace_back(prefs.default_filename ? prefs.default_filename : ""); } else if (prefs.default_file_behavior == CLOUD_DEFAULT_FILE) { auto cloudURL = getCloudURL(); if (cloudURL) - files.push_back(QString::fromStdString(*cloudURL)); + files.emplace_back(*cloudURL); } } - if (!files.isEmpty()) { - qDebug() << "loading dive data from" << files; - if (parse_file(qPrintable(files.first()), &divelog) < 0) { - printf("Failed to load dives from file '%s', aborting.\n", qPrintable(files.first())); + if (!files.empty()) { + report_info("loading dive data from %s", join(files, ", ").c_str()); + if (parse_file(files.front().c_str(), &divelog) < 0) { + printf("Failed to load dives from file '%s', aborting.\n", files.front().c_str()); exit(1); } } @@ -104,11 +102,10 @@ int main(int argc, char **argv) cliDownloader(prefs.dive_computer.vendor, prefs.dive_computer.product, prefs.dive_computer.device); } } - if (!files.isEmpty()) { - qDebug() << "saving dive data to" << files; - save_dives(qPrintable(files.first())); - } - else { + if (!files.empty()) { + report_info("saving dive data to %s", join(files, ", ").c_str()); + save_dives(files.front().c_str()); + } else { printf("No log files given, not saving dive data.\n"); printf("Give a log file name as argument, or configure a cloud URL.\n"); }