QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsbrowsertreeview.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsbrowsertreeview.cpp
3  --------------------------------------
4  Date : January 2015
5  Copyright : (C) 2015 by Radim Blazek
6  Email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgssettings.h"
17 #include "qgsbrowsermodel.h"
18 #include "qgsbrowsertreeview.h"
19 #include "qgslogger.h"
20 
21 
23  : QTreeView( parent )
24  , mSettingsSection( QStringLiteral( "browser" ) )
25 {
26 }
27 
28 void QgsBrowserTreeView::setModel( QAbstractItemModel *model )
29 {
30 
31  QTreeView::setModel( model );
32 
33  restoreState();
34 }
35 
37 {
38  mBrowserModel = model;
39 }
40 
41 void QgsBrowserTreeView::showEvent( QShowEvent *e )
42 {
43  Q_UNUSED( e );
44  if ( model() )
45  restoreState();
46  QTreeView::showEvent( e );
47 }
48 
49 // closeEvent is not called when application is closed
50 void QgsBrowserTreeView::hideEvent( QHideEvent *e )
51 {
52  Q_UNUSED( e );
53  // hideEvent() may be called (Mac) before showEvent
54  if ( model() )
55  saveState();
56  QTreeView::hideEvent( e );
57 }
58 
59 void QgsBrowserTreeView::saveState()
60 {
61  QgsSettings settings;
62  QStringList expandedPaths = expandedPathsList( QModelIndex() );
63  settings.setValue( expandedPathsKey(), expandedPaths );
64  QgsDebugMsgLevel( "expandedPaths = " + expandedPaths.join( " " ), 4 );
65 }
66 
67 void QgsBrowserTreeView::restoreState()
68 {
69  QgsSettings settings;
70  mExpandPaths = settings.value( expandedPathsKey(), QVariant() ).toStringList();
71 
72  QgsDebugMsgLevel( "mExpandPaths = " + mExpandPaths.join( " " ), 4 );
73  if ( !mExpandPaths.isEmpty() )
74  {
75  QSet<QModelIndex> expandIndexSet;
76  Q_FOREACH ( const QString &path, mExpandPaths )
77  {
78  QModelIndex expandIndex = QgsBrowserModel::findPath( model(), path, Qt::MatchStartsWith );
79  if ( expandIndex.isValid() )
80  {
81  QModelIndex modelIndex = browserModel()->findPath( path, Qt::MatchExactly );
82  if ( modelIndex.isValid() )
83  {
84  QgsDataItem *ptr = browserModel()->dataItem( modelIndex );
85  if ( ptr && ( ptr->capabilities2() & QgsDataItem::Capability::Collapse ) )
86  {
87  QgsDebugMsgLevel( "do not expand index for path " + path, 4 );
88  QModelIndex parentIndex = model()->parent( expandIndex );
89  // Still we need to store the parent in order to expand it
90  if ( parentIndex.isValid() )
91  expandIndexSet.insert( parentIndex );
92  }
93  else
94  {
95  expandIndexSet.insert( expandIndex );
96  }
97  }
98  }
99  else
100  {
101  QgsDebugMsgLevel( "index for path " + path + " not found", 4 );
102  }
103  }
104  Q_FOREACH ( const QModelIndex &expandIndex, expandIndexSet )
105  {
106  expandTree( expandIndex );
107  }
108  }
109 
110  // expand root favorites item
111  QModelIndex index = QgsBrowserModel::findPath( model(), QStringLiteral( "favorites:" ) );
112  expand( index );
113 }
114 
115 void QgsBrowserTreeView::expandTree( const QModelIndex &index )
116 {
117  if ( !model() )
118  return;
119 
120  QgsDebugMsgLevel( "itemPath = " + model()->data( index, QgsBrowserModel::PathRole ).toString(), 4 );
121 
122  expand( index );
123  QModelIndex parentIndex = model()->parent( index );
124  if ( parentIndex.isValid() )
125  expandTree( parentIndex );
126 }
127 
128 bool QgsBrowserTreeView::treeExpanded( const QModelIndex &index )
129 {
130  if ( !model() )
131  return false;
132  if ( !isExpanded( index ) )
133  return false;
134  QModelIndex parentIndex = model()->parent( index );
135  if ( parentIndex.isValid() )
136  return treeExpanded( parentIndex );
137 
138  return true; // root
139 }
140 
141 bool QgsBrowserTreeView::hasExpandedDescendant( const QModelIndex &index ) const
142 {
143  if ( !model() )
144  return false;
145 
146  for ( int i = 0; i < model()->rowCount( index ); i++ )
147  {
148  QModelIndex childIndex = model()->index( i, 0, index );
149  if ( isExpanded( childIndex ) )
150  return true;
151 
152  if ( hasExpandedDescendant( childIndex ) )
153  return true;
154  }
155  return false;
156 }
157 
158 // rowsInserted signal is used to continue in state restoring
159 void QgsBrowserTreeView::rowsInserted( const QModelIndex &parentIndex, int start, int end )
160 {
161  QTreeView::rowsInserted( parentIndex, start, end );
162 
163  if ( !model() )
164  return;
165 
166  if ( mExpandPaths.isEmpty() )
167  return;
168 
169  QgsDebugMsgLevel( "mExpandPaths = " + mExpandPaths.join( "," ), 2 );
170 
171  QString parentPath = model()->data( parentIndex, QgsBrowserModel::PathRole ).toString();
172  QgsDebugMsgLevel( "parentPath = " + parentPath, 2 );
173 
174  // remove parentPath from paths to be expanded
175  mExpandPaths.removeOne( parentPath );
176 
177  // Remove the subtree from mExpandPaths if user collapsed the item in the meantime
178  if ( !treeExpanded( parentIndex ) )
179  {
180  Q_FOREACH ( const QString &path, mExpandPaths )
181  {
182  if ( path.startsWith( parentPath + '/' ) )
183  mExpandPaths.removeOne( path );
184  }
185  return;
186  }
187 
188  for ( int i = start; i <= end; i++ )
189  {
190  QModelIndex childIndex = model()->index( i, 0, parentIndex );
191  QString childPath = model()->data( childIndex, QgsBrowserModel::PathRole ).toString();
192  QString escapedChildPath = childPath;
193  escapedChildPath.replace( '|', QLatin1String( "\\|" ) );
194 
195  QgsDebugMsgLevel( "childPath = " + childPath + " escapedChildPath = " + escapedChildPath, 2 );
196  if ( mExpandPaths.contains( childPath ) || mExpandPaths.indexOf( QRegExp( "^" + escapedChildPath + "/.*" ) ) != -1 )
197  {
198  QgsDebugMsgLevel( "-> expand", 2 );
199  expand( childIndex );
200  }
201  }
202 }
203 
204 QString QgsBrowserTreeView::expandedPathsKey() const
205 {
206  return '/' + mSettingsSection + "/expandedPaths";
207 }
208 
209 QStringList QgsBrowserTreeView::expandedPathsList( const QModelIndex &index )
210 {
211  QStringList paths;
212 
213  if ( !model() )
214  return paths;
215 
216  for ( int i = 0; i < model()->rowCount( index ); i++ )
217  {
218  QModelIndex childIndex = model()->index( i, 0, index );
219  if ( isExpanded( childIndex ) )
220  {
221  QStringList childrenPaths = expandedPathsList( childIndex );
222  if ( !childrenPaths.isEmpty() )
223  {
224  paths.append( childrenPaths );
225  }
226  else
227  {
228  paths.append( model()->data( childIndex, QgsBrowserModel::PathRole ).toString() );
229  }
230  }
231  }
232  return paths;
233 }
void setModel(QAbstractItemModel *model) override
void setBrowserModel(QgsBrowserModel *model)
Sets the browser model.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QModelIndex findPath(const QString &path, Qt::MatchFlag matchFlag=Qt::MatchExactly)
Returns index of item with given path.
QgsBrowserTreeView(QWidget *parent=nullptr)
Constructor for QgsBrowserTreeView.
Item path used to access path in the tree, see QgsDataItem::mPath.
bool hasExpandedDescendant(const QModelIndex &index) const
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsDataItem * dataItem(const QModelIndex &idx) const
void rowsInserted(const QModelIndex &parentIndex, int start, int end) override
Base class for all items in the model.
Definition: qgsdataitem.h:49
void showEvent(QShowEvent *e) override
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void hideEvent(QHideEvent *e) override
A model for showing available data sources and other items in a structured tree.
QgsBrowserModel * browserModel()
Returns the browser model.
virtual Capabilities capabilities2() const
Definition: qgsdataitem.h:224