00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "cnitem.h"
00012 #include "icndocument.h"
00013 #include "connector.h"
00014 #include "itemdocumentdata.h"
00015 #include "node.h"
00016
00017 #include <kdebug.h>
00018
00019 #include <qpainter.h>
00020
00021 Node::Node( ICNDocument *icnDocument, Node::node_type type, node_dir dir, const QPoint &pos, QString *id )
00022 : QObject(), QCanvasPolygon( icnDocument->canvas() )
00023 {
00024 p_nodeGroup = 0;
00025 p_parentItem = 0;
00026 b_deleted = false;
00027 m_dir = dir;
00028 m_type = type;
00029 p_icnDocument = icnDocument;
00030 m_level = 0;
00031 m_selectedColor = QColor( 101, 134, 192 );
00032
00033 if (id) {
00034 m_id = *id;
00035 if ( !p_icnDocument->registerUID(*id) )
00036 kdError() << k_funcinfo << "Could not register id " << *id << endl;
00037 } else m_id = p_icnDocument->generateUID("node"+QString::number(type));
00038
00039 initPoints();
00040 move( pos.x(), pos.y() );
00041 setBrush( Qt::black );
00042 setPen( Qt::black );
00043 show();
00044
00045 emit (moved(this));
00046 }
00047
00048
00049 Node::~Node()
00050 {
00051 p_icnDocument->unregisterUID( id() );
00052 }
00053
00054
00055 int Node::rtti() const
00056 {
00057 return ICNDocument::RTTI::Node;
00058 }
00059
00060
00061 void Node::setLevel(const int level)
00062 {
00063 m_level = level;
00064 }
00065
00066 bool Node::acceptInput() const
00067 {
00068 return type() != fp_out;
00069 }
00070
00071
00072 bool Node::acceptOutput() const
00073 {
00074 return type() != fp_in;
00075 }
00076
00077 void Node::setVisible(bool yes)
00078 {
00079 if ( isVisible() == yes)
00080 return;
00081
00082 QCanvasPolygon::setVisible(yes);
00083
00084 const ConnectorList::iterator inputEnd = m_inputConnectorList.end();
00085 for ( ConnectorList::iterator it = m_inputConnectorList.begin(); it != inputEnd; ++it )
00086 {
00087 Connector *connector = *it;
00088 if (connector)
00089 {
00090 if ( isVisible() )
00091 connector->setVisible(true);
00092
00093 else
00094 {
00095 Node *node = connector->startNode();
00096 connector->setVisible( node && node->isVisible() );
00097 }
00098 }
00099 }
00100
00101 const ConnectorList::iterator outputEnd = m_outputConnectorList.end();
00102 for ( ConnectorList::iterator it = m_outputConnectorList.begin(); it != outputEnd; ++it )
00103 {
00104 Connector *connector = *it;
00105 if (connector)
00106 {
00107 if ( isVisible() )
00108 connector->setVisible(true);
00109
00110 else
00111 {
00112 Node *node = connector->endNode();
00113 connector->setVisible( node && node->isVisible() );
00114 }
00115 }
00116 }
00117 }
00118
00119
00120 bool Node::isConnected( Node *node, NodeList *checkedNodes )
00121 {
00122 if ( this == node )
00123 return true;
00124
00125 bool firstNode = !checkedNodes;
00126 if (firstNode)
00127 checkedNodes = new NodeList();
00128
00129 else if ( checkedNodes->contains(this) )
00130 return false;
00131
00132
00133 checkedNodes->append(this);
00134
00135 const ConnectorList::const_iterator inputEnd = m_inputConnectorList.end();
00136 for ( ConnectorList::const_iterator it = m_inputConnectorList.begin(); it != inputEnd; ++it )
00137 {
00138 Connector *connector = *it;
00139 if (connector)
00140 {
00141 Node *startNode = connector->startNode();
00142 if ( startNode && startNode->isConnected( node, checkedNodes ) ) {
00143 if (firstNode) {
00144 delete checkedNodes;
00145 checkedNodes = 0;
00146 }
00147 return true;
00148 }
00149 }
00150 }
00151
00152 const ConnectorList::const_iterator outputEnd = m_outputConnectorList.end();
00153 for ( ConnectorList::const_iterator it = m_outputConnectorList.begin(); it != outputEnd; ++it )
00154 {
00155 Connector *connector = *it;
00156 if (connector)
00157 {
00158 Node *endNode = connector->endNode();
00159 if ( endNode && endNode->isConnected( node, checkedNodes ) ) {
00160 if (firstNode) {
00161 delete checkedNodes;
00162 checkedNodes = 0;
00163 }
00164 return true;
00165 }
00166 }
00167 }
00168
00169 if (firstNode) {
00170 delete checkedNodes;
00171 checkedNodes = 0;
00172 }
00173
00174 return false;
00175 }
00176
00177 void Node::setOrientation( node_dir dir )
00178 {
00179 if ( m_dir == dir ) return;
00180
00181 if ( dir != Node::dir_up &&
00182 dir != Node::dir_right &&
00183 dir != Node::dir_down &&
00184 dir != Node::dir_left )
00185 {
00186 kdDebug() << "Node::setOrientation: Unknown node direction "<<dir<<endl;
00187 return;
00188 } else m_dir = dir;
00189 initPoints();
00190 }
00191
00192
00193 void Node::initPoints()
00194 {
00195 if ( type() == ec_junction )
00196 {
00197 setPoints( QPointArray( QRect( -4, -4, 8, 8 ) ) );
00198 return;
00199 }
00200
00201 if ( type() == fp_junction )
00202 {
00203 setPoints( QPointArray( QRect( -4, -4, 9, 9 ) ) );
00204 return;
00205 }
00206
00207 const int length = ( type() == ec_pin ) ? 8 : -8;
00208
00209
00210 QPointArray pa( QRect( 0, -8, length, 16 ) );
00211
00212 double angle;
00213 if ( m_dir == Node::dir_up ) angle = -90.;
00214 else if ( m_dir == Node::dir_right ) angle = 0.;
00215 else if ( m_dir == Node::dir_down ) angle = 90.;
00216 else if ( m_dir == Node::dir_left ) angle = 180.;
00217 else
00218 {
00219 kdError() << "Node::initPoints: unknown m_dir = "<<m_dir<<endl;
00220 return;
00221 }
00222
00223 QWMatrix m;
00224 m.rotate(angle);
00225 pa = m.map(pa);
00226 setPoints(pa);
00227 }
00228
00229
00230 QPoint Node::findConnectorDivergePoint( bool * found )
00231 {
00232 bool temp;
00233 if (!found)
00234 found = &temp;
00235 *found = false;
00236
00237 if ( numCon( false, false ) != 2 )
00238 return QPoint(0,0);
00239
00240 QPointList p1;
00241 QPointList p2;
00242
00243 int inSize = m_inputConnectorList.count();
00244
00245 const ConnectorList connectors = m_inputConnectorList + m_outputConnectorList;
00246 const ConnectorList::const_iterator end = connectors.end();
00247 bool gotP1 = false;
00248 bool gotP2 = false;
00249 int at = -1;
00250 for ( ConnectorList::const_iterator it = connectors.begin(); it != end && !gotP2; ++it )
00251 {
00252 at++;
00253 if ( !(*it) || !(*it)->canvas() )
00254 continue;
00255
00256 if (gotP1)
00257 {
00258 p2 = (*it)->connectorPoints( at < inSize );
00259 gotP2 = true;
00260 }
00261 else
00262 {
00263 p1 = (*it)->connectorPoints( at < inSize );
00264 gotP1 = true;
00265 }
00266 }
00267 if ( !gotP1 || !gotP2 )
00268 return QPoint(0,0);
00269
00270 unsigned maxLength = p1.size() > p2.size() ? p1.size() : p2.size();
00271
00272 for ( unsigned i = 1; i < maxLength; ++i ) {
00273 if ( p1[i] != p2[i] ) {
00274 *found = true;
00275 return p1[i-1];
00276 }
00277 }
00278 return QPoint(0, 0);
00279 }
00280
00281 void Node::setParentItem( CNItem *parentItem )
00282 {
00283 if (!parentItem) {
00284 kdError() << k_funcinfo << "no parent item" << endl;
00285 return;
00286 }
00287
00288 p_parentItem = parentItem;
00289
00290 setLevel(p_parentItem->level());
00291
00292 connect( p_parentItem, SIGNAL(movedBy(double, double )), this, SLOT(moveBy(double, double)) );
00293 connect( p_parentItem, SIGNAL(removed(Item*)), this, SLOT(removeNode(Item*)) );
00294 }
00295
00296 void Node::removeNode()
00297 {
00298 if (b_deleted) return;
00299
00300 b_deleted = true;
00301
00302 emit removed(this);
00303 p_icnDocument->appendDeleteList(this);
00304 }
00305
00306 void Node::moveBy( double dx, double dy )
00307 {
00308 if ( dx == 0 && dy == 0 ) return;
00309 QCanvasPolygon::moveBy( dx, dy );
00310 emit moved(this);
00311 }
00312
00313 int Node::numCon( bool includeParentItem, bool includeHiddenConnectors ) const
00314 {
00315 unsigned count = 0;
00316
00317 const ConnectorList connectors[2] = { m_inputConnectorList, m_outputConnectorList };
00318
00319 for ( unsigned i = 0; i < 2; i++ )
00320 {
00321 ConnectorList::const_iterator end = connectors[i].end();
00322 for ( ConnectorList::const_iterator it = connectors[i].begin(); it != end; ++it )
00323 {
00324 if ( *it && (includeHiddenConnectors || (*it)->canvas()) )
00325 count++;
00326 }
00327 }
00328
00329 if ( isChildNode() && includeParentItem )
00330 count++;
00331
00332 return count;
00333 }
00334
00335
00336 void Node::addOutputConnector( Connector * const connector )
00337 {
00338 if ( type() == fp_in || !handleNewConnector(connector) )
00339 return;
00340
00341 m_outputConnectorList.append(connector);
00342
00343 if(type() == fp_out || type() == fp_junction) {
00344
00345
00346
00347
00348
00349 const ConnectorList connectors = m_outputConnectorList;
00350 const ConnectorList::const_iterator end = connectors.end();
00351 for ( ConnectorList::const_iterator it = connectors.begin(); it != end; ++it ) {
00352 Connector * con = *it;
00353 if ( con && con != connector )
00354 con->removeConnector();
00355 }
00356 }
00357
00358 m_outputConnectorList.remove((Connector*)0);
00359 }
00360
00361 void Node::addInputConnector( Connector * const connector )
00362 {
00363 if ( type() == fp_out || !handleNewConnector(connector) )
00364 return;
00365
00366 m_inputConnectorList.append(connector);
00367 }
00368
00369 bool Node::handleNewConnector( Connector * connector )
00370 {
00371 if (!connector) return false;
00372
00373 if(m_inputConnectorList.contains(connector) || m_outputConnectorList.contains(connector)) {
00374 kdWarning() << k_funcinfo << " Already have connector = " << connector << endl;
00375 return false;
00376 }
00377
00378 connect( this, SIGNAL(removed(Node*)), connector, SLOT(removeConnector(Node*)) );
00379 connect( connector, SIGNAL(removed(Connector*)), this, SLOT(checkForRemoval(Connector*)) );
00380 connect( connector, SIGNAL(selected(bool)), this, SLOT(setNodeSelected(bool)) );
00381
00382 if ( !isChildNode() )
00383 p_icnDocument->slotRequestAssignNG();
00384
00385 return true;
00386 }
00387
00388 Connector* Node::createInputConnector( Node * startNode )
00389 {
00390 if(type() == fp_out || !startNode) return 0;
00391
00392 Connector *connector = new Connector( startNode, this, p_icnDocument );
00393 addInputConnector(connector);
00394
00395 return connector;
00396 }
00397
00398 void Node::removeConnector( Connector *connector )
00399 {
00400 if (!connector) return;
00401
00402 ConnectorList::iterator it;
00403
00404 it = m_inputConnectorList.find(connector);
00405 if(it != m_inputConnectorList.end() ) {
00406 (*it)->removeConnector();
00407 (*it) = 0;
00408 }
00409
00410 it = m_outputConnectorList.find(connector);
00411 if(it != m_outputConnectorList.end()) {
00412 (*it)->removeConnector();
00413 (*it) = 0;
00414 }
00415 }
00416
00417 void Node::checkForRemoval( Connector *connector )
00418 {
00419 removeConnector(connector);
00420 setNodeSelected(false);
00421
00422 removeNullConnectors();
00423
00424 if (!p_parentItem) {
00425 int conCount = m_inputConnectorList.count() + m_outputConnectorList.count();
00426 if ( conCount < 2 ) removeNode();
00427 }
00428
00429 if ( type() == Node::fp_junction && m_outputConnectorList.isEmpty() )
00430 removeNode();
00431 }
00432
00433 void Node::removeNullConnectors()
00434 {
00435 m_inputConnectorList.remove((Connector*)0);
00436 m_outputConnectorList.remove((Connector*)0);
00437 }
00438
00439 NodeData Node::nodeData() const
00440 {
00441 NodeData data;
00442 data.x = x();
00443 data.y = y();
00444 return data;
00445 }
00446
00447 void Node::setNodeSelected( bool yes )
00448 {
00449 if ( isSelected() == yes ) return;
00450
00451 QCanvasItem::setSelected(yes);
00452
00453 setPen( yes ? m_selectedColor : Qt::black );
00454 setBrush( yes ? m_selectedColor : Qt::black );
00455 }
00456
00457 #include "node.moc"
00458