diff --git a/plugins/robots/checker/twoDModelRunner/main.cpp b/plugins/robots/checker/twoDModelRunner/main.cpp index 75bc4d5c72..f71082b23b 100644 --- a/plugins/robots/checker/twoDModelRunner/main.cpp +++ b/plugins/robots/checker/twoDModelRunner/main.cpp @@ -13,19 +13,19 @@ * limitations under the License. */ #include - #include #include #include #include #include - #include #include - #include "runner.h" -const int maxLogSize = 10 * 1024 * 1024; // 10 MB +constexpr int maxLogSize = 10 * 1024 * 1024; // 10 MB +constexpr int TWO_D_MODEL_RUNNER_INTERPRET_ERROR = 2; +constexpr int TWO_D_MODEL_RUNNER_GENERATE_ERROR = 3; +constexpr int TWO_D_MODEL_RUNNER_GENERATE_MODE_NOT_EXIST = 4; const QString description = QObject::tr( "Emulates robot`s behaviour on TRIK Studio 2D model separately from programming environment. "\ @@ -124,6 +124,15 @@ int main(int argc, char *argv[]) , QObject::tr("Close the window and exit after diagram/script"\ " finishes.")); QCommandLineOption showConsoleOption({"c", "console"}, QObject::tr("Shows robot's console.")); + QCommandLineOption generatePathOption("generate-path" + , QObject::tr("The complete file path, including the filename"\ + ", to save the generated JavaScript or Python code.") + , "path-to-save-code", QString()); + QCommandLineOption generateModeOption("generate-mode", QObject::tr("Select \"python\" or \"javascript\".") + , "generate-mode", "python"); + QCommandLineOption directScriptExecutionPathOption("script-path" + , QObject::tr("The path to the Python or JavaScript file that will be used for interpretation.") + , "script-path", QString()); parser.addOption(backgroundOption); parser.addOption(reportOption); parser.addOption(trajectoryOption); @@ -133,14 +142,14 @@ int main(int argc, char *argv[]) parser.addOption(closeOnFinishOption); parser.addOption(closeOnSuccessOption); parser.addOption(showConsoleOption); - + parser.addOption(generatePathOption); + parser.addOption(generateModeOption); + parser.addOption(directScriptExecutionPathOption); parser.process(*app); - const QStringList positionalArgs = parser.positionalArguments(); if (positionalArgs.size() != 1) { parser.showHelp(); } - const QString &qrsFile = positionalArgs.first(); const bool backgroundMode = parser.isSet(backgroundOption); const QString report = parser.isSet(reportOption) ? parser.value(reportOption) : QString(); @@ -150,12 +159,28 @@ int main(int argc, char *argv[]) const bool closeOnSuccessMode = parser.isSet(closeOnSuccessOption); const bool closeOnFinishMode = backgroundMode || parser.isSet(closeOnFinishOption); const bool showConsoleMode = parser.isSet(showConsoleOption); - QScopedPointer runner(new twoDModel::Runner(report, trajectory, input, mode)); + const QString generatePath = parser.value(generatePathOption); + const QString generateMode = parser.value(generateModeOption); + const QString scriptFilePath = parser.value(directScriptExecutionPathOption); + QScopedPointer runner(new twoDModel::Runner(report, trajectory, input, mode, qrsFile)); auto speedFactor = parser.value(speedOption).toInt(); - if (!runner->interpret(qrsFile, backgroundMode, speedFactor - , closeOnFinishMode, closeOnSuccessMode, showConsoleMode)) { - return 2; + + if (!generatePath.isEmpty()) { + if (generateMode != "python" and generateMode != "javascript") { + parser.showHelp(); + QLOG_ERROR() << "Problem with generate code to " << generatePath; + return TWO_D_MODEL_RUNNER_GENERATE_MODE_NOT_EXIST; + } + if (!runner->generate(generatePath, generateMode)) { + QLOG_ERROR() << "Problem with generate code to " << generatePath; + return TWO_D_MODEL_RUNNER_GENERATE_ERROR; + } + } + + if (!runner->interpret(backgroundMode, speedFactor, closeOnFinishMode, + closeOnSuccessMode, showConsoleMode, scriptFilePath)) { + return TWO_D_MODEL_RUNNER_INTERPRET_ERROR; } const int exitCode = app->exec(); diff --git a/plugins/robots/checker/twoDModelRunner/runner.cpp b/plugins/robots/checker/twoDModelRunner/runner.cpp index 9ac4eca504..a278d90ba4 100644 --- a/plugins/robots/checker/twoDModelRunner/runner.cpp +++ b/plugins/robots/checker/twoDModelRunner/runner.cpp @@ -23,13 +23,17 @@ #include #include #include - +#include #include #include using namespace twoDModel; -Runner::Runner(const QString &report, const QString &trajectory) +Runner::Runner(const QString &report, const QString &trajectory, + const QString &input, const QString &mode, const QString &qrsFile): + mInputsFile(input) + , mMode(mode) + , mSaveFile(qrsFile) { mQRealFacade.reset(new qReal::SystemFacade()); mProjectManager.reset(new qReal::ProjectManager(mQRealFacade->models())); @@ -39,7 +43,7 @@ Runner::Runner(const QString &report, const QString &trajectory) mController.reset(new qReal::Controller()); mSceneCustomizer.reset(new qReal::gui::editor::SceneCustomizer()); - mTextManager.reset(new qReal::NullTextManager()); + mTextManager.reset(new qReal::text::TextManager(mQRealFacade->events(), *mMainWindow)); mConfigurator.reset(new qReal::PluginConfigurator(mQRealFacade->models().repoControlApi() , mQRealFacade->models().graphicalModelAssistApi() , mQRealFacade->models().logicalModelAssistApi() @@ -61,14 +65,8 @@ Runner::Runner(const QString &report, const QString &trajectory) connect(&*mErrorReporter, &qReal::ConsoleErrorReporter::errorAdded, &*mReporter, &Reporter::addError); connect(&*mErrorReporter, &qReal::ConsoleErrorReporter::criticalAdded, &*mReporter, &Reporter::addError); connect(&*mErrorReporter, &qReal::ConsoleErrorReporter::logAdded, &*mReporter, &Reporter::addLog); -} -Runner::Runner(const QString &report, const QString &trajectory, const QString &input, const QString &mode) - : Runner(report, trajectory) - -{ - mInputsFile = input; - mMode = mode; + mProjectManager->open(mSaveFile); } Runner::~Runner() @@ -87,14 +85,38 @@ Runner::~Runner() mQRealFacade.reset(); } -bool Runner::interpret(const QString &saveFile, const bool background - , const int customSpeedFactor, bool closeOnFinish - , const bool closeOnSuccess, const bool showConsole) +bool Runner::generate(const QString &generatePath, const QString &generateMode) { - if (!mProjectManager->open(saveFile)) { + for (auto&& action: mPluginFacade->actionsManager().actions()){ + if (generateMode == "python") { + if (action.action()->objectName() == "generatePythonTrikCode") { + emit action.action()->triggered(); + } + } + if (generateMode == "javascript") { + if (action.action()->objectName() == "generateTRIKCode") { + emit action.action()->triggered(); + } + } + } + + auto codes = mTextManager->code(mMainWindow->activeDiagram()); + if (codes.empty()) { + // The application has already logged a + // description of the problem that prevented script generation. + return false; + } + auto path = mTextManager->path(codes.first()); + if (!QFile::copy(path, generatePath)) { + QLOG_ERROR() << "File with name " << generatePath << " already exist"; return false; } + return true; +} +bool Runner::interpret(const bool background, const int customSpeedFactor, bool closeOnFinish + , const bool closeOnSuccess, const bool showConsole, const QString &filePath) +{ /// @todo: A bit hacky way to get 2D model window. Actually we must not have need in this. /// GUI must be separated from logic and not appear here at all. QList twoDModelWindows; @@ -143,7 +165,7 @@ bool Runner::interpret(const QString &saveFile, const bool background mReporter->onInterpretationStart(); if (mMode == "script") { - return mPluginFacade->interpretCode(mInputsFile); + return mPluginFacade->interpretCode(mInputsFile, filePath); } else if (mMode == "diagram") { mPluginFacade->actionsManager().runAction().trigger(); } diff --git a/plugins/robots/checker/twoDModelRunner/runner.h b/plugins/robots/checker/twoDModelRunner/runner.h index 881a5645fa..50af575dba 100644 --- a/plugins/robots/checker/twoDModelRunner/runner.h +++ b/plugins/robots/checker/twoDModelRunner/runner.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -46,17 +46,14 @@ class Runner : public QObject Q_OBJECT public: - /// Constructor. - /// @param report A path to a file where JSON report about the session will be written after it ends. - /// @param trajectory A path to a file where robot`s trajectory will be written during the session. - Runner(const QString &report, const QString &trajectory); - /// Constructor. /// @param report A path to a file where JSON report about the session will be written after it ends. /// @param trajectory A path to a file where robot`s trajectory will be written during the session. /// @param input A path to a file where JSON with inputs for JavaScript. /// @param mode Interpret mode. - Runner(const QString &report, const QString &trajectory, const QString &input, const QString &mode); + /// @param qrsFile Path to TRIK Studio project + Runner(const QString &report, const QString &trajectory, const QString &input, + const QString &mode, const QString &qrsFile); ~Runner(); @@ -67,8 +64,14 @@ class Runner : public QObject /// @param speedFactor can be used when not in background mode to tune interpretation speed /// @param closeOnSuccessMode If true then model will be closed if the program finishes without errors. /// @param showConsole If true then robot's console will be showed. - bool interpret(const QString &saveFile, bool background, int speedFactor - , bool closeOnFinish, bool closeOnSuccess, bool showConsole); + /// @param filePath If not QString() interpret code on this path instead of the code in the TRIK Studio file format. + bool interpret(bool background, int speedFactor + , bool closeOnFinish, bool closeOnSuccess, bool showConsole, const QString &filePath); + + /// Generate code from TRIK Studio save file + /// @param generatePath The path to save the generated code + /// @param generateMode "python" or "javascript" + bool generate(const QString &generatePath, const QString &generateMode); private slots: void close(); @@ -85,7 +88,7 @@ private slots: QScopedPointer mErrorReporter; QScopedPointer mProjectManager; QScopedPointer mMainWindow; - QScopedPointer mTextManager; + QScopedPointer mTextManager; QScopedPointer mSceneCustomizer; QScopedPointer mConfigurator; QScopedPointer mReporter; @@ -93,6 +96,7 @@ private slots: QList mRobotConsoles; QString mInputsFile; QString mMode; + QString mSaveFile; }; } diff --git a/plugins/robots/interpreters/interpreterCore/include/interpreterCore/robotsPluginFacade.h b/plugins/robots/interpreters/interpreterCore/include/interpreterCore/robotsPluginFacade.h index 1466ddf12b..a3b7858481 100644 --- a/plugins/robots/interpreters/interpreterCore/include/interpreterCore/robotsPluginFacade.h +++ b/plugins/robots/interpreters/interpreterCore/include/interpreterCore/robotsPluginFacade.h @@ -83,7 +83,7 @@ class RobotsPluginFacade : public QObject const kitBase::EventsForKitPluginInterface &eventsForKitPlugins() const; //tempory solution - bool interpretCode(const QString &inputs); + bool interpretCode(const QString &inputs, const QString &filepath); public slots: void saveCode(const QString &code, const QString &languageExtension); diff --git a/plugins/robots/interpreters/interpreterCore/src/robotsPluginFacade.cpp b/plugins/robots/interpreters/interpreterCore/src/robotsPluginFacade.cpp index 7f5a161fab..4fda1ed4f5 100644 --- a/plugins/robots/interpreters/interpreterCore/src/robotsPluginFacade.cpp +++ b/plugins/robots/interpreters/interpreterCore/src/robotsPluginFacade.cpp @@ -304,11 +304,27 @@ const kitBase::EventsForKitPluginInterface &RobotsPluginFacade::eventsForKitPlug return mEventsForKitPlugin; } -bool RobotsPluginFacade::interpretCode(const QString &inputs) +bool RobotsPluginFacade::interpretCode(const QString &inputs, const QString &filepath) { - auto logicalRepo = &mLogicalModelApi->logicalRepoApi(); - QString code = logicalRepo->metaInformation("activeCode").toString(); - QString extension = logicalRepo->metaInformation("activeCodeLanguageExtension").toString(); + QString code; + QString extension; + if (filepath.isEmpty()) { + QFile file(filepath); + QFileInfo fileInfo(file); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + mMainWindow->errorReporter()->addError( + tr("The specified script file could not be opened for reading ") + filepath); + return false; + } + code = file.readAll(); + extension = fileInfo.suffix().toLower(); + } + else { + auto logicalRepo = &mLogicalModelApi->logicalRepoApi(); + code = logicalRepo->metaInformation("activeCode").toString(); + extension = logicalRepo->metaInformation("activeCodeLanguageExtension").toString(); + } if (code.isEmpty()) { mMainWindow->errorReporter()->addError(tr("No saved code found in the qrs file")); return false; diff --git a/qrtranslations/fr/plugins/robots/interpreterCore_fr.ts b/qrtranslations/fr/plugins/robots/interpreterCore_fr.ts index addf70adb8..2b64f8bd9e 100644 --- a/qrtranslations/fr/plugins/robots/interpreterCore_fr.ts +++ b/qrtranslations/fr/plugins/robots/interpreterCore_fr.ts @@ -314,7 +314,12 @@ - + + The specified script file could not be opened for reading + + + + No saved code found in the qrs file diff --git a/qrtranslations/fr/plugins/robots/twoDModelRunner_fr.ts b/qrtranslations/fr/plugins/robots/twoDModelRunner_fr.ts index a6d1d69230..7467f61262 100644 --- a/qrtranslations/fr/plugins/robots/twoDModelRunner_fr.ts +++ b/qrtranslations/fr/plugins/robots/twoDModelRunner_fr.ts @@ -40,6 +40,21 @@ In background mode the session will be terminated just after the execution ended Speed factor, try from 5 to 20, or even 1000 (at your own risk!). + + + The complete file path, including the filename, to save the generated JavaScript or Python code. + + + + + The path to the Python or JavaScript file that will be used for interpretation. + + + + + Select "python" or "javascript". + + Use this option set to "minimal" to disable connection to X server Mettez "minimal" dans cette option pour désactiver la connexion au serveur X @@ -49,7 +64,7 @@ In background mode the session will be terminated just after the execution ended Le chemin au fichier de sauvegarde des resultats (JSON) - + A path to file where robot`s trajectory will be written. The writing will not be performed not immediately, each trajectory point will be written just when obtained by checker, so FIFOs are recommended to be targets for this option. Le chemin au ficher ou la trajectoire du robot sera enregistrée. L'enregistrement ne sera pas fait immediatement, chaque point de trajectoire sera écrit dès lors qu'il est obteneur par le checker, donc FIFO sont récommandés pour cette option. @@ -72,7 +87,7 @@ In background mode the session will be terminated just after the execution ended twoDModel::Runner - + Robot console diff --git a/qrtranslations/ru/plugins/robots/interpreterCore_ru.ts b/qrtranslations/ru/plugins/robots/interpreterCore_ru.ts index fcfcd8da3b..6b8c26c7f4 100644 --- a/qrtranslations/ru/plugins/robots/interpreterCore_ru.ts +++ b/qrtranslations/ru/plugins/robots/interpreterCore_ru.ts @@ -228,7 +228,12 @@ Экспорт упражнения по заданному пути не удался (попробуйте другой путь) - + + The specified script file could not be opened for reading + Не удалось открыть указанный файл для чтения скрипта + + + No saved code found in the qrs file В qrs не найден сохраннёный код diff --git a/qrtranslations/ru/plugins/robots/twoDModelRunner_ru.ts b/qrtranslations/ru/plugins/robots/twoDModelRunner_ru.ts index efcdffd1fe..725c4b3121 100644 --- a/qrtranslations/ru/plugins/robots/twoDModelRunner_ru.ts +++ b/qrtranslations/ru/plugins/robots/twoDModelRunner_ru.ts @@ -47,7 +47,22 @@ In background mode the session will be terminated just after the execution ended Ускорение, попробуйте от 5 до 20, но можно пробовать и 1000. - + + The complete file path, including the filename, to save the generated JavaScript or Python code. + Полный путь, включающий имя файла, для сохранения сгенерированного Javascript или Python кода. + + + + The path to the Python or JavaScript file that will be used for interpretation. + Путь к Python или Javascript файлу, который будет использоваться для интерпретации. + + + + Select "python" or "javascript". + Выберите "python" или "javascript". + + + A path to file where robot`s trajectory will be written. The writing will not be performed not immediately, each trajectory point will be written just when obtained by checker, so FIFOs are recommended to be targets for this option. Путь к файлу, куда будет выводиться траектори робота. Запись не будет осуществлена единомоментно, каждый узел траектории будет записан по факту его просчета проверяющей системой. Поэтому разумно использования FIFO-файлов в качестве значения этого параметра. @@ -74,7 +89,7 @@ In background mode the session will be terminated just after the execution ended twoDModel::Runner - + Robot console Консоль робота