16#include <QApplication> 
   18#include <QtConcurrentMap> 
   20#include <QStorageInfo> 
   22#include <QFutureWatcher> 
   38#define PROJECT_HOME_PREFIX "project:" 
   39#define HOME_PREFIX "home:" 
   42class QgsBrowserWatcher : 
public QFutureWatcher<QVector <QgsDataItem *> >
 
   48      : QFutureWatcher( 
nullptr )
 
   56    void finished( 
QgsDataItem *item, 
const QVector <QgsDataItem *> &items );
 
   66  return QString::localeAwareCompare( a->
name(), b->
name() ) < 0;
 
   70  : QAbstractItemModel( parent )
 
   74           this, &QgsBrowserModel::dataItemProviderAdded );
 
   76           this, &QgsBrowserModel::dataItemProviderWillBeRemoved );
 
 
   95    beginRemoveRows( QModelIndex(), idx, idx );
 
  105    beginInsertRows( QModelIndex(), 0, 0 );
 
 
  118      QStringLiteral( 
"special:Home" ) );
 
  120  setupItemConnections( item );
 
  132  const auto drives { QDir::drives() };
 
  133  for ( 
const QFileInfo &drive : drives )
 
  135    const QString path = drive.absolutePath();
 
  140    const QString driveName = QStorageInfo( path ).displayName();
 
  141    const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( 
"%1 (%2)" ).arg( path, driveName );
 
  144    item->
setSortKey( QStringLiteral( 
" 3 %1" ).arg( path ) );
 
  145    mDriveItems.insert( path, item );
 
  147    setupItemConnections( item );
 
  152  QString path = QString( 
"/Volumes" );
 
  154  setupItemConnections( vols );
 
  159  QMultiMap<int, QgsDataItem *> providerMap;
 
  164    if ( 
QgsDataItem *item = addProviderRootItem( pr ) )
 
  166      providerMap.insert( pr->capabilities(), item );
 
  171  const auto constUniqueKeys = providerMap.uniqueKeys();
 
  172  for ( 
int key : constUniqueKeys )
 
  174    QList<QgsDataItem *> providerGroup = providerMap.values( key );
 
  175    if ( providerGroup.size() > 1 )
 
  177      std::sort( providerGroup.begin(), providerGroup.end(), cmpByDataItemName_ );
 
  180    const auto constProviderGroup = providerGroup;
 
 
  205  if ( 
QgsDataItem *item = addProviderRootItem( provider ) )
 
  218    if ( item->providerKey() == provider->
name() )
 
  220      removeRootItem( item );
 
  226void QgsBrowserModel::onConnectionsChanged( 
const QString &providerKey )
 
  231    if ( item->providerKey() == providerKey )
 
  249  if ( ! mInitialized )
 
 
  259  if ( !
index.isValid() )
 
  260    return Qt::ItemFlags();
 
  262  Qt::ItemFlags 
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 
  269    return Qt::ItemFlags();
 
  273    flags |= Qt::ItemIsDragEnabled;
 
  277    flags |= Qt::ItemIsDropEnabled;
 
  282    flags |= Qt::ItemIsEditable;
 
 
  289  if ( !
index.isValid() )
 
  297  else if ( role == Qt::DisplayRole || role == Qt::EditRole )
 
  305  else if ( role == Qt::ToolTipRole )
 
  309  else if ( role == Qt::DecorationRole && 
index.column() == 0 )
 
  321      QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
 
  330      QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
 
 
  348  if ( !
index.isValid() )
 
  367      return item->
rename( value.toString() );
 
 
  377  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
 
  379    return QVariant( 
"header" );
 
 
  420  return findPath( 
this, path, matchFlag );
 
 
  426    return QModelIndex();
 
  429  bool foundChild = 
true;
 
  435    for ( 
int i = 0; i < model->rowCount( 
index ); i++ )
 
  437      QModelIndex idx = model->index( i, 0, 
index );
 
  440      if ( itemPath == path )
 
  447      if ( path.startsWith( itemPath + 
'/' ) )
 
  456  if ( matchFlag == Qt::MatchStartsWith )
 
  460  return QModelIndex(); 
 
 
  465  for ( 
int i = 0; i < this->
rowCount( index ); i++ )
 
  469    if ( qobject_cast<QgsLayerItem *>( 
dataItem( idx ) ) )
 
  471      QString itemUri = qobject_cast<QgsLayerItem *>( 
dataItem( idx ) )->uri();
 
  473      if ( itemUri == uri )
 
  480    QModelIndex childIdx = 
findUri( uri, idx );
 
  481    if ( childIdx.isValid() )
 
  484  return QModelIndex();
 
 
  503  const QList< QFileInfo > drives = QDir::drives();
 
  505  const QStringList existingDrives = mDriveItems.keys();
 
  506  for ( 
const QString &drivePath : existingDrives )
 
  508    bool stillExists = 
false;
 
  509    for ( 
const QFileInfo &drive : drives )
 
  511      if ( drivePath == drive.absolutePath() )
 
  523      removeRootItem( driveItem );
 
  526  for ( 
const QFileInfo &drive : drives )
 
  528    const QString path = drive.absolutePath();
 
  534    if ( !mDriveItems.contains( path ) )
 
  536      const QString driveName = QStorageInfo( path ).displayName();
 
  537      const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( 
"%1 (%2)" ).arg( path, driveName );
 
  540      item->
setSortKey( QStringLiteral( 
" 3 %1" ).arg( path ) );
 
  542      mDriveItems.insert( path, item );
 
  543      setupItemConnections( item );
 
 
  554  if ( column < 0 || column >= 
columnCount() || row < 0 )
 
  555    return QModelIndex();
 
  560  return item ? createIndex( row, column, item ) : QModelIndex();
 
 
  567    return QModelIndex();
 
 
  576  for ( 
int i = 0; i < items.size(); i++ )
 
  578    if ( items[i] == item )
 
  579      return createIndex( i, 0, item );
 
  581    QModelIndex childIndex = 
findItem( item, items[i] );
 
  582    if ( childIndex.isValid() )
 
  585  return QModelIndex();
 
 
  592  if ( !idx.isValid() )
 
  595  beginInsertRows( idx, first, last );
 
 
  607  if ( !idx.isValid() )
 
  609  beginRemoveRows( idx, first, last );
 
 
  620  if ( !idx.isValid() )
 
  622  emit dataChanged( idx, idx );
 
 
  629  if ( !idx.isValid() )
 
  631  QgsDebugMsgLevel( QStringLiteral( 
"item %1 state changed %2 -> %3" ).arg( item->
path() ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( oldState ) ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( item->
state() ) ), 4 );
 
 
  635void QgsBrowserModel::setupItemConnections( 
QgsDataItem *item )
 
  652  if ( collectionItem )
 
  661  types << QStringLiteral( 
"application/x-vnd.qgis.qgis.uri" );
 
 
  668  const auto constIndexes = indexes;
 
  669  for ( 
const QModelIndex &
index : constIndexes )
 
  671    if ( 
index.isValid() )
 
  675      if ( uris.isEmpty() )
 
 
  714  void *v = idx.internalPointer();
 
 
  785  QStringList hiddenItems = settings.
value( QStringLiteral( 
"browser/hiddenPaths" ),
 
  786                            QStringList() ).toStringList();
 
  787  int idx = hiddenItems.indexOf( item->
path() );
 
  790    hiddenItems.removeAt( idx );
 
  794    hiddenItems << item->
path();
 
  796  settings.
setValue( QStringLiteral( 
"browser/hiddenPaths" ), hiddenItems );
 
  803    removeRootItem( item );
 
 
  808void QgsBrowserModel::removeRootItem( 
QgsDataItem *item )
 
  811  beginRemoveRows( QModelIndex(), i, i );
 
  814  if ( !mDriveItems.key( dirItem ).isEmpty() )
 
  816    mDriveItems.remove( mDriveItems.key( dirItem ) );
 
  824  const Qgis::DataItemProviderCapabilities capabilities = pr->
capabilities();
 
  839    setupItemConnections( item );
 
  845#include "qgsbrowsermodel.moc" 
@ NoCapabilities
No capabilities.
BrowserItemState
Browser item states.
@ NotPopulated
Children not yet created.
@ Populating
Creating children in separate thread (populating or refreshing)
@ Populated
Children created.
@ Rename
Item can be renamed.
@ ItemRepresentsFile
Item's path() directly represents a file on disk (since QGIS 3.22)
@ 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.
@ Sort
Custom sort role, see QgsDataItem::sortKey()
@ Path
Item path used to access path in the tree, see QgsDataItem::mPath.
@ ProviderKey
Data item provider key that created the item, see QgsDataItem::providerKey()
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
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 QString name()=0
Human-readable name of the provider name.
virtual QgsDataItem * createDataItem(const QString &path, QgsDataItem *parentItem)=0
Create a new instance of QgsDataItem (or nullptr) for given path and parent item.
virtual Qgis::DataItemProviderCapabilities capabilities() const =0
Returns combination of flags from QgsDataProvider::DataCapabilities.
Base class for all items in the model.
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.
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.
virtual Q_DECL_DEPRECATED bool handleDrop(const QMimeData *, Qt::DropAction)
Attempts to process the mime data dropped on this item.
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)
QVector< QgsDataItem * > children() const
void beginRemoveItems(QgsDataItem *parent, int first, int last)
virtual Q_DECL_DEPRECATED bool acceptDrop()
Returns whether the item accepts drag and dropped layers - e.g.
Qgis::BrowserItemType type() const
Qgis::BrowserItemState state() const
virtual bool hasDragEnabled() const
Returns true if the item may be dragged.
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.
virtual Q_DECL_DEPRECATED QgsMimeDataUtils::Uri mimeUri() const
Returns mime URI for the data item.
QString name() const
Returns the name of the item (the displayed text for the item).
void beginInsertItems(QgsDataItem *parent, int first, int last)
QgsDataItem * parent() const
Gets item parent.
virtual QgsMimeDataUtils::UriList mimeUris() const
Returns mime URIs for the data item, most data providers will only return a single URI but some data ...
QString providerKey() const
Returns the provider key that created this item (e.g.
virtual Qgis::BrowserItemCapabilities capabilities2() const
Returns the capabilities for the data item.
void setProviderKey(const QString &value)
Sets the provider key that created this item (e.g.
virtual void populate(const QVector< QgsDataItem * > &children)
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.
virtual QString comments() const
Returns comments of the layer.
const QgsLayerMetadata & layerMetadata() const
Returns layer's metadata, it may be a default constructed metadata if metadata is not explicitly set.
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.
void homePathChanged()
Emitted when the home path of the project changes.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
#define PROJECT_HOME_PREFIX
#define QgsDebugMsgLevel(str, level)
QString filePath
Path to file, if uri is associated with a file.