Bug Summary

File:OMEdit/OMEditLIB/TransformationalDebugger/TransformationsWidget.cpp
Warning:line 637, column 51
Potential leak of memory pointed to by 'pModelicaTextHighlighter'

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 "MainWindow.h"
36#include "TransformationsWidget.h"
37#include "Options/OptionsDialog.h"
38#include "Util/StringHandler.h"
39#include "Modeling/LibraryTreeWidget.h"
40#include "Modeling/ItemDelegate.h"
41#include "Editors/TransformationsEditor.h"
42#include "Editors/ModelicaEditor.h"
43#include <qjson/parser.h>
44#include "diff_match_patch.h"
45
46#include <QStatusBar>
47#include <QGridLayout>
48#include <QVBoxLayout>
49#include <QMessageBox>
50
51/*!
52 \class TVariablesTreeItem
53 \brief Contains the information about the result variable.
54 */
55/*!
56 \param tVariableItemData - a list of items.\n
57 0 -> name\n
58 1 -> displayName\n
59 2 -> comment\n
60 3 -> lineNumber\n
61 4 -> filePath
62 */
63TVariablesTreeItem::TVariablesTreeItem(const QVector<QVariant> &tVariableItemData, TVariablesTreeItem *pParent, bool isRootItem)
64{
65 mpParentTVariablesTreeItem = pParent;
66 mIsRootItem = isRootItem;
67 mVariableName = tVariableItemData[0].toString();
68 mDisplayVariableName = tVariableItemData[1].toString();
69 mComment = tVariableItemData[2].toString();
70 mLineNumber = tVariableItemData[3].toString();
71 mFilePath = tVariableItemData[4].toString();
72}
73
74TVariablesTreeItem::~TVariablesTreeItem()
75{
76 qDeleteAll(mChildren);
77 mChildren.clear();
78}
79
80void TVariablesTreeItem::insertChild(int position, TVariablesTreeItem *pTVariablesTreeItem)
81{
82 mChildren.insert(position, pTVariablesTreeItem);
83}
84
85TVariablesTreeItem* TVariablesTreeItem::child(int row)
86{
87 return mChildren.value(row);
88}
89
90void TVariablesTreeItem::removeChildren()
91{
92 qDeleteAll(mChildren);
93 mChildren.clear();
94}
95
96void TVariablesTreeItem::removeChild(TVariablesTreeItem *pTVariablesTreeItem)
97{
98 mChildren.removeOne(pTVariablesTreeItem);
99}
100
101int TVariablesTreeItem::columnCount() const
102{
103 return 4;
104}
105
106QVariant TVariablesTreeItem::data(int column, int role) const
107{
108 switch (column)
109 {
110 case 0:
111 switch (role)
112 {
113 case Qt::DisplayRole:
114 return mDisplayVariableName;
115 case Qt::ToolTipRole:
116 return mVariableName;
117 default:
118 return QVariant();
119 }
120 case 1:
121 switch (role)
122 {
123 case Qt::DisplayRole:
124 return mComment;
125 case Qt::ToolTipRole:
126 return mComment;
127 default:
128 return QVariant();
129 }
130 case 2:
131 switch (role)
132 {
133 case Qt::DisplayRole:
134 return mLineNumber;
135 case Qt::ToolTipRole:
136 return mLineNumber;
137 default:
138 return QVariant();
139 }
140 case 3:
141 switch (role)
142 {
143 case Qt::DisplayRole:
144 return mFilePath;
145 case Qt::ToolTipRole:
146 return mFilePath;
147 default:
148 return QVariant();
149 }
150 default:
151 return QVariant();
152 }
153}
154
155int TVariablesTreeItem::row() const
156{
157 if (mpParentTVariablesTreeItem)
158 return mpParentTVariablesTreeItem->mChildren.indexOf(const_cast<TVariablesTreeItem*>(this));
159
160 return 0;
161}
162
163TVariablesTreeItem* TVariablesTreeItem::parent()
164{
165 return mpParentTVariablesTreeItem;
166}
167
168TVariablesTreeModel::TVariablesTreeModel(TVariablesTreeView *pTVariablesTreeView)
169 : QAbstractItemModel(pTVariablesTreeView)
170{
171 mpTVariablesTreeView = pTVariablesTreeView;
172 QVector<QVariant> headers;
173 headers << "" << Helper::variables << tr("Comment") << tr("Line") << Helper::fileLocation;
174 mpRootTVariablesTreeItem = new TVariablesTreeItem(headers, 0, true);
175}
176
177int TVariablesTreeModel::columnCount(const QModelIndex &parent) const
178{
179 if (parent.isValid())
180 return static_cast<TVariablesTreeItem*>(parent.internalPointer())->columnCount();
181 else
182 return mpRootTVariablesTreeItem->columnCount();
183}
184
185int TVariablesTreeModel::rowCount(const QModelIndex &parent) const
186{
187 TVariablesTreeItem *pParentTVariablesTreeItem;
188 if (parent.column() > 0)
189 return 0;
190
191 if (!parent.isValid())
192 pParentTVariablesTreeItem = mpRootTVariablesTreeItem;
193 else
194 pParentTVariablesTreeItem = static_cast<TVariablesTreeItem*>(parent.internalPointer());
195 return pParentTVariablesTreeItem->getChildren().size();
196}
197
198QVariant TVariablesTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
199{
200 if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
201 return mpRootTVariablesTreeItem->data(section);
202 return QVariant();
203}
204
205QModelIndex TVariablesTreeModel::index(int row, int column, const QModelIndex &parent) const
206{
207 if (!hasIndex(row, column, parent))
208 return QModelIndex();
209
210 TVariablesTreeItem *pParentTVariablesTreeItem;
211
212 if (!parent.isValid())
213 pParentTVariablesTreeItem = mpRootTVariablesTreeItem;
214 else
215 pParentTVariablesTreeItem = static_cast<TVariablesTreeItem*>(parent.internalPointer());
216
217 TVariablesTreeItem *pChildTVariablesTreeItem = pParentTVariablesTreeItem->child(row);
218 if (pChildTVariablesTreeItem)
219 return createIndex(row, column, pChildTVariablesTreeItem);
220 else
221 return QModelIndex();
222}
223
224QModelIndex TVariablesTreeModel::parent(const QModelIndex &index) const
225{
226 if (!index.isValid())
227 return QModelIndex();
228
229 TVariablesTreeItem *pChildTVariablesTreeItem = static_cast<TVariablesTreeItem*>(index.internalPointer());
230 TVariablesTreeItem *pParentTVariablesTreeItem = pChildTVariablesTreeItem->parent();
231 if (pParentTVariablesTreeItem == mpRootTVariablesTreeItem)
232 return QModelIndex();
233
234 return createIndex(pParentTVariablesTreeItem->row(), 0, pParentTVariablesTreeItem);
235}
236
237QVariant TVariablesTreeModel::data(const QModelIndex &index, int role) const
238{
239 if (!index.isValid())
240 return QVariant();
241
242 TVariablesTreeItem *pTVariablesTreeItem = static_cast<TVariablesTreeItem*>(index.internalPointer());
243 return pTVariablesTreeItem->data(index.column(), role);
244}
245
246Qt::ItemFlags TVariablesTreeModel::flags(const QModelIndex &index) const
247{
248 if (!index.isValid())
249 return 0;
250
251 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
252 /* Ticket #3207. Make all the items enable and selectable.
253 */
254// TVariablesTreeItem *pTVariablesTreeItem = static_cast<TVariablesTreeItem*>(index.internalPointer());
255// if (pTVariablesTreeItem && pTVariablesTreeItem->getChildren().size() == 0)
256// flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable;
257
258 return flags;
259}
260
261TVariablesTreeItem* TVariablesTreeModel::findTVariablesTreeItem(const QString &name, TVariablesTreeItem *root) const
262{
263 if (root->getVariableName() == name)
264 return root;
265 for (int i = root->getChildren().size(); --i >= 0; )
266 if (TVariablesTreeItem *item = findTVariablesTreeItem(name, root->getChildren().at(i)))
267 return item;
268 return 0;
269}
270
271QModelIndex TVariablesTreeModel::tVariablesTreeItemIndex(const TVariablesTreeItem *pTVariablesTreeItem) const
272{
273 return tVariablesTreeItemIndexHelper(pTVariablesTreeItem, mpRootTVariablesTreeItem, QModelIndex());
274}
275
276QModelIndex TVariablesTreeModel::tVariablesTreeItemIndexHelper(const TVariablesTreeItem *pTVariablesTreeItem,
277 const TVariablesTreeItem *pParentTVariablesTreeItem,
278 const QModelIndex &parentIndex) const
279{
280 if (pTVariablesTreeItem == pParentTVariablesTreeItem)
281 return parentIndex;
282 for (int i = pParentTVariablesTreeItem->getChildren().size(); --i >= 0; ) {
283 const TVariablesTreeItem *childItem = pParentTVariablesTreeItem->getChildren().at(i);
284 QModelIndex childIndex = index(i, 0, parentIndex);
285 QModelIndex index = tVariablesTreeItemIndexHelper(pTVariablesTreeItem, childItem, childIndex);
286 if (index.isValid())
287 return index;
288 }
289 return QModelIndex();
290}
291
292void TVariablesTreeModel::insertTVariablesItems(QHashIterator<QString, OMVariable> variables)
293{
294 while (variables.hasNext())
295 {
296 variables.next();
297 const OMVariable &variable = variables.value();
298 if (variable.name.startsWith("$PRE.") || variable.name.startsWith("$res"))
299 continue;
300
301 QStringList tVariables;
302 QString parentTVariable;
303 if (variable.name.startsWith("der(")) {
304 QString str = variable.name;
305 str.chop((str.lastIndexOf("der(")/4)+1);
306 tVariables = StringHandler::makeVariableParts(str.mid(str.lastIndexOf("der(") + 4));
307 } else {
308 tVariables = StringHandler::makeVariableParts(variable.name);
309 }
310 int count = 1;
311 TVariablesTreeItem *pParentTVariablesTreeItem = 0;
312 foreach (QString tVariable, tVariables)for (auto _container_ = QtPrivate::qMakeForeachContainer(tVariables
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString tVariable
= *_container_.i; _container_.control; _container_.control =
0)
{
313 if (count == 1) /* first loop iteration */ {
314 pParentTVariablesTreeItem = mpRootTVariablesTreeItem;
315 }
316 QString findVariable;
317 /* if last item */
318 if (tVariables.size() == count && variable.name.startsWith("der(")) {
319 if (parentTVariable.isEmpty()) {
320 findVariable = StringHandler::joinDerivativeAndPreviousVariable(variable.name, tVariable, "der(");
321 } else {
322 findVariable = QString("%1.%2").arg(parentTVariable, StringHandler::joinDerivativeAndPreviousVariable(variable.name, tVariable, "der("));
323 }
324 } else {
325 findVariable = parentTVariable.isEmpty() ? tVariable : parentTVariable + "." + tVariable;
326 }
327 if ((pParentTVariablesTreeItem = findTVariablesTreeItem(findVariable, pParentTVariablesTreeItem))) {
328 if (count == 1) {
329 parentTVariable = tVariable;
330 } else {
331 parentTVariable += "." + tVariable;
332 }
333 count++;
334 continue;
335 }
336 /*
337 If pParentTVariablesTreeItem is 0 and it is first loop iteration then use mpRootTVariablesTreeItem as parent.
338 If loop iteration is not first and pParentTVariablesTreeItem is 0 then find the parent item.
339 */
340 if (!pParentTVariablesTreeItem && count > 1) {
341 pParentTVariablesTreeItem = findTVariablesTreeItem(parentTVariable, mpRootTVariablesTreeItem);
342 } else {
343 pParentTVariablesTreeItem = mpRootTVariablesTreeItem;
344 }
345 QModelIndex index = tVariablesTreeItemIndex(pParentTVariablesTreeItem);
346 QVector<QVariant> tVariableData;
347 QString parentVarName = pParentTVariablesTreeItem->getVariableName();
348 parentVarName = parentVarName.isEmpty() ? parentVarName : parentVarName.append(".");
349 /* if last item */
350 if (tVariables.size() == count && variable.name.startsWith("der(")) {
351 tVariableData << variable.name << StringHandler::joinDerivativeAndPreviousVariable(variable.name, tVariable, "der(") << variable.comment << variable.info.lineStart << variable.info.file;
352 } else {
353 tVariableData << parentVarName + tVariable << tVariable << variable.comment << variable.info.lineStart << variable.info.file;
354 }
355 TVariablesTreeItem *pTVariablesTreeItem = new TVariablesTreeItem(tVariableData, pParentTVariablesTreeItem);
356 int row = rowCount(index);
357 beginInsertRows(index, row, row);
358 pParentTVariablesTreeItem->insertChild(row, pTVariablesTreeItem);
359 endInsertRows();
360 if (count == 1) {
361 parentTVariable = tVariable;
362 } else {
363 parentTVariable += "." + tVariable;
364 }
365 count++;
366 }
367 }
368}
369
370void TVariablesTreeModel::clearTVariablesTreeItems()
371{
372 beginRemoveRows(tVariablesTreeItemIndex(mpRootTVariablesTreeItem), 0, mpRootTVariablesTreeItem->getChildren().size());
373 mpRootTVariablesTreeItem->removeChildren();
374 endRemoveRows();
375}
376
377TVariableTreeProxyModel::TVariableTreeProxyModel(QObject *parent)
378 : QSortFilterProxyModel(parent)
379{
380}
381
382bool TVariableTreeProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
383{
384 if (!filterRegExp().isEmpty())
385 {
386 QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
387 if (index.isValid())
388 {
389 // if any of children matches the filter, then current index matches the filter as well
390 int rows = sourceModel()->rowCount(index);
391 for (int i = 0 ; i < rows ; ++i)
392 {
393 if (filterAcceptsRow(i, index))
394 {
395 return true;
396 }
397 }
398 // check current index itself
399 TVariablesTreeItem *pTVariablesTreeItem = static_cast<TVariablesTreeItem*>(index.internalPointer());
400 if (pTVariablesTreeItem)
401 {
402 QString variableName = pTVariablesTreeItem->getVariableName();
403 variableName.remove(QRegExp("(\\.mat|\\.plt|\\.csv|_res.mat|_res.plt|_res.csv)"));
404 return variableName.contains(filterRegExp());
405 }
406 else
407 {
408 return sourceModel()->data(index).toString().contains(filterRegExp());
409 }
410 QString key = sourceModel()->data(index, filterRole()).toString();
411 return key.contains(filterRegExp());
412 }
413 }
414 return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
415}
416
417TVariablesTreeView::TVariablesTreeView(TransformationsWidget *pTransformationsWidget)
418 : QTreeView(pTransformationsWidget)
419{
420 mpTransformationsWidget = pTransformationsWidget;
421 setItemDelegate(new ItemDelegate(this));
422 setTextElideMode(Qt::ElideMiddle);
423 setIndentation(Helper::treeIndentation);
424 setSortingEnabled(true);
425 sortByColumn(0, Qt::AscendingOrder);
426 setExpandsOnDoubleClick(false);
427 setUniformRowHeights(true);
428}
429
430EquationTreeWidget::EquationTreeWidget(TransformationsWidget *pTransformationWidget)
431 : QTreeWidget(pTransformationWidget), mpTransformationWidget(pTransformationWidget)
432{
433 setItemDelegate(new ItemDelegate(this));
434 setIndentation(0);
435 setColumnCount(7);
436 setTextElideMode(Qt::ElideMiddle);
437 setSortingEnabled(true);
438 sortByColumn(0, Qt::AscendingOrder);
439 setColumnWidth(0, 55);
440 setColumnWidth(1, 60);
441 setColumnWidth(2, 200);
442 setColumnWidth(3, 55);
443 setColumnWidth(4, 80);
444 setColumnWidth(5, 80);
445 setColumnWidth(6, 60);
446 setExpandsOnDoubleClick(false);
447 QStringList headerLabels;
448 headerLabels << Helper::index << Helper::type << Helper::equation << Helper::executionCount << Helper::executionMaxTime << Helper::executionTime << Helper::executionFraction;
449 setHeaderLabels(headerLabels);
450 connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int))"2""itemDoubleClicked(QTreeWidgetItem*,int)", mpTransformationWidget, SLOT(fetchEquationData(QTreeWidgetItem*,int))"1""fetchEquationData(QTreeWidgetItem*,int)");
451}
452
453TransformationsWidget::TransformationsWidget(QString infoJSONFullFileName, QWidget *pParent)
454 : QWidget(pParent), mInfoJSONFullFileName(infoJSONFullFileName)
455{
456 if (!mInfoJSONFullFileName.endsWith("_info.json")) {
1
Assuming the condition is false
2
Taking false branch
457 mProfJSONFullFileName = "";
458 mProfilingDataRealFileName = "";
459 } else {
460 mProfJSONFullFileName = infoJSONFullFileName.left(infoJSONFullFileName.size() - 9) + "prof.json";
461 mProfilingDataRealFileName = infoJSONFullFileName.left(infoJSONFullFileName.size() - 9) + "prof.realdata";
462 }
463 mCurrentEquationIndex = 0;
464 setWindowIcon(QIcon(":/Resources/icons/equational-debugger.svg"));
465 setWindowTitle(QString(Helper::applicationName).append(" - ").append(Helper::transformationalDebugger));
466 QToolButton *pReloadToolButton = new QToolButton;
467 pReloadToolButton->setToolTip(Helper::reload);
468 pReloadToolButton->setAutoRaise(true);
469 pReloadToolButton->setIcon(QIcon(":/Resources/icons/refresh.svg"));
470 connect(pReloadToolButton, SIGNAL(clicked())"2""clicked()", SLOT(reloadTransformations())"1""reloadTransformations()");
471 /* info xml file path label */
472 Label *pInfoXMLFilePathLabel = new Label(mInfoJSONFullFileName, this);
473 pInfoXMLFilePathLabel->setElideMode(Qt::ElideMiddle);
474 /* create status bar */
475 QStatusBar *pStatusBar = new QStatusBar;
476 pStatusBar->setObjectName("ModelStatusBar");
477 pStatusBar->setSizeGripEnabled(false);
478 pStatusBar->addPermanentWidget(pReloadToolButton, 0);
479 pStatusBar->addPermanentWidget(pInfoXMLFilePathLabel, 1);
480 /* Variables Heading */
481 Label *pVariablesBrowserLabel = new Label(Helper::variablesBrowser);
482 pVariablesBrowserLabel->setObjectName("LabelWithBorder");
483 // tree search filters
484 mpTreeSearchFilters = new TreeSearchFilters(this);
485 mpTreeSearchFilters->getFilterTextBox()->setPlaceholderText(Helper::filterVariables);
486 connect(mpTreeSearchFilters->getFilterTextBox(), SIGNAL(returnPressed())"2""returnPressed()", SLOT(findVariables())"1""findVariables()");
487 connect(mpTreeSearchFilters->getFilterTextBox(), SIGNAL(textEdited(QString))"2""textEdited(QString)", SLOT(findVariables())"1""findVariables()");
488 connect(mpTreeSearchFilters->getCaseSensitiveCheckBox(), SIGNAL(toggled(bool))"2""toggled(bool)", SLOT(findVariables())"1""findVariables()");
489 connect(mpTreeSearchFilters->getSyntaxComboBox(), SIGNAL(currentIndexChanged(int))"2""currentIndexChanged(int)", SLOT(findVariables())"1""findVariables()");
490 /* variables tree view */
491 mpTVariablesTreeView = new TVariablesTreeView(this);
492 mpTVariablesTreeModel = new TVariablesTreeModel(mpTVariablesTreeView);
493 mpTVariableTreeProxyModel = new TVariableTreeProxyModel;
494 mpTVariableTreeProxyModel->setDynamicSortFilter(true);
495 mpTVariableTreeProxyModel->setSourceModel(mpTVariablesTreeModel);
496 mpTVariablesTreeView->setModel(mpTVariableTreeProxyModel);
497 mpTVariablesTreeView->setColumnWidth(2, 40); /* line number column */
498 connect(mpTVariablesTreeView, SIGNAL(doubleClicked(QModelIndex))"2""doubleClicked(QModelIndex)", SLOT(fetchVariableData(QModelIndex))"1""fetchVariableData(QModelIndex)");
499 connect(mpTreeSearchFilters->getExpandAllButton(), SIGNAL(clicked())"2""clicked()", mpTVariablesTreeView, SLOT(expandAll())"1""expandAll()");
500 connect(mpTreeSearchFilters->getCollapseAllButton(), SIGNAL(clicked())"2""clicked()", mpTVariablesTreeView, SLOT(collapseAll())"1""collapseAll()");
501 QGridLayout *pVariablesGridLayout = new QGridLayout;
502 pVariablesGridLayout->setSpacing(1);
503 pVariablesGridLayout->setContentsMargins(0, 0, 0, 0);
504 pVariablesGridLayout->addWidget(pVariablesBrowserLabel, 0, 0);
505 pVariablesGridLayout->addWidget(mpTreeSearchFilters, 1, 0);
506 pVariablesGridLayout->addWidget(mpTVariablesTreeView, 2, 0);
507 QFrame *pVariablesFrame = new QFrame;
508 pVariablesFrame->setLayout(pVariablesGridLayout);
509 /* Defined in tree widget */
510 Label *pDefinedInLabel = new Label(tr("Defined In Equations"));
511 pDefinedInLabel->setObjectName("LabelWithBorder");
512 mpDefinedInEquationsTreeWidget = new EquationTreeWidget(this);
513 QGridLayout *pDefinedInGridLayout = new QGridLayout;
514 pDefinedInGridLayout->setSpacing(1);
515 pDefinedInGridLayout->setContentsMargins(0, 0, 0, 0);
516 pDefinedInGridLayout->addWidget(pDefinedInLabel, 0, 0);
517 pDefinedInGridLayout->addWidget(mpDefinedInEquationsTreeWidget, 1, 0);
518 QFrame *pDefinedInFrame = new QFrame;
519 pDefinedInFrame->setLayout(pDefinedInGridLayout);
520 /* Used in tree widget */
521 Label *pUsedInLabel = new Label(tr("Used In Equations"));
522 pUsedInLabel->setObjectName("LabelWithBorder");
523 mpUsedInEquationsTreeWidget = new EquationTreeWidget(this);
524 QGridLayout *pUsedInGridLayout = new QGridLayout;
525 pUsedInGridLayout->setSpacing(1);
526 pUsedInGridLayout->setContentsMargins(0, 0, 0, 0);
527 pUsedInGridLayout->addWidget(pUsedInLabel, 0, 0);
528 pUsedInGridLayout->addWidget(mpUsedInEquationsTreeWidget, 1, 0);
529 QFrame *pUsedInFrame = new QFrame;
530 pUsedInFrame->setLayout(pUsedInGridLayout);
531 /* variable operations tree widget */
532 Label *pOperationsLabel = new Label(tr("Variable Operations"));
533 pOperationsLabel->setObjectName("LabelWithBorder");
534 mpVariableOperationsTreeWidget = new QTreeWidget;
535 mpVariableOperationsTreeWidget->setItemDelegate(new ItemDelegate(mpVariableOperationsTreeWidget));
536 mpVariableOperationsTreeWidget->setIndentation(0);
537 mpVariableOperationsTreeWidget->setColumnCount(1);
538 mpVariableOperationsTreeWidget->setTextElideMode(Qt::ElideMiddle);
539 mpVariableOperationsTreeWidget->setHeaderLabel(tr("Operations"));
540 QGridLayout *pVariableOperationsGridLayout = new QGridLayout;
541 pVariableOperationsGridLayout->setSpacing(1);
542 pVariableOperationsGridLayout->setContentsMargins(0, 0, 0, 0);
543 pVariableOperationsGridLayout->addWidget(pOperationsLabel, 0, 0);
544 pVariableOperationsGridLayout->addWidget(mpVariableOperationsTreeWidget, 1, 0);
545 QFrame *pVariableOperationsFrame = new QFrame;
546 pVariableOperationsFrame->setLayout(pVariableOperationsGridLayout);
547 /* Equations Heading */
548 Label *pEquationsBrowserLabel = new Label(tr("Equations Browser"));
549 pEquationsBrowserLabel->setObjectName("LabelWithBorder");
550 /* Equations tree widget */
551 mpEquationsTreeWidget = new EquationTreeWidget(this);
552 mpEquationsTreeWidget->setIndentation(Helper::treeIndentation);
553 QGridLayout *pEquationsGridLayout = new QGridLayout;
554 pEquationsGridLayout->setSpacing(1);
555 pEquationsGridLayout->setContentsMargins(0, 0, 0, 0);
556 pEquationsGridLayout->addWidget(pEquationsBrowserLabel, 0, 0);
557 pEquationsGridLayout->addWidget(mpEquationsTreeWidget, 1, 0);
558 QFrame *pEquationsFrame = new QFrame;
559 pEquationsFrame->setLayout(pEquationsGridLayout);
560 /* defines tree widget */
561 Label *pDefinesLabel = new Label(tr("Defines"));
562 pDefinesLabel->setObjectName("LabelWithBorder");
563 mpDefinesVariableTreeWidget = new QTreeWidget;
564 mpDefinesVariableTreeWidget->setItemDelegate(new ItemDelegate(mpDefinesVariableTreeWidget));
565 mpDefinesVariableTreeWidget->setIndentation(0);
566 mpDefinesVariableTreeWidget->setColumnCount(1);
567 mpDefinesVariableTreeWidget->setTextElideMode(Qt::ElideMiddle);
568 mpDefinesVariableTreeWidget->setSortingEnabled(true);
569 mpDefinesVariableTreeWidget->sortByColumn(0, Qt::AscendingOrder);
570 QStringList headerLabels;
571 headerLabels << tr("Variable");
572 mpDefinesVariableTreeWidget->setHeaderLabels(headerLabels);
573 QGridLayout *pDefinesGridLayout = new QGridLayout;
574 pDefinesGridLayout->setSpacing(1);
575 pDefinesGridLayout->setContentsMargins(0, 0, 0, 0);
576 pDefinesGridLayout->addWidget(pDefinesLabel, 0, 0);
577 pDefinesGridLayout->addWidget(mpDefinesVariableTreeWidget, 1, 0);
578 QFrame *pDefinesFrame = new QFrame;
579 pDefinesFrame->setLayout(pDefinesGridLayout);
580 /* depends tree widget */
581 Label *pDependsLabel = new Label(tr("Depends"));
582 pDependsLabel->setObjectName("LabelWithBorder");
583 mpDependsVariableTreeWidget = new QTreeWidget;
584 mpDependsVariableTreeWidget->setItemDelegate(new ItemDelegate(mpDependsVariableTreeWidget));
585 mpDependsVariableTreeWidget->setIndentation(0);
586 mpDependsVariableTreeWidget->setColumnCount(1);
587 mpDependsVariableTreeWidget->setTextElideMode(Qt::ElideMiddle);
588 mpDependsVariableTreeWidget->setSortingEnabled(true);
589 mpDependsVariableTreeWidget->sortByColumn(0, Qt::AscendingOrder);
590 mpDependsVariableTreeWidget->setHeaderLabel(tr("Variable"));
591 QGridLayout *pDependsGridLayout = new QGridLayout;
592 pDependsGridLayout->setSpacing(1);
593 pDependsGridLayout->setContentsMargins(0, 0, 0, 0);
594 pDependsGridLayout->addWidget(pDependsLabel, 0, 0);
595 pDependsGridLayout->addWidget(mpDependsVariableTreeWidget, 1, 0);
596 QFrame *pDependsFrame = new QFrame;
597 pDependsFrame->setLayout(pDependsGridLayout);
598 /* operations tree widget */
599 Label *pEquationOperationsLabel = new Label(tr("Equation Operations"));
600 pEquationOperationsLabel->setObjectName("LabelWithBorder");
601 mpEquationDiffFilterComboBox = new QComboBox;
602 mpEquationDiffFilterComboBox->addItem(tr("Diff"), HtmlDiff::Both);
603 mpEquationDiffFilterComboBox->addItem(tr("After"), HtmlDiff::Insertion);
604 mpEquationDiffFilterComboBox->addItem(tr("Before"), HtmlDiff::Deletion);
605 connect(mpEquationDiffFilterComboBox, SIGNAL(currentIndexChanged(int))"2""currentIndexChanged(int)", SLOT(filterEquationOperations(int))"1""filterEquationOperations(int)");
606 QHBoxLayout *pEquationTransformationFilterLayout = new QHBoxLayout;
607 pEquationTransformationFilterLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
608 pEquationTransformationFilterLayout->addWidget(new Label(tr("Transformation:")));
609 pEquationTransformationFilterLayout->addWidget(mpEquationDiffFilterComboBox);
610 mpEquationOperationsTreeWidget = new QTreeWidget;
611 mpEquationOperationsTreeWidget->setItemDelegate(new ItemDelegate(mpEquationOperationsTreeWidget));
612 mpEquationOperationsTreeWidget->setIndentation(0);
613 mpEquationOperationsTreeWidget->setColumnCount(1);
614 mpEquationOperationsTreeWidget->setTextElideMode(Qt::ElideMiddle);
615 mpEquationOperationsTreeWidget->setHeaderLabel(tr("Operations"));
616 QGridLayout *pEquationOperationsGridLayout = new QGridLayout;
617 pEquationOperationsGridLayout->setSpacing(1);
618 pEquationOperationsGridLayout->setContentsMargins(0, 0, 0, 0);
619 pEquationOperationsGridLayout->addWidget(pEquationOperationsLabel, 0, 0);
620 pEquationOperationsGridLayout->addLayout(pEquationTransformationFilterLayout, 1, 0, Qt::AlignLeft);
621 pEquationOperationsGridLayout->addWidget(mpEquationOperationsTreeWidget, 2, 0);
622 QFrame *pEquationOperationsFrame = new QFrame;
623 pEquationOperationsFrame->setLayout(pEquationOperationsGridLayout);
624 /* TSourceEditor */
625 Label *pTSourceEditorBrowserLabel = new Label(tr("Source Browser"));
626 pTSourceEditorBrowserLabel->setObjectName("LabelWithBorder");
627 mpTSourceEditorFileLabel = new Label("");
628 mpTSourceEditorFileLabel->setElideMode(Qt::ElideMiddle);
629 mpTSourceEditorFileLabel->hide();
630 mpTSourceEditorInfoBar = new InfoBar(this);
631 mpTSourceEditorInfoBar->hide();
632 mpTransformationsEditor = new TransformationsEditor(this);
633 ModelicaHighlighter *pModelicaTextHighlighter;
634 pModelicaTextHighlighter = new ModelicaHighlighter(OptionsDialog::instance()->getModelicaEditorPage(),
3
Memory is allocated
635 mpTransformationsEditor->getPlainTextEdit());
636 connect(OptionsDialog::instance(), SIGNAL(modelicaEditorSettingsChanged())"2""modelicaEditorSettingsChanged()", pModelicaTextHighlighter, SLOT(settingsChanged())"1""settingsChanged()");
637 QVBoxLayout *pTSourceEditorVerticalLayout = new QVBoxLayout;
4
Potential leak of memory pointed to by 'pModelicaTextHighlighter'
638 pTSourceEditorVerticalLayout->setSpacing(1);
639 pTSourceEditorVerticalLayout->setContentsMargins(0, 0, 0, 0);
640 pTSourceEditorVerticalLayout->addWidget(pTSourceEditorBrowserLabel);
641 pTSourceEditorVerticalLayout->addWidget(mpTSourceEditorFileLabel);
642 pTSourceEditorVerticalLayout->addWidget(mpTSourceEditorInfoBar);
643 pTSourceEditorVerticalLayout->addWidget(mpTransformationsEditor);
644 QFrame *pTSourceEditorFrame = new QFrame;
645 pTSourceEditorFrame->setLayout(pTSourceEditorVerticalLayout);
646 /* variables nested horizontal splitter */
647 mpVariablesNestedHorizontalSplitter = new QSplitter;
648 mpVariablesNestedHorizontalSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
649 mpVariablesNestedHorizontalSplitter->setChildrenCollapsible(false);
650 mpVariablesNestedHorizontalSplitter->setHandleWidth(4);
651 mpVariablesNestedHorizontalSplitter->setContentsMargins(0, 0, 0, 0);
652 mpVariablesNestedHorizontalSplitter->addWidget(pDefinedInFrame);
653 mpVariablesNestedHorizontalSplitter->addWidget(pUsedInFrame);
654 /* variables vertical splitter */
655 mpVariablesNestedVerticalSplitter = new QSplitter;
656 mpVariablesNestedVerticalSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
657 mpVariablesNestedVerticalSplitter->setOrientation(Qt::Vertical);
658 mpVariablesNestedVerticalSplitter->setChildrenCollapsible(false);
659 mpVariablesNestedVerticalSplitter->setHandleWidth(4);
660 mpVariablesNestedVerticalSplitter->setContentsMargins(0, 0, 0, 0);
661 mpVariablesNestedVerticalSplitter->addWidget(mpVariablesNestedHorizontalSplitter);
662 mpVariablesNestedVerticalSplitter->addWidget(pVariableOperationsFrame);
663 /* variables horizontal splitter */
664 mpVariablesHorizontalSplitter = new QSplitter;
665 mpVariablesHorizontalSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
666 mpVariablesHorizontalSplitter->setChildrenCollapsible(false);
667 mpVariablesHorizontalSplitter->setHandleWidth(4);
668 mpVariablesHorizontalSplitter->setContentsMargins(0, 0, 0, 0);
669 mpVariablesHorizontalSplitter->addWidget(pVariablesFrame);
670 mpVariablesHorizontalSplitter->addWidget(mpVariablesNestedVerticalSplitter);
671 Label *pVariablesHeadingLabel = new Label(Helper::variables);
672 pVariablesHeadingLabel->setObjectName("LabelWithBorder");
673 QVBoxLayout *pVariablesMainLayout = new QVBoxLayout;
674 pVariablesMainLayout->setSpacing(1);
675 pVariablesMainLayout->setContentsMargins(0, 0, 0, 0);
676 pVariablesMainLayout->addWidget(pVariablesHeadingLabel);
677 pVariablesMainLayout->addWidget(mpVariablesHorizontalSplitter);
678 QFrame *pVariablesMainFrame = new QFrame;
679 pVariablesMainFrame->setLayout(pVariablesMainLayout);
680 /* Equations nested horizontal splitter */
681 mpEquationsNestedHorizontalSplitter = new QSplitter;
682 mpEquationsNestedHorizontalSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
683 mpEquationsNestedHorizontalSplitter->setChildrenCollapsible(false);
684 mpEquationsNestedHorizontalSplitter->setHandleWidth(4);
685 mpEquationsNestedHorizontalSplitter->setContentsMargins(0, 0, 0, 0);
686 mpEquationsNestedHorizontalSplitter->addWidget(pDefinesFrame);
687 mpEquationsNestedHorizontalSplitter->addWidget(pDependsFrame);
688 /* Equations nested vertical splitter */
689 mpEquationsNestedVerticalSplitter = new QSplitter;
690 mpEquationsNestedVerticalSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
691 mpEquationsNestedVerticalSplitter->setOrientation(Qt::Vertical);
692 mpEquationsNestedVerticalSplitter->setChildrenCollapsible(false);
693 mpEquationsNestedVerticalSplitter->setHandleWidth(4);
694 mpEquationsNestedVerticalSplitter->setContentsMargins(0, 0, 0, 0);
695 mpEquationsNestedVerticalSplitter->addWidget(mpEquationsNestedHorizontalSplitter);
696 mpEquationsNestedVerticalSplitter->addWidget(pEquationOperationsFrame);
697 /* equations horizontal splitter */
698 mpEquationsHorizontalSplitter = new QSplitter;
699 mpEquationsHorizontalSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
700 mpEquationsHorizontalSplitter->setChildrenCollapsible(false);
701 mpEquationsHorizontalSplitter->setHandleWidth(4);
702 mpEquationsHorizontalSplitter->setContentsMargins(0, 0, 0, 0);
703 mpEquationsHorizontalSplitter->addWidget(pEquationsFrame);
704 mpEquationsHorizontalSplitter->addWidget(mpEquationsNestedVerticalSplitter);
705 Label *pEquationsHeadingLabel = new Label(tr("Equations"));
706 pEquationsHeadingLabel->setObjectName("LabelWithBorder");
707 QVBoxLayout *pEquationsMainLayout = new QVBoxLayout;
708 pEquationsMainLayout->setSpacing(1);
709 pEquationsMainLayout->setContentsMargins(0, 0, 0, 0);
710 pEquationsMainLayout->addWidget(pEquationsHeadingLabel);
711 pEquationsMainLayout->addWidget(mpEquationsHorizontalSplitter);
712 QFrame *pEquationsMainFrame = new QFrame;
713 pEquationsMainFrame->setLayout(pEquationsMainLayout);
714 /* Transformations vertical splitter */
715 mpTransformationsVerticalSplitter = new QSplitter;
716 mpTransformationsVerticalSplitter->setObjectName("TransformationsVerticalSplitter");
717 mpTransformationsVerticalSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
718 mpTransformationsVerticalSplitter->setOrientation(Qt::Vertical);
719 mpTransformationsVerticalSplitter->setChildrenCollapsible(false);
720 mpTransformationsVerticalSplitter->setHandleWidth(4);
721 mpTransformationsVerticalSplitter->setContentsMargins(0, 0, 0, 0);
722 mpTransformationsVerticalSplitter->addWidget(pTSourceEditorFrame);
723 mpTransformationsVerticalSplitter->addWidget(pVariablesMainFrame);
724 mpTransformationsVerticalSplitter->addWidget(pEquationsMainFrame);
725 /* Load the transformations before setting the layout */
726 loadTransformations();
727 /* set the layout */
728 QGridLayout *pMainLayout = new QGridLayout;
729 pMainLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
730 pMainLayout->setContentsMargins(0, 0, 0, 0);
731 pMainLayout->addWidget(pStatusBar, 0, 0);
732 pMainLayout->addWidget(mpTransformationsVerticalSplitter, 1, 0);
733 setLayout(pMainLayout);
734 /* restore the TransformationsWidget geometry and splitters state. */
735 QSettings *pSettings = Utilities::getApplicationSettings();
736 if (OptionsDialog::instance()->getGeneralSettingsPage()->getPreserveUserCustomizations())
737 {
738 pSettings->beginGroup("transformationalDebugger");
739 restoreGeometry(pSettings->value("geometry").toByteArray());
740 mpVariablesNestedHorizontalSplitter->restoreState(pSettings->value("variablesNestedHorizontalSplitter").toByteArray());
741 mpVariablesNestedVerticalSplitter->restoreState(pSettings->value("variablesNestedVerticalSplitter").toByteArray());
742 mpVariablesHorizontalSplitter->restoreState(pSettings->value("variablesHorizontalSplitter").toByteArray());
743 mpEquationsNestedHorizontalSplitter->restoreState(pSettings->value("equationsNestedHorizontalSplitter").toByteArray());
744 mpEquationsNestedVerticalSplitter->restoreState(pSettings->value("equationsNestedVerticalSplitter").toByteArray());
745 mpEquationsHorizontalSplitter->restoreState(pSettings->value("equationsHorizontalSplitter").toByteArray());
746 mpTransformationsVerticalSplitter->restoreState(pSettings->value("transformationsVerticalSplitter").toByteArray());
747 pSettings->endGroup();
748 }
749}
750
751static OMOperation* variantToOperationPtr(QVariantMap var)
752{
753 QString op = var["op"].toString();
754 QString display = var["display"].toString();
755 QStringList dataStrings = Utilities::variantListToStringList(var["data"].toList());
756
757 if (op == "before-after") {
758 return new OMOperationBeforeAfter(display != "" ? display : op, dataStrings);
759 } else if (op == "before-after-assert") {
760 return new OMOperationBeforeAfter(display != "" ? display : op, dataStrings);
761 } else if (op == "chain") {
762 QStringList firstLast;
763 firstLast << dataStrings.first() << dataStrings.last();
764 return new OMOperationBeforeAfter(display != "" ? display : op, firstLast);
765 } else if (op == "info") {
766 return new OMOperationInfo(display != "" ? display : op, dataStrings.join(", "));
767 }
768 // "chain"
769 return NULL__null;
770}
771
772
773static void variantToSource(QVariantMap var, OMInfo &info, QStringList &types, QList<OMOperation*> &ops)
774{
775 Q_UNUSED(types)(void)types;;
776 QVariantMap vinfo = var["info"].toMap();
777 info.file = vinfo["file"].toString();
778 info.lineStart = vinfo["lineStart"].toInt();
779 info.lineEnd = vinfo["lineEnd"].toInt();
780 info.colStart = vinfo["colStart"].toInt();
781 info.colEnd = vinfo["colEnd"].toInt();
782 info.isValid = true;
783 QVariantList vops = var["operations"].toList();
784 foreach (QVariant vop, vops)for (auto _container_ = QtPrivate::qMakeForeachContainer(vops
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QVariant vop
= *_container_.i; _container_.control; _container_.control =
0)
{
785 OMOperation *op = variantToOperationPtr(vop.toMap());
786 if (op) {
787 ops += op;
788 }
789 }
790}
791
792static OMEquation* getOMEquation(QList<OMEquation*> equations, int index)
793{
794 for (int i = 1 ; i < equations.size() ; i++) {
795 if (equations[i]->index == index) {
796 return equations[i];
797 }
798 }
799 return NULL__null;
800}
801
802void TransformationsWidget::loadTransformations()
803{
804 QFile file(mInfoJSONFullFileName);
805 mEquations.clear();
806 mVariables.clear();
807 hasOperationsEnabled = false;
808 if (mInfoJSONFullFileName.endsWith(".json")) {
809 QJson::Parser parser;
810 bool ok;
811 QVariantMap result;
812 result = parser.parse(&file, &ok).toMap();
813 if (!ok) {
814 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::parsingFailedJson), Helper::parsingFailedJson + ": " + mInfoJSONFullFileName, Helper::ok);
815 return;
816 }
817 QVariantMap vars = result["variables"].toMap();
818 QVariantList eqs = result["equations"].toList();
819 for(QVariantMap::const_iterator iter = vars.begin(); iter != vars.end(); ++iter) {
820 QVariantMap value = iter.value().toMap();
821 OMVariable *var = new OMVariable();
822 var->name = iter.key();
823 var->comment = value["comment"].toString();
824 QVariantMap sourceMap = value["source"].toMap();
825 variantToSource(value["source"].toMap(), var->info, var->types, var->ops);
826 if (!hasOperationsEnabled && sourceMap.contains("operations")) {
827 hasOperationsEnabled = true;
828 }
829 mVariables[iter.key()] = *var;
830 }
831 mpTVariablesTreeModel->insertTVariablesItems(mVariables);
832 for (int i=0; i<eqs.size(); i++) {
833 mEquations << new OMEquation();
834 }
835 for (int i=0; i<eqs.size(); i++) {
836 QVariantMap veq = eqs[i].toMap();
837 OMEquation *eq = mEquations[i];
838 eq->section = veq["section"].toString();
839 if (veq["eqIndex"].toInt() != i) {
840 QMessageBox::critical(this, QString(Helper::applicationName).append(" - ").append(Helper::parsingFailedJson), Helper::parsingFailedJson + QString(": got index ") + veq["eqIndex"].toString() + QString(" expected ") + QString::number(i), Helper::ok);
841 return;
842 }
843 eq->index = i;
844 eq->profileBlock = -1;
845 if (veq.find("parent") != veq.end()) {
846 eq->parent = veq["parent"].toInt();
847 mEquations[eq->parent]->eqs << eq->index;
848 } else {
849 eq->parent = 0;
850 }
851 if (veq.find("defines") != veq.end()) {
852 eq->defines = Utilities::variantListToStringList(veq["defines"].toList());
853 foreach (QString v, eq->defines)for (auto _container_ = QtPrivate::qMakeForeachContainer(eq->
defines); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString v
= *_container_.i; _container_.control; _container_.control =
0)
{
854 mVariables[v].definedIn << eq->index;
855 }
856 }
857 if (veq.find("uses") != veq.end()) {
858 eq->depends = Utilities::variantListToStringList(veq["uses"].toList());
859 foreach (QString v, eq->depends)for (auto _container_ = QtPrivate::qMakeForeachContainer(eq->
depends); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString v
= *_container_.i; _container_.control; _container_.control =
0)
{
860 mVariables[v].usedIn << eq->index;
861 }
862 }
863 eq->text = Utilities::variantListToStringList(veq["equation"].toList());
864 eq->tag = veq["tag"].toString();
865 if (veq.find("display") != veq.end()) {
866 eq->display = veq["display"].toString();
867 } else {
868 eq->display = eq->tag;
869 }
870 eq->unknowns = veq["unknowns"].toInt();
871 QVariantMap sourceMap = veq["source"].toMap();
872 variantToSource(veq["source"].toMap(), eq->info, eq->types, eq->ops);
873 if (!hasOperationsEnabled && sourceMap.contains("operations")) {
874 hasOperationsEnabled = true;
875 }
876 }
877 parseProfiling(mProfJSONFullFileName);
878 fetchEquations();
879 } else {
880 mpInfoXMLFileHandler = new MyHandler(file,mVariables,mEquations);
881 mpTVariablesTreeModel->insertTVariablesItems(mVariables);
882 /* load equations */
883 parseProfiling(mProfJSONFullFileName);
884 fetchEquations();
885 hasOperationsEnabled = mpInfoXMLFileHandler->hasOperationsEnabled;
886 }
887 fetchVariableData(mpTVariableTreeProxyModel->index(0, 0));
888}
889
890void TransformationsWidget::fetchDefinedInEquations(const OMVariable &variable)
891{
892 /* Clear the defined in tree. */
893 clearTreeWidgetItems(mpDefinedInEquationsTreeWidget);
894 /* add defined in equations */
895 for (int i=0; i<variable.definedIn.size(); i++) {
896 OMEquation *equation = getOMEquation(mEquations, variable.definedIn[i]);
897 if (equation) {
898 QStringList values;
899 values << QString::number(variable.definedIn[i]) << equation->section << equation->toString();
900 QTreeWidgetItem *pDefinedInTreeItem = new IntegerTreeWidgetItem(values, mpDefinedInEquationsTreeWidget);
901 pDefinedInTreeItem->setToolTip(0, values[0]);
902 pDefinedInTreeItem->setToolTip(1, values[1]);
903 pDefinedInTreeItem->setToolTip(2, values[2]);
904 mpDefinedInEquationsTreeWidget->addTopLevelItem(pDefinedInTreeItem);
905 }
906 }
907}
908
909void TransformationsWidget::fetchUsedInEquations(const OMVariable &variable)
910{
911 /* Clear the used in tree. */
912 clearTreeWidgetItems(mpUsedInEquationsTreeWidget);
913 /* add used in equations */
914 foreach (int index, variable.usedIn)for (auto _container_ = QtPrivate::qMakeForeachContainer(variable
.usedIn); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (int index
= *_container_.i; _container_.control; _container_.control =
0)
{
915 OMEquation *equation = getOMEquation(mEquations, index);
916 if (equation) {
917 QStringList values;
918 values << QString::number(index) << equation->section << equation->toString();
919 QTreeWidgetItem *pUsedInTreeItem = new IntegerTreeWidgetItem(values, mpUsedInEquationsTreeWidget);
920 pUsedInTreeItem->setToolTip(0, values[0]);
921 pUsedInTreeItem->setToolTip(1, values[1]);
922 pUsedInTreeItem->setToolTip(2, values[2]);
923 mpUsedInEquationsTreeWidget->addTopLevelItem(pUsedInTreeItem);
924 }
925 }
926}
927
928void TransformationsWidget::fetchOperations(const OMVariable &variable)
929{
930 /* Clear the operations tree. */
931 clearTreeWidgetItems(mpVariableOperationsTreeWidget);
932 /* add operations */
933 if (hasOperationsEnabled) {
934 foreach (OMOperation *op, variable.ops)for (auto _container_ = QtPrivate::qMakeForeachContainer(variable
.ops); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (OMOperation
*op = *_container_.i; _container_.control; _container_.control
= 0)
{
935 QTreeWidgetItem *pOperationTreeItem = new QTreeWidgetItem();
936 mpVariableOperationsTreeWidget->addTopLevelItem(pOperationTreeItem);
937 // set label item
938 Label *opText = new Label("<html><div style=\"margin:3px;\">" + op->toHtml() + "</div></html>");
939 mpVariableOperationsTreeWidget->setItemWidget(pOperationTreeItem, 0, opText);
940 }
941 } else {
942 QString message = GUIMessages::getMessage(GUIMessages::SET_INFO_XML_FLAG).arg(Helper::toolsOptionsPath).arg(Helper::toolsOptionsPath);
943 QStringList values;
944 values << message;
945 QString toolTip = message;
946 QTreeWidgetItem *pOperationTreeItem = new QTreeWidgetItem(values);
947 pOperationTreeItem->setToolTip(0, toolTip);
948 mpVariableOperationsTreeWidget->addTopLevelItem(pOperationTreeItem);
949 }
950 mpVariableOperationsTreeWidget->resizeColumnToContents(0);
951}
952
953QTreeWidgetItem* TransformationsWidget::makeEquationTreeWidgetItem(int equationIndex, int allowChild)
954{
955 OMEquation *equation = mEquations[equationIndex];
956 if (!allowChild && equation->parent) {
957 return NULL__null; // Only output equations in one position
958 }
959 QStringList values;
960 values << QString::number(equation->index)
961 << equation->section
962 << equation->toString();
963 if (equation->profileBlock >= 0) {
964 values << QString::number(equation->ncall)
965 << QString::number(equation->maxTime, 'g', 3)
966 << QString::number(equation->time, 'g', 3)
967 << QString::number(100 * equation->fraction, 'g', 3) + "%";
968 }
969
970 QTreeWidgetItem *pEquationTreeItem = new IntegerTreeWidgetItem(values, mpEquationsTreeWidget);
971 pEquationTreeItem->setToolTip(0, values[0]);
972 pEquationTreeItem->setToolTip(1, values[1]);
973 pEquationTreeItem->setToolTip(2, "<html><div style=\"margin:3px;\">" +
974#if (QT_VERSION((5<<16)|(9<<8)|(5)) >= QT_VERSION_CHECK(5, 0, 0)((5<<16)|(0<<8)|(0)))
975 QString(values[2]).toHtmlEscaped()
976#else /* Qt4 */
977 Qt::escape(values[2])
978#endif
979 + "</div></html>");
980 pEquationTreeItem->setToolTip(4, "Maximum execution time in a single step");
981 pEquationTreeItem->setToolTip(5, "Total time excluding the overhead of measuring.");
982 pEquationTreeItem->setToolTip(6, "Fraction of time, 100% is the total time of all non-child equations.");
983 return pEquationTreeItem;
984}
985
986void TransformationsWidget::fetchEquations()
987{
988 for (int i = 1 ; i < mEquations.size() ; i++)
989 {
990 QTreeWidgetItem *pEquationTreeItem = makeEquationTreeWidgetItem(i,0);
991 if (pEquationTreeItem) {
992 mpEquationsTreeWidget->addTopLevelItem(pEquationTreeItem);
993 fetchNestedEquations(pEquationTreeItem, i);
994 }
995 }
996}
997
998void TransformationsWidget::fetchNestedEquations(QTreeWidgetItem *pParentTreeWidgetItem, int index)
999{
1000 foreach (int nestedIndex, mEquations[index]->eqs)for (auto _container_ = QtPrivate::qMakeForeachContainer(mEquations
[index]->eqs); _container_.control && _container_.
i != _container_.e; ++_container_.i, _container_.control ^= 1
) for (int nestedIndex = *_container_.i; _container_.control;
_container_.control = 0)
1001 {
1002 // OMEquation *nestedEquation = mpInfoXMLFileHandler->equations[nestedIndex];
1003 QTreeWidgetItem *pNestedEquationTreeItem = makeEquationTreeWidgetItem(nestedIndex,1);
1004 if (pNestedEquationTreeItem) {
1005 pParentTreeWidgetItem->addChild(pNestedEquationTreeItem);
1006 fetchNestedEquations(pNestedEquationTreeItem, nestedIndex);
1007 }
1008 }
1009}
1010
1011QTreeWidgetItem* TransformationsWidget::findEquationTreeItem(int equationIndex)
1012{
1013 QTreeWidgetItemIterator it(mpEquationsTreeWidget);
1014 while (*it)
1015 {
1016 QTreeWidgetItem *pEquationTreeItem = dynamic_cast<QTreeWidgetItem*>(*it);
1017 if (pEquationTreeItem->text(0).toInt() == equationIndex)
1018 return pEquationTreeItem;
1019 ++it;
1020 }
1021 return 0;
1022}
1023
1024#include <qwt_plot.h>
1025
1026void TransformationsWidget::fetchEquationData(int equationIndex)
1027{
1028 OMEquation *equation = getOMEquation(mEquations, equationIndex);
1029 if (!equation) {
1030 return;
1031 }
1032 mCurrentEquationIndex = equationIndex;
1033 /* fetch defines */
1034 fetchDefines(equation);
1035 /* fetch depends */
1036 fetchDepends(equation);
1037 /* fetch operations */
1038 fetchOperations(equation, (HtmlDiff)mpEquationDiffFilterComboBox->itemData(mpEquationDiffFilterComboBox->currentIndex()).toInt());
1039
1040 /* TODO: This data is correct. Add this to some widget thingy somewhere.
1041 * Maybe a small one that you can click to enlarge.
1042 * Also add the count one (Model_prof.intdata)
1043 */
1044#if 0
1045 if (equation->profileBlock >= 0) {
1046 QFile file(mProfilingDataRealFileName);
1047 if (file.open(QIODevice::ReadOnly)) {
1048
1049 QwtPlot *w;
1050 long c1;
1051 w = new QwtPlot();
1052
1053 size_t rowSize = sizeof(double) * profilingNumSteps;
1054 file.seek(0);
1055 QByteArray datax = file.read(rowSize);
1056 file.seek((equation->profileBlock+2) * rowSize);
1057 QByteArray datay = file.read(rowSize);
1058 double *x = (double*)datax.data();
1059 double *y = (double*)datay.data();
1060
1061 QwtPlotCurve *curve = new QwtPlotCurve("Curve 1");
1062
1063 curve->setData(x, y, profilingNumSteps);
1064 curve->attach(w);
1065 w->replot();
1066 w->show();
1067 }
1068 } else {
1069 qDebugQMessageLogger(nullptr, 0, nullptr).debug() << equation->profileBlock;
1070 }
1071#endif
1072
1073 if (!equation->info.isValid) {
1074 return;
1075 }
1076 /* open the model with and go to the equation line */
1077 QString fileName = equation->info.file;
1078 QFileInfo fileInfo(fileName);
1079 if (fileInfo.isRelative()) {
1080 // find the class
1081 LibraryTreeItem *pLibraryTreeItem = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->findLibraryTreeItem(fileName);
1082 if (pLibraryTreeItem) {
1083 fileName = pLibraryTreeItem->getFileName();
1084 }
1085 }
1086 QFile file(fileName);
1087 if (file.exists()) {
1088 mpTSourceEditorFileLabel->setText(file.fileName());
1089 mpTSourceEditorFileLabel->show();
1090 file.open(QIODevice::ReadOnly);
1091 mpTransformationsEditor->getPlainTextEdit()->setPlainText(QString(file.readAll()));
1092 mpTSourceEditorInfoBar->hide();
1093 file.close();
1094 mpTransformationsEditor->getPlainTextEdit()->goToLineNumber(equation->info.lineStart);
1095 mpTransformationsEditor->getPlainTextEdit()->foldAll();
1096 }
1097}
1098
1099void TransformationsWidget::fetchDefines(OMEquation *equation)
1100{
1101 /* Clear the defines tree. */
1102 clearTreeWidgetItems(mpDefinesVariableTreeWidget);
1103 /* add defines */
1104 if (equation) {
1105 foreach (QString define, equation->defines)for (auto _container_ = QtPrivate::qMakeForeachContainer(equation
->defines); _container_.control && _container_.i !=
_container_.e; ++_container_.i, _container_.control ^= 1) for
(QString define = *_container_.i; _container_.control; _container_
.control = 0)
{
1106 QStringList values;
1107 values << define;
1108 QString toolTip = define;
1109 QTreeWidgetItem *pDefineTreeItem = new QTreeWidgetItem(values);
1110 pDefineTreeItem->setToolTip(0, toolTip);
1111 mpDefinesVariableTreeWidget->addTopLevelItem(pDefineTreeItem);
1112 }
1113 if ((equation->tag.compare("residual") == 0) && (equation->defines.isEmpty())) {
1114 QStringList values;
1115 values << QString("Part of an implicit system of equations");
1116 QString toolTip = values.at(0);
1117 QTreeWidgetItem *pDefineTreeItem = new QTreeWidgetItem(values);
1118 pDefineTreeItem->setToolTip(0, toolTip);
1119 mpDefinesVariableTreeWidget->addTopLevelItem(pDefineTreeItem);
1120 }
1121 mpDefinesVariableTreeWidget->resizeColumnToContents(0);
1122 }
1123}
1124
1125void TransformationsWidget::fetchDepends(OMEquation *equation)
1126{
1127 /* Clear the depends tree. */
1128 clearTreeWidgetItems(mpDependsVariableTreeWidget);
1129 /* add depends */
1130 if (equation) {
1131 foreach (QString depend, equation->depends)for (auto _container_ = QtPrivate::qMakeForeachContainer(equation
->depends); _container_.control && _container_.i !=
_container_.e; ++_container_.i, _container_.control ^= 1) for
(QString depend = *_container_.i; _container_.control; _container_
.control = 0)
{
1132 QStringList values;
1133 values << depend;
1134 QString toolTip = depend;
1135 QTreeWidgetItem *pDependTreeItem = new QTreeWidgetItem(values);
1136 pDependTreeItem->setToolTip(0, toolTip);
1137 mpDependsVariableTreeWidget->addTopLevelItem(pDependTreeItem);
1138 }
1139 mpDependsVariableTreeWidget->resizeColumnToContents(0);
1140 }
1141}
1142
1143void TransformationsWidget::fetchOperations(OMEquation *equation, HtmlDiff htmlDiff)
1144{
1145 /* Clear the operations tree. */
1146 clearTreeWidgetItems(mpEquationOperationsTreeWidget);
1147 /* add operations */
1148 if (hasOperationsEnabled) {
1149 if (equation) {
1150 foreach (OMOperation *op, equation->ops)for (auto _container_ = QtPrivate::qMakeForeachContainer(equation
->ops); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (OMOperation
*op = *_container_.i; _container_.control; _container_.control
= 0)
{
1151 QTreeWidgetItem *pOperationTreeItem = new QTreeWidgetItem();
1152 mpEquationOperationsTreeWidget->addTopLevelItem(pOperationTreeItem);
1153 // set label item
1154 Label *opText = new Label("<html><div style=\"margin:3px;\">" + op->toHtml(htmlDiff) + "</div></html>");
1155 mpEquationOperationsTreeWidget->setItemWidget(pOperationTreeItem, 0, opText);
1156 }
1157 }
1158 } else {
1159 QString message = GUIMessages::getMessage(GUIMessages::SET_INFO_XML_FLAG).arg(Helper::toolsOptionsPath).arg(Helper::toolsOptionsPath);
1160 QStringList values;
1161 values << message;
1162 QString toolTip = message;
1163 QTreeWidgetItem *pOperationTreeItem = new QTreeWidgetItem(values);
1164 pOperationTreeItem->setToolTip(0, toolTip);
1165 mpEquationOperationsTreeWidget->addTopLevelItem(pOperationTreeItem);
1166 }
1167 mpEquationOperationsTreeWidget->resizeColumnToContents(0);
1168}
1169
1170void TransformationsWidget::clearTreeWidgetItems(QTreeWidget *pTreeWidget)
1171{
1172 int i = 0;
1173 while(i < pTreeWidget->topLevelItemCount())
1174 {
1175 qDeleteAll(pTreeWidget->topLevelItem(i)->takeChildren());
1176 delete pTreeWidget->topLevelItem(i);
1177 i = 0; //Restart iteration
1178 }
1179}
1180
1181void TransformationsWidget::reloadTransformations()
1182{
1183 mCurrentEquationIndex = 0;
1184 /* clear trees */
1185 mpTVariablesTreeModel->clearTVariablesTreeItems();
1186 /* Clear the defined in tree. */
1187 clearTreeWidgetItems(mpDefinedInEquationsTreeWidget);
1188 /* Clear the used in tree. */
1189 clearTreeWidgetItems(mpUsedInEquationsTreeWidget);
1190 /* Clear the variable operations tree. */
1191 clearTreeWidgetItems(mpVariableOperationsTreeWidget);
1192 /* clear the variable tree filters. */
1193 bool signalsState = mpTreeSearchFilters->getFilterTextBox()->blockSignals(true);
1194 mpTreeSearchFilters->getFilterTextBox()->clear();
1195 mpTreeSearchFilters->getFilterTextBox()->blockSignals(signalsState);
1196 signalsState = mpTreeSearchFilters->getSyntaxComboBox()->blockSignals(true);
1197 mpTreeSearchFilters->getSyntaxComboBox()->setCurrentIndex(0);
1198 mpTreeSearchFilters->getSyntaxComboBox()->blockSignals(signalsState);
1199 signalsState = mpTreeSearchFilters->getCaseSensitiveCheckBox()->blockSignals(true);
1200 mpTreeSearchFilters->getCaseSensitiveCheckBox()->setChecked(false);
1201 mpTreeSearchFilters->getCaseSensitiveCheckBox()->blockSignals(signalsState);
1202 mpTVariableTreeProxyModel->setFilterRegExp(QRegExp());
1203 /* clear equations tree */
1204 clearTreeWidgetItems(mpEquationsTreeWidget);
1205 /* clear defines in tree */
1206 clearTreeWidgetItems(mpDefinesVariableTreeWidget);
1207 /* clear depends tree */
1208 clearTreeWidgetItems(mpDependsVariableTreeWidget);
1209 /* clear equation operations tree */
1210 clearTreeWidgetItems(mpEquationOperationsTreeWidget);
1211 /* clear TSourceEditor */
1212 mpTSourceEditorFileLabel->setText("");
1213 mpTSourceEditorFileLabel->hide();
1214 mpTransformationsEditor->getPlainTextEdit()->clear();
1215 mpTSourceEditorInfoBar->hide();
1216 /* Clear the equations tree. */
1217 clearTreeWidgetItems(mpEquationsTreeWidget);
1218 /* initialize all fields again */
1219 loadTransformations();
1220}
1221
1222/*!
1223 * \brief TransformationsWidget::findVariables
1224 * Finds the variables in the TransformationsWidget Variables Browser.
1225 */
1226void TransformationsWidget::findVariables()
1227{
1228 QString findText = mpTreeSearchFilters->getFilterTextBox()->text();
1229 QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(mpTreeSearchFilters->getSyntaxComboBox()->itemData(mpTreeSearchFilters->getSyntaxComboBox()->currentIndex()).toInt());
1230 Qt::CaseSensitivity caseSensitivity = mpTreeSearchFilters->getCaseSensitiveCheckBox()->isChecked() ? Qt::CaseSensitive: Qt::CaseInsensitive;
1231 QRegExp regExp(findText, caseSensitivity, syntax);
1232 mpTVariableTreeProxyModel->setFilterRegExp(regExp);
1233 /* expand all so that the filtered items can be seen. */
1234 if (!findText.isEmpty()) {
1235 mpTVariablesTreeView->expandAll();
1236 }
1237}
1238
1239void TransformationsWidget::fetchVariableData(const QModelIndex &index)
1240{
1241 if (!index.isValid())
1242 return;
1243 QModelIndex modelIndex = mpTVariableTreeProxyModel->mapToSource(index);
1244 TVariablesTreeItem *pTVariableTreeItem = static_cast<TVariablesTreeItem*>(modelIndex.internalPointer());
1245 if (!pTVariableTreeItem)
1246 return;
1247
1248 const OMVariable &variable = mVariables[pTVariableTreeItem->getVariableName()];
1249 /* fetch defined in equations */
1250 fetchDefinedInEquations(variable);
1251 /* fetch used in equations */
1252 fetchUsedInEquations(variable);
1253 /* fetch operations */
1254 fetchOperations(variable);
1255
1256 if (!variable.info.isValid)
1257 return;
1258 /* open the model with and go to the variable line */
1259 QString fileName = variable.info.file;
1260 QFileInfo fileInfo(fileName);
1261 if (fileInfo.isRelative()) {
1262 // find the class
1263 LibraryTreeItem *pLibraryTreeItem = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->findLibraryTreeItem(fileName);
1264 if (pLibraryTreeItem) {
1265 fileName = pLibraryTreeItem->getFileName();
1266 }
1267 }
1268 QFile file(fileName);
1269 if (file.exists()) {
1270 mpTSourceEditorFileLabel->setText(file.fileName());
1271 mpTSourceEditorFileLabel->show();
1272 file.open(QIODevice::ReadOnly);
1273 mpTransformationsEditor->getPlainTextEdit()->setPlainText(QString(file.readAll()));
1274 mpTSourceEditorInfoBar->hide();
1275 file.close();
1276 mpTransformationsEditor->getPlainTextEdit()->goToLineNumber(variable.info.lineStart);
1277 mpTransformationsEditor->getPlainTextEdit()->foldAll();
1278 }
1279}
1280
1281void TransformationsWidget::fetchEquationData(QTreeWidgetItem *pEquationTreeItem, int column)
1282{
1283 Q_UNUSED(column)(void)column;;
1284 if (!pEquationTreeItem) {
1285 return;
1286 }
1287
1288 int equationIndex = pEquationTreeItem->text(0).toInt();
1289 /* if the sender is mpEquationsTreeWidget then there is no need to select the item. */
1290 EquationTreeWidget *pSender = qobject_cast<EquationTreeWidget*>(sender());
1291 if (pSender != mpEquationsTreeWidget) {
1292 QTreeWidgetItem *pTreeWidgetItem = findEquationTreeItem(equationIndex);
1293 if (pTreeWidgetItem) {
1294 mpEquationsTreeWidget->clearSelection();
1295 mpEquationsTreeWidget->setCurrentItem(pTreeWidgetItem);
1296 }
1297 }
1298 fetchEquationData(equationIndex);
1299}
1300
1301void TransformationsWidget::filterEquationOperations(int index)
1302{
1303 if (mCurrentEquationIndex < 1) {
1304 return;
1305 }
1306 OMEquation *equation = getOMEquation(mEquations, mCurrentEquationIndex);
1307 if (!equation) {
1308 return;
1309 }
1310 fetchOperations(equation, (HtmlDiff)mpEquationDiffFilterComboBox->itemData(index).toInt());
1311}
1312
1313void TransformationsWidget::parseProfiling(QString fileName)
1314{
1315 QFile *file = new QFile(fileName);
1316 if (!file->exists()) {
1317 delete file;
1318 return;
1319 }
1320 QJson::Parser parser;
1321 bool ok;
1322 QVariantMap result = parser.parse(file, &ok).toMap();
1323 double totalStepsTime = result["totalTimeProfileBlocks"].toDouble();
1324 QVariantList functions = result["functions"].toList();
1325 QVariantList list = result["profileBlocks"].toList();
1326 profilingNumSteps = result["numStep"].toInt() + 1; // Initialization is not a step, but part of the file
1327 for (int i=0; i<list.size(); i++) {
1328 QVariantMap eq = list[i].toMap();
1329 long id = eq["id"].toInt();
1330 double time = eq["time"].toDouble();
1331 mEquations[id]->ncall = eq["ncall"].toInt();
1332 mEquations[id]->maxTime = eq["maxTime"].toDouble();
1333 mEquations[id]->time = time;
1334 mEquations[id]->fraction = time / totalStepsTime;
1335 mEquations[id]->profileBlock = i + functions.size();
1336 }
1337 delete file;
1338}