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

akonadi

  • sources
  • kde-4.12
  • kdepimlibs
  • akonadi
entitytreeviewstatesaver.cpp
1 /*
2  Copyright (c) 2009 Volker Krause <vkrause@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "entitytreeviewstatesaver.h"
21 
22 #include <akonadi/collection.h>
23 #include <akonadi/entitytreemodel.h>
24 #include <akonadi/item.h>
25 
26 #include <KConfigGroup>
27 #include <KDebug>
28 
29 #include <QScrollBar>
30 #include <QTimer>
31 #include <QTreeView>
32 
33 namespace Akonadi {
34 
35 struct State
36 {
37  State() : selected( false ), expanded( false ), currentIndex( false ) {}
38  bool selected;
39  bool expanded;
40  bool currentIndex;
41 };
42 
43 class EntityTreeViewStateSaverPrivate
44 {
45  public:
46  explicit EntityTreeViewStateSaverPrivate( EntityTreeViewStateSaver *parent ) :
47  q( parent ),
48  view( 0 ),
49  horizontalScrollBarValue( -1 ),
50  verticalScrollBarValue( -1 )
51  {
52  }
53 
54  inline bool hasChanges() const
55  {
56  return !pendingCollectionChanges.isEmpty() || !pendingItemChanges.isEmpty();
57  }
58 
59  static inline QString key( const QModelIndex &index )
60  {
61  if ( !index.isValid() )
62  return QLatin1String( "x-1" );
63  const Collection c = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
64  if ( c.isValid() )
65  return QString::fromLatin1( "c%1" ).arg( c.id() );
66  return QString::fromLatin1( "i%1" ).arg( index.data( EntityTreeModel::ItemIdRole ).value<Entity::Id>() );
67  }
68 
69  void saveState( const QModelIndex &index, QStringList &selection, QStringList &expansion )
70  {
71  const QString cfgKey = key( index );
72  if ( view->selectionModel()->isSelected( index ) )
73  selection.append( cfgKey );
74  if ( view->isExpanded( index ) )
75  expansion.append( cfgKey );
76  for ( int i = 0; i < view->model()->rowCount( index ); ++i ) {
77  const QModelIndex child = view->model()->index( i, 0, index );
78  saveState( child, selection, expansion );
79  }
80  }
81 
82  inline void restoreState( const QModelIndex &index, const State &state )
83  {
84  if ( state.selected )
85  view->selectionModel()->select( index, QItemSelectionModel::Select | QItemSelectionModel::Rows );
86  if ( state.expanded )
87  view->setExpanded( index, true );
88  if ( state.currentIndex )
89  view->setCurrentIndex( index );
90  QTimer::singleShot( 0, q, SLOT(restoreScrollBarState()) );
91  }
92 
93  void restoreState( const QModelIndex &index )
94  {
95  const Collection c = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
96  if ( c.isValid() ) {
97  if ( pendingCollectionChanges.contains( c.id() ) ) {
98  restoreState( index, pendingCollectionChanges.value( c.id() ) );
99  pendingCollectionChanges.remove( c.id() );
100  }
101  } else {
102  Entity::Id itemId = index.data( EntityTreeModel::ItemIdRole ).value<Entity::Id>();
103  if ( pendingItemChanges.contains( itemId ) ) {
104  restoreState( index, pendingItemChanges.value( itemId ) );
105  pendingItemChanges.remove( itemId );
106  }
107  }
108  for ( int i = 0; i < view->model()->rowCount( index ) && hasChanges(); ++i ) {
109  const QModelIndex child = view->model()->index( i, 0, index );
110  restoreState( child );
111  }
112  }
113 
114  inline void restoreScrollBarState()
115  {
116  if ( horizontalScrollBarValue >= 0 && horizontalScrollBarValue <= view->horizontalScrollBar()->maximum() ) {
117  view->horizontalScrollBar()->setValue( horizontalScrollBarValue );
118  horizontalScrollBarValue = -1;
119  }
120  if ( verticalScrollBarValue >= 0 && verticalScrollBarValue <= view->verticalScrollBar()->maximum() ) {
121  view->verticalScrollBar()->setValue( verticalScrollBarValue );
122  verticalScrollBarValue = -1;
123  }
124  }
125 
126  void rowsInserted( const QModelIndex &index, int start, int end )
127  {
128  if ( !hasChanges() ) {
129  QObject::disconnect( view->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
130  q, SLOT(rowsInserted(QModelIndex,int,int)) );
131  return;
132  }
133 
134  for ( int i = start; i <= end && hasChanges(); ++i ) {
135  const QModelIndex child = view->model()->index( i, 0, index);;
136  restoreState( child );
137  }
138  }
139 
140  EntityTreeViewStateSaver *q;
141  QTreeView *view;
142  QHash<Entity::Id, State> pendingCollectionChanges, pendingItemChanges;
143  int horizontalScrollBarValue, verticalScrollBarValue;
144 };
145 
146 EntityTreeViewStateSaver::EntityTreeViewStateSaver( QTreeView * view ) :
147  QObject( view ),
148  d( new EntityTreeViewStateSaverPrivate( this ) )
149 {
150  d->view = view;
151 }
152 
153 EntityTreeViewStateSaver::~EntityTreeViewStateSaver()
154 {
155  delete d;
156 }
157 
158 void EntityTreeViewStateSaver::saveState( KConfigGroup &configGroup ) const
159 {
160  if ( !d->view->model() )
161  return;
162 
163  configGroup.deleteGroup();
164  QStringList selection, expansion;
165  const int rowCount = d->view->model()->rowCount();
166  for ( int i = 0; i < rowCount; ++i ) {
167  const QModelIndex index = d->view->model()->index( i, 0 );
168  d->saveState( index, selection, expansion );
169  }
170 
171  const QString currentIndex = d->key( d->view->selectionModel()->currentIndex() );
172 
173  configGroup.writeEntry( "Selection", selection );
174  configGroup.writeEntry( "Expansion", expansion );
175  configGroup.writeEntry( "CurrentIndex", currentIndex );
176  configGroup.writeEntry( "ScrollBarHorizontal", d->view->horizontalScrollBar()->value() );
177  configGroup.writeEntry( "ScrollBarVertical", d->view->verticalScrollBar()->value() );
178 }
179 
180 void EntityTreeViewStateSaver::restoreState (const KConfigGroup & configGroup) const
181 {
182  if ( !d->view->model() )
183  return;
184 
185  const QStringList selection = configGroup.readEntry( "Selection", QStringList() );
186  foreach ( const QString &key, selection ) {
187  Entity::Id id = key.mid( 1 ).toLongLong();
188  if ( id < 0 )
189  continue;
190  if ( key.startsWith( QLatin1Char( 'c' ) ) )
191  d->pendingCollectionChanges[id].selected = true;
192  else if ( key.startsWith( QLatin1Char( 'i' ) ) )
193  d->pendingItemChanges[id].selected = true;
194  }
195 
196  const QStringList expansion = configGroup.readEntry( "Expansion", QStringList() );
197  foreach ( const QString &key, expansion ) {
198  Entity::Id id = key.mid( 1 ).toLongLong();
199  if ( id < 0 )
200  continue;
201  if ( key.startsWith( QLatin1Char( 'c' ) ) )
202  d->pendingCollectionChanges[id].expanded = true;
203  else if ( key.startsWith( QLatin1Char( 'i' ) ) )
204  d->pendingItemChanges[id].expanded = true;
205  }
206 
207  const QString key = configGroup.readEntry( "CurrentIndex", QString() );
208  const Entity::Id id = key.mid( 1 ).toLongLong();
209  if ( id >= 0 ) {
210  if ( key.startsWith( QLatin1Char( 'c' ) ) )
211  d->pendingCollectionChanges[id].currentIndex = true;
212  else if ( key.startsWith( QLatin1Char( 'i' ) ) )
213  d->pendingItemChanges[id].currentIndex = true;
214  }
215 
216  d->horizontalScrollBarValue = configGroup.readEntry( "ScrollBarHorizontal", -1 );
217  d->verticalScrollBarValue = configGroup.readEntry( "ScrollBarVertical", -1 );
218 
219  // initial restore run, for everything already loaded
220  for ( int i = 0; i < d->view->model()->rowCount() && d->hasChanges(); ++i ) {
221  const QModelIndex index = d->view->model()->index( i, 0 );
222  d->restoreState( index );
223  }
224  d->restoreScrollBarState();
225 
226  // watch the model for stuff coming in delayed
227  if ( d->hasChanges() )
228  connect( d->view->model(), SIGNAL(rowsInserted(QModelIndex,int,int)),
229  SLOT(rowsInserted(QModelIndex,int,int)) );
230 }
231 
232 } // namespace Akonadi
233 
234 #include "moc_entitytreeviewstatesaver.cpp"
Akonadi::EntityTreeViewStateSaver::~EntityTreeViewStateSaver
~EntityTreeViewStateSaver()
Destroys this state saver.
Definition: entitytreeviewstatesaver.cpp:153
Akonadi::Entity::Id
qint64 Id
Describes the unique id type.
Definition: entity.h:65
Akonadi::EntityTreeViewStateSaver::EntityTreeViewStateSaver
EntityTreeViewStateSaver(QTreeView *view)
Creates a new state saver, for saving or restoring.
Definition: entitytreeviewstatesaver.cpp:146
Akonadi::EntityTreeModel::CollectionRole
The collection.
Definition: entitytreemodel.h:335
Akonadi::EntityTreeViewStateSaver::restoreState
void restoreState(const KConfigGroup &configGroup) const
Restore the state stored in configGroup as soon as the corresponding entities become available in the...
Definition: entitytreeviewstatesaver.cpp:180
Akonadi::EntityTreeViewStateSaver::saveState
void saveState(KConfigGroup &configGroup) const
Stores the current state in the given config group.
Definition: entitytreeviewstatesaver.cpp:158
Akonadi::EntityTreeModel::ItemIdRole
The item id.
Definition: entitytreemodel.h:330
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:27 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



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