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.