From 5de3dd4762ca33a0f92e79ffa4fe2ff67069d531 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 24 Feb 2010 01:49:02 +0000 Subject: Added KDE3 version of ktechlab git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/ktechlab@1095338 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- src/node.cpp | 486 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 486 insertions(+) create mode 100644 src/node.cpp (limited to 'src/node.cpp') diff --git a/src/node.cpp b/src/node.cpp new file mode 100644 index 0000000..9a3531d --- /dev/null +++ b/src/node.cpp @@ -0,0 +1,486 @@ +/*************************************************************************** + * Copyright (C) 2003-2005 by David Saxton * + * david@bluehaze.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "cnitem.h" +#include "icndocument.h" +#include "connector.h" +#include "itemdocumentdata.h" +#include "node.h" + +#include + +#include + +Node::Node( ICNDocument *icnDocument, Node::node_type type, node_dir dir, const QPoint &pos, QString *id ) + : QObject(), QCanvasPolygon( icnDocument->canvas() ) +{ + p_nodeGroup = 0l; + p_parentItem = 0L; + b_deleted = false; + m_dir = dir; + m_type = type; + p_icnDocument = icnDocument; + m_level = 0; + m_selectedColor = QColor( 101, 134, 192 ); + + if (id) + { + m_id = *id; + if ( !p_icnDocument->registerUID(*id) ) + kdError() << k_funcinfo << "Could not register id " << *id << endl; + } + else m_id = p_icnDocument->generateUID("node"+QString::number(type)); + + initPoints(); + move( pos.x(), pos.y() ); + setBrush( Qt::black ); + setPen( Qt::black ); + show(); + + emit (moved(this)); +} + + +Node::~Node() +{ + p_icnDocument->unregisterUID( id() ); +} + + +int Node::rtti() const +{ + return ICNDocument::RTTI::Node; +} + + +void Node::setLevel( const int level ) +{ + m_level = level; +} + + +bool Node::acceptInput() const +{ + return type() != fp_out; +} + + +bool Node::acceptOutput() const +{ + return type() != fp_in; +} + + +void Node::setVisible( bool yes ) +{ + if ( isVisible() == yes ) + return; + + QCanvasPolygon::setVisible(yes); + + const ConnectorList::iterator inputEnd = m_inputConnectorList.end(); + for ( ConnectorList::iterator it = m_inputConnectorList.begin(); it != inputEnd; ++it ) + { + Connector *connector = *it; + if (connector) + { + if ( isVisible() ) + connector->setVisible(true); + + else + { + Node *node = connector->startNode(); + connector->setVisible( node && node->isVisible() ); + } + } + } + + const ConnectorList::iterator outputEnd = m_outputConnectorList.end(); + for ( ConnectorList::iterator it = m_outputConnectorList.begin(); it != outputEnd; ++it ) + { + Connector *connector = *it; + if (connector) + { + if ( isVisible() ) + connector->setVisible(true); + + else + { + Node *node = connector->endNode(); + connector->setVisible( node && node->isVisible() ); + } + } + } +} + + +bool Node::isConnected( Node *node, NodeList *checkedNodes ) +{ + if ( this == node ) + return true; + + bool firstNode = !checkedNodes; + if (firstNode) + checkedNodes = new NodeList(); + + else if ( checkedNodes->contains(this) ) + return false; + + + checkedNodes->append(this); + + const ConnectorList::const_iterator inputEnd = m_inputConnectorList.end(); + for ( ConnectorList::const_iterator it = m_inputConnectorList.begin(); it != inputEnd; ++it ) + { + Connector *connector = *it; + if (connector) + { + Node *startNode = connector->startNode(); + if ( startNode && startNode->isConnected( node, checkedNodes ) ) { + if (firstNode) { + delete checkedNodes; + } + return true; + } + } + } + + const ConnectorList::const_iterator outputEnd = m_outputConnectorList.end(); + for ( ConnectorList::const_iterator it = m_outputConnectorList.begin(); it != outputEnd; ++it ) + { + Connector *connector = *it; + if (connector) + { + Node *endNode = connector->endNode(); + if ( endNode && endNode->isConnected( node, checkedNodes ) ) { + if (firstNode) { + delete checkedNodes; + } + return true; + } + } + } + + if (firstNode) { + delete checkedNodes; + } + + return false; +} + + +void Node::setOrientation( node_dir dir ) +{ + if ( m_dir == dir ) + return; + + if ( dir != Node::dir_up && + dir != Node::dir_right && + dir != Node::dir_down && + dir != Node::dir_left ) + { + kdDebug() << "Node::setOrientation: Unknown node direction "<level()); + + connect( p_parentItem, SIGNAL(movedBy(double, double )), this, SLOT(moveBy(double, double)) ); + connect( p_parentItem, SIGNAL(removed(Item*)), this, SLOT(removeNode(Item*)) ); +} + + +void Node::removeNode() +{ + if (b_deleted) + return; + b_deleted = true; + + emit removed(this); + p_icnDocument->appendDeleteList(this); +} + + +void Node::moveBy( double dx, double dy ) +{ + if ( dx == 0 && dy == 0 ) return; + QCanvasPolygon::moveBy( dx, dy ); + emit moved(this); +} + + +int Node::numCon( bool includeParentItem, bool includeHiddenConnectors ) const +{ + unsigned count = 0; + + const ConnectorList connectors[2] = { m_inputConnectorList, m_outputConnectorList }; + + for ( unsigned i = 0; i < 2; i++ ) + { + ConnectorList::const_iterator end = connectors[i].end(); + for ( ConnectorList::const_iterator it = connectors[i].begin(); it != end; ++it ) + { + if ( *it && (includeHiddenConnectors || (*it)->canvas()) ) + count++; + } + } + + if ( isChildNode() && includeParentItem ) + count++; + + return count; +} + + +void Node::addOutputConnector( Connector * const connector ) +{ + if ( type() == fp_in || !handleNewConnector(connector) ) + return; + + m_outputConnectorList.append(connector); + + if ( type() == fp_out || type() == fp_junction ) + { + // We can only have one output connector, so remove the others. Note + // that this code has to come *after* adding the new output connector, + // as this node will delete itself if it's an fp_junction and there are + // no output connectors. + + const ConnectorList connectors = m_outputConnectorList; + const ConnectorList::const_iterator end = connectors.end(); + for ( ConnectorList::const_iterator it = connectors.begin(); it != end; ++it ) + { + Connector * con = *it; + if ( con && con != connector ) + con->removeConnector(); + } + } + + m_outputConnectorList.remove((Connector*)0l); +} + + +void Node::addInputConnector( Connector * const connector ) +{ + if ( type() == fp_out || !handleNewConnector(connector) ) + return; + + m_inputConnectorList.append(connector); +} + + +bool Node::handleNewConnector( Connector * connector ) +{ + if (!connector) + return false; + + if ( m_inputConnectorList.contains(connector) || m_outputConnectorList.contains(connector) ) + { + kdWarning() << k_funcinfo << " Already have connector = " << connector << endl; + return false; + } + + connect( this, SIGNAL(removed(Node*)), connector, SLOT(removeConnector(Node*)) ); + connect( connector, SIGNAL(removed(Connector*)), this, SLOT(checkForRemoval(Connector*)) ); + connect( connector, SIGNAL(selected(bool)), this, SLOT(setNodeSelected(bool)) ); + + if ( !isChildNode() ) + p_icnDocument->slotRequestAssignNG(); + + return true; +} + + +Connector* Node::createInputConnector( Node * startNode ) +{ + if ( type() == fp_out || !startNode ) + return 0l; + + Connector *connector = new Connector( startNode, this, p_icnDocument ); + addInputConnector(connector); + + return connector; +} + + +void Node::removeConnector( Connector *connector ) +{ + if (!connector) + return; + + ConnectorList::iterator it; + + it = m_inputConnectorList.find(connector); + if ( it != m_inputConnectorList.end() ) + { + (*it)->removeConnector(); + (*it) = 0L; + } + + it = m_outputConnectorList.find(connector); + if ( it != m_outputConnectorList.end() ) + { + (*it)->removeConnector(); + (*it) = 0L; + } +} + +void Node::checkForRemoval( Connector *connector ) +{ + removeConnector(connector); + setNodeSelected(false); + + removeNullConnectors(); + + if (!p_parentItem) + { + int conCount = m_inputConnectorList.count() + m_outputConnectorList.count(); + if ( conCount < 2 ) + removeNode(); + } + + if ( type() == Node::fp_junction && m_outputConnectorList.isEmpty() ) + removeNode(); +} + +void Node::removeNullConnectors() +{ + m_inputConnectorList.remove((Connector*)0L); + m_outputConnectorList.remove((Connector*)0L); +} + + +NodeData Node::nodeData() const +{ + NodeData data; + data.x = x(); + data.y = y(); + return data; +} + + +void Node::setNodeSelected( bool yes ) +{ + if ( isSelected() == yes ) + return; + + QCanvasItem::setSelected(yes); + + setPen( yes ? m_selectedColor : Qt::black ); + setBrush( yes ? m_selectedColor : Qt::black ); +} + +#include "node.moc" -- cgit v1.2.3