• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

umbrello/umbrello

  • sources
  • kde-4.12
  • kdesdk
  • umbrello
  • umbrello
  • widgets
associationline.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * This program is free software; you can redistribute it and/or modify *
3  * it under the terms of the GNU General Public License as published by *
4  * the Free Software Foundation; either version 2 of the License, or *
5  * (at your option) any later version. *
6  * *
7  * copyright (C) 2002-2013 *
8  * Umbrello UML Modeller Authors <umbrello-devel@kde.org> *
9  ***************************************************************************/
10 
11 // own header
12 #include "associationline.h"
13 
14 // application includes
15 #include "associationwidget.h"
16 #include "debug_utils.h"
17 #include "umlwidget.h"
18 
19 // qt includes
20 #include <QDomDocument>
21 #include <QPainter>
22 
23 // system includes
24 #include <cstdlib>
25 #include <cmath>
26 
27 DEBUG_REGISTER_DISABLED(AssociationLine)
28 
29 // Initialize static variables.
30 const qreal AssociationLine::Delta = 5;
31 const qreal AssociationLine::SelectedPointDiameter = 4;
32 const qreal AssociationLine::SelfAssociationMinimumHeight = 30;
33 
38 AssociationLine::AssociationLine(AssociationWidget *association)
39  : QGraphicsObject(association),
40  m_associationWidget(association),
41  m_activePointIndex(-1),
42  m_activeSegmentIndex(-1),
43  m_startSymbol(0),
44  m_endSymbol(0),
45  m_subsetSymbol(0),
46  m_collaborationLineItem(0),
47  m_collaborationLineHead(0),
48  m_layout(Polyline)
49 {
50  Q_ASSERT(association);
51  setFlag(QGraphicsLineItem::ItemIsSelectable);
52  setAcceptHoverEvents(true);
53  setZValue(3);
54 }
55 
59 AssociationLine::~AssociationLine()
60 {
61 }
62 
67 QPointF AssociationLine::point(int index) const
68 {
69  if ((index < 0) | (index >= m_points.size())) {
70  uWarning() << "Index " << index << " out of range [0.." << m_points.size() - 1 << "].";
71  return QPointF(-1.0, -1.0);
72  }
73  return m_points.at(index);
74 }
75 
79 bool AssociationLine::setPoint(int index, const QPointF &point)
80 {
81  if ((index < 0) | (index >= m_points.size())) {
82  uWarning() << "Index " << index << " out of range [0.." << m_points.size() - 1 << "].";
83  return false;
84  }
85  if (m_points.at(index) == point) {
86  return false; // nothing to change
87  }
88  prepareGeometryChange();
89  m_points[index] = point;
90  alignSymbols();
91  return true;
92 }
93 
97 QPointF AssociationLine::startPoint() const
98 {
99  return m_points.at(0);
100 }
101 
105 QPointF AssociationLine::endPoint() const
106 {
107  return m_points.at(m_points.size()-1);
108 }
109 
114 void AssociationLine::insertPoint(int index, const QPointF &point)
115 {
116  prepareGeometryChange();
117  m_points.insert(index, point);
118  alignSymbols();
119 }
120 
125 void AssociationLine::removePoint(int index)
126 {
127  prepareGeometryChange();
128  m_points.remove(index);
129  alignSymbols();
130 }
131 
137 int AssociationLine::count() const
138 {
139  return m_points.size();
140 }
141 
145 void AssociationLine::cleanup()
146 {
147  if (!m_points.isEmpty()) {
148  prepareGeometryChange();
149  m_points.clear();
150  alignSymbols();
151  }
152 }
153 
161 void AssociationLine::optimizeLinePoints()
162 {
163  int i = 1;
164  prepareGeometryChange();
165  while (i < m_points.size()) {
166  if (m_points.at(i) == m_points.at(i-1)) {
167  m_points.remove(i);
168  }
169  else {
170  ++i;
171  }
172  }
173  alignSymbols();
174 }
175 
185 int AssociationLine::closestPointIndex(const QPointF &point, qreal delta) const
186 {
187  for(int i = 0; i < m_points.size(); ++i) {
188  const QPointF& linePoint = m_points.at(i);
189  // Apply distance formula to see point closeness.
190  qreal deltaXSquare = (point.x() - linePoint.x()) * (point.x() - linePoint.x());
191  qreal deltaYSquare = (point.y() - linePoint.y()) * (point.y() - linePoint.y());
192 
193  qreal lhs = deltaXSquare + deltaYSquare;
194  qreal rhs = delta * delta;
195 
196  if (lhs <= rhs) {
197  return i;
198  }
199  }
200  return -1;
201 }
202 
211 int AssociationLine::closestSegmentIndex(const QPointF &point, qreal delta) const
212 {
213  QPainterPathStroker stroker;
214  stroker.setWidth(delta);
215 
216  for(int i = 1; i < m_points.size(); ++i) {
217  QLineF segment(m_points[i-1], m_points[i]);
218 
219  QPainterPath path;
220  path.moveTo(segment.p1());
221  path.lineTo(segment.p2());
222 
223  path = stroker.createStroke(path);
224 
225  if (path.contains(point)) {
226  return i-1;
227  }
228  }
229  return -1;
230 }
231 
235 bool AssociationLine::isEndPointIndex(int index) const
236 {
237  const int size = m_points.size();
238  Q_ASSERT(index >= 0 && index < size);
239 
240  return (index == 0 || index == (size - 1));
241 }
242 
246 bool AssociationLine::isEndSegmentIndex(int index) const
247 {
248  // num of seg = num of points - 1
249  const int size = m_points.size() - 1;
250  Q_ASSERT(index >= 0 && index < size);
251 
252  return (index == 0 || index == (size - 1));
253 }
254 
258 bool AssociationLine::setEndPoints(const QPointF &start, const QPointF &end)
259 {
260  const int size = m_points.size();
261 
262  prepareGeometryChange();
263 
264  if (size == 0) {
265  m_points.insert(0, start);
266  m_points.insert(1, end);
267  }
268  else if (size == 1) {
269  m_points[0] = start;
270  m_points.insert(1, end);
271  }
272  else {
273  m_points[0] = start;
274  m_points[size-1] = end;
275  }
276 
277  alignSymbols();
278  return true;
279 }
280 
284 void AssociationLine::dumpPoints()
285 {
286  for (int i = 1; i < m_points.size(); ++i) {
287  QPointF p = m_points.at(i);
288  DEBUG(DBG_SRC) << i << ". point x:" << p.x() << " / y:" << p.y();
289  }
290 }
291 
295 bool AssociationLine::loadFromXMI(QDomElement &qElement)
296 {
297  QString layout = qElement.attribute("layout", "polyline");
298  m_layout = fromString(layout);
299 
300  QDomNode node = qElement.firstChild();
301 
302  m_points.clear();
303 
304  QDomElement startElement = node.toElement();
305  if(startElement.isNull() || startElement.tagName() != "startpoint") {
306  return false;
307  }
308  QString x = startElement.attribute("startx", "0");
309  qreal nX = x.toFloat();
310  QString y = startElement.attribute("starty", "0");
311  qreal nY = y.toFloat();
312  QPointF startPoint(nX, nY);
313 
314  node = startElement.nextSibling();
315  QDomElement endElement = node.toElement();
316  if(endElement.isNull() || endElement.tagName() != "endpoint") {
317  return false;
318  }
319  x = endElement.attribute("endx", "0");
320  nX = x.toFloat();
321  y = endElement.attribute("endy", "0");
322  nY = y.toFloat();
323  QPointF endPoint(nX, nY);
324  setEndPoints(startPoint, endPoint);
325  QPointF point;
326  node = endElement.nextSibling();
327  QDomElement element = node.toElement();
328  int i = 1;
329  while(!element.isNull()) {
330  if(element.tagName() == "point") {
331  x = element.attribute("x", "0");
332  y = element.attribute("y", "0");
333  point.setX(x.toFloat());
334  point.setY(y.toFloat());
335  insertPoint(i++, point);
336  }
337  node = element.nextSibling();
338  element = node.toElement();
339  }
340 
341  return true;
342 }
343 
348 void AssociationLine::saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
349 {
350  QPointF point = m_associationWidget->mapToScene(startPoint());
351  QDomElement lineElement = qDoc.createElement("linepath");
352  lineElement.setAttribute("layout", toString(m_layout));
353  QDomElement startElement = qDoc.createElement("startpoint");
354  startElement.setAttribute("startx", point.x());
355  startElement.setAttribute("starty", point.y());
356  lineElement.appendChild(startElement);
357  QDomElement endElement = qDoc.createElement("endpoint");
358  point = m_associationWidget->mapToScene(endPoint());
359  endElement.setAttribute("endx", point.x());
360  endElement.setAttribute("endy", point.y());
361  lineElement.appendChild(endElement);
362  for(int i = 1; i < count()-1; ++i) {
363  QDomElement pointElement = qDoc.createElement("point");
364  point = m_associationWidget->mapToScene(this->point(i));
365  pointElement.setAttribute("x", point.x());
366  pointElement.setAttribute("y", point.y());
367  lineElement.appendChild(pointElement);
368  }
369  qElement.appendChild(lineElement);
370 }
371 
375 QBrush AssociationLine::brush() const
376 {
377  QBrush brush(Qt::SolidPattern);
378  Uml::AssociationType::Enum type = m_associationWidget->associationType();
379  if (type == Uml::AssociationType::Aggregation ||
380  type == Uml::AssociationType::Generalization ||
381  type == Uml::AssociationType::Realization) {
382  brush.setColor(Qt::white);
383  }
384  if (type == Uml::AssociationType::Composition) {
385  brush.setColor(m_associationWidget->lineColor());
386  }
387  return brush;
388 }
389 
393 QPen AssociationLine::pen() const
394 {
395  QPen pen(m_associationWidget->lineColor(),
396  m_associationWidget->lineWidth(),
397  Qt::SolidLine,
398  Qt::RoundCap,
399  Qt::RoundJoin);
400  Uml::AssociationType::Enum type = m_associationWidget->associationType();
401  if (type == Uml::AssociationType::Dependency ||
402  type == Uml::AssociationType::Realization ||
403  type == Uml::AssociationType::Anchor) {
404  pen.setStyle(Qt::DashLine);
405  }
406  return pen;
407 }
408 
413 void AssociationLine::calculateInitialEndPoints()
414 {
415  if (m_associationWidget->isSelf() && count() < 4) {
416  for (int i = count(); i < 4; ++i) {
417  insertPoint(i, QPointF());
418  }
419  UMLWidget *wid = m_associationWidget->widgetForRole(Uml::RoleType::B);
420  if (!wid) {
421  uError() << "AssociationWidget is partially constructed."
422  "UMLWidget for role A is null.";
423  return;
424  }
425  const QRectF rect = m_associationWidget->mapFromScene(
426  mapToScene(wid->rect()).boundingRect()).boundingRect();
427 
428  qreal l = rect.left() + .25 * rect.width();
429  qreal r = rect.left() + .75 * rect.width();
430  bool drawAbove = rect.top() >= SelfAssociationMinimumHeight;
431  qreal y = drawAbove ? rect.top() : rect.bottom();
432  qreal yOffset = SelfAssociationMinimumHeight;
433  if (drawAbove) {
434  yOffset *= -1.0;
435  }
436 
437  setPoint(0, QPointF(l, y));
438  setPoint(1, QPointF(l, y + yOffset));
439  setPoint(2, QPointF(r, y + yOffset));
440  setPoint(3, QPointF(r, y));
441  } else if (!m_associationWidget->isSelf() && count() < 2) {
442  setEndPoints(QPointF(), QPointF());
443  }
444 }
445 
452 void AssociationLine::reconstructSymbols()
453 {
454  switch( m_associationWidget->associationType() ) {
455  case Uml::AssociationType::State:
456  case Uml::AssociationType::Activity:
457  case Uml::AssociationType::Exception:
458  case Uml::AssociationType::UniAssociation:
459  case Uml::AssociationType::Dependency:
460  setStartSymbol(Symbol::None);
461  setEndSymbol(Symbol::OpenArrow);
462  removeSubsetSymbol();
463  removeCollaborationLine();
464  break;
465 
466  case Uml::AssociationType::Relationship:
467  setStartSymbol(Symbol::None);
468  setEndSymbol(Symbol::CrowFeet);
469  removeSubsetSymbol();
470  removeCollaborationLine();
471  break;
472 
473  case Uml::AssociationType::Generalization:
474  case Uml::AssociationType::Realization:
475  setStartSymbol(Symbol::None);
476  setEndSymbol(Symbol::ClosedArrow);
477  removeSubsetSymbol();
478  removeCollaborationLine();
479  break;
480 
481  case Uml::AssociationType::Composition:
482  case Uml::AssociationType::Aggregation:
483  setStartSymbol(Symbol::Diamond);
484  setEndSymbol(Symbol::None);
485  removeSubsetSymbol();
486  removeCollaborationLine();
487  break;
488 
489  case Uml::AssociationType::Containment:
490  setStartSymbol(Symbol::Circle);
491  setEndSymbol(Symbol::None);
492  removeSubsetSymbol();
493  removeCollaborationLine();
494  break;
495 
496  case Uml::AssociationType::Child2Category:
497  setStartSymbol(Symbol::None);
498  setEndSymbol(Symbol::None);
499  createSubsetSymbol();
500  removeCollaborationLine();
501  break;
502 
503  case Uml::AssociationType::Coll_Message:
504  case Uml::AssociationType::Coll_Message_Self:
505  setStartSymbol(Symbol::None);
506  setEndSymbol(Symbol::None);
507  removeSubsetSymbol();
508  createCollaborationLine();
509  break;
510 
511  default:
512  break;
513  }
514  alignSymbols();
515 }
516 
522 void AssociationLine::setStartSymbol(Symbol::SymbolType symbolType)
523 {
524  Q_ASSERT(symbolType != Symbol::Count);
525  if (symbolType == Symbol::None) {
526  delete m_startSymbol;
527  m_startSymbol = 0;
528  return;
529  }
530 
531  if (m_startSymbol) {
532  m_startSymbol->setSymbolType(symbolType);
533  }
534  else {
535  m_startSymbol = new Symbol(symbolType, m_associationWidget);
536  }
537  m_startSymbol->setPen(pen());
538  m_startSymbol->setBrush(brush());
539 }
540 
546 void AssociationLine::setEndSymbol(Symbol::SymbolType symbolType)
547 {
548  Q_ASSERT(symbolType != Symbol::Count);
549  if (symbolType == Symbol::None) {
550  delete m_endSymbol;
551  m_endSymbol = 0;
552  return;
553  }
554 
555  if (m_endSymbol) {
556  m_endSymbol->setSymbolType(symbolType);
557  }
558  else {
559  m_endSymbol = new Symbol(symbolType, m_associationWidget);
560  }
561  m_endSymbol->setPen(pen());
562  m_endSymbol->setBrush(brush());
563 }
564 
568 void AssociationLine::createSubsetSymbol()
569 {
570  delete m_subsetSymbol; // recreate
571  m_subsetSymbol = new Symbol(Symbol::Subset, m_associationWidget);
572  m_subsetSymbol->setPen(pen());
573  m_subsetSymbol->setBrush(brush());
574 }
575 
579 void AssociationLine::removeSubsetSymbol()
580 {
581  delete m_subsetSymbol;
582  m_subsetSymbol = 0;
583 }
584 
588 void AssociationLine::createCollaborationLine()
589 {
590  const QPen p = pen();
591 
592  // recreate
593  delete m_collaborationLineItem;
594  delete m_collaborationLineHead;
595 
596  m_collaborationLineItem = new QGraphicsLineItem(m_associationWidget);
597  m_collaborationLineItem->setPen(p);
598 
599  m_collaborationLineHead = new Symbol(Symbol::OpenArrow, m_associationWidget);
600  m_collaborationLineHead->setPen(p);
601 }
602 
606 void AssociationLine::removeCollaborationLine()
607 {
608  delete m_collaborationLineItem;
609  m_collaborationLineItem = 0;
610 
611  delete m_collaborationLineHead;
612  m_collaborationLineHead = 0;
613 }
614 
620 void AssociationLine::alignSymbols()
621 {
622  const int sz = m_points.size();
623  if (sz < 2) {
624  // cannot align if there is no line (one line = 2 points)
625  return;
626  }
627 
628  QList<QPolygonF> polygons = path().toSubpathPolygons();
629 
630  if (m_startSymbol) {
631  QPolygonF firstLine = polygons.first();
632  QLineF segment(firstLine.at(1), firstLine.at(0));
633  m_startSymbol->alignTo(segment);
634  }
635 
636  if (m_endSymbol) {
637  QPolygonF lastLine = polygons.last();
638  int maxIndex = lastLine.size();
639  QLineF segment(lastLine.at(maxIndex-2), lastLine.at(maxIndex-1));
640  m_endSymbol->alignTo(segment);
641  }
642 
643  if (m_subsetSymbol) {
644  QPointF p1 = path().pointAtPercent(0.4);
645  QPointF p2 = path().pointAtPercent(0.5);
646  QLineF segment(p1, p2);
647  m_subsetSymbol->alignTo(segment);
648  }
649 
650  if (m_collaborationLineItem) {
651  const qreal distance = 10;
652  const int midSegmentIndex = (sz - 1) / 2;
653 
654  const QPointF a = m_points.at(midSegmentIndex);
655  const QPointF b = m_points.at(midSegmentIndex + 1);
656 
657  const QPointF p1 = (a + b) / 2.0;
658  const QPointF p2 = (p1 + b) / 2.0;
659 
660  // Reversed line as we want normal in opposite direction.
661  QLineF segment(p2, p1);
662  QLineF normal = segment.normalVector().unitVector();
663  normal.setLength(distance);
664 
665  QLineF actualLine;
666  actualLine.setP2(normal.p2());
667 
668  normal.translate(p1 - p2);
669  actualLine.setP1(normal.p2());
670 
671  m_collaborationLineItem->setLine(actualLine);
672  m_collaborationLineHead->alignTo(actualLine);
673  }
674 }
675 
679 QPainterPath AssociationLine::path() const
680 {
681  if (m_points.count() > 0) {
682  QPainterPath path;
683  switch (m_layout) {
684  case Direct:
685  path.moveTo(m_points.first());
686  path.lineTo(m_points.last());
687  break;
688 
689  case Spline:
690  path = createBezierCurve(m_points);
691  break;
692 
693  case Orthogonal:
694  path = createOrthogonalPath(m_points);
695  break;
696 
697  case Polyline:
698  default:
699  QPolygonF polygon(m_points);
700  path.addPolygon(polygon);
701  break;
702  }
703  return path;
704  }
705  else {
706  return QPainterPath();
707  }
708 }
709 
715 QRectF AssociationLine::boundingRect() const
716 {
717  QPolygonF polygon(m_points);
718  QRectF rect = polygon.boundingRect();
719  const qreal margin(5.0);
720  rect.adjust(-margin, -margin, margin, margin);
721  return rect;
722 }
723 
727 QPainterPath AssociationLine::shape() const
728 {
729  QPainterPathStroker stroker;
730  stroker.setWidth(qMax<qreal>(2*SelectedPointDiameter, pen().widthF()) + 2.0); // allow delta region
731  stroker.setCapStyle(Qt::FlatCap);
732  return stroker.createStroke(path());
733 }
734 
738 QString AssociationLine::toString(LayoutType layout)
739 {
740  return QLatin1String(ENUM_NAME(AssociationLine, LayoutType, layout));
741 }
742 
746 AssociationLine::LayoutType AssociationLine::fromString(const QString &layout)
747 {
748  if (layout == "Direct")
749  return Direct;
750  if (layout == "Spline")
751  return Spline;
752  if (layout == "Orthogonal")
753  return Orthogonal;
754  return Polyline;
755 }
756 
761 AssociationLine::LayoutType AssociationLine::layout() const
762 {
763  return m_layout;
764 }
765 
770 void AssociationLine::setLayout(LayoutType layout)
771 {
772  prepareGeometryChange();
773  m_layout = layout;
774  DEBUG(DBG_SRC) << "new layout = " << toString(m_layout);
775  if (m_layout == Spline) {
776  createSplinePoints();
777  }
778  alignSymbols();
779 }
780 
786 void AssociationLine::createSplinePoints()
787 {
788  if (m_points.size() == 2) { // create two points
789  QPointF p1 = m_points.first(); // start point
790  QPointF p2 = m_points.last(); // end point
791  qreal dx = p2.x() - p1.x();
792  qreal dy = p2.y() - p1.y();
793  qreal oneThirdX = 0.33 * dx;
794  qreal oneThirdY = 0.33 * dy;
795  QPointF c1(p1.x() + oneThirdX, // control point 1
796  p1.y() - oneThirdY);
797  QPointF c2(p2.x() - oneThirdX, // control point 2
798  p2.y() + oneThirdY);
799  insertPoint(1, c1);
800  insertPoint(2, c2);
801  }
802  if (m_points.size() == 3) { // create one point
803  // insertPoint(1 or 2, );
804  // Note: For now we use a quadratic Bezier curve in createBezierCurve(...).
805  }
806 }
807 
813 QPainterPath AssociationLine::createBezierCurve(QVector<QPointF> points)
814 {
815  QPainterPath path;
816  if (points.size() > 3) { // cubic Bezier curve(s)
817  path.moveTo(points.at(0));
818  int i = 1;
819  while (i + 2 < points.size()) {
820  path.cubicTo(points.at(i), points.at(i+1), points.at(i+2));
821  i += 3;
822  }
823  while (i < points.size()) { // draw a line if points are not modulo 3
824  path.lineTo(points.at(i));
825  ++i;
826  }
827  }
828  else {
829  if (points.size() == 3) { // quadratic Bezier curve
830  path.moveTo(points.at(0));
831  path.quadTo(points.at(1), points.at(2));
832  }
833  else { // should not be reached
834  QPolygonF polygon(points);
835  path.addPolygon(polygon);
836  }
837  }
838  return path;
839 }
840 
847 QPainterPath AssociationLine::createOrthogonalPath(QVector<QPointF> points)
848 {
849  QPainterPath path;
850  if (points.size() > 1) {
851  QPointF start = points.first();
852  QPointF end = points.last();
853  qreal deltaX = abs(start.x() - end.x());
854  qreal deltaY = abs(start.y() - end.y());
855  // DEBUG("AssociationLine") << "start=" << start << " / end=" << end
856  // << " / deltaX=" << deltaX << " / deltaY=" << deltaY;
857  QVector<QPointF> vector;
858  for (int i = 0; i < points.size() - 1; ++i) {
859  QPointF curr = points.at(i);
860  QPointF next = points.at(i+1);
861  QPointF center = (next + curr)/2.0;
862 
863  vector.append(curr);
864  if (deltaX < deltaY) {
865  // go vertical first
866  vector.append(QPointF(curr.x(), center.y()));
867  vector.append(QPointF(next.x(), center.y()));
868  }
869  else {
870  // go horizontal first
871  vector.append(QPointF(center.x(), curr.y()));
872  vector.append(QPointF(center.x(), next.y()));
873  }
874  vector.append(next);
875  }
876 
877  QPolygonF rectLine(vector);
878  path.addPolygon(rectLine);
879  }
880  else {
881  QPolygonF polygon(points);
882  path.addPolygon(polygon);
883  }
884  return path;
885 }
886 
891 void AssociationLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
892 {
893  Q_UNUSED(widget)
894  QPen _pen = pen();
895  const QColor orig = _pen.color().lighter();
896  QColor invertedColor(orig.green(), orig.blue(), orig.red());
897  if (invertedColor == _pen.color()) {
898  // Ensure different color.
899  invertedColor.setRed((invertedColor.red() + 50) % 256);
900  }
901  invertedColor.setAlpha(150);
902 
903  int sz = m_points.size();
904  if (sz < 1) {
905  // not enough points - do nothing
906  return;
907  }
908 
909  QPointF savedStart = m_points.first();
910  QPointF savedEnd = m_points.last();
911 
912  // modify the m_points array not to include the Symbol, the value depends on Symbol
913  if (m_startSymbol) {
914  QPointF newStart = m_startSymbol->mapToParent(m_startSymbol->symbolEndPoints().first);
915  m_points[0] = newStart;
916  }
917 
918  if (m_endSymbol) {
919  QPointF newEnd = m_endSymbol->mapToParent(m_endSymbol->symbolEndPoints().first);
920  m_points[sz - 1] = newEnd;
921  }
922 
923  painter->setPen(_pen);
924  painter->setBrush(Qt::NoBrush);
925  painter->drawPath(path());
926 
927  if (option->state & QStyle::State_Selected) {
928  // make the association broader in the selected state
929  QPainterPathStroker stroker;
930  stroker.setWidth(3.0);
931  QPainterPath outline = stroker.createStroke(path());
932  QColor shadowColor(Qt::lightGray);
933  shadowColor.setAlpha(80);
934  QBrush shadowBrush(shadowColor);
935  painter->setBrush(shadowBrush);
936  painter->setPen(Qt::NoPen);
937  painter->drawPath(outline);
938 
939  // set color for selected painting
940  _pen.setColor(Qt::blue);
941  QRectF circle(0, 0, SelectedPointDiameter, SelectedPointDiameter);
942  painter->setBrush(_pen.color());
943  painter->setPen(Qt::NoPen);
944 
945  // draw points
946  circle.moveCenter(savedStart);
947  painter->drawRect(circle);
948  for (int i = 1; i < sz-1; ++i) {
949  if (i != m_activePointIndex) {
950  circle.moveCenter(m_points.at(i));
951  painter->drawRect(circle);
952  }
953  }
954  circle.moveCenter(savedEnd);
955  painter->drawRect(circle);
956 
957  if (m_activePointIndex != -1) {
958  painter->setBrush(invertedColor);
959  painter->setPen(Qt::NoPen);
960  circle.setWidth(1.5*SelectedPointDiameter);
961  circle.setHeight(1.5*SelectedPointDiameter);
962  circle.moveCenter(m_points.at(m_activePointIndex));
963  painter->drawEllipse(circle);
964  }
965  else if (m_activeSegmentIndex != -1) {
966  if (m_layout == Polyline) {
967  painter->setPen(QPen(invertedColor, _pen.widthF() + 1));
968  painter->setBrush(Qt::NoBrush);
969 
970  QLineF segmentLine(m_points[m_activeSegmentIndex], m_points[m_activeSegmentIndex + 1]);
971  painter->drawLine(segmentLine);
972  }
973  }
974 
975  // debug info
976  if (Tracer::instance()->isEnabled(metaObject()->className())) {
977  painter->setPen(Qt::green);
978  painter->setBrush(Qt::NoBrush);
979  painter->drawPath(shape());
980  painter->setPen(Qt::red);
981  painter->drawRect(boundingRect());
982  // origin
983  painter->drawLine(-10, 0, 10, 0);
984  painter->drawLine(0, -10, 0, 10);
985  }
986  }
987 
988  // now restore the points array
989  m_points[0] = savedStart;
990  m_points[sz - 1] = savedEnd;
991 }
992 
996 void AssociationLine::mousePressEvent(QGraphicsSceneMouseEvent *event)
997 {
998  DEBUG(DBG_SRC) << "at " << event->scenePos();
999  if (event->buttons() & Qt::LeftButton) {
1000  m_activePointIndex = closestPointIndex(event->scenePos());
1001  if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
1002  // end points are not drawn and hence not active
1003  m_activePointIndex = -1;
1004  }
1005  // calculate only if active point index is -1
1006  m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
1007  }
1008  else if (event->buttons() & Qt::RightButton) {
1009  DEBUG(DBG_SRC) << "call context menu of association widget at " << event->scenePos();
1010  }
1011  else {
1012  m_activePointIndex = -1;
1013  m_activeSegmentIndex = -1;
1014  }
1015 }
1016 
1020 void AssociationLine::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1021 {
1022  if (m_activePointIndex != -1) {
1023  setPoint(m_activePointIndex, event->scenePos());
1024  }
1025  else if (m_activeSegmentIndex != -1 && !isEndSegmentIndex(m_activeSegmentIndex)) {
1026  QPointF delta = event->scenePos() - event->lastScenePos();
1027  setPoint(m_activeSegmentIndex, m_points[m_activeSegmentIndex] + delta);
1028  setPoint(m_activeSegmentIndex + 1, m_points[m_activeSegmentIndex + 1] + delta);
1029  }
1030  else {
1031  return;
1032  }
1033 }
1034 
1038 void AssociationLine::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1039 {
1040  if (event->buttons() & Qt::LeftButton) {
1041  m_activeSegmentIndex = -1;
1042  m_activePointIndex = -1;
1043  }
1044 }
1045 
1050 void AssociationLine::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
1051 {
1052  DEBUG(DBG_SRC) << "at " << event->scenePos();
1053  int oldPointIndex = m_activePointIndex;
1054  int oldSegmentIndex = m_activeSegmentIndex;
1055 
1056  m_activePointIndex = closestPointIndex(event->scenePos());
1057  // End points are not drawn and hence not active.
1058  if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
1059  m_activePointIndex = -1;
1060  }
1061  // Activate segment index only if point index is -1
1062  m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
1063 
1064  bool isChanged = (oldSegmentIndex != m_activeSegmentIndex || oldPointIndex != m_activePointIndex);
1065  if (isChanged) {
1066  m_associationWidget->update();
1067  }
1068 }
1069 
1074 void AssociationLine::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
1075 {
1076  int oldPointIndex = m_activePointIndex;
1077  int oldSegmentIndex = m_activeSegmentIndex;
1078 
1079  m_activePointIndex = closestPointIndex(event->scenePos());
1080  // End points are not drawn and hence not active.
1081  if (m_activePointIndex != -1 && isEndPointIndex(m_activePointIndex)) {
1082  m_activePointIndex = -1;
1083  }
1084  // Activate segment index only if point index is -1
1085  m_activeSegmentIndex = (m_activePointIndex != -1) ? -1 : closestSegmentIndex(event->scenePos());
1086 
1087  bool isChanged = (oldSegmentIndex != m_activeSegmentIndex || oldPointIndex != m_activePointIndex);
1088  if (isChanged) {
1089  m_associationWidget->update();
1090  }
1091 }
1092 
1096 void AssociationLine::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
1097 {
1098  DEBUG(DBG_SRC) << "at " << event->scenePos();
1099  //Q_UNUSED(event)
1100  m_activePointIndex = -1;
1101  m_activeSegmentIndex = -1;
1102  m_associationWidget->update();
1103 }
1104 
1105 //-----------------------------------------------------------------------------
1106 
1113 Symbol::SymbolProperty Symbol::symbolTable[Count] =
1114 {
1115  {
1116  QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
1117  SymbolEndPoints(QPointF(0, 10), QPointF(0, 10))
1118  },
1119  {
1120  QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
1121  SymbolEndPoints(QPointF(0, 0), QPointF(0, 10))
1122  },
1123  {
1124  QRectF(-6, 0, 12, 10), QPainterPath(), QLineF(0, 0, 0, 10),
1125  SymbolEndPoints(QPointF(0, 10), QPointF(0, 10))
1126  },
1127  {
1128  QRectF(-5, -10, 10, 20), QPainterPath(), QLineF(0, -10, 0, 10),
1129  SymbolEndPoints(QPointF(0, -10), QPointF(0, 10))
1130  },
1131  {
1132  QRectF(-15, -10, 30, 20), QPainterPath(), QLineF(-10, 0, 0, 0),
1133  SymbolEndPoints(QPointF(0, 0), QPointF(0, 0))
1134  },
1135  {
1136  QRectF(-8, -8, 16, 16), QPainterPath(), QLineF(0, -8, 0, 8),
1137  SymbolEndPoints(QPointF(0, -8), QPointF(0, 8))
1138  }
1139 
1140 };
1141 
1145 void Symbol::setupSymbolTable()
1146 {
1147  SymbolProperty &openArrow = symbolTable[OpenArrow];
1148  if (openArrow.shape.isEmpty()) {
1149  QRectF rect = openArrow.boundRect;
1150  // Defines a 'V' shape arrow fitting in the bound rect.
1151  openArrow.shape.moveTo(rect.topLeft());
1152  openArrow.shape.lineTo(rect.center().x(), rect.bottom());
1153  openArrow.shape.lineTo(rect.topRight());
1154  }
1155 
1156  SymbolProperty &closedArrow = symbolTable[ClosedArrow];
1157  if (closedArrow.shape.isEmpty()) {
1158  QRectF rect = closedArrow.boundRect;
1159  // Defines a 'V' shape arrow fitting in the bound rect.
1160  closedArrow.shape.moveTo(rect.topLeft());
1161  closedArrow.shape.lineTo(rect.center().x(), rect.bottom());
1162  closedArrow.shape.lineTo(rect.topRight());
1163  closedArrow.shape.lineTo(rect.topLeft());
1164  }
1165 
1166  SymbolProperty &crowFeet = symbolTable[CrowFeet];
1167  if (crowFeet.shape.isEmpty()) {
1168  QRectF rect = crowFeet.boundRect;
1169  // Defines a crowFeet fitting in the bound rect.
1170  QPointF topMid(rect.center().x(), rect.top());
1171 
1172  // left leg
1173  crowFeet.shape.moveTo(rect.bottomLeft());
1174  crowFeet.shape.lineTo(topMid);
1175 
1176  // middle leg
1177  crowFeet.shape.moveTo(rect.center().x(), rect.bottom());
1178  crowFeet.shape.lineTo(topMid);
1179 
1180  // left leg
1181  crowFeet.shape.moveTo(rect.bottomRight());
1182  crowFeet.shape.lineTo(topMid);
1183  }
1184 
1185  SymbolProperty &diamond = symbolTable[Diamond];
1186  if (diamond.shape.isEmpty()) {
1187  QRectF rect = diamond.boundRect;
1188  // Defines a 'diamond' shape fitting in the bound rect.
1189  diamond.shape.moveTo(rect.center().x(), rect.top());
1190  diamond.shape.lineTo(rect.left(), rect.center().y());
1191  diamond.shape.lineTo(rect.center().x(), rect.bottom());
1192  diamond.shape.lineTo(rect.right(), rect.center().y());
1193  diamond.shape.lineTo(rect.center().x(), rect.top());
1194  }
1195 
1196  SymbolProperty &subset = symbolTable[Subset];
1197  if (subset.shape.isEmpty()) {
1198  QRectF rect = subset.boundRect;
1199  // Defines an arc fitting in bound rect.
1200  qreal start = 90, span = 180;
1201  subset.shape.arcMoveTo(rect, start);
1202  subset.shape.arcTo(rect, start, span);
1203  }
1204 
1205  SymbolProperty &circle = symbolTable[Circle];
1206  if (circle.shape.isEmpty()) {
1207  QRectF rect = circle.boundRect;
1208  // Defines a circle with a horizontal-vertical cross lines.
1209  circle.shape.addEllipse(rect);
1210 
1211  circle.shape.moveTo(rect.center().x(), rect.top());
1212  circle.shape.lineTo(rect.center().x(), rect.bottom());
1213 
1214  circle.shape.moveTo(rect.left(), rect.center().y());
1215  circle.shape.lineTo(rect.right(), rect.center().y());
1216  }
1217 
1218 }
1219 
1224 Symbol::Symbol(SymbolType symbolType, QGraphicsItem *parent)
1225  : QGraphicsItem(parent),
1226  m_symbolType(symbolType)
1227 {
1228  // ensure SymbolTable is validly initialized
1229  setupSymbolTable();
1230 }
1231 
1235 Symbol::~Symbol()
1236 {
1237 }
1238 
1242 Symbol::SymbolType Symbol::symbolType() const
1243 {
1244  return m_symbolType;
1245 }
1246 
1250 void Symbol::setSymbolType(SymbolType symbolType)
1251 {
1252  prepareGeometryChange(); // calls update implicitly
1253  m_symbolType = symbolType;
1254 }
1255 
1260 void Symbol::paint(QPainter *painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
1261 {
1262  Q_UNUSED(option) Q_UNUSED(widget)
1263  painter->setPen(m_pen);
1264  switch (m_symbolType) {
1265  case ClosedArrow:
1266  case CrowFeet:
1267  case Diamond:
1268  painter->setBrush(m_brush);
1269  break;
1270  default:
1271  break;
1272  }
1273  painter->drawPath(Symbol::symbolTable[m_symbolType].shape);
1274 }
1275 
1279 QRectF Symbol::boundingRect() const
1280 {
1281  const qreal adj = .5 * m_pen.widthF();
1282  return Symbol::symbolTable[m_symbolType].boundRect.
1283  adjusted(-adj, -adj, adj, adj);
1284 }
1285 
1289 QPainterPath Symbol::shape() const
1290 {
1291  QPainterPath path;
1292  path.addRect(boundingRect());
1293  return path;
1294 }
1295 
1305 void Symbol::alignTo(const QLineF& to)
1306 {
1307  QLineF toMapped(mapFromParent(to.p1()), mapFromParent(to.p2()));
1308 
1309  QLineF origAxis = Symbol::symbolTable[m_symbolType].axisLine;
1310  QLineF translatedAxis = origAxis.translated(toMapped.p2() - origAxis.p2());
1311 
1312  qreal angle = translatedAxis.angleTo(toMapped);
1313  rotate(-angle);
1314 
1315  QPointF delta = to.p2() - mapToParent(symbolEndPoints().second);
1316  moveBy(delta.x(), delta.y());
1317 }
1318 
1322 Symbol::SymbolEndPoints Symbol::symbolEndPoints() const
1323 {
1324  return Symbol::symbolTable[m_symbolType].endPoints;
1325 }
1326 
1330 QPen Symbol::pen() const
1331 {
1332  return m_pen;
1333 }
1334 
1338 void Symbol::setPen(const QPen& pen)
1339 {
1340  prepareGeometryChange();
1341  m_pen = pen;
1342  if (m_symbolType == ClosedArrow)
1343  m_pen.setStyle(Qt::SolidLine);
1344 }
1345 
1349 QBrush Symbol::brush() const
1350 {
1351  return m_brush;
1352 }
1353 
1357 void Symbol::setBrush(const QBrush &brush)
1358 {
1359  m_brush = brush;
1360  update();
1361 }
1362 
1363 #include "associationline.moc"
Uml::AssociationType::Aggregation
Definition: basictypes.h:101
Symbol::ClosedArrow
Definition: associationline.h:44
AssociationLine::Direct
Definition: associationline.h:111
associationline.h
Symbol::~Symbol
virtual ~Symbol()
Destructor.
Definition: associationline.cpp:1235
Symbol::SymbolEndPoints
QPair< QPointF, QPointF > SymbolEndPoints
Definition: associationline.h:35
AssociationLine::toString
static QString toString(LayoutType layout)
Convert enum LayoutType to string.
Definition: associationline.cpp:738
AssociationLine::closestSegmentIndex
int closestSegmentIndex(const QPointF &point, qreal delta=Delta) const
Return index of closest segment.
Definition: associationline.cpp:211
Uml::AssociationType::Generalization
Definition: basictypes.h:100
AssociationLine::isEndSegmentIndex
bool isEndSegmentIndex(int index) const
Retval True If segment at index is start or end.
Definition: associationline.cpp:246
AssociationLine::startPoint
QPointF startPoint() const
Shortcut for point(0).
Definition: associationline.cpp:97
Uml::AssociationType::Coll_Message
Definition: basictypes.h:105
AssociationLine::mouseReleaseEvent
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
Reset active indices and also push undo command.
Definition: associationline.cpp:1038
Uml::AssociationType::Activity
Definition: basictypes.h:115
AssociationLine::loadFromXMI
bool loadFromXMI(QDomElement &qElement)
Loads AssociationLine information saved in qElement XMI element.
Definition: associationline.cpp:295
Uml::AssociationType::UniAssociation
Definition: basictypes.h:112
Symbol::shape
virtual QPainterPath shape() const
Definition: associationline.cpp:1289
AssociationLine::Polyline
Definition: associationline.h:113
AssociationLine::count
int count() const
Returns the amount of POINTS on the line.
Definition: associationline.cpp:137
Uml::AssociationType::Child2Category
Definition: basictypes.h:118
Symbol::paint
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
Draws the current symbol using the QPainterPath stored for the current symbol.
Definition: associationline.cpp:1260
QGraphicsItem
Symbol::setPen
void setPen(const QPen &pen)
Sets the pen used to draw the symbol.
Definition: associationline.cpp:1338
Uml::AssociationType::State
Definition: basictypes.h:114
Uml::RoleType::B
Definition: basictypes.h:210
QWidget
AssociationWidget::isSelf
bool isSelf() const
Returns true if this AssociationWidget represents a self message.
Definition: associationwidget.cpp:1417
Uml::AssociationType::Anchor
Definition: basictypes.h:113
Symbol::Subset
Definition: associationline.h:47
Symbol::Diamond
Definition: associationline.h:46
uWarning
#define uWarning()
Definition: debug_utils.h:97
AssociationLine::closestPointIndex
int closestPointIndex(const QPointF &point, qreal delta=Delta) const
Return index of point closer a given delta.
Definition: associationline.cpp:185
QVector
AssociationLine::boundingRect
QRectF boundingRect() const
The points are used for the bounding rect.
Definition: associationline.cpp:715
AssociationLine::Orthogonal
Definition: associationline.h:112
Symbol::Count
Definition: associationline.h:49
DEBUG_REGISTER_DISABLED
#define DEBUG_REGISTER_DISABLED(src)
Definition: debug_utils.h:103
Symbol::Circle
Definition: associationline.h:48
debug_utils.h
AssociationLine::hoverMoveEvent
void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
Calculates the "to be highlighted" point and segment indicies and updates if necessary.
Definition: associationline.cpp:1074
Uml::AssociationType::Coll_Message_Self
Definition: basictypes.h:107
Uml::AssociationType::Dependency
Definition: basictypes.h:102
Symbol::OpenArrow
Definition: associationline.h:43
AssociationWidget
This class represents an association inside a diagram.
Definition: associationwidget.h:50
ENUM_NAME
#define ENUM_NAME(o, e, v)
In a Q_OBJECT class define any enum as Q_ENUMS.
Definition: debug_utils.h:114
AssociationLine::calculateInitialEndPoints
void calculateInitialEndPoints()
This method simply ensures presence of two points and adds the needed points for self associations...
Definition: associationline.cpp:413
AssociationLine::shape
QPainterPath shape() const
Definition: associationline.cpp:727
AssociationLine
A convenience class that encapsulates geometry management, handles mouse and hover events...
Definition: associationline.h:105
Symbol::brush
QBrush brush() const
Definition: associationline.cpp:1349
AssociationWidget::association
UMLAssociation * association() const
Returns the UMLAssociation representation of this object.
Definition: associationwidget.cpp:548
Symbol::setBrush
void setBrush(const QBrush &brush)
Sets the brush used to fill symbol.
Definition: associationline.cpp:1357
AssociationLine::fromString
static LayoutType fromString(const QString &layout)
Convert string to enum LayoutType.
Definition: associationline.cpp:746
umlwidget.h
Symbol::SymbolType
SymbolType
This enumeration lists all the symbols that can be used as embedded on AssociationLine.
Definition: associationline.h:41
AssociationLine::paint
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
Reimplemented from QGraphicsItem::paint.
Definition: associationline.cpp:891
Symbol::None
Definition: associationline.h:42
AssociationLine::mouseMoveEvent
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Moves the point or line if active.
Definition: associationline.cpp:1020
AssociationLine::optimizeLinePoints
void optimizeLinePoints()
This method optimizes the number of points in the AssociationLine.
Definition: associationline.cpp:161
AssociationLine::removePoint
void removePoint(int index)
Removes the point at index passed in.
Definition: associationline.cpp:125
AssociationLine::setEndPoints
bool setEndPoints(const QPointF &start, const QPointF &end)
Sets the start and end points.
Definition: associationline.cpp:258
Uml::AssociationType::Enum
Enum
Definition: basictypes.h:99
WidgetBase::lineWidth
uint lineWidth() const
Returns line width.
Definition: widgetbase.cpp:286
DEBUG
#define DEBUG(src)
Definition: debug_utils.h:101
WidgetBase::m_brush
QBrush m_brush
Definition: widgetbase.h:170
Tracer::instance
static Tracer * instance()
Definition: debug_utils.cpp:30
Symbol::Symbol
Symbol(SymbolType symbolType, QGraphicsItem *parent=0)
Constructs a Symbol with current symbol being symbol and parented to parent.
Definition: associationline.cpp:1224
AssociationLine::saveToXMI
void saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
Saves association line information into XMI element named "linepath".
Definition: associationline.cpp:348
AssociationLine::setLayout
void setLayout(LayoutType layout)
Set the layout type of the association line.
Definition: associationline.cpp:770
AssociationLine::~AssociationLine
virtual ~AssociationLine()
Destructor.
Definition: associationline.cpp:59
Symbol::alignTo
void alignTo(const QLineF &line)
This method aligns this Symbol to the line being passed.
Definition: associationline.cpp:1305
WidgetBase::rect
QRectF rect() const
return drawing rectangle of widget in local coordinates
Definition: widgetbase.cpp:600
Uml::AssociationType::Realization
Definition: basictypes.h:111
Uml::AssociationType::Composition
Definition: basictypes.h:110
QGraphicsLineItem
AssociationLine::cleanup
void cleanup()
Removes all the points and signals a geometry update.
Definition: associationline.cpp:145
associationwidget.h
AssociationLine::insertPoint
void insertPoint(int index, const QPointF &point)
Inserts the passed in point at the index passed in and recalculates the bounding rect.
Definition: associationline.cpp:114
AssociationLine::reconstructSymbols
void reconstructSymbols()
This method creates, deletes symbols and collaboration lines based on m_associationWidget->associatio...
Definition: associationline.cpp:452
Symbol::setSymbolType
void setSymbolType(SymbolType symbolType)
Sets the current symbol type to symbol and updates the geometry.
Definition: associationline.cpp:1250
AssociationLine::pen
QPen pen() const
Returns the type of pen to use depending on the type of Association.
Definition: associationline.cpp:393
AssociationLine::point
QPointF point(int index) const
Returns the point at the point index.
Definition: associationline.cpp:67
Symbol::pen
QPen pen() const
Definition: associationline.cpp:1330
Uml::AssociationType::Exception
Definition: basictypes.h:116
AssociationLine::mousePressEvent
void mousePressEvent(QGraphicsSceneMouseEvent *event)
Determines the active point or segment, the latter being given more priority.
Definition: associationline.cpp:996
AssociationLine::LayoutType
LayoutType
Definition: associationline.h:110
AssociationLine::hoverEnterEvent
void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
Calculates the "to be highlighted" point and segment indicies and updates if necessary.
Definition: associationline.cpp:1050
Symbol
This class provides with various symbols that can be embedded in AssociationLine. ...
Definition: associationline.h:32
Symbol::CrowFeet
Definition: associationline.h:45
Symbol::symbolEndPoints
SymbolEndPoints symbolEndPoints() const
Definition: associationline.cpp:1322
uError
#define uError()
Definition: debug_utils.h:96
Uml::AssociationType::Relationship
Definition: basictypes.h:119
AssociationLine::isEndPointIndex
bool isEndPointIndex(int index) const
Retval True If point at index is start or end.
Definition: associationline.cpp:235
AssociationLine::setPoint
bool setPoint(int index, const QPointF &point)
Sets the point value at given index to point.
Definition: associationline.cpp:79
AssociationLine::endPoint
QPointF endPoint() const
Shortcut for end point.
Definition: associationline.cpp:105
Uml::AssociationType::Containment
Definition: basictypes.h:109
AssociationLine::Spline
Definition: associationline.h:114
AssociationLine::hoverLeaveEvent
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
Reset active indicies and updates.
Definition: associationline.cpp:1096
AssociationLine::dumpPoints
void dumpPoints()
Debug helper method to write out the points.
Definition: associationline.cpp:284
QGraphicsObject
AssociationLine::brush
QBrush brush() const
Returns the type of brush to use depending on the type of Association.
Definition: associationline.cpp:375
AssociationWidget::widgetForRole
UMLWidget * widgetForRole(Uml::RoleType::Enum role) const
Gets the given role widget.
Definition: associationwidget.cpp:1235
AssociationLine::layout
LayoutType layout() const
Return the layout type of the association line.
Definition: associationline.cpp:761
Symbol::boundingRect
virtual QRectF boundingRect() const
Definition: associationline.cpp:1279
AssociationWidget::associationType
Uml::AssociationType::Enum associationType() const
Gets the association's type.
Definition: associationwidget.cpp:1427
Symbol::symbolType
SymbolType symbolType() const
Definition: associationline.cpp:1242
WidgetBase::lineColor
QColor lineColor() const
Returns line color.
Definition: widgetbase.cpp:244
AssociationLine::path
QPainterPath path() const
Definition: associationline.cpp:679
QList
DBG_SRC
#define DBG_SRC
Definition: import_utils.cpp:42
UMLWidget
This is the base class for nearly all graphical widgets.
Definition: umlwidget.h:40
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:05:59 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

umbrello/umbrello

Skip menu "umbrello/umbrello"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal