Connector *CircuitICNDocument::createConnector( const QString &startNodeId, const QString &endNodeId, QPointList *pointList )
{
	ECNode *startNode = getEcNodeWithID(startNodeId);
	ECNode *endNode = getEcNodeWithID(endNodeId);
	
	if ( !startNode || !endNode ) {
		kDebug() << "Either/both the connector start node and end node could not be found" << endl;
		return 0L;
	}
	
	if ( !canConnect( startNode, endNode ) ) return 0l;
	
	Connector *connector = endNode->createConnector(startNode);
	if (!connector) {
		kError() << k_funcinfo << "End node did not create the connector" << endl;
		return 0l;
	}

	startNode->addConnector(connector);
	flushDeleteList(); // Delete any connectors that might have been removed by the nodes
	
	// Set the route to the manual created one if the user created such a route
	if(pointList) connector->setRoutePoints(*pointList,true);
	
	// FIXME WTF is going on here? Redundant/meaningless code?
//	ConnectorList connectorList;
//	connectorList.append(connector);
	
	setModified(true);
	
	requestRerouteInvalidatedConnectors();
	return connector;
}
Connector * CircuitICNDocument::createConnector( Node *node, Connector *con, const QPoint &pos2, QPointList *pointList )
{
	if(!canConnect( node, con ) ) return 0;
	
	// FIXME dynamic_cast used, fix it in Connector class
	
	ECNode *conStartNode = dynamic_cast<ECNode *> (con->startNode() );
	ECNode *conEndNode   = dynamic_cast<ECNode *> (con->endNode() );
	ECNode *ecNode       = dynamic_cast<ECNode *> (node );
	
	const bool usedManual = con->usesManualPoints();
	
	ECNode *newNode = new JunctionNode(this, 0, pos2);

	QPointList autoPoints;
	if (!pointList) {
		addAllItemConnectorPoints();
		ConRouter cr(this);
		cr.mapRoute( int(node->x()), int(node->y()), pos2.x(), pos2.y() );
		autoPoints = cr.pointList(false);
		pointList = &autoPoints;
	}
	
	QList<QPointList> oldConPoints = con->splitConnectorPoints(pos2);
	con->hide();

	// The actual new connector
	Connector *new1 = newNode->createConnector(node);
	ecNode->addConnector(new1);
	new1->setRoutePoints(*pointList,usedManual);

	// The two connectors formed from the original one when split
	Connector *new2 = newNode->createConnector(conStartNode);
	conStartNode->addConnector(new2);
	new2->setRoutePoints( oldConPoints.at(0), usedManual );

	Connector *new3 = conEndNode->createConnector(newNode);
	newNode->addConnector(new3);
	new3->setRoutePoints( oldConPoints.at(1), usedManual );

	// Avoid flicker: tell them to update their draw lists now
	con->updateConnectorPoints(false);
	new1->updateDrawList();
	new2->updateDrawList();
	new3->updateDrawList();

	// Now it's safe to remove the connector...
	con->removeConnector();
	flushDeleteList();

	deleteNodeGroup(conStartNode);
	deleteNodeGroup(conEndNode);
	createNodeGroup(newNode)->init();

	return new1;
}
bool CircuitICNDocument::joinConnectors( ECNode *node )
{
	// We don't want to destroy the node if it has a parent
	if ( node->parentItem() ) return false;

	node->removeNullConnectors();

	// an electronic node can be removed if it has exactly 2 connectors connected to it

	int conCount = node->getAllConnectors().count();
	if ( conCount != 2 ) return false;

	Connector *con1, *con2;
	ECNode *startNode = NULL;
    ECNode *endNode = NULL;
	QPointList conPoints;

	con1 = node->connectorList().at(0).data();
	con2 = node->connectorList().at(1).data();

	if ( con1 == con2 ) return false;

	// we don't know on which end of the connectors is our node, so we must check both ends
	// HACK // TODO // dynamic_cast used, because Connector doesn't know about ECNode, only Node
	if( con1->startNode() == node )
		startNode = dynamic_cast<ECNode*> ( con1->endNode() );
	else	startNode = dynamic_cast<ECNode*> ( con1->startNode() );

	if( con2->startNode() == node )
		endNode = dynamic_cast<ECNode*> ( con2->endNode() );
	else	endNode = dynamic_cast<ECNode*> ( con2->startNode() );

	conPoints = con1->connectorPoints(false) + con2->connectorPoints(false);
	
	if( !startNode || !endNode ) return false;

	Connector *newCon = endNode->createConnector(startNode);

	if(!newCon) return false;

	startNode->addConnector(newCon);
	newCon->setRoutePoints( conPoints, con1->usesManualPoints() || con2->usesManualPoints() );

	// Avoid flicker: update draw lists now
	con1->updateConnectorPoints(false);
	con2->updateConnectorPoints(false);
	newCon->updateDrawList();

	node->removeNode();
	con1->removeConnector();
	con2->removeConnector();
	
	return true;
}
Esempio n. 4
0
void MultiInputGate::updateInputs(int newNum) {
	if (newNum == m_numInputs) return;

	if (newNum < 2) newNum = 2;
	else if (newNum > maxGateInput)
		newNum = maxGateInput;

	int newWidth = logicSymbolShapeToWidth();

	QRect r(-newWidth / 2, -8 * newNum, newWidth, 16 * newNum);

	setSize(r, true);
	updateSymbolText();

	const bool added = (newNum > m_numInputs);

	if (added) {
		for (int i = m_numInputs; i < newNum; ++i) {
			ECNode *node = createPin(0, 0, 0, "in" + QString::number(i));
			inNode[i] = node;

			inLogic[i] = new LogicIn(LogicConfig());
			setup1pinElement(*(inLogic[i]), node->pin());

			inLogic[i]->setCallback(this, (CallbackPtr)(&MultiInputGate::inStateChanged));
		}
	} else {
		for (int i = newNum; i < m_numInputs; ++i) {
			removeNode("in" + QString::number(i));
			removeElement(inLogic[i], false);
			inNode[i] = 0;
			inLogic[i] = 0;
		}
	}

	m_numInputs = newNum;

	// We can't call a pure-virtual function if we haven't finished our constructor yet...

	if (m_bDoneInit)
		inStateChanged(!added);

	updateAttachedPositioning();
}
void CircuitICNDocument::deleteAllNodes() {

    const ECNodeMap::iterator nodeListEnd = m_ecNodeList.end();
	for ( ECNodeMap::iterator it = m_ecNodeList.begin(); it != nodeListEnd; ++it ) {
        qDebug() << "CircuitICNDocument::deleteAllNodes removing [" << it.key() << "] " << it.value();
		//delete *it; // 2015.07.31 - this will not work

        // prevent crash on node destructor
        {
            ECNode *ecNode = it.value();
            //unregisterUID( ecNode->id() ); // do not use, will modify m_ecNodeList
            ICNDocument::unregisterUID( ecNode->id() );
            ecNode->setICNDocument( NULL );
        }


        it.value()->deleteLater();
    }

	m_ecNodeList.clear();
}
Esempio n. 6
0
ParallelPortComponent::ParallelPortComponent(ICNDocument *icnDocument, bool newItem, const char *id)
		: DSubCon(icnDocument, newItem, id ? id : "parallel_port") {
	m_name = i18n("Parallel Port");

	Q3PointArray pa(4);
	pa[0] = QPoint(-32, -112);
	pa[1] = QPoint(32, -104);
	pa[2] = QPoint(32, 104);
	pa[3] = QPoint(-32, 112);
	setItemPoints(pa);

	m_pParallelPort = new ParallelPort();

	for (unsigned i = 0; i < 24; ++i)
		m_pLogic[i] = 0;

	ECNode *pin = 0;

	//BEGIN Data register
	for (int i = 0; i < 8; ++i) {
		QString id = QString("D%1").arg(i);
		QString name = id;

		pin = createPin(-40, -80 + 16 * i, 0, id);
		addDisplayText(id, QRect(-28, -88 + 16 * i, 28, 16), name, true, Qt::AlignLeft | Qt::AlignVCenter);

		m_pLogic[i] = new LogicOut(LogicConfig(), false);
		setup1pinElement(*(m_pLogic[i]), createPin(-40, -80 + 16 * i, 0, id)->pin());

//		m_pLogic[i]->setCallback(this, (CallbackPtr)(&ParallelPortComponent::dataCallback));
	}
	//END Data register

	//BEGIN Status register
	QString statusNames[] = {"ERR", "ON", "PE", "ACK", "BUSY"};

	// The statusIDs are referenced in the save file and must not change
	QString statusIDs[] = {"ERROR", "ONLINE", "PE", "ACK", "BUSY"};

	// Bits 0...2 in the Status register are not used
	for (int i = 3; i < 8; ++i) {
		QString id = statusIDs[i - 3];
		QString name = statusNames[i - 3];

		// Bit 3 (pin 15) doesn't not follow the same positioning pattern as
		// the other pins in the Status register.

		if (i == 3) {
			pin = createPin(40, -72, 180, id);
			addDisplayText(id, QRect(0, -80, 28, 16), name, true, Qt::AlignRight | Qt::AlignVCenter);
		} else {
			pin = createPin(-40, -16 + 16 * i, 0, id);
			addDisplayText(id, QRect(-28, -24 + 16*i, 28, 16), name, true, Qt::AlignLeft | Qt::AlignVCenter);
		}

		m_pLogic[i + 8] = new LogicOut(LogicConfig(), false);

		setup1pinElement(*(m_pLogic[i + 8]), pin->pin());
	}
	//END Status register

	//BEGIN Control register
	QString controlNames[] = { "STR", "AUT", "INIT", "SEL" };

	// The controlIDs are referenced in the save file and must not change
	QString controlIDs[] = { "STROBE", "AUTO", "INIT", "SELECT" };

	// Bits 4..7 are not used (well; bit 5 is, but not as a pin)
	for (int i = 0; i < 4; ++i) {
		QString id = controlIDs[i];
		QString name = controlNames[i];

		if (i == 0) {
			pin = createPin(-40, -96, 0, id);
			addDisplayText(id, QRect(-28, -104, 28, 16), name, true, Qt::AlignLeft | Qt::AlignVCenter);
		} else if (i == 1) {
			pin = createPin(40, -88, 180, id);
			addDisplayText(id, QRect(0, -96, 28, 16), name, true, Qt::AlignRight | Qt::AlignVCenter);
		} else {
			pin = createPin(40, -88 + i * 16, 180, id);
			addDisplayText(id, QRect(0, -96 + i * 16, 28, 16), name, true, Qt::AlignRight | Qt::AlignVCenter);
		}

		m_pLogic[i + 16] = new LogicOut(LogicConfig(), false);

		setup1pinElement(*(m_pLogic[i + 16]), pin->pin());

//		m_pLogic[i + 16]->setCallback(this, (CallbackPtr)(&ParallelPortComponent::controlCallback));
	}
	//END Control register

#if 0
	// And make the rest of the pins ground
	for (int i = 0; i < 8; ++i) {
		pin = createPin(40, -24 + i * 16, 180, QString("GND%1").arg(i));
		pin->pin()->setGroundType(Pin::gt_always);
	}

#endif
	Variant *v = createProperty("port", Variant::Type::Combo);
	v->setAllowed(ParallelPort::ports(Port::ExistsAndRW));
	v->setCaption(i18n("Port"));
}
SerialPortComponent::SerialPortComponent( ICNDocument *icnDocument, bool newItem, const char *id )
	: Component( icnDocument, newItem, id ? id : "serial_port" )
{
	m_name = i18n("Serial Port");
	
	Q3PointArray pa( 4 );
	pa[0] = QPoint( -32, -48 );
	pa[1] = QPoint( 32, -40 );
	pa[2] = QPoint( 32, 40 );
	pa[3] = QPoint( -32, 48 );
	
	setItemPoints( pa );
	
	m_pSerialPort = new SerialPort();
	
	ECNode * pin = 0;
	
	// Works
	pin = createPin( -40,  32,   0, "CD" );
	addDisplayText( "CD", QRect( -28, 24, 28, 16 ), "CD", true, Qt::AlignLeft | Qt::AlignVCenter );
	m_pCD = createLogicOut( pin, false  );
	
	// Doesn't work
// 	pin = createPin( -40,  16,   0, "RD" );
	addDisplayText( "RD", QRect( -28, 8, 28, 16 ), "RD", true, Qt::AlignLeft | Qt::AlignVCenter );
// 	m_pRD = createLogicOut( pin, false  );
	
	// Works
	pin = createPin( -40,   0,   0, "TD" );
	addDisplayText( "TD", QRect( -28, -8, 28, 16 ), "TD", true, Qt::AlignLeft | Qt::AlignVCenter );
	m_pTD = createLogicIn( pin);
	m_pTD->setCallback( this, (CallbackPtr)(&SerialPortComponent::tdCallback) );
	
	// Works
	pin = createPin( -40, -16,   0, "DTR" );
	addDisplayText( "DTR", QRect( -28, -24, 28, 16 ), "DTR", true, Qt::AlignLeft | Qt::AlignVCenter );
	m_pDTR = createLogicIn( pin );
	m_pDTR->setCallback( this, (CallbackPtr)(&SerialPortComponent::dtrCallback) );
	
	// N/A
	pin = createPin( -40, -32,   0, "GND" );
	addDisplayText( "GND", QRect( -28, -40, 28, 16 ), "GND", true, Qt::AlignLeft | Qt::AlignVCenter );
	pin->pin()->setGroundType( Pin::gt_always );
	
	// Doesn't work
// 	pin = createPin(  40,  24, 180, "DSR" );
	addDisplayText( "DSR", QRect( 0, 16, 28, 16 ), "DSR", true, Qt::AlignRight | Qt::AlignVCenter );
// 	m_pDSR = createLogicIn( pin );
// 	m_pDSR->setCallback( this, (CallbackPtr)(&SerialPortComponent::dsrCallback) );
	
	// Doesn't work
// 	pin = createPin(  40,   8, 180, "RTS" );
	addDisplayText( "RTS", QRect( 0, 0, 28, 16 ), "RTS", true, Qt::AlignRight | Qt::AlignVCenter );
// 	m_pRTS = createLogicIn( pin );
// 	m_pRTS->setCallback( this, (CallbackPtr)(&SerialPortComponent::rtsCallback) );
	
	// Works
	pin = createPin(  40,  -8, 180, "CTS" );
	addDisplayText( "CTS", QRect( 0, -16, 28, 16 ), "CTS", true, Qt::AlignRight | Qt::AlignVCenter );
	m_pCTS = createLogicOut( pin, false  );
	
	// Works
	pin = createPin(  40, -24, 180, "RI" );
	addDisplayText( "RI", QRect( 0, -32, 28, 16 ), "RI", true, Qt::AlignRight | Qt::AlignVCenter );
	m_pRI = createLogicOut( pin, false  );
	
	Variant * v = createProperty( "port", Variant::Type::Combo );
	v->setAllowed( SerialPort::ports( Port::ExistsAndRW ) );
	v->setCaption( i18n("Port") );
	
// 	v = createProperty( "baudRate", Variant::Type::Select );
// 	v->setAllowed( QStringList::split( ",", "B0,B50,B75,B110,B134,B150,B200,B300,B600,B1200,B1800,B2400,B4800,B9600,B19200,B38400" ) );
// 	v->setCaption( i18n("Baud rate") );
// 	v->setValue("B9600");
}