Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <Loader.h>
- Loader::Loader() {
- startTimer(5*60*1000);
- // запустить машину
- programm = compiler.Make(MAIN_PATH);
- qDebug() << compiler.mErrorList;
- Q_ASSERT_X(programm != nullptr, "Loader::Loader()", "Compile failed");
- // получить таблицу символов скриптов
- QVariantMap map = programm->Symbols();
- // счетчик добавить отдельно, он не начинается с vg
- symbolTable.insert("vpuTickCount", map.value("vpuTickCount").toInt());
- // запомнить переменные (начинаются с vg)
- foreach(QString symbol, map.keys()) {
- if (symbol.startsWith("vg")) {
- symbolTable.insert(symbol, map.value(symbol).toInt());
- }
- if ((!symbol.isNull()) && (symbol.at(0).isUpper())) {
- //если останется true - включить символ в список функций
- bool includeFunc = true;
- //проверить условия отсева функций
- if (baseFuncList.contains(symbol))
- includeFunc = false;
- else if (symbol.startsWith("Module"))
- includeFunc = false;
- else if (symbol.startsWith("Can"))
- includeFunc = false;
- else if (symbol.startsWith("Log"))
- includeFunc = false;
- else if (symbol.startsWith("Setup"))
- includeFunc = false;
- else if (symbol.endsWith("Enter"))
- includeFunc = false;
- else if (symbol.endsWith("Hnd"))
- includeFunc = false;
- //добавить функцию в список
- if (includeFunc == true) {
- functionTable.insert(symbol, map.value(symbol).toInt());
- functions[symbol] = map.value(symbol);
- }
- }
- }
- // запустить программу
- vpu->SetProgram(programm, false, false);
- vpu->start();
- // по обновлению переменных в контроллере обновлять их проекцию в qml
- connect(vpu.data(), SIGNAL(updateVariables()), SLOT(getVariables()));
- }
- void Loader::init() {
- // QTimer *timer = new QTimer(this);
- // timer->start(500);
- // connect(timer, &QTimer::timeout, [this] () {
- // QMetaProperty aaa = QQmlProperty(this, "aaa", engine->rootContext()).property();
- // int val = aaa.read(this).toInt();
- //// blockSignals(true);
- // aaa.write(this, val+1);
- //// blockSignals(false);
- //// aaa.notifySignal().invoke(this, Qt::DirectConnection);
- // qDebug() << "timeout" << aaa.isValid() << val;
- // });
- engine = qobject_cast<QQmlApplicationEngine *>(this->QObject::parent());
- Q_ASSERT_X(!engine.isNull(), "Loader::init()", "no engine found!");
- QFile file(CONFIG_PATH);
- QTextStream stream(&file);
- QStringList lines;
- int pos = 0;
- Q_ASSERT_X(file.exists(), "Loader::init()", "scripts/config.h not exists!");
- file.open(QIODevice::ReadOnly);
- while (!stream.atEnd()) {
- QString line = stream.readLine();
- lines += line;
- if (line.contains("#define")) {
- //узнать, закомментирована ли строка
- QRegExp rexp("//\s?#define");
- bool off = line.count(rexp);
- //если да - раскомментировать
- if (off) {
- line.replace(rexp, "#define");
- }
- //вырезать комментарий в конце
- int commentPos = line.lastIndexOf("//");
- if (commentPos != -1) {
- line = line.left(commentPos);
- }
- //оставить только пару ключ-значение
- line.remove("#define");
- line = line.simplified();
- QStringList splitted = line.split(' ');
- QString key = splitted.first();
- if (splitted.size() > 1) {
- QString value = splitted.last();
- ConstType type = LINK;
- if (value.contains(QRegExp("^0?x[0-9a-fA-F]+$"))) {
- type = HEX;
- } else if (value.contains(QRegExp("^[0-9]+$"))) {
- type = DEC;
- }
- ConfigValue mConfigValue;
- mConfigValue.active = off;
- mConfigValue.line = pos;
- mConfigValue.key = key;
- mConfigValue.value = value;
- mConfigValues += mConfigValue;
- if (!off) {
- QVariant variant;
- switch (type) {
- case HEX:
- variant = value.toInt(0, 16);
- break;
- case DEC:
- variant = value.toInt();
- case LINK:
- variant = value;
- }
- config[key] = variant;
- }
- } else {
- config[key] = !off;
- }
- }
- pos++;
- }
- emit configChanged();
- file.close();
- //ищем в конфиге #define LOADER
- QVariant loader = config["LOADER"];
- //если нашли
- if (loader.isValid()) {
- //если он не закомментирован
- if (loader.toBool() == true) {
- const_cast<QString &>(initPath) = SCRIPT_PATH "initLoader.c";
- } else {
- const_cast<QString &>(initPath) = SCRIPT_PATH "initUnloader.c";
- }
- }
- }
- void Loader::initVariables() {
- foreach(const QString& variable, symbolTable.keys()) {
- const PropertyPtr prop = PropertyPtr(new QQmlProperty(this, variable));
- if (prop->isValid()) {
- variables.insert(variable, prop);
- prop->connectNotifySignal(this, SLOT(setVariable()));
- }
- }
- }
- void Loader::initConstants() {
- //регулярное выращение для поиска вещественных констант
- const QRegExp realVal(R"(^\s*[a-zA-Z]\w+\s*=\s*-?\d+\.\d{1,3}\s*\*\s*\d+("
- "\.\d{1,3});\s*(\/{2}.*)?$)");
- //регулярное выращение для поиска целочисленных констант
- const QRegExp intVal(R"(^\s*[a-zA-Z]\w+\s*=\s*-?\d+;\s*(\/{2}.*)?$)");
- //регулярное выражение для поиска целочисленного элемента массива
- const QRegExp intArr(
- R"(^\s*segments[A-Z]\w*\[\d+\]\s*=\s*-?\d+;\s*(\/{2}.*)?$)");
- //регулярное выражение для поиска вещественного элемента массива
- const QRegExp realArr(R"(^\s*segments[A-Z]\w*\[\d+\]\s*=\s*-?\d+\.\d{1,3}\s*"
- "\*\s*\d+(\.\d{1,3});\s*(\/{2}.*)?$)");
- QFile file(initPath);
- Q_ASSERT_X(file.exists(), "Loader::initConstants()",
- "Файл с константами не найден");
- QTextStream stream(&file);
- QStringList split;
- file.open(QIODevice::ReadOnly);
- while (!stream.atEnd()) {
- QString line = stream.readLine();
- initFile += line;
- bool isIntVal = line.contains(intVal);
- bool isRealVal = line.contains(realVal);
- bool isIntArr = line.contains(intArr);
- bool isRealArr = line.contains(realArr);
- bool isConstant = isIntVal || isRealVal || isIntArr || isRealArr;
- if (isConstant) {
- QString variable; //имя переменной
- QString constant; //константа
- QString factor; //множитель
- QString comment; //комментарий
- int spaceCount; //количество пробелов в начале
- //определить количество пробелов в начале строки
- QRegExp spaces(R"(^\s*)");
- spaces.indexIn(line);
- spaceCount = spaces.matchedLength();
- //определить содержание комментария, если есть
- int commentPos = line.indexOf("//");
- if (commentPos != -1) {
- int commentWidth = line.length() - commentPos - 2;
- comment = line.right(commentWidth);
- }
- //подготовить выражение для анализа
- line = line.left(line.indexOf(';')).simplified();
- split = line.split('=');
- //получить имя переменной
- variable = split.first().simplified();
- //если строка содержит целочисленную или вещественную константу
- {
- // если целочисленное
- if (isIntVal || isIntArr) {
- constant = split.last().simplified();
- }
- // если вещественное
- else if (isRealVal || isRealArr) {
- split = split.last().split('*');
- constant = split.first().simplified();
- factor = split.last().simplified();
- }
- //
- if (isIntVal || isRealVal || isIntArr) {
- QVariantMap constantElement;
- constantElement["position"] = initFile.length() - 1;
- constantElement["constant"] = constant;
- constantElement["factor"] = factor;
- constantElement["comment"] = comment;
- constantElement["spaces"] = spaceCount;
- constants.insert(variable, constantElement);
- if (isIntArr) {
- split = variable.split('[');
- variable = split.first().remove("segments");
- int index = split.last().remove(']').toInt();
- QVariantList list = segments[variable].toList();
- list.append(constant);
- segments[variable] = list;
- }
- }
- }
- }
- }
- file.close();
- }
- void Loader::initFunctions() {
- //главный объект qml, который умеет работать с переменными контроллера
- QJSValue qmlRoot = engine->newQObject(this);
- //функция, генерирующая функцию для управления контроллером
- QJSValue funcGenerator = engine->evaluate(
- "function(n,r){return function(){n.vgComplete=0;n.vgCall=r;for(var a in "
- "arguments){var "
- "t=arguments[a];n['vgParam'+ ++a]=t}}}");
- //функция, создающая в qml свойство-функцию
- QJSValue propertyCreator =
- engine->evaluate("function(obj, name, func) { "
- "Object.defineProperty(obj, name, {value : func}); }");
- foreach(QString funcName, functionTable.keys()) {
- //получить адрес функции
- QJSValue adress = functionTable.value(funcName);
- //подготовить список аргументов для функции-генератора
- QJSValueList args = { qmlRoot, adress };
- //сгенерировать функцию, для вызова функции контроллера
- QJSValue func = funcGenerator.call(args);
- funcName[0] = funcName.at(0).toLower();
- args = { qmlRoot, funcName, func };
- propertyCreator.call(args);
- }
- }
- void Loader::getVariable(const QString &name)
- {
- if (!variables.contains(name)) return;
- const PropertyPtr variable = variables[name];
- if (!variable.isNull()) {
- const int addr = symbolTable.value(name);
- const int prev = variable->read().toInt();
- const int val = vpu->valueByIndex(addr);
- if (prev != val) {
- variable->write(val);
- }
- }
- }
- void Loader::getVariables() {
- // чтобы отделить изменение переменных по сигналу
- // обновления от изменения вручную - на время
- // выставляем флаг updating
- updating = true;
- //хак, сперва обновить vgDevice и vgResult
- getVariable("vgDevice");
- getVariable("vgResult");
- // перебираем используемые переменные
- foreach(const QString & variable, variables.keys()) {
- getVariable(variable);
- }
- updating = false;
- }
- void Loader::setVariable() {
- // если переменная изменяется из qml
- if (!updating) {
- // перебираем все переменные в qml, связаные с контроллером
- foreach(const QString & variable, variables.keys()) {
- const PropertyPtr prop = variables[variable];
- // получить значение переменной из qml
- int value = prop->read().toInt();
- // получить значение переменной из контроллера
- int prev = vpu->valueByName(variable);
- // если отличаются - записать в контроллер
- if (value != prev) {
- vpu->setValueByName(variable, value);
- }
- }
- }
- }
- void Loader::saveInit() {
- SaveSegmentsInfo(initFile, segments, constants);
- foreach(const QString & variable, symbolTable.keys()) {
- if (constants.contains(variable)) {
- QVariantMap constant = constants.value(variable).toMap();
- QString strFactor = constant["factor"].toString();
- QString strConstant = constant["constant"].toString();
- double factor = (strFactor.isEmpty()) ? 1 : strFactor.toDouble();
- const int oldValue = strConstant.toDouble() * factor;
- const int newValue = vpu->valueByName(variable);
- if (newValue != oldValue) {
- QString value;
- if (factor == 1)
- value.setNum(newValue);
- else {
- const double x = newValue / factor;
- if (x == int(x)) {
- value.setNum(x, 'f', 1);
- } else {
- value.setNum(x);
- }
- // обновить константу в карте
- constant["constant"] = value;
- value.append(" * ");
- value.append(strFactor);
- }
- const int spaces = constant["spaces"].toInt();
- const QString comment = constant["comment"].toString();
- QString newLine = QString(spaces, ' ');
- newLine.append(variable);
- newLine.append(" = ");
- newLine.append(value);
- newLine.append(';');
- if (!comment.isEmpty()) {
- newLine.append(" //");
- newLine.append(comment);
- }
- const int pos = constant["position"].toInt();
- initFile[pos] = newLine;
- }
- }
- }
- //все записать в файл
- QFile file(initPath);
- QTextStream stream(&file);
- file.open(QIODevice::WriteOnly);
- stream << initFile.join('\n');
- file.close();
- }
- bool Loader::saveJson(QVariantMap settings, const QString &filePath) {
- QString fileName = filePath.split('/').last();
- QJsonDocument config;
- config.setObject(QJsonObject::fromVariantMap(settings));
- QByteArray rawConfig = config.toJson();
- // предупредить, если конфиг пустой
- if (config.isEmpty()) {
- QString debug_msg =
- QObject::tr("Config for export in file '%1' is empty").arg(fileName);
- qWarning() << debug_msg.toStdString().c_str();
- return false;
- }
- // предупредить, если файла не существует
- bool fileExists = QFile::exists(filePath);
- if (!fileExists) {
- QString debug_msg = QObject::tr("File '%1' is not exist").arg(fileName);
- qWarning() << debug_msg.toStdString().c_str();
- }
- // предупредить, если файл не удалось открыть
- QFile configFile(filePath);
- bool fileOpened = configFile.open(QIODevice::WriteOnly);
- if (!fileOpened) {
- QString debug_msg = QObject::tr("Cannot open file '%1'").arg(fileName);
- qWarning() << debug_msg.toStdString().c_str();
- return false;
- }
- // регулярка, соответствует числу с одним знаком после запятой, в кавычках
- // нужно убрать кавычки (чтобы при чтении считывалось как число, а не
- // строка)
- QRegExp rx(R"("\d +\.\d ")");
- QStringList strings = QString(rawConfig).split('\n');
- QStringList numbers;
- // поиск удовлетворяющих выражению строк
- foreach(QString str, strings) {
- int pos = rx.indexIn(str);
- if (pos > -1)
- numbers.append(rx.cap(0));
- }
- // удалить дубликаты
- numbers.removeDuplicates();
- // замены строк на обескавыченые
- foreach(QString number, numbers) {
- QString repl = number.mid(1, number.length() - 2);
- rawConfig.replace(number, qPrintable(repl));
- }
- int bytesWritten = configFile.write(rawConfig);
- configFile.close();
- if (bytesWritten != rawConfig.size()) {
- QString debug_msg =
- QObject::tr("Error: in file '%1' written %2 bytes of %3")
- .arg(fileName)
- .arg(bytesWritten)
- .arg(rawConfig.size());
- qWarning() << debug_msg.toStdString().c_str();
- return false;
- }
- return true;
- }
- QVariantMap Loader::parseJson(const QString &filePath) {
- QString fileName = filePath.split('/').last();
- QVariantMap result;
- QString errMsg;
- bool fileExists = QFile::exists(filePath);
- if (!fileExists) {
- errMsg = QObject::tr("File '%1' not exist").arg(fileName);
- qDebug() << qPrintable(errMsg);
- return result;
- }
- QFile configFile(filePath);
- bool fileOpen = configFile.open(QIODevice::ReadOnly | QIODevice::Text);
- if (!fileOpen) {
- errMsg = QObject::tr("File '%1' cannot be open").arg(fileName);
- qDebug() << qPrintable(errMsg);
- return result;
- }
- QByteArray rawConfig = configFile.readAll();
- configFile.close();
- QJsonParseError parseError;
- QJsonDocument config = QJsonDocument::fromJson(rawConfig, &parseError);
- bool parseOk = parseError.error == QJsonParseError::NoError;
- if (!parseOk) {
- QString errMsg =
- QObject::tr("File '%1': parse error '%2' in char position %3")
- .arg(fileName)
- .arg(parseError.errorString())
- .arg(parseError.offset);
- qDebug() << qPrintable(errMsg);
- return result;
- }
- if (config.isEmpty()) {
- errMsg = QObject::tr("File '%1': empty config").arg(fileName);
- qDebug() << qPrintable(errMsg);
- return result;
- }
- if (!config.isObject()) {
- errMsg = QObject::tr("File '%1': not object").arg(fileName);
- qDebug() << qPrintable(errMsg);
- return result;
- }
- result = config.object().toVariantMap();
- return result;
- }
- void Loader::mouseMoveEvent(QMouseEvent *event) {
- int x = event->x();
- int y = event->y();
- if (mouseX != x) {
- mouseX = x;
- emit mouseXChanged();
- }
- if (mouseY != y) {
- mouseY = y;
- emit mouseYChanged();
- }
- QQuickWindow::mousePressEvent(event);
- }
- void SaveSegmentsInfo(QStringList &lines, const QVariantMap &segments,
- const QVariantMap &constants) {
- const int segmentCount = segments.value("Id").toList().length();
- const QStringList segmentParams = { "AddWidth", "LoadSpeed", "MoveSpeed",
- "TransferSpeed" };
- foreach(const QString & param, segmentParams) {
- for (int i = 0; i < segmentCount; i++) {
- const QString variable = "segments" + param + QString("[%1]").arg(i);
- const int value = segments.value(param).toList().at(i).toString().toInt();
- const QVariantMap constant = constants.value(variable).toMap();
- const QString comment = constant["comment"].toString();
- const int spaces = constant["spaces"].toInt();
- const int pos = constant["position"].toInt();
- QString newLine = QString(spaces, ' ');
- newLine += variable;
- newLine += " = ";
- newLine += QString::number(value);
- newLine += ';';
- if (!comment.isEmpty()) {
- newLine += " //";
- newLine += comment;
- }
- lines[pos] = newLine;
- }
- }
- }
Add Comment
Please, Sign In to add comment