QGIS API Documentation  2.14.0-Essen
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 {
28 }
29 
31 {
32 }
33 
35 {
36  QgsDebugMsg( "Entered" );
37 
38  QTreeView::setModel( model );
39 
40  restoreState();
41 }
42 
44 {
45  Q_UNUSED( e );
46  QgsDebugMsg( "Entered" );
47  if ( model() )
48  restoreState();
50 }
51 
52 // closeEvent is not called when application is closed
54 {
55  Q_UNUSED( e );
56  QgsDebugMsg( "Entered" );
57  // hideEvent() may be called (Mac) before showEvent
58  if ( model() )
59  saveState();
61 }
62 
63 void QgsBrowserTreeView::saveState()
64 {
65  QgsDebugMsg( "Entered" );
66  QSettings settings;
67  QStringList expandedPaths = expandedPathsList( QModelIndex() );
68  settings.setValue( expandedPathsKey(), expandedPaths );
69  QgsDebugMsg( "expandedPaths = " + expandedPaths.join( " " ) );
70 }
71 
72 void QgsBrowserTreeView::restoreState()
73 {
74  QgsDebugMsg( "Entered" );
75  QSettings settings;
76  mExpandPaths = settings.value( expandedPathsKey(), QVariant() ).toStringList();
77 
78  QgsDebugMsg( "mExpandPaths = " + mExpandPaths.join( " " ) );
79  if ( !mExpandPaths.isEmpty() )
80  {
81  QSet<QModelIndex> expandIndexSet;
82  Q_FOREACH ( const QString& path, mExpandPaths )
83  {
84  QModelIndex expandIndex = QgsBrowserModel::findPath( model(), path, Qt::MatchStartsWith );
85  if ( expandIndex.isValid() )
86  expandIndexSet.insert( expandIndex );
87  else
88  {
89  QgsDebugMsg( "index for path " + path + " not found" );
90  }
91  }
92  Q_FOREACH ( const QModelIndex& expandIndex, expandIndexSet )
93  {
94  expandTree( expandIndex );
95  }
96  }
97  else
98  {
99  // expand root favourites item
100  QModelIndex index = QgsBrowserModel::findPath( model(), "favourites:" );
101  expand( index );
102  }
103 }
104 
105 void QgsBrowserTreeView::expandTree( const QModelIndex & index )
106 {
107  if ( !model() )
108  return;
109 
110  QString itemPath = model()->data( index, QgsBrowserModel::PathRole ).toString();
111  QgsDebugMsg( "itemPath = " + itemPath );
112 
113  expand( index );
114  QModelIndex parentIndex = model()->parent( index );
115  if ( parentIndex.isValid() )
116  expandTree( parentIndex );
117 }
118 
119 bool QgsBrowserTreeView::treeExpanded( const QModelIndex & index )
120 {
121  if ( !model() )
122  return false;
123  if ( !isExpanded( index ) )
124  return false;
125  QModelIndex parentIndex = model()->parent( index );
126  if ( parentIndex.isValid() )
127  return treeExpanded( parentIndex );
128 
129  return true; // root
130 }
131 
133 {
134  if ( !model() )
135  return false;
136 
137  for ( int i = 0 ; i < model()->rowCount( index ); i++ )
138  {
139  QModelIndex childIndex = model()->index( i, 0, index );
140  if ( isExpanded( childIndex ) )
141  return true;
142 
143  if ( hasExpandedDescendant( childIndex ) )
144  return true;
145  }
146  return false;
147 }
148 
149 // rowsInserted signal is used to continue in state restoring
150 void QgsBrowserTreeView::rowsInserted( const QModelIndex & parentIndex, int start, int end )
151 {
152  QTreeView::rowsInserted( parentIndex, start, end );
153 
154  if ( !model() )
155  return;
156 
157  if ( mExpandPaths.isEmpty() )
158  return;
159 
160  QgsDebugMsgLevel( "mExpandPaths = " + mExpandPaths.join( "," ), 2 );
161 
162  QString parentPath = model()->data( parentIndex, QgsBrowserModel::PathRole ).toString();
163  QgsDebugMsgLevel( "parentPath = " + parentPath, 2 );
164 
165  // remove parentPath from paths to be expanded
166  mExpandPaths.removeOne( parentPath );
167 
168  // Remove the subtree from mExpandPaths if user collapsed the item in the meantime
169  if ( !treeExpanded( parentIndex ) )
170  {
171  Q_FOREACH ( const QString& path, mExpandPaths )
172  {
173  if ( path.startsWith( parentPath + '/' ) )
174  mExpandPaths.removeOne( path );
175  }
176  return;
177  }
178 
179  for ( int i = start; i <= end; i++ )
180  {
181  QModelIndex childIndex = model()->index( i, 0, parentIndex );
182  QString childPath = model()->data( childIndex, QgsBrowserModel::PathRole ).toString();
183  QString escapedChildPath = childPath;
184  escapedChildPath.replace( '|', "\\|" );
185 
186  QgsDebugMsgLevel( "childPath = " + childPath + " escapedChildPath = " + escapedChildPath, 2 );
187  if ( mExpandPaths.contains( childPath ) || mExpandPaths.indexOf( QRegExp( "^" + escapedChildPath + "/.*" ) ) != -1 )
188  {
189  QgsDebugMsgLevel( "-> expand", 2 );
190  expand( childIndex );
191  }
192  }
193 }
194 
195 QString QgsBrowserTreeView::expandedPathsKey() const
196 {
197  return '/' + mSettingsSection + "/expandedPaths";
198 }
199 
200 QStringList QgsBrowserTreeView::expandedPathsList( const QModelIndex & index )
201 {
202  QStringList paths;
203 
204  if ( !model() )
205  return paths;
206 
207  for ( int i = 0; i < model()->rowCount( index ); i++ )
208  {
209  QModelIndex childIndex = model()->index( i, 0, index );
210  if ( isExpanded( childIndex ) )
211  {
212  QStringList childrenPaths = expandedPathsList( childIndex );
213  if ( !childrenPaths.isEmpty() )
214  {
215  paths.append( childrenPaths );
216  }
217  else
218  {
219  paths.append( model()->data( childIndex, QgsBrowserModel::PathRole ).toString() );
220  }
221  }
222  }
223  return paths;
224 }
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
#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)
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
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
QString & replace(int position, int n, QChar after)
bool hasExpandedDescendant(const QModelIndex &index) const
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
QString toString() const
bool removeOne(const T &value)