/*************************************************************************** * Copyright (C) 2003-2004 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 "cnitemgroup.h" #include "component.h" #include "connector.h" #include "flowpart.h" #include "icndocument.h" #include "node.h" #include "nodegroup.h" CNItemGroup::CNItemGroup( ICNDocument *icnDocument, const char *name) : ItemGroup( icnDocument, name ) { p_icnDocument = icnDocument; m_connectorCount = 0; m_nodeCount = 0; m_currentLevel = -1; } CNItemGroup::~CNItemGroup() { } bool CNItemGroup::addItem( Item *item ) { // Note, we must prepend the item to the list so that // activeCNItem() can return the item at the start // of the list as the most recently added item if some // the previous activeCNItem is removed if ( !item || !item->canvas() || m_itemList.contains(item) || !item->isMovable() ) return false; if ( m_currentLevel != -1 && item->level() > m_currentLevel ) return false; if ( item && m_currentLevel > item->level() ) removeAllItems(); registerItem(item); m_currentLevel = item->level(); setActiveItem(item); item->setSelected(true); updateInfo(); emit itemAdded(item); return true; } bool CNItemGroup::addNode( Node *node ) { if ( !node || m_nodeList.contains(node) || node->isChildNode() ) return false; m_nodeList.prepend(node); node->setSelected(true); updateInfo(); emit nodeAdded(node); return true; } bool CNItemGroup::addConnector( Connector *con ) { if ( !con || m_connectorList.contains(con) ) return false; m_connectorList.prepend(con); con->setSelected(true); updateInfo(); emit connectorAdded(con); return true; } bool CNItemGroup::addTQCanvasItem( TQCanvasItem *qcanvasItem ) { if (!qcanvasItem) return false; Item *item = dynamic_cast(qcanvasItem); if (item) return addItem(item); Node *node = dynamic_cast(qcanvasItem); if (node) return addNode(node); Connector *connector = dynamic_cast(qcanvasItem); if (!connector) { ConnectorLine *connectorLine = dynamic_cast(qcanvasItem); if (connectorLine) connector = connectorLine->parent(); } if (connector) return addConnector(connector); return false; } void CNItemGroup::setItems( TQCanvasItemList list ) { ItemList itemRemoveList = m_itemList; ConnectorList connectorRemoveList = m_connectorList; NodeList nodeRemoveList = m_nodeList; const TQCanvasItemList::const_iterator end = list.end(); for ( TQCanvasItemList::const_iterator it = list.begin(); it != end; ++it ) { switch ( *it ? (*it)->rtti() : 0 ) { case ItemDocument::RTTI::CNItem: case ItemDocument::RTTI::DrawPart: { itemRemoveList.remove( dynamic_cast(*it) ); break; } case ItemDocument::RTTI::Node: { nodeRemoveList.remove( dynamic_cast(*it) ); break; } case ItemDocument::RTTI::Connector: { connectorRemoveList.remove( dynamic_cast(*it) ); break; } case ItemDocument::RTTI::ConnectorLine: { connectorRemoveList.remove( (dynamic_cast(*it))->parent() ); break; } default: break; } } { const ItemList::const_iterator end = itemRemoveList.end(); for ( ItemList::const_iterator it = itemRemoveList.begin(); it != end; ++it ) { removeItem(*it); (*it)->setSelected(false); } } { const NodeList::const_iterator end = nodeRemoveList.end(); for ( NodeList::const_iterator it = nodeRemoveList.begin(); it != end; ++it ) { removeNode(*it); (*it)->setSelected(false); } } { const ConnectorList::const_iterator end = connectorRemoveList.end(); for ( ConnectorList::const_iterator it = connectorRemoveList.begin(); it != end; ++it ) { removeConnector(*it); (*it)->setSelected(false); } } { const TQCanvasItemList::const_iterator end = list.end(); for ( TQCanvasItemList::const_iterator it = list.begin(); it != end; ++it ) { // We don't need to check that we've already got the item as it will // be checked in the function call addTQCanvasItem(*it); } } } void CNItemGroup::removeItem( Item *item ) { if ( !item || !m_itemList.contains(item) ) return; unregisterItem(item); if ( m_activeItem == item ) getActiveItem(); item->setSelected(false); updateInfo(); emit itemRemoved(item); } void CNItemGroup::removeNode( Node *node ) { if ( !node || !m_nodeList.contains(node) ) return; m_nodeList.remove(node); node->setSelected(false); updateInfo(); emit nodeRemoved(node); } void CNItemGroup::removeConnector( Connector *con ) { if ( !con || !m_connectorList.contains(con) ) return; m_connectorList.remove(con); con->setSelected(false); updateInfo(); emit connectorRemoved(con); } void CNItemGroup::removeTQCanvasItem( TQCanvasItem *qcanvasItem ) { if (!qcanvasItem) return; Item *item = dynamic_cast(qcanvasItem); if (item) return removeItem(item); Node *node = dynamic_cast(qcanvasItem); if (node) return removeNode(node); Connector *connector = dynamic_cast(qcanvasItem); if (!connector) { ConnectorLine *connectorLine = dynamic_cast(qcanvasItem); if (connectorLine) connector = connectorLine->parent(); } if (connector) return removeConnector(connector); } NodeList CNItemGroup::nodes( bool excludeParented ) const { NodeList nodeList = m_nodeList; if (excludeParented) return nodeList; NodeGroupList translatableNodeGroups; p_icnDocument->getTranslatable( items(false), 0l, 0l, &translatableNodeGroups ); NodeGroupList::iterator end = translatableNodeGroups.end(); for ( NodeGroupList::iterator it = translatableNodeGroups.begin(); it != end; ++it ) { const NodeList internal = (*it)->internalNodeList(); NodeList::const_iterator internalEnd = internal.end(); for ( NodeList::const_iterator intIt = internal.begin(); intIt != internalEnd; ++intIt ) { if ( *intIt && !nodeList.contains(*intIt) ) nodeList << *intIt; } } return nodeList; } ConnectorList CNItemGroup::connectors( bool excludeParented ) const { ConnectorList connectorList = m_connectorList; if (excludeParented) return connectorList; ConnectorList translatableConnectors; NodeGroupList translatableNodeGroups; p_icnDocument->getTranslatable( items(false), 0l, &translatableConnectors, &translatableNodeGroups ); ConnectorList::iterator tcEnd = translatableConnectors.end(); for ( ConnectorList::iterator it = translatableConnectors.begin(); it != tcEnd; ++it ) { if ( *it && !connectorList.contains(*it) ) connectorList << *it; } NodeGroupList::iterator end = translatableNodeGroups.end(); for ( NodeGroupList::iterator it = translatableNodeGroups.begin(); it != end; ++it ) { const NodeList internal = (*it)->internalNodeList(); NodeList::const_iterator internalEnd = internal.end(); for ( NodeList::const_iterator intIt = internal.begin(); intIt != internalEnd; ++intIt ) { const ConnectorList connected = (*intIt)->inputConnectorList() + (*intIt)->outputConnectorList(); ConnectorList::const_iterator connectedEnd = connected.end(); for ( ConnectorList::const_iterator conIt = connected.begin(); conIt != connectedEnd; ++conIt ) { if ( *conIt && !connectorList.contains(*conIt) ) connectorList << *conIt; } } } return connectorList; } bool CNItemGroup::contains( TQCanvasItem *qcanvasItem ) const { if (!qcanvasItem) return false; const ItemList::const_iterator ciEnd = m_itemList.end(); for ( ItemList::const_iterator it = m_itemList.begin(); it != ciEnd; ++it ) { if ( *it == qcanvasItem ) return true; } const ConnectorList::const_iterator conEnd = m_connectorList.end(); for ( ConnectorList::const_iterator it = m_connectorList.begin(); it != conEnd; ++it ) { if ( *it == qcanvasItem ) return true; } const NodeList::const_iterator nodeEnd = m_nodeList.end(); for ( NodeList::const_iterator it = m_nodeList.begin(); it != nodeEnd; ++it ) { if ( *it == qcanvasItem ) return true; } return false; } void CNItemGroup::setSelected( bool sel ) { const ItemList::iterator ciEnd = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != ciEnd; ++it ) { if (*it && (*it)->isSelected() != sel ) (*it)->setSelected(sel); } const ConnectorList::iterator conEnd = m_connectorList.end(); for ( ConnectorList::iterator it = m_connectorList.begin(); it != conEnd; ++it ) { if ( *it && (*it)->isSelected() != sel ) (*it)->setSelected(sel); } const NodeList::iterator nodeEnd = m_nodeList.end(); for ( NodeList::iterator it = m_nodeList.begin(); it != nodeEnd; ++it ) { if ( *it && (*it)->isSelected() != sel ) (*it)->setSelected(sel); } } bool CNItemGroup::canRotate() const { const ItemList::const_iterator end = m_itemList.end(); for ( ItemList::const_iterator it = m_itemList.begin(); it != end; ++it ) { CNItem *cnItem = dynamic_cast((Item*)*it); if ( cnItem && cnItem->canRotate() ) return true; } return false; } bool CNItemGroup::canFlip() const { const ItemList::const_iterator end = m_itemList.end(); for ( ItemList::const_iterator it = m_itemList.begin(); it != end; ++it ) { CNItem *cnItem = dynamic_cast((Item*)*it); if ( cnItem && cnItem->canFlip() ) return true; } return false; } void CNItemGroup::slotRotateCW() { const ItemList::iterator end = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it ) { Component *component = dynamic_cast((Item*)*it); if ( component && component->isMovable() && component->canRotate() ) { int oldAngle = component->angleDegrees(); component->setAngleDegrees((oldAngle+90)%360); } } p_icnDocument->requestStateSave(); } void CNItemGroup::slotRotateCCW() { const ItemList::iterator end = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it ) { Component *component = dynamic_cast((Item*)*it); if ( component && component->isMovable() && component->canRotate() ) { int oldAngle = component->angleDegrees(); component->setAngleDegrees((oldAngle+270)%360); } } p_icnDocument->requestStateSave(); } void CNItemGroup::slotFlip() { const ItemList::iterator end = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it ) { Component *component = dynamic_cast((Item*)*it); if ( component && component->isMovable() && component->canFlip() ) { bool oldFlipped = component->flipped(); component->setFlipped(!oldFlipped); } } p_icnDocument->requestStateSave(); } void CNItemGroup::setOrientationAngle( int _angle ) { const ItemList::iterator end = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it ) { Component *component = dynamic_cast((Item*)*it); if ( component && component->isMovable() && component->canRotate() ) { int oldAngle = component->angleDegrees(); if ( oldAngle != _angle ) { component->setAngleDegrees(_angle); } } } p_icnDocument->requestStateSave(); } void CNItemGroup::setComponentOrientation( int angleDegrees, bool flipped ) { bool flipping = flipped; bool rotating = (((angleDegrees%360)+360)%360) != 0; const ItemList::iterator end = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it ) { Component *component = dynamic_cast((Item*)*it); if ( component && component->isMovable() && (!flipping || component->canFlip()) && (!rotating || component->canRotate()) ) { int oldAngle = component->angleDegrees(); int oldFlipped = component->flipped(); if ( (oldAngle != angleDegrees) || (oldFlipped != flipped) ) { if ( component->canFlip() ) component->setFlipped(flipped); if ( component->canRotate() ) component->setAngleDegrees(angleDegrees); } } } p_icnDocument->requestStateSave(); } void CNItemGroup::setFlowPartOrientation( unsigned orientation ) { const ItemList::iterator end = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it ) { FlowPart * flowPart = dynamic_cast((Item*)*it); if ( flowPart && flowPart->isMovable() ) flowPart->setOrientation(orientation); } p_icnDocument->requestStateSave(); } void CNItemGroup::mergeGroup( ItemGroup *itemGroup ) { CNItemGroup *group = dynamic_cast(itemGroup); if (!group) return; const ItemList items = group->items(); const ConnectorList connectors = group->connectors(); const NodeList nodes = group->nodes(); const ItemList::const_iterator ciEnd = items.end(); for ( ItemList::const_iterator it = items.begin(); it != ciEnd; ++it ) { addItem(*it); } const ConnectorList::const_iterator conEnd = connectors.end(); for ( ConnectorList::const_iterator it = connectors.begin(); it != conEnd; ++it ) { addConnector(*it); } const NodeList::const_iterator nodeEnd = nodes.end(); for ( NodeList::const_iterator it = nodes.begin(); it != nodeEnd; ++it ) { addNode(*it); } } void CNItemGroup::removeAllItems() { while ( !m_itemList.isEmpty() ) removeItem(*m_itemList.begin()); while ( !m_connectorList.isEmpty() ) removeConnector(*m_connectorList.begin()); while ( !m_nodeList.isEmpty() ) removeNode(*m_nodeList.begin()); } void CNItemGroup::deleteAllItems() { const ItemList::iterator ciEnd = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != ciEnd; ++it ) { if (*it) (*it)->removeItem(); } const NodeList::iterator nodeEnd = m_nodeList.end(); for ( NodeList::iterator it = m_nodeList.begin(); it != nodeEnd; ++it ) { if ( *it && !(*it)->isChildNode() ) { (*it)->removeNode(); } } const ConnectorList::iterator conEnd = m_connectorList.end(); for ( ConnectorList::iterator it = m_connectorList.begin(); it != conEnd; ++it ) { if (*it) { (*it)->removeConnector(); } } // Clear the lists removeAllItems(); } void CNItemGroup::updateInfo() { m_connectorCount = m_connectorList.count(); m_nodeCount = m_nodeList.count(); if ( m_itemList.isEmpty() ) m_currentLevel = -1; } void CNItemGroup::getActiveItem() { if ( m_itemList.isEmpty() ) setActiveItem(0l); else setActiveItem( *m_itemList.begin() ); } void CNItemGroup::setActiveItem( Item *item ) { if ( item == m_activeItem ) return; m_activeItem = item; } TQStringList CNItemGroup::itemIDs() { TQStringList list; ItemList::iterator end = m_itemList.end(); for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it ) { if (*it) { list += (*it)->id(); } } return list; } #include "cnitemgroup.moc"