summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2020-07-18 05:07:32 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2020-11-03 11:39:01 -0500
commitccab9eae8df3cf5367ce5cf164c98d1534ac13cb (patch)
tree603bddc6dc14d256d4b416514e089326be83c42e
parent75cc2ffead148ab2409cd1ef469613d2e9b80e17 (diff)
add warning when profile given with -p doesn't exist
implemented moshortcut, nxm links and executable names as command line options
-rw-r--r--src/commandline.cpp98
-rw-r--r--src/commandline.h13
-rw-r--r--src/main.cpp117
-rw-r--r--src/moshortcut.cpp9
-rw-r--r--src/moshortcut.h8
-rw-r--r--src/organizercore.cpp9
-rw-r--r--src/organizercore.h3
-rw-r--r--src/shared/util.cpp6
-rw-r--r--src/shared/util.h2
9 files changed, 174 insertions, 91 deletions
diff --git a/src/commandline.cpp b/src/commandline.cpp
index f84906e9..f5c4df60 100644
--- a/src/commandline.cpp
+++ b/src/commandline.cpp
@@ -1,5 +1,6 @@
#include "commandline.h"
#include "env.h"
+#include "shared/util.h"
namespace cl
{
@@ -29,21 +30,22 @@ std::optional<int> CommandLine::run(const std::wstring& line)
po::store(parsed, m_vm);
+ auto opts = po::collect_unrecognized(
+ parsed.options, po::include_positional);
+
+
if (m_vm.count("command")) {
const auto commandName = m_vm["command"].as<std::string>();
for (auto&& c : m_commands) {
if (c->name() == commandName) {
+ // remove the command name itself
+ opts.erase(opts.begin());
+
auto co = c->options();
co.add_options()
("help", "shows this message");
- auto opts = po::collect_unrecognized(
- parsed.options, po::include_positional);
-
- // remove the command name itself
- opts.erase(opts.begin());
-
po::wcommand_line_parser parser(opts);
parser.options(co);
@@ -72,6 +74,26 @@ std::optional<int> CommandLine::run(const std::wstring& line)
return 0;
}
+ if (!opts.empty()) {
+ const auto qs = QString::fromStdWString(opts[0]);
+ m_shortcut = qs;
+
+ if (!m_shortcut.isValid()) {
+ if (isNxmLink(qs)) {
+ m_nxmLink = qs;
+ } else {
+ m_executable = qs;
+ }
+ }
+
+ // remove the shortcut/nxm/executable
+ opts.erase(opts.begin());
+
+ for (auto&& o : opts) {
+ m_untouched.push_back(QString::fromStdWString(o));
+ }
+ }
+
return {};
}
catch(po::error& e)
@@ -86,11 +108,19 @@ std::optional<int> CommandLine::run(const std::wstring& line)
}
}
+void CommandLine::clear()
+{
+ m_vm.clear();
+ m_shortcut = {};
+ m_nxmLink = {};
+}
+
void CommandLine::createOptions()
{
m_visibleOptions.add_options()
- ("help", "shows this message")
- ("multiple", "allows multiple instances of MO to run; see below");
+ ("help", "show this message")
+ ("multiple", "allow multiple instances of MO to run; see below")
+ ("profile,p", po::value<std::string>(), "use the given profile (defaults to last used)");
po::options_description options;
options.add_options()
@@ -148,20 +178,50 @@ bool CommandLine::multiple() const
return (m_vm.count("multiple") > 0);
}
+std::optional<QString> CommandLine::profile() const
+{
+ if (m_vm.count("profile")) {
+ return QString::fromStdString(m_vm["profile"].as<std::string>());
+ }
+
+ return {};
+}
+
+const MOShortcut& CommandLine::shortcut() const
+{
+ return m_shortcut;
+}
+
+std::optional<QString> CommandLine::nxmLink() const
+{
+ return m_nxmLink;
+}
+
+std::optional<QString> CommandLine::executable() const
+{
+ return m_executable;
+}
+
+const QStringList& CommandLine::untouched() const
+{
+ return m_untouched;
+}
+
std::string CommandLine::more() const
{
return
- "--multiple can be used to allow multiple instances of MO to run\n"
- "simultaneously. This is unsupported and can create all sorts of weird\n"
- "problems. To minimize the problems:\n"
- "\n"
- " 1) Never have multiple MO instances opened that manage the same game\n"
- " instance.\n"
- " 2) If an executable is launched from an instance, only this instance\n"
- " may launch executables until all instances are closed.\n"
- "\n"
- "It is recommended to close _all_ instances of MO as soon as multiple\n"
- "instances become unnecessary.";
+ "Multiple instances\n"
+ " --multiple can be used to allow multiple instances of MO to run\n"
+ " simultaneously. This is unsupported and can create all sorts of weird\n"
+ " problems. To minimize the problems:\n"
+ " \n"
+ " 1) Never have multiple MO instances opened that manage the same\n"
+ " game instance.\n"
+ " 2) If an executable is launched from an instance, only this\n"
+ " instance may launch executables until all instances are closed.\n"
+ " \n"
+ " It is recommended to close _all_ instances of MO as soon as multiple\n"
+ " instances become unnecessary.";
}
diff --git a/src/commandline.h b/src/commandline.h
index deeb9923..cdd1c917 100644
--- a/src/commandline.h
+++ b/src/commandline.h
@@ -1,5 +1,6 @@
#pragma once
+#include "moshortcut.h"
#include <vector>
#include <memory>
@@ -92,15 +93,27 @@ public:
CommandLine();
std::optional<int> run(const std::wstring& line);
+ void clear();
+
std::string usage(const Command* c=nullptr) const;
bool multiple() const;
+ std::optional<QString> profile() const;
+ const MOShortcut& shortcut() const;
+ std::optional<QString> nxmLink() const;
+ std::optional<QString> executable() const;
+
+ const QStringList& untouched() const;
private:
po::options_description m_visibleOptions, m_allOptions;
po::positional_options_description m_positional;
std::vector<std::unique_ptr<Command>> m_commands;
po::variables_map m_vm;
+ MOShortcut m_shortcut;
+ std::optional<QString> m_nxmLink;
+ std::optional<QString> m_executable;
+ QStringList m_untouched;
void createOptions();
std::string more() const;
diff --git a/src/main.cpp b/src/main.cpp
index a1a4be01..3c5bc92d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -225,18 +225,13 @@ static bool HaveWriteAccess(const std::wstring &path)
}
-QString determineProfile(QStringList &arguments, const Settings &settings)
+QString determineProfile(const cl::CommandLine& cl, const Settings &settings)
{
auto selectedProfileName = settings.game().selectedProfileName();
- { // see if there is a profile on the command line
- int profileIndex = arguments.indexOf("-p", 1);
- if ((profileIndex != -1) && (profileIndex < arguments.size() - 1)) {
- log::debug("profile overwritten on command line");
- selectedProfileName = arguments.at(profileIndex + 1);
- }
- arguments.removeAt(profileIndex);
- arguments.removeAt(profileIndex);
+ if (cl.profile()) {
+ log::debug("profile overwritten on command line");
+ selectedProfileName = *cl.profile();
}
if (!selectedProfileName) {
@@ -481,7 +476,7 @@ static QString getVersionDisplayString()
int runApplication(
- MOApplication &application, QStringList& arguments,
+ MOApplication &application, const cl::CommandLine& cl,
SingleInstance &instance, const QString &splashPath)
{
TimeThis tt("runApplication() to exec()");
@@ -635,57 +630,51 @@ int runApplication(
organizer.updateExecutablesList();
organizer.updateModInfoFromDisc();
- QString selectedProfileName = determineProfile(arguments, settings);
+ QString selectedProfileName = determineProfile(cl, settings);
organizer.setCurrentProfile(selectedProfileName);
// if we have a command line parameter, it is either a nxm link or
// a binary to start
- if (arguments.size() > 1) {
- if (MOShortcut shortcut{ arguments.at(1) }) {
- if (shortcut.hasExecutable()) {
- try {
- organizer.processRunner()
- .setFromShortcut(shortcut)
- .setWaitForCompletion()
- .run();
+ if (cl.shortcut().isValid()) {
+ if (cl.shortcut().hasExecutable()) {
+ try {
+ organizer.processRunner()
+ .setFromShortcut(cl.shortcut())
+ .setWaitForCompletion()
+ .run();
- return 0;
- }
- catch (const std::exception &e) {
- reportError(
- QObject::tr("failed to start shortcut: %1").arg(e.what()));
- return 1;
- }
- }
- }
- else if (OrganizerCore::isNxmLink(arguments.at(1))) {
- log::debug("starting download from command line: {}", arguments.at(1));
- organizer.externalMessage(arguments.at(1));
- }
- else {
- QString exeName = arguments.at(1);
- log::debug("starting {} from command line", exeName);
+ return 0;
+ }
+ catch (const std::exception &e) {
+ reportError(
+ QObject::tr("failed to start shortcut: %1").arg(e.what()));
+ return 1;
+ }
+ }
+ } else if (cl.nxmLink()) {
+ log::debug("starting download from command line: {}", *cl.nxmLink());
+ organizer.externalMessage(*cl.nxmLink());
+ } else if (cl.executable()) {
+ const QString exeName = *cl.executable();
+ log::debug("starting {} from command line", exeName);
- arguments.removeFirst(); // remove application name (ModOrganizer.exe)
- arguments.removeFirst(); // remove binary name
+ try
+ {
+ // pass the remaining parameters to the binary
+ organizer.processRunner()
+ .setFromFileOrExecutable(exeName, cl.untouched())
+ .setWaitForCompletion()
+ .run();
- try
- {
- // pass the remaining parameters to the binary
- organizer.processRunner()
- .setFromFileOrExecutable(exeName, arguments)
- .setWaitForCompletion()
- .run();
- return 0;
- }
- catch (const std::exception &e)
- {
- reportError(
- QObject::tr("failed to start application: %1").arg(e.what()));
- return 1;
- }
- }
- }
+ return 0;
+ }
+ catch (const std::exception &e)
+ {
+ reportError(
+ QObject::tr("failed to start application: %1").arg(e.what()));
+ return 1;
+ }
+ }
QPixmap pixmap;
@@ -857,15 +846,13 @@ int main(int argc, char *argv[])
siFlags |= SingleInstance::AllowMultiple;
}
- MOShortcut moshortcut{ arguments.size() > 1 ? arguments.at(1) : "" };
-
SingleInstance instance(siFlags);
if (instance.ephemeral()) {
- if (moshortcut ||
- arguments.size() > 1 && OrganizerCore::isNxmLink(arguments.at(1)))
- {
- log::debug("not primary instance, sending shortcut/download message");
- instance.sendMessage(arguments.at(1));
+ if (cl.shortcut().isValid()) {
+ instance.sendMessage(cl.shortcut().toString());
+ return 0;
+ } else if (cl.nxmLink()) {
+ instance.sendMessage(*cl.nxmLink());
return 0;
} else if (arguments.size() == 1) {
QMessageBox::information(
@@ -887,8 +874,8 @@ int main(int argc, char *argv[])
try {
InstanceManager& instanceManager = InstanceManager::instance();
- if (moshortcut && moshortcut.hasInstance())
- instanceManager.overrideInstance(moshortcut.instance());
+ if (cl.shortcut().isValid() && cl.shortcut().hasInstance())
+ instanceManager.overrideInstance(cl.shortcut().instance());
dataPath = instanceManager.determineDataPath();
} catch (const std::exception &e) {
if (strcmp(e.what(),"Canceled"))
@@ -920,12 +907,12 @@ int main(int argc, char *argv[])
tt.stop();
- const int result = runApplication(application, arguments, instance, splash);
+ const int result = runApplication(application, cl, instance, splash);
if (result != RestartExitCode) {
return result;
}
argc = 1;
- moshortcut = MOShortcut("");
+ cl.clear();
} while (true);
}
diff --git a/src/moshortcut.cpp b/src/moshortcut.cpp
index aad7380e..4efedbdb 100644
--- a/src/moshortcut.cpp
+++ b/src/moshortcut.cpp
@@ -40,3 +40,12 @@ MOShortcut::MOShortcut(const QString& link)
m_hasExecutable=true;
}
}
+
+QString MOShortcut::toString() const
+{
+ if (m_hasInstance) {
+ return "moshortcut://" + m_instance + ":" + m_executable;
+ } else {
+ return "moshortcut://" + m_executable;
+ }
+}
diff --git a/src/moshortcut.h b/src/moshortcut.h
index 2ce54910..0067b3bc 100644
--- a/src/moshortcut.h
+++ b/src/moshortcut.h
@@ -27,19 +27,21 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
class MOShortcut {
public:
- MOShortcut(const QString& link);
+ MOShortcut(const QString& link={});
/// true iff intialized using a valid moshortcut link
- operator bool() const { return m_valid; }
+ bool isValid() const { return m_valid; }
bool hasInstance() const { return m_hasInstance; }
-
+
bool hasExecutable() const { return m_hasExecutable; }
const QString& instance() const { return m_instance; }
const QString& executable() const { return m_executable; }
+ QString toString() const;
+
private:
QString m_instance;
QString m_executable;
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 1c35720b..f9cafc95 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -38,6 +38,7 @@
#include "shared/directoryentry.h"
#include "shared/filesorigin.h"
#include "shared/fileentry.h"
+#include "shared/util.h"
#include <QApplication>
#include <QCoreApplication>
@@ -395,7 +396,9 @@ void OrganizerCore::profileRemoved(QString const& profileName)
void OrganizerCore::externalMessage(const QString &message)
{
- if (MOShortcut moshortcut{ message } ) {
+ MOShortcut moshortcut(message);
+
+ if (moshortcut.isValid()) {
if(moshortcut.hasExecutable()) {
processRunner()
.setFromShortcut(moshortcut)
@@ -555,12 +558,16 @@ void OrganizerCore::setCurrentProfile(const QString &profileName)
QString profileDir = profileBaseDir.absoluteFilePath(profileName);
if (!QDir(profileDir).exists()) {
+ log::error("profile '{}' does not exist", profileName);
+
// selected profile doesn't exist. Ensure there is at least one profile,
// then pick any one
createDefaultProfile();
profileDir = profileBaseDir.absoluteFilePath(
profileBaseDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot).at(0));
+
+ log::error("picked profile '{}' instead", QDir(profileDir).dirName());
}
// Keep the old profile to emit signal-changed:
diff --git a/src/organizercore.h b/src/organizercore.h
index 70ce94f5..1452bf08 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -191,9 +191,6 @@ public:
};
public:
-
- static bool isNxmLink(const QString &link) { return link.startsWith("nxm://", Qt::CaseInsensitive); }
-
OrganizerCore(Settings &settings);
~OrganizerCore();
diff --git a/src/shared/util.cpp b/src/shared/util.cpp
index ba500da9..f316549e 100644
--- a/src/shared/util.cpp
+++ b/src/shared/util.cpp
@@ -435,3 +435,9 @@ void ResetExitFlag()
{
g_exiting = false;
}
+
+
+bool isNxmLink(const QString& link)
+{
+ return link.startsWith("nxm://", Qt::CaseInsensitive);
+}
diff --git a/src/shared/util.h b/src/shared/util.h
index 2761b64f..1688a931 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -83,4 +83,6 @@ bool ModOrganizerExiting();
bool ModOrganizerCanCloseNow();
void ResetExitFlag();
+bool isNxmLink(const QString& link);
+
#endif // UTIL_H