Beispiel #1
0
void ClassDiagramView::save(QTextStream & st, QString & warning,
			    bool copy) const {
  DiagramItemList items(canvas()->allItems());
  DiagramItem * di;
  
  if (!copy)
    // sort is useless for a copy
    items.sort();
    
  st << "format " << FILEFORMAT << "\n";
  
  // save first the classes packages fragment notes and icons
  
  for (di = items.first(); di != 0; di = items.next()) {
    switch (di->type()) {
    case UmlClass:
    case UmlNote:
    case UmlText:
    case UmlImage:
    case UmlPackage:
    case UmlFragment:
    case UmlIcon:
      if (!copy || di->copyable())
	di->save(st, FALSE, warning);
      // no break
    default:
      break;
    }
  }

  // then saves relations
  
  for (di = items.first(); di != 0; di = items.next()) {
    if (!copy || di->copyable()) {
      UmlCode k = di->type();
      
      if (IsaRelation(k) || IsaSimpleRelation(k) || (k == UmlInner))
	di->save(st, FALSE, warning);
    }
  }
  
  // then saves anchors
  
  for (di = items.first(); di != 0; di = items.next())
    if ((!copy || di->copyable()) && (di->type() == UmlAnchor))
      di->save(st, FALSE, warning);
  
  if (!copy && (preferred_zoom != 0)) {
    nl_indent(st);
    st << "preferred_whz " << preferred_size.width() << ' '
      << preferred_size.height() << ' ' << preferred_zoom;
  }
  
  nl_indent(st);
  st << "end\n";
}
// if elt parent is present, force inside it
bool ActivityContainerCanvas::force_inside(DiagramCanvas * elt, bool part)
{
  // if its parent is present, force inside it  
  Q3CanvasItemList all = elt->the_canvas()->allItems();
  Q3CanvasItemList::Iterator cit;
  BrowserNode * parent = (BrowserNode *) elt->get_bn()->parent();

  for (cit = all.begin(); cit != all.end(); ++cit) {
    if ((*cit)->visible()) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
      
      if ((di != 0) &&
	  IsaActivityContainer(di->type(), part) &&
	  (((ActivityContainerCanvas *) di)->get_bn() == parent)) {
	BooL under = FALSE;
	
	((ActivityContainerCanvas *) di)->force_inside(elt, elt, under);
	
	if (under)
	  elt->upper();
	
	return TRUE;
      }
    }
  }
  
  elt->upper();
  return FALSE;
}
Beispiel #3
0
void SubjectCanvas::send(ToolCom * com, Q3CanvasItemList & all)
{
  Q3PtrList<SubjectCanvas> subjects;
  Q3CanvasItemList::Iterator cit;

  for (cit = all.begin(); cit != all.end(); ++cit) {
    DiagramItem *di = QCanvasItemToDiagramItem(*cit);
    
    if ((di != 0) && 
	(*cit)->visible() &&
	(di->type() == UmlSubject))
      subjects.append((SubjectCanvas *) di);
  }
  
  com->write_unsigned(subjects.count());
  
  SubjectCanvas * sc;
  
  for (sc = subjects.first(); sc != 0; sc = subjects.next()) {
    Q3CString s = fromUnicode(sc->name);
    
    com->write_string((const char *) s);
    com->write(sc->rect());
  }
}
Beispiel #4
0
void ColDiagramView::update_msg_supports()
{
    Q3CanvasItemList l = canvas()->allItems();
    Q3CanvasItemList::Iterator it;

    for (it = l.begin(); it != l.end(); ++it) {
        if ((*it)->visible()) { // at least not deleted
            DiagramItem * di = QCanvasItemToDiagramItem(*it);

            if (di != 0) {
                switch (di->type()) {
                case UmlSelfLink:
                    ((CodSelfLinkCanvas *) di)->update_msgs();
                    break;

                case UmlLinkDirs:
                    ((CodDirsCanvas *) di)->update_msgs();
                    break;

                default:	// to avoid compiler warning
                    break;
                }
            }
        }
    }
}
Beispiel #5
0
void ArtifactCanvas::draw_all_relations() {
  if (strcmp(browser_node->get_stereotype(), "source") != 0)
    // may start association
    update_relations();
  else if (!DrawingSettings::just_modified() &&
	   !on_load_diagram()) {
    // remove all association starting from 'this'
    Q3PtrListIterator<ArrowCanvas> it(lines);
    
    while (it.current()) {
      if ((it.current()->type() == UmlContain) &&
	  (((AssocContainCanvas *) it.current())->get_start() == this))
	it.current()->delete_it();
      else
	++it;
    }
    
    // update non source artifact vis a vis 'this'
    Q3CanvasItemList all = canvas()->allItems();
    Q3CanvasItemList::Iterator cit;
    
    for (cit = all.begin(); cit != all.end(); ++cit) {
      if ((*cit)->visible()) {
	DiagramItem * adi = QCanvasItemToDiagramItem(*cit);
	
	if ((adi != 0) &&		// an uml canvas item
	    (adi->type() == UmlArtifact) &&
	    strcmp(((ArtifactCanvas *) adi)->browser_node->get_stereotype(), "source"))
	  ((ArtifactCanvas *) adi)->update_relations(this);
      }
    }
  }
}
BrowserNode * ActivityDiagramView::container(const QPoint & p, bool part)
{
    Q3CanvasItem * ci = the_canvas()->collision(p);
    DiagramItem * di;

    return ((ci != 0) &&
            ((di = QCanvasItemToDiagramItem(ci)) != 0) &&
            IsaActivityContainer(di->type(), part))
           ? ((ActivityContainerCanvas *) di)->get_bn()
           : (BrowserNode *) window()->browser_diagram()->parent();
}
void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if (line != 0 && myMode == InsertLine)
    {
        QList<QGraphicsItem *> startItems = items(line->line().p1());
        if (startItems.count() && startItems.first() == line)
            startItems.removeFirst();
        QList<QGraphicsItem *> endItems = items(line->line().p2());
        if (endItems.count() && endItems.first() == line)
            endItems.removeFirst();

        removeItem(line);
        delete line;

        if (startItems.count() > 0 && endItems.count() > 0 &&
                startItems.first()->type() == Connector::Type &&
                endItems.first()->type() == Connector::Type &&
                startItems.first() != endItems.first())
        {
            Connector *startItem =
                    qgraphicsitem_cast<Connector *>(startItems.first());
            Connector *endItem =
                    qgraphicsitem_cast<Connector *>(endItems.first());
            QDomNode arrowXml =  createArrowXml(startItem,endItem);
            Arrow *arrow = new Arrow(startItem, endItem,arrowXml);

            arrowList.append(arrow);
            arrow->setColor(myLineColor);
            startItem->addArrow(arrow);
            endItem->addArrow(arrow);
            arrow->setZValue(-1000.0);
            addItem(arrow);
            arrow->updatePosition();

        }
    }

    line = 0;
    QGraphicsScene::mouseReleaseEvent(mouseEvent);
    if(myMode == MoveItem)
    {
        DiagramItem* item =(DiagramItem*)itemAt(mouseEvent->scenePos());
        if(item == 0)
            return;
        if(item->type() == DiagramItem::Type)
            {
                item->updatePoz();
                ((DiagramWindow*)parent())->updateXml();
            }
    }
}
Beispiel #8
0
bool UmlCanvas::already_drawn(BrowserNode * bn) {
  Q3CanvasItemList all = allItems();
  Q3CanvasItemList::Iterator cit;
  UmlCode k = bn->get_type();

  for (cit = all.begin(); cit != all.end(); ++cit) {
    if ((*cit)->visible()) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
    
      if ((di != 0) && (di->type() == k) && (di->get_bn() == bn))
	return TRUE;
    }
  }

  return FALSE;
}
// update sub nodes to be upper this, recursively
void ActivityContainerCanvas::force_sub_upper(Q3CanvasItemList & all) {
  Q3CanvasItemList::Iterator cit;
  BrowserNode * browser_node = get_bn();
  
  for (cit = all.begin(); cit != all.end(); ++cit) {
    if ((*cit)->visible()) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
      
      if ((di != 0) &&
	  (di->get_bn() != 0) &&
	  (((BrowserNode *) di->get_bn())->parent() == browser_node)) {
	  // must look at the type because some canvas items have browser_node
	  // attr equals to the diagram and the parent of the diagram is the activity
	  switch (di->type()) {
	  case UmlActivityObject:
	  case UmlActivityAction:
	  case UmlActivityPartition:
	  case UmlExpansionRegion:
	  case UmlInterruptibleActivityRegion:
	  case InitialAN:
	  case FlowFinalAN:
	  case ActivityFinalAN:
	  case DecisionAN:
	  case MergeAN:
	  case ForkAN:
	  case JoinAN:	    
	    if ((*cit)->z() <= z())
	      ((DiagramCanvas *) di)->upper();
	    
	    {
	      ActivityContainerCanvas * cntr =
		dynamic_cast<ActivityContainerCanvas *>(di);
	      
	      if (cntr != 0)
		cntr->force_sub_upper(all);
	    }
	    break;
	  default:
	    break;
	  }
      }
    }
  }  
}
Beispiel #10
0
static void get_drawn(DiagramItemList & items,
		      Q3PtrDict<DiagramItem> & drawn)
{
  DiagramItem * di;
  
  for (di = items.first(); di != 0; di = items.next()) {
    UmlCode k = di->type();
    
    switch (k) {
    case UmlComponent:
    case UmlPackage:
      drawn.replace(di->get_bn()->get_data(), di);
      break;
    default:
      if (IsaSimpleRelation(k))
	drawn.replace(((ArrowCanvas *) di)->get_data(), di);
    }
  }
}
Beispiel #11
0
void DiagramItem::remove_if_already_present()
{
    const UmlCode k = type();
    const BrowserNode * bn = get_bn();
    IdIterator<DiagramItem> it(the_canvas()->get_all_items());
    DiagramItem * di;

    while ((di = it.current()) != 0) {
        if ((di->type() == k) && (di->get_bn() == bn) && (di != this)) {
            // already present
            if (Undefined.isEmpty())
                msg_warning("Douml", TR("some elements already present in the diagram are NOT paste"));

            Undefined.append(this);
            return;
        }

        ++it;
    }
}
Beispiel #12
0
void TextCanvas::send(ToolCom * com, QCanvasItemList & all)
{
    QCanvasItemList::Iterator cit;

    for (cit = all.begin(); cit != all.end(); ++cit) {
        DiagramItem *di = QCanvasItemToDiagramItem(*cit);

        if ((di != 0) &&
                (*cit)->visible() &&
                (di->type() == UmlText)) {
            TextCanvas * tx = (TextCanvas *) di;
            QCString s = fromUnicode(tx->text);

            com->write_bool(TRUE);	// one more
            com->write_string((const char *) s);
            com->write(tx->rect());
        }
    }

    com->write_bool(FALSE);	// done
}
Beispiel #13
0
bool ActivityActionCanvas::force_inside() {
  // if its parent is present, force inside it
  
  QCanvasItemList all = the_canvas()->allItems();
  QCanvasItemList::Iterator cit;
  BrowserNode * parent = (BrowserNode *) browser_node->parent();

  for (cit = all.begin(); cit != all.end(); ++cit) {
    if ((*cit)->visible()) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
      
      if ((di != 0) &&
	  IsaActivityContainer(di->type()) &&
	  (((ActivityContainerCanvas *) di)->get_bn() == parent)) {
	((ActivityContainerCanvas *) di)->force_inside(this, this);
	return TRUE;
      }
    }
  }
  
  return FALSE;
}
Beispiel #14
0
void CodClassInstCanvas::send(ToolCom * com, QCanvasItemList & all)
{
  QList<CodClassInstCanvas> l;
  QCanvasItemList::Iterator cit;

  for (cit = all.begin(); cit != all.end(); ++cit) {
    DiagramItem *di = QCanvasItemToDiagramItem(*cit);
    
    if ((di != 0) && (*cit)->visible()) {
       switch (di->type()) {
       case UmlClass:
       case UmlClassInstance:
	 l.append((CodClassInstCanvas *) di);
	 break;
       default:
	 break;
       }
    }
  }

  com->write_unsigned(l.count());
  
  QListIterator<CodClassInstCanvas> it(l);
  
  for (; it.current(); ++it) {
    CodClassInstCanvas * i = it.current();
    
    com->write_unsigned((unsigned) i->get_ident());
    if (i->browser_node->get_type() == UmlClass) {      
      com->write_id(0);
      
      QCString s = fromUnicode(i->iname);
      
      com->write_string((const char *) s);
    }
    i->browser_node->write_id(com);
  }
}
// update sub nodes position to be inside this
void ActivityContainerCanvas::force_sub_inside(Q3CanvasItemList & all,
					       BooL & need_sub_upper) {
  Q3CanvasItemList::Iterator cit;
  BrowserNode * browser_node = get_bn();
  
  for (cit = all.begin(); cit != all.end(); ++cit) {
    if ((*cit)->visible()/* && !(*cit)->selected()*/) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
      
      if ((di != 0) &&
	  (di->get_bn() != 0) &&
	  (((BrowserNode *) di->get_bn())->parent() == browser_node)) {
	// must look at the type because some canvas items have browser_node
	// attr equals to the diagram and the parent of the diagram is the activity
	switch (di->type()) {
	case UmlActivityObject:
	case UmlActivityAction:
	case UmlActivityPartition:
	case UmlExpansionRegion:
	case UmlInterruptibleActivityRegion:
	case InitialAN:
	case FlowFinalAN:
	case ActivityFinalAN:
	case DecisionAN:
	case MergeAN:
	case ForkAN:
	case JoinAN:
	  force_inside(di, *cit, need_sub_upper);
	  break;
	default:
	  break;
	}
      }
    }
  }
}
Beispiel #16
0
void UcUseCaseCanvas::send(ToolCom * com, Q3CanvasItemList & all)
{
  Q3PtrList<UcUseCaseCanvas> lu;
  Q3PtrList<UcClassCanvas> la;
  Q3CanvasItemList::Iterator cit;

  for (cit = all.begin(); cit != all.end(); ++cit) {
    DiagramItem *di = QCanvasItemToDiagramItem(*cit);
    
    if ((di != 0) && (*cit)->visible()) {
      switch (di->type()) {
      case UmlUseCase:
	lu.append((UcUseCaseCanvas *) di);
	break;
      case UmlClass:
	la.append((UcClassCanvas *) di);
	break;
      default:
	break;
      }
    }
  }
  
  // send UC
  
  com->write_unsigned(lu.count());
  
  Q3PtrListIterator<UcUseCaseCanvas> itu(lu);
  
  for (; itu.current(); ++itu) {
    com->write_unsigned((unsigned) itu.current()->get_ident());
    itu.current()->get_bn()->write_id(com);
    com->write(itu.current()->rect());
  }
  
  // send Actors
  
  com->write_unsigned(la.count());
  
  Q3PtrListIterator<UcClassCanvas> ita(la);
  
  for (; ita.current(); ++ita)
    ita.current()->get_bn()->write_id(com);
  
  // send rels
  
  Q3PtrList<ArrowCanvas> lr;
  
  for (itu.toFirst(); itu.current(); ++itu) {
    Q3PtrListIterator<ArrowCanvas> itl(itu.current()->lines);
    
    for (; itl.current(); ++itl) {
      ArrowCanvas * r = itl.current();
      DiagramItem * from = r->get_start();
      DiagramItem * to = r->get_end();
      
      if ((from->type() == UmlUseCase)
	  ? (to->type() == UmlClass)
	  : (from->type() == UmlClass))
	lr.append(r);
    }
  }
  
  com->write_unsigned(lr.count());
  
  Q3PtrListIterator<ArrowCanvas> itr(lr);
  
  for (; itr.current(); ++itr)
    itr.current()->write_uc_rel(com);
}
Beispiel #17
0
void SdDurationCanvas::menu(const QPoint & p) {
  Q3PopupMenu m(0);
  Q3CanvasItemList items = collisions(TRUE);
  Q3PtrList<SdDurationCanvas> l;
  Q3CanvasItemList::ConstIterator it;
  Q3CanvasItemList::ConstIterator end = items.end();
  
  for (it = items.begin(); it != end; ++it) {
    if ((*it)->visible()) {
      DiagramItem * di = QCanvasItemToDiagramItem(*it);
      
      if ((di != 0) &&
	  (di->type() == UmlActivityDuration) &&
	  (((SdDurationCanvas *) di)->support == support))
	l.append((SdDurationCanvas *) di);
    }
  }
  
  m.insertItem(new MenuTitle(TR("Activity bar"), m.font()), -1);
  m.insertSeparator();
  m.insertItem(TR("Upper"), 0);
  m.insertItem(TR("Lower"), 1);
  m.insertItem(TR("Go up"), 9);
  m.insertItem(TR("Go down"), 10);
  m.insertSeparator();
  m.insertItem((coregion) ? TR("Draw as activity bar") :  TR("Draw as a coregion"), 7);
  m.insertItem(TR("Edit drawing settings"), 2);
  m.insertSeparator();
  m.insertItem(TR("Select linked items"), 3);
  m.insertSeparator();
  m.insertItem(TR("Remove from diagram"), 4);
  m.insertSeparator();
  m.insertItem(TR("Cut here"), 5);
  if (!l.isEmpty())
    m.insertItem(TR("Merge juxtaposed activity bars"), 6);
  if (support->isaDuration())
    m.insertItem(TR("Collapse in parent bar"), 8);

  switch (m.exec(QCursor::pos())) {
  case 0:
    upper();
    modified();
    return;
  case 1:
    lower();
    modified();
    return;
  case 9:
    z_up();
    modified();	// call package_modified()
    return;
  case 10:
    z_down();
    modified();	// call package_modified()
    return;
  case 2:
    edit_drawing_settings();
    return;
  case 3:
    select_associated();
    break;
  case 4:
    delete_it();
    package_modified();
    break;
  case 5:
    cut(p);
    package_modified();
    break;
  case 6:
    merge(l);
    package_modified();
    break;
  case 7:
    coregion = !coregion;
    modified();
    return;
  case 8:
    {
      SdDurationCanvas * d = (SdDurationCanvas *) support;
      
      d->collapse(this);
      d->update_hpos(); // update sub duration and msg hpos
      d->update_self();
    }    
    package_modified();
    break;
  default:
    return;
  }
  
  canvas()->update();
}
Beispiel #18
0
void FragmentCanvas::send(ToolCom * com, Q3CanvasItemList & all,
			  Q3PtrList<FragmentCanvas> & fragments,
			  Q3PtrList<FragmentCanvas> & refs)
{
  Q3CanvasItemList::Iterator cit;

  for (cit = all.begin(); cit != all.end(); ++cit) {
    DiagramItem *di = QCanvasItemToDiagramItem(*cit);
    
    if ((di != 0) && (*cit)->visible() && (di->type() == UmlFragment))
      fragments.append((FragmentCanvas *) di);
  }
  
  com->write_unsigned(fragments.count());
  
  FragmentCanvas * f;
  
  for (f = fragments.first(); f != 0; f = fragments.next()) {
    Q3CString s = fromUnicode(f->name);
    
    com->write_string((const char *) s);
    com->write(f->rect());
    
    // few separators, use bubble sort
    unsigned sz = f->separators.count();
    
    if (sz == 0)
      com->write_unsigned(1);
    else {
      FragmentSeparatorCanvas ** v = new FragmentSeparatorCanvas *[sz];
      unsigned index;      
      Q3PtrListIterator<FragmentSeparatorCanvas> it(f->separators);
      
      for (index = 0; it.current(); ++it, index += 1)
	v[index] = it.current();
      
      bool modified;
      
      do {
	modified = FALSE;
	
	for (index = 1; index < sz; index += 1) {
	  if (v[index - 1]->y() > v[index]->y()) {
	    modified = TRUE;
	    
	    FragmentSeparatorCanvas * fs = v[index - 1];
	    
	    v[index - 1] = v[index];
	    v[index] = fs;
	  }
	}
      } while (modified);
      
      com->write_unsigned(sz + 1);
      
      for (index = 0; index != sz; index += 1)
	com->write_unsigned((unsigned) v[index]->y());
      
      delete [] v;
    }
      
    com->write_unsigned((unsigned) (f->y() + f->height() - 1));

    if (com->api_format() >= 41) {
      if (f->refer != 0)
	f->refer->write_id(com);
      else
	com->write_id(0);
      
      s = fromUnicode(f->form);
      com->write_string((const char *) s);
      
      if (f->name == "ref")
	refs.append(f);
    }
  }
}
Beispiel #19
0
void ArtifactCanvas::update_relations() {
  // 'this' is a non source, check its associations
  const Q3PtrDict<BrowserArtifact> * associated = 
    ((ArtifactData *) browser_node->get_data())->get_associated();
  Q3PtrDict<BrowserArtifact> associations;
  Q3PtrListIterator<ArrowCanvas> it(lines);
    
  while (it.current()) {
    if ((it.current()->type() == UmlContain) &&
	(((AssocContainCanvas *) it.current())->get_start() == this)) {
      DiagramItem * adi = ((AssocContainCanvas *) it.current())->get_end();
      
      if ((adi->type() == UmlArtifact) &&
	  (associated != 0) &&
	  (associated->find((BrowserArtifact *) 
			    ((ArtifactCanvas *) adi)->browser_node) != 0)) {
	// association must exist
	BrowserArtifact * c = (BrowserArtifact *) 
	  ((ArtifactCanvas *) adi)->browser_node;
	
	associations.insert(c, c);
	++it;
      }
      else
	// association must not exist
	it.current()->delete_it();
    }
    else
      ++it;
  }
  
  if (associated != 0) {
    Q3PtrDictIterator<BrowserArtifact> it(*associated);
    
    while (it.current()) {
      if (associations.find(it.current()) == 0) {
	// the association to 'it.current()' is not yet drawn
	
	// search 'it.current()' cancas
	Q3CanvasItemList all = canvas()->allItems();
	Q3CanvasItemList::Iterator cit;
	
	for (cit = all.begin(); cit != all.end(); ++cit) {
	  if ((*cit)->visible()) {
	    DiagramItem * adi = QCanvasItemToDiagramItem(*cit);
	    
	    if ((adi != 0) &&		// an uml canvas item
		(adi->type() == UmlArtifact) &&
		(((ArtifactCanvas *) adi)->browser_node == it.current())) {
	      // find
	      (new AssocContainCanvas(the_canvas(), this, adi, 0, -1.0, -1.0))
		->show();
	      break;
	    }
	  }
	}
      }
      ++it;
    }
  }
}
Beispiel #20
0
void SdLifeLineCanvas::send(ToolCom * com, const Q3CanvasItemList & l,
			    Q3PtrList<FragmentCanvas> & fragments,
			    Q3PtrList<FragmentCanvas> & refs)
{
  int api_format = com->api_format();
  Q3PtrDict<SdLifeLineCanvas> used_refs; // the key is the fragment ref
  Q3PtrList<SdLifeLineCanvas> lls;
  Q3CanvasItemList::ConstIterator cit;
  unsigned n = 0;
  
  // count msgs
  
  for (cit = l.begin(); cit != l.end(); ++cit) {
    DiagramItem * it = QCanvasItemToDiagramItem(*cit);
      
    if ((it != 0) && // an uml canvas item
	(*cit)->visible() &&
	(it->type() == UmlLifeLine)) {
      SdLifeLineCanvas * ll = (SdLifeLineCanvas *) it;

      lls.append(ll);
      
      Q3PtrListIterator<SdDurationCanvas> iter(ll->durations);
      
      // standard msgs
      for (; iter.current(); ++iter)
	n += iter.current()->count_msg(api_format);
      
      if (com->api_format() >= 41) {
	if (ll->end != LIFE_LINE_HEIGHT)
	  // deletion message, ll can't masked by user
	  n += 1;
      
	FragmentCanvas * f;
	
	for (f = refs.first(); f != 0; f = refs.next()) {
	  if (f->collidesWith(ll)) {
	    // interaction use message
	    if (used_refs.find((void *) f) == 0) {
	      n += 1;
	      used_refs.insert((void *) f, ll);
	    }
	  }
	}
      }
    }
  }
  
  // write messages
  
  com->write_unsigned(n);
  
  SdLifeLineCanvas * ll;
  
  for (ll = lls.first(); ll != 0; ll = lls.next()) {
    int id = ll->obj->get_ident();
    Q3PtrListIterator<SdDurationCanvas> iter(ll->durations);
  
    // write standard messages
    for (; iter.current(); ++iter)
      iter.current()->send(com, id);
    
    if ((ll->end != LIFE_LINE_HEIGHT) && (com->api_format() >= 41)) {
      // deletion message, lf can't masked by user
      int m = ll->width()/2;
      
      SdMsgBaseCanvas::send(com, id, (unsigned) ll->x() + m,
			    (unsigned) ll->end + m, aDestruction, "", "", "");
    }
  }
  
  if (com->api_format() >= 41) {
    // interaction use messages
    Q3PtrDictIterator<SdLifeLineCanvas>itref(used_refs);
    
    while ((ll = itref.current()) != 0) {
      FragmentCanvas * f = (FragmentCanvas *) itref.currentKey();
      int m = ll->width()/2;
      
      SdMsgBaseCanvas::send(com, ll->obj->get_ident(),
			    (unsigned) ll->x() + m, (unsigned) f->center().y(),
			    anInteractionUse, "", "", f->arguments());
      
      ++itref;
    }
    
    // send life lines covered by fragment
    FragmentCanvas * f;
    
    for (f = fragments.first(); f != 0; f = fragments.next()) {
      Q3PtrList<SdLifeLineCanvas> covered;
      
      for (ll = lls.first(); ll != 0; ll = lls.next())
	if (f->collidesWith(ll))
	  covered.append(ll);
      
      com->write_unsigned(covered.count());
      
      for (ll = covered.first(); ll != 0; ll = covered.next())
	com->write_unsigned((unsigned) ll->obj->get_ident());
    }
  }
}
Beispiel #21
0
FlowCanvas * FlowCanvas::read(char * & st, UmlCanvas * canvas, char * k)
{
  if (!strcmp(k, "flowcanvas_ref"))
    return ((FlowCanvas *) dict_get(read_id(st), "flowcanvas", canvas));
  else if (!strcmp(k, "flowcanvas")) {    
    int id = read_id(st);
    BrowserFlow * br = BrowserFlow::read_ref(st);
    FlowData * tr = (FlowData *) br->get_data();
    LineGeometry geo;
    bool fixed = FALSE;
    
    k = read_keyword(st);
    if (! strcmp(k, "geometry")) {
      geo = line_geometry(read_keyword(st));
      k = read_keyword(st);
      if (! strcmp(k, "unfixed"))
	k = read_keyword(st);
      else {
	fixed = TRUE;
      }
    }
    else
      geo = NoGeometry;
    
    float dbegin;
    float dend;

    if (! strcmp(k, "decenter_begin")) {
      dbegin = read_double(st) / 1000;
      k = read_keyword(st);
    }
    else
      dbegin = -1;

    if (! strcmp(k, "decenter_end")) {
      dend = read_double(st) / 1000;
      k = read_keyword(st);
    }
    else
      dend = -1;

    unread_keyword(k, st);
    
    read_keyword(st, "from");
    read_keyword(st, "ref");
    
    DiagramItem * bi = dict_get(read_id(st), "canvas", canvas);
    BrowserNode * b = tr->get_start_node();
    QString s = br->get_name();
    FlowCanvas * first = 0;
    FlowCanvas * result;
    LabelCanvas * label;
    LabelCanvas * stereotype;
    double z;
              
    for (;;) {
      read_keyword(st, "z");
      z = read_double(st);
      k = read_keyword(st);
      
      if ((label = LabelCanvas::read(st, canvas, k)) != 0) {
	// the flow name can't be empty
	label->setZ(z);
	k = read_keyword(st);
      }
      
      if (!strcmp(k, "stereotype")) {
	(void) read_string(st);
	read_keyword(st, "xyz");
	
	int x = (int) read_double(st);
	int y = (int) read_double(st);
	
	if ((tr == 0) || (*(tr->get_stereotype()) == 0)) {
	  stereotype = 0;
	  read_double(st);	// z
	}
	else {
	  QString s = tr->get_short_stereotype();
	 
	  if (s == "interrupt")
	    s = LabelCanvas::Zigzag;
	  else
	    s = QString("<<") + toUnicode(s) + ">>";

	  stereotype = new LabelCanvas(s, canvas, x, y);
	  stereotype->setZ(read_double(st));
	}
	k = read_keyword(st);
      }
      else
	stereotype = 0;

      if (strcmp(k, "to"))
	wrong_keyword(k, "to");

      DiagramItem * di;
      
      if (strcmp(k = read_keyword(st), "ref")) {
	di = ArrowPointCanvas::read(st, canvas, k);
	
	if (di == 0)
	  unknown_keyword(k);
      }
      else
	di = dict_get(read_id(st), "activity node", canvas);

      // do not give data to not call update()
      result = new FlowCanvas(canvas, bi, di, b, id, dbegin, dend);
      result->geometry = geo;
      result->fixed_geometry = fixed;
      result->set_z(z);
      result->data = tr;
      connect(tr, SIGNAL(changed()), result, SLOT(modified()));
      connect(tr, SIGNAL(deleted()), result, SLOT(deleted()));

      if (first == 0) {
	first = result;
	if (read_file_format() == 30)
	  // to remove redondant relation made by release 2.22
	  RelsToCheck.append(result);
      }
      if (label != 0)
	result->label = label;
      if (stereotype != 0)
	(result->stereotype = stereotype)->show();
      result->show();
      
      if (di->type() != UmlArrowPoint)
	break;
      
      bi = di;
      
      read_keyword(st, "line");
      id = read_id(st);
    }
    
    k = read_keyword(st);
    result->settings.read(st, k);	// updates k    
    if (strcmp(k, "write_horizontally") != 0)
      wrong_keyword(k, "write_horizontally");
    result->write_horizontally = state(read_keyword(st));
    k = read_keyword(st);
    result->propagate_drawing_settings();
    
    // to add label, stereotype ... if needed    
    first->update(FALSE);
    if (first != result)
      result->update(FALSE);
    
    if (! strcmp(k, "selection")) {
      k = read_keyword(st);
      first->selection = InfoCanvas::read(st, canvas, k, first);
      k = read_keyword(st);
    }
    if (! strcmp(k, "transformation")) {
      k = read_keyword(st);
      first->transformation = InfoCanvas::read(st, canvas, k, first);
      k = read_keyword(st);
    }

    first->stereotypeproperties = 
      StereotypePropertiesCanvas::read(st,  canvas, k, first);
    
    if (first->stereotypeproperties != 0)
      k = read_keyword(st);
    
    first->check_sel_trans();
    first->check_stereotypeproperties();

    // manage case where the relation is deleted but present in the browser
    if (result->data->get_start()->deletedp())
      RelsToDel.append(result);
    else
      result->update_geometry();
    
    if (strcmp(k, "end"))
      wrong_keyword(k, "end");
    
    return result;
  }
  else
    return 0;
}
void ActivityDiagramView::save(QTextStream & st, QString & warning,
                               bool copy) const
{
    DiagramItemList items(canvas()->allItems());
    DiagramItem * di;

    if (!copy)
        // sort is useless for a copy
        items.sort();

    st << "format " << api_format() << "\n";

    // save first activity, activity nodes, actions, objects, packages, fragments, notes and icons

    for (di = items.first(); di != 0; di = items.next()) {
        switch (di->type()) {
        case UmlActivity:
        case UmlInterruptibleActivityRegion:
        case UmlExpansionRegion:
        case UmlActivityPartition:
        case InitialAN:
        case ActivityFinalAN:
        case FlowFinalAN:
        case DecisionAN:
        case MergeAN:
        case ForkAN:
        case JoinAN:
        case UmlActivityAction:
        case UmlActivityObject:
        case UmlNote:
        case UmlText:
        case UmlImage:
        case UmlPackage:
        case UmlFragment:
        case UmlIcon:
            if (!copy || di->copyable())
                di->save(st, FALSE, warning);

            // no break
        default:
            // Parameters, parameter sets and pins are saved by their parents
            // pre & post conditions are saved by activity action
            break;
        }
    }

    // then saves relations

    for (di = items.first(); di != 0; di = items.next()) {
        switch (di->type()) {
        case UmlFlow:
        case UmlDependOn:
            if (!copy || di->copyable())
                di->save(st, FALSE, warning);

        default:
            break;
        }
    }

    // then saves anchors

    for (di = items.first(); di != 0; di = items.next())
        if ((!copy || di->copyable()) && (di->type() == UmlAnchor))
            di->save(st, FALSE, warning);

    if (!copy && (preferred_zoom != 0)) {
        nl_indent(st);
        st << "preferred_whz " << preferred_size.width() << " "
           << preferred_size.height() << " " << preferred_zoom;
    }

    nl_indent(st);
    st << "end\n";
}
Beispiel #23
0
void OdClassInstCanvas::draw_all_relations(OdClassInstCanvas * end) {
  QCanvasItemList all = canvas()->allItems();
  QCanvasItemList::Iterator cit;
  ClassInstanceData * d = (ClassInstanceData *) browser_node->get_data();
  const QValueList<SlotRel> & rels = d->get_relations();
  QValueList<SlotRel>::ConstIterator it_rel;
  
  for (it_rel = rels.begin(); it_rel != rels.end(); it_rel++) {
    const SlotRel & slot_rel = *it_rel;
    
    if (!has_relation(slot_rel)) {
      BrowserClassInstance * end_inst = slot_rel.value;
      DiagramItem * di;
      
      if (end_inst == browser_node)
	di = this;
      else {	
	di = 0;
	for (cit = all.begin(); cit != all.end(); ++cit) {
	  DiagramItem * adi = QCanvasItemToDiagramItem(*cit);
	  
	  if ((adi != 0) &&		// an uml canvas item
	      (adi->type() == UmlClassInstance) &&
	      (((OdClassInstCanvas *) adi)->browser_node == end_inst) &&
	      ((((OdClassInstCanvas *) adi) == end) || (*cit)->visible())) {
	    // other class canvas find
	    di = adi;
	    break;
	  }
	}
      }
      if (di != 0) {
	if (slot_rel.is_a)
	  (new ObjectLinkCanvas(the_canvas(), this, di,
				slot_rel.rel->get_type(),
				0, -1.0, -1.0, slot_rel.rel))
	    ->show();
	else
	  (new ObjectLinkCanvas(the_canvas(), di, this,
				slot_rel.rel->get_type(),
				0, -1.0, -1.0, slot_rel.rel))
	    ->show();
      }
    }
  }
  
  if ((end == 0) &&
      !DrawingSettings::just_modified() &&
      !on_load_diagram()) {
    for (cit = all.begin(); cit != all.end(); ++cit) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
      
      if ((di != 0) &&	// an uml canvas item
	  (di->type() == UmlClassInstance) &&
	  (((OdClassInstCanvas *) di) != this) &&
	  !((OdClassInstCanvas *) di)->browser_node->deletedp() &&
	  ((OdClassInstCanvas *) di)->visible())
	((OdClassInstCanvas *) di)->draw_all_relations(this);
    }
  }
}
SimpleRelationCanvas * SimpleRelationCanvas::read(char *& st, UmlCanvas * canvas, char * k)
{
    if (!strcmp(k, "simplerelationcanvas_ref"))
        return ((SimpleRelationCanvas *) dict_get(read_id(st), "simplerelationcanvas", canvas));
    else if (!strcmp(k, "simplerelationcanvas")) {
        int id = read_id(st);
        BrowserSimpleRelation * br = BrowserSimpleRelation::read_ref(st);
        SimpleRelationData * rd = (SimpleRelationData *) br->get_data();
        LineGeometry geo;
        bool fixed;

        k = read_keyword(st);

        if (! strcmp(k, "geometry")) {
            geo = line_geometry(read_keyword(st));
            k = read_keyword(st);

            if (! strcmp(k, "unfixed")) {
                k = read_keyword(st);
                fixed = FALSE;
            }
            else
                fixed = TRUE;
        }
        else {
            geo = NoGeometry;
            fixed = FALSE;
        }

        float dbegin;
        float dend;

        if (! strcmp(k, "decenter_begin")) {
            dbegin = read_double(st) / 1000;
            k = read_keyword(st);
        }
        else
            dbegin = -1;

        if (! strcmp(k, "decenter_end")) {
            dend = read_double(st) / 1000;
            k = read_keyword(st);
        }
        else
            dend = -1;

        unread_keyword(k, st);

        read_keyword(st, "from");
        read_keyword(st, "ref");

        DiagramItem * bi = dict_get(read_id(st), "canvas", canvas);
        BrowserNode * b = rd->get_start_node();
        UmlCode t = rd->get_type();
        SimpleRelationCanvas * first = 0;
        SimpleRelationCanvas * result;
        LabelCanvas * stereotype;
        double z;

        for (;;) {
            read_keyword(st, "z");
            z = read_double(st);
            k = read_keyword(st);

            if (!strcmp(k, "stereotype")) {
                (void) read_string(st);
                read_keyword(st, "xyz");

                int x = (int) read_double(st);
                int y = (int) read_double(st);

                if ((rd == 0) || (*(rd->get_stereotype()) == 0)) {
                    stereotype = 0;
                    read_double(st);	// z
                }
                else {
                    QString s = toUnicode(rd->get_short_stereotype());

                    if (s[0] != '{')
                        s = QString("<<") + s + ">>";

                    stereotype = new LabelCanvas(s, canvas, x, y);
                    stereotype->setZ(read_double(st));
                }

                k = read_keyword(st);
            }
            else
                stereotype = 0;

            if (strcmp(k, "to"))
                wrong_keyword(k, "to");

            DiagramItem * di;

            if (strcmp(k = read_keyword(st), "ref")) {
                di = ArrowPointCanvas::read(st, canvas, k);

                if (di == 0)
                    unknown_keyword(k);
            }
            else
                di = dict_get(read_id(st), "classcanvas", canvas);

            // do not give rd to not call update()
            result = new SimpleRelationCanvas(canvas, bi, di, b, t, id, dbegin, dend);
            result->geometry = geo;
            result->fixed_geometry = fixed;
            result->set_z(z);
            result->data = rd;
            connect(rd, SIGNAL(changed()), result, SLOT(modified()));
            connect(rd, SIGNAL(deleted()), result, SLOT(deleted()));

            if (first == 0) {
                first = result;

                if (read_file_format() == 30)
                    // to remove redondant relation made by release 2.22
                    RelsToCheck.append(result);
            }

            if (stereotype != 0)
                (result->stereotype = stereotype)->show();

            result->show();

            if (di->type() != UmlArrowPoint)
                break;

            bi = di;

            read_keyword(st, "line");
            id = read_id(st);
        }

        if (read_file_format() >= 58) {
            // stereotype property

            k = read_keyword(st);

            first->stereotypeproperties =
                StereotypePropertiesCanvas::read(st,  canvas, k, first);

            if (first->stereotypeproperties != 0)
                k = read_keyword(st);

            if (strcmp(k, "end"))
                wrong_keyword(k, "end");
        }

        // to add stereotype ... if needed

        first->update(FALSE);

        if (first != result)
            result->update(FALSE);

        first->check_stereotypeproperties();

        // manage case where the relation is deleted but present in the browser
        if (result->data->get_start()->deletedp())
            RelsToDel.append(result);
        else
            result->update_geometry();

        return result;
    }
    else
        return 0;
}
void ActivityContainerCanvas::prepare_for_move(bool on_resize) {
  if (! on_resize) {
    // select all sub nodes
    Q3CanvasItemList all = canvas()->allItems();
    Q3CanvasItemList::Iterator cit;
    UmlCanvas * canvas = the_canvas();
    
    for (cit = all.begin(); cit != all.end(); ++cit) {
      if ((*cit)->visible() && !(*cit)->selected()) {
	DiagramItem * di = QCanvasItemToDiagramItem(*cit);
	
	if ((di != 0) &&
	    (di->get_bn() != 0) &&
	    (((BrowserNode *) di->get_bn()->parent()) == browser_node)) {
	  // must look at the type because some canvas items have browser_node
	  // attr set to the diagram and the parent of the diagram is the activity
	  switch (di->type()) {
	  case UmlActivityObject:
	  case UmlActivityAction:
	  case UmlActivityPartition:
	  case InitialAN:
	  case FlowFinalAN:
	  case ActivityFinalAN:
	  case DecisionAN:
	  case MergeAN:
	  case ForkAN:
	  case JoinAN:
	  case UmlExpansionRegion:
	  case UmlInterruptibleActivityRegion:
	    canvas->select(*cit);
	    ((DiagramCanvas *) di)->prepare_for_move(on_resize);
	    break;
	  default:
	    break;
	  }
	}
      }
    }

    // select points on lines having the two extremities selected or
    // connecting pin/parameter/expansion node of element selected
    for (cit = all.begin(); cit != all.end(); ++cit) {
      if ((*cit)->visible() && !(*cit)->selected() && isa_arrow(*cit)) {
	ArrowCanvas * ar = (ArrowCanvas *) *cit;
	DiagramItem * b;
	DiagramItem * e;
	
	ar->extremities(b, e);

	if (!b->isSelected() || !e->isSelected()) {
	  DiagramItem * start = ar->get_start();
	  DiagramItem * dest = ar->get_end();

	  if ((start->isSelected() || indirectly_selected(start)) &&
	      (dest->isSelected() || indirectly_selected(dest))) {
	    while (b->type() == UmlArrowPoint) {
	      canvas->select((ArrowPointCanvas *) b);
	      ar = ((ArrowPointCanvas *) b)->get_other(ar);
	      ar->extremities(b, e);
	    }

	    ar = (ArrowCanvas *) *cit;
	    ar->extremities(b, e);

	    while (e->type() == UmlArrowPoint) {
	      canvas->select((ArrowPointCanvas *) e);
	      ar = ((ArrowPointCanvas *) e)->get_other(ar);
	      ar->extremities(b, e);
	    }
	  }
	}
      }
    }
  }
}
Beispiel #26
0
void ComponentDiagramView::save(Q3TextStream & st, QString & warning,
				bool copy) const {
  DiagramItemList items(canvas()->allItems());
  DiagramItem * di;
  
  if (!copy)
    // sort is useless for a copy
    items.sort();
  
  st << "format " << FILEFORMAT << "\n";
  
  // save first component packages fragment notes junctions and icons
  
  for (di = items.first(); di != 0; di = items.next()) {
    switch (di->type()) {
    case UmlComponent:
    case UmlNote:
    case UmlText:
    case UmlImage:
    case UmlPackage:
    case UmlFragment:
    case UmlArrowJunction:
    case UmlIcon:
      if (!copy || di->copyable())
	di->save(st, FALSE, warning);
      // no break
    default:
      break;
    }
  }

  // then saves relations
  
  for (di = items.first(); di != 0; di = items.next()) {
    switch (di->type()) {
    case UmlInherit:
    case UmlDependency:
    case UmlDependOn:
    case UmlRequired:
    case UmlProvided:
      if (!copy || di->copyable())
	di->save(st, FALSE, warning);
    default:	// to avoid compiler warning
      break;
    }
  }
  
  // then saves anchors
  
  for (di = items.first(); di != 0; di = items.next())
    if ((!copy || di->copyable()) && (di->type() == UmlAnchor))
      di->save(st, FALSE, warning);
  
  if (!copy && (preferred_zoom != 0)) {
    nl_indent(st);
    st << "preferred_whz " << preferred_size.width() << ' '
      << preferred_size.height() << ' ' << preferred_zoom;
  }
  
  nl_indent(st);
  st << "end\n";
}
// resize this to contain its sub elements
void ActivityContainerCanvas::resize_to_contain(Q3CanvasItemList & all,
						BooL & need_sub_upper) {
  Q3CanvasItemList::Iterator cit;
  BrowserNode * browser_node = get_bn();
  QRect r = rect();
  int resize_left = 0;
  int resize_right = 0;
  int resize_top = 0;
  int resize_bottom = 0;
  
  for (cit = all.begin(); cit != all.end(); ++cit) {
    if ((*cit)->visible() && !(*cit)->selected()) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
      
      if ((di != 0) &&
	  (di->get_bn() != 0) &&
	  (((BrowserNode *) di->get_bn())->parent() == browser_node)) {
	// must look at the type because some canvas items have browser_node
	// attr equals to the diagram and the parent of the diagram is the activity
	switch (di->type()) {
	case UmlActivityObject:
	case UmlActivityAction:
	case UmlActivityPartition:
	case UmlExpansionRegion:
	case UmlInterruptibleActivityRegion:
	case InitialAN:
	case FlowFinalAN:
	case ActivityFinalAN:
	case DecisionAN:
	case MergeAN:
	case ForkAN:
	case JoinAN:
	  {
	    QRect di_r = di->rect();
	    int dx = 0;
	    int dy = 0;
	    
	    if (di_r.left() < r.left()) {
	      dx = r.left() - di_r.left();
	      if (dx > resize_left)
		resize_left = dx;
	    }
	    
	    if (di_r.right() > r.right()) {
	      dx = di_r.right() - r.right();
	      if (dx > resize_right)
		resize_right = dx;
	    }
	    
	    if (di_r.top() < r.top()) {
	      dy = r.top() - di_r.top();
	      if (dy > resize_top)
		resize_top = dy;
	    }
	    
	    if (di_r.bottom() > r.bottom()) {
	      dy = di_r.bottom() - r.bottom();
	      if (dy > resize_bottom)
		resize_bottom = dy;
	    }
	  }
	      
	  need_sub_upper |= ((*cit)->z() <= z());
	  break;
	default:
	  break;
	}
      }
    }
  }
  
  int dx = 0;
  int dy = 0;
  int dw = 0;
  int dh = 0;
  
  if (resize_top != 0) {
    dy = -resize_top;
    dh = resize_top;
  }
  
  if (resize_bottom != 0)
    dh += resize_bottom;
  
  if (resize_left != 0) {
    dx = -resize_left;
    dw = resize_left;
  }
  
  if (resize_right != 0)
    dw += resize_right;
  
  if ((dx != 0) || (dy != 0)) {
    moveBy(dx, dy);
    moveSelfRelsBy(dx, dy);
  }
  
  if ((dw != 0) || (dh != 0))
    DiagramCanvas::resize(width() + dw, height() + dh);
}
Beispiel #28
0
void UcClassCanvas::draw_all_depend_gene(UcClassCanvas * end) {
  Q3ListViewItem * child;
  Q3CanvasItemList all = canvas()->allItems();
  Q3CanvasItemList::Iterator cit;
  
  for (child = browser_node->firstChild(); child; child = child->nextSibling()) {
    if (dependencyOrGeneralization(((BrowserNode *) child)->get_type()) &&
	!((BrowserNode *) child)->deletedp()) {
      RelationData * def =
	((RelationData *) ((BrowserNode *) child)->get_data());

      if ((def->get_start_class() == browser_node) && 	// rel begins by this
	  ((end == 0) || (def->get_end_class() == end->browser_node)) &&
	  !has_relation(def)) {
	// adds it in case the other class is drawn
	BrowserClass * end_class = 
	  ((BrowserClass *) def->get_end_class());
	DiagramItem * di;
	
	if (end_class == browser_node)
	  di = this;
	else {	
	  di = 0;
	  for (cit = all.begin(); cit != all.end(); ++cit) {
	    DiagramItem * adi = QCanvasItemToDiagramItem(*cit);
	    
	    if ((adi != 0) &&		// an uml canvas item
		(adi->type() == UmlClass) &&
		(((UcClassCanvas *) adi)->browser_node == end_class) &&
		((((UcClassCanvas *) adi) == end) || (*cit)->visible())) {
	      // other class canvas find
	      di = adi;
	      break;
	    }
	  }
	}
	
	if (di != 0)
	  (new RelationCanvas(the_canvas(), this, di,
			      ((BrowserClass *) browser_node), 
			      def->get_type(), 0, -1.0, -1.0, def))
	    ->show();
      }
    }
  }
  
  if ((end == 0) &&
      !DrawingSettings::just_modified() &&
      !on_load_diagram()) {
    for (cit = all.begin(); cit != all.end(); ++cit) {
      DiagramItem * di = QCanvasItemToDiagramItem(*cit);
      
      if ((di != 0) &&	// an uml canvas item
	  (di->type() == UmlClass) &&
	  (((UcClassCanvas *) di) != this) &&
	  !((UcClassCanvas *) di)->browser_node->deletedp() &&
	  ((UcClassCanvas *) di)->visible())
	((UcClassCanvas *) di)->draw_all_depend_gene(this);
    }
  }
}
Beispiel #29
0
void ColDiagramView::read(char * st, char * k)
{
    UmlCanvas * canvas = the_canvas();

    // reads first the instances, package, fragment notes, icons text and images
    while (CodClassInstCanvas::read(st, canvas, k) ||
           NoteCanvas::read(st, canvas, k) ||
           TextCanvas::read(st, canvas, k) ||
           IconCanvas::read(st, canvas, k) ||
           PackageCanvas::read(st, canvas, k) ||
           FragmentCanvas::read(st, canvas, k) ||
           ImageCanvas::read(st, canvas, k))
        k = read_keyword(st);

    // then reads links selflink and dirs (without messages)
    while (CodLinkCanvas::read(st, canvas, k) ||	// updates k
           CodSelfLinkCanvas::read(st, canvas, k) ||	// updates k
           CodDirsCanvas::read(st, canvas, k))		// updates k
        ;

    // then read messages
    if (!strcmp(k, "msgs"))
        ColMsg::read(st, msgs, canvas);
    else if (strcmp(k, "no_msg"))
        wrong_keyword(k, "msgs/no_msg");

    k = read_keyword(st);

    // then show/update msgs
    Q3CanvasItemList items = canvas->allItems();
    Q3CanvasItemList::Iterator it;

    for (it = items.begin(); it != items.end(); ++it) {
        DiagramItem * di = QCanvasItemToDiagramItem(*it);

        if (di != 0) {
            switch (di->type()) {
            case UmlSelfLink:
                ((CodSelfLinkCanvas *) di)->update_msgs();
                break;

            case UmlLinkDirs:
                ((CodDirsCanvas *) di)->update_msgs();
                break;

            default:	// to avoid warning
                break;
            }
        }
    }

    // then reads anchors
    while (ArrowCanvas::read(st, canvas, k))
        k = read_keyword(st);

    if (!strcmp(k, "preferred_whz") || !strcmp(k, "prefered_whz")) {
        preferred_size.setWidth(read_unsigned(st));
        preferred_size.setHeight(read_unsigned(st));
        preferred_zoom = read_double(st);
        k = read_keyword(st);
    }

    if (strcmp(k, "end"))
        wrong_keyword(k, "end");
}