27 #include <QFileSystemWatcher> 
   29 #include <QMouseEvent> 
   46                                     const QString &dirPath, 
const QString &path,
 
   47                                     const QString &providerKey )
 
   62   switch ( mMonitoring )
 
   75   settings.
beginGroup( QStringLiteral( 
"qgis/browserPathColors" ) );
 
   77   settingKey.replace( 
'/', QLatin1String( 
"|||" ) );
 
   78   if ( settings.
childKeys().contains( settingKey ) )
 
   80     const QString colorString = settings.
value( settingKey ).toString();
 
   81     mIconColor = QColor( colorString );
 
   89   switch ( mMonitoring )
 
  102   const QVector<QgsDataItem *> childItems = 
children();
 
  105     if ( 
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem *>( child ) )
 
  106       dirItem->reevaluateMonitoring();
 
  109   createOrDestroyFileSystemWatcher();
 
  112 void QgsDirectoryItem::createOrDestroyFileSystemWatcher()
 
  114   if ( !mMonitored && mFileSystemWatcher )
 
  116     mFileSystemWatcher->deleteLater();
 
  117     mFileSystemWatcher = 
nullptr;
 
  121     mFileSystemWatcher = 
new QFileSystemWatcher( 
this );
 
  122     mFileSystemWatcher->addPath( 
mDirPath );
 
  134   if ( color == mIconColor )
 
  144   settings.
beginGroup( QStringLiteral( 
"qgis/browserPathColors" ) );
 
  145   QString settingKey = directory;
 
  146   settingKey.replace( 
'/', QLatin1String( 
"|||" ) );
 
  147   if ( color.isValid() )
 
  148     settings.
setValue( settingKey, color.name( QColor::HexArgb ) );
 
  150     settings.
remove( settingKey );
 
  157     return homeDirIcon( mIconColor, mIconColor.darker() );
 
  165   if ( fi.isDir() && fi.isSymLink() )
 
  167     return mIconColor.isValid()
 
  174     return openDirIcon( mIconColor, mIconColor.darker() );
 
  177   return iconDir( mIconColor, mIconColor.darker() );
 
  190   QStringList noMonitorDirs = settings.
value( QStringLiteral( 
"qgis/disableMonitorItemUris" ), QStringList() ).toStringList();
 
  191   QStringList alwaysMonitorDirs = settings.
value( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), QStringList() ).toStringList();
 
  193   switch ( mMonitoring )
 
  198       noMonitorDirs.removeAll( 
mDirPath );
 
  199       settings.
setValue( QStringLiteral( 
"qgis/disableMonitorItemUris" ), noMonitorDirs );
 
  201       alwaysMonitorDirs.removeAll( 
mDirPath );
 
  202       settings.
setValue( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
 
  210       if ( !noMonitorDirs.contains( 
mDirPath ) )
 
  213         settings.
setValue( QStringLiteral( 
"qgis/disableMonitorItemUris" ), noMonitorDirs );
 
  216       alwaysMonitorDirs.removeAll( 
mDirPath );
 
  217       settings.
setValue( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
 
  225       noMonitorDirs.removeAll( 
mDirPath );
 
  226       settings.
setValue( QStringLiteral( 
"qgis/disableMonitorItemUris" ), noMonitorDirs );
 
  228       if ( !alwaysMonitorDirs.contains( 
mDirPath ) )
 
  230         alwaysMonitorDirs.append( 
mDirPath );
 
  231         settings.
setValue( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
 
  239   const QVector<QgsDataItem *> childItems = 
children();
 
  242     if ( 
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem *>( child ) )
 
  243       dirItem->reevaluateMonitoring();
 
  246   createOrDestroyFileSystemWatcher();
 
  256   const QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
 
  257   for ( 
const QString &subdir : entries )
 
  265     const QString subdirPath = dir.absoluteFilePath( subdir );
 
  267     QgsDebugMsgLevel( QStringLiteral( 
"creating subdir: %1" ).arg( subdirPath ), 2 );
 
  269     const QString 
path = 
mPath + 
'/' + subdir; 
 
  273     bool handledByProvider = 
false;
 
  276       if ( provider->handlesDirectoryPath( 
path ) )
 
  278         handledByProvider = 
true;
 
  282     if ( handledByProvider )
 
  288     item->
setSortKey( QStringLiteral( 
"  %1" ).arg( subdir ) );
 
  295   const QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
 
  296   for ( 
const QString &
name : fileEntries )
 
  304     const QString 
path = dir.absoluteFilePath( 
name );
 
  305     const QFileInfo fileInfo( 
path );
 
  307     if ( fileInfo.suffix().compare( QLatin1String( 
"zip" ), Qt::CaseInsensitive ) == 0 ||
 
  308          fileInfo.suffix().compare( QLatin1String( 
"tar" ), Qt::CaseInsensitive ) == 0 )
 
  318     bool createdItem = 
false;
 
  321       const int capabilities = provider->capabilities();
 
  346       if ( fileInfo.suffix().compare( QLatin1String( 
"qgs" ), Qt::CaseInsensitive ) == 0 ||
 
  347            fileInfo.suffix().compare( QLatin1String( 
"qgz" ), Qt::CaseInsensitive ) == 0 )
 
  366     if ( !mFileSystemWatcher )
 
  368       mFileSystemWatcher = 
new QFileSystemWatcher( 
this );
 
  369       mFileSystemWatcher->addPath( 
mDirPath );
 
  372     mLastScan = QDateTime::currentDateTime();
 
  376     if ( mFileSystemWatcher )
 
  378       delete mFileSystemWatcher;
 
  379       mFileSystemWatcher = 
nullptr;
 
  387   if ( mLastScan.msecsTo( QDateTime::currentDateTime() ) < 
QgsSettings().value( QStringLiteral( 
"browser/minscaninterval" ), 10000 ).toInt() )
 
  394     mRefreshLater = 
true;
 
  408     QTimer::singleShot( 100, 
this, [ = ] { 
refresh(); } );
 
  415   const QStringList hiddenItems = settings.
value( QStringLiteral( 
"browser/hiddenPaths" ),
 
  416                                   QStringList() ).toStringList();
 
  417   const int idx = hiddenItems.indexOf( 
path );
 
  424   if ( settings.
value( QStringLiteral( 
"qgis/disableMonitorItemUris" ), QStringList() ).toStringList().contains( 
path ) )
 
  426   else if ( settings.
value( QStringLiteral( 
"qgis/alwaysMonitorItemUris" ), QStringList() ).toStringList().contains( 
path ) )
 
  435   const QString originalPath = QDir::cleanPath( 
path );
 
  436   QString currentPath = originalPath;
 
  438   while ( currentPath != prevPath )
 
  440     prevPath = currentPath;
 
  441     currentPath = QFileInfo( currentPath ).path();
 
  461   return QgsSettings().
value( QStringLiteral( 
"/qgis/monitorDirectoriesInBrowser" ), 
true ).toBool();
 
  466   QgsDebugMsgLevel( QStringLiteral( 
"mRefreshLater = %1" ).arg( mRefreshLater ), 3 );
 
  470     QgsDebugMsgLevel( QStringLiteral( 
"directory changed during createChidren() -> refresh() again" ), 3 );
 
  471     mRefreshLater = 
false;
 
  480   if ( mFileSystemWatcher && mMonitored )
 
  502   u.
layerType = QStringLiteral( 
"directory" );
 
  513   : QTreeWidget( parent )
 
  515   setRootIsDecorated( 
false );
 
  520   labels << tr( 
"Name" ) << tr( 
"Size" ) << tr( 
"Date" ) << tr( 
"Permissions" ) << tr( 
"Owner" ) << tr( 
"Group" ) << tr( 
"Type" );
 
  521   setHeaderLabels( labels );
 
  528   QList<QTreeWidgetItem *> items;
 
  530   const QDir dir( path );
 
  531   const QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
 
  532   for ( 
const QString &name : entries )
 
  534     const QFileInfo fi( dir.absoluteFilePath( name ) );
 
  538     if ( fi.size() > 1024 )
 
  540       size = QStringLiteral( 
"%1 KiB" ).arg( QLocale().toString( fi.size() / 1024.0, 
'f', 1 ) );
 
  542     else if ( fi.size() > 1.048576e6 )
 
  544       size = QStringLiteral( 
"%1 MiB" ).arg( QLocale().toString( fi.size() / 1.048576e6, 
'f', 1 ) );
 
  548       size = QStringLiteral( 
"%1 B" ).arg( fi.size() );
 
  551     texts << QLocale().toString( fi.lastModified(), QLocale::ShortFormat );
 
  553     perm += fi.permission( QFile::ReadOwner ) ? 
'r' : 
'-';
 
  554     perm += fi.permission( QFile::WriteOwner ) ? 
'w' : 
'-';
 
  555     perm += fi.permission( QFile::ExeOwner ) ? 
'x' : 
'-';
 
  557     perm += fi.permission( QFile::ReadGroup ) ? 
'r' : 
'-';
 
  558     perm += fi.permission( QFile::WriteGroup ) ? 
'w' : 
'-';
 
  559     perm += fi.permission( QFile::ExeGroup ) ? 
'x' : 
'-';
 
  560     perm += fi.permission( QFile::ReadOther ) ? 
'r' : 
'-';
 
  561     perm += fi.permission( QFile::WriteOther ) ? 
'w' : 
'-';
 
  562     perm += fi.permission( QFile::ExeOther ) ? 
'x' : 
'-';
 
  570     if ( fi.isDir() && fi.isSymLink() )
 
  572       type = tr( 
"folder" );
 
  575     else if ( fi.isDir() )
 
  577       type = tr( 
"folder" );
 
  578       icon = iconDirectory;
 
  580     else if ( fi.isFile() && fi.isSymLink() )
 
  585     else if ( fi.isFile() )
 
  593     QTreeWidgetItem *item = 
new QTreeWidgetItem( texts );
 
  594     item->setIcon( 0, icon );
 
  598   addTopLevelItems( items );
 
  602   const QList<QVariant> lst = settings.
value( QStringLiteral( 
"dataitem/directoryHiddenColumns" ) ).toList();
 
  603   for ( 
const QVariant &colVariant : lst )
 
  605     setColumnHidden( colVariant.toInt(), 
true );
 
  611   if ( event->button() == Qt::RightButton )
 
  617     labels << tr( 
"Name" ) << tr( 
"Size" ) << tr( 
"Date" ) << tr( 
"Permissions" ) << tr( 
"Owner" ) << tr( 
"Group" ) << tr( 
"Type" );
 
  618     for ( 
int i = 0; i < labels.count(); i++ )
 
  621       action->setObjectName( QString::number( i ) );
 
  622       action->setCheckable( 
true );
 
  623       action->setChecked( !isColumnHidden( i ) );
 
  626     popupMenu.exec( event->globalPos() );
 
  632   QAction *action = qobject_cast<QAction *>( sender() );
 
  636   const int columnIndex = action->objectName().toInt();
 
  637   setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
 
  642   for ( 
int i = 0; i < columnCount(); i++ )
 
  644     if ( isColumnHidden( i ) )
 
  645       lst.append( QVariant( i ) );
 
  647   settings.
setValue( QStringLiteral( 
"dataitem/directoryHiddenColumns" ), lst );
 
  655   : 
QgsDirectoryItem( parent, name, dirPath, path, QStringLiteral( 
"special:ProjectHome" ) )
 
  668   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).
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.
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.