added command line register

This commit is contained in:
Igor Korsukov 2020-12-19 23:22:24 +02:00
parent 2ee2399d8c
commit 883b11ab0b
15 changed files with 277 additions and 127 deletions

View file

@ -78,6 +78,7 @@ endif(BUILD_PCH)
if (BUILD_UNITY)
if (MODULE_USE_UNITY_NONE)
# disabled unity build for current module
set_target_properties(${MODULE} PROPERTIES UNITY_BUILD OFF)
else()
set_target_properties(${MODULE} PROPERTIES UNITY_BUILD ON)
endif()

View file

@ -17,18 +17,15 @@ add_subdirectory(audiofile)
add_subdirectory(context)
add_subdirectory(notation)
add_subdirectory(userscores)
add_subdirectory(convertor)
if (NOT OS_IS_WASM)
add_subdirectory(importexport)
add_subdirectory(cloud)
add_subdirectory(extensions)
add_subdirectory(languages)
add_subdirectory(plugins)
<<<<<<< HEAD
add_subdirectory(importexport)
add_subdirectory(cloud)
add_subdirectory(extensions)
add_subdirectory(languages)
add_subdirectory(plugins)
endif()
=======
add_subdirectory(convertor)
>>>>>>> added comandline module
# Scenes common
add_subdirectory(commonscene)

View file

@ -95,6 +95,10 @@ int AppShell::run(int argc, char** argv)
// ====================================================
QCommandLineParser parser;
parseCommandLineArguments(parser);
int retCode = 0;
RunMode mode = runMode(parser.optionNames());
applyCommandLineArguments(parser);
// ====================================================
@ -107,60 +111,66 @@ int AppShell::run(int argc, char** argv)
// ====================================================
// Setup Qml Engine
// ====================================================
QQmlApplicationEngine* engine = new QQmlApplicationEngine();
//! NOTE Move ownership to UiEngine
framework::UiEngine::instance()->moveQQmlEngine(engine);
if (RunMode::Gui == mode) {
QQmlApplicationEngine* engine = new QQmlApplicationEngine();
//! NOTE Move ownership to UiEngine
framework::UiEngine::instance()->moveQQmlEngine(engine);
#ifndef Q_OS_WASM
const QString mainQmlFile = "/Main.qml";
const QString mainQmlFile = "/Main.qml";
#else
const QString mainQmlFile = "/main.wasm.qml";
const QString mainQmlFile = "/main.wasm.qml";
#endif
#ifdef QML_LOAD_FROM_SOURCE
const QUrl url(QString(appshell_QML_IMPORT) + mainQmlFile);
const QUrl url(QString(appshell_QML_IMPORT) + mainQmlFile);
#else
const QUrl url(QStringLiteral("qrc:/qml") + mainQmlFile);
const QUrl url(QStringLiteral("qrc:/qml") + mainQmlFile);
#endif
QObject::connect(engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject* obj, const QUrl& objUrl) {
if (!obj && url == objUrl) {
LOGE() << "failed Qml load\n";
QCoreApplication::exit(-1);
}
}, Qt::QueuedConnection);
QObject::connect(engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject* obj, const QUrl& objUrl) {
if (!obj && url == objUrl) {
LOGE() << "failed Qml load\n";
QCoreApplication::exit(-1);
}
}, Qt::QueuedConnection);
QObject::connect(engine, &QQmlEngine::warnings, [](const QList<QQmlError>& warnings) {
for (const QQmlError& e : warnings) {
LOGE() << "error: " << e.toString().toStdString() << "\n";
}
});
QObject::connect(engine, &QQmlEngine::warnings, [](const QList<QQmlError>& warnings) {
for (const QQmlError& e : warnings) {
LOGE() << "error: " << e.toString().toStdString() << "\n";
}
});
// ====================================================
// Load Main qml
// ====================================================
engine->load(url);
// ====================================================
// Setup modules: onStartApp (on next event loop)
// ====================================================
QMetaObject::invokeMethod(qApp, [this]() {
globalModule.onStartApp();
for (mu::framework::IModuleSetup* m : m_modules) {
m->onStartApp();
}
}, Qt::QueuedConnection);
// ====================================================
// Run main loop
// ====================================================
retCode = app.exec();
// ====================================================
// Qml Engine quit
// ====================================================
framework::UiEngine::instance()->quit();
}
// ====================================================
// Load Main qml
// Deinit
// ====================================================
engine->load(url);
// ====================================================
// Setup modules: onStartApp (on next event loop)
// ====================================================
QMetaObject::invokeMethod(qApp, [this]() {
globalModule.onStartApp();
for (mu::framework::IModuleSetup* m : m_modules) {
m->onStartApp();
}
}, Qt::QueuedConnection);
// ====================================================
// Run main loop
// ====================================================
int code = app.exec();
// ====================================================
// Quit and deinit
// ====================================================
framework::UiEngine::instance()->quit();
for (mu::framework::IModuleSetup* m : m_modules) {
m->onDeinit();
}
@ -169,15 +179,36 @@ int AppShell::run(int argc, char** argv)
globalModule.onDeinit();
return code;
return retCode;
}
void AppShell::parseCommandLineArguments(QCommandLineParser& parser) const
AppShell::RunMode AppShell::runMode(const QStringList& options) const
{
for (const QString& opt : options) {
if (m_consoleRunModeOptions.contains(opt)) {
return RunMode::Concole;
}
}
return RunMode::Gui;
}
void AppShell::parseCommandLineArguments(QCommandLineParser& parser)
{
parser.addHelpOption(); // -?, -h, --help
parser.addVersionOption(); // -v, --version
parser.addOption(QCommandLineOption({ "j", "job" }, "Process a conversion job", "file"));
auto addGuiOption = [&parser, this](const QCommandLineOption& opt) {
parser.addOption(opt);
};
auto addConsoleOption = [&parser, this](const QCommandLineOption& opt) {
parser.addOption(opt);
for(const QString& name : opt.names()) {
m_consoleRunModeOptions << name;
}
};
addConsoleOption(QCommandLineOption({ "j", "job" }, "Process a conversion job", "file"));
//! NOTE Here will be added others options
parser.process(QCoreApplication::arguments());
@ -185,21 +216,21 @@ void AppShell::parseCommandLineArguments(QCommandLineParser& parser) const
void AppShell::applyCommandLineArguments(QCommandLineParser& parser)
{
using namespace mu::commandline;
QStringList options = parser.optionNames();
qDebug() << "options: " << options;
for (const QString& opt : options) {
ICommandLineControllerPtr h = clregister()->handler(opt.toStdString());
if (h) {
ICommandLineController::Values hvals;
QStringList values = parser.values(opt);
for (const QString& v : values) {
hvals.push_back(v.toStdString());
}
CommandLineValues values;
QStringList vals = parser.values(opt);
for (const QString& v : vals) {
values.push_back(v.toStdString());
}
h->exec(hvals);
} else {
LOGW() << "Not found command line handler for option: " << opt;
Ret ret = commandlineRegister()->apply(opt.toStdString(), values);
if (!ret) {
LOGE() << "failed apply option: opt, error: " << ret.toString();
}
}
}

View file

@ -20,11 +20,12 @@
#ifndef MU_APPSHELL_APPSHELL_H
#define MU_APPSHELL_APPSHELL_H
#include <vector>
#include <QList>
#include <QMap>
#include "modularity/imodulesetup.h"
#include "modularity/ioc.h"
#include "icommandlineregister.h"
#include "framework/commandline/icommandlineregister.h"
class QCommandLineParser;
@ -32,7 +33,7 @@ namespace mu {
namespace appshell {
class AppShell
{
INJECT(appshell, ICommandLineRegister, clregister)
INJECT(appshell, commandline::ICommandLineRegister, commandlineRegister)
public:
AppShell();
@ -41,10 +42,21 @@ public:
int run(int argc, char** argv);
private:
void parseCommandLineArguments(QCommandLineParser& parser) const;
enum class RunMode {
Gui,
Concole
};
void parseCommandLineArguments(QCommandLineParser& parser);
void applyCommandLineArguments(QCommandLineParser& parser);
std::vector<mu::framework::IModuleSetup*> m_modules;
RunMode runMode(const QStringList &options) const;
QList<mu::framework::IModuleSetup*> m_modules;
QList<QString> m_consoleRunModeOptions;
};
}
}

View file

@ -26,6 +26,8 @@ set(MODULE convertor)
set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/convertormodule.cpp
${CMAKE_CURRENT_LIST_DIR}/convertormodule.h
${CMAKE_CURRENT_LIST_DIR}/internal/convertorcommandlinecontroller.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/convertorcommandlinecontroller.h
)
include(${PROJECT_SOURCE_DIR}/build/module.cmake)

View file

@ -19,10 +19,14 @@
#include "convertormodule.h"
#include "modularity/ioc.h"
#include "appshell/icommandlineregister.h"
#include "commandline/icommandlineregister.h"
#include "internal/convertorcommandlinecontroller.h"
using namespace mu::convertor;
static ConvertorCommandLineController s_clcontroller;
std::string ConvertorModule::moduleName() const
{
return "convertor";
@ -30,7 +34,5 @@ std::string ConvertorModule::moduleName() const
void ConvertorModule::resolveImports()
{
auto cr = framework::ioc()->resolve<appshell::ICommandLineRegister>(moduleName());
if (cr) {
}
s_clcontroller.setup();
}

View file

@ -0,0 +1,31 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "convertorcommandlinecontroller.h"
#include "log.h"
using namespace mu::convertor;
using namespace mu::commandline;
void ConvertorCommandLineController::setup()
{
clinereg()->reg(this, {"j", "job"}, [this](const CommandLineValue& val) {
LOGI() << "do job " << val;
});
}

View file

@ -0,0 +1,37 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef MU_CONVERTOR_CONVERTORCOMMANDLINECONTROLLER_H
#define MU_CONVERTOR_CONVERTORCOMMANDLINECONTROLLER_H
#include "commandline/icommandlinehandler.h"
#include "commandline/icommandlineregister.h"
#include "modularity/ioc.h"
namespace mu::convertor {
class ConvertorCommandLineController : public commandline::ICommandLineHandler
{
INJECT(convertor, commandline::ICommandLineRegister, clinereg)
public:
ConvertorCommandLineController() = default;
void setup();
};
}
#endif // MU_CONVERTOR_CONVERTORCOMMANDLINECONTROLLER_H

View file

@ -24,7 +24,7 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/commandlinemodule.h
${CMAKE_CURRENT_LIST_DIR}/commandlinetypes.h
${CMAKE_CURRENT_LIST_DIR}/icommandlineregister.h
${CMAKE_CURRENT_LIST_DIR}/icommandlinecontroller.h
${CMAKE_CURRENT_LIST_DIR}/icommandlinehandler.h
${CMAKE_CURRENT_LIST_DIR}/internal/commandlineregister.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/commandlineregister.h
)

View file

@ -24,13 +24,18 @@
#include <vector>
namespace mu::commandline {
using CommandLineOption = std::pair<std::string /*short*/, std::string /*long*/>;
using CommandLineOption = std::list<std::string>;
using CommandLineValue = std::string;
using CommandLineValues = std::vector<CommandLineValue>;
inline bool operator ==(const CommandLineOption& opt, const std::string& str)
{
return opt.first == str || opt.second == str;
for (const std::string& o : opt) {
if (o == str) {
return true;
}
}
return false;
}
}

View file

@ -16,23 +16,18 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef MU_COMMANDLINE_ICOMMANDLINECONTROLLER_H
#define MU_COMMANDLINE_ICOMMANDLINECONTROLLER_H
#ifndef MU_COMMANDLINE_ICOMMANDLINEHANDLER_H
#define MU_COMMANDLINE_ICOMMANDLINEHANDLER_H
#include <memory>
#include "commandlinetypes.h"
namespace mu::commandline {
class ICommandLineController
class ICommandLineHandler
{
public:
virtual ~ICommandLineController() = default;
virtual bool canHandleOption(const CommandLineOption& opt) const = 0;
virtual bool apply(const CommandLineOption& opt, const CommandLineValues& vals) = 0;
virtual ~ICommandLineHandler() = default;
};
using ICommandLineControllerPtr = std::shared_ptr<ICommandLineController>;
}
#endif // MU_COMMANDLINE_ICOMMANDLINECONTROLLER_H
#endif // MU_COMMANDLINE_ICOMMANDLINEHANDLER_H

View file

@ -20,8 +20,10 @@
#define MU_COMMANDLINE_ICOMMANDLINEREGISTER_H
#include <memory>
#include <functional>
#include "modularity/imoduleexport.h"
#include "icommandlinehandler.h"
#include "ret.h"
namespace mu::commandline {
class ICommandLineRegister : MODULE_EXPORT_INTERFACE
@ -31,12 +33,24 @@ class ICommandLineRegister : MODULE_EXPORT_INTERFACE
public:
virtual ~ICommandLineRegister() = default;
virtual bool reg(const ICommandLineControllerPtr& h) = 0;
virtual bool reg(const ICommandLineController::Option& opt, const std::function<void()>& f) = 0;
virtual bool reg(const ICommandLineController::Option& opt, const std::function<void(const ICommandLineHandler::Values& vals)>& f) = 0;
using CallBack = std::function<void ()>;
using CallBackWithVal = std::function<void (const CommandLineValue&)>;
using CallBackWithVals = std::function<void (const CommandLineValues&)>;
virtual ICommandLineControllerPtr handler(const ICommandLineController::Option& opt) const = 0;
virtual ICommandLineControllerPtr handler(const std::string& opt) const = 0;
virtual Ret apply(const std::string& opt, const CommandLineValues& vals) = 0;
virtual void unReg(ICommandLineHandler* handler) = 0;
virtual void reg(ICommandLineHandler* handler, const CommandLineOption& opt, const CallBackWithVals& call) = 0;
void reg(ICommandLineHandler* handler, const CommandLineOption& opt, const CallBackWithVal& call)
{
reg(handler, opt, [call](const CommandLineValues& vals) { call(!vals.empty() ? vals.front() : CommandLineValue()); });
}
void reg(ICommandLineHandler* handler, const CommandLineOption& opt, const CallBack& call)
{
reg(handler, opt, [call](const CommandLineValues&) { call(); });
}
};
}

View file

@ -20,42 +20,51 @@
#include "log.h"
using namespace mu::appshell;
using namespace mu::commandline;
CommandLineRegister::CommandLineRegister()
{
}
bool CommandLineRegister::reg(const ICommandLineControllerPtr& h)
mu::Ret CommandLineRegister::apply(const std::string& opt, const CommandLineValues& vals)
{
IF_ASSERT_FAILED(h) {
return false;
auto found = m_handlers.find(opt);
if (found == m_handlers.end()) {
return make_ret(Ret::Code::UnknownError, "not found handler");
}
IF_ASSERT_FAILED(handler(h->option()) == nullptr) {
return false;
}
m_handlers.push_back(h);
return true;
Handler& h = found->second;
h.callback(vals);
return make_ret(Ret::Code::Ok);
}
ICommandLineControllerPtr CommandLineRegister::handler(const ICommandLineController::Option& opt) const
void CommandLineRegister::reg(ICommandLineHandler* handler, const CommandLineOption& opt, const CallBackWithVals& call)
{
for (const ICommandLineControllerPtr& h : m_handlers) {
if (h->option() == opt) {
return h;
for (const std::string& op : opt) {
doReg(handler, op, call);
}
}
void CommandLineRegister::doReg(ICommandLineHandler* handler, const std::string& opt, const CallBackWithVals& call)
{
auto found = m_handlers.find(opt);
IF_ASSERT_FAILED(found == m_handlers.end()) {
return;
}
Handler h;
h.h = handler;
h.callback = call;
m_handlers.insert({opt, h});
}
void CommandLineRegister::unReg(ICommandLineHandler* handler)
{
std::list<std::string> opts;
for (auto const& it : m_handlers) {
if (it.second.h == handler) {
opts.push_back(it.first);
}
}
return nullptr;
}
ICommandLineControllerPtr CommandLineRegister::handler(const std::string& opt) const
{
for (const ICommandLineControllerPtr& h : m_handlers) {
if (h->option() == opt) {
return h;
}
for (const std::string& opt : opts) {
m_handlers.erase(opt);
}
return nullptr;
}

View file

@ -16,27 +16,36 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef MU_APPSHELL_COMMANDLINEREGISTER_H
#define MU_APPSHELL_COMMANDLINEREGISTER_H
#ifndef MU_COMMANDLINE_COMMANDLINEREGISTER_H
#define MU_COMMANDLINE_COMMANDLINEREGISTER_H
#include <vector>
#include <map>
#include "../icommandlineregister.h"
namespace mu::appshell {
namespace mu::commandline {
class CommandLineRegister : public ICommandLineRegister
{
public:
CommandLineRegister();
CommandLineRegister() = default;
bool reg(const ICommandLineControllerPtr& h) override;
ICommandLineControllerPtr handler(const ICommandLineController::Option& opt) const override;
ICommandLineControllerPtr handler(const std::string& opt) const override;
Ret apply(const std::string& opt, const CommandLineValues& vals) override;
void unReg(ICommandLineHandler* handler) override;
void reg(ICommandLineHandler* handler, const CommandLineOption& opt, const CallBackWithVals& call) override;
private:
std::vector<ICommandLineControllerPtr> m_handlers;
void doReg(ICommandLineHandler* handler, const std::string& opt, const CallBackWithVals& call);
struct Handler
{
ICommandLineHandler* h = nullptr;
CallBackWithVals callback;
};
std::map<std::string/*option*/, Handler > m_handlers;
};
}
#endif // MU_APPSHELL_COMMANDLINEREGISTER_H
#endif // MU_COMMANDLINE_COMMANDLINEREGISTER_H

View file

@ -97,6 +97,11 @@ inline mu::Ret make_ret(Ret::Code e)
return Ret(static_cast<int>(e));
}
inline mu::Ret make_ret(Ret::Code e, const std::string& text)
{
return Ret(static_cast<int>(e), text);
}
inline bool check_ret(const Ret& r, Ret::Code c)
{
return r.code() == int(c);