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", |
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 |