19#include "moc_qgsbrowsertreeview.cpp"
28#include <QSortFilterProxyModel>
31#include <QRegularExpression>
35 , mSettingsSection( QStringLiteral(
"browser" ) )
37 setEditTriggers( QAbstractItemView::EditKeyPressed );
43 if ( event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter )
44 emit doubleClicked( currentIndex() );
46 QTreeView::keyPressEvent( event );
52 QTreeView::setModel( model );
59 mBrowserModel = model;
67 QTreeView::showEvent( e );
77 QTreeView::hideEvent( e );
80void QgsBrowserTreeView::saveState()
83 const QStringList expandedPaths = expandedPathsList( QModelIndex() );
84 settings.
setValue( expandedPathsKey(), expandedPaths );
88void QgsBrowserTreeView::restoreState()
91 mExpandPaths = settings.
value( expandedPathsKey(), QVariant() ).toStringList();
94 if ( !mExpandPaths.isEmpty() )
96 QSet<QModelIndex> expandIndexSet;
97 const auto constMExpandPaths = mExpandPaths;
98 for (
const QString &path : constMExpandPaths )
101 if ( expandIndex.isValid() )
104 if ( modelIndex.isValid() )
110 const QModelIndex parentIndex = model()->parent( expandIndex );
112 if ( parentIndex.isValid() )
113 expandIndexSet.insert( parentIndex );
117 expandIndexSet.insert( expandIndex );
126 const auto constExpandIndexSet = expandIndexSet;
127 for (
const QModelIndex &expandIndex : constExpandIndexSet )
129 expandTree( expandIndex );
138void QgsBrowserTreeView::expandTree(
const QModelIndex &index )
146 const QModelIndex parentIndex = model()->parent( index );
147 if ( parentIndex.isValid() )
148 expandTree( parentIndex );
151bool QgsBrowserTreeView::treeExpanded(
const QModelIndex &index )
155 if ( !isExpanded( index ) )
157 const QModelIndex parentIndex = model()->parent( index );
158 if ( parentIndex.isValid() )
159 return treeExpanded( parentIndex );
166 if ( !model() || !index.isValid() )
169 for (
int i = 0; i < model()->rowCount( index ); i++ )
171 const QModelIndex childIndex = model()->index( i, 0, index );
172 if ( isExpanded( childIndex ) )
184 if ( pathParts.isEmpty() )
188 QVector< QgsDirectoryItem * > initialDirectoryItemCandidates;
189 const QVector< QgsDataItem * > rootItems = mBrowserModel->
rootItems();
192 if (
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem * >( item ) )
194 initialDirectoryItemCandidates << dirItem;
196 else if (
QgsFavoritesItem *favoritesItem = qobject_cast< QgsFavoritesItem * >( item ) )
198 const QVector<QgsDataItem * > favoriteChildren = favoritesItem->children();
199 for (
QgsDataItem *favoriteChild : favoriteChildren )
201 if (
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem * >( favoriteChild ) )
203 initialDirectoryItemCandidates << dirItem;
210 QString currentCandidatePath;
211 for (
const QString &thisPart : pathParts )
213 currentCandidatePath += ( currentCandidatePath.isEmpty() || currentCandidatePath.endsWith(
'/' ) ? QString() : QStringLiteral(
"/" ) ) + thisPart;
215 auto it = initialDirectoryItemCandidates.begin();
216 while ( it != initialDirectoryItemCandidates.end() )
218 if ( !( *it )->dirPath().startsWith( currentCandidatePath ) )
220 it = initialDirectoryItemCandidates.erase( it );
224 if (
str.startsWith( ( *it )->dirPath() ) )
225 currentDirectoryItem = *it;
231 if ( !currentDirectoryItem )
234 QStringList remainingParts = pathParts;
235 auto it = remainingParts.begin();
236 QDir currentDir = *it;
237 while ( it != remainingParts.end() )
239 if ( currentDirectoryItem->
dirPath().startsWith( currentDir.filePath( *it ) ) )
241 currentDir = QDir( currentDir.filePath( *it ) );
242 it = remainingParts.erase( it );
250 currentDir = QDir( currentDirectoryItem->
dirPath() );
251 QList< QgsDirectoryItem * > pathItems;
253 pathItems << currentDirectoryItem;
255 for (
const QString ¤tFolderName : std::as_const( remainingParts ) )
257 const QString thisPath = currentDir.filePath( currentFolderName );
259 if ( !QFile::exists( thisPath ) )
264 const QVector< QgsDataItem * > children = currentDirectoryItem->
children();
267 if (
QgsDirectoryItem *childDirectoryItem = qobject_cast< QgsDirectoryItem *>( child ) )
269 if ( childDirectoryItem->dirPath() == thisPath )
271 existingChild = childDirectoryItem;
279 pathItems << existingChild;
280 currentDirectoryItem = existingChild;
287 currentDirectoryItem = newDir;
290 currentDir = QDir( thisPath );
296 QModelIndex index = mBrowserModel->
findItem( i );
297 if ( QSortFilterProxyModel *proxyModel = qobject_cast< QSortFilterProxyModel *>( model() ) )
299 index = proxyModel->mapFromSource( index );
305 if ( selectPath && lastItem )
311 if ( !mBrowserModel )
314 QModelIndex index = mBrowserModel->
findItem( item );
315 if ( !index.isValid() )
318 if ( QSortFilterProxyModel *proxyModel = qobject_cast< QSortFilterProxyModel *>( model() ) )
320 index = proxyModel->mapFromSource( index );
323 setCurrentIndex( index );
330 QTreeView::rowsInserted( parentIndex, start, end );
335 if ( mExpandPaths.isEmpty() )
344 mExpandPaths.removeOne( parentPath );
347 if ( !treeExpanded( parentIndex ) )
349 const auto constMExpandPaths = mExpandPaths;
350 for (
const QString &path : constMExpandPaths )
352 if ( path.startsWith( parentPath +
'/' ) )
353 mExpandPaths.removeOne( path );
358 for (
int i = start; i <= end; i++ )
360 const QModelIndex childIndex = model()->index( i, 0, parentIndex );
362 const QString escapedChildPath = QRegularExpression::escape( childPath );
364 QgsDebugMsgLevel(
"childPath = " + childPath +
" escapedChildPath = " + escapedChildPath, 2 );
365 if ( mExpandPaths.contains( childPath ) || mExpandPaths.indexOf( QRegularExpression(
"^" + escapedChildPath +
"/.*" ) ) != -1 )
369 if ( modelIndex.isValid() )
374 expand( childIndex );
381QString QgsBrowserTreeView::expandedPathsKey()
const
383 return '/' + mSettingsSection +
"/expandedPaths";
386QStringList QgsBrowserTreeView::expandedPathsList(
const QModelIndex &index )
393 for (
int i = 0; i < model()->rowCount( index ); i++ )
395 const QModelIndex childIndex = model()->index( i, 0, index );
396 if ( isExpanded( childIndex ) )
398 const QStringList childrenPaths = expandedPathsList( childIndex );
399 if ( !childrenPaths.isEmpty() )
401 paths.append( childrenPaths );
@ Collapse
The collapse/expand status for this items children should be ignored in order to avoid undesired netw...
A model for showing available data sources and other items in a structured tree.
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index.
QModelIndex findPath(const QString &path, Qt::MatchFlag matchFlag=Qt::MatchExactly)
Returns index of item with given path.
QModelIndex findItem(QgsDataItem *item, QgsDataItem *parent=nullptr) const
Returns the model index corresponding to the specified data item.
QVector< QgsDataItem * > rootItems() const
Returns the root items for the model.
@ Path
Item path used to access path in the tree, see QgsDataItem::mPath.
void showEvent(QShowEvent *e) override
QgsBrowserTreeView(QWidget *parent=nullptr)
Constructor for QgsBrowserTreeView.
void keyPressEvent(QKeyEvent *event) override
void expandPath(const QString &path, bool selectPath=false)
Expands out a file path in the view.
void setBrowserModel(QgsBrowserGuiModel *model)
Sets the browser model.
void setModel(QAbstractItemModel *model) override
bool setSelectedItem(QgsDataItem *item)
Sets the item currently selected in the view.
void hideEvent(QHideEvent *e) override
bool hasExpandedDescendant(const QModelIndex &index) const
void rowsInserted(const QModelIndex &parentIndex, int start, int end) override
QgsBrowserGuiModel * browserModel()
Returns the browser model.
Base class for all items in the model.
QVector< QgsDataItem * > children() const
virtual void addChildItem(QgsDataItem *child, bool refresh=false)
Inserts a new child item.
virtual Qgis::BrowserItemCapabilities capabilities2() const
Returns the capabilities for the data item.
A directory: contains subdirectories and layers.
QString dirPath() const
Returns the full path to the directory the item represents.
Contains various Favorites directories.
static QStringList splitPathToComponents(const QString &path)
Given a file path, returns a list of all the components leading to that path.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
#define QgsDebugMsgLevel(str, level)