[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdepim/kleopatra/models
From:       Frank Osterfeld <frank.osterfeld () kdemail ! net>
Date:       2008-04-14 8:53:19
Message-ID: 1208163199.053622.25841.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 796743 by osterfeld:

change update order from:
add new key; remove its children from mTopLevels and mKeysByNonExistingParent; add \
children to new parent to
remove children from all indexes; add new key; re-add its children.

This avoids an inconsistent state when a key was just added but its children are \
still in mTopLevels (which leads to index( x, y, QModelIndex() ).parent() == \
justAddedKey )

 M  +93 -62    keylistmodel.cpp  


--- trunk/KDE/kdepim/kleopatra/models/keylistmodel.cpp #796742:796743
@@ -646,6 +646,8 @@
         return QList<QModelIndex>();
 
 
+    const std::vector<Key> oldKeys = mKeysByFingerprint;
+
     std::vector<Key> merged;
     merged.reserve( keys.size() + mKeysByFingerprint.size() );
     std::set_union( keys.begin(), keys.end(),
@@ -655,58 +657,78 @@
     mKeysByFingerprint = merged;
 
     Q_FOREACH( const Key & key, topological_sort( keys ) ) {
-	
-	const char * const issuer_fpr = cleanChainID( key );
 
-	if ( !issuer_fpr || !*issuer_fpr )
-	    // root or something...
-	    addTopLevelKey( key );
-	else if ( std::binary_search( mKeysByFingerprint.begin(), mKeysByFingerprint.end(), \
                issuer_fpr, ByFingerprint<std::less>() ) )
-	    // parent exists...
-	    addKeyWithParent( issuer_fpr, key );
-	else
-	    // parent does't exist yet...
-	    addKeyWithoutParent( issuer_fpr, key );
-
         // check to see whether this key is a parent for a previously parent-less \
group:  const char * const fpr = key.primaryFingerprint();
         if ( !fpr || !*fpr )
             continue;
+        
+        const bool keyAlreadyExisted = qBinaryFind( oldKeys.begin(), oldKeys.end(), \
key, ByFingerprint<std::less>() ) != oldKeys.end();  
         const Map::iterator it = mKeysByNonExistingParent.find( fpr );
-        if ( it == mKeysByNonExistingParent.end() )
-            continue;
-        assert( !it->second.empty() );
+        const std::vector<Key> children = it != mKeysByNonExistingParent.end() ? \
it->second : std::vector<Key>(); +        if ( it != mKeysByNonExistingParent.end() )
+            mKeysByNonExistingParent.erase( it );
 
-        const std::vector<Key> children = it->second;
+        // Step 1: For new keys, remove children from toplevel:
 
-        // Step 1: Remove children from toplevel:
-        std::vector<Key>::iterator last = mTopLevels.begin();
-        Q_FOREACH( const Key & k, children ) {
-            last = qBinaryFind( last, mTopLevels.end(), k, \
                ByFingerprint<std::less>() );
-            assert( last != mTopLevels.end() );
-            const int row = std::distance( mTopLevels.begin(), last );
-
-            emit rowAboutToBeMoved( QModelIndex(), row );
-            beginRemoveRows( QModelIndex(), row, row );
-            last = mTopLevels.erase( last );
-            endRemoveRows();
+        if ( !keyAlreadyExisted ) {
+            std::vector<Key>::iterator last = mTopLevels.begin();
+            std::vector<Key>::iterator lastFP = mKeysByFingerprint.begin();
+    
+            Q_FOREACH( const Key & k, children ) {
+                last = qBinaryFind( last, mTopLevels.end(), k, \
ByFingerprint<std::less>() ); +                assert( last != mTopLevels.end() );
+                const int row = std::distance( mTopLevels.begin(), last );
+    
+                lastFP = qBinaryFind( lastFP, mKeysByFingerprint.end(), k, \
ByFingerprint<std::less>() ); +                assert( lastFP != \
mKeysByFingerprint.end() ); +                const int fpRow = std::distance( \
mKeysByFingerprint.begin(), lastFP ); +    
+                emit rowAboutToBeMoved( QModelIndex(), row );
+                beginRemoveRows( QModelIndex(), row, row );
+                last = mTopLevels.erase( last );
+                lastFP = mKeysByFingerprint.erase( lastFP );
+                endRemoveRows();
+            }
         }
+        // Step 2: add/update key
 
-        mKeysByNonExistingParent.erase( it );
+        const char * const issuer_fpr = cleanChainID( key );
+        if ( !issuer_fpr || !*issuer_fpr )
+            // root or something...
+            addTopLevelKey( key );
+        else if ( std::binary_search( mKeysByFingerprint.begin(), \
mKeysByFingerprint.end(), issuer_fpr, ByFingerprint<std::less>() ) ) +            // \
parent exists... +            addKeyWithParent( issuer_fpr, key );
+        else
+            // parent does't exist yet...
+            addKeyWithoutParent( issuer_fpr, key );
 
-        // Step 2: Add children to new parent ( == key )
-        const QModelIndex new_parent = index( key );
-        beginInsertRows( index( key ), 0, children.size()-1 );
-        assert( mKeysByExistingParent.find( fpr ) == mKeysByExistingParent.end() );
-        mKeysByExistingParent[fpr] = children;
-        endInsertRows();
+        // Step 3: Add children to new parent ( == key )
 
-        // emit the rowMoved() signals in reversed direction, so the
-        // implementation can use a stack for mapping.
-        for ( int i = children.size() - 1 ; i >= 0 ; --i )
-            emit rowMoved( new_parent, i );
-
+        if ( !keyAlreadyExisted && !children.empty() ) {
+            const QModelIndex new_parent = index( key );
+            beginInsertRows( index( key ), 0, children.size()-1 );
+            assert( mKeysByExistingParent.find( fpr ) == mKeysByExistingParent.end() \
); +            mKeysByExistingParent[fpr] = children;
+            
+            //merge children into mKeysByFingerprint:
+            
+            std::vector<Key> mergedChildren;
+            mergedChildren.reserve( children.size() + mKeysByFingerprint.size() );
+            std::set_union( children.begin(), children.end(),
+                            mKeysByFingerprint.begin(), mKeysByFingerprint.end(),
+                            std::back_inserter( mergedChildren ), \
ByFingerprint<std::less>() ); +                
+            mKeysByFingerprint = mergedChildren;
+            endInsertRows();
+    
+            // emit the rowMoved() signals in reversed direction, so the
+            // implementation can use a stack for mapping.
+            for ( int i = children.size() - 1 ; i >= 0 ; --i )
+                emit rowMoved( new_parent, i );
+        }
     }
 
     return indexes( keys );
@@ -716,37 +738,46 @@
     const QModelIndex idx = index( key );
     if ( !idx.isValid() )
         return;
+    
+    const char * const fpr = key.primaryFingerprint();
     //TODO: only removal of leaf nodes is implemented so far
-    if ( hasChildren( idx ) )
+    if ( mKeysByExistingParent.find( fpr ) != mKeysByExistingParent.end() )
         return;
 
-    const std::vector<Key>::iterator it
-        = qBinaryFind( mKeysByFingerprint.begin(), mKeysByFingerprint.end(),
-                       key, ByFingerprint<std::less>() );
-    if ( it == mKeysByFingerprint.end() )
-        return;
+    const std::vector<Key>::iterator it = qBinaryFind( mKeysByFingerprint.begin(), \
mKeysByFingerprint.end(), +        key, ByFingerprint<std::less>() );
+    
+    assert( it != mKeysByFingerprint.end() );
+    assert( mKeysByNonExistingParent.find( fpr ) == mKeysByNonExistingParent.end() \
); +    assert( mKeysByExistingParent.find( fpr ) == mKeysByExistingParent.end() );
 
-    const QModelIndex parentIdx = parent( idx );
-    const Key parentKey = this->key( parentIdx );
+    beginRemoveRows( parent( idx ), idx.row(), idx.row() );
+    mKeysByFingerprint.erase( it );
 
-    assert( idx.isValid() );
-    assert( !parentIdx.isValid() || !parentKey.isNull() );
+    const char * const issuer_fpr = static_cast<const char*>( idx.internalPointer() \
);  
-    beginRemoveRows( parentIdx, idx.row(), idx.row() );
-    mKeysByFingerprint.erase( it );
-
-    if ( !parentIdx.isValid() ) {
+    if ( !issuer_fpr || !*issuer_fpr ) {
         const std::vector<Key>::iterator tlIt = qBinaryFind( mTopLevels.begin(), \
                mTopLevels.end(), key, ByFingerprint<std::less>() );
-        if ( tlIt != mTopLevels.end() )
-            mTopLevels.erase( tlIt );
-        const char* const pfpr = cleanChainID( key );
-        const Map::iterator siblingsIt = mKeysByNonExistingParent.find( pfpr );
-        if ( siblingsIt != mKeysByNonExistingParent.end() )
-            siblingsIt->second.erase( std::remove_if( siblingsIt->second.begin(), \
siblingsIt->second.end(), bind( ByFingerprint<std::equal_to>(), key, _1 ) ), \
siblingsIt->second.end() ); +        assert( tlIt != mTopLevels.end() );
+        mTopLevels.erase( tlIt );
     } else {
-        const Map::iterator siblingsIt = mKeysByExistingParent.find( \
                parentKey.primaryFingerprint() );
-        if ( siblingsIt != mKeysByExistingParent.end() )
-            siblingsIt->second.erase( std::remove_if( siblingsIt->second.begin(), \
siblingsIt->second.end(), bind( ByFingerprint<std::equal_to>(), key, _1 ) ), \
siblingsIt->second.end() ); +        const Map::iterator nexIt = \
mKeysByNonExistingParent.find( issuer_fpr ); +        if ( nexIt != \
mKeysByNonExistingParent.end() ) { +            const std::vector<Key>::iterator eit \
= qBinaryFind( nexIt->second.begin(), nexIt->second.end(), key, \
ByFingerprint<std::less>() ); +            if ( eit != nexIt->second.end() )
+                nexIt->second.erase( eit );
+            if ( nexIt->second.empty() )
+                mKeysByNonExistingParent.erase( nexIt );
+        }
+    
+        const Map::iterator exIt = mKeysByExistingParent.find( issuer_fpr );
+        if ( exIt != mKeysByExistingParent.end() ) {
+            const std::vector<Key>::iterator eit = qBinaryFind( \
exIt->second.begin(), exIt->second.end(), key, ByFingerprint<std::less>() ); +        \
if ( eit != exIt->second.end() ) +                exIt->second.erase( eit );
+            if ( exIt->second.empty() )
+                mKeysByExistingParent.erase( exIt );
+        }
     }
     endRemoveRows();
 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic