[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