19#include "moc_qgsmodelarrowitem.cpp" 
   24#include <QApplication> 
   30QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Qt::Edge startEdge, 
int startIndex, 
bool startIsOutgoing, Marker startMarker, QgsModelComponentGraphicItem *endItem, Qt::Edge endEdge, 
int endIndex, 
bool endIsIncoming, Marker endMarker )
 
   32  , mStartItem( startItem )
 
   33  , mStartEdge( startEdge )
 
   34  , mStartIndex( startIndex )
 
   35  , mStartIsOutgoing( startIsOutgoing )
 
   36  , mStartMarker( startMarker )
 
   39  , mEndIndex( endIndex )
 
   40  , mEndIsIncoming( endIsIncoming )
 
   41  , mEndMarker( endMarker )
 
   43  setCacheMode( QGraphicsItem::DeviceCoordinateCache );
 
   44  setFlag( QGraphicsItem::ItemIsSelectable, 
false );
 
   45  mColor = QApplication::palette().color( QPalette::Text );
 
   46  mColor.setAlpha( 150 );
 
   47  setPen( QPen( mColor, 8, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
 
   48  setZValue( QgsModelGraphicsScene::ArrowLink );
 
   51  connect( mStartItem, &QgsModelComponentGraphicItem::updateArrowPaths, 
this, &QgsModelArrowItem::updatePath );
 
   52  connect( mStartItem, &QgsModelComponentGraphicItem::repaintArrows, 
this, [
this] { update(); } );
 
   53  connect( mEndItem, &QgsModelComponentGraphicItem::updateArrowPaths, 
this, &QgsModelArrowItem::updatePath );
 
   54  connect( mEndItem, &QgsModelComponentGraphicItem::repaintArrows, 
this, [
this] { update(); } );
 
   57QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Qt::Edge startEdge, 
int startIndex, Marker startMarker, QgsModelComponentGraphicItem *endItem, Marker endMarker )
 
   58  : QgsModelArrowItem( startItem, startEdge, startIndex, true, startMarker, endItem, Qt::LeftEdge, -1, true, endMarker )
 
   62QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Marker startMarker, QgsModelComponentGraphicItem *endItem, Qt::Edge endEdge, 
int endIndex, Marker endMarker )
 
   63  : QgsModelArrowItem( startItem, Qt::LeftEdge, -1, true, startMarker, endItem, endEdge, endIndex, true, endMarker )
 
   67QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Marker startMarker, QgsModelComponentGraphicItem *endItem, Marker endMarker )
 
   68  : QgsModelArrowItem( startItem, Qt::LeftEdge, -1, true, startMarker, endItem, Qt::LeftEdge, -1, true, endMarker )
 
   73void QgsModelArrowItem::paint( QPainter *painter, 
const QStyleOptionGraphicsItem *, QWidget * )
 
   75  QColor color = mColor;
 
   77  if ( mStartItem->state() == QgsModelComponentGraphicItem::Selected || mEndItem->state() == QgsModelComponentGraphicItem::Selected )
 
   78    color.setAlpha( 220 );
 
   79  else if ( mStartItem->state() == QgsModelComponentGraphicItem::Hover || mEndItem->state() == QgsModelComponentGraphicItem::Hover )
 
   80    color.setAlpha( 150 );
 
   88  painter->setBrush( color );
 
   89  painter->setRenderHint( QPainter::Antialiasing );
 
   92  switch ( mStartMarker )
 
   95      painter->drawEllipse( mStartPoint, 3.0, 3.0 );
 
   97    case Marker::ArrowHead:
 
   98      drawArrowHead( painter, mStartPoint, path().pointAtPercent( 0.0 ) - path().pointAtPercent( 0.05 ) );
 
  100    case Marker::NoMarker:
 
  104  switch ( mEndMarker )
 
  107      painter->drawEllipse( mEndPoint, 3.0, 3.0 );
 
  109    case Marker::ArrowHead:
 
  110      drawArrowHead( painter, mEndPoint, path().pointAtPercent( 1.0 ) - path().pointAtPercent( 0.95 ) );
 
  112    case Marker::NoMarker:
 
  116  painter->setBrush( Qt::NoBrush );
 
  117  painter->drawPath( path() );
 
  120void QgsModelArrowItem::drawArrowHead( QPainter *painter, 
const QPointF &position, 
const QPointF &vector )
 
  122  const float angle = atan2( vector.y(), vector.x() ) * 180.0 / M_PI;
 
  123  painter->translate( position );
 
  124  painter->rotate( angle );
 
  126  arrowHead << QPointF( 0, 0 ) << QPointF( -6, 4 ) << QPointF( -6, -4 ) << QPointF( 0, 0 );
 
  127  painter->drawPolygon( arrowHead );
 
  128  painter->rotate( -angle );
 
  129  painter->translate( -position );
 
  132void QgsModelArrowItem::setPenStyle( Qt::PenStyle style )
 
  140void QgsModelArrowItem::updatePath()
 
  142  QList<QPointF> controlPoints;
 
  146  bool hasStartPt = 
false;
 
  151  bool startHasSpecificDirectionalFlow = qobject_cast<QgsModelChildAlgorithmGraphicItem *>( mStartItem );
 
  152  bool endHasSpecificDirectionalFlow = qobject_cast<QgsModelChildAlgorithmGraphicItem *>( mEndItem );
 
  155  if ( qobject_cast<QgsModelCommentGraphicItem *>( mStartItem )
 
  156       || qobject_cast<QgsModelCommentGraphicItem *>( mEndItem ) )
 
  159    startHasSpecificDirectionalFlow = 
false;
 
  160    endHasSpecificDirectionalFlow = 
false;
 
  163  if ( mStartIndex != -1 )
 
  165    startPt = mStartItem->linkPoint( mStartEdge, mStartIndex, !mStartIsOutgoing );
 
  169  bool hasEndPt = 
false;
 
  170  if ( mEndIndex != -1 )
 
  172    endPt = mEndItem->linkPoint( mEndEdge, mEndIndex, mEndIsIncoming );
 
  181      pt = mStartItem->calculateAutomaticLinkPoint( mEndItem, startEdge );
 
  183      pt = mStartItem->calculateAutomaticLinkPoint( endPt + mEndItem->pos(), startEdge );
 
  185    controlPoints.append( pt );
 
  187    controlPoints.append( bezierPointForCurve( pt, startEdge, !mStartIsOutgoing, startHasSpecificDirectionalFlow ) );
 
  191    mStartPoint = mStartItem->pos() + startPt;
 
  192    controlPoints.append( mStartItem->pos() + startPt );
 
  193    controlPoints.append( bezierPointForCurve( mStartItem->pos() + startPt, mStartEdge == Qt::BottomEdge ? Qt::RightEdge : Qt::LeftEdge, !mStartIsOutgoing, startHasSpecificDirectionalFlow ) );
 
  201      pt = mEndItem->calculateAutomaticLinkPoint( mStartItem, endEdge );
 
  203      pt = mEndItem->calculateAutomaticLinkPoint( startPt + mStartItem->pos(), endEdge );
 
  205    controlPoints.append( bezierPointForCurve( pt, endEdge, mEndIsIncoming, endHasSpecificDirectionalFlow ) );
 
  206    controlPoints.append( pt );
 
  211    mEndPoint = mEndItem->pos() + endPt;
 
  212    controlPoints.append( bezierPointForCurve( mEndItem->pos() + endPt, mEndEdge == Qt::BottomEdge ? Qt::RightEdge : Qt::LeftEdge, mEndIsIncoming, endHasSpecificDirectionalFlow ) );
 
  213    controlPoints.append( mEndItem->pos() + endPt );
 
  217  path.moveTo( controlPoints.at( 0 ) );
 
  218  path.cubicTo( controlPoints.at( 1 ), controlPoints.at( 2 ), controlPoints.at( 3 ) );
 
  222QPointF QgsModelArrowItem::bezierPointForCurve( 
const QPointF &point, Qt::Edge edge, 
bool incoming, 
bool hasSpecificDirectionalFlow )
 const 
  227      return point + QPointF( hasSpecificDirectionalFlow ? ( incoming ? -50 : 50 ) : -50, 0 );
 
  230      return point + QPointF( hasSpecificDirectionalFlow ? ( incoming ? -50 : 50 ) : 50, 0 );
 
  233      return point + QPointF( 0, hasSpecificDirectionalFlow ? ( incoming ? -30 : 30 ) : -30 );
 
  236      return point + QPointF( 0, hasSpecificDirectionalFlow ? ( incoming ? -30 : 30 ) : 30 );
 
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)