QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsbrowsermodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsbrowsermodel.cpp
3  ---------------------
4  begin : July 2011
5  copyright : (C) 2011 by Martin Dobias
6  email : wonder dot sk at gmail dot com
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 #include <QDir>
16 #include <QApplication>
17 #include <QStyle>
18 #include <QtConcurrentMap>
19 #include <QUrl>
20 #include <QStorageInfo>
21 #include <QFuture>
22 #include <QFutureWatcher>
23 
24 #include "qgis.h"
25 #include "qgsapplication.h"
26 #include "qgsdataitemprovider.h"
28 #include "qgsdataprovider.h"
29 #include "qgsmimedatautils.h"
30 #include "qgslogger.h"
31 #include "qgsproviderregistry.h"
32 #include "qgsbrowsermodel.h"
33 #include "qgsproject.h"
34 #include "qgssettings.h"
35 #include "qgsdirectoryitem.h"
36 #include "qgsprojectitem.h"
37 #include "qgslayeritem.h"
38 #include "qgsfavoritesitem.h"
39 
40 #define PROJECT_HOME_PREFIX "project:"
41 #define HOME_PREFIX "home:"
42 
44 class QgsBrowserWatcher : public QFutureWatcher<QVector <QgsDataItem *> >
45 {
46  Q_OBJECT
47 
48  public:
49  QgsBrowserWatcher( QgsDataItem *item )
50  : QFutureWatcher( nullptr )
51  , mItem( item )
52  {
53  }
54 
55  QgsDataItem *item() const { return mItem; }
56 
57  signals:
58  void finished( QgsDataItem *item, const QVector <QgsDataItem *> &items );
59 
60  private:
61  QgsDataItem *mItem = nullptr;
62 };
64 
65 // sort function for QList<QgsDataItem*>, e.g. sorted/grouped provider listings
66 static bool cmpByDataItemName_( QgsDataItem *a, QgsDataItem *b )
67 {
68  return QString::localeAwareCompare( a->name(), b->name() ) < 0;
69 }
70 
72  : QAbstractItemModel( parent )
73 
74 {
76  this, &QgsBrowserModel::dataItemProviderAdded );
78  this, &QgsBrowserModel::dataItemProviderWillBeRemoved );
79 }
80 
82 {
84 }
85 
87 {
88  QString home = QgsProject::instance()->homePath();
89  if ( mProjectHome && mProjectHome->path().mid( QStringLiteral( PROJECT_HOME_PREFIX ).length() ) == home )
90  return;
91 
92  int idx = mRootItems.indexOf( mProjectHome );
93 
94  // using layoutAboutToBeChanged() was messing expanded items
95  if ( idx >= 0 )
96  {
97  beginRemoveRows( QModelIndex(), idx, idx );
98  mRootItems.remove( idx );
99  endRemoveRows();
100  }
101  delete mProjectHome;
102  mProjectHome = home.isNull() ? nullptr : new QgsProjectHomeItem( nullptr, tr( "Project Home" ), home, QStringLiteral( PROJECT_HOME_PREFIX ) + home );
103  if ( mProjectHome )
104  {
105  setupItemConnections( mProjectHome );
106 
107  beginInsertRows( QModelIndex(), 0, 0 );
108  mRootItems.insert( 0, mProjectHome );
109  endInsertRows();
110  }
111 }
112 
114 {
116 
117  // give the home directory a prominent third place
118  QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, tr( "Home" ), QDir::homePath(),
119  QStringLiteral( HOME_PREFIX ) + QDir::homePath(),
120  QStringLiteral( "special:Home" ) );
121  item->setSortKey( QStringLiteral( " 2" ) );
122  setupItemConnections( item );
123  mRootItems << item;
124 
125  // add favorite directories
126  mFavorites = new QgsFavoritesItem( nullptr, tr( "Favorites" ) );
127  if ( mFavorites )
128  {
129  setupItemConnections( mFavorites );
131  }
132 
133  // add drives
134  const auto drives { QDir::drives() };
135  for ( const QFileInfo &drive : drives )
136  {
137  const QString path = drive.absolutePath();
138 
139  if ( QgsDirectoryItem::hiddenPath( path ) )
140  continue;
141 
142  const QString driveName = QStorageInfo( path ).displayName();
143  const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( "%1 (%2)" ).arg( path, driveName );
144 
145  QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, name, path, path, QStringLiteral( "special:Drives" ) );
146  item->setSortKey( QStringLiteral( " 3 %1" ).arg( path ) );
147  mDriveItems.insert( path, item );
148 
149  setupItemConnections( item );
150  mRootItems << item;
151  }
152 
153 #ifdef Q_OS_MAC
154  QString path = QString( "/Volumes" );
155  QgsDirectoryItem *vols = new QgsDirectoryItem( nullptr, path, path, path, QStringLiteral( "special:Volumes" ) );
156  setupItemConnections( vols );
157  mRootItems << vols;
158 #endif
159 
160  // container for displaying providers as sorted groups (by QgsDataProvider::DataCapability enum)
161  QMultiMap<int, QgsDataItem *> providerMap;
162 
163  const auto constProviders = QgsApplication::dataItemProviderRegistry()->providers();
164  for ( QgsDataItemProvider *pr : constProviders )
165  {
166  if ( QgsDataItem *item = addProviderRootItem( pr ) )
167  {
168  providerMap.insert( pr->capabilities(), item );
169  }
170  }
171 
172  // add as sorted groups by QgsDataProvider::DataCapability enum
173  const auto constUniqueKeys = providerMap.uniqueKeys();
174  for ( int key : constUniqueKeys )
175  {
176  QList<QgsDataItem *> providerGroup = providerMap.values( key );
177  if ( providerGroup.size() > 1 )
178  {
179  std::sort( providerGroup.begin(), providerGroup.end(), cmpByDataItemName_ );
180  }
181 
182  const auto constProviderGroup = providerGroup;
183  for ( QgsDataItem *ditem : constProviderGroup )
184  {
185  mRootItems << ditem;
186  }
187  }
188 }
189 
191 {
192  const auto constMRootItems = mRootItems;
193  for ( QgsDataItem *item : constMRootItems )
194  {
195  delete item;
196  }
197 
198  mRootItems.clear();
199  mDriveItems.clear();
200 }
201 
202 void QgsBrowserModel::dataItemProviderAdded( QgsDataItemProvider *provider )
203 {
204  if ( !mInitialized )
205  return;
206 
207  if ( QgsDataItem *item = addProviderRootItem( provider ) )
208  {
209  beginInsertRows( QModelIndex(), rowCount(), rowCount() );
210  mRootItems << item;
211  endInsertRows();
212  }
213 }
214 
215 void QgsBrowserModel::dataItemProviderWillBeRemoved( QgsDataItemProvider *provider )
216 {
217  const auto constMRootItems = mRootItems;
218  for ( QgsDataItem *item : constMRootItems )
219  {
220  if ( item->providerKey() == provider->name() )
221  {
222  removeRootItem( item );
223  break; // assuming there is max. 1 root item per provider
224  }
225  }
226 }
227 
228 void QgsBrowserModel::onConnectionsChanged( const QString &providerKey )
229 {
230  // refresh the matching provider
231  for ( QgsDataItem *item : std::as_const( mRootItems ) )
232  {
233  if ( item->providerKey() == providerKey )
234  {
235  item->refresh();
236  break; // assuming there is max. 1 root item per provider
237  }
238  }
239 
240  emit connectionsChanged( providerKey );
241 }
242 
243 QMap<QString, QgsDirectoryItem *> QgsBrowserModel::driveItems() const
244 {
245  return mDriveItems;
246 }
247 
248 
250 {
251  if ( ! mInitialized )
252  {
254  addRootItems();
255  mInitialized = true;
256  }
257 }
258 
259 Qt::ItemFlags QgsBrowserModel::flags( const QModelIndex &index ) const
260 {
261  if ( !index.isValid() )
262  return Qt::ItemFlags();
263 
264  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
265 
266  QgsDataItem *ptr = dataItem( index );
267 
268  if ( !ptr )
269  {
270  QgsDebugMsgLevel( QStringLiteral( "FLAGS PROBLEM!" ), 4 );
271  return Qt::ItemFlags();
272  }
273 
274  if ( ptr->hasDragEnabled() )
275  flags |= Qt::ItemIsDragEnabled;
276 
278  if ( ptr->acceptDrop() )
279  flags |= Qt::ItemIsDropEnabled;
281 
284  flags |= Qt::ItemIsEditable;
285 
286  return flags;
287 }
288 
289 QVariant QgsBrowserModel::data( const QModelIndex &index, int role ) const
290 {
291  if ( !index.isValid() )
292  return QVariant();
293 
294  QgsDataItem *item = dataItem( index );
295  if ( !item )
296  {
297  return QVariant();
298  }
299  else if ( role == Qt::DisplayRole || role == Qt::EditRole )
300  {
301  return item->name();
302  }
303  else if ( role == QgsBrowserModel::SortRole )
304  {
305  return item->sortKey();
306  }
307  else if ( role == Qt::ToolTipRole )
308  {
309  return item->toolTip();
310  }
311  else if ( role == Qt::DecorationRole && index.column() == 0 )
312  {
313  return item->icon();
314  }
315  else if ( role == QgsBrowserModel::PathRole )
316  {
317  return item->path();
318  }
319  else if ( role == QgsBrowserModel::CommentRole )
320  {
321  if ( item->type() == Qgis::BrowserItemType::Layer )
322  {
323  QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
324  return lyrItem->comments();
325  }
326  return QVariant();
327  }
328  else if ( role == QgsBrowserModel::ProviderKeyRole )
329  {
330  return item->providerKey();
331  }
332  else
333  {
334  // unsupported role
335  return QVariant();
336  }
337 }
338 
339 bool QgsBrowserModel::setData( const QModelIndex &index, const QVariant &value, int role )
340 {
341  if ( !index.isValid() )
342  return false;
343 
344 
345  QgsDataItem *item = dataItem( index );
346  if ( !item )
347  {
348  return false;
349  }
350 
353  return false;
354 
355  switch ( role )
356  {
357  case Qt::EditRole:
358  {
360  return item->rename( value.toString() );
362  }
363  }
364  return false;
365 }
366 
367 QVariant QgsBrowserModel::headerData( int section, Qt::Orientation orientation, int role ) const
368 {
369  Q_UNUSED( section )
370  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
371  {
372  return QVariant( "header" );
373  }
374 
375  return QVariant();
376 }
377 
378 int QgsBrowserModel::rowCount( const QModelIndex &parent ) const
379 {
380  //QgsDebugMsg(QString("isValid = %1 row = %2 column = %3").arg(parent.isValid()).arg(parent.row()).arg(parent.column()));
381 
382  if ( !parent.isValid() )
383  {
384  // root item: its children are top level items
385  return mRootItems.count(); // mRoot
386  }
387  else
388  {
389  // ordinary item: number of its children
390  QgsDataItem *item = dataItem( parent );
391  //if ( item ) QgsDebugMsg(QString("path = %1 rowCount = %2").arg(item->path()).arg(item->rowCount()) );
392  return item ? item->rowCount() : 0;
393  }
394 }
395 
396 bool QgsBrowserModel::hasChildren( const QModelIndex &parent ) const
397 {
398  if ( !parent.isValid() )
399  return !mRootItems.isEmpty(); // root item: its children are top level items
400 
401  QgsDataItem *item = dataItem( parent );
402  return item && item->hasChildren();
403 }
404 
405 int QgsBrowserModel::columnCount( const QModelIndex &parent ) const
406 {
407  Q_UNUSED( parent )
408  return 1;
409 }
410 
411 QModelIndex QgsBrowserModel::findPath( const QString &path, Qt::MatchFlag matchFlag )
412 {
413  return findPath( this, path, matchFlag );
414 }
415 
416 QModelIndex QgsBrowserModel::findPath( QAbstractItemModel *model, const QString &path, Qt::MatchFlag matchFlag )
417 {
418  if ( !model )
419  return QModelIndex();
420 
421  QModelIndex index; // starting from root
422  bool foundChild = true;
423 
424  while ( foundChild )
425  {
426  foundChild = false; // assume that the next child item will not be found
427 
428  for ( int i = 0; i < model->rowCount( index ); i++ )
429  {
430  QModelIndex idx = model->index( i, 0, index );
431 
432  QString itemPath = model->data( idx, PathRole ).toString();
433  if ( itemPath == path )
434  {
435  QgsDebugMsgLevel( "Arrived " + itemPath, 4 );
436  return idx; // we have found the item we have been looking for
437  }
438 
439  // paths are slash separated identifier
440  if ( path.startsWith( itemPath + '/' ) )
441  {
442  foundChild = true;
443  index = idx;
444  break;
445  }
446  }
447  }
448 
449  if ( matchFlag == Qt::MatchStartsWith )
450  return index;
451 
452  QgsDebugMsgLevel( QStringLiteral( "path not found" ), 4 );
453  return QModelIndex(); // not found
454 }
455 
456 QModelIndex QgsBrowserModel::findUri( const QString &uri, QModelIndex index )
457 {
458  for ( int i = 0; i < this->rowCount( index ); i++ )
459  {
460  QModelIndex idx = this->index( i, 0, index );
461 
462  if ( qobject_cast<QgsLayerItem *>( dataItem( idx ) ) )
463  {
464  QString itemUri = qobject_cast<QgsLayerItem *>( dataItem( idx ) )->uri();
465 
466  if ( itemUri == uri )
467  {
468  QgsDebugMsgLevel( "Arrived " + itemUri, 4 );
469  return idx; // we have found the item we have been looking for
470  }
471  }
472 
473  QModelIndex childIdx = findUri( uri, idx );
474  if ( childIdx.isValid() )
475  return childIdx;
476  }
477  return QModelIndex();
478 }
479 
481 {
482  // deprecated, no use
483 }
484 
486 {
487  // TODO: put items creating currently children in threads to deleteLater (does not seem urget because reload() is not used in QGIS)
488  beginResetModel();
489  removeRootItems();
490  addRootItems();
491  endResetModel();
492 }
493 
495 {
496  const QList< QFileInfo > drives = QDir::drives();
497  // remove any removed drives
498  const QStringList existingDrives = mDriveItems.keys();
499  for ( const QString &drivePath : existingDrives )
500  {
501  bool stillExists = false;
502  for ( const QFileInfo &drive : drives )
503  {
504  if ( drivePath == drive.absolutePath() )
505  {
506  stillExists = true;
507  break;
508  }
509  }
510 
511  if ( stillExists )
512  continue;
513 
514  // drive has been removed, remove corresponding item
515  if ( QgsDirectoryItem *driveItem = mDriveItems.value( drivePath ) )
516  removeRootItem( driveItem );
517  }
518 
519  for ( const QFileInfo &drive : drives )
520  {
521  const QString path = drive.absolutePath();
522 
523  if ( QgsDirectoryItem::hiddenPath( path ) )
524  continue;
525 
526  // does an item for this drive already exist?
527  if ( !mDriveItems.contains( path ) )
528  {
529  const QString driveName = QStorageInfo( path ).displayName();
530  const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( "%1 (%2)" ).arg( path, driveName );
531 
532  QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, name, path, path, QStringLiteral( "special:Drives" ) );
533  item->setSortKey( QStringLiteral( " 3 %1" ).arg( path ) );
534 
535  mDriveItems.insert( path, item );
536  setupItemConnections( item );
537 
538  beginInsertRows( QModelIndex(), mRootItems.count(), mRootItems.count() );
539  mRootItems << item;
540  endInsertRows();
541  }
542  }
543 }
544 
545 QModelIndex QgsBrowserModel::index( int row, int column, const QModelIndex &parent ) const
546 {
547  if ( column < 0 || column >= columnCount() || row < 0 )
548  return QModelIndex();
549 
550  QgsDataItem *p = dataItem( parent );
551  const QVector<QgsDataItem *> &items = p ? p->children() : mRootItems;
552  QgsDataItem *item = items.value( row, nullptr );
553  return item ? createIndex( row, column, item ) : QModelIndex();
554 }
555 
556 QModelIndex QgsBrowserModel::parent( const QModelIndex &index ) const
557 {
558  QgsDataItem *item = dataItem( index );
559  if ( !item )
560  return QModelIndex();
561 
562  return findItem( item->parent() );
563 }
564 
565 QModelIndex QgsBrowserModel::findItem( QgsDataItem *item, QgsDataItem *parent ) const
566 {
567  const QVector<QgsDataItem *> &items = parent ? parent->children() : mRootItems;
568 
569  for ( int i = 0; i < items.size(); i++ )
570  {
571  if ( items[i] == item )
572  return createIndex( i, 0, item );
573 
574  QModelIndex childIndex = findItem( item, items[i] );
575  if ( childIndex.isValid() )
576  return childIndex;
577  }
578  return QModelIndex();
579 }
580 
581 void QgsBrowserModel::beginInsertItems( QgsDataItem *parent, int first, int last )
582 {
583  QgsDebugMsgLevel( "parent mPath = " + parent->path(), 3 );
584  QModelIndex idx = findItem( parent );
585  if ( !idx.isValid() )
586  return;
587  QgsDebugMsgLevel( QStringLiteral( "valid" ), 3 );
588  beginInsertRows( idx, first, last );
589  QgsDebugMsgLevel( QStringLiteral( "end" ), 3 );
590 }
592 {
593  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 3 );
594  endInsertRows();
595 }
596 void QgsBrowserModel::beginRemoveItems( QgsDataItem *parent, int first, int last )
597 {
598  QgsDebugMsgLevel( "parent mPath = " + parent->path(), 3 );
599  QModelIndex idx = findItem( parent );
600  if ( !idx.isValid() )
601  return;
602  beginRemoveRows( idx, first, last );
603 }
605 {
606  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 3 );
607  endRemoveRows();
608 }
610 {
611  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 3 );
612  QModelIndex idx = findItem( item );
613  if ( !idx.isValid() )
614  return;
615  emit dataChanged( idx, idx );
616 }
618 {
619  if ( !item )
620  return;
621  QModelIndex idx = findItem( item );
622  if ( !idx.isValid() )
623  return;
624  QgsDebugMsgLevel( QStringLiteral( "item %1 state changed %2 -> %3" ).arg( item->path() ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( oldState ) ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( item->state() ) ), 4 );
625  emit stateChanged( idx, oldState );
626 }
627 
628 void QgsBrowserModel::setupItemConnections( QgsDataItem *item )
629 {
630  connect( item, &QgsDataItem::beginInsertItems,
632  connect( item, &QgsDataItem::endInsertItems,
634  connect( item, &QgsDataItem::beginRemoveItems,
636  connect( item, &QgsDataItem::endRemoveItems,
638  connect( item, &QgsDataItem::dataChanged,
640  connect( item, &QgsDataItem::stateChanged,
642 
643  // if it's a collection item, also forwards connectionsChanged
644  QgsDataCollectionItem *collectionItem = qobject_cast<QgsDataCollectionItem *>( item );
645  if ( collectionItem )
646  connect( collectionItem, &QgsDataCollectionItem::connectionsChanged, this, &QgsBrowserModel::onConnectionsChanged );
647 }
648 
649 QStringList QgsBrowserModel::mimeTypes() const
650 {
651  QStringList types;
652  // In theory the mime type convention is: application/x-vnd.<vendor>.<application>.<type>
653  // but it seems a bit over formalized. Would be an application/x-qgis-uri better?
654  types << QStringLiteral( "application/x-vnd.qgis.qgis.uri" );
655  return types;
656 }
657 
658 QMimeData *QgsBrowserModel::mimeData( const QModelIndexList &indexes ) const
659 {
661  const auto constIndexes = indexes;
662  for ( const QModelIndex &index : constIndexes )
663  {
664  if ( index.isValid() )
665  {
666  QgsDataItem *ptr = reinterpret_cast< QgsDataItem * >( index.internalPointer() );
667  const QgsMimeDataUtils::UriList uris = ptr->mimeUris();
668  for ( QgsMimeDataUtils::Uri uri : std::as_const( uris ) )
669  {
671  {
672  uri.filePath = ptr->path();
673  }
674  lst.append( uri );
675  }
676  }
677  }
678  return QgsMimeDataUtils::encodeUriList( lst );
679 }
680 
681 bool QgsBrowserModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int, int, const QModelIndex &parent )
682 {
683  QgsDataItem *destItem = dataItem( parent );
684  if ( !destItem )
685  {
686  QgsDebugMsgLevel( QStringLiteral( "DROP PROBLEM!" ), 4 );
687  return false;
688  }
689 
691  return destItem->handleDrop( data, action );
693 }
694 
695 QgsDataItem *QgsBrowserModel::dataItem( const QModelIndex &idx ) const
696 {
697  void *v = idx.internalPointer();
698  QgsDataItem *d = reinterpret_cast<QgsDataItem *>( v );
699  Q_ASSERT( !v || d );
700  return d;
701 }
702 
703 bool QgsBrowserModel::canFetchMore( const QModelIndex &parent ) const
704 {
705  QgsDataItem *item = dataItem( parent );
706  // if ( item )
707  // QgsDebugMsg( QStringLiteral( "path = %1 canFetchMore = %2" ).arg( item->path() ).arg( item && ! item->isPopulated() ) );
708  return ( item && item->state() == Qgis::BrowserItemState::NotPopulated );
709 }
710 
711 void QgsBrowserModel::fetchMore( const QModelIndex &parent )
712 {
713  QgsDataItem *item = dataItem( parent );
714 
716  return;
717 
718  QgsDebugMsgLevel( "path = " + item->path(), 4 );
719 
720  item->populate();
721 }
722 
723 /* Refresh dir path */
724 void QgsBrowserModel::refresh( const QString &path )
725 {
726  QModelIndex index = findPath( path );
727  refresh( index );
728 }
729 
730 /* Refresh item */
731 void QgsBrowserModel::refresh( const QModelIndex &index )
732 {
733  QgsDataItem *item = dataItem( index );
734  if ( !item || item->state() == Qgis::BrowserItemState::Populating )
735  return;
736 
737  QgsDebugMsgLevel( "Refresh " + item->path(), 4 );
738 
739  item->refresh();
740 }
741 
742 void QgsBrowserModel::addFavoriteDirectory( const QString &directory, const QString &name )
743 {
744  Q_ASSERT( mFavorites );
745  mFavorites->addDirectory( directory, name );
746 }
747 
748 void QgsBrowserModel::removeFavorite( const QModelIndex &index )
749 {
750  QgsDirectoryItem *item = qobject_cast<QgsDirectoryItem *>( dataItem( index ) );
751  if ( !item )
752  return;
753 
754  mFavorites->removeDirectory( item );
755 }
756 
758 {
759  if ( !favorite )
760  return;
761 
762  mFavorites->removeDirectory( favorite );
763 }
764 
766 {
767  QgsSettings settings;
768  QStringList hiddenItems = settings.value( QStringLiteral( "browser/hiddenPaths" ),
769  QStringList() ).toStringList();
770  int idx = hiddenItems.indexOf( item->path() );
771  if ( idx != -1 )
772  {
773  hiddenItems.removeAt( idx );
774  }
775  else
776  {
777  hiddenItems << item->path();
778  }
779  settings.setValue( QStringLiteral( "browser/hiddenPaths" ), hiddenItems );
780  if ( item->parent() )
781  {
782  item->parent()->deleteChildItem( item );
783  }
784  else
785  {
786  removeRootItem( item );
787  }
788 }
789 
790 
791 void QgsBrowserModel::removeRootItem( QgsDataItem *item )
792 {
793  int i = mRootItems.indexOf( item );
794  beginRemoveRows( QModelIndex(), i, i );
795  mRootItems.remove( i );
796  QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem * >( item );
797  if ( !mDriveItems.key( dirItem ).isEmpty() )
798  {
799  mDriveItems.remove( mDriveItems.key( dirItem ) );
800  }
801  item->deleteLater();
802  endRemoveRows();
803 }
804 
805 QgsDataItem *QgsBrowserModel::addProviderRootItem( QgsDataItemProvider *pr )
806 {
807  int capabilities = pr->capabilities();
808  if ( capabilities == QgsDataProvider::NoDataCapabilities )
809  {
810  QgsDebugMsgLevel( pr->name() + " does not have any dataCapabilities", 4 );
811  return nullptr;
812  }
813 
814  QgsDataItem *item = pr->createDataItem( QString(), nullptr ); // empty path -> top level
815  if ( item )
816  {
817  // make sure the top level key is always set
818  item->setProviderKey( pr->name() );
819  // Forward the signal from the root items to the model (and then to the app)
820  connect( item, &QgsDataItem::connectionsChanged, this, &QgsBrowserModel::onConnectionsChanged );
821  QgsDebugMsgLevel( "Add new top level item : " + item->name(), 4 );
822  setupItemConnections( item );
823  }
824  return item;
825 }
826 
827 // For QgsBrowserWatcher
828 #include "qgsbrowsermodel.moc"
QgsBrowserModel::columnCount
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowsermodel.cpp:405
QgsBrowserModel::findUri
QModelIndex findUri(const QString &uri, QModelIndex index=QModelIndex())
Returns index of layer item with given uri.
Definition: qgsbrowsermodel.cpp:456
QgsBrowserModel::addRootItems
void addRootItems()
Populates the model.
Definition: qgsbrowsermodel.cpp:113
QgsDataItemProvider::capabilities
virtual int capabilities() const =0
Returns combination of flags from QgsDataProvider::DataCapabilities.
QgsDataItemProviderRegistry::providerAdded
void providerAdded(QgsDataItemProvider *provider)
Emitted when a new data item provider has been added.
QgsDataItem::icon
virtual QIcon icon()
Definition: qgsdataitem.cpp:162
QgsBrowserModel::refresh
void refresh(const QString &path)
Refresh item specified by path.
Definition: qgsbrowsermodel.cpp:724
QgsBrowserModel::connectionsChanged
void connectionsChanged(const QString &providerKey)
Emitted when connections for the specified providerKey have changed in the browser.
QgsDataItem::rowCount
int rowCount()
Definition: qgsdataitem.cpp:393
QgsBrowserModel::reload
void reload()
Reload the whole model.
Definition: qgsbrowsermodel.cpp:485
QgsDataCollectionItem
A Collection: logical collection of layers or subcollections, e.g. GRASS location/mapset,...
Definition: qgsdatacollectionitem.h:28
QgsBrowserModel::beginRemoveItems
void beginRemoveItems(QgsDataItem *parent, int first, int last)
Definition: qgsbrowsermodel.cpp:596
QgsBrowserModel::initialize
void initialize()
Delayed initialization, needed because the provider registry must be already populated.
Definition: qgsbrowsermodel.cpp:249
QgsBrowserModel::parent
QModelIndex parent(const QModelIndex &index) const override
Definition: qgsbrowsermodel.cpp:556
qgsdirectoryitem.h
QgsDataItem::path
QString path() const
Definition: qgsdataitem.h:354
qgsdataitemproviderregistry.h
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsDirectoryItem::hiddenPath
static bool hiddenPath(const QString &path)
Check if the given path is hidden from the browser model.
Definition: qgsdirectoryitem.cpp:412
QgsBrowserModel::ProviderKeyRole
@ ProviderKeyRole
Data item provider key that created the item, see QgsDataItem::providerKey()
Definition: qgsbrowsermodel.h:74
Qgis::BrowserItemState::NotPopulated
@ NotPopulated
Children not yet created.
QgsBrowserModel::dropMimeData
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
Definition: qgsbrowsermodel.cpp:681
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
Qgis::BrowserItemState
BrowserItemState
Browser item states.
Definition: qgis.h:367
QgsDataItem::sortKey
virtual QVariant sortKey() const
Returns the sorting key for the item.
Definition: qgsdataitem.cpp:96
QgsBrowserModel::endInsertItems
void endInsertItems()
Definition: qgsbrowsermodel.cpp:591
QgsBrowserModel::stateChanged
void stateChanged(const QModelIndex &index, Qgis::BrowserItemState oldState)
Emitted when item children fetch was finished.
QgsDataItem::refresh
virtual void refresh(const QVector< QgsDataItem * > &children)
Refresh the items from a specified list of child items.
Definition: qgsdataitem.cpp:331
QgsDataItem::state
Qgis::BrowserItemState state() const
Definition: qgsdataitem.cpp:552
QgsFavoritesItem::removeDirectory
void removeDirectory(QgsDirectoryItem *item)
Removes an existing directory from the favorites group.
Definition: qgsfavoritesitem.cpp:85
QgsBrowserModel::itemDataChanged
void itemDataChanged(QgsDataItem *item)
Definition: qgsbrowsermodel.cpp:609
QgsProject::homePath
QString homePath
Definition: qgsproject.h:108
QgsDataItem::setProviderKey
void setProviderKey(const QString &value)
Sets the provider key that created this item (e.g.
Definition: qgsdataitem.cpp:388
qgis.h
QgsBrowserModel::SortRole
@ SortRole
Custom sort role, see QgsDataItem::sortKey()
Definition: qgsbrowsermodel.h:73
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsBrowserModel::mRootItems
QVector< QgsDataItem * > mRootItems
Definition: qgsbrowsermodel.h:237
QgsProjectHomeItem
A directory item showing the current project directory.
Definition: qgsdirectoryitem.h:254
Qgis::BrowserItemType::Layer
@ Layer
Represents a map layer.
QgsBrowserModel::itemStateChanged
void itemStateChanged(QgsDataItem *item, Qgis::BrowserItemState oldState)
Emitted when an item's state is changed.
Definition: qgsbrowsermodel.cpp:617
QgsBrowserModel::hasChildren
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowsermodel.cpp:396
QgsDataItem::name
QString name() const
Returns the name of the item (the displayed text for the item).
Definition: qgsdataitem.h:345
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsDataItem::dataChanged
void dataChanged(QgsDataItem *item)
QgsDataItem::deleteLater
static void deleteLater(QVector< QgsDataItem * > &items)
Definition: qgsdataitem.cpp:130
QgsDataItem::toolTip
QString toolTip() const
Definition: qgsdataitem.h:407
QgsDataItemProvider::createDataItem
virtual QgsDataItem * createDataItem(const QString &path, QgsDataItem *parentItem)=0
Create a new instance of QgsDataItem (or nullptr) for given path and parent item.
qgsmimedatautils.h
QgsMimeDataUtils::UriList
QList< QgsMimeDataUtils::Uri > UriList
Definition: qgsmimedatautils.h:164
QgsBrowserModel::CommentRole
@ CommentRole
Item comment.
Definition: qgsbrowsermodel.h:72
QgsDataItem::beginRemoveItems
void beginRemoveItems(QgsDataItem *parent, int first, int last)
QgsProject::homePathChanged
void homePathChanged()
Emitted when the home path of the project changes.
QgsBrowserModel::findPath
QModelIndex findPath(const QString &path, Qt::MatchFlag matchFlag=Qt::MatchExactly)
Returns index of item with given path.
Definition: qgsbrowsermodel.cpp:411
QgsFavoritesItem::addDirectory
void addDirectory(const QString &directory, const QString &name=QString())
Adds a new directory to the favorites group.
Definition: qgsfavoritesitem.cpp:66
QgsBrowserModel::removeRootItems
void removeRootItems()
Definition: qgsbrowsermodel.cpp:190
QgsBrowserModel::mProjectHome
QgsDirectoryItem * mProjectHome
Definition: qgsbrowsermodel.h:239
QgsDataItemProvider::name
virtual QString name()=0
Human-readable name of the provider name.
qgsapplication.h
PROJECT_HOME_PREFIX
#define PROJECT_HOME_PREFIX
Definition: qgsbrowsermodel.cpp:40
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2820
qgslayeritem.h
QgsDataItem::endRemoveItems
void endRemoveItems()
QgsBrowserModel::driveItems
QMap< QString, QgsDirectoryItem * > driveItems() const
Returns a map of the root drive items shown in the browser.
Definition: qgsbrowsermodel.cpp:243
QgsBrowserModel::updateProjectHome
void updateProjectHome()
Definition: qgsbrowsermodel.cpp:86
Qgis::BrowserItemCapability::ItemRepresentsFile
@ ItemRepresentsFile
Item's path() directly represents a file on disk (since QGIS 3.22)
QgsDataItem::rename
virtual Q_DECL_DEPRECATED bool rename(const QString &name)
Sets a new name for the item, and returns true if the item was successfully renamed.
Definition: qgsdataitem.cpp:542
QgsBrowserModel::removeFavorite
void removeFavorite(const QModelIndex &index)
Removes a favorite directory from its corresponding model index.
Definition: qgsbrowsermodel.cpp:748
QgsBrowserModel::headerData
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Definition: qgsbrowsermodel.cpp:367
qgsproviderregistry.h
QgsDirectoryItem
A directory: contains subdirectories and layers.
Definition: qgsdirectoryitem.h:33
HOME_PREFIX
#define HOME_PREFIX
Definition: qgsbrowsermodel.cpp:41
QgsBrowserModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: qgsbrowsermodel.cpp:289
QgsDataItem::parent
QgsDataItem * parent() const
Gets item parent.
Definition: qgsdataitem.h:330
QgsDataItemProviderRegistry::providers
QList< QgsDataItemProvider * > providers() const
Returns the list of available providers.
Definition: qgsdataitemproviderregistry.cpp:51
QgsDataItemProvider
This is the interface for those who want to add custom data items to the browser tree.
Definition: qgsdataitemprovider.h:44
QgsBrowserModel::connectItem
Q_DECL_DEPRECATED void connectItem(QgsDataItem *item)
Definition: qgsbrowsermodel.cpp:480
Qgis::BrowserItemState::Populated
@ Populated
Children created.
QgsApplication::dataItemProviderRegistry
static QgsDataItemProviderRegistry * dataItemProviderRegistry()
Returns the application's data item provider registry, which keeps a list of data item providers that...
Definition: qgsapplication.cpp:2335
QgsBrowserModel::endRemoveItems
void endRemoveItems()
Definition: qgsbrowsermodel.cpp:604
QgsDataItem::acceptDrop
virtual Q_DECL_DEPRECATED bool acceptDrop()
Returns whether the item accepts drag and dropped layers - e.g.
Definition: qgsdataitem.h:218
qgsfavoritesitem.h
QgsBrowserModel::mFavorites
QgsFavoritesItem * mFavorites
Definition: qgsbrowsermodel.h:238
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:279
QgsDataItem::hasDragEnabled
virtual bool hasDragEnabled() const
Returns true if the item may be dragged.
Definition: qgsdataitem.h:253
QgsBrowserModel::PathRole
@ PathRole
Item path used to access path in the tree, see QgsDataItem::mPath.
Definition: qgsbrowsermodel.h:71
QgsMimeDataUtils::Uri
Definition: qgsmimedatautils.h:40
QgsBrowserModel::hidePath
void hidePath(QgsDataItem *item)
Hide the given path in the browser model.
Definition: qgsbrowsermodel.cpp:765
QgsDataItem::connectionsChanged
void connectionsChanged(const QString &providerKey=QString())
Emitted when the connections of the provider with the specified providerKey have changed.
QgsDataItem::stateChanged
void stateChanged(QgsDataItem *item, Qgis::BrowserItemState oldState)
Emitted when an item's state is changed.
QgsDataItem::endInsertItems
void endInsertItems()
QgsBrowserModel::beginInsertItems
void beginInsertItems(QgsDataItem *parent, int first, int last)
Definition: qgsbrowsermodel.cpp:581
QgsFavoriteItem
A directory item showing the a single favorite directory.
Definition: qgsfavoritesitem.h:92
qgsbrowsermodel.h
QgsBrowserModel::QgsBrowserModel
QgsBrowserModel(QObject *parent=nullptr)
Constructor for QgsBrowserModel, with the specified parent object.
Definition: qgsbrowsermodel.cpp:71
qgsdataitemprovider.h
QgsDataItem::hasChildren
bool hasChildren()
Definition: qgsdataitem.cpp:397
QgsMimeDataUtils::encodeUriList
static QMimeData * encodeUriList(const UriList &layers)
Encodes a URI list to a new QMimeData object.
Definition: qgsmimedatautils.cpp:220
QgsBrowserModel::setData
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Definition: qgsbrowsermodel.cpp:339
QgsBrowserModel::refreshDrives
void refreshDrives()
Refreshes the list of drive items, removing any corresponding to removed drives and adding newly adde...
Definition: qgsbrowsermodel.cpp:494
QgsBrowserModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowsermodel.cpp:378
QgsDataItemProviderRegistry::providerWillBeRemoved
void providerWillBeRemoved(QgsDataItemProvider *provider)
Emitted when a data item provider is about to be removed.
QgsLayerItem::comments
virtual QString comments() const
Returns comments of the layer.
Definition: qgslayeritem.h:102
QgsBrowserModel::mimeData
QMimeData * mimeData(const QModelIndexList &indexes) const override
Definition: qgsbrowsermodel.cpp:658
QgsBrowserModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: qgsbrowsermodel.cpp:545
QgsBrowserModel::mimeTypes
QStringList mimeTypes() const override
Definition: qgsbrowsermodel.cpp:649
QgsDataItem::populate
virtual void populate(const QVector< QgsDataItem * > &children)
Definition: qgsdataitem.cpp:264
qgssettings.h
Qgis::BrowserItemState::Populating
@ Populating
Creating children in separate thread (populating or refreshing)
QgsDataProvider::NoDataCapabilities
@ NoDataCapabilities
Definition: qgsdataprovider.h:78
QgsDataItem::handleDrop
virtual Q_DECL_DEPRECATED bool handleDrop(const QMimeData *, Qt::DropAction)
Attempts to process the mime data dropped on this item.
Definition: qgsdataitem.h:233
QgsBrowserModel::addFavoriteDirectory
void addFavoriteDirectory(const QString &directory, const QString &name=QString())
Adds a directory to the favorites group.
Definition: qgsbrowsermodel.cpp:742
qgsprojectitem.h
QgsDataItem::children
QVector< QgsDataItem * > children() const
Definition: qgsdataitem.h:337
qgsdataprovider.h
QgsLayerItem
Item that represents a layer that can be opened with one of the providers.
Definition: qgslayeritem.h:29
Qgis::BrowserItemCapability::Rename
@ Rename
Item can be renamed.
QgsBrowserModel::~QgsBrowserModel
~QgsBrowserModel() override
Definition: qgsbrowsermodel.cpp:81
QgsBrowserModel::findItem
QModelIndex findItem(QgsDataItem *item, QgsDataItem *parent=nullptr) const
Returns the model index corresponding to the specified data item.
Definition: qgsbrowsermodel.cpp:565
QgsDataItem::mimeUris
virtual QgsMimeDataUtils::UriList mimeUris() const
Returns mime URIs for the data item, most data providers will only return a single URI but some data ...
Definition: qgsdataitem.cpp:523
QgsDataItem::capabilities2
virtual Qgis::BrowserItemCapabilities capabilities2() const
Returns the capabilities for the data item.
Definition: qgsdataitem.h:303
qgslogger.h
QgsDataItem::providerKey
QString providerKey() const
Returns the provider key that created this item (e.g.
Definition: qgsdataitem.cpp:383
QgsFavoritesItem
Contains various Favorites directories.
Definition: qgsfavoritesitem.h:32
QgsDataItem
Base class for all items in the model.
Definition: qgsdataitem.h:45
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2819
QgsDataItem::deleteChildItem
virtual void deleteChildItem(QgsDataItem *child)
Removes and deletes a child item, emitting relevant signals to the model.
Definition: qgsdataitem.cpp:461
QgsBrowserModel::dataItem
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index.
Definition: qgsbrowsermodel.cpp:695
QgsDataItem::setSortKey
void setSortKey(const QVariant &key)
Sets a custom sorting key for the item.
Definition: qgsdataitem.cpp:101
QgsBrowserModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: qgsbrowsermodel.cpp:259
QgsDataItem::type
Qgis::BrowserItemType type() const
Definition: qgsdataitem.h:324
QgsBrowserModel::fetchMore
void fetchMore(const QModelIndex &parent) override
Definition: qgsbrowsermodel.cpp:711
qgsproject.h
QgsBrowserModel::canFetchMore
bool canFetchMore(const QModelIndex &parent) const override
Definition: qgsbrowsermodel.cpp:703
QgsDataItem::beginInsertItems
void beginInsertItems(QgsDataItem *parent, int first, int last)