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

List:       kde-commits
Subject:    branches/kdepim/kmail-soc/kmail/messagelistview/core
From:       Szymon Stefanek <pragma () kvirc ! net>
Date:       2008-07-25 23:53:29
Message-ID: 1217030009.692519.9799.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 837906 by stefanek:

Complete the item expansion code

 M  +1 -42     item.cpp  
 M  +0 -1      item.h  
 M  +83 -83    model.cpp  
 M  +9 -2      model.h  


--- branches/kdepim/kmail-soc/kmail/messagelistview/core/item.cpp #837905:837906
@@ -150,11 +150,6 @@
   if ( mIsViewable == bViewable )
     return;
 
-//  if ( !mIsViewable )
-//    qDebug("SETTING %x AS NON VIEWABLE", this);
-//  else
-//    qDebug("SETTING %x AS VIEWABLE", this );
-
   if ( !mChildItems )
   {
     mIsViewable = bViewable;
@@ -189,16 +184,6 @@
       // It seems that we can avoid removing child items here since the parent has \
                been removed: this is a hack tough
       // and should check if Qt4 still supports it in the next (hopefully largely \
fixed) release  
-      //switch ( mInitialExpandStatus )
-      //{
-      //  case ExpandExecuted:
-      //    qDebug("BEGIN REMOVE ROWS FOR EXPANDED PARENT %x: from %d to %d, (will) \
                remain with %d children",this,0,mChildItems->count()-1,0);
-      //  break;
-      //  default:
-      //    qDebug("BEGIN REMOVE ROWS FOR PARENT %x: from %d to %d, (will) remain \
                with %d children",this,0,mChildItems->count()-1,0);
-      //  break;
-      //}
-
       // fake having no children, for a second
       model->beginRemoveRows( model->index( this, 0 ), 0, mChildItems->count() - 1 \
);  QList< Item * > * tmp = mChildItems;
@@ -237,11 +222,7 @@
     mChildItems = new QList< Item * >();
   int idx = mChildItems->count();
   if ( mIsViewable )
-  {
-    //qDebug("BEGIN INSERT ROWS FOR PARENT %x: from %d to %d, will remain with %d \
                children",this,idx,idx, mChildItems->count()+1);
     model->beginInsertRows( model->index( this, 0 ), idx, idx ); // THIS IS \
                EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME \
                OF WRITING
-  }
-  //qDebug("APPENDING CHILD ITEM %x TO PARENT %x",child,this);
   mChildItems->append( child );
   child->setIndexGuess( idx );
   if ( mIsViewable )
@@ -289,25 +270,7 @@
     child->setParent( 0 );
     return;
   }
-/*
-  switch ( mInitialExpandStatus )
-  {
-    case ExpandExecuted:
-      switch ( child->mInitialExpandStatus )
-      {
-        case ExpandExecuted:
-          qDebug("TAKING VIEWABLE EXPANDED CHILD ITEM %x FROM EXPANDED PARENT \
                %x",child,this);
-        break;
-        default:
-          qDebug("TAKING VIEWABLE CHILD ITEM %x FROM EXPANDED PARENT \
                %x",child,this);
-        break;
-      }
-    break;
-    default:
-      qDebug("TAKING VIEWABLE CHILD ITEM %x FROM PARENT %x",child,this);
-    break;
-  }
-*/
+
   // Can't optimise: must call the model functions
   int idx = child->indexGuess();
   if ( mChildItems->count() > idx )
@@ -318,17 +281,13 @@
     idx = mChildItems->indexOf( child ); // bad guess :/
 
   if ( idx < 0 )
-  {
-    //qDebug("INVALID CHILD TO BE TAKEN: NOT FOUND IN CHILDREN LIST!");
     return; // Aaargh... not our child ?
-  }
 
   child->setViewable( model, false );
   model->beginRemoveRows( model->index( this, 0 ), idx, idx );
   child->setParent( 0 );
   mChildItems->removeAt( idx );
   model->endRemoveRows();
-  //qDebug("CHILD TAKEN");
 
 #if 0
   // This *could* be done, but we optimize and avoid it.
--- branches/kdepim/kmail-soc/kmail/messagelistview/core/item.h #837905:837906
@@ -89,7 +89,6 @@
   QString mFormattedMaxDate;
   QString mFormattedMinDate;
   KPIM::MessageStatus mStatus;
-
 protected:
   Item( Type type )
     : mType( type ), mChildItems( 0 ), mParent( 0 ), mThisItemIndexGuess( 0 ),
--- branches/kdepim/kmail-soc/kmail/messagelistview/core/model.cpp #837905:837906
@@ -217,17 +217,6 @@
       mFillStepTimer, SIGNAL( timeout() ),
       this, SLOT( viewItemJobStep() )
     );
-/*
-  QObject::connect(
-      mView, SIGNAL( expanded( const QModelIndex & ) ),
-      this, SLOT( itemExpanded( const QModelIndex & ) )
-    );
-
-  QObject::connect(
-      mView, SIGNAL( collapsed( const QModelIndex & ) ),
-      this, SLOT( itemCollapsed( const QModelIndex & ) )
-    );
-*/
 }
 
 Model::~Model()
@@ -602,8 +591,14 @@
 {
   if ( ghi->parent() )
   {
+    if (
+         ( ( ghi )->childItemCount() > 0 ) && // has children
+         ( ghi )->isViewable() && // is actually attached to the viewable root
+         mView->isExpanded( index( ghi, 0 ) ) // is actually expanded
+       )
+      saveExpandedStateOfSubtree( ghi );
+
     ghi->parent()->takeChildItem( this, ghi );
-    // FIXME: Should store expanded state of items!
   }
 
   ghi->setParent( mRootItem );
@@ -658,6 +653,30 @@
       syncExpandedStateOfSubtree( ghi );
 }
 
+void Model::saveExpandedStateOfSubtree( Item *root )
+{
+  Q_ASSERT( root );
+
+  qDebug("SAVING EXPANDED STATE OF CHILD %s", root->subject().toUtf8().data() );
+
+  root->setInitialExpandStatus( Item::ExpandNeeded );
+
+  QList< Item * > * children = root->childItems();
+  if ( !children )
+    return;
+
+  for( QList< Item * >::Iterator it = children->begin(); it != children->end(); ++it \
) +  {
+    if (
+         ( ( *it )->childItemCount() > 0 ) && // has children
+         ( *it )->isViewable() && // is actually attached to the viewable root
+         mView->isExpanded( index( *it, 0 ) ) // is actually expanded
+       )
+      saveExpandedStateOfSubtree( *it );
+  }
+}
+
+
 void Model::syncExpandedStateOfSubtree( Item *root )
 {
   // WE ASSUME that:
@@ -668,6 +687,7 @@
   QModelIndex idx = index( root, 0 );
 
   //if ( !mView->isExpanded( idx ) ) // this is O(logN!) in Qt.... very ugly... but \
it should never happen here +  qDebug("EXPANDING ITEM \
%s",root->subject().toUtf8().data());  mView->expand( idx ); // sync the real state \
in the view  root->setInitialExpandStatus( Item::ExpandExecuted );
 
@@ -1189,11 +1209,15 @@
     // The item already had a parent and this means that we're moving it.
     oldParentWasTheSame = oldParent == pParent; // just re-sorting ?
 
+    if (
+         ( ( mi )->childItemCount() > 0 ) && // has children
+         ( mi )->isViewable() && // is actually attached to the viewable root
+         mView->isExpanded( index( mi, 0 ) ) // is actually expanded
+       )
+      saveExpandedStateOfSubtree( mi );
+
     // If the parent is viewable (so mi was viewable too) then the beginRemoveRows()
     // and endRemoveRows() functions of this model will be called too.
-
-    // FIXME: Save the expanded state of messages here!
-
     oldParent->takeChildItem( this, mi );
 
     if ( ( !oldParentWasTheSame ) && ( oldParent != mRootItem ) )
@@ -1297,17 +1321,44 @@
     break;
   }
 
-  if ( mi->isViewable() )
+  // Decide if we need to expand parents
+  bool childNeedsExpanding = mi->isViewable() && ( mi->initialExpandStatus() == \
Item::ExpandNeeded ); +
+  if ( pParent->initialExpandStatus() == Item::NoExpandNeeded )
   {
-    // The message item is now viewable. Might need expanding.
-    if ( mi->initialExpandStatus() != Item::NoExpandNeeded ) // this is actually a \
non viewable state +    switch( mAggregation->threadExpandPolicy() )
     {
-      // Either expand needed or expand executed
-      if ( mi->initialExpandStatus() == Item::ExpandNeeded )
-        if ( mi->childItemCount() > 0 )
-          syncExpandedStateOfSubtree( mi ); // sync the real state in the view
+      case Aggregation::NeverExpandThreads:
+        // just do nothing unless this child has children and is already marked for \
expansion +        if ( childNeedsExpanding )
+          pParent->setInitialExpandStatus( Item::ExpandNeeded );
+      break;
+      case Aggregation::ExpandThreadsWithNewMessages:
+        // expand only if new (or it has children marked for expansion)
+        if ( childNeedsExpanding || mi->status().isNew() )
+          pParent->setInitialExpandStatus( Item::ExpandNeeded );
+      break;
+      case Aggregation::ExpandThreadsWithUnreadMessages:
+        // expand only if unread (or it has children marked for expansion)
+        if ( childNeedsExpanding || mi->status().isUnread() )
+          pParent->setInitialExpandStatus( Item::ExpandNeeded );
+      break;
+      case Aggregation::AlwaysExpandThreads:
+        // expand everything
+        pParent->setInitialExpandStatus( Item::ExpandNeeded );
+      break;
+      default:
+        // BUG
+      break;
+    }
+  } // else it's already marked for expansion or expansion has been already executed
 
-      // But we also need to make all the parents expanded
+  // expand parent first, if possible
+  if ( pParent->isViewable() )
+  {
+    if ( pParent->initialExpandStatus() == Item::ExpandNeeded )
+    {
+      // Now expand parents as needed
       Item * parentToExpand = pParent;
       while ( parentToExpand )
       {
@@ -1317,15 +1368,22 @@
         if ( parentToExpand->initialExpandStatus() == Item::ExpandExecuted )
           break;
 
+        qDebug("EXPANDING ITEM %s",parentToExpand->subject().toUtf8().data());
         mView->expand( index( parentToExpand, 0 ) );
 
         parentToExpand->setInitialExpandStatus( Item::ExpandExecuted );
-
         parentToExpand = parentToExpand->parent();
       }
     }
-  } // else it will be synched when the parent will become viewable.
 
+    // mi is viewable too, now
+    if ( childNeedsExpanding )
+      if ( mi->childItemCount() > 0 )
+        syncExpandedStateOfSubtree( mi ); // sync the real state in the view
+  }
+
+
+
   // Now we need to propagate the property changes the upper levels.
 
   // If we have just inserted a message inside the root then no work needs to be \
done: @@ -1710,30 +1768,6 @@
     mstat.fromQInt32( statusBits );
     mi->setStatus( mstat );
 
-    switch( mAggregation->threadExpandPolicy() )
-    {
-      case Aggregation::NeverExpandThreads:
-        // just do nothing
-      break;
-      case Aggregation::ExpandThreadsWithNewMessages:
-        // expand only if new (parents will be expanded when this item becomes \
                viewable)
-        if ( mi->status().isNew() )
-          mi->setInitialExpandStatus( Item::ExpandNeeded );
-      break;
-      case Aggregation::ExpandThreadsWithUnreadMessages:
-        // expand only if unread (parents will be expanded when this item becomes \
                viewable)
-        if ( mi->status().isUnread() )
-          mi->setInitialExpandStatus( Item::ExpandNeeded );
-      break;
-      case Aggregation::AlwaysExpandThreads:
-        // expand everything
-        mi->setInitialExpandStatus( Item::ExpandNeeded );
-      break;
-      default:
-        // BUG
-      break;
-    }
-
     // Attempt to do threading as soon as possible (to display items to the user)
     if ( mAggregation->threading() != Aggregation::NoThreading )
     {
@@ -2274,31 +2308,6 @@
     return; // nothing more to do
 
 
-  // The view fill operation time/cpu usage is dominated by the item insertion \
                function.
-  // In particular there is a endInsertRows() call which seems to trigger complex \
                view updates
-  // via the rowsInserted() signal. (Thnx to Thomas for finding it out! :) )
-  // 
-  // At the time of writing the Qt4 code seem to "feel fine" when the rowsInserted()
-  // signal is disconnected in endInsertRows() and a layoutChanged() signal is \
                emitted
-  // at the end of the operations (step).
-  //
-  // The bad news is that layoutChanged() also becomes very slow when there are many
-  // explicitly expanded items in the view. This is because layoutChanged() needs to \
                re-expand
-  // and re-scan them. So we apply the hack when the explicitly expanded item count
-  // is below 100 (empiric constant).
-  //
-  // Be aware that this is a *hack*. This code can live also without it, it will be \
                just
-  // slower in some cases.
-#if 0
-  bool useDisconnectViewSlotsHack = false; //&& ( mExpandedItemCount < 100 );
-
-  //qDebug(" USE DISCONNECT VIEW: %d (EXPANDED: %d)",useDisconnectViewSlotsHack, \
                mExpandedItemCount );
-
-  if ( useDisconnectViewSlotsHack )
-    QObject::disconnect(this, SIGNAL(rowsInserted(QModelIndex,int,int)),
-                        mView, SLOT(rowsInserted(QModelIndex,int,int)));
-
-#endif
   switch( viewItemJobStepInternal() )
   {
     case ViewItemJobInterrupted:
@@ -2314,15 +2323,6 @@
       assert( false );
     break;
   }
-#if 0
-  if ( useDisconnectViewSlotsHack )
-  {
-    QObject::connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)),
-                     mView, SLOT(rowsInserted(QModelIndex,int,int)));
-
-  }
-  emit layoutChanged(); // this will update the view
-#endif
 }
 
 void Model::slotStorageModelRowsInserted( const QModelIndex &parent, int from, int \
                to )
--- branches/kdepim/kmail-soc/kmail/messagelistview/core/model.h #837905:837906
@@ -153,12 +153,19 @@
   void clearOrphanChildrenHash();
   /**
    * Sync the expanded state of the subtree with the specified root.
-   * This will cause the items that are marked with "isInternallyExpanded()" to be
+   * This will cause the items that are marked with Item::ExpandNeeded to be
    * expanded also in the view. For optimisation purposes the specified root
-   * is assumed to be marked as isInternallyExpanded() so be sure to check it
+   * is assumed to be marked as Item::ExpandNeeded so be sure to check it
    * before calling this function.
    */
   void syncExpandedStateOfSubtree( Item *root );
+  /**
+   * Save the expanded state of the subtree with the specified root.
+   * The state will be saved in the initialExpandStatus() variable.
+   * For optimisation purposes the specified root is assumed to be expanded
+   * and viewable.
+   */
+  void saveExpandedStateOfSubtree( Item *root );
 
   enum PropertyChanges
   {


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

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