void ribi::cmap::QtConceptMap::onSelectionChanged()
{
  Graph& g = m_conceptmap;

  //Selectness of vertices
  const auto vip = vertices(g);
  std::for_each(vip.first,vip.second,
    [this, &g](const VertexDescriptor vd) {
      const auto vertex_map = get(boost::vertex_custom_type,g);
      const auto is_selected_map = get(boost::vertex_is_selected,g);
      const auto qtnode = FindQtNode(get(vertex_map,vd).GetId(),GetScene());
      //qtnode can be nullptr when onSelectionChanged is called while building up the QtConceptMap
      if (qtnode) { put(is_selected_map,vd,qtnode->isSelected()); }
    }
  );

  //Selectness of edges
  const auto eip = edges(g);
  std::for_each(eip.first,eip.second,
    [this, &g](const EdgeDescriptor ed) {
      const auto edge_map = get(boost::edge_custom_type,g);
      const auto is_selected_map = get(boost::edge_is_selected,g);
      const auto qtedge = FindQtEdge(get(edge_map,ed).GetId(),GetScene());
      if (qtedge) { put(is_selected_map,ed,qtedge->isSelected()); }
    }
  );
  scene()->update();
}
void ribi::cmap::QtConceptMap::SetConceptMap(const ConceptMap& conceptmap)
{
  RemoveConceptMap();
  m_conceptmap = conceptmap;
  assert(GetConceptMap() == conceptmap);

  assert(this->scene());

  //This std::vector keeps the QtNodes in the same order as the nodes in the concept map
  //You cannot rely on Collect<QtConceptMapNodeConcept*>(scene), as this shuffles the order
  //std::vector<QtNode*> qtnodes;

  assert(Collect<QtNode>(scene()).empty());

  //Add the nodes to the scene, if there are any
  const auto vip = vertices(m_conceptmap);
  for(auto i=vip.first; i!=vip.second; ++i)
  {
    assert(boost::num_vertices(m_conceptmap));
    const auto pmap = get(boost::vertex_custom_type, m_conceptmap);
    const Node node = get(pmap, *i);
    const bool is_focal_node{i == vip.first};
    QtNode * const qtnode{new QtNode(node)};
    if (is_focal_node) { qtnode->setFlags(0); }
    assert(qtnode);
    assert(!qtnode->scene());
    scene()->addItem(qtnode);
    assert(qtnode->scene());
    assert(FindQtNode(node.GetId(), scene()));
  }
  //Add the Edges
  const auto eip = edges(m_conceptmap);
  for(auto i = eip.first; i != eip.second; ++i)
  {
    assert(boost::num_edges(m_conceptmap));
    const VertexDescriptor vd_from = boost::source(*i, m_conceptmap);
    const VertexDescriptor vd_to = boost::target(*i, m_conceptmap);
    assert(vd_from != vd_to);
    const auto vertex_map = get(boost::vertex_custom_type, m_conceptmap);
    const Node from = get(vertex_map, vd_from);
    const Node to = get(vertex_map, vd_to);
    assert(from.GetId() != to.GetId());
    QtNode * const qtfrom = FindQtNode(from.GetId(), scene());
    QtNode * const qtto = FindQtNode(to.GetId(), scene());
    assert(qtfrom != qtto);
    const auto edge_map = get(boost::edge_custom_type, m_conceptmap);
    const Edge edge = get(edge_map, *i);
    QtEdge * const qtedge{new QtEdge(edge,qtfrom,qtto)};
    if (qtfrom->GetNode().IsCenterNode() || qtto->GetNode().IsCenterNode())
    {
      qtedge->GetQtNode()->setVisible(false);
    }

    assert(!qtedge->scene());
    assert(!qtedge->GetQtNode()->scene());
    assert(!qtedge->GetArrow()->scene());
    scene()->addItem(qtedge);
    //scene()->addItem(qtedge->GetQtNode()); //Get these for free
    //scene()->addItem(qtedge->GetArrow()); //Get these for free
    assert(qtedge->scene());
    assert(qtedge->GetQtNode()->scene());
    assert(qtedge->GetArrow()->scene());
  }
  assert(GetConceptMap() == conceptmap);

  CheckInvariants();
}
void ribi::cmap::QtRateConceptMap::AddEdge(
  const boost::shared_ptr<Edge> edge)
{
  const boost::shared_ptr<QtEditStrategy> qtconcept(new QtEditStrategy(edge->GetConcept()));
  assert(qtconcept);
  QtNode * const from = FindQtNode(edge->GetFrom().get());
  assert(from);
  QtNode * const to   = FindQtNode(edge->GetTo().get());
  assert(to);
  assert(from != to);
  QtEdge * const qtedge = new QtEdge(
    edge,
    qtconcept,
    from,
    to
  );
  assert(qtedge);

  //Edges connected to the center node do not show their concepts

  //Approaches should be equivalent
  #ifndef NDEBUG
  if(IsCenterNode(from->GetNode()) != IsQtCenterNode(from))
  {
    TRACE("ERROR");
    TRACE(IsCenterNode(from->GetNode()));
    TRACE(IsQtCenterNode(from));
  }
  if(IsCenterNode(to->GetNode()) != IsQtCenterNode(to))
  {
    TRACE("ERROR");
    TRACE(IsCenterNode(to->GetNode()));
    TRACE(IsQtCenterNode(to));
  }
  assert(IsCenterNode(from->GetNode()) == IsQtCenterNode(from));
  assert(IsCenterNode(to->GetNode()) == IsQtCenterNode(to));
  #endif
  if (IsQtCenterNode(from) || IsQtCenterNode(to))
  {
    assert(qtconcept == qtedge->GetDisplayStrategy());
    qtconcept->setVisible(false);
  }


  //General
  qtedge->m_signal_request_scene_update.connect(
    boost::bind(&QtConceptMap::OnRequestSceneUpdate,this));

  //General: inform an Observer that this item has changed
  qtedge->m_signal_item_has_updated.connect(
   boost::bind(&QtConceptMap::OnItemRequestsUpdate,this,boost::lambda::_1));

  //General: inform an Observer that a QGraphicsScene needs to be updated
  qtedge->m_signal_request_scene_update.connect(
    boost::bind(&QtConceptMap::OnRequestSceneUpdate,this));

  //Specific: disable changing arrow heads
  qtedge->GetArrow()->setEnabled(false);

  //Do not connect m_signal_rate, because Edges will never be rated


  //Add the EdgeConcepts to the scene
  assert(!qtedge->scene());
  this->scene()->addItem(qtedge);

  assert(std::count(
    this->GetConceptMap()->GetEdges().begin(),
    this->GetConceptMap()->GetEdges().end(),
    edge) == 1 && "Assume edge is already in the concept map");

  #ifndef NDEBUG
  const double epsilon = 0.000001;
  #endif
  assert(std::abs(qtedge->pos().x() - edge->GetX()) < epsilon);
  assert(std::abs(qtedge->pos().y() - edge->GetY()) < epsilon);
}