Back to index

salome-gui  6.5.0
SUIT_TreeSync.h
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File   : SUIT_TreeSync.h
00024 // Author : Alexander SOLOVYOV
00025 //
00026 #ifndef SUIT_TREESYNC_H
00027 #define SUIT_TREESYNC_H
00028 
00029 #include <QList>
00030 
00041 template <class SrcItem, class TrgItem>
00042 struct DiffItem
00043 {
00044   SrcItem  mySrc;      
00045   TrgItem  myTrg;      
00046 };
00047 
00048 
00049 //
00050 // Function prototypes.
00051 //
00052 
00053 template <class SrcItem, class TrgItem, class TreeData>
00054 TrgItem synchronize( const SrcItem&, const TrgItem&, const TreeData& );
00055 
00056 template <class SrcItem, class TrgItem, class TreeData>
00057 QList< DiffItem<SrcItem,TrgItem> > diffSiblings( const SrcItem&, 
00058                                                  const TrgItem&, 
00059                                                  const TreeData& );
00060 
00061 template <class SrcItem, class TrgItem, class TreeData>
00062 TrgItem createSubTree( const SrcItem&, const TrgItem&, const TrgItem&, const TreeData& );
00063 
00064 template <class SrcItem, class TrgItem, class TreeData>
00065 const typename QList<TrgItem>::const_iterator findEqual( const SrcItem& it,
00066                                                          const typename QList<TrgItem>::const_iterator& first,
00067                                                          const typename QList<TrgItem>::const_iterator& last,
00068                                                          const TreeData& td );
00069 
00070 
00071 //
00072 // Function imlpementation.
00073 //
00074 
00117 template <class SrcItem, class TrgItem, class TreeData>
00118 TrgItem synchronize( const SrcItem& r1, const TrgItem& r2, const TreeData& td )
00119 {
00120   if ( td.isEqual( r1, r2 ) ) {
00121     // update items themselves
00122     td.updateItem( r1, r2 );
00123     
00124     // iterate through children
00125     QList< DiffItem< SrcItem, TrgItem > > d =  diffSiblings( r1, r2, td );
00126     
00127     typename QList< DiffItem< SrcItem, TrgItem > >::const_iterator anIt = d.begin(), aLast = d.end();
00128     TrgItem lastItem = td.nullTrg();
00129 
00130     for ( ; anIt != aLast; anIt++ ) {
00131       const DiffItem<SrcItem,TrgItem>& item = *anIt;
00132       if ( item.mySrc == td.nullSrc() ) {
00133         if ( item.myTrg == td.nullTrg() )
00134           qDebug( "error: both null" );
00135         else
00136           // delete item
00137           td.deleteItemWithChildren( item.myTrg );
00138       }
00139       else {
00140         if ( item.myTrg == td.nullTrg() ) {
00141           // add item (recursively)
00142           TrgItem nitem = createSubTree( item.mySrc, r2, lastItem, td );
00143           if ( nitem != td.nullTrg() )
00144             lastItem = nitem;
00145         }
00146         else {
00147           // update item
00148           synchronize( item.mySrc, item.myTrg, td );
00149           lastItem = item.myTrg;
00150         }
00151       }
00152     }
00153     return r2;
00154   }
00155   else {
00156     TrgItem new_r2 = td.nullTrg();
00157     if ( r1 != td.nullSrc() ) {
00158       // add new item (recursively)
00159       new_r2 = createSubTree( r1, td.parent( r2 ), r2, td );
00160     }
00161     if ( r2 != td.nullTrg() ) {
00162       // delete old one (if it is not null)
00163       td.deleteItemWithChildren( r2 );
00164     }
00165     return new_r2;
00166   }
00167 }
00168 
00179 template <class SrcItem, class TrgItem, class TreeData>
00180 const typename QList<TrgItem>::const_iterator findEqual( const SrcItem& it,
00181                                                          const typename QList<TrgItem>::const_iterator& first,
00182                                                          const typename QList<TrgItem>::const_iterator& last,
00183                                                          const TreeData& td )
00184 {
00185   typename QList<TrgItem>::const_iterator cur = first;
00186   for ( ; cur != last; cur++ ) {
00187     if ( td.isEqual( it, *cur ) )
00188       return cur;
00189   }
00190   return last;
00191 }
00192 
00201 template <class SrcItem, class TrgItem, class TreeData>
00202 QList< DiffItem<SrcItem,TrgItem> > diffSiblings( const SrcItem& src, const TrgItem& trg,
00203                                                  const TreeData& td )
00204 {
00205   //if( src==td.nullSrc() || trg==td.nullTrg() )
00206   //  return;
00207   
00208   QList< DiffItem<SrcItem,TrgItem> > d;
00209    
00210   QList<SrcItem> src_ch = td.children( src );
00211   QList<TrgItem> trg_ch = td.children( trg );
00212 
00213   typename QList<SrcItem>::const_iterator src_it = src_ch.begin(), src_last = src_ch.end();
00214   typename QList<TrgItem>::const_iterator cur    = trg_ch.begin(), trg_last = trg_ch.end();
00215 
00216   for ( ; src_it != src_last; src_it++ ) {
00217     typename QList<TrgItem>::const_iterator f =
00218       findEqual<SrcItem, TrgItem, TreeData>( *src_it, cur, trg_last, td );
00219     if ( f != trg_last )  { 
00220       // target is found
00221       // mark all items before found one as "to be deleted"
00222       for ( typename QList<TrgItem>::const_iterator it = cur; it != f; it++ ) {
00223         DiffItem<SrcItem,TrgItem> ndiff;
00224         ndiff.mySrc = td.nullSrc();
00225         ndiff.myTrg = *it;        // delete item
00226         d.append( ndiff );
00227       }
00228       cur = f;
00229       DiffItem<SrcItem,TrgItem> ndiff;
00230       ndiff.mySrc = *src_it;
00231       ndiff.myTrg = *cur;         // update this (found) item
00232       d.append( ndiff );
00233       cur++;
00234     }
00235     else {
00236       // target is not found
00237       DiffItem<SrcItem,TrgItem> ndiff;
00238       ndiff.mySrc = *src_it;
00239       ndiff.myTrg = td.nullTrg(); // add item
00240       d.append( ndiff );
00241     }
00242   }
00243   // delete rest items
00244   for ( ; cur != trg_last; cur++ ) {
00245     DiffItem<SrcItem,TrgItem> ndiff;
00246     ndiff.mySrc = td.nullSrc();
00247     ndiff.myTrg = *cur;           // delete item
00248     d.append( ndiff );
00249   }
00250   
00251   return d;
00252 }
00253 
00263 template <class SrcItem, class TrgItem, class TreeData>
00264 TrgItem createSubTree( const SrcItem& src, const TrgItem& parent,
00265                        const TrgItem& after, const TreeData& td )
00266 {
00267   if ( src == td.nullSrc() )
00268     return td.nullTrg();
00269 
00270   TrgItem nitem = td.createItem( src, parent, after );
00271   if ( nitem == td.nullTrg() )
00272     return nitem;
00273 
00274   QList<SrcItem> ch = td.children( src );
00275   typename QList<SrcItem>::const_iterator anIt = ch.begin(), aLast = ch.end();
00276   TrgItem last = td.nullTrg();
00277   for( ; anIt != aLast; anIt++ )
00278     last = createSubTree( *anIt, nitem, last, td );
00279 
00280   return nitem;
00281 }
00282 
00283 #endif // SUIT_TREESYNC_H