diff options
Diffstat (limited to 'src/cnitemgroup.cpp')
-rw-r--r-- | src/cnitemgroup.cpp | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/src/cnitemgroup.cpp b/src/cnitemgroup.cpp new file mode 100644 index 0000000..21a9878 --- /dev/null +++ b/src/cnitemgroup.cpp @@ -0,0 +1,598 @@ +/*************************************************************************** + * 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::addQCanvasItem( QCanvasItem *qcanvasItem ) +{ + if (!qcanvasItem) return false; + + Item *item = dynamic_cast<Item*>(qcanvasItem); + if (item) + return addItem(item); + + Node *node = dynamic_cast<Node*>(qcanvasItem); + if (node) + return addNode(node); + + Connector *connector = dynamic_cast<Connector*>(qcanvasItem); + if (!connector) + { + ConnectorLine *connectorLine = dynamic_cast<ConnectorLine*>(qcanvasItem); + if (connectorLine) + connector = connectorLine->parent(); + } + if (connector) + return addConnector(connector); + + return false; +} + +void CNItemGroup::setItems( QCanvasItemList list ) +{ + ItemList itemRemoveList = m_itemList; + ConnectorList connectorRemoveList = m_connectorList; + NodeList nodeRemoveList = m_nodeList; + + const QCanvasItemList::const_iterator end = list.end(); + for ( QCanvasItemList::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<Item*>(*it) ); + break; + } + case ItemDocument::RTTI::Node: + { + nodeRemoveList.remove( dynamic_cast<Node*>(*it) ); + break; + } + case ItemDocument::RTTI::Connector: + { + connectorRemoveList.remove( dynamic_cast<Connector*>(*it) ); + break; + } + case ItemDocument::RTTI::ConnectorLine: + { + connectorRemoveList.remove( (dynamic_cast<ConnectorLine*>(*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 QCanvasItemList::const_iterator end = list.end(); + for ( QCanvasItemList::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 + addQCanvasItem(*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::removeQCanvasItem( QCanvasItem *qcanvasItem ) +{ + if (!qcanvasItem) return; + + Item *item = dynamic_cast<Item*>(qcanvasItem); + if (item) + return removeItem(item); + + Node *node = dynamic_cast<Node*>(qcanvasItem); + if (node) + return removeNode(node); + + Connector *connector = dynamic_cast<Connector*>(qcanvasItem); + if (!connector) + { + ConnectorLine *connectorLine = dynamic_cast<ConnectorLine*>(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( QCanvasItem *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<CNItem*>((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<CNItem*>((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<Component*>((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<Component*>((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<Component*>((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<Component*>((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<Component*>((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<FlowPart*>((Item*)*it); + if ( flowPart && flowPart->isMovable() ) + flowPart->setOrientation(orientation); + } + p_icnDocument->requestStateSave(); +} + + +void CNItemGroup::mergeGroup( ItemGroup *itemGroup ) +{ + CNItemGroup *group = dynamic_cast<CNItemGroup*>(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; +} + + +QStringList CNItemGroup::itemIDs() +{ + QStringList 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" |