Bug Summary

File:OMEdit/OMEditLIB/Annotations/LineAnnotation.cpp
Warning:line 1111, column 35
Array access (via field 'pointsX') results in a null pointer dereference

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 "LineAnnotation.h"
37#include "Modeling/ItemDelegate.h"
38#include "Modeling/Commands.h"
39#include "OMS/BusDialog.h"
40#include "Util/ResourceCache.h"
41
42#include <QMessageBox>
43
44LineAnnotation::LineAnnotation(QString annotation, GraphicsView *pGraphicsView)
45 : ShapeAnnotation(false, pGraphicsView, 0, 0)
46{
47 mpOriginItem = new OriginItem(this);
48 mpOriginItem->setPassive();
49 setLineType(LineAnnotation::ShapeType);
50 setStartComponent(0);
51 setStartComponentName("");
52 setEndComponent(0);
53 setEndComponentName("");
54 mStartAndEndComponentsSelected = false;
55 setCondition("");
56 setImmediate(true);
57 setReset(true);
58 setSynchronize(false);
59 setPriority(1);
60 mpTextAnnotation = 0;
61 setOldAnnotation("");
62 setDelay("");
63 setZf("");
64 setZfr("");
65 setAlpha("");
66 setOMSConnectionType(oms_connection_single);
67 setActiveState(false);
68 // set the default values
69 GraphicItem::setDefaults();
70 ShapeAnnotation::setDefaults();
71 // set users default value by reading the settings file.
72 ShapeAnnotation::setUserDefaults();
73 parseShapeAnnotation(annotation);
74 setShapeFlags(true);
75}
76
77LineAnnotation::LineAnnotation(ShapeAnnotation *pShapeAnnotation, Component *pParent)
78 : ShapeAnnotation(pShapeAnnotation, pParent)
79{
80 mpOriginItem = 0;
81 updateShape(pShapeAnnotation);
82 setLineType(LineAnnotation::ComponentType);
83 setStartComponent(0);
84 setStartComponentName("");
85 setEndComponent(0);
86 setEndComponentName("");
87 mStartAndEndComponentsSelected = false;
88 setCondition("");
89 setImmediate(true);
90 setReset(true);
91 setSynchronize(false);
92 setPriority(1);
93 mpTextAnnotation = 0;
94 setOldAnnotation("");
95 setDelay("");
96 setZf("");
97 setZfr("");
98 setAlpha("");
99 setOMSConnectionType(oms_connection_single);
100 setActiveState(false);
101 setPos(mOrigin);
102 setRotation(mRotation);
103}
104
105LineAnnotation::LineAnnotation(ShapeAnnotation *pShapeAnnotation, GraphicsView *pGraphicsView)
106 : ShapeAnnotation(true, pGraphicsView, pShapeAnnotation, 0)
107{
108 mpOriginItem = new OriginItem(this);
109 mpOriginItem->setPassive();
110 updateShape(pShapeAnnotation);
111 setShapeFlags(true);
112 mpGraphicsView->addItem(this);
113 mpGraphicsView->addItem(mpOriginItem);
114}
115
116LineAnnotation::LineAnnotation(LineAnnotation::LineType lineType, Component *pStartComponent, GraphicsView *pGraphicsView)
117 : ShapeAnnotation(false, pGraphicsView, 0, 0)
118{
119 mpOriginItem = 0;
120 mLineType = lineType;
121 setZValue(1000);
122 // set the default values
123 GraphicItem::setDefaults();
124 ShapeAnnotation::setDefaults();
125 // set the start component
126 setStartComponent(pStartComponent);
127 setStartComponentName("");
128 setEndComponent(0);
129 setEndComponentName("");
130 mStartAndEndComponentsSelected = false;
131 setCondition("");
132 setImmediate(true);
133 setReset(true);
134 setSynchronize(false);
135 setPriority(1);
136 setOMSConnectionType(oms_connection_single);
137 setActiveState(false);
138 if (mLineType == LineAnnotation::ConnectionType) {
139 /* Use the linecolor of the first shape of the start component for the connection line.
140 * If there is no shape then look in the inherited shapes.
141 * Or use black color if no shape is found even in inheritance.
142 * Dymola is doing it the way explained above. The Modelica specification doesn't say anything about it.
143 */
144 if (mpGraphicsView->getModelWidget()->getLibraryTreeItem()->getLibraryType() == LibraryTreeItem::Modelica) {
145 if (pStartComponent->getShapesList().size() > 0) {
146 mLineColor = pStartComponent->getShapesList().at(0)->getLineColor();
147 } else {
148 mLineColor = findLineColorForConnection(pStartComponent);
149 }
150 }
151 mpTextAnnotation = 0;
152 } else if (mLineType == LineAnnotation::TransitionType) {
153 /* From Modelica Spec 33revision1,
154 * The recommended color is {175,175,175} for transition lines.
155 */
156 mLineColor = QColor(175, 175, 175);
157 mSmooth = StringHandler::SmoothBezier;
158 QString textShape = "true, {0.0, 0.0}, 0, {95, 95, 95}, {0, 0, 0}, LinePattern.Solid, FillPattern.None, 0.25, {{-4, 4}, {-4, 10}}, \"%condition\", 10, {TextStyle.Bold}, TextAlignment.Right";
159 mpTextAnnotation = new TextAnnotation(textShape, this);
160 }
161 // set the graphics view
162 mpGraphicsView->addItem(this);
163 setOldAnnotation("");
164
165 ComponentInfo *pInfo = getStartComponent()->getComponentInfo();
166 bool tlm = (pInfo->getTLMCausality() == "Bidirectional");
167 int dimensions = pInfo->getDimensions();
168
169 setDelay("1e-4");
170 if(tlm && dimensions>1) { //3D connection, use Zf and Zfr
171 setZf("10000");
172 setZfr("100");
173 setAlpha("0.2");
174 }
175 else if(tlm && dimensions == 1) { //1D connection, only Zf
176 setZf("10000");
177 setZfr("");
178 setAlpha("0.2");
179 }
180 else { //Signal connection, no TLM parameters
181 setZf("");
182 setZfr("");
183 setAlpha("");
184 }
185}
186
187LineAnnotation::LineAnnotation(QString annotation, Component *pStartComponent, Component *pEndComponent, GraphicsView *pGraphicsView)
188 : ShapeAnnotation(false, pGraphicsView, 0, 0)
189{
190 mpOriginItem = 0;
191 setFlag(QGraphicsItem::ItemIsSelectable);
192 mLineType = LineAnnotation::ConnectionType;
193 setZValue(1000);
194 // set the default values
195 GraphicItem::setDefaults();
196 ShapeAnnotation::setDefaults();
197 // set the start component
198 setStartComponent(pStartComponent);
199 setStartComponentName("");
200 // set the end component
201 setEndComponent(pEndComponent);
202 setEndComponentName("");
203 mStartAndEndComponentsSelected = false;
204 setCondition("");
205 setImmediate(true);
206 setReset(true);
207 setSynchronize(false);
208 setPriority(1);
209 mpTextAnnotation = 0;
210 setOldAnnotation("");
211 setDelay("");
212 setZf("");
213 setZfr("");
214 setAlpha("");
215 setOMSConnectionType(oms_connection_single);
216 setActiveState(false);
217 parseShapeAnnotation(annotation);
218 /* make the points relative to origin */
219 QList<QPointF> points;
220 for (int i = 0 ; i < mPoints.size() ; i++) {
221 QPointF point = mOrigin + mPoints[i];
222 points.append(point);
223 }
224 mPoints = points;
225 mOrigin = QPointF(0, 0);
226 // set the graphics view
227 mpGraphicsView->addItem(this);
228}
229
230LineAnnotation::LineAnnotation(QString annotation, QString text, Component *pStartComponent, Component *pEndComponent, QString condition,
231 QString immediate, QString reset, QString synchronize, QString priority, GraphicsView *pGraphicsView)
232 : ShapeAnnotation(false, pGraphicsView, 0, 0)
233{
234 mpOriginItem = 0;
235 setFlag(QGraphicsItem::ItemIsSelectable);
236 mLineType = LineAnnotation::TransitionType;
237 setZValue(1000);
238 // set the default values
239 GraphicItem::setDefaults();
240 ShapeAnnotation::setDefaults();
241 // set the start component
242 setStartComponent(pStartComponent);
243 setStartComponentName("");
244 // set the end component
245 setEndComponent(pEndComponent);
246 setEndComponentName("");
247 mStartAndEndComponentsSelected = false;
248 setCondition(condition);
249 setImmediate(immediate.contains("true"));
250 setReset(reset.contains("true"));
251 setSynchronize(synchronize.contains("true"));
252 setPriority(priority.toInt());
253 setOldAnnotation("");
254 setDelay("");
255 setZf("");
256 setZfr("");
257 setAlpha("");
258 setOMSConnectionType(oms_connection_single);
259 setActiveState(false);
260 parseShapeAnnotation(annotation);
261 /* make the points relative to origin */
262 QList<QPointF> points;
263 for (int i = 0 ; i < mPoints.size() ; i++) {
264 QPointF point = mOrigin + mPoints[i];
265 points.append(point);
266 }
267 mPoints = points;
268 mOrigin = QPointF(0, 0);
269 mpTextAnnotation = new TextAnnotation(text, this);
270 // set the graphics view
271 mpGraphicsView->addItem(this);
272}
273
274LineAnnotation::LineAnnotation(QString annotation, Component *pComponent, GraphicsView *pGraphicsView)
275 : ShapeAnnotation(false, pGraphicsView, 0, 0)
276{
277 mpOriginItem = 0;
278 setFlag(QGraphicsItem::ItemIsSelectable);
279 mLineType = LineAnnotation::InitialStateType;
280 setZValue(1000);
281 // set the default values
282 GraphicItem::setDefaults();
283 ShapeAnnotation::setDefaults();
284 // set the start component
285 setStartComponent(pComponent);
286 setStartComponentName("");
287 // set the end component
288 setEndComponent(0);
289 setEndComponentName("");
290 mStartAndEndComponentsSelected = false;
291 setCondition("");
292 setImmediate(true);
293 setReset(true);
294 setSynchronize(false);
295 setPriority(1);
296 mpTextAnnotation = 0;
297 setOldAnnotation("");
298 setDelay("");
299 setZf("");
300 setZfr("");
301 setAlpha("");
302 setOMSConnectionType(oms_connection_single);
303 setActiveState(false);
304 parseShapeAnnotation(annotation);
305 /* make the points relative to origin */
306 QList<QPointF> points;
307 for (int i = 0 ; i < mPoints.size() ; i++) {
308 QPointF point = mOrigin + mPoints[i];
309 points.append(point);
310 }
311 mPoints = points;
312 mOrigin = QPointF(0, 0);
313 // set the graphics view
314 mpGraphicsView->addItem(this);
315}
316
317LineAnnotation::LineAnnotation(Component *pParent)
318 : ShapeAnnotation(0, pParent)
319{
320 mpOriginItem = 0;
321 setLineType(LineAnnotation::ComponentType);
322 setStartComponent(0);
323 setStartComponentName("");
324 setEndComponent(0);
325 setEndComponentName("");
326 mStartAndEndComponentsSelected = false;
327 setCondition("");
328 setImmediate(true);
329 setReset(true);
330 setSynchronize(false);
331 setPriority(1);
332 mpTextAnnotation = 0;
333 setOldAnnotation("");
334 setDelay("");
335 setZf("");
336 setZfr("");
337 setAlpha("");
338 setOMSConnectionType(oms_connection_single);
339 setActiveState(false);
340 // set the default values
341 GraphicItem::setDefaults();
342 ShapeAnnotation::setDefaults();
343 // create a red cross
344 setLineColor(QColor(255, 0, 0));
345 // create a red cross with points
346 addPoint(QPointF(-100, -100));
347 addPoint(QPointF(100, 100));
348 addPoint(QPointF(-100, 100));
349 addPoint(QPointF(100, -100));
350 addPoint(QPointF(-100, -100));
351 addPoint(QPointF(-100, 100));
352 addPoint(QPointF(100, 100));
353 addPoint(QPointF(100, -100));
354 setPos(mOrigin);
355 setRotation(mRotation);
356}
357
358LineAnnotation::LineAnnotation(GraphicsView *pGraphicsView)
359 : ShapeAnnotation(true, pGraphicsView, 0, 0)
360{
361 mpOriginItem = 0;
362 setLineType(LineAnnotation::ShapeType);
363 setStartComponent(0);
364 setStartComponentName("");
365 setEndComponent(0);
366 setEndComponentName("");
367 mStartAndEndComponentsSelected = false;
368 setCondition("");
369 setImmediate(true);
370 setReset(true);
371 setSynchronize(false);
372 setPriority(1);
373 mpTextAnnotation = 0;
374 setOldAnnotation("");
375 setDelay("");
376 setZf("");
377 setZfr("");
378 setAlpha("");
379 setOMSConnectionType(oms_connection_single);
380 setActiveState(false);
381 // set the default values
382 GraphicItem::setDefaults();
383 ShapeAnnotation::setDefaults();
384 // set users default value by reading the settings file.
385 ShapeAnnotation::setUserDefaults();
386 // create a red cross
387 setLineColor(QColor(255, 0, 0));
388 // create a red cross with points
389 addPoint(QPointF(-100, -100));
390 addPoint(QPointF(100, 100));
391 addPoint(QPointF(-100, 100));
392 addPoint(QPointF(100, -100));
393 addPoint(QPointF(-100, -100));
394 addPoint(QPointF(-100, 100));
395 addPoint(QPointF(100, 100));
396 addPoint(QPointF(100, -100));
397 setShapeFlags(true);
398 mpGraphicsView->addItem(this);
399}
400
401void LineAnnotation::parseShapeAnnotation(QString annotation)
402{
403 GraphicItem::parseShapeAnnotation(annotation);
404 // parse the shape to get the list of attributes of Line.
405 QStringList list = StringHandler::getStrings(annotation);
406 if (list.size() < 10) {
407 return;
408 }
409 mPoints.clear();
410 // 4th item of list contains the points.
411 QStringList pointsList = StringHandler::getStrings(StringHandler::removeFirstLastCurlBrackets(list.at(3)));
412 foreach (QString point, pointsList)for (auto _container_ = QtPrivate::qMakeForeachContainer(pointsList
); _container_.control && _container_.i != _container_
.e; ++_container_.i, _container_.control ^= 1) for (QString point
= *_container_.i; _container_.control; _container_.control =
0)
{
413 QStringList linePoints = StringHandler::getStrings(StringHandler::removeFirstLastCurlBrackets(point));
414 if (linePoints.size() >= 2) {
415 addPoint(QPointF(linePoints.at(0).toFloat(), linePoints.at(1).toFloat()));
416 }
417 }
418 // 5th item of list contains the color.
419 QStringList colorList = StringHandler::getStrings(StringHandler::removeFirstLastCurlBrackets(list.at(4)));
420 if (colorList.size() >= 3) {
421 int red, green, blue = 0;
422 red = colorList.at(0).toInt();
423 green = colorList.at(1).toInt();
424 blue = colorList.at(2).toInt();
425 mLineColor = QColor (red, green, blue);
426 }
427 // 6th item of list contains the Line Pattern.
428 mLinePattern = StringHandler::getLinePatternType(list.at(5));
429 // 7th item of list contains the Line thickness.
430 mLineThickness = list.at(6).toFloat();
431 // 8th item of list contains the Line Arrows.
432 QStringList arrowList = StringHandler::getStrings(StringHandler::removeFirstLastCurlBrackets(list.at(7)));
433 if (arrowList.size() >= 2) {
434 mArrow.replace(0, StringHandler::getArrowType(arrowList.at(0)));
435 mArrow.replace(1, StringHandler::getArrowType(arrowList.at(1)));
436 }
437 // 9th item of list contains the Line Arrow Size.
438 mArrowSize = list.at(8).toFloat();
439 // 10th item of list contains the smooth.
440 mSmooth = StringHandler::getSmoothType(list.at(9));
441}
442
443QPainterPath LineAnnotation::getShape() const
444{
445 QPainterPath path;
446 if (mPoints.size() > 0) {
447 // mPoints.size() is at least 1
448 path.moveTo(mPoints.at(0));
449 if (mSmooth) {
450 if (mPoints.size() == 2) {
451 // if points are only two then spline acts as simple line
452 path.lineTo(mPoints.at(1));
453 } else {
454 for (int i = 2 ; i < mPoints.size() ; i++) {
455 QPointF point3 = mPoints.at(i);
456 // calculate middle points for bezier curves
457 QPointF point2 = mPoints.at(i - 1);
458 QPointF point1 = mPoints.at(i - 2);
459 QPointF point12((point1.x() + point2.x())/2, (point1.y() + point2.y())/2);
460 QPointF point23((point2.x() + point3.x())/2, (point2.y() + point3.y())/2);
461 path.lineTo(point12);
462 path.cubicTo(point12, point2, point23);
463 // if its the last point
464 if (i == mPoints.size() - 1) {
465 path.lineTo(point3);
466 }
467 }
468 }
469 } else {
470 for (int i = 1 ; i < mPoints.size() ; i++) {
471 path.lineTo(mPoints.at(i));
472 }
473 }
474 }
475 return path;
476}
477
478QRectF LineAnnotation::boundingRect() const
479{
480 return shape().boundingRect();
481}
482
483QPainterPath LineAnnotation::shape() const
484{
485 QPainterPath path = getShape();
486 return addPathStroker(path);
487}
488
489void LineAnnotation::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
490{
491 Q_UNUSED(option)(void)option;;
492 Q_UNUSED(widget)(void)widget;;
493 if (mVisible || !mDynamicVisible.isEmpty()) {
494 if (mLineType == LineAnnotation::TransitionType && mpGraphicsView->isVisualizationView()) {
495 if (isActiveState()) {
496 painter->setOpacity(1.0);
497 } else {
498 painter->setOpacity(0.2);
499 }
500 } else if (!mDynamicVisibleValue && ((mpGraphicsView && mpGraphicsView->isVisualizationView())
501 || (mpParentComponent && mpParentComponent->getGraphicsView()->isVisualizationView()))) {
502 return;
503 }
504 drawLineAnnotaion(painter);
505 }
506}
507
508void LineAnnotation::drawLineAnnotaion(QPainter *painter)
509{
510 applyLinePattern(painter);
511 // draw start arrow
512 if (mPoints.size() > 1) {
513 /* If line is a initial state then we need to draw filled arrow.
514 * From Modelica Spec 33revision1,
515 * The initialState line has a filled arrow head and a bullet at the opposite end of the initial state [ as shown above ].
516 */
517 if (mLineType == LineAnnotation::InitialStateType) {
518 drawArrow(painter, mPoints.at(0), mPoints.at(1), mArrowSize, StringHandler::ArrowFilled);
519 } else {
520 /* If line is a transition then we need to draw starting fork if needed.
521 * From Modelica Spec 33revision1,
522 * For synchronize=true, an inverse "fork" symbol is used in the beginning of the arrow [ See the rightmost transition above. ].
523 */
524 if (mLineType == LineAnnotation::TransitionType) {
525 if (mSynchronize) {
526 painter->save();
527 QPolygonF polygon1 = perpendicularLine(mPoints.at(0), mPoints.at(1), 4.0);
528 QPointF midPoint = (polygon1.at(0) + polygon1.at(1)) / 2;
529 QPolygonF polygon2 = perpendicularLine(midPoint, mPoints.at(0), 4.0);
530 QPolygonF polygon;
531 polygon << polygon1 << polygon2 << polygon1.at(0);
532 painter->drawPolygon(polygon);
533 painter->restore();
534 }
535 /* From Modelica Spec 33revision1,
536 * In addition to the line defined by the points of the Line annotation, a perpendicular line is used to represent the transition.
537 * This line is closer to the first point if immediate=false otherwise closer to the last point.
538 */
539 painter->save();
540 QPolygonF polygon;
541 if (mImmediate) {
542 polygon = perpendicularLine(mPoints.at(mPoints.size() - 1), mPoints.at(mPoints.size() - 2), 5.0);
543 } else {
544 polygon = perpendicularLine(mPoints.at(0), mPoints.at(1), 5.0);
545 }
546 QPen pen = painter->pen();
547 pen.setWidth(2);
548 painter->setPen(pen);
549 painter->drawLine(polygon.at(0), polygon.at(1));
550 painter->restore();
551 }
552 drawArrow(painter, mPoints.at(0), mPoints.at(1), mArrowSize, mArrow.at(0));
553 }
554 }
555 painter->drawPath(getShape());
556 // draw end arrow
557 if (mPoints.size() > 1) {
558 /* If line is a transition then we need to draw ending arrow in any case.
559 * From Modelica Spec 33revision1,
560 * If reset=true, a filled arrow head is used otherwise an open arrow head.
561 */
562 if (mLineType == LineAnnotation::TransitionType) {
563 drawArrow(painter, mPoints.at(mPoints.size() - 1), mPoints.at(mPoints.size() - 2), mArrowSize,
564 mReset ? StringHandler::ArrowFilled : StringHandler::ArrowOpen);
565 } else if (mLineType == LineAnnotation::InitialStateType) {
566 /* If line is a initial state then we need to draw bullet.
567 * From Modelica Spec 33revision1,
568 * The initialState line has a filled arrow head and a bullet at the opposite end of the initial state [ as shown above ].
569 */
570 painter->save();
571 painter->setBrush(QBrush(mLineColor, Qt::SolidPattern));
572 painter->drawEllipse(mPoints.at(mPoints.size() - 1), 2, 2);
573 painter->restore();
574 } else {
575 drawArrow(painter, mPoints.at(mPoints.size() - 1), mPoints.at(mPoints.size() - 2), mArrowSize, mArrow.at(1));
576 }
577 }
578}
579
580/*!
581 * \brief LineAnnotation::drawArrow
582 * Draws the arrow according to the arrow type.
583 * \param painter
584 * \param startPos
585 * \param endPos
586 * \param size
587 * \param arrowType
588 */
589void LineAnnotation::drawArrow(QPainter *painter, QPointF startPos, QPointF endPos, qreal size, int arrowType) const
590{
591 double xA = size / 2;
592 double yA = size * sqrt(3) / 2;
593 double xB = -xA;
594 double yB = yA;
595 double angle = 0.0f;
596
597 if (arrowType == StringHandler::ArrowHalf) {
598 xB = 0;
599 }
600
601 if (endPos.x() - startPos.x() == 0) {
602 if (endPos.y() - startPos.y() >= 0) {
603 angle = 0;
604 } else {
605 angle = M_PI3.14159265358979323846;
606 }
607 } else {
608 angle = -(M_PI3.14159265358979323846 / 2 - (atan((endPos.y() - startPos.y())/(endPos.x() - startPos.x()))));
609 if(startPos.x() > endPos.x()) {
610 angle += M_PI3.14159265358979323846;
611 }
612 }
613 qreal m11, m12, m13, m21, m22, m23, m31, m32, m33;
614 m11 = cos(angle);
615 m22 = m11;
616 m21 = sin(angle);
617 m12 = -m21;
618 m13 = startPos.x();
619 m23 = startPos.y();
620 m31 = 0;
621 m32 = 0;
622 m33 = 1;
623 QTransform t1(m11, m12, m13, m21, m22, m23, m31, m32, m33);
624 QTransform t2(xA, 1, 1, yA, 1, 1, 1, 1, 1);
625 QTransform t3 = t1 * t2;
626 QPolygonF arrowPolygon;
627 arrowPolygon << startPos;
628 arrowPolygon << QPointF(t3.m11(), t3.m21());
629 t2.setMatrix(xB, 1, 1, yB, 1, 1, 1, 1, 1);
630 t3 = t1 * t2;
631 arrowPolygon << QPointF(t3.m11(), t3.m21());
632 arrowPolygon << startPos;
633 // draw arrow
634 switch (arrowType) {
635 case StringHandler::ArrowFilled:
636 painter->save();
637 painter->setBrush(QBrush(mLineColor, Qt::SolidPattern));
638 painter->drawPolygon(arrowPolygon);
639 painter->restore();
640 break;
641 case StringHandler::ArrowOpen:
642 if (arrowPolygon.size() > 2) {
643 painter->drawLine(arrowPolygon.at(0), arrowPolygon.at(1));
644 painter->drawLine(arrowPolygon.at(0), arrowPolygon.at(2));
645 }
646 break;
647 case StringHandler::ArrowHalf:
648 if (arrowPolygon.size() > 1) {
649 painter->drawLine(arrowPolygon.at(0), arrowPolygon.at(1));
650 }
651 break;
652 case StringHandler::ArrowNone:
653 default:
654 break;
655 }
656}
657
658/*!
659 * \brief LineAnnotation::perpendicularLine
660 * Returns a polygon which represents a prependicular line.
661 * \param painter
662 * \param startPos
663 * \param endPos
664 * \param size
665 */
666QPolygonF LineAnnotation::perpendicularLine(QPointF startPos, QPointF endPos, qreal size) const
667{
668 double xA = size / 2;
669 double yA = size * sqrt(3) / 2;
670 double xB = -xA;
671 double yB = yA;
672 double angle = 0.0f;
673 if (endPos.x() - startPos.x() == 0) {
674 if (endPos.y() - startPos.y() >= 0) {
675 angle = 0;
676 } else {
677 angle = M_PI3.14159265358979323846;
678 }
679 } else {
680 angle = -(M_PI3.14159265358979323846 / 2 - (atan((endPos.y() - startPos.y())/(endPos.x() - startPos.x()))));
681 if(startPos.x() > endPos.x()) {
682 angle += M_PI3.14159265358979323846;
683 }
684 }
685 qreal m11, m12, m13, m21, m22, m23, m31, m32, m33;
686 m11 = cos(angle);
687 m22 = m11;
688 m21 = sin(angle);
689 m12 = -m21;
690 m13 = startPos.x();
691 m23 = startPos.y();
692 m31 = 0;
693 m32 = 0;
694 m33 = 1;
695 QTransform t1(m11, m12, m13, m21, m22, m23, m31, m32, m33);
696 QTransform t2(xA, 1, 1, yA, 1, 1, 1, 1, 1);
697 QTransform t3 = t1 * t2;
698 QPolygonF polygon;
699 polygon << QPointF(t3.m11(), t3.m21());
700 t2.setMatrix(xB, 1, 1, yB, 1, 1, 1, 1, 1);
701 t3 = t1 * t2;
702 polygon << QPointF(t3.m11(), t3.m21());
703 return polygon;
704}
705
706/*!
707 * \brief LineAnnotation::getOMCShapeAnnotation
708 * Returns Line annotation in format as returned by OMC.
709 * \return
710 */
711QString LineAnnotation::getOMCShapeAnnotation()
712{
713 QStringList annotationString;
714 annotationString.append(GraphicItem::getOMCShapeAnnotation());
715 // get points
716 QString pointsString;
717 if (mPoints.size() > 0) {
718 pointsString.append("{");
719 }
720 for (int i = 0 ; i < mPoints.size() ; i++) {
721 pointsString.append("{").append(QString::number(mPoints[i].x())).append(",");
722 pointsString.append(QString::number(mPoints[i].y())).append("}");
723 if (i < mPoints.size() - 1) {
724 pointsString.append(",");
725 }
726 }
727 if (mPoints.size() > 0) {
728 pointsString.append("}");
729 annotationString.append(pointsString);
730 }
731 // get the line color
732 QString colorString;
733 colorString.append("{");
734 colorString.append(QString::number(mLineColor.red())).append(",");
735 colorString.append(QString::number(mLineColor.green())).append(",");
736 colorString.append(QString::number(mLineColor.blue()));
737 colorString.append("}");
738 annotationString.append(colorString);
739 // get the line pattern
740 annotationString.append(StringHandler::getLinePatternString(mLinePattern));
741 // get the thickness
742 annotationString.append(QString::number(mLineThickness));
743 // get the start and end arrow
744 QString arrowString;
745 arrowString.append("{").append(StringHandler::getArrowString(mArrow.at(0))).append(",");
746 arrowString.append(StringHandler::getArrowString(mArrow.at(1))).append("}");
747 annotationString.append(arrowString);
748 // get the arrow size
749 annotationString.append(QString::number(mArrowSize));
750 // get the smooth
751 annotationString.append(StringHandler::getSmoothString(mSmooth));
752 return annotationString.join(",");
753}
754
755/*!
756 * \brief LineAnnotation::getOMCShapeAnnotationWithShapeName
757 * Returns Line annotation in format as returned by OMC wrapped in Line keyword.
758 * \return
759 */
760QString LineAnnotation::getOMCShapeAnnotationWithShapeName()
761{
762 return QString("Line(%1)").arg(getOMCShapeAnnotation());
763}
764
765/*!
766 * \brief LineAnnotation::getShapeAnnotation
767 * Returns Line annotation.
768 * \return
769 */
770QString LineAnnotation::getShapeAnnotation()
771{
772 QStringList annotationString;
773 annotationString.append(GraphicItem::getShapeAnnotation());
774 // get points
775 QString pointsString;
776 if (mPoints.size() > 0) {
777 pointsString.append("points={");
778 }
779 for (int i = 0 ; i < mPoints.size() ; i++) {
780 pointsString.append("{").append(QString::number(mPoints[i].x())).append(",");
781 pointsString.append(QString::number(mPoints[i].y())).append("}");
782 if (i < mPoints.size() - 1) {
783 pointsString.append(",");
784 }
785 }
786 if (mPoints.size() > 0) {
787 pointsString.append("}");
788 annotationString.append(pointsString);
789 }
790 // get the line color
791 if (mLineColor != Qt::black) {
792 QString colorString;
793 colorString.append("color={");
794 colorString.append(QString::number(mLineColor.red())).append(",");
795 colorString.append(QString::number(mLineColor.green())).append(",");
796 colorString.append(QString::number(mLineColor.blue()));
797 colorString.append("}");
798 annotationString.append(colorString);
799 }
800 // get the line pattern
801 if (mLinePattern != StringHandler::LineSolid) {
802 annotationString.append(QString("pattern=").append(StringHandler::getLinePatternString(mLinePattern)));
803 }
804 // get the thickness
805 if (mLineThickness != 0.25) {
806 annotationString.append(QString("thickness=").append(QString::number(mLineThickness)));
807 }
808 // get the start and end arrow
809 if ((mArrow.at(0) != StringHandler::ArrowNone) || (mArrow.at(1) != StringHandler::ArrowNone)) {
810 QString arrowString;
811 arrowString.append("arrow=");
812 arrowString.append("{").append(StringHandler::getArrowString(mArrow.at(0))).append(",");
813 arrowString.append(StringHandler::getArrowString(mArrow.at(1))).append("}");
814 annotationString.append(arrowString);
815 }
816 // get the arrow size
817 if (mArrowSize != 3) {
818 annotationString.append(QString("arrowSize=").append(QString::number(mArrowSize)));
819 }
820 // get the smooth
821 if (mSmooth != StringHandler::SmoothNone) {
822 annotationString.append(QString("smooth=").append(StringHandler::getSmoothString(mSmooth)));
823 }
824 return QString("Line(").append(annotationString.join(",")).append(")");
825}
826
827/*!
828 * \brief LineAnnotation::getCompositeModelShapeAnnotation
829 * \return
830 */
831QString LineAnnotation::getCompositeModelShapeAnnotation()
832{
833 QStringList annotationString;
834 annotationString.append(GraphicItem::getShapeAnnotation());
835 // get points
836 QString pointsString;
837 if (mPoints.size() > 0) {
838 pointsString.append("{");
839 }
840 for (int i = 0 ; i < mPoints.size() ; i++) {
841 pointsString.append("{").append(QString::number(mPoints[i].x())).append(",");
842 pointsString.append(QString::number(mPoints[i].y())).append("}");
843 if (i < mPoints.size() - 1) {
844 pointsString.append(",");
845 }
846 }
847 if (mPoints.size() > 0) {
848 pointsString.append("}");
849 annotationString.append(pointsString);
850 }
851 return annotationString.join(",");
852}
853
854void LineAnnotation::addPoint(QPointF point)
855{
856 prepareGeometryChange();
857 mPoints.append(point);
858 if (mPoints.size() > 1) {
859 if (mGeometries.size() == 0) {
860 QPointF currentPoint = mPoints[mPoints.size() - 1];
861 QPointF previousPoint = mPoints[mPoints.size() - 2];
862 mGeometries.append(findLineGeometryType(previousPoint, currentPoint));
863 } else {
864 if (mGeometries.back() == ShapeAnnotation::HorizontalLine) {
865 mGeometries.push_back(ShapeAnnotation::VerticalLine);
866 } else if (mGeometries.back() == ShapeAnnotation::VerticalLine) {
867 mGeometries.push_back(ShapeAnnotation::HorizontalLine);
868 }
869 }
870 }
871}
872
873void LineAnnotation::removePoint(int index)
874{
875 prepareGeometryChange();
876 if (mPoints.size() > index) {
877 mPoints.removeAt(index);
878 }
879 if (mGeometries.size() > index - 1) {
880 mGeometries.removeAt(index -1);
881 // adjust the remaining geometries accordingly
882 for (int i = index - 1 ; i < mGeometries.size() ; i++) {
883 if (mGeometries.size() > i - 1) {
884 if (mGeometries[i - 1] == ShapeAnnotation::HorizontalLine) {
885 mGeometries[i] = ShapeAnnotation::VerticalLine;
886 } else if (mGeometries[i - 1] == ShapeAnnotation::VerticalLine) {
887 mGeometries[i] = ShapeAnnotation::HorizontalLine;
888 }
889 }
890 }
891 }
892}
893
894/*!
895 Clears the points list.
896 */
897void LineAnnotation::clearPoints()
898{
899 mPoints.clear();
900 mGeometries.clear();
901}
902
903/*!
904 Updates the first point of the connection, and adjusts the second point accordingly depending on the geometry list.
905 \param point - is the new start point.
906 \sa updateEndPoint(QPointF point)
907 */
908void LineAnnotation::updateStartPoint(QPointF point)
909{
910 prepareGeometryChange();
911 manhattanizeShape();
912 removeRedundantPointsGeometriesAndCornerItems();
913 qreal dx = point.x() - mPoints[0].x();
914 qreal dy = point.y() - mPoints[0].y();
915 // if connection points are just two we need to add extra points
916 if (mPoints.size() == 2) {
917 // just check if additional points are really needed or not.
918 if ((mGeometries[0] == ShapeAnnotation::HorizontalLine && mPoints[0].y() != point.y()) ||
919 (mGeometries[0] == ShapeAnnotation::VerticalLine && mPoints[0].x() != point.x())) {
920 insertPointsGeometriesAndCornerItems(1);
921 setCornerItemsActiveOrPassive();
922 }
923 }
924 /* update the 1st point */
925 if (mPoints.size() > 0) {
926 mPoints[0] = point;
927 updateCornerItem(0);
928 }
929 /* update the 2nd point */
930 if (mPoints.size() > 1) {
931 if (mGeometries[0] == ShapeAnnotation::HorizontalLine) {
932 mPoints[1] = QPointF(mPoints[1].x(), mPoints[1].y() + dy);
933 } else if (mGeometries[0] == ShapeAnnotation::VerticalLine) {
934 mPoints[1] = QPointF(mPoints[1].x() + dx, mPoints[1].y());
935 }
936 updateCornerItem(1);
937 }
938 removeRedundantPointsGeometriesAndCornerItems();
939}
940
941/*!
942 Updates the end point of the connection, and adjusts the second last point accordingly depending on the geometry list.
943 \param point - is the new end point.
944 \sa updateStartPoint(QPointF point)
945 */
946void LineAnnotation::updateEndPoint(QPointF point)
947{
948 prepareGeometryChange();
949 if (mLineType == LineAnnotation::ConnectionType || mLineType == LineAnnotation::TransitionType) {
950 if (!mpGraphicsView->isCreatingConnection() && !mpGraphicsView->isCreatingTransition()) {
951 manhattanizeShape();
952 removeRedundantPointsGeometriesAndCornerItems();
953 }
954 int lastIndex = mPoints.size() - 1;
955 int secondLastIndex = mPoints.size() - 2;
956 qreal dx = point.x() - mPoints[lastIndex].x();
957 qreal dy = point.y() - mPoints[lastIndex].y();
958 /*
959 if connection points are just two we need to add extra points
960 This function is also called when creating a component so for that we don't need to add extra points. In order to avoid this we check
961 for the mpEndComponent since mpEndComponent will only be set when the connection is complete.
962 */
963 if (mPoints.size() == 2 && mpEndComponent) {
964 // just check if additional points are really needed or not.
965 if ((mGeometries[secondLastIndex] == ShapeAnnotation::HorizontalLine && mPoints[lastIndex].y() != point.y()) ||
966 (mGeometries[secondLastIndex] == ShapeAnnotation::VerticalLine && mPoints[lastIndex].x() != point.x())) {
967 insertPointsGeometriesAndCornerItems(lastIndex);
968 setCornerItemsActiveOrPassive();
969 lastIndex = mPoints.size() - 1;
970 secondLastIndex = mPoints.size() - 2;
971 }
972 }
973 /* update the last point */
974 if (mPoints.size() > 1) {
975 mPoints.back() = point;
976 updateCornerItem(lastIndex);
977 /* update the 2nd point */
978 assert(secondLastIndex < mGeometries.size())(static_cast <bool> (secondLastIndex < mGeometries.size
()) ? void (0) : __assert_fail ("secondLastIndex < mGeometries.size()"
, "Annotations/LineAnnotation.cpp", 978, __extension__ __PRETTY_FUNCTION__
))
;
979 if (mGeometries[secondLastIndex] == ShapeAnnotation::HorizontalLine) {
980 mPoints[secondLastIndex] = QPointF(mPoints[secondLastIndex].x(), mPoints[secondLastIndex].y() + dy);
981 } else if (mGeometries[secondLastIndex] == ShapeAnnotation::VerticalLine) {
982 mPoints[secondLastIndex] = QPointF(mPoints[secondLastIndex].x() + dx, mPoints[secondLastIndex].y());
983 }
984 updateCornerItem(secondLastIndex);
985 }
986 if (!mpGraphicsView->isCreatingConnection() && !mpGraphicsView->isCreatingTransition()) {
987 removeRedundantPointsGeometriesAndCornerItems();
988 }
989 } else {
990 mPoints.back() = point;
991 }
992}
993
994/*!
995 * \brief LineAnnotation::updateTransitionTextPosition
996 * Updates the position of the transition text.
997 */
998void LineAnnotation::updateTransitionTextPosition()
999{
1000 /* From Modelica Spec 33revision1,
1001 * The extent of the Text is interpreted relative to either the first point of the Line, in the case of immediate=false,
1002 * or the last point (immediate=true).
1003 */
1004 if (mpTextAnnotation) {
1005 if (mPoints.size() > 0) {
1006 if (mImmediate) {
1007 mpTextAnnotation->setPos(mPoints.last());
1008 } else {
1009 mpTextAnnotation->setPos(mPoints.first());
1010 }
1011 }
1012 }
1013}
1014
1015/*!
1016 Sets the shape flags.
1017 */
1018void LineAnnotation::setShapeFlags(bool enable)
1019{
1020 if ((mLineType == LineAnnotation::ConnectionType || mLineType == LineAnnotation::TransitionType || mLineType == LineAnnotation::ShapeType)
1021 && mpGraphicsView) {
1022 /*
1023 Only set the ItemIsMovable & ItemSendsGeometryChanges flags on Line if the class is not a system library class
1024 AND Line is not an inherited Line AND Line type is not ConnectionType.
1025 */
1026 bool isSystemLibrary = mpGraphicsView->getModelWidget()->getLibraryTreeItem()->isSystemLibrary();
1027 if (!isSystemLibrary && !isInheritedShape() && mLineType != LineAnnotation::ConnectionType &&
1028 mLineType != LineAnnotation::TransitionType && mLineType != LineAnnotation::InitialStateType) {
1029 setFlag(QGraphicsItem::ItemIsMovable, enable);
1030 setFlag(QGraphicsItem::ItemSendsGeometryChanges, enable);
1031 }
1032 setFlag(QGraphicsItem::ItemIsSelectable, enable);
1033 }
1034}
1035
1036void LineAnnotation::updateShape(ShapeAnnotation *pShapeAnnotation)
1037{
1038 prepareGeometryChange();
1039 LineAnnotation *pLineAnnotation = dynamic_cast<LineAnnotation*>(pShapeAnnotation);
1040 setLineType(pLineAnnotation->getLineType());
1041 setStartComponent(pLineAnnotation->getStartComponent());
1042 setStartComponentName(pLineAnnotation->getStartComponentName());
1043 setEndComponent(pLineAnnotation->getEndComponent());
1044 setEndComponentName(pLineAnnotation->getEndComponentName());
1045 setCondition(pLineAnnotation->getCondition());
1046 setImmediate(pLineAnnotation->getImmediate());
1047 setReset(pLineAnnotation->getReset());
1048 setSynchronize(pLineAnnotation->getSynchronize());
1049 setPriority(pLineAnnotation->getPriority());
1050 if (pLineAnnotation->getTextAnnotation()) {
1051 mpTextAnnotation = new TextAnnotation("", this);
1052 mpTextAnnotation->updateShape(pLineAnnotation->getTextAnnotation());
1053 } else {
1054 mpTextAnnotation = 0;
1055 }
1056 setOldAnnotation(pLineAnnotation->getOldAnnotation());
1057 setDelay(pLineAnnotation->getDelay());
1058 setZf(pLineAnnotation->getZf());
1059 setZfr(pLineAnnotation->getZfr());
1060 setAlpha(pLineAnnotation->getAlpha());
1061 setOMSConnectionType(pLineAnnotation->getOMSConnectionType());
1062 setActiveState(pLineAnnotation->isActiveState());
1063 // set the default values
1064 GraphicItem::setDefaults(pShapeAnnotation);
1065 mPoints.clear();
1066 QList<QPointF> points = pShapeAnnotation->getPoints();
1067 for (int i = 0 ; i < points.size() ; i++) {
1068 addPoint(points[i]);
1069 }
1070 updateTransitionTextPosition();
1071 ShapeAnnotation::setDefaults(pShapeAnnotation);
1072}
1073
1074/*!
1075 * \brief LineAnnotation::setAligned
1076 * Marks the connection line as aligned or not aligned.
1077 * \param aligned
1078 */
1079void LineAnnotation::setAligned(bool aligned)
1080{
1081 if (aligned) {
1082 setLineColor(QColor(Qt::black));
1083 } else {
1084 setLineColor(QColor(Qt::red));
1085 }
1086 update();
1087}
1088
1089/*!
1090 * \brief LineAnnotation::updateOMSConnection
1091 * Updates the OMSimulator model connection
1092 */
1093void LineAnnotation::updateOMSConnection()
1094{
1095 // connection geometry
1096 ssd_connection_geometry_t connectionGeometry;
1097 QList<QPointF> points = mPoints;
1098 if (points.size() >= 2) {
6
Assuming the condition is false
7
Taking false branch
1099 points.removeFirst();
1100 points.removeLast();
1101 }
1102 connectionGeometry.n = points.size();
1103 if (points.size() == 0) {
8
Assuming the condition is true
9
Taking true branch
1104 connectionGeometry.pointsX = NULL__null;
10
Null pointer value stored to 'connectionGeometry.pointsX'
1105 connectionGeometry.pointsY = NULL__null;
1106 } else {
1107 connectionGeometry.pointsX = new double[points.size()];
1108 connectionGeometry.pointsY = new double[points.size()];
1109 }
1110 for (int i = 0 ; i < points.size() ; i++) {
11
Assuming the condition is true
12
Loop condition is true. Entering loop body
1111 connectionGeometry.pointsX[i] = points.at(i).x();
13
Array access (via field 'pointsX') results in a null pointer dereference
1112 connectionGeometry.pointsY[i] = points.at(i).y();
1113 }
1114
1115 OMSProxy::instance()->setConnectionGeometry(getStartComponentName(), getEndComponentName(), &connectionGeometry);
1116}
1117
1118void LineAnnotation::updateToolTip()
1119{
1120 if (mLineType == LineAnnotation::ConnectionType) {
1121 setToolTip(QString("<b>connect</b>(%1, %2)").arg(getStartComponentName()).arg(getEndComponentName()));
1122 } else if (mLineType == LineAnnotation::TransitionType) {
1123 setToolTip(QString("<b>transition</b>(%1, %2, %3, %4, %5, %6, %7)")
1124 .arg(getStartComponentName())
1125 .arg(getEndComponentName())
1126 .arg(getCondition())
1127 .arg(getImmediate() ? "true" : "false")
1128 .arg(getReset() ? "true" : "false")
1129 .arg(getSynchronize() ? "true" : "false")
1130 .arg(getPriority()));
1131 }
1132}
1133
1134void LineAnnotation::showOMSConnection()
1135{
1136 if ((mpStartComponent && mpStartComponent->getLibraryTreeItem()->getOMSBusConnector())
1137 && (mpEndComponent && mpEndComponent->getLibraryTreeItem()->getOMSBusConnector())) {
1138 BusConnectionDialog *pBusConnectionDialog = new BusConnectionDialog(mpGraphicsView, this, false);
1139 pBusConnectionDialog->exec();
1140 } else if ((mpStartComponent && mpStartComponent->getLibraryTreeItem()->getOMSTLMBusConnector())
1141 && (mpEndComponent && mpEndComponent->getLibraryTreeItem()->getOMSTLMBusConnector())) {
1142 TLMConnectionDialog *pTLMBusConnectionDialog = new TLMConnectionDialog(mpGraphicsView, this, false);
1143 pTLMBusConnectionDialog->exec();
1144 }
1145}
1146
1147/*!
1148 * \brief LineAnnotation::findLineColorForConnection
1149 * Finds the line color for the connection from the shapes of the start component.
1150 * \param pComponent
1151 * \return
1152 */
1153QColor LineAnnotation::findLineColorForConnection(Component *pComponent)
1154{
1155 QColor lineColor(0, 0, 0);
1156 foreach (Component *pInheritedComponent, pComponent->getInheritedComponentsList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pComponent
->getInheritedComponentsList()); _container_.control &&
_container_.i != _container_.e; ++_container_.i, _container_
.control ^= 1) for (Component *pInheritedComponent = *_container_
.i; _container_.control; _container_.control = 0)
{
1157 if (pInheritedComponent->getShapesList().size() > 0) {
1158 return pInheritedComponent->getShapesList().at(0)->getLineColor();
1159 } else {
1160 lineColor = findLineColorForConnection(pInheritedComponent);
1161 }
1162 }
1163 return lineColor;
1164}
1165
1166QVariant LineAnnotation::itemChange(GraphicsItemChange change, const QVariant &value)
1167{
1168 ShapeAnnotation::itemChange(change, value);
1169#if !defined(WITHOUT_OSG)
1170 if (change == QGraphicsItem::ItemSelectedHasChanged) {
1171
1172 // if connection selection is changed in CompositeModel
1173 if (mpGraphicsView->getModelWidget()->getLibraryTreeItem()->getLibraryType() == LibraryTreeItem::CompositeModel) {
1174 MainWindow::instance()->getModelWidgetContainer()->updateThreeDViewer(mpGraphicsView->getModelWidget());
1175 }
1176 }
1177#endif
1178 return value;
1179}
1180
1181/*!
1182 * \brief LineAnnotation::handleComponentMoved
1183 * If the component associated with the connection is moved then update the connection accordingly.
1184 * \param positionChanged
1185 */
1186void LineAnnotation::handleComponentMoved(bool positionChanged)
1187{
1188 if (mPoints.size() < 2) {
1189 return;
1190 }
1191 prepareGeometryChange();
1192 // if both start and end component are selected and positionChanged is true
1193 if (positionChanged && mpStartComponent && mpStartComponent->getRootParentComponent()->isSelected() && mpEndComponent && mpEndComponent->getRootParentComponent()->isSelected()) {
1194 if (mpStartComponent) {
1195 QPointF offset = mpStartComponent->mapToScene(mpStartComponent->boundingRect().center()) - mPoints[0];
1196 for (int i = 0 ; i < mPoints.size() ; i++) {
1197 mPoints[i] = QPointF(mPoints[i].x() + offset.x(), mPoints[i].y() + offset.y());
1198 updateCornerItem(i);
1199 }
1200 }
1201 } else {
1202 if (mpStartComponent) {
1203 Component *pComponent = qobject_cast<Component*>(sender());
1204 if (pComponent == mpStartComponent->getRootParentComponent()) {
1205 updateStartPoint(mpGraphicsView->roundPoint(mpStartComponent->mapToScene(mpStartComponent->boundingRect().center())));
1206 if (mLineType == LineAnnotation::TransitionType) {
1207 QRectF sceneRectF = mpStartComponent->sceneBoundingRect();
1208 QList<QPointF> newPos = Utilities::liangBarskyClipper(sceneRectF.topLeft().x(), sceneRectF.topLeft().y(),
1209 sceneRectF.bottomRight().x(), sceneRectF.bottomRight().y(),
1210 mPoints.at(0).x(), mPoints.at(0).y(),
1211 mPoints.at(1).x(), mPoints.at(1).y());
1212 updateStartPoint(mpGraphicsView->roundPoint(newPos.at(1)));
1213 updateTransitionTextPosition();
1214 } else if (mLineType == LineAnnotation::InitialStateType) {
1215 QRectF sceneRectF = mpStartComponent->sceneBoundingRect();
1216 QList<QPointF> newPos = Utilities::liangBarskyClipper(sceneRectF.topLeft().x(), sceneRectF.topLeft().y(),
1217 sceneRectF.bottomRight().x(), sceneRectF.bottomRight().y(),
1218 mPoints.at(0).x(), mPoints.at(0).y(),
1219 mPoints.at(1).x(), mPoints.at(1).y());
1220 updateStartPoint(mpGraphicsView->roundPoint(newPos.at(1)));
1221 }
1222 }
1223 }
1224 if (mpEndComponent) {
1225 Component *pComponent = qobject_cast<Component*>(sender());
1226 if (pComponent == mpEndComponent->getRootParentComponent()) {
1227 updateEndPoint(mpGraphicsView->roundPoint(mpEndComponent->mapToScene(mpEndComponent->boundingRect().center())));
1228 if (mLineType == LineAnnotation::TransitionType) {
1229 QRectF sceneRectF = mpEndComponent->sceneBoundingRect();
1230 QList<QPointF> newPos = Utilities::liangBarskyClipper(sceneRectF.topLeft().x(), sceneRectF.topLeft().y(),
1231 sceneRectF.bottomRight().x(), sceneRectF.bottomRight().y(),
1232 mPoints.at(mPoints.size() - 2).x(), mPoints.at(mPoints.size() - 2).y(),
1233 mPoints.at(mPoints.size() - 1).x(), mPoints.at(mPoints.size() - 1).y());
1234 updateEndPoint(mpGraphicsView->roundPoint(newPos.at(0)));
1235 updateTransitionTextPosition();
1236 }
1237 }
1238 }
1239 }
1240}
1241
1242/*!
1243 * \brief LineAnnotation::updateConnectionAnnotation
1244 * Updates the connection annotation.
1245 */
1246void LineAnnotation::updateConnectionAnnotation()
1247{
1248 if (mpGraphicsView->getModelWidget()->getLibraryTreeItem()->getLibraryType()== LibraryTreeItem::CompositeModel) {
1
Assuming the condition is false
2
Taking false branch
1249 CompositeModelEditor *pCompositeModelEditor = dynamic_cast<CompositeModelEditor*>(mpGraphicsView->getModelWidget()->getEditor());
1250 pCompositeModelEditor->updateConnection(this);
1251 } else if (mpGraphicsView->getModelWidget()->getLibraryTreeItem()->getLibraryType()== LibraryTreeItem::OMS) {
3
Assuming the condition is true
4
Taking true branch
1252 updateOMSConnection();
5
Calling 'LineAnnotation::updateOMSConnection'
1253 } else {
1254 // get the connection line annotation.
1255 QString annotationString = QString("annotate=$annotation(%1)").arg(getShapeAnnotation());
1256 // update the connection
1257 OMCProxy *pOMCProxy = MainWindow::instance()->getOMCProxy();
1258 pOMCProxy->updateConnection(mpGraphicsView->getModelWidget()->getLibraryTreeItem()->getNameStructure(), getStartComponentName(), getEndComponentName(), annotationString);
1259 }
1260}
1261
1262/*!
1263 * \brief LineAnnotation::updateConnectionTransformation
1264 * Slot activated when Component transformChanging SIGNAL is emitted.\n
1265 * Updates the connection.
1266 */
1267void LineAnnotation::updateConnectionTransformation()
1268{
1269 /* If both start and end component are selected then this function is called twice.
1270 * we use the flag mStartAndEndComponentSelected to make sure that we only use this function once in such case.
1271 */
1272 if (!mStartAndEndComponentsSelected
1273 && mpStartComponent && mpStartComponent->getRootParentComponent()->isSelected()
1274 && mpEndComponent && mpEndComponent->getRootParentComponent()->isSelected()) {
1275 mStartAndEndComponentsSelected = true;
1276 return;
1277 } else if (mStartAndEndComponentsSelected) {
1278 mStartAndEndComponentsSelected = false;
1279 }
1280
1281 assert(!mOldAnnotation.isEmpty())(static_cast <bool> (!mOldAnnotation.isEmpty()) ? void (
0) : __assert_fail ("!mOldAnnotation.isEmpty()", "Annotations/LineAnnotation.cpp"
, 1281, __extension__ __PRETTY_FUNCTION__))
;
1282 if (mLineType == LineAnnotation::ConnectionType) {
1283 mpGraphicsView->getModelWidget()->getUndoStack()->push(new UpdateConnectionCommand(this, mOldAnnotation, getOMCShapeAnnotation()));
1284 } else if (mLineType == LineAnnotation::TransitionType) {
1285 mpGraphicsView->getModelWidget()->getUndoStack()->push(new UpdateTransitionCommand(this, mCondition, mImmediate, mReset,
1286 mSynchronize, mPriority, mOldAnnotation,
1287 mCondition, mImmediate, mReset, mSynchronize,
1288 mPriority, getOMCShapeAnnotation()));
1289 } else if (mLineType == LineAnnotation::InitialStateType) {
1290 mpGraphicsView->getModelWidget()->getUndoStack()->push(new UpdateInitialStateCommand(this, mOldAnnotation, getOMCShapeAnnotation()));
1291 }
1292}
1293
1294/*!
1295 * \brief LineAnnotation::updateTransitionAnnotation
1296 * Updates the transition annotation.
1297 */
1298void LineAnnotation::updateTransitionAnnotation(QString oldCondition, bool oldImmediate, bool oldReset, bool oldSynchronize, int oldPriority)
1299{
1300 // get the transition line and text annotation.
1301 QString annotationString = QString("annotate=$annotation(%1,%2)").arg(getShapeAnnotation()).arg(mpTextAnnotation->getShapeAnnotation());
1302 // update the transition
1303 OMCProxy *pOMCProxy = MainWindow::instance()->getOMCProxy();
1304 pOMCProxy->updateTransition(mpGraphicsView->getModelWidget()->getLibraryTreeItem()->getNameStructure(), getStartComponentName(),
1305 getEndComponentName(), oldCondition, oldImmediate, oldReset, oldSynchronize, oldPriority, getCondition(),
1306 getImmediate(), getReset(), getSynchronize(), getPriority(), annotationString);
1307}
1308
1309/*!
1310 * \brief LineAnnotation::updateInitialStateAnnotation
1311 * Updates the initial state annotation.
1312 */
1313void LineAnnotation::updateInitialStateAnnotation()
1314{
1315 // get the initial state line annotation.
1316 QString annotationString = QString("annotate=$annotation(%1)").arg(getShapeAnnotation());
1317 // update the initial state
1318 OMCProxy *pOMCProxy = MainWindow::instance()->getOMCProxy();
1319 pOMCProxy->updateInitialState(mpGraphicsView->getModelWidget()->getLibraryTreeItem()->getNameStructure(), getStartComponentName(), annotationString);
1320}
1321
1322/*!
1323 * \brief LineAnnotation::duplicate
1324 * Duplicates the shape.
1325 */
1326void LineAnnotation::duplicate()
1327{
1328 LineAnnotation *pLineAnnotation = new LineAnnotation("", mpGraphicsView);
1329 pLineAnnotation->updateShape(this);
1330 QPointF gridStep(mpGraphicsView->mMergedCoOrdinateSystem.getHorizontalGridStep() * 5,
1331 mpGraphicsView->mMergedCoOrdinateSystem.getVerticalGridStep() * 5);
1332 pLineAnnotation->setOrigin(mOrigin + gridStep);
1333 pLineAnnotation->drawCornerItems();
1334 pLineAnnotation->setCornerItemsActiveOrPassive();
1335 pLineAnnotation->applyTransformation();
1336 pLineAnnotation->update();
1337 mpGraphicsView->getModelWidget()->getUndoStack()->push(new AddShapeCommand(pLineAnnotation));
1338 mpGraphicsView->getModelWidget()->getLibraryTreeItem()->emitShapeAdded(pLineAnnotation, mpGraphicsView);
1339 setSelected(false);
1340 pLineAnnotation->setSelected(true);
1341}
1342
1343void LineAnnotation::redraw(const QString& annotation, std::function<void()> updateAnnotationFunction)
1344{
1345 prepareGeometryChange();
1346 parseShapeAnnotation(annotation);
1347 removeCornerItems();
1348 drawCornerItems();
1349 applyTransformation();
1350 adjustGeometries();
1351 setCornerItemsActiveOrPassive();
1352 emitChanged();
1353 updateAnnotationFunction();
1354}
1355
1356/*!
1357 * \class ExpandableConnectorTreeItem
1358 * \brief Contains the information about the expandable connector item.
1359 */
1360/*!
1361 * \brief ExpandableConnectorTreeItem::ExpandableConnectorTreeItem
1362 * Used for creating the root item.
1363 */
1364ExpandableConnectorTreeItem::ExpandableConnectorTreeItem()
1365{
1366 mIsRootItem = true;
1367 mpParentExpandableConnectorTreeItem = 0;
1368 setName("");
1369 setArray(false);
1370 setArrayIndex("");
1371 setRestriction(StringHandler::Model);
1372 setNewVariable(false);
1373}
1374
1375/*!
1376 * \brief ExpandableConnectorTreeItem::ExpandableConnectorTreeItem
1377 * Used for creatind the expandable item.
1378 * \param name
1379 * \param array
1380 * \param arrayIndex
1381 * \param restriction
1382 * \param newVariable
1383 * \param pParentExpandableConnectorTreeItem
1384 */
1385ExpandableConnectorTreeItem::ExpandableConnectorTreeItem(QString name, bool array, QString arrayIndex,
1386 StringHandler::ModelicaClasses restriction, bool newVariable,
1387 ExpandableConnectorTreeItem *pParentExpandableConnectorTreeItem)
1388{
1389 mIsRootItem = false;
1390 mpParentExpandableConnectorTreeItem = pParentExpandableConnectorTreeItem;
1391 setName(name);
1392 setArray(array);
1393 setArrayIndex(arrayIndex);
1394 setRestriction(restriction);
1395 setNewVariable(newVariable);
1396}
1397
1398/*!
1399 * \brief ExpandableConnectorTreeItem::~ExpandableConnectorTreeItem
1400 * Destructor for ExpandableConnectorTreeItem
1401 */
1402ExpandableConnectorTreeItem::~ExpandableConnectorTreeItem()
1403{
1404 qDeleteAll(mChildren);
1405 mChildren.clear();
1406}
1407
1408/*!
1409 * \brief ExpandableConnectorTreeItem::data
1410 * Returns the data stored under the given role for the item referred to by the column.
1411 * \param column
1412 * \param role
1413 * \return
1414 */
1415QVariant ExpandableConnectorTreeItem::data(int column, int role) const
1416{
1417 switch (column) {
1418 case 0:
1419 switch (role) {
1420 case Qt::DisplayRole:
1421 return mName;
1422 case Qt::DecorationRole:
1423 switch (mRestriction) {
1424 case StringHandler::ExpandableConnector:
1425 return ResourceCache::getIcon(":/Resources/icons/connect-mode.svg");
1426 break;
1427 case StringHandler::Connector:
1428 return ResourceCache::getIcon(":/Resources/icons/connector-icon.svg");
1429 break;
1430 default:
1431 return QVariant();
1432 break;
1433 }
1434 default:
1435 return QVariant();
1436 }
1437 default:
1438 return QVariant();
1439 }
1440}
1441
1442/*!
1443 * \brief ExpandableConnectorTreeItem::row
1444 * Returns the row number corresponding to ExpandableConnectorTreeItem.
1445 * \return
1446 */
1447int ExpandableConnectorTreeItem::row() const
1448{
1449 if (mpParentExpandableConnectorTreeItem) {
1450 return mpParentExpandableConnectorTreeItem->mChildren.indexOf(const_cast<ExpandableConnectorTreeItem*>(this));
1451 }
1452
1453 return 0;
1454}
1455
1456/*!
1457 * \class ExpandableConnectorTreeProxyModel
1458 * \brief A sort filter proxy model for Expandable connectors treeview.
1459 */
1460/*!
1461 * \brief ExpandableConnectorTreeProxyModel::ExpandableConnectorTreeProxyModel
1462 * \param pCreateConnectionDialog
1463 */
1464ExpandableConnectorTreeProxyModel::ExpandableConnectorTreeProxyModel(CreateConnectionDialog *pCreateConnectionDialog)
1465 : QSortFilterProxyModel(pCreateConnectionDialog)
1466{
1467 mpCreateConnectionDialog = pCreateConnectionDialog;
1468}
1469
1470/*!
1471 * \class ExpandableConnectorTreeModel
1472 * \brief A model for Expandable connectors treeview.
1473 */
1474/*!
1475 * \brief ExpandableConnectorTreeModel::ExpandableConnectorTreeModel
1476 * \param pCreateConnectionDialog
1477 */
1478ExpandableConnectorTreeModel::ExpandableConnectorTreeModel(CreateConnectionDialog *pCreateConnectionDialog)
1479 : QAbstractItemModel(pCreateConnectionDialog)
1480{
1481 mpCreateConnectionDialog = pCreateConnectionDialog;
1482 mpRootExpandableConnectorTreeItem = new ExpandableConnectorTreeItem;
1483}
1484
1485/*!
1486 * \brief ExpandableConnectorTreeModel::columnCount
1487 * Returns the number of columns for the children of the given parent.
1488 * \param parent
1489 * \return
1490 */
1491int ExpandableConnectorTreeModel::columnCount(const QModelIndex &parent) const
1492{
1493 Q_UNUSED(parent)(void)parent;;
1494 return 1;
1495}
1496
1497/*!
1498 * \brief ExpandableConnectorTreeModel::rowCount
1499 * Returns the number of rows under the given parent.
1500 * When the parent is valid it means that rowCount is returning the number of children of parent.
1501 * \param parent
1502 * \return
1503 */
1504int ExpandableConnectorTreeModel::rowCount(const QModelIndex &parent) const
1505{
1506 ExpandableConnectorTreeItem *pParentExpandableConnectorTreeItem;
1507 if (parent.column() > 0) {
1508 return 0;
1509 }
1510
1511 if (!parent.isValid()) {
1512 pParentExpandableConnectorTreeItem = mpRootExpandableConnectorTreeItem;
1513 } else {
1514 pParentExpandableConnectorTreeItem = static_cast<ExpandableConnectorTreeItem*>(parent.internalPointer());
1515 }
1516 return pParentExpandableConnectorTreeItem->getChildren().size();
1517}
1518
1519/*!
1520 * \brief ExpandableConnectorTreeModel::headerData
1521 * Returns the data for the given role and section in the header with the specified orientation.
1522 * \param section
1523 * \param orientation
1524 * \param role
1525 * \return
1526 */
1527QVariant ExpandableConnectorTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
1528{
1529 Q_UNUSED(section)(void)section;;
1530 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
1531 return tr("Connector");
1532 }
1533 return QVariant();
1534}
1535
1536/*!
1537 * \brief ExpandableConnectorTreeModel::index
1538 * Returns the index of the item in the model specified by the given row, column and parent index.
1539 * \param row
1540 * \param column
1541 * \param parent
1542 * \return
1543 */
1544QModelIndex ExpandableConnectorTreeModel::index(int row, int column, const QModelIndex &parent) const
1545{
1546 if (!hasIndex(row, column, parent)) {
1547 return QModelIndex();
1548 }
1549
1550 ExpandableConnectorTreeItem *pParentExpandableConnectorTreeItem;
1551 if (!parent.isValid()) {
1552 pParentExpandableConnectorTreeItem = mpRootExpandableConnectorTreeItem;
1553 } else {
1554 pParentExpandableConnectorTreeItem = static_cast<ExpandableConnectorTreeItem*>(parent.internalPointer());
1555 }
1556
1557 ExpandableConnectorTreeItem *pChildExpandableConnectorTreeItem = pParentExpandableConnectorTreeItem->child(row);
1558 if (pChildExpandableConnectorTreeItem) {
1559 return createIndex(row, column, pChildExpandableConnectorTreeItem);
1560 } else {
1561 return QModelIndex();
1562 }
1563}
1564
1565/*!
1566 * \brief ExpandableConnectorTreeModel::parent
1567 * Finds the parent for QModelIndex
1568 * \param index
1569 * \return
1570 */
1571QModelIndex ExpandableConnectorTreeModel::parent(const QModelIndex &index) const
1572{
1573 if (!index.isValid()) {
1574 return QModelIndex();
1575 }
1576
1577 ExpandableConnectorTreeItem *pChildExpandableConnectorTreeItem = static_cast<ExpandableConnectorTreeItem*>(index.internalPointer());
1578 ExpandableConnectorTreeItem *pParentExpandableConnectorTreeItem = pChildExpandableConnectorTreeItem->parent();
1579 if (pParentExpandableConnectorTreeItem == mpRootExpandableConnectorTreeItem)
1580 return QModelIndex();
1581
1582 return createIndex(pParentExpandableConnectorTreeItem->row(), 0, pParentExpandableConnectorTreeItem);
1583}
1584
1585/*!
1586 * \brief ExpandableConnectorTreeModel::data
1587 * Returns the LibraryTreeItem data.
1588 * \param index
1589 * \param role
1590 * \return
1591 */
1592QVariant ExpandableConnectorTreeModel::data(const QModelIndex &index, int role) const
1593{
1594 if (!index.isValid()) {
1595 return QVariant();
1596 }
1597
1598
1599 ExpandableConnectorTreeItem *pExpandableConnectorTreeItem = static_cast<ExpandableConnectorTreeItem*>(index.internalPointer());
1600 return pExpandableConnectorTreeItem->data(index.column(), role);
1601}
1602
1603/*!
1604 * \brief ExpandableConnectorTreeModel::flags
1605 * Returns the LibraryTreeItem flags.
1606 * \param index
1607 * \return
1608 */
1609Qt::ItemFlags ExpandableConnectorTreeModel::flags(const QModelIndex &index) const
1610{
1611 ExpandableConnectorTreeItem *pExpandableConnectorTreeItem = static_cast<ExpandableConnectorTreeItem*>(index.internalPointer());
1612 if (pExpandableConnectorTreeItem &&
1613 ((pExpandableConnectorTreeItem->getRestriction() == StringHandler::ExpandableConnector) ||
1614 (pExpandableConnectorTreeItem->parent() && pExpandableConnectorTreeItem->parent()->getRestriction() == StringHandler::ExpandableConnector))) {
1615 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
1616 } else {
1617 return 0;
1618 }
1619}
1620
1621/*!
1622 * \brief ExpandableConnectorTreeModel::findFirstEnabledItem
1623 * \param pExpandableConnectorTreeItem
1624 * Finds the first enabled item and returns its index.
1625 * \return
1626 */
1627QModelIndex ExpandableConnectorTreeModel::findFirstEnabledItem(ExpandableConnectorTreeItem *pExpandableConnectorTreeItem)
1628{
1629 for (int i = 0 ; i < pExpandableConnectorTreeItem->getChildren().size(); i++) {
1630 QModelIndex index = expandableConnectorTreeItemIndex(pExpandableConnectorTreeItem->child(i));
1631 if (index.isValid() && index.flags() & Qt::ItemIsEnabled) {
1632 return index;
1633 }
1634 index = findFirstEnabledItem(pExpandableConnectorTreeItem->child(i));
1635 if (index.isValid() && index.flags() & Qt::ItemIsEnabled) {
1636 return index;
1637 }
1638 }
1639 return QModelIndex();
1640}
1641
1642/*!
1643 * \brief ExpandableConnectorTreeModel::expandableConnectorTreeItemIndex
1644 * Finds the QModelIndex attached to ExpandableConnectorTreeItem.
1645 * \param pExpandableConnectorTreeItem
1646 * \return
1647 */
1648QModelIndex ExpandableConnectorTreeModel::expandableConnectorTreeItemIndex(const ExpandableConnectorTreeItem *pExpandableConnectorTreeItem) const
1649{
1650 return expandableConnectorTreeItemIndexHelper(pExpandableConnectorTreeItem, mpRootExpandableConnectorTreeItem, QModelIndex());
1651}
1652
1653void ExpandableConnectorTreeModel::createExpandableConnectorTreeItem(Component *pComponent,
1654 ExpandableConnectorTreeItem *pParentExpandableConnectorTreeItem)
1655{
1656 StringHandler::ModelicaClasses restriction = StringHandler::Model;
1657 if (pComponent->getLibraryTreeItem()) {
1658 restriction = pComponent->getLibraryTreeItem()->getRestriction();
1659 }
1660 ExpandableConnectorTreeItem *pExpandableConnectorTreeItem = new ExpandableConnectorTreeItem(pComponent->getName(),
1661 pComponent->getComponentInfo()->isArray(),
1662 pComponent->getComponentInfo()->getArrayIndex(),
1663 restriction, false,
1664 pParentExpandableConnectorTreeItem);
1665 int row = pParentExpandableConnectorTreeItem->getChildren().size();
1666 QModelIndex index = expandableConnectorTreeItemIndex(pParentExpandableConnectorTreeItem);
1667 beginInsertRows(index, row, row);
1668 pParentExpandableConnectorTreeItem->insertChild(row, pExpandableConnectorTreeItem);
1669 endInsertRows();
1670 if (pComponent->getLibraryTreeItem()) {
1671 foreach (Component *pChildComponent, pComponent->getLibraryTreeItem()->getModelWidget()->getDiagramGraphicsView()->getComponentsList())for (auto _container_ = QtPrivate::qMakeForeachContainer(pComponent
->getLibraryTreeItem()->getModelWidget()->getDiagramGraphicsView
()->getComponentsList()); _container_.control && _container_
.i != _container_.e; ++_container_.i, _container_.control ^= 1
) for (Component *pChildComponent = *_container_.i; _container_
.control; _container_.control = 0)
{
1672 createExpandableConnectorTreeItem(pChildComponent, pExpandableConnectorTreeItem);
1673 }
1674 }
1675 // create add variable item only if item is expandable connector
1676 if (pExpandableConnectorTreeItem->getRestriction() == StringHandler::ExpandableConnector) {
1677 ExpandableConnectorTreeItem *pNewVariableExpandableConnectorTreeItem = new ExpandableConnectorTreeItem(Helper::newVariable, false, "",
1678 StringHandler::Model, true,
1679 pExpandableConnectorTreeItem);
1680 int row = pExpandableConnectorTreeItem->getChildren().size();
1681 QModelIndex index = expandableConnectorTreeItemIndex(pExpandableConnectorTreeItem);
1682 beginInsertRows(index, row, row);
1683 pExpandableConnectorTreeItem->insertChild(row, pNewVariableExpandableConnectorTreeItem);
1684 endInsertRows();
1685 }
1686}
1687
1688/*!
1689 * \brief ExpandableConnectorTreeModel::expandableConnectorTreeItemIndexHelper
1690 * Helper function for ExpandableConnectorTreeModel::expandableConnectorTreeItemIndex()
1691 * \param pExpandableConnectorTreeItem
1692 * \param pParentExpandableConnectorTreeItem
1693 * \param parentIndex
1694 * \return
1695 */
1696QModelIndex ExpandableConnectorTreeModel::expandableConnectorTreeItemIndexHelper(const ExpandableConnectorTreeItem *pExpandableConnectorTreeItem,
1697 const ExpandableConnectorTreeItem *pParentExpandableConnectorTreeItem,
1698 const QModelIndex &parentIndex) const
1699{
1700 if (pExpandableConnectorTreeItem == pParentExpandableConnectorTreeItem) {
1701 return parentIndex;
1702 }
1703 for (int i = pParentExpandableConnectorTreeItem->getChildren().size(); --i >= 0; ) {
1704 const ExpandableConnectorTreeItem *childItem = pParentExpandableConnectorTreeItem->getChildren().at(i);
1705 QModelIndex childIndex = index(i, 0, parentIndex);
1706 QModelIndex index = expandableConnectorTreeItemIndexHelper(pExpandableConnectorTreeItem, childItem, childIndex);
1707 if (index.isValid()) {
1708 return index;
1709 }
1710 }
1711 return QModelIndex();
1712}
1713
1714/*!
1715 * \class ExpandableConnectorTreeView
1716 * \brief A tree view for Expandable connectors.
1717 */
1718/*!
1719 * \brief ExpandableConnectorTreeView::ExpandableConnectorTreeView
1720 * \param pCreateConnectionDialog
1721 */
1722ExpandableConnectorTreeView::ExpandableConnectorTreeView(CreateConnectionDialog *pCreateConnectionDialog)
1723 : QTreeView(pCreateConnectionDialog), mpCreateConnectionDialog(pCreateConnectionDialog)
1724{
1725 setItemDelegate(new ItemDelegate(this));
1726 setTextElideMode(Qt::ElideMiddle);
1727 setIndentation(Helper::treeIndentation);
1728 setUniformRowHeights(true);
1729}
1730
1731/*!
1732 * \class CreateConnectionDialog
1733 * \brief A dialog interface for making expandable & array connections.
1734 */
1735/*!
1736 * \brief CreateConnectionDialog::CreateConnectionDialog
1737 * \param pGraphicsView
1738 * \param pConnectionLineAnnotation
1739 * \param pParent
1740 */
1741CreateConnectionDialog::CreateConnectionDialog(GraphicsView *pGraphicsView, LineAnnotation *pConnectionLineAnnotation, QWidget *pParent)
1742 : QDialog(pParent), mpGraphicsView(pGraphicsView), mpConnectionLineAnnotation(pConnectionLineAnnotation)
1743{
1744 setWindowTitle(QString(Helper::applicationName).append(" - ").append(Helper::createConnection));
1745 setAttribute(Qt::WA_DeleteOnClose);
1746 // heading
1747 mpHeading = Utilities::getHeadingLabel(Helper::createConnection);
1748 // horizontal line
1749 mpHorizontalLine = Utilities::getHeadingLine();
1750 // Start expandable connector treeview
1751 mpStartExpandableConnectorTreeView = 0;
1752 mpStartComponent = mpConnectionLineAnnotation->getStartComponent();
1753 mpStartRootComponent = mpStartComponent->getParentComponent() ? mpStartComponent->getRootParentComponent() : 0;
1754 if (mpStartComponent->isExpandableConnector() || (mpStartRootComponent && mpStartRootComponent->isExpandableConnector())) {
1755 mpStartExpandableConnectorTreeModel = new ExpandableConnectorTreeModel(this);
1756 mpStartExpandableConnectorTreeProxyModel = new ExpandableConnectorTreeProxyModel(this);
1757 mpStartExpandableConnectorTreeProxyModel->setDynamicSortFilter(true);
1758 mpStartExpandableConnectorTreeProxyModel->setSourceModel(mpStartExpandableConnectorTreeModel);
1759 mpStartExpandableConnectorTreeView = new ExpandableConnectorTreeView(this);
1760 mpStartExpandableConnectorTreeView->setModel(mpStartExpandableConnectorTreeProxyModel);
1761 mpStartExpandableConnectorTreeModel->createExpandableConnectorTreeItem(mpStartComponent->getRootParentComponent(), mpStartExpandableConnectorTreeModel->getRootExpandableConnectorTreeItem());
1762 mpStartExpandableConnectorTreeView->expandAll();
1763 mpStartExpandableConnectorTreeView->setSortingEnabled(true);
1764 mpStartExpandableConnectorTreeView->sortByColumn(0, Qt::AscendingOrder);
1765 connect(mpStartExpandableConnectorTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex))"2""currentChanged(QModelIndex,QModelIndex)", SLOT(startConnectorChanged(QModelIndex,QModelIndex))"1""startConnectorChanged(QModelIndex,QModelIndex)");
1766 }
1767 // End expandable connector treeview
1768 mpEndComponent = mpConnectionLineAnnotation->getEndComponent();
1769 mpEndRootComponent = mpEndComponent->getParentComponent() ? mpEndComponent->getRootParentComponent() : 0;
1770 mpEndExpandableConnectorTreeView = 0;
1771 if (mpEndComponent->isExpandableConnector() || (mpEndRootComponent && mpEndRootComponent->isExpandableConnector())) {
1772 mpEndExpandableConnectorTreeModel = new ExpandableConnectorTreeModel(this);
1773 mpEndExpandableConnectorTreeProxyModel = new ExpandableConnectorTreeProxyModel(this);
1774 mpEndExpandableConnectorTreeProxyModel->setDynamicSortFilter(true);
1775 mpEndExpandableConnectorTreeProxyModel->setSourceModel(mpEndExpandableConnectorTreeModel);
1776 mpEndExpandableConnectorTreeView = new ExpandableConnectorTreeView(this);
1777 mpEndExpandableConnectorTreeView->setModel(mpEndExpandableConnectorTreeProxyModel);
1778 mpEndExpandableConnectorTreeModel->createExpandableConnectorTreeItem(mpEndComponent->getRootParentComponent(), mpEndExpandableConnectorTreeModel->getRootExpandableConnectorTreeItem());
1779 mpEndExpandableConnectorTreeView->expandAll();
1780 mpEndExpandableConnectorTreeView->setSortingEnabled(true);
1781 mpEndExpandableConnectorTreeView->sortByColumn(0, Qt::AscendingOrder);
1782 connect(mpEndExpandableConnectorTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex))"2""currentChanged(QModelIndex,QModelIndex)", SLOT(endConnectorChanged(QModelIndex,QModelIndex))"1""endConnectorChanged(QModelIndex,QModelIndex)");
1783 }
1784 // Indexes Description text
1785 mpIndexesDescriptionLabel = new Label(tr("Specify the indexes below to connect to the parts of the connectors."));
1786 mpStartRootComponentSpinBox = 0;
1787 mpStartComponentSpinBox = 0;
1788 mpEndRootComponentSpinBox = 0;
1789 mpEndComponentSpinBox = 0;
1790 // only create normal start connector controls if start connector is not expandable
1791 if (!mpStartExpandableConnectorTreeView) {
1792 if (mpStartComponent->getParentComponent()) {
1793 mpStartRootComponentLabel = new Label(mpStartRootComponent->getName());
1794 if (mpStartRootComponent->isArray() && !mpStartRootComponent->isConnectorSizing()) {
1795 mpStartRootComponentSpinBox = createSpinBox(mpStartRootComponent->getComponentInfo()->getArrayIndex());
1796 }
1797 }
1798 mpStartComponentLabel = new Label(mpStartComponent->getName());
1799 if (mpStartComponent->isArray() && !mpStartComponent->isConnectorSizing()) {
1800 mpStartComponentSpinBox = createSpinBox(mpStartComponent->getComponentInfo()->getArrayIndex());
1801 }
1802 }
1803 // only create normal end connector controls if end connector is not expandable
1804 if (!mpEndExpandableConnectorTreeView) {
1805 if (mpEndComponent->getParentComponent()) {
1806 mpEndRootComponentLabel = new Label(mpEndRootComponent->getName());
1807 if (mpEndRootComponent->isArray() && !mpEndRootComponent->isConnectorSizing()) {
1808 mpEndRootComponentSpinBox = createSpinBox(mpEndRootComponent->getComponentInfo()->getArrayIndex());
1809 }
1810 }
1811 mpEndComponentLabel = new Label(mpEndComponent->getName());
1812 if (mpEndComponent->isArray() && !mpEndComponent->isConnectorSizing()) {
1813 mpEndComponentSpinBox = createSpinBox(mpEndComponent->getComponentInfo()->getArrayIndex());
1814 }
1815 }
1816 // Create the buttons
1817 mpOkButton = new QPushButton(Helper::ok);
1818 mpOkButton->setAutoDefault(true);
1819 connect(mpOkButton, SIGNAL(clicked())"2""clicked()", SLOT(createConnection())"1""createConnection()");
1820 mpCancelButton = new QPushButton(Helper::cancel);
1821 mpCancelButton->setAutoDefault(false);
1822 connect(mpCancelButton, SIGNAL(clicked())"2""clicked()", SLOT(reject())"1""reject()");
1823 // add buttons
1824 mpButtonBox = new QDialogButtonBox(Qt::Horizontal);
1825 mpButtonBox->addButton(mpOkButton, QDialogButtonBox::ActionRole);
1826 mpButtonBox->addButton(mpCancelButton, QDialogButtonBox::ActionRole);
1827 // Create a layout
1828 mpMainLayout = new QGridLayout;
1829 mpMainLayout->setAlignment(Qt::AlignTop);
1830 mpMainLayout->addWidget(mpHeading, 0, 0, 1, 2);
1831 mpMainLayout->addWidget(mpHorizontalLine, 1, 0, 1, 2);
1832 int row = 2;
1833 if (mpStartExpandableConnectorTreeView && mpEndExpandableConnectorTreeView) {
1834 QHBoxLayout *pExpandableTreeHorizontalLayout = new QHBoxLayout;
1835 pExpandableTreeHorizontalLayout->addWidget(mpStartExpandableConnectorTreeView);
1836 pExpandableTreeHorizontalLayout->addWidget(mpEndExpandableConnectorTreeView);
1837 mpMainLayout->addLayout(pExpandableTreeHorizontalLayout, row, 0, 1, 2);
1838 row++;
1839 } else if (mpStartExpandableConnectorTreeView) {
1840 mpMainLayout->addWidget(mpStartExpandableConnectorTreeView, row, 0, 1, 2);
1841 row++;
1842 } else if (mpEndExpandableConnectorTreeView) {
1843 mpMainLayout->addWidget(mpEndExpandableConnectorTreeView, row, 0, 1, 2);
1844 row++;
1845 }
1846 if (mpStartRootComponentSpinBox || mpStartComponentSpinBox || mpEndRootComponentSpinBox || mpEndComponentSpinBox) {
1847 mpMainLayout->addWidget(mpIndexesDescriptionLabel, row, 0, 1, 2);
1848 row++;
1849 }
1850 mpMainLayout->addWidget(new Label("connect("), row, 0);
1851 // connection start horizontal layout
1852 mpConnectionStartHorizontalLayout = new QHBoxLayout;
1853 mpConnectionStartHorizontalLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
1854 if (mpStartExpandableConnectorTreeView) {
1855 QModelIndex modelIndex = mpStartExpandableConnectorTreeModel->findFirstEnabledItem(mpStartExpandableConnectorTreeModel->getRootExpandableConnectorTreeItem());
1856 QModelIndex proxyIndex = mpStartExpandableConnectorTreeProxyModel->mapFromSource(modelIndex);
1857 startConnectorChanged(proxyIndex, QModelIndex());
1858 } else {
1859 if (mpStartComponent->getParentComponent()) {
1860 mpConnectionStartHorizontalLayout->addWidget(mpStartRootComponentLabel);
1861 if (mpStartRootComponent->isArray() && !mpStartRootComponent->isConnectorSizing()) {
1862 mpConnectionStartHorizontalLayout->addWidget(mpStartRootComponentSpinBox);
1863 }
1864 mpConnectionStartHorizontalLayout->addWidget(new Label("."));
1865 }
1866 mpConnectionStartHorizontalLayout->addWidget(mpStartComponentLabel);
1867 if (mpStartComponent->isArray() && !mpStartComponent->isConnectorSizing()) {
1868 mpConnectionStartHorizontalLayout->addWidget(mpStartComponentSpinBox);
1869 }
1870 mpConnectionStartHorizontalLayout->addWidget(new Label(","));
1871 }
1872 mpMainLayout->addLayout(mpConnectionStartHorizontalLayout, row, 1, 1, 1, Qt::AlignLeft);
1873 row++;
1874 mpMainLayout->addItem(new QSpacerItem(1, 1), row, 0);
1875 // connection end horizontal layout
1876 mpConnectionEndHorizontalLayout = new QHBoxLayout;
1877 mpConnectionEndHorizontalLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
1878 if (mpEndExpandableConnectorTreeView) {
1879 QModelIndex modelIndex = mpEndExpandableConnectorTreeModel->findFirstEnabledItem(mpEndExpandableConnectorTreeModel->getRootExpandableConnectorTreeItem());
1880 QModelIndex proxyIndex = mpEndExpandableConnectorTreeProxyModel->mapFromSource(modelIndex);
1881 endConnectorChanged(proxyIndex, QModelIndex());
1882 } else {
1883 if (mpEndComponent->getParentComponent()) {
1884 mpConnectionEndHorizontalLayout->addWidget(mpEndRootComponentLabel);
1885 if (mpEndRootComponent->isArray() && !mpEndRootComponent->isConnectorSizing()) {
1886 mpConnectionEndHorizontalLayout->addWidget(mpEndRootComponentSpinBox);
1887 }
1888 mpConnectionEndHorizontalLayout->addWidget(new Label("."));
1889 }
1890 mpConnectionEndHorizontalLayout->addWidget(mpEndComponentLabel);
1891 if (mpEndComponent->isArray() && !mpEndComponent->isConnectorSizing()) {
1892 mpConnectionEndHorizontalLayout->addWidget(mpEndComponentSpinBox);
1893 }
1894 mpConnectionEndHorizontalLayout->addWidget(new Label(");"));
1895 }
1896 mpMainLayout->addLayout(mpConnectionEndHorizontalLayout, row, 1, 1, 1, Qt::AlignLeft);
1897 row++;
1898 mpMainLayout->addWidget(mpButtonBox, row, 0, 1, 2, Qt::AlignRight);
1899 setLayout(mpMainLayout);
1900}
1901
1902/*!
1903 * \brief CreateConnectionDialog::createSpinBox
1904 * Creates a QSpinBox with arrayIndex limit.
1905 * \param arrayIndex
1906 * \return
1907 */
1908QSpinBox* CreateConnectionDialog::createSpinBox(QString arrayIndex)
1909{
1910 QSpinBox *pSpinBox = new QSpinBox;
1911 pSpinBox->setPrefix("[");
1912 pSpinBox->setSuffix("]");
1913 pSpinBox->setSpecialValueText("[:]");
1914 int intArrayIndex = arrayIndex.toInt();
1915 if (intArrayIndex > 0) {
1916 pSpinBox->setMaximum(intArrayIndex);
1917 }
1918 return pSpinBox;
1919}
1920
1921/*!
1922 * \brief CreateConnectionDialog::createComponentNameFromLayout
1923 * Creates a component name from the layout controls. Used when we have expandable connectors.
1924 * \param pLayout
1925 * \return
1926 */
1927QString CreateConnectionDialog::createComponentNameFromLayout(QHBoxLayout *pLayout)
1928{
1929 QString componentName;
1930 int i = 0;
1931 while (QLayoutItem* pLayoutItem = pLayout->itemAt(i)) {
1932 if (dynamic_cast<Label*>(pLayoutItem->widget())) {
1933 Label *pLabel = dynamic_cast<Label*>(pLayoutItem->widget());
1934 if (pLabel->text().compare(",") != 0 && pLabel->text().compare(");") != 0) { // "," & ");" are fixed labels so we skip them here.
1935 componentName += pLabel->text();
1936 }
1937 } else if (dynamic_cast<QSpinBox*>(pLayoutItem->widget())) {
1938 QSpinBox *pSpinBox = dynamic_cast<QSpinBox*>(pLayoutItem->widget());
1939 if (pSpinBox->value() > 0) {
1940 componentName += QString("[%1]").arg(pSpinBox->value());
1941 }
1942 } else if (dynamic_cast<QLineEdit*>(pLayoutItem->widget())) {
1943 QLineEdit *pLineEdit = dynamic_cast<QLineEdit*>(pLayoutItem->widget());
1944 if (pLineEdit->text().isEmpty()) {
1945 componentName += "ERROR";
1946 } else {
1947 componentName += pLineEdit->text();
1948 }
1949 }
1950 i++;
1951 }
1952 return componentName;
1953}
1954
1955/*!
1956 * \brief CreateConnectionDialog::getComponentConnectionName
1957 * Checks if component1 is array then make an array connection.
1958 * If component1 is an array with connectorSizing then connect to component2.
1959 * If component2 is also an array use it size to define the connectorSizing on component1.
1960 * \param pGraphicsView
1961 * \param pExpandableConnectorTreeView
1962 * \param pConnectionHorizontalLayout
1963 * \param pComponent1
1964 * \param pRootComponent1
1965 * \param pComponentSpinBox1
1966 * \param pRootComponentSpinBox1
1967 * \param pComponent2
1968 * \param pRootComponent2
1969 * \param pComponentSpinBox2
1970 * \param pRootComponentSpinBox2
1971 * \return
1972 */
1973QString CreateConnectionDialog::getComponentConnectionName(GraphicsView *pGraphicsView, ExpandableConnectorTreeView *pExpandableConnectorTreeView, QHBoxLayout *pConnectionHorizontalLayout,
1974 Component *pComponent1, Component *pRootComponent1, QSpinBox *pComponentSpinBox1, QSpinBox *pRootComponentSpinBox1,
1975 Component *pComponent2, Component *pRootComponent2, QSpinBox *pComponentSpinBox2, QSpinBox *pRootComponentSpinBox2)
1976{
1977 QString componentName;
1978 if (pExpandableConnectorTreeView) {
1979 componentName = CreateConnectionDialog::createComponentNameFromLayout(pConnectionHorizontalLayout);
1980 } else {
1981 /* if component1 is an array try to make an array connection.
1982 * Parent component can't be connectorSizing.
1983 */
1984 if (pComponent1->getParentComponent()) {
1985 componentName = pComponent1->getParentComponent()->getName();
1986 if (pRootComponent1->isArray()) {
1987 if (pRootComponentSpinBox1->value() > 0) {
1988 componentName += QString("[%1]").arg(pRootComponentSpinBox1->value());
1989 }
1990 }
1991 componentName += ".";
1992 }
1993 componentName += pComponent1->getName();
1994 // If the component1 is an array and not connectorSizing then try to make array connection.
1995 if (pComponent1->isArray() && !pComponent1->isConnectorSizing()) {
1996 if (pComponentSpinBox1->value() > 0) {
1997 componentName += QString("[%1]").arg(pComponentSpinBox1->value());
1998 }
1999 } else if (pComponent1->isConnectorSizing()) { // If the component1 is a connectorSizing then use the component2 to find the connectorSizing value.
2000 int numberOfComponentConnections = pGraphicsView->numberOfComponentConnections(pComponent1);
2001 if (pComponent2->isExpandableConnector()) {
2002 componentName += QString("[%1]").arg(++numberOfComponentConnections);
2003 } else if (pComponent2->getParentComponent() && pRootComponent2->isArray() && !pRootComponent2->isConnectorSizing()) {
2004 if (pRootComponentSpinBox2->value() > 0 || pRootComponent2->getArrayIndexAsNumber() == 0) {
2005 componentName += QString("[%1]").arg(++numberOfComponentConnections);
2006 } else {
2007 int endConnectionIndex = numberOfComponentConnections + pRootComponent2->getArrayIndexAsNumber();
2008 componentName += QString("[%1:%2]").arg(++numberOfComponentConnections).arg(endConnectionIndex);
2009 }
2010 } else if (pComponent2->isArray() && !pComponent2->isConnectorSizing()) {
2011 if (pComponentSpinBox2->value() > 0 || pComponent2->getArrayIndexAsNumber() == 0) {
2012 componentName += QString("[%1]").arg(++numberOfComponentConnections);
2013 } else {
2014 int endConnectionIndex = numberOfComponentConnections + pComponent2->getArrayIndexAsNumber();
2015 componentName += QString("[%1:%2]").arg(++numberOfComponentConnections).arg(endConnectionIndex);
2016 }
2017 }
2018 }
2019 }
2020 return componentName;
2021}
2022
2023/*!
2024 * \brief CreateConnectionDialog::startConnectorChanged
2025 * Updates the start component name in the connection.
2026 * \param current
2027 * \param previous
2028 */
2029void CreateConnectionDialog::startConnectorChanged(const QModelIndex &current, const QModelIndex &previous)
2030{
2031 Q_UNUSED(previous)(void)previous;;
2032
2033 while (QLayoutItem* pLayoutItem = mpConnectionStartHorizontalLayout->takeAt(0)) {
2034 if (pLayoutItem->widget()) {
2035 delete pLayoutItem->widget();
2036 }
2037 }
2038 mStartConnectorsList.clear();
2039
2040 QModelIndex currentIndex = mpStartExpandableConnectorTreeProxyModel->mapToSource(current);
2041 ExpandableConnectorTreeItem *pExpandableConnectorTreeItem = static_cast<ExpandableConnectorTreeItem*>(currentIndex.internalPointer());
2042 if (!pExpandableConnectorTreeItem) {
2043 return;
2044 }
2045
2046 mStartConnectorsList.append(pExpandableConnectorTreeItem);
2047 while (pExpandableConnectorTreeItem->parent() && pExpandableConnectorTreeItem->parent() != mpStartExpandableConnectorTreeModel->getRootExpandableConnectorTreeItem()) {
2048 pExpandableConnectorTreeItem = pExpandableConnectorTreeItem->parent();
2049 mStartConnectorsList.prepend(pExpandableConnectorTreeItem);
2050 }
2051
2052 for (int i = 0 ; i < mStartConnectorsList.size() ; i++) {
2053 if (mStartConnectorsList.at(i)->isArray()) {
2054 mpConnectionStartHorizontalLayout->addWidget(new Label(mStartConnectorsList.at(i)->getName()));
2055 mpConnectionStartHorizontalLayout->addWidget(createSpinBox(mStartConnectorsList.at(i)->getArrayIndex()));
2056 } else if (mStartConnectorsList.at(i)->isNewVariable()) {
2057 QLineEdit *pNewVariableTextBox = new QLineEdit;
2058 pNewVariableTextBox->setPlaceholderText(Helper::newVariable);
2059 mpConnectionStartHorizontalLayout->addWidget(pNewVariableTextBox);
2060 } else {
2061 mpConnectionStartHorizontalLayout->addWidget(new Label(mStartConnectorsList.at(i)->getName()));
2062 }
2063 if (i < mStartConnectorsList.size() - 1) {
2064 mpConnectionStartHorizontalLayout->addWidget(new Label("."));
2065 }
2066 }
2067 mpConnectionStartHorizontalLayout->addWidget(new Label(","));
2068}
2069
2070/*!
2071 * \brief CreateConnectionDialog::endConnectorChanged
2072 * Updates the end component name in the connection.
2073 * \param current
2074 * \param previous
2075 */
2076void CreateConnectionDialog::endConnectorChanged(const QModelIndex &current, const QModelIndex &previous)
2077{
2078 Q_UNUSED(previous)(void)previous;;
2079
2080 while (QLayoutItem* pLayoutItem = mpConnectionEndHorizontalLayout->takeAt(0)) {
2081 if (pLayoutItem->widget()) {
2082 delete pLayoutItem->widget();
2083 }
2084 }
2085 mEndConnectorsList.clear();
2086
2087 QModelIndex currentIndex = mpEndExpandableConnectorTreeProxyModel->mapToSource(current);
2088 ExpandableConnectorTreeItem *pExpandableConnectorTreeItem = static_cast<ExpandableConnectorTreeItem*>(currentIndex.internalPointer());
2089 if (!pExpandableConnectorTreeItem) {
2090 return;
2091 }
2092
2093 mEndConnectorsList.append(pExpandableConnectorTreeItem);
2094 while (pExpandableConnectorTreeItem->parent() && pExpandableConnectorTreeItem->parent() != mpEndExpandableConnectorTreeModel->getRootExpandableConnectorTreeItem()) {
2095 pExpandableConnectorTreeItem = pExpandableConnectorTreeItem->parent();
2096 mEndConnectorsList.prepend(pExpandableConnectorTreeItem);
2097 }
2098
2099 for (int i = 0 ; i < mEndConnectorsList.size() ; i++) {
2100 if (mEndConnectorsList.at(i)->isArray()) {
2101 mpConnectionEndHorizontalLayout->addWidget(new Label(mEndConnectorsList.at(i)->getName()));
2102 mpConnectionEndHorizontalLayout->addWidget(createSpinBox(mEndConnectorsList.at(i)->getArrayIndex()));
2103 } else if (mEndConnectorsList.at(i)->isNewVariable()) {
2104 QLineEdit *pNewVariableTextBox = new QLineEdit;
2105 pNewVariableTextBox->setPlaceholderText(Helper::newVariable);
2106 mpConnectionEndHorizontalLayout->addWidget(pNewVariableTextBox);
2107 } else {
2108 mpConnectionEndHorizontalLayout->addWidget(new Label(mEndConnectorsList.at(i)->getName()));
2109 }
2110 if (i < mEndConnectorsList.size() - 1) {
2111 mpConnectionEndHorizontalLayout->addWidget(new Label("."));
2112 }
2113 }
2114 mpConnectionEndHorizontalLayout->addWidget(new Label(");"));
2115}
2116
2117/*!
2118 * \brief CreateConnectionDialog::createConnection
2119 * Slot activated when mpOkButton clicked SIGNAL is raised. Creates an array connection.
2120 */
2121void CreateConnectionDialog::createConnection()
2122{
2123 // set start component name
2124 QString startComponentName = CreateConnectionDialog::getComponentConnectionName(mpGraphicsView, mpStartExpandableConnectorTreeView, mpConnectionStartHorizontalLayout,
2125 mpStartComponent, mpStartRootComponent, mpStartComponentSpinBox, mpStartRootComponentSpinBox,
2126 mpEndComponent, mpEndRootComponent, mpEndComponentSpinBox, mpEndRootComponentSpinBox);
2127 // set end component name
2128 QString endComponentName = CreateConnectionDialog::getComponentConnectionName(mpGraphicsView, mpEndExpandableConnectorTreeView, mpConnectionEndHorizontalLayout,
2129 mpEndComponent, mpEndRootComponent, mpEndComponentSpinBox, mpEndRootComponentSpinBox,
2130 mpStartComponent, mpStartRootComponent, mpStartComponentSpinBox, mpStartRootComponentSpinBox);
2131 mpConnectionLineAnnotation->setStartComponentName(startComponentName);
2132 mpConnectionLineAnnotation->setEndComponentName(endComponentName);
2133 mpGraphicsView->getModelWidget()->getUndoStack()->push(new AddConnectionCommand(mpConnectionLineAnnotation, true));
2134 mpGraphicsView->getModelWidget()->getLibraryTreeItem()->emitConnectionAdded(mpConnectionLineAnnotation);
2135 mpGraphicsView->getModelWidget()->updateModelText();
2136 accept();
2137}
2138
2139/*!
2140 * \class CreateOrEditTransitionDialog
2141 * \brief A dialog interface for creating and editing transitions.
2142 */
2143/*!
2144 * \brief CreateOrEditTransitionDialog::CreateOrEditTransitionDialog
2145 * \param pGraphicsView
2146 * \param pTransitionLineAnnotation
2147 * \param editCase
2148 * \param pParent
2149 */
2150CreateOrEditTransitionDialog::CreateOrEditTransitionDialog(GraphicsView *pGraphicsView, LineAnnotation *pTransitionLineAnnotation,
2151 bool editCase, QWidget *pParent)
2152 : QDialog(pParent), mpGraphicsView(pGraphicsView), mpTransitionLineAnnotation(pTransitionLineAnnotation), mEditCase(editCase)
2153{
2154 setAttribute(Qt::WA_DeleteOnClose);
2155 // heading
2156 if (mEditCase) {
2157 setWindowTitle(QString("%1 - %2").arg(Helper::applicationName).arg(Helper::editTransition));
2158 mpHeading = Utilities::getHeadingLabel(Helper::editTransition);
2159 } else {
2160 setWindowTitle(QString("%1 - %2").arg(Helper::applicationName).arg(Helper::createTransition));
2161 mpHeading = Utilities::getHeadingLabel(Helper::createTransition);
2162 }
2163 // horizontal line
2164 mpHorizontalLine = Utilities::getHeadingLine();
2165 // properties groupbox
2166 mpPropertiesGroupBox = new QGroupBox(Helper::properties);
2167 // condition
2168 mpConditionLabel = new Label(Helper::condition);
2169 mpConditionTextBox = new QLineEdit(mpTransitionLineAnnotation->getCondition());
2170 // immediate
2171 mpImmediateCheckBox = new QCheckBox(Helper::immediate);
2172 mpImmediateCheckBox->setChecked(mpTransitionLineAnnotation->getImmediate());
2173 // reset
2174 mpResetCheckBox = new QCheckBox(Helper::reset);
2175 mpResetCheckBox->setChecked(mpTransitionLineAnnotation->getReset());
2176 // synchronize
2177 mpSynchronizeCheckBox = new QCheckBox(Helper::synchronize);
2178 mpSynchronizeCheckBox->setChecked(mpTransitionLineAnnotation->getSynchronize());
2179 // priority
2180 mpPriorityLabel = new Label(Helper::priority);
2181 mpPrioritySpinBox = new QSpinBox;
2182 mpPrioritySpinBox->setMinimum(1);
2183 mpPrioritySpinBox->setValue(mpTransitionLineAnnotation->getPriority());
2184 // Create the buttons
2185 mpOkButton = new QPushButton(Helper::ok);
2186 mpOkButton->setAutoDefault(true);
2187 if (mpGraphicsView->getModelWidget()->getLibraryTreeItem()->isSystemLibrary() || mpGraphicsView->isVisualizationView()) {
2188 mpOkButton->setDisabled(true);
2189 }
2190 connect(mpOkButton, SIGNAL(clicked())"2""clicked()", SLOT(createOrEditTransition())"1""createOrEditTransition()");
2191 mpCancelButton = new QPushButton(Helper::cancel);
2192 mpCancelButton->setAutoDefault(false);
2193 connect(mpCancelButton, SIGNAL(clicked())"2""clicked()", SLOT(reject())"1""reject()");
2194 // add buttons
2195 mpButtonBox = new QDialogButtonBox(Qt::Horizontal);
2196 mpButtonBox->addButton(mpOkButton, QDialogButtonBox::ActionRole);
2197 mpButtonBox->addButton(mpCancelButton, QDialogButtonBox::ActionRole);
2198 // properties groupbox layout
2199 QGridLayout *pPropertiesGridLayout = new QGridLayout;
2200 pPropertiesGridLayout->addWidget(mpConditionLabel, 0, 0);
2201 pPropertiesGridLayout->addWidget(mpConditionTextBox, 0, 1);
2202 pPropertiesGridLayout->addWidget(mpImmediateCheckBox, 1, 1);
2203 pPropertiesGridLayout->addWidget(mpResetCheckBox, 2, 1);
2204 pPropertiesGridLayout->addWidget(mpSynchronizeCheckBox, 3, 1);
2205 pPropertiesGridLayout->addWidget(mpPriorityLabel, 4, 0);
2206 pPropertiesGridLayout->addWidget(mpPrioritySpinBox, 4, 1);
2207 mpPropertiesGroupBox->setLayout(pPropertiesGridLayout);
2208 // main layout
2209 QGridLayout *pMainGridLayout = new QGridLayout;
2210 pMainGridLayout->setAlignment(Qt::AlignTop);
2211 pMainGridLayout->addWidget(mpHeading, 0, 0);
2212 pMainGridLayout->addWidget(mpHorizontalLine, 1, 0);
2213 pMainGridLayout->addWidget(mpPropertiesGroupBox, 2, 0);
2214 pMainGridLayout->addWidget(mpButtonBox, 3, 0, Qt::AlignRight);
2215 setLayout(pMainGridLayout);
2216}
2217
2218/*!
2219 * \brief CreateOrEditTransitionDialog::createOrEditTransition
2220 * Slot activated when mpOkButton clicked SIGNAL is raised. Creates a transition.
2221 */
2222void CreateOrEditTransitionDialog::createOrEditTransition()
2223{
2224 if (mpConditionTextBox->text().isEmpty()) {
2225 QMessageBox::critical(mpGraphicsView, QString("%1 - %2").arg(Helper::applicationName).arg(Helper::error),
2226 GUIMessages::getMessage(GUIMessages::INVALID_TRANSITION_CONDITION), Helper::ok);
2227 mpConditionTextBox->setFocus(Qt::ActiveWindowFocusReason);
2228 return;
2229 }
2230 QString oldCondition = mpTransitionLineAnnotation->getCondition();
2231 mpTransitionLineAnnotation->setCondition(mpConditionTextBox->text());
2232 bool oldImmediate = mpTransitionLineAnnotation->getImmediate();
2233 mpTransitionLineAnnotation->setImmediate(mpImmediateCheckBox->isChecked());
2234 bool oldReset = mpTransitionLineAnnotation->getReset();
2235 mpTransitionLineAnnotation->setReset(mpResetCheckBox->isChecked());
2236 bool oldSynchronize = mpTransitionLineAnnotation->getSynchronize();
2237 mpTransitionLineAnnotation->setSynchronize(mpSynchronizeCheckBox->isChecked());
2238 int oldPriority = mpTransitionLineAnnotation->getPriority();
2239 mpTransitionLineAnnotation->setPriority(mpPrioritySpinBox->value());
2240 mpTransitionLineAnnotation->getTextAnnotation()->setVisible(true);
2241 if (mEditCase) {
2242 mpGraphicsView->getModelWidget()->getUndoStack()->push(new UpdateTransitionCommand(mpTransitionLineAnnotation, oldCondition, oldImmediate,
2243 oldReset, oldSynchronize, oldPriority,
2244 mpTransitionLineAnnotation->getOMCShapeAnnotation(),
2245 mpConditionTextBox->text(),
2246 mpImmediateCheckBox->isChecked(),
2247 mpResetCheckBox->isChecked(),
2248 mpSynchronizeCheckBox->isChecked(),
2249 mpPrioritySpinBox->value(),
2250 mpTransitionLineAnnotation->getOMCShapeAnnotation()));
2251 } else {
2252 mpGraphicsView->getModelWidget()->getUndoStack()->push(new AddTransitionCommand(mpTransitionLineAnnotation, true));
2253 //mpGraphicsView->getModelWidget()->getLibraryTreeItem()->emitConnectionAdded(mpTransitionLineAnnotation);
2254 }
2255 mpGraphicsView->getModelWidget()->updateModelText();
2256 accept();
2257}
2258
2259void LineAnnotation::setProperties(const QString& condition, const bool immediate, const bool rest, const bool synchronize, const int priority)
2260{
2261 setCondition(condition);
2262 setImmediate(immediate);
2263 setReset(rest);
2264 setSynchronize(synchronize);
2265 setPriority(priority);
2266 getTextAnnotation()->setTextString("%condition");
2267}
2268
2269void LineAnnotation::updateTransistion(const QString& condition, const bool immediate, const bool rest, const bool synchronize, const int priority)
2270{
2271 getTextAnnotation()->updateTextString();
2272 updateTransitionTextPosition();
2273 updateTransitionAnnotation(condition, immediate, rest, synchronize, priority);
2274 updateToolTip();
2275}