From 1e41b0d914251cfa0e1657dcffd2b040a67b844d Mon Sep 17 00:00:00 2001 From: Viktor Kopp Date: Thu, 24 Oct 2024 08:54:45 +0200 Subject: [PATCH] Reapply "Use QCommandLineParser instead of custom cmd args parsing (#543)" (#566) This reverts commit 3e370ece1537c041253fa4d636adaf226f5a27b3. Signed-off-by: Viktor Kopp --- qdlt/qdltoptmanager.cpp | 307 ++++++++++++++---------------- qdlt/qdltoptmanager.h | 10 +- qdlt/tests/test_dltoptmanager.cpp | 24 +-- src/mainwindow.cpp | 2 - 4 files changed, 165 insertions(+), 178 deletions(-) diff --git a/qdlt/qdltoptmanager.cpp b/qdlt/qdltoptmanager.cpp index 3c9eb874..233f5baf 100644 --- a/qdlt/qdltoptmanager.cpp +++ b/qdlt/qdltoptmanager.cpp @@ -23,9 +23,38 @@ #include "qdltoptmanager.h" #include "version.h" + #include #include +QDltOptManager::QDltOptManager() +{ + m_parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); + + m_parser.addPositionalArgument("logfile", "Loading one or more logfiles on startup (must end with .dlt)"); + m_parser.addPositionalArgument("projectfile", "Loading project file on startup (must end with .dlp)"); + m_parser.addPositionalArgument("filterfile", "Loading filterfile on startup (must end with .dlf)"); + m_parser.addPositionalArgument("pcapfile", "Importing DLT/IPC from pcap file on startup (must end with .pcap)"); + m_parser.addPositionalArgument("mf4file", "Importing DLT/IPC from mf4 file on startup (must end with .mf4)"); + m_parser.addOptions({ + {"c", "Convert logfile file to ", "textfile"}, + {"u", "Conversion will be done in UTF8 instead of ASCII"}, + {"csv", "Conversion will be done in CSV format"}, + {"d", "Conversion will NOT be done, save in dlt file format again instead"}, + {"dd", "Conversion will NOT be done, save as decoded messages in dlt format"}, + {"b", "Execute a plugin command with parameters before loading log file.", "plugin|command|param1|..|param"}, + {"e", "Execute a plugin command with parameters after loading log file.", "plugin|command|param1|..|param"}, + {QStringList() << "s" << "silent", "Enable silent mode without any GUI. Ideal for commandline usage."}, + {"stream", "Treat the input logfiles as DLT stream instead of DLT files."}, + {QStringList() << "t" << "terminate", "Terminate DLT Viewer after command line execution."}, + {"w", "Set the working directory", "workingdirectory"}, + {"delimiter", "The used delimiter for CSV export (Default: ,).", "character"}, + {QStringList() << "h" << "help", "Print this help message."}, + {QStringList() << "v" << "version", "Print the version."} + }); + +} + QDltOptManager* QDltOptManager::getInstance() { static QDltOptManager instance; @@ -60,177 +89,157 @@ void QDltOptManager::printVersion(QString appname) qDebug() << "Version:" << PACKAGE_VERSION << PACKAGE_VERSION_STATE; } -void QDltOptManager::printUsage() +void QDltOptManager::printUsage(const QString& helpText) { - qDebug().noquote() << getHelpText(); - - qDebug()<<"\nExamples:"; - qDebug()<<" dlt-viewer.exe -t -c output.txt input.dlt"; - qDebug()<<" dlt-viewer.exe -t -s -u -c output.txt input.dlt"; - qDebug()<<" dlt-viewer.exe -t -s -d -c output.dlt input.dlt"; - qDebug()<<" dlt-viewer.exe -t -s decoded.dlp -dd -c output.dlt input.dlt "; - qDebug()<<" dlt-viewer.exe -t -s -csv -c output.csv input.dlt"; - qDebug()<<" dlt-viewer.exe -t -s -d filter.dlf -c output.dlt input.dlt"; - qDebug()<<" dlt-viewer.exe -p export.dlp -e \"Filetransfer Plugin|export|ftransferdir\" input.dlt"; - qDebug()<<" dlt-viewer.exe input1.dlt input2.dlt"; - qDebug()<<" dlt-viewer.exe -t -c output.txt input.pcap"; - qDebug()<<" dlt-viewer.exe -t -c output.txt input1.mf4 input2.mf4"; + qDebug().noquote() << helpText; + qDebug() << "\nExamples:"; + qDebug() << " dlt-viewer.exe -t -c output.txt input.dlt"; + qDebug() << " dlt-viewer.exe -t -s -u -c output.txt input.dlt"; + qDebug() << " dlt-viewer.exe -t -s -d -c output.dlt input.dlt"; + qDebug() << " dlt-viewer.exe -t -s decoded.dlp -dd -c output.dlt input.dlt "; + qDebug() << " dlt-viewer.exe -t -s -csv -c output.csv input.dlt"; + qDebug() << " dlt-viewer.exe -t -s -d filter.dlf -c output.dlt input.dlt"; + qDebug() << " dlt-viewer.exe -p export.dlp -e \"Filetransfer Plugin|export|ftransferdir\" input.dlt"; + qDebug() << " dlt-viewer.exe input1.dlt input2.dlt"; + qDebug() << " dlt-viewer.exe -t -c output.txt input.pcap"; + qDebug() << " dlt-viewer.exe -t -c output.txt input1.mf4 input2.mf4"; } -void QDltOptManager::parse(QStringList&& opt) +void QDltOptManager::parse(const QStringList& args) { - qDebug() << "### Starting DLT Viewer"; + m_parser.parse(args); - printVersion(opt.at(0)); + qDebug() << "### Starting DLT Viewer"; - qDebug() << "### Parsing Options"; + printVersion(args.at(0)); /* the default parameter - exactly one parameter - should either be * a dlt or a dlp file, so this enables the "doubleclick" feature */ - //str = opt.at(0); && ( str.compare("-h)") != 0 || str.compare("-v") !=0 ) - if (opt.size() == 2) { - if (opt.at(1).endsWith(".dlp") || opt.at(1).endsWith(".DLP")) { - projectFile = QString("%1").arg(opt.at(1)); + + if (m_parser.optionNames().isEmpty() && m_parser.positionalArguments().size() == 1) + { + const QString& arg = m_parser.positionalArguments().at(0); + if(arg.endsWith(".dlp") || arg.endsWith(".DLP")) + { + projectFile = arg; project = true; - qDebug() << "Project filename:" << projectFile; + qDebug()<< "Project filename:" << projectFile; return; } - if (opt.at(1).endsWith(".dlt") || opt.at(1).endsWith(".DLT")) { - const QString logFile = QString("%1").arg(opt.at(1)); + if (arg.endsWith(".dlt") || arg.endsWith(".DLT")) + { + const QString logFile = arg; logFiles += logFile; - qDebug() << "DLT filename:" << logFile; + qDebug()<< "DLT filename:" << logFile; return; } } - // 0==Binary 1==First Argument - for (int i = 0; i < opt.size(); ++i) - { - QString str = opt.at(i); - - if(str.compare("-h") == 0 || str.compare("--help") == 0) - { - printUsage(); - exit(0); - } - else if(str.compare("-s") == 0 || str.compare("--silent") == 0) - { - if ( silent_mode == false) - { - silent_mode = true; - qDebug() << "Silent mode enabled"; - } - } - else if(str.compare("-v") == 0 || str.compare("--version") == 0) - { - // version has already been printed above, just exit - exit(0); - } - else if(str.compare("-t") == 0 || str.compare("--terminate") == 0) - { - terminate = true; - commandline_mode = true; - } - else if(str.compare("-c")==0) - { - QString c1 = opt.value(i+1); - - convertDestFile = QString("%1").arg(c1); - // check here already if the selected file exists - - qDebug() << "Convert filename:" << convertDestFile; - commandline_mode = true; - - i += 1; - } - else if(str.compare("-delimiter")==0) - { - QString c1 = opt.value(i+1); - - delimiter = QString("%1").arg(c1).front().toLatin1(); - - qDebug() << "Delimiter:" << delimiter; - - i += 1; - } - else if(str.compare("-u")==0) - { - convertionmode = e_UTF8; - } - else if(str.compare("-csv")==0) - { - convertionmode = e_CSV; - } - else if(str.compare("-d")==0) - { - convertionmode = e_DLT; - } - else if(str.compare("-dd")==0) - { - convertionmode = e_DDLT; - } - else if(str.compare("-stream")==0) - { - inputmode = e_inputmode::STREAM; - } - else if(str.compare("-e")==0) - { - QString c = opt.value(i+1); - postPluginCommands += c; - commandline_mode = true; - ++i; - } - else if(str.compare("-b")==0) - { - QString c = opt.value(i+1); - prePluginCommands += c; - commandline_mode = true; - ++i; - } - else if (str.compare("-w") == 0) - { - workingDirectory = opt.value(i+1); - ++i; - } - else if(opt.at(i).endsWith(".dlt") || opt.at(i).endsWith(".DLT")) + if (m_parser.isSet("help")) { + printUsage(m_parser.helpText()); + exit(0); + } + + if (m_parser.isSet("silent")) { + silent_mode = true; + qDebug() << "Silent mode enabled"; + } + + if (m_parser.isSet("version")) { + // version is already printed above + exit(0); + } + + if (m_parser.isSet("terminate")) { + terminate = true; + commandline_mode = true; + } + + if (m_parser.isSet("c")) { + convertDestFile = m_parser.value("c"); + qDebug() << "Convert filename:" << convertDestFile; + commandline_mode = true; + } + + if (m_parser.isSet("delimiter")) { + delimiter = m_parser.value("delimiter").front().toLatin1(); + qDebug() << "Delimiter:" << delimiter; + } + + if (m_parser.isSet("u")) { + convertionmode = e_UTF8; + } + + if (m_parser.isSet("csv")) { + convertionmode = e_CSV; + } + + if (m_parser.isSet("d")) { + convertionmode = e_DLT; + } + + if (m_parser.isSet("dd")) { + convertionmode = e_DDLT; + } + + if (m_parser.isSet("stream")) { + inputmode = e_inputmode::STREAM; + } + + if (m_parser.isSet("e")) { + postPluginCommands += m_parser.value("e"); + commandline_mode = true; + } + + if (m_parser.isSet("b")) { + prePluginCommands += m_parser.value("b"); + commandline_mode = true; + } + + if (m_parser.isSet("w")) { + workingDirectory = m_parser.value("w"); + } + + QStringList positionalArguments = m_parser.positionalArguments(); + for (const QString &arg : positionalArguments) + { + if(arg.endsWith(".dlt") || arg.endsWith(".DLT")) { - const QString logFile = QString("%1").arg(opt.at(i)); + const QString logFile = arg; logFiles += logFile; qDebug()<< "DLT filename:" << logFile; } - else if(opt.at(i).endsWith(".dlp") || opt.at(i).endsWith(".DLP")) - { + else if(arg.endsWith(".dlp") || arg.endsWith(".DLP")) { if (project == true) { qDebug() << "\nError: Can only load one project file\n"; - printUsage(); + printUsage(m_parser.helpText()); exit(-1); } - projectFile = QString("%1").arg(opt.at(i)); + projectFile = arg; project = true; qDebug()<< "Project filename:" << projectFile; } - else if(opt.at(i).endsWith(".dlf") || opt.at(i).endsWith(".DLF")) + else if(arg.endsWith(".dlf") || arg.endsWith(".DLF")) { - filterFiles += QString("%1").arg(opt.at(i)); - qDebug()<< "Filter filename:" << QString("%1").arg(opt.at(i)); + filterFiles += arg; + qDebug()<< "Filter filename:" << arg; } - else if(opt.at(i).endsWith(".pcap") || opt.at(i).endsWith(".PCAP")) + else if(arg.endsWith(".pcap") || arg.endsWith(".PCAP")) { - const QString pcapFile = QString("%1").arg(opt.at(i)); + const QString pcapFile = arg; pcapFiles += pcapFile; qDebug()<< "Pcap filename:" << pcapFile; } - else if(opt.at(i).endsWith(".mf4") || opt.at(i).endsWith(".MF4")) + else if(arg.endsWith(".mf4") || arg.endsWith(".MF4")) { - const QString mf4File = QString("%1").arg(opt.at(i)); + const QString mf4File = arg; mf4Files += mf4File; qDebug()<< "MF4 filename:" << mf4File; } - - } // end of for loop + } /* On Windows we do not want to open a console in case * we start the application e.g. from file explorer. @@ -268,39 +277,13 @@ QStringList QDltOptManager::getCommandParams(){return commandParams;} QString QDltOptManager::getWorkingDirectory() const { return workingDirectory; } char QDltOptManager::getDelimiter(){return delimiter;} -QString QDltOptManager::getHelpText() const { - QStringList helpText; -#if (WIN32) - helpText << "Usage: dlt-viewer.exe [OPTIONS] [logfile] [projectfile] [filterfile] [mf4file] [pcapfile]"; -#else - helpText << "Usage: dlt-viewer [OPTIONS] [logfile] [projectfile] [filterfile] [mf4file] [pcapfile]"; -#endif - - helpText << "\nOptions:"; - helpText << " [logfile]\tLoading one or more logfiles on startup (must end with .dlt)"; - helpText << " [projectfile]\tLoading project file on startup (must end with .dlp)"; - helpText << " [filterfile]\tLoading filterfile on startup (must end with .dlf)"; - helpText << " [pcapfile]\tImporting DLT/IPC from pcap file on startup (must end with .pcap)"; - helpText << " [mf4file]\tImporting DLT/IPC from mf4 file on startup (must end with .mf4)"; - helpText << " -h or --help\tPrint usage"; - helpText << " -c textfile\tConvert logfile file to textfile"; - helpText << " -u\tConversion will be done in UTF8 instead of ASCII"; - helpText << " -csv\tConversion will be done in CSV format"; - helpText << " -d\tConversion will NOT be done, save in dlt file format again instead"; - helpText << " -dd\tConversion will NOT be done, save as decoded messages in dlt format"; - helpText << " -b \"plugin|command|param1|..|param\"\tExecute a plugin command with parameters before loading log file."; - helpText << " -e \"plugin|command|param1|..|param\"\tExecute a plugin command with parameters after loading log file."; - helpText << " -s or --silent\tEnable silent mode without any GUI. Ideal for commandline usage."; - helpText << " -stream\tTreat the input logfiles as DLT stream instead of DLT files."; - helpText << " -t or --terminate\tTerminate DLT Viewer after command line execution."; - helpText << " -v or --version\tOnly show version and buildtime information"; - helpText << " -w workingdirectory\tSet the working directory"; - helpText << " -delimiter \tThe used delimiter for CSV export (Default: ,)."; - - return helpText.join('\n'); +QString QDltOptManager::getHelpText() const +{ + return m_parser.helpText(); } -void QDltOptManager::reset() { +void QDltOptManager::reset() +{ project = false; terminate = false; silent_mode = false; @@ -317,7 +300,7 @@ void QDltOptManager::reset() { prePluginCommands.clear(); postPluginCommands.clear(); workingDirectory.clear(); - delimiter = ','; + delimiter=','; pcapFiles.clear(); mf4Files.clear(); } diff --git a/qdlt/qdltoptmanager.h b/qdlt/qdltoptmanager.h index f1fccd71..e1cb12d0 100644 --- a/qdlt/qdltoptmanager.h +++ b/qdlt/qdltoptmanager.h @@ -21,6 +21,7 @@ #define QDLTOPTMANAGER_H #include +#include #include "export_rules.h" @@ -44,9 +45,9 @@ class QDLT_EXPORT QDltOptManager { public: static QDltOptManager* getInstance(); - void printUsage(); + void printUsage(const QString& helpText); void printVersion(QString appname); - void parse(QStringList&& opt); + void parse(const QStringList& opt); bool isProjectFile(); bool isTerminate(); @@ -76,6 +77,9 @@ class QDLT_EXPORT QDltOptManager // only testing relevant void reset(); +private: + QDltOptManager(); + private: bool project{false}; bool terminate{false}; @@ -99,6 +103,8 @@ class QDLT_EXPORT QDltOptManager QString workingDirectory; char delimiter{','}; + + QCommandLineParser m_parser; }; #endif //QDLTOPTMANAGER_H diff --git a/qdlt/tests/test_dltoptmanager.cpp b/qdlt/tests/test_dltoptmanager.cpp index 116d19c9..b9593933 100644 --- a/qdlt/tests/test_dltoptmanager.cpp +++ b/qdlt/tests/test_dltoptmanager.cpp @@ -38,7 +38,7 @@ QDltOptManager* OptManagerTest::m_manager = nullptr; TEST_F(OptManagerTest, txtConversion) { auto args = QStringList() << "executable" << "-t" << "-c" << "output.txt" << "input.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->isTerminate()); EXPECT_EQ(m_manager->getConvertDestFile(), "output.txt"); @@ -49,7 +49,7 @@ TEST_F(OptManagerTest, txtConversion) { TEST_F(OptManagerTest, txtConversionSilentUtf8Mode) { auto args = QStringList() << "executable" << "-t" << "-s" << "-u" << "-c" << "output.txt" << "input.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->isTerminate()); EXPECT_TRUE(m_manager->issilentMode()); @@ -62,7 +62,7 @@ TEST_F(OptManagerTest, txtConversionSilentUtf8Mode) { TEST_F(OptManagerTest, txtConversionSilentAsciiMode) { auto args = QStringList() << "executable" << "-t" << "-s" << "-d" << "-c" << "output.txt" << "input.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->isTerminate()); EXPECT_TRUE(m_manager->issilentMode()); @@ -75,7 +75,7 @@ TEST_F(OptManagerTest, txtConversionSilentAsciiMode) { TEST_F(OptManagerTest, csvConversionSilentMode) { auto args = QStringList() << "executable" << "-t" << "-s" << "-csv" << "-c" << "output.csv" << "input.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->isTerminate()); EXPECT_TRUE(m_manager->issilentMode()); @@ -88,7 +88,7 @@ TEST_F(OptManagerTest, csvConversionSilentMode) { TEST_F(OptManagerTest, txtConversionSilentDdlMode) { auto args = QStringList() << "executable" << "-t" << "-s" << "decoded.dlp" << "-dd" << "-c" << "output.dlt" << "input.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->isTerminate()); EXPECT_TRUE(m_manager->issilentMode()); @@ -106,7 +106,7 @@ TEST_F(OptManagerTest, pluginPostCommands) { << "-e" << "\"Filetransfer Plugin|export|ftransferdir\"" << "input.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_EQ(m_manager->getProjectFile(), "export.dlp"); EXPECT_TRUE(m_manager->getLogFiles().contains("input.dlt")); @@ -119,7 +119,7 @@ TEST_F(OptManagerTest, pluginPreCommands) { << "-b" << "\"Filetransfer Plugin|export|ftransferdir\"" << "input.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->getLogFiles().contains("input.dlt")); EXPECT_TRUE(m_manager->getPrePluginCommands().contains("\"Filetransfer Plugin|export|ftransferdir\"")); @@ -129,7 +129,7 @@ TEST_F(OptManagerTest, pluginPreCommands) { TEST_F(OptManagerTest, multipleLogFiles) { auto args = QStringList() << "executable" << "input1.dlt" << "input2.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->getLogFiles().contains("input1.dlt")); EXPECT_TRUE(m_manager->getLogFiles().contains("input2.dlt")); @@ -138,7 +138,7 @@ TEST_F(OptManagerTest, multipleLogFiles) { TEST_F(OptManagerTest, pcapFile) { auto args = QStringList() << "executable" << "-t" << "-c" << "output.txt" << "input.pcap"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->isTerminate()); EXPECT_EQ(m_manager->getConvertDestFile(), "output.txt"); @@ -149,7 +149,7 @@ TEST_F(OptManagerTest, pcapFile) { TEST_F(OptManagerTest, mf4Files) { auto args = QStringList() << "executable" << "-t" << "-c" << "output.txt" << "input1.mf4" << "input2.mf4"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->isTerminate()); EXPECT_EQ(m_manager->getConvertDestFile(), "output.txt"); @@ -168,7 +168,7 @@ TEST_F(OptManagerTest, filterFile) { << "-s" << "-t"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(m_manager->getLogFiles().contains("input.dlt")); EXPECT_TRUE(m_manager->getFilterFiles().contains("filter.dlf")); @@ -183,7 +183,7 @@ TEST_F(OptManagerTest, version) { // but any output will be enough to check the version call because it is always printed auto args = QStringList() << "executable" << "some.dlt"; - m_manager->parse(std::move(args)); + m_manager->parse(args); EXPECT_TRUE(logMessageSink.contains("Executable Name:")); EXPECT_TRUE(logMessageSink.contains("Build time:")); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 45cf7092..c1cf64c3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -280,7 +280,6 @@ MainWindow::~MainWindow() delete sortProxyModel; } - void MainWindow::initState() { /* Settings */ @@ -5727,7 +5726,6 @@ void MainWindow::on_action_menuHelp_Info_triggered() QString("(C) 2016,2024 BMW AG\n")); } - void MainWindow::on_action_menuHelp_Command_Line_triggered() { QMessageBox::information( 0, "DLT Viewer - Command line usage\t\t\t\t\t", // tabs used to expand message box !