16#include <QApplication> 
   18#include <QtConcurrentMap> 
   20#include <QStorageInfo> 
   22#include <QFutureWatcher> 
   41#define PROJECT_HOME_PREFIX "project:" 
   42#define HOME_PREFIX "home:" 
   45class QgsBrowserWatcher : 
public QFutureWatcher<QVector <QgsDataItem *> >
 
   51      : QFutureWatcher( 
nullptr )
 
   59    void finished( 
QgsDataItem *item, 
const QVector <QgsDataItem *> &items );
 
   69  return QString::localeAwareCompare( a->
name(), b->
name() ) < 0;
 
   73  : QAbstractItemModel( parent )
 
   77           this, &QgsBrowserModel::dataItemProviderAdded );
 
   79           this, &QgsBrowserModel::dataItemProviderWillBeRemoved );
 
   98    beginRemoveRows( QModelIndex(), idx, idx );
 
  108    beginInsertRows( QModelIndex(), 0, 0 );
 
  121      QStringLiteral( 
"special:Home" ) );
 
  123  setupItemConnections( item );
 
  135  const auto drives { QDir::drives() };
 
  136  for ( 
const QFileInfo &drive : drives )
 
  138    const QString path = drive.absolutePath();
 
  143    const QString driveName = QStorageInfo( path ).displayName();
 
  144    const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( 
"%1 (%2)" ).arg( path, driveName );
 
  147    item->
setSortKey( QStringLiteral( 
" 3 %1" ).arg( path ) );
 
  148    mDriveItems.insert( path, item );
 
  150    setupItemConnections( item );
 
  155  QString path = QString( 
"/Volumes" );
 
  157  setupItemConnections( vols );
 
  162  QMultiMap<int, QgsDataItem *> providerMap;
 
  167    if ( 
QgsDataItem *item = addProviderRootItem( pr ) )
 
  169      providerMap.insert( pr->capabilities(), item );
 
  174  const auto constUniqueKeys = providerMap.uniqueKeys();
 
  175  for ( 
int key : constUniqueKeys )
 
  177    QList<QgsDataItem *> providerGroup = providerMap.values( key );
 
  178    if ( providerGroup.size() > 1 )
 
  180      std::sort( providerGroup.begin(), providerGroup.end(), cmpByDataItemName_ );
 
  183    const auto constProviderGroup = providerGroup;
 
  208  if ( 
QgsDataItem *item = addProviderRootItem( provider ) )
 
  221    if ( item->providerKey() == provider->
name() )
 
  223      removeRootItem( item );
 
  229void QgsBrowserModel::onConnectionsChanged( 
const QString &providerKey )
 
  234    if ( item->providerKey() == providerKey )
 
  252  if ( ! mInitialized )
 
  262  if ( !
index.isValid() )
 
  263    return Qt::ItemFlags();
 
  265  Qt::ItemFlags 
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 
  272    return Qt::ItemFlags();
 
  276    flags |= Qt::ItemIsDragEnabled;
 
  280    flags |= Qt::ItemIsDropEnabled;
 
  285    flags |= Qt::ItemIsEditable;
 
  292  if ( !
index.isValid() )
 
  300  else if ( role == Qt::DisplayRole || role == Qt::EditRole )
 
  308  else if ( role == Qt::ToolTipRole )
 
  312  else if ( role == Qt::DecorationRole && 
index.column() == 0 )
 
  324      QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
 
  333      QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
 
  351  if ( !
index.isValid() )
 
  370      return item->
rename( value.toString() );
 
  380  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
 
  382    return QVariant( 
"header" );
 
  423  return findPath( 
this, path, matchFlag );
 
  429    return QModelIndex();
 
  432  bool foundChild = 
true;
 
  438    for ( 
int i = 0; i < model->rowCount( 
index ); i++ )
 
  440      QModelIndex idx = model->index( i, 0, 
index );
 
  442      QString itemPath = model->data( idx, 
PathRole ).toString();
 
  443      if ( itemPath == path )
 
  450      if ( path.startsWith( itemPath + 
'/' ) )
 
  459  if ( matchFlag == Qt::MatchStartsWith )
 
  463  return QModelIndex(); 
 
  468  for ( 
int i = 0; i < this->
rowCount( index ); i++ )
 
  472    if ( qobject_cast<QgsLayerItem *>( 
dataItem( idx ) ) )
 
  474      QString itemUri = qobject_cast<QgsLayerItem *>( 
dataItem( idx ) )->uri();
 
  476      if ( itemUri == uri )
 
  483    QModelIndex childIdx = 
findUri( uri, idx );
 
  484    if ( childIdx.isValid() )
 
  487  return QModelIndex();
 
  506  const QList< QFileInfo > drives = QDir::drives();
 
  508  const QStringList existingDrives = mDriveItems.keys();
 
  509  for ( 
const QString &drivePath : existingDrives )
 
  511    bool stillExists = 
false;
 
  512    for ( 
const QFileInfo &drive : drives )
 
  514      if ( drivePath == drive.absolutePath() )
 
  526      removeRootItem( driveItem );
 
  529  for ( 
const QFileInfo &drive : drives )
 
  531    const QString path = drive.absolutePath();
 
  537    if ( !mDriveItems.contains( path ) )
 
  539      const QString driveName = QStorageInfo( path ).displayName();
 
  540      const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( 
"%1 (%2)" ).arg( path, driveName );
 
  543      item->
setSortKey( QStringLiteral( 
" 3 %1" ).arg( path ) );
 
  545      mDriveItems.insert( path, item );
 
  546      setupItemConnections( item );
 
  557  if ( column < 0 || column >= 
columnCount() || row < 0 )
 
  558    return QModelIndex();
 
  563  return item ? createIndex( row, column, item ) : QModelIndex();
 
  570    return QModelIndex();
 
  579  for ( 
int i = 0; i < items.size(); i++ )
 
  581    if ( items[i] == item )
 
  582      return createIndex( i, 0, item );
 
  584    QModelIndex childIndex = 
findItem( item, items[i] );
 
  585    if ( childIndex.isValid() )
 
  588  return QModelIndex();
 
  595  if ( !idx.isValid() )
 
  598  beginInsertRows( idx, first, last );
 
  610  if ( !idx.isValid() )
 
  612  beginRemoveRows( idx, first, last );
 
  623  if ( !idx.isValid() )
 
  625  emit dataChanged( idx, idx );
 
  632  if ( !idx.isValid() )
 
  634  QgsDebugMsgLevel( QStringLiteral( 
"item %1 state changed %2 -> %3" ).arg( item->
path() ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( oldState ) ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( item->
state() ) ), 4 );
 
  638void QgsBrowserModel::setupItemConnections( 
QgsDataItem *item )
 
  655  if ( collectionItem )
 
  664  types << QStringLiteral( 
"application/x-vnd.qgis.qgis.uri" );
 
  671  const auto constIndexes = indexes;
 
  672  for ( 
const QModelIndex &
index : constIndexes )
 
  674    if ( 
index.isValid() )
 
  682          uri.filePath = ptr->
path();
 
  707  void *v = idx.internalPointer();
 
  778  QStringList hiddenItems = settings.
value( QStringLiteral( 
"browser/hiddenPaths" ),
 
  779                            QStringList() ).toStringList();
 
  780  int idx = hiddenItems.indexOf( item->
path() );
 
  783    hiddenItems.removeAt( idx );
 
  787    hiddenItems << item->
path();
 
  789  settings.
setValue( QStringLiteral( 
"browser/hiddenPaths" ), hiddenItems );
 
  796    removeRootItem( item );
 
  801void QgsBrowserModel::removeRootItem( 
QgsDataItem *item )
 
  804  beginRemoveRows( QModelIndex(), i, i );
 
  807  if ( !mDriveItems.key( dirItem ).isEmpty() )
 
  809    mDriveItems.remove( mDriveItems.key( dirItem ) );
 
  832    setupItemConnections( item );
 
  838#include "qgsbrowsermodel.moc" 
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.
 
@ 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
 
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 int capabilities() const =0
Returns combination of flags from QgsDataProvider::DataCapabilities.
 
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.
 
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.
 
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)