graphicsportitem.cpp
1 /*
2  name: tools/editor/graphicsportitem.cpp
3 
4  This file is part of ARCS - Augmented Reality Component System
5  (version 2-current), written by Jean-Yves Didier
6  for IBISC Laboratory (http://www.ibisc.univ-evry.fr)
7 
8  Copyright (C) 2013 Université d'Evry-Val d'Essonne
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 
23 
24  Please send bugreports with examples or suggestions to
25  jean-yves.didier__at__ibisc.univ-evry.fr
26 */
27 
28 
29 #include "graphicsportitem.h"
30 #include "graphicslinkitem.h"
31 #include "graphicscomponentitem.h"
32 #include "graphicsinvocationitem.h"
33 #include "invocationdialog.h"
34 #include "sheetview.h"
35 #include <arcs/arcssheet.h>
36 #include <QBrush>
37 #include <QGraphicsSceneMouseEvent>
38 #include <iostream>
39 #include <QGraphicsScene>
40 #include <QAction>
41 #include <QMenu>
42 #include <QRegExp>
43 #include <QMetaObject>
44 #include <QMessageBox>
45 #include <QStyleOptionGraphicsItem>
46 
47 #include <QInputDialog>
48 
49 GraphicsPortItem::GraphicsPortItem(QGraphicsItem *parent)
50  : QGraphicsPathItem(parent)
51 {
52  markedForDeletion= false;
53  linkInConstruction = 0;
54 
55 #if QT_VERSION >= 0x050000
56  setAcceptHoverEvents(true);
57 #else
58  setAcceptsHoverEvents(true);
59 #endif
60  setFlag(QGraphicsItem::ItemIsSelectable);
61  setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
62  defaultPen = pen();
63 
64  QBrush br=brush();
65  br.setStyle(Qt::SolidPattern);
66  br.setColor(Qt::white);
67 
68  setBrush(br);
69 
70  QPainterPath pp ;
71 
72  pp.addRect(-5,-5,10,10);
73  pp.moveTo(-5,0);
74  pp.lineTo(5,0);
75  pp.moveTo(5,0);
76  pp.lineTo(0,-3);
77  pp.moveTo(5,0);
78  pp.lineTo(0,3);
79 
80  setPath(pp);
81 
82  setAcceptHoverEvents(true);
83  rectOperation = new QGraphicsRectItem(this);
84  textOperation = new QGraphicsSimpleTextItem(rectOperation);
85  rectOperation->setVisible(false);
86  rectOperation->setRect(textOperation->boundingRect());
87  rectOperation->setBrush(QBrush(Qt::yellow));
88  //setFlag(QGraphicsItem::ItemIsMovable,false);
89  updateView();
90 }
91 
92 GraphicsPortItem::~GraphicsPortItem()
93 {
94  setSelected(false);
95  int i;
96  // when a portitem is removed, it should destroy all links it is connected with.
97  for(i=0; i < links.count(); i++)
98  {
99  if (markedForDeletion)
100  links[i]->markForDeletion();
101  delete links[i];
102  }
103 
104  // we should also mark for deletion invocations
105  if (markedForDeletion)
106  {
107 #if QT_VERSION >= 0x050000
108  QList<QGraphicsItem*> items = childItems();
109 #else
110  QList<QGraphicsItem*> items = children();
111 #endif
112  for (i=0; i < items.count(); i++ )
113  {
114  if (items[i]->type() == GraphicsInvocationItem::Type)
115  dynamic_cast<GraphicsInvocationItem*>(items[i])->markForDeletion();
116  }
117  }
118 
119  // we should tell our father we do not enlist anymore.
120  GraphicsComponentItem* parentComponent = dynamic_cast<GraphicsComponentItem*>(parentItem());
121  if (parentComponent)
122  parentComponent->removePort(textOperation->text());
123 }
124 
125 
126 void GraphicsPortItem::updateView()
127 {
128  textOperation->setText(operationName);
129  rectOperation->setRect(textOperation->boundingRect().adjusted(-2,-2,2,2));
130  QSizeF s = rectOperation->rect().size();
131 
132  if (operationType == Slot)
133  rectOperation->setPos(-s.width()-15,-s.height() -10);
134  else
135  rectOperation->setPos(15,-s.height()-10);
136 }
137 
138 
139 void GraphicsPortItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * /*event*/ )
140 {
141  showName();
142 }
143 
144 void GraphicsPortItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * /*event*/ )
145 {
146  hideName();
147 }
148 
149 void GraphicsPortItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
150 {
151  linkInConstruction = new GraphicsLinkItem(this);
152 
153  if (operationType== Slot)
154  linkInConstruction->setDestination(this);
155  else
156  linkInConstruction->setSource(this);
157 
158  QGraphicsPathItem::mousePressEvent(event);
159 }
160 
161 
162 void GraphicsPortItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
163 {
164  if (linkInConstruction)
165  {
166  linkInConstruction->setCurrentPoint(event->pos());
167  }
168 
169 
170 }
171 
172 
173 void GraphicsPortItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
174 {
175 
176  //QGraphicsItem* item = scene()->itemAt(event->scenePos());
177  QList<QGraphicsItem*> items = scene()->items(event->scenePos(), Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
178  QGraphicsItem* item = 0;
179  for (int i=0; i < items.count(); i++)
180  {
181  if (items[i]->type() == GraphicsPortItem::Type)
182  item = items[i];
183  }
184 
185 
186  if (item && item != this)
187  {
188  GraphicsPortItem* portItem = dynamic_cast<GraphicsPortItem*>(item);
189 
190 
191  if (portItem->getType() != this->getType())
192  {
193  if ( portItem->getType() == Slot)
194  linkInConstruction->setDestination(portItem);
195  else
196  linkInConstruction->setSource(portItem);
197 
198  // put here more test, for example compatibility between signature of each signal/slot pair
199  if (!QMetaObject::checkConnectArgs(
200  qPrintable(linkInConstruction->getDestination()->getName()),
201  qPrintable(linkInConstruction->getSource()->getName()) ) )
202  {
203  if ( QMessageBox::question(0,"Connect argument mismatch",
204  "Arguments from your signal and your slot mismatch. Do you want to continue ?",
205  QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
206  {
207  delete linkInConstruction;
208  linkInConstruction = 0;
209  }
210 
211  }
212 
213  linkInConstruction->finalize();
214  links.append(linkInConstruction);
215  portItem->links.append(linkInConstruction);
216  }
217 
218 
219  if (item == this)
220  {
221  QGraphicsPathItem::mouseReleaseEvent(event);
222  }
223 
224 
225  }
226 
227  if (!linkInConstruction->isFinalized())
228  {
229  delete linkInConstruction;
230  linkInConstruction = 0;
231  }
232 
233 }
234 
235 
236 void GraphicsPortItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
237 {
238  if (operationType == Signal)
239  return ;
240  QMenu menu ;
241  /*QAction* addInvocation =*/ menu.addAction("Add invocation");
242 
243 
244  QAction* selectedAction = menu.exec(event->screenPos());
245  if (!selectedAction)
246  return;
247 
248  //QString text = QInputDialog::getText(0,"Enter an invocation value","Enter an invocation value");
249  /*if (text.isEmpty())
250  return;*/
251  // put here something in order to parse the invocation
252 
253  InvocationDialog dialog(operationName);
254 
255  if (dialog.exec() == QDialog::Accepted)
256  {
257  GraphicsComponentItem* component = dynamic_cast<GraphicsComponentItem*>(parentItem());
258 
259  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
260  if (sheetView)
261  {
262  ARCSSheet& sheet = sheetView->getSheet();
263  ARCSInit* init=0;
264  switch(dialog.getInvocationType())
265  {
266  case GraphicsInvocationItem::Pre:
267  init = &sheet.addPreconnect(component->getComponent()->getProperty("id").toString(),
268  operationName,dialog.getTypeName(),dialog.getValue());
269  break;
270  case GraphicsInvocationItem::Post:
271  init = &sheet.addPostconnect(component->getComponent()->getProperty("id").toString(),
272  operationName,dialog.getTypeName(),dialog.getValue());
273  break;
274  case GraphicsInvocationItem::Cleanup:
275  init = &sheet.addCleanup(component->getComponent()->getProperty("id").toString(),
276  operationName,dialog.getTypeName(),dialog.getValue());
277  break;
278  }
279  if (init )
280  new GraphicsInvocationItem(this,dialog.getInvocationType(),*init);
281  }
282  }
283 
284  std::cout << "invocation added" << std::endl;
285 }
286 
287 
288 QVariant GraphicsPortItem::itemChange(GraphicsItemChange change, const QVariant &value)
289 {
290  if (change == ItemChildRemovedChange)
291  {
292  }
293  return QGraphicsItem::itemChange(change,value);
294 
295 }
296 
297 void GraphicsPortItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
298 {
299  QStyleOptionGraphicsItem myOptions(*option);
300  if (myOptions.state & (QStyle::State_Selected))
301  {
302  QPen myPen(Qt::darkRed);
303  myPen.setCapStyle(Qt::RoundCap);
304  myPen.setWidth(2);
305  setPen(myPen);
306  myOptions.state = myOptions.state ^ QStyle::State_Selected ;
307  }
308  else
309  {
310  setPen(defaultPen);
311  }
312  QGraphicsPathItem::paint(painter,& myOptions, widget );
313 }
314 
315 void GraphicsPortItem::setName(QString s)
316 {
317  operationName = s;
318  updateView();
319 }
320 
321 
322 void GraphicsPortItem::fireUpdate()
323 {
324  //std::cout << "Redrawing all children" << std::endl;
325  for (int i=0; i< links.count(); i++)
326  {
327  //links[i]->setParentItem(this);
328  links[i]->redraw(/*operationType == Signal*/);
329  }
330 }
331 
332 void GraphicsPortItem::removeLinkItem(GraphicsLinkItem *item)
333 {
334  links.removeAll(item);
335 }
ARCSInit & addCleanup(QString dst, QString slt, QString t, QString val)
Adds a cleanup invocation to the sheet structure.
Definition: arcssheet.h:98
ARCSInit & addPreconnect(QString dst, QString slt, QString t, QString val)
Adds a pre-connection initialisation to the sheet structure.
Definition: arcssheet.h:76
Desribes an initialization over a component.
Definition: arcsinit.h:46
QVariant getProperty(QString name)
Gets a meta-property from this component.
ARCSInit & addPostconnect(QString dst, QString slt, QString t, QString val)
Adds a post-connection initialisation to the sheet structure.
Definition: arcssheet.h:87
Maintains connections between objects.
Definition: arcssheet.h:48