Beispiel #1
0
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, embeddedBrowser=True):
        """
        Constructor
        
        @param project reference to the project object
        @param parent parent widget (QWidget)
        @param embeddedBrowser flag indicating whether the file browser should
            be included. This flag is set to False by those layouts, that
            have the file browser in a separate window or embedded
            in the debeug browser instead
        """
        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
        # 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)
        # others browser
        self.poBrowser = ProjectOthersBrowser(self.project)
        
        # add the file browser, if it should be embedded here
        self.embeddedBrowser = embeddedBrowser
        if embeddedBrowser:
            self.fileBrowser = Browser()
        
        # 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 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 ourself
        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()
        if self.embeddedBrowser:
            self.setCurrentWidget(self.fileBrowser)
        else:
            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 & OthersBrowserFlag:
            index = self.addTab(
                self.poBrowser,
                UI.PixmapCache.getIcon("projectOthers.png"), '')
            self.setTabToolTip(index, self.poBrowser.windowTitle())
        
        if self.embeddedBrowser:
            index = self.addTab(
                self.fileBrowser,
                UI.PixmapCache.getIcon("browser.png"), '')
            self.setTabToolTip(index, self.fileBrowser.windowTitle())
        
        QApplication.processEvents()
        
    def showEvent(self, evt):
        """
        Protected method handleing the show event.
        
        @param evt show event to handle (QShowEvent)
        """
        E5TabWidget.showEvent(self, evt)
        if self.embeddedBrowser:
            self.fileBrowser.layoutDisplay()
        
    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()
        if self.embeddedBrowser:
            self.setCurrentWidget(self.fileBrowser)
        else:
            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)
        
        if self.embeddedBrowser:
            endIndex = self.count() - 1
        else:
            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.pdata["PROGLANGUAGE"][0] in \
                    ["Python", "Python2", "Python3"]:
                if self.project.pdata["MIXEDLANGUAGE"][0]:
                    icon = UI.PixmapCache.getIcon("projectSourcesPyMixed.png")
                else:
                    icon = UI.PixmapCache.getIcon("projectSourcesPy.png")
            elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
                if self.project.pdata["MIXEDLANGUAGE"][0]:
                    icon = UI.PixmapCache.getIcon("projectSourcesRbMixed.png")
                else:
                    icon = UI.PixmapCache.getIcon("projectSourcesRb.png")
            elif self.project.pdata["PROGLANGUAGE"][0] == "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)
    
    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.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, 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 == "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", "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())
Beispiel #2
0
 def __init__(self, project, parent=None, embeddedBrowser=True):
     """
     Constructor
     
     @param project reference to the project object
     @param parent parent widget (QWidget)
     @param embeddedBrowser flag indicating whether the file browser should
         be included. This flag is set to False by those layouts, that
         have the file browser in a separate window or embedded
         in the debeug browser instead
     """
     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
     # 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)
     # others browser
     self.poBrowser = ProjectOthersBrowser(self.project)
     
     # add the file browser, if it should be embedded here
     self.embeddedBrowser = embeddedBrowser
     if embeddedBrowser:
         self.fileBrowser = Browser()
     
     # 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 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 ourself
     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()
     if self.embeddedBrowser:
         self.setCurrentWidget(self.fileBrowser)
     else:
         self.setCurrentIndex(0)
Beispiel #3
0
    def __init__(self, debugServer, docked, vm, parent=None,
                 embeddedShell=True, embeddedBrowser=True):
        """
        Constructor
        
        @param debugServer reference to the debug server object
        @param docked flag indicating a dock window
        @param vm reference to the viewmanager object
        @param parent parent widget (QWidget)
        @param embeddedShell flag indicating whether the shell should be
            included. This flag is set to False by those layouts, that have
            the interpreter shell in a separate window.
        @param embeddedBrowser flag indicating whether the file browser should
            be included. This flag is set to False by those layouts, that
            have the file browser in a separate window or embedded
            in the project browser instead.
        """
        super(DebugViewer, self).__init__(parent)
        
        self.debugServer = debugServer
        self.debugUI = None
        
        self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
        
        self.__mainLayout = QVBoxLayout()
        self.__mainLayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.__mainLayout)
        
        self.__tabWidget = E5TabWidget()
        self.__mainLayout.addWidget(self.__tabWidget)
        
        self.embeddedShell = embeddedShell
        if embeddedShell:
            from QScintilla.Shell import ShellAssembly
            # add the interpreter shell
            self.shellAssembly = ShellAssembly(debugServer, vm, False)
            self.shell = self.shellAssembly.shell()
            index = self.__tabWidget.addTab(
                self.shellAssembly,
                UI.PixmapCache.getIcon("shell.png"), '')
            self.__tabWidget.setTabToolTip(index, self.shell.windowTitle())
        
        self.embeddedBrowser = embeddedBrowser
        if embeddedBrowser:
            from UI.Browser import Browser
            # add the browser
            self.browser = Browser()
            index = self.__tabWidget.addTab(
                self.browser,
                UI.PixmapCache.getIcon("browser.png"), '')
            self.__tabWidget.setTabToolTip(index, self.browser.windowTitle())
        
        from .VariablesViewer import VariablesViewer
        # add the global variables viewer
        self.glvWidget = QWidget()
        self.glvWidgetVLayout = QVBoxLayout(self.glvWidget)
        self.glvWidgetVLayout.setContentsMargins(0, 0, 0, 0)
        self.glvWidgetVLayout.setSpacing(3)
        self.glvWidget.setLayout(self.glvWidgetVLayout)
        
        self.globalsViewer = VariablesViewer(self.glvWidget, True)
        self.glvWidgetVLayout.addWidget(self.globalsViewer)
        
        self.glvWidgetHLayout = QHBoxLayout()
        self.glvWidgetHLayout.setContentsMargins(3, 3, 3, 3)
        
        self.globalsFilterEdit = QLineEdit(self.glvWidget)
        self.globalsFilterEdit.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.glvWidgetHLayout.addWidget(self.globalsFilterEdit)
        self.globalsFilterEdit.setToolTip(
            self.tr("Enter regular expression patterns separated by ';'"
                    " to define variable filters. "))
        self.globalsFilterEdit.setWhatsThis(
            self.tr("Enter regular expression patterns separated by ';'"
                    " to define variable filters. All variables and"
                    " class attributes matched by one of the expressions"
                    " are not shown in the list above."))
        
        self.setGlobalsFilterButton = QPushButton(
            self.tr('Set'), self.glvWidget)
        self.glvWidgetHLayout.addWidget(self.setGlobalsFilterButton)
        self.glvWidgetVLayout.addLayout(self.glvWidgetHLayout)
        
        index = self.__tabWidget.addTab(
            self.glvWidget,
            UI.PixmapCache.getIcon("globalVariables.png"), '')
        self.__tabWidget.setTabToolTip(index, self.globalsViewer.windowTitle())
        
        self.setGlobalsFilterButton.clicked.connect(
            self.__setGlobalsFilter)
        self.globalsFilterEdit.returnPressed.connect(self.__setGlobalsFilter)
        
        # add the local variables viewer
        self.lvWidget = QWidget()
        self.lvWidgetVLayout = QVBoxLayout(self.lvWidget)
        self.lvWidgetVLayout.setContentsMargins(0, 0, 0, 0)
        self.lvWidgetVLayout.setSpacing(3)
        self.lvWidget.setLayout(self.lvWidgetVLayout)
        
        self.lvWidgetHLayout1 = QHBoxLayout()
        self.lvWidgetHLayout1.setContentsMargins(3, 3, 3, 3)
        
        self.stackComboBox = QComboBox(self.lvWidget)
        self.stackComboBox.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.lvWidgetHLayout1.addWidget(self.stackComboBox)

        self.sourceButton = QPushButton(self.tr('Source'), self.lvWidget)
        self.lvWidgetHLayout1.addWidget(self.sourceButton)
        self.sourceButton.setEnabled(False)
        self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout1)

        self.localsViewer = VariablesViewer(self.lvWidget, False)
        self.lvWidgetVLayout.addWidget(self.localsViewer)
        
        self.lvWidgetHLayout2 = QHBoxLayout()
        self.lvWidgetHLayout2.setContentsMargins(3, 3, 3, 3)
        
        self.localsFilterEdit = QLineEdit(self.lvWidget)
        self.localsFilterEdit.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.lvWidgetHLayout2.addWidget(self.localsFilterEdit)
        self.localsFilterEdit.setToolTip(
            self.tr(
                "Enter regular expression patterns separated by ';' to define "
                "variable filters. "))
        self.localsFilterEdit.setWhatsThis(
            self.tr(
                "Enter regular expression patterns separated by ';' to define "
                "variable filters. All variables and class attributes matched"
                " by one of the expressions are not shown in the list above."))
        
        self.setLocalsFilterButton = QPushButton(
            self.tr('Set'), self.lvWidget)
        self.lvWidgetHLayout2.addWidget(self.setLocalsFilterButton)
        self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout2)
        
        index = self.__tabWidget.addTab(
            self.lvWidget,
            UI.PixmapCache.getIcon("localVariables.png"), '')
        self.__tabWidget.setTabToolTip(index, self.localsViewer.windowTitle())
        
        self.sourceButton.clicked.connect(self.__showSource)
        self.stackComboBox.currentIndexChanged[int].connect(
            self.__frameSelected)
        self.setLocalsFilterButton.clicked.connect(self.__setLocalsFilter)
        self.localsFilterEdit.returnPressed.connect(self.__setLocalsFilter)
        
        from .CallStackViewer import CallStackViewer
        # add the call stack viewer
        self.callStackViewer = CallStackViewer(self.debugServer)
        index = self.__tabWidget.addTab(
            self.callStackViewer,
            UI.PixmapCache.getIcon("step.png"), "")
        self.__tabWidget.setTabToolTip(
            index, self.callStackViewer.windowTitle())
        self.callStackViewer.sourceFile.connect(self.sourceFile)
        self.callStackViewer.frameSelected.connect(
            self.__callStackFrameSelected)
        
        from .CallTraceViewer import CallTraceViewer
        # add the call trace viewer
        self.callTraceViewer = CallTraceViewer(self.debugServer)
        index = self.__tabWidget.addTab(
            self.callTraceViewer,
            UI.PixmapCache.getIcon("callTrace.png"), "")
        self.__tabWidget.setTabToolTip(
            index, self.callTraceViewer.windowTitle())
        self.callTraceViewer.sourceFile.connect(self.sourceFile)
        
        from .BreakPointViewer import BreakPointViewer
        # add the breakpoint viewer
        self.breakpointViewer = BreakPointViewer()
        self.breakpointViewer.setModel(self.debugServer.getBreakPointModel())
        index = self.__tabWidget.addTab(
            self.breakpointViewer,
            UI.PixmapCache.getIcon("breakpoints.png"), '')
        self.__tabWidget.setTabToolTip(
            index, self.breakpointViewer.windowTitle())
        self.breakpointViewer.sourceFile.connect(self.sourceFile)
        
        from .WatchPointViewer import WatchPointViewer
        # add the watch expression viewer
        self.watchpointViewer = WatchPointViewer()
        self.watchpointViewer.setModel(self.debugServer.getWatchPointModel())
        index = self.__tabWidget.addTab(
            self.watchpointViewer,
            UI.PixmapCache.getIcon("watchpoints.png"), '')
        self.__tabWidget.setTabToolTip(
            index, self.watchpointViewer.windowTitle())
        
        from .ExceptionLogger import ExceptionLogger
        # add the exception logger
        self.exceptionLogger = ExceptionLogger()
        index = self.__tabWidget.addTab(
            self.exceptionLogger,
            UI.PixmapCache.getIcon("exceptions.png"), '')
        self.__tabWidget.setTabToolTip(
            index, self.exceptionLogger.windowTitle())
        
        if self.embeddedShell:
            self.__tabWidget.setCurrentWidget(self.shellAssembly)
        else:
            if self.embeddedBrowser:
                self.__tabWidget.setCurrentWidget(self.browser)
            else:
                self.__tabWidget.setCurrentWidget(self.glvWidget)
        
        # add the threads viewer
        self.__mainLayout.addWidget(QLabel(self.tr("Threads:")))
        self.__threadList = QTreeWidget()
        self.__threadList.setHeaderLabels(
            [self.tr("ID"), self.tr("Name"),
             self.tr("State"), ""])
        self.__threadList.setSortingEnabled(True)
        self.__mainLayout.addWidget(self.__threadList)
        
        self.__doThreadListUpdate = True
        
        self.__threadList.currentItemChanged.connect(self.__threadSelected)
        
        self.__mainLayout.setStretchFactor(self.__tabWidget, 5)
        self.__mainLayout.setStretchFactor(self.__threadList, 1)
        
        self.currPage = None
        self.currentStack = None
        self.framenr = 0
        
        self.debugServer.clientStack.connect(self.handleClientStack)
        
        self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
        self.sourceButton.setVisible(not self.__autoViewSource)
Beispiel #4
0
class DebugViewer(QWidget):
    """
    Class implementing a widget conatining various debug related views.
    
    The individual tabs contain the interpreter shell (optional),
    the filesystem browser (optional), the two variables viewers
    (global and local), a breakpoint viewer, a watch expression viewer and
    the exception logger. Additionally a list of all threads is shown.
    
    @signal sourceFile(string, int) emitted to open a source file at a line
    """
    sourceFile = pyqtSignal(str, int)
    
    def __init__(self, debugServer, docked, vm, parent=None,
                 embeddedShell=True, embeddedBrowser=True):
        """
        Constructor
        
        @param debugServer reference to the debug server object
        @param docked flag indicating a dock window
        @param vm reference to the viewmanager object
        @param parent parent widget (QWidget)
        @param embeddedShell flag indicating whether the shell should be
            included. This flag is set to False by those layouts, that have
            the interpreter shell in a separate window.
        @param embeddedBrowser flag indicating whether the file browser should
            be included. This flag is set to False by those layouts, that
            have the file browser in a separate window or embedded
            in the project browser instead.
        """
        super(DebugViewer, self).__init__(parent)
        
        self.debugServer = debugServer
        self.debugUI = None
        
        self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
        
        self.__mainLayout = QVBoxLayout()
        self.__mainLayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.__mainLayout)
        
        self.__tabWidget = E5TabWidget()
        self.__mainLayout.addWidget(self.__tabWidget)
        
        self.embeddedShell = embeddedShell
        if embeddedShell:
            from QScintilla.Shell import ShellAssembly
            # add the interpreter shell
            self.shellAssembly = ShellAssembly(debugServer, vm, False)
            self.shell = self.shellAssembly.shell()
            index = self.__tabWidget.addTab(
                self.shellAssembly,
                UI.PixmapCache.getIcon("shell.png"), '')
            self.__tabWidget.setTabToolTip(index, self.shell.windowTitle())
        
        self.embeddedBrowser = embeddedBrowser
        if embeddedBrowser:
            from UI.Browser import Browser
            # add the browser
            self.browser = Browser()
            index = self.__tabWidget.addTab(
                self.browser,
                UI.PixmapCache.getIcon("browser.png"), '')
            self.__tabWidget.setTabToolTip(index, self.browser.windowTitle())
        
        from .VariablesViewer import VariablesViewer
        # add the global variables viewer
        self.glvWidget = QWidget()
        self.glvWidgetVLayout = QVBoxLayout(self.glvWidget)
        self.glvWidgetVLayout.setContentsMargins(0, 0, 0, 0)
        self.glvWidgetVLayout.setSpacing(3)
        self.glvWidget.setLayout(self.glvWidgetVLayout)
        
        self.globalsViewer = VariablesViewer(self.glvWidget, True)
        self.glvWidgetVLayout.addWidget(self.globalsViewer)
        
        self.glvWidgetHLayout = QHBoxLayout()
        self.glvWidgetHLayout.setContentsMargins(3, 3, 3, 3)
        
        self.globalsFilterEdit = QLineEdit(self.glvWidget)
        self.globalsFilterEdit.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.glvWidgetHLayout.addWidget(self.globalsFilterEdit)
        self.globalsFilterEdit.setToolTip(
            self.tr("Enter regular expression patterns separated by ';'"
                    " to define variable filters. "))
        self.globalsFilterEdit.setWhatsThis(
            self.tr("Enter regular expression patterns separated by ';'"
                    " to define variable filters. All variables and"
                    " class attributes matched by one of the expressions"
                    " are not shown in the list above."))
        
        self.setGlobalsFilterButton = QPushButton(
            self.tr('Set'), self.glvWidget)
        self.glvWidgetHLayout.addWidget(self.setGlobalsFilterButton)
        self.glvWidgetVLayout.addLayout(self.glvWidgetHLayout)
        
        index = self.__tabWidget.addTab(
            self.glvWidget,
            UI.PixmapCache.getIcon("globalVariables.png"), '')
        self.__tabWidget.setTabToolTip(index, self.globalsViewer.windowTitle())
        
        self.setGlobalsFilterButton.clicked.connect(
            self.__setGlobalsFilter)
        self.globalsFilterEdit.returnPressed.connect(self.__setGlobalsFilter)
        
        # add the local variables viewer
        self.lvWidget = QWidget()
        self.lvWidgetVLayout = QVBoxLayout(self.lvWidget)
        self.lvWidgetVLayout.setContentsMargins(0, 0, 0, 0)
        self.lvWidgetVLayout.setSpacing(3)
        self.lvWidget.setLayout(self.lvWidgetVLayout)
        
        self.lvWidgetHLayout1 = QHBoxLayout()
        self.lvWidgetHLayout1.setContentsMargins(3, 3, 3, 3)
        
        self.stackComboBox = QComboBox(self.lvWidget)
        self.stackComboBox.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.lvWidgetHLayout1.addWidget(self.stackComboBox)

        self.sourceButton = QPushButton(self.tr('Source'), self.lvWidget)
        self.lvWidgetHLayout1.addWidget(self.sourceButton)
        self.sourceButton.setEnabled(False)
        self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout1)

        self.localsViewer = VariablesViewer(self.lvWidget, False)
        self.lvWidgetVLayout.addWidget(self.localsViewer)
        
        self.lvWidgetHLayout2 = QHBoxLayout()
        self.lvWidgetHLayout2.setContentsMargins(3, 3, 3, 3)
        
        self.localsFilterEdit = QLineEdit(self.lvWidget)
        self.localsFilterEdit.setSizePolicy(
            QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.lvWidgetHLayout2.addWidget(self.localsFilterEdit)
        self.localsFilterEdit.setToolTip(
            self.tr(
                "Enter regular expression patterns separated by ';' to define "
                "variable filters. "))
        self.localsFilterEdit.setWhatsThis(
            self.tr(
                "Enter regular expression patterns separated by ';' to define "
                "variable filters. All variables and class attributes matched"
                " by one of the expressions are not shown in the list above."))
        
        self.setLocalsFilterButton = QPushButton(
            self.tr('Set'), self.lvWidget)
        self.lvWidgetHLayout2.addWidget(self.setLocalsFilterButton)
        self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout2)
        
        index = self.__tabWidget.addTab(
            self.lvWidget,
            UI.PixmapCache.getIcon("localVariables.png"), '')
        self.__tabWidget.setTabToolTip(index, self.localsViewer.windowTitle())
        
        self.sourceButton.clicked.connect(self.__showSource)
        self.stackComboBox.currentIndexChanged[int].connect(
            self.__frameSelected)
        self.setLocalsFilterButton.clicked.connect(self.__setLocalsFilter)
        self.localsFilterEdit.returnPressed.connect(self.__setLocalsFilter)
        
        from .CallStackViewer import CallStackViewer
        # add the call stack viewer
        self.callStackViewer = CallStackViewer(self.debugServer)
        index = self.__tabWidget.addTab(
            self.callStackViewer,
            UI.PixmapCache.getIcon("step.png"), "")
        self.__tabWidget.setTabToolTip(
            index, self.callStackViewer.windowTitle())
        self.callStackViewer.sourceFile.connect(self.sourceFile)
        self.callStackViewer.frameSelected.connect(
            self.__callStackFrameSelected)
        
        from .CallTraceViewer import CallTraceViewer
        # add the call trace viewer
        self.callTraceViewer = CallTraceViewer(self.debugServer)
        index = self.__tabWidget.addTab(
            self.callTraceViewer,
            UI.PixmapCache.getIcon("callTrace.png"), "")
        self.__tabWidget.setTabToolTip(
            index, self.callTraceViewer.windowTitle())
        self.callTraceViewer.sourceFile.connect(self.sourceFile)
        
        from .BreakPointViewer import BreakPointViewer
        # add the breakpoint viewer
        self.breakpointViewer = BreakPointViewer()
        self.breakpointViewer.setModel(self.debugServer.getBreakPointModel())
        index = self.__tabWidget.addTab(
            self.breakpointViewer,
            UI.PixmapCache.getIcon("breakpoints.png"), '')
        self.__tabWidget.setTabToolTip(
            index, self.breakpointViewer.windowTitle())
        self.breakpointViewer.sourceFile.connect(self.sourceFile)
        
        from .WatchPointViewer import WatchPointViewer
        # add the watch expression viewer
        self.watchpointViewer = WatchPointViewer()
        self.watchpointViewer.setModel(self.debugServer.getWatchPointModel())
        index = self.__tabWidget.addTab(
            self.watchpointViewer,
            UI.PixmapCache.getIcon("watchpoints.png"), '')
        self.__tabWidget.setTabToolTip(
            index, self.watchpointViewer.windowTitle())
        
        from .ExceptionLogger import ExceptionLogger
        # add the exception logger
        self.exceptionLogger = ExceptionLogger()
        index = self.__tabWidget.addTab(
            self.exceptionLogger,
            UI.PixmapCache.getIcon("exceptions.png"), '')
        self.__tabWidget.setTabToolTip(
            index, self.exceptionLogger.windowTitle())
        
        if self.embeddedShell:
            self.__tabWidget.setCurrentWidget(self.shellAssembly)
        else:
            if self.embeddedBrowser:
                self.__tabWidget.setCurrentWidget(self.browser)
            else:
                self.__tabWidget.setCurrentWidget(self.glvWidget)
        
        # add the threads viewer
        self.__mainLayout.addWidget(QLabel(self.tr("Threads:")))
        self.__threadList = QTreeWidget()
        self.__threadList.setHeaderLabels(
            [self.tr("ID"), self.tr("Name"),
             self.tr("State"), ""])
        self.__threadList.setSortingEnabled(True)
        self.__mainLayout.addWidget(self.__threadList)
        
        self.__doThreadListUpdate = True
        
        self.__threadList.currentItemChanged.connect(self.__threadSelected)
        
        self.__mainLayout.setStretchFactor(self.__tabWidget, 5)
        self.__mainLayout.setStretchFactor(self.__threadList, 1)
        
        self.currPage = None
        self.currentStack = None
        self.framenr = 0
        
        self.debugServer.clientStack.connect(self.handleClientStack)
        
        self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
        self.sourceButton.setVisible(not self.__autoViewSource)
        
    def preferencesChanged(self):
        """
        Public slot to handle the preferencesChanged signal.
        """
        self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
        self.sourceButton.setVisible(not self.__autoViewSource)
        
    def setDebugger(self, debugUI):
        """
        Public method to set a reference to the Debug UI.
        
        @param debugUI reference to the DebugUI object (DebugUI)
        """
        self.debugUI = debugUI
        self.debugUI.clientStack.connect(self.handleClientStack)
        self.callStackViewer.setDebugger(debugUI)
        
    def handleResetUI(self):
        """
        Public method to reset the SBVviewer.
        """
        self.globalsViewer.handleResetUI()
        self.localsViewer.handleResetUI()
        self.__setGlobalsFilter()
        self.__setLocalsFilter()
        self.sourceButton.setEnabled(False)
        self.currentStack = None
        self.stackComboBox.clear()
        self.__threadList.clear()
        if self.embeddedShell:
            self.__tabWidget.setCurrentWidget(self.shellAssembly)
        else:
            if self.embeddedBrowser:
                self.__tabWidget.setCurrentWidget(self.browser)
            else:
                self.__tabWidget.setCurrentWidget(self.glvWidget)
        self.breakpointViewer.handleResetUI()
        
    def handleRawInput(self):
        """
        Public slot to handle the switch to the shell in raw input mode.
        """
        if self.embeddedShell:
            self.saveCurrentPage()
            self.__tabWidget.setCurrentWidget(self.shellAssembly)
        
    def initCallStackViewer(self, projectMode):
        """
        Public method to initialize the call stack viewer.
        
        @param projectMode flag indicating to enable the project mode (boolean)
        """
        self.callStackViewer.clear()
        self.callStackViewer.setProjectMode(projectMode)
        
    def isCallTraceEnabled(self):
        """
        Public method to get the state of the call trace function.
        
        @return flag indicating the state of the call trace function (boolean)
        """
        return self.callTraceViewer.isCallTraceEnabled()
        
    def clearCallTrace(self):
        """
        Public method to clear the recorded call trace.
        """
        self.callTraceViewer.clear()
        
    def setCallTraceToProjectMode(self, enabled):
        """
        Public slot to set the call trace viewer to project mode.
        
        In project mode the call trace info is shown with project relative
        path names.
        
        @param enabled flag indicating to enable the project mode (boolean)
        """
        self.callTraceViewer.setProjectMode(enabled)
        
    def showVariables(self, vlist, globals):
        """
        Public method to show the variables in the respective window.
        
        @param vlist list of variables to display
        @param globals flag indicating global/local state
        """
        if globals:
            self.globalsViewer.showVariables(vlist, self.framenr)
        else:
            self.localsViewer.showVariables(vlist, self.framenr)
            
    def showVariable(self, vlist, globals):
        """
        Public method to show the variables in the respective window.
        
        @param vlist list of variables to display
        @param globals flag indicating global/local state
        """
        if globals:
            self.globalsViewer.showVariable(vlist)
        else:
            self.localsViewer.showVariable(vlist)
            
    def showVariablesTab(self, globals):
        """
        Public method to make a variables tab visible.
        
        @param globals flag indicating global/local state
        """
        if globals:
            self.__tabWidget.setCurrentWidget(self.glvWidget)
        else:
            self.__tabWidget.setCurrentWidget(self.lvWidget)
        
    def saveCurrentPage(self):
        """
        Public slot to save the current page.
        """
        self.currPage = self.__tabWidget.currentWidget()
        
    def restoreCurrentPage(self):
        """
        Public slot to restore the previously saved page.
        """
        if self.currPage is not None:
            self.__tabWidget.setCurrentWidget(self.currPage)
            
    def handleClientStack(self, stack):
        """
        Public slot to show the call stack of the program being debugged.
        
        @param stack list of tuples with call stack data (file name,
            line number, function name, formatted argument/values list)
        """
        block = self.stackComboBox.blockSignals(True)
        self.framenr = 0
        self.stackComboBox.clear()
        self.currentStack = stack
        self.sourceButton.setEnabled(len(stack) > 0)
        for s in stack:
            # just show base filename to make it readable
            s = (os.path.basename(s[0]), s[1], s[2])
            self.stackComboBox.addItem('{0}:{1}:{2}'.format(*s))
        self.stackComboBox.blockSignals(block)
        
    def setVariablesFilter(self, globalsFilter, localsFilter):
        """
        Public slot to set the local variables filter.
        
        @param globalsFilter filter list for global variable types
            (list of int)
        @param localsFilter filter list for local variable types (list of int)
        """
        self.globalsFilter = globalsFilter
        self.localsFilter = localsFilter
        
    def __showSource(self):
        """
        Private slot to handle the source button press to show the selected
        file.
        """
        index = self.stackComboBox.currentIndex()
        if index > -1 and self.currentStack:
            s = self.currentStack[index]
            self.sourceFile.emit(s[0], int(s[1]))
        
    def __frameSelected(self, frmnr):
        """
        Private slot to handle the selection of a new stack frame number.
        
        @param frmnr frame number (0 is the current frame) (int)
        """
        self.framenr = frmnr
        self.debugServer.remoteClientVariables(0, self.localsFilter, frmnr)
        
        if self.__autoViewSource:
            self.__showSource()
        
    def __setGlobalsFilter(self):
        """
        Private slot to set the global variable filter.
        """
        filter = self.globalsFilterEdit.text()
        self.debugServer.remoteClientSetFilter(1, filter)
        self.debugServer.remoteClientVariables(2, self.globalsFilter)
        
    def __setLocalsFilter(self):
        """
        Private slot to set the local variable filter.
        """
        filter = self.localsFilterEdit.text()
        self.debugServer.remoteClientSetFilter(0, filter)
        if self.currentStack:
            self.debugServer.remoteClientVariables(
                0, self.localsFilter, self.framenr)
        
    def handleDebuggingStarted(self):
        """
        Public slot to handle the start of a debugging session.
        
        This slot sets the variables filter expressions.
        """
        self.__setGlobalsFilter()
        self.__setLocalsFilter()
        self.showVariablesTab(False)
        
    def currentWidget(self):
        """
        Public method to get a reference to the current widget.
        
        @return reference to the current widget (QWidget)
        """
        return self.__tabWidget.currentWidget()
        
    def setCurrentWidget(self, widget):
        """
        Public slot to set the current page based on the given widget.
        
        @param widget reference to the widget (QWidget)
        """
        self.__tabWidget.setCurrentWidget(widget)
        
    def showThreadList(self, currentID, threadList):
        """
        Public method to show the thread list.
        
        @param currentID id of the current thread (integer)
        @param threadList list of dictionaries containing the thread data
        """
        citm = None
        
        self.__threadList.clear()
        for thread in threadList:
            if thread['broken']:
                state = self.tr("waiting at breakpoint")
            else:
                state = self.tr("running")
            itm = QTreeWidgetItem(self.__threadList,
                                  ["{0:d}".format(thread['id']),
                                   thread['name'], state])
            if thread['id'] == currentID:
                citm = itm
        
        self.__threadList.header().resizeSections(QHeaderView.ResizeToContents)
        self.__threadList.header().setStretchLastSection(True)
        
        if citm:
            self.__doThreadListUpdate = False
            self.__threadList.setCurrentItem(citm)
            self.__doThreadListUpdate = True
        
    def __threadSelected(self, current, previous):
        """
        Private slot to handle the selection of a thread in the thread list.
        
        @param current reference to the new current item (QTreeWidgetItem)
        @param previous reference to the previous current item
            (QTreeWidgetItem)
        """
        if current is not None and self.__doThreadListUpdate:
            tid = int(current.text(0))
            self.debugServer.remoteSetThread(tid)
    
    def __callStackFrameSelected(self, frameNo):
        """
        Private slot to handle the selection of a call stack entry of the
        call stack viewer.
        
        @param frameNo frame number (index) of the selected entry (integer)
        """
        if frameNo >= 0:
            self.stackComboBox.setCurrentIndex(frameNo)
Beispiel #5
0
    def __init__(self, project, parent=None, embeddedBrowser=True):
        """
        Constructor
        
        @param project reference to the project object
        @param parent parent widget (QWidget)
        @param embeddedBrowser flag indicating whether the file browser should
            be included. This flag is set to False by those layouts, that
            have the file browser in a separate window or embedded
            in the debeug browser instead
        """
        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
        # 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)
        # others browser
        self.poBrowser = ProjectOthersBrowser(self.project)

        # add the file browser, if it should be embedded here
        self.embeddedBrowser = embeddedBrowser
        if embeddedBrowser:
            self.fileBrowser = Browser()

        # 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 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 ourself
        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()
        if self.embeddedBrowser:
            self.setCurrentWidget(self.fileBrowser)
        else:
            self.setCurrentIndex(0)
Beispiel #6
0
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, embeddedBrowser=True):
        """
        Constructor
        
        @param project reference to the project object
        @param parent parent widget (QWidget)
        @param embeddedBrowser flag indicating whether the file browser should
            be included. This flag is set to False by those layouts, that
            have the file browser in a separate window or embedded
            in the debeug browser instead
        """
        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
        # 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)
        # others browser
        self.poBrowser = ProjectOthersBrowser(self.project)

        # add the file browser, if it should be embedded here
        self.embeddedBrowser = embeddedBrowser
        if embeddedBrowser:
            self.fileBrowser = Browser()

        # 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 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 ourself
        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()
        if self.embeddedBrowser:
            self.setCurrentWidget(self.fileBrowser)
        else:
            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 & OthersBrowserFlag:
            index = self.addTab(self.poBrowser,
                                UI.PixmapCache.getIcon("projectOthers.png"),
                                '')
            self.setTabToolTip(index, self.poBrowser.windowTitle())

        if self.embeddedBrowser:
            index = self.addTab(self.fileBrowser,
                                UI.PixmapCache.getIcon("browser.png"), '')
            self.setTabToolTip(index, self.fileBrowser.windowTitle())

        QApplication.processEvents()

    def showEvent(self, evt):
        """
        Protected method handleing the show event.
        
        @param evt show event to handle (QShowEvent)
        """
        E5TabWidget.showEvent(self, evt)
        if self.embeddedBrowser:
            self.fileBrowser.layoutDisplay()

    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()
        if self.embeddedBrowser:
            self.setCurrentWidget(self.fileBrowser)
        else:
            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)

        if self.embeddedBrowser:
            endIndex = self.count() - 1
        else:
            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.pdata["PROGLANGUAGE"][0] in \
                    ["Python", "Python2", "Python3"]:
                if self.project.pdata["MIXEDLANGUAGE"][0]:
                    icon = UI.PixmapCache.getIcon("projectSourcesPyMixed.png")
                else:
                    icon = UI.PixmapCache.getIcon("projectSourcesPy.png")
            elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
                if self.project.pdata["MIXEDLANGUAGE"][0]:
                    icon = UI.PixmapCache.getIcon("projectSourcesRbMixed.png")
                else:
                    icon = UI.PixmapCache.getIcon("projectSourcesRb.png")
            elif self.project.pdata["PROGLANGUAGE"][0] == "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)

    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.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, 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 == "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",
            "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())
class DebugViewer(QWidget):
    """
    Class implementing a widget conatining various debug related views.
    
    The individual tabs contain the interpreter shell (optional), 
    the filesystem browser (optional), the two variables viewers (global and local),
    a breakpoint viewer, a watch expression viewer and the exception logger. Additionally
    a list of all threads is shown.
    
    @signal sourceFile(string, int) emitted to open a source file at a line
    """
    def __init__(self, debugServer, docked, vm, parent = None, 
                 embeddedShell = True, embeddedBrowser = True):
        """
        Constructor
        
        @param debugServer reference to the debug server object
        @param docked flag indicating a dock window
        @param vm reference to the viewmanager object
        @param parent parent widget (QWidget)
        @param embeddedShell flag indicating whether the shell should be included.
                This flag is set to False by those layouts, that have the interpreter
                shell in a separate window.
        @param embeddedBrowser flag indicating whether the file browser should
                be included. This flag is set to False by those layouts, that
                have the file browser in a separate window or embedded
                in the project browser instead.
        """
        QWidget.__init__(self, parent)
        
        self.debugServer = debugServer
        self.debugUI = None
        
        self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
        
        self.__mainLayout = QVBoxLayout()
        self.__mainLayout.setMargin(0)
        self.setLayout(self.__mainLayout)
        
        self.__tabWidget = E4TabWidget()
        self.__mainLayout.addWidget(self.__tabWidget)
        
        self.embeddedShell = embeddedShell
        if embeddedShell:
            # add the interpreter shell
            self.shell = Shell(debugServer, vm)
            index = self.__tabWidget.addTab(self.shell, 
                UI.PixmapCache.getIcon("shell.png"), '')
            self.__tabWidget.setTabToolTip(index, self.shell.windowTitle())
        
        self.embeddedBrowser = embeddedBrowser
        if embeddedBrowser:
            from UI.Browser import Browser
            # add the browser
            self.browser = Browser()
            index = self.__tabWidget.addTab(self.browser, 
                UI.PixmapCache.getIcon("browser.png"), '')
            self.__tabWidget.setTabToolTip(index, self.browser.windowTitle())
        
        # add the global variables viewer
        self.glvWidget = QWidget()
        self.glvWidgetVLayout = QVBoxLayout(self.glvWidget)
        self.glvWidgetVLayout.setMargin(0)
        self.glvWidgetVLayout.setSpacing(3)
        self.glvWidget.setLayout(self.glvWidgetVLayout)
        
        self.globalsViewer = VariablesViewer(self.glvWidget, True)
        self.glvWidgetVLayout.addWidget(self.globalsViewer)
        
        self.glvWidgetHLayout = QHBoxLayout()
        self.glvWidgetHLayout.setMargin(3)
        
        self.globalsFilterEdit = QLineEdit(self.glvWidget)
        self.globalsFilterEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.glvWidgetHLayout.addWidget(self.globalsFilterEdit)
        self.globalsFilterEdit.setToolTip(\
            self.trUtf8("Enter regular expression patterns separated by ';' to define "
                "variable filters. "))
        self.globalsFilterEdit.setWhatsThis(\
            self.trUtf8("Enter regular expression patterns separated by ';' to define "
                "variable filters. All variables and class attributes matched by one of "
                "the expressions are not shown in the list above."))
        
        self.setGlobalsFilterButton = QPushButton(self.trUtf8('Set'), self.glvWidget)
        self.glvWidgetHLayout.addWidget(self.setGlobalsFilterButton)
        self.glvWidgetVLayout.addLayout(self.glvWidgetHLayout)
        
        index = self.__tabWidget.addTab(self.glvWidget,
            UI.PixmapCache.getIcon("globalVariables.png"), '')
        self.__tabWidget.setTabToolTip(index, self.globalsViewer.windowTitle())
        
        self.connect(self.setGlobalsFilterButton, SIGNAL('clicked()'),
                     self.__setGlobalsFilter)
        self.connect(self.globalsFilterEdit, SIGNAL('returnPressed()'),
                     self.__setGlobalsFilter)
        
        # add the local variables viewer
        self.lvWidget = QWidget()
        self.lvWidgetVLayout = QVBoxLayout(self.lvWidget)
        self.lvWidgetVLayout.setMargin(0)
        self.lvWidgetVLayout.setSpacing(3)
        self.lvWidget.setLayout(self.lvWidgetVLayout)
        
        self.lvWidgetHLayout1 = QHBoxLayout()
        self.lvWidgetHLayout1.setMargin(3)
        
        self.stackComboBox = QComboBox(self.lvWidget)
        self.stackComboBox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.lvWidgetHLayout1.addWidget(self.stackComboBox)

        self.sourceButton = QPushButton(self.trUtf8('Source'), self.lvWidget)
        self.lvWidgetHLayout1.addWidget(self.sourceButton)
        self.sourceButton.setEnabled(False)
        self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout1)

        self.localsViewer = VariablesViewer(self.lvWidget, False)
        self.lvWidgetVLayout.addWidget(self.localsViewer)
        
        self.lvWidgetHLayout2 = QHBoxLayout()
        self.lvWidgetHLayout2.setMargin(3)
        
        self.localsFilterEdit = QLineEdit(self.lvWidget)
        self.localsFilterEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.lvWidgetHLayout2.addWidget(self.localsFilterEdit)
        self.localsFilterEdit.setToolTip(\
            self.trUtf8("Enter regular expression patterns separated by ';' to define "
                "variable filters. "))
        self.localsFilterEdit.setWhatsThis(\
            self.trUtf8("Enter regular expression patterns separated by ';' to define "
                "variable filters. All variables and class attributes matched by one of "
                "the expressions are not shown in the list above."))
        
        self.setLocalsFilterButton = QPushButton(self.trUtf8('Set'), self.lvWidget)
        self.lvWidgetHLayout2.addWidget(self.setLocalsFilterButton)
        self.lvWidgetVLayout.addLayout(self.lvWidgetHLayout2)
        
        index = self.__tabWidget.addTab(self.lvWidget,
            UI.PixmapCache.getIcon("localVariables.png"), '')
        self.__tabWidget.setTabToolTip(index, self.localsViewer.windowTitle())
        
        self.connect(self.sourceButton, SIGNAL('clicked()'), 
                     self.__showSource)
        self.connect(self.stackComboBox, SIGNAL('activated(int)'), 
                     self.__frameSelected)
        self.connect(self.setLocalsFilterButton, SIGNAL('clicked()'),
                     self.__setLocalsFilter)
        self.connect(self.localsFilterEdit, SIGNAL('returnPressed()'),
                     self.__setLocalsFilter)
        
        # add the breakpoint viewer
        self.breakpointViewer = BreakPointViewer()
        self.breakpointViewer.setModel(self.debugServer.getBreakPointModel())
        index = self.__tabWidget.addTab(self.breakpointViewer,
            UI.PixmapCache.getIcon("breakpoints.png"), '')
        self.__tabWidget.setTabToolTip(index, self.breakpointViewer.windowTitle())
        self.connect(self.breakpointViewer, SIGNAL("sourceFile"),
                     self, SIGNAL("sourceFile"))
        
        # add the watch expression viewer
        self.watchpointViewer = WatchPointViewer()
        self.watchpointViewer.setModel(self.debugServer.getWatchPointModel())
        index = self.__tabWidget.addTab(self.watchpointViewer,
            UI.PixmapCache.getIcon("watchpoints.png"), '')
        self.__tabWidget.setTabToolTip(index, self.watchpointViewer.windowTitle())
        
        # add the exception logger
        self.exceptionLogger = ExceptionLogger()
        index = self.__tabWidget.addTab(self.exceptionLogger, 
            UI.PixmapCache.getIcon("exceptions.png"), '')
        self.__tabWidget.setTabToolTip(index, self.exceptionLogger.windowTitle())
        
        if self.embeddedShell:
            self.__tabWidget.setCurrentWidget(self.shell)
        else:
            if self.embeddedBrowser:
                self.__tabWidget.setCurrentWidget(self.browser)
            else:
                self.__tabWidget.setCurrentWidget(self.lvWidget)
        
        # add the threads viewer
        self.__mainLayout.addWidget(QLabel(self.trUtf8("Threads:")))
        self.__threadList = QTreeWidget()
        self.__threadList.setHeaderLabels([self.trUtf8("ID"), self.trUtf8("Name"), 
                                           self.trUtf8("State"), ""])
        self.__threadList.setSortingEnabled(True)
        self.__mainLayout.addWidget(self.__threadList)
        
        self.__doThreadListUpdate = True
        
        self.connect(self.__threadList, 
                     SIGNAL('currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)'), 
                     self.__threadSelected)
        
        self.__mainLayout.setStretchFactor(self.__tabWidget, 5)
        self.__mainLayout.setStretchFactor(self.__threadList, 1)
        
        self.currPage = None
        self.currentStack = None
        self.framenr = 0
        
        self.connect(self.debugServer, SIGNAL('clientStack'), self.handleClientStack)
        
        self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
        self.sourceButton.setVisible(not self.__autoViewSource)
        
    def preferencesChanged(self):
        """
        Public slot to handle the preferencesChanged signal.
        """
        self.__autoViewSource = Preferences.getDebugger("AutoViewSourceCode")
        self.sourceButton.setVisible(not self.__autoViewSource)
        
    def setDebugger(self, debugUI):
        """
        Public method to set a reference to the Debug UI.
        
        @param debugUI reference to the DebugUI objectTrees
        """
        self.debugUI = debugUI
        self.connect(self.debugUI, SIGNAL('clientStack'), self.handleClientStack)
        
    def handleResetUI(self):
        """
        Public method to reset the SBVviewer.
        """
        self.globalsViewer.handleResetUI()
        self.localsViewer.handleResetUI()
        self.stackComboBox.clear()
        self.sourceButton.setEnabled(False)
        self.currentStack = None
        self.__threadList.clear()
        if self.embeddedShell:
            self.__tabWidget.setCurrentWidget(self.shell)
        else:
            if self.embeddedBrowser:
                self.__tabWidget.setCurrentWidget(self.browser)
            else:
                self.__tabWidget.setCurrentWidget(self.lvWidget)
        self.breakpointViewer.handleResetUI()
        
    def handleRawInput(self):
        """
        Pulic slot to handle the switch to the shell in raw input mode.
        """
        if self.embeddedShell:
            self.saveCurrentPage()
            self.__tabWidget.setCurrentWidget(self.shell)
            
    def showVariables(self, vlist, globals):
        """
        Public method to show the variables in the respective window.
        
        @param vlist list of variables to display
        @param globals flag indicating global/local state
        """
        if globals:
            self.globalsViewer.showVariables(vlist, self.framenr)
        else:
            self.localsViewer.showVariables(vlist, self.framenr)
            
    def showVariable(self, vlist, globals):
        """
        Public method to show the variables in the respective window.
        
        @param vlist list of variables to display
        @param globals flag indicating global/local state
        """
        if globals:
            self.globalsViewer.showVariable(vlist)
        else:
            self.localsViewer.showVariable(vlist)
            
    def showVariablesTab(self, globals):
        """
        Public method to make a variables tab visible.
        
        @param globals flag indicating global/local state
        """
        if globals:
            self.__tabWidget.setCurrentWidget(self.glvWidget)
        else:
            self.__tabWidget.setCurrentWidget(self.lvWidget)
        
    def saveCurrentPage(self):
        """
        Public slot to save the current page.
        """
        self.currPage = self.__tabWidget.currentWidget()
        
    def restoreCurrentPage(self):
        """
        Public slot to restore the previously saved page.
        """
        if self.currPage is not None:
            self.__tabWidget.setCurrentWidget(self.currPage)
            
    def handleClientStack(self, stack):
        """
        Public slot to show the call stack of the program being debugged.
        """
        self.framenr = 0
        self.stackComboBox.clear()
        self.currentStack = stack
        self.sourceButton.setEnabled(len(stack) > 0)
        for s in stack:
            # just show base filename to make it readable
            s = (os.path.basename(s[0]), s[1], s[2])
            self.stackComboBox.addItem('%s:%s:%s' % s)
        
    def setVariablesFilter(self, globalsFilter, localsFilter):
        """
        Public slot to set the local variables filter.
        
        @param globalsFilter filter list for global variable types (list of int)
        @param localsFilter filter list for local variable types (list of int)
        """
        self.globalsFilter = globalsFilter
        self.localsFilter = localsFilter
        
    def __showSource(self):
        """
        Private slot to handle the source button press to show the selected file.
        """
        s = self.currentStack[self.stackComboBox.currentIndex()]
        self.emit(SIGNAL('sourceFile'), s[0], int(s[1]))
        
    def __frameSelected(self, frmnr):
        """
        Private slot to handle the selection of a new stack frame number.
        
        @param frmnr frame number (0 is the current frame) (int)
        """
        self.framenr = frmnr
        self.debugServer.remoteClientVariables(0, self.localsFilter, frmnr)
        
        if self.__autoViewSource:
            self.__showSource()
        
    def __setGlobalsFilter(self):
        """
        Private slot to set the global variable filter
        """
        filter = unicode(self.globalsFilterEdit.text())
        self.debugServer.remoteClientSetFilter(1, filter)
        if self.currentStack:
            self.debugServer.remoteClientVariables(2, self.globalsFilter)
        
    def __setLocalsFilter(self):
        """
        Private slot to set the local variable filter
        """
        filter = unicode(self.localsFilterEdit.text())
        self.debugServer.remoteClientSetFilter(0, filter)
        if self.currentStack:
            self.debugServer.remoteClientVariables(0, self.localsFilter, self.framenr)
        
    def handleDebuggingStarted(self):
        """
        Public slot to handle the start of a debugging session.
        
        This slot sets the variables filter expressions.
        """
        self.__setGlobalsFilter()
        self.__setLocalsFilter()
        self.showVariablesTab(False)
        
    def currentWidget(self):
        """
        Public method to get a reference to the current widget.
        
        @return reference to the current widget (QWidget)
        """
        return self.__tabWidget.currentWidget()
        
    def setCurrentWidget(self, widget):
        """
        Public slot to set the current page based on the given widget.
        
        @param widget reference to the widget (QWidget)
        """
        self.__tabWidget.setCurrentWidget(widget)
        
    def showThreadList(self, currentID, threadList):
        """
        Public method to show the thread list.
        
        @param currentID id of the current thread (integer)
        @param threadList list of dictionaries containing the thread data
        """
        citm = None
        
        self.__threadList.clear()
        for thread in threadList:
            if thread['broken']:
                state = self.trUtf8("waiting at breakpoint")
            else:
                state = self.trUtf8("running")
            itm = QTreeWidgetItem(self.__threadList, 
                                  ["%d" % thread['id'], thread['name'], state])
            if thread['id'] == currentID:
                citm = itm
        
        self.__threadList.header().resizeSections(QHeaderView.ResizeToContents)
        self.__threadList.header().setStretchLastSection(True)
        
        if citm:
            self.__doThreadListUpdate = False
            self.__threadList.setCurrentItem(citm)
            self.__doThreadListUpdate = True
        
    def __threadSelected(self, current, previous):
        """
        Private slot to handle the selection of a thread in the thread list.
        
        @param current reference to the new current item (QTreeWidgetItem)
        @param previous reference to the previous current item (QTreeWidgetItem)
        """
        if current is not None and self.__doThreadListUpdate:
            tid, ok = current.text(0).toLong()
            if ok:
                self.debugServer.remoteSetThread(tid)