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

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

"""
Module implementing a tab widget conatining a shell, a browser, variables viewers and exception logger.
"""

import os

from qt import *

from Shell import Shell
from Browser import Browser
from Debugger.VariablesViewer import VariablesViewer
from Debugger.ExceptionLogger import ExceptionLogger
import Utilities

class SBVviewer(QTabWidget):
    """
    Module implementing tab widget conatining a shell, a browser, variables viewers and exception logger.
    
    The individual tabs contain the Python shell (optional), the filesystem browser,
    the two variables viewers (global and local) and the exception logger in that 
    order.
    
    Signals
    
        pythonFile(string, int) -- emitted to open a Python file at a line
    """
    def __init__(self, dbs, parent=None, noShell=0):
        """
        Constructor
        
        Arguments
        
            dbs -- reference to the debug server object
            
            parent -- parent widget (QWidget)
            
            noShell -- flag indicating whether the shell should be excluded
                This flag is set to 1 by those layouts, that have the Python
                shell in a separate window.
        """
        QTabWidget.__init__(self, parent)
        
        self.dbs = dbs
        
        self.noShell = noShell
        if not noShell:
            # add the python shell
            self.shell = Shell(dbs, self)
            self.addTab(self.shell, self.shell.caption())
        
        # add the browser
        self.browser = Browser(self)
        self.addTab(self.browser, self.browser.caption())
        
        # add the global variables viewer
        self.globalsViewer = VariablesViewer(self, 1)
        self.addTab(self.globalsViewer, self.globalsViewer.caption())
        
        # add the local variables viewer
        self.lvWidget = QWidget(self)
        lvWidgetLayout = QGridLayout(self.lvWidget,1,1,0,3)
        
        self.sourceButton = QPushButton(self.trUtf8('Source'), self.lvWidget)
        lvWidgetLayout.addWidget(self.sourceButton,0,0)
        self.sourceButton.setEnabled(0)

        self.stackComboBox = QComboBox(0,self.lvWidget)
        self.stackComboBox.setSizePolicy(QSizePolicy(7,0,0,0,
            self.stackComboBox.sizePolicy().hasHeightForWidth()))
        lvWidgetLayout.addWidget(self.stackComboBox,0,1)

        self.localsViewer = VariablesViewer(self.lvWidget, 0)
        lvWidgetLayout.addMultiCellWidget(self.localsViewer,1,1,0,1)
        
        self.addTab(self.lvWidget, self.localsViewer.caption())
        
        self.connect(self.sourceButton, SIGNAL('clicked()'), 
                     self.handleShowSource)
        self.connect(self.stackComboBox, SIGNAL('activated(int)'), 
                     self.handleFrameSelected)
        
        # add the exception logger
        self.exceptionLogger = ExceptionLogger(self)
        self.addTab(self.exceptionLogger, self.exceptionLogger.caption())
        
        if noShell:
            self.showPage(self.browser)
        else:
            self.showPage(self.shell)
            
        self.currPage = None
        self.clientWD = ""
        self.currentStack = None
        self.framenr = 0
        
    def handleResetUI(self):
        """
        Public method to reset the SBVviewer.
        """
        self.globalsViewer.clear()
        self.localsViewer.clear()
        self.stackComboBox.clear()
        self.sourceButton.setEnabled(0)
        self.clientWD = ""
        self.currentStack = None
        if self.noShell:
            self.showPage(self.browser)
        else:
            self.showPage(self.shell)
        
    def handleRawInput(self):
        """
        Pulic slot to handle the switch to the shell in raw input mode.
        """
        if not self.noShell:
            self.saveCurrentPage()
            self.showPage(self.shell)
            
    def showVariables(self, vlist, globals):
        """
        Public method to show the variables in the respective window.
        
        Arguments
        
            vlist -- list of variables to display
            
            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.
        
        Arguments
        
            vlist -- list of variables to display
            
            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.
        
        Arguments
        
            globals -- flag indicating global/local state
        """
        if globals:
            self.showPage(self.globalsViewer)
        else:
            self.showPage(self.lvWidget)
        
    def saveCurrentPage(self):
        """
        Public slot to save the current page.
        """
        self.currPage = self.currentPage()
        
    def restoreCurrentPage(self):
        """
        Public slot to restore the previously saved page.
        """
        if self.currPage is not None:
            self.showPage(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))
        for s in stack:
            # just show base filename to make it readable
            s = (os.path.basename(s[0]), s[1], s[2])
            self.stackComboBox.insertItem('%s:%s:%s' % s)
            
    def setWD(self, wd):
        """
        Public slot to set the working directory of the program being debugged.
        
        Arguments
        
            wd -- working directory (string)
        """
        self.clientWD = wd
        
    def setLocalVariablesFilter(self, filter):
        """
        Public slot to set the local variables filter.
        
        Arguments
        
            filter -- filter list (list of int)
        """
        self.localsFilter = filter
        
    def handleShowSource(self):
        """
        Private slot to handle the source button press to show the selected file.
        """
        s = self.currentStack[self.stackComboBox.currentItem()]
        self.emit(PYSIGNAL('pythonFile'),(s[0], int(s[1])))
        
    def handleFrameSelected(self, frmnr):
        """
        Private slot to handle the selection of a new stack frame number.
        
        Arguments
        
            frmnr -- frame number (0 is the current frame) (int)
        """
        self.framenr = frmnr
        self.dbs.remoteClientVariables(0, self.localsFilter, frmnr)
