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 = QString::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,
558 SimulationOptions simulationOptions)
559{
560 QString toolTip;
561 if (simulationOptions.isInteractiveSimulation()) {
562 toolTip = tr("Interactive Simulation\nPort: %1").arg(simulationOptions.getInteractiveSimulationPortNumber());
563 } else {
564 toolTip = tr("Simulation Result File: %1\n%2: %3/%4").arg(fileName).arg(Helper::fileLocation).arg(filePath).arg(fileName);
565 }
566 QRegExp resultTypeRegExp("(\\.mat|\\.plt|\\.csv|_res.mat|_res.plt|_res.csv)");
567 QString text = QString(fileName).remove(resultTypeRegExp);
568 QModelIndex index = variablesTreeItemIndex(mpRootVariablesTreeItem);
569 QVector<QVariant> Variabledata;
570 Variabledata << filePath << fileName << fileName << text << "" << "" << "" << QStringList() << "" << toolTip << false << QVariantList() << QVariantList() << QVariantList() << "dummy.json";
571
572 VariablesTreeItem *pTopVariablesTreeItem = new VariablesTreeItem(Variabledata, mpRootVariablesTreeItem, true);
573 pTopVariablesTreeItem->setSimulationOptions(simulationOptions);
574 int row = rowCount();
575 beginInsertRows(index, row, row);
576 mpRootVariablesTreeItem->insertChild(row, pTopVariablesTreeItem);
577 endInsertRows();
578 // set the newly inserted VariablesTreeItem active
579 mpActiveVariablesTreeItem = pTopVariablesTreeItem;
580 if (simulationOptions.isValid() && !simulationOptions.isInteractiveSimulation()) {
581 pTopVariablesTreeItem->setActive();
582 }
583 /* open the model_init.xml file for reading */
584 mScalarVariablesHash.clear();
585 QString initFileName, infoFileName;
586 if (simulationOptions.isValid()) {
587 initFileName = QString(simulationOptions.getOutputFileName()).append("_init.xml");
588 infoFileName = QString(simulationOptions.getOutputFileName()).append("_info.json");
589 } else {
590 initFileName = QString(text).append("_info.json");
591 infoFileName = QString(text).append("_init.xml");
592 }
593 QFile initFile(QString(filePath).append(QDir::separator()).append(initFileName));
594 if (initFile.exists()) {
595 if (initFile.open(QIODevice::ReadOnly)) {
596 QXmlStreamReader initXmlReader(&initFile);
597 parseInitXml(initXmlReader);
598 initFile.close();
599 } else {
600 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
601 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(initFile.fileName())
602 .arg(initFile.errorString()), Helper::scriptingKind, Helper::errorLevel));
603 }
604 }
605 QFile infoFile(QString(filePath).append(QDir::separator()).append(infoFileName));
606
607 QMap<QString,QSet<QString>> usedInitialVars;
608 QMap<QString,QSet<QString>> usedVars;
609 QMap<QString,QList<IntStringPair>> definedIn;
610
611 if (infoFile.exists()) {
612 QJson::Parser parser;
613 bool ok;
614 QVariantMap result;
615 result = parser.parse(&infoFile, &ok).toMap();
616 if (!ok) {
617 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(infoFile.fileName())
618 .arg(initFile.errorString()), Helper::scriptingKind, Helper::errorLevel));
619 return;
620 }
621 QVariantMap vars = result["variables"].toMap();
622 QVariantList eqs = result["equations"].toList();
623
624 for (int i=0; i<eqs.size(); i++) {
625 QVariantMap veq = eqs[i].toMap();
626 bool isInitial = (veq.find("section") != veq.end() && veq["section"] == QString("initial"));
627
628 if (veq.find("defines") != veq.end()) {
629 QStringList defines = Utilities::variantListToStringList(veq["defines"].toList());
630 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)
{
631 if (!definedIn.contains(v1)) {
632 definedIn[v1] = QList<IntStringPair>();
633 }
634 definedIn[v1] << IntStringPair(veq["eqIndex"].toInt(), veq.find("section") != veq.end() ? veq["section"].toString() : QString("unknown"));
635 QString v1_1 = QString("%1.%2").arg(fileName ,v1);
636 if (veq.find("uses") != veq.end()) {
637 QStringList uses = Utilities::variantListToStringList(veq["uses"].toList());
638 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)
{
639 if (isInitial) {
640 usedInitialVars[v1].insert(v2);
641 } else {
642 usedVars[v1].insert(v2);
643 }
644 }
645 }
646 }
647 }
648 }
649 }
650
651 /* open the .mat file */
652 ModelicaMatReader matReader;
653 matReader.file = 0;
654 const char *msg[] = {""};
655 if (fileName.endsWith(".mat")) {
656 //Read in mat file
657 if (0 != (msg[0] = omc_new_matlab4_reader(QString(filePath + "/" + fileName).toUtf8().constData(), &matReader))) {
658 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
659 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(filePath + "/" + fileName)
660 .arg(QString(msg[0])), Helper::scriptingKind, Helper::errorLevel));
661 }
662 }
663
664 // remove time from variables list
665 variablesList.removeOne("time");
666 QStringList variables;
667 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)
{
668 QString parentVariable = "";
669 if (plotVariable.startsWith("der(")) {
670 QString str = plotVariable;
671 str.chop((str.lastIndexOf("der(")/4)+1);
672 variables = StringHandler::makeVariablePartsWithInd(str.mid(str.lastIndexOf("der(") + 4));
673 } else if (plotVariable.startsWith("previous(")) {
674 QString str = plotVariable;
675 str.chop((str.lastIndexOf("previous(")/9)+1);
676 variables = StringHandler::makeVariablePartsWithInd(str.mid(str.lastIndexOf("previous(") + 9));
677 } else {
678 variables = StringHandler::makeVariablePartsWithInd(plotVariable);
679 }
680 int count = 1;
681 VariablesTreeItem *pParentVariablesTreeItem = 0;
682 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)
{
683 if (count == 1) { /* first loop iteration */
684 pParentVariablesTreeItem = pTopVariablesTreeItem;
685 }
686 QString findVariable;
687 /* if last item of derivative */
688 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
689 if (parentVariable.isEmpty()) {
690 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der("));
691 } else {
692 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, parentVariable, "der("));
693 }
694 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
695 if (parentVariable.isEmpty()) {
696 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous("));
697 } else {
698 findVariable = QString("%1.%2").arg(fileName ,StringHandler::joinDerivativeAndPreviousVariable(plotVariable, parentVariable, "previous("));
699 }
700 } else {
701 if (parentVariable.isEmpty()) {
702 findVariable = QString("%1.%2").arg(fileName, variable);
703 } else {
704 findVariable = QString("%1.%2.%3").arg(fileName, parentVariable, variable);
705 }
706 }
707 if ((pParentVariablesTreeItem = findVariablesTreeItem(findVariable, pParentVariablesTreeItem)) != NULL__null) {
708 QString addVar = "";
709 /* if last item of derivative */
710 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
711 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der(");
712 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
713 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous(");
714 } else {
715 addVar = variable;
716 }
717 if (count == 1) {
718 parentVariable = addVar;
719 } else {
720 parentVariable += "." + addVar;
721 }
722 count++;
723 continue;
724 }
725 /* If pParentVariablesTreeItem is 0 and it is first loop iteration then use pTopVariablesTreeItem as parent.
726 * If loop iteration is not first and pParentVariablesTreeItem is 0 then find the parent item.
727 */
728 if (!pParentVariablesTreeItem && count > 1) {
729 pParentVariablesTreeItem = findVariablesTreeItem(fileName + "." + parentVariable, pTopVariablesTreeItem);
730 } else {
731 pParentVariablesTreeItem = pTopVariablesTreeItem;
732 }
733 QModelIndex index = variablesTreeItemIndex(pParentVariablesTreeItem);
734 QVector<QVariant> variableData;
735 /* if last item of derivative */
736 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
737 variableData << filePath << fileName << fileName + "." + plotVariable << StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der(");
738 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
739 variableData << filePath << fileName << fileName + "." + plotVariable << StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous(");
740 } else if (variables.size() == count && QRegExp("\\[\\d+\\]").exactMatch(variable)) { /* if last item of array derivative*/
741 variableData << filePath << fileName << fileName + "." + plotVariable << variable;
742 } else {
743 variableData << filePath << fileName << pParentVariablesTreeItem->getVariableName() + "." + variable << variable;
744 }
745
746 /* find the variable in the xml file */
747 QString variableToFind = variableData[2].toString();
748 variableToFind.remove(QRegExp(pTopVariablesTreeItem->getVariableName() + "."));
749 /* get the variable information i.e value, unit, displayunit, description */
750 QString value, variability, unit, displayUnit, description;
751 bool changeAble = false;
752 getVariableInformation(&matReader, variableToFind, &value, &changeAble, &variability, &unit, &displayUnit, &description);
753 variableData << StringHandler::unparse(QString("\"").append(value).append("\""));
754 /* set the variable unit */
755 variableData << StringHandler::unparse(QString("\"").append(unit).append("\""));
756 /* set the variable displayUnit */
757 variableData << StringHandler::unparse(QString("\"").append(displayUnit).append("\""));
758 /* set the variable displayUnits */
759 if (!variableData[5].toString().isEmpty()) {
760 QStringList displayUnits, displayUnitOptions;
761 displayUnits << variableData[5].toString();
762 if (!variableData[6].toString().isEmpty()) {
763 displayUnitOptions << variableData[6].toString();
764 /* convert value to displayUnit */
765 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(variableData[5].toString(), variableData[6].toString());
766 if (convertUnit.unitsCompatible) {
767 bool ok = true;
768 qreal realValue = variableData[4].toDouble(&ok);
769 if (ok) {
770 realValue = Utilities::convertUnit(realValue, convertUnit.offset, convertUnit.scaleFactor);
771 variableData[4] = QString::number(realValue);
772 }
773 }
774 } else { /* use unit as displayUnit */
775 variableData[6] = variableData[5];
776 }
777 displayUnits << displayUnitOptions;
778 variableData << displayUnits;
779 } else {
780 variableData << QStringList();
781 }
782 /* set the variable description */
783 variableData << StringHandler::unparse(QString("\"").append(description).append("\""));
784 /* construct tooltip text */
785 if (simulationOptions.isInteractiveSimulation()) {
786 variableData << tr("Variable: %1\nVariability: %2").arg(variableToFind).arg(variability);
787 } else {
788 variableData << tr("File: %1/%2\nVariable: %3\nVariability: %4").arg(filePath).arg(fileName).arg(variableToFind).arg(variability);
789 }
790 /*is main array*/
791 if (variables.size() == count+1 && QRegExp("\\[\\d+\\]").exactMatch(variables.last())) {
792 variableData << true;
793 } else {
794 variableData << false;
795 }
796 QString findVariableNoFileName = findVariable.right(findVariable.size()-fileName.size()-1);
797
798 if (usedVars.find(findVariableNoFileName) != usedVars.end()) {
799 QStringList lst = QStringList(usedVars[findVariableNoFileName].toList());
800 lst << findVariableNoFileName;
801 variableData << lst;
802 } else {
803 variableData << QStringList(findVariableNoFileName);
804 }
805 if (usedInitialVars.find(findVariableNoFileName) != usedInitialVars.end()) {
806 QStringList lst = QStringList(usedInitialVars[findVariableNoFileName].toList());
807 lst << findVariableNoFileName;
808 variableData << lst;
809 } else {
810 variableData << QStringList(findVariableNoFileName);
811 }
812 QVariantList variantDefinedIn;
813 if (definedIn.find(findVariableNoFileName) != definedIn.end()) {
814 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)
{
815 variantDefinedIn << QVariant::fromValue(pair);
816 }
817 } else {
818 variantDefinedIn << QVariant::fromValue(IntStringPair(0,QString("")));
819 }
820 variableData << variantDefinedIn;
821 variableData << infoFileName;
822
823 VariablesTreeItem *pVariablesTreeItem = new VariablesTreeItem(variableData, pParentVariablesTreeItem);
824 pVariablesTreeItem->setEditable(changeAble);
825 pVariablesTreeItem->setVariability(variability);
826 int row = rowCount(index);
827 beginInsertRows(index, row, row);
828 pParentVariablesTreeItem->insertChild(row, pVariablesTreeItem);
829 endInsertRows();
830 QString addVar = "";
831 /* if last item of derivative */
832 if ((variables.size() == count) && (plotVariable.startsWith("der("))) {
833 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "der(");
834 } else if ((variables.size() == count) && (plotVariable.startsWith("previous("))) { /* if last item of previous */
835 addVar = StringHandler::joinDerivativeAndPreviousVariable(plotVariable, variable, "previous(");
836 } else {
837 addVar = variable;
838 }
839 if (count == 1) {
840 parentVariable = addVar;
841 } else {
842 parentVariable += "." + addVar;
843 }
844 count++;
845 }
846 }
847 /* close the .mat file */
848 if (fileName.endsWith(".mat")) {
849 if (matReader.file) {
850 omc_free_matlab4_reader(&matReader);
851 }
852 }
853 mpVariablesTreeView->collapseAll();
854 QModelIndex idx = variablesTreeItemIndex(pTopVariablesTreeItem);
855 idx = mpVariablesTreeView->getVariablesWidget()->getVariableTreeProxyModel()->mapFromSource(idx);
856 mpVariablesTreeView->expand(idx);
857 /* Ticket #3016.
858 * If you only have one model the message "You must select a class to re-simulate" is annoying.
859 * A default behavior of selecting the (single) model would be good.
860 * The following line selects the result tree top level item.
861 */
862 mpVariablesTreeView->setCurrentIndex(idx);
863 MainWindow::instance()->enableReSimulationToolbar(MainWindow::instance()->getVariablesDockWidget()->isVisible());
864}
865
866/*!
867 * \brief VariablesTreeModel::removeVariableTreeItem
868 * Removes the VariablesTreeItem.
869 * \param variable
870 * \return
871 */
872bool VariablesTreeModel::removeVariableTreeItem(QString variable)
873{
874 VariablesTreeItem *pVariablesTreeItem = findVariablesTreeItem(variable, mpRootVariablesTreeItem);
875 if (pVariablesTreeItem) {
876 // if we are going to remove an active VariablesTreeItem then we should disable the visualization controls.
877 if (pVariablesTreeItem->isActive()) {
878 mpVariablesTreeView->getVariablesWidget()->enableVisualizationControls(false);
879 mpVariablesTreeView->getVariablesWidget()->rewindVisualization();
880 }
881 beginRemoveRows(variablesTreeItemIndex(pVariablesTreeItem), 0, pVariablesTreeItem->getChildren().size());
882 pVariablesTreeItem->removeChildren();
883 VariablesTreeItem *pParentVariablesTreeItem = pVariablesTreeItem->parent();
884 pParentVariablesTreeItem->removeChild(pVariablesTreeItem);
885
886 if (pVariablesTreeItem->getSimulationOptions().isInteractiveSimulation()) {
887 for (const auto& p : MainWindow::instance()->getSimulationDialog()->getSimulationOutputWidgetsList()) {
888 // remove the right interactive output widget
889 if (p->getSimulationOptions().getClassName() == pVariablesTreeItem->getFileName()) {
890 MainWindow::instance()->getSimulationDialog()->removeSimulationOutputWidget(p);
891 break;
892 }
893 }
894 }
895 if (pVariablesTreeItem) {
896 delete pVariablesTreeItem;
897 }
898 endRemoveRows();
899 mpVariablesTreeView->getVariablesWidget()->findVariables();
900 return true;
901 }
902 return false;
903}
904
905void VariablesTreeModel::unCheckVariables(VariablesTreeItem *pVariablesTreeItem)
906{
907 QList<VariablesTreeItem*> items = pVariablesTreeItem->getChildren();
908 for (int i = 0 ; i < items.size() ; i++) {
909 items[i]->setData(0, Qt::Unchecked, Qt::CheckStateRole);
910 unCheckVariables(items[i]);
911 }
912}
913
914void VariablesTreeModel::plotAllVariables(VariablesTreeItem *pVariablesTreeItem, PlotWindow *pPlotWindow)
915{
916 QList<VariablesTreeItem*> variablesTreeItems = pVariablesTreeItem->getChildren();
917 if (variablesTreeItems.size() == 0) {
918 QModelIndex index = variablesTreeItemIndex(pVariablesTreeItem);
919 OMPlot::PlotCurve *pPlotCurve = 0;
920 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)
{
921 if (curve->getNameStructure().compare(pVariablesTreeItem->getVariableName()) == 0) {
922 pPlotCurve = curve;
923 break;
924 }
925 }
926 setData(index, Qt::Checked, Qt::CheckStateRole);
927 mpVariablesTreeView->getVariablesWidget()->plotVariables(index, pPlotWindow->getCurveWidth(), pPlotWindow->getCurveStyle(), pPlotCurve);
928 } else {
929 for (int i = 0 ; i < variablesTreeItems.size() ; i++) {
930 plotAllVariables(variablesTreeItems[i], pPlotWindow);
931 }
932 }
933}
934
935/*!
936 * \brief VariablesTreeModel::parseScalarVariable
937 * Parses the scalar variable.
938 * Helper function for VariablesTreeModel::parseInitXml
939 * \param xmlReader
940 * \return
941 */
942QHash<QString, QString> VariablesTreeModel::parseScalarVariable(QXmlStreamReader &xmlReader)
943{
944 QHash<QString, QString> scalarVariable;
945 /* Let's check that we're really getting a ScalarVariable. */
946 if (xmlReader.tokenType() != QXmlStreamReader::StartElement && xmlReader.name() == "ScalarVariable") {
947 return scalarVariable;
948 }
949 /* Let's get the attributes for ScalarVariable */
950 QXmlStreamAttributes attributes = xmlReader.attributes();
951 /* Read the ScalarVariable attributes. */
952 scalarVariable["name"] = attributes.value("name").toString();
953 scalarVariable["description"] = attributes.value("description").toString();
954 scalarVariable["isValueChangeable"] = attributes.value("isValueChangeable").toString();
955 scalarVariable["variability"] = attributes.value("variability").toString();
956 /* Read the next element i.e Real, Integer, Boolean etc. */
957 xmlReader.readNext();
958 while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement && xmlReader.name() == "ScalarVariable")) {
959 if (xmlReader.tokenType() == QXmlStreamReader::StartElement) {
960 QXmlStreamAttributes attributes = xmlReader.attributes();
961 scalarVariable["start"] = attributes.value("start").toString();
962 scalarVariable["unit"] = attributes.value("unit").toString();
963 scalarVariable["displayUnit"] = attributes.value("displayUnit").toString();
964 }
965 xmlReader.readNext();
966 }
967 return scalarVariable;
968}
969
970/*!
971 * \brief VariablesTreeModel::getVariableInformation
972 * Returns the variable information like value, unit, displayunit and description.
973 * \param pMatReader
974 * \param variableToFind
975 * \param value
976 * \param changeAble
977 * \param variability
978 * \param unit
979 * \param displayUnit
980 * \param description
981 */
982void VariablesTreeModel::getVariableInformation(ModelicaMatReader *pMatReader, QString variableToFind, QString *value, bool *changeAble,
983 QString *variability, QString *unit, QString *displayUnit, QString *description)
984{
985 QHash<QString, QString> hash = mScalarVariablesHash.value(variableToFind);
986 if (hash["name"].compare(variableToFind) == 0) {
987 *changeAble = (hash["isValueChangeable"].compare("true") == 0) ? true : false;
988 *variability = hash["variability"];
989 if (*changeAble) {
990 *value = hash["start"];
991 } else { /* if the variable is not a tunable parameter then read the final value of the variable. Only mat result files are supported. */
992 if ((pMatReader->file != NULL__null) && strcmp(pMatReader->fileName, "")) {
993 *value = "";
994 ModelicaMatVariable_t *var;
995 if (0 == (var = omc_matlab4_find_var(pMatReader, variableToFind.toUtf8().constData()))) {
996 qDebugQMessageLogger(nullptr, 0, nullptr).debug() << QString("%1 not found in %2").arg(variableToFind).arg(pMatReader->fileName);
997 }
998 double res;
999 if (var && !omc_matlab4_val(&res, pMatReader, var, omc_matlab4_stopTime(pMatReader))) {
1000 *value = QString::number(res);
1001 }
1002 }
1003 }
1004 *unit = hash["unit"];
1005 *displayUnit = hash["displayUnit"];
1006 *description = hash["description"];
1007 }
1008}
1009
1010/*!
1011 * \brief VariablesTreeModel::removeVariableTreeItem
1012 * Slot activated when pDeleteResultAction triggered SIGNAL is raised.
1013 * Removes a VariablesTreeItem
1014 */
1015void VariablesTreeModel::removeVariableTreeItem()
1016{
1017 QAction *pAction = qobject_cast<QAction*>(sender());
1018 if (pAction) {
1019 removeVariableTreeItem(pAction->data().toString());
1020 emit variableTreeItemRemoved(pAction->data().toString());
1021 }
1022}
1023
1024
1025void VariablesTreeModel::filterDependencies()
1026{
1027 QAction *pAction = qobject_cast<QAction*>(sender());
1028 if (pAction) {
1029 QStringList uses = pAction->data().toStringList();
1030 QStringList escapedUses;
1031 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)
{
1032 escapedUses << s.replace("[","[[]").replace("]","[]]").replace("[[[]]","[[]").replace("(","[(]").replace(")","[)]").replace(".","[.]");
1033 }
1034 QRegExp regexp = QRegExp("^" + escapedUses.join("|") + "$");
1035 mpVariablesTreeView->getVariablesWidget()->getVariableTreeProxyModel()->setFilterRegExp(regexp);
1036 }
1037}
1038
1039void VariablesTreeModel::openTransformationsBrowser()
1040{
1041 QAction *pAction = qobject_cast<QAction*>(sender());
1042 if (pAction) {
1043 QVariantList list = pAction->data().toList();
1044 QString fileName = list[0].toString();
1045 int equationIndex = list[1].toInt();
1046 if (QFileInfo(fileName).exists()) {
1047 TransformationsWidget *pTransformationsWidget = MainWindow::instance()->showTransformationsWidget(fileName);
1048 QTreeWidgetItem *pTreeWidgetItem = pTransformationsWidget->findEquationTreeItem(equationIndex);
1049 if (pTreeWidgetItem) {
1050 pTransformationsWidget->getEquationsTreeWidget()->clearSelection();
1051 pTransformationsWidget->getEquationsTreeWidget()->setCurrentItem(pTreeWidgetItem);
1052 }
1053 pTransformationsWidget->fetchEquationData(equationIndex);
1054 } else {
1055 QMessageBox::critical(MainWindow::instance(), QString("%1 - %2").arg(Helper::applicationName, Helper::error), GUIMessages::getMessage(GUIMessages::FILE_NOT_FOUND).arg(fileName), Helper::ok);
1056 }
1057 }
1058}
1059
1060/*!
1061 * \brief VariablesTreeModel::setVariableTreeItemActive
1062 * Slots activated when mpSetResultActiveAction triggered SIGNAL is raised.
1063 * Sets a VariablesTreeItem active.
1064 */
1065void VariablesTreeModel::setVariableTreeItemActive()
1066{
1067 QAction *pAction = qobject_cast<QAction*>(sender());
1068 if (pAction) {
1069 VariablesTreeItem *pVariablesTreeItem = findVariablesTreeItem(pAction->data().toString(), mpRootVariablesTreeItem);
1070 if (pVariablesTreeItem) {
1071 mpActiveVariablesTreeItem = pVariablesTreeItem;
1072 pVariablesTreeItem->setActive();
1073 }
1074 }
1075}
1076
1077/*!
1078 * \class VariableTreeProxyModel
1079 * \brief A sort filter proxy model for Variables Browser.
1080 */
1081/*!
1082 * \brief VariableTreeProxyModel::VariableTreeProxyModel
1083 * \param parent
1084 */
1085VariableTreeProxyModel::VariableTreeProxyModel(QObject *parent)
1086 : QSortFilterProxyModel(parent)
1087{
1088}
1089
1090/*!
1091 * \brief VariableTreeProxyModel::filterAcceptsRow
1092 * Filters the VariablesTreeItems based on the filter reguler expression.
1093 * \param sourceRow
1094 * \param sourceParent
1095 * \return
1096 */
1097bool VariableTreeProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
1098{
1099 if (!filterRegExp().isEmpty()) {
1100 QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
1101 if (index.isValid()) {
1102 // if any of children matches the filter, then current index matches the filter as well
1103 int rows = sourceModel()->rowCount(index);
1104 for (int i = 0 ; i < rows ; ++i) {
1105 if (filterAcceptsRow(i, index)) {
1106 return true;
1107 }
1108 }
1109 // check current index itself
1110 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1111 if (pVariablesTreeItem) {
1112 QString variableName = pVariablesTreeItem->getVariableName();
1113 variableName.remove(QRegExp("(\\.mat|\\.plt|\\.csv|_res.mat|_res.plt|_res.csv)"));
1114 return variableName.contains(filterRegExp());
1115 } else {
1116 return sourceModel()->data(index).toString().contains(filterRegExp());
1117 }
1118 QString key = sourceModel()->data(index, filterRole()).toString();
1119 return key.contains(filterRegExp());
1120 }
1121 }
1122 return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
1123}
1124
1125/*!
1126 * \brief VariableTreeProxyModel::lessThan
1127 * Sorts the VariablesTreeItems using the natural sort.
1128 * \param left
1129 * \param right
1130 * \return
1131 */
1132bool VariableTreeProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
1133{
1134 QVariant l = (left.model() ? left.model()->data(left) : QVariant());
1135 QVariant r = (right.model() ? right.model()->data(right) : QVariant());
1136 return StringHandler::naturalSort(l.toString(), r.toString());
1137}
1138
1139VariablesTreeView::VariablesTreeView(VariablesWidget *pVariablesWidget)
1140 : QTreeView(pVariablesWidget)
1141{
1142 mpVariablesWidget = pVariablesWidget;
1143 setItemDelegate(new ItemDelegate(this));
1144 setTextElideMode(Qt::ElideMiddle);
1145 setIndentation(Helper::treeIndentation);
1146 setIconSize(Helper::iconSize);
1147 setContextMenuPolicy(Qt::CustomContextMenu);
1148 setExpandsOnDoubleClick(false);
1149 setEditTriggers(QAbstractItemView::AllEditTriggers);
1150 setUniformRowHeights(true);
1151}
1152
1153/*!
1154 * \brief VariablesTreeView::mouseReleaseEvent
1155 * Reimplementation of QTreeView::mouseReleaseEvent\n
1156 * Checks if user clicks on the first column then check/uncheck the corresponsing checkbox of the column.\n
1157 * Otherwise calls the QTreeView::mouseReleaseEvent
1158 * \param event
1159 */
1160void VariablesTreeView::mouseReleaseEvent(QMouseEvent *event)
1161{
1162 QModelIndex index = indexAt(event->pos());
1163 if (index.isValid() &&
1164 index.column() == 0 &&
1165 index.parent().isValid() &&
1166 index.flags() & Qt::ItemIsUserCheckable &&
1167 event->button() == Qt::LeftButton) {
1168 if (visualRect(index).contains(event->pos())) {
1169 index = mpVariablesWidget->getVariableTreeProxyModel()->mapToSource(index);
1170 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1171 if (pVariablesTreeItem && pVariablesTreeItem) {
1172 if (pVariablesTreeItem->isChecked()) {
1173 mpVariablesWidget->getVariablesTreeModel()->setData(index, Qt::Unchecked, Qt::CheckStateRole);
1174 } else {
1175 mpVariablesWidget->getVariablesTreeModel()->setData(index, Qt::Checked, Qt::CheckStateRole);
1176 }
1177 }
1178 return;
1179 }
1180 }
1181 QTreeView::mouseReleaseEvent(event);
1182}
1183
1184/*!
1185 * \brief VariablesTreeView::keyPressEvent
1186 * Reimplementation of keypressevent.
1187 * \param event
1188 */
1189void VariablesTreeView::keyPressEvent(QKeyEvent *event)
1190{
1191 QModelIndexList indexes = selectionModel()->selectedIndexes();
1192 if (!indexes.isEmpty()) {
1193 QModelIndex index = indexes.at(0);
1194 index = mpVariablesWidget->getVariableTreeProxyModel()->mapToSource(index);
1195 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1196 if (event->key() == Qt::Key_Delete && pVariablesTreeItem->isRootItem()) {
1197 mpVariablesWidget->getVariablesTreeModel()->removeVariableTreeItem(pVariablesTreeItem->getVariableName());
1198 return;
1199 }
1200 }
1201 QTreeView::keyPressEvent(event);
1202}
1203
1204VariablesWidget::VariablesWidget(QWidget *pParent)
1205 : QWidget(pParent)
1206{
1207 // tree search filters
1208 mpTreeSearchFilters = new TreeSearchFilters(this);
1209 mpTreeSearchFilters->getFilterTextBox()->setPlaceholderText(Helper::filterVariables);
1210 mpTreeSearchFilters->getFilterTimer()->setInterval(OptionsDialog::instance()->getPlottingPage()->getFilterIntervalSpinBox()->value() * 1000);
1211 connect(mpTreeSearchFilters->getFilterTextBox(), SIGNAL(returnPressed())"2""returnPressed()", SLOT(findVariables())"1""findVariables()");
1212 connect(mpTreeSearchFilters->getFilterTextBox(), SIGNAL(textEdited(QString))"2""textEdited(QString)", mpTreeSearchFilters->getFilterTimer(), SLOT(start())"1""start()");
1213 connect(mpTreeSearchFilters->getFilterTimer(), SIGNAL(timeout())"2""timeout()", SLOT(findVariables())"1""findVariables()");
1214 connect(mpTreeSearchFilters->getCaseSensitiveCheckBox(), SIGNAL(toggled(bool))"2""toggled(bool)", SLOT(findVariables())"1""findVariables()");
1215 connect(mpTreeSearchFilters->getSyntaxComboBox(), SIGNAL(currentIndexChanged(int))"2""currentIndexChanged(int)", SLOT(findVariables())"1""findVariables()");
1216 // simulation time label and combobox
1217 mpSimulationTimeLabel = new Label(tr("Simulation Time Unit"));
1218 mpSimulationTimeComboBox = new QComboBox;
1219 mpSimulationTimeComboBox->addItem("s");
1220 mpSimulationTimeComboBox->addItems(MainWindow::instance()->getOMCProxy()->getDerivedUnits("s"));
1221 connect(mpSimulationTimeComboBox, SIGNAL(currentIndexChanged(QString))"2""currentIndexChanged(QString)", SLOT(timeUnitChanged(QString))"1""timeUnitChanged(QString)");
1222 // simulation time slider
1223 mSliderRange = 1000;
1224 mpSimulationTimeSlider = new QSlider(Qt::Horizontal);
1225 mpSimulationTimeSlider->setRange(0, mSliderRange);
1226 mpSimulationTimeSlider->setSliderPosition(0);
1227 connect(mpSimulationTimeSlider, SIGNAL(valueChanged(int))"2""valueChanged(int)", SLOT(simulationTimeChanged(int))"1""simulationTimeChanged(int)");
1228 // toolbar
1229 mpToolBar = new QToolBar;
1230 int toolbarIconSize = OptionsDialog::instance()->getGeneralSettingsPage()->getToolbarIconSizeSpinBox()->value();
1231 mpToolBar->setIconSize(QSize(toolbarIconSize, toolbarIconSize));
1232 // rewind action
1233 mpRewindAction = new QAction(QIcon(":/Resources/icons/initialize.svg"), tr("Rewind"), this);
1234 mpRewindAction->setStatusTip(tr("Rewinds the visualization to the start"));
1235 connect(mpRewindAction, SIGNAL(triggered())"2""triggered()", SLOT(rewindVisualization())"1""rewindVisualization()");
1236 // play action
1237 mpPlayAction = new QAction(QIcon(":/Resources/icons/play_animation.svg"), Helper::animationPlay, this);
1238 mpPlayAction->setStatusTip(tr("Play the visualization"));
1239 connect(mpPlayAction, SIGNAL(triggered())"2""triggered()", SLOT(playVisualization())"1""playVisualization()");
1240 // pause action
1241 mpPauseAction = new QAction(QIcon(":/Resources/icons/pause.svg"), Helper::animationPause, this);
1242 mpPauseAction->setStatusTip(tr("Pause the visualization"));
1243 connect(mpPauseAction, SIGNAL(triggered())"2""triggered()", SLOT(pauseVisualization())"1""pauseVisualization()");
1244 // time
1245 QDoubleValidator *pDoubleValidator = new QDoubleValidator(this);
1246 pDoubleValidator->setBottom(0);
1247 mpTimeLabel = new Label;
1248 mpTimeLabel->setText(tr("Time:"));
1249 mpTimeTextBox = new QLineEdit("0.0");
1250 mpTimeTextBox->setMaximumHeight(toolbarIconSize);
1251 mpTimeTextBox->setValidator(pDoubleValidator);
1252 connect(mpTimeTextBox, SIGNAL(returnPressed())"2""returnPressed()", SLOT(visulizationTimeChanged())"1""visulizationTimeChanged()");
1253 // speed
1254 mpSpeedLabel = new Label;
1255 mpSpeedLabel->setText(Helper::speed);
1256 mpSpeedComboBox = new QComboBox;
1257 mpSpeedComboBox->setEditable(true);
1258 mpSpeedComboBox->addItems(Helper::speedOptions.split(","));
1259 mpSpeedComboBox->setCurrentIndex(3);
1260 mpSpeedComboBox->setMaximumHeight(toolbarIconSize);
1261 mpSpeedComboBox->setValidator(pDoubleValidator);
1262 mpSpeedComboBox->setCompleter(0);
1263 connect(mpSpeedComboBox, SIGNAL(currentIndexChanged(int))"2""currentIndexChanged(int)", SLOT(visualizationSpeedChanged())"1""visualizationSpeedChanged()");
1264 connect(mpSpeedComboBox->lineEdit(), SIGNAL(textChanged(QString))"2""textChanged(QString)", SLOT(visualizationSpeedChanged())"1""visualizationSpeedChanged()");
1265 // add actions to toolbar
1266 mpToolBar->addAction(mpRewindAction);
1267 mpToolBar->addSeparator();
1268 mpToolBar->addAction(mpPlayAction);
1269 mpToolBar->addAction(mpPauseAction);
1270 mpToolBar->addSeparator();
1271 mpToolBar->addWidget(mpTimeLabel);
1272 mpToolBar->addWidget(mpTimeTextBox);
1273 mpToolBar->addSeparator();
1274 mpToolBar->addWidget(mpSpeedLabel);
1275 mpToolBar->addWidget(mpSpeedComboBox);
1276 // time manager
1277 mpTimeManager = new TimeManager(0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 1.0);
1278 mpTimeManager->setStartTime(0.0);
1279 mpTimeManager->setEndTime(1.0);
1280 mpTimeManager->setVisTime(mpTimeManager->getStartTime());
1281 mpTimeManager->setPause(true);
1282 connect(mpTimeManager->getUpdateSceneTimer(), SIGNAL(timeout())"2""timeout()", SLOT(incrementVisualization())"1""incrementVisualization()");
1283 // create variables tree widget
1284 mpVariablesTreeView = new VariablesTreeView(this);
1285 mpVariablesTreeModel = new VariablesTreeModel(mpVariablesTreeView);
1286 mpVariableTreeProxyModel = new VariableTreeProxyModel;
1287 mpVariableTreeProxyModel->setDynamicSortFilter(true);
1288 mpVariableTreeProxyModel->setSourceModel(mpVariablesTreeModel);
1289 mpVariablesTreeView->setModel(mpVariableTreeProxyModel);
1290 mpVariablesTreeView->setColumnWidth(0, 150);
1291 mpVariablesTreeView->setColumnWidth(1, 70);
1292 mpVariablesTreeView->setColumnWidth(2, 50);
1293 mpVariablesTreeView->setColumnWidth(3, 70);
1294 mpVariablesTreeView->setColumnHidden(2, true); // hide Unit column
1295 mpLastActiveSubWindow = 0;
1296 mModelicaMatReader.file = 0;
1297 mpCSVData = 0;
1298 // create the layout
1299 QGridLayout *pMainLayout = new QGridLayout;
1300 pMainLayout->setContentsMargins(0, 0, 0, 0);
1301 pMainLayout->setAlignment(Qt::AlignTop);
1302 pMainLayout->addWidget(mpTreeSearchFilters, 0, 0, 1, 2);
1303 pMainLayout->addWidget(mpSimulationTimeLabel, 1, 0);
1304 pMainLayout->addWidget(mpSimulationTimeComboBox, 1, 1);
1305 pMainLayout->addWidget(mpSimulationTimeSlider, 2, 0, 1, 2);
1306 pMainLayout->addWidget(mpToolBar, 3, 0, 1, 2);
1307 pMainLayout->addWidget(mpVariablesTreeView, 4, 0, 1, 2);
1308 setLayout(pMainLayout);
1309 connect(mpTreeSearchFilters->getExpandAllButton(), SIGNAL(clicked())"2""clicked()", mpVariablesTreeView, SLOT(expandAll())"1""expandAll()");
1310 connect(mpTreeSearchFilters->getCollapseAllButton(), SIGNAL(clicked())"2""clicked()", mpVariablesTreeView, SLOT(collapseAll())"1""collapseAll()");
1311 connect(mpVariablesTreeModel, SIGNAL(rowsInserted(QModelIndex,int,int))"2""rowsInserted(QModelIndex,int,int)", mpVariableTreeProxyModel, SLOT(invalidate())"1""invalidate()");
1312 connect(mpVariablesTreeModel, SIGNAL(rowsRemoved(QModelIndex,int,int))"2""rowsRemoved(QModelIndex,int,int)", mpVariableTreeProxyModel, SLOT(invalidate())"1""invalidate()");
1313 connect(mpVariablesTreeModel, SIGNAL(itemChecked(QModelIndex,qreal,int))"2""itemChecked(QModelIndex,qreal,int)", SLOT(plotVariables(QModelIndex,qreal,int))"1""plotVariables(QModelIndex,qreal,int)");
1314 connect(mpVariablesTreeModel, SIGNAL(unitChanged(QModelIndex))"2""unitChanged(QModelIndex)", SLOT(unitChanged(QModelIndex))"1""unitChanged(QModelIndex)");
1315 connect(mpVariablesTreeModel, SIGNAL(valueEntered(QModelIndex))"2""valueEntered(QModelIndex)", SLOT(valueEntered(QModelIndex))"1""valueEntered(QModelIndex)");
1316 connect(mpVariablesTreeView, SIGNAL(customContextMenuRequested(QPoint))"2""customContextMenuRequested(QPoint)", SLOT(showContextMenu(QPoint))"1""showContextMenu(QPoint)");
1317 connect(MainWindow::instance()->getPlotWindowContainer(), SIGNAL(subWindowActivated(QMdiSubWindow*))"2""subWindowActivated(QMdiSubWindow*)", this, SLOT(updateVariablesTree(QMdiSubWindow*))"1""updateVariablesTree(QMdiSubWindow*)");
1318 connect(mpVariablesTreeModel, SIGNAL(variableTreeItemRemoved(QString))"2""variableTreeItemRemoved(QString)", MainWindow::instance()->getPlotWindowContainer(), SLOT(updatePlotWindows(QString))"1""updatePlotWindows(QString)");
1319 //connect(mpVariablesTreeModel, SIGNAL(clicked(QModelIndex)), this, SLOT(selectInteractivePlotWindow(QModelIndex)));
1320 //connect(mpVariablesTreeModel, SIGNAL(itemChecked(QModelIndex)), SLOT(selectInteractivePlotWindow(QModelIndex)));
1321 enableVisualizationControls(false);
1322}
1323
1324/*!
1325 * \brief VariablesWidget::enableVisualizationControls
1326 * Enables/Disables the visualization controls.
1327 * \param enable
1328 */
1329void VariablesWidget::enableVisualizationControls(bool enable)
1330{
1331 mpSimulationTimeSlider->setEnabled(enable);
1332 mpSimulationTimeSlider->setToolTip(enable ? "" : tr("Mark a result file active to enable the controls."));
1333 mpToolBar->setEnabled(enable);
1334}
1335
1336/*!
1337 * \brief VariablesWidget::insertVariablesItemsToTree
1338 * Inserts the result variables in the Variables Browser.
1339 * \param fileName
1340 * \param filePath
1341 * \param variablesList
1342 * \param simulationOptions
1343 */
1344void VariablesWidget::insertVariablesItemsToTree(QString fileName, QString filePath, QStringList variablesList,
1345 SimulationOptions simulationOptions)
1346{
1347 /* Remove the simulation result if we already had it in tree */
1348 bool variableItemDeleted = false;
1349 variableItemDeleted = mpVariablesTreeModel->removeVariableTreeItem(fileName);
1350
1351 mpVariablesTreeView->setSortingEnabled(false);
1352 /* In order to improve the response time of insertVariablesItems function we should clear the filter and collapse all the items. */
1353 mpVariableTreeProxyModel->setFilterRegExp(QRegExp(""));
1354 mpVariablesTreeView->collapseAll();
1355 /* add the plot variables */
1356 mpVariablesTreeModel->insertVariablesItems(fileName, filePath, variablesList, simulationOptions);
1357
1358 /* re-check previously checked variables */
1359 if (simulationOptions.isInteractiveSimulation() && simulationOptions.isReSimulate()) {
1360 interactiveReSimulation(simulationOptions.getClassName());
1361 }
1362
1363 /* update the plot variables tree */
1364 if (variableItemDeleted) {
1365 variablesUpdated();
1366 }
1367 mpVariablesTreeView->setSortingEnabled(true);
1368 mpVariablesTreeView->sortByColumn(0, Qt::AscendingOrder);
1369 /* since we cleared the filter above so we need to apply it back. */
1370 findVariables();
1371}
1372
1373/*!
1374 * \brief VariablesWidget::variablesUpdated
1375 * Updates the already plotted variables after simulation with new values.
1376 */
1377void VariablesWidget::variablesUpdated()
1378{
1379 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)
{
1380 PlotWindow *pPlotWindow = qobject_cast<PlotWindow*>(pSubWindow->widget());
1381 if (pPlotWindow) { // we can have an AnimateWindow there as well so always check
1382 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)
{
1383 if (pPlotWindow->getPlotType() == PlotWindow::PLOT || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY) {
1384 QString curveNameStructure = pPlotCurve->getNameStructure();
1385 VariablesTreeItem *pVariableTreeItem;
1386 pVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(curveNameStructure, mpVariablesTreeModel->getRootVariablesTreeItem());
1387 pPlotCurve->detach();
1388 if (pVariableTreeItem) {
1389 bool state = mpVariablesTreeModel->blockSignals(true);
1390 QModelIndex index = mpVariablesTreeModel->variablesTreeItemIndex(pVariableTreeItem);
1391 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1392 plotVariables(index, pPlotCurve->getCurveWidth(), pPlotCurve->getCurveStyle(), pPlotCurve, pPlotWindow);
1393 mpVariablesTreeModel->blockSignals(state);
1394 } else {
1395 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1396 }
1397 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) {
1398 QString xVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getXVariable());
1399 VariablesTreeItem *pXVariableTreeItem;
1400 pXVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(xVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1401 QString yVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getYVariable());
1402 VariablesTreeItem *pYVariableTreeItem;
1403 pYVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(yVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1404 pPlotCurve->detach();
1405 if (pXVariableTreeItem && pYVariableTreeItem) {
1406 bool state = mpVariablesTreeModel->blockSignals(true);
1407 QModelIndex xIndex = mpVariablesTreeModel->variablesTreeItemIndex(pXVariableTreeItem);
1408 mpVariablesTreeModel->setData(xIndex, Qt::Checked, Qt::CheckStateRole);
1409 plotVariables(xIndex, pPlotCurve->getCurveWidth(), pPlotCurve->getCurveStyle(), pPlotCurve, pPlotWindow);
1410 QModelIndex yIndex = mpVariablesTreeModel->variablesTreeItemIndex(pYVariableTreeItem);
1411 mpVariablesTreeModel->setData(yIndex, Qt::Checked, Qt::CheckStateRole);
1412 plotVariables(yIndex, pPlotCurve->getCurveWidth(), pPlotCurve->getCurveStyle(), pPlotCurve, pPlotWindow);
1413 mpVariablesTreeModel->blockSignals(state);
1414 } else {
1415 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1416 pPlotCurve->detach();
1417 }
1418 }
1419 }
1420 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1421 pPlotWindow->fitInView();
1422 } else {
1423 pPlotWindow->getPlot()->replot();
1424 }
1425 }
1426 }
1427 updateVariablesTreeHelper(MainWindow::instance()->getPlotWindowContainer()->currentSubWindow());
1428}
1429
1430void VariablesWidget::updateVariablesTreeHelper(QMdiSubWindow *pSubWindow)
1431{
1432 /* We always pause the visualization if we reach this function
1433 * This function can be reached via following ways,
1434 * When active PlotWindow is changed.
1435 * When active PlotWindow variables are updated.
1436 * When clearing the PlotWindow curves
1437 */
1438 pauseVisualization();
1439 if (!pSubWindow) {
1440 return;
1441 }
1442 // first clear all the check boxes in the tree
1443 bool state = mpVariablesTreeModel->blockSignals(true);
1444 mpVariablesTreeModel->unCheckVariables(mpVariablesTreeModel->getRootVariablesTreeItem());
1445 mpVariablesTreeModel->blockSignals(state);
1446 // all plotwindows are closed down then simply return
1447 if (MainWindow::instance()->getPlotWindowContainer()->subWindowList().size() == 0) {
1448 return;
1449 }
1450 PlotWindow *pPlotWindow = qobject_cast<PlotWindow*>(pSubWindow->widget());
1451 if (pPlotWindow) { // we can have an AnimateWindow there as well so always check
1452 // update the simulation time unit
1453 mpSimulationTimeComboBox->setCurrentIndex(mpSimulationTimeComboBox->findText(pPlotWindow->getTimeUnit(), Qt::MatchExactly));
1454 // now loop through the curves and tick variables in the tree whose curves are on the plot
1455 state = mpVariablesTreeModel->blockSignals(true);
1456 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)
{
1457 VariablesTreeItem *pVariablesTreeItem;
1458 if (pPlotWindow->getPlotType() == PlotWindow::PLOT || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY) {
1459 QString variable = pPlotCurve->getNameStructure();
1460 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(variable, mpVariablesTreeModel->getRootVariablesTreeItem());
1461 if (pVariablesTreeItem) {
1462 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1463 }
1464 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) {
1465 // check the xvariable
1466 QString xVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getXVariable());
1467 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(xVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1468 if (pVariablesTreeItem)
1469 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1470 // check the y variable
1471 QString yVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getYVariable());
1472 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(yVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1473 if (pVariablesTreeItem)
1474 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1475 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTINTERACTIVE) {
1476 QString variable = pPlotCurve->getNameStructure();
1477 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(variable, mpVariablesTreeModel->getRootVariablesTreeItem());
1478 if (pVariablesTreeItem) {
1479 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Checked, Qt::CheckStateRole);
1480 }
1481 // if a simulation was left running, make a replot
1482 pPlotWindow->getPlot()->replot();
1483 }
1484 }
1485 mpVariablesTreeModel->blockSignals(state);
1486 }
1487 /* invalidate the view so that the items show the updated values. */
1488 mpVariableTreeProxyModel->invalidate();
1489}
1490
1491void VariablesWidget::interactiveReSimulation(QString modelName)
1492{
1493 QList<QString> selectedVariables = mSelectedInteractiveVariables.value(modelName);
1494
1495 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)
{
1496 QString curveNameStructure = modelName + "." + variable;
1497 VariablesTreeItem *pVariableTreeItem;
1498 pVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(curveNameStructure, mpVariablesTreeModel->getRootVariablesTreeItem());
1499 if (pVariableTreeItem) {
1500 bool state = mpVariablesTreeModel->blockSignals(true);
1501 QModelIndex index = mpVariablesTreeModel->variablesTreeItemIndex(pVariableTreeItem);
1502 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1503 plotVariables(index, 1, 1);
1504 mpVariablesTreeModel->blockSignals(state);
1505 }
1506 }
1507}
1508
1509/*!
1510 * \brief VariablesWidget::readVariablesAndUpdateXML
1511 * Reads the updated values
1512 * \sa VariablesWidget::findVariableAndUpdateValue()
1513 * \param pVariablesTreeItem
1514 * \param outputFileName
1515 * \param variables
1516 */
1517void VariablesWidget::readVariablesAndUpdateXML(VariablesTreeItem *pVariablesTreeItem, QString outputFileName,
1518 QHash<QString, QHash<QString, QString> > *variables)
1519{
1520 for (int i = 0 ; i < pVariablesTreeItem->getChildren().size() ; i++) {
1521 VariablesTreeItem *pChildVariablesTreeItem = pVariablesTreeItem->child(i);
1522 if (pChildVariablesTreeItem->isEditable() && pChildVariablesTreeItem->isValueChanged()) {
1523 //QString value = pChildVariablesTreeItem->data(1, Qt::DisplayRole).toString();
1524 /* Ticket #2250, 4031
1525 * We need to convert the value to base unit since the values stored in init xml are always in base unit.
1526 */
1527 QString value = pChildVariablesTreeItem->getValue(pChildVariablesTreeItem->getDisplayUnit(),
1528 pChildVariablesTreeItem->getUnit()).toString();
1529 QString variableToFind = pChildVariablesTreeItem->getVariableName();
1530 variableToFind.remove(QRegExp(outputFileName + "."));
1531 QHash<QString, QString> hash;
1532 hash["name"] = variableToFind;
1533 hash["value"] = value;
1534 variables->insert(variableToFind, hash);
1535 }
1536 readVariablesAndUpdateXML(pChildVariablesTreeItem, outputFileName, variables);
1537 }
1538}
1539
1540/*!
1541 * \brief VariablesWidget::findVariableAndUpdateValue
1542 * Writes the updated values in the init xml dom
1543 * \param xmlDocument
1544 * \param variables
1545 */
1546void VariablesWidget::findVariableAndUpdateValue(QDomDocument xmlDocument, QHash<QString, QHash<QString, QString> > variables)
1547{
1548 /* if no variables are changed. */
1549 if (variables.empty()) {
1550 return;
1551 }
1552 /* update the variables */
1553 int count = 0;
1554 QDomNodeList scalarVariable = xmlDocument.elementsByTagName("ScalarVariable");
1555 for (int i = 0; i < scalarVariable.size(); i++) {
1556 if (count >= variables.size()) {
1557 break;
1558 }
1559 QDomElement element = scalarVariable.at(i).toElement();
1560 if (!element.isNull()) {
1561 QHash<QString, QString> hash = variables.value(element.attribute("name"));
1562 if (element.attribute("name").compare(hash["name"]) == 0) {
1563 count++;
1564 QDomElement el = scalarVariable.at(i).firstChild().toElement();
1565 if (!el.isNull()) {
1566 el.setAttribute("start", hash["value"]);
1567 }
1568 }
1569 }
1570 }
1571}
1572
1573void VariablesWidget::reSimulate(bool showSetup)
1574{
1575 QModelIndexList indexes = mpVariablesTreeView->selectionModel()->selectedIndexes();
1576 if (indexes.isEmpty()) {
1577 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1578 tr("You must select a class to re-simulate."), Helper::ok);
1579 return;
1580 }
1581 QModelIndex index = indexes.at(0);
1582 index = mpVariableTreeProxyModel->mapToSource(index);
1583 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1584 pVariablesTreeItem = pVariablesTreeItem->rootParent();
1585 SimulationOptions simulationOptions = pVariablesTreeItem->getSimulationOptions();
1586 if (simulationOptions.isValid()) {
1587 if (simulationOptions.isInteractiveSimulation()) {
1588 QMessageBox::information(this, QString("%1 - %2").arg(Helper::applicationName, Helper::information),
1589 tr("You cannot re-simulate an interactive simulation."), Helper::ok);
1590 } else {
1591 simulationOptions.setReSimulate(true);
1592 updateInitXmlFile(simulationOptions);
1593 if (showSetup) {
1594 MainWindow::instance()->getSimulationDialog()->show(0, true, simulationOptions);
1595 } else {
1596 MainWindow::instance()->getSimulationDialog()->reSimulate(simulationOptions);
1597 }
1598 }
1599 } else {
1600 QMessageBox::information(this, QString("%1 - %2").arg(Helper::applicationName, Helper::information),
1601 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);
1602 }
1603}
1604
1605void VariablesWidget::updateInitXmlFile(SimulationOptions simulationOptions)
1606{
1607 /* Update the _init.xml file with new values. */
1608 /* open the model_init.xml file for writing */
1609 QString initFileName = QString(simulationOptions.getOutputFileName()).append("_init.xml");
1610 QFile initFile(QString(simulationOptions.getWorkingDirectory()).append(QDir::separator()).append(initFileName));
1611 QDomDocument initXmlDocument;
1612 if (initFile.open(QIODevice::ReadOnly)) {
1613 if (initXmlDocument.setContent(&initFile)) {
1614 VariablesTreeItem *pTopVariableTreeItem;
1615 pTopVariableTreeItem = mpVariablesTreeModel->findVariablesTreeItem(simulationOptions.getFullResultFileName(),
1616 mpVariablesTreeModel->getRootVariablesTreeItem());
1617 if (pTopVariableTreeItem) {
1618 QHash<QString, QHash<QString, QString> > variables;
1619 readVariablesAndUpdateXML(pTopVariableTreeItem, simulationOptions.getFullResultFileName(), &variables);
1620 findVariableAndUpdateValue(initXmlDocument, variables);
1621 }
1622 } else {
1623 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
1624 tr("Unable to set the content of QDomDocument from file %1")
1625 .arg(initFile.fileName()), Helper::scriptingKind, Helper::errorLevel));
1626 }
1627 initFile.close();
1628 initFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
1629 QTextStream textStream(&initFile);
1630 textStream.setCodec(Helper::utf8.toUtf8().constData());
1631 textStream.setGenerateByteOrderMark(false);
1632 textStream << initXmlDocument.toString();
1633 initFile.close();
1634 } else {
1635 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
1636 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE).arg(initFile.fileName())
1637 .arg(initFile.errorString()), Helper::scriptingKind, Helper::errorLevel));
1638 }
1639}
1640
1641/*!
1642 * \brief VariablesWidget::initializeVisualization
1643 * Initializes the TimeManager with SimulationOptions for Visualization.
1644 * \param simulationOptions
1645 */
1646void VariablesWidget::initializeVisualization(SimulationOptions simulationOptions)
1647{
1648 // close any result file before opening a new one
1649 closeResultFile();
1650 // Open the file for reading
1651 openResultFile();
1652 // Initialize the time manager
1653 mpTimeManager->setStartTime(simulationOptions.getStartTime().toDouble());
1654 mpTimeManager->setEndTime(simulationOptions.getStopTime().toDouble());
1655 mpTimeManager->setVisTime(mpTimeManager->getStartTime());
1656 mpTimeManager->setPause(true);
1657 // reset the visualization controls
1658 mpTimeTextBox->setText("0.0");
1659 mpSimulationTimeSlider->setValue(mpSimulationTimeSlider->minimum());
1660 enableVisualizationControls(true);
1661}
1662
1663/*!
1664 * \brief VariablesWidget::readVariableValue
1665 * Reads the variable value at specific time.
1666 * \param variable
1667 * \param time
1668 * \return
1669 */
1670double VariablesWidget::readVariableValue(QString variable, double time)
1671{
1672 double value = 0.0;
1673 if (mModelicaMatReader.file) {
1674 ModelicaMatVariable_t* var = omc_matlab4_find_var(&mModelicaMatReader, variable.toUtf8().constData());
1675 if (var) {
1676 omc_matlab4_val(&value, &mModelicaMatReader, var, time);
1677 }
1678 } else if (mpCSVData) {
1679 double *timeDataSet = read_csv_dataset(mpCSVData, "time");
1680 if (timeDataSet) {
1681 for (int i = 0 ; i < mpCSVData->numsteps ; i++) {
1682 if (QString::number(timeDataSet[i]).compare(QString::number(time)) == 0) {
1683 double *varDataSet = read_csv_dataset(mpCSVData, variable.toUtf8().constData());
1684 if (varDataSet) {
1685 value = varDataSet[i];
1686 break;
1687 }
1688 }
1689 }
1690 }
1691 } else if (mPlotFileReader.isOpen()) {
1692 QTextStream textStream(&mPlotFileReader);
1693 QString currentLine;
1694 bool variableFound = false;
1695 while (!textStream.atEnd()) {
1696 currentLine = textStream.readLine();
1697 if (currentLine.compare(QString("DataSet: %1").arg(variable)) == 0) {
1698 variableFound = true;
1699 } else if (variableFound) {
1700 if (currentLine.startsWith("DataSet:")) { // new dataset started. Unable to find the value.
1701 break;
1702 }
1703 QStringList values = currentLine.split(",");
1704 if (QString::number(time).compare(values[0]) == 0) {
1705 value = values[1].toDouble();
1706 break;
1707 }
1708 }
1709 }
1710 textStream.seek(0);
1711 }
1712 return value;
1713}
1714
1715void VariablesWidget::plotVariables(const QModelIndex &index, qreal curveThickness, int curveStyle, PlotCurve *pPlotCurve,
1716 PlotWindow *pPlotWindow)
1717{
1718 if (index.column() > 0) {
1719 return;
1720 }
1721 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
1722 if (!pVariablesTreeItem) {
1723 return;
1724 }
1725 try {
1726 // if pPlotWindow is 0 then get the current window.
1727 if (!pPlotWindow) {
1728 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
1729 }
1730 // if the variable is not an array and
1731 // pPlotWindow is 0 or the plot's type is PLOTARRAY or PLOTARRAYPARAMETRIC
1732 // then create a new plot window.
1733 if (!pVariablesTreeItem->isMainArray() &&
1734 (!pPlotWindow || pPlotWindow->getPlotType()==PlotWindow::PLOTARRAY
1735 || pPlotWindow->getPlotType()== PlotWindow::PLOTARRAYPARAMETRIC))
1736 {
1737 MainWindow::instance()->getPlotWindowContainer()->addPlotWindow();
1738 bool state = MainWindow::instance()->getPlotWindowContainer()->blockSignals(true);
1739 bool state2 = mpVariablesTreeModel->blockSignals(true);
1740 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1741 mpVariablesTreeModel->blockSignals(state2);
1742 MainWindow::instance()->getPlotWindowContainer()->blockSignals(state);
1743 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
1744 }
1745 // if the variable is an array and
1746 // pPlotWindow is 0 or the plot's type is PLOT or PLOTPARAMETRIC
1747 // then create a new plot window.
1748 else if (pVariablesTreeItem->isMainArray() &&
1749 (!pPlotWindow || pPlotWindow->getPlotType()==PlotWindow::PLOT ||
1750 pPlotWindow->getPlotType()==PlotWindow::PLOTPARAMETRIC))
1751 {
1752 MainWindow::instance()->getPlotWindowContainer()->addArrayPlotWindow();
1753 bool state = MainWindow::instance()->getPlotWindowContainer()->blockSignals(true);
1754 bool state2 = mpVariablesTreeModel->blockSignals(true);
1755 mpVariablesTreeModel->setData(index, Qt::Checked, Qt::CheckStateRole);
1756 mpVariablesTreeModel->blockSignals(state2);
1757 MainWindow::instance()->getPlotWindowContainer()->blockSignals(state);
1758 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
1759 }
1760
1761
1762
1763 // if still pPlotWindow is 0 then return.
1764 if (!pPlotWindow) {
1765 bool state = mpVariablesTreeModel->blockSignals(true);
1766 mpVariablesTreeModel->setData(index, Qt::Unchecked, Qt::CheckStateRole);
1767 mpVariablesTreeModel->blockSignals(state);
1768 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1769 tr("No plot window is active for plotting. Please select a plot window or open a new."), Helper::ok);
1770 return;
1771 }
1772 // if plottype is PLOT or PLOTARRAY then
1773 if (pPlotWindow->getPlotType() == PlotWindow::PLOT || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY) {
1774 // check the item checkstate
1775 if (pVariablesTreeItem->isChecked()) {
1776 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
1777 if (!pVariablesTreeItem->isRootItem()) {
1778 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
1779 }
1780 if (pVariablesTreeRootItem->getSimulationOptions().isInteractiveSimulation()) {
1781 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1782 tr("Can not be attached to a plot window."), Helper::ok);
1783 pVariablesTreeItem->setChecked(false);
1784 return;
1785 }
1786 pPlotWindow->initializeFile(QString(pVariablesTreeItem->getFilePath()).append("/").append(pVariablesTreeItem->getFileName()));
1787 pPlotWindow->setCurveWidth(curveThickness);
1788 pPlotWindow->setCurveStyle(curveStyle);
1789 pPlotWindow->setVariablesList(QStringList(pVariablesTreeItem->getPlotVariable()));
1790 pPlotWindow->setUnit(pVariablesTreeItem->getUnit());
1791 pPlotWindow->setDisplayUnit(pVariablesTreeItem->getDisplayUnit());
1792 if (pPlotWindow->getPlotType() == PlotWindow::PLOT)
1793 pPlotWindow->plot(pPlotCurve);
1794 else/* ie. (pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY)*/{
1795 double timePercent = mpTimeTextBox->text().toDouble();
1796 pPlotWindow->plotArray(timePercent,pPlotCurve);
1797 }
1798 /* Ticket:4231
1799 * Only update the variables browser value and unit when updating some curve not when checking/unchecking variable.
1800 */
1801 if (pPlotCurve) {
1802 /* Ticket:2250
1803 * Update the value of Variables Browser display unit according to the display unit of already plotted curve.
1804 */
1805 pVariablesTreeItem->setData(3, pPlotCurve->getDisplayUnit(), Qt::EditRole);
1806 QString value = pVariablesTreeItem->getValue(pVariablesTreeItem->getPreviousUnit(), pVariablesTreeItem->getDisplayUnit()).toString();
1807 pVariablesTreeItem->setData(1, value, Qt::EditRole);
1808 }
1809 if (!pPlotCurve) {
1810 pPlotCurve = pPlotWindow->getPlot()->getPlotCurvesList().last();
1811 }
1812 if (pPlotCurve && pVariablesTreeItem->getUnit().compare(pVariablesTreeItem->getDisplayUnit()) != 0) {
1813 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(pVariablesTreeItem->getUnit(),
1814 pVariablesTreeItem->getDisplayUnit());
1815 if (convertUnit.unitsCompatible) {
1816 for (int i = 0 ; i < pPlotCurve->mYAxisVector.size() ; i++) {
1817 pPlotCurve->updateYAxisValue(i, Utilities::convertUnit(pPlotCurve->mYAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
1818 }
1819 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
1820 pPlotWindow->getPlot()->replot();
1821 } else {
1822 pPlotCurve->setDisplayUnit(pVariablesTreeItem->getUnit());
1823 }
1824 pPlotCurve->setTitleLocal();
1825 }
1826 // update the time values if time unit is different then s
1827 if (pPlotWindow->getTimeUnit().compare("s") != 0) {
1828 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits("s", pPlotWindow->getTimeUnit());
1829 if (convertUnit.unitsCompatible) {
1830 for (int i = 0 ; i < pPlotCurve->mXAxisVector.size() ; i++) {
1831 pPlotCurve->updateXAxisValue(i, Utilities::convertUnit(pPlotCurve->mXAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
1832 }
1833 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
1834 pPlotWindow->getPlot()->replot();
1835 }
1836 }
1837 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1838 pPlotWindow->fitInView();
1839 } else {
1840 pPlotWindow->getPlot()->replot();
1841 if (pPlotWindow->getPlot()->getPlotZoomer()->zoomStack().size() == 1) {
1842 pPlotWindow->getPlot()->getPlotZoomer()->setZoomBase(false);
1843 }
1844 }
1845 } else if (!pVariablesTreeItem->isChecked()) { // if user unchecks the variable then remove it from the plot
1846 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)
{
1847 QString curveTitle = pPlotCurve->getNameStructure();
1848 if (curveTitle.compare(pVariablesTreeItem->getVariableName()) == 0) {
1849 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1850 pPlotCurve->detach();
1851 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1852 pPlotWindow->fitInView();
1853 } else {
1854 pPlotWindow->getPlot()->replot();
1855 }
1856 break;
1857 }
1858 }
1859 }
1860 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC || pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) { // if plottype is PLOTPARAMETRIC or PLOTARRAYPARAMETRIC then
1861 // check the item checkstate
1862 if (pVariablesTreeItem->isChecked()) {
1863 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
1864 if (!pVariablesTreeItem->isRootItem()) {
1865 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
1866 }
1867 if (pVariablesTreeRootItem->getSimulationOptions().isInteractiveSimulation()) {
1868 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
1869 tr("Can not be attached to a parametric plot window."), Helper::ok);
1870 pVariablesTreeItem->setChecked(false);
1871 return;
1872 }
1873 // if mPlotParametricVariables is empty just add one QStringlist with 1 varibale to it
1874 if (mPlotParametricVariables.isEmpty()) {
1875 mPlotParametricVariables.append(QStringList() << pVariablesTreeItem->getPlotVariable() << pVariablesTreeItem->getUnit());
1876 mFileName = pVariablesTreeItem->getFileName();
1877 } else { // if mPlotParametricVariables is not empty then add one string to its last element
1878 if (mPlotParametricVariables.last().size() < 4) {
1879 if (mFileName.compare(pVariablesTreeItem->getFileName()) != 0) {
1880 bool state = mpVariablesTreeModel->blockSignals(true);
1881 mpVariablesTreeModel->setData(index, Qt::Unchecked, Qt::CheckStateRole);
1882 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error),
1883 GUIMessages::getMessage(GUIMessages::PLOT_PARAMETRIC_DIFF_FILES), Helper::ok);
1884 mpVariablesTreeModel->blockSignals(state);
1885 return;
1886 }
1887 mPlotParametricVariables.last().append(QStringList() << pVariablesTreeItem->getPlotVariable() << pVariablesTreeItem->getUnit());
1888 pPlotWindow->initializeFile(QString(pVariablesTreeItem->getFilePath()).append("/").append(pVariablesTreeItem->getFileName()));
1889 pPlotWindow->setCurveWidth(curveThickness);
1890 pPlotWindow->setCurveStyle(curveStyle);
1891 pPlotWindow->setVariablesList(QStringList() << mPlotParametricVariables.last().at(0) << mPlotParametricVariables.last().at(2));
1892 if (pPlotWindow->getPlotType() == PlotWindow::PLOTPARAMETRIC)
1893 pPlotWindow->plotParametric(pPlotCurve);
1894 else /* ie. (pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC)*/{
1895 double timePercent = mpTimeTextBox->text().toDouble();
1896 pPlotWindow->plotArrayParametric(timePercent,pPlotCurve);
1897 }
1898
1899 if (pPlotWindow->getPlot()->getPlotCurvesList().size() > 1) {
1900 pPlotWindow->setXLabel("");
1901 pPlotWindow->setYLabel("");
1902 } else {
1903 QString xVariable = mPlotParametricVariables.last().at(0);
1904 QString xUnit = mPlotParametricVariables.last().at(1);
1905 QString yVariable = mPlotParametricVariables.last().at(2);
1906 QString yUnit = mPlotParametricVariables.last().at(3);
1907 if (xUnit.isEmpty()) {
1908 pPlotWindow->setXLabel(xVariable);
1909 } else {
1910 pPlotWindow->setXLabel(xVariable + " (" + xUnit + ")");
1911 }
1912
1913 if (yUnit.isEmpty()) {
1914 pPlotWindow->setYLabel(yVariable);
1915 } else {
1916 pPlotWindow->setYLabel(yVariable + " (" + yUnit + ")");
1917 }
1918 }
1919 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1920 pPlotWindow->fitInView();
1921 } else {
1922 pPlotWindow->getPlot()->replot();
1923 if (pPlotWindow->getPlot()->getPlotZoomer()->zoomStack().size() == 1) {
1924 pPlotWindow->getPlot()->getPlotZoomer()->setZoomBase(false);
1925 }
1926 }
1927 } else {
1928 mPlotParametricVariables.append(QStringList() << pVariablesTreeItem->getPlotVariable() << pVariablesTreeItem->getUnit());
1929 mFileName = pVariablesTreeItem->getFileName();
1930 }
1931 }
1932 } else if (!pVariablesTreeItem->isChecked()) { // if user unchecks the variable then remove it from the plot
1933 // remove the variable from mPlotParametricVariables list
1934 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)
{
1935 if (list.contains(pVariablesTreeItem->getPlotVariable())) {
1936 // if list has only one variable then clear the list and return;
1937 if (list.size() < 4) {
1938 mPlotParametricVariables.removeOne(list);
1939 break;
1940 } else { // if list has more than two variables then remove both and remove the curve
1941 QString itemTitle = QString(pVariablesTreeItem->getFileName()).append(".").append(list.at(2)).append(" vs ").append(list.at(0));
1942 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)
{
1943 QString curveTitle = pPlotCurve->getNameStructure();
1944 if ((curveTitle.compare(itemTitle) == 0) && (pVariablesTreeItem->getFileName().compare(pPlotCurve->getFileName()) == 0)) {
1945 bool state = mpVariablesTreeModel->blockSignals(true);
1946 // uncheck the x variable
1947 QString xVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getXVariable());
1948 VariablesTreeItem *pVariablesTreeItem;
1949 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(xVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1950 if (pVariablesTreeItem) {
1951 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Unchecked, Qt::CheckStateRole);
1952 }
1953 // uncheck the y variable
1954 QString yVariable = QString(pPlotCurve->getFileName()).append(".").append(pPlotCurve->getYVariable());
1955 pVariablesTreeItem = mpVariablesTreeModel->findVariablesTreeItem(yVariable, mpVariablesTreeModel->getRootVariablesTreeItem());
1956 if (pVariablesTreeItem) {
1957 mpVariablesTreeModel->setData(mpVariablesTreeModel->variablesTreeItemIndex(pVariablesTreeItem), Qt::Unchecked, Qt::CheckStateRole);
1958 }
1959 mpVariablesTreeModel->blockSignals(state);
1960 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
1961 pPlotCurve->detach();
1962 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
1963 pPlotWindow->fitInView();
1964 } else {
1965 pPlotWindow->getPlot()->replot();
1966 }
1967 }
1968 }
1969 mPlotParametricVariables.removeOne(list);
1970 if (pPlotWindow->getPlot()->getPlotCurvesList().size() == 1) {
1971 if (mPlotParametricVariables.last().size() > 3) {
1972 QString xVariable = mPlotParametricVariables.last().at(0);
1973 QString xUnit = mPlotParametricVariables.last().at(1);
1974 QString yVariable = mPlotParametricVariables.last().at(2);
1975 QString yUnit = mPlotParametricVariables.last().at(3);
1976 if (xUnit.isEmpty()) {
1977 pPlotWindow->setXLabel(xVariable);
1978 } else {
1979 pPlotWindow->setXLabel(xVariable + " (" + xUnit + ")");
1980 }
1981
1982 if (yUnit.isEmpty()) {
1983 pPlotWindow->setYLabel(yVariable);
1984 } else {
1985 pPlotWindow->setYLabel(yVariable + " (" + yUnit + ")");
1986 }
1987 } else {
1988 pPlotWindow->setXLabel("");
1989 pPlotWindow->setYLabel("");
1990 }
1991 } else {
1992 pPlotWindow->setXLabel("");
1993 pPlotWindow->setYLabel("");
1994 }
1995 }
1996 }
1997 }
1998 }
1999 }
2000 else { // if plottype is INTERACTIVE then
2001 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
2002 if (!pVariablesTreeItem->isRootItem()) {
2003 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
2004 }
2005 int port = pVariablesTreeRootItem->getSimulationOptions().getInteractiveSimulationPortNumber();
2006
2007 if (pVariablesTreeItem->isChecked()) { // if user checks the variable
2008 if (!pVariablesTreeRootItem->getSimulationOptions().isInteractiveSimulation()) {
2009 QMessageBox::information(this, QString(Helper::applicationName).append(" - ").append(Helper::information),
2010 tr("Can not be attached to an interactive plot window."), Helper::ok);
2011 pVariablesTreeItem->setChecked(false);
2012 } else {
2013 // if user checks a variable belonging to an inactive plot window, switch to it.
2014 if (pPlotWindow->getInteractiveOwner() != pVariablesTreeRootItem->getFileName()) {
2015 pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getInteractiveWindow(pVariablesTreeRootItem->getFileName());
2016 MainWindow::instance()->getPlotWindowContainer()->setActiveSubWindow(pPlotWindow->getSubWindow());
2017 } else {
2018 pPlotWindow->setCurveWidth(curveThickness);
2019 pPlotWindow->setCurveStyle(curveStyle);
2020 QString plotVariable = pVariablesTreeItem->getPlotVariable();
2021 pPlotWindow->setVariablesList(QStringList(plotVariable));
2022 pPlotWindow->setUnit(pVariablesTreeItem->getUnit());
2023 pPlotWindow->setDisplayUnit(pVariablesTreeItem->getDisplayUnit());
2024 pPlotWindow->setInteractiveModelName(pVariablesTreeItem->getFileName());
2025 OpcUaClient *pOpcUaClient = MainWindow::instance()->getSimulationDialog()->getOpcUaClient(port);
2026 if (pOpcUaClient) {
2027 Variable *pCurveData = *pOpcUaClient->getVariables()->find(plotVariable);
2028 QwtSeriesData<QPointF>* pData = dynamic_cast<QwtSeriesData<QPointF>*>(pCurveData);
2029 pPlotWindow->setInteractivePlotData(pData);
2030 QPair<QVector<double>*, QVector<double>*> memory = pPlotWindow->plotInteractive(pPlotCurve);
2031 // use the same vectors as a normal plot
2032 pCurveData->setAxisVectors(memory);
2033 pOpcUaClient->checkVariable(pCurveData->getNodeId(), pVariablesTreeItem);
2034 }
2035 }
2036 }
2037 }
2038 else if (!pVariablesTreeItem->isChecked()) { // if user unchecks the variable
2039 // remove the variable from the data fetch list
2040 OpcUaClient *pOpcUaClient = MainWindow::instance()->getSimulationDialog()->getOpcUaClient(port);
2041 if (pOpcUaClient) {
2042 Variable *pCurveData = *pOpcUaClient->getVariables()->find(pVariablesTreeItem->getPlotVariable());
2043 pOpcUaClient->unCheckVariable(pCurveData->getNodeId(), pVariablesTreeItem->getPlotVariable());
2044 }
2045 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)
{
2046 /* FIX: Make sure to remove the right curve when implementing several interactive simulations at the same time */
2047 if (pVariablesTreeItem->getVariableName().endsWith("." + pPlotCurve->getName())) {
2048 pPlotWindow->getPlot()->removeCurve(pPlotCurve);
2049 pPlotCurve->detach();
2050 if (pPlotWindow->getAutoScaleButton()->isChecked()) {
2051 pPlotWindow->fitInView();
2052 } else {
2053 pPlotWindow->getPlot()->replot();
2054 }
2055 break;
2056 }
2057 }
2058 }
2059 }
2060 } catch (PlotException &e) {
2061 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2062 }
2063}
2064
2065void VariablesWidget::addSelectedInteractiveVariables(const QString &modelName, const QList<QString> &selectedVariables)
2066{
2067 mSelectedInteractiveVariables.insert(modelName, selectedVariables);
2068}
2069
2070/*!
2071 * \brief VariablesWidget::unitChanged
2072 * Handles the case when display unit is changed in VariablesTreeView.\n
2073 * Updates the values according to the new display unit.
2074 * \param index
2075 */
2076void VariablesWidget::unitChanged(const QModelIndex &index)
2077{
2078 if (index.column() != 3) {
2079 return;
2080 }
2081 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
2082 if (!pVariablesTreeItem) {
2083 return;
2084 }
2085 try {
2086 OMPlot::PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2087 // if still pPlotWindow is 0 then return.
2088 if (!pPlotWindow) {
2089 return;
2090 }
2091 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(pVariablesTreeItem->getPreviousUnit(),
2092 pVariablesTreeItem->getDisplayUnit());
2093 if (convertUnit.unitsCompatible) {
2094 /* update value */
2095 QVariant stringValue = pVariablesTreeItem->data(1, Qt::EditRole);
2096 bool ok = true;
2097 qreal realValue = stringValue.toDouble(&ok);
2098 if (ok) {
2099 realValue = Utilities::convertUnit(realValue, convertUnit.offset, convertUnit.scaleFactor);
2100 pVariablesTreeItem->setData(1, QString::number(realValue), Qt::EditRole);
2101 }
2102 /* update plots */
2103 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)
{
2104 QString curveTitle = pPlotCurve->getNameStructure();
2105 if (curveTitle.compare(pVariablesTreeItem->getVariableName()) == 0) {
2106 for (int i = 0 ; i < pPlotCurve->mYAxisVector.size() ; i++) {
2107 pPlotCurve->updateYAxisValue(i, Utilities::convertUnit(pPlotCurve->mYAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
2108 }
2109 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
2110 pPlotCurve->setDisplayUnit(pVariablesTreeItem->getDisplayUnit());
2111 pPlotCurve->setTitleLocal();
2112 pPlotWindow->getPlot()->replot();
2113 break;
2114 }
2115 }
2116 }
2117 } catch (PlotException &e) {
2118 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2119 }
2120}
2121
2122/*!
2123 * \brief VariablesWidget::simulationTimeChanged
2124 * SLOT activated when mpSimulationTimeSlider valueChanged SIGNAL is raised.
2125 * \param time
2126 */
2127void VariablesWidget::simulationTimeChanged(int timePercent)
2128{
2129 double time = (mpTimeManager->getEndTime() - mpTimeManager->getStartTime()) * ((double)timePercent / (double)mSliderRange);
2130 mpTimeManager->setVisTime(time);
2131 mpTimeTextBox->setText(QString::number(mpTimeManager->getVisTime()));
2132
2133 PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2134 if (pPlotWindow) {
2135 try {
2136 PlotWindow::PlotType plotType = pPlotWindow->getPlotType();
2137 if (plotType == PlotWindow::PLOTARRAY) {
2138 QList<PlotCurve*> curves = pPlotWindow->getPlot()->getPlotCurvesList();
2139 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)
{
2140 QString varName = curve->getYVariable();
2141 pPlotWindow->setVariablesList(QStringList(varName));
2142 pPlotWindow->plotArray(time, curve);
2143 }
2144 } else if (plotType == PlotWindow::PLOTARRAYPARAMETRIC) {
2145 QList<PlotCurve*> curves = pPlotWindow->getPlot()->getPlotCurvesList();
2146 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)
{
2147 QString xVarName = curve->getXVariable();
2148 QString yVarName = curve->getYVariable();
2149 pPlotWindow->setVariablesList({xVarName,yVarName});
2150 pPlotWindow->plotArrayParametric(time, curve);
2151 }
2152 } else {
2153 return;
2154 }
2155 } catch (PlotException &e) {
2156 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, e.what(), Helper::scriptingKind, Helper::errorLevel));
2157 }
2158 } else { // if no plot window then try to update the DiagramWindow
2159 updateVisualization();
2160 }
2161}
2162/*!
2163 * \brief VariablesWidget::valueEntered
2164 * Handles the case when a new value is entered in VariablesTreeView.\n
2165 * \param index
2166 */
2167void VariablesWidget::valueEntered(const QModelIndex &index)
2168{
2169 if (index.column() != 1) {
2170 return;
2171 }
2172 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
2173 if (!pVariablesTreeItem) {
2174 return;
2175 }
2176 try {
2177 OMPlot::PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2178 // if still pPlotWindow is 0 then return.
2179 if (!pPlotWindow) {
2180 return;
2181 }
2182 QVariant variableValue = pVariablesTreeItem->getValue(pVariablesTreeItem->getDisplayUnit(), pVariablesTreeItem->getUnit()).toDouble();
2183 QString variableName = pVariablesTreeItem->getPlotVariable();
2184 // make sure the write goes to the right server
2185 VariablesTreeItem *pVariablesTreeRootItem = pVariablesTreeItem;
2186 if (!pVariablesTreeItem->isRootItem()) {
2187 pVariablesTreeRootItem = pVariablesTreeItem->rootParent();
2188 }
2189 int port = pVariablesTreeRootItem->getSimulationOptions().getInteractiveSimulationPortNumber();
2190 OpcUaClient *pOpcUaClient = MainWindow::instance()->getSimulationDialog()->getOpcUaClient(port);
2191 if (pOpcUaClient) {
2192 pOpcUaClient->writeValue(variableValue, variableName);
2193 }
2194
2195 } catch (PlotException &e) {
2196 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2197 }
2198}
2199
2200void VariablesWidget::selectInteractivePlotWindow(VariablesTreeItem *pVariablesTreeItem)
2201{
2202 // look at the root parent
2203 if (!pVariablesTreeItem->isRootItem()) {
2204 pVariablesTreeItem = pVariablesTreeItem->rootParent();
2205 }
2206 // change to the corresponding subwindow
2207 if (pVariablesTreeItem->getSimulationOptions().isInteractiveSimulation()) {
2208 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)
{
2209 PlotWindow *pPlotWindow = qobject_cast<PlotWindow*>(pSubWindow->widget());
2210 if (pPlotWindow->getInteractiveOwner() == pVariablesTreeItem->getFileName()) {
2211 MainWindow::instance()->getPlotWindowContainer()->setActiveSubWindow(pSubWindow);
2212 }
2213 }
2214 }
2215}
2216
2217/*!
2218 * \brief VariablesWidget::closeResultFile
2219 * Closes the result file.
2220 */
2221void VariablesWidget::closeResultFile()
2222{
2223 if (mModelicaMatReader.file) {
2224 omc_free_matlab4_reader(&mModelicaMatReader);
2225 mModelicaMatReader.file = 0;
2226 }
2227 if (mpCSVData) {
2228 omc_free_csv_reader(mpCSVData);
2229 mpCSVData = 0;
2230 }
2231 if (mPlotFileReader.isOpen()) {
2232 mPlotFileReader.close();
2233 }
2234}
2235
2236/*!
2237 * \brief VariablesWidget::openResultFile
2238 * Opens the result file.
2239 */
2240void VariablesWidget::openResultFile()
2241{
2242 if (mpVariablesTreeModel->getActiveVariablesTreeItem()) {
2243 // read filename
2244 QString fileName = QString("%1/%2").arg(mpVariablesTreeModel->getActiveVariablesTreeItem()->getFilePath())
2245 .arg(mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName());
2246 bool errorOpeningFile = false;
2247 QString errorString = "";
2248 if (mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName().endsWith(".mat")) {
2249 const char *msg[] = {""};
2250 if (0 != (msg[0] = omc_new_matlab4_reader(fileName.toUtf8().constData(), &mModelicaMatReader))) {
2251 errorOpeningFile = true;
2252 errorString = msg[0];
2253 }
2254 } else if (mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName().endsWith(".csv")) {
2255 mpCSVData = read_csv(fileName.toUtf8().constData());
2256 if (!mpCSVData) {
2257 errorOpeningFile = true;
2258 }
2259 } else if (mpVariablesTreeModel->getActiveVariablesTreeItem()->getFileName().endsWith(".plt")) {
2260 mPlotFileReader.setFileName(fileName);
2261 if (!mPlotFileReader.open(QIODevice::ReadOnly)) {
2262 errorOpeningFile = true;
2263 errorString = mPlotFileReader.errorString();
2264 }
2265 }
2266 // check file opening error
2267 if (errorOpeningFile) {
2268 MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica,
2269 GUIMessages::getMessage(GUIMessages::ERROR_OPENING_FILE)
2270 .arg(fileName, errorString), Helper::scriptingKind, Helper::errorLevel));
2271 }
2272 }
2273}
2274
2275/*!
2276 * \brief VariablesWidget::updateVisualization
2277 * Updates the visualization.
2278 */
2279void VariablesWidget::updateVisualization()
2280{
2281 mpTimeManager->updateTick(); //for real-time measurement
2282 double visTime = mpTimeManager->getRealTime();
2283 // Update the DiagramWindow
2284 emit updateDynamicSelect(mpTimeManager->getVisTime());
2285 if (MainWindow::instance()->getPlotWindowContainer()->getDiagramWindow()
2286 && MainWindow::instance()->getPlotWindowContainer()->getDiagramWindow()->getGraphicsView()) {
2287 MainWindow::instance()->getPlotWindowContainer()->getDiagramWindow()->getGraphicsView()->scene()->update();
2288 }
2289 mpTimeManager->updateTick(); //for real-time measurement
2290 visTime = mpTimeManager->getRealTime() - visTime;
2291 mpTimeManager->setRealTimeFactor(mpTimeManager->getHVisual() / visTime);
2292}
2293
2294/*!
2295 * \brief VariablesWidget::timeUnitChanged
2296 * Handles the case when simulation time unit is changed.\n
2297 * Updates the x values of all the curves.
2298 * \param unit
2299 */
2300void VariablesWidget::timeUnitChanged(QString unit)
2301{
2302 if (unit.isEmpty()) {
2303 return;
2304 }
2305 try {
2306 OMPlot::PlotWindow *pPlotWindow = MainWindow::instance()->getPlotWindowContainer()->getCurrentWindow();
2307 // if still pPlotWindow is 0 then return.
2308 if (!pPlotWindow) {
2309 return;
2310 }
2311 if (pPlotWindow->getPlotType() == PlotWindow::PLOTARRAY ||
2312 pPlotWindow->getPlotType() == PlotWindow::PLOTARRAYPARAMETRIC) {
2313 pPlotWindow->setTimeUnit(unit);
2314 pPlotWindow->updateTimeText(unit);
2315 } else if (pPlotWindow->getPlotType() == PlotWindow::PLOT ||
2316 pPlotWindow->getPlotType() == PlotWindow::PLOTINTERACTIVE) {
2317 OMCInterface::convertUnits_res convertUnit = MainWindow::instance()->getOMCProxy()->convertUnits(pPlotWindow->getTimeUnit(), unit);
2318 if (convertUnit.unitsCompatible) {
2319 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)
{
2320 for (int i = 0 ; i < pPlotCurve->mXAxisVector.size() ; i++) {
2321 pPlotCurve->updateXAxisValue(i, Utilities::convertUnit(pPlotCurve->mXAxisVector.at(i), convertUnit.offset, convertUnit.scaleFactor));
2322 }
2323 pPlotCurve->setData(pPlotCurve->getXAxisVector(), pPlotCurve->getYAxisVector(), pPlotCurve->getSize());
2324 }
2325 pPlotWindow->setXLabel(QString("time (%1)").arg(unit));
2326 pPlotWindow->setTimeUnit(unit);
2327 pPlotWindow->getPlot()->replot();
2328 }
2329 }
2330 } catch (PlotException &e) {
2331 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::error), e.what(), Helper::ok);
2332 }
2333}
2334
2335/*!
2336 * \brief VariablesWidget::updateVariablesTree
2337 * Updates the VariablesTreeView when the subwindow is changed in PlotWindowContainer
2338 * \param pSubWindow
2339 */
2340void VariablesWidget::updateVariablesTree(QMdiSubWindow *pSubWindow)
2341{
2342 if (!pSubWindow && MainWindow::instance()->getPlotWindowContainer()->subWindowList().size() != 0) {
2343 return;
2344 }
2345 /* if the same sub window is activated again then just return */
2346 if (mpLastActiveSubWindow == pSubWindow) {
2347 mpLastActiveSubWindow = pSubWindow;
2348 return;
2349 }
2350 mpLastActiveSubWindow = pSubWindow;
2351 updateVariablesTreeHelper(pSubWindow);
2352}
2353
2354void VariablesWidget::showContextMenu(QPoint point)
2355{
2356 int adjust = 24;
2357 QModelIndex index = mpVariablesTreeView->indexAt(point);
2358 index = mpVariableTreeProxyModel->mapToSource(index);
2359 VariablesTreeItem *pVariablesTreeItem = static_cast<VariablesTreeItem*>(index.internalPointer());
2360 if (pVariablesTreeItem && pVariablesTreeItem->isRootItem()) {
2361 /* delete result action */
2362 QAction *pDeleteResultAction = new QAction(QIcon(":/Resources/icons/delete.svg"), tr("Delete Result"), this);
2363 pDeleteResultAction->setData(pVariablesTreeItem->getVariableName());
2364 pDeleteResultAction->setShortcut(QKeySequence::Delete);
2365 pDeleteResultAction->setStatusTip(tr("Delete the result"));
2366 connect(pDeleteResultAction, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(removeVariableTreeItem())"1""removeVariableTreeItem()");
2367
2368 /* set result active action */
2369 QAction *pSetResultActiveAction = new QAction(tr("Set Active"), this);
2370 pSetResultActiveAction->setData(pVariablesTreeItem->getVariableName());
2371 pSetResultActiveAction->setStatusTip(tr("An active item is used for the visualization"));
2372 pSetResultActiveAction->setEnabled(pVariablesTreeItem->getSimulationOptions().isValid()
2373 && !pVariablesTreeItem->getSimulationOptions().isInteractiveSimulation()
2374 && !pVariablesTreeItem->isActive());
2375 connect(pSetResultActiveAction, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(setVariableTreeItemActive())"1""setVariableTreeItemActive()");
2376
2377 QMenu menu(this);
2378 menu.addAction(pDeleteResultAction);
2379 menu.addSeparator();
2380 menu.addAction(pSetResultActiveAction);
2381 menu.addSeparator();
2382 menu.addAction(MainWindow::instance()->getReSimulateModelAction());
2383 menu.addAction(MainWindow::instance()->getReSimulateSetupAction());
2384 point.setY(point.y() + adjust);
2385 menu.exec(mpVariablesTreeView->mapToGlobal(point));
2386 } else if (pVariablesTreeItem) {
2387 qDebugQMessageLogger(nullptr, 0, nullptr).debug() << "showContextMenu" << index;
2388 qDebugQMessageLogger(nullptr, 0, nullptr).debug() << "name" << pVariablesTreeItem->getVariableName() << "path" << pVariablesTreeItem->getFilePath() << "uses" << pVariablesTreeItem->getUses();
2389 QAction *pGetDepends = new QAction(tr("Show only direct dependencies"), this);
2390 if (pVariablesTreeItem->getUses().size() <= 1 /* Self only */) {
2391 pGetDepends->setEnabled(false);
2392 }
2393 pGetDepends->setData(pVariablesTreeItem->getUses());
2394 pGetDepends->setStatusTip(tr("Show only variables that depend on this variable"));
2395
2396 QAction *pGetInitDepends = new QAction(tr("Show only direct dependencies (initial)"), this);
2397 if (pVariablesTreeItem->getInitialUses().size() <= 1 /* Self only */) {
2398 pGetInitDepends->setEnabled(false);
2399 }
2400 pGetInitDepends->setData(pVariablesTreeItem->getInitialUses());
2401 pGetInitDepends->setStatusTip(tr("Show only variables that depend on this variable in the initial system of equations"));
2402
2403 connect(pGetDepends, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(filterDependencies())"1""filterDependencies()");
2404 connect(pGetInitDepends, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(filterDependencies())"1""filterDependencies()");
2405
2406 QMenu menu(this);
2407 menu.addAction(pGetDepends);
2408 menu.addAction(pGetInitDepends);
2409
2410 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)
{
2411 if (pair.second == QString("")) {
2412 continue;
2413 }
2414 QAction *pGetDefines = new QAction(tr("Open debugger (equation %1 - %2)").arg(QString::number(pair.first), pair.second), this);
2415 QVariantList lst;
2416 lst << QString("%1/%2").arg(pVariablesTreeItem->getFilePath(), pVariablesTreeItem->getInfoFileName());
2417 lst << pair.first;
2418 pGetDefines->setData(lst);
2419 pGetDefines->setStatusTip(tr("Open debugger for the equation"));
2420 menu.addAction(pGetDefines);
2421
2422 connect(pGetDefines, SIGNAL(triggered())"2""triggered()", mpVariablesTreeModel, SLOT(openTransformationsBrowser())"1""openTransformationsBrowser()");
2423 }
2424
2425 menu.exec(mpVariablesTreeView->mapToGlobal(point));
2426 }
2427}
2428
2429/*!
2430 * \brief VariablesWidget::findVariables
2431 * Finds the variables in the Variables Browser.
2432 */
2433void VariablesWidget::findVariables()
2434{
2435 QString findText = mpTreeSearchFilters->getFilterTextBox()->text();
2436 QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(mpTreeSearchFilters->getSyntaxComboBox()->itemData(mpTreeSearchFilters->getSyntaxComboBox()->currentIndex()).toInt());
2437 Qt::CaseSensitivity caseSensitivity = mpTreeSearchFilters->getCaseSensitiveCheckBox()->isChecked() ? Qt::CaseSensitive: Qt::CaseInsensitive;
2438 QRegExp regExp(findText, caseSensitivity, syntax);
2439 mpVariableTreeProxyModel->setFilterRegExp(regExp);
2440 /* expand all so that the filtered items can be seen. */
2441 if (!findText.isEmpty()) {
2442 mpVariablesTreeView->expandAll();
2443 }
2444 if (mpVariablesTreeView->selectionModel()->selectedIndexes().isEmpty()) {
2445 QModelIndex proxyIndex = mpVariableTreeProxyModel->index(0, 0);
2446 if (proxyIndex.isValid()) {
2447 mpVariablesTreeView->selectionModel()->select(proxyIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows);
2448 }
2449 }
2450 MainWindow::instance()->enableReSimulationToolbar(MainWindow::instance()->getVariablesDockWidget()->isVisible());
2451}
2452
2453void VariablesWidget::directReSimulate()
2454{
2455 reSimulate(false);
2456}
2457
2458void VariablesWidget::showReSimulateSetup()
2459{
2460 reSimulate(true);
2461}
2462
2463/*!
2464 * \brief VariablesWidget::rewindVisualization
2465 * Slot activated when mpRewindAction triggered SIGNAL is raised.
2466 */
2467void VariablesWidget::rewindVisualization()
2468{
2469 mpTimeManager->setVisTime(mpTimeManager->getStartTime());
2470 mpTimeManager->setRealTimeFactor(0.0);
2471 mpTimeManager->setPause(true);
2472 mpSimulationTimeSlider->setValue(mpSimulationTimeSlider->minimum());
2473 mpTimeTextBox->setText(QString::number(mpTimeManager->getVisTime()));
2474}
2475
2476/*!
2477 * \brief VariablesWidget::playVisualization
2478 * Slot activated when mpPlayAction triggered SIGNAL is raised.
2479 */
2480void VariablesWidget::playVisualization()
2481{
2482 mpTimeManager->setPause(false);
2483}
2484
2485/*!
2486 * \brief VariablesWidget::pauseVisualization
2487 * Slot activated when mpPauseAction triggered SIGNAL is raised.
2488 */
2489void VariablesWidget::pauseVisualization()
2490{
2491 mpTimeManager->setPause(true);
2492}
2493
2494/*!
2495 * \brief VariablesWidget::visulizationTimeChanged
2496 * Slot activated when mpTimeTextBox returnPressed SIGNAL is raised.
2497 */
2498void VariablesWidget::visulizationTimeChanged()
2499{
2500 QString time = mpTimeTextBox->text();
2501 bool isFloat = true;
2502 double start = mpTimeManager->getStartTime();
2503 double end = mpTimeManager->getEndTime();
2504 double value = time.toFloat(&isFloat);
2505 if (isFloat && value >= 0.0) {
2506 if (value < start) {
2507 value = start;
2508 } else if (value > end) {
2509 value = end;
2510 }
2511 mpTimeManager->setVisTime(value);
2512 mpSimulationTimeSlider->setValue(mpTimeManager->getTimeFraction());
2513
2514 }
2515}
2516
2517/*!
2518 * \brief VariablesWidget::visualizationSpeedChanged
2519 * Slot activated when mpSpeedComboBox currentIndexChanged SIGNAL is raised.
2520 */
2521void VariablesWidget::visualizationSpeedChanged()
2522{
2523 QString speed = mpSpeedComboBox->lineEdit()->text();
2524 bool isFloat = true;
2525 double value = speed.toFloat(&isFloat);
2526 if (isFloat && value > 0.0) {
2527 mpTimeManager->setSpeedUp(value);
2528 }
2529}
2530
2531/*!
2532 * \brief VariablesWidget::incrementVisualization
2533 * Slot activated when TimeManager timer emits timeout SIGNAL.
2534 */
2535void VariablesWidget::incrementVisualization()
2536{
2537 //measure realtime
2538 mpTimeManager->updateTick();
2539 //update scene and set next time step
2540 if (!mpTimeManager->isPaused()) {
2541 mpTimeTextBox->setText(QString::number(mpTimeManager->getVisTime()));
2542 // set time slider
2543 int time = mpTimeManager->getTimeFraction();
2544 mpSimulationTimeSlider->setValue(time);
2545 //finish animation with pause when endtime is reached
2546 if (mpTimeManager->getVisTime() >= mpTimeManager->getEndTime()) {
2547 pauseVisualization();
2548 } else { // get the new visualization time
2549 double newTime = mpTimeManager->getVisTime() + (mpTimeManager->getHVisual()*mpTimeManager->getSpeedUp());
2550 if (newTime <= mpTimeManager->getEndTime()) {
2551 mpTimeManager->setVisTime(newTime);
2552 } else {
2553 mpTimeManager->setVisTime(mpTimeManager->getEndTime());
2554 }
2555 }
2556 }
2557}