Logo Search packages:      
Sourcecode: ktechlab version File versions  Download package

bool ICNDocument::canConnect ( QCanvasItem *  qcanvasItem1,
QCanvasItem *  qcanvasItem2 
) const [virtual, inherited]

Reinherit this function to perform special checks on whether the two given QCanvasItems (either nodes or connectors or both) can be connected together.

Definition at line 155 of file icndocument.cpp.

References Node::acceptInput(), Node::acceptOutput(), Connector::endNode(), Item::level(), Node::level(), Node::numCon(), Item::parentItem(), Connector::startNode(), and Document::type().

Referenced by ICNDocument::createConnector(), CMManualConnector::mouseMoved(), and CMAutoConnector::mouseMoved().

{
      // Rough outline of what can and can't connect:
      // * At most three connectors to a node
      // * Can't have connectors going between different levels (e.g. can't have
      //   a connector coming outside a FlowContainer from inside).
      // * Can't have more than one route between any two nodes
      // * In all connections between nodes, must have at least one input and one
      //   output node at the ends.
      
      Node *startNode = dynamic_cast<Node*>(qcanvasItem1);
      Node *endNode = dynamic_cast<Node*>(qcanvasItem2);
      
      if ( (startNode && startNode->numCon( true, false ) > 2) || (endNode && endNode->numCon( true, false ) > 2) )
            return false;
      
      
      Connector *startConnector = dynamic_cast<Connector*>(qcanvasItem1);
      Connector *endConnector = dynamic_cast<Connector*>(qcanvasItem2);
      
      // Can't have T- or I- junction in PinMapEditor document
      if ( type() == Document::dt_pinMapEditor && (startConnector || endConnector) )
            return false;
      
      // Can't have I-junction in flowcode document
      if ( type() == Document::dt_flowcode && startConnector && endConnector )
            return false;
      
      
      //BEGIN Change connectors to nodes
      Node * startNode1 = 0l;
      Node * startNode2 = 0l;
      if (startConnector)
      {
            startNode1 = startConnector->startNode();
            startNode2 = startConnector->endNode();
            
            if ( !startNode1 || !startNode2 )
                  return false;
      }
      else if (!startNode)
            return false;
      
      Node * endNode1 = 0l;
      Node * endNode2 = 0l;
      if (endConnector)
      {
            endNode1 = endConnector->startNode();
            endNode2 = endConnector->endNode();
            
            if ( !endNode1 || !endNode2 )
                  return false;
      }
      else if ( !endNode )
            return false;
      
      Node * start[3];
      start[0] = startNode;
      start[1] = startNode1;
      start[2] = startNode2;
      
      Node * end[3];
      end[0] = endNode;
      end[1] = endNode1;
      end[2] = endNode2;
      //END Change connectors to nodes
      
      
      //BEGIN Check nodes aren't already connected
      for ( unsigned i = 0; i < 3; i++ )
      {
            for ( unsigned j = 0; j < 3; j++ )
            {
                  if ( start[i] && end[j] && start[i]->isConnected(end[j]) )
                        return false;
            }
      }
      //END Check nodes aren't already connected together
      
      
      //BEGIN Check we have appropriate input and output allowance
      if ( type() == Document::dt_flowcode )
      {
            if ( startNode1 && startNode2 && endNode1 && endNode2 )
            {
                  // Can't have I-configuration
                  return false;
            }
            
            if ( startNode && endNode )
            {
                  // Nice and easy straight line to check
                  
                  if ( !startNode->acceptInput() && !endNode->acceptInput() )
                        return false;
      
                  if ( !startNode->acceptOutput() && !endNode->acceptOutput() )
                        return false;
            }
            
            else
            {
                  // We're in a T-configuration, we can only make this if the base of
                  // the T is an output
                  Node * base = startNode ? startNode : endNode;
                  if ( !base->acceptOutput() )
                        return false;
            }
      }
      //END Check we have appropriate input and output allowance

      
      //BEGIN Simple level check
      for ( unsigned i = 0; i < 3; i++ )
      {
            for ( unsigned j = 0; j < 3; j++ )
            {
                  if ( start[i] && end[j] && start[i]->level() != end[j]->level() )
                        return false;
            }
      }
      //END Simple level check
      
      
      //BEGIN Advanced level check
      CNItem * startParentItem[3];
      for ( unsigned i = 0; i < 3; i++ )
            startParentItem[i] = start[i] ? start[i]->parentItem() : 0l;
      
      CNItem * endParentItem[3];
      for ( unsigned i = 0; i < 3; i++ )
            endParentItem[i] = end[i] ? end[i]->parentItem() : 0l;
      
      Item * container[6] = {0l};
      
      for ( unsigned i = 0; i < 3; i++ )
      {
            if (startParentItem[i])
            {
                  int dl = start[i]->level() - startParentItem[i]->level();
                  if ( dl == 0 )
                        container[i] = startParentItem[i]->parentItem();
                  else if ( dl == 1 )
                        container[i] = startParentItem[i];
                  else
                        kdError() << k_funcinfo << " start, i="<<i<<" dl="<<dl<<endl;
            }
            if (endParentItem[i])
            {
                  int dl = end[i]->level() - endParentItem[i]->level();
                  if ( dl == 0 )
                        container[i+3] = endParentItem[i]->parentItem();
                  else if ( dl == 1 )
                        container[i+3] = endParentItem[i];
                  else
                        kdError() << k_funcinfo << " end, i="<<i<<" dl="<<dl<<endl;
            }
      }
      
      // Everything better well have the same container...
      for ( unsigned i = 0; i < 6; ++i )
      {
            for ( unsigned j = 0; j < i; ++j )
            {
                  Node * n1 = i < 3 ? start[i] : end[i-3];
                  Node * n2 = j < 3 ? start[j] : end[j-3];
                  if ( n1 && n2 && (container[i] != container[j]) )
                        return false;
            }
      }
      //END Advanced level check
      
      
      // Well, it looks like we can, afterall, connect them...
      return true;
}


Generated by  Doxygen 1.6.0   Back to index