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

KDEUI

  • 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
33static const char * selectionKey = "Selection";
34static const char * expansionKey = "Expansion";
35static const char * currentKey = "Current";
36static const char * scrollStateHorizontalKey = "HorizontalScroll";
37static const char * scrollStateVerticalKey = "VerticalScroll";
38
39class KViewStateSaverPrivate
40{
41public:
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
120KViewStateSaver::KViewStateSaver(QObject* parent)
121 : QObject(0), d_ptr( new KViewStateSaverPrivate(this) )
122{
123 Q_UNUSED(parent);
124 qRegisterMetaType<QModelIndex>( "QModelIndex" );
125}
126
127KViewStateSaver::~KViewStateSaver()
128{
129 delete d_ptr;
130}
131
132void 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
146QAbstractItemView* KViewStateSaver::view() const
147{
148 Q_D(const KViewStateSaver);
149 return d->m_view;
150}
151
152QItemSelectionModel* KViewStateSaver::selectionModel() const
153{
154 Q_D(const KViewStateSaver);
155 return d->m_selectionModel;
156}
157
158void KViewStateSaver::setSelectionModel(QItemSelectionModel* selectionModel)
159{
160 Q_D(KViewStateSaver);
161 d->m_selectionModel = selectionModel;
162}
163
164void 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
186void 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
196void 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
215QStringList 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
233void 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
258void 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
273void 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
290void 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
308void 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
323void 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
336void 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
354void 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
370QString 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
378QStringList 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
387QStringList 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
401QPair<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
KConfigGroup
KConfigGroup::writeEntry
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
KConfigGroup::readEntry
QString readEntry(const char *key, const char *aDefault=0) const
KViewStateSaver
Object for saving and restoring state in QTreeViews and QItemSelectionModels.
Definition: kviewstatesaver.h:170
KViewStateSaver::indexToConfigString
virtual QString indexToConfigString(const QModelIndex &index) const =0
Reimplement to return a unique string for the index.
KViewStateSaver::currentIndexKey
QString currentIndexKey() const
Returns a QString describing the current index in the selection model.
Definition: kviewstatesaver.cpp:370
KViewStateSaver::expansionKeys
QStringList expansionKeys() const
Returns a QStringList representing the expanded indexes in the QTreeView.
Definition: kviewstatesaver.cpp:378
KViewStateSaver::view
QAbstractItemView * view() const
The view whose state is persisted.
Definition: kviewstatesaver.cpp:146
KViewStateSaver::scrollState
QPair< int, int > scrollState() const
Returns the vertical and horizontal scroll of the QAbstractScrollArea.
Definition: kviewstatesaver.cpp:401
KViewStateSaver::restoreCurrentItem
void restoreCurrentItem(const QString &indexString)
Make the index described by indexString the currentIndex in the selectionModel.
Definition: kviewstatesaver.cpp:273
KViewStateSaver::restoreSelection
void restoreSelection(const QStringList &indexStrings)
Select the indexes described by indexStrings.
Definition: kviewstatesaver.cpp:354
KViewStateSaver::~KViewStateSaver
~KViewStateSaver()
Destructor.
Definition: kviewstatesaver.cpp:127
KViewStateSaver::restoreState
void restoreState(const KConfigGroup &configGroup)
Restores the state from the configGroup.
Definition: kviewstatesaver.cpp:196
KViewStateSaver::setSelectionModel
void setSelectionModel(QItemSelectionModel *selectionModel)
Sets the QItemSelectionModel whose state is persisted.
Definition: kviewstatesaver.cpp:158
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::KViewStateSaver
KViewStateSaver(QObject *parent=0)
Constructor.
Definition: kviewstatesaver.cpp:120
KViewStateSaver::selectionModel
QItemSelectionModel * selectionModel() const
The QItemSelectionModel whose state is persisted.
Definition: kviewstatesaver.cpp:152
KViewStateSaver::restoreScrollState
void restoreScrollState(int verticalScoll, int horizontalScroll)
Restores the scroll state of the QAbstractScrollArea to the verticalScoll and horizontalScroll.
Definition: kviewstatesaver.cpp:323
KViewStateSaver::restoreExpanded
void restoreExpanded(const QStringList &indexStrings)
Expand the indexes described by indexStrings in the QTreeView.
Definition: kviewstatesaver.cpp:308
KViewStateSaver::selectionKeys
QStringList selectionKeys() const
Returns a QStringList describing the selection in the selectionModel.
Definition: kviewstatesaver.cpp:387
QAbstractItemModel
QItemSelectionModel
QObject
QPair
QSet
kconfiggroup.h
kdebug.h
expansionKey
static const char * expansionKey
Definition: kviewstatesaver.cpp:34
scrollStateHorizontalKey
static const char * scrollStateHorizontalKey
Definition: kviewstatesaver.cpp:36
scrollStateVerticalKey
static const char * scrollStateVerticalKey
Definition: kviewstatesaver.cpp:37
selectionKey
static const char * selectionKey
Definition: kviewstatesaver.cpp:33
currentKey
static const char * currentKey
Definition: kviewstatesaver.cpp:35
kviewstatesaver.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
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