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

KDEUI

  • sources
  • kde-4.12
  • kdelibs
  • kdeui
  • itemviews
kviewstatesaver.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 Klarälvdalens Datakonsult AB,
3  a KDAB Group company, info@kdab.net,
4  author Stephen Kelly <stephen@kdab.com>
5 
6  This library is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Library General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or (at your
9  option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14  License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301, USA.
20 */
21 
22 #include "kviewstatesaver.h"
23 
24 #include <QtGui/QAbstractScrollArea>
25 #include <QScrollBar>
26 #include <QTimer>
27 #include <QTreeView>
28 
29 #include "kdebug.h"
30 
31 #include "kconfiggroup.h"
32 
33 static const char * selectionKey = "Selection";
34 static const char * expansionKey = "Expansion";
35 static const char * currentKey = "Current";
36 static const char * scrollStateHorizontalKey = "HorizontalScroll";
37 static const char * scrollStateVerticalKey = "VerticalScroll";
38 
39 class KViewStateSaverPrivate
40 {
41 public:
42  KViewStateSaverPrivate(KViewStateSaver *qq)
43  : q_ptr(qq),
44  m_treeView(0),
45  m_view(0),
46  m_selectionModel(0),
47  m_scrollArea(0),
48  m_horizontalScrollBarValue(-1),
49  m_verticalScrollBarValue(-1)
50  {
51 
52  }
53 
54  Q_DECLARE_PUBLIC(KViewStateSaver)
55  KViewStateSaver * const q_ptr;
56 
57  QStringList getExpandedItems(const QModelIndex &index) const;
58 
59  void listenToPendingChanges();
60  void processPendingChanges();
61 
62  inline void restoreScrollBarState()
63  {
64  if ( m_horizontalScrollBarValue >= 0 && m_horizontalScrollBarValue <= m_scrollArea->horizontalScrollBar()->maximum() ) {
65  m_scrollArea->horizontalScrollBar()->setValue( m_horizontalScrollBarValue );
66  m_horizontalScrollBarValue = -1;
67  }
68  if ( m_verticalScrollBarValue >= 0 && m_verticalScrollBarValue <= m_scrollArea->verticalScrollBar()->maximum() ) {
69  m_scrollArea->verticalScrollBar()->setValue( m_verticalScrollBarValue );
70  m_verticalScrollBarValue = -1;
71  }
72  }
73 
74  void restoreSelection();
75  void restoreCurrentItem();
76  void restoreExpanded();
77 
78  inline bool hasPendingChanges() const
79  {
80  return !m_pendingCurrent.isEmpty() || !m_pendingExpansions.isEmpty() || !m_pendingSelections.isEmpty();
81  }
82 
83  const QAbstractItemModel* getModel()
84  {
85  if ( m_selectionModel && m_selectionModel->model() )
86  return m_selectionModel->model();
87  else if ( m_view && m_view->model() )
88  return m_view->model();
89  return 0;
90  }
91 
92  void rowsInserted( const QModelIndex &/*index*/, int /*start*/, int /*end*/ )
93  {
94  Q_Q(KViewStateSaver);
95  processPendingChanges();
96 
97  if ( !hasPendingChanges() )
98  {
99  q->disconnect( getModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
100  q, SLOT(rowsInserted(QModelIndex,int,int)) );
101  q->deleteLater();
102  }
103  }
104 
105  QTreeView *m_treeView;
106  QAbstractItemView *m_view;
107  QItemSelectionModel *m_selectionModel;
108  QAbstractScrollArea *m_scrollArea;
109 
110  int m_horizontalScrollBarValue;
111  int m_verticalScrollBarValue;
112  QSet<QString> m_pendingSelections;
113  QSet<QString> m_pendingExpansions;
114  QString m_pendingCurrent;
115 };
116 
117 KViewStateSaver::KViewStateSaver(QObject* parent)
118  : QObject(0), d_ptr( new KViewStateSaverPrivate(this) )
119 {
120  Q_UNUSED(parent);
121  qRegisterMetaType<QModelIndex>( "QModelIndex" );
122 }
123 
124 KViewStateSaver::~KViewStateSaver()
125 {
126  delete d_ptr;
127 }
128 
129 void KViewStateSaver::setView(QAbstractItemView* view)
130 {
131  Q_D(KViewStateSaver);
132  d->m_scrollArea = view;
133  if (view) {
134  d->m_selectionModel = view->selectionModel();
135  d->m_treeView = qobject_cast<QTreeView*>(view);
136  } else {
137  d->m_selectionModel = 0;
138  d->m_treeView = 0;
139  }
140  d->m_view = view;
141 }
142 
143 QAbstractItemView* KViewStateSaver::view() const
144 {
145  Q_D(const KViewStateSaver);
146  return d->m_view;
147 }
148 
149 QItemSelectionModel* KViewStateSaver::selectionModel() const
150 {
151  Q_D(const KViewStateSaver);
152  return d->m_selectionModel;
153 }
154 
155 void KViewStateSaver::setSelectionModel(QItemSelectionModel* selectionModel)
156 {
157  Q_D(KViewStateSaver);
158  d->m_selectionModel = selectionModel;
159 }
160 
161 void KViewStateSaverPrivate::listenToPendingChanges()
162 {
163  Q_Q(KViewStateSaver);
164  // watch the model for stuff coming in delayed
165  if ( hasPendingChanges() )
166  {
167  const QAbstractItemModel *model = getModel();
168  if ( model )
169  {
170  q->disconnect( model, SIGNAL(rowsInserted(QModelIndex,int,int)),
171  q, SLOT(rowsInserted(QModelIndex,int,int)) );
172  q->connect( model, SIGNAL(rowsInserted(QModelIndex,int,int)),
173  SLOT(rowsInserted(QModelIndex,int,int)) );
174  return;
175  } else {
176  q->deleteLater();
177  }
178  } else {
179  q->deleteLater();
180  }
181 }
182 
183 void KViewStateSaverPrivate::processPendingChanges()
184 {
185  Q_Q(KViewStateSaver);
186 
187  q->restoreCurrentItem(m_pendingCurrent);
188  q->restoreSelection(m_pendingSelections.toList());
189  q->restoreExpanded(m_pendingExpansions.toList());
190  q->restoreScrollState(m_verticalScrollBarValue, m_horizontalScrollBarValue);
191 }
192 
193 void KViewStateSaver::restoreState(const KConfigGroup& configGroup)
194 {
195  Q_D(KViewStateSaver);
196 
197  // Delete myself if not finished after 60 seconds.
198  QTimer::singleShot(60000, this, SLOT(deleteLater()));
199 
200 
201  d->m_pendingCurrent = configGroup.readEntry( currentKey, QString() );
202  d->m_pendingSelections = configGroup.readEntry( selectionKey, QStringList() ).toSet();
203  d->m_pendingExpansions = configGroup.readEntry( expansionKey, QStringList() ).toSet();
204  d->m_horizontalScrollBarValue = configGroup.readEntry( scrollStateHorizontalKey, -1 );
205  d->m_verticalScrollBarValue = configGroup.readEntry( scrollStateVerticalKey, -1 );
206 
207  d->processPendingChanges();
208  if (d->hasPendingChanges())
209  d->listenToPendingChanges();
210 }
211 
212 QStringList KViewStateSaverPrivate::getExpandedItems(const QModelIndex &index) const
213 {
214  Q_Q(const KViewStateSaver);
215 
216  QStringList expansion;
217  for ( int i = 0; i < m_treeView->model()->rowCount( index ); ++i ) {
218  const QModelIndex child = m_treeView->model()->index( i, 0, index );
219 
220  // http://bugreports.qt.nokia.com/browse/QTBUG-18039
221  if ( m_treeView->model()->hasChildren( child ) ) {
222  if ( m_treeView->isExpanded( child ) )
223  expansion << q->indexToConfigString( child );
224  expansion << getExpandedItems( child );
225  }
226  }
227  return expansion;
228 }
229 
230 void KViewStateSaver::saveState(KConfigGroup& configGroup)
231 {
232  Q_D(KViewStateSaver);
233 
234  if ( d->m_selectionModel )
235  {
236  configGroup.writeEntry( selectionKey, selectionKeys() );
237  configGroup.writeEntry( currentKey, currentIndexKey() );
238  }
239 
240  if ( d->m_treeView )
241  {
242  QStringList expansion = expansionKeys();
243 
244  configGroup.writeEntry( expansionKey, expansion );
245  }
246 
247  if ( d->m_scrollArea )
248  {
249  QPair<int, int> _scrollState = scrollState();
250  configGroup.writeEntry( scrollStateVerticalKey, _scrollState.first );
251  configGroup.writeEntry( scrollStateHorizontalKey, _scrollState.second );
252  }
253 }
254 
255 void KViewStateSaverPrivate::restoreCurrentItem()
256 {
257  Q_Q(KViewStateSaver);
258 
259  QModelIndex currentIndex = q->indexFromConfigString(m_selectionModel->model(), m_pendingCurrent);
260  if ( currentIndex.isValid() )
261  {
262  if (m_treeView)
263  m_treeView->setCurrentIndex(currentIndex);
264  else
265  m_selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::NoUpdate);
266  m_pendingCurrent.clear();
267  }
268 }
269 
270 void KViewStateSaver::restoreCurrentItem(const QString& indexString)
271 {
272  Q_D(KViewStateSaver);
273  if (!d->m_selectionModel || !d->m_selectionModel->model())
274  return;
275 
276  if (indexString.isEmpty())
277  {
278  return;
279  }
280  d->m_pendingCurrent = indexString;
281  d->restoreCurrentItem();
282 
283  if (d->hasPendingChanges())
284  d->listenToPendingChanges();
285 }
286 
287 void KViewStateSaverPrivate::restoreExpanded()
288 {
289  Q_Q(KViewStateSaver);
290 
291  QSet<QString>::iterator it = m_pendingExpansions.begin();
292  for ( ; it != m_pendingExpansions.end(); )
293  {
294  QModelIndex idx = q->indexFromConfigString( m_treeView->model(), *it);
295  if ( idx.isValid() )
296  {
297  m_treeView->expand( idx );
298  it = m_pendingExpansions.erase( it );
299  } else {
300  ++it;
301  }
302  }
303 }
304 
305 void KViewStateSaver::restoreExpanded(const QStringList& indexStrings)
306 {
307  Q_D(KViewStateSaver);
308  if (!d->m_treeView || !d->m_treeView->model())
309  return;
310 
311  if (indexStrings.isEmpty())
312  return;
313 
314  d->m_pendingExpansions.unite(indexStrings.toSet());
315  d->restoreExpanded();
316  if (d->hasPendingChanges())
317  d->listenToPendingChanges();
318 }
319 
320 void KViewStateSaver::restoreScrollState(int verticalScoll, int horizontalScroll)
321 {
322  Q_D(KViewStateSaver);
323 
324  if ( !d->m_scrollArea )
325  return;
326 
327  d->m_verticalScrollBarValue = verticalScoll;
328  d->m_horizontalScrollBarValue = horizontalScroll;
329 
330  QTimer::singleShot( 0, this, SLOT(restoreScrollBarState()) );
331 }
332 
333 void KViewStateSaverPrivate::restoreSelection()
334 {
335  Q_Q(KViewStateSaver);
336 
337  QSet<QString>::iterator it = m_pendingSelections.begin();
338  for ( ; it != m_pendingSelections.end(); )
339  {
340  QModelIndex idx = q->indexFromConfigString( m_selectionModel->model(), *it);
341  if ( idx.isValid() )
342  {
343  m_selectionModel->select( idx, QItemSelectionModel::Select );
344  it = m_pendingSelections.erase( it );
345  } else {
346  ++it;
347  }
348  }
349 }
350 
351 void KViewStateSaver::restoreSelection(const QStringList& indexStrings)
352 {
353  Q_D(KViewStateSaver);
354 
355  if (!d->m_selectionModel || !d->m_selectionModel->model())
356  return;
357 
358  if (indexStrings.isEmpty())
359  return;
360 
361  d->m_pendingSelections.unite(indexStrings.toSet());
362  d->restoreSelection();
363  if (d->hasPendingChanges())
364  d->listenToPendingChanges();
365 }
366 
367 QString KViewStateSaver::currentIndexKey() const
368 {
369  Q_D(const KViewStateSaver);
370  if (!d->m_selectionModel)
371  return QString();
372  return indexToConfigString(d->m_selectionModel->currentIndex());
373 }
374 
375 QStringList KViewStateSaver::expansionKeys() const
376 {
377  Q_D(const KViewStateSaver);
378  if (!d->m_treeView || !d->m_treeView->model())
379  return QStringList();
380 
381  return d->getExpandedItems(QModelIndex());
382 }
383 
384 QStringList KViewStateSaver::selectionKeys() const
385 {
386  Q_D(const KViewStateSaver);
387  if (!d->m_selectionModel)
388  return QStringList();
389 
390  QModelIndexList selectedIndexes = d->m_selectionModel->selectedRows();
391  QStringList selection;
392  foreach ( const QModelIndex &index, selectedIndexes )
393  selection << indexToConfigString( index );
394 
395  return selection;
396 }
397 
398 QPair<int, int> KViewStateSaver::scrollState() const
399 {
400  Q_D(const KViewStateSaver);
401  return qMakePair(d->m_scrollArea->verticalScrollBar()->value(), d->m_scrollArea->horizontalScrollBar()->value());
402 }
403 
404 #include "kviewstatesaver.moc"
405 
QItemSelectionModel
KViewStateSaver::selectionModel
QItemSelectionModel * selectionModel() const
The QItemSelectionModel whose state is persisted.
Definition: kviewstatesaver.cpp:149
KViewStateSaver::currentIndexKey
QString currentIndexKey() const
Returns a QString describing the current index in the selection model.
Definition: kviewstatesaver.cpp:367
kdebug.h
currentKey
static const char * currentKey
Definition: kviewstatesaver.cpp:35
KConfigGroup::writeEntry
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
KViewStateSaver::restoreCurrentItem
void restoreCurrentItem(const QString &indexString)
Make the index described by indexString the currentIndex in the selectionModel.
Definition: kviewstatesaver.cpp:270
QString
QObject
KViewStateSaver::selectionKeys
QStringList selectionKeys() const
Returns a QStringList describing the selection in the selectionModel.
Definition: kviewstatesaver.cpp:384
KViewStateSaver::KViewStateSaver
KViewStateSaver(QObject *parent=0)
Constructor.
Definition: kviewstatesaver.cpp:117
scrollStateHorizontalKey
static const char * scrollStateHorizontalKey
Definition: kviewstatesaver.cpp:36
KViewStateSaver::~KViewStateSaver
~KViewStateSaver()
Destructor.
Definition: kviewstatesaver.cpp:124
KViewStateSaver::restoreScrollState
void restoreScrollState(int verticalScoll, int horizontalScroll)
Restores the scroll state of the QAbstractScrollArea to the verticalScoll and horizontalScroll.
Definition: kviewstatesaver.cpp:320
QStringList
KViewStateSaver::saveState
void saveState(KConfigGroup &configGroup)
Saves the state to the configGroup.
Definition: kviewstatesaver.cpp:230
KViewStateSaver::setView
void setView(QAbstractItemView *view)
Sets the view whose state is persisted.
Definition: kviewstatesaver.cpp:129
KViewStateSaver::expansionKeys
QStringList expansionKeys() const
Returns a QStringList representing the expanded indexes in the QTreeView.
Definition: kviewstatesaver.cpp:375
expansionKey
static const char * expansionKey
Definition: kviewstatesaver.cpp:34
KViewStateSaver::scrollState
QPair< int, int > scrollState() const
Returns the vertical and horizontal scroll of the QAbstractScrollArea.
Definition: kviewstatesaver.cpp:398
QAbstractItemModel
KViewStateSaver::restoreExpanded
void restoreExpanded(const QStringList &indexStrings)
Expand the indexes described by indexStrings in the QTreeView.
Definition: kviewstatesaver.cpp:305
QSet< QString >
scrollStateVerticalKey
static const char * scrollStateVerticalKey
Definition: kviewstatesaver.cpp:37
kviewstatesaver.h
KConfigGroup
KViewStateSaver::setSelectionModel
void setSelectionModel(QItemSelectionModel *selectionModel)
Sets the QItemSelectionModel whose state is persisted.
Definition: kviewstatesaver.cpp:155
KViewStateSaver::restoreSelection
void restoreSelection(const QStringList &indexStrings)
Select the indexes described by indexStrings.
Definition: kviewstatesaver.cpp:351
QPair< int, int >
KViewStateSaver::indexToConfigString
virtual QString indexToConfigString(const QModelIndex &index) const =0
Reimplement to return a unique string for the index.
KViewStateSaver::view
QAbstractItemView * view() const
The view whose state is persisted.
Definition: kviewstatesaver.cpp:143
KViewStateSaver::restoreState
void restoreState(const KConfigGroup &configGroup)
Restores the state from the configGroup.
Definition: kviewstatesaver.cpp:193
selectionKey
static const char * selectionKey
Definition: kviewstatesaver.cpp:33
KConfigGroup::readEntry
T readEntry(const QString &key, const T &aDefault) const
KViewStateSaver
Object for saving and restoring state in QTreeViews and QItemSelectionModels.
Definition: kviewstatesaver.h:169
kconfiggroup.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:49:16 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

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