sheetview.cpp
1 /*
2  name: tools/editor/sheetview.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 "sheetview.h"
30 #include <QDragEnterEvent>
31 #include <QDropEvent>
32 #include <QGraphicsScene>
33 #include <QGraphicsRectItem>
34 #include <QTransform>
35 #include <QMessageBox>
36 
37 #include <QApplication>
38 #include <QClipboard>
39 #include <QMimeData>
40 
41 #include <QMenu>
42 
43 #include <QPen>
44 #include <QBrush>
45 
46 #include <iostream>
47 
48 #include <arcs/arcscompositecomponent.h>
49 
50 #include "graphicscomponentitem.h"
51 #include "graphicslinkitem.h"
52 #include "orderconnectionsdialog.h"
53 
54 /******************************************************************************
55  A sheet should have something in order to store graphical details.
56  The main idea :
57  - list of components that are in the sheet ;
58  - for each components, its coordinates and visible ports ;
59  - for each connection : graphical details.
60 
61 
62  ****************************************************************************/
63 
64 #ifndef MAX
65 #define MAX(A,B) (((A)>(B))?(A):(B))
66 #endif
67 
68 #ifndef MIN
69 #define MIN(A,B) (((A)<(B))?(A):(B))
70 #endif
71 
72 
73 
74 SheetView::SheetView(ARCSSheet& s, QWidget *parent) : QGraphicsView(parent),sheet(s)
75 {
76  setScene(new QGraphicsScene(this));
77  //scene()->setSceneRect(0,0,1024,768);
78 
79  setAcceptDrops(true);
80  setResizeAnchor(QGraphicsView::NoAnchor);
81  setTransformationAnchor(QGraphicsView::NoAnchor);
82 
83  setSceneRect(viewport()->rect());
84  setAlignment(Qt::AlignLeft|Qt::AlignTop);
85 
86  //rectSelection = new QGraphicsRectItem(0,scene());
87  rectSelection = new QGraphicsRectItem();
88  scene()->addItem(rectSelection);
89  rectSelection->setPen(QPen(Qt::darkGreen));
90  rectSelection->setBrush(QBrush(QColor(0,255,0,63)));
91  rectSelection->setVisible(false);
92 
93 
94  // this code is written in order to ease buttons and actions manipulation.
95  actionSelectAll = new QAction("Select all",this);
96  actionSelectAll->setShortcuts(QKeySequence::SelectAll);
97  connect(actionSelectAll,SIGNAL(triggered()),this,SLOT(selectAll()));
98  actionCopy = new QAction("&Copy",this);
99  actionCopy->setShortcuts(QKeySequence::Copy);
100  connect(actionCopy,SIGNAL(triggered()),this,SLOT(copy()));
101  actionPaste = new QAction("&Paste",this);
102  actionPaste->setShortcuts(QKeySequence::Paste);
103  connect(actionPaste,SIGNAL(triggered()),this,SLOT(paste()));
104  actionDelete = new QAction("Delete selection",this);
105  actionDelete->setShortcuts(QKeySequence::Delete);
106  connect(actionDelete,SIGNAL(triggered()),this,SLOT(deleteSelection()));
107  QAction* sep1 = new QAction(this);
108  sep1->setSeparator(true);
109  QAction* sep2 = new QAction(this);
110  sep2->setSeparator(true);
111 
112  actionOrderInvocations = new QAction("Order invocations...",this);
113  connect(actionOrderInvocations,SIGNAL(triggered()),this,SLOT(orderInvocations()));
114  actionOrderConnections = new QAction("Order connections...",this);
115  connect(actionOrderConnections,SIGNAL(triggered()),this,SLOT(orderConnections()));
116 
117 
118  addAction(actionOrderConnections);
119  addAction(actionOrderInvocations);
120  addAction(sep2);
121  addAction(actionCopy);
122  addAction(actionPaste);
123  addAction(actionDelete);
124  addAction(sep1);
125  addAction(actionSelectAll);
126 
127  layoutSheet();
128 
129 }
130 
131 
132 SheetView::~SheetView()
133 {
134  delete scene();
135 
136 }
137 
138 
139 void SheetView::layoutSheet()
140 {
141  int i,j;
142 
143  // first we should read component-list property
144  QString list = sheet.getProperty("component-list");
145  QStringList actualComponents = sheet.getComponentList();
146 
147 
148  if (list.isEmpty())
149  componentList = actualComponents;
150  else
151  componentList = list.split(';').toSet().unite(actualComponents.toSet()).intersect(sheet.getContext()->getComponentList().toSet()).toList();
152 
153 
154  //componentList = list.split(";");
155  for (i=0; i < componentList.count(); i++)
156  {
157  GraphicsComponentItem* gci = new GraphicsComponentItem(sheet.getContext()->getComponent(componentList[i]));
158  gci->show();
159  scene()->addItem(gci);
160  QString pos = sheet.getProperty(componentList[i]+"-pos");
161  if (!pos.isEmpty())
162  gci->setPos(pos.section(",",0,0).toFloat(),pos.section(",",1,1).toFloat());
163 
164  QString slts = sheet.getProperty(componentList[i]+"-slots");
165  if (!slts.isEmpty())
166  {
167  QStringList slotList = slts.split(";");
168  for (j=0; j < slotList.count(); j++ )
169  gci->addSlot(slotList[j],false);
170  }
171  QString sgnls = sheet.getProperty(componentList[i]+"-signals");
172  if (!sgnls.isEmpty())
173  {
174  QStringList signalList = sgnls.split(";");
175  for (j=0; j < signalList.count(); j++ )
176  gci->addSignal(signalList[j],false);
177  }
178  }
179  // after all this, we should assess if all components have been rendered.
180  // if not, we should compute their layout (maybe we can use dot ?)
181 
182 
183  // below, we process connections
184  QStringList sources;
185  QStringList destinations;
186  QStringList signalList;
187  QStringList slotList;
188  QStringList invocationTypes;
189  QStringList invocationValues;
190  sheet.getConnections(sources,signalList,destinations,slotList);
191  for (i=0; i< sources.count(); i++)
192  {
193  ARCSConnection& c = sheet.getConnection(sources[i],signalList[i],destinations[i],slotList[i]);
194 
195 
196  GraphicsComponentItem* srcGComponent = findComponentByName(sources[i]);
197  GraphicsComponentItem* dstGComponent = findComponentByName(destinations[i]);
198  if (srcGComponent && dstGComponent)
199  {
200  GraphicsPortItem* sgnPort = srcGComponent->getSignalPort(signalList[i]);
201  if (!sgnPort)
202  {
203  srcGComponent->addSignal(signalList[i]);
204  sgnPort = srcGComponent->getSignalPort(signalList[i]);
205  }
206 
207  GraphicsPortItem* sltPort = dstGComponent->getSlotPort(slotList[i]);
208  if (!sltPort)
209  {
210  dstGComponent->addSlot(slotList[i]);
211  sltPort = dstGComponent->getSlotPort(slotList[i]);
212 
213  }
214 
215  if (sgnPort && sltPort)
216  {
217  GraphicsLinkItem* link = new GraphicsLinkItem(sgnPort,&c);
218  link->setSource(sgnPort);
219  sgnPort->addLink(link);
220  link->setDestination(sltPort);
221  sltPort->addLink(link);
222  link->show();
223  link->redraw(false);
224  }
225  }
226  }
227 
228  //after all this, we process invocations
229  sheet.getPreconnects(destinations,slotList,invocationTypes,invocationValues);
230  layoutInvocations(GraphicsInvocationItem::Pre,destinations,slotList,invocationTypes,invocationValues);
231  sheet.getPostconnects(destinations,slotList,invocationTypes,invocationValues);
232  layoutInvocations(GraphicsInvocationItem::Post,destinations,slotList,invocationTypes,invocationValues);
233  sheet.getCleanups(destinations,slotList,invocationTypes,invocationValues);
234  layoutInvocations(GraphicsInvocationItem::Cleanup,destinations,slotList,invocationTypes,invocationValues);
235 
236 
237  sheet.setProperty("component-list",componentList.join(";"));
238  if (componentList.count() == 0)
239  actionSelectAll->setEnabled(false);
240  actionCopy->setEnabled(false);
241  actionDelete->setEnabled(false);
242 
243 
244  scene()->setSceneRect(sceneRect().united(scene()->itemsBoundingRect()));
245  setSceneRect(scene()->sceneRect());
246 }
247 
248 void SheetView::layoutInvocations(GraphicsInvocationItem::InvocationType invocationType, QStringList destinations, QStringList slotList, QStringList typeList, QStringList valueList)
249 {
250  for (int i=0; i < destinations.count(); i++)
251  {
252  ARCSInit* init = 0 ; //ARCSInit::null;
253  switch (invocationType)
254  {
255  case GraphicsInvocationItem::Pre:
256  init = &sheet.getPreConnect(destinations[i],slotList[i],typeList[i],valueList[i]);
257  break;
258  case GraphicsInvocationItem::Post:
259  init = &sheet.getPostConnect(destinations[i],slotList[i],typeList[i],valueList[i]);
260  break;
261  case GraphicsInvocationItem::Cleanup:
262  init = &sheet.getCleanup(destinations[i],slotList[i],typeList[i],valueList[i]);
263  break;
264  }
265 
266  GraphicsComponentItem* dstGComponent = findComponentByName(destinations[i]);
267  if (dstGComponent)
268  {
269  GraphicsPortItem* sltPort = dstGComponent->getSlotPort(slotList[i]);
270  if (!sltPort)
271  {
272  dstGComponent->addSlot(slotList[i]);
273  sltPort = dstGComponent->getSlotPort(slotList[i]);
274  }
275  if (sltPort && init )
276  {
278  new GraphicsInvocationItem(sltPort,invocationType,*init);
279  }
280  }
281  }
282 }
283 
284 
285 
286 void SheetView::dragEnterEvent(QDragEnterEvent *event)
287 {
288  if (event->mimeData()->hasFormat("text/plain"))
289  if (event->source()->property("appId") == this->property("appId"))
290  event->acceptProposedAction();
291 }
292 
293 void SheetView::dragMoveEvent(QDragMoveEvent *event)
294 {
295  if (event->mimeData()->hasFormat("text/plain"))
296  if (event->source()->property("appId") == this->property("appId"))
297  event->acceptProposedAction();
298 }
299 
300 
301 void SheetView::dropEvent(QDropEvent *event)
302 {
303  if (event->source()->property("appId") != this->property("appId"))
304  return;
305 
306  addComponent( event->pos(),event->mimeData()->text());
307  event->acceptProposedAction();
308 }
309 
310 
311 
312 void SheetView::updateSheet()
313 {
314  clearScene();
315  layoutSheet();
316 }
317 
318 
319 void SheetView::clearScene()
320 {
321  // clearing the scene is somewhat complicated.
322  // it is better to do it in the right order
323  int i;
324  QList<QGraphicsItem*> itemList = scene()->items();
325  for (i=0; i < itemList.count();i++)
326  {
327  if (itemList[i]->type() == GraphicsComponentItem::Type)
328  {
329  GraphicsComponentItem* item = dynamic_cast<GraphicsComponentItem*>(itemList[i]);
330  delete item;
331  // each time an item is removed from list, we must regenerate list of selected items.
332  itemList = scene()->items();
333  i=-1;
334  }
335  }
336 
337 
338  itemList = scene()->items();
339  for (i=0; i < itemList.count();i++)
340  {
341  if (itemList[i]->type() == GraphicsPortItem::Type)
342  {
343  GraphicsPortItem* item = dynamic_cast<GraphicsPortItem*>(itemList[i]);
344  delete item;
345  // each time an item is removed from list, we must regenerate list of selected items.
346  itemList = scene()->items();
347  i=-1;
348  }
349  }
350 
351  itemList = scene()->items();
352  for (i=0; i < itemList.count(); i++)
353  {
354  if (itemList[i]->type() == GraphicsInvocationItem::Type)
355  {
356  GraphicsInvocationItem* item = dynamic_cast<GraphicsInvocationItem*>(itemList[i]);
357  delete item;
358  // each time an item is removed from list, we must regenerate list of selected items.
359  itemList = scene()->items();
360  i=-1;
361 
362  }
363  else
364  {
365  if (itemList[i]->type() == GraphicsLinkItem::Type )
366  {
367  GraphicsLinkItem* item = dynamic_cast<GraphicsLinkItem*>(itemList[i]);
368  delete item;
369  // each time an item is removed from list, we must regenerate list of selected items.
370  itemList = scene()->items();
371  i=-1;
372  }
373  }
374 
375  }
376  //scene()->clear();
377 
378  actionSelectAll->setEnabled(false);
379  actionCopy->setEnabled(false);
380 }
381 
382 
383 
384 void SheetView::addComponent(QPoint p, QString name)
385 {
386  ARCSContext* ctx=sheet.getContext();
387  if (!ctx )
388  return ;
389 
390  if (!scene())
391  return ;
392 
393  QStringList sl = ctx->getComponentList();
394 
395  if (!ctx->getComponent(name))
396  {
397  std::cerr << "component not found" << std::endl;
398  return ;
399  }
400 
401  // here we should also check if the component is already in the sheet or not.
402  // therefore sheets should have data on components that are inside them.
403 
404  if (componentList.contains(name))
405  return ;
406 
407  componentList.append(name);
408  sheet.setProperty("component-list",componentList.join(";"));
409 
410  // now let's draw our component.
412  QTransform tr = transform();
413 
414  gci->setPos(mapToScene(tr.map(p)));
415  gci->show();
416  scene()->addItem(gci);
418  sheet.setProperty(name+"-pos",QString::number(gci->pos().x())+","+QString::number(gci->pos().y()));
419 
420  scene()->setSceneRect(sceneRect().united(scene()->itemsBoundingRect()));
421  setSceneRect(scene()->sceneRect());
422  actionSelectAll->setEnabled(true);
423 }
424 
425 
426 
427 GraphicsComponentItem* SheetView::findComponentByName(QString name)
428 {
430  QList<QGraphicsItem*> items = scene()->items();
431  for (int i=0; i<items.count(); i++)
432  {
433  if (items[i]->type() == GraphicsComponentItem::Type)
434  {
435  GraphicsComponentItem* gItem = dynamic_cast<GraphicsComponentItem*>(items[i]);
436  if (gItem->getComponent()->getProperty("id").toString() == name)
437  return gItem;
438  }
439 
440  }
441  return 0;
442 }
443 
444 
445 void SheetView::mouseMoveEvent(QMouseEvent *event)
446 {
447  if (event->buttons() & Qt::LeftButton)
448  {
449  scene()->setSceneRect(sceneRect().united(scene()->itemsBoundingRect()));
450  setSceneRect(scene()->sceneRect());
451  if (rectSelection->isVisible())
452  {
453  QTransform tr = transform();
454  QPointF endPos = mapToScene(tr.map(event->pos()));
455 
456  QPointF lowerLeft( MIN(rectSelection->x(),endPos.x()), MIN(rectSelection->y(),endPos.y()) );
457  QPointF upperRight(MAX(rectSelection->x(),endPos.x()), MAX(rectSelection->y(),endPos.y()) );
458 
459  rectSelection->setRect(QRectF(lowerLeft - rectSelection->pos(), upperRight - rectSelection->pos()));
460  }
461  //event->setAccepted(true);
462  //return;
463  }
464  QGraphicsView::mouseMoveEvent(event);
465 }
466 
467 
468 void SheetView::mousePressEvent(QMouseEvent *event)
469 {
470 
471  if (event->buttons() & Qt::LeftButton)
472  {
473  QTransform tr = transform();
474 
475  QPointF posStart = mapToScene(tr.map(event->pos()));
476 
477  QList<QGraphicsItem*> items = scene()->items(posStart);
478 
479 
480  if (!items.count())
481  {
482  rectSelection->setVisible(true);
483  rectSelection->setRect(0,0,2,2);
484  rectSelection->setPos(posStart);
485  }
486  //event->setAccepted(true);
487  //return;
488  }
489 
490 
491  QGraphicsView::mousePressEvent(event);
492 }
493 
494 
495 void SheetView::mouseReleaseEvent(QMouseEvent *event)
496 {
497  if (rectSelection->isVisible())
498  {
499  QList<QGraphicsItem*> items = scene()->items(rectSelection->mapToScene(rectSelection->rect()));
500  for (int i = 0; i< items.count(); i++)
501  {
502  if (items[i] != rectSelection)
503  items[i]->setSelected(true);
504  }
505  }
506  QGraphicsView::mouseReleaseEvent(event);
507  rectSelection->setVisible(false);
508 
509  actionCopy->setEnabled(scene()->selectedItems().count());
510  actionDelete->setEnabled(scene()->selectedItems().count());
511 }
512 
513 void SheetView::contextMenuEvent(QContextMenuEvent *event)
514 {
515  QTransform tr = transform();
516  QPointF posStart = mapToScene(tr.map(event->pos()));
517  QList<QGraphicsItem*> items = scene()->items(posStart);
518 
519 
520  if (items.count() != 0)
521  {
522  QGraphicsView::contextMenuEvent(event);
523  }
524  else
525  {
526  QMenu menu;
527  menu.addActions(this->actions());
528  menu.exec(event->globalPos());
529  }
530 }
531 
532 
533 void SheetView::deleteSelection()
534 {
535  // deletion is not a simple task :
536  // it should be in the accurate order :
537  // - first process components, then regenerate list of selectedItems;
538  // - then ports and again regeneration
539  // - finally invocations as well as links in any order
540  QList<QGraphicsItem*> itemList = scene()->selectedItems();
541  itemList = scene()->selectedItems();
542  QString name;
543  int i;
544  for (i=0; i < itemList.count();i++)
545  {
546  if (itemList[i]->type() == GraphicsComponentItem::Type)
547  {
548  GraphicsComponentItem* item = dynamic_cast<GraphicsComponentItem*>(itemList[i]);
549  name = item->getComponent()->getProperty("id").toString();
550  componentList.removeAll(name);
551  item->markForDeletion();
552  delete item;
553  // each time an item is removed from list, we must regenerate list of selected items.
554  itemList = scene()->selectedItems();
555  i=-1;
556  }
557  }
558  sheet.setProperty("component-list",componentList.join(";"));
559 
560 
561  itemList = scene()->selectedItems();
562  for (i=0; i < itemList.count();i++)
563  {
564  if (itemList[i]->type() == GraphicsPortItem::Type)
565  {
566  GraphicsPortItem* item = dynamic_cast<GraphicsPortItem*>(itemList[i]);
567  item->markForDeletion();
568  delete item;
569  // each time an item is removed from list, we must regenerate list of selected items.
570  itemList = scene()->selectedItems();
571  i=-1;
572 
573  }
574 
575  }
576 
577  itemList = scene()->selectedItems();
578  for (i=0; i < itemList.count(); i++)
579  {
580  if (itemList[i]->type() == GraphicsInvocationItem::Type)
581  {
582  GraphicsInvocationItem* item = dynamic_cast<GraphicsInvocationItem*>(itemList[i]);
583  item->markForDeletion();
584  delete item;
585  // each time an item is removed from list, we must regenerate list of selected items.
586  itemList = scene()->selectedItems();
587  i=-1;
588 
589  }
590  else
591  {
592  if (itemList[i]->type() == GraphicsLinkItem::Type )
593  {
594  GraphicsLinkItem* item = dynamic_cast<GraphicsLinkItem*>(itemList[i]);
595  item->markForDeletion();
596  delete item;
597  // each time an item is removed from list, we must regenerate list of selected items.
598  itemList = scene()->selectedItems();
599  i=-1;
600  }
601  }
602 
603  }
604  actionCopy->setEnabled(scene()->selectedItems().count());
605  actionDelete->setEnabled(scene()->selectedItems().count());
606  actionSelectAll->setEnabled(false);
607 }
608 
609 void SheetView::clearSelection()
610 {
611  QList<QGraphicsItem*> items = scene()->selectedItems();
612  for (int i=0; i< items.count(); i++)
613  items[i]->setSelected(false);
614 
615  actionCopy->setEnabled(scene()->selectedItems().count());
616  actionDelete->setEnabled(scene()->selectedItems().count());
617 
618 }
619 
620 void SheetView::selectAll()
621 {
622  QList<QGraphicsItem*> items = scene()->items();
623  for (int i=0; i< items.count(); i++)
624  items[i]->setSelected(true);
625 
626  actionCopy->setEnabled(scene()->selectedItems().count());
627  actionDelete->setEnabled(scene()->selectedItems().count());
628 
629 }
630 
631 
632 
633 
635 {
636  int i;
637  // first we create the needed structures
639  ARCSContext* copyContext = new ARCSContext();
640  ARCSSheet* copySheet = new ARCSSheet(copyContext);
641 
642  // now we should look into selected elements.
643  // it will be done using two passes.
644  // the first one is to look for components.
645  // the second one is to assess invocations and links.
646 
647  QList<QGraphicsItem*> selectedItems = scene()->selectedItems();
648 
649  for (i=0; i < selectedItems.count(); i++)
650  {
651  if (selectedItems[i]->type() == GraphicsComponentItem::Type)
652  {
653  ARCSAbstractComponent* origComponent = dynamic_cast<GraphicsComponentItem*>(selectedItems[i])->getComponent();
654  if (! copyContext->addComponent(origComponent->getProperty("id").toString(), origComponent->getType(), origComponent->toString()))
655  std::cerr << "problem creating component " << qPrintable(origComponent->getProperty("id").toString()) << std::endl;
656  }
657  }
658  QStringList copiedComponents = copyContext->getComponentList();
660  copySheet->setProperty("component-list",copiedComponents.join(";"));
661 
662  for (i=0; i < copiedComponents.count(); i++ )
663  {
664  /* we remap coordinates */
665  QString propertyString = sheet.getProperty(copiedComponents[i]+"-pos");
666  QPointF pos = QPointF(propertyString.section(",",0,0).toFloat(),
667  propertyString.section(",",1,1).toFloat()) ;
668  pos -= mapToScene(0,0);
669  copySheet->setProperty(copiedComponents[i]+"-pos",QString::number(pos.x())+","+QString::number(pos.y()));
670  /* end of remapping */
671  copySheet->setProperty(copiedComponents[i]+"-slots",sheet.getProperty(copiedComponents[i]+"-slots"));
672  copySheet->setProperty(copiedComponents[i]+"-signals",sheet.getProperty(copiedComponents[i]+"-signals"));
673  }
674 
676  // Once the components are selected, we can look for invocations and links.
677  for (i=0; i< selectedItems.count(); i++)
678  {
679  if (selectedItems[i]->type() == GraphicsLinkItem::Type)
680  {
681  ARCSConnection* origLink = dynamic_cast<GraphicsLinkItem*>(selectedItems[i])->getConnection();
682  QString origSource = origLink->getSourceName();
683  QString origDestination = origLink->getDestinationName();
684  if (copiedComponents.contains(origSource) && copiedComponents.contains(origDestination))
685  {
686  ARCSConnection& copyLink = copySheet->addConnection(origSource,origLink->getSignalName(),
687  origDestination,origLink->getSlotName(),
688  origLink->isQueued());
689  copyLink.setCoordinates(origLink->getCoordinates());
690  std::cout << "Connection append" << std::endl;
691  }
692  }
693  if (selectedItems[i]->type() == GraphicsInvocationItem::Type)
694  {
695  ARCSInit& origInvocation = dynamic_cast<GraphicsInvocationItem*>(selectedItems[i])->getInvocation();
696  GraphicsInvocationItem::InvocationType origInvocationType = dynamic_cast<GraphicsInvocationItem*>(selectedItems[i])->getInvocationType();
697  QString origDestination = origInvocation.getDestinationName();
698  if (copiedComponents.contains(origDestination))
699  {
700  switch(origInvocationType)
701  {
702  case GraphicsInvocationItem::Pre:
703  copySheet->addPreconnect(origDestination, origInvocation.getSlotName(),origInvocation.getValueType(), origInvocation.getValueString());
704  break;
705  case GraphicsInvocationItem::Post:
706  copySheet->addPostconnect(origDestination, origInvocation.getSlotName(),origInvocation.getValueType(), origInvocation.getValueString());
707  break;
708  case GraphicsInvocationItem::Cleanup:
709  copySheet->addCleanup(origDestination, origInvocation.getSlotName(),origInvocation.getValueType(), origInvocation.getValueString());
710  break;
711  }
712  std::cout << "invocation append" << std::endl;
713  }
714  }
715  }
716 
717  acc->setSheet(*copySheet);
718  // once all is set, we prepare clipBoard data
719  QClipboard *clipboard = QApplication::clipboard();
720  QString copyText = acc->toString();
721  clipboard->clear();
722  clipboard->setText(copyText);
723 
724  // last thing, we do some cleanup
725  delete acc;
726  delete copySheet;
727  delete copyContext;
728 }
729 
730 
731 
732 void SheetView::paste()
733 {
734  int i,j/*,k*/;
735  // first, we should recover data
736  QClipboard *clipboard = QApplication::clipboard();
737  QString dataString = clipboard->text();
738  QPointF offsetPos = mapToScene(0,0);//sceneRect().bottomLeft();
739 
740  QRectF rect = sceneRect();
741  std::cout << "offsetPos: " << offsetPos.x() << ", " << offsetPos.y() << std::endl;
742  std::cout << "sceneRect: " << rect.x() << ", " << rect.y() << ": " << rect.width() << "x" << rect.height() << std::endl;
743 
744  // now we should create a composite component standing on its feets !
746  if (!acc->parseString(dataString))
747  return ;
748 
749  // acc now contains a lot of things.
750  // We will have to fuse them with the current sheet as well as reactualize the context !
751  ARCSSheet* incomingSheet = acc->getSheet();
752  ARCSContext* incomingContext = incomingSheet->getContext();//acc->getContext();
753 
754  QStringList actualComponents = sheet.getContext()->getComponentList();
755  QStringList incomingComponents = incomingContext->getComponentList();
756  QMap<QString,QString> renamedComponents;
757 
758  // first pass: we have some components we will have to rename and add them to context
759  for (i=0; i < incomingComponents.count(); i++)
760  {
761  QString candidateComponent = incomingComponents[i];
762  ARCSAbstractComponent* aac = incomingContext->getComponent(candidateComponent);
763  while (actualComponents.contains(candidateComponent) || renamedComponents.contains(candidateComponent))
764  {
765  // let's rename the component
766  candidateComponent += "_";
767  }
768  if (actualComponents.contains(incomingComponents[i]))
769  renamedComponents[incomingComponents[i]] = candidateComponent;
770 
771  std::cout << "Adding one component" << std::endl;
772  sheet.getContext()->addComponent(candidateComponent, aac->getType(), aac->toString());
773 
774  // let's look for properties inside this.
775  QString propertyString;
776  if (! (propertyString =incomingSheet->getProperty(incomingComponents[i] + "-slots")).isEmpty())
777  sheet.setProperty(candidateComponent+ "-slots",propertyString);
778  if (! (propertyString =incomingSheet->getProperty(incomingComponents[i] + "-signals")).isEmpty())
779  sheet.setProperty(candidateComponent+"-signals",propertyString);
780  if (! (propertyString =incomingSheet->getProperty(incomingComponents[i] + "-pos")).isEmpty())
781  {
782  QPointF pos = QPointF(propertyString.section(",",0,0).toFloat(),
783  propertyString.section(",",1,1).toFloat()) + offsetPos ;
784  sheet.setProperty(candidateComponent+"-pos",
785  QString::number(pos.x())+","+QString::number(pos.y()));
786  }
787  }
788 
789  // then we also look for the connections and invocations
790  QStringList sources;
791  QStringList destinations;
792  QStringList signalList;
793  QStringList slotList;
794  QStringList invocationTypes;
795  QStringList invocationValues;
796  QString source, destination;
797  incomingSheet->getConnections(sources,signalList,destinations,slotList);
798  for (i=0; i< sources.count(); i++)
799  {
800  ARCSConnection& c = incomingSheet->getConnection(sources[i],signalList[i],destinations[i],slotList[i]);
801  source = (renamedComponents.contains(sources[i]))?renamedComponents[sources[i]]:sources[i];
802  destination = (renamedComponents.contains(destinations[i]))?renamedComponents[destinations[i]]:destinations[i];
803  ARCSConnection& cbis = sheet.addConnection(source, signalList[i],destination, slotList[i], c.isQueued());
804  QList<QPointF> coords = c.getCoordinates();
805  for (j=0; j< 4 ; j++)
806  {
807  coords[i] += offsetPos;
808  }
809  cbis.setCoordinates(c.getCoordinates());
810 
811  }
812  incomingSheet->getPreconnects(destinations,slotList,invocationTypes,invocationValues);
813  for (i=0; i< destinations.count();i++)
814  {
815  destination = (renamedComponents.contains(destinations[i]))?renamedComponents[destinations[i]]:destinations[i];
816  sheet.addPreconnect(destination, slotList[i], invocationTypes[i], invocationValues[i]);
817  }
818  incomingSheet->getPostconnects(destinations,slotList,invocationTypes,invocationValues);
819  for (i=0; i< destinations.count();i++)
820  {
821  destination = (renamedComponents.contains(destinations[i]))?renamedComponents[destinations[i]]:destinations[i];
822  sheet.addPostconnect(destination, slotList[i], invocationTypes[i], invocationValues[i]);
823  }
824  incomingSheet->getCleanups(destinations,slotList,invocationTypes,invocationValues);
825  for (i=0; i< destinations.count();i++)
826  {
827  destination = (renamedComponents.contains(destinations[i]))?renamedComponents[destinations[i]]:destinations[i];
828  sheet.addCleanup(destination, slotList[i], invocationTypes[i], invocationValues[i]);
829  }
830 
831  /* right now we clear the scene and make a new layout.
832  * selection is cleared and only new components are selected
833  * it could help moving the new components in a more interesting location.
834  */
835  clearScene();
836  layoutSheet();
837 
838  scene()->clearSelection();
839  for(i=0; i < incomingComponents.count(); i++)
840  {
841  if (renamedComponents.contains(incomingComponents[i]))
842  findComponentByName(renamedComponents[incomingComponents[i]])->setSelected(true);
843  else
844  findComponentByName(incomingComponents[i])->setSelected(true);
845  }
846 
847  emit requestApplicationUpdate();
848 
849  actionCopy->setEnabled(scene()->selectedItems().count());
850  actionDelete->setEnabled(scene()->selectedItems().count());
851  actionSelectAll->setEnabled(true);
852 }
853 
854 void SheetView::orderInvocations()
855 {
856 
857 
858 }
859 
860 
861 void SheetView::orderConnections()
862 {
863  OrderConnectionsDialog* ocd= new OrderConnectionsDialog(&sheet,this);
864  ocd->exec();
865 
866 }
virtual QString toString()
Defines a basic seralization mechanism.
ARCSInit & addCleanup(QString dst, QString slt, QString t, QString val)
Adds a cleanup invocation to the sheet structure.
Definition: arcssheet.h:98
Class defining a composite component i.e. a component made of components.
virtual QString toString()=0
Defines a basic seralization mechanism.
virtual bool parseString(QString s)
Defines a basic seralization mechanism.
QString getSlotName()
void addComponent(QPoint p, QString name)
Definition: sheetview.cpp:384
void setSheet(ARCSSheet ref)
Sets the sheet to use as an internal description of embedded components.
QString getProperty(QString name)
Definition: arcssheet.h:216
QStringList getComponentList()
ARCSSheet * getSheet()
Returns the internal structure of this composite component described as a sheet.
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
bool addComponent(QString name, QString className, QString contents=QString::null)
Adds a component to the list.
QString getValueString()
Definition: arcsinit.cpp:110
Describes a connection.
void setProperty(QString name, QString value)
Definition: arcssheet.h:214
QVariant getProperty(QString name)
Gets a meta-property from this component.
void getCleanups(QStringList &destinations, QStringList &slts, QStringList &types, QStringList &values)
Allows to retrieve cleanup invocations.
Definition: arcssheet.h:176
Class handling the generic description of a component.
QStringList getComponentList()
Retrieves the list of components that are used in this sheet.
Definition: arcssheet.cpp:74
QString getSignalName()
void copy()
Definition: sheetview.cpp:634
ARCSAbstractComponent * getComponent(QString name)
Retrieves a component by its id.
void getConnections(QStringList &sources, QStringList &signls, QStringList &destinations, QStringList &slts)
Allows to retrieve connections.
Definition: arcssheet.cpp:248
void getPostconnects(QStringList &destinations, QStringList &slts, QStringList &types, QStringList &values)
Allows to retrieve postconnection invocations.
Definition: arcssheet.h:165
This class manages components and constants in a given context.
Definition: arcscontext.h:45
ARCSConnection & addConnection(QString src, QString sgn, QString dst, QString slt, bool q=false, bool head=false)
Adds a connection to the sheet structure.
Definition: arcssheet.cpp:183
QString getSlotName()
Definition: arcsinit.h:73
QString getValueType()
Definition: arcsinit.cpp:102
ARCSConnection & getConnection(QString source, QString sgn, QString dst, QString slt)
returns a reference to a connection in the sheet structure
Definition: arcssheet.cpp:206
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
void getPreconnects(QStringList &destinations, QStringList &slts, QStringList &types, QStringList &values)
Allows to retrieve preconnection invocations.
Definition: arcssheet.h:154