cnitemgroup.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2003-2004 by David Saxton                               *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "cnitemgroup.h"
00012 #include "component.h"
00013 #include "connector.h"
00014 #include "flowpart.h"
00015 #include "icndocument.h"
00016 #include "node.h"
00017 #include "nodegroup.h"
00018 
00019 CNItemGroup::CNItemGroup( ICNDocument *icnDocument, const char *name)
00020         : ItemGroup( icnDocument, name )
00021 {
00022         p_icnDocument = icnDocument;
00023         m_connectorCount = 0;
00024         m_nodeCount = 0;
00025         m_currentLevel = -1;
00026 }
00027 
00028 CNItemGroup::~CNItemGroup()
00029 {
00030 }
00031 
00032 bool CNItemGroup::addItem( Item *item )
00033 {
00034         // Note, we must prepend the item to the list so that
00035         // activeCNItem() can return the item at the start
00036         // of the list as the most recently added item if some
00037         // the previous activeCNItem is removed
00038         
00039         if ( !item || !item->canvas() || m_itemList.contains(item) || !item->isMovable() )
00040                 return false;
00041         
00042         if ( m_currentLevel != -1 && item->level() > m_currentLevel )
00043                 return false;
00044         
00045         if ( item && m_currentLevel > item->level() )
00046                 removeAllItems();
00047         
00048         registerItem(item);
00049         m_currentLevel = item->level();
00050         setActiveItem(item);
00051         item->setSelected(true);
00052         updateInfo();
00053         emit itemAdded(item);
00054         return true;
00055 }
00056 
00057 bool CNItemGroup::addNode( Node *node )
00058 {
00059         if ( !node || m_nodeList.contains(node) || node->isChildNode() )
00060                 return false;
00061         m_nodeList.prepend(node);
00062         node->setSelected(true);
00063         updateInfo();
00064         emit nodeAdded(node);
00065         return true;
00066 }
00067 
00068 bool CNItemGroup::addConnector( Connector *con )
00069 {
00070         if ( !con || m_connectorList.contains(con) )
00071                 return false;
00072         m_connectorList.prepend(con);
00073         con->setSelected(true);
00074         updateInfo();
00075         emit connectorAdded(con);
00076         return true;
00077 }
00078 
00079 bool CNItemGroup::addQCanvasItem( QCanvasItem *qcanvasItem )
00080 {
00081         if (!qcanvasItem) return false;
00082 
00083         Item *item = dynamic_cast<Item*>(qcanvasItem);
00084 
00085         if (item) return addItem(item);
00086 
00087         Node *node = dynamic_cast<Node*>(qcanvasItem);
00088         if (node) return addNode(node);
00089 
00090         Connector *connector = dynamic_cast<Connector*>(qcanvasItem);
00091         if (!connector) {
00092                 ConnectorLine *connectorLine = dynamic_cast<ConnectorLine*>(qcanvasItem);
00093                 if (connectorLine)
00094                         connector = connectorLine->parent();
00095         }
00096 
00097         if (connector) return addConnector(connector);
00098 
00099         return false;
00100 }
00101 
00102 void CNItemGroup::setItems( QCanvasItemList list )
00103 {
00104         ItemList itemRemoveList = m_itemList;
00105         ConnectorList connectorRemoveList = m_connectorList;
00106         NodeList nodeRemoveList = m_nodeList;
00107         
00108         const QCanvasItemList::const_iterator end = list.end();
00109         for ( QCanvasItemList::const_iterator it = list.begin(); it != end; ++it )
00110         {
00111                 switch ( *it ? (*it)->rtti() : 0 ) {
00112                         case ItemDocument::RTTI::CNItem:
00113                         case ItemDocument::RTTI::DrawPart:
00114                         {
00115                                 itemRemoveList.remove( dynamic_cast<Item*>(*it) );
00116                                 break;
00117                         }
00118                         case ItemDocument::RTTI::Node:
00119                         {
00120                                 nodeRemoveList.remove( dynamic_cast<Node*>(*it) );
00121                                 break;
00122                         }
00123                         case ItemDocument::RTTI::Connector:
00124                         {
00125                                 connectorRemoveList.remove( dynamic_cast<Connector*>(*it) );
00126                                 break;
00127                         }
00128                         case ItemDocument::RTTI::ConnectorLine:
00129                         {
00130                                 connectorRemoveList.remove( (dynamic_cast<ConnectorLine*>(*it))->parent() );
00131                                 break;
00132                         }
00133                         default:
00134                                 break;
00135                 }
00136         }
00137 
00138         {
00139                 const ItemList::const_iterator end = itemRemoveList.end();
00140                 for ( ItemList::const_iterator it = itemRemoveList.begin(); it != end; ++it )
00141                 {
00142                         removeItem(*it);
00143                         (*it)->setSelected(false);
00144                 }
00145         }
00146 
00147         {
00148                 const NodeList::const_iterator end = nodeRemoveList.end();
00149                 for ( NodeList::const_iterator it = nodeRemoveList.begin(); it != end; ++it )
00150                 {
00151                         removeNode(*it);
00152                         (*it)->setSelected(false);
00153                 }
00154         }
00155 
00156         {
00157                 const ConnectorList::const_iterator end = connectorRemoveList.end();
00158                 for ( ConnectorList::const_iterator it = connectorRemoveList.begin(); it != end; ++it )
00159                 {
00160                         removeConnector(*it);
00161                         (*it)->setSelected(false);
00162                 }
00163         }
00164 
00165         {
00166                 const QCanvasItemList::const_iterator end = list.end();
00167                 for ( QCanvasItemList::const_iterator it = list.begin(); it != end; ++it )
00168                 {
00169                         // We don't need to check that we've already got the item as it will
00170                         // be checked in the function call
00171                         addQCanvasItem(*it);
00172                 }
00173         }
00174 }
00175 
00176 void CNItemGroup::removeItem( Item *item )
00177 {
00178         if(!item || !m_itemList.contains(item) ) return;
00179 
00180         unregisterItem(item);
00181         if(m_activeItem == item ) getActiveItem();
00182         
00183         item->setSelected(false);
00184         updateInfo();
00185         emit itemRemoved(item);
00186 }
00187 
00188 void CNItemGroup::removeNode( Node *node )
00189 {
00190         if(!node || !m_nodeList.contains(node)) return;
00191 
00192         m_nodeList.remove(node);
00193         node->setSelected(false);
00194         updateInfo();
00195         emit nodeRemoved(node);
00196 }
00197 
00198 void CNItemGroup::removeConnector( Connector *con )
00199 {
00200         if ( !con || !m_connectorList.contains(con) ) return;
00201         m_connectorList.remove(con);
00202         con->setSelected(false);
00203         updateInfo();
00204         emit connectorRemoved(con);
00205 }
00206 
00207 void CNItemGroup::removeQCanvasItem( QCanvasItem *qcanvasItem )
00208 {
00209         if (!qcanvasItem) return;
00210         
00211         Item *item = dynamic_cast<Item*>(qcanvasItem);
00212         if(item) return removeItem(item);
00213         
00214         Node *node = dynamic_cast<Node*>(qcanvasItem);
00215         if(node) return removeNode(node);
00216         
00217         Connector *connector = dynamic_cast<Connector*>(qcanvasItem);
00218         if (!connector) {
00219                 ConnectorLine *connectorLine = dynamic_cast<ConnectorLine*>(qcanvasItem);
00220                 if (connectorLine)
00221                         connector = connectorLine->parent();
00222         }
00223 
00224         if(connector) return removeConnector(connector);
00225 }
00226 
00227 NodeList CNItemGroup::nodes( bool excludeParented ) const
00228 {
00229         NodeList nodeList = m_nodeList;
00230         if (excludeParented) return nodeList;
00231 
00232         NodeGroupList translatableNodeGroups;
00233         p_icnDocument->getTranslatable( items(false), 0, 0, &translatableNodeGroups );
00234         
00235         NodeGroupList::iterator end = translatableNodeGroups.end();
00236         for ( NodeGroupList::iterator it = translatableNodeGroups.begin(); it != end; ++it )
00237         {
00238                 const NodeList internal = (*it)->internalNodeList();
00239                 NodeList::const_iterator internalEnd = internal.end();
00240                 for ( NodeList::const_iterator intIt = internal.begin(); intIt != internalEnd; ++intIt ) {
00241                         if ( *intIt && !nodeList.contains(*intIt) )
00242                                 nodeList << *intIt;
00243                 }
00244         }
00245 
00246         return nodeList;
00247 }
00248 
00249 ConnectorList CNItemGroup::connectors( bool excludeParented ) const
00250 {
00251         ConnectorList connectorList = m_connectorList;
00252         if(excludeParented) return connectorList;
00253 
00254         ConnectorList translatableConnectors;
00255         NodeGroupList translatableNodeGroups;
00256         p_icnDocument->getTranslatable( items(false), 0, &translatableConnectors, &translatableNodeGroups );
00257 
00258         ConnectorList::iterator tcEnd = translatableConnectors.end();
00259         for ( ConnectorList::iterator it = translatableConnectors.begin(); it != tcEnd; ++it ) {
00260                 if ( *it && !connectorList.contains(*it) )
00261                         connectorList << *it;
00262         }
00263 
00264         NodeGroupList::iterator end = translatableNodeGroups.end();
00265         for ( NodeGroupList::iterator it = translatableNodeGroups.begin(); it != end; ++it ) {
00266                 const NodeList internal = (*it)->internalNodeList();
00267                 NodeList::const_iterator internalEnd = internal.end();
00268                 for ( NodeList::const_iterator intIt = internal.begin(); intIt != internalEnd; ++intIt ) {
00269                         const ConnectorList connected = (*intIt)->inputConnectorList() + (*intIt)->outputConnectorList();
00270                         ConnectorList::const_iterator connectedEnd = connected.end();
00271                         for ( ConnectorList::const_iterator conIt = connected.begin(); conIt != connectedEnd; ++conIt ) {
00272                                 if ( *conIt && !connectorList.contains(*conIt) )
00273                                         connectorList << *conIt;
00274                         }
00275                 }
00276         }
00277 
00278         return connectorList;
00279 }
00280 
00281 bool CNItemGroup::contains( QCanvasItem *qcanvasItem ) const
00282 {
00283         if (!qcanvasItem) return false;
00284 
00285         const ItemList::const_iterator ciEnd = m_itemList.end();
00286         for ( ItemList::const_iterator it = m_itemList.begin(); it != ciEnd; ++it )
00287         {
00288                 if ( *it == qcanvasItem ) return true;
00289         }
00290 
00291         const ConnectorList::const_iterator conEnd = m_connectorList.end();
00292         for ( ConnectorList::const_iterator it = m_connectorList.begin(); it != conEnd; ++it )
00293         {
00294                 if ( *it == qcanvasItem )
00295                         return true;
00296         }
00297 
00298         const NodeList::const_iterator nodeEnd = m_nodeList.end();
00299         for ( NodeList::const_iterator it = m_nodeList.begin(); it != nodeEnd; ++it )
00300         {
00301                 if ( *it == qcanvasItem )
00302                         return true;
00303         }
00304 
00305         return false;
00306 }
00307 
00308 void CNItemGroup::setSelected( bool sel )
00309 {
00310         const ItemList::iterator ciEnd = m_itemList.end();
00311         for ( ItemList::iterator it = m_itemList.begin(); it != ciEnd; ++it )
00312         {
00313                 if (*it && (*it)->isSelected() != sel )
00314                         (*it)->setSelected(sel);
00315         }
00316 
00317         const ConnectorList::iterator conEnd = m_connectorList.end();
00318         for ( ConnectorList::iterator it = m_connectorList.begin(); it != conEnd; ++it )
00319         {
00320                 if ( *it && (*it)->isSelected() != sel )
00321                         (*it)->setSelected(sel);
00322         }
00323 
00324         const NodeList::iterator nodeEnd = m_nodeList.end();
00325         for ( NodeList::iterator it = m_nodeList.begin(); it != nodeEnd; ++it )
00326         {
00327                 if ( *it && (*it)->isSelected() != sel )
00328                         (*it)->setSelected(sel);
00329         }
00330 }
00331 
00332 bool CNItemGroup::canRotate() const
00333 {
00334         const ItemList::const_iterator end = m_itemList.end();
00335         for ( ItemList::const_iterator it = m_itemList.begin(); it != end; ++it )
00336         {
00337                 CNItem *cnItem = dynamic_cast<CNItem*>((Item*)*it);
00338                 if ( cnItem && cnItem->canRotate() )
00339                         return true;
00340         }
00341         return false;
00342 }
00343 
00344 bool CNItemGroup::canFlip() const
00345 {
00346         const ItemList::const_iterator end = m_itemList.end();
00347         for ( ItemList::const_iterator it = m_itemList.begin(); it != end; ++it )
00348         {
00349                 CNItem *cnItem = dynamic_cast<CNItem*>((Item*)*it);
00350                 if ( cnItem && cnItem->canFlip() )
00351                         return true;
00352         }
00353         return false;
00354 }
00355 
00356 void CNItemGroup::slotRotateCW()
00357 {
00358         const ItemList::iterator end = m_itemList.end();
00359         for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it )
00360         {
00361                 Component *component = dynamic_cast<Component*>((Item*)*it);
00362                 if ( component && component->isMovable() && component->canRotate() )
00363                 {
00364                         int oldAngle = component->angleDegrees();
00365                         component->setAngleDegrees((oldAngle+90)%360);
00366                 }
00367         }
00368         p_icnDocument->requestStateSave();
00369 }
00370 
00371 void CNItemGroup::slotRotateCCW()
00372 {
00373         const ItemList::iterator end = m_itemList.end();
00374         for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it )
00375         {
00376                 Component *component = dynamic_cast<Component*>((Item*)*it);
00377                 if ( component && component->isMovable() && component->canRotate() )
00378                 {
00379                         int oldAngle = component->angleDegrees();
00380                         component->setAngleDegrees((oldAngle+270)%360);
00381                 }
00382         }
00383         p_icnDocument->requestStateSave();
00384 }
00385 
00386 void CNItemGroup::slotFlip()
00387 {
00388         const ItemList::iterator end = m_itemList.end();
00389         for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it )
00390         {
00391                 Component *component = dynamic_cast<Component*>((Item*)*it);
00392                 if ( component && component->isMovable() && component->canFlip() )
00393                 {
00394                         bool oldFlipped = component->flipped();
00395                         component->setFlipped(!oldFlipped);
00396                 }
00397         }
00398         p_icnDocument->requestStateSave();
00399 }
00400 
00401 
00402 void CNItemGroup::setOrientationAngle( int _angle )
00403 {
00404         const ItemList::iterator end = m_itemList.end();
00405         for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it )
00406         {
00407                 Component *component = dynamic_cast<Component*>((Item*)*it);
00408                 if ( component && component->isMovable() && component->canRotate() )
00409                 {
00410                         int oldAngle = component->angleDegrees();
00411                         if ( oldAngle != _angle )
00412                         {
00413                                 component->setAngleDegrees(_angle);
00414                         }
00415                 }
00416         }
00417         p_icnDocument->requestStateSave();
00418 }
00419 
00420 
00421 void CNItemGroup::setComponentOrientation( int angleDegrees, bool flipped )
00422 {
00423         bool flipping = flipped;
00424         bool rotating = (((angleDegrees%360)+360)%360) != 0;
00425         
00426         const ItemList::iterator end = m_itemList.end();
00427         for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it )
00428         {
00429                 Component *component = dynamic_cast<Component*>((Item*)*it);
00430                 if ( component && component->isMovable() && (!flipping || component->canFlip()) && (!rotating || component->canRotate()) )
00431                 {
00432                         int oldAngle = component->angleDegrees();
00433                         int oldFlipped = component->flipped();
00434                         if ( (oldAngle != angleDegrees) || (oldFlipped != flipped) )
00435                         {
00436                                 if ( component->canFlip() )
00437                                         component->setFlipped(flipped);
00438                                 if ( component->canRotate() )
00439                                         component->setAngleDegrees(angleDegrees);
00440                         }
00441                 }
00442         }
00443         p_icnDocument->requestStateSave();
00444 }
00445 
00446 
00447 void CNItemGroup::setFlowPartOrientation( unsigned orientation )
00448 {
00449         const ItemList::iterator end = m_itemList.end();
00450         for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it )
00451         {
00452                 FlowPart * flowPart = dynamic_cast<FlowPart*>((Item*)*it);
00453                 if ( flowPart && flowPart->isMovable() )
00454                         flowPart->setOrientation(orientation);
00455         }
00456         p_icnDocument->requestStateSave();
00457 }
00458 
00459 void CNItemGroup::mergeGroup( ItemGroup *itemGroup )
00460 {
00461         CNItemGroup *group = dynamic_cast<CNItemGroup*>(itemGroup);
00462         if (!group) return;
00463         
00464         const ItemList items = group->items();
00465         const ConnectorList connectors = group->connectors();
00466         const NodeList nodes = group->nodes();
00467         
00468         const ItemList::const_iterator ciEnd = items.end();
00469         for ( ItemList::const_iterator it = items.begin(); it != ciEnd; ++it )
00470         {
00471                 addItem(*it);
00472         }
00473         const ConnectorList::const_iterator conEnd = connectors.end();
00474         for ( ConnectorList::const_iterator it = connectors.begin(); it != conEnd; ++it )
00475         {
00476                 addConnector(*it);
00477         }
00478         const NodeList::const_iterator nodeEnd = nodes.end();
00479         for ( NodeList::const_iterator it = nodes.begin(); it != nodeEnd; ++it )
00480         {
00481                 addNode(*it);
00482         }
00483 }
00484 
00485 void CNItemGroup::removeAllItems()
00486 {
00487         while ( !m_itemList.isEmpty() )
00488                 removeItem(*m_itemList.begin());
00489 
00490         while ( !m_connectorList.isEmpty() )
00491                 removeConnector(*m_connectorList.begin());
00492 
00493         while ( !m_nodeList.isEmpty() )
00494                 removeNode(*m_nodeList.begin());
00495 }
00496 
00497 void CNItemGroup::deleteAllItems()
00498 {
00499         const ItemList::iterator ciEnd = m_itemList.end();
00500         for ( ItemList::iterator it = m_itemList.begin(); it != ciEnd; ++it )
00501         {
00502                 if(*it) (*it)->removeItem();
00503         }
00504         const NodeList::iterator nodeEnd = m_nodeList.end();
00505         for ( NodeList::iterator it = m_nodeList.begin(); it != nodeEnd; ++it )
00506         {
00507                 if(*it && !(*it)->isChildNode() ) (*it)->removeNode();
00508 
00509         }
00510         const ConnectorList::iterator conEnd = m_connectorList.end();
00511         for ( ConnectorList::iterator it = m_connectorList.begin(); it != conEnd; ++it )
00512         {
00513                 if(*it) (*it)->removeConnector();
00514         }
00515         
00516         // Clear the lists
00517         removeAllItems();
00518 }
00519 
00520 void CNItemGroup::updateInfo()
00521 {
00522         m_connectorCount = m_connectorList.count();
00523         m_nodeCount = m_nodeList.count();
00524         
00525         if(m_itemList.isEmpty() ) m_currentLevel = -1;
00526 }
00527 
00528 void CNItemGroup::getActiveItem()
00529 {
00530         if(m_itemList.isEmpty() ) setActiveItem(0);
00531         else setActiveItem( *m_itemList.begin() );
00532 }
00533 
00534 void CNItemGroup::setActiveItem( Item *item )
00535 {
00536         if ( item == m_activeItem ) return;
00537         m_activeItem = item;
00538 }
00539 
00540 QStringList CNItemGroup::itemIDs()
00541 {
00542         QStringList list;
00543         ItemList::iterator end = m_itemList.end();
00544         for ( ItemList::iterator it = m_itemList.begin(); it != end; ++it )
00545         {
00546                 if (*it) {
00547                         list += (*it)->id();
00548                 }
00549         }
00550         return list;
00551 }
00552 
00553 #include "cnitemgroup.moc"
00554 

Generated on Tue May 8 17:05:28 2007 for KTechLab by  doxygen 1.5.1