|
@@ -0,0 +1,588 @@
|
|
|
+#include "task.h"
|
|
|
+
|
|
|
+#include <QJsonDocument>
|
|
|
+#include <QVersionNumber>
|
|
|
+#include <QDebug>
|
|
|
+#include <QJsonValue>
|
|
|
+#include <QJsonArray>
|
|
|
+#include <QAction>
|
|
|
+#include <QRegularExpression>
|
|
|
+#include <QInputDialog>
|
|
|
+#include <QTextCodec>
|
|
|
+#include <QRandomGenerator>
|
|
|
+#include <QJsonObject>
|
|
|
+#include <QProcess>
|
|
|
+#include <QScopedPointer>
|
|
|
+
|
|
|
+#include <utils/fileutils.h>
|
|
|
+#include <utils/pathutils.h>
|
|
|
+#include <core/vnotex.h>
|
|
|
+#include <core/exception.h>
|
|
|
+#include <notebook/notebook.h>
|
|
|
+#include <buffer/buffer.h>
|
|
|
+
|
|
|
+#include "shellexecution.h"
|
|
|
+#include "taskmgr.h"
|
|
|
+
|
|
|
+using namespace vnotex;
|
|
|
+
|
|
|
+QString Task::s_latestVersion = "0.1.3";
|
|
|
+
|
|
|
+QSharedPointer<Task> Task::fromFile(const QString &p_file, const QString &p_locale, TaskMgr *p_taskMgr)
|
|
|
+{
|
|
|
+ QSharedPointer<Task> task(new Task(p_locale, p_file, p_taskMgr, nullptr));
|
|
|
+ const auto obj = FileUtils::readJsonFile(p_file);
|
|
|
+ if (fromJson(task.data(), obj)) {
|
|
|
+ return task;
|
|
|
+ }
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+bool Task::fromJson(Task *p_task, const QJsonObject &p_obj)
|
|
|
+{
|
|
|
+ // For child task, it will inherit the version from parent.
|
|
|
+ if (p_obj.contains("version")) {
|
|
|
+ p_task->m_dto.version = p_obj["version"].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ const auto version = QVersionNumber::fromString(p_task->getVersion());
|
|
|
+ if (version.isNull()) {
|
|
|
+ qWarning() << "invalid task" << p_task->m_dto._source;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (version < QVersionNumber(1, 0, 0)) {
|
|
|
+ return fromJsonV0(p_task, p_obj);
|
|
|
+ } else {
|
|
|
+ qWarning() << "unknown task version" << version << p_task->m_dto._source;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool Task::fromJsonV0(Task *p_task, const QJsonObject &p_obj, bool p_mergeTasks)
|
|
|
+{
|
|
|
+ if (p_obj.contains("type")) {
|
|
|
+ p_task->m_dto.type = p_obj["type"].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("icon")) {
|
|
|
+ QString iconPath = p_obj["icon"].toString();
|
|
|
+ if (!iconPath.isEmpty()) {
|
|
|
+ if (QDir::isRelativePath(iconPath)) {
|
|
|
+ iconPath = QFileInfo(p_task->m_dto._source).dir().absoluteFilePath(iconPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (QFileInfo::exists(iconPath)) {
|
|
|
+ p_task->m_dto.icon = iconPath;
|
|
|
+ } else {
|
|
|
+ qWarning() << "task icon does not exist" << p_task->getLabel() << iconPath;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("shortcut")) {
|
|
|
+ p_task->m_dto.shortcut = p_obj["shortcut"].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("type")) {
|
|
|
+ p_task->m_dto.type = p_obj["type"].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("command")) {
|
|
|
+ p_task->m_dto.command = getLocaleString(p_obj["command"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("args")) {
|
|
|
+ p_task->m_dto.args = getLocaleStringList(p_obj["args"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("label")) {
|
|
|
+ p_task->m_dto.label = getLocaleString(p_obj["label"], p_task->m_locale);
|
|
|
+ } else if (p_task->m_dto.label.isNull() && !p_task->m_dto.command.isNull()) {
|
|
|
+ p_task->m_dto.label = p_task->m_dto.command;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("options")) {
|
|
|
+ auto options = p_obj["options"].toObject();
|
|
|
+
|
|
|
+ if (options.contains("cwd")) {
|
|
|
+ p_task->m_dto.options.cwd = options["cwd"].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (options.contains("env")) {
|
|
|
+ p_task->m_dto.options.env.clear();
|
|
|
+ auto env = options["env"].toObject();
|
|
|
+ for (auto it = env.begin(); it != env.end(); it++) {
|
|
|
+ auto value = getLocaleString(it.value(), p_task->m_locale);
|
|
|
+ p_task->m_dto.options.env.insert(it.key(), value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (options.contains("shell") && p_task->getType() == "shell") {
|
|
|
+ auto shell = options["shell"].toObject();
|
|
|
+
|
|
|
+ if (shell.contains("executable")) {
|
|
|
+ p_task->m_dto.options.shell.executable = shell["executable"].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (shell.contains("args")) {
|
|
|
+ p_task->m_dto.options.shell.args.clear();
|
|
|
+
|
|
|
+ const auto arr = shell["args"].toArray();
|
|
|
+ for (int i = 0; i < arr.size(); ++i) {
|
|
|
+ p_task->m_dto.options.shell.args << arr[i].toString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("tasks")) {
|
|
|
+ if (!p_mergeTasks) {
|
|
|
+ p_task->m_children.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ auto arr = p_obj["tasks"].toArray();
|
|
|
+ for (int i = 0; i < arr.size(); ++i) {
|
|
|
+ QScopedPointer<Task> childTask(new Task(p_task->m_locale, p_task->getFile(), p_task->m_taskMgr, p_task));
|
|
|
+ if (fromJson(childTask.data(), arr[i].toObject())) {
|
|
|
+ connect(childTask.data(), &Task::outputRequested,
|
|
|
+ p_task, &Task::outputRequested);
|
|
|
+ p_task->m_children.append(childTask.take());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("inputs")) {
|
|
|
+ p_task->m_dto.inputs.clear();
|
|
|
+ auto arr = p_obj["inputs"].toArray();
|
|
|
+ for (int i = 0; i < arr.size(); ++i) {
|
|
|
+ const auto inputObj = arr[i].toObject();
|
|
|
+ InputDTO input;
|
|
|
+ if (inputObj.contains("id")) {
|
|
|
+ input.id = inputObj["id"].toString();
|
|
|
+ } else {
|
|
|
+ qWarning() << "Input configuration not contains id";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (inputObj.contains("type")) {
|
|
|
+ input.type = inputObj["type"].toString();
|
|
|
+ } else {
|
|
|
+ input.type = "promptString";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (inputObj.contains("description")) {
|
|
|
+ input.description = getLocaleString(inputObj["description"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (inputObj.contains("default")) {
|
|
|
+ input.default_ = getLocaleString(inputObj["default"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (input.type == "promptString" && inputObj.contains("password")) {
|
|
|
+ input.password = inputObj["password"].toBool();
|
|
|
+ } else {
|
|
|
+ input.password = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (input.type == "pickString") {
|
|
|
+ if (inputObj.contains("options")) {
|
|
|
+ input.options = getLocaleStringList(inputObj["options"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!input.default_.isNull() && !input.options.contains(input.default_)) {
|
|
|
+ qWarning() << "default of input must be one of the option values";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ p_task->m_dto.inputs << input;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p_obj.contains("messages")) {
|
|
|
+ p_task->m_dto.messages.clear();
|
|
|
+ auto arr = p_obj["messages"].toArray();
|
|
|
+ for (int i = 0; i < arr.size(); ++i) {
|
|
|
+ const auto msgObj = arr[i].toObject();
|
|
|
+ MessageDTO msg;
|
|
|
+ if (msgObj.contains("id")) {
|
|
|
+ msg.id = msgObj["id"].toString();
|
|
|
+ } else {
|
|
|
+ qWarning() << "Message configuration not contain id";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msgObj.contains("type")) {
|
|
|
+ msg.type = msgObj["type"].toString();
|
|
|
+ } else {
|
|
|
+ msg.type = "information";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msgObj.contains("title")) {
|
|
|
+ msg.title = getLocaleString(msgObj["title"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msgObj.contains("text")) {
|
|
|
+ msg.text = getLocaleString(msgObj["text"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msgObj.contains("detailedText")) {
|
|
|
+ msg.detailedText = getLocaleString(msgObj["detailedText"], p_task->m_locale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msgObj.contains("buttons")) {
|
|
|
+ auto buttonsArr = msgObj["buttons"].toArray();
|
|
|
+ for (int j = 0; j < buttonsArr.size(); ++j) {
|
|
|
+ const auto btnObj = buttonsArr[j].toObject();
|
|
|
+ ButtonDTO btn;
|
|
|
+ btn.text = getLocaleString(btnObj["text"], p_task->m_locale);
|
|
|
+ msg.buttons << btn;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ p_task->m_dto.messages << msg;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // OS-specific task configuration
|
|
|
+#if defined (Q_OS_WIN)
|
|
|
+ #define OS_SPEC "windows"
|
|
|
+#elif defined (Q_OS_MACOS)
|
|
|
+ #define OS_SPEC "osx"
|
|
|
+#else
|
|
|
+ #define OS_SPEC "linux"
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (p_obj.contains(OS_SPEC)) {
|
|
|
+ const auto osObj = p_obj[OS_SPEC].toObject();
|
|
|
+ fromJsonV0(p_task, osObj, true);
|
|
|
+ }
|
|
|
+
|
|
|
+#undef OS_SPEC
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+const QString &Task::getVersion() const
|
|
|
+{
|
|
|
+ return m_dto.version;
|
|
|
+}
|
|
|
+
|
|
|
+const QString &Task::getType() const
|
|
|
+{
|
|
|
+ return m_dto.type;
|
|
|
+}
|
|
|
+
|
|
|
+QString Task::getCommand()
|
|
|
+{
|
|
|
+ return variableMgr().evaluate(this, m_dto.command);
|
|
|
+}
|
|
|
+
|
|
|
+QStringList Task::getArgs()
|
|
|
+{
|
|
|
+ return variableMgr().evaluate(this, m_dto.args);
|
|
|
+}
|
|
|
+
|
|
|
+const QString &Task::getLabel() const
|
|
|
+{
|
|
|
+ return m_dto.label;
|
|
|
+}
|
|
|
+
|
|
|
+const QString &Task::getIcon() const
|
|
|
+{
|
|
|
+ return m_dto.icon;
|
|
|
+}
|
|
|
+
|
|
|
+const QString &Task::getShortcut() const
|
|
|
+{
|
|
|
+ return m_dto.shortcut;
|
|
|
+}
|
|
|
+
|
|
|
+QString Task::getOptionsCwd()
|
|
|
+{
|
|
|
+ auto cwd = m_dto.options.cwd;
|
|
|
+ if (!cwd.isNull()) {
|
|
|
+ return variableMgr().evaluate(this, cwd);
|
|
|
+ }
|
|
|
+
|
|
|
+ auto notebook = TaskVariableMgr::getCurrentNotebook();
|
|
|
+ if (notebook) {
|
|
|
+ cwd = notebook->getRootFolderAbsolutePath();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cwd.isNull()) {
|
|
|
+ return cwd;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto buffer = TaskVariableMgr::getCurrentBuffer();
|
|
|
+ if (buffer) {
|
|
|
+ return QFileInfo(buffer->getPath()).dir().absolutePath();
|
|
|
+ }
|
|
|
+
|
|
|
+ return QFileInfo(m_dto._source).dir().absolutePath();
|
|
|
+}
|
|
|
+
|
|
|
+const QMap<QString, QString> &Task::getOptionsEnv() const
|
|
|
+{
|
|
|
+ return m_dto.options.env;
|
|
|
+}
|
|
|
+
|
|
|
+const QString &Task::getOptionsShellExecutable() const
|
|
|
+{
|
|
|
+ return m_dto.options.shell.executable;
|
|
|
+}
|
|
|
+
|
|
|
+QStringList Task::getOptionsShellArgs()
|
|
|
+{
|
|
|
+ if (m_dto.options.shell.args.isEmpty()) {
|
|
|
+ return ShellExecution::defaultShellArguments(m_dto.options.shell.executable);
|
|
|
+ } else {
|
|
|
+ return variableMgr().evaluate(this, m_dto.options.shell.args);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const QVector<Task *> &Task::getChildren() const
|
|
|
+{
|
|
|
+ return m_children;
|
|
|
+}
|
|
|
+
|
|
|
+const QVector<InputDTO> &Task::getInputs() const
|
|
|
+{
|
|
|
+ return m_dto.inputs;
|
|
|
+}
|
|
|
+
|
|
|
+const InputDTO *Task::findInput(const QString &p_id) const
|
|
|
+{
|
|
|
+ for (const auto &input : m_dto.inputs) {
|
|
|
+ if (input.id == p_id) {
|
|
|
+ return &input;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ qWarning() << "input" << p_id << "not found for task" << getLabel();
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+const MessageDTO *Task::findMessage(const QString &p_id) const
|
|
|
+{
|
|
|
+ for (const auto &msg : m_dto.messages) {
|
|
|
+ if (msg.id == p_id) {
|
|
|
+ return &msg;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ qWarning() << "message" << p_id << "not found for task" << getLabel();
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+const QString &Task::getFile() const
|
|
|
+{
|
|
|
+ return m_dto._source;
|
|
|
+}
|
|
|
+
|
|
|
+Task::Task(const QString &p_locale,
|
|
|
+ const QString &p_file,
|
|
|
+ TaskMgr *p_taskMgr,
|
|
|
+ QObject *p_parent)
|
|
|
+ : QObject(p_parent),
|
|
|
+ m_taskMgr(p_taskMgr),
|
|
|
+ m_locale(p_locale)
|
|
|
+{
|
|
|
+ m_dto._source = p_file;
|
|
|
+ m_dto.version = s_latestVersion;
|
|
|
+ m_dto.type = "shell";
|
|
|
+ m_dto.options.shell.executable = ShellExecution::defaultShell();
|
|
|
+
|
|
|
+ // Inherit configuration.
|
|
|
+ m_parent = qobject_cast<Task *>(p_parent);
|
|
|
+ if (m_parent) {
|
|
|
+ m_dto.version = m_parent->m_dto.version;
|
|
|
+ m_dto.type = m_parent->m_dto.type;
|
|
|
+ m_dto.command = m_parent->m_dto.command;
|
|
|
+ m_dto.args = m_parent->m_dto.args;
|
|
|
+ m_dto.options.cwd = m_parent->m_dto.options.cwd;
|
|
|
+ m_dto.options.env = m_parent->m_dto.options.env;
|
|
|
+ m_dto.options.shell.executable = m_parent->m_dto.options.shell.executable;
|
|
|
+ m_dto.options.shell.args = m_parent->m_dto.options.shell.args;
|
|
|
+ // Do not inherit label/inputs/tasks.
|
|
|
+ } else {
|
|
|
+ m_dto.label = QFileInfo(p_file).baseName();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+QProcess *Task::setupProcess()
|
|
|
+{
|
|
|
+ setCancelled(false);
|
|
|
+
|
|
|
+ auto command = getCommand();
|
|
|
+ if (command.isEmpty()) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ QScopedPointer<QProcess> scopedProcess(new QProcess(this));
|
|
|
+
|
|
|
+ auto process = scopedProcess.data();
|
|
|
+ process->setWorkingDirectory(getOptionsCwd());
|
|
|
+
|
|
|
+ const auto &optionsEnv = getOptionsEnv();
|
|
|
+ if (!optionsEnv.isEmpty()) {
|
|
|
+ auto env = QProcessEnvironment::systemEnvironment();
|
|
|
+ for (auto it = optionsEnv.begin(); it != optionsEnv.end(); it++) {
|
|
|
+ env.insert(it.key(), it.value());
|
|
|
+ }
|
|
|
+ process->setProcessEnvironment(env);
|
|
|
+ }
|
|
|
+
|
|
|
+ const auto args = getArgs();
|
|
|
+ const auto &type = getType();
|
|
|
+
|
|
|
+ if (type == "shell") {
|
|
|
+ ShellExecution::setupProcess(process,
|
|
|
+ command,
|
|
|
+ args,
|
|
|
+ getOptionsShellExecutable(),
|
|
|
+ getOptionsShellArgs());
|
|
|
+ } else if (getType() == "process") {
|
|
|
+ process->setProgram(command);
|
|
|
+ process->setArguments(args);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isCancelled()) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ scopedProcess.take();
|
|
|
+
|
|
|
+ connect(process, &QProcess::started,
|
|
|
+ this, [this]() {
|
|
|
+ emit outputRequested(tr("[Task (%1) started]\n").arg(getLabel()));
|
|
|
+ });
|
|
|
+ connect(process, &QProcess::readyReadStandardOutput,
|
|
|
+ this, [this, process]() {
|
|
|
+ auto text = decodeText(process->readAllStandardOutput());
|
|
|
+ // TODO: interaction with process.
|
|
|
+ emit outputRequested(text);
|
|
|
+ });
|
|
|
+ connect(process, &QProcess::readyReadStandardError,
|
|
|
+ this, [this, process]() {
|
|
|
+ auto text = process->readAllStandardError();
|
|
|
+ emit outputRequested(decodeText(text));
|
|
|
+ });
|
|
|
+ connect(process, &QProcess::errorOccurred,
|
|
|
+ this, [this](QProcess::ProcessError error) {
|
|
|
+ emit outputRequested(tr("[Task (%1) error occurred (%2)]\n").arg(getLabel()).arg(error));
|
|
|
+ });
|
|
|
+ connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
|
+ this, [this, process](int exitCode) {
|
|
|
+ emit outputRequested(tr("\n[Task (%1) finished (%2)]\n").arg(getLabel()).arg(exitCode));
|
|
|
+ process->deleteLater();
|
|
|
+ });
|
|
|
+
|
|
|
+ return process;
|
|
|
+}
|
|
|
+
|
|
|
+void Task::run()
|
|
|
+{
|
|
|
+ QProcess *process;
|
|
|
+ try {
|
|
|
+ process = setupProcess();
|
|
|
+ } catch (const char *msg) {
|
|
|
+ qWarning() << "exception while setup process" << msg;
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (process) {
|
|
|
+ qDebug() << "run task" << process->program() << process->arguments();
|
|
|
+ process->start();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const TaskDTO &Task::getDTO() const
|
|
|
+{
|
|
|
+ return m_dto;
|
|
|
+}
|
|
|
+
|
|
|
+QString Task::decodeText(const QByteArray &p_text)
|
|
|
+{
|
|
|
+ static QByteArrayList codecNames = {
|
|
|
+ "UTF-8",
|
|
|
+ "System",
|
|
|
+ "UTF-16",
|
|
|
+ "GB18030"
|
|
|
+ };
|
|
|
+
|
|
|
+ for (const auto &name : codecNames) {
|
|
|
+ auto text = decodeText(p_text, name);
|
|
|
+ if (!text.isNull()) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return QString::fromLocal8Bit(p_text);
|
|
|
+}
|
|
|
+
|
|
|
+QString Task::decodeText(const QByteArray &p_text, const QByteArray &p_name)
|
|
|
+{
|
|
|
+ auto codec = QTextCodec::codecForName(p_name);
|
|
|
+ if (codec) {
|
|
|
+ QTextCodec::ConverterState state;
|
|
|
+ auto text = codec->toUnicode(p_text.data(), p_text.size(), &state);
|
|
|
+ if (state.invalidChars > 0) {
|
|
|
+ return QString();
|
|
|
+ }
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+ return QString();
|
|
|
+}
|
|
|
+
|
|
|
+QString Task::getLocaleString(const QJsonValue &p_value, const QString &p_locale)
|
|
|
+{
|
|
|
+ if (p_value.isObject()) {
|
|
|
+ auto obj = p_value.toObject();
|
|
|
+ if (obj.contains(p_locale)) {
|
|
|
+ return obj.value(p_locale).toString();
|
|
|
+ } else {
|
|
|
+ qWarning() << "value of locale not found" << p_locale;
|
|
|
+ if (!obj.isEmpty()){
|
|
|
+ return obj.begin().value().toString();
|
|
|
+ } else {
|
|
|
+ return QString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return p_value.toString();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+QStringList Task::getLocaleStringList(const QJsonValue &p_value, const QString &p_locale)
|
|
|
+{
|
|
|
+ QStringList strs;
|
|
|
+ const auto arr = p_value.toArray();
|
|
|
+ for (int i = 0; i < arr.size(); ++i) {
|
|
|
+ strs << getLocaleString(arr[i], p_locale);
|
|
|
+ }
|
|
|
+ return strs;
|
|
|
+}
|
|
|
+
|
|
|
+QStringList Task::getStringList(const QJsonValue &p_value)
|
|
|
+{
|
|
|
+ QStringList strs;
|
|
|
+ const auto arr = p_value.toArray();
|
|
|
+ for (int i = 0; i < arr.size(); ++i) {
|
|
|
+ strs << arr[i].toString();
|
|
|
+ }
|
|
|
+ return strs;
|
|
|
+}
|
|
|
+
|
|
|
+const TaskVariableMgr &Task::variableMgr() const
|
|
|
+{
|
|
|
+ return m_taskMgr->getVariableMgr();
|
|
|
+}
|
|
|
+
|
|
|
+bool Task::isCancelled() const
|
|
|
+{
|
|
|
+ return m_cancelled;
|
|
|
+}
|
|
|
+
|
|
|
+void Task::setCancelled(bool p_cancelled)
|
|
|
+{
|
|
|
+ m_cancelled = p_cancelled;
|
|
|
+}
|