bool ribi::cmap::IsConnectedToCenterNode(const boost::shared_ptr<const Edge> edge) noexcept { assert(!(IsCenterNode(edge->GetFrom()) && IsCenterNode(edge->GetTo())) && "An Edge cannot be connected to two CenterNodes"); return IsCenterNode(edge->GetFrom()) || IsCenterNode(edge->GetTo()); }
ribi::cmap::QtNode * ribi::cmap::QtRateConceptMap::AddNode(const boost::shared_ptr<Node> node) { //const boost::shared_ptr<QtRateStrategy> display_strategy(new QtRateStrategy(node->GetConcept())); //assert(display_strategy); //QtNode * const qtnode = new QtNode(node,display_strategy); QtNode * const qtnode { IsCenterNode(node) ? new QtCenterNode(boost::dynamic_pointer_cast<CenterNode>(node)) : new QtNode(node,GetDisplayStrategy(node->GetConcept())) }; assert(qtnode); assert(IsCenterNode(qtnode->GetNode()) == IsQtCenterNode(qtnode) && "Should be equivalent"); //General: inform an Observer that this item has changed qtnode->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 qtnode->m_signal_request_scene_update.connect( boost::bind(&QtConceptMap::OnRequestSceneUpdate,this)); //Specific: inform an Observer that the Node requests its Concept being rated qtnode->m_signal_node_requests_rate_concept.connect( boost::bind( &ribi::cmap::QtRateConceptMap::OnNodeRequestsRateConcept, this, boost::lambda::_1)); //Do not forget the placeholder! //Specific: inform an Observer that the Node requests its Examples being rated qtnode->m_signal_node_requests_rate_examples.connect( boost::bind( &ribi::cmap::QtRateConceptMap::OnNodeRequestsRateExamples, this, boost::lambda::_1)); //Do not forget the placeholder! assert(!qtnode->scene()); this->scene()->addItem(qtnode); assert(std::count( GetConceptMap()->GetNodes().begin(), GetConceptMap()->GetNodes().end(), node) == 1 && "Assume Node is already in the concept map"); //this->GetConceptMap()->AddNode(node); assert(qtnode->pos().x() == node->GetX()); assert(qtnode->pos().y() == node->GetY()); //Cannot test this: during construction not all nodes are put in //assert(Collect<QtNode>(this->scene()).size() == this->GetConceptMap()->GetNodes().size()); return qtnode; }
bool ribi::cmap::HasCenterNode(const ConceptMap& c) noexcept { const auto nodes = GetNodes(c); const auto i = std::find_if( std::begin(nodes),std::end(nodes), [](const Node& node) { return IsCenterNode(node); } ); return i != std::end(nodes); }
ribi::cmap::VertexDescriptor ribi::cmap::FindCenterNode(const ConceptMap& g) { if (CountCenterNodes(g) != 1) { std::stringstream msg; msg << __func__ << ": " << "Cannot find the one center node, as there are " << CountCenterNodes(g) ; throw std::logic_error(msg.str()); } using vd = VertexDescriptor; const auto vip = vertices(g); const auto i = std::find_if( vip.first, vip.second, [g](const vd d) { const auto my_vertex_map = get(boost::vertex_custom_type, g); return IsCenterNode(get(my_vertex_map, d)); } ); assert(i != vip.second); return *i; }
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); }
bool ribi::cmap::QtConceptMap::IsQtCenterNode(const QGraphicsItem* const item) { const QtCenterNode * const qtnode = dynamic_cast<const QtCenterNode*>(item); assert(!qtnode || IsCenterNode(qtnode->GetNode())); return qtnode; }
void ribi::cmap::QtConceptMap::BuildQtConceptMap() { CleanMe(); assert(m_concept_map); assert(m_concept_map->IsValid()); 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 if (!m_concept_map->GetNodes().empty()) { //Add the main question as the first node const boost::shared_ptr<Node> node = m_concept_map->GetFocalNode(); QtNode * qtnode = nullptr; if (IsCenterNode(node)) { const boost::shared_ptr<CenterNode> centernode = boost::dynamic_pointer_cast<CenterNode>(node); qtnode = new QtCenterNode(centernode); } else { qtnode = new QtNode(node,this->GetDisplayStrategy(node->GetConcept())); } assert(qtnode); //Let the center node respond to mouse clicks qtnode->m_signal_request_scene_update.connect( boost::bind(&ribi::cmap::QtConceptMap::OnRequestSceneUpdate,this)); qtnode->m_signal_item_has_updated.connect( boost::bind(&ribi::cmap::QtConceptMap::OnItemRequestsUpdate,this,boost::lambda::_1)); //Add the center node to scene assert(!qtnode->scene()); this->scene()->addItem(qtnode); qtnodes.push_back(qtnode); assert(Collect<QtNode>(scene()).size() == 1); //Add the regular nodes to the scene const std::vector<boost::shared_ptr<ribi::cmap::Node> > nodes = m_concept_map->GetNodes(); const std::size_t n_nodes = nodes.size(); assert(n_nodes >= 1); for (std::size_t i=1; i!=n_nodes; ++i) //+1 to skip focal node { assert(Collect<QtNode>(scene()).size() == i && "Node not yet added to scene"); assert(i < nodes.size()); boost::shared_ptr<Node> node = nodes[i]; assert(node); assert( (IsCenterNode(node) || !IsCenterNode(node)) && "focal node != center node"); QtNode * const qtnode = AddNode(node); qtnodes.push_back(qtnode); assert(Collect<QtNode>(scene()).size() == i + 1 && "Node is added to scene"); } } #ifndef NDEBUG { //Check the number of const auto qtnodes = Collect<QtNode>(scene()); const auto n_qtnodes = qtnodes.size(); const auto nodes = m_concept_map->GetNodes(); const auto n_nodes = nodes.size(); assert(n_qtnodes == n_nodes && "There must as much nodes in the scene as there were in the concept map"); } #endif //Add the Concepts on the Edges { const std::vector<boost::shared_ptr<ribi::cmap::Edge> > edges = m_concept_map->GetEdges(); std::for_each(edges.begin(),edges.end(), [this,qtnodes](const boost::shared_ptr<Edge> edge) { assert(edge->GetFrom()); assert(edge->GetTo()); assert(edge->GetFrom() != edge->GetTo()); this->AddEdge(edge); } ); } #ifndef NDEBUG { //Check the number of edges const auto qtedges = Collect<QtEdge>(scene()); const auto n_qtedges = qtedges.size(); const auto edges = m_concept_map->GetEdges(); const auto n_edges = edges.size(); assert(n_qtedges == n_edges && "There must as much edges in the scene as there were in the concept map"); } #endif //Put the nodes around the focal question in an initial position if (MustReposition(AddConst(m_concept_map->GetNodes()))) { RepositionItems(); } #ifndef NDEBUG assert(m_concept_map->IsValid()); const auto nodes = m_concept_map->GetNodes(); const auto items = Collect<QtNode>(this->scene()); const std::size_t n_items = items.size(); const std::size_t n_nodes = nodes.size(); if (n_items != n_nodes) { TRACE(m_concept_map->GetNodes().size()); TRACE(n_items); TRACE(n_nodes); } assert(n_items == n_nodes && "GUI and non-GUI concept map must match"); TestMe(m_concept_map); #endif }