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