From 60e2f730df44d1d7ae476e3ae48d9c02b551e566 Mon Sep 17 00:00:00 2001 From: raspopov Date: Fri, 3 Jul 2026 17:24:09 +0300 Subject: [PATCH] Fix project file version 1.x compatibility. Fixes #116. --- src/appproject.cpp | 12 ++ src/controls/outputtypes.h | 20 +-- src/displaydefinition.h | 4 +- src/formdataview.cpp | 329 +++++++++++++++++++++++++++++++++++++ src/formdataview.h | 253 +--------------------------- src/formscriptview.cpp | 2 +- src/formscriptview.h | 3 +- src/mainwindow.cpp | 1 + src/mainwindow.h | 3 +- 9 files changed, 364 insertions(+), 263 deletions(-) diff --git a/src/appproject.cpp b/src/appproject.cpp index fd5584f2..7449a48d 100644 --- a/src/appproject.cpp +++ b/src/appproject.cpp @@ -1792,6 +1792,10 @@ void AppProject::loadProject(const QString& filename) bool isForm = true; if (xml.name() == QLatin1String("FormDataView")) { kind = ProjectFormKind::Data; + // Version 1.x multi-view project + } else if (xml.name() == QLatin1String("FormModSim")) { + kind = ProjectFormKind::Data; + _mainWindow->setViewMode(viewMode = QMdiArea::SubWindowView); } else if (xml.name() == QLatin1String("FormTrafficView")) { kind = ProjectFormKind::Traffic; } else if (xml.name() == QLatin1String("FormScriptView")) { @@ -1943,6 +1947,14 @@ void AppProject::loadProject(const QString& filename) } } } + // Version 1.x single view project + else if (xml.name() == QLatin1String("FormModSim")) { + _mainWindow->setViewMode(viewMode = QMdiArea::SubWindowView); + if (const auto frm = createMdiChild(ProjectFormKind::Data)) { + loadXmlOfForm(frm, xml); + frm->show(); + } + } else { xml.skipCurrentElement(); } diff --git a/src/controls/outputtypes.h b/src/controls/outputtypes.h index 70d858ec..883b3980 100644 --- a/src/controls/outputtypes.h +++ b/src/controls/outputtypes.h @@ -229,17 +229,17 @@ inline QXmlStreamReader& operator>>(QXmlStreamReader& in, AddressColorMap& map) if (in.name() == QLatin1String("Color")) { const auto attributes = in.attributes(); bool ok; - const auto device_id = static_cast(attributes.value("DeviceId").toUShort(&ok)); + auto device_id = static_cast(attributes.value("DeviceId").toUShort(&ok)); + if (!ok) + device_id = 0; // use current view device id + auto type = static_cast(attributes.value("Type").toInt(&ok)); + if (!ok) + type = QModbusDataUnit::RegisterType::Invalid; // use current view type + const auto address = attributes.value("Address").toUShort(&ok); if (ok) { - const auto type = static_cast(attributes.value("Type").toInt(&ok)); - if (ok) { - const auto address = attributes.value("Address").toUShort(&ok); - if (ok) { - const auto value = attributes.value("Value").toString(); - if (!value.isEmpty()) - map.insert({ device_id, type, address }, value); - } - } + const auto value = attributes.value("Value").toString(); + if (!value.isEmpty()) + map.insert({ device_id, type, address }, value); } } in.skipCurrentElement(); diff --git a/src/displaydefinition.h b/src/displaydefinition.h index 7ca234b9..28e45df3 100644 --- a/src/displaydefinition.h +++ b/src/displaydefinition.h @@ -290,7 +290,9 @@ inline QXmlStreamWriter& operator <<(QXmlStreamWriter& xml, const ScriptViewDefi /// inline QXmlStreamReader& operator >>(QXmlStreamReader& xml, DataViewDefinitions& dd) { - if (xml.isStartElement() && xml.name() == QLatin1String("DataViewDefinitions")) { + if (xml.isStartElement() && (xml.name() == QLatin1String("DataViewDefinitions") || + // Version 1.x definitions + xml.name() == QLatin1String("DisplayDefinition"))) { const QXmlStreamAttributes attributes = xml.attributes(); if (attributes.hasAttribute("FormName")) { diff --git a/src/formdataview.cpp b/src/formdataview.cpp index a1e40eb0..d22879fe 100644 --- a/src/formdataview.cpp +++ b/src/formdataview.cpp @@ -162,6 +162,15 @@ FormDataView::~FormDataView() delete ui; } +/// +/// \brief FormDataView::project +/// \return +/// +AppProject* FormDataView::project() const noexcept +{ + return _parent->project(); +} + /// /// \brief FormDataView::saveSettings /// \param out @@ -1327,3 +1336,323 @@ void FormDataView::updateDisplayBar() updateSettingsControls(); } + +/// +/// \brief operator << +/// \param xml +/// \param frm +/// \return +/// +inline QXmlStreamWriter& operator <<(QXmlStreamWriter& xml, FormDataView* frm) +{ + if (!frm) return xml; + + xml.writeStartElement("FormDataView"); + + const auto panel = frm->property("SplitPanel").toString(); + if(!panel.isEmpty()) + xml.writeAttribute("Panel", panel); + xml.writeAttribute("Title", frm->windowTitle()); + if(frm->property("SplitAutoClone").toBool()) + xml.writeAttribute("AutoClone", "1"); + if(frm->property("Closed").toBool()) + xml.writeAttribute("Closed", "1"); + xml.writeAttribute("DataType", enumToString(frm->dataType())); + xml.writeAttribute("RegisterOrder", enumToString(frm->registerOrder())); + xml.writeAttribute("Codepage", frm->codepage()); + xml.writeAttribute("ByteOrder", enumToString(frm->byteOrder())); + + const auto wnd = frm->parentWidget(); + xml.writeStartElement("Window"); + xml.writeAttribute("Maximized", boolToString(wnd->isMaximized())); + xml.writeAttribute("Minimized", boolToString(wnd->isMinimized())); + + const auto windowPos = wnd->pos(); + xml.writeAttribute("Left", QString::number(windowPos.x())); + xml.writeAttribute("Top", QString::number(windowPos.y())); + + const auto windowSize = (wnd->isMinimized() || wnd->isMaximized()) ? wnd->sizeHint() : wnd->size(); + xml.writeAttribute("Width", QString::number(windowSize.width())); + xml.writeAttribute("Height", QString::number(windowSize.height())); + xml.writeEndElement(); + + const auto dd = frm->displayDefinition(); + xml.writeStartElement("DataViewDefinitions"); + xml.writeAttribute("DeviceId", QString::number(dd.DeviceId)); + xml.writeAttribute("PointType", enumToString(dd.PointType)); + xml.writeAttribute("PointAddress", QString::number(dd.PointAddress)); + xml.writeAttribute("Length", QString::number(dd.Length)); + xml.writeAttribute("DataViewColumnsDistance", QString::number(dd.DataViewColumnsDistance)); + xml.writeAttribute("LeadingZeros", boolToString(dd.LeadingZeros)); + xml.writeEndElement(); + + xml << frm->colorMap(); + + xml.writeEndElement(); // FormDataView + + return xml; +} + +/// +/// \brief operator >> +/// \param xml +/// \param frm +/// \return +/// +QXmlStreamReader& operator >>(QXmlStreamReader& xml, FormDataView* frm) +{ + if (!frm) return xml; + + if (xml.isStartElement() && (xml.name() == QLatin1String("FormDataView") || + // Version 1.x data view + xml.name() == QLatin1String("FormModSim"))) { + DataType dataType = DataType::UInt16; + RegisterOrder regOrder = RegisterOrder::MSRF; + DataViewDefinitions dd; + QHash data; + QHash simulations; + + // Version 1.x script view + FormScriptView * script = nullptr; + ScriptViewDefinitions script_dd; + + const QXmlStreamAttributes attributes = xml.attributes(); + const QString formTitle = attributes.value("Title").toString(); + + if (attributes.hasAttribute("DataType")) { + dataType = enumFromString(attributes.value("DataType").toString(), DataType::UInt16); + } + + // Version 1.x data type + if (attributes.hasAttribute("DataDisplayMode")) { + dataType = enumFromString(attributes.value("DataDisplayMode").toString(), DataType::UInt16); + } + + if (attributes.hasAttribute("RegisterOrder")) { + regOrder = enumFromString(attributes.value("RegisterOrder").toString(), RegisterOrder::MSRF); + } + + if (attributes.hasAttribute("Codepage")) { + frm->setCodepage(attributes.value("Codepage").toString()); + } + + if (attributes.hasAttribute("ByteOrder")) { + const ByteOrder order = enumFromString(attributes.value("ByteOrder").toString()); + frm->setByteOrder(order); + } + + while (xml.readNextStartElement()) { + if (xml.name() == QLatin1String("Window")) { + const QXmlStreamAttributes windowAttrs = xml.attributes(); + + const auto wnd = frm->parentWidget(); + if (wnd) { + if(windowAttrs.hasAttribute("Left") && windowAttrs.hasAttribute("Top")) { + bool okLeft, okTop; + const int left = windowAttrs.value("Left").toInt(&okLeft); + const int top = windowAttrs.value("Top").toInt(&okTop); + if(okLeft && okTop) { + wnd->move(left, top); + } + } + + if (windowAttrs.hasAttribute("Width") && windowAttrs.hasAttribute("Height")) { + bool okWidth, okHeight; + const int width = windowAttrs.value("Width").toInt(&okWidth); + const int height = windowAttrs.value("Height").toInt(&okHeight); + + if (okWidth && okHeight && !wnd->isMaximized() && !wnd->isMinimized()) { + wnd->resize(width, height); + } + } + + if (windowAttrs.hasAttribute("Maximized")) { + const bool maximized = stringToBool(windowAttrs.value("Maximized").toString()); + if (maximized) wnd->showMaximized(); + } + + if (windowAttrs.hasAttribute("Minimized")) { + const bool minimized = stringToBool(windowAttrs.value("Minimized").toString()); + if (minimized) wnd->showMinimized(); + } + + + } + xml.skipCurrentElement(); + } + else if (xml.name() == QLatin1String("DataViewDefinitions")) { + xml >> dd; + xml.skipCurrentElement(); + if (dd.FormName.isEmpty() && !formTitle.isEmpty()) + dd.FormName = formTitle; + frm->setDisplayDefinition(dd); + } + // Version 1.x definitions + else if (xml.name() == QLatin1String("DisplayDefinition")) { + const auto attributes = xml.attributes(); + xml >> dd; + xml.skipCurrentElement(); + + // Reload PointAddress since it may be wrongly normalized from 0 to 1 + if (attributes.hasAttribute("PointAddress")) { + dd.PointAddress = attributes.value("PointAddress").toUShort(); + } + if (attributes.hasAttribute("ZeroBasedAddress")) { + if (stringToBool(attributes.value("ZeroBasedAddress").toString())) { + frm->setAddressBase(AddressBase::Base0); + } else { + frm->setAddressBase(AddressBase::Base1); + } + } + + frm->setDisplayDefinition(dd); + } + // Version 1.x simulation map + else if (xml.name() == QLatin1String("ModbusSimulationMap")) { + while (xml.readNextStartElement()) { + if (xml.name() == QLatin1String("Simulation")) { + + const QXmlStreamAttributes attributes = xml.attributes(); + bool ok; const quint16 address = attributes.value("Address").toUShort(&ok); + + if(ok) { + xml.readNextStartElement(); + + ModbusSimulationParams params; + xml >> params; + + simulations[address] = params; + } + + xml.skipCurrentElement(); + + } else { + xml.skipCurrentElement(); + } + } + } + // Version 1.x script control + else if (xml.name() == QLatin1String("JScriptControl")) { + if (script = static_cast(frm->project()->createMdiChild(ProjectFormKind::Script))) { + xml >> script->scriptControl(); + } else { + xml.skipCurrentElement(); + } + } + // Version 1.x script settings + else if (xml.name() == QLatin1String("ScriptSettings")) { + xml >> script_dd.ScriptCfg; + } + else if (xml.name() == QLatin1String("AddressDescriptionMap")) { + AddressDescriptionMap map; + xml >> map; + for(auto it = map.cbegin(); it != map.cend(); ++it) + { + const auto device_id = it.key().DeviceId; + const auto type = it.key().Type; + frm->setDescription(device_id ? device_id : dd.DeviceId, type ? type : dd.PointType, it.key().Address, it.value()); + } + } + else if (xml.name() == QLatin1String("AddressColorMap")) { + AddressColorMap map; + xml >> map; + for(auto it = map.cbegin(); it != map.cend(); ++it) + { + const auto device_id = it.key().DeviceId; + const auto type = it.key().Type; + frm->setColor(device_id ? device_id : dd.DeviceId, type ? type : dd.PointType, it.key().Address, it.value()); + } + } + // Version 1.x data units + else if (xml.name() == QLatin1String("ModbusDataUnit")) { + while (xml.readNextStartElement()) { + if (xml.name() == QLatin1String("Value")) { + QXmlStreamAttributes attributes = xml.attributes(); + bool ok; const quint16 address = attributes.value("Address").toUShort(&ok); + if(ok) { + const quint16 value = xml.readElementText().toUShort(&ok); + if (ok) { + data[address] = value; + } + } + } else { + xml.skipCurrentElement(); + } + } + } + else { + xml.skipCurrentElement(); + } + } + + if(dd.PointType != QModbusDataUnit::Invalid) { + frm->setDataType(dataType); + frm->setRegisterOrder(regOrder); + + // Version 1.x simulation map + if(!simulations.isEmpty()) { + QHashIterator it(simulations); + while(it.hasNext()) { + const auto item = it.next(); + switch(dd.PointType) { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + if(item->Mode == SimulationMode::Toggle || item->Mode == SimulationMode::Random) + frm->startSimulation(dd.PointType, item.key() - (frm->zeroBasedAddress() ? 0 : 1), item.value()); + break; + case QModbusDataUnit::InputRegisters: + case QModbusDataUnit::HoldingRegisters: + if(item->Mode != SimulationMode::Off && item->Mode != SimulationMode::Toggle) + frm->startSimulation(dd.PointType, item.key() - (frm->zeroBasedAddress() ? 0 : 1), item.value()); + break; + default: break; + } + } + } + + // Version 1.x data units + if (!data.isEmpty()) { + QVector values(dd.Length); + + QHashIterator it(data); + while(it.hasNext()) { + const auto item = it.next(); + const auto index = item.key() - dd.PointAddress; + switch(dd.PointType) { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + values[index] = qBound(0, item.value(), 1); + break; + case QModbusDataUnit::InputRegisters: + case QModbusDataUnit::HoldingRegisters: + values[index] = item.value(); + break; + default: break; + } + if(index >= values.length()) break; + } + + frm->configureModbusDataUnit(dd.DeviceId, dd.PointType, dd.PointAddress - (frm->zeroBasedAddress() ? 0 : 1), values); + } + } + + // Version 1.x script + if (script) { + script_dd.FormName = frm->windowTitle(); // the same title as data view + script_dd.normalize(); + script->setDefinitions(script_dd); + script->setFont(AppPreferences::instance().scriptFont()); + + frm->project()->closeMdiChild(script); // script view hidden by default + + if (script_dd.ScriptCfg.RunOnStartup) { + script->runScript(); + } + } + } + else { + xml.skipCurrentElement(); + } + + return xml; +} diff --git a/src/formdataview.h b/src/formdataview.h index ec641750..8e731ad4 100644 --- a/src/formdataview.h +++ b/src/formdataview.h @@ -27,6 +27,7 @@ /// class MainWindow; class FindReplaceBar; +class AppProject; namespace Ui { class FormDataView; @@ -49,6 +50,8 @@ class FormDataView : public QWidget explicit FormDataView(ModbusMultiServer& server, DataSimulator* simulator, MainWindow* parent); ~FormDataView(); + AppProject* project() const noexcept; + QVector data() const; DataViewDefinitions displayDefinition() const; @@ -267,55 +270,7 @@ inline QSettings& operator >>(QSettings& in, FormDataView* frm) /// \param frm /// \return /// -inline QXmlStreamWriter& operator <<(QXmlStreamWriter& xml, FormDataView* frm) -{ - if (!frm) return xml; - - xml.writeStartElement("FormDataView"); - - const auto panel = frm->property("SplitPanel").toString(); - if(!panel.isEmpty()) - xml.writeAttribute("Panel", panel); - xml.writeAttribute("Title", frm->windowTitle()); - if(frm->property("SplitAutoClone").toBool()) - xml.writeAttribute("AutoClone", "1"); - if(frm->property("Closed").toBool()) - xml.writeAttribute("Closed", "1"); - xml.writeAttribute("DataType", enumToString(frm->dataType())); - xml.writeAttribute("RegisterOrder", enumToString(frm->registerOrder())); - xml.writeAttribute("Codepage", frm->codepage()); - xml.writeAttribute("ByteOrder", enumToString(frm->byteOrder())); - - const auto wnd = frm->parentWidget(); - xml.writeStartElement("Window"); - xml.writeAttribute("Maximized", boolToString(wnd->isMaximized())); - xml.writeAttribute("Minimized", boolToString(wnd->isMinimized())); - - const auto windowPos = wnd->pos(); - xml.writeAttribute("Left", QString::number(windowPos.x())); - xml.writeAttribute("Top", QString::number(windowPos.y())); - - const auto windowSize = (wnd->isMinimized() || wnd->isMaximized()) ? wnd->sizeHint() : wnd->size(); - xml.writeAttribute("Width", QString::number(windowSize.width())); - xml.writeAttribute("Height", QString::number(windowSize.height())); - xml.writeEndElement(); - - const auto dd = frm->displayDefinition(); - xml.writeStartElement("DataViewDefinitions"); - xml.writeAttribute("DeviceId", QString::number(dd.DeviceId)); - xml.writeAttribute("PointType", enumToString(dd.PointType)); - xml.writeAttribute("PointAddress", QString::number(dd.PointAddress)); - xml.writeAttribute("Length", QString::number(dd.Length)); - xml.writeAttribute("DataViewColumnsDistance", QString::number(dd.DataViewColumnsDistance)); - xml.writeAttribute("LeadingZeros", boolToString(dd.LeadingZeros)); - xml.writeEndElement(); - - xml << frm->colorMap(); - - xml.writeEndElement(); // FormDataView - - return xml; -} +QXmlStreamWriter& operator <<(QXmlStreamWriter& xml, FormDataView* frm); /// /// \brief operator >> @@ -323,205 +278,7 @@ inline QXmlStreamWriter& operator <<(QXmlStreamWriter& xml, FormDataView* frm) /// \param frm /// \return /// -inline QXmlStreamReader& operator >>(QXmlStreamReader& xml, FormDataView* frm) -{ - if (!frm) return xml; - - if (xml.isStartElement() && xml.name() == QLatin1String("FormDataView")) { - DataType dataType = DataType::UInt16; - RegisterOrder regOrder = RegisterOrder::MSRF; - DataViewDefinitions dd; - QHash data; - QHash simulations; - - const QXmlStreamAttributes attributes = xml.attributes(); - const QString formTitle = attributes.value("Title").toString(); - - if (attributes.hasAttribute("DataType")) { - dataType = enumFromString(attributes.value("DataType").toString(), DataType::UInt16); - } - - if (attributes.hasAttribute("RegisterOrder")) { - regOrder = enumFromString(attributes.value("RegisterOrder").toString(), RegisterOrder::MSRF); - } - - if (attributes.hasAttribute("Codepage")) { - frm->setCodepage(attributes.value("Codepage").toString()); - } - - if (attributes.hasAttribute("ByteOrder")) { - const ByteOrder order = enumFromString(attributes.value("ByteOrder").toString()); - frm->setByteOrder(order); - } - - while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("Window")) { - const QXmlStreamAttributes windowAttrs = xml.attributes(); - - const auto wnd = frm->parentWidget(); - if (wnd) { - if(windowAttrs.hasAttribute("Left") && windowAttrs.hasAttribute("Top")) { - bool okLeft, okTop; - const int left = windowAttrs.value("Left").toInt(&okLeft); - const int top = windowAttrs.value("Top").toInt(&okTop); - if(okLeft && okTop) { - wnd->move(left, top); - } - } - - if (windowAttrs.hasAttribute("Width") && windowAttrs.hasAttribute("Height")) { - bool okWidth, okHeight; - const int width = windowAttrs.value("Width").toInt(&okWidth); - const int height = windowAttrs.value("Height").toInt(&okHeight); - - if (okWidth && okHeight && !wnd->isMaximized() && !wnd->isMinimized()) { - wnd->resize(width, height); - } - } - - if (windowAttrs.hasAttribute("Maximized")) { - const bool maximized = stringToBool(windowAttrs.value("Maximized").toString()); - if (maximized) wnd->showMaximized(); - } - - if (windowAttrs.hasAttribute("Minimized")) { - const bool minimized = stringToBool(windowAttrs.value("Minimized").toString()); - if (minimized) wnd->showMinimized(); - } - - - } - xml.skipCurrentElement(); - } - else if (xml.name() == QLatin1String("DataViewDefinitions")) { - xml >> dd; - xml.skipCurrentElement(); - if (dd.FormName.isEmpty() && !formTitle.isEmpty()) - dd.FormName = formTitle; - frm->setDisplayDefinition(dd); - } - else if (xml.name() == QLatin1String("ModbusSimulationMap")) { - while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("Simulation")) { - - const QXmlStreamAttributes attributes = xml.attributes(); - bool ok; const quint16 address = attributes.value("Address").toUShort(&ok); - - if(ok) { - xml.readNextStartElement(); - - ModbusSimulationParams params; - xml >> params; - - simulations[address] = params; - } - - xml.skipCurrentElement(); - - } else { - xml.skipCurrentElement(); - } - } - } - else if (xml.name() == QLatin1String("JScriptControl")) { - xml.skipCurrentElement(); - } - else if (xml.name() == QLatin1String("AddressDescriptionMap")) { - AddressDescriptionMap map; - xml >> map; - for(auto it = map.cbegin(); it != map.cend(); ++it) - { - const auto device_id = it.key().DeviceId; - const auto type = it.key().Type; - frm->setDescription(device_id ? device_id : dd.DeviceId, type ? type : dd.PointType, it.key().Address, it.value()); - } - } - else if (xml.name() == QLatin1String("AddressColorMap")) { - AddressColorMap map; - xml >> map; - for(auto it = map.cbegin(); it != map.cend(); ++it) - { - const auto device_id = it.key().DeviceId; - const auto type = it.key().Type; - frm->setColor(device_id ? device_id : dd.DeviceId, type ? type : dd.PointType, it.key().Address, it.value()); - } - } - else if (xml.name() == QLatin1String("ModbusDataUnit")) { - while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("Value")) { - QXmlStreamAttributes attributes = xml.attributes(); - bool ok; const quint16 address = attributes.value("Address").toUShort(&ok); - if(ok) { - const quint16 value = xml.readElementText().toUShort(&ok); - if (ok) { - data[address] = value; - } - } - } else { - xml.skipCurrentElement(); - } - } - } - else { - xml.skipCurrentElement(); - } - } - - if(dd.PointType != QModbusDataUnit::Invalid) { - frm->setDataType(dataType); - frm->setRegisterOrder(regOrder); - - if(!simulations.isEmpty()) { - QHashIterator it(simulations); - while(it.hasNext()) { - const auto item = it.next(); - switch(dd.PointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - if(item->Mode == SimulationMode::Toggle || item->Mode == SimulationMode::Random) - frm->startSimulation(dd.PointType, item.key() - (frm->zeroBasedAddress() ? 0 : 1), item.value()); - break; - case QModbusDataUnit::InputRegisters: - case QModbusDataUnit::HoldingRegisters: - if(item->Mode != SimulationMode::Off && item->Mode != SimulationMode::Toggle) - frm->startSimulation(dd.PointType, item.key() - (frm->zeroBasedAddress() ? 0 : 1), item.value()); - break; - default: break; - } - } - } - - if (!data.isEmpty()) { - QVector values(dd.Length); - - QHashIterator it(data); - while(it.hasNext()) { - const auto item = it.next(); - const auto index = item.key() - dd.PointAddress; - switch(dd.PointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - values[index] = qBound(0, item.value(), 1); - break; - case QModbusDataUnit::InputRegisters: - case QModbusDataUnit::HoldingRegisters: - values[index] = item.value(); - break; - default: break; - } - if(index >= values.length()) break; - } - - frm->configureModbusDataUnit(dd.DeviceId, dd.PointType, dd.PointAddress - (frm->zeroBasedAddress() ? 0 : 1), values); - } - } - } - else { - xml.skipCurrentElement(); - } - - return xml; -} +QXmlStreamReader& operator >>(QXmlStreamReader& xml, FormDataView* frm); #endif // FORMDATAVIEW_H diff --git a/src/formscriptview.cpp b/src/formscriptview.cpp index 169d71c5..6f22947f 100644 --- a/src/formscriptview.cpp +++ b/src/formscriptview.cpp @@ -483,7 +483,7 @@ void FormScriptView::linkRunStopTo(FormScriptView* master) /// \brief FormScriptView::scriptControl /// \return /// -JScriptControl* FormScriptView::scriptControl() +JScriptControl* FormScriptView::scriptControl() const noexcept { return ui->scriptControl; } diff --git a/src/formscriptview.h b/src/formscriptview.h index 20c10cb6..c2ef957f 100644 --- a/src/formscriptview.h +++ b/src/formscriptview.h @@ -65,6 +65,7 @@ class FormScriptView : public QWidget void setScript(const QString& text); QTextDocument* scriptDocument() const; void setScriptDocument(QTextDocument* document); + JScriptControl* scriptControl() const noexcept; int scriptCursorPosition() const; void setScriptCursorPosition(int pos); @@ -131,8 +132,6 @@ public slots: void consoleMessage(const QString& source, const QString& text, ConsoleOutput::MessageType type); private: - JScriptControl* scriptControl(); - void setupScriptBar(); void updateScriptBar(); void updateScriptBarToolTips(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cebf3694..b35cbacc 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -929,6 +929,7 @@ void MainWindow::on_actionOpenProject_triggered() { QStringList filters; filters << tr("Project files (*.omsim)"); + filters << tr("Project 1.x files (*.xml)"); filters << tr("All files (*)"); const auto filename = QFileDialog::getOpenFileName(this, QString(), _project->savePath(), filters.join(";;")); diff --git a/src/mainwindow.h b/src/mainwindow.h index 0330747c..bbd1caf3 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -60,6 +60,7 @@ class MainWindow : public QMainWindow void loadProject(const QString& filename); bool saveProject(const QString& filename); + inline AppProject* project() const noexcept { return _project; } void appendConsoleMessage(const QString& source, const QString& text, ConsoleOutput::MessageType type); void showOutputConsole(); @@ -84,7 +85,7 @@ public slots: void windowActivate(QMdiSubWindow* wnd); void updateHelpWidgetState(); void markModified(); - + private slots: void on_awake();