00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
00122 td.updateItem( r1, r2 );
00123
00124
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
00137 td.deleteItemWithChildren( item.myTrg );
00138 }
00139 else {
00140 if ( item.myTrg == td.nullTrg() ) {
00141
00142 TrgItem nitem = createSubTree( item.mySrc, r2, lastItem, td );
00143 if ( nitem != td.nullTrg() )
00144 lastItem = nitem;
00145 }
00146 else {
00147
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
00159 new_r2 = createSubTree( r1, td.parent( r2 ), r2, td );
00160 }
00161 if ( r2 != td.nullTrg() ) {
00162
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
00206
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
00221
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;
00226 d.append( ndiff );
00227 }
00228 cur = f;
00229 DiffItem<SrcItem,TrgItem> ndiff;
00230 ndiff.mySrc = *src_it;
00231 ndiff.myTrg = *cur;
00232 d.append( ndiff );
00233 cur++;
00234 }
00235 else {
00236
00237 DiffItem<SrcItem,TrgItem> ndiff;
00238 ndiff.mySrc = *src_it;
00239 ndiff.myTrg = td.nullTrg();
00240 d.append( ndiff );
00241 }
00242 }
00243
00244 for ( ; cur != trg_last; cur++ ) {
00245 DiffItem<SrcItem,TrgItem> ndiff;
00246 ndiff.mySrc = td.nullSrc();
00247 ndiff.myTrg = *cur;
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