src/eric7/Project/ProjectBrowser.py

Mon, 07 Nov 2022 17:19:58 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 07 Nov 2022 17:19:58 +0100
branch
eric7
changeset 9482
a2bc06a54d9d
parent 9473
3f23dbf37dbe
child 9512
6e29913ba7b6
permissions
-rw-r--r--

Corrected/acknowledged some bad import style and removed some obsolete code.

# -*- coding: utf-8 -*-

# Copyright (c) 2002 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the project browser part of the eric UI.
"""

from PyQt6.QtCore import Qt
from PyQt6.QtGui import QColor
from PyQt6.QtWidgets import QApplication

from eric7 import Preferences
from eric7.EricGui import EricPixmapCache
from eric7.EricWidgets.EricLed import EricClickableLed
from eric7.EricWidgets.EricTabWidget import EricTabWidget

from .ProjectBrowserFlags import (
    AllBrowsersFlag,
    FormsBrowserFlag,
    InterfacesBrowserFlag,
    OthersBrowserFlag,
    ProtocolsBrowserFlag,
    ResourcesBrowserFlag,
    SourcesBrowserFlag,
    TranslationsBrowserFlag,
)
from .ProjectFormsBrowser import ProjectFormsBrowser
from .ProjectInterfacesBrowser import ProjectInterfacesBrowser
from .ProjectOthersBrowser import ProjectOthersBrowser
from .ProjectProtocolsBrowser import ProjectProtocolsBrowser
from .ProjectResourcesBrowser import ProjectResourcesBrowser
from .ProjectSourcesBrowser import ProjectSourcesBrowser
from .ProjectTranslationsBrowser import ProjectTranslationsBrowser


class ProjectBrowser(EricTabWidget):
    """
    Class implementing the project browser part of the eric 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)
        """
        EricTabWidget.__init__(self, parent)
        self.project = project

        self.setWindowIcon(EricPixmapCache.getIcon("eric"))

        self.setUsesScrollButtons(True)

        self.vcsStatusIndicator = EricClickableLed(self)
        self.setCornerWidget(self.vcsStatusIndicator, Qt.Corner.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
        # 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, EricPixmapCache.getIcon("projectSources"), ""
            )
            self.setTabToolTip(index, self.psBrowser.windowTitle())

        if browserFlags & FormsBrowserFlag:
            index = self.addTab(
                self.pfBrowser, EricPixmapCache.getIcon("projectForms"), ""
            )
            self.setTabToolTip(index, self.pfBrowser.windowTitle())

        if browserFlags & ResourcesBrowserFlag:
            index = self.addTab(
                self.prBrowser, EricPixmapCache.getIcon("projectResources"), ""
            )
            self.setTabToolTip(index, self.prBrowser.windowTitle())

        if browserFlags & TranslationsBrowserFlag:
            index = self.addTab(
                self.ptBrowser, EricPixmapCache.getIcon("projectTranslations"), ""
            )
            self.setTabToolTip(index, self.ptBrowser.windowTitle())

        if browserFlags & InterfacesBrowserFlag:
            index = self.addTab(
                self.piBrowser, EricPixmapCache.getIcon("projectInterfaces"), ""
            )
            self.setTabToolTip(index, self.piBrowser.windowTitle())

        if browserFlags & ProtocolsBrowserFlag:
            index = self.addTab(self.ppBrowser, EricPixmapCache.getIcon("protobuf"), "")
            self.setTabToolTip(index, self.ppBrowser.windowTitle())

        if browserFlags & OthersBrowserFlag:
            index = self.addTab(
                self.poBrowser, EricPixmapCache.getIcon("projectOthers"), ""
            )
            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.
        """
        flags = (
            Preferences.getProjectBrowserFlags(self.project.getProjectType())
            if self.project.isOpen()
            else 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 = EricPixmapCache.getIcon("projectSources")
        else:
            if self.project.getProjectLanguage() == "Python3":
                if self.project.isMixedLanguageProject():
                    icon = EricPixmapCache.getIcon("projectSourcesPyMixed")
                else:
                    icon = EricPixmapCache.getIcon("projectSourcesPy")
            elif self.project.getProjectLanguage() == "MicroPython":
                icon = EricPixmapCache.getIcon("micropython")
            elif self.project.getProjectLanguage() == "Ruby":
                if self.project.isMixedLanguageProject():
                    icon = EricPixmapCache.getIcon("projectSourcesRbMixed")
                else:
                    icon = EricPixmapCache.getIcon("projectSourcesRb")
            elif self.project.getProjectLanguage() == "JavaScript":
                icon = EricPixmapCache.getIcon("projectSourcesJavaScript")
            else:
                icon = EricPixmapCache.getIcon("projectSources")
        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.isProjectResource(fn):
                self.prBrowser.selectFile(fn)
            elif self.project.isProjectInterface(fn):
                self.piBrowser.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")
            and 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
        """
        return {
            "sources": self.psBrowser,
            "forms": self.pfBrowser,
            "resources": self.prBrowser,
            "translations": self.ptBrowser,
            "interfaces": self.piBrowser,
            "protocols": self.ppBrowser,
            "others": self.poBrowser,
        }.get(name, 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.GlobalColor.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