--- a/src/eric7/Project/ProjectBrowserModel.py Wed Apr 10 10:45:31 2024 +0200 +++ b/src/eric7/Project/ProjectBrowserModel.py Wed Apr 10 16:45:06 2024 +0200 @@ -11,10 +11,11 @@ import os import re -from PyQt6.QtCore import QDir, QFileSystemWatcher, QModelIndex, Qt, pyqtSignal +from PyQt6.QtCore import QDir, QModelIndex, Qt, pyqtSignal from PyQt6.QtGui import QColor from eric7 import Preferences +from eric7.EricCore import EricFileSystemWatcher from eric7.SystemUtilities import FileSystemUtilities from eric7.UI.BrowserModel import ( BrowserDirectoryItem, @@ -215,10 +216,13 @@ self.project = parent self.__projectBrowser = None - self.watchedItems = {} + self.watchedDirItems = {} self.__watcherActive = True - self.watcher = QFileSystemWatcher(self) - self.watcher.directoryChanged.connect(self.directoryChanged) + watcher = EricFileSystemWatcher.instance() + watcher.directoryCreated.connect(lambda x: self.entryCreated(x, isDir=True)) + watcher.directoryDeleted.connect(lambda x: self.entryDeleted(x, isDir=True)) + watcher.fileCreated.connect(lambda x: self.entryCreated(x, isDir=False)) + watcher.fileDeleted.connect(lambda x: self.entryDeleted(x, isDir=False)) self.inRefresh = False @@ -379,10 +383,11 @@ """ self.__vcsStatus = {} - self.watchedItems = {} - watchedDirs = self.watcher.directories() - if watchedDirs: - self.watcher.removePaths(watchedDirs) + paths = list(self.watchedDirItems.keys()) + if paths: + watcher = EricFileSystemWatcher.instance() + watcher.removePaths(paths) + self.watchedDirItems.clear() self.rootItem.removeChildren() self.beginResetModel() @@ -683,90 +688,61 @@ """ self.__watcherActive = False - def directoryChanged(self, path): + def entryCreated(self, path, isDir=False): """ - Public slot to handle the directoryChanged signal of the watcher. + Public method to handle the creation of a file or directory. - @param path path of the directory + @param path path of the created file or directory @type str + @param isDir flag indicating a created directory (defaults to False) + @type bool (optional) """ if not self.__watcherActive: return - if path not in self.watchedItems: + parentPath = os.path.dirname(path) + if parentPath not in self.watchedDirItems: # just ignore the situation we don't have a reference to the item return - fileFilter = ( - (QDir.Filter.AllEntries | QDir.Filter.Hidden | QDir.Filter.NoDotAndDotDot) - if Preferences.getProject("BrowsersListHiddenFiles") - else QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot - ) - - for itm in self.watchedItems[path]: - oldCnt = itm.childCount() - - qdir = QDir(itm.dirName()) - - entryInfoList = qdir.entryInfoList(fileFilter) - - # step 1: check for new entries - children = itm.children() - for f in entryInfoList: - fpath = FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()) - childFound = False - for child in children[:]: - if child.name() == fpath: - childFound = True - children.remove(child) - break - if childFound: - continue + if not Preferences.getProject("BrowsersListHiddenFiles") and os.path.basename( + path + ).startswith("."): + return - cnt = itm.childCount() - self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt) - node = ( - ProjectBrowserDirectoryItem( - itm, - FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()), - itm.getProjectTypes()[0], - False, - ) - if f.isDir() - else ProjectBrowserFileItem( - itm, - FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()), - itm.getProjectTypes()[0], - ) + for itm in self.watchedDirItems[parentPath]: + cnt = itm.childCount() + self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt) + node = ( + ProjectBrowserDirectoryItem( + itm, + FileSystemUtilities.toNativeSeparators(path), + itm.getProjectTypes()[0], + False, + ) + if isDir + else ProjectBrowserFileItem( + itm, + FileSystemUtilities.toNativeSeparators(path), + itm.getProjectTypes()[0], ) - self._addItem(node, itm) - if self.project.vcs is not None: - self.project.vcs.clearStatusCache() - state = self.project.vcs.vcsRegisteredState(node.name()) - if state == VersionControlState.Controlled: - node.addVcsStatus(self.project.vcs.vcsName()) - else: - node.addVcsStatus(self.tr("local")) - self.endInsertRows() + ) + self._addItem(node, itm) + self.endInsertRows() + + def entryDeleted(self, path, isDir=False): + """ + Public method to handle the deletion of a file or directory. - # step 2: check for removed entries - if len(entryInfoList) != itm.childCount(): - for row in range(oldCnt - 1, -1, -1): - child = itm.child(row) - childname = FileSystemUtilities.fromNativeSeparators(child.name()) - entryFound = False - for f in entryInfoList[:]: - if f.absoluteFilePath() == childname: - entryFound = True - entryInfoList.remove(f) - break - if entryFound: - continue + @param path path of the deleted file or directory + @type str + @param isDir flag indicating a deleted directory (defaults to False) + @type bool (optional) + """ + if not self.__watcherActive: + return - self._removeWatchedItem(child) - self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row) - itm.removeChild(child) - self.endRemoveRows() + super().entryDeleted(path, isDir=isDir) def __addVCSStatus(self, item, name): """