Bug Summary

File:OMEdit/OMEditLIB/Plotting/VariablesWidget.cpp
Warning:line 475, column 104
Called C++ object pointer is null

Annotated Source Code

[?] Use j/k keys for keyboard navigation

1/*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
14 * ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the Open Source Modelica
17 * Consortium (OSMC) Public License (OSMC-PL) are obtained
18 * from OSMC, either from the above address,
19 * from the URLs: http://www.ida.liu.se/projects/OpenModelica or
20 * http://www.openmodelica.org, and in the OpenModelica distribution.
21 * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
22 *
23 * This program is distributed WITHOUT ANY WARRANTY; without
24 * even the implied warranty of MERCHANTABILITY or FITNESS
25 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
26 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
27 *
28 * See the full OSMC Public License conditions for more details.
29 *
30 */
31/*
32 * @author Adeel Asghar <adeel.asghar@liu.se>
33 */
34
35#include "VariablesWidget.h"
36#include "MainWindow.h"
37#include "OMC/OMCProxy.h"
38#include "Modeling/ModelWidgetContainer.h"
39#include "Modeling/ItemDelegate.h"
40#include "Options/OptionsDialog.h"
41#include "Modeling/MessagesWidget.h"
42#include "util/read_matlab4.h"
43#include "Plotting/PlotWindowContainer.h"
44#include "Plotting/DiagramWindow.h"
45#include "Simulation/SimulationDialog.h"
46#include "Simulation/SimulationOutputWidget.h"
47#include "Simulation/SimulationProcessThread.h"
48#include "TransformationalDebugger/TransformationsWidget.h"
49
50#include <qjson/parser.h>
51
52#include <QObject>
53
54using namespace OMPlot;
55
56namespace VariableItemData {
57 enum VariableItemData {
58 FILEPATH=0,
59 FILENAME,
60 NAME,
61 DISPLAYNAME,
62 VALUE,
63 UNIT,
64 DISPLAYUNIT,
65 DISPLAYUNITS,
66 DESCRIPTION,
67 TOOLTIP,
68 ISMAINARRAY,
69 USES,
70 INITIAL_USES,
71 DEFINED_IN,
72 INFOFILE
73 };
74}
75
76/*!
77 * \class VariablesTreeItem
78 * \brief Contains the information about the result variable.
79 */
80/*!
81 * \param variableItemData - a list of items.\n
82 * 0 -> filePath\n
83 * 1 -> fileName\n
84 * 2 -> name\n
85 * 3 -> displayName\n
86 * 4 -> value\n
87 * 5 -> unit\n
88 * 6 -> displayUnit\n
89 * 7 -> displayUnits (QStringList)\n
90 * 8 -> description\n
91 * 9 -> tooltip\n
92 * 10 -> isMainArray
93 */
94VariablesTreeItem::VariablesTreeItem(const QVector<QVariant> &variableItemData, VariablesTreeItem *pParent, bool isRootItem)
95{
96 mpParentVariablesTreeItem = pParent;
97 mIsRootItem = isRootItem;
98 mFilePath = variableItemData[VariableItemData::FILEPATH].toString();
99 mFileName = variableItemData[VariableItemData::FILENAME].toString();
100 mVariableName = variableItemData[VariableItemData::NAME].toString();
101 mDisplayVariableName = variableItemData[VariableItemData::DISPLAYNAME].toString();
102 mValue = variableItemData[VariableItemData::VALUE].toString();
103 mValueChanged = false;
104 mUnit = variableItemData[VariableItemData::UNIT].toString();
105 mDisplayUnit = variableItemData[VariableItemData::DISPLAYUNIT].toString();
106 mPreviousUnit = variableItemData[VariableItemData::DISPLAYUNIT].toString();
107 mDisplayUnits = variableItemData[VariableItemData::DISPLAYUNITS].toStringList();
108 mDescription = variableItemData[VariableItemData::DESCRIPTION].toString();
109 mToolTip = variableItemData[VariableItemData::TOOLTIP].toString();
110 mChecked = false;
111 mEditable = false;
112 mVariability = "";
113 mIsMainArray = variableItemData[VariableItemData::ISMAINARRAY].toBool();
114 mActive = false;
115 mUses = variableItemData[VariableItemData::USES].toStringList();
116 mInitialUses = variableItemData[VariableItemData::INITIAL_USES].toStringList();
117
118 foreach(QVariant var, variableItemData[VariableItemData::DEFINED_IN].toList())for (auto _container_ = QtPrivate::qMakeForeachContainer(variableItemData
[VariableItemData::DEFINED_IN].toList()); _container_.control
&& _container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (QVariant var = *_container_.i; _container_
.control; _container_.control = 0)
119 {
120 mDefinedIn << var.value<IntStringPair>();
121 }
122 mInfoFileName = variableItemData[VariableItemData::INFOFILE].toString();
123}
124
125VariablesTreeItem::~VariablesTreeItem()
126{
127 qDeleteAll(mChildren);
128 mChildren.clear();
129}
130
131QString VariablesTreeItem::getPlotVariable()
132{
133 return QString(mVariableName).remove(0, mFileName.length() + 1);
134}
135
136/*!
137 * \brief VariablesTreeItem::setActive
138 * Sets all the VariablesTreeItems inactive except this one.
139 */
140void VariablesTreeItem::setActive()
141{
142 VariablesTreeItem *pRootVariablesTreeItem;
143 pRootVariablesTreeItem = MainWindow::instance()->getVariablesWidget()->getVariablesTreeModel()->getRootVariablesTreeItem();
144 for (int i = 0 ; i < pRootVariablesTreeItem->getChildren().size() ; i++) {
145 VariablesTreeItem *pVariablesTreeItem = pRootVariablesTreeItem->child(i);
146 if (pVariablesTreeItem) {
147 if (pVariablesTreeItem != this) {
148 pVariablesTreeItem->mActive = false;
149 }
150 }
151 }
152 // set VariablesTreeView to active.
153 mActive = true;
154 MainWindow::instance()->getVariablesWidget()->initializeVisualization(mSimulationOptions);
155}
156
157QIcon VariablesTreeItem::getVariableTreeItemIcon(QString name) const
158{
159 if (name.endsWith(".mat"))
160 return QIcon(":/Resources/icons/mat.svg");
161 else if (name.endsWith(".plt"))
162 return QIcon(":/Resources/icons/plt.svg");
163 else if (name.endsWith(".csv"))
164 return QIcon(":/Resources/icons/csv.svg");
165 else
166 return QIcon(":/Resources/icons/interaction.svg");
167}
168
169void VariablesTreeItem::insertChild(int position, VariablesTreeItem *pVariablesTreeItem)
170{
171 mChildren.insert(position, pVariablesTreeItem);
172}
173
174VariablesTreeItem* VariablesTreeItem::child(int row)
175{
176 return mChildren.value(row);
177}
178
179void VariablesTreeItem::removeChildren()
180{
181 qDeleteAll(mChildren);
182 mChildren.clear();
183}
184
185void VariablesTreeItem::removeChild(VariablesTreeItem *pVariablesTreeItem)
186{
187 mChildren.removeOne(pVariablesTreeItem);
188}
189
190int VariablesTreeItem::columnCount() const
191{
192 return 5;
193}
194
195/*!
196 * \brief VariablesTreeItem::setData
197 * Updates the item data.
198 * \param column
199 * \param value
200 * \param role
201 * \return
202 */
203bool VariablesTreeItem::setData(int column, const QVariant &value, int role)
204{
205 if (column == 0 && role == Qt::CheckStateRole) {
206 if (value.toInt() == Qt::Checked) {
207 setChecked(true);
208 } else if (value.toInt() == Qt::Unchecked) {
209 setChecked(false);
210 }
211 return true;
212 } else if (column == 1 && role == Qt::EditRole) {
213 if (mValue.compare(value.toString()) != 0) {
214 mValueChanged = true;
215 mValue = value.toString();
216 }
217 return true;
218 } else if (column == 3 && role == Qt::EditRole) {
219 if (mDisplayUnit.compare(value.toString()) != 0) {
220 mPreviousUnit = mDisplayUnit;
221 mDisplayUnit = value.toString();
222 }
223 return true;
224 }
225 return false;
226}
227
228QVariant VariablesTreeItem::data(int column, int role) const
229{
230 switch (column) {
231 case 0:
232 switch (role) {
233 case Qt::DisplayRole:
234 return isActive() ? "(Active) " + mDisplayVariableName : mDisplayVariableName;
235 case Qt::DecorationRole:
236 return mIsRootItem ? getVariableTreeItemIcon(mVariableName) : QIcon();
237 case Qt::ToolTipRole:
238 return mToolTip;
239 case Qt::CheckStateRole:
240 if ((mChildren.size() == 0 && parent()->parent()) || mIsMainArray) { // do not show checkbox for top level items without children.
241 return isChecked() ? Qt::Checked : Qt::Unchecked;
242 } else {
243 return QVariant();
244 }
245 case Qt::FontRole:
246 if (isActive()) {
247 QFont font;
248 font.setBold(true);
249 return font;
250 } else {
251 return QVariant();
252 }
253 default:
254 return QVariant();
255 }
256 case 1:
257 switch (role) {
258 case Qt::DisplayRole:
259 case Qt::ToolTipRole:
260 case Qt::EditRole:
261 return mValue;
262 case Qt::FontRole:
263 if (isParameter()) {
264 QFont font;
265 font.setItalic(true);
266 return font;
267 } else {
268 return QVariant();
269 }
270 default:
271 return QVariant();
272 }
273 case 2:
274 switch (role) {
275 case Qt::DisplayRole:
276 case Qt::ToolTipRole:
277 return mUnit;
278 default:
279 return QVariant();
280 }
281 case 3:
282 switch (role) {
283 case Qt::DisplayRole:
284 case Qt::ToolTipRole:
285 return mDisplayUnit;
286 default:
287 return QVariant();
288 }
289 case 4:
290 switch (role) {
291 case Qt::DisplayRole:
292 case Qt::ToolTipRole:
293 return mDescription;
294 default:
295 return QVariant();
296 }
297 default:
298 return QVariant();
299 }
300}
301
302int VariablesTreeItem::row() const
303{
304 if (mpParentVariablesTreeItem)
305 return mpParentVariablesTreeItem->mChildren.indexOf(const_cast<VariablesTreeItem*>(this));
306
307 return 0;
308}
309
310VariablesTreeItem* VariablesTreeItem::rootParent()
311{
312 // since we have global mpRootVariablesTreeItem so we return one level down from this function in order to get the top level item.
313 VariablesTreeItem *pVariablesTreeItem, *pVariablesTreeItem1;
314 pVariablesTreeItem = this;
315 pVariablesTreeItem1 = this;
316 while (pVariablesTreeItem->mpParentVariablesTreeItem) {
317 pVariablesTreeItem1 = pVariablesTreeItem;
318 pVariablesTreeItem = pVariablesTreeItem->mpParentVariablesTreeItem;
319 }
320 return pVariablesTreeItem1;
321}
322
323/*!
324 * \brief VariablesTreeItem::getValue
325 * Returns the value in the desired unit or
326 * an empty value in case of conversion error.
327 * \param fromUnit
328 * \param toUnit
329 * \return
330 */
331QVariant VariablesTreeItem::getValue(QString fromUnit, QString toUnit)
332{
333 QString value = "";
334 if (fromUnit.compare(toUnit) == 0) {
335 value = mValue;
336 } else {
337 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(fromUnit, toUnit);
338 if (convertUnit.unitsCompatible) {
339 bool ok = false;
340 qreal realValue = mValue.toDouble(&ok);
341 if (ok) {
342 realValue = Utilities::convertUnit(realValue, convertUnit.offset, convertUnit.scaleFactor);
343 value = StringHandler::number(realValue);
344 }
345 }
346 }
347 return value;
348}
349
350VariablesTreeModel::VariablesTreeModel(VariablesTreeView *pVariablesTreeView)
351 : QAbstractItemModel(pVariablesTreeView)
352{
353 mpVariablesTreeView = pVariablesTreeView;
354 QVector<QVariant> headers;
355 headers << "" << "" << Helper::variables << Helper::variables << tr("Value") << tr("Unit") << tr("Display Unit") <<
356 QStringList() << Helper::description << "" << false << QVariantList() << QVariantList() << QVariantList() << "dummy.json";
357 mpRootVariablesTreeItem = new VariablesTreeItem(headers, 0, true);
358 mpActiveVariablesTreeItem = 0;
359}
360
361int VariablesTreeModel::columnCount(const QModelIndex &parent) const
362{
363 if (parent.isValid())
364 return static_cast<VariablesTreeItem*>(parent.internalPointer())->columnCount();
365 else
366 return mpRootVariablesTreeItem->columnCount();
367}
368
369int VariablesTreeModel::rowCount(const QModelIndex &parent) const
370{
371 VariablesTreeItem *pParentVariablesTreeItem;
372 if (parent.column() > 0)
373 return 0;
374
375 if (!parent.isValid())
376 pParentVariablesTreeItem = mpRootVariablesTreeItem;
377 else
378 pParentVariablesTreeItem = static_cast<VariablesTreeItem*>(parent.internalPointer());
379 return pParentVariablesTreeItem->getChildren().size();
380}
381
382QVariant VariablesTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
383{
384 if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
385 return mpRootVariablesTreeItem->data(section);
386 return QVariant();
387}
388
389QModelIndex VariablesTreeModel::index(int row, int column, const QModelIndex &parent) const
390{
391 if (!hasIndex(row, column, parent))
392 return QModelIndex();
393
394 VariablesTreeItem *pParentVariablesTreeItem;
395
396 if (!parent.isValid())
397 pParentVariablesTreeItem = mpRootVariablesTreeItem;
398 else
399 pParentVariablesTreeItem = static_cast<VariablesTreeItem*>(parent.internalPointer());
400
401 VariablesTreeItem *pChildVariablesTreeItem = pParentVariablesTreeItem->child(row);
402 if (pChildVariablesTreeItem)
403 return createIndex(row, column, pChildVariablesTreeItem);
404 else
405 return QModelIndex();
406}
407
408QModelIndex VariablesTreeModel::parent(const QModelIndex &index) const
409{
410 if (!index.isValid())
411 return QModelIndex();
412
413 VariablesTreeItem *pChildVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
414 VariablesTreeItem *pParentVariablesTreeItem = pChildVariablesTreeItem->parent();
415 if (pParentVariablesTreeItem == mpRootVariablesTreeItem)
416 return QModelIndex();
417
418 return createIndex(pParentVariablesTreeItem->row(), 0, pParentVariablesTreeItem);
419}
420
421/*!
422 * \brief VariablesTreeModel::setData
423 * Updates the model data.
424 * \param index
425 * \param value
426 * \param role
427 * \return
428 */
429bool VariablesTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
430{
431 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
432 if (!pVariablesTreeItem) {
433 return false;
434 }
435 QString displayUnit = pVariablesTreeItem->getDisplayUnit();
436 bool result = pVariablesTreeItem->setData(index.column(), value, role);
437 if (index.column() == 0 && role == Qt::CheckStateRole) {
438 if (!signalsBlocked()) {
439 PlottingPage *pPlottingPage = OptionsDialog::instance()->getPlottingPage();
440 emit itemChecked(index, pPlottingPage->getCurveThickness(), pPlottingPage->getCurvePattern());
441 }
442 } else if (index.column() == 1) { // value
443 if (!signalsBlocked()) {
444 VariablesTreeItem *pVariablesRootTreeItem = pVariablesTreeItem->rootParent();
445 if (pVariablesRootTreeItem->getSimulationOptions().isInteractiveSimulation()) {
446 emit valueEntered(index);
447 }
448 }
449 } else if (index.column() == 3) { // display unit
450 if (!signalsBlocked() && displayUnit.compare(value.toString()) != 0) {
451 emit unitChanged(index);
452 }
453 }
454 emit dataChanged(index, index);
455 return result;
456}
457
458QVariant VariablesTreeModel::data(const QModelIndex &index, int role) const
459{
460 if (!index.isValid())
461 return QVariant();
462
463 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
464 return pVariablesTreeItem->data(index.column(), role);
465}
466
467Qt::ItemFlags VariablesTreeModel::flags(const QModelIndex &index) const
468{
469 if (!index.isValid()) {
1
Taking false branch
470 return 0;
471 }
472
473 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
474 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
2
Calling 'QModelIndex::internalPointer'
3
Returning from 'QModelIndex::internalPointer'
4
'pVariablesTreeItem' initialized here
475 if (((index.column() == 0 && pVariablesTreeItem && pVariablesTreeItem->getChildren().size() == 0) || pVariablesTreeItem->isMainArray())
5
Assuming the condition is true
6
Assuming 'pVariablesTreeItem' is null
7
Assuming pointer value is null
8
Called C++ object pointer is null
476 && pVariablesTreeItem->parent() != mpRootVariablesTreeItem) {
477 flags |= Qt::ItemIsUserCheckable;
478 } else if (index.column() == 1 && pVariablesTreeItem && pVariablesTreeItem->getChildren().size() == 0 && pVariablesTreeItem->isEditable()) {
479 flags |= Qt::ItemIsEditable;
480 } else if (index.column() == 3) {
481 flags |= Qt::ItemIsEditable;
482 }
483
484 return flags;
485}
486
487VariablesTreeItem* VariablesTreeModel::findVariablesTreeItem(const QString &name, VariablesTreeItem *root) const
488{
489 if (root->getVariableName() == name) {
490 return root;
491 }
492 for (int i = root->getChildren().size(); --i >= 0; ) {
493 if (VariablesTreeItem *item = findVariablesTreeItem(name, root->getChildren().at(i))) {
494 return item;
495 }
496 }
497 return 0;
498}
499
500QModelIndex VariablesTreeModel::variablesTreeItemIndex(const VariablesTreeItem *pVariablesTreeItem) const
501{
502 return variablesTreeItemIndexHelper(pVariablesTreeItem, mpRootVariablesTreeItem, QModelIndex());
503}
504
505QModelIndex VariablesTreeModel::variablesTreeItemIndexHelper(const VariablesTreeItem *pVariablesTreeItem,
506 const VariablesTreeItem *pParentVariablesTreeItem,
507 const QModelIndex &parentIndex) const
508{
509 if (pVariablesTreeItem == pParentVariablesTreeItem)
510 return parentIndex;
511 for (int i = pParentVariablesTreeItem->getChildren().size(); --i >= 0; ) {
512 const VariablesTreeItem *childItem = pParentVariablesTreeItem->getChildren().at(i);
513 QModelIndex childIndex = index(i, 0, parentIndex);
514 QModelIndex index = variablesTreeItemIndexHelper(pVariablesTreeItem, childItem, childIndex);
515 if (index.isValid())
516 return index;
517 }
518 return QModelIndex();
519}
520
521/*!
522 * \brief VariablesTreeModel::parseInitXml
523 * Parses the model_init.xml file and returns the scalar variables information.
524 * \param xmlReader
525 * \return
526 */
527void VariablesTreeModel::parseInitXml(QXmlStreamReader &xmlReader)
528{
529 /* We'll parse the XML until we reach end of it.*/
530 while (!xmlReader.atEnd() && !xmlReader.hasError()) {
531 /* Read next element.*/
532 QXmlStreamReader::TokenType token = xmlReader.readNext();
533 /* If token is just StartDocument, we'll go to next.*/
534 if (token == QXmlStreamReader::StartDocument) {
535 continue;
536 }
537 /* If token is StartElement, we'll see if we can read it.*/
538 if (token == QXmlStreamReader::StartElement) {
539 /* If it's named ScalarVariable, we'll dig the information from there.*/
540 if (xmlReader.name() == "ScalarVariable") {
541 QHash<QString, QString> scalarVariable = parseScalarVariable(xmlReader);
542 mScalarVariablesHash.insert(scalarVariable.value("name"),scalarVariable);
543 }
544 }
545 }
546 xmlReader.clear();
547}
548
549/*!
550 * \brief VariablesTreeModel::insertVariablesItems
551 * Inserts the variables in the Variables Browser.
552 * \param fileName
553 * \param filePath
554 * \param variablesList
555 * \param simulationOptions
556 */
557void VariablesTreeModel::insertVariablesItems(QString fileName, QString filePath, QStringList variablesList, SimulationOptions simulationOptions)
558{
559 QString toolTip;
560 if (simulationOptions.isInteractiveSimulation()) {
561 toolTip = tr("Interactive Simulation\nPort: %1").arg(simulationOptions.getInteractiveSimulationPortNumber());
562 } else {
563 toolTip = tr("Simulation Result File: %1\n%2: %3/%4").arg(fileName).arg(Helper::fileLocation).arg(filePath).arg(fileName);
564 }
565 QRegExp resultTypeRegExp("(\\.mat|\\.plt|\\.csv|_res.mat|_res.plt|_res.csv)");
566 QString text = QString(fileName).remove(resultTypeRegExp);
567 QModelIndex index = variablesTreeItemIndex(mpRootVariablesTreeItem);
568 QVector<QVariant> Variabledata;
569 Variabledata << filePath << fileName << fileName << text << "" << "" << "" << QStringList() << "" << toolTip << false << QVariantList() << QVariantList() << QVariantList() << "dummy.json";
570
571 VariablesTreeItem *pTopVariablesTreeItem = new VariablesTreeItem(Variabledata, mpRootVariablesTreeItem, true);
572 pTopVariablesTreeItem->setSimulationOptions(simulationOptions);
573 int row = rowCount();
574 beginInsertRows(index, row, row);
575 mpRootVariablesTreeItem->insertChild(row, pTopVariablesTreeItem);
576 endInsertRows();
577 // set the newly inserted VariablesTreeItem active
578 mpActiveVariablesTreeItem = pTopVariablesTreeItem;
579 if (simulationOptions.isValid() && !simulationOptions.isInteractiveSimulation()) {
580 pTopVariablesTreeItem->setActive();
581 }
582 /* open the model_init.xml file for reading */
583 mScalarVariablesHash.clear();
584 QString initFileName, infoFileName;
585 if (simulationOptions.isValid()) {
586 initFileName = QString("%1_init.xml").arg(simulationOptions.getOutputFileName());
587 infoFileName = QString("%1_info.json").arg(simulationOptions.getOutputFileName());
588 } else {
589 initFileName = QString("%1_init.xml").arg(text);
590 infoFileName = QString("%1_info.json").arg(text);
591 }
592 QFile initFile(QString(filePath).append(QDir::separator()).append(initFileName));
593 if (initFile.exists()) {
594 if (initFile.open(QIODevice::ReadOnly)) {
595 QXmlStreamReader initXmlReader(&initFile);
596 parseInitXml(initXmlReader);
597 initFile.close();
598 } else {
599 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
600 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(initFile.fileName())
601 .arg(initFile.errorString()), Helper::scriptingKind, Helper::errorLevel));
602 }
603 }
604 QFile infoFile(QString(filePath).append(QDir::separator()).append(infoFileName));
605
606 QMap<QString,QSet<QString>> usedInitialVars;
607 QMap<QString,QSet<QString>> usedVars;
608 QMap<QString,QList<IntStringPair>> definedIn;
609
610 if (infoFile.exists()) {
611 if (MainWindow::instance()->isDebug()) {
612 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, "Opening json file " + infoFile.fileName(), Helper::scriptingKind, Helper::errorLevel));
613 if (infoFile.open(QIODevice::ReadOnly)) {
614 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, "Reading json file " + infoFile.fileName(), Helper::scriptingKind, Helper::errorLevel));
615 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, "Json file contents are " + infoFile.readAll(), Helper::scriptingKind, Helper::errorLevel));
616 infoFile.close();
617 } else {
618 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, "Unable to open the json file for reading " + infoFile.fileName(), Helper::scriptingKind, Helper::errorLevel));
619 }
620 }
621 QJson::Parser parser;
622 bool ok;
623 QVariantMap result;
624 if (MainWindow::instance()->isDebug()) {
625 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, "Parsing json file " + infoFile.fileName(), Helper::scriptingKind, Helper::errorLevel));
626 }
627 result = parser.parse(&infoFile, &ok).toMap();
628 if (!ok) {
629 if (MainWindow::instance()->isDebug()) {
630 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, "Failed to parse json file " + infoFile.fileName(), Helper::scriptingKind, Helper::errorLevel));
631 }
632 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(infoFile.fileName())
633 .arg(parser.errorString()), Helper::scriptingKind, Helper::errorLevel));
634 MainWindow::instance()->printStandardOutAndErrorFilesMessages();
635 return;
636 } else {
637 if (MainWindow::instance()->isDebug()) {
638 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, "Parsed json file " + infoFile.fileName(), Helper::scriptingKind, Helper::errorLevel));
639 }
640 }
641 QVariantMap vars = result["variables"].toMap();
642 QVariantList eqs = result["equations"].toList();
643
644 for (int i=0; i<eqs.size(); i++) {
645 QVariantMap veq = eqs[i].toMap();
646 bool isInitial = (veq.find("section") != veq.end() && veq["section"] == QString("initial"));
647
648 if (veq.find("defines") != veq.end()) {
649 QStringList defines = Utilities::variantListToStringList(veq["defines"].toList());
650 foreach (QString v1, defines)for (auto _container_ = QtPrivate::qMakeForeachContainer(defines
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString v1
= *_container_.i; _container_.control; _container_.control =
0)
{
651 if (!definedIn.contains(v1)) {
652 definedIn[v1] = QList<IntStringPair>();
653 }
654 definedIn[v1] << IntStringPair(veq["eqIndex"].toInt(), veq.find("section") != veq.end() ? veq["section"].toString() : QString("unknown"));
655 QString v1_1 = QString("%1.%2").arg(fileName ,v1);
656 if (veq.find("uses") != veq.end()) {
657 QStringList uses = Utilities::variantListToStringList(veq["uses"].toList());
658 foreach (QString v2, uses)for (auto _container_ = QtPrivate::qMakeForeachContainer(uses
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString v2
= *_container_.i; _container_.control; _container_.control =
0)
{
659 if (isInitial) {
660 usedInitialVars[v1].insert(v2);
661 } else {
662 usedVars[v1].insert(v2);
663 }
664 }
665 }
666 }
667 }
668 }
669 }
670
671 /* open the .mat file */
672 ModelicaMatReader matReader;
673 matReader.file = 0;
674 const char *msg[] = {""};
675 if (fileName.endsWith(".mat")) {
676 //Read in mat file
677 if (0 != (msg[0] = omc_new_matlab4_reader(QString(filePath + "/" + fileName).toUtf8().constData(), &matReader))) {
678 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
679 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(filePath + "/" + fileName)
680 .arg(QString(msg[0])), Helper::scriptingKind, Helper::errorLevel));
681 }
682 }
683
684 // remove time from variables list
685 variablesList.removeOne("time");
686 QStringList variables;
687 foreach (QString plotVariable, variablesList)for (auto _container_ = QtPrivate::qMakeForeachContainer(variablesList
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString plotVariable
= *_container_.i; _container_.control; _container_.control =
0)
{
688 QString parentVariable = "";
689 if (plotVariable.startsWith("der(")) {
690 QString str = plotVariable;
691 str.chop((str.lastIndexOf("der(")/4)+1);
692 variables = StringHandler::makeVariablePartsWithInd(str.mid(str.lastIndexOf("der(") + 4));
693 } else if (plotVariable.startsWith("previous(")) {
694 QString str = plotVariable;
695 str.chop((str.lastIndexOf("previous(")/9)+1);
696 variables = StringHandler::makeVariablePartsWithInd(str.mid(str.lastIndexOf("previous(") + 9));
697 } else {
698 variables = StringHandler::makeVariablePartsWithInd(plotVariable);
699 }
700 int count = 1;
701 VariablesTreeItem *pParentVariablesTreeItem = 0;
702 foreach (QString variable, variables)for (auto _container_ = QtPrivate::qMakeForeachContainer(variables
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString variable
= *_container_.i; _container_.control; _container_.control =
0)
{
703 if (count == 1) { /* first loop iteration */
704 pParentVariablesTreeItem = pTopVariablesTreeItem;
705 }
706 QString findVariable;
707 /* if last item of derivative */
708 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
709 if (parentVariable.isEmpty()) {
710 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der("));
711 } else {
712 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, parentVariable, "der("));
713 }
714 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
715 if (parentVariable.isEmpty()) {
716 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous("));
717 } else {
718 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, parentVariable, "previous("));
719 }
720 } else {
721 if (parentVariable.isEmpty()) {
722 findVariable = QString("%1.%2").arg(fileName, variable);
723 } else {
724 findVariable = QString("%1.%2.%3").arg(fileName, parentVariable, variable);
725 }
726 }
727 if ((pParentVariablesTreeItem = findVariablesTreeItem(findVariable, pParentVariablesTreeItem)) != NULL__null) {
728 QString addVar = "";
729 /* if last item of derivative */
730 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
731 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der(");
732 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
733 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous(");
734 } else {
735 addVar = variable;
736 }
737 if (count == 1) {
738 parentVariable = addVar;
739 } else {
740 parentVariable += "." + addVar;
741 }
742 count++;
743 continue;
744 }
745 /* If pParentVariablesTreeItem is 0 and it is first loop iteration then use pTopVariablesTreeItem as parent.
746 * If loop iteration is not first and pParentVariablesTreeItem is 0 then find the parent item.
747 */
748 if (!pParentVariablesTreeItem && count > 1) {
749 pParentVariablesTreeItem = findVariablesTreeItem(fileName + "." + parentVariable, pTopVariablesTreeItem);
750 } else {
751 pParentVariablesTreeItem = pTopVariablesTreeItem;
752 }
753 QModelIndex index = variablesTreeItemIndex(pParentVariablesTreeItem);
754 QVector<QVariant> variableData;
755 /* if last item of derivative */
756 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
757 variableData << filePath << fileName << fileName + "." + plotVariable << StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der(");
758 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
759 variableData << filePath << fileName << fileName + "." + plotVariable << StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous(");
760 } else if (variables.size() == count && QRegExp("\\[\\d+\\]").exactMatch(variable)) { /* if last item of array derivative*/
761 variableData << filePath << fileName << fileName + "." + plotVariable << variable;
762 } else {
763 variableData << filePath << fileName << pParentVariablesTreeItem->getVariableName() + "." + variable << variable;
764 }
765
766 /* find the variable in the xml file */
767 QString variableToFind = variableData[2].toString();
768 variableToFind.remove(QRegExp(pTopVariablesTreeItem->getVariableName() + "."));
769 /* get the variable information i.e value, unit, displayunit, description */
770 QString value, variability, unit, displayUnit, description;
771 bool changeAble = false;
772 getVariableInformation(&matReader, variableToFind, &value, &changeAble, &variability, &unit, &displayUnit, &description);
773 variableData << StringHandler::unparse(QString("\"").append(value).append("\""));
774 /* set the variable unit */
775 variableData << StringHandler::unparse(QString("\"").append(unit).append("\""));
776 /* set the variable displayUnit */
777 variableData << StringHandler::unparse(QString("\"").append(displayUnit).append("\""));
778 /* set the variable displayUnits */
779 if (!variableData[5].toString().isEmpty()) {
780 QStringList displayUnits, displayUnitOptions;
781 displayUnits << variableData[5].toString();
782 if (!variableData[6].toString().isEmpty()) {
783 displayUnitOptions << variableData[6].toString();
784 /* convert value to displayUnit */
785 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(variableData[5].toString(), variableData[6].toString());
786 if (convertUnit.unitsCompatible) {
787 bool ok = true;
788 qreal realValue = variableData[4].toDouble(&ok);
789 if (ok) {
790 realValue = Utilities::convertUnit(realValue, convertUnit.offset, convertUnit.scaleFactor);
791 variableData[4] = StringHandler::number(realValue);
792 }
793 }
794 } else { /* use unit as displayUnit */
795 variableData[6] = variableData[5];
796 }
797 displayUnits << displayUnitOptions;
798 variableData << displayUnits;
799 } else {
800 variableData << QStringList();
801 }
802 /* set the variable description */
803 variableData << StringHandler::unparse(QString("\"").append(description).append("\""));
804 /* construct tooltip text */
805 if (simulationOptions.isInteractiveSimulation()) {
806 variableData << tr("Variable: %1\nVariability: %2").arg(variableToFind).arg(variability);
807 } else {
808 variableData << tr("File: %1/%2\nVariable: %3\nVariability: %4").arg(filePath).arg(fileName).arg(variableToFind).arg(variability);
809 }
810 /*is main array*/
811 if (variables.size() == count+1 && QRegExp("\\[\\d+\\]").exactMatch(variables.last())) {
812 variableData << true;
813 } else {
814 variableData << false;
815 }
816 QString findVariableNoFileName = findVariable.right(findVariable.size()-fileName.size()-1);
817
818 if (usedVars.find(findVariableNoFileName) != usedVars.end()) {
819 QStringList lst = QStringList(usedVars[findVariableNoFileName].toList());
820 lst << findVariableNoFileName;
821 variableData << lst;
822 } else {
823 variableData << QStringList(findVariableNoFileName);
824 }
825 if (usedInitialVars.find(findVariableNoFileName) != usedInitialVars.end()) {
826 QStringList lst = QStringList(usedInitialVars[findVariableNoFileName].toList());
827 lst << findVariableNoFileName;
828 variableData << lst;
829 } else {
830 variableData << QStringList(findVariableNoFileName);
831 }
832 QVariantList variantDefinedIn;
833 if (definedIn.find(findVariableNoFileName) != definedIn.end()) {
834 foreach (IntStringPair pair, definedIn[findVariableNoFileName])for (auto _container_ = QtPrivate::qMakeForeachContainer(definedIn
[findVariableNoFileName]); _container_.control && _container_
.i != _container_.e; ++_container_.i, _container_.control ^= 1
) for (IntStringPair pair = *_container_.i; _container_.control
; _container_.control = 0)
{
835 variantDefinedIn << QVariant::fromValue(pair);
836 }
837 } else {
838 variantDefinedIn << QVariant::fromValue(IntStringPair(0,QString("")));
839 }
840 variableData << variantDefinedIn;
841 variableData << infoFileName;
842
843 VariablesTreeItem *pVariablesTreeItem = new VariablesTreeItem(variableData, pParentVariablesTreeItem);
844 pVariablesTreeItem->setEditable(changeAble);
845 pVariablesTreeItem->setVariability(variability);
846 int row = rowCount(index);
847 beginInsertRows(index, row, row);
848 pParentVariablesTreeItem->insertChild(row, pVariablesTreeItem);
849 endInsertRows();
850 QString addVar = "";
851 /* if last item of derivative */
852 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
853 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der(");
854 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
855 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous(");
856 } else {
857 addVar = variable;
858 }
859 if (count == 1) {
860 parentVariable = addVar;
861 } else {
862 parentVariable += "." + addVar;
863 }
864 count++;
865 }
866 }
867 /* close the .mat file */
868 if (fileName.endsWith(".mat")) {
869 if (matReader.file) {
870 omc_free_matlab4_reader(&matReader);
871 }
872 }
873 mpVariablesTreeView->collapseAll();
874 QModelIndex idx = variablesTreeItemIndex(pTopVariablesTreeItem);
875 idx = mpVariablesTreeView->getVariablesWidget()->getVariableTreeProxyModel()->mapFromSource(idx);
876 mpVariablesTreeView->expand(idx);
877 /* Ticket #3016.
878 * If you only have one model the message "You must select a class to re-simulate" is annoying.
879 * A default behavior of selecting the (single) model would be good.
880 * The following line selects the result tree top level item.
881 */
882 mpVariablesTreeView->setCurrentIndex(idx);
883 MainWindow::instance()->enableReSimulationToolbar(MainWindow::instance()->getVariablesDockWidget()->isVisible());
884}
885
886/*!
887 * \brief VariablesTreeModel::removeVariableTreeItem
888 * Removes the VariablesTreeItem.
889 * \param variable
890 * \return
891 */
892bool VariablesTreeModel::removeVariableTreeItem(QString variable)
893{
894 VariablesTreeItem *pVariablesTreeItem = findVariablesTreeItem(variable, mpRootVariablesTreeItem);
895 if (pVariablesTreeItem) {
896 // if we are going to remove an active VariablesTreeItem then we should disable the visualization controls.
897 if (pVariablesTreeItem->isActive()) {
898 mpVariablesTreeView->getVariablesWidget()->enableVisualizationControls(false);
899 mpVariablesTreeView->getVariablesWidget()->rewindVisualization();
900 }
901 beginRemoveRows(variablesTreeItemIndex(pVariablesTreeItem), 0, pVariablesTreeItem->getChildren().size());
902 pVariablesTreeItem->removeChildren();
903 VariablesTreeItem *pParentVariablesTreeItem = pVariablesTreeItem->parent();
904 pParentVariablesTreeItem->removeChild(pVariablesTreeItem);
905
906 if (pVariablesTreeItem->getSimulationOptions().isInteractiveSimulation()) {
907 for (const auto& p : MainWindow::instance()->getSimulationDialog()->getSimulationOutputWidgetsList()) {
908 // remove the right interactive output widget
909 if (p->getSimulationOptions().getClassName() == pVariablesTreeItem->getFileName()) {
910 MainWindow::instance()->getSimulationDialog()->removeSimulationOutputWidget(p);
911 break;
912 }
913 }
914 }
915 if (pVariablesTreeItem) {
916 delete pVariablesTreeItem;
917 }
918 endRemoveRows();
919 mpVariablesTreeView->getVariablesWidget()->findVariables();
920 return true;
921 }
922 return false;
923}
924
925void VariablesTreeModel::unCheckVariables(VariablesTreeItem *pVariablesTreeItem)
926{
927 QList<VariablesTreeItem*> items = pVariablesTreeItem->getChildren();
928 for (int i = 0 ; i < items.size() ; i++) {
929 items[i]->setData(0, Qt::Unchecked, Qt::CheckStateRole);
930 unCheckVariables(items[i]);
931 }
932}
933
934void VariablesTreeModel::plotAllVariables(VariablesTreeItem *pVariablesTreeItem, PlotWindow *pPlotWindow)
935{
936 QList<VariablesTreeItem*> variablesTreeItems = pVariablesTreeItem->getChildren();
937 if (variablesTreeItems.size() == 0) {
938 QModelIndex index = variablesTreeItemIndex(pVariablesTreeItem);
939 OMPlot::PlotCurve *pPlotCurve = 0;
940 foreach (OMPlot::PlotCurve *curve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (OMPlot::PlotCurve *curve = *_container_.i
; _container_.control; _container_.control = 0)
{
941 if (curve->getNameStructure().compare(pVariablesTreeItem->getVariableName()) == 0) {
942 pPlotCurve = curve;
943 break;
944 }
945 }
946 setData(index, Qt::Checked, Qt::CheckStateRole);
947 mpVariablesTreeView->getVariablesWidget()->plotVariables(index, pPlotWindow->getCurveWidth(), pPlotWindow->getCurveStyle(), pPlotCurve);
948 } else {
949 for (int i = 0 ; i < variablesTreeItems.size() ; i++) {
950 plotAllVariables(variablesTreeItems[i], pPlotWindow);
951 }
952 }
953}
954
955/*!
956 * \brief VariablesTreeModel::parseScalarVariable
957 * Parses the scalar variable.
958 * Helper function for VariablesTreeModel::parseInitXml
959 * \param xmlReader
960 * \return
961 */
962QHash<QString, QString> VariablesTreeModel::parseScalarVariable(QXmlStreamReader &xmlReader)
963{
964 QHash<QString, QString> scalarVariable;
965 /* Let's check that we're really getting a ScalarVariable. */
966 if (xmlReader.tokenType() != QXmlStreamReader::StartElement && xmlReader.name() == "ScalarVariable") {
967 return scalarVariable;
968 }
969 /* Let's get the attributes for ScalarVariable */
970 QXmlStreamAttributes attributes = xmlReader.attributes();
971 /* Read the ScalarVariable attributes. */
972 scalarVariable["name"] = attributes.value("name").toString();
973 scalarVariable["description"] = attributes.value("description").toString();
974 scalarVariable["isValueChangeable"] = attributes.value("isValueChangeable").toString();
975 scalarVariable["variability"] = attributes.value("variability").toString();
976 /* Read the next element i.e Real, Integer, Boolean etc. */
977 xmlReader.readNext();
978 while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement && xmlReader.name() == "ScalarVariable")) {
979 if (xmlReader.tokenType() == QXmlStreamReader::StartElement) {
980 QXmlStreamAttributes attributes = xmlReader.attributes();
981 scalarVariable["start"] = attributes.value("start").toString();
982 scalarVariable["unit"] = attributes.value("unit").toString();
983 scalarVariable["displayUnit"] = attributes.value("displayUnit").toString();
984 }
985 xmlReader.readNext();
986 }
987 return scalarVariable;
988}
989
990/*!
991 * \brief VariablesTreeModel::getVariableInformation
992 * Returns the variable information like value, unit, displayunit and description.
993 * \param pMatReader
994 * \param variableToFind
995 * \param value
996 * \param changeAble
997 * \param variability
998 * \param unit
999 * \param displayUnit
1000 * \param description
1001 */
1002void VariablesTreeModel::getVariableInformation(ModelicaMatReader *pMatReader, QString variableToFind, QString *value, bool *changeAble,
1003 QString *variability, QString *unit, QString *displayUnit, QString *description)
1004{
1005 QHash<QString, QString> hash = mScalarVariablesHash.value(variableToFind);
1006 if (hash["name"].compare(variableToFind) == 0) {
1007 *changeAble = (hash["isValueChangeable"].compare("true") == 0) ? true : false;
1008 *variability = hash["variability"];
1009 if (*changeAble) {
1010 *value = hash["start"];
1011 } else { /* if the variable is not a tunable parameter then read the final value of the variable. Only mat result files are supported. */
1012 if ((pMatReader->file != NULL__null) && strcmp(pMatReader->fileName, "")) {
1013 *value = "";
1014 ModelicaMatVariable_t *var;
1015 if (0 == (var = omc_matlab4_find_var(pMatReader, variableToFind.toUtf8().constData()))) {
1016 qDebugQMessageLogger(nullptr, 0, nullptr).debug() << QString("%1 not found in %2").arg(variableToFind).arg(pMatReader->fileName);
1017 }
1018 double res;
1019 if (var && !omc_matlab4_val(&res, pMatReader, var, omc_matlab4_stopTime(pMatReader))) {
1020 *value = QString::number(res);
1021 }
1022 }
1023 }
1024 *unit = hash["unit"];
1025 *displayUnit = hash["displayUnit"];
1026 *description = hash["description"];
1027 }
1028}
1029
1030/*!
1031 * \brief VariablesTreeModel::removeVariableTreeItem
1032 * Slot activated when pDeleteResultAction triggered SIGNAL is raised.
1033 * Removes a VariablesTreeItem
1034 */
1035void VariablesTreeModel::removeVariableTreeItem()
1036{
1037 QAction *pAction = qobject_cast<QAction*>(sender());
1038 if (pAction) {
1039 removeVariableTreeItem(pAction->data().toString());
1040 emit variableTreeItemRemoved(pAction->data().toString());
1041 }
1042}
1043
1044
1045void VariablesTreeModel::filterDependencies()
1046{
1047 QAction *pAction = qobject_cast<QAction*>(sender());
1048 if (pAction) {
1049 QStringList uses = pAction->data().toStringList();
1050 QStringList escapedUses;
1051 foreach(QString s, uses)for (auto _container_ = QtPrivate::qMakeForeachContainer(uses
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString s
= *_container_.i; _container_.control; _container_.control =
0)
{
1052 escapedUses << s.replace("[","[[]").replace("]","[]]").replace("[[[]]","[[]").replace("(","[(]").replace(")","[)]").replace(".","[.]");
1053 }
1054 QRegExp regexp = QRegExp("^" + escapedUses.join("|") + "$");
1055 mpVariablesTreeView->getVariablesWidget()->getVariableTreeProxyModel()->setFilterRegExp(regexp);
1056 }
1057}
1058
1059void VariablesTreeModel::openTransformationsBrowser()
1060{
1061 QAction *pAction = qobject_cast<QAction*>(sender());
1062 if (pAction) {
1063 QVariantList list = pAction->data().toList();
1064 QString fileName = list[0].toString();
1065 int equationIndex = list[1].toInt();
1066 if (QFileInfo(fileName).exists()) {
1067 TransformationsWidget *pTransformationsWidget = MainWindow::instance()->showTransformationsWidget(fileName);
1068 QTreeWidgetItem *pTreeWidgetItem = pTransformationsWidget->findEquationTreeItem(equationIndex);
1069 if (pTreeWidgetItem) {
1070 pTransformationsWidget->getEquationsTreeWidget()->clearSelection();
1071 pTransformationsWidget->getEquationsTreeWidget()->setCurrentItem(pTreeWidgetItem);
1072 }
1073 pTransformationsWidget->fetchEquationData(equationIndex);
1074 } else {
1075 QMessageBox::critical(MainWindow::instance(), QString("%1 - %2").arg(Helper::applicationName, Helper::error), GUIMessages::getMessage(GUIMessages::FILE_NOT_FOUND).arg(fileName), Helper::ok);
1076 }
1077 }
1078}
1079
1080/*!
1081 * \brief VariablesTreeModel::setVariableTreeItemActive
1082 * Slots activated when mpSetResultActiveAction triggered SIGNAL is raised.
1083 * Sets a VariablesTreeItem active.
1084 */
1085void VariablesTreeModel::setVariableTreeItemActive()
1086{
1087 QAction *pAction = qobject_cast<QAction*>(sender());
1088 if (pAction) {
1089 VariablesTreeItem *pVariablesTreeItem = findVariablesTreeItem(pAction->data().toString(), mpRootVariablesTreeItem);
1090 if (pVariablesTreeItem) {
1091 mpActiveVariablesTreeItem = pVariablesTreeItem;
1092 pVariablesTreeItem->setActive();
1093 }
1094 }
1095}
1096
1097/*!
1098 * \class VariableTreeProxyModel
1099 * \brief A sort filter proxy model for Variables Browser.
1100 */
1101/*!
1102 * \brief VariableTreeProxyModel::VariableTreeProxyModel
1103 * \param parent
1104 */
1105VariableTreeProxyModel::VariableTreeProxyModel(QObject *parent)
1106 : QSortFilterProxyModel(parent)
1107{
1108}
1109
1110/*!
1111 * \brief VariableTreeProxyModel::filterAcceptsRow
1112 * Filters the VariablesTreeItems based on the filter reguler expression.
1113 * \param sourceRow
1114 * \param sourceParent
1115 * \return
1116 */
1117bool VariableTreeProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
1118{
1119 if (!filterRegExp().isEmpty()) {
1120 QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
1121 if (index.isValid()) {
1122 // if any of children matches the filter, then current index matches the filter as well
1123 int rows = sourceModel()->rowCount(index);
1124 for (int i = 0 ; i < rows ; ++i) {
1125 if (filterAcceptsRow(i, index)) {
1126 return true;
1127 }
1128 }
1129 // check current index itself
1130 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1131 if (pVariablesTreeItem) {
1132 QString variableName = pVariablesTreeItem->getVariableName();
1133 variableName.remove(QRegExp("(\\.mat|\\.plt|\\.csv|_res.mat|_res.plt|_res.csv)"));
1134 return variableName.contains(filterRegExp());
1135 } else {
1136 return sourceModel()->data(index).toString().contains(filterRegExp());
1137 }
1138 QString key = sourceModel()->data(index, filterRole()).toString();
1139 return key.contains(filterRegExp());
1140 }
1141 }
1142 return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
1143}
1144
1145/*!
1146 * \brief VariableTreeProxyModel::lessThan
1147 * Sorts the VariablesTreeItems using the natural sort.
1148 * \param left
1149 * \param right
1150 * \return
1151 */
1152bool VariableTreeProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
1153{
1154 QVariant l = (left.model() ? left.model()->data(left) : QVariant());
1155 QVariant r = (right.model() ? right.model()->data(right) : QVariant());
1156 return StringHandler::naturalSort(l.toString(), r.toString());
1157}
1158
1159VariablesTreeView::VariablesTreeView(VariablesWidget *pVariablesWidget)
1160 : QTreeView(pVariablesWidget)
1161{
1162 mpVariablesWidget = pVariablesWidget;
1163 setItemDelegate(new ItemDelegate(this));
1164 setTextElideMode(Qt::ElideMiddle);
1165 setIndentation(Helper::treeIndentation);
1166 setIconSize(Helper::iconSize);
1167 setContextMenuPolicy(Qt::CustomContextMenu);
1168 setExpandsOnDoubleClick(false);
1169 setEditTriggers(QAbstractItemView::AllEditTriggers);
1170 setUniformRowHeights(true);
1171}
1172
1173/*!
1174 * \brief VariablesTreeView::mouseReleaseEvent
1175 * Reimplementation of QTreeView::mouseReleaseEvent\n
1176 * Checks if user clicks on the first column then check/uncheck the corresponsing checkbox of the column.\n
1177 * Otherwise calls the QTreeView::mouseReleaseEvent
1178 * \param event
1179 */
1180void VariablesTreeView::mouseReleaseEvent(QMouseEvent *event)
1181{
1182 QModelIndex index = indexAt(event->pos());
1183 if (index.isValid() &&
1184 index.column() == 0 &&
1185 index.parent().isValid() &&
1186 index.flags() & Qt::ItemIsUserCheckable &&
1187 event->button() == Qt::LeftButton) {
1188 if (visualRect(index).contains(event->pos())) {
1189 index = mpVariablesWidget->getVariableTreeProxyModel()->mapToSource(index);
1190 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1191 if (pVariablesTreeItem && pVariablesTreeItem) {
1192 if (pVariablesTreeItem->isChecked()) {
1193 mpVariablesWidget->getVariablesTreeModel()->setData(index, Qt::Unchecked, Qt::CheckStateRole);
1194 } else {
1195 mpVariablesWidget->getVariablesTreeModel()->setData(index, Qt::Checked, Qt::CheckStateRole);
1196 }
1197 }
1198 return;
1199 }
1200 }
1201 QTreeView::mouseReleaseEvent(event);
1202}
1203
1204/*!
1205 * \brief VariablesTreeView::keyPressEvent
1206 * Reimplementation of keypressevent.
1207 * \param event
1208 */
1209void VariablesTreeView::keyPressEvent(QKeyEvent *event)
1210{
1211 QModelIndexList indexes = selectionModel()->selectedIndexes();
1212 if (!indexes.isEmpty()) {
1213 QModelIndex index = indexes.at(0);
1214 index = mpVariablesWidget->getVariableTreeProxyModel()->mapToSource(index);
1215 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1216 if (event->key() == Qt::Key_Delete && pVariablesTreeItem->isRootItem()) {
1217 mpVariablesWidget->getVariablesTreeModel()->removeVariableTreeItem(pVariablesTreeItem->getVariableName());
1218 return;
1219 }
1220 }
1221 QTreeView::keyPressEvent(event);
1222}
1223
1224VariablesWidget::VariablesWidget(QWidget *pParent)
1225 : QWidget(pParent)
1226{
1227 // tree search filters
1228 mpTreeSearchFilters = new TreeSearchFilters(this);
1229 mpTreeSearchFilters->getFilterTextBox()->setPlaceholderText(Helper::filterVariables);
1230 mpTreeSearchFilters->getFilterTimer()->setInterval(OptionsDialog::instance()->getPlottingPage()->getFilterIntervalSpinBox()->value() * 1000);
1231 connect(mpTreeSearchFilters->getFilterTextBox(), SIGNAL(returnPressed())"2""returnPressed()", SLOT(findVariables())"1""findVariables()");
1232 connect(mpTreeSearchFilters->getFilterTextBox(), SIGNAL(textEdited(QString))"2""textEdited(QString)", mpTreeSearchFilters->getFilterTimer(), SLOT(start())"1""start()");
1233 connect(mpTreeSearchFilters->getFilterTimer(), SIGNAL(timeout())"2""timeout()", SLOT(findVariables())"1""findVariables()");
1234 connect(mpTreeSearchFilters->getCaseSensitiveCheckBox(), SIGNAL(toggled(bool))"2""toggled(bool)", SLOT(findVariables())"1""findVariables()");
1235 connect(mpTreeSearchFilters->getSyntaxComboBox(), SIGNAL(currentIndexChanged(int))"2""currentIndexChanged(int)", SLOT(findVariables())"1""findVariables()");
1236 // simulation time label and combobox
1237 mpSimulationTimeLabel = new Label(tr("Simulation Time Unit"));
1238 mpSimulationTimeComboBox = new QComboBox;
1239 mpSimulationTimeComboBox->addItem("s");
1240 mpSimulationTimeComboBox->addItems(MainWindow::instance()->getOMCProxy()->getDerivedUnits("s"));
1241 connect(mpSimulationTimeComboBox, SIGNAL(currentIndexChanged(QString))"2""currentIndexChanged(QString)", SLOT(timeUnitChanged(QString))"1""timeUnitChanged(QString)");
1242 // simulation time slider
1243 mSliderRange = 1000;
1244 mpSimulationTimeSlider = new QSlider(Qt::Horizontal);
1245 mpSimulationTimeSlider->setRange(0, mSliderRange);
1246 mpSimulationTimeSlider->setSliderPosition(0);
1247 connect(mpSimulationTimeSlider, SIGNAL(valueChanged(int))"2""valueChanged(int)", SLOT(simulationTimeChanged(int))"1""simulationTimeChanged(int)");
1248 // toolbar
1249 mpToolBar = new QToolBar;
1250 int toolbarIconSize = OptionsDialog::instance()->getGeneralSettingsPage()->getToolbarIconSizeSpinBox()->value();
1251 mpToolBar->setIconSize(QSize(toolbarIconSize, toolbarIconSize));
1252 // rewind action
1253 mpRewindAction = new QAction(QIcon(":/Resources/icons/initialize.svg"), tr("Rewind"), this);
1254 mpRewindAction->setStatusTip(tr("Rewinds the visualization to the start"));
1255 connect(mpRewindAction, SIGNAL(triggered())"2""triggered()", SLOT(rewindVisualization())"1""rewindVisualization()");
1256 // play action
1257 mpPlayAction = new QAction(QIcon(":/Resources/icons/play_animation.svg"), Helper::animationPlay, this);
1258 mpPlayAction->setStatusTip(tr("Play the visualization"));
1259 connect(mpPlayAction, SIGNAL(triggered())"2""triggered()", SLOT(playVisualization())"1""playVisualization()");
1260 // pause action
1261 mpPauseAction = new QAction(QIcon(":/Resources/icons/pause.svg"), Helper::animationPause, this);
1262 mpPauseAction->setStatusTip(tr("Pause the visualization"));
1263 connect(mpPauseAction, SIGNAL(triggered())"2""triggered()", SLOT(pauseVisualization())"1""pauseVisualization()");
1264 // time
1265 QDoubleValidator *pDoubleValidator = new QDoubleValidator(this);
1266 pDoubleValidator->setBottom(0);
1267 mpTimeLabel = new Label;
1268 mpTimeLabel->setText(tr("Time:"));
1269 mpTimeTextBox = new QLineEdit("0.0");
1270 mpTimeTextBox->setMaximumHeight(toolbarIconSize);
1271 mpTimeTextBox->setValidator(pDoubleValidator);
1272 connect(mpTimeTextBox, SIGNAL(returnPressed())"2""returnPressed()", SLOT(visulizationTimeChanged())"1""visulizationTimeChanged()");
1273 // speed
1274 mpSpeedLabel = new Label;
1275 mpSpeedLabel->setText(Helper::speed);
1276 mpSpeedComboBox = new QComboBox;
1277 mpSpeedComboBox->setEditable(true);
1278 mpSpeedComboBox->addItems(Helper::speedOptions.split(","));
1279 mpSpeedComboBox->setCurrentIndex(3);
1280 mpSpeedComboBox->setMaximumHeight(toolbarIconSize);
1281 mpSpeedComboBox->setValidator(pDoubleValidator);
1282 mpSpeedComboBox->setCompleter(0);
1283 connect(mpSpeedComboBox, SIGNAL(currentIndexChanged(int))"2""currentIndexChanged(int)", SLOT(visualizationSpeedChanged())"1""visualizationSpeedChanged()");
1284 connect(mpSpeedComboBox->lineEdit(), SIGNAL(textChanged(QString))"2""textChanged(QString)", SLOT(visualizationSpeedChanged())"1""visualizationSpeedChanged()");
1285 // add actions to toolbar
1286 mpToolBar->addAction(mpRewindAction);
1287 mpToolBar->addSeparator();
1288 mpToolBar->addAction(mpPlayAction);
1289 mpToolBar->addAction(mpPauseAction);
1290 mpToolBar->addSeparator();
1291 mpToolBar->addWidget(mpTimeLabel);
1292 mpToolBar->addWidget(mpTimeTextBox);
1293 mpToolBar->addSeparator();
1294 mpToolBar->addWidget(mpSpeedLabel);
1295 mpToolBar->addWidget(mpSpeedComboBox);
1296 // time manager
1297 mpTimeManager = new TimeManager(0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 1.0);
1298 mpTimeManager->setStartTime(0.0);
1299 mpTimeManager->setEndTime(1.0);
1300 mpTimeManager->setVisTime(mpTimeManager->getStartTime());
1301 mpTimeManager->setPause(true);
1302 connect(mpTimeManager->getUpdateSceneTimer(), SIGNAL(timeout())"2""timeout()", SLOT(incrementVisualization())"1""incrementVisualization()");
1303 // create variables tree widget
1304 mpVariablesTreeView = new VariablesTreeView(this);
1305 mpVariablesTreeModel = new VariablesTreeModel(mpVariablesTreeView);
1306 mpVariableTreeProxyModel = new VariableTreeProxyModel;
1307 mpVariableTreeProxyModel->setDynamicSortFilter(true);
1308 mpVariableTreeProxyModel->setSourceModel(mpVariablesTreeModel);
1309 mpVariablesTreeView->setModel(mpVariableTreeProxyModel);
1310 mpVariablesTreeView->setColumnWidth(0, 150);
1311 mpVariablesTreeView->setColumnWidth(1, 70);
1312 mpVariablesTreeView->setColumnWidth(2, 50);
1313 mpVariablesTreeView->setColumnWidth(3, 70);
1314 mpVariablesTreeView->setColumnHidden(2, true); // hide Unit column
1315 mpLastActiveSubWindow = 0;
1316 mModelicaMatReader.file = 0;
1317 mpCSVData = 0;
1318 // create the layout
1319 QGridLayout *pMainLayout = new QGridLayout;
1320 pMainLayout->setContentsMargins(0, 0, 0, 0);
1321 pMainLayout->setAlignment(Qt::AlignTop);
1322 pMainLayout->addWidget(mpTreeSearchFilters, 0, 0, 1, 2);
1323 pMainLayout->addWidget(mpSimulationTimeLabel, 1, 0);
1324 pMainLayout->addWidget(mpSimulationTimeComboBox, 1, 1);
1325 pMainLayout->addWidget(mpSimulationTimeSlider, 2, 0, 1, 2);
1326 pMainLayout->addWidget(mpToolBar, 3, 0, 1, 2);
1327 pMainLayout->addWidget(mpVariablesTreeView, 4, 0, 1, 2);
1328 setLayout(pMainLayout);
1329 connect(mpTreeSearchFilters->getExpandAllButton(), SIGNAL(clicked())"2""clicked()", mpVariablesTreeView, SLOT(expandAll())"1""expandAll()");
1330 connect(mpTreeSearchFilters->getCollapseAllButton(), SIGNAL(clicked())"2""clicked()", mpVariablesTreeView, SLOT(collapseAll())"1""collapseAll()");
1331 connect(mpVariablesTreeModel, SIGNAL(rowsInserted(QModelIndex,int,int))"2""rowsInserted(QModelIndex,int,int)", mpVariableTreeProxyModel, SLOT(invalidate())"1""invalidate()");
1332 connect(mpVariablesTreeModel, SIGNAL(rowsRemoved(QModelIndex,int,int))"2""rowsRemoved(QModelIndex,int,int)", mpVariableTreeProxyModel, SLOT(invalidate())"1""invalidate()");
1333 connect(mpVariablesTreeModel, SIGNAL(itemChecked(QModelIndex,qreal,int))"2""itemChecked(QModelIndex,qreal,int)", SLOT(plotVariables(QModelIndex,qreal,int))"1""plotVariables(QModelIndex,qreal,int)");
1334 connect(mpVariablesTreeModel, SIGNAL(unitChanged(QModelIndex))"2""unitChanged(QModelIndex)", SLOT(unitChanged(QModelIndex))"1""unitChanged(QModelIndex)");
1335 connect(mpVariablesTreeModel, SIGNAL(valueEntered(QModelIndex))"2""valueEntered(QModelIndex)", SLOT(valueEntered(QModelIndex))"1""valueEntered(QModelIndex)");
1336 connect(mpVariablesTreeView, SIGNAL(customContextMenuRequested(QPoint))"2""customContextMenuRequested(QPoint)", SLOT(showContextMenu(QPoint))"1""showContextMenu(QPoint)");
1337 connect(MainWindow::instance()->getPlotWindowContainer(), SIGNAL(subWindowActivated(QMdiSubWindow*))"2""subWindowActivated(QMdiSubWindow*)", this, SLOT(updateVariablesTree(QMdiSubWindow*))"1""updateVariablesTree(QMdiSubWindow*)");
1338 connect(mpVariablesTreeModel, SIGNAL(variableTreeItemRemoved(QString))"2""variableTreeItemRemoved(QString)", MainWindow::instance()->getPlotWindowContainer(), SLOT(updatePlotWindows(QString))"1""updatePlotWindows(QString)");
1339 //connect(mpVariablesTreeModel, SIGNAL(clicked(QModelIndex)), this, SLOT(selectInteractivePlotWindow(QModelIndex)));
1340 //connect(mpVariablesTreeModel, SIGNAL(itemChecked(QModelIndex)), SLOT(selectInteractivePlotWindow(QModelIndex)));
1341 enableVisualizationControls(false);
1342}
1343
1344/*!
1345 * \brief VariablesWidget::enableVisualizationControls
1346 * Enables/Disables the visualization controls.
1347 * \param enable
1348 */
1349void VariablesWidget::enableVisualizationControls(bool enable)
1350{
1351 mpSimulationTimeSlider->setEnabled(enable);
1352 mpSimulationTimeSlider->setToolTip(enable ? "" : tr("Mark a result file active to enable the controls."));
1353 mpToolBar->setEnabled(enable);
1354}
1355
1356/*!
1357 * \brief VariablesWidget::insertVariablesItemsToTree
1358 * Inserts the result variables in the Variables Browser.
1359 * \param fileName
1360 * \param filePath
1361 * \param variablesList
1362 * \param simulationOptions
1363 */
1364void VariablesWidget::insertVariablesItemsToTree(QString fileName, QString filePath, QStringList variablesList, SimulationOptions simulationOptions)
1365{
1366 /* Remove the simulation result if we already had it in tree */
1367 bool variableItemDeleted = false;
1368 variableItemDeleted = mpVariablesTreeModel->removeVariableTreeItem(fileName);
1369
1370 mpVariablesTreeView->setSortingEnabled(false);
1371 /* In order to improve the response time of insertVariablesItems function we should clear the filter and collapse all the items. */
1372 mpVariableTreeProxyModel->setFilterRegExp(QRegExp(""));
1373 mpVariablesTreeView->collapseAll();
1374 /* add the plot variables */
1375 mpVariablesTreeModel->insertVariablesItems(fileName, filePath, variablesList, simulationOptions);
1376
1377 /* re-check previously checked variables */
1378 if (simulationOptions.isInteractiveSimulation() && simulationOptions.isReSimulate()) {
1379 interactiveReSimulation(simulationOptions.getClassName());
1380 }
1381
1382 /* update the plot variables tree */
1383 if (variableItemDeleted) {
1384 variablesUpdated();
1385 }
1386 mpVariablesTreeView->setSortingEnabled(true);
1387 mpVariablesTreeView->sortByColumn(0, Qt::AscendingOrder);
1388 /* since we cleared the filter above so we need to apply it back. */
1389 findVariables();
1390}
1391
1392/*!
1393 * \brief VariablesWidget::variablesUpdated
1394 * Updates the already plotted variables after simulation with new values.
1395 */
1396void VariablesWidget::variablesUpdated()
1397{
1398 foreach (QMdiSubWindow *pSubWindow, MainWindow::instance()->getPlotWindowContainer()->subWindowList(QMdiArea::StackingOrder))for (auto _container_ = QtPrivate::qMakeForeachContainer(MainWindow
::instance()->getPlotWindowContainer()->subWindowList(QMdiArea
::StackingOrder)); _container_.control && _container_
.i != _container_.e; ++_container_.i, _container_.control ^= 1
) for (QMdiSubWindow *pSubWindow = *_container_.i; _container_
.control; _container_.control = 0)
{
1399 PlotWindow *pPlotWindow = qobject_cast<PlotWindow*>(pSubWindow->widget());
1400 if (pPlotWindow) { // we can have an AnimateWindow there as well so always check
1401 foreach (PlotCurve *pPlotCurve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (PlotCurve *pPlotCurve = *_container_.i; _container_
.control; _container_.control = 0)
{
1402 if (pPlotWindow->getPlotType() == PlotWindow::PLOT || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY) {
1403 QString curveNameStructure = pPlotCurve->getNameStructure();
1404 VariablesTreeItem *pVariableTreeItem;
1405 pVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(curveNameStructure, mpVariablesTreeModel->getRootVariablesTreeItem());
1406 pPlotCurve->detach();
1407 if (pVariableTreeItem) {
1408 bool state = mpVariablesTreeModel->blockSignals(true);
1409 QModelIndex index = mpVariablesTreeModel->variablesTreeItemIndex(pVariableTreeItem);
1410 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1411 plotVariables(index, pPlotCurve->getCurveWidth(), pPlotCurve->getCurveStyle(), pPlotCurve, pPlotWindow);
1412 mpVariablesTreeModel->blockSignals(state);
1413 } else {
1414 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1415 }
1416 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) {
1417 QString xVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getXVariable());
1418 VariablesTreeItem *pXVariableTreeItem;
1419 pXVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(xVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1420 QString yVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getYVariable());
1421 VariablesTreeItem *pYVariableTreeItem;
1422 pYVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(yVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1423 pPlotCurve->detach();
1424 if (pXVariableTreeItem && pYVariableTreeItem) {
1425 bool state = mpVariablesTreeModel->blockSignals(true);
1426 QModelIndex xIndex = mpVariablesTreeModel->variablesTreeItemIndex(pXVariableTreeItem);
1427 mpVariablesTreeModel->setData(xIndex, Qt::Checked, Qt::CheckStateRole);
1428 plotVariables(xIndex, pPlotCurve->getCurveWidth(), pPlotCurve->getCurveStyle(), pPlotCurve, pPlotWindow);
1429 QModelIndex yIndex = mpVariablesTreeModel->variablesTreeItemIndex(pYVariableTreeItem);
1430 mpVariablesTreeModel->setData(yIndex, Qt::Checked, Qt::CheckStateRole);
1431 plotVariables(yIndex, pPlotCurve->getCurveWidth(), pPlotCurve->getCurveStyle(), pPlotCurve, pPlotWindow);
1432 mpVariablesTreeModel->blockSignals(state);
1433 } else {
1434 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1435 pPlotCurve->detach();
1436 }
1437 }
1438 }
1439 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1440 pPlotWindow->fitInView();
1441 } else {
1442 pPlotWindow->getPlot()->replot();
1443 }
1444 }
1445 }
1446 updateVariablesTreeHelper(MainWindow::instance()->getPlotWindowContainer()->currentSubWindow());
1447}
1448
1449void VariablesWidget::updateVariablesTreeHelper(QMdiSubWindow *pSubWindow)
1450{
1451 /* We always pause the visualization if we reach this function
1452 * This function can be reached via following ways,
1453 * When active PlotWindow is changed.
1454 * When active PlotWindow variables are updated.
1455 * When clearing the PlotWindow curves
1456 */
1457 pauseVisualization();
1458 if (!pSubWindow) {
1459 return;
1460 }
1461 // first clear all the check boxes in the tree
1462 bool state = mpVariablesTreeModel->blockSignals(true);
1463 mpVariablesTreeModel->unCheckVariables(mpVariablesTreeModel->getRootVariablesTreeItem());
1464 mpVariablesTreeModel->blockSignals(state);
1465 // all plotwindows are closed down then simply return
1466 if (MainWindow::instance()->getPlotWindowContainer()->subWindowList().size() == 0) {
1467 return;
1468 }
1469 PlotWindow *pPlotWindow = qobject_cast<PlotWindow*>(pSubWindow->widget());
1470 if (pPlotWindow) { // we can have an AnimateWindow there as well so always check
1471 // update the simulation time unit
1472 mpSimulationTimeComboBox->setCurrentIndex(mpSimulationTimeComboBox->findText(pPlotWindow->getTimeUnit(), Qt::MatchExactly));
1473 // now loop through the curves and tick variables in the tree whose curves are on the plot
1474 state = mpVariablesTreeModel->blockSignals(true);
1475 foreach (PlotCurve *pPlotCurve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (PlotCurve *pPlotCurve = *_container_.i; _container_
.control; _container_.control = 0)
{
1476 VariablesTreeItem *pVariablesTreeItem;
1477 if (pPlotWindow->getPlotType() == PlotWindow::PLOT || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY) {
1478 QString variable = pPlotCurve->getNameStructure();
1479 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(variable, mpVariablesTreeModel->getRootVariablesTreeItem());
1480 if (pVariablesTreeItem) {
1481 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1482 }
1483 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) {
1484 // check the xvariable
1485 QString xVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getXVariable());
1486 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(xVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1487 if (pVariablesTreeItem)
1488 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1489 // check the y variable
1490 QString yVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getYVariable());
1491 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(yVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1492 if (pVariablesTreeItem)
1493 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1494 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTINTERACTIVE) {
1495 QString variable = pPlotCurve->getNameStructure();
1496 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(variable, mpVariablesTreeModel->getRootVariablesTreeItem());
1497 if (pVariablesTreeItem) {
1498 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1499 }
1500 // if a simulation was left running, make a replot
1501 pPlotWindow->getPlot()->replot();
1502 }
1503 }
1504 mpVariablesTreeModel->blockSignals(state);
1505 }
1506 /* invalidate the view so that the items show the updated values. */
1507 mpVariableTreeProxyModel->invalidate();
1508}
1509
1510void VariablesWidget::interactiveReSimulation(QString modelName)
1511{
1512 QList<QString> selectedVariables = mSelectedInteractiveVariables.value(modelName);
1513
1514 foreach (QString variable, selectedVariables)for (auto _container_ = QtPrivate::qMakeForeachContainer(selectedVariables
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString variable
= *_container_.i; _container_.control; _container_.control =
0)
{
1515 QString curveNameStructure = modelName + "." + variable;
1516 VariablesTreeItem *pVariableTreeItem;
1517 pVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(curveNameStructure, mpVariablesTreeModel->getRootVariablesTreeItem());
1518 if (pVariableTreeItem) {
1519 bool state = mpVariablesTreeModel->blockSignals(true);
1520 QModelIndex index = mpVariablesTreeModel->variablesTreeItemIndex(pVariableTreeItem);
1521 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1522 plotVariables(index, 1, 1);
1523 mpVariablesTreeModel->blockSignals(state);
1524 }
1525 }
1526}
1527
1528/*!
1529 * \brief VariablesWidget::readVariablesAndUpdateXML
1530 * Reads the updated values
1531 * \sa VariablesWidget::findVariableAndUpdateValue()
1532 * \param pVariablesTreeItem
1533 * \param outputFileName
1534 * \param variables
1535 */
1536void VariablesWidget::readVariablesAndUpdateXML(VariablesTreeItem *pVariablesTreeItem, QString outputFileName,
1537 QHash<QString, QHash<QString, QString> > *variables)
1538{
1539 for (int i = 0 ; i < pVariablesTreeItem->getChildren().size() ; i++) {
1540 VariablesTreeItem *pChildVariablesTreeItem = pVariablesTreeItem->child(i);
1541 if (pChildVariablesTreeItem->isEditable() && pChildVariablesTreeItem->isValueChanged()) {
1542 //QString value = pChildVariablesTreeItem->data(1, Qt::DisplayRole).toString();
1543 /* Ticket #2250, 4031
1544 * We need to convert the value to base unit since the values stored in init xml are always in base unit.
1545 */
1546 QString value = pChildVariablesTreeItem->getValue(pChildVariablesTreeItem->getDisplayUnit(),
1547 pChildVariablesTreeItem->getUnit()).toString();
1548 QString variableToFind = pChildVariablesTreeItem->getVariableName();
1549 variableToFind.remove(QRegExp(outputFileName + "."));
1550 QHash<QString, QString> hash;
1551 hash["name"] = variableToFind;
1552 hash["value"] = value;
1553 variables->insert(variableToFind, hash);
1554 }
1555 readVariablesAndUpdateXML(pChildVariablesTreeItem, outputFileName, variables);
1556 }
1557}
1558
1559/*!
1560 * \brief VariablesWidget::findVariableAndUpdateValue
1561 * Writes the updated values in the init xml dom
1562 * \param xmlDocument
1563 * \param variables
1564 */
1565void VariablesWidget::findVariableAndUpdateValue(QDomDocument xmlDocument, QHash<QString, QHash<QString, QString> > variables)
1566{
1567 /* if no variables are changed. */
1568 if (variables.empty()) {
1569 return;
1570 }
1571 /* update the variables */
1572 int count = 0;
1573 QDomNodeList scalarVariable = xmlDocument.elementsByTagName("ScalarVariable");
1574 for (int i = 0; i < scalarVariable.size(); i++) {
1575 if (count >= variables.size()) {
1576 break;
1577 }
1578 QDomElement element = scalarVariable.at(i).toElement();
1579 if (!element.isNull()) {
1580 QHash<QString, QString> hash = variables.value(element.attribute("name"));
1581 if (element.attribute("name").compare(hash["name"]) == 0) {
1582 count++;
1583 QDomElement el = scalarVariable.at(i).firstChild().toElement();
1584 if (!el.isNull()) {
1585 el.setAttribute("start", hash["value"]);
1586 }
1587 }
1588 }
1589 }
1590}
1591
1592void VariablesWidget::reSimulate(bool showSetup)
1593{
1594 QModelIndexList indexes = mpVariablesTreeView->selectionModel()->selectedIndexes();
1595 if (indexes.isEmpty()) {
1596 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1597 tr("You must select a class to re-simulate."), Helper::ok);
1598 return;
1599 }
1600 QModelIndex index = indexes.at(0);
1601 index = mpVariableTreeProxyModel->mapToSource(index);
1602 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1603 pVariablesTreeItem = pVariablesTreeItem->rootParent();
1604 SimulationOptions simulationOptions = pVariablesTreeItem->getSimulationOptions();
1605 if (simulationOptions.isValid()) {
1606 if (simulationOptions.isInteractiveSimulation()) {
1607 QMessageBox::information(this, QString("%1 - %2").arg(Helper::applicationName, Helper::information),
1608 tr("You cannot re-simulate an interactive simulation."), Helper::ok);
1609 } else {
1610 simulationOptions.setReSimulate(true);
1611 updateInitXmlFile(simulationOptions);
1612 if (showSetup) {
1613 MainWindow::instance()->getSimulationDialog()->show(0, true, simulationOptions);
1614 } else {
1615 MainWindow::instance()->getSimulationDialog()->reSimulate(simulationOptions);
1616 }
1617 }
1618 } else {
1619 QMessageBox::information(this, QString("%1 - %2").arg(Helper::applicationName, Helper::information),
1620 tr("You cannot re-simulate this class.<br />This is just a result file loaded via menu <b>File->Open Result File(s)</b>."), Helper::ok);
1621 }
1622}
1623
1624void VariablesWidget::updateInitXmlFile(SimulationOptions simulationOptions)
1625{
1626 /* Update the _init.xml file with new values. */
1627 /* open the model_init.xml file for writing */
1628 QString initFileName = QString(simulationOptions.getOutputFileName()).append("_init.xml");
1629 QFile initFile(QString(simulationOptions.getWorkingDirectory()).append(QDir::separator()).append(initFileName));
1630 QDomDocument initXmlDocument;
1631 if (initFile.open(QIODevice::ReadOnly)) {
1632 if (initXmlDocument.setContent(&initFile)) {
1633 VariablesTreeItem *pTopVariableTreeItem;
1634 pTopVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(simulationOptions.getFullResultFileName(),
1635 mpVariablesTreeModel->getRootVariablesTreeItem());
1636 if (pTopVariableTreeItem) {
1637 QHash<QString, QHash<QString, QString> > variables;
1638 readVariablesAndUpdateXML(pTopVariableTreeItem, simulationOptions.getFullResultFileName(), &variables);
1639 findVariableAndUpdateValue(initXmlDocument, variables);
1640 }
1641 } else {
1642 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
1643 tr("Unable to set the content of QDomDocument from file %1")
1644 .arg(initFile.fileName()), Helper::scriptingKind, Helper::errorLevel));
1645 }
1646 initFile.close();
1647 initFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
1648 QTextStream textStream(&initFile);
1649 textStream.setCodec(Helper::utf8.toUtf8().constData());
1650 textStream.setGenerateByteOrderMark(false);
1651 textStream << initXmlDocument.toString();
1652 initFile.close();
1653 } else {
1654 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
1655 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(initFile.fileName())
1656 .arg(initFile.errorString()), Helper::scriptingKind, Helper::errorLevel));
1657 }
1658}
1659
1660/*!
1661 * \brief VariablesWidget::initializeVisualization
1662 * Initializes the TimeManager with SimulationOptions for Visualization.
1663 * \param simulationOptions
1664 */
1665void VariablesWidget::initializeVisualization(SimulationOptions simulationOptions)
1666{
1667 // close any result file before opening a new one
1668 closeResultFile();
1669 // Open the file for reading
1670 openResultFile();
1671 // Initialize the time manager
1672 mpTimeManager->setStartTime(simulationOptions.getStartTime().toDouble());
1673 mpTimeManager->setEndTime(simulationOptions.getStopTime().toDouble());
1674 mpTimeManager->setVisTime(mpTimeManager->getStartTime());
1675 mpTimeManager->setPause(true);
1676 // reset the visualization controls
1677 mpTimeTextBox->setText("0.0");
1678 mpSimulationTimeSlider->setValue(mpSimulationTimeSlider->minimum());
1679 enableVisualizationControls(true);
1680}
1681
1682/*!
1683 * \brief VariablesWidget::readVariableValue
1684 * Reads the variable value at specific time.
1685 * \param variable
1686 * \param time
1687 * \return
1688 */
1689double VariablesWidget::readVariableValue(QString variable, double time)
1690{
1691 double value = 0.0;
1692 if (mModelicaMatReader.file) {
1693 ModelicaMatVariable_t* var = omc_matlab4_find_var(&mModelicaMatReader, variable.toUtf8().constData());
1694 if (var) {
1695 omc_matlab4_val(&value, &mModelicaMatReader, var, time);
1696 }
1697 } else if (mpCSVData) {
1698 double *timeDataSet = read_csv_dataset(mpCSVData, "time");
1699 if (timeDataSet) {
1700 for (int i = 0 ; i < mpCSVData->numsteps ; i++) {
1701 if (QString::number(timeDataSet[i]).compare(QString::number(time)) == 0) {
1702 double *varDataSet = read_csv_dataset(mpCSVData, variable.toUtf8().constData());
1703 if (varDataSet) {
1704 value = varDataSet[i];
1705 break;
1706 }
1707 }
1708 }
1709 }
1710 } else if (mPlotFileReader.isOpen()) {
1711 QTextStream textStream(&mPlotFileReader);
1712 QString currentLine;
1713 bool variableFound = false;
1714 while (!textStream.atEnd()) {
1715 currentLine = textStream.readLine();
1716 if (currentLine.compare(QString("DataSet: %1").arg(variable)) == 0) {
1717 variableFound = true;
1718 } else if (variableFound) {
1719 if (currentLine.startsWith("DataSet:")) { // new dataset started. Unable to find the value.
1720 break;
1721 }
1722 QStringList values = currentLine.split(",");
1723 if (QString::number(time).compare(values[0]) == 0) {
1724 value = values[1].toDouble();
1725 break;
1726 }
1727 }
1728 }
1729 textStream.seek(0);
1730 }
1731 return value;
1732}
1733
1734void VariablesWidget::plotVariables(const QModelIndex &index, qreal curveThickness, int curveStyle, PlotCurve *pPlotCurve,
1735 PlotWindow *pPlotWindow)
1736{
1737 if (index.column() > 0) {
1738 return;
1739 }
1740 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1741 if (!pVariablesTreeItem) {
1742 return;
1743 }
1744 try {
1745 // if pPlotWindow is 0 then get the current window.
1746 if (!pPlotWindow) {
1747 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
1748 }
1749 // if the variable is not an array and
1750 // pPlotWindow is 0 or the plot's type is PLOTARRAY or PLOTARRAYPARAMETRIC
1751 // then create a new plot window.
1752 if (!pVariablesTreeItem->isMainArray() &&
1753 (!pPlotWindow || pPlotWindow->getPlotType()==PlotWindow::PLOTARRAY
1754 || pPlotWindow->getPlotType()== PlotWindow::PLOTARRAYPARAMETRIC))
1755 {
1756 MainWindow::instance()->getPlotWindowContainer()->addPlotWindow();
1757 bool state = MainWindow::instance()->getPlotWindowContainer()->blockSignals(true);
1758 bool state2 = mpVariablesTreeModel->blockSignals(true);
1759 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1760 mpVariablesTreeModel->blockSignals(state2);
1761 MainWindow::instance()->getPlotWindowContainer()->blockSignals(state);
1762 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
1763 }
1764 // if the variable is an array and
1765 // pPlotWindow is 0 or the plot's type is PLOT or PLOTPARAMETRIC
1766 // then create a new plot window.
1767 else if (pVariablesTreeItem->isMainArray() &&
1768 (!pPlotWindow || pPlotWindow->getPlotType()==PlotWindow::PLOT ||
1769 pPlotWindow->getPlotType()==PlotWindow::PLOTPARAMETRIC))
1770 {
1771 MainWindow::instance()->getPlotWindowContainer()->addArrayPlotWindow();
1772 bool state = MainWindow::instance()->getPlotWindowContainer()->blockSignals(true);
1773 bool state2 = mpVariablesTreeModel->blockSignals(true);
1774 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1775 mpVariablesTreeModel->blockSignals(state2);
1776 MainWindow::instance()->getPlotWindowContainer()->blockSignals(state);
1777 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
1778 }
1779
1780
1781
1782 // if still pPlotWindow is 0 then return.
1783 if (!pPlotWindow) {
1784 bool state = mpVariablesTreeModel->blockSignals(true);
1785 mpVariablesTreeModel->setData(index, Qt::Unchecked, Qt::CheckStateRole);
1786 mpVariablesTreeModel->blockSignals(state);
1787 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1788 tr("No plot window is active for plotting. Please select a plot window or open a new."), Helper::ok);
1789 return;
1790 }
1791 // if plottype is PLOT or PLOTARRAY then
1792 if (pPlotWindow->getPlotType() == PlotWindow::PLOT || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY) {
1793 // check the item checkstate
1794 if (pVariablesTreeItem->isChecked()) {
1795 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
1796 if (!pVariablesTreeItem->isRootItem()) {
1797 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
1798 }
1799 if (pVariablesTreeRootItem->getSimulationOptions().isInteractiveSimulation()) {
1800 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1801 tr("Can not be attached to a plot window."), Helper::ok);
1802 pVariablesTreeItem->setChecked(false);
1803 return;
1804 }
1805 pPlotWindow->initializeFile(QString(pVariablesTreeItem->getFilePath()).append("/").append(pVariablesTreeItem->getFileName()));
1806 pPlotWindow->setCurveWidth(curveThickness);
1807 pPlotWindow->setCurveStyle(curveStyle);
1808 pPlotWindow->setVariablesList(QStringList(pVariablesTreeItem->getPlotVariable()));
1809 pPlotWindow->setUnit(pVariablesTreeItem->getUnit());
1810 pPlotWindow->setDisplayUnit(pVariablesTreeItem->getDisplayUnit());
1811 if (pPlotWindow->getPlotType() == PlotWindow::PLOT)
1812 pPlotWindow->plot(pPlotCurve);
1813 else/* ie. (pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY)*/{
1814 double timePercent = mpTimeTextBox->text().toDouble();
1815 pPlotWindow->plotArray(timePercent,pPlotCurve);
1816 }
1817 /* Ticket:4231
1818 * Only update the variables browser value and unit when updating some curve not when checking/unchecking variable.
1819 */
1820 if (pPlotCurve) {
1821 /* Ticket:2250
1822 * Update the value of Variables Browser display unit according to the display unit of already plotted curve.
1823 */
1824 pVariablesTreeItem->setData(3, pPlotCurve->getDisplayUnit(), Qt::EditRole);
1825 QString value = pVariablesTreeItem->getValue(pVariablesTreeItem->getPreviousUnit(), pVariablesTreeItem->getDisplayUnit()).toString();
1826 pVariablesTreeItem->setData(1, value, Qt::EditRole);
1827 }
1828 if (!pPlotCurve) {
1829 pPlotCurve = pPlotWindow->getPlot()->getPlotCurvesList().last();
1830 }
1831 if (pPlotCurve && pVariablesTreeItem->getUnit().compare(pVariablesTreeItem->getDisplayUnit()) != 0) {
1832 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(pVariablesTreeItem->getUnit(),
1833 pVariablesTreeItem->getDisplayUnit());
1834 if (convertUnit.unitsCompatible) {
1835 for (int i = 0 ; i < pPlotCurve->mYAxisVector.size() ; i++) {
1836 pPlotCurve->updateYAxisValue(i, Utilities::convertUnit(pPlotCurve->mYAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
1837 }
1838 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
1839 pPlotWindow->getPlot()->replot();
1840 } else {
1841 pPlotCurve->setDisplayUnit(pVariablesTreeItem->getUnit());
1842 }
1843 pPlotCurve->setTitleLocal();
1844 }
1845 // update the time values if time unit is different then s
1846 if (pPlotWindow->getTimeUnit().compare("s") != 0) {
1847 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits("s", pPlotWindow->getTimeUnit());
1848 if (convertUnit.unitsCompatible) {
1849 for (int i = 0 ; i < pPlotCurve->mXAxisVector.size() ; i++) {
1850 pPlotCurve->updateXAxisValue(i, Utilities::convertUnit(pPlotCurve->mXAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
1851 }
1852 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
1853 pPlotWindow->getPlot()->replot();
1854 }
1855 }
1856 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1857 pPlotWindow->fitInView();
1858 } else {
1859 pPlotWindow->getPlot()->replot();
1860 if (pPlotWindow->getPlot()->getPlotZoomer()->zoomStack().size() == 1) {
1861 pPlotWindow->getPlot()->getPlotZoomer()->setZoomBase(false);
1862 }
1863 }
1864 } else if (!pVariablesTreeItem->isChecked()) { // if user unchecks the variable then remove it from the plot
1865 foreach (PlotCurve *pPlotCurve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (PlotCurve *pPlotCurve = *_container_.i; _container_
.control; _container_.control = 0)
{
1866 QString curveTitle = pPlotCurve->getNameStructure();
1867 if (curveTitle.compare(pVariablesTreeItem->getVariableName()) == 0) {
1868 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1869 pPlotCurve->detach();
1870 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1871 pPlotWindow->fitInView();
1872 } else {
1873 pPlotWindow->getPlot()->replot();
1874 }
1875 break;
1876 }
1877 }
1878 }
1879 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) { // if plottype is PLOTPARAMETRIC or PLOTARRAYPARAMETRIC then
1880 // check the item checkstate
1881 if (pVariablesTreeItem->isChecked()) {
1882 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
1883 if (!pVariablesTreeItem->isRootItem()) {
1884 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
1885 }
1886 if (pVariablesTreeRootItem->getSimulationOptions().isInteractiveSimulation()) {
1887 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1888 tr("Can not be attached to a parametric plot window."), Helper::ok);
1889 pVariablesTreeItem->setChecked(false);
1890 return;
1891 }
1892 // if mPlotParametricVariables is empty just add one QStringlist with 1 varibale to it
1893 if (mPlotParametricVariables.isEmpty()) {
1894 mPlotParametricVariables.append(QStringList() << pVariablesTreeItem->getPlotVariable() << pVariablesTreeItem->getUnit());
1895 mFileName = pVariablesTreeItem->getFileName();
1896 } else { // if mPlotParametricVariables is not empty then add one string to its last element
1897 if (mPlotParametricVariables.last().size() < 4) {
1898 if (mFileName.compare(pVariablesTreeItem->getFileName()) != 0) {
1899 bool state = mpVariablesTreeModel->blockSignals(true);
1900 mpVariablesTreeModel->setData(index, Qt::Unchecked, Qt::CheckStateRole);
1901 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error),
1902 GUIMessages::getMessage(GUIMessages::PLOT_PARAMETRIC_DIFF_FILES), Helper::ok);
1903 mpVariablesTreeModel->blockSignals(state);
1904 return;
1905 }
1906 mPlotParametricVariables.last().append(QStringList() << pVariablesTreeItem->getPlotVariable() << pVariablesTreeItem->getUnit());
1907 pPlotWindow->initializeFile(QString(pVariablesTreeItem->getFilePath()).append("/").append(pVariablesTreeItem->getFileName()));
1908 pPlotWindow->setCurveWidth(curveThickness);
1909 pPlotWindow->setCurveStyle(curveStyle);
1910 pPlotWindow->setVariablesList(QStringList() << mPlotParametricVariables.last().at(0) << mPlotParametricVariables.last().at(2));
1911 if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC)
1912 pPlotWindow->plotParametric(pPlotCurve);
1913 else /* ie. (pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC)*/{
1914 double timePercent = mpTimeTextBox->text().toDouble();
1915 pPlotWindow->plotArrayParametric(timePercent,pPlotCurve);
1916 }
1917
1918 if (pPlotWindow->getPlot()->getPlotCurvesList().size() > 1) {
1919 pPlotWindow->setXLabel("");
1920 pPlotWindow->setYLabel("");
1921 } else {
1922 QString xVariable = mPlotParametricVariables.last().at(0);
1923 QString xUnit = mPlotParametricVariables.last().at(1);
1924 QString yVariable = mPlotParametricVariables.last().at(2);
1925 QString yUnit = mPlotParametricVariables.last().at(3);
1926 if (xUnit.isEmpty()) {
1927 pPlotWindow->setXLabel(xVariable);
1928 } else {
1929 pPlotWindow->setXLabel(xVariable + " (" + xUnit + ")");
1930 }
1931
1932 if (yUnit.isEmpty()) {
1933 pPlotWindow->setYLabel(yVariable);
1934 } else {
1935 pPlotWindow->setYLabel(yVariable + " (" + yUnit + ")");
1936 }
1937 }
1938 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1939 pPlotWindow->fitInView();
1940 } else {
1941 pPlotWindow->getPlot()->replot();
1942 if (pPlotWindow->getPlot()->getPlotZoomer()->zoomStack().size() == 1) {
1943 pPlotWindow->getPlot()->getPlotZoomer()->setZoomBase(false);
1944 }
1945 }
1946 } else {
1947 mPlotParametricVariables.append(QStringList() << pVariablesTreeItem->getPlotVariable() << pVariablesTreeItem->getUnit());
1948 mFileName = pVariablesTreeItem->getFileName();
1949 }
1950 }
1951 } else if (!pVariablesTreeItem->isChecked()) { // if user unchecks the variable then remove it from the plot
1952 // remove the variable from mPlotParametricVariables list
1953 foreach (QStringList list, mPlotParametricVariables)for (auto _container_ = QtPrivate::qMakeForeachContainer(mPlotParametricVariables
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QStringList
list = *_container_.i; _container_.control; _container_.control
= 0)
{
1954 if (list.contains(pVariablesTreeItem->getPlotVariable())) {
1955 // if list has only one variable then clear the list and return;
1956 if (list.size() < 4) {
1957 mPlotParametricVariables.removeOne(list);
1958 break;
1959 } else { // if list has more than two variables then remove both and remove the curve
1960 QString itemTitle = QString(pVariablesTreeItem->getFileName()).append(".").append(list.at(2)).append(" vs ").append(list.at(0));
1961 foreach (PlotCurve *pPlotCurve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (PlotCurve *pPlotCurve = *_container_.i; _container_
.control; _container_.control = 0)
{
1962 QString curveTitle = pPlotCurve->getNameStructure();
1963 if ((curveTitle.compare(itemTitle) == 0) && (pVariablesTreeItem->getFileName().compare(pPlotCurve->getFileName()) == 0)) {
1964 bool state = mpVariablesTreeModel->blockSignals(true);
1965 // uncheck the x variable
1966 QString xVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getXVariable());
1967 VariablesTreeItem *pVariablesTreeItem;
1968 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(xVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1969 if (pVariablesTreeItem) {
1970 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Unchecked, Qt::CheckStateRole);
1971 }
1972 // uncheck the y variable
1973 QString yVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getYVariable());
1974 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(yVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1975 if (pVariablesTreeItem) {
1976 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Unchecked, Qt::CheckStateRole);
1977 }
1978 mpVariablesTreeModel->blockSignals(state);
1979 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1980 pPlotCurve->detach();
1981 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1982 pPlotWindow->fitInView();
1983 } else {
1984 pPlotWindow->getPlot()->replot();
1985 }
1986 }
1987 }
1988 mPlotParametricVariables.removeOne(list);
1989 if (pPlotWindow->getPlot()->getPlotCurvesList().size() == 1) {
1990 if (mPlotParametricVariables.last().size() > 3) {
1991 QString xVariable = mPlotParametricVariables.last().at(0);
1992 QString xUnit = mPlotParametricVariables.last().at(1);
1993 QString yVariable = mPlotParametricVariables.last().at(2);
1994 QString yUnit = mPlotParametricVariables.last().at(3);
1995 if (xUnit.isEmpty()) {
1996 pPlotWindow->setXLabel(xVariable);
1997 } else {
1998 pPlotWindow->setXLabel(xVariable + " (" + xUnit + ")");
1999 }
2000
2001 if (yUnit.isEmpty()) {
2002 pPlotWindow->setYLabel(yVariable);
2003 } else {
2004 pPlotWindow->setYLabel(yVariable + " (" + yUnit + ")");
2005 }
2006 } else {
2007 pPlotWindow->setXLabel("");
2008 pPlotWindow->setYLabel("");
2009 }
2010 } else {
2011 pPlotWindow->setXLabel("");
2012 pPlotWindow->setYLabel("");
2013 }
2014 }
2015 }
2016 }
2017 }
2018 }
2019 else { // if plottype is INTERACTIVE then
2020 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
2021 if (!pVariablesTreeItem->isRootItem()) {
2022 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
2023 }
2024 int port = pVariablesTreeRootItem->getSimulationOptions().getInteractiveSimulationPortNumber();
2025
2026 if (pVariablesTreeItem->isChecked()) { // if user checks the variable
2027 if (!pVariablesTreeRootItem->getSimulationOptions().isInteractiveSimulation()) {
2028 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
2029 tr("Can not be attached to an interactive plot window."), Helper::ok);
2030 pVariablesTreeItem->setChecked(false);
2031 } else {
2032 // if user checks a variable belonging to an inactive plot window, switch to it.
2033 if (pPlotWindow->getInteractiveOwner() != pVariablesTreeRootItem->getFileName()) {
2034 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getInteractiveWindow(pVariablesTreeRootItem->getFileName());
2035 MainWindow::instance()->getPlotWindowContainer()->setActiveSubWindow(pPlotWindow->getSubWindow());
2036 } else {
2037 pPlotWindow->setCurveWidth(curveThickness);
2038 pPlotWindow->setCurveStyle(curveStyle);
2039 QString plotVariable = pVariablesTreeItem->getPlotVariable();
2040 pPlotWindow->setVariablesList(QStringList(plotVariable));
2041 pPlotWindow->setUnit(pVariablesTreeItem->getUnit());
2042 pPlotWindow->setDisplayUnit(pVariablesTreeItem->getDisplayUnit());
2043 pPlotWindow->setInteractiveModelName(pVariablesTreeItem->getFileName());
2044 OpcUaClient *pOpcUaClient = MainWindow::instance()->getSimulationDialog()->getOpcUaClient(port);
2045 if (pOpcUaClient) {
2046 Variable *pCurveData = *pOpcUaClient->getVariables()->find(plotVariable);
2047 QwtSeriesData<QPointF>* pData = dynamic_cast<QwtSeriesData<QPointF>*>(pCurveData);
2048 pPlotWindow->setInteractivePlotData(pData);
2049 QPair<QVector<double>*, QVector<double>*> memory = pPlotWindow->plotInteractive(pPlotCurve);
2050 // use the same vectors as a normal plot
2051 pCurveData->setAxisVectors(memory);
2052 pOpcUaClient->checkVariable(pCurveData->getNodeId(), pVariablesTreeItem);
2053 }
2054 }
2055 }
2056 }
2057 else if (!pVariablesTreeItem->isChecked()) { // if user unchecks the variable
2058 // remove the variable from the data fetch list
2059 OpcUaClient *pOpcUaClient = MainWindow::instance()->getSimulationDialog()->getOpcUaClient(port);
2060 if (pOpcUaClient) {
2061 Variable *pCurveData = *pOpcUaClient->getVariables()->find(pVariablesTreeItem->getPlotVariable());
2062 pOpcUaClient->unCheckVariable(pCurveData->getNodeId(), pVariablesTreeItem->getPlotVariable());
2063 }
2064 foreach (PlotCurve *pPlotCurve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (PlotCurve *pPlotCurve = *_container_.i; _container_
.control; _container_.control = 0)
{
2065 /* FIX: Make sure to remove the right curve when implementing several interactive simulations at the same time */
2066 if (pVariablesTreeItem->getVariableName().endsWith("." + pPlotCurve->getName())) {
2067 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
2068 pPlotCurve->detach();
2069 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
2070 pPlotWindow->fitInView();
2071 } else {
2072 pPlotWindow->getPlot()->replot();
2073 }
2074 break;
2075 }
2076 }
2077 }
2078 }
2079 } catch (PlotException &e) {
2080 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2081 }
2082}
2083
2084void VariablesWidget::addSelectedInteractiveVariables(const QString &modelName, const QList<QString> &selectedVariables)
2085{
2086 mSelectedInteractiveVariables.insert(modelName, selectedVariables);
2087}
2088
2089/*!
2090 * \brief VariablesWidget::unitChanged
2091 * Handles the case when display unit is changed in VariablesTreeView.\n
2092 * Updates the values according to the new display unit.
2093 * \param index
2094 */
2095void VariablesWidget::unitChanged(const QModelIndex &index)
2096{
2097 if (index.column() != 3) {
2098 return;
2099 }
2100 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
2101 if (!pVariablesTreeItem) {
2102 return;
2103 }
2104 try {
2105 OMPlot::PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2106 // if still pPlotWindow is 0 then return.
2107 if (!pPlotWindow) {
2108 return;
2109 }
2110 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(pVariablesTreeItem->getPreviousUnit(),
2111 pVariablesTreeItem->getDisplayUnit());
2112 if (convertUnit.unitsCompatible) {
2113 /* update value */
2114 QVariant stringValue = pVariablesTreeItem->data(1, Qt::EditRole);
2115 bool ok = true;
2116 qreal realValue = stringValue.toDouble(&ok);
2117 if (ok) {
2118 realValue = Utilities::convertUnit(realValue, convertUnit.offset, convertUnit.scaleFactor);
2119 pVariablesTreeItem->setData(1, StringHandler::number(realValue), Qt::EditRole);
2120 }
2121 /* update plots */
2122 foreach (PlotCurve *pPlotCurve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (PlotCurve *pPlotCurve = *_container_.i; _container_
.control; _container_.control = 0)
{
2123 QString curveTitle = pPlotCurve->getNameStructure();
2124 if (curveTitle.compare(pVariablesTreeItem->getVariableName()) == 0) {
2125 for (int i = 0 ; i < pPlotCurve->mYAxisVector.size() ; i++) {
2126 pPlotCurve->updateYAxisValue(i, Utilities::convertUnit(pPlotCurve->mYAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
2127 }
2128 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
2129 pPlotCurve->setDisplayUnit(pVariablesTreeItem->getDisplayUnit());
2130 pPlotCurve->setTitleLocal();
2131 pPlotWindow->getPlot()->replot();
2132 break;
2133 }
2134 }
2135 }
2136 } catch (PlotException &e) {
2137 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2138 }
2139}
2140
2141/*!
2142 * \brief VariablesWidget::simulationTimeChanged
2143 * SLOT activated when mpSimulationTimeSlider valueChanged SIGNAL is raised.
2144 * \param time
2145 */
2146void VariablesWidget::simulationTimeChanged(int timePercent)
2147{
2148 double time = (mpTimeManager->getEndTime() - mpTimeManager->getStartTime()) * ((double)timePercent / (double)mSliderRange);
2149 mpTimeManager->setVisTime(time);
2150 mpTimeTextBox->setText(QString::number(mpTimeManager->getVisTime()));
2151
2152 PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2153 if (pPlotWindow) {
2154 try {
2155 PlotWindow::PlotType plotType = pPlotWindow->getPlotType();
2156 if (plotType == PlotWindow::PLOTARRAY) {
2157 QList<PlotCurve*> curves = pPlotWindow->getPlot()->getPlotCurvesList();
2158 foreach (PlotCurve* curve, curves)for (auto _container_ = QtPrivate::qMakeForeachContainer(curves
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (PlotCurve
* curve = *_container_.i; _container_.control; _container_.control
= 0)
{
2159 QString varName = curve->getYVariable();
2160 pPlotWindow->setVariablesList(QStringList(varName));
2161 pPlotWindow->plotArray(time, curve);
2162 }
2163 } else if (plotType == PlotWindow::PLOTARRAYPARAMETRIC) {
2164 QList<PlotCurve*> curves = pPlotWindow->getPlot()->getPlotCurvesList();
2165 foreach (PlotCurve* curve, curves)for (auto _container_ = QtPrivate::qMakeForeachContainer(curves
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (PlotCurve
* curve = *_container_.i; _container_.control; _container_.control
= 0)
{
2166 QString xVarName = curve->getXVariable();
2167 QString yVarName = curve->getYVariable();
2168 pPlotWindow->setVariablesList({xVarName,yVarName});
2169 pPlotWindow->plotArrayParametric(time, curve);
2170 }
2171 } else {
2172 return;
2173 }
2174 } catch (PlotException &e) {
2175 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, e.what(), Helper::scriptingKind, Helper::errorLevel));
2176 }
2177 } else { // if no plot window then try to update the DiagramWindow
2178 updateVisualization();
2179 }
2180}
2181/*!
2182 * \brief VariablesWidget::valueEntered
2183 * Handles the case when a new value is entered in VariablesTreeView.\n
2184 * \param index
2185 */
2186void VariablesWidget::valueEntered(const QModelIndex &index)
2187{
2188 if (index.column() != 1) {
2189 return;
2190 }
2191 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
2192 if (!pVariablesTreeItem) {
2193 return;
2194 }
2195 try {
2196 OMPlot::PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2197 // if still pPlotWindow is 0 then return.
2198 if (!pPlotWindow) {
2199 return;
2200 }
2201 QVariant variableValue = pVariablesTreeItem->getValue(pVariablesTreeItem->getDisplayUnit(), pVariablesTreeItem->getUnit()).toDouble();
2202 QString variableName = pVariablesTreeItem->getPlotVariable();
2203 // make sure the write goes to the right server
2204 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
2205 if (!pVariablesTreeItem->isRootItem()) {
2206 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
2207 }
2208 int port = pVariablesTreeRootItem->getSimulationOptions().getInteractiveSimulationPortNumber();
2209 OpcUaClient *pOpcUaClient = MainWindow::instance()->getSimulationDialog()->getOpcUaClient(port);
2210 if (pOpcUaClient) {
2211 pOpcUaClient->writeValue(variableValue, variableName);
2212 }
2213
2214 } catch (PlotException &e) {
2215 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2216 }
2217}
2218
2219void VariablesWidget::selectInteractivePlotWindow(VariablesTreeItem *pVariablesTreeItem)
2220{
2221 // look at the root parent
2222 if (!pVariablesTreeItem->isRootItem()) {
2223 pVariablesTreeItem = pVariablesTreeItem->rootParent();
2224 }
2225 // change to the corresponding subwindow
2226 if (pVariablesTreeItem->getSimulationOptions().isInteractiveSimulation()) {
2227 foreach (QMdiSubWindow *pSubWindow, MainWindow::instance()->getPlotWindowContainer()->subWindowList(QMdiArea::StackingOrder))for (auto _container_ = QtPrivate::qMakeForeachContainer(MainWindow
::instance()->getPlotWindowContainer()->subWindowList(QMdiArea
::StackingOrder)); _container_.control && _container_
.i != _container_.e; ++_container_.i, _container_.control ^= 1
) for (QMdiSubWindow *pSubWindow = *_container_.i; _container_
.control; _container_.control = 0)
{
2228 PlotWindow *pPlotWindow = qobject_cast<PlotWindow*>(pSubWindow->widget());
2229 if (pPlotWindow->getInteractiveOwner() == pVariablesTreeItem->getFileName()) {
2230 MainWindow::instance()->getPlotWindowContainer()->setActiveSubWindow(pSubWindow);
2231 }
2232 }
2233 }
2234}
2235
2236/*!
2237 * \brief VariablesWidget::closeResultFile
2238 * Closes the result file.
2239 */
2240void VariablesWidget::closeResultFile()
2241{
2242 if (mModelicaMatReader.file) {
2243 omc_free_matlab4_reader(&mModelicaMatReader);
2244 mModelicaMatReader.file = 0;
2245 }
2246 if (mpCSVData) {
2247 omc_free_csv_reader(mpCSVData);
2248 mpCSVData = 0;
2249 }
2250 if (mPlotFileReader.isOpen()) {
2251 mPlotFileReader.close();
2252 }
2253}
2254
2255/*!
2256 * \brief VariablesWidget::openResultFile
2257 * Opens the result file.
2258 */
2259void VariablesWidget::openResultFile()
2260{
2261 if (mpVariablesTreeModel->getActiveVariablesTreeItem()) {
2262 // read filename
2263 QString fileName = QString("%1/%2").arg(mpVariablesTreeModel->getActiveVariablesTreeItem()->getFilePath())
2264 .arg(mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName());
2265 bool errorOpeningFile = false;
2266 QString errorString = "";
2267 if (mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName().endsWith(".mat")) {
2268 const char *msg[] = {""};
2269 if (0 != (msg[0] = omc_new_matlab4_reader(fileName.toUtf8().constData(), &mModelicaMatReader))) {
2270 errorOpeningFile = true;
2271 errorString = msg[0];
2272 }
2273 } else if (mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName().endsWith(".csv")) {
2274 mpCSVData = read_csv(fileName.toUtf8().constData());
2275 if (!mpCSVData) {
2276 errorOpeningFile = true;
2277 }
2278 } else if (mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName().endsWith(".plt")) {
2279 mPlotFileReader.setFileName(fileName);
2280 if (!mPlotFileReader.open(QIODevice::ReadOnly)) {
2281 errorOpeningFile = true;
2282 errorString = mPlotFileReader.errorString();
2283 }
2284 }
2285 // check file opening error
2286 if (errorOpeningFile) {
2287 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
2288 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE)
2289 .arg(fileName, errorString), Helper::scriptingKind, Helper::errorLevel));
2290 }
2291 }
2292}
2293
2294/*!
2295 * \brief VariablesWidget::updateVisualization
2296 * Updates the visualization.
2297 */
2298void VariablesWidget::updateVisualization()
2299{
2300 mpTimeManager->updateTick(); //for real-time measurement
2301 double visTime = mpTimeManager->getRealTime();
2302 // Update the DiagramWindow
2303 emit updateDynamicSelect(mpTimeManager->getVisTime());
2304 if (MainWindow::instance()->getPlotWindowContainer()->getDiagramWindow()
2305 && MainWindow::instance()->getPlotWindowContainer()->getDiagramWindow()->getGraphicsView()) {
2306 MainWindow::instance()->getPlotWindowContainer()->getDiagramWindow()->getGraphicsView()->scene()->update();
2307 }
2308 mpTimeManager->updateTick(); //for real-time measurement
2309 visTime = mpTimeManager->getRealTime() - visTime;
2310 mpTimeManager->setRealTimeFactor(mpTimeManager->getHVisual() / visTime);
2311}
2312
2313/*!
2314 * \brief VariablesWidget::timeUnitChanged
2315 * Handles the case when simulation time unit is changed.\n
2316 * Updates the x values of all the curves.
2317 * \param unit
2318 */
2319void VariablesWidget::timeUnitChanged(QString unit)
2320{
2321 if (unit.isEmpty()) {
2322 return;
2323 }
2324 try {
2325 OMPlot::PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2326 // if still pPlotWindow is 0 then return.
2327 if (!pPlotWindow) {
2328 return;
2329 }
2330 if (pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY ||
2331 pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) {
2332 pPlotWindow->setTimeUnit(unit);
2333 pPlotWindow->updateTimeText(unit);
2334 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOT ||
2335 pPlotWindow->getPlotType() == PlotWindow::PLOTINTERACTIVE) {
2336 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(pPlotWindow->getTimeUnit(), unit);
2337 if (convertUnit.unitsCompatible) {
2338 foreach (PlotCurve *pPlotCurve, pPlotWindow->getPlot()->getPlotCurvesList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pPlotWindow
->getPlot()->getPlotCurvesList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (PlotCurve *pPlotCurve = *_container_.i; _container_
.control; _container_.control = 0)
{
2339 for (int i = 0 ; i < pPlotCurve->mXAxisVector.size() ; i++) {
2340 pPlotCurve->updateXAxisValue(i, Utilities::convertUnit(pPlotCurve->mXAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
2341 }
2342 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
2343 }
2344 pPlotWindow->setXLabel(QString("time (%1)").arg(unit));
2345 pPlotWindow->setTimeUnit(unit);
2346 pPlotWindow->getPlot()->replot();
2347 }
2348 }
2349 } catch (PlotException &e) {
2350 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2351 }
2352}
2353
2354/*!
2355 * \brief VariablesWidget::updateVariablesTree
2356 * Updates the VariablesTreeView when the subwindow is changed in PlotWindowContainer
2357 * \param pSubWindow
2358 */
2359void VariablesWidget::updateVariablesTree(QMdiSubWindow *pSubWindow)
2360{
2361 MainWindow::instance()->getModelWidgetContainer()->currentModelWidgetChanged(0);
2362 if (!pSubWindow && MainWindow::instance()->getPlotWindowContainer()->subWindowList().size() != 0) {
2363 return;
2364 }
2365 /* if the same sub window is activated again then just return */
2366 if (mpLastActiveSubWindow == pSubWindow) {
2367 mpLastActiveSubWindow = pSubWindow;
2368 return;
2369 }
2370 mpLastActiveSubWindow = pSubWindow;
2371 updateVariablesTreeHelper(pSubWindow);
2372}
2373
2374void VariablesWidget::showContextMenu(QPoint point)
2375{
2376 int adjust = 24;
2377 QModelIndex index = mpVariablesTreeView->indexAt(point);
2378 index = mpVariableTreeProxyModel->mapToSource(index);
2379 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
2380 if (pVariablesTreeItem && pVariablesTreeItem->isRootItem()) {
2381 /* delete result action */
2382 QAction *pDeleteResultAction = new QAction(QIcon(":/Resources/icons/delete.svg"), tr("Delete Result"), this);
2383 pDeleteResultAction->setData(pVariablesTreeItem->getVariableName());
2384 pDeleteResultAction->setShortcut(QKeySequence::Delete);
2385 pDeleteResultAction->setStatusTip(tr("Delete the result"));
2386 connect(pDeleteResultAction, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(removeVariableTreeItem())"1""removeVariableTreeItem()");
2387
2388 /* set result active action */
2389 QAction *pSetResultActiveAction = new QAction(tr("Set Active"), this);
2390 pSetResultActiveAction->setData(pVariablesTreeItem->getVariableName());
2391 pSetResultActiveAction->setStatusTip(tr("An active item is used for the visualization"));
2392 pSetResultActiveAction->setEnabled(pVariablesTreeItem->getSimulationOptions().isValid()
2393 && !pVariablesTreeItem->getSimulationOptions().isInteractiveSimulation()
2394 && !pVariablesTreeItem->isActive());
2395 connect(pSetResultActiveAction, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(setVariableTreeItemActive())"1""setVariableTreeItemActive()");
2396
2397 QMenu menu(this);
2398 menu.addAction(pDeleteResultAction);
2399 menu.addSeparator();
2400 menu.addAction(pSetResultActiveAction);
2401 menu.addSeparator();
2402 menu.addAction(MainWindow::instance()->getReSimulateModelAction());
2403 menu.addAction(MainWindow::instance()->getReSimulateSetupAction());
2404 point.setY(point.y() + adjust);
2405 menu.exec(mpVariablesTreeView->mapToGlobal(point));
2406 } else if (pVariablesTreeItem) {
2407 qDebugQMessageLogger(nullptr, 0, nullptr).debug() << "showContextMenu" << index;
2408 qDebugQMessageLogger(nullptr, 0, nullptr).debug() << "name" << pVariablesTreeItem->getVariableName() << "path" << pVariablesTreeItem->getFilePath() << "uses" << pVariablesTreeItem->getUses();
2409 QAction *pGetDepends = new QAction(tr("Show only direct dependencies"), this);
2410 if (pVariablesTreeItem->getUses().size() <= 1 /* Self only */) {
2411 pGetDepends->setEnabled(false);
2412 }
2413 pGetDepends->setData(pVariablesTreeItem->getUses());
2414 pGetDepends->setStatusTip(tr("Show only variables that depend on this variable"));
2415
2416 QAction *pGetInitDepends = new QAction(tr("Show only direct dependencies (initial)"), this);
2417 if (pVariablesTreeItem->getInitialUses().size() <= 1 /* Self only */) {
2418 pGetInitDepends->setEnabled(false);
2419 }
2420 pGetInitDepends->setData(pVariablesTreeItem->getInitialUses());
2421 pGetInitDepends->setStatusTip(tr("Show only variables that depend on this variable in the initial system of equations"));
2422
2423 connect(pGetDepends, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(filterDependencies())"1""filterDependencies()");
2424 connect(pGetInitDepends, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(filterDependencies())"1""filterDependencies()");
2425
2426 QMenu menu(this);
2427 menu.addAction(pGetDepends);
2428 menu.addAction(pGetInitDepends);
2429
2430 foreach(IntStringPair pair, pVariablesTreeItem->getDefinedIn())for (auto _container_ = QtPrivate::qMakeForeachContainer(pVariablesTreeItem
->getDefinedIn()); _container_.control && _container_
.i != _container_.e; ++_container_.i, _container_.control ^= 1
) for (IntStringPair pair = *_container_.i; _container_.control
; _container_.control = 0)
{
2431 if (pair.second == QString("")) {
2432 continue;
2433 }
2434 QAction *pGetDefines = new QAction(tr("Open debugger (equation %1 - %2)").arg(QString::number(pair.first), pair.second), this);
2435 QVariantList lst;
2436 lst << QString("%1/%2").arg(pVariablesTreeItem->getFilePath(), pVariablesTreeItem->getInfoFileName());
2437 lst << pair.first;
2438 pGetDefines->setData(lst);
2439 pGetDefines->setStatusTip(tr("Open debugger for the equation"));
2440 menu.addAction(pGetDefines);
2441
2442 connect(pGetDefines, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(openTransformationsBrowser())"1""openTransformationsBrowser()");
2443 }
2444
2445 menu.exec(mpVariablesTreeView->mapToGlobal(point));
2446 }
2447}
2448
2449/*!
2450 * \brief VariablesWidget::findVariables
2451 * Finds the variables in the Variables Browser.
2452 */
2453void VariablesWidget::findVariables()
2454{
2455 QString findText = mpTreeSearchFilters->getFilterTextBox()->text();
2456 QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(mpTreeSearchFilters->getSyntaxComboBox()->itemData(mpTreeSearchFilters->getSyntaxComboBox()->currentIndex()).toInt());
2457 Qt::CaseSensitivity caseSensitivity = mpTreeSearchFilters->getCaseSensitiveCheckBox()->isChecked() ? Qt::CaseSensitive: Qt::CaseInsensitive;
2458 QRegExp regExp(findText, caseSensitivity, syntax);
2459 mpVariableTreeProxyModel->setFilterRegExp(regExp);
2460 /* expand all so that the filtered items can be seen. */
2461 if (!findText.isEmpty()) {
2462 mpVariablesTreeView->expandAll();
2463 }
2464 if (mpVariablesTreeView->selectionModel()->selectedIndexes().isEmpty()) {
2465 QModelIndex proxyIndex = mpVariableTreeProxyModel->index(0, 0);
2466 if (proxyIndex.isValid()) {
2467 mpVariablesTreeView->selectionModel()->select(proxyIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows);
2468 }
2469 }
2470 MainWindow::instance()->enableReSimulationToolbar(MainWindow::instance()->getVariablesDockWidget()->isVisible());
2471}
2472
2473void VariablesWidget::directReSimulate()
2474{
2475 reSimulate(false);
2476}
2477
2478void VariablesWidget::showReSimulateSetup()
2479{
2480 reSimulate(true);
2481}
2482
2483/*!
2484 * \brief VariablesWidget::rewindVisualization
2485 * Slot activated when mpRewindAction triggered SIGNAL is raised.
2486 */
2487void VariablesWidget::rewindVisualization()
2488{
2489 mpTimeManager->setVisTime(mpTimeManager->getStartTime());
2490 mpTimeManager->setRealTimeFactor(0.0);
2491 mpTimeManager->setPause(true);
2492 mpSimulationTimeSlider->setValue(mpSimulationTimeSlider->minimum());
2493 mpTimeTextBox->setText(QString::number(mpTimeManager->getVisTime()));
2494}
2495
2496/*!
2497 * \brief VariablesWidget::playVisualization
2498 * Slot activated when mpPlayAction triggered SIGNAL is raised.
2499 */
2500void VariablesWidget::playVisualization()
2501{
2502 mpTimeManager->setPause(false);
2503}
2504
2505/*!
2506 * \brief VariablesWidget::pauseVisualization
2507 * Slot activated when mpPauseAction triggered SIGNAL is raised.
2508 */
2509void VariablesWidget::pauseVisualization()
2510{
2511 mpTimeManager->setPause(true);
2512}
2513
2514/*!
2515 * \brief VariablesWidget::visulizationTimeChanged
2516 * Slot activated when mpTimeTextBox returnPressed SIGNAL is raised.
2517 */
2518void VariablesWidget::visulizationTimeChanged()
2519{
2520 QString time = mpTimeTextBox->text();
2521 bool isFloat = true;
2522 double start = mpTimeManager->getStartTime();
2523 double end = mpTimeManager->getEndTime();
2524 double value = time.toFloat(&isFloat);
2525 if (isFloat && value >= 0.0) {
2526 if (value < start) {
2527 value = start;
2528 } else if (value > end) {
2529 value = end;
2530 }
2531 mpTimeManager->setVisTime(value);
2532 mpSimulationTimeSlider->setValue(mpTimeManager->getTimeFraction());
2533
2534 }
2535}
2536
2537/*!
2538 * \brief VariablesWidget::visualizationSpeedChanged
2539 * Slot activated when mpSpeedComboBox currentIndexChanged SIGNAL is raised.
2540 */
2541void VariablesWidget::visualizationSpeedChanged()
2542{
2543 QString speed = mpSpeedComboBox->lineEdit()->text();
2544 bool isFloat = true;
2545 double value = speed.toFloat(&isFloat);
2546 if (isFloat && value > 0.0) {
2547 mpTimeManager->setSpeedUp(value);
2548 }
2549}
2550
2551/*!
2552 * \brief VariablesWidget::incrementVisualization
2553 * Slot activated when TimeManager timer emits timeout SIGNAL.
2554 */
2555void VariablesWidget::incrementVisualization()
2556{
2557 //measure realtime
2558 mpTimeManager->updateTick();
2559 //update scene and set next time step
2560 if (!mpTimeManager->isPaused()) {
2561 mpTimeTextBox->setText(QString::number(mpTimeManager->getVisTime()));
2562 // set time slider
2563 int time = mpTimeManager->getTimeFraction();
2564 mpSimulationTimeSlider->setValue(time);
2565 //finish animation with pause when endtime is reached
2566 if (mpTimeManager->getVisTime() >= mpTimeManager->getEndTime()) {
2567 pauseVisualization();
2568 } else { // get the new visualization time
2569 double newTime = mpTimeManager->getVisTime() + (mpTimeManager->getHVisual()*mpTimeManager->getSpeedUp());
2570 if (newTime <= mpTimeManager->getEndTime()) {
2571 mpTimeManager->setVisTime(newTime);
2572 } else {
2573 mpTimeManager->setVisTime(mpTimeManager->getEndTime());
2574 }
2575 }
2576 }
2577}