QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 <QSettings>
17 
18 #include "qgsbrowsermodel.h"
19 #include "qgsbrowsertreeview.h"
20 
21 #include "qgslogger.h"
22 
23 
25  : QTreeView( parent )
26  , mSettingsSection( "browser" )
27  , mBrowserModel( nullptr )
28 {
29 }
30 
32 {
33 }
34 
36 {
37  mBrowserModel = model;
38 }
39 
41 {
42 
43  QTreeView::setModel( model );
44 
45  restoreState();
46 }
47 
49 {
50  Q_UNUSED( e );
51  if ( model() )
52  restoreState();
54 }
55 
56 // closeEvent is not called when application is closed
58 {
59  Q_UNUSED( e );
60  // hideEvent() may be called (Mac) before showEvent
61  if ( model() )
62  saveState();
64 }
65 
66 void QgsBrowserTreeView::saveState()
67 {
68  QSettings settings;
69  QStringList expandedPaths = expandedPathsList( QModelIndex() );
70  settings.setValue( expandedPathsKey(), expandedPaths );
71  QgsDebugMsg( "expandedPaths = " + expandedPaths.join( " " ) );
72 }
73 
74 void QgsBrowserTreeView::restoreState()
75 {
76  QSettings settings;
77  mExpandPaths = settings.value( expandedPathsKey(), QVariant() ).toStringList();
78 
79  QgsDebugMsg( "mExpandPaths = " + mExpandPaths.join( " " ) );
80  if ( !mExpandPaths.isEmpty() )
81  {
82  QSet<QModelIndex> expandIndexSet;
83  Q_FOREACH ( const QString& path, mExpandPaths )
84  {
85  QModelIndex expandIndex = QgsBrowserModel::findPath( model(), path, Qt::MatchStartsWith );
86  if ( expandIndex.isValid() )
87  {
88  QModelIndex modelIndex = browserModel()->findPath( path, Qt::MatchExactly );
89  if ( modelIndex.isValid() )
90  {
91  QgsDataItem *ptr = browserModel()->dataItem( modelIndex );
92  if ( ptr && ( ptr->capabilities2() & QgsDataItem::Capability::Collapse ) )
93  {
94  QgsDebugMsgLevel( "do not expand index for path " + path, 4 );
95  QModelIndex parentIndex = model()->parent( expandIndex );
96  // Still we need to store the parent in order to expand it
97  if ( parentIndex.isValid() )
98  expandIndexSet.insert( parentIndex );
99  }
100  else
101  {
102  expandIndexSet.insert( expandIndex );
103  }
104  }
105 
106  }
107  else
108  {
109  QgsDebugMsg( "index for path " + path + " not found" );
110  }
111  }
112  Q_FOREACH ( const QModelIndex& expandIndex, expandIndexSet )
113  {
114  expandTree( expandIndex );
115  }
116  }
117  else
118  {
119  // expand root favourites item
120  QModelIndex index = QgsBrowserModel::findPath( model(), "favourites:" );
121  expand( index );
122  }
123 }
124 
125 void QgsBrowserTreeView::expandTree( const QModelIndex & index )
126 {
127  if ( !model() )
128  return;
129 
130  QgsDebugMsg( "itemPath = " + model()->data( index, QgsBrowserModel::PathRole ).toString() );
131 
132  expand( index );
133  QModelIndex parentIndex = model()->parent( index );
134  if ( parentIndex.isValid() )
135  expandTree( parentIndex );
136 }
137 
138 bool QgsBrowserTreeView::treeExpanded( const QModelIndex & index )
139 {
140  if ( !model() )
141  return false;
142  if ( !isExpanded( index ) )
143  return false;
144  QModelIndex parentIndex = model()->parent( index );
145  if ( parentIndex.isValid() )
146  return treeExpanded( parentIndex );
147 
148  return true; // root
149 }
150 
152 {
153  if ( !model() )
154  return false;
155 
156  for ( int i = 0 ; i < model()->rowCount( index ); i++ )
157  {
158  QModelIndex childIndex = model()->index( i, 0, index );
159  if ( isExpanded( childIndex ) )
160  return true;
161 
162  if ( hasExpandedDescendant( childIndex ) )
163  return true;
164  }
165  return false;
166 }
167 
168 // rowsInserted signal is used to continue in state restoring
169 void QgsBrowserTreeView::rowsInserted( const QModelIndex & parentIndex, int start, int end )
170 {
171  QTreeView::rowsInserted( parentIndex, start, end );
172 
173  if ( !model() )
174  return;
175 
176  if ( mExpandPaths.isEmpty() )
177  return;
178 
179  QgsDebugMsgLevel( "mExpandPaths = " + mExpandPaths.join( "," ), 2 );
180 
181  QString parentPath = model()->data( parentIndex, QgsBrowserModel::PathRole ).toString();
182  QgsDebugMsgLevel( "parentPath = " + parentPath, 2 );
183 
184  // remove parentPath from paths to be expanded
185  mExpandPaths.removeOne( parentPath );
186 
187  // Remove the subtree from mExpandPaths if user collapsed the item in the meantime
188  if ( !treeExpanded( parentIndex ) )
189  {
190  Q_FOREACH ( const QString& path, mExpandPaths )
191  {
192  if ( path.startsWith( parentPath + '/' ) )
193  mExpandPaths.removeOne( path );
194  }
195  return;
196  }
197 
198  for ( int i = start; i <= end; i++ )
199  {
200  QModelIndex childIndex = model()->index( i, 0, parentIndex );
201  QString childPath = model()->data( childIndex, QgsBrowserModel::PathRole ).toString();
202  QString escapedChildPath = childPath;
203  escapedChildPath.replace( '|', "\\|" );
204 
205  QgsDebugMsgLevel( "childPath = " + childPath + " escapedChildPath = " + escapedChildPath, 2 );
206  if ( mExpandPaths.contains( childPath ) || mExpandPaths.indexOf( QRegExp( "^" + escapedChildPath + "/.*" ) ) != -1 )
207  {
208  QgsDebugMsgLevel( "-> expand", 2 );
209  expand( childIndex );
210  }
211  }
212 }
213 
214 QString QgsBrowserTreeView::expandedPathsKey() const
215 {
216  return '/' + mSettingsSection + "/expandedPaths";
217 }
218 
219 QStringList QgsBrowserTreeView::expandedPathsList( const QModelIndex & index )
220 {
221  QStringList paths;
222 
223  if ( !model() )
224  return paths;
225 
226  for ( int i = 0; i < model()->rowCount( index ); i++ )
227  {
228  QModelIndex childIndex = model()->index( i, 0, index );
229  if ( isExpanded( childIndex ) )
230  {
231  QStringList childrenPaths = expandedPathsList( childIndex );
232  if ( !childrenPaths.isEmpty() )
233  {
234  paths.append( childrenPaths );
235  }
236  else
237  {
238  paths.append( model()->data( childIndex, QgsBrowserModel::PathRole ).toString() );
239  }
240  }
241  }
242  return paths;
243 }
static unsigned index
virtual int rowCount(const QModelIndex &parent) const=0
virtual void setModel(QAbstractItemModel *model) override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const=0
void setBrowserModel(QgsBrowserModel *model)
Set the browser model.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QModelIndex findPath(const QString &path, Qt::MatchFlag matchFlag=Qt::MatchExactly)
Return index of item with given path.
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QString join(const QString &separator) const
const_iterator insert(const T &value)
QgsBrowserTreeView(QWidget *parent=nullptr)
bool hasExpandedDescendant(const QModelIndex &index) const
void setValue(const QString &key, const QVariant &value)
bool isValid() const
virtual void showEvent(QShowEvent *event)
void append(const T &value)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
virtual void hideEvent(QHideEvent *event)
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
bool isEmpty() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QgsDataItem * dataItem(const QModelIndex &idx) const
virtual void rowsInserted(const QModelIndex &parentIndex, int start, int end) override
virtual QVariant data(const QModelIndex &index, int role) const=0
bool isExpanded(const QModelIndex &index) const
virtual QModelIndex parent(const QModelIndex &index) const=0
Base class for all items in the model.
Definition: qgsdataitem.h:79
QString & replace(int position, int n, QChar after)
QVariant value(const QString &key, const QVariant &defaultValue) const
virtual void showEvent(QShowEvent *e) override
QStringList toStringList() const
virtual void setModel(QAbstractItemModel *model)
virtual void hideEvent(QHideEvent *e) override
int indexOf(const QRegExp &rx, int from) const
void expand(const QModelIndex &index)
QAbstractItemModel * model() const
QgsBrowserModel * browserModel()
Return the browser model.
QString toString() const
bool removeOne(const T &value)
virtual Capabilities capabilities2() const
Definition: qgsdataitem.h:185