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

KDEUI

  • sources
  • kde-4.14
  • 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_scrollArea )
65  return;
66 
67  if ( m_horizontalScrollBarValue >= 0 && m_horizontalScrollBarValue <= m_scrollArea->horizontalScrollBar()->maximum() ) {
68  m_scrollArea->horizontalScrollBar()->setValue( m_horizontalScrollBarValue );
69  m_horizontalScrollBarValue = -1;
70  }
71  if ( m_verticalScrollBarValue >= 0 && m_verticalScrollBarValue <= m_scrollArea->verticalScrollBar()->maximum() ) {
72  m_scrollArea->verticalScrollBar()->setValue( m_verticalScrollBarValue );
73  m_verticalScrollBarValue = -1;
74  }
75  }
76 
77  void restoreSelection();
78  void restoreCurrentItem();
79  void restoreExpanded();
80 
81  inline bool hasPendingChanges() const
82  {
83  return !m_pendingCurrent.isEmpty() || !m_pendingExpansions.isEmpty() || !m_pendingSelections.isEmpty();
84  }
85 
86  const QAbstractItemModel* getModel()
87  {
88  if ( m_selectionModel && m_selectionModel->model() )
89  return m_selectionModel->model();
90  else if ( m_view && m_view->model() )
91  return m_view->model();
92  return 0;
93  }
94 
95  void rowsInserted( const QModelIndex &/*index*/, int /*start*/, int /*end*/ )
96  {
97  Q_Q(KViewStateSaver);
98  processPendingChanges();
99 
100  if ( !hasPendingChanges() )
101  {
102  q->disconnect( getModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
103  q, SLOT(rowsInserted(QModelIndex,int,int)) );
104  q->deleteLater();
105  }
106  }
107 
108  QTreeView *m_treeView;
109  QAbstractItemView *m_view;
110  QItemSelectionModel *m_selectionModel;
111  QAbstractScrollArea *m_scrollArea;
112 
113  int m_horizontalScrollBarValue;
114  int m_verticalScrollBarValue;
115  QSet<QString> m_pendingSelections;
116  QSet<QString> m_pendingExpansions;
117  QString m_pendingCurrent;
118 };
119 
120 KViewStateSaver::KViewStateSaver(QObject* parent)
121  : QObject(0), d_ptr( new KViewStateSaverPrivate(this) )
122 {
123  Q_UNUSED(parent);
124  qRegisterMetaType<QModelIndex>( "QModelIndex" );
125 }
126 
127 KViewStateSaver::~KViewStateSaver()
128 {
129  delete d_ptr;
130 }
131 
132 void KViewStateSaver::setView(QAbstractItemView* view)
133 {
134  Q_D(KViewStateSaver);
135  d->m_scrollArea = view;
136  if (view) {
137  d->m_selectionModel = view->selectionModel();
138  d->m_treeView = qobject_cast<QTreeView*>(view);
139  } else {
140  d->m_selectionModel = 0;
141  d->m_treeView = 0;
142  }
143  d->m_view = view;
144 }
145 
146 QAbstractItemView* KViewStateSaver::view() const
147 {
148  Q_D(const KViewStateSaver);
149  return d->m_view;
150 }
151 
152 QItemSelectionModel* KViewStateSaver::selectionModel() const
153 {
154  Q_D(const KViewStateSaver);
155  return d->m_selectionModel;
156 }
157 
158 void KViewStateSaver::setSelectionModel(QItemSelectionModel* selectionModel)
159 {
160  Q_D(KViewStateSaver);
161  d->m_selectionModel = selectionModel;
162 }
163 
164 void KViewStateSaverPrivate::listenToPendingChanges()
165 {
166  Q_Q(KViewStateSaver);
167  // watch the model for stuff coming in delayed
168  if ( hasPendingChanges() )
169  {
170  const QAbstractItemModel *model = getModel();
171  if ( model )
172  {
173  q->disconnect( model, SIGNAL(rowsInserted(QModelIndex,int,int)),
174  q, SLOT(rowsInserted(QModelIndex,int,int)) );
175  q->connect( model, SIGNAL(rowsInserted(QModelIndex,int,int)),
176  SLOT(rowsInserted(QModelIndex,int,int)) );
177  return;
178  } else {
179  q->deleteLater();
180  }
181  } else {
182  q->deleteLater();
183  }
184 }
185 
186 void KViewStateSaverPrivate::processPendingChanges()
187 {
188  Q_Q(KViewStateSaver);
189 
190  q->restoreCurrentItem(m_pendingCurrent);
191  q->restoreSelection(m_pendingSelections.toList());
192  q->restoreExpanded(m_pendingExpansions.toList());
193  q->restoreScrollState(m_verticalScrollBarValue, m_horizontalScrollBarValue);
194 }
195 
196 void KViewStateSaver::restoreState(const KConfigGroup& configGroup)
197 {
198  Q_D(KViewStateSaver);
199 
200  // Delete myself if not finished after 60 seconds.
201  QTimer::singleShot(60000, this, SLOT(deleteLater()));
202 
203 
204  d->m_pendingCurrent = configGroup.readEntry( currentKey, QString() );
205  d->m_pendingSelections = configGroup.readEntry( selectionKey, QStringList() ).toSet();
206  d->m_pendingExpansions = configGroup.readEntry( expansionKey, QStringList() ).toSet();
207  d->m_horizontalScrollBarValue = configGroup.readEntry( scrollStateHorizontalKey, -1 );
208  d->m_verticalScrollBarValue = configGroup.readEntry( scrollStateVerticalKey, -1 );
209 
210  d->processPendingChanges();
211  if (d->hasPendingChanges())
212  d->listenToPendingChanges();
213 }
214 
215 QStringList KViewStateSaverPrivate::getExpandedItems(const QModelIndex &index) const
216 {
217  Q_Q(const KViewStateSaver);
218 
219  QStringList expansion;
220  for ( int i = 0; i < m_treeView->model()->rowCount( index ); ++i ) {
221  const QModelIndex child = m_treeView->model()->index( i, 0, index );
222 
223  // http://bugreports.qt.nokia.com/browse/QTBUG-18039
224  if ( m_treeView->model()->hasChildren( child ) ) {
225  if ( m_treeView->isExpanded( child ) )
226  expansion << q->indexToConfigString( child );
227  expansion << getExpandedItems( child );
228  }
229  }
230  return expansion;
231 }
232 
233 void KViewStateSaver::saveState(KConfigGroup& configGroup)
234 {
235  Q_D(KViewStateSaver);
236 
237  if ( d->m_selectionModel )
238  {
239  configGroup.writeEntry( selectionKey, selectionKeys() );
240  configGroup.writeEntry( currentKey, currentIndexKey() );
241  }
242 
243  if ( d->m_treeView )
244  {
245  QStringList expansion = expansionKeys();
246 
247  configGroup.writeEntry( expansionKey, expansion );
248  }
249 
250  if ( d->m_scrollArea )
251  {
252  QPair<int, int> _scrollState = scrollState();
253  configGroup.writeEntry( scrollStateVerticalKey, _scrollState.first );
254  configGroup.writeEntry( scrollStateHorizontalKey, _scrollState.second );
255  }
256 }
257 
258 void KViewStateSaverPrivate::restoreCurrentItem()
259 {
260  Q_Q(KViewStateSaver);
261 
262  QModelIndex currentIndex = q->indexFromConfigString(m_selectionModel->model(), m_pendingCurrent);
263  if ( currentIndex.isValid() )
264  {
265  if (m_treeView)
266  m_treeView->setCurrentIndex(currentIndex);
267  else
268  m_selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::NoUpdate);
269  m_pendingCurrent.clear();
270  }
271 }
272 
273 void KViewStateSaver::restoreCurrentItem(const QString& indexString)
274 {
275  Q_D(KViewStateSaver);
276  if (!d->m_selectionModel || !d->m_selectionModel->model())
277  return;
278 
279  if (indexString.isEmpty())
280  {
281  return;
282  }
283  d->m_pendingCurrent = indexString;
284  d->restoreCurrentItem();
285 
286  if (d->hasPendingChanges())
287  d->listenToPendingChanges();
288 }
289 
290 void KViewStateSaverPrivate::restoreExpanded()
291 {
292  Q_Q(KViewStateSaver);
293 
294  QSet<QString>::iterator it = m_pendingExpansions.begin();
295  for ( ; it != m_pendingExpansions.end(); )
296  {
297  QModelIndex idx = q->indexFromConfigString( m_treeView->model(), *it);
298  if ( idx.isValid() )
299  {
300  m_treeView->expand( idx );
301  it = m_pendingExpansions.erase( it );
302  } else {
303  ++it;
304  }
305  }
306 }
307 
308 void KViewStateSaver::restoreExpanded(const QStringList& indexStrings)
309 {
310  Q_D(KViewStateSaver);
311  if (!d->m_treeView || !d->m_treeView->model())
312  return;
313 
314  if (indexStrings.isEmpty())
315  return;
316 
317  d->m_pendingExpansions.unite(indexStrings.toSet());
318  d->restoreExpanded();
319  if (d->hasPendingChanges())
320  d->listenToPendingChanges();
321 }
322 
323 void KViewStateSaver::restoreScrollState(int verticalScoll, int horizontalScroll)
324 {
325  Q_D(KViewStateSaver);
326 
327  if ( !d->m_scrollArea )
328  return;
329 
330  d->m_verticalScrollBarValue = verticalScoll;
331  d->m_horizontalScrollBarValue = horizontalScroll;
332 
333  QTimer::singleShot( 0, this, SLOT(restoreScrollBarState()) );
334 }
335 
336 void KViewStateSaverPrivate::restoreSelection()
337 {
338  Q_Q(KViewStateSaver);
339 
340  QSet<QString>::iterator it = m_pendingSelections.begin();
341  for ( ; it != m_pendingSelections.end(); )
342  {
343  QModelIndex idx = q->indexFromConfigString( m_selectionModel->model(), *it);
344  if ( idx.isValid() )
345  {
346  m_selectionModel->select( idx, QItemSelectionModel::Select );
347  it = m_pendingSelections.erase( it );
348  } else {
349  ++it;
350  }
351  }
352 }
353 
354 void KViewStateSaver::restoreSelection(const QStringList& indexStrings)
355 {
356  Q_D(KViewStateSaver);
357 
358  if (!d->m_selectionModel || !d->m_selectionModel->model())
359  return;
360 
361  if (indexStrings.isEmpty())
362  return;
363 
364  d->m_pendingSelections.unite(indexStrings.toSet());
365  d->restoreSelection();
366  if (d->hasPendingChanges())
367  d->listenToPendingChanges();
368 }
369 
370 QString KViewStateSaver::currentIndexKey() const
371 {
372  Q_D(const KViewStateSaver);
373  if (!d->m_selectionModel)
374  return QString();
375  return indexToConfigString(d->m_selectionModel->currentIndex());
376 }
377 
378 QStringList KViewStateSaver::expansionKeys() const
379 {
380  Q_D(const KViewStateSaver);
381  if (!d->m_treeView || !d->m_treeView->model())
382  return QStringList();
383 
384  return d->getExpandedItems(QModelIndex());
385 }
386 
387 QStringList KViewStateSaver::selectionKeys() const
388 {
389  Q_D(const KViewStateSaver);
390  if (!d->m_selectionModel)
391  return QStringList();
392 
393  QModelIndexList selectedIndexes = d->m_selectionModel->selectedRows();
394  QStringList selection;
395  foreach ( const QModelIndex &index, selectedIndexes )
396  selection << indexToConfigString( index );
397 
398  return selection;
399 }
400 
401 QPair<int, int> KViewStateSaver::scrollState() const
402 {
403  Q_D(const KViewStateSaver);
404  return qMakePair(d->m_scrollArea->verticalScrollBar()->value(), d->m_scrollArea->horizontalScrollBar()->value());
405 }
406 
407 #include "kviewstatesaver.moc"
408 
QModelIndex
QAbstractItemModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
KViewStateSaver::selectionModel
QItemSelectionModel * selectionModel() const
The QItemSelectionModel whose state is persisted.
Definition: kviewstatesaver.cpp:152
KViewStateSaver::currentIndexKey
QString currentIndexKey() const
Returns a QString describing the current index in the selection model.
Definition: kviewstatesaver.cpp:370
kdebug.h
QAbstractItemView
QAbstractItemView::selectionModel
QItemSelectionModel * selectionModel() const
currentKey
static const char * currentKey
Definition: kviewstatesaver.cpp:35
QAbstractScrollArea
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:273
QList::toSet
QSet< T > toSet() const
KViewStateSaver::selectionKeys
QStringList selectionKeys() const
Returns a QStringList describing the selection in the selectionModel.
Definition: kviewstatesaver.cpp:387
KViewStateSaver::KViewStateSaver
KViewStateSaver(QObject *parent=0)
Constructor.
Definition: kviewstatesaver.cpp:120
QModelIndex::isValid
bool isValid() const
scrollStateHorizontalKey
static const char * scrollStateHorizontalKey
Definition: kviewstatesaver.cpp:36
KViewStateSaver::~KViewStateSaver
~KViewStateSaver()
Destructor.
Definition: kviewstatesaver.cpp:127
KViewStateSaver::restoreScrollState
void restoreScrollState(int verticalScoll, int horizontalScroll)
Restores the scroll state of the QAbstractScrollArea to the verticalScoll and horizontalScroll.
Definition: kviewstatesaver.cpp:323
QObject
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
KViewStateSaver::saveState
void saveState(KConfigGroup &configGroup)
Saves the state to the configGroup.
Definition: kviewstatesaver.cpp:233
KViewStateSaver::setView
void setView(QAbstractItemView *view)
Sets the view whose state is persisted.
Definition: kviewstatesaver.cpp:132
KViewStateSaver::expansionKeys
QStringList expansionKeys() const
Returns a QStringList representing the expanded indexes in the QTreeView.
Definition: kviewstatesaver.cpp:378
QSet< QString >
QObject::deleteLater
void deleteLater()
QString
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:401
QStringList
QPair< int, int >
KViewStateSaver::restoreExpanded
void restoreExpanded(const QStringList &indexStrings)
Expand the indexes described by indexStrings in the QTreeView.
Definition: kviewstatesaver.cpp:308
QSet::begin
iterator begin()
scrollStateVerticalKey
static const char * scrollStateVerticalKey
Definition: kviewstatesaver.cpp:37
QSet::erase
iterator erase(iterator pos)
kviewstatesaver.h
KConfigGroup
QModelIndex::model
const QAbstractItemModel * model() const
QTreeView
KViewStateSaver::setSelectionModel
void setSelectionModel(QItemSelectionModel *selectionModel)
Sets the QItemSelectionModel whose state is persisted.
Definition: kviewstatesaver.cpp:158
QSet::end
iterator end()
QAbstractItemModel
KViewStateSaver::restoreSelection
void restoreSelection(const QStringList &indexStrings)
Select the indexes described by indexStrings.
Definition: kviewstatesaver.cpp:354
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:146
QItemSelectionModel
KViewStateSaver::restoreState
void restoreState(const KConfigGroup &configGroup)
Restores the state from the configGroup.
Definition: kviewstatesaver.cpp:196
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
QTimer::singleShot
singleShot
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:00 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • 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