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

KDEUI

kviewstatesaver.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2010 Klarälvdalens Datakonsult AB,
00003         a KDAB Group company, info@kdab.net,
00004         author Stephen Kelly <stephen@kdab.com>
00005 
00006     This library is free software; you can redistribute it and/or modify it
00007     under the terms of the GNU Library General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or (at your
00009     option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful, but WITHOUT
00012     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00014     License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to the
00018     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019     02110-1301, USA.
00020 */
00021 
00022 #include "kviewstatesaver.h"
00023 
00024 #include <QtGui/QAbstractScrollArea>
00025 #include <QScrollBar>
00026 #include <QTimer>
00027 #include <QTreeView>
00028 
00029 #include "kdebug.h"
00030 
00031 #include "kconfiggroup.h"
00032 
00033 static const char * selectionKey = "Selection";
00034 static const char * expansionKey = "Expansion";
00035 static const char * currentKey = "Current";
00036 static const char * scrollStateHorizontalKey = "HorizontalScroll";
00037 static const char * scrollStateVerticalKey = "VerticalScroll";
00038 
00039 class KViewStateSaverPrivate
00040 {
00041 public:
00042   KViewStateSaverPrivate(KViewStateSaver *qq)
00043     : q_ptr(qq),
00044       m_treeView(0),
00045       m_view(0),
00046       m_selectionModel(0),
00047       m_scrollArea(0),
00048       m_horizontalScrollBarValue(-1),
00049       m_verticalScrollBarValue(-1)
00050   {
00051 
00052   }
00053 
00054   Q_DECLARE_PUBLIC(KViewStateSaver)
00055   KViewStateSaver * const q_ptr;
00056 
00057   QStringList getExpandedItems(const QModelIndex &index) const;
00058 
00059   void listenToPendingChanges();
00060   void processPendingChanges();
00061 
00062   inline void restoreScrollBarState()
00063   {
00064     if ( m_horizontalScrollBarValue >= 0 && m_horizontalScrollBarValue <= m_scrollArea->horizontalScrollBar()->maximum() ) {
00065       m_scrollArea->horizontalScrollBar()->setValue( m_horizontalScrollBarValue );
00066       m_horizontalScrollBarValue = -1;
00067     }
00068     if ( m_verticalScrollBarValue >= 0 && m_verticalScrollBarValue <= m_scrollArea->verticalScrollBar()->maximum() ) {
00069       m_scrollArea->verticalScrollBar()->setValue( m_verticalScrollBarValue );
00070       m_verticalScrollBarValue = -1;
00071     }
00072   }
00073 
00074   void restoreSelection();
00075   void restoreCurrentItem();
00076   void restoreExpanded();
00077 
00078   inline bool hasPendingChanges() const
00079   {
00080     return !m_pendingCurrent.isEmpty() || !m_pendingExpansions.isEmpty() || !m_pendingSelections.isEmpty();
00081   }
00082 
00083   const QAbstractItemModel* getModel()
00084   {
00085     if ( m_selectionModel && m_selectionModel->model() )
00086       return m_selectionModel->model();
00087     else if ( m_view && m_view->model() )
00088       return m_view->model();
00089     return 0;
00090   }
00091 
00092   void rowsInserted( const QModelIndex &index, int start, int end )
00093   {
00094     Q_Q(KViewStateSaver);
00095     processPendingChanges();
00096 
00097     if ( !hasPendingChanges() )
00098     {
00099       q->disconnect( getModel(), SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
00100           q, SLOT( rowsInserted( const QModelIndex&, int, int ) ) );
00101       q->deleteLater();
00102     }
00103   }
00104 
00105   QTreeView *m_treeView;
00106   QAbstractItemView *m_view;
00107   QItemSelectionModel *m_selectionModel;
00108   QAbstractScrollArea *m_scrollArea;
00109 
00110   int m_horizontalScrollBarValue;
00111   int m_verticalScrollBarValue;
00112   QSet<QString> m_pendingSelections;
00113   QSet<QString> m_pendingExpansions;
00114   QString m_pendingCurrent;
00115 };
00116 
00117 KViewStateSaver::KViewStateSaver(QObject* parent)
00118   : QObject(0), d_ptr( new KViewStateSaverPrivate(this) )
00119 {
00120   Q_UNUSED(parent);
00121   qRegisterMetaType<QModelIndex>( "QModelIndex" );
00122 }
00123 
00124 KViewStateSaver::~KViewStateSaver()
00125 {
00126   delete d_ptr;
00127 }
00128 
00129 void KViewStateSaver::setView(QAbstractItemView* view)
00130 {
00131   Q_D(KViewStateSaver);
00132   d->m_scrollArea = view;
00133   if (view) {
00134     d->m_selectionModel = view->selectionModel();
00135     d->m_treeView = qobject_cast<QTreeView*>(view);
00136   } else {
00137     d->m_selectionModel = 0;
00138     d->m_treeView = 0;
00139   }
00140   d->m_view = view;
00141 }
00142 
00143 QAbstractItemView* KViewStateSaver::view() const
00144 {
00145   Q_D(const KViewStateSaver);
00146   return d->m_view;
00147 }
00148 
00149 QItemSelectionModel* KViewStateSaver::selectionModel() const
00150 {
00151   Q_D(const KViewStateSaver);
00152   return d->m_selectionModel;
00153 }
00154 
00155 void KViewStateSaver::setSelectionModel(QItemSelectionModel* selectionModel)
00156 {
00157   Q_D(KViewStateSaver);
00158   d->m_selectionModel = selectionModel;
00159 }
00160 
00161 void KViewStateSaverPrivate::listenToPendingChanges()
00162 {
00163   Q_Q(KViewStateSaver);
00164   // watch the model for stuff coming in delayed
00165   if ( hasPendingChanges() )
00166   {
00167     const QAbstractItemModel *model = getModel();
00168     if ( model )
00169     {
00170       q->disconnect( model, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
00171           q, SLOT( rowsInserted( const QModelIndex&, int, int ) ) );
00172       q->connect( model, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
00173           SLOT( rowsInserted( const QModelIndex&, int, int ) ) );
00174       return;
00175     } else {
00176       q->deleteLater();
00177     }
00178   } else {
00179     q->deleteLater();
00180   }
00181 }
00182 
00183 void KViewStateSaverPrivate::processPendingChanges()
00184 {
00185   Q_Q(KViewStateSaver);
00186 
00187   q->restoreCurrentItem(m_pendingCurrent);
00188   q->restoreSelection(m_pendingSelections.toList());
00189   q->restoreExpanded(m_pendingExpansions.toList());
00190   q->restoreScrollState(m_verticalScrollBarValue, m_horizontalScrollBarValue);
00191 }
00192 
00193 void KViewStateSaver::restoreState(const KConfigGroup& configGroup)
00194 {
00195   Q_D(KViewStateSaver);
00196 
00197   // Delete myself if not finished after ten seconds.
00198   QTimer::singleShot(10000, this, SLOT(deleteLater()));
00199 
00200 
00201   d->m_pendingCurrent = configGroup.readEntry( currentKey, QString() );
00202   d->m_pendingSelections = configGroup.readEntry( selectionKey, QStringList() ).toSet();
00203   d->m_pendingExpansions = configGroup.readEntry( expansionKey, QStringList() ).toSet();
00204   d->m_horizontalScrollBarValue = configGroup.readEntry( scrollStateHorizontalKey, -1 );
00205   d->m_verticalScrollBarValue = configGroup.readEntry( scrollStateVerticalKey, -1 );
00206 
00207   d->processPendingChanges();
00208   if (d->hasPendingChanges())
00209     d->listenToPendingChanges();
00210 }
00211 
00212 QStringList KViewStateSaverPrivate::getExpandedItems(const QModelIndex &index) const
00213 {
00214   Q_Q(const KViewStateSaver);
00215 
00216   QStringList expansion;
00217   for ( int i = 0; i < m_treeView->model()->rowCount( index ); ++i ) {
00218     const QModelIndex child = m_treeView->model()->index( i, 0, index );
00219     if ( m_treeView->isExpanded( child ) )
00220       expansion << q->indexToConfigString( child );
00221     if ( m_treeView->model()->hasChildren( child ) )
00222       expansion << getExpandedItems( child );
00223   }
00224   return expansion;
00225 }
00226 
00227 void KViewStateSaver::saveState(KConfigGroup& configGroup)
00228 {
00229   Q_D(KViewStateSaver);
00230 
00231   if ( d->m_selectionModel )
00232   {
00233     configGroup.writeEntry( selectionKey, selectionKeys() );
00234     configGroup.writeEntry( currentKey, currentIndexKey() );
00235   }
00236 
00237   if ( d->m_treeView )
00238   {
00239     QStringList expansion = expansionKeys();
00240 
00241     configGroup.writeEntry( expansionKey, expansion );
00242   }
00243 
00244   if ( d->m_scrollArea )
00245   {
00246     QPair<int, int> _scrollState = scrollState();
00247     configGroup.writeEntry( scrollStateVerticalKey, _scrollState.first );
00248     configGroup.writeEntry( scrollStateHorizontalKey, _scrollState.second );
00249   }
00250 }
00251 
00252 void KViewStateSaverPrivate::restoreCurrentItem()
00253 {
00254   Q_Q(KViewStateSaver);
00255 
00256   QModelIndex currentIndex = q->indexFromConfigString(m_selectionModel->model(), m_pendingCurrent);
00257   if ( currentIndex.isValid() )
00258   {
00259     if (m_treeView)
00260       m_treeView->setCurrentIndex(currentIndex);
00261     else
00262       m_selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::NoUpdate);
00263     m_pendingCurrent.clear();
00264   }
00265 }
00266 
00267 void KViewStateSaver::restoreCurrentItem(const QString& indexString)
00268 {
00269   Q_D(KViewStateSaver);
00270   if (!d->m_selectionModel || !d->m_selectionModel->model())
00271       return;
00272 
00273   if (indexString.isEmpty())
00274   {
00275     return;
00276   }
00277   d->m_pendingCurrent = indexString;
00278   d->restoreCurrentItem();
00279 
00280   if (d->hasPendingChanges())
00281     d->listenToPendingChanges();
00282 }
00283 
00284 void KViewStateSaverPrivate::restoreExpanded()
00285 {
00286   Q_Q(KViewStateSaver);
00287 
00288   QSet<QString>::iterator it = m_pendingExpansions.begin();
00289   for ( ; it != m_pendingExpansions.end(); )
00290   {
00291     QModelIndex idx = q->indexFromConfigString( m_treeView->model(), *it);
00292     if ( idx.isValid() )
00293     {
00294       m_treeView->expand( idx );
00295       it = m_pendingExpansions.erase( it );
00296     } else {
00297       ++it;
00298     }
00299   }
00300 }
00301 
00302 void KViewStateSaver::restoreExpanded(const QStringList& indexStrings)
00303 {
00304   Q_D(KViewStateSaver);
00305   if (!d->m_treeView || !d->m_treeView->model())
00306       return;
00307 
00308   if (indexStrings.isEmpty())
00309     return;
00310 
00311   d->m_pendingExpansions.unite(indexStrings.toSet());
00312   d->restoreExpanded();
00313   if (d->hasPendingChanges())
00314     d->listenToPendingChanges();
00315 }
00316 
00317 void KViewStateSaver::restoreScrollState(int verticalScoll, int horizontalScroll)
00318 {
00319   Q_D(KViewStateSaver);
00320 
00321   if ( !d->m_scrollArea )
00322     return;
00323 
00324   d->m_verticalScrollBarValue = verticalScoll;
00325   d->m_horizontalScrollBarValue = horizontalScroll;
00326 
00327   QTimer::singleShot( 0, this, SLOT( restoreScrollBarState() ) );
00328 }
00329 
00330 void KViewStateSaverPrivate::restoreSelection()
00331 {
00332   Q_Q(KViewStateSaver);
00333 
00334   QSet<QString>::iterator it = m_pendingSelections.begin();
00335   for ( ; it != m_pendingSelections.end(); )
00336   {
00337     QModelIndex idx = q->indexFromConfigString( m_selectionModel->model(), *it);
00338     if ( idx.isValid() )
00339     {
00340       m_selectionModel->select( idx, QItemSelectionModel::Select );
00341       it = m_pendingSelections.erase( it );
00342     } else {
00343       ++it;
00344     }
00345   }
00346 }
00347 
00348 void KViewStateSaver::restoreSelection(const QStringList& indexStrings)
00349 {
00350   Q_D(KViewStateSaver);
00351 
00352   if (!d->m_selectionModel || !d->m_selectionModel->model())
00353       return;
00354 
00355   if (indexStrings.isEmpty())
00356     return;
00357 
00358   d->m_pendingSelections.unite(indexStrings.toSet());
00359   d->restoreSelection();
00360   if (d->hasPendingChanges())
00361     d->listenToPendingChanges();
00362 }
00363 
00364 QString KViewStateSaver::currentIndexKey() const
00365 {
00366   Q_D(const KViewStateSaver);
00367   if (!d->m_selectionModel)
00368       return QString();
00369   return indexToConfigString(d->m_selectionModel->currentIndex());
00370 }
00371 
00372 QStringList KViewStateSaver::expansionKeys() const
00373 {
00374   Q_D(const KViewStateSaver);
00375   if (!d->m_treeView || !d->m_treeView->model())
00376       return QStringList();
00377 
00378   return d->getExpandedItems(QModelIndex());
00379 }
00380 
00381 QStringList KViewStateSaver::selectionKeys() const
00382 {
00383   Q_D(const KViewStateSaver);
00384   if (!d->m_selectionModel)
00385       return QStringList();
00386 
00387   QModelIndexList selectedIndexes = d->m_selectionModel->selectedRows();
00388   QStringList selection;
00389   foreach ( const QModelIndex &index, selectedIndexes )
00390     selection << indexToConfigString( index );
00391 
00392   return selection;
00393 }
00394 
00395 QPair<int, int> KViewStateSaver::scrollState() const
00396 {
00397   Q_D(const KViewStateSaver);
00398   return qMakePair(d->m_scrollArea->verticalScrollBar()->value(), d->m_scrollArea->horizontalScrollBar()->value());
00399 }
00400 
00401 #include "kviewstatesaver.moc"
00402 

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal