• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

akonadi

entitytreeviewstatesaver.cpp
00001 /*
00002     Copyright (c) 2009 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "entitytreeviewstatesaver.h"
00021 
00022 #include <akonadi/collection.h>
00023 #include <akonadi/entitytreemodel.h>
00024 #include <akonadi/item.h>
00025 
00026 #include <KConfigGroup>
00027 #include <KDebug>
00028 
00029 #include <QScrollBar>
00030 #include <QTimer>
00031 #include <QTreeView>
00032 
00033 namespace Akonadi {
00034 
00035 struct State
00036 {
00037   State() : selected( false ), expanded( false ), currentIndex( false ) {}
00038   bool selected;
00039   bool expanded;
00040   bool currentIndex;
00041 };
00042 
00043 class EntityTreeViewStateSaverPrivate
00044 {
00045   public:
00046     explicit EntityTreeViewStateSaverPrivate( EntityTreeViewStateSaver *parent ) :
00047       q( parent ),
00048       view( 0 ),
00049       horizontalScrollBarValue( -1 ),
00050       verticalScrollBarValue( -1 )
00051     {
00052     }
00053 
00054     inline bool hasChanges() const
00055     {
00056       return !pendingCollectionChanges.isEmpty() || !pendingItemChanges.isEmpty();
00057     }
00058 
00059     static inline QString key( const QModelIndex &index )
00060     {
00061       if ( !index.isValid() )
00062         return QLatin1String( "x-1" );
00063       const Collection c = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
00064       if ( c.isValid() )
00065         return QString::fromLatin1( "c%1" ).arg( c.id() );
00066       return QString::fromLatin1( "i%1" ).arg( index.data( EntityTreeModel::ItemIdRole ).value<Entity::Id>() );
00067     }
00068 
00069     void saveState( const QModelIndex &index, QStringList &selection, QStringList &expansion )
00070     {
00071       const QString cfgKey = key( index );
00072       if ( view->selectionModel()->isSelected( index ) )
00073         selection.append( cfgKey );
00074       if ( view->isExpanded( index ) )
00075         expansion.append( cfgKey );
00076       for ( int i = 0; i < view->model()->rowCount( index ); ++i ) {
00077         const QModelIndex child = view->model()->index( i, 0, index );
00078         saveState( child, selection, expansion );
00079       }
00080     }
00081 
00082     inline void restoreState( const QModelIndex &index, const State &state )
00083     {
00084       if ( state.selected )
00085         view->selectionModel()->select( index, QItemSelectionModel::Select | QItemSelectionModel::Rows );
00086       if ( state.expanded )
00087         view->setExpanded( index, true );
00088       if ( state.currentIndex )
00089         view->setCurrentIndex( index );
00090       QTimer::singleShot( 0, q, SLOT(restoreScrollBarState()) );
00091     }
00092 
00093     void restoreState( const QModelIndex &index )
00094     {
00095       const Collection c = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
00096       if ( c.isValid() ) {
00097         if ( pendingCollectionChanges.contains( c.id() ) ) {
00098           restoreState( index, pendingCollectionChanges.value( c.id() ) );
00099           pendingCollectionChanges.remove( c.id() );
00100         }
00101       } else {
00102         Entity::Id itemId = index.data( EntityTreeModel::ItemIdRole ).value<Entity::Id>();
00103         if ( pendingItemChanges.contains( itemId ) ) {
00104           restoreState( index, pendingItemChanges.value( itemId ) );
00105           pendingItemChanges.remove( itemId );
00106         }
00107       }
00108       for ( int i = 0; i < view->model()->rowCount( index ) && hasChanges(); ++i ) {
00109         const QModelIndex child = view->model()->index( i, 0, index );
00110         restoreState( child );
00111       }
00112     }
00113 
00114     inline void restoreScrollBarState()
00115     {
00116       if ( horizontalScrollBarValue >= 0 && horizontalScrollBarValue <= view->horizontalScrollBar()->maximum() ) {
00117         view->horizontalScrollBar()->setValue( horizontalScrollBarValue );
00118         horizontalScrollBarValue = -1;
00119       }
00120       if ( verticalScrollBarValue >= 0 && verticalScrollBarValue <= view->verticalScrollBar()->maximum() ) {
00121         view->verticalScrollBar()->setValue( verticalScrollBarValue );
00122         verticalScrollBarValue = -1;
00123       }
00124     }
00125 
00126     void rowsInserted( const QModelIndex &index, int start, int end )
00127     {
00128       if ( !hasChanges() ) {
00129         QObject::disconnect( view->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
00130                              q, SLOT(rowsInserted(QModelIndex,int,int)) );
00131         return;
00132       }
00133 
00134       for ( int i = start; i <= end && hasChanges(); ++i ) {
00135         const QModelIndex child = view->model()->index( i, 0, index);;
00136         restoreState( child );
00137       }
00138     }
00139 
00140     EntityTreeViewStateSaver *q;
00141     QTreeView *view;
00142     QHash<Entity::Id, State> pendingCollectionChanges, pendingItemChanges;
00143     int horizontalScrollBarValue, verticalScrollBarValue;
00144 };
00145 
00146 EntityTreeViewStateSaver::EntityTreeViewStateSaver( QTreeView * view ) :
00147   QObject( view ),
00148   d( new EntityTreeViewStateSaverPrivate( this ) )
00149 {
00150   d->view = view;
00151 }
00152 
00153 EntityTreeViewStateSaver::~EntityTreeViewStateSaver()
00154 {
00155   delete d;
00156 }
00157 
00158 void EntityTreeViewStateSaver::saveState( KConfigGroup &configGroup ) const
00159 {
00160   if ( !d->view->model() )
00161     return;
00162 
00163   configGroup.deleteGroup();
00164   QStringList selection, expansion;
00165   const int rowCount = d->view->model()->rowCount();
00166   for ( int i = 0; i < rowCount; ++i ) {
00167     const QModelIndex index = d->view->model()->index( i, 0 );
00168     d->saveState( index, selection, expansion );
00169   }
00170 
00171   const QString currentIndex = d->key( d->view->selectionModel()->currentIndex() );
00172 
00173   configGroup.writeEntry( "Selection", selection );
00174   configGroup.writeEntry( "Expansion", expansion );
00175   configGroup.writeEntry( "CurrentIndex", currentIndex );
00176   configGroup.writeEntry( "ScrollBarHorizontal", d->view->horizontalScrollBar()->value() );
00177   configGroup.writeEntry( "ScrollBarVertical", d->view->verticalScrollBar()->value() );
00178 }
00179 
00180 void EntityTreeViewStateSaver::restoreState (const KConfigGroup & configGroup) const
00181 {
00182   if ( !d->view->model() )
00183     return;
00184 
00185   const QStringList selection = configGroup.readEntry( "Selection", QStringList() );
00186   foreach ( const QString &key, selection ) {
00187     Entity::Id id = key.mid( 1 ).toLongLong();
00188     if ( id < 0 )
00189       continue;
00190     if ( key.startsWith( QLatin1Char( 'c' ) ) )
00191       d->pendingCollectionChanges[id].selected = true;
00192     else if ( key.startsWith( QLatin1Char( 'i' ) ) )
00193       d->pendingItemChanges[id].selected = true;
00194   }
00195 
00196   const QStringList expansion = configGroup.readEntry( "Expansion", QStringList() );
00197   foreach ( const QString &key, expansion ) {
00198     Entity::Id id = key.mid( 1 ).toLongLong();
00199     if ( id < 0 )
00200       continue;
00201     if ( key.startsWith( QLatin1Char( 'c' ) ) )
00202       d->pendingCollectionChanges[id].expanded = true;
00203     else if ( key.startsWith( QLatin1Char( 'i' ) ) )
00204       d->pendingItemChanges[id].expanded = true;
00205   }
00206 
00207   const QString key = configGroup.readEntry( "CurrentIndex", QString() );
00208   const Entity::Id id = key.mid( 1 ).toLongLong();
00209   if ( id >= 0 ) {
00210     if ( key.startsWith( QLatin1Char( 'c' ) ) )
00211       d->pendingCollectionChanges[id].currentIndex = true;
00212     else if ( key.startsWith( QLatin1Char( 'i' ) ) )
00213       d->pendingItemChanges[id].currentIndex = true;
00214   }
00215 
00216   d->horizontalScrollBarValue = configGroup.readEntry( "ScrollBarHorizontal", -1 );
00217   d->verticalScrollBarValue = configGroup.readEntry( "ScrollBarVertical", -1 );
00218 
00219   // initial restore run, for everything already loaded
00220   for ( int i = 0; i < d->view->model()->rowCount() && d->hasChanges(); ++i ) {
00221     const QModelIndex index = d->view->model()->index( i, 0 );
00222     d->restoreState( index );
00223   }
00224   d->restoreScrollBarState();
00225 
00226   // watch the model for stuff coming in delayed
00227   if ( d->hasChanges() )
00228     connect( d->view->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
00229              SLOT(rowsInserted(QModelIndex,int,int)) );
00230 }
00231 
00232 } // namespace Akonadi
00233 
00234 #include "entitytreeviewstatesaver.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:09:22 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs-4.8.5 API Reference

Skip menu "kdepimlibs-4.8.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal