eric6/Project/ProjectBrowser.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7178
43e994af5ee0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Project/ProjectBrowser.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,415 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2002 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the project browser part of the eric6 UI.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import Qt
+from PyQt5.QtGui import QColor
+from PyQt5.QtWidgets import QApplication
+
+from E5Gui.E5TabWidget import E5TabWidget
+from E5Gui.E5Led import E5ClickableLed
+
+import UI.PixmapCache
+import Preferences
+
+from .ProjectBrowserFlags import SourcesBrowserFlag, FormsBrowserFlag, \
+    ResourcesBrowserFlag, TranslationsBrowserFlag, InterfacesBrowserFlag, \
+    OthersBrowserFlag, ProtocolsBrowserFlag, AllBrowsersFlag
+
+
+class ProjectBrowser(E5TabWidget):
+    """
+    Class implementing the project browser part of the eric6 UI.
+    
+    It generates a widget with up to seven tabs. The individual tabs contain
+    the project sources browser, the project forms browser,
+    the project resources browser, the project translations browser,
+    the project interfaces (IDL) browser and a browser for stuff,
+    that doesn't fit these categories. Optionally it contains an additional
+    tab with the file system browser.
+    """
+    def __init__(self, project, parent=None):
+        """
+        Constructor
+        
+        @param project reference to the project object
+        @param parent parent widget (QWidget)
+        """
+        E5TabWidget.__init__(self, parent)
+        self.project = project
+        
+        self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
+        
+        self.setUsesScrollButtons(True)
+        
+        self.vcsStatusIndicator = E5ClickableLed(self)
+        self.setCornerWidget(self.vcsStatusIndicator, Qt.TopLeftCorner)
+        self.vcsStatusIndicator.clicked.connect(
+            self.__vcsStatusIndicatorClicked)
+        self.vcsStatusColorNames = {
+            "A": "VcsAdded",
+            "M": "VcsModified",
+            "O": "VcsRemoved",
+            "R": "VcsReplaced",
+            "U": "VcsUpdate",
+            "Z": "VcsConflict",
+        }
+        self.vcsStatusText = {
+            " ": self.tr("up to date"),
+            "A": self.tr("files added"),
+            "M": self.tr("local modifications"),
+            "O": self.tr("files removed"),
+            "R": self.tr("files replaced"),
+            "U": self.tr("update required"),
+            "Z": self.tr("conflict"),
+        }
+        self.__vcsStateChanged(" ")
+        
+        # step 1: create all the individual browsers
+        from .ProjectSourcesBrowser import ProjectSourcesBrowser
+        from .ProjectFormsBrowser import ProjectFormsBrowser
+        from .ProjectTranslationsBrowser import ProjectTranslationsBrowser
+        from .ProjectResourcesBrowser import ProjectResourcesBrowser
+        from .ProjectInterfacesBrowser import ProjectInterfacesBrowser
+        from .ProjectOthersBrowser import ProjectOthersBrowser
+        from .ProjectProtocolsBrowser import ProjectProtocolsBrowser
+        # sources browser
+        self.psBrowser = ProjectSourcesBrowser(self.project)
+        # forms browser
+        self.pfBrowser = ProjectFormsBrowser(self.project)
+        # resources browser
+        self.prBrowser = ProjectResourcesBrowser(self.project)
+        # translations browser
+        self.ptBrowser = ProjectTranslationsBrowser(self.project)
+        # interfaces (IDL) browser
+        self.piBrowser = ProjectInterfacesBrowser(self.project)
+        # protocols (protobuf) browser
+        self.ppBrowser = ProjectProtocolsBrowser(self.project)
+        # others browser
+        self.poBrowser = ProjectOthersBrowser(self.project)
+        
+        # step 2: connect all the browsers
+        # connect the sources browser
+        self.project.projectClosed.connect(self.psBrowser._projectClosed)
+        self.project.projectOpened.connect(self.psBrowser._projectOpened)
+        self.project.newProject.connect(self.psBrowser._newProject)
+        self.project.reinitVCS.connect(self.psBrowser._initMenusAndVcs)
+        self.project.projectPropertiesChanged.connect(
+            self.psBrowser._initMenusAndVcs)
+        
+        # connect the forms browser
+        self.project.projectClosed.connect(self.pfBrowser._projectClosed)
+        self.project.projectOpened.connect(self.pfBrowser._projectOpened)
+        self.project.newProject.connect(self.pfBrowser._newProject)
+        self.project.reinitVCS.connect(self.pfBrowser._initMenusAndVcs)
+        self.project.projectPropertiesChanged.connect(
+            self.pfBrowser._initMenusAndVcs)
+        
+        # connect the resources browser
+        self.project.projectClosed.connect(self.prBrowser._projectClosed)
+        self.project.projectOpened.connect(self.prBrowser._projectOpened)
+        self.project.newProject.connect(self.prBrowser._newProject)
+        self.project.reinitVCS.connect(self.prBrowser._initMenusAndVcs)
+        self.project.projectPropertiesChanged.connect(
+            self.prBrowser._initMenusAndVcs)
+        
+        # connect the translations browser
+        self.project.projectClosed.connect(self.ptBrowser._projectClosed)
+        self.project.projectOpened.connect(self.ptBrowser._projectOpened)
+        self.project.newProject.connect(self.ptBrowser._newProject)
+        self.project.reinitVCS.connect(self.ptBrowser._initMenusAndVcs)
+        self.project.projectPropertiesChanged.connect(
+            self.ptBrowser._initMenusAndVcs)
+        
+        # connect the interfaces (IDL)  browser
+        self.project.projectClosed.connect(self.piBrowser._projectClosed)
+        self.project.projectOpened.connect(self.piBrowser._projectOpened)
+        self.project.newProject.connect(self.piBrowser._newProject)
+        self.project.reinitVCS.connect(self.piBrowser._initMenusAndVcs)
+        self.project.projectPropertiesChanged.connect(
+            self.piBrowser._initMenusAndVcs)
+        
+        # connect the protocols (protobuf)  browser
+        self.project.projectClosed.connect(self.ppBrowser._projectClosed)
+        self.project.projectOpened.connect(self.ppBrowser._projectOpened)
+        self.project.newProject.connect(self.ppBrowser._newProject)
+        self.project.reinitVCS.connect(self.ppBrowser._initMenusAndVcs)
+        self.project.projectPropertiesChanged.connect(
+            self.ppBrowser._initMenusAndVcs)
+        
+        # connect the others browser
+        self.project.projectClosed.connect(self.poBrowser._projectClosed)
+        self.project.projectOpened.connect(self.poBrowser._projectOpened)
+        self.project.newProject.connect(self.poBrowser._newProject)
+        self.project.reinitVCS.connect(self.poBrowser._initMenusAndVcs)
+        self.project.projectPropertiesChanged.connect(
+            self.poBrowser._initMenusAndVcs)
+        
+        # add signal connection to ourselves
+        self.project.projectOpened.connect(self.__projectOpened)
+        self.project.projectClosed.connect(self.__projectClosed)
+        self.project.newProject.connect(self.__newProject)
+        self.project.projectPropertiesChanged.connect(
+            self.__projectPropertiesChanged)
+        self.currentChanged.connect(self.__currentChanged)
+        self.project.getModel().vcsStateChanged.connect(self.__vcsStateChanged)
+        
+        self.__currentBrowsersFlags = 0
+        self.__projectPropertiesChanged()
+        self.setCurrentIndex(0)
+        
+    def __setBrowsersAvailable(self, browserFlags):
+        """
+        Private method to add selected browsers to the project browser.
+        
+        @param browserFlags flags indicating the browsers to add (integer)
+        """
+        # step 1: remove all tabs
+        while self.count() > 0:
+            self.removeTab(0)
+        
+        # step 2: add browsers
+        if browserFlags & SourcesBrowserFlag:
+            index = self.addTab(
+                self.psBrowser,
+                UI.PixmapCache.getIcon("projectSources.png"), '')
+            self.setTabToolTip(index, self.psBrowser.windowTitle())
+        
+        if browserFlags & FormsBrowserFlag:
+            index = self.addTab(
+                self.pfBrowser,
+                UI.PixmapCache.getIcon("projectForms.png"), '')
+            self.setTabToolTip(index, self.pfBrowser.windowTitle())
+        
+        if browserFlags & ResourcesBrowserFlag:
+            index = self.addTab(
+                self.prBrowser,
+                UI.PixmapCache.getIcon("projectResources.png"), '')
+            self.setTabToolTip(index, self.prBrowser.windowTitle())
+        
+        if browserFlags & TranslationsBrowserFlag:
+            index = self.addTab(
+                self.ptBrowser,
+                UI.PixmapCache.getIcon("projectTranslations.png"), '')
+            self.setTabToolTip(index, self.ptBrowser.windowTitle())
+        
+        if browserFlags & InterfacesBrowserFlag:
+            index = self.addTab(
+                self.piBrowser,
+                UI.PixmapCache.getIcon("projectInterfaces.png"), '')
+            self.setTabToolTip(index, self.piBrowser.windowTitle())
+        
+        if browserFlags & ProtocolsBrowserFlag:
+            index = self.addTab(
+                self.ppBrowser,
+                UI.PixmapCache.getIcon("protobuf.png"), '')
+            self.setTabToolTip(index, self.ppBrowser.windowTitle())
+        
+        if browserFlags & OthersBrowserFlag:
+            index = self.addTab(
+                self.poBrowser,
+                UI.PixmapCache.getIcon("projectOthers.png"), '')
+            self.setTabToolTip(index, self.poBrowser.windowTitle())
+        
+        QApplication.processEvents()
+        
+    def __currentChanged(self, index):
+        """
+        Private slot to handle the currentChanged(int) signal.
+        
+        @param index index of the tab (integer)
+        """
+        if index > -1:
+            browser = self.widget(index)
+            if browser is not None:
+                browser.layoutDisplay()
+        
+    def __projectOpened(self):
+        """
+        Private slot to handle the projectOpened signal.
+        """
+        self.__projectPropertiesChanged()
+        self.setCurrentIndex(0)
+        self.__vcsStateChanged(" ")
+        
+    def __projectClosed(self):
+        """
+        Private slot to handle the projectClosed signal.
+        """
+        self.__projectPropertiesChanged()
+        self.setCurrentIndex(0)
+        self.__setSourcesIcon()
+        self.__vcsStateChanged(" ")
+        
+    def __newProject(self):
+        """
+        Private slot to handle the newProject signal.
+        """
+        self.setCurrentIndex(0)
+        self.__projectPropertiesChanged()
+        
+    def __projectPropertiesChanged(self):
+        """
+        Private slot to handle the projectPropertiesChanged signal.
+        """
+        if self.project.isOpen():
+            flags = Preferences.getProjectBrowserFlags(
+                self.project.getProjectType())
+        else:
+            flags = AllBrowsersFlag
+        
+        if flags != self.__currentBrowsersFlags:
+            self.__currentBrowsersFlags = flags
+            self.__setBrowsersAvailable(flags)
+        
+        endIndex = self.count()
+        for index in range(endIndex):
+            self.setTabEnabled(index, self.project.isOpen())
+        
+        self.__setSourcesIcon()
+        
+    def __setSourcesIcon(self):
+        """
+        Private method to set the right icon for the sources browser tab.
+        """
+        if not self.project.isOpen():
+            icon = UI.PixmapCache.getIcon("projectSources.png")
+        else:
+            if self.project.getProjectLanguage() in \
+                    ["Python", "Python2", "Python3"]:
+                if self.project.isMixedLanguageProject():
+                    icon = UI.PixmapCache.getIcon("projectSourcesPyMixed.png")
+                else:
+                    icon = UI.PixmapCache.getIcon("projectSourcesPy.png")
+            elif self.project.getProjectLanguage() == "Ruby":
+                if self.project.isMixedLanguageProject():
+                    icon = UI.PixmapCache.getIcon("projectSourcesRbMixed.png")
+                else:
+                    icon = UI.PixmapCache.getIcon("projectSourcesRb.png")
+            elif self.project.getProjectLanguage() == "JavaScript":
+                icon = UI.PixmapCache.getIcon("projectSourcesJavaScript.png")
+            else:
+                icon = UI.PixmapCache.getIcon("projectSources.png")
+        self.setTabIcon(self.indexOf(self.psBrowser), icon)
+        
+    def handleEditorChanged(self, fn):
+        """
+        Public slot to handle the editorChanged signal.
+        
+        @param fn filename of the changed file (string)
+        """
+        if Preferences.getProject("FollowEditor"):
+            if self.project.isProjectSource(fn):
+                self.psBrowser.selectFile(fn)
+            elif self.project.isProjectForm(fn):
+                self.pfBrowser.selectFile(fn)
+            elif self.project.isProjectInterface(fn):
+                self.piBrowser.selectFile(fn)
+            elif self.project.isProjectProtocol(fn):
+                self.ppBrowser.selectFile(fn)
+            elif self.project.isProjectProtocol(fn):
+                self.ppBrowser.selectFile(fn)
+    
+    def handleEditorLineChanged(self, fn, lineno):
+        """
+        Public slot to handle the editorLineChanged signal.
+        
+        @param fn filename of the changed file (string)
+        @param lineno one based line number of the item (integer)
+        """
+        if Preferences.getProject("FollowEditor") and \
+           Preferences.getProject("FollowCursorLine"):
+            if self.project.isProjectSource(fn):
+                self.psBrowser.selectFileLine(fn, lineno)
+    
+    def getProjectBrowsers(self):
+        """
+        Public method to get references to the individual project browsers.
+        
+        @return list of references to project browsers
+        """
+        return [self.psBrowser, self.pfBrowser, self.prBrowser,
+                self.ptBrowser, self.piBrowser, self.ppBrowser,
+                self.poBrowser]
+    
+    def getProjectBrowser(self, name):
+        """
+        Public method to get a reference to the named project browser.
+        
+        @param name name of the requested project browser (string).
+            Valid names are "sources, forms, resources, translations,
+            interfaces, protocols, others".
+        @return reference to the requested browser or None
+        """
+        if name == "sources":
+            return self.psBrowser
+        elif name == "forms":
+            return self.pfBrowser
+        elif name == "resources":
+            return self.prBrowser
+        elif name == "translations":
+            return self.ptBrowser
+        elif name == "interfaces":
+            return self.piBrowser
+        elif name == "protocols":
+            return self.ppBrowser
+        elif name == "others":
+            return self.poBrowser
+        else:
+            return None
+    
+    def getProjectBrowserNames(self):
+        """
+        Public method to get the names of the various project browsers.
+        
+        @return list of project browser names (list of string)
+        """
+        return ["sources", "forms", "resources",
+                "translations", "interfaces", "protocols", "others"]
+    
+    def handlePreferencesChanged(self):
+        """
+        Public slot used to handle the preferencesChanged signal.
+        """
+        self.__projectPropertiesChanged()
+        self.__vcsStateChanged(self.currentVcsStatus)
+    
+    def __vcsStateChanged(self, state):
+        """
+        Private slot to handle a change in the vcs state.
+        
+        @param state new vcs state (string)
+        """
+        self.currentVcsStatus = state
+        if state == " " or state not in self.vcsStatusColorNames:
+            self.vcsStatusIndicator.setColor(QColor(Qt.lightGray))
+        else:
+            self.vcsStatusIndicator.setColor(
+                Preferences.getProjectBrowserColour(
+                    self.vcsStatusColorNames[state]))
+        if state not in self.vcsStatusText:
+            self.vcsStatusIndicator.setToolTip(self.tr("unknown status"))
+        else:
+            self.vcsStatusIndicator.setToolTip(self.vcsStatusText[state])
+    
+    def __vcsStatusIndicatorClicked(self, pos):
+        """
+        Private slot to react upon clicks on the VCS indicator LED.
+        
+        @param pos position of the click (QPoint)
+        """
+        vcs = self.project.getVcs()
+        if vcs:
+            if self.currentVcsStatus == " ":
+                # call log browser dialog
+                vcs.vcsLogBrowser(self.project.getProjectPath())
+            else:
+                # call status dialog
+                vcs.vcsStatus(self.project.getProjectPath())

eric ide

mercurial