82 self.__sysPathItem = None |
82 self.__sysPathItem = None |
83 |
83 |
84 self.__remotefsInterface = fsInterface |
84 self.__remotefsInterface = fsInterface |
85 |
85 |
86 if not nopopulate: |
86 if not nopopulate: |
87 self.watchedItems = {} |
87 self.watchedDirItems = {} |
88 self.watchedFileItems = {} |
88 self.watchedFileItems = {} |
89 self.watcher = QFileSystemWatcher(self) |
89 watcher = EricFileSystemWatcher.instance() |
90 self.watcher.directoryChanged.connect(self.directoryChanged) |
90 watcher.directoryCreated.connect(lambda x: self.entryCreated(x, isDir=True)) |
91 self.watcher.fileChanged.connect(self.fileChanged) |
91 watcher.directoryDeleted.connect(lambda x: self.entryDeleted(x, isDir=True)) |
|
92 watcher.fileCreated.connect(lambda x: self.entryCreated(x, isDir=False)) |
|
93 watcher.fileDeleted.connect(lambda x: self.entryDeleted(x, isDir=False)) |
|
94 watcher.fileModified.connect(self.fileChanged) |
92 |
95 |
93 rootData = QCoreApplication.translate("BrowserModel", "Name") |
96 rootData = QCoreApplication.translate("BrowserModel", "Name") |
94 self.rootItem = BrowserItem(None, rootData) |
97 self.rootItem = BrowserItem(None, rootData) |
95 |
98 |
96 self.__populateModel() |
99 self.__populateModel() |
332 if ( |
335 if ( |
333 dirName != "" |
336 dirName != "" |
334 and not FileSystemUtilities.isRemoteFileName(dirName) |
337 and not FileSystemUtilities.isRemoteFileName(dirName) |
335 and not dirName.startswith(("//", "\\\\")) |
338 and not dirName.startswith(("//", "\\\\")) |
336 ): |
339 ): |
337 if dirName not in self.watcher.directories(): |
340 EricFileSystemWatcher.instance().addPath(dirName) |
338 self.watcher.addPath(dirName) |
341 if dirName in self.watchedDirItems: |
339 if dirName in self.watchedItems: |
342 if itm not in self.watchedDirItems[dirName]: |
340 if itm not in self.watchedItems[dirName]: |
343 self.watchedDirItems[dirName].append(itm) |
341 self.watchedItems[dirName].append(itm) |
|
342 else: |
344 else: |
343 self.watchedItems[dirName] = [itm] |
345 self.watchedDirItems[dirName] = [itm] |
344 |
346 |
345 def _removeWatchedItem(self, itm): |
347 def _removeWatchedItem(self, itm): |
346 """ |
348 """ |
347 Protected method to remove a watched item. |
349 Protected method to remove a watched item. |
348 |
350 |
351 """ |
353 """ |
352 if isinstance(itm, BrowserDirectoryItem): |
354 if isinstance(itm, BrowserDirectoryItem): |
353 dirName = itm.dirName() |
355 dirName = itm.dirName() |
354 with contextlib.suppress(KeyError): |
356 with contextlib.suppress(KeyError): |
355 with contextlib.suppress(ValueError): |
357 with contextlib.suppress(ValueError): |
356 self.watchedItems[dirName].remove(itm) |
358 self.watchedDirItems[dirName].remove(itm) |
357 if len(self.watchedItems[dirName]) == 0: |
359 if len(self.watchedDirItems[dirName]) == 0: |
358 del self.watchedItems[dirName] |
360 del self.watchedDirItems[dirName] |
359 self.watcher.removePath(dirName) |
361 EricFileSystemWatcher.instance().removePath(dirName) |
360 |
362 |
361 def directoryChanged(self, path): |
363 def entryCreated(self, path, isDir=False): |
362 """ |
364 """ |
363 Public slot to handle the directoryChanged signal of the watcher. |
365 Public method to handle the creation of a file or directory. |
364 |
366 |
365 @param path path of the directory |
367 @param path path of the created file or directory |
366 @type str |
368 @type str |
367 """ |
369 @param isDir flag indicating a created directory (defaults to False) |
368 if path not in self.watchedItems: |
370 @type bool (optional) |
|
371 """ |
|
372 parentPath = os.path.dirname(path) |
|
373 if parentPath not in self.watchedDirItems: |
369 # just ignore the situation we don't have a reference to the item |
374 # just ignore the situation we don't have a reference to the item |
370 return |
375 return |
371 |
376 |
372 dirFilter = ( |
377 for itm in self.watchedDirItems[parentPath]: |
373 QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot | QDir.Filter.Hidden |
378 cnt = itm.childCount() |
374 ) |
379 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt) |
375 |
380 node = ( |
376 for itm in self.watchedItems[path]: |
381 BrowserDirectoryItem( |
377 oldCnt = itm.childCount() |
382 itm, |
378 |
383 FileSystemUtilities.toNativeSeparators(path), |
379 qdir = QDir(itm.dirName()) |
384 False, |
380 |
|
381 entryInfoList = qdir.entryInfoList(dirFilter) |
|
382 |
|
383 # step 1: check for new entries |
|
384 children = itm.children() |
|
385 for f in entryInfoList: |
|
386 fpath = FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()) |
|
387 childFound = False |
|
388 for child in children[:]: |
|
389 if child.name() == fpath: |
|
390 childFound = True |
|
391 children.remove(child) |
|
392 break |
|
393 if childFound: |
|
394 continue |
|
395 |
|
396 cnt = itm.childCount() |
|
397 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt) |
|
398 node = ( |
|
399 BrowserDirectoryItem( |
|
400 itm, |
|
401 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()), |
|
402 False, |
|
403 ) |
|
404 if f.isDir() |
|
405 else BrowserFileItem( |
|
406 itm, |
|
407 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()), |
|
408 ) |
|
409 ) |
385 ) |
410 self._addItem(node, itm) |
386 if isDir |
411 self.endInsertRows() |
387 else BrowserFileItem( |
412 |
388 itm, |
413 # step 2: check for removed entries |
389 FileSystemUtilities.toNativeSeparators(path), |
414 if len(entryInfoList) != itm.childCount(): |
390 ) |
415 for row in range(oldCnt - 1, -1, -1): |
391 ) |
416 child = itm.child(row) |
392 self._addItem(node, itm) |
417 childname = FileSystemUtilities.fromNativeSeparators(child.name()) |
393 self.endInsertRows() |
418 entryFound = False |
394 |
419 for f in entryInfoList[:]: |
395 def entryDeleted(self, path, isDir=False): # noqa: U100 |
420 if f.absoluteFilePath() == childname: |
396 """ |
421 entryFound = True |
397 Public method to handle the deletion of a file or directory. |
422 entryInfoList.remove(f) |
398 |
423 break |
399 @param path path of the deleted file or directory |
424 if entryFound: |
400 @type str |
425 continue |
401 @param isDir flag indicating a deleted directory (defaults to False) |
426 |
402 @type bool (optional) |
|
403 """ |
|
404 parentPath = os.path.dirname(path) |
|
405 if parentPath not in self.watchedDirItems: |
|
406 # just ignore the situation we don't have a reference to the item |
|
407 return |
|
408 |
|
409 for itm in self.watchedDirItems[parentPath]: |
|
410 for row in range(itm.childCount() - 1, -1, -1): |
|
411 child = itm.child(row) |
|
412 if child.name() == path: |
427 self._removeWatchedItem(child) |
413 self._removeWatchedItem(child) |
428 self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row) |
414 self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row) |
429 itm.removeChild(child) |
415 itm.removeChild(child) |
430 self.endRemoveRows() |
416 self.endRemoveRows() |
|
417 break |
431 |
418 |
432 def __populateModel(self): |
419 def __populateModel(self): |
433 """ |
420 """ |
434 Private method to populate the browser model. |
421 Private method to populate the browser model. |
435 """ |
422 """ |
1914 @return tuple with start end end line number |
1922 @return tuple with start end end line number |
1915 @rtype tuple of (int, int) |
1923 @rtype tuple of (int, int) |
1916 """ |
1924 """ |
1917 return (self._classObject.lineno, self._classObject.endlineno) |
1925 return (self._classObject.lineno, self._classObject.endlineno) |
1918 |
1926 |
|
1927 def colOffset(self): |
|
1928 """ |
|
1929 Public method to return the column offset of the item definition. |
|
1930 |
|
1931 @return column offset defining the object |
|
1932 @rtype int |
|
1933 """ |
|
1934 return self._classObject.coloffset |
|
1935 |
1919 def lessThan(self, other, column, order): |
1936 def lessThan(self, other, column, order): |
1920 """ |
1937 """ |
1921 Public method to check, if the item is less than the other one. |
1938 Public method to check, if the item is less than the other one. |
1922 |
1939 |
1923 @param other reference to item to compare against |
1940 @param other reference to item to compare against |
2045 @return tuple with start end end line number |
2062 @return tuple with start end end line number |
2046 @rtype tuple of (int, int) |
2063 @rtype tuple of (int, int) |
2047 """ |
2064 """ |
2048 return (self._functionObject.lineno, self._functionObject.endlineno) |
2065 return (self._functionObject.lineno, self._functionObject.endlineno) |
2049 |
2066 |
|
2067 def colOffset(self): |
|
2068 """ |
|
2069 Public method to return the column offset of the item definition. |
|
2070 |
|
2071 @return column offset defining the object |
|
2072 @rtype int |
|
2073 """ |
|
2074 return self._functionObject.coloffset |
|
2075 |
2050 def lessThan(self, other, column, order): |
2076 def lessThan(self, other, column, order): |
2051 """ |
2077 """ |
2052 Public method to check, if the item is less than the other one. |
2078 Public method to check, if the item is less than the other one. |
2053 |
2079 |
2054 @param other reference to item to compare against |
2080 @param other reference to item to compare against |