77 |
77 |
78 self.__sysPathInterpreter = "" |
78 self.__sysPathInterpreter = "" |
79 self.__sysPathItem = None |
79 self.__sysPathItem = None |
80 |
80 |
81 if not nopopulate: |
81 if not nopopulate: |
82 self.watchedItems = {} |
82 self.watchedDirItems = {} |
83 self.watchedFileItems = {} |
83 self.watchedFileItems = {} |
84 self.watcher = QFileSystemWatcher(self) |
84 watcher = EricFileSystemWatcher.instance() |
85 self.watcher.directoryChanged.connect(self.directoryChanged) |
85 watcher.directoryCreated.connect(lambda x: self.entryCreated(x, isDir=True)) |
86 self.watcher.fileChanged.connect(self.fileChanged) |
86 watcher.directoryDeleted.connect(lambda x: self.entryDeleted(x, isDir=True)) |
|
87 watcher.fileCreated.connect(lambda x: self.entryCreated(x, isDir=False)) |
|
88 watcher.fileDeleted.connect(lambda x: self.entryDeleted(x, isDir=False)) |
|
89 watcher.fileModified.connect(self.fileChanged) |
87 |
90 |
88 rootData = QCoreApplication.translate("BrowserModel", "Name") |
91 rootData = QCoreApplication.translate("BrowserModel", "Name") |
89 self.rootItem = BrowserItem(None, rootData) |
92 self.rootItem = BrowserItem(None, rootData) |
90 |
93 |
91 self.__populateModel() |
94 self.__populateModel() |
346 """ |
348 """ |
347 if isinstance(itm, BrowserDirectoryItem): |
349 if isinstance(itm, BrowserDirectoryItem): |
348 dirName = itm.dirName() |
350 dirName = itm.dirName() |
349 with contextlib.suppress(KeyError): |
351 with contextlib.suppress(KeyError): |
350 with contextlib.suppress(ValueError): |
352 with contextlib.suppress(ValueError): |
351 self.watchedItems[dirName].remove(itm) |
353 self.watchedDirItems[dirName].remove(itm) |
352 if len(self.watchedItems[dirName]) == 0: |
354 if len(self.watchedDirItems[dirName]) == 0: |
353 del self.watchedItems[dirName] |
355 del self.watchedDirItems[dirName] |
354 self.watcher.removePath(dirName) |
356 EricFileSystemWatcher.instance().removePath(dirName) |
355 |
357 |
356 def directoryChanged(self, path): |
358 def entryCreated(self, path, isDir=False): |
357 """ |
359 """ |
358 Public slot to handle the directoryChanged signal of the watcher. |
360 Public method to handle the creation of a file or directory. |
359 |
361 |
360 @param path path of the directory |
362 @param path path of the created file or directory |
361 @type str |
363 @type str |
362 """ |
364 @param isDir flag indicating a created directory (defaults to False) |
363 if path not in self.watchedItems: |
365 @type bool (optional) |
|
366 """ |
|
367 parentPath = os.path.dirname(path) |
|
368 if parentPath not in self.watchedDirItems: |
364 # just ignore the situation we don't have a reference to the item |
369 # just ignore the situation we don't have a reference to the item |
365 return |
370 return |
366 |
371 |
367 dirFilter = ( |
372 for itm in self.watchedDirItems[parentPath]: |
368 QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot | QDir.Filter.Hidden |
373 cnt = itm.childCount() |
369 ) |
374 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt) |
370 |
375 node = ( |
371 for itm in self.watchedItems[path]: |
376 BrowserDirectoryItem( |
372 oldCnt = itm.childCount() |
377 itm, |
373 |
378 FileSystemUtilities.toNativeSeparators(path), |
374 qdir = QDir(itm.dirName()) |
379 False, |
375 |
|
376 entryInfoList = qdir.entryInfoList(dirFilter) |
|
377 |
|
378 # step 1: check for new entries |
|
379 children = itm.children() |
|
380 for f in entryInfoList: |
|
381 fpath = FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()) |
|
382 childFound = False |
|
383 for child in children[:]: |
|
384 if child.name() == fpath: |
|
385 childFound = True |
|
386 children.remove(child) |
|
387 break |
|
388 if childFound: |
|
389 continue |
|
390 |
|
391 cnt = itm.childCount() |
|
392 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt) |
|
393 node = ( |
|
394 BrowserDirectoryItem( |
|
395 itm, |
|
396 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()), |
|
397 False, |
|
398 ) |
|
399 if f.isDir() |
|
400 else BrowserFileItem( |
|
401 itm, |
|
402 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()), |
|
403 ) |
|
404 ) |
380 ) |
405 self._addItem(node, itm) |
381 if isDir |
406 self.endInsertRows() |
382 else BrowserFileItem( |
407 |
383 itm, |
408 # step 2: check for removed entries |
384 FileSystemUtilities.toNativeSeparators(path), |
409 if len(entryInfoList) != itm.childCount(): |
385 ) |
410 for row in range(oldCnt - 1, -1, -1): |
386 ) |
411 child = itm.child(row) |
387 self._addItem(node, itm) |
412 childname = FileSystemUtilities.fromNativeSeparators(child.name()) |
388 self.endInsertRows() |
413 entryFound = False |
389 |
414 for f in entryInfoList[:]: |
390 def entryDeleted(self, path, isDir=False): # noqa: U100 |
415 if f.absoluteFilePath() == childname: |
391 """ |
416 entryFound = True |
392 Public method to handle the deletion of a file or directory. |
417 entryInfoList.remove(f) |
393 |
418 break |
394 @param path path of the deleted file or directory |
419 if entryFound: |
395 @type str |
420 continue |
396 @param isDir flag indicating a deleted directory (defaults to False) |
421 |
397 @type bool (optional) |
|
398 """ |
|
399 parentPath = os.path.dirname(path) |
|
400 if parentPath not in self.watchedDirItems: |
|
401 # just ignore the situation we don't have a reference to the item |
|
402 return |
|
403 |
|
404 for itm in self.watchedDirItems[parentPath]: |
|
405 for row in range(itm.childCount() - 1, -1, -1): |
|
406 child = itm.child(row) |
|
407 if child.name() == path: |
422 self._removeWatchedItem(child) |
408 self._removeWatchedItem(child) |
423 self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row) |
409 self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row) |
424 itm.removeChild(child) |
410 itm.removeChild(child) |
425 self.endRemoveRows() |
411 self.endRemoveRows() |
|
412 break |
426 |
413 |
427 def __populateModel(self): |
414 def __populateModel(self): |
428 """ |
415 """ |
429 Private method to populate the browser model. |
416 Private method to populate the browser model. |
430 """ |
417 """ |