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" );