16#include <QApplication> 
   18#include <QtConcurrentMap> 
   20#include <QStorageInfo> 
   22#include <QFutureWatcher> 
   31#include "moc_qgsbrowsermodel.cpp" 
   39#define PROJECT_HOME_PREFIX "project:" 
   40#define HOME_PREFIX "home:" 
   43class QgsBrowserWatcher : 
public QFutureWatcher<QVector <QgsDataItem *> >
 
   49      : QFutureWatcher( 
nullptr )
 
   57    void finished( 
QgsDataItem *item, 
const QVector <QgsDataItem *> &items );
 
   67  return QString::localeAwareCompare( a->
name(), b->
name() ) < 0;
 
   71  : QAbstractItemModel( parent )
 
   75           this, &QgsBrowserModel::dataItemProviderAdded );
 
   77           this, &QgsBrowserModel::dataItemProviderWillBeRemoved );
 
 
   96    beginRemoveRows( QModelIndex(), idx, idx );
 
  106    beginInsertRows( QModelIndex(), 0, 0 );
 
 
  119      QStringLiteral( 
"special:Home" ) );
 
  121  setupItemConnections( item );
 
  133  const auto drives { QDir::drives() };
 
  134  for ( 
const QFileInfo &drive : drives )
 
  136    const QString path = drive.absolutePath();
 
  141    const QString driveName = QStorageInfo( path ).displayName();
 
  142    const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( 
"%1 (%2)" ).arg( path, driveName );
 
  145    item->
setSortKey( QStringLiteral( 
" 3 %1" ).arg( path ) );
 
  146    mDriveItems.insert( path, item );
 
  148    setupItemConnections( item );
 
  153  QString path = QString( 
"/Volumes" );
 
  155  setupItemConnections( vols );
 
  160  QMultiMap<int, QgsDataItem *> providerMap;
 
  165    if ( 
QgsDataItem *item = addProviderRootItem( pr ) )
 
  167      providerMap.insert( pr->capabilities(), item );
 
  172  const auto constUniqueKeys = providerMap.uniqueKeys();
 
  173  for ( 
int key : constUniqueKeys )
 
  175    QList<QgsDataItem *> providerGroup = providerMap.values( key );
 
  176    if ( providerGroup.size() > 1 )
 
  178      std::sort( providerGroup.begin(), providerGroup.end(), cmpByDataItemName_ );
 
  181    const auto constProviderGroup = providerGroup;
 
 
  206  if ( 
QgsDataItem *item = addProviderRootItem( provider ) )
 
  219    if ( item->providerKey() == provider->
name() )
 
  221      removeRootItem( item );
 
  227void QgsBrowserModel::onConnectionsChanged( 
const QString &providerKey )
 
  232    if ( item->providerKey() == providerKey )
 
  250  if ( ! mInitialized )
 
 
  260  if ( !
index.isValid() )
 
  261    return Qt::ItemFlags();
 
  263  Qt::ItemFlags 
flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 
  270    return Qt::ItemFlags();
 
  274    flags |= Qt::ItemIsDragEnabled;
 
  278    flags |= Qt::ItemIsDropEnabled;
 
  283    flags |= Qt::ItemIsEditable;
 
 
  290  if ( !
index.isValid() )
 
  298  else if ( role == Qt::DisplayRole || role == Qt::EditRole )
 
  306  else if ( role == Qt::ToolTipRole )
 
  310  else if ( role == Qt::DecorationRole && 
index.column() == 0 )
 
  322      QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
 
  331      QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
 
 
  349  if ( !
index.isValid() )
 
  368      return item->
rename( value.toString() );
 
 
  378  if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
 
  380    return QVariant( 
"header" );
 
 
  421  return findPath( 
this, path, matchFlag );
 
 
  427    return QModelIndex();
 
  430  bool foundChild = 
true;
 
  436    for ( 
int i = 0; i < model->rowCount( 
index ); i++ )
 
  438      QModelIndex idx = model->index( i, 0, 
index );
 
  441      if ( itemPath == path )
 
  448      if ( path.startsWith( itemPath + 
'/' ) )
 
  457  if ( matchFlag == Qt::MatchStartsWith )
 
  461  return QModelIndex(); 
 
 
  466  for ( 
int i = 0; i < this->
rowCount( index ); i++ )
 
  470    if ( qobject_cast<QgsLayerItem *>( 
dataItem( idx ) ) )
 
  472      QString itemUri = qobject_cast<QgsLayerItem *>( 
dataItem( idx ) )->uri();
 
  474      if ( itemUri == uri )
 
  481    QModelIndex childIdx = 
findUri( uri, idx );
 
  482    if ( childIdx.isValid() )
 
  485  return QModelIndex();
 
 
  504  const QList< QFileInfo > drives = QDir::drives();
 
  506  const QStringList existingDrives = mDriveItems.keys();
 
  507  for ( 
const QString &drivePath : existingDrives )
 
  509    bool stillExists = 
false;
 
  510    for ( 
const QFileInfo &drive : drives )
 
  512      if ( drivePath == drive.absolutePath() )
 
  524      removeRootItem( driveItem );
 
  527  for ( 
const QFileInfo &drive : drives )
 
  529    const QString path = drive.absolutePath();
 
  535    if ( !mDriveItems.contains( path ) )
 
  537      const QString driveName = QStorageInfo( path ).displayName();
 
  538      const QString name = driveName.isEmpty() || driveName == path ? path : QStringLiteral( 
"%1 (%2)" ).arg( path, driveName );
 
  541      item->
setSortKey( QStringLiteral( 
" 3 %1" ).arg( path ) );
 
  543      mDriveItems.insert( path, item );
 
  544      setupItemConnections( item );
 
 
  555  if ( column < 0 || column >= 
columnCount() || row < 0 )
 
  556    return QModelIndex();
 
  561  return item ? createIndex( row, column, item ) : QModelIndex();
 
 
  568    return QModelIndex();
 
 
  577  for ( 
int i = 0; i < items.size(); i++ )
 
  579    if ( items[i] == item )
 
  580      return createIndex( i, 0, item );
 
  582    QModelIndex childIndex = 
findItem( item, items[i] );
 
  583    if ( childIndex.isValid() )
 
  586  return QModelIndex();
 
 
  593  if ( !idx.isValid() )
 
  596  beginInsertRows( idx, first, last );
 
 
  608  if ( !idx.isValid() )
 
  610  beginRemoveRows( idx, first, last );
 
 
  621  if ( !idx.isValid() )
 
  623  emit dataChanged( idx, idx );
 
 
  630  if ( !idx.isValid() )
 
  632  QgsDebugMsgLevel( QStringLiteral( 
"item %1 state changed %2 -> %3" ).arg( item->
path() ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( oldState ) ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( item->
state() ) ), 4 );
 
 
  636void QgsBrowserModel::setupItemConnections( 
QgsDataItem *item )
 
  653  if ( collectionItem )
 
  662  types << QStringLiteral( 
"application/x-vnd.qgis.qgis.uri" );
 
 
  669  const auto constIndexes = indexes;
 
  670  for ( 
const QModelIndex &
index : constIndexes )
 
  672    if ( 
index.isValid() )
 
  676      if ( uris.isEmpty() )
 
 
  715  void *v = idx.internalPointer();
 
 
  786  QStringList hiddenItems = settings.
value( QStringLiteral( 
"browser/hiddenPaths" ),
 
  787                            QStringList() ).toStringList();
 
  788  int idx = hiddenItems.indexOf( item->
path() );
 
  791    hiddenItems.removeAt( idx );
 
  795    hiddenItems << item->
path();
 
  797  settings.
setValue( QStringLiteral( 
"browser/hiddenPaths" ), hiddenItems );
 
  804    removeRootItem( item );
 
 
  809void QgsBrowserModel::removeRootItem( 
QgsDataItem *item )
 
  812  beginRemoveRows( QModelIndex(), i, i );
 
  815  if ( !mDriveItems.key( dirItem ).isEmpty() )
 
  817    mDriveItems.remove( mDriveItems.key( dirItem ) );
 
  840    setupItemConnections( item );
 
  846#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.
 
QFlags< DataItemProviderCapability > DataItemProviderCapabilities
Capabilities for data item providers.
 
@ 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 browser item for collections of data.
 
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.
 
Interface for providers that 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)
Emitted when data changes for an item.
 
static void deleteLater(QVector< QgsDataItem * > &items)
 
void endRemoveItems()
Emitted after child items have been removed from this data item.
 
QVector< QgsDataItem * > children() const
 
void beginRemoveItems(QgsDataItem *parent, int first, int last)
Emitted before child items are removed from this data item.
 
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)
Emitted before child items are added to this data item.
 
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.
 
void endInsertItems()
Emitted after child items have been added to this data item.
 
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 browser item for directories: 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 a single favorite directory.
 
A browser item which 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.
 
A browser 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.
 
Stores settings for use within QGIS.
 
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.