graphicscomponentitem.cpp
1 /*
2  name: tools/editor/graphicscomponentitem.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 "graphicscomponentitem.h"
30 #include "sheetview.h"
31 #include "editcomponentwidget.h"
32 #include <QFont>
33 #include <QMenu>
34 #include <QGraphicsSceneContextMenuEvent>
35 #include <QMessageBox>
36 #include <QFontMetrics>
37 #include <QStringList>
38 #include <QStyle>
39 #include <QStyleOptionGraphicsItem>
40 
41 
42 #include "portdialog.h"
43 #include <iostream>
44 
45 GraphicsComponentItem::GraphicsComponentItem(ARCSAbstractComponent *aac)
46  : QGraphicsRectItem()
47 {
48  markedForDeletion = false;
49  defaultPen = pen();
50  setAcceptHoverEvents(true);
51 
52  setFlag(QGraphicsItem::ItemIsMovable);
53  setFlag(QGraphicsItem::ItemIsSelectable);
54  setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
55 
56  component = aac;
57 
58  componentLabel = new QGraphicsSimpleTextItem(aac->getProperty("id").toString()+":"+aac->getType(),this);
59  setRect(componentLabel->boundingRect().adjusted(-5,-5,5,5));
60 }
61 
62 GraphicsComponentItem::~GraphicsComponentItem()
63 {
64  setSelected(false);
65  if (markedForDeletion)
66  {
67 
68 
69  QMapIterator<QString,GraphicsPortItem*> i(signalPorts);
70  while (i.hasNext())
71  {
72  i.next();
73  i.value()->markForDeletion();
74  }
75  QMapIterator<QString,GraphicsPortItem*> i2(slotPorts);
76  while (i2.hasNext())
77  {
78  i2.next();
79  i2.value()->markForDeletion();
80  }
81 
82 
83  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
84  if (sheetView)
85  {
86  sheetView->getSheet().removeProperty(component->getProperty("id").toString() + "-slots");
87  sheetView->getSheet().removeProperty(component->getProperty("id").toString() + "-signals");
88  sheetView->getSheet().removeProperty(component->getProperty("id").toString() + "-pos");
89  }
90  }
91 }
92 
93 
94 void GraphicsComponentItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * /*event*/ )
95 {
96  setPen(QPen(Qt::darkBlue));
97  update();
98 }
99 
100 
101 void GraphicsComponentItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * /*event*/ )
102 {
103  setPen(defaultPen);
104  update();
105 }
106 
107 
108 
109 void GraphicsComponentItem::removePort(QString name)
110 {
111 
112  slotPorts.remove(name);
113  signalPorts.remove(name);
114 
115  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
116  if (sheetView)
117  {
118  sheetView->getSheet().setProperty(component->getProperty("id").toString() + "-slots",
119  QStringList(slotPorts.keys()).join(";"));
120  sheetView->getSheet().setProperty(component->getProperty("id").toString() + "-signals",
121  QStringList(signalPorts.keys()).join(";"));
122  }
123 
124 }
125 
126 void GraphicsComponentItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
127 {
128  QMenu menu;
129 
130  QAction* addSlot = menu.addAction("Add slot");
131  /*QAction* addSignal =*/ menu.addAction("Add signal");
132  menu.addSeparator();
133 
134  QAction* selectedAction = menu.exec(event->screenPos());
135 
136  if (!selectedAction)
137  return ;
138 
139  bool type = (selectedAction==addSlot);
140 
141  PortDialog pd(this->component,type);
142 
143  pd.exec();
144 
145  if (pd.result() == QDialog::Accepted)
146  {
147  if (type)
148  {
149  // in this case we have a slot
150  if (slotPorts.contains(pd.getPort()))
151  {
152  QMessageBox::information(0,"Port already added",
153  "The port "+ pd.getPort() + " has already been added to this component.",
154  QMessageBox::Ok);
155  return;
156  }
157  this->addSlot(pd.getPort());
158  }
159  else
160  {
161  if (signalPorts.contains(pd.getPort()))
162  {
163  QMessageBox::information(0,"Port already added",
164  "The port "+ pd.getPort() + " has already been added to this component.",
165  QMessageBox::Ok);
166  return;
167  }
168  this->addSignal(pd.getPort());
169  }
170  // ajouter slot ou signal
171  }
172 }
173 
174 
175 void GraphicsComponentItem::addSignal(QString s, bool updateSheet)
176 {
177  GraphicsPortItem* item = new GraphicsPortItem(this);
178  item->setType(GraphicsPortItem::Signal);
179  item->setName(s);
180 
181  signalPorts[s] = item;
182  item->setPos(rect().width()-5,QFontMetrics(componentLabel->font()).height()+15*(signalPorts.count()-1)+5);
183 
184  QRectF rectangle(rect());
185  rectangle.setHeight(QFontMetrics(componentLabel->font()).height()
186  + 15*( (signalPorts.count()>slotPorts.count())?signalPorts.count():slotPorts.count() )+5);
187  setRect(rectangle);
188 
189  if (updateSheet)
190  {
191  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
192  if (sheetView)
193  sheetView->getSheet().setProperty(component->getProperty("id").toString() + "-signals",
194  QStringList(signalPorts.keys()).join(";"));
195  }
196 
197 }
198 
199 
200 void GraphicsComponentItem::addSlot(QString s, bool updateSheet)
201 {
202  GraphicsPortItem* item = new GraphicsPortItem(this);
203  item->setType(GraphicsPortItem::Slot);
204  item->setName(s);
205 
206  slotPorts[s] = item;
207  item->setPos(-5,QFontMetrics(componentLabel->font()).height()+15*(slotPorts.count()-1)+5);
208 
209  QRectF rectangle(rect());
210  rectangle.setHeight(QFontMetrics(componentLabel->font()).height()
211  + 15*( (signalPorts.count()>slotPorts.count())?signalPorts.count():slotPorts.count())+5);
212  setRect(rectangle);
213 
214  if (updateSheet)
215  {
216  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
217  if (sheetView)
218  sheetView->getSheet().setProperty(component->getProperty("id").toString() + "-slots",
219  QStringList(slotPorts.keys()).join(";"));
220  }
221 
222 }
223 
224 
225 QVariant GraphicsComponentItem::itemChange ( GraphicsItemChange change, const QVariant & value )
226 {
227  if ( change == ItemScenePositionHasChanged && scene() )
228  {
229  QMap<QString,GraphicsPortItem*>::iterator i;
230  for (i = slotPorts.begin(); i != slotPorts.end(); ++i)
231  (i.value())->fireUpdate();
232  for (i = signalPorts.begin(); i != signalPorts.end(); ++i)
233  (i.value())->fireUpdate();
234 
235  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
236  if (sheetView)
237  sheetView->getSheet().setProperty(component->getProperty("id").toString() + "-pos",
238  QString::number(x())+","+QString::number(y()));
239 
240  }
241 
242  if (change == ItemChildRemovedChange)
243  {
244  // we shall recompute layout for ports !
246  int j=0;
247  QMap<QString,GraphicsPortItem*>::iterator i;
248  for (i = slotPorts.begin(); i != slotPorts.end(); ++i)
249  {
250  i.value()->setPos(-5,QFontMetrics(componentLabel->font()).height()+15*j+5);
251  (i.value())->fireUpdate();
252  j++;
253  }
254  j=0;
255  for (i = signalPorts.begin(); i != signalPorts.end(); ++i)
256  {
257  i.value()->setPos(rect().width()-5,QFontMetrics(componentLabel->font()).height()+15*j+5);
258  (i.value())->fireUpdate();
259  j++;
260  }
261 
263  QRectF rectangle(rect());
264 
265  rectangle.setHeight(QFontMetrics(componentLabel->font()).height()
266  + 15*( (signalPorts.count()>slotPorts.count())?signalPorts.count():slotPorts.count())+5);
267  setRect(rectangle);
268 
269  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
270  if (sheetView)
271  sheetView->getSheet().setProperty(component->getProperty("id").toString() + "-slots",
272  QStringList(slotPorts.keys()).join(";"));
273 
274  }
275 
276 
277  return QGraphicsRectItem::itemChange(change,value);
278 }
279 
280 
281 void GraphicsComponentItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
282 {
283  QStyleOptionGraphicsItem myOptions(*option);
284  if (myOptions.state & (QStyle::State_Selected))
285  {
286  QPen myPen(Qt::darkRed);
287  myPen.setWidth(2);
288  setPen(myPen);
289  componentLabel->setPen(QPen(Qt::darkRed));
290  myOptions.state = myOptions.state ^ QStyle::State_Selected ;
291  }
292  else
293  {
294  setPen(defaultPen);
295  componentLabel->setPen(Qt::NoPen);
296  }
297  QGraphicsRectItem::paint(painter,& myOptions, widget );
298 
299 }
300 
301 
302 void GraphicsComponentItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent */*event*/)
303 {
304  // here we make an editable component.
305  SheetView* sheetView = dynamic_cast<SheetView*>(scene()->views()[0]);
306  if (sheetView)
307  sheetView->sendWidget(new EditComponentWidget(component,sheetView));
308 }
void setProperty(QString name, QString value)
Definition: arcssheet.h:214
QVariant getProperty(QString name)
Gets a meta-property from this component.
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value)
Class handling the generic description of a component.