28#include <QFileSystemWatcher> 
   47                                    const QString &dirPath, 
const QString &path,
 
   48                                    const QString &providerKey )
 
   55void QgsDirectoryItem::init( 
const QString &dirName )
 
   63  switch ( mMonitoring )
 
   76  settings.
beginGroup( QStringLiteral( 
"qgis/browserPathColors" ) );
 
   78  settingKey.replace( 
'/', QLatin1String( 
"|||" ) );
 
   79  if ( settings.
childKeys().contains( settingKey ) )
 
   81    const QString colorString = settings.
value( settingKey ).toString();
 
   82    mIconColor = QColor( colorString );
 
   87  setSortKey( QStringLiteral( 
"  %1" ).arg( dirName ) );
 
   93  switch ( mMonitoring )
 
  106  const QVector<QgsDataItem *> childItems = 
children();
 
  109    if ( 
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem *>( child ) )
 
  110      dirItem->reevaluateMonitoring();
 
  113  createOrDestroyFileSystemWatcher();
 
  116void QgsDirectoryItem::createOrDestroyFileSystemWatcher()
 
  118  if ( !mMonitored && mFileSystemWatcher )
 
  120    mFileSystemWatcher->deleteLater();
 
  121    mFileSystemWatcher = 
nullptr;
 
  125    mFileSystemWatcher = 
new QFileSystemWatcher( 
this );
 
  126    mFileSystemWatcher->addPath( 
mDirPath );
 
  138  if ( color == mIconColor )
 
  148  settings.
beginGroup( QStringLiteral( 
"qgis/browserPathColors" ) );
 
  149  QString settingKey = directory;
 
  150  settingKey.replace( 
'/', QLatin1String( 
"|||" ) );
 
  151  if ( color.isValid() )
 
  152    settings.
setValue( settingKey, color.name( QColor::HexArgb ) );
 
  154    settings.
remove( settingKey );
 
  161    return homeDirIcon( mIconColor, mIconColor.darker() );
 
  169  if ( fi.isDir() && fi.isSymLink() )
 
  171    return mIconColor.isValid()
 
  178    return openDirIcon( mIconColor, mIconColor.darker() );
 
  181  return iconDir( mIconColor, mIconColor.darker() );
 
  194  QStringList noMonitorDirs = settings.
value( QStringLiteral( 
"qgis/disableMonitorItemUris" ), QStringList() ).toStringList();
 
  195  QStringList alwaysMonitorDirs = settings.
value( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), QStringList() ).toStringList();
 
  197  switch ( mMonitoring )
 
  202      noMonitorDirs.removeAll( 
mDirPath );
 
  203      settings.
setValue( QStringLiteral( 
"qgis/disableMonitorItemUris" ), noMonitorDirs );
 
  205      alwaysMonitorDirs.removeAll( 
mDirPath );
 
  206      settings.
setValue( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
 
  214      if ( !noMonitorDirs.contains( 
mDirPath ) )
 
  217        settings.
setValue( QStringLiteral( 
"qgis/disableMonitorItemUris" ), noMonitorDirs );
 
  220      alwaysMonitorDirs.removeAll( 
mDirPath );
 
  221      settings.
setValue( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
 
  229      noMonitorDirs.removeAll( 
mDirPath );
 
  230      settings.
setValue( QStringLiteral( 
"qgis/disableMonitorItemUris" ), noMonitorDirs );
 
  232      if ( !alwaysMonitorDirs.contains( 
mDirPath ) )
 
  234        alwaysMonitorDirs.append( 
mDirPath );
 
  235        settings.
setValue( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
 
  243  const QVector<QgsDataItem *> childItems = 
children();
 
  246    if ( 
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem *>( child ) )
 
  247      dirItem->reevaluateMonitoring();
 
  250  createOrDestroyFileSystemWatcher();
 
  260  const QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
 
  261  for ( 
const QString &subdir : entries )
 
  269    const QString subdirPath = dir.absoluteFilePath( subdir );
 
  271    QgsDebugMsgLevel( QStringLiteral( 
"creating subdir: %1" ).arg( subdirPath ), 2 );
 
  273    const QString 
path = 
mPath + ( 
mPath.endsWith( 
'/' ) ? QString() : QStringLiteral( 
"/" ) ) + subdir; 
 
  277    bool handledByProvider = 
false;
 
  280      if ( provider->handlesDirectoryPath( subdirPath ) )
 
  282        handledByProvider = 
true;
 
  286    if ( handledByProvider )
 
  296  const QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
 
  297  for ( 
const QString &
name : fileEntries )
 
  305    const QString 
path = dir.absoluteFilePath( 
name );
 
  306    const QFileInfo fileInfo( 
path );
 
  317    bool createdItem = 
false;
 
  320      const int capabilities = provider->capabilities();
 
  345      if ( fileInfo.suffix().compare( QLatin1String( 
"qgs" ), Qt::CaseInsensitive ) == 0 ||
 
  346           fileInfo.suffix().compare( QLatin1String( 
"qgz" ), Qt::CaseInsensitive ) == 0 )
 
  365    if ( !mFileSystemWatcher )
 
  367      mFileSystemWatcher = 
new QFileSystemWatcher( 
this );
 
  368      mFileSystemWatcher->addPath( 
mDirPath );
 
  371    mLastScan = QDateTime::currentDateTime();
 
  375    if ( mFileSystemWatcher )
 
  377      delete mFileSystemWatcher;
 
  378      mFileSystemWatcher = 
nullptr;
 
  386  if ( mLastScan.msecsTo( QDateTime::currentDateTime() ) < 
QgsSettings().value( QStringLiteral( 
"browser/minscaninterval" ), 10000 ).toInt() )
 
  393    mRefreshLater = 
true;
 
  407    QTimer::singleShot( 100, 
this, [ = ] { 
refresh(); } );
 
  414  const QStringList hiddenItems = settings.
value( QStringLiteral( 
"browser/hiddenPaths" ),
 
  415                                  QStringList() ).toStringList();
 
  416  const int idx = hiddenItems.indexOf( 
path );
 
  423  if ( settings.
value( QStringLiteral( 
"qgis/disableMonitorItemUris" ), QStringList() ).toStringList().contains( 
path ) )
 
  425  else if ( settings.
value( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), QStringList() ).toStringList().contains( 
path ) )
 
  434  const QString originalPath = QDir::cleanPath( 
path );
 
  435  QString currentPath = originalPath;
 
  437  while ( currentPath != prevPath )
 
  439    prevPath = currentPath;
 
  440    currentPath = QFileInfo( currentPath ).path();
 
  460  return QgsSettings().
value( QStringLiteral( 
"/qgis/monitorDirectoriesInBrowser" ), 
true ).toBool();
 
  465  QgsDebugMsgLevel( QStringLiteral( 
"mRefreshLater = %1" ).arg( mRefreshLater ), 3 );
 
  469    QgsDebugMsgLevel( QStringLiteral( 
"directory changed during createChidren() -> refresh() again" ), 3 );
 
  470    mRefreshLater = 
false;
 
  479  if ( mFileSystemWatcher && mMonitored )
 
  490  const QgsDirectoryItem *otherDirItem = qobject_cast< const QgsDirectoryItem * >( other );
 
  505  u.
layerType = QStringLiteral( 
"directory" );
 
  516  : QTreeWidget( parent )
 
  518  setRootIsDecorated( 
false );
 
  523  labels << tr( 
"Name" ) << tr( 
"Size" ) << tr( 
"Date" ) << tr( 
"Permissions" ) << tr( 
"Owner" ) << tr( 
"Group" ) << tr( 
"Type" );
 
  524  setHeaderLabels( labels );
 
  531  QList<QTreeWidgetItem *> items;
 
  533  const QDir dir( path );
 
  534  const QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
 
  535  for ( 
const QString &name : entries )
 
  537    const QFileInfo fi( dir.absoluteFilePath( name ) );
 
  541    if ( fi.size() > 1024 )
 
  543      size = QStringLiteral( 
"%1 KiB" ).arg( QLocale().toString( fi.size() / 1024.0, 
'f', 1 ) );
 
  545    else if ( fi.size() > 1.048576e6 )
 
  547      size = QStringLiteral( 
"%1 MiB" ).arg( QLocale().toString( fi.size() / 1.048576e6, 
'f', 1 ) );
 
  551      size = QStringLiteral( 
"%1 B" ).arg( fi.size() );
 
  554    texts << QLocale().toString( fi.lastModified(), QLocale::ShortFormat );
 
  556    perm += fi.permission( QFile::ReadOwner ) ? 
'r' : 
'-';
 
  557    perm += fi.permission( QFile::WriteOwner ) ? 
'w' : 
'-';
 
  558    perm += fi.permission( QFile::ExeOwner ) ? 
'x' : 
'-';
 
  560    perm += fi.permission( QFile::ReadGroup ) ? 
'r' : 
'-';
 
  561    perm += fi.permission( QFile::WriteGroup ) ? 
'w' : 
'-';
 
  562    perm += fi.permission( QFile::ExeGroup ) ? 
'x' : 
'-';
 
  563    perm += fi.permission( QFile::ReadOther ) ? 
'r' : 
'-';
 
  564    perm += fi.permission( QFile::WriteOther ) ? 
'w' : 
'-';
 
  565    perm += fi.permission( QFile::ExeOther ) ? 
'x' : 
'-';
 
  573    if ( fi.isDir() && fi.isSymLink() )
 
  575      type = tr( 
"folder" );
 
  578    else if ( fi.isDir() )
 
  580      type = tr( 
"folder" );
 
  581      icon = iconDirectory;
 
  583    else if ( fi.isFile() && fi.isSymLink() )
 
  588    else if ( fi.isFile() )
 
  596    QTreeWidgetItem *item = 
new QTreeWidgetItem( texts );
 
  597    item->setIcon( 0, icon );
 
  601  addTopLevelItems( items );
 
  605  const QList<QVariant> lst = settings.
value( QStringLiteral( 
"dataitem/directoryHiddenColumns" ) ).toList();
 
  606  for ( 
const QVariant &colVariant : lst )
 
  608    setColumnHidden( colVariant.toInt(), 
true );
 
  614  if ( event->button() == Qt::RightButton )
 
  620    labels << tr( 
"Name" ) << tr( 
"Size" ) << tr( 
"Date" ) << tr( 
"Permissions" ) << tr( 
"Owner" ) << tr( 
"Group" ) << tr( 
"Type" );
 
  621    for ( 
int i = 0; i < labels.count(); i++ )
 
  624      action->setObjectName( QString::number( i ) );
 
  625      action->setCheckable( 
true );
 
  626      action->setChecked( !isColumnHidden( i ) );
 
  629    popupMenu.exec( event->globalPos() );
 
  635  QAction *action = qobject_cast<QAction *>( sender() );
 
  639  const int columnIndex = action->objectName().toInt();
 
  640  setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
 
  645  for ( 
int i = 0; i < columnCount(); i++ )
 
  647    if ( isColumnHidden( i ) )
 
  648      lst.append( QVariant( i ) );
 
  650  settings.
setValue( QStringLiteral( 
"dataitem/directoryHiddenColumns" ), lst );
 
  658  : 
QgsDirectoryItem( parent, name, dirPath, path, QStringLiteral( 
"special:ProjectHome" ) )
 
  671  return QStringLiteral( 
" 1" );
 
BrowserItemState
Browser item states.
 
@ NotPopulated
Children not yet created.
 
@ Populating
Creating children in separate thread (populating or refreshing)
 
@ Populated
Children created.
 
@ ItemRepresentsFile
Item's path() directly represents a file on disk (since QGIS 3.22)
 
BrowserDirectoryMonitoring
Browser directory item monitoring switches.
 
@ Default
Use default logic to determine whether directory should be monitored.
 
@ AlwaysMonitor
Always monitor the directory, regardless of the default logic.
 
@ NeverMonitor
Never monitor the directory, regardless of the default logic.
 
@ Directory
Represents a file directory.
 
static QgsDataItemProviderRegistry * dataItemProviderRegistry()
Returns the application's data item provider registry, which keeps a list of data item providers that...
 
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
 
A Collection: logical collection of layers or subcollections, e.g.
 
static QIcon homeDirIcon(const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Shared home directory icon.
 
static QIcon iconDir(const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Returns the standard browser directory icon.
 
static QIcon openDirIcon(const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Shared open directory icon.
 
QList< QgsDataItemProvider * > providers() const
Returns the list of available providers.
 
This is the interface for those who want to add custom data items to the browser tree.
 
Base class for all items in the model.
 
void setSortKey(const QVariant &key)
Sets a custom sorting key for the item.
 
Qgis::BrowserItemType mType
 
void setToolTip(const QString &msg)
 
void dataChanged(QgsDataItem *item)
 
QVector< QgsDataItem * > children() const
 
virtual void deleteLater()
Safely delete the item:
 
Qgis::BrowserItemType type() const
 
Qgis::BrowserItemState state() const
 
virtual void childrenCreated()
 
QString name() const
Returns the name of the item (the displayed text for the item).
 
virtual void setState(Qgis::BrowserItemState state)
Set item state.
 
virtual void setCapabilities(Qgis::BrowserItemCapabilities capabilities)
Sets the capabilities for the data item.
 
virtual Qgis::BrowserItemCapabilities capabilities2() const
Returns the capabilities for the data item.
 
A directory: contains subdirectories and layers.
 
QVector< QgsDataItem * > createChildren() override
Create children.
 
Q_DECL_DEPRECATED QWidget * paramWidget() override
Returns source widget from data item for QgsBrowserPropertiesWidget.
 
static Qgis::BrowserDirectoryMonitoring monitoringForPath(const QString &path)
Returns the monitoring setting for a directory path.
 
QgsMimeDataUtils::UriList mimeUris() const override
Returns mime URIs for the data item, most data providers will only return a single URI but some data ...
 
Qgis::BrowserDirectoryMonitoring monitoring() const
Returns the monitoring setting for this directory item.
 
static void setCustomColor(const QString &directory, const QColor &color)
Sets a custom icon color to use for the items for the corresponding directory path.
 
bool equal(const QgsDataItem *other) override
Returns true if this item is equal to another item (by testing item type and path).
 
QString dirPath() const
Returns the full path to the directory the item represents.
 
void setMonitoring(Qgis::BrowserDirectoryMonitoring monitoring)
Sets the monitoring setting for this directory.
 
QColor iconColor() const
Returns the directory's icon color.
 
void childrenCreated() override
 
void setIconColor(const QColor &color)
Sets the directory's icon color.
 
QgsDirectoryItem(QgsDataItem *parent, const QString &name, const QString &path)
Constructor for QgsDirectoryItem, with the specified parent item.
 
void reevaluateMonitoring()
Re-evaluate whether the directory item should be monitored for changes.
 
static bool hiddenPath(const QString &path)
Check if the given path is hidden from the browser model.
 
void setState(Qgis::BrowserItemState state) override
Set item state.
 
static bool pathShouldByMonitoredByDefault(const QString &path)
Returns true if a directory path should be monitored by default.
 
static bool pathIsSlowDevice(const QString &path)
Returns true if the specified path is assumed to reside on a slow device, e.g.
 
static bool isVsiArchiveFileExtension(const QString &extension)
Returns true if a file extension is a supported archive style container (e.g.
 
QList< QgsMimeDataUtils::Uri > UriList
 
QVariant sortKey() const override
Returns the sorting key for the item.
 
QgsProjectHomeItem(QgsDataItem *parent, const QString &name, const QString &dirPath, const QString &path)
Constructor for QgsProjectHomeItem.
 
Data item that can be used to represent QGIS projects.
 
This class is a composition of two QSettings instances:
 
void endGroup()
Resets the group to what it was before the corresponding beginGroup() call.
 
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
 
void beginGroup(const QString &prefix, QgsSettings::Section section=QgsSettings::NoSection)
Appends prefix to the current group.
 
QStringList childKeys() const
Returns a list of all top-level keys that can be read using the QSettings object.
 
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
 
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
 
static QgsDataItem * itemFromPath(QgsDataItem *parent, const QString &path, const QString &name)
Creates a new data item from the specified path.
 
#define QgsDebugMsgLevel(str, level)
 
QString filePath
Path to file, if uri is associated with a file.
 
QString uri
Identifier of the data source recognized by its providerKey.
 
QString name
Human readable name to be used e.g. in layer tree.
 
QString layerType
Type of URI.