@@ -288,7 +288,6 @@ QgsBrowserDockWidget::QgsBrowserDockWidget( QString name, QWidget * parent ) :
288288
289289 connect ( mBrowserView , SIGNAL ( customContextMenuRequested ( const QPoint & ) ), this , SLOT ( showContextMenu ( const QPoint & ) ) );
290290 connect ( mBrowserView , SIGNAL ( doubleClicked ( const QModelIndex& ) ), this , SLOT ( addLayerAtIndex ( const QModelIndex& ) ) );
291- connect ( mBrowserView , SIGNAL ( expanded ( const QModelIndex& ) ), this , SLOT ( itemExpanded ( const QModelIndex& ) ) );
292291}
293292
294293void QgsBrowserDockWidget::showEvent ( QShowEvent * e )
@@ -309,28 +308,20 @@ void QgsBrowserDockWidget::showEvent( QShowEvent * e )
309308 mBrowserView ->header ()->setResizeMode ( 0 , QHeaderView::ResizeToContents );
310309 mBrowserView ->header ()->setStretchLastSection ( false );
311310
312- QSettings settings;
313- mInitPath = settings.value ( lastExpandedKey () ).toString ();
314-
315- // expand root favourites item
316- for ( int i = 0 ; i < mModel ->rowCount (); i++ )
317- {
318- QModelIndex index = mModel ->index ( i, 0 );
319- QgsDataItem* item = mModel ->dataItem ( index );
320- if ( item && item->type () == QgsDataItem::Favourites )
321- {
322- QModelIndex proxyIndex = mProxyModel ->mapFromSource ( index );
323- mBrowserView ->expand ( proxyIndex );
324- }
325- }
326-
327- // expand last expanded path from previous session
328- expandPath ( mInitPath );
311+ restoreState ();
329312 }
330313
331314 QDockWidget::showEvent ( e );
332315}
333316
317+ // closeEvent is not called when application is closed
318+ void QgsBrowserDockWidget::hideEvent ( QHideEvent * e )
319+ {
320+ QgsDebugMsg ( " Entered" );
321+ saveState ();
322+ QDockWidget::hideEvent ( e );
323+ }
324+
334325void QgsBrowserDockWidget::showContextMenu ( const QPoint & pt )
335326{
336327 QModelIndex index = mProxyModel ->mapToSource ( mBrowserView ->indexAt ( pt ) );
@@ -426,38 +417,61 @@ void QgsBrowserDockWidget::removeFavourite()
426417
427418void QgsBrowserDockWidget::refresh ()
428419{
429- // QApplication::setOverrideCursor( Qt::WaitCursor );
430420 refreshModel ( QModelIndex () );
431- // QApplication::restoreOverrideCursor();
432421}
433422
434423void QgsBrowserDockWidget::refreshModel ( const QModelIndex& index )
435424{
436425 QgsDebugMsg ( " Entered" );
437- if ( index.isValid () )
426+ QgsDataItem *item = mModel ->dataItem ( index );
427+ if ( item )
438428 {
439- QgsDataItem *item = mModel ->dataItem ( index );
440- if ( item )
441- {
442- QgsDebugMsg ( " path = " + item->path () );
443- }
444- else
445- {
446- QgsDebugMsg ( " invalid item" );
447- }
429+ QgsDebugMsg ( " path = " + item->path () );
430+ }
431+ else
432+ {
433+ QgsDebugMsg ( " invalid item" );
448434 }
449435
450- mModel ->refresh ( index );
436+ if ( item && ( item->capabilities2 () & QgsDataItem::Fertile ) )
437+ {
438+ mModel ->refresh ( index );
439+ }
451440
452441 for ( int i = 0 ; i < mModel ->rowCount ( index ); i++ )
453442 {
454443 QModelIndex idx = mModel ->index ( i, 0 , index );
455444 QModelIndex proxyIdx = mProxyModel ->mapFromSource ( idx );
456- if ( mBrowserView ->isExpanded ( proxyIdx ) || !mProxyModel ->hasChildren ( proxyIdx ) )
445+ QgsDataItem *child = mModel ->dataItem ( idx );
446+
447+ // Check also expanded descendants so that the whole expanded path does not get collapsed if one item is collapsed.
448+ // Fast items (usually root items) are refreshed so that when collapsed, it is obvious they are if empty (no expand symbol).
449+ if ( mBrowserView ->isExpanded ( proxyIdx ) || hasExpandedDescendant ( proxyIdx ) || ( child && child->capabilities2 () & QgsDataItem::Fast ) )
457450 {
458451 refreshModel ( idx );
459452 }
453+ else
454+ {
455+ if ( child && ( child->capabilities2 () & QgsDataItem::Fertile ) )
456+ {
457+ child->depopulate ();
458+ }
459+ }
460+ }
461+ }
462+
463+ bool QgsBrowserDockWidget::hasExpandedDescendant ( const QModelIndex& proxyIndex ) const
464+ {
465+ for ( int i = 0 ; i < mProxyModel ->rowCount ( proxyIndex ); i++ )
466+ {
467+ QModelIndex proxyIdx = mProxyModel ->index ( i, 0 , proxyIndex );
468+ if ( mBrowserView ->isExpanded ( proxyIdx ) )
469+ return true ;
470+
471+ if ( hasExpandedDescendant ( proxyIdx ) )
472+ return true ;
460473 }
474+ return false ;
461475}
462476
463477void QgsBrowserDockWidget::addLayer ( QgsLayerItem *layerItem )
@@ -690,83 +704,134 @@ void QgsBrowserDockWidget::setCaseSensitive( bool caseSensitive )
690704 mProxyModel ->setCaseSensitive ( caseSensitive );
691705}
692706
693- void QgsBrowserDockWidget::itemExpanded ( const QModelIndex& index )
707+ void QgsBrowserDockWidget::saveState ( )
694708{
695- if ( !mModel || !mProxyModel )
696- return ;
709+ QgsDebugMsg ( " Entered" );
697710 QSettings settings;
698- QModelIndex srcIndex = mProxyModel ->mapToSource ( index );
699- QgsDataItem *item = mModel ->dataItem ( srcIndex );
700- if ( !item )
701- return ;
702-
703- settings.setValue ( lastExpandedKey (), item->path () );
704- QgsDebugMsg ( " last expanded: " + item->path () );
711+ QStringList expandedPaths = expandedPathsList ( QModelIndex () );
712+ settings.setValue ( expandedPathsKey (), expandedPaths );
713+ QgsDebugMsg ( " expandedPaths = " + expandedPaths.join ( " " ) );
705714}
706715
707- void QgsBrowserDockWidget::expandPath ( QString path )
716+ void QgsBrowserDockWidget::restoreState ( )
708717{
709- QgsDebugMsg ( " path = " + path );
710-
711- if ( path.isEmpty () )
712- return ;
713-
714- if ( !mModel || !mProxyModel )
715- return ;
716-
717- QModelIndex srcIndex = mModel ->findPath ( path, Qt::MatchStartsWith );
718- QModelIndex index = mProxyModel ->mapFromSource ( srcIndex );
719- QgsDebugMsg ( QString ( " srcIndex.isValid() = %1 index.isValid() = %2" ).arg ( srcIndex.isValid () ).arg ( index.isValid () ) );
720-
721- if ( !index.isValid () )
722- return ;
723-
724- QgsDataItem *item = mModel ->dataItem ( srcIndex );
725- if ( !item )
726- return ;
718+ QgsDebugMsg ( " Entered" );
719+ QSettings settings;
720+ QStringList expandedPaths = settings.value ( expandedPathsKey (), QVariant () ).toStringList ();
727721
728- if ( item-> isPopulated () ) // may be already populated if children were added with grandchildren
722+ if ( !expandedPaths. isEmpty () )
729723 {
730- mBrowserView ->expand ( index );
724+ QSet<QModelIndex> expandIndexSet;
725+ foreach ( QString path, expandedPaths )
726+ {
727+ QModelIndex expandIndex = mModel ->findPath ( path, Qt::MatchStartsWith );
728+ if ( expandIndex.isValid () )
729+ expandIndexSet.insert ( expandIndex );
730+ }
731+ foreach ( QModelIndex expandIndex, expandIndexSet )
732+ {
733+ QModelIndex proxyExpandIndex = mProxyModel ->mapFromSource ( expandIndex );
734+ expand ( proxyExpandIndex );
735+ }
731736 }
732737 else
733738 {
734- mModel ->fetchMore ( srcIndex ); // -> fetch in thread -> fetchFinished
739+ // expand root favourites item
740+ QModelIndex index = mModel ->findPath ( " favourites:" );
741+ QModelIndex proxyIndex = mProxyModel ->mapFromSource ( index );
742+ mBrowserView ->expand ( proxyIndex );
735743 }
736- mBrowserView ->scrollTo ( index, QAbstractItemView::PositionAtTop );
737744}
738745
739746void QgsBrowserDockWidget::fetchFinished ( const QModelIndex & index )
740747{
741- Q_UNUSED ( index );
742- QgsDebugMsg ( " Entered" );
743- QSettings settings;
744-
745- // Continue expanding mInitPath if user has not expanded another item
746- if ( mInitPath .isEmpty () )
748+ QgsDataItem *item = mModel ->dataItem ( index );
749+ if ( !item )
747750 return ;
748751
749- QString lastExpanded = settings.value ( lastExpandedKey () ).toString ();
752+ QgsDebugMsg ( " path = " + item->path () );
753+
754+ QSettings settings;
755+ QStringList expandedPaths = settings.value ( expandedPathsKey (), QVariant () ).toStringList ();
750756
751- if ( !mInitPath .startsWith ( lastExpanded ) )
757+ // Check if user did not collapse it in the meantime
758+ QModelIndex proxyIndex = mProxyModel ->mapFromSource ( index );
759+ if ( !treeExpanded ( proxyIndex ) )
752760 {
753- // User expanded another -> stop mInitPath expansion
754- QgsDebugMsg ( " Stop init path expansion" );
755- mInitPath .clear ();
761+ foreach ( QString path, expandedPaths )
762+ {
763+ if ( path.startsWith ( item->path () + " /" ) )
764+ expandedPaths.removeOne ( path );
765+ }
766+ settings.setValue ( expandedPathsKey (), expandedPaths );
756767 return ;
757768 }
758769
759- // Expand fetched children in init path
760- QModelIndex proxyIndex = mProxyModel ->mapFromSource ( index );
761- if ( index.isValid () )
770+ QSet<QModelIndex> expandIndexSet;
771+ foreach ( QString path, expandedPaths )
762772 {
763- mBrowserView ->expand ( proxyIndex );
773+ if ( path.startsWith ( item->path () + " /" ) )
774+ {
775+ QModelIndex expandIndex = mModel ->findPath ( path, Qt::MatchStartsWith );
776+ if ( expandIndex.isValid () )
777+ expandIndexSet.insert ( expandIndex );
778+ }
779+ }
780+ foreach ( QModelIndex expandIndex, expandIndexSet )
781+ {
782+ QModelIndex proxyExpandIndex = mProxyModel ->mapFromSource ( expandIndex );
783+ expand ( proxyExpandIndex );
764784 }
785+ }
786+
787+ void QgsBrowserDockWidget::expand ( const QModelIndex & proxyIndex )
788+ {
789+ mBrowserView ->expand ( proxyIndex );
790+ QModelIndex parentIndex = mProxyModel ->parent ( proxyIndex );
791+ if ( parentIndex.isValid () )
792+ expand ( parentIndex );
793+ }
794+
795+ bool QgsBrowserDockWidget::treeExpanded ( const QModelIndex & proxyIndex )
796+ {
797+ if ( !mBrowserView ->isExpanded ( proxyIndex ) )
798+ return false ;
799+ QModelIndex parentIndex = mProxyModel ->parent ( proxyIndex );
800+ if ( parentIndex.isValid () )
801+ return treeExpanded ( parentIndex );
765802
766- expandPath ( mInitPath );
803+ return true ; // root
804+ }
805+
806+ QString QgsBrowserDockWidget::expandedPathsKey () const
807+ {
808+ return " /" + objectName ().toLower () + " /expandedPaths" ;
767809}
768810
769- QString QgsBrowserDockWidget::lastExpandedKey () const
811+ QStringList QgsBrowserDockWidget::expandedPathsList ( const QModelIndex & proxyIndex )
770812{
771- return " /" + objectName ().toLower () + " /lastExpanded" ;
813+ QStringList paths;
814+
815+ for ( int i = 0 ; i < mProxyModel ->rowCount ( proxyIndex ); i++ )
816+ {
817+ QModelIndex childProxyIndex = mProxyModel ->index ( i, 0 , proxyIndex );
818+ if ( mBrowserView ->isExpanded ( childProxyIndex ) )
819+ {
820+ QStringList childrenPaths = expandedPathsList ( childProxyIndex );
821+ if ( !childrenPaths.isEmpty () )
822+ {
823+ paths.append ( childrenPaths );
824+ }
825+ else
826+ {
827+ QModelIndex childIndex = mProxyModel ->mapToSource ( childProxyIndex );
828+ QgsDataItem* item = mModel ->dataItem ( childIndex );
829+ if ( item )
830+ {
831+ paths.append ( item->path () );
832+ }
833+ }
834+ }
835+ }
836+ return paths;
772837}
0 commit comments