27#include <QFileSystemWatcher>
46 const QString &dirPath,
const QString &path,
47 const QString &providerKey )
54void QgsDirectoryItem::init(
const QString &dirName )
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 );
86 setSortKey( QStringLiteral(
" %1" ).arg( dirName ) );
92 switch ( mMonitoring )
105 const QVector<QgsDataItem *> childItems =
children();
108 if (
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem *>( child ) )
109 dirItem->reevaluateMonitoring();
112 createOrDestroyFileSystemWatcher();
115void QgsDirectoryItem::createOrDestroyFileSystemWatcher()
117 if ( !mMonitored && mFileSystemWatcher )
119 mFileSystemWatcher->deleteLater();
120 mFileSystemWatcher =
nullptr;
124 mFileSystemWatcher =
new QFileSystemWatcher(
this );
125 mFileSystemWatcher->addPath(
mDirPath );
137 if ( color == mIconColor )
147 settings.
beginGroup( QStringLiteral(
"qgis/browserPathColors" ) );
148 QString settingKey = directory;
149 settingKey.replace(
'/', QLatin1String(
"|||" ) );
150 if ( color.isValid() )
151 settings.
setValue( settingKey, color.name( QColor::HexArgb ) );
153 settings.
remove( settingKey );
160 return homeDirIcon( mIconColor, mIconColor.darker() );
168 if ( fi.isDir() && fi.isSymLink() )
170 return mIconColor.isValid()
177 return openDirIcon( mIconColor, mIconColor.darker() );
180 return iconDir( mIconColor, mIconColor.darker() );
193 QStringList noMonitorDirs = settings.
value( QStringLiteral(
"qgis/disableMonitorItemUris" ), QStringList() ).toStringList();
194 QStringList alwaysMonitorDirs = settings.
value( QStringLiteral(
"qgis/alwaysMonitorItemUris" ), QStringList() ).toStringList();
196 switch ( mMonitoring )
201 noMonitorDirs.removeAll(
mDirPath );
202 settings.
setValue( QStringLiteral(
"qgis/disableMonitorItemUris" ), noMonitorDirs );
204 alwaysMonitorDirs.removeAll(
mDirPath );
205 settings.
setValue( QStringLiteral(
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
213 if ( !noMonitorDirs.contains(
mDirPath ) )
216 settings.
setValue( QStringLiteral(
"qgis/disableMonitorItemUris" ), noMonitorDirs );
219 alwaysMonitorDirs.removeAll(
mDirPath );
220 settings.
setValue( QStringLiteral(
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
228 noMonitorDirs.removeAll(
mDirPath );
229 settings.
setValue( QStringLiteral(
"qgis/disableMonitorItemUris" ), noMonitorDirs );
231 if ( !alwaysMonitorDirs.contains(
mDirPath ) )
233 alwaysMonitorDirs.append(
mDirPath );
234 settings.
setValue( QStringLiteral(
"qgis/alwaysMonitorItemUris" ), alwaysMonitorDirs );
242 const QVector<QgsDataItem *> childItems =
children();
245 if (
QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem *>( child ) )
246 dirItem->reevaluateMonitoring();
249 createOrDestroyFileSystemWatcher();
259 const QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
260 for (
const QString &subdir : entries )
268 const QString subdirPath = dir.absoluteFilePath( subdir );
270 QgsDebugMsgLevel( QStringLiteral(
"creating subdir: %1" ).arg( subdirPath ), 2 );
272 const QString
path =
mPath + (
mPath.endsWith(
'/' ) ? QString() : QStringLiteral(
"/" ) ) + subdir;
276 bool handledByProvider =
false;
279 if ( provider->handlesDirectoryPath( subdirPath ) )
281 handledByProvider =
true;
285 if ( handledByProvider )
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 );
316 bool createdItem =
false;
319 const Qgis::DataItemProviderCapabilities capabilities = provider->capabilities();
344 if ( fileInfo.suffix().compare( QLatin1String(
"qgs" ), Qt::CaseInsensitive ) == 0 ||
345 fileInfo.suffix().compare( QLatin1String(
"qgz" ), Qt::CaseInsensitive ) == 0 )
364 if ( !mFileSystemWatcher )
366 mFileSystemWatcher =
new QFileSystemWatcher(
this );
367 mFileSystemWatcher->addPath(
mDirPath );
370 mLastScan = QDateTime::currentDateTime();
374 if ( mFileSystemWatcher )
376 delete mFileSystemWatcher;
377 mFileSystemWatcher =
nullptr;
385 if ( mLastScan.msecsTo( QDateTime::currentDateTime() ) <
QgsSettings().value( QStringLiteral(
"browser/minscaninterval" ), 10000 ).toInt() )
392 mRefreshLater =
true;
406 QTimer::singleShot( 100,
this, [
this] {
refresh(); } );
413 const QStringList hiddenItems = settings.
value( QStringLiteral(
"browser/hiddenPaths" ),
414 QStringList() ).toStringList();
415 const int idx = hiddenItems.indexOf(
path );
422 if ( settings.
value( QStringLiteral(
"qgis/disableMonitorItemUris" ), QStringList() ).toStringList().contains(
path ) )
424 else if ( settings.
value( QStringLiteral(
"qgis/alwaysMonitorItemUris" ), QStringList() ).toStringList().contains(
path ) )
433 const QString originalPath = QDir::cleanPath(
path );
434 QString currentPath = originalPath;
436 while ( currentPath != prevPath )
438 prevPath = currentPath;
439 currentPath = QFileInfo( currentPath ).path();
459 return QgsSettings().
value( QStringLiteral(
"/qgis/monitorDirectoriesInBrowser" ),
true ).toBool();
464 QgsDebugMsgLevel( QStringLiteral(
"mRefreshLater = %1" ).arg( mRefreshLater ), 3 );
468 QgsDebugMsgLevel( QStringLiteral(
"directory changed during createChidren() -> refresh() again" ), 3 );
469 mRefreshLater =
false;
478 if ( mFileSystemWatcher && mMonitored )
489 const QgsDirectoryItem *otherDirItem = qobject_cast< const QgsDirectoryItem * >( other );
504 u.
layerType = QStringLiteral(
"directory" );
515 : QTreeWidget( parent )
517 setRootIsDecorated(
false );
522 labels << tr(
"Name" ) << tr(
"Size" ) << tr(
"Date" ) << tr(
"Permissions" ) << tr(
"Owner" ) << tr(
"Group" ) << tr(
"Type" );
523 setHeaderLabels( labels );
530 QList<QTreeWidgetItem *> items;
532 const QDir dir( path );
533 const QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
534 for (
const QString &name : entries )
536 const QFileInfo fi( dir.absoluteFilePath( name ) );
540 if ( fi.size() > 1024 )
542 size = QStringLiteral(
"%1 KiB" ).arg( QLocale().toString( fi.size() / 1024.0,
'f', 1 ) );
544 else if ( fi.size() > 1.048576e6 )
546 size = QStringLiteral(
"%1 MiB" ).arg( QLocale().toString( fi.size() / 1.048576e6,
'f', 1 ) );
550 size = QStringLiteral(
"%1 B" ).arg( fi.size() );
553 texts << QLocale().toString( fi.lastModified(), QLocale::ShortFormat );
555 perm += fi.permission( QFile::ReadOwner ) ?
'r' :
'-';
556 perm += fi.permission( QFile::WriteOwner ) ?
'w' :
'-';
557 perm += fi.permission( QFile::ExeOwner ) ?
'x' :
'-';
559 perm += fi.permission( QFile::ReadGroup ) ?
'r' :
'-';
560 perm += fi.permission( QFile::WriteGroup ) ?
'w' :
'-';
561 perm += fi.permission( QFile::ExeGroup ) ?
'x' :
'-';
562 perm += fi.permission( QFile::ReadOther ) ?
'r' :
'-';
563 perm += fi.permission( QFile::WriteOther ) ?
'w' :
'-';
564 perm += fi.permission( QFile::ExeOther ) ?
'x' :
'-';
572 if ( fi.isDir() && fi.isSymLink() )
574 type = tr(
"folder" );
577 else if ( fi.isDir() )
579 type = tr(
"folder" );
580 icon = iconDirectory;
582 else if ( fi.isFile() && fi.isSymLink() )
587 else if ( fi.isFile() )
595 QTreeWidgetItem *item =
new QTreeWidgetItem( texts );
596 item->setIcon( 0, icon );
600 addTopLevelItems( items );
604 const QList<QVariant> lst = settings.
value( QStringLiteral(
"dataitem/directoryHiddenColumns" ) ).toList();
605 for (
const QVariant &colVariant : lst )
607 setColumnHidden( colVariant.toInt(),
true );
613 if ( event->button() == Qt::RightButton )
619 labels << tr(
"Name" ) << tr(
"Size" ) << tr(
"Date" ) << tr(
"Permissions" ) << tr(
"Owner" ) << tr(
"Group" ) << tr(
"Type" );
620 for (
int i = 0; i < labels.count(); i++ )
623 action->setObjectName( QString::number( i ) );
624 action->setCheckable(
true );
625 action->setChecked( !isColumnHidden( i ) );
628 popupMenu.exec( event->globalPos() );
634 QAction *action = qobject_cast<QAction *>( sender() );
638 const int columnIndex = action->objectName().toInt();
639 setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
644 for (
int i = 0; i < columnCount(); i++ )
646 if ( isColumnHidden( i ) )
647 lst.append( QVariant( i ) );
649 settings.
setValue( QStringLiteral(
"dataitem/directoryHiddenColumns" ), lst );
657 :
QgsDirectoryItem( parent, name, dirPath, path, QStringLiteral(
"special:ProjectHome" ) )
670 return QStringLiteral(
" 1" );
@ Files
Can provides items which corresponds to files.
@ Directories
Can provides items which corresponds to directories.
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.