Skip to content

Commit

Permalink
cmdlineargs: Added a second parser path for user feedback ...
Browse files Browse the repository at this point in the history
after the QApplication has processed the command line as well.

This allows proper feedback when a unknown command line option is found
and considers also the Qt internal command line arguments.

As extra bounty the help output is now translated.
  • Loading branch information
daschuer committed Aug 1, 2021
1 parent ac4cacd commit e951cd5
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 63 deletions.
4 changes: 2 additions & 2 deletions src/coreservices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ CoreServices::CoreServices(const CmdlineArgs& args, QApplication* pApp)
mixxx::Time::start();
ScopedTimer t("CoreServices::CoreServices");
// All this here is running without without start up screen
// Defere long initialisations to CoreServices::initialize() which is
// called after the GUI is initalized
// Defer long initializations to CoreServices::initialize() which is
// called after the GUI is initialized
initializeSettings();
initializeLogging();
// Only record stats in developer mode.
Expand Down
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ constexpr int kParseCmdlineArgsErrorExitCode = 2;
int runMixxx(MixxxApplication* pApp, const CmdlineArgs& args) {
const auto pCoreServices = std::make_shared<mixxx::CoreServices>(args, pApp);

CmdlineArgs::Instance().parseForUserFeedback();

MixxxMainWindow mainWindow(pApp, pCoreServices);
pApp->installEventFilter(&mainWindow);

Expand Down
152 changes: 91 additions & 61 deletions src/util/cmdlineargs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "config.h"
#include "defs_urls.h"
#include "sources/soundsourceproxy.h"
#include "util/assert.h"

CmdlineArgs::CmdlineArgs()
: m_startInFullscreen(false), // Initialize vars
Expand All @@ -24,6 +25,7 @@ CmdlineArgs::CmdlineArgs()
m_debugAssertBreak(false),
m_settingsPathSet(false),
m_useColors(false),
m_hasUserFeedback(false),
m_logLevel(mixxx::kLogLevelDefault),
m_logFlushLevel(mixxx::kLogFlushLevelDefault),
// We are not ready to switch to XDG folders under Linux, so keeping $HOME/.mixxx as preferences folder. see lp:1463273
Expand Down Expand Up @@ -73,39 +75,54 @@ bool CmdlineArgs::parse(int argc, char** argv) {
for (int a = 0; a < argc; ++a) {
arguments << QString::fromLocal8Bit(argv[a]);
}
return parse(arguments, false);
}

void CmdlineArgs::parseForUserFeedback() {
DEBUG_ASSERT(QCoreApplication::instance());
if (!m_hasUserFeedback) {
return;
}
parse(QCoreApplication::arguments(), true);
}

bool CmdlineArgs::parse(const QStringList& arguments, bool forUserFeedback) {
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);

parser.setApplicationDescription(
QCoreApplication::translate("CmdlineArgs",
"Mixxx is an open source DJ software. For more "
"information, see: ") +
MIXXX_MANUAL_COMMANDLINEOPTIONS_URL);

if (forUserFeedback) {
parser.setApplicationDescription(
QCoreApplication::translate("CmdlineArgs",
"Mixxx is an open source DJ software. For more "
"information, see: ") +
MIXXX_MANUAL_COMMANDLINEOPTIONS_URL);
}
// add options
const QCommandLineOption fullScreen(
QStringList({QStringLiteral("f"), QStringLiteral("full-screen")}),
QCoreApplication::translate(
"CmdlineArgs", "Starts Mixxx in full-screen mode"));
forUserFeedback ? QCoreApplication::translate(
"CmdlineArgs", "Starts Mixxx in full-screen mode")
: QString());
QCommandLineOption fullScreenDeprecated(QStringLiteral("fullScreen"));
fullScreenDeprecated.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(fullScreen);
parser.addOption(fullScreenDeprecated);

const QCommandLineOption locale(QStringLiteral("locale"),
QCoreApplication::translate("CmdlineArgs",
"Use a custom locale for loading translations. (e.g "
"'fr')"),
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Use a custom locale for loading translations. (e.g "
"'fr')")
: QString(),
QStringLiteral("locale"));
parser.addOption(locale);

// An option with a value
const QCommandLineOption settingsPath(QStringLiteral("settings-path"),
QCoreApplication::translate("CmdlineArgs",
"Top-level directory where Mixxx should look for settings. "
"Default is:") +
getSettingsPath(),
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Top-level directory where Mixxx should look for settings. "
"Default is:") +
getSettingsPath()
: QString(),
QStringLiteral("path"));
QCommandLineOption settingsPathDeprecated(
QStringLiteral("settingsPath"));
Expand All @@ -115,10 +132,11 @@ bool CmdlineArgs::parse(int argc, char** argv) {
parser.addOption(settingsPathDeprecated);

QCommandLineOption resourcePath(QStringLiteral("resource-path"),
QCoreApplication::translate("CmdlineArgs",
"Top-level directory where Mixxx should look for its "
"resource files such as MIDI mappings, overriding the "
"default installation location."),
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Top-level directory where Mixxx should look for its "
"resource files such as MIDI mappings, overriding the "
"default installation location.")
: QString(),
QStringLiteral("path"));
QCommandLineOption resourcePathDeprecated(
QStringLiteral("resourcePath"));
Expand All @@ -128,8 +146,9 @@ bool CmdlineArgs::parse(int argc, char** argv) {
parser.addOption(resourcePathDeprecated);

const QCommandLineOption timelinePath(QStringLiteral("timeline-path"),
QCoreApplication::translate("CmdlineArgs",
"Path the debug statistics time line is written to"),
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Path the debug statistics time line is written to")
: QString(),
QStringLiteral("path"));
QCommandLineOption timelinePathDeprecated(
QStringLiteral("timelinePath"), timelinePath.description());
Expand All @@ -139,9 +158,10 @@ bool CmdlineArgs::parse(int argc, char** argv) {
parser.addOption(timelinePathDeprecated);

const QCommandLineOption controllerDebug(QStringLiteral("controller-debug"),
QCoreApplication::translate("CmdlineArgs",
"Causes Mixxx to display/log all of the controller data it "
"receives and script functions it loads"));
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Causes Mixxx to display/log all of the controller data it "
"receives and script functions it loads")
: QString());
QCommandLineOption controllerDebugDeprecated(
QStringList({QStringLiteral("controllerDebug"),
QStringLiteral("midiDebug")}));
Expand All @@ -150,36 +170,40 @@ bool CmdlineArgs::parse(int argc, char** argv) {
parser.addOption(controllerDebugDeprecated);

const QCommandLineOption developer(QStringLiteral("developer"),
QCoreApplication::translate("CmdlineArgs",
"Enables developer-mode. Includes extra log info, stats on "
"performance, and a Developer tools menu."));
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Enables developer-mode. Includes extra log info, stats on "
"performance, and a Developer tools menu.")
: QString());
parser.addOption(developer);

const QCommandLineOption safeMode(QStringLiteral("safe-mode"),
QCoreApplication::translate("CmdlineArgs",
"Enables safe-mode. Disables OpenGL waveforms, and "
"spinning vinyl widgets. Try this option if Mixxx is "
"crashing on startup."));
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Enables safe-mode. Disables OpenGL waveforms, and "
"spinning vinyl widgets. Try this option if Mixxx is "
"crashing on startup.")
: QString());
QCommandLineOption safeModeDeprecated(QStringLiteral("safeMode"), safeMode.description());
safeModeDeprecated.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(safeMode);
parser.addOption(safeModeDeprecated);

const QCommandLineOption color(QStringLiteral("color"),
QCoreApplication::translate("CmdlineArgs",
"[auto|always|never] Use colors on the console output."),
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"[auto|always|never] Use colors on the console output.")
: QString(),
QStringLiteral("color"),
QStringLiteral("auto"));
parser.addOption(color);

const QCommandLineOption logLevel(QStringLiteral("log-level"),
QCoreApplication::translate("CmdlineArgs",
"Sets the verbosity of command line logging.\n"
"critical - Critical/Fatal only\n"
"warning - Above + Warnings\n"
"info - Above + Informational messages\n"
"debug - Above + Debug/Developer messages\n"
"trace - Above + Profiling messages"),
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Sets the verbosity of command line logging.\n"
"critical - Critical/Fatal only\n"
"warning - Above + Warnings\n"
"info - Above + Informational messages\n"
"debug - Above + Debug/Developer messages\n"
"trace - Above + Profiling messages")
: QString(),
QStringLiteral("level"));
QCommandLineOption logLevelDeprecated(QStringLiteral("logLevel"), logLevel.description());
logLevelDeprecated.setFlags(QCommandLineOption::HiddenFromHelp);
Expand All @@ -188,10 +212,11 @@ bool CmdlineArgs::parse(int argc, char** argv) {
parser.addOption(logLevelDeprecated);

const QCommandLineOption logFlushLevel(QStringLiteral("log-flush-level"),
QCoreApplication::translate("CmdlineArgs",
"Sets the the logging level at which the log buffer is "
"flushed to mixxx.log. <level> is one of the values defined "
"at --log-level above."),
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Sets the the logging level at which the log buffer is "
"flushed to mixxx.log. <level> is one of the values defined "
"at --log-level above.")
: QString(),
QStringLiteral("level"));
QCommandLineOption logFlushLevelDeprecated(
QStringLiteral("logFlushLevel"), logLevel.description());
Expand All @@ -201,9 +226,10 @@ bool CmdlineArgs::parse(int argc, char** argv) {
parser.addOption(logFlushLevelDeprecated);

QCommandLineOption debugAssertBreak(QStringLiteral("debug-assert-break"),
QCoreApplication::translate("CmdlineArgs",
"Breaks (SIGINT) Mixxx, if a DEBUG_ASSERT evaluates to "
"false. Under a debugger you can continue afterwards."));
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Breaks (SIGINT) Mixxx, if a DEBUG_ASSERT evaluates to "
"false. Under a debugger you can continue afterwards.")
: QString());
QCommandLineOption debugAssertBreakDeprecated(
QStringLiteral("debugAssertBreak"), debugAssertBreak.description());
debugAssertBreakDeprecated.setFlags(QCommandLineOption::HiddenFromHelp);
Expand All @@ -214,29 +240,33 @@ bool CmdlineArgs::parse(int argc, char** argv) {
const QCommandLineOption versionOption = parser.addVersionOption();

parser.addPositionalArgument(QStringLiteral("file"),
QCoreApplication::translate("CmdlineArgs",
"Load the specified music file(s) at start-up. Each file "
"you specify will be loaded into the next virtual deck."));
forUserFeedback ? QCoreApplication::translate("CmdlineArgs",
"Load the specified music file(s) at start-up. Each file "
"you specify will be loaded into the next virtual deck.")
: QString());

if (forUserFeedback) {
// We know form the first path, that there will be likely an error message, check again.
// This is not the case if the user uses a Qt internal option that is unknown
// in the first path
puts(""); // Add a blank line to make the parser output more visible
// This call does not return and calls exit() in case of help or an parser error
parser.process(arguments);
return true;
}

// process all arguments
if (!parser.parse(arguments)) {
qWarning() << parser.errorText();
m_hasUserFeedback = true;
}

if (parser.isSet(helpOption)
if (parser.isSet(versionOption) ||
parser.isSet(helpOption)
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|| parser.isSet(QStringLiteral("help-all"))
#endif
) {
// we need to call process here with an initialized QCoreApplication
// otherwise there is no way to print the help-all information
QCoreApplication coreApp(argc, argv);
parser.process(arguments);
return false;
}
if (parser.isSet(versionOption)) {
parser.showVersion();
return false;
m_hasUserFeedback = true;
}

m_startInFullscreen = parser.isSet(fullScreen) || parser.isSet(fullScreenDeprecated);
Expand Down
9 changes: 9 additions & 0 deletions src/util/cmdlineargs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ class CmdlineArgs final {
return cla;
}

//! The original parser that provides the parsed values to Mixxx
//! This can be called before anything else is initialized
bool parse(int argc, char** argv);

//! The optional second run, that provides translated user feedback
//! This requires an initialized QCoreApplication
void parseForUserFeedback();

const QList<QString>& getMusicFiles() const { return m_musicFiles; }
bool getStartInFullscreen() const { return m_startInFullscreen; }
bool getMidiDebug() const { return m_midiDebug; }
Expand All @@ -45,6 +51,8 @@ class CmdlineArgs final {
const QString& getTimelinePath() const { return m_timelinePath; }

private:
bool parse(const QStringList& arguments, bool forUserFeedback);

QList<QString> m_musicFiles; // List of files to load into players at startup
bool m_startInFullscreen; // Start in fullscreen mode
bool m_midiDebug;
Expand All @@ -53,6 +61,7 @@ class CmdlineArgs final {
bool m_debugAssertBreak;
bool m_settingsPathSet; // has --settingsPath been set on command line ?
bool m_useColors; // should colors be used
bool m_hasUserFeedback;
mixxx::LogLevel m_logLevel; // Level of stderr logging message verbosity
mixxx::LogLevel m_logFlushLevel; // Level of mixx.log file flushing
QString m_locale;
Expand Down

0 comments on commit e951cd5

Please sign in to comment.