Bug Summary

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