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