src/eric7/Project/ProjectBrowserModel.py

branch
server
changeset 10680
306373ccf8fd
parent 10631
00f5aae565a3
parent 10679
4d3e0ce54322
child 10704
27d21e5163b8
equal deleted inserted replaced
10651:280a53840aa3 10680:306373ccf8fd
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,
238 self.project = parent 239 self.project = parent
239 self.__projectBrowser = None 240 self.__projectBrowser = None
240 241
241 self.__remotefsInterface = fsInterface 242 self.__remotefsInterface = fsInterface
242 243
243 self.watchedItems = {} 244 self.watchedDirItems = {}
245
244 self.__watcherActive = True 246 self.__watcherActive = True
245 self.watcher = QFileSystemWatcher(self) 247 watcher = EricFileSystemWatcher.instance()
246 self.watcher.directoryChanged.connect(self.directoryChanged) 248 watcher.directoryCreated.connect(lambda x: self.entryCreated(x, isDir=True))
249 watcher.directoryDeleted.connect(lambda x: self.entryDeleted(x, isDir=True))
250 watcher.fileCreated.connect(lambda x: self.entryCreated(x, isDir=False))
251 watcher.fileDeleted.connect(lambda x: self.entryDeleted(x, isDir=False))
247 252
248 self.inRefresh = False 253 self.inRefresh = False
249 254
250 self.colorNames = { 255 self.colorNames = {
251 "A": "VcsAdded", 256 "A": "VcsAdded",
447 """ 452 """
448 Public method called after a project has been closed. 453 Public method called after a project has been closed.
449 """ 454 """
450 self.__vcsStatus = {} 455 self.__vcsStatus = {}
451 456
452 self.watchedItems = {} 457 paths = list(self.watchedDirItems.keys())
453 watchedDirs = self.watcher.directories() 458 if paths:
454 if watchedDirs: 459 watcher = EricFileSystemWatcher.instance()
455 self.watcher.removePaths(watchedDirs) 460 watcher.removePaths(paths)
461 self.watchedDirItems.clear()
456 462
457 self.rootItem.removeChildren() 463 self.rootItem.removeChildren()
458 self.beginResetModel() 464 self.beginResetModel()
459 self.endResetModel() 465 self.endResetModel()
460 466
771 """ 777 """
772 Public method to stop monitoring the project file system. 778 Public method to stop monitoring the project file system.
773 """ 779 """
774 self.__watcherActive = False 780 self.__watcherActive = False
775 781
776 def directoryChanged(self, path): 782 def entryCreated(self, path, isDir=False):
777 """ 783 """
778 Public slot to handle the directoryChanged signal of the watcher. 784 Public method to handle the creation of a file or directory.
779 785
780 @param path path of the directory 786 @param path path of the created file or directory
781 @type str 787 @type str
788 @param isDir flag indicating a created directory (defaults to False)
789 @type bool (optional)
782 """ 790 """
783 if not self.__watcherActive: 791 if not self.__watcherActive:
784 return 792 return
785 793
786 if path not in self.watchedItems: 794 parentPath = os.path.dirname(path)
795 if parentPath not in self.watchedDirItems:
787 # just ignore the situation we don't have a reference to the item 796 # just ignore the situation we don't have a reference to the item
788 return 797 return
789 798
790 fileFilter = ( 799 if not Preferences.getProject("BrowsersListHiddenFiles") and os.path.basename(
791 (QDir.Filter.AllEntries | QDir.Filter.Hidden | QDir.Filter.NoDotAndDotDot) 800 path
792 if Preferences.getProject("BrowsersListHiddenFiles") 801 ).startswith("."):
793 else QDir.Filter.AllEntries | QDir.Filter.NoDotAndDotDot 802 return
794 ) 803
795 804 for itm in self.watchedDirItems[parentPath]:
796 for itm in self.watchedItems[path]: 805 cnt = itm.childCount()
797 oldCnt = itm.childCount() 806 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt)
798 807 node = (
799 qdir = QDir(itm.dirName()) 808 ProjectBrowserDirectoryItem(
800 809 itm,
801 entryInfoList = qdir.entryInfoList(fileFilter) 810 FileSystemUtilities.toNativeSeparators(path),
802 811 itm.getProjectTypes()[0],
803 # step 1: check for new entries 812 False,
804 children = itm.children() 813 fsInterface=self.__remotefsInterface,
805 for f in entryInfoList:
806 fpath = FileSystemUtilities.toNativeSeparators(f.absoluteFilePath())
807 childFound = False
808 for child in children[:]:
809 if child.name() == fpath:
810 childFound = True
811 children.remove(child)
812 break
813 if childFound:
814 continue
815
816 cnt = itm.childCount()
817 self.beginInsertRows(self.createIndex(itm.row(), 0, itm), cnt, cnt)
818 node = (
819 ProjectBrowserDirectoryItem(
820 itm,
821 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()),
822 itm.getProjectTypes()[0],
823 False,
824 fsInterface=self.__remotefsInterface,
825 )
826 if f.isDir()
827 else ProjectBrowserFileItem(
828 itm,
829 FileSystemUtilities.toNativeSeparators(f.absoluteFilePath()),
830 itm.getProjectTypes()[0],
831 fsInterface=self.__remotefsInterface,
832 )
833 ) 814 )
834 self._addItem(node, itm) 815 if isDir
835 if self.project.vcs is not None: 816 else ProjectBrowserFileItem(
836 self.project.vcs.clearStatusCache() 817 itm,
837 state = self.project.vcs.vcsRegisteredState(node.name()) 818 FileSystemUtilities.toNativeSeparators(path),
838 if state == VersionControlState.Controlled: 819 itm.getProjectTypes()[0],
839 node.addVcsStatus(self.project.vcs.vcsName()) 820 fsInterface=self.__remotefsInterface,
840 else: 821 )
841 node.addVcsStatus(self.tr("local")) 822 )
842 self.endInsertRows() 823 self._addItem(node, itm)
843 824 self.endInsertRows()
844 # step 2: check for removed entries 825
845 if len(entryInfoList) != itm.childCount(): 826 def entryDeleted(self, path, isDir=False):
846 for row in range(oldCnt - 1, -1, -1): 827 """
847 child = itm.child(row) 828 Public method to handle the deletion of a file or directory.
848 childname = FileSystemUtilities.fromNativeSeparators(child.name()) 829
849 entryFound = False 830 @param path path of the deleted file or directory
850 for f in entryInfoList[:]: 831 @type str
851 if f.absoluteFilePath() == childname: 832 @param isDir flag indicating a deleted directory (defaults to False)
852 entryFound = True 833 @type bool (optional)
853 entryInfoList.remove(f) 834 """
854 break 835 if not self.__watcherActive:
855 if entryFound: 836 return
856 continue 837
857 838 super().entryDeleted(path, isDir=isDir)
858 self._removeWatchedItem(child)
859 self.beginRemoveRows(self.createIndex(itm.row(), 0, itm), row, row)
860 itm.removeChild(child)
861 self.endRemoveRows()
862 839
863 def __addVCSStatus(self, item, name): 840 def __addVCSStatus(self, item, name):
864 """ 841 """
865 Private method used to set the vcs status of a node. 842 Private method used to set the vcs status of a node.
866 843
961 if itm.childCount(): 938 if itm.childCount():
962 index = self.createIndex(itm.row(), 0, itm) 939 index = self.createIndex(itm.row(), 0, itm)
963 self.beginRemoveRows(index, 0, itm.childCount() - 1) 940 self.beginRemoveRows(index, 0, itm.childCount() - 1)
964 itm.removeChildren() 941 itm.removeChildren()
965 self.endRemoveRows() 942 self.endRemoveRows()
943
944 # reset the module parser cache
966 ModuleParser.resetParsedModule(os.path.join(self.project.ppath, name)) 945 ModuleParser.resetParsedModule(os.path.join(self.project.ppath, name))
967 946
968 self.populateItem(itm, True) 947 self.populateItem(itm, True)
969 948
970 def projectPropertiesChanged(self): 949 def projectPropertiesChanged(self):

eric ide

mercurial