src/eric7/Project/ProjectBrowserModel.py

branch
eric7
changeset 10679
4d3e0ce54322
parent 10677
6ee2e475490c
child 10680
306373ccf8fd
child 10692
9becf9ca115c
equal deleted inserted replaced
10678:665f1084ebf9 10679:4d3e0ce54322
9 9
10 import contextlib 10 import contextlib
11 import os 11 import os
12 import re 12 import re
13 13
14 from PyQt6.QtCore import QDir, QFileSystemWatcher, QModelIndex, Qt, pyqtSignal 14 from PyQt6.QtCore import QDir, QModelIndex, Qt, pyqtSignal
15 from PyQt6.QtGui import QColor 15 from PyQt6.QtGui import QColor
16 16
17 from eric7 import Preferences 17 from eric7 import Preferences
18 from eric7.EricCore import EricFileSystemWatcher
18 from eric7.SystemUtilities import FileSystemUtilities 19 from eric7.SystemUtilities import FileSystemUtilities
19 from eric7.UI.BrowserModel import ( 20 from eric7.UI.BrowserModel import (
20 BrowserDirectoryItem, 21 BrowserDirectoryItem,
21 BrowserFileItem, 22 BrowserFileItem,
22 BrowserItem, 23 BrowserItem,
213 214
214 self.progDir = None 215 self.progDir = None
215 self.project = parent 216 self.project = parent
216 self.__projectBrowser = None 217 self.__projectBrowser = None
217 218
218 self.watchedItems = {} 219 self.watchedDirItems = {}
219 self.__watcherActive = True 220 self.__watcherActive = True
220 self.watcher = QFileSystemWatcher(self) 221 watcher = EricFileSystemWatcher.instance()
221 self.watcher.directoryChanged.connect(self.directoryChanged) 222 watcher.directoryCreated.connect(lambda x: self.entryCreated(x, isDir=True))
223 watcher.directoryDeleted.connect(lambda x: self.entryDeleted(x, isDir=True))
224 watcher.fileCreated.connect(lambda x: self.entryCreated(x, isDir=False))
225 watcher.fileDeleted.connect(lambda x: self.entryDeleted(x, isDir=False))
222 226
223 self.inRefresh = False 227 self.inRefresh = False
224 228
225 self.colorNames = { 229 self.colorNames = {
226 "A": "VcsAdded", 230 "A": "VcsAdded",
377 """ 381 """
378 Public method called after a project has been closed. 382 Public method called after a project has been closed.
379 """ 383 """
380 self.__vcsStatus = {} 384 self.__vcsStatus = {}
381 385
382 self.watchedItems = {} 386 paths = list(self.watchedDirItems.keys())
383 watchedDirs = self.watcher.directories() 387 if paths:
384 if watchedDirs: 388 watcher = EricFileSystemWatcher.instance()
385 self.watcher.removePaths(watchedDirs) 389 watcher.removePaths(paths)
390 self.watchedDirItems.clear()
386 391
387 self.rootItem.removeChildren() 392 self.rootItem.removeChildren()
388 self.beginResetModel() 393 self.beginResetModel()
389 self.endResetModel() 394 self.endResetModel()
390 395
681 """ 686 """
682 Public method to stop monitoring the project file system. 687 Public method to stop monitoring the project file system.
683 """ 688 """
684 self.__watcherActive = False 689 self.__watcherActive = False
685 690
686 def directoryChanged(self, path): 691 def entryCreated(self, path, isDir=False):
687 """ 692 """
688 Public slot to handle the directoryChanged signal of the watcher. 693 Public method to handle the creation of a file or directory.
689 694
690 @param path path of the directory 695 @param path path of the created file or directory
691 @type str 696 @type str
697 @param isDir flag indicating a created directory (defaults to False)
698 @type bool (optional)
692 """ 699 """
693 if not self.__watcherActive: 700 if not self.__watcherActive:
694 return 701 return
695 702
696 if path not in self.watchedItems: 703 parentPath = os.path.dirname(path)
704 if parentPath not in self.watchedDirItems:
697 # just ignore the situation we don't have a reference to the item 705 # just ignore the situation we don't have a reference to the item
698 return 706 return
699 707
700 fileFilter = ( 708 if not Preferences.getProject("BrowsersListHiddenFiles") and os.path.basename(
701 (QDir.Filter.AllEntries | QDir.Filter.Hidden | QDir.Filter.NoDotAndDotDot) 709 path
702 if Preferences.getProject("BrowsersListHiddenFiles") 710 ).startswith("."):
703 else QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot 711 return
704 ) 712
705 713 for itm in self.watchedDirItems[parentPath]:
706 for itm in self.watchedItems[path]: 714 cnt = itm.childCount()
707 oldCnt = itm.childCount() 715 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt)
708 716 node = (
709 qdir = QDir(itm.dirName()) 717 ProjectBrowserDirectoryItem(
710 718 itm,
711 entryInfoList = qdir.entryInfoList(fileFilter) 719 FileSystemUtilities.toNativeSeparators(path),
712 720 itm.getProjectTypes()[0],
713 # step 1: check for new entries 721 False,
714 children = itm.children()
715 for f in entryInfoList:
716 fpath = FileSystemUtilities.toNativeSeparators(f.absoluteFilePath())
717 childFound = False
718 for child in children[:]:
719 if child.name() == fpath:
720 childFound = True
721 children.remove(child)
722 break
723 if childFound:
724 continue
725
726 cnt = itm.childCount()
727 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt)
728 node = (
729 ProjectBrowserDirectoryItem(
730 itm,
731 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()),
732 itm.getProjectTypes()[0],
733 False,
734 )
735 if f.isDir()
736 else ProjectBrowserFileItem(
737 itm,
738 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()),
739 itm.getProjectTypes()[0],
740 )
741 ) 722 )
742 self._addItem(node, itm) 723 if isDir
743 if self.project.vcs is not None: 724 else ProjectBrowserFileItem(
744 self.project.vcs.clearStatusCache() 725 itm,
745 state = self.project.vcs.vcsRegisteredState(node.name()) 726 FileSystemUtilities.toNativeSeparators(path),
746 if state == VersionControlState.Controlled: 727 itm.getProjectTypes()[0],
747 node.addVcsStatus(self.project.vcs.vcsName()) 728 )
748 else: 729 )
749 node.addVcsStatus(self.tr("local")) 730 self._addItem(node, itm)
750 self.endInsertRows() 731 self.endInsertRows()
751 732
752 # step 2: check for removed entries 733 def entryDeleted(self, path, isDir=False):
753 if len(entryInfoList) != itm.childCount(): 734 """
754 for row in range(oldCnt - 1, -1, -1): 735 Public method to handle the deletion of a file or directory.
755 child = itm.child(row) 736
756 childname = FileSystemUtilities.fromNativeSeparators(child.name()) 737 @param path path of the deleted file or directory
757 entryFound = False 738 @type str
758 for f in entryInfoList[:]: 739 @param isDir flag indicating a deleted directory (defaults to False)
759 if f.absoluteFilePath() == childname: 740 @type bool (optional)
760 entryFound = True 741 """
761 entryInfoList.remove(f) 742 if not self.__watcherActive:
762 break 743 return
763 if entryFound: 744
764 continue 745 super().entryDeleted(path, isDir=isDir)
765
766 self._removeWatchedItem(child)
767 self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row)
768 itm.removeChild(child)
769 self.endRemoveRows()
770 746
771 def __addVCSStatus(self, item, name): 747 def __addVCSStatus(self, item, name):
772 """ 748 """
773 Private method used to set the vcs status of a node. 749 Private method used to set the vcs status of a node.
774 750

eric ide

mercurial