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

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

"""
Module implementing the main user interface.
"""

import os
import sys
import string

from qt import *
from qtext import QSCINTILLA_VERSION_STR

from KdeQt import KQFileDialog, KQMessageBox
import KdeQt

from IconProvider import IconProvider
from Debugger.DebugUI import DebugUI
from Debugger.DebugServer import DebugServer
from DebugClients.Python.DebugClientCapabilities import HasUnittest
from SBVviewer import SBVviewer
from QScintilla.Shell import Shell
from Browser import Browser
from Info import *
from EmailDialog import EmailDialog
from PyUnit.UnittestDialog import UnittestDialog
from Helpviewer.HelpWindow import HelpWindow
from Preferences.ConfigurationDialog import ConfigurationDialog
from Preferences.ViewProfileDialog import ViewProfileDialog
from Preferences.ShortcutsDialog import ShortcutsDialog
from ToolConfigurationDialog import ToolConfigurationDialog
from DiffDialog import DiffDialog
from CompareDialog import CompareDialog
from Project.Project import Project
from Project.ProjectBrowser import ProjectBrowser
from LogView import LogView
from TaskViewer import TaskViewer
from TemplateViewer import TemplateViewer
from FindFileDialog import FindFileDialog
from FindFileNameDialog import FindFileNameDialog
from Wizards.Wizard import Wizards
import Preferences
import ViewManager
import Utilities
import Scripting
from Scripting.LoadScriptDialog import LoadScriptDialog
from Scripting.ScriptManager import *
from Graphics.PixmapDiagram import PixmapDiagram
import UI.PixmapCache
from E3SingleApplication import E3SingleApplicationServer
from AboutDialog import AboutDialog

from XML.XMLUtilities import make_parser
from XML.XMLErrorHandler import XMLErrorHandler, XMLFatalParseError
from XML.XMLEntityResolver import XMLEntityResolver
from XML.TasksHandler import TasksHandler
from XML.TasksWriter import TasksWriter
from XML.TemplatesHandler import TemplatesHandler
from XML.TemplatesWriter import TemplatesWriter

from E3Action import E3Action, E3ActionGroup

from eric3config import getConfig

from Refactoring.Refactoring import Refactoring, BRM_VERSION_STR


class Redirector(QObject):
    """
    Helper class used to redirect stdout and stderr to the log window
    
    @signal appendStderr(string) emitted to write data to stderr logger
    @signal appendStdout(string) emitted to write data to stdout logger
    """
    def __init__(self, stderr):
        """
        Constructor
        
        @param stderr flag indicating stderr is being redirected
        """
        QObject.__init__(self)
        self.stderr = stderr
        self.buffer = ''
        
    def nWrite(self, n):
        """
        Private method used to write data.
        
        @param n max numebr of bytes to write
        """
        if n:
            if self.buffer[n-1] == '\n':
                line = self.buffer[:n-1]
            else:
                line = self.buffer[:n]
            if self.stderr:
                qApp.mainWidget().showLogTab("stderr")
                self.emit(PYSIGNAL('appendStderr'), (line,))
            else:
                qApp.mainWidget().showLogTab("stdout")
                self.emit(PYSIGNAL('appendStdout'), (line,))
            self.buffer = self.buffer[n:]
            
    def bufferedWrite(self):
        """
        Private method returning number of characters to write.
        
        @return number of characters buffered or length of buffered line
        """
        return self.buffer.rfind('\n') + 1
        
    def flush(self):
        """
        Public method used to flush the buffered data.
        """
        self.nWrite(len(self.buffer))
        
    def write(self, s):
        """
        Public method used to write data.
        
        @param s data to be written (it must support the str-method)
        """
        self.buffer = self.buffer + unicode(s)
        self.nWrite(self.bufferedWrite())
        
class UserInterface(QMainWindow):
    """
    Class implementing the main user interface.
    
    @signal appendStderr(string) emitted to write data to stderr logger
    @signal appendStdout(string) emitted to write data to stdout logger
    @signal preferencesChanged() emitted after the preferences were changed
    @signal reloadAPIs() emitted to reload the api information
    """
    def __init__(self, loc, splash):
        """
        Constructor
        
        @param loc locale to be used by the UI (string)
        @param splash reference to the splashscreen (UI.SplashScreen.SplashScreen)
        """
        QMainWindow.__init__(self)

        self.loc = loc
        
        self.layout, self.embeddedShell, self.embeddedFileBrowser = \
            Preferences.getUILayout()
        
        self.passiveMode = Preferences.getDebugger("PassiveDbgEnabled")
        
        g = Preferences.getGeometry("MainGeometry")
        if g == [0,0,0,0]:
            s = QSize(800, 600)
            self.resize(s)
        else:
            self.move(g[0], g[1])
            self.resize(g[2], g[3])
            
        self.capProject = ""
        self.capEditor = ""
        self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename")
        
        self.setIcon(UI.PixmapCache.getPixmap("eric.png"))
        self.setWindowCaption()
        
        # load the view profiles
        self.profiles = Preferences.getUI("ViewProfiles").copy()
        
        if self.layout == 0:    # splitters
            self.setCentralWidget(QWidget(self))
            self.appWindowLayout = QHBoxLayout(self.centralWidget(),0,6)

        self.qtdir = Preferences.getQtDir()

        # Generate and set our icon provider for KQFileDialog
        self.iconProvider = IconProvider()
        KQFileDialog.setIconProvider(self.iconProvider)
        
        # Generate the debug server object
        dbs = DebugServer()
        
        # Generate an empty project object
        self.project = Project(self)
        
        splash.message(self.trUtf8("Generating Main User Interface..."))
        
        # Create the main window now so that we can connect QActions to it.
        self.createLayout(dbs)
        self.sizeLayout()
        
        # Generate the debugger part of the ui
        self.dbg = DebugUI(self, self.viewmanager, dbs, self.sbv, self.project)
        self.sbv.setDebugger(self.dbg)
        
        # Generate the redirection helpers
        self.stdout = Redirector(0)
        self.stderr = Redirector(1)
        
        # Generate the shortcuts configuration dialog
        self.shortcutsDialog = ShortcutsDialog(self, 'Shortcuts')
        
        # Generate the refactoring object
        self.refactoring = Refactoring(self)
            
        # now setup the connections
        splash.message(self.trUtf8("Setting up connections..."))
        self.connect(self.browser,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.browser,PYSIGNAL('designerFile'),
                     self.handleDesigner)
        self.connect(self.browser,PYSIGNAL('linguistFile'),
                     self.handleLinguist)
        self.connect(self.browser,PYSIGNAL('projectFile'),
                     self.project.openProject)
        self.connect(self.browser,PYSIGNAL('pixmapFile'),
                     self.handlePixmap)
        self.connect(self.browser,PYSIGNAL('unittestOpen'),
                     self.handleUnittestScript)
        
        self.connect(self.sbv.exceptionLogger,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        
        self.connect(self.sbv,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        
        self.connect(self.taskViewer,PYSIGNAL('displayFile'),
                     self.viewmanager.handlePythonFile)
        
        self.connect(self.projectBrowser.psBrowser,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.projectBrowser.psBrowser,PYSIGNAL('closeSourceWindow'),
                     self.viewmanager.handleCloseWindow)
        self.connect(self.projectBrowser.psBrowser,PYSIGNAL('unittestOpen'),
                     self.handleUnittestScript)
        
        self.connect(self.projectBrowser.pfBrowser,PYSIGNAL('designerFile'),
                     self.handleDesigner)
        self.connect(self.projectBrowser.pfBrowser,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.projectBrowser.pfBrowser,PYSIGNAL('uipreview'),
                     self.handleUIPreviewer)
        self.connect(self.projectBrowser.pfBrowser,PYSIGNAL('trpreview'),
                     self.handleTRPreviewer)
        self.connect(self.projectBrowser.pfBrowser,PYSIGNAL('closeSourceWindow'),
                     self.viewmanager.handleCloseWindow)
        self.connect(self.projectBrowser.pfBrowser,PYSIGNAL('appendStdout'),
                     self.stdoutTab.append)
        self.connect(self.projectBrowser.pfBrowser,PYSIGNAL('appendStderr'),
                     self.stderrTab.append)
        
        self.connect(self.projectBrowser.ptBrowser,PYSIGNAL('linguistFile'),
                     self.handleLinguist)
        self.connect(self.projectBrowser.ptBrowser,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.projectBrowser.ptBrowser,PYSIGNAL('trpreview'),
                     self.handleTRPreviewer)
        self.connect(self.projectBrowser.ptBrowser,PYSIGNAL('closeSourceWindow'),
                     self.viewmanager.handleCloseWindow)
        self.connect(self.projectBrowser.ptBrowser,PYSIGNAL('appendStdout'),
                     self.stdoutTab.append)
        self.connect(self.projectBrowser.ptBrowser,PYSIGNAL('appendStderr'),
                     self.stderrTab.append)
        
        self.connect(self.projectBrowser.piBrowser,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.projectBrowser.piBrowser,PYSIGNAL('closeSourceWindow'),
                     self.viewmanager.handleCloseWindow)
        self.connect(self.projectBrowser.piBrowser,PYSIGNAL('appendStdout'),
                     self.stdoutTab.append)
        self.connect(self.projectBrowser.piBrowser,PYSIGNAL('appendStderr'),
                     self.stderrTab.append)
        
        self.connect(self.projectBrowser.poBrowser,PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.projectBrowser.poBrowser,PYSIGNAL('closeSourceWindow'),
                     self.viewmanager.handleCloseWindow)
        self.connect(self.projectBrowser.poBrowser,PYSIGNAL('pixmapFile'),
                     self.handlePixmap)
        
        self.connect(self.project,PYSIGNAL('pythonFile'),
                    self.viewmanager.handleOpen)
        self.connect(self.project,PYSIGNAL('newProject'),
                     self.viewmanager.handleNewProject)
        self.connect(self.project,PYSIGNAL('projectOpened'),
                     self.viewmanager.handleProjectOpened)
        self.connect(self.project,PYSIGNAL('projectClosed'),
                     self.viewmanager.handleProjectClosed)
        self.connect(self.project,PYSIGNAL('projectFileRenamed'),
                     self.viewmanager.handleProjectFileRenamed)
        self.connect(self.project,PYSIGNAL('newProject'),
                     self.handleNewProject)
        self.connect(self.project,PYSIGNAL('projectOpened'),
                     self.handleProjectOpened)
        self.connect(self.project,PYSIGNAL('projectClosed'),
                     self.handleProjectClosed)
        
        self.connect(self.dbg,PYSIGNAL('resetUI'),
                     self.viewmanager.handleResetUI)
        self.connect(self.dbg,PYSIGNAL('resetUI'),
                     self.sbv.handleResetUI)
        self.connect(self.dbg,PYSIGNAL('resetUI'),
                     self.handleSetEditProfile)
        self.connect(self.dbg,PYSIGNAL('clientStack'),
                     self.sbv.handleClientStack)
        self.connect(self.dbg,PYSIGNAL('debuggingStarted'),
                     self.browser.handleProgramChange)
        self.connect(self.dbg,PYSIGNAL('debuggingStarted'),
                     self.sbv.exceptionLogger.debuggingStarted)
        self.connect(self.dbg,PYSIGNAL('debuggingStarted'),
                     self.sbv.handleDebuggingStarted)
        self.connect(self.dbg,PYSIGNAL('debuggingStarted'),
                     self.handleProgramChange)
        self.connect(self.dbg,PYSIGNAL('debuggingStarted'),
                     self.handleSetDebugProfile)
        self.connect(self.dbg,PYSIGNAL('compileForms'),
                     self.projectBrowser.pfBrowser.handleCompileChangedForms)
        
        self.connect(dbs,PYSIGNAL('clientStack'),
                     self.sbv.handleClientStack)
        self.connect(dbs,PYSIGNAL('passiveDebugStarted'),
                     self.sbv.exceptionLogger.debuggingStarted)
        self.connect(dbs,PYSIGNAL('passiveDebugStarted'),
                     self.sbv.handleDebuggingStarted)
        self.connect(dbs,PYSIGNAL('clientException'),
                     self.sbv.exceptionLogger.addException)
        self.connect(dbs,PYSIGNAL('clientClearWatch'),
                     self.sbv.watchpointViewer.clearWatchpoint)
        self.connect(dbs,PYSIGNAL('clientClearBreak'),
                     self.sbv.breakpointViewer.clearBreakpoint)
        self.connect(dbs,PYSIGNAL('clientLine'),
                     self.sbv.breakpointViewer.highlightBreakpoint)
        
        self.connect(self.stdout,PYSIGNAL('appendStdout'),
                     self.stdoutTab.append)
        
        self.connect(self.stderr,PYSIGNAL('appendStderr'),
                     self.stderrTab.append)
        
        self.connect(self,PYSIGNAL('preferencesChanged'),
                     self.viewmanager.handlePreferencesChanged)
        self.connect(self,PYSIGNAL('reloadAPIs'),
                     self.viewmanager.handleReloadAPIs)
        self.connect(self,PYSIGNAL('appendStdout'),
                     self.stdoutTab.append)
        self.connect(self,PYSIGNAL('appendStderr'),
                     self.stderrTab.append)
        self.connect(self,PYSIGNAL('preferencesChanged'),
                     self.shell.handlePreferencesChanged)
        self.connect(self,PYSIGNAL('preferencesChanged'),
                     self.projectBrowser.psBrowser.handlePreferencesChanged)
        self.connect(self,PYSIGNAL('preferencesChanged'),
                     self.browser.handlePreferencesChanged)
        self.connect(self,PYSIGNAL('preferencesChanged'),
                     self.taskViewer.handlePreferencesChanged)
        
        self.connect(self.viewmanager,PYSIGNAL('editorSaved'),
                     self.projectBrowser.psBrowser.handleEditorSaved)
        self.connect(self.viewmanager,PYSIGNAL('lastEditorClosed'),
                     self.handleLastEditorClosed)
        self.connect(self.viewmanager,PYSIGNAL('editorOpened'),
                     self.handleEditorOpened)
        self.connect(self.viewmanager,PYSIGNAL('changeCaption'),
                     self.setWindowCaption)
        self.connect(self.viewmanager,PYSIGNAL('checkActions'),
                     self.checkActions)
        self.connect(self.viewmanager,PYSIGNAL('breakpointToggled'),
                     self.sbv.breakpointViewer.refresh)
        self.connect(self.viewmanager,PYSIGNAL('breakpointEnabledToggled'),
                     self.sbv.breakpointViewer.refresh)
        self.connect(self.viewmanager,PYSIGNAL('editorClosed'),
                     self.sbv.breakpointViewer.editorClosed)
        self.connect(self.viewmanager,PYSIGNAL('editorChanged'),
                     self.projectBrowser.handleEditorChanged)
        
        self.connect(self,PYSIGNAL('preferencesChanged'),
                     self.refactoring.handlePreferencesChanged)
        self.connect(self.project,PYSIGNAL('projectOpened'),
                     self.refactoring.handleProjectOpened)
        self.connect(self.project,PYSIGNAL('projectClosed'),
                     self.refactoring.handleProjectClosed)
        self.connect(self.project,PYSIGNAL('newProject'),
                     self.refactoring.handleProjectOpened)
        
        # Generate the unittest dialog
        self.unittestDialog = UnittestDialog(None, self.dbg.dbs, self)
        self.connect(self.unittestDialog,PYSIGNAL('unittestFile'),
                     self.viewmanager.setFileLine)
        
        # Generate the find in project files dialog
        self.findFilesDialog = FindFileDialog(self.project)
        self.connect(self.findFilesDialog, PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.findFilesDialog,PYSIGNAL('designerFile'),
                     self.handleDesigner)
        
        # generate the find file dialog
        self.findFileNameDialog = FindFileNameDialog(self.project)
        self.connect(self.findFileNameDialog, PYSIGNAL('pythonFile'),
                     self.viewmanager.handlePythonFile)
        self.connect(self.findFileNameDialog,PYSIGNAL('designerFile'),
                     self.handleDesigner)
        
        # generate the diff dialogs
        self.diffDlg = DiffDialog()
        self.compareDlg = CompareDialog()
        
        # generate the wizards
        splash.message(self.trUtf8("Loading Wizards..."))
        self.wizards = Wizards(self.loc, self)
        
        # Initialize the actions, menues, toolbar and statusbar
        splash.message(self.trUtf8("Initializing Actions..."))
        self.initActions()
        splash.message(self.trUtf8("Initializing Menus..."))
        self.initMenus()
        splash.message(self.trUtf8("Initializing Toolbars..."))
        self.initToolbars()
        splash.message(self.trUtf8("Initializing Statusbar..."))
        self.initStatusbar()

        # Initialise the instance variables.
        self.currentProg = None
        self.isProg = 0
        self.utEditorOpen = 0
        self.utProjectOpen = 0
        
        self.inDragDrop = 0
        self.setAcceptDrops(1)
        
        self.currentProfile = None
        
        self.shutdownCalled = 0

        # Initialize the toollist and list of started tools
        splash.message(self.trUtf8("Initializing Tools..."))
        self.toollist = Preferences.readToolsMenu()
        self.toolProcs = []
        
        # now redirect stdout and stderr
        sys.stdout = self.stdout
        sys.stderr = self.stderr

        # now fire up the single application server
        if Preferences.getUI("SingleApplicationMode"):
            splash.message(self.trUtf8("Initializing Single Application Server..."))
            self.SAServer = E3SingleApplicationServer()
        else:
            self.SAServer = None
            
        # now fire up the scripting stuff
        splash.message(self.trUtf8("Initializing Scripting..."))
        self.scriptManager = Scripting.init(self)
        self.connect(self.scriptManager, PYSIGNAL("firstScriptAdded"),
            self.handleFirstScriptAdded)
        self.connect(self.scriptManager, PYSIGNAL("lastScriptDeleted"),
            self.handleLastScriptDeleted)
        Scripting.runStartupScripts(self)
        
        # now activate the initial view profile
        self.handleSetEditProfile()
        
        # now read the saved tasks
        self.readTasks()
        
        # now read the saved templates
        self.readTemplates()
        
        # now start the debug client
        dbs.startRemote()
        
    def createLayout(self, dbs):
        """
        Private method to create the layout of the various windows.
        
        @param dbs reference to the debug server object
        """
        # Create the main layout type 0 (splitters)
        if self.layout == 0:
            if self.embeddedShell:
                # A layout like the appearence of Qt Designer.
                self.hSplitter = QSplitter(self.centralWidget(),"hSplitter")
                self.hSplitter.setOrientation(QSplitter.Horizontal)
                
                # Create the project browser
                self.projectBrowser = ProjectBrowser(self.project, self.qtdir, self.hSplitter,
                    embeddedBrowser=(self.embeddedFileBrowser != 1))
                self.projectBrowser.show()
                
                # Create the view manager depending on the configuration setting
                self.viewmanager = ViewManager.factory(self.hSplitter, self, dbs)
                
                # Create a splitter for the right hand side
                self.vSplitter = QSplitter(self.hSplitter,"vSplitter")
                self.vSplitter.setOrientation(QSplitter.Vertical)
                
                # Create the shell, browser, variables part of the user interface
                self.sbv = SBVviewer(dbs, 0, self.viewmanager, self.vSplitter,
                    embeddedBrowser=(self.embeddedFileBrowser == 1))
                self.shell = self.sbv.shell
                
                # Create the log viewer part of the user interface
                self.logViewer = LogView(self.vSplitter)
                self.logViewer.setMinimumSize(100,100)
                
                # Create the task viewer part of the user interface
                self.taskViewer = TaskViewer(self.vSplitter, self.project)
                self.taskViewer.setMinimumSize(100,150)
                
                # Create the template viewer part of the user interface
                self.templateViewer = TemplateViewer(self.vSplitter, self.viewmanager)
                self.templateViewer.setMinimumSize(100,150)
                
                # Add the splitter to the main windows layout
                self.appWindowLayout.addWidget(self.hSplitter)
                
                self.windows = [self.projectBrowser, None, self.sbv, 
                    None, self.logViewer, self.taskViewer, self.templateViewer]
            else:
                # A layout like the appearance of KDevelop
                self.vSplitter = QSplitter(self.centralWidget(),"vSplitter")
                self.vSplitter.setOrientation(QSplitter.Vertical)
                
                # Create the top part
                self.hSplitter1 = QSplitter(self.vSplitter,"hSplitter1")
                self.hSplitter1.setOrientation(QSplitter.Horizontal)
            
                # Create the project browser
                self.projectBrowser = ProjectBrowser(self.project, self.qtdir, self.hSplitter1,
                    embeddedBrowser=(self.embeddedFileBrowser != 1))
                self.projectBrowser.show()
                
                # Create the view manager depending on the configuration setting
                self.viewmanager = ViewManager.factory(self.hSplitter1, self, dbs)
                
                # Create the shell, browser, variables part of the user interface
                # but without the shell. The shell gets a separate part of the UI
                self.sbv = SBVviewer(dbs, 0, self.viewmanager, self.hSplitter1,
                    embeddedShell=0,
                    embeddedBrowser=(self.embeddedFileBrowser == 1))
                
                # Create the bottom part
                self.hSplitter2 = QSplitter(self.vSplitter,"hSplitter2")
                self.hSplitter2.setOrientation(QSplitter.Horizontal)
                
                # Create the shell
                self.shell = Shell(dbs, self.viewmanager, self.hSplitter2)
            
                # Create the log viewer part of the user interface
                self.logViewer = LogView(self.hSplitter2)
                self.logViewer.setMinimumSize(100,100)
                
                # Create the task viewer part of the user interface
                self.taskViewer = TaskViewer(self.hSplitter2, self.project)
                self.taskViewer.setMinimumSize(100,150)
                
                # Create the template viewer part of the user interface
                self.templateViewer = TemplateViewer(self.hSplitter2, self.viewmanager)
                self.templateViewer.setMinimumSize(100,150)
                
                # Add the splitter to the main windows layout
                self.appWindowLayout.addWidget(self.vSplitter)
            
                self.windows = [self.projectBrowser, None, self.sbv, 
                    self.shell, self.logViewer, self.taskViewer, self.templateViewer]
                
            if self.embeddedFileBrowser == 1:   # embedded in debug browser
                self.browser = self.sbv.browser
            else:                               # embedded in project browser
                self.browser = self.projectBrowser.fileBrowser
                
        # Create the main layout type 1 (movable dock windows)
        elif self.layout == 1:
            # Create the view manager depending on the configuration setting
            self.viewmanager = ViewManager.factory(self, self, dbs)
            self.setCentralWidget(self.viewmanager)

            # Create the project browser
            self.projectBrowserDock = self.createDockWindow()
            self.projectBrowser = ProjectBrowser(self.project, self.qtdir, self.projectBrowserDock,
                embeddedBrowser=(self.embeddedFileBrowser == 2))
            self.setupDockWindow(self.projectBrowserDock, Qt.DockLeft,
                                 self.projectBrowser, self.trUtf8("Project-Browser"))

            # Create the shell, browser, variables part of the user interface,
            # maybe without the embedded shell
            self.sbvDock = self.createDockWindow()
            self.sbv = SBVviewer(dbs, 1, self.viewmanager, self.sbvDock,
                embeddedShell=self.embeddedShell, 
                embeddedBrowser=(self.embeddedFileBrowser == 1))
            self.setupDockWindow(self.sbvDock, Qt.DockRight,
                                 self.sbv, self.trUtf8("Debug-Browser"))

            # Create the log viewer part of the user interface
            self.logViewerDock = self.createDockWindow()
            self.logViewer = LogView(self.logViewerDock)
            self.setupDockWindow(self.logViewerDock, Qt.DockBottom,
                                 self.logViewer, self.trUtf8("Log-Viewer"))

            # Create the task viewer part of the user interface
            self.taskViewerDock = self.createDockWindow()
            self.taskViewer = TaskViewer(self.taskViewerDock, self.project)
            self.setupDockWindow(self.taskViewerDock, Qt.DockBottom,
                                 self.taskViewer, self.trUtf8("Task-Viewer"))
            
            # Create the template viewer part of the user interface
            self.templateViewerDock = self.createDockWindow()
            self.templateViewer = TemplateViewer(self.templateViewerDock, self.viewmanager)
            self.setupDockWindow(self.templateViewerDock, Qt.DockRight,
                                 self.templateViewer, self.trUtf8("Template-Viewer"))
            
            self.dockwindows = {}
            self.dockwindows[0] = (self.trUtf8('Project-Browser'), self.projectBrowserDock)
            self.dockwindows[1] = (self.trUtf8('Debug-Browser'), self.sbvDock)
            self.dockwindows[2] = (self.trUtf8('Log-Viewer'), self.logViewerDock)
            self.dockwindows[3] = (self.trUtf8('Task-Viewer'), self.taskViewerDock)
            self.dockwindows[4] = (self.trUtf8('Template-Viewer'), self.templateViewerDock)
            nextDockIndex = 5
    
            self.windows = [self.projectBrowserDock, None, self.sbvDock, 
                None, self.logViewerDock, self.taskViewerDock, self.templateViewerDock]
                
            if self.embeddedShell:
                self.shell = self.sbv.shell
            else:
                # Create the shell
                self.shellDock = self.createDockWindow()
                self.shell = Shell(dbs, self.viewmanager, self.shellDock)
                self.setupDockWindow(self.shellDock, Qt.DockBottom,
                                     self.shell, self.trUtf8("Shell"))
                self.dockwindows[nextDockIndex] = \
                    (self.trUtf8('Shell'), self.shellDock)
                nextDockIndex += 1
                self.windows[3] = self.shellDock
                
            if self.embeddedFileBrowser == 0:   # separate window
                # Create the file browser
                self.browserDock = self.createDockWindow()
                self.browser = Browser(self.browserDock)
                self.setupDockWindow(self.browserDock, Qt.DockRight,
                                     self.browser, self.trUtf8("File-Browser"))
                self.dockwindows[nextDockIndex] = \
                    (self.trUtf8('File-Browser'), self.browserDock)
                nextDockIndex += 1
                self.windows[1] = self.browserDock
            elif self.embeddedFileBrowser == 1: # embedded in debug browser
                self.browser = self.sbv.browser
            else:                               # embedded in project browser
                self.browser = self.projectBrowser.fileBrowser

        # Create main layout type 2 (floating windows)
        elif self.layout == 2:
            # Create the view manager depending on the configuration setting
            self.viewmanager = ViewManager.factory(self, self, dbs)
            self.setCentralWidget(self.viewmanager)

            # Create the project browser
            self.projectBrowser = ProjectBrowser(self.project, self.qtdir, None,
                embeddedBrowser=(self.embeddedFileBrowser == 2))
            self.projectBrowser.setCaption(self.trUtf8("Project-Browser"))

            # Create the shell, browser, variables part of the user interface,
            # maybe without the embedded shell
            self.sbv = SBVviewer(dbs, 0, self.viewmanager, None,
                embeddedShell=self.embeddedShell, 
                embeddedBrowser=(self.embeddedFileBrowser == 1))
            self.sbv.setCaption(self.trUtf8("Debug-Browser"))

            # Create the log viewer part of the user interface
            self.logViewer = LogView(None)
            self.logViewer.setCaption(self.trUtf8("Log-Viewer"))
    
            # Create the task viewer part of the user interface
            self.taskViewer = TaskViewer(None, self.project)
            self.taskViewer.setCaption(self.trUtf8("Task-Viewer"))
            
            # Create the template viewer part of the user interface
            self.templateViewer = TemplateViewer(None, self.viewmanager)
            self.templateViewer.setCaption(self.trUtf8("Template-Viewer"))
            
            self.windows = [self.projectBrowser, None, self.sbv, 
                None, self.logViewer, self.taskViewer, self.templateViewer]
                
            if self.embeddedShell:
                self.shell = self.sbv.shell
            else:
                # Create the shell
                self.shell = Shell(dbs, self.viewmanager, None)
                self.windows[3] = self.shell

            if self.embeddedFileBrowser == 0:   # separate window
                # Create the file browser
                self.browser = Browser(None)
                self.browser.setCaption(self.trUtf8("File-Browser"))
                self.windows[1] = self.browser
            elif self.embeddedFileBrowser == 1: # embedded in debug browser
                self.browser = self.sbv.browser
            else:                               # embedded in project browser
                self.browser = self.projectBrowser.fileBrowser
            
        # Create and add the log viewer tabs
        self.logTabs = {}
        (self.logTabs["stdout"], self.stdoutTab) = self.logViewer.addTab(self.trUtf8("stdout"))

        (self.logTabs["stderr"], self.stderrTab) = self.logViewer.addTab(self.trUtf8("stderr"))
        
    def sizeLayout(self):
        """
        Private method to setup the layout of the various windows.
        """
        # Set the sizes of the splitters
        width = self.width()
        height = self.height()
        if self.layout == 0:            # splitters
            if self.embeddedShell:
                g = Preferences.getGeometry("MainSplitter0")
                if g == [0,0,0,0,0]:
                    hSizes = [int(0.21*width), int(0.49*width), int(0.3*width)]
                    vSizes = [int(0.8*height), int(0.2*height)]
                else:
                    hSizes = g[:3]
                    vSizes = g[3:]
                self.hSplitter.setSizes(hSizes)
                self.vSplitter.setSizes(vSizes)
            else:
                g = Preferences.getGeometry("MainSplitter1")
                if g == [0,0,0,0,0,0,0]:
                    vSizes = [int(0.9*height), int(0.1*height)]
                    hSizes1 = [int(0.23*width), int(0.52*width), int(0.25*width)]
                    hSizes2 = [int(0.5*width), int(0.5*width)]
                else:
                    vSizes = g[:2]
                    hSizes1 = g[2:5]
                    hSizes2 = g[5:]
                self.vSplitter.setSizes(vSizes)
                self.hSplitter1.setSizes(hSizes1)
                self.hSplitter2.setSizes(hSizes2)
        elif self.layout == 1:      # dockable windows
            if self.embeddedShell and self.embeddedFileBrowser:
                # shell and browser are embedded
                if not Preferences.getMainDockLayout(self, 0):
                    self.projectBrowserDock.setFixedExtentWidth(int(0.2*width))
                    self.sbvDock.setFixedExtentWidth(int(0.3*width))
                    self.logViewerDock.setFixedExtentHeight(int(0.1*height))
            elif not self.embeddedFileBrowser and not self.embeddedShell:
                # shell and browser are separate
                if not Preferences.getMainDockLayout(self, 3):
                    self.projectBrowserDock.setFixedExtentWidth(int(0.23*width))
                    self.sbvDock.setFixedExtentWidth(int(0.3*width))
                    self.shellDock.setFixedExtentHeight(int(0.15*height))
                    self.logViewerDock.setFixedExtentHeight(int(0.15*height))
                    self.logViewerDock.setFixedExtentWidth(int(0.4*width))
                    self.browserDock.setFixedExtentWidth(int(0.3*width))
            elif not self.embeddedShell:
                # only shell is separate
                if not Preferences.getMainDockLayout(self, 1):
                    self.projectBrowserDock.setFixedExtentWidth(int(0.23*width))
                    self.sbvDock.setFixedExtentWidth(int(0.3*width))
                    self.shellDock.setFixedExtentHeight(int(0.15*height))
                    self.logViewerDock.setFixedExtentHeight(int(0.15*height))
                    self.logViewerDock.setFixedExtentWidth(int(0.4*width))
            else:
                # only browser is separate
                if not Preferences.getMainDockLayout(self, 2):
                    self.projectBrowserDock.setFixedExtentWidth(int(0.2*width))
                    self.sbvDock.setFixedExtentWidth(int(0.3*width))
                    self.logViewerDock.setFixedExtentHeight(int(0.1*height))
                    self.browserDock.setFixedExtentWidth(int(0.3*width))
        elif self.layout == 2:      # floating windows
            # Project Browser
            g = Preferences.getGeometry("ProjectBrowser")
            self.projectBrowser.resize(g[2], g[3])
            self.projectBrowser.move(g[0], g[1])
            self.projectBrowser.setShown(g[4])
            
            # SBV Viewer
            g = Preferences.getGeometry("SBV")
            self.sbv.resize(g[2], g[3])
            self.sbv.move(g[0], g[1])
            self.sbv.setShown(g[4])
            
            # Log Viewer
            g = Preferences.getGeometry("LogViewer")
            self.logViewer.resize(g[2], g[3])
            self.logViewer.move(g[0], g[1])
            self.logViewer.setShown(g[4])
           
            # Shell (only for separate shell)
            if not self.embeddedShell:
                g = Preferences.getGeometry("Shell")
                self.shell.resize(g[2], g[3])
                self.shell.move(g[0], g[1])
                self.shell.setShown(g[4])
           
            # Browser (only for separate browser)
            if not self.embeddedFileBrowser:
                g = Preferences.getGeometry("FileBrowser")
                self.browser.resize(g[2], g[3])
                self.browser.move(g[0], g[1])
                self.browser.setShown(g[4])
            
            # Task Viewer
            g = Preferences.getGeometry("TaskViewer")
            self.taskViewer.resize(g[2], g[3])
            self.taskViewer.move(g[0], g[1])
            self.taskViewer.setShown(g[4])
            
            # Template Viewer
            g = Preferences.getGeometry("TemplateViewer")
            self.templateViewer.resize(g[2], g[3])
            self.templateViewer.move(g[0], g[1])
            self.templateViewer.setShown(g[4])
        
    def showLogTab(self, tabname):
        """
        Public method to show a particular Log-Viewer tab.
        
        @param tabname string naming the tab to be shown (string)
        """
        if tabname in self.logTabs.keys():
            self.logViewer.setCurrentPage(self.logTabs[tabname])
        
    def processArgs(self, args):
        """
        Public method to process the command line args passed to the UI.
        
        @param args list of files to open<br />
                The args are processed one at a time. All arguments after a
                '--' option are considered debug arguments to the program 
                for the debugger. All files named before the '--' option
                are opened in a text editor, unless the argument ends in 
                .e3p or .e3pz, then it is opened as a project file.
        """
        # no args, return
        if args is None:
            return

        # holds space delimited list of command args, if any
        argsStr = None
        # flag indicating '--' options was found
        ddseen = 0
        
        if sys.platform == 'win32':
            argChars = ['-', '/']
        else:
            argChars = ['-']

        for arg in args:
            if arg == '--' and not ddseen:
                ddseen = 1
                continue
                
            if arg[0] in argChars or ddseen:
                if argsStr is None:
                    argsStr = arg
                else:
                    argsStr = "%s %s" % (argsStr, arg)
                continue

            ext = os.path.splitext(arg)[1]
            ext = os.path.normcase(ext)

            if ext in ['.e3p', '.e3pz']:
                self.project.openProject(arg)
            else:
                self.viewmanager.handleOpen(arg)

        # store away any args we had
        if argsStr is not None:
            self.dbg.setArgvHistory(argsStr)
        
    def createDockWindow(self):
        """
        Private method to create a dock window with common properties.
        
        @return the generated dock window (QDockWindow)
        """
        dock = QDockWindow()
        dock.setResizeEnabled(1)
        dock.setCloseMode(QDockWindow.Always)
        return dock

    def setupDockWindow(self, dock, where, widget, caption):
        """
        Private method to configure the dock window created with createDockWindow().
        
        @param dock the dock window (QDockWindow)
        @param where dock area to be docked to (QDockArea)
        @param widget widget to be shown in the dock window (QWidget)
        @param caption caption of the dock window (string or QString)
        """
        if caption is None:
            caption = QString.null
        self.addDockWindow(dock, where)
        dock.setWidget(widget)
        dock.setCaption(caption)
        dock.show()
        self.setAppropriate(dock, 1)

    def setWindowCaption(self, editor=None, project=None):
        """
        Private method to set the caption of the Main Window.
        
        @param editor filename to be displayed (string or QString)
        @param project project name to be displayed (string or QString)
        """
        if editor is not None and self.captionShowsFilename:
            self.capEditor = unicode(editor)
        if project is not None:
            self.capProject = unicode(project)
            
        if self.passiveMode:
            if not self.capProject and not self.capEditor:
                self.setCaption(self.trUtf8("%1 - Passive Mode").arg(Program))
            elif self.capProject and not self.capEditor:
                self.setCaption(self.trUtf8("%1 - %2 - Passive Mode")\
                    .arg(self.capProject)\
                    .arg(Program))
            elif not self.capProject and self.capEditor:
                self.setCaption(self.trUtf8("%1 - %2 - Passive Mode")\
                    .arg(self.capEditor)\
                    .arg(Program))
            else:
                self.setCaption(self.trUtf8("%1 - %2 - %3 - Passive Mode")\
                    .arg(self.capProject)\
                    .arg(self.capEditor)\
                    .arg(Program))
        else:
            if not self.capProject and not self.capEditor:
                self.setCaption(Program)
            elif self.capProject and not self.capEditor:
                self.setCaption("%s - %s" % (self.capProject, Program))
            elif not self.capProject and self.capEditor:
                self.setCaption("%s - %s" % (self.capEditor, Program))
            else:
                self.setCaption("%s - %s - %s" % \
                    (self.capProject, self.capEditor, Program))
        
    def initActions(self):
        """
        Private method to define the user interface actions.
        """
        self.actions = []
        
        self.exitAct = E3Action(self.trUtf8('Quit'),
                QIconSet(UI.PixmapCache.getPixmap("exit.png")),
                self.trUtf8('&Quit'),
                QKeySequence(self.trUtf8("CTRL+Q","File|Quit")),
                0,self,'quit')
        self.exitAct.setStatusTip(self.trUtf8('Quit the IDE'))
        self.exitAct.setWhatsThis(self.trUtf8(
            """<b>Quit the IDE</b>"""
            """<p>This quits the IDE. Any unsaved changes may be saved first."""
            """ Any Python program being debugged will be stopped and the"""
            """ preferences will be written to disc.</p>"""
        ))
        self.exitAct.connectIt(SIGNAL('activated()'), self.handleQuit)
        self.actions.append(self.exitAct)

        self.viewProfileActGrp = E3ActionGroup(self, "viewprofiles", 1)
        
        self.setEditProfileAct = E3Action(self.trUtf8('Edit Profile'),
                QIconSet(UI.PixmapCache.getPixmap("viewProfileEdit.png")),
                self.trUtf8('Edit Profile'),
                0, 0,
                self.viewProfileActGrp, 'edit_profile', 1)
        self.setEditProfileAct.setStatusTip(self.trUtf8('Activate the edit view profile'))
        self.setEditProfileAct.setWhatsThis(self.trUtf8(
            """<b>Edit Profile</b>"""
            """<p>Activate the "Edit View Profile". Windows being shown,"""
            """ if this profile is active, may be configured with the"""
            """ "View Profile Configuration" dialog.</p>"""
        ))
        self.setEditProfileAct.connectIt(SIGNAL('activated()'),self.handleSetEditProfile)
        self.actions.append(self.setEditProfileAct)
        
        self.setDebugProfileAct = E3Action(self.trUtf8('Debug Profile'),
                QIconSet(UI.PixmapCache.getPixmap("viewProfileDebug.png")),
                self.trUtf8('Debug Profile'),
                0, 0,
                self.viewProfileActGrp, 'debug_profile', 1)
        self.setDebugProfileAct.setStatusTip(self.trUtf8('Activate the debug view profile'))
        self.setDebugProfileAct.setWhatsThis(self.trUtf8(
            """<b>Debug Profile</b>"""
            """<p>Activate the "Debug View Profile". Windows being shown,"""
            """ if this profile is active, may be configured with the"""
            """ "View Profile Configuration" dialog.</p>"""
        ))
        self.setDebugProfileAct.connectIt(SIGNAL('activated()'),self.handleSetDebugProfile)
        self.actions.append(self.setDebugProfileAct)
        
        self.pbAct = E3Action(self.trUtf8('Project-Browser'),
                self.trUtf8('&Project-Browser'),0,0,self,'project_browser',1)
        self.pbAct.setStatusTip(self.trUtf8('Toggle the Project-Browser window'))
        self.pbAct.setWhatsThis(self.trUtf8(
            """<b>Toggle the Project-Browser window</b>"""
            """<p>If the Project-Browser window is hidden then display it. It is displayed"""
            """ then close it.</p>"""
        ))
        self.pbAct.connectIt(SIGNAL('activated()'),self.handleProjectBrowser)
        self.actions.append(self.pbAct)

        self.sbvAct = E3Action(self.trUtf8('Debug-Browser'),
                self.trUtf8('&Debug-Browser'),0,0,self,'debug_browser',1)
        self.sbvAct.setStatusTip(self.trUtf8('Toggle the Debug-Browser window'))
        self.sbvAct.setWhatsThis(self.trUtf8(
            """<b>Toggle the Debug-Browser window</b>"""
            """<p>If the Debug-Browser window is hidden then display it."""
            """ If it is displayed then close it.</p>"""
        ))
        self.sbvAct.connectIt(SIGNAL('activated()'),self.handleSBV)
        self.actions.append(self.sbvAct)
        
        if not self.embeddedShell:
            self.shellAct = E3Action(self.trUtf8('Shell'),
                    self.trUtf8('&Shell'),0,0,self,'python_shell',1)
            self.shellAct.setStatusTip(self.trUtf8('Toggle the Shell window'))
            self.shellAct.setWhatsThis(self.trUtf8(
                """<b>Toggle the Shell window</b>"""
                """<p>If the Shell window is hidden then display it."""
                """ If it is displayed then close it.</p>"""
            ))
            self.shellAct.connectIt(SIGNAL('activated()'),self.handleShell)
            self.actions.append(self.shellAct)

        if not self.embeddedFileBrowser:
            self.browserAct = E3Action(self.trUtf8('File-Browser'),
                    self.trUtf8('File-&Browser'),0,0,self,'file_browser',1)
            self.browserAct.setStatusTip(self.trUtf8('Toggle the File-Browser window'))
            self.browserAct.setWhatsThis(self.trUtf8(
                """<b>Toggle the File-Browser window</b>"""
                """<p>If the File-Browser window is hidden then display it."""
                """ If it is displayed then close it.</p>"""
            ))
            self.browserAct.connectIt(SIGNAL('activated()'),self.handleBrowser)
            self.actions.append(self.browserAct)

        self.lvAct = E3Action(self.trUtf8('Log-Viewer'),
                self.trUtf8('&Log-Viewer'),0,0,self,'log_viewer',1)
        self.lvAct.setStatusTip(self.trUtf8('Toggle the Log-Viewer window'))
        self.lvAct.setWhatsThis(self.trUtf8(
            """<b>Toggle the Log-Viewer window</b>"""
            """<p>If the Log-Viewer window is hidden then display it."""
            """ If it is displayed then close it.</p>"""
        ))
        self.lvAct.connectIt(SIGNAL('activated()'),self.handleLogViewer)
        self.actions.append(self.lvAct)

        self.tvAct = E3Action(self.trUtf8('Task-Viewer'),
                self.trUtf8('T&ask-Viewer'),0,0,self,'task_viewer',1)
        self.tvAct.setStatusTip(self.trUtf8('Toggle the Task-Viewer window'))
        self.tvAct.setWhatsThis(self.trUtf8(
            """<b>Toggle the Task-Viewer window</b>"""
            """<p>If the Task-Viewer window is hidden then display it."""
            """ If it is displayed then close it.</p>"""
        ))
        self.tvAct.connectIt(SIGNAL('activated()'),self.handleTaskViewer)
        self.actions.append(self.tvAct)

        self.tevAct = E3Action(self.trUtf8('Template-Viewer'),
                self.trUtf8('Te&mplate-Viewer'),0,0,self,'template_viewer',1)
        self.tevAct.setStatusTip(self.trUtf8('Toggle the Template-Viewer window'))
        self.tevAct.setWhatsThis(self.trUtf8(
            """<b>Toggle the Template-Viewer window</b>"""
            """<p>If the Template-Viewer window is hidden then display it."""
            """ If it is displayed then close it.</p>"""
        ))
        self.tevAct.connectIt(SIGNAL('activated()'),self.handleTemplateViewer)
        self.actions.append(self.tevAct)

        self.whatsThisAct = E3Action(self.trUtf8('What\'s This?'),
                QIconSet(UI.PixmapCache.getPixmap("whatsThis.png")),
                self.trUtf8('&What\'s This?'), Qt.SHIFT+Qt.Key_F1,0,self,'whatsThis')
        self.whatsThisAct.setStatusTip(self.trUtf8('Context sensitive help'))
        self.whatsThisAct.setWhatsThis(self.trUtf8(
            """<b>Display context sensitive help</b>"""
            """<p>In What's This? mode, the mouse cursor shows an arrow with a question"""
            """ mark, and you can click on the interface elements to get a short"""
            """ description of what they do and how to use them. In dialogs, this"""
            """ feature can be accessed using the context help button in the"""
            """ titlebar.</p>"""
        ))
        self.whatsThisAct.connectIt(SIGNAL('activated()'),self.whatsThis)
        self.actions.append(self.whatsThisAct)

        self.helpviewerAct = E3Action(self.trUtf8('Helpviewer'),
                self.trUtf8('&Helpviewer...'), Qt.Key_F1,0,self,'helpviewer')
        self.helpviewerAct.setStatusTip(self.trUtf8('Open the helpviewer window'))
        self.helpviewerAct.setWhatsThis(self.trUtf8(
            """<b>Helpviewer</b>"""
            """<p>Display the helpviewer window. This window will show"""
            """ HTML help files. It has the capability to navigate to"""
            """ links, set bookmarks, print the displayed help and some"""
            """ more features.</p>"""
        ))
        self.helpviewerAct.connectIt(SIGNAL('activated()'),self.handleHelpViewer)
        self.actions.append(self.helpviewerAct)
        
        self.initQtDocAction()
        self.initPythonDocAction()
        self.initEricDocAction()
      
              
        self.aboutAct = E3Action(self.trUtf8('About %1').arg(Program),
                self.trUtf8('&About %1').arg(Program),
                0,0,self,'about_eric')
        self.aboutAct.setStatusTip(self.trUtf8('Display information about this software'))
        self.aboutAct.setWhatsThis(self.trUtf8(
            """<b>About %1</b>"""
            """<p>Display some information about this software.</p>"""
                             ).arg(Program))
        self.aboutAct.connectIt(SIGNAL('activated()'),self.handleAbout)
        self.actions.append(self.aboutAct)

        self.aboutQtAct = E3Action(self.trUtf8('About Qt'),
                self.trUtf8('About &Qt'),0,0,self,'about_qt')
        self.aboutQtAct.setStatusTip(self.trUtf8('Display information about the Qt toolkit'))
        self.aboutQtAct.setWhatsThis(self.trUtf8(
            """<b>About Qt</b>"""
            """<p>Display some information about the Qt toolkit.</p>"""
        ))
        self.aboutQtAct.connectIt(SIGNAL('activated()'),self.handleAboutQt)
        self.actions.append(self.aboutQtAct)
        
        if KdeQt.isKDE():
            self.aboutKdeAct = E3Action(self.trUtf8('About KDE'),
                    self.trUtf8('About &KDE'),0,0,self,'about_kde')
            self.aboutKdeAct.setStatusTip(self.trUtf8('Display information about KDE'))
            self.aboutKdeAct.setWhatsThis(self.trUtf8(
                """<b>About KDE</b>"""
                """<p>Display some information about KDE.</p>"""
            ))
            self.aboutKdeAct.connectIt(SIGNAL('activated()'),self.handleAboutKde)
            self.actions.append(self.aboutKdeAct)
        else:
            self.aboutKdeAct = None

        self.versionAct = E3Action(self.trUtf8('Show Versions'),
                self.trUtf8('Show &Versions'),0,0,self,'show_versions')
        self.versionAct.setStatusTip(self.trUtf8('Display version information'))
        self.versionAct.setWhatsThis(self.trUtf8(
            """<b>Show Versions</b>"""
            """<p>Display version information.</p>"""
                             ))
        self.versionAct.connectIt(SIGNAL('activated()'),self.handleVersions)
        self.actions.append(self.versionAct)

        self.reportBugAct = E3Action(self.trUtf8('Report Bug'),
                self.trUtf8('Report &Bug...'),0,0,self,'report_bug')
        self.reportBugAct.setStatusTip(self.trUtf8('Report a bug'))
        self.reportBugAct.setWhatsThis(self.trUtf8(
            """<b>Report Bug...</b>"""
            """<p>Opens a dialog to report a bug.</p>"""
                             ))
        self.reportBugAct.connectIt(SIGNAL('activated()'),self.handleReportBug)
        self.actions.append(self.reportBugAct)

        self.utActGrp = E3ActionGroup(self)
        
        self.utDialogAct = E3Action(self.trUtf8('Unittest'), 
                QIconSet(UI.PixmapCache.getPixmap("unittest.png")),
                self.trUtf8('&Unittest...'),
                0, 0, self.utActGrp, 'unittest')
        self.utDialogAct.setStatusTip(self.trUtf8('Start unittest dialog'))
        self.utDialogAct.setWhatsThis(self.trUtf8(
            """<b>Unittest</b>"""
            """<p>Perform unit tests. The dialog gives you the"""
            """ ability to select and run a unittest suite.</p>"""
        ))
        self.utDialogAct.connectIt(SIGNAL('activated()'), self.handleUnittest)
        self.actions.append(self.utDialogAct)

        self.utRestartAct = E3Action(self.trUtf8('Unittest Restart'),
            QIconSet(UI.PixmapCache.getPixmap("unittestRestart.png")),
            self.trUtf8('&Restart Unittest...'),
            0, 0, self.utActGrp, 'unittest_restart')
        self.utRestartAct.setStatusTip(self.trUtf8('Restart last unittest'))
        self.utRestartAct.setWhatsThis(self.trUtf8(
            """<b>Restart Unittest</b>"""
            """<p>Restart the unittest performed last.</p>"""
        ))
        self.utRestartAct.connectIt(SIGNAL('activated()'), self.handleUnittestRestart)
        self.utRestartAct.setEnabled(0)
        self.actions.append(self.utRestartAct)
        
        self.utScriptAct = E3Action(self.trUtf8('Unittest Script'),
            QIconSet(UI.PixmapCache.getPixmap("unittestScript.png")),
            self.trUtf8('Unittest &Script...'),
            0, 0, self.utActGrp, 'unittest_script')
        self.utScriptAct.setStatusTip(self.trUtf8('Run unittest with current script'))
        self.utScriptAct.setWhatsThis(self.trUtf8(
            """<b>Unittest Script</b>"""
            """<p>Run unittest with current script.</p>"""
        ))
        self.utScriptAct.connectIt(SIGNAL('activated()'), self.handleUnittestScript)
        self.utScriptAct.setEnabled(0)
        self.actions.append(self.utScriptAct)
        
        self.utProjectAct = E3Action(self.trUtf8('Unittest Project'),
            QIconSet(UI.PixmapCache.getPixmap("unittestProject.png")),
            self.trUtf8('Unittest &Project...'),
            0, 0, self.utActGrp, 'unittest_project')
        self.utProjectAct.setStatusTip(self.trUtf8('Run unittest with current project'))
        self.utProjectAct.setWhatsThis(self.trUtf8(
            """<b>Unittest Project</b>"""
            """<p>Run unittest with current project.</p>"""
        ))
        self.utProjectAct.connectIt(SIGNAL('activated()'), self.handleUnittestProject)
        self.utProjectAct.setEnabled(0)
        self.actions.append(self.utProjectAct)
        
        if self.qtdir is None:
            self.qtActGrp = None
        else:
            self.qtActGrp = E3ActionGroup(self)
            
            act = E3Action(self.trUtf8('Qt-Designer'), 
                    QIconSet(UI.PixmapCache.getPixmap("designer.png")),
                    self.trUtf8('&Designer...'), 0, 0, self.qtActGrp, 'qt_designer')
            act.setStatusTip(self.trUtf8('Start the Qt-Designer'))
            act.setWhatsThis(self.trUtf8(
                """<b>Qt-Designer</b>"""
                """<p>Start the Qt-Designer.</p>"""
            ))
            act.connectIt(SIGNAL('activated()'), self.handleDesigner)
            self.actions.append(act)
            
            act = E3Action(self.trUtf8('Qt-Linguist'), 
                    QIconSet(UI.PixmapCache.getPixmap("linguist.png")),
                    self.trUtf8('&Linguist...'), 0, 0, self.qtActGrp, 'qt_linguist')
            act.setStatusTip(self.trUtf8('Start the Qt-Linguist'))
            act.setWhatsThis(self.trUtf8(
                """<b>Qt-Linguist</b>"""
                """<p>Start the Qt-Linguist.</p>"""
            ))
            act.connectIt(SIGNAL('activated()'), self.handleLinguist)
            self.actions.append(act)
        
        self.uipreviewerAct = E3Action(self.trUtf8('UI Previewer'), 
                QIconSet(UI.PixmapCache.getPixmap("uiPreviewer.png")),
                self.trUtf8('&UI Previewer...'), 0, 0, self, 'ui_previewer')
        self.uipreviewerAct.setStatusTip(self.trUtf8('Start the UI Previewer'))
        self.uipreviewerAct.setWhatsThis(self.trUtf8(
            """<b>UI Previewer</b>"""
            """<p>Start the UI Previewer.</p>"""
        ))
        self.uipreviewerAct.connectIt(SIGNAL('activated()'), self.handleUIPreviewer)
        self.actions.append(self.uipreviewerAct)
        if not getConfig('qtui'):
            self.uipreviewerAct.setEnabled(False)
        
        self.trpreviewerAct = E3Action(self.trUtf8('Translations Previewer'), 
                QIconSet(UI.PixmapCache.getPixmap("trPreviewer.png")),
                self.trUtf8('&Translations Previewer...'), 0, 0, self, 'tr_previewer')
        self.trpreviewerAct.setStatusTip(self.trUtf8('Start the Translations Previewer'))
        self.trpreviewerAct.setWhatsThis(self.trUtf8(
            """<b>Translations Previewer</b>"""
            """<p>Start the Translations Previewer.</p>"""
        ))
        self.trpreviewerAct.connectIt(SIGNAL('activated()'), self.handleTRPreviewer)
        self.actions.append(self.trpreviewerAct)
        if not getConfig('qtui'):
            self.trpreviewerAct.setEnabled(False)
        
        self.diffAct = E3Action(self.trUtf8('Compare Files'),
                QIconSet(UI.PixmapCache.getPixmap("diffFiles.png")),
                self.trUtf8('&Compare Files...'), 0, 0, self, 'diff_files')
        self.diffAct.setStatusTip(self.trUtf8('Compare two files'))
        self.diffAct.setWhatsThis(self.trUtf8(
            """<b>Compare Files</b>"""
            """<p>Open a dialog to compare two files.</p>"""
        ))
        self.diffAct.connectIt(SIGNAL('activated()'), self.handleCompareFiles)
        self.actions.append(self.diffAct)

        self.compareAct = E3Action(self.trUtf8('Compare Files side by side'),
                QIconSet(UI.PixmapCache.getPixmap("compareFiles.png")),
                self.trUtf8('Compare Files &side by side...'), 0, 0, self, 'compare_files')
        self.compareAct.setStatusTip(self.trUtf8('Compare two files'))
        self.compareAct.setWhatsThis(self.trUtf8(
            """<b>Compare Files side by side</b>"""
            """<p>Open a dialog to compare two files and show the result"""
            """ side by side.</p>"""
        ))
        self.compareAct.connectIt(SIGNAL('activated()'), self.handleCompareFilesSbs)
        self.actions.append(self.compareAct)

        self.prefAct = E3Action(self.trUtf8('Preferences'),
                QIconSet(UI.PixmapCache.getPixmap("configure.png")),
                self.trUtf8('&Preferences...'), 0, 0, self, 'preferences')
        self.prefAct.setStatusTip(self.trUtf8('Set the prefered configuration'))
        self.prefAct.setWhatsThis(self.trUtf8(
            """<b>Preferences</b>"""
            """<p>Set the configuration items of the application"""
            """ with your prefered values.</p>"""
        ))
        self.prefAct.connectIt(SIGNAL('activated()'), self.handlePreferences)
        self.actions.append(self.prefAct)

        self.reloadAPIsAct = E3Action(self.trUtf8('Reload APIs'),
                self.trUtf8('Reload &APIs'), 0, 0, self, 'reload_apis')
        self.reloadAPIsAct.setStatusTip(self.trUtf8('Reload the API information'))
        self.reloadAPIsAct.setWhatsThis(self.trUtf8(
            """<b>Reload APIs</b>"""
            """<p>Reload the API information.</p>"""
        ))
        self.reloadAPIsAct.connectIt(SIGNAL('activated()'), self.handleReloadAPIs)
        self.actions.append(self.reloadAPIsAct)

        self.configViewProfilesAct = E3Action(self.trUtf8('View Profiles'),
                QIconSet(UI.PixmapCache.getPixmap("configureViewProfiles.png")),
                self.trUtf8('&View Profiles...'), 0, 0, self, 'view_profiles')
        self.configViewProfilesAct.setStatusTip(self.trUtf8('Configure view profiles'))
        self.configViewProfilesAct.setWhatsThis(self.trUtf8(
            """<b>View Profiles</b>"""
            """<p>Configure the view profiles. With this dialog you may"""
            """ set the visibility of the various windows for the predetermined"""
            """ view profiles.</p>"""
        ))
        self.configViewProfilesAct.connectIt(SIGNAL('activated()'), self.handleConfigViewProfiles)
        self.actions.append(self.configViewProfilesAct)

        self.shortcutsAct = E3Action(self.trUtf8('Keyboard Shortcuts'),
                QIconSet(UI.PixmapCache.getPixmap("configureShortcuts.png")),
                self.trUtf8('Keyboard &Shortcuts...'), 0, 0, self, 'keyboard_shortcuts')
        self.shortcutsAct.setStatusTip(self.trUtf8('Set the keyboard shortcuts'))
        self.shortcutsAct.setWhatsThis(self.trUtf8(
            """<b>Keyboard Shortcuts</b>"""
            """<p>Set the keyboard shortcuts of the application"""
            """ with your prefered values.</p>"""
        ))
        self.shortcutsAct.connectIt(SIGNAL('activated()'), self.handleConfigShortcuts)
        self.actions.append(self.shortcutsAct)

        self.exportShortcutsAct = E3Action(self.trUtf8('Export Keyboard Shortcuts'),
                QIconSet(UI.PixmapCache.getPixmap("exportShortcuts.png")),
                self.trUtf8('&Export Keyboard Shortcuts...'), 0, 0, self,
                'export_keyboard_shortcuts')
        self.exportShortcutsAct.setStatusTip(self.trUtf8('Export the keyboard shortcuts'))
        self.exportShortcutsAct.setWhatsThis(self.trUtf8(
            """<b>Export Keyboard Shortcuts</b>"""
            """<p>Export the keyboard shortcuts of the application.</p>"""
        ))
        self.exportShortcutsAct.connectIt(SIGNAL('activated()'), self.handleExportShortcuts)
        self.actions.append(self.exportShortcutsAct)

        self.importShortcutsAct = E3Action(self.trUtf8('Import Keyboard Shortcuts'),
                QIconSet(UI.PixmapCache.getPixmap("importShortcuts.png")),
                self.trUtf8('&Import Keyboard Shortcuts...'), 0, 0, self,
                'import_keyboard_shortcuts')
        self.importShortcutsAct.setStatusTip(self.trUtf8('Import the keyboard shortcuts'))
        self.importShortcutsAct.setWhatsThis(self.trUtf8(
            """<b>Import Keyboard Shortcuts</b>"""
            """<p>Import the keyboard shortcuts of the application.</p>"""
        ))
        self.importShortcutsAct.connectIt(SIGNAL('activated()'), self.handleImportShortcuts)
        self.actions.append(self.importShortcutsAct)

        self.toolsConfAct = E3Action(self.trUtf8('Configure Tools'),
                QIconSet(UI.PixmapCache.getPixmap("toolsConfigure.png")),
                self.trUtf8('&Configure Tools...'), 0, 0, self, 'configure_tools')
        self.toolsConfAct.setStatusTip(self.trUtf8('Configure the entries for the tools menu'))
        self.toolsConfAct.setWhatsThis(self.trUtf8(
            """<b>Configure Tools</b>"""
            """<p>Configure the entries for the tools menu.</p>"""
        ))
        self.toolsConfAct.connectIt(SIGNAL('activated()'), self.handleToolsConfiguration)
        self.actions.append(self.toolsConfAct)

        self.scriptsActGrp = E3ActionGroup(self)
        
        act = E3Action(self.trUtf8('Load Script'),
                self.trUtf8('&Load Script...'), 0, 0, self.scriptsActGrp, 'load_script')
        act.setStatusTip(self.trUtf8('Load an eric3 script'))
        act.setWhatsThis(self.trUtf8(
            """<b>Load Script</b>"""
            """<p>Load an eric3 script for later use.</p>"""
        ))
        act.connectIt(SIGNAL('activated()'), self.handleLoadScript)
        self.actions.append(act)

        self.scriptsExecAct = E3Action(self.trUtf8('Execute Script'),
                self.trUtf8('&Execute Script...'), 0, 0, self.scriptsActGrp, 'execute_script')
        self.scriptsExecAct.setStatusTip(self.trUtf8('Execute an eric3 script'))
        self.scriptsExecAct.setWhatsThis(self.trUtf8(
            """<b>Execute Script</b>"""
            """<p>Execute an eric3 script.</p>"""
        ))
        self.scriptsExecAct.connectIt(SIGNAL('activated()'), self.handleExecuteScript)
        self.scriptsExecAct.setEnabled(0)
        self.actions.append(self.scriptsExecAct)
        
        self.scriptsDeleteAct = E3Action(self.trUtf8('Delete Script'),
                self.trUtf8('&Delete Script...'), 0, 0, self.scriptsActGrp, 'delete_script')
        self.scriptsDeleteAct.setStatusTip(self.trUtf8('Delete an eric3 script'))
        self.scriptsDeleteAct.setWhatsThis(self.trUtf8(
            """<b>Delete Script</b>"""
            """<p>Delete an eric3 script.</p>"""
        ))
        self.scriptsDeleteAct.connectIt(SIGNAL('activated()'), self.handleDeleteScript)
        self.scriptsDeleteAct.setEnabled(0)
        self.actions.append(self.scriptsDeleteAct)
        
        self.scriptsExecDocAct = E3Action(self.trUtf8('Execute Document as Script'),
                self.trUtf8('E&xecute Document as Script'), 0, 0, self,
                'execute_document_as_script')
        self.scriptsExecDocAct.setStatusTip(self.trUtf8('Execute current document as an eric3 script'))
        self.scriptsExecDocAct.setWhatsThis(self.trUtf8(
            """<b>Execute Document as Script</b>"""
            """<p>Execute the current document as an eric3 script.</p>"""
        ))
        self.scriptsExecDocAct.connectIt(SIGNAL('activated()'), self.handleExecuteDocumentAsScript)
        self.scriptsExecDocAct.setEnabled(0)
        self.actions.append(self.scriptsExecDocAct)
        
        # initialize viewmanager actions
        self.viewmanager.initActions()
        
        # initialize debugger actions
        self.dbg.initActions()
        
        # initialize project actions
        self.project.initActions()
        
        # initialize refactoring actions
        self.refactoring.initActions()
        
        # now read the keyboard shortcuts for the actions
        Preferences.readShortcuts(self)
    
    def initQtDocAction(self):
        """
        Private slot to initilize the action to show the Qt documentation.
        """
        self.qtDocAct = E3Action(self.trUtf8('Qt Documentation'),
                self.trUtf8('Q&t Documentation'), 0, 0, self, 'qt_documentation')
        self.qtDocAct.setStatusTip(self.trUtf8('Open Qt Documentation'))
        self.qtDocAct.setWhatsThis(self.trUtf8(
            """<b>Qt Documentation</b>"""
            """<p>Display the Qt Documentation. Dependant upon your settings, this"""
            """ will either show the help in Eric's internal help viewer, or execute"""
            """ Qt Assistant. </p>"""
        ))
        self.qtDocAct.connectIt(SIGNAL('activated()'),self.handleQtDoc)
        self.actions.append(self.qtDocAct)
      
    def initPythonDocAction(self):
        """
        Private slot to initilize the action to show the Python documentation.
        """
        self.pythonDocAct = E3Action(self.trUtf8('Python Documentation'),
            self.trUtf8('&Python Documentation'), 0, 0, self, 'python_documentation')
        self.pythonDocAct.setStatusTip(self.trUtf8('Open Python Documentation'))
        self.pythonDocAct.setWhatsThis(self.trUtf8(
                """<b>Python Documentation</b>"""
                """<p>Display the python documentation."""
                """ If no documentation directory is configured,"""
                """ the location of the python documentation is assumed to be the doc"""
                """ directory underneath the location of the python executable on"""
                """ Windows and <i>/usr/share/doc/packages/python/html</i> on Unix."""
                """ Set PYTHONDOCDIR in your environment to override this. </p>"""
        ))
        self.pythonDocAct.connectIt(SIGNAL('activated()'),self.handlePythonDoc)
        self.actions.append(self.pythonDocAct)
        
    def initEricDocAction(self):
        """
        Private slot to initialize the action to show the eric3 documentation.
        """
        self.ericDocAct = E3Action(self.trUtf8("Eric Documentation"),
            self.trUtf8('&Eric Documentation'), 0, 0, self, 'eric_documentation')
        self.ericDocAct.setStatusTip(self.trUtf8("Open Eric Documentation"))
        self.ericDocAct.setWhatsThis(self.trUtf8(
            """<b>Eric Documentation</b>"""
            """<p>Display the Eric documantation."""
            """ The location for the documentation is the Documentation/Source"""
            """ subdirectory of the eric3 installation directory.</p>"""
        ))
        self.ericDocAct.connectIt(SIGNAL('activated()'),self.handleEricDoc)
        self.actions.append(self.ericDocAct)
        
    def initMenus(self):
        """
        Private slot to create the menus.
        """
        mb = self.menuBar()

        self.fileMenu = self.viewmanager.initFileMenu()
        mb.insertItem(self.trUtf8('&File'), self.fileMenu)
        self.fileMenu.insertSeparator()
        self.exitAct.addTo(self.fileMenu)
        
        self.editMenu = self.viewmanager.initEditMenu()
        mb.insertItem(self.trUtf8('&Edit'), self.editMenu)
        
        self.viewMenu = self.viewmanager.initViewMenu()
        mb.insertItem(self.trUtf8('&View'), self.viewMenu)
        
        self.debugMenu = self.dbg.initMenu()
        mb.insertItem(self.trUtf8('&Debug'), self.debugMenu)
        
        self.unittestMenu = QPopupMenu(self)
        self.unittestMenu.insertTearOffHandle()
        mb.insertItem(self.trUtf8('&Unittest'), self.unittestMenu)
        self.utDialogAct.addTo(self.unittestMenu)
        self.unittestMenu.insertSeparator()
        self.utRestartAct.addTo(self.unittestMenu)
        self.utScriptAct.addTo(self.unittestMenu)
        self.utProjectAct.addTo(self.unittestMenu)
        
        self.projectMenu = self.project.initMenu()
        mb.insertItem(self.trUtf8('&Project'), self.projectMenu)
        
        self.refactoringMenu = self.refactoring.initMenu()
        self.refactoringMenuItem = \
            mb.insertItem(self.trUtf8('&Refactoring'), self.refactoringMenu)
        mb.setItemEnabled(self.refactoringMenuItem, 0)
        
        self.extrasMenu = QPopupMenu(self)
        self.extrasMenu.insertTearOffHandle()
        mb.insertItem(self.trUtf8('E&xtras'), self.extrasMenu)
        self.macrosMenu = self.viewmanager.initMacroMenu()
        self.extrasMenu.insertItem(self.trUtf8("&Macros"), self.macrosMenu)
        self.scriptsMenu = QPopupMenu(self)
        self.scriptsMenu.insertTearOffHandle()
        self.scriptsActGrp.addTo(self.scriptsMenu)
        self.scriptsMenu.insertSeparator()
        self.scriptsExecDocAct.addTo(self.scriptsMenu)
        self.scriptsMenu.insertSeparator()
        self.extrasMenu.insertItem(self.trUtf8("&Scripts"), self.scriptsMenu)
        self.wizardsMenu = self.wizards.initMenu()
        self.wizardsMenuItem = \
            self.extrasMenu.insertItem(self.trUtf8('Wi&zards'), self.wizardsMenu)
        self.extrasMenu.setItemEnabled(self.wizardsMenuItem, 0)
        self.toolsMenu = QPopupMenu(self)
        self.extrasMenu.insertItem(self.trUtf8('&Tools'), self.toolsMenu)
        self.connect(self.toolsMenu, SIGNAL('aboutToShow()'), self.handleShowToolsMenu)
        
        self.settingsMenu = QPopupMenu(self)
        mb.insertItem(self.trUtf8('&Settings'), self.settingsMenu)
        self.settingsMenu.insertTearOffHandle()
        self.prefAct.addTo(self.settingsMenu)
        self.reloadAPIsAct.addTo(self.settingsMenu)
        self.settingsMenu.insertSeparator()
        self.configViewProfilesAct.addTo(self.settingsMenu)
        self.settingsMenu.insertSeparator()
        self.shortcutsAct.addTo(self.settingsMenu)
        self.exportShortcutsAct.addTo(self.settingsMenu)
        self.importShortcutsAct.addTo(self.settingsMenu)
        self.settingsMenu.insertSeparator()
        self.toolsConfAct.addTo(self.settingsMenu)
        
        self.windowMenu = QPopupMenu(self)
        mb.insertItem(self.trUtf8('&Window'), self.windowMenu)
        self.connect(self.windowMenu, SIGNAL('aboutToShow()'), self.handleShowWindowMenu)
        
        self.toolbarsMenu = QPopupMenu(self.windowMenu)
        self.connect(self.toolbarsMenu, SIGNAL('aboutToShow()'), self.handleShowToolbarsMenu)
        
        self.bookmarkMenu = self.viewmanager.initBookmarkMenu()
        mb.insertItem(self.trUtf8('&Bookmarks'), self.bookmarkMenu)

        mb.insertSeparator()

        self.helpMenu = QPopupMenu(self)
        mb.insertItem(self.trUtf8('&Help'), self.helpMenu)
        self.helpMenu.insertTearOffHandle()
        self.helpviewerAct.addTo(self.helpMenu)
        self.helpMenu.insertSeparator()
        separatorNeeded = 0
        if not self.ericDocAct is None:
            self.ericDocAct.addTo(self.helpMenu)
            separatorNeeded = 1
        if not self.pythonDocAct is None:
            self.pythonDocAct.addTo(self.helpMenu)
            separatorNeeded = 1
        if not self.qtDocAct is None:
            self.qtDocAct.addTo(self.helpMenu)
            separatorNeeded = 1
        if separatorNeeded:
            self.helpMenu.insertSeparator()
        self.aboutAct.addTo(self.helpMenu)
        self.aboutQtAct.addTo(self.helpMenu)
        if self.aboutKdeAct is not None:
            self.aboutKdeAct.addTo(self.helpMenu)
        self.versionAct.addTo(self.helpMenu)
        self.helpMenu.insertSeparator()
        self.reportBugAct.addTo(self.helpMenu)
        self.helpMenu.insertSeparator()
        self.whatsThisAct.addTo(self.helpMenu)

    def initToolbars(self):
        """
        Private slot to create the toolbars.
        """
        filetb = self.viewmanager.initFileToolbar()
        edittb = self.viewmanager.initEditToolbar()
        searchtb = self.viewmanager.initSearchToolbar()
        viewtb = self.viewmanager.initViewToolbar()
        debugtb = self.dbg.initToolbar()
        projecttb = self.project.initToolbar()
        toolstb = QToolBar(self)
        unittesttb = QToolBar(self)
        bookmarktb = self.viewmanager.initBookmarkToolbar()
        settingstb = QToolBar(self)
        helptb = QToolBar(self)
        self.scriptsToolBar = QToolBar(self)
        profilestb = QToolBar(self)

        filetb.addSeparator()
        self.exitAct.addTo(filetb)
        
        self.utDialogAct.addTo(unittesttb)
        unittesttb.addSeparator()
        self.utRestartAct.addTo(unittesttb)
        self.utScriptAct.addTo(unittesttb)
        self.utProjectAct.addTo(unittesttb)
        
        if self.qtActGrp is not None:
            self.qtActGrp.addTo(toolstb)
        self.uipreviewerAct.addTo(toolstb)
        self.trpreviewerAct.addTo(toolstb)
        toolstb.addSeparator()
        self.diffAct.addTo(toolstb)
        self.compareAct.addTo(toolstb)
        
        self.prefAct.addTo(settingstb)
        self.configViewProfilesAct.addTo(settingstb)
        self.shortcutsAct.addTo(settingstb)
        self.toolsConfAct.addTo(settingstb)
        
        self.whatsThisAct.addTo(helptb)
        
        self.viewProfileActGrp.addTo(profilestb)

        # just add new toolbars to the end of the list
        self.toolbars = {}
        self.toolbars[0] = (self.trUtf8('File'), filetb)
        self.toolbars[1] = (self.trUtf8('Edit'), edittb)
        self.toolbars[2] = (self.trUtf8('Search'), searchtb)
        self.toolbars[3] = (self.trUtf8('View'), viewtb)
        self.toolbars[4] = (self.trUtf8('Debug'), debugtb)
        self.toolbars[5] = (self.trUtf8('Project'), projecttb)
        self.toolbars[6] = (self.trUtf8('Tools'), toolstb)
        self.toolbars[7] = (self.trUtf8('Help'), helptb)
        self.toolbars[8] = (self.trUtf8('Settings'), settingstb)
        self.toolbars[9] = (self.trUtf8('Scripts'), self.scriptsToolBar)
        self.toolbars[10] = (self.trUtf8('Bookmarks'), bookmarktb)
        self.toolbars[11] = (self.trUtf8('Unittest'), unittesttb)
        self.toolbars[12] = (self.trUtf8('View Profiles'), profilestb)
        Preferences.readToolbarSettings(self, self.toolbars)
        
    def initStatusbar(self):
        """
        Private slot to set up the status bar.
        """
        sb = self.statusBar()

        self.sbWritable = QLabel(sb)
        sb.addWidget(self.sbWritable,0,1)
        QWhatsThis.add(self.sbWritable,self.trUtf8(
            """<p>This part of the status bar displays an indications of the"""
            """ current editors files writability.</p>"""
        ))

        self.sbFile = QLabel(sb)
        sb.addWidget(self.sbFile,0,1)
        QWhatsThis.add(self.sbFile,self.trUtf8(
            """<p>This part of the status bar displays the name of the file of"""
            """ the current editor or of the file containing the"""
            """ Python statement that is about to be executed if a program is"""
            """ currently being debugged.</p>"""
        ))

        self.sbLine = QLabel(sb)
        sb.addWidget(self.sbLine,0,1)
        QWhatsThis.add(self.sbLine,self.trUtf8(
            """<p>This part of the status bar displays the line number of the"""
            """ current editor or the line number of the Python"""
            """ statement that is about to be executed if a program is"""
            """ currently being debugged.</p>"""
        ))

        self.sbPos = QLabel(sb)
        sb.addWidget(self.sbPos,0,1)
        QWhatsThis.add(self.sbPos,self.trUtf8(
            """<p>This part of the status bar displays the cursor position of"""
            """ the current editor. It is blank if there is no current editor or"""
            """ a program is currently being debugged.</p>"""
        ))
            
        self.viewmanager.setSbInfo(self.sbFile, self.sbLine, self.sbPos, self.sbWritable)

    def handleAbout(self):
        """
        Private slot to handle the About dialog.
        """
        dlg = AboutDialog(self)
        dlg.exec_loop()

    def handleAboutQt(self):
        """
        Private slot to handle the About Qt dialog.
        """
        QMessageBox.aboutQt(self,Program)

    def handleAboutKde(self):
        """
        Private slot to handle the About KDE dialog.
        """
        from kdeui import KAboutKDE
        dlg = KAboutKDE(self)
        dlg.exec_loop()
        
    def handleVersions(self):
        """
        Private slot to handle the Versions dialog.
        """
        try:
            import sipconfig
            sip_version_str = sipconfig.Configuration().sip_version_str
        except ImportError:
            sip_version_str = "sip version not available"
        
        if KdeQt.isKDE():
            versionText = self.trUtf8(
                """<h3>Version Numbers</h3>"""
                """<table>"""
                """<tr><td><b>Python</b></td><td>%1</td></tr>"""
                """<tr><td><b>KDE</b></td><td>%2</td></tr>"""
                """<tr><td><b>PyKDE</b></td><td>%3</td></tr>"""
                """<tr><td><b>Qt</b></td><td>%4</td></tr>"""
                """<tr><td><b>PyQt</b></td><td>%5</td></tr>"""
                """<tr><td><b>sip</b></td><td>%6</td></tr>"""
                """<tr><td><b>QScintilla</b></td><td>%7</td></tr>"""
                """<tr><td><b>%8</b></td><td>%9</td></tr>"""
                """<tr><td><b>Bicycle Repair Man</b></td><td>%1</td></tr>"""
                """</table>"""
            )\
            .arg(string.split(sys.version)[0])\
            .arg(BRM_VERSION_STR)\
            .arg(KdeQt.kdeVersionString())\
            .arg(KdeQt.pyKdeVersionString())\
            .arg(QT_VERSION_STR)\
            .arg(PYQT_VERSION_STR)\
            .arg(sip_version_str)\
            .arg(QSCINTILLA_VERSION_STR)\
            .arg(Program)\
            .arg(Version)
        else:
            versionText = self.trUtf8(
                """<h3>Version Numbers</h3>"""
                """<table>"""
                """<tr><td><b>Python</b></td><td>%1</td></tr>"""
                """<tr><td><b>Qt</b></td><td>%2</td></tr>"""
                """<tr><td><b>PyQt</b></td><td>%3</td></tr>"""
                """<tr><td><b>sip</b></td><td>%4</td></tr>"""
                """<tr><td><b>QScintilla</b></td><td>%5</td></tr>"""
                """<tr><td><b>%6</b></td><td>%7</td></tr>"""
                """<tr><td><b>Bicycle Repair Man</b></td><td>%8</td></tr>"""
                """</table>"""
            )\
            .arg(string.split(sys.version)[0])\
            .arg(QT_VERSION_STR)\
            .arg(PYQT_VERSION_STR)\
            .arg(sip_version_str)\
            .arg(QSCINTILLA_VERSION_STR)\
            .arg(Program)\
            .arg(Version)\
            .arg(BRM_VERSION_STR)
            
        KQMessageBox.about(self,Program,versionText)
        
    def handleReportBug(self):
        """
        Private slot to handle the Report Bug dialog.
        """
        if Preferences.getUser("Email").isEmpty() or \
           Preferences.getUser("MailServer").isEmpty():
            KQMessageBox.critical(None,
                self.trUtf8("Report Bug"),
                self.trUtf8("""Email address or mail server address is empty.""" 
                            """ Please configure your Email settings in the"""
                            """ Preferences Dialog."""),
                self.trUtf8("&OK"),
                QString.null,
                QString.null,
                0, -1)
            self.handlePreferences()
            return
            
        self.dlg = EmailDialog()
        self.dlg.show()
        
    def handleCompareFiles(self):
        """
        Private slot to handle the Compare Files dialog.
        """
        self.diffDlg.show()
        
    def handleCompareFilesSbs(self):
        """
        Private slot to handle the Compare Files dialog.
        """
        self.compareDlg.show()

    def getViewManager(self):
        """
        Public method to retrieve the viewmanager object.
        
        @return reference to the viewmanager object
        """
        return self.viewmanager
        
    def getProject(self):
        """
        Public method to retrieve the project object.
        
        @return reference to the project object
        """
        return self.project
        
    def getProjectBrowser(self):
        """
        Public method to retrieve the project browser object.
        
        @return reference to the project browser object
        """
        return self.projectBrowser
        
    def getDebugServer(self):
        """
        Public method to retrieve the debug server object.
        
        @return reference to the debug server object
        """
        return self.dbg.dbs
        
    def getDebugger(self):
        """
        Public method to retrieve the debugger object
        
        @return reference to the debug UI object
        """
        return self.dbg
        
    def getWizards(self):
        """
        Public method to retrieve the wizards object
        
        @return reference to the wizards object
        """
        return self.wizards
        
    def getRefactoring(self):
        """
        Public method to retrieve the refactoring object
        
        @return reference to the refactoring object
        """
        return self.refactoring
        
    def getTaskViewer(self):
        """
        Public method to retrieve the taskviewer object
        
        @return reference to the taskviewer object
        """
        return self.taskViewer
        
    def getTemplateViewer(self):
        """
        Public method to retrieve the templateviewer object
        
        @return reference to the templateviewer object
        """
        return self.templateViewer
        
    def getShell(self):
        """
        Public method to retrieve the shell object
        
        @return reference to the shell object
        """
        return self.shell
        
    def getActions(self):
        """
        Public method to get a list of all actions.
        
        @return list of all actions (list of E3Action)
        """
        return self.actions[:]
        
    def handleQuit(self):
        """
        Private method to quit the application.
        """
        if self.shutdown():
            qApp.closeAllWindows()
        
    def handleShowToolsMenu(self):
        """
        Private slot to display the Tools menu.
        """
        self.toolsMenu.clear()
        
        self.toolsMenu.insertTearOffHandle()
        
        # add the fixed entries
        if self.qtActGrp is not None:
            self.qtActGrp.addTo(self.toolsMenu)
        self.uipreviewerAct.addTo(self.toolsMenu)
        self.trpreviewerAct.addTo(self.toolsMenu)
        self.diffAct.addTo(self.toolsMenu)
        self.compareAct.addTo(self.toolsMenu)
        self.toolsMenu.insertSeparator()
        
        #add the configurable entries
        idx = 0

        for tool in self.toollist:
            id = self.toolsMenu.insertItem(tool[0], self.handleToolExecute)
            self.toolsMenu.setItemParameter(id,idx)
            
            idx = idx + 1
        
    def handleShowWindowMenu(self):
        """
        Private slot to display the Window menu.
        """
        self.windowMenu.clear()

        self.windowMenu.insertTearOffHandle()

        self.viewProfileActGrp.addTo(self.windowMenu)
        self.windowMenu.insertSeparator()
        
        # Set the options according to what is being displayed.
        self.pbAct.addTo(self.windowMenu)
        if self.layout == 1:
            self.pbAct.setOn(not self.projectBrowserDock.isHidden())
        else:
            self.pbAct.setOn(not self.projectBrowser.isHidden())
        
        if not self.embeddedFileBrowser:
            self.browserAct.addTo(self.windowMenu)
            if self.layout == 1:
                self.browserAct.setOn(not self.browserDock.isHidden())
            else:
                self.browserAct.setOn(not self.browser.isHidden())
            
        self.sbvAct.addTo(self.windowMenu)
        if self.layout == 1:
            self.sbvAct.setOn(not self.sbvDock.isHidden())
        else:
            self.sbvAct.setOn(not self.sbv.isHidden())
        
        if not self.embeddedShell:
            self.shellAct.addTo(self.windowMenu)
            if self.layout == 1:
                self.shellAct.setOn(not self.shellDock.isHidden())
            else:
                self.shellAct.setOn(not self.shell.isHidden())
            
        self.lvAct.addTo(self.windowMenu)
        if self.layout == 1:
            self.lvAct.setOn(not self.logViewerDock.isHidden())
        else:
            self.lvAct.setOn(not self.logViewer.isHidden())
        
        self.tvAct.addTo(self.windowMenu)
        if self.layout == 1:
            self.tvAct.setOn(not self.taskViewerDock.isHidden())
        else:
            self.tvAct.setOn(not self.taskViewer.isHidden())

        self.tevAct.addTo(self.windowMenu)
        if self.layout == 1:
            self.tevAct.setOn(not self.templateViewerDock.isHidden())
        else:
            self.tevAct.setOn(not self.templateViewer.isHidden())

        # Insert menu entry for toolbar settings
        self.windowMenu.insertSeparator()
        self.windowMenu.insertItem(self.trUtf8('&Toolbars'), self.toolbarsMenu)
        
        # Now do any Source Viewer related stuff.
        self.viewmanager.handleShowWindowMenu(self.windowMenu)
        
    def handleShowToolbarsMenu(self):
        """
        Private slot to display the Toolbars menu.
        """
        self.toolbarsMenu.clear()
        
        tbList = []
        for ind, (text, tb) in self.toolbars.items():
            tbList.append((unicode(text), tb, ind))
        
        tbList.sort()
        for text, tb, ind in tbList:
            id = self.toolbarsMenu.insertItem(text, self.handleTBMenu)
            self.toolbarsMenu.setItemParameter(id,ind)
            self.toolbarsMenu.setItemChecked(id,not tb.isHidden())
            
        self.toolbarsMenu.insertSeparator()
        self.toolbarsMenu.insertItem(self.trUtf8('Line up'), self.handleLineUpTBs)

    def handleTBMenu(self,idx):
        """
        Private method to handle the toggle of a toolbar.
        
        @param idx index of the selected toolbar (integer)
        """
        dummy, tb = self.toolbars[idx]
        self.toggleWindow(tb)
        
    def handleLineUpTBs(self):
        """
        Private slot to handle the line up toolbars menu entry.
        """
        self.lineUpDockWindows()
        
    def activateViewProfile(self, name):
        """
        Private slot to activate a view profile.
        
        @param name name of the profile to be activated (string)
        """
        # step 1: save the window geometries of the active profile
        if self.currentProfile:
            if self.layout == 1:
                s = QString()
                ts = QTextStream(s, IO_WriteOnly)
                ts << self
                self.profiles[self.currentProfile][1] = unicode(s)
            elif self.layout == 2:
                for window, i in zip(self.windows, range(len(self.windows))):
                    if window is not None:
                        self.profiles[self.currentProfile][2][i] = \
                            self.getFloatingGeometry(window)[:4]
        
        # step 2: set the window geometries of the new profile
        if self.layout == 1:
            s = QString(self.profiles[name][1])
            if not s.isEmpty():
                ts = QTextStream(s, IO_ReadOnly)
                ts >> self
        elif self.layout == 2:
            for window, i in zip(self.windows, range(len(self.windows))):
                if window is not None:
                    g = self.profiles[name][2][i]
                    window.resize(g[2], g[3])
                    window.move(g[0], g[1])
        
        # step 3: activate the windows of the new profile
        for window, visible in zip(self.windows, self.profiles[name][0]):
            if window is not None:
                window.setShown(visible)
        
        # step 4: remember the new profile
        self.currentProfile = name
        
        # step 5: make sure that cursor of the shell is visible
        self.shell.ensureCursorVisible()
        
    def handleSetEditProfile(self):
        """
        Public slot to activate the edit view profile.
        """
        self.activateViewProfile("edit")
        self.setEditProfileAct.setOn(1)
        
    def handleSetDebugProfile(self):
        """
        Public slot to activate the debug view profile.
        """
        self.activateViewProfile("debug")
        self.setDebugProfileAct.setOn(1)
        
    def getViewProfile(self):
        """
        Public method to get the current view profile.
        
        @return the name of the current view profile (string)
        """
        return self.currentProfile
        
    def handleProjectBrowser(self):
        """
        Private slot to handle the toggle of the Project Browser window.
        """
        if self.layout == 1:
            self.toggleWindow(self.projectBrowserDock)
        else:
            self.toggleWindow(self.projectBrowser)

    def handleSBV(self):
        """
        Private slot to handle the toggle of the Shell/Browser/Variables window.
        """
        if self.layout == 1:
            self.toggleWindow(self.sbvDock)
        else:
            self.toggleWindow(self.sbv)

    def handleShell(self):
        """
        Private slot to handle the toggle of the Shell window .
        """
        if self.layout == 1:
            self.toggleWindow(self.shellDock)
        else:
            self.toggleWindow(self.shell)

    def handleLogViewer(self):
        """
        Private slot to handle the toggle of the Log Viewer window.
        """
        if self.layout == 1:
            self.toggleWindow(self.logViewerDock)
        else:
            self.toggleWindow(self.logViewer)

    def handleTaskViewer(self):
        """
        Private slot to handle the toggle of the Task Viewer window.
        """
        if self.layout == 1:
            self.toggleWindow(self.taskViewerDock)
        else:
            self.toggleWindow(self.taskViewer)

    def handleTemplateViewer(self):
        """
        Private slot to handle the toggle of the Template Viewer window.
        """
        if self.layout == 1:
            self.toggleWindow(self.templateViewerDock)
        else:
            self.toggleWindow(self.templateViewer)

    def handleBrowser(self):
        """
        Private slot to handle the toggle of the File Browser window.
        """
        if self.layout == 1:
            self.toggleWindow(self.browserDock)
        else:
            self.toggleWindow(self.browser)

    def toggleWindow(self,w):
        """
        Private method to toggle a workspace editor window.
        
        @param w reference to the workspace editor window
        """
        if w.isHidden():
            w.show()
        else:
            w.hide()
        
    def handleToolsConfiguration(self):
        """
        Private slot to handle the tools configuration menu entry.
        """
        dlg = ToolConfigurationDialog(self.toollist, self)
        if dlg.exec_loop() == QDialog.Accepted:
            self.toollist = dlg.getToollist()
            
    def handleUnittest(self):
        """
        Private slot for displaying the unittest dialog.
        """
        self.unittestDialog.show()
        self.unittestDialog.raiseW()

    def handleUnittestScript(self, prog = None):
        """
        Private slot for displaying the unittest dialog and run the current script.
        
        @param prog the python program to be opened
        """
        if prog is None:
            aw = self.viewmanager.activeWindow()
            fn = aw.getFileName()
            tfn = Utilities.getTestFileName(fn)
            if os.path.exists(tfn):
                prog = tfn
            else:
                prog = fn
        
        self.unittestDialog.insertProg(prog)
        self.unittestDialog.show()
        self.unittestDialog.raiseW()
        self.utRestartAct.setEnabled(1)
        
    def handleUnittestProject(self):
        """
        Private slot for displaying the unittest dialog and run the current project.
        """
        fn = self.project.getMainScript(1)
        if fn:
            tfn = Utilities.getTestFileName(fn)
            if os.path.exists(tfn):
                prog = tfn
            else:
                prog = fn
        else:
            KQMessageBox.critical(self,
                self.trUtf8("Unittest Project"),
                self.trUtf8("There is no main script defined for the"
                    " current project. Aborting"),
                self.trUtf8("&OK"))
            return
        
        self.unittestDialog.insertProg(prog)
        self.unittestDialog.show()
        self.unittestDialog.raiseW()
        self.utRestartAct.setEnabled(1)
        
    def handleUnittestRestart(self):
        """
        Private slot to display the unittest dialog and rerun the last test.
        """
        self.unittestDialog.show()
        self.unittestDialog.raiseW()
        self.unittestDialog.handleStartTest()
        
    def handleDesigner(self,fn=None):
        """
        Private slot to start the Qt-Designer executable.
        
        @param fn filename of the form to be opened
        """
        proc = QProcess()
        
        designer = os.path.join(self.qtdir, 'bin', 'designer')
        if sys.platform == "win32":
            designer = designer + '.exe'
        proc.addArgument(designer)
        if fn is not None:
            fn = unicode(fn)
            try:
                if os.path.isfile(fn) and os.path.getsize(fn):
                    proc.addArgument(fn)
                else:
                    KQMessageBox.critical(self,
                        self.trUtf8('Problem'),
                        self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                            .arg(fn))
                    return
            except:
                KQMessageBox.critical(self,
                    self.trUtf8('Problem'),
                    self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                        .arg(fn))
                return
                
        if not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start Qt-Designer.<br>'
                    'Ensure that it is available as <b>%1</b>.</p>'
                ).arg(designer),
                self.trUtf8('OK'))
        
    def handleLinguist(self,fn=None):
        """
        Private slot to start the Qt-Linguist executable.
        
        @param fn filename of the translation file to be opened
        """
        proc = QProcess()
        
        linguist = os.path.join(self.qtdir, 'bin', 'linguist')
        if sys.platform == "win32":
            linguist = linguist + '.exe'
        proc.addArgument(linguist)
        if fn is not None:
            fn = unicode(fn)
            try:
                if os.path.isfile(fn) and os.path.getsize(fn):
                    proc.addArgument(fn)
                else:
                    KQMessageBox.critical(self,
                        self.trUtf8('Problem'),
                        self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                            .arg(fn))
                    return
            except:
                KQMessageBox.critical(self,
                    self.trUtf8('Problem'),
                    self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                        .arg(fn))
                return
                
        if not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start Qt-Linguist.<br>'
                    'Ensure that it is available as <b>%1</b>.</p>'
                ).arg(linguist),
                self.trUtf8('OK'))

    def handleAssistant(self, home=None):
        """
        Private slot to start the Qt-Assistant executable.
        
        @param home full pathname of a file to display (string or QString)
        """
        proc = QProcess()
        
        assistant = os.path.join(self.qtdir, 'bin', 'assistant')
        if sys.platform == "win32":
            assistant = assistant + '.exe'
        proc.addArgument(assistant)
        if home:
            proc.addArgument('-file')
            proc.addArgument(home)
        
        if not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start Qt-Assistant.<br>'
                    'Ensure that it is available as <b>%1</b>.</p>'
                ).arg(assistant),
                self.trUtf8('OK'))
        
    def handleWebBrowser(self, home=None):
        """
        Private slot to start a web browser executable.
        
        @param home full pathname of a file to display (string or QString)
        """
        webbrowser = Preferences.getHelp("Webbrowser")
        if webbrowser.isEmpty():
            webbrowser = os.environ.get("BROWSER", "")
            if not webbrowser:
                KQMessageBox.information(self,
                    self.trUtf8("Help"),
                    self.trUtf8("""Currently no Web browser is selected."""
                                """ Please use the preferences dialog to specify one."""),
                    self.trUtf8("&OK"),
                    QString.null,
                    QString.null,
                    0, -1)
                return
            
        proc = QProcess()
        proc.addArgument(webbrowser)
        if home:
            proc.addArgument(home)
        
        if not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start web browser.<br>'
                    'Ensure that it is available as <b>%1</b>.</p>'
                ).arg(webbrowser),
                self.trUtf8('OK'))
        
    def handleCustomViewer(self, home=None):
        """
        Private slot to start a custom viewer.
        
        @param home full pathname of a file to display (string or QString)
        """
        customViewer = Preferences.getHelp("CustomViewer")
        if customViewer.isEmpty():
            KQMessageBox.information(self,
                self.trUtf8("Help"),
                self.trUtf8("""Currently no custom viewer is selected."""
                            """ Please use the preferences dialog to specify one."""),
                self.trUtf8("&OK"),
                QString.null,
                QString.null,
                0, -1)
            return
            
        proc = QProcess()
        proc.addArgument(customViewer)
        if home:
            proc.addArgument(home)
        
        if not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start custom viewer.<br>'
                    'Ensure that it is available as <b>%1</b>.</p>'
                ).arg(customViewer),
                self.trUtf8('OK'))
        
    def handleUIPreviewer(self,fn=None):
        """
        Private slot to start the UI Previewer executable.
        
        @param fn filename of the form to be previewed
        """
        proc = QProcess()
        
        viewer = os.path.join(getConfig("ericDir"), "eric3-uipreviewer.py")
        
        proc.addArgument(sys.executable)
        proc.addArgument(viewer)
        
        if fn is not None:
            fn = unicode(fn)
            try:
                if os.path.isfile(fn) and os.path.getsize(fn):
                    proc.addArgument(fn)
                else:
                    KQMessageBox.critical(self,
                        self.trUtf8('Problem'),
                        self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                            .arg(fn))
                    return
            except:
                KQMessageBox.critical(self,
                    self.trUtf8('Problem'),
                    self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                        .arg(fn))
                return
                
        if not os.path.isfile(viewer) or not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start UI Previewer.<br>'
                    'Ensure that it is available as <b>%1</b>.</p>'
                ).arg(viewer),
                self.trUtf8('OK'))
        
    def handleTRPreviewer(self,fileNames=None):
        """
        Private slot to start the Translation Previewer executable.
        
        @param fileNames filenames of forms and/or translations to be previewed
        """
        proc = QProcess()
        
        viewer = os.path.join(getConfig("ericDir"), "eric3-trpreviewer.py")
        
        proc.addArgument(sys.executable)
        proc.addArgument(viewer)
        
        if fileNames is not None:
            for fn in fileNames:
                fn = unicode(fn)
                try:
                    if os.path.isfile(fn) and os.path.getsize(fn):
                        proc.addArgument(fn)
                    else:
                        KQMessageBox.critical(self,
                            self.trUtf8('Problem'),
                            self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                                .arg(fn))
                        return
                except:
                    KQMessageBox.critical(self,
                        self.trUtf8('Problem'),
                        self.trUtf8('<p>The file <b>%1</b> does not exist or is zero length.</p>')
                            .arg(fn))
                    return
        
        if not os.path.isfile(viewer) or not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start Translation Previewer.<br>'
                    'Ensure that it is available as <b>%1</b>.</p>'
                ).arg(viewer),
                self.trUtf8('OK'))
        
    def handlePixmap(self, fn):
        """
        Private slot to show a pixmap in a dialog.
        """
        dlg = PixmapDiagram(fn, self)
        if dlg.getStatus():
            dlg.show()

    def handleToolExecute(self, idx):
        """
        Private slot to execute a particular tool.
        
        @param idx index into the list of configured tools
        """
        proc = QProcess()
        proc.addArgument(self.toollist[idx][1])
        argv = Utilities.parseOptionString(self.toollist[idx][2])
        for arg in argv:
            proc.addArgument(arg)
        pl = proc.arguments()
        t = self.trUtf8("Starting process: %1").arg(pl.join(' '))
        self.emit(PYSIGNAL('appendStdout'), (t,))
            
        self.connect(proc, SIGNAL('processExited()'), self.handleToolExited)
        if self.toollist[idx][3]:
            proc.setCommunication(QProcess.Stdout | QProcess.Stderr)
            self.connect(proc, SIGNAL('readyReadStdout()'), self.handleToolStdout)
            self.connect(proc, SIGNAL('readyReadStderr()'), self.handleToolStderr)
        else:
            proc.setCommunication(0)
            
        if not proc.start():
            KQMessageBox.critical(self,
                self.trUtf8('Process Generation Error'),
                self.trUtf8(
                    '<p>Could not start the tool entry <b>%1</b>.<br>'
                    'Ensure that it is available as <b>%2</b>.</p>')\
                .arg(self.toollist[idx][0])\
                .arg(self.toollist[idx][1]),
                self.trUtf8('OK'))
        else:
            self.toolProcs.append(proc)
        
    def handleToolStdout(self):
        """
        Private slot to handle the readyReadStdout signal of a tool process.
        """
        # loop through all running tool processes
        for toolProc in self.toolProcs:
            if toolProc.canReadLineStdout():
                pl = toolProc.arguments()
                tool = pl[0]
                tool.append(" - ")
                while toolProc.canReadLineStdout():
                    s = QString(tool)
                    s.append(toolProc.readLineStdout())
                    self.emit(PYSIGNAL('appendStdout'), (s,))
        
    def handleToolStderr(self):
        """
        Private slot to handle the readyReadStderr signal of a tool process.
        """
        # loop through all running tool processes
        for toolProc in self.toolProcs:
            if toolProc.canReadLineStderr():
                pl = toolProc.arguments()
                tool = pl[0]
                tool.append(" - ")
                while toolProc.canReadLineStderr():
                    s = QString(tool)
                    s.append(toolProc.readLineStderr())
                    self.emit(PYSIGNAL('appendStderr'), (s,))
            
    def handleToolExited(self):
        """
        Private slot to handle the processExited signal of a tool process.
        """
        exitedProcs = []
        
        # loop through all running tool processes
        for toolProc in self.toolProcs:
            if not toolProc.isRunning():
                exitedProcs.append(toolProc)
                
        # now delete the exited procs from the list of running processes
        for proc in exitedProcs:
            self.toolProcs.remove(proc)
            pl = proc.arguments()
            tool = pl[0]
            t = self.trUtf8("Process '%1' has exited.").arg(tool)
            self.emit(PYSIGNAL('appendStdout'), (t,))
    
    def handlePythonDoc(self):
        """
        Private slot to show the Python documentation.
        """
        pythonDocDir = unicode(Preferences.getHelp("PythonDocDir"))
        if not pythonDocDir:
            if sys.platform == "win32":
                pythonDocDir = os.environ.get("PYTHONDOCDIR", 
                    os.path.join(os.path.dirname(sys.executable), "doc"))
            else:
                pythonDocDir = os.environ.get("PYTHONDOCDIR", 
                    '/usr/share/doc/packages/python/html')
        home = Utilities.normjoinpath(pythonDocDir, 'index.html')
        
        if not os.path.exists(home):
            KQMessageBox.warning(None,
                self.trUtf8("Documentation Missing"),
                self.trUtf8("""<p>The documentation starting point"""
                            """ "<b>%1</b>" could not be found.</p>""")\
                    .arg(home),
                self.trUtf8("&OK"),
                QString.null,
                QString.null,
                0, -1)
            return
        
        hvType = Preferences.getHelp("HelpViewerType")
        if hvType == 1:
            self.launchHelpViewer(home)
        elif hvType == 2:
            self.handleAssistant(home)
        elif hvType == 3:
            self.handleWebBrowser(home)
        else:
            self.handleCustomViewer(home)

    def handleQtDoc(self):
        """
        Private slot to show the Qt documentation.
        """
        qtDocDir = unicode(Preferences.getHelp("QtDocDir"))
        if not qtDocDir:
            if self.qtdir is None:
                qtDefDocDir = ""
            else:
                qtDefDocDir = os.path.join(self.qtdir, 'doc', 'html')
            qtDocDir = os.environ.get("QTDOCDIR", qtDefDocDir)
        home = Utilities.normjoinpath(qtDocDir, 'index.html')
        
        if not os.path.exists(home):
            KQMessageBox.warning(None,
                self.trUtf8("Documentation Missing"),
                self.trUtf8("""<p>The documentation starting point"""
                            """ "<b>%1</b>" could not be found.</p>""")\
                    .arg(home),
                self.trUtf8("&OK"),
                QString.null,
                QString.null,
                0, -1)
            return
        
        hvType = Preferences.getHelp("HelpViewerType")
        if hvType == 1:
            self.launchHelpViewer(home)
        elif hvType == 2:
            self.handleAssistant(home)
        elif hvType == 3:
            self.handleWebBrowser(home)
        else:
            self.handleCustomViewer(home)
        
    def handleEricDoc(self):
        """
        Private slot to show the Eric documentation.
        """
        home = Utilities.normjoinpath(getConfig('ericDocDir'),
            "Source", "index.html")
            
        if not os.path.exists(home):
            KQMessageBox.warning(None,
                self.trUtf8("Documentation Missing"),
                self.trUtf8("""<p>The documentation starting point"""
                            """ "<b>%1</b>" could not be found.</p>""")\
                    .arg(home),
                self.trUtf8("&OK"),
                QString.null,
                QString.null,
                0, -1)
            return
        
        hvType = Preferences.getHelp("HelpViewerType")
        if hvType == 1:
            self.launchHelpViewer(home)
        elif hvType == 2:
            self.handleAssistant(home)
        elif hvType == 3:
            self.handleWebBrowser(home)
        else:
            self.handleCustomViewer(home)
        
    def launchHelpViewer(self, home):
        """
        Private slot to start the help viewer.
        
        @param home filename of to be shown
        """
        help = HelpWindow(home, '.', None, 'help viewer', 1)
        help.setCaption(self.trUtf8('Helpviewer'))

        if QApplication.desktop().width() > 400 and \
           QApplication.desktop().height() > 500:
            help.show()
        else:
            help.showMaximized()
    
    def handleHelpViewer(self):
        """
        Private slot to start an empty help viewer.
        """
        self.launchHelpViewer("")   

    def handlePreferences(self):
        """
        Private slot to set the preferences.
        """
        dlg = ConfigurationDialog(self, 'Configuration', 1)
        dlg.exec_loop()
        qApp.processEvents()
        if dlg.result() == QDialog.Accepted:
            dlg.setPreferences()
            Preferences.syncPreferences()
            self.handlePreferencesChanged()
            self.emit(PYSIGNAL('preferencesChanged'), ())
        
    def handlePreferencesChanged(self):
        """
        Private method to handle a change of the preferences.
        """
        if Preferences.getUI("SingleApplicationMode"):
            if self.SAServer is None:
                self.SAServer = E3SingleApplicationServer()
        else:
            if self.SAServer is not None:
                self.SAServer.shutdown()
                self.SAServer = None
        
        if not Preferences.getUI("CaptionShowsFilename"):
            self.setWindowCaption(editor="")
            self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename")
        else:
            self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename")
            aw = self.viewmanager.activeWindow()
            fn = aw and aw.getFileName() or None
            if fn:
                self.setWindowCaption(editor=unicode(fn))
            else:
                self.setWindowCaption(editor="")
        
    def handleReloadAPIs(self):
        """
        Public slot to reload the api information.
        """
        self.emit(PYSIGNAL('reloadAPIs'), ())
        
    def handleConfigViewProfiles(self):
        """
        Private method to configure the various view profiles.
        """
        dlg = ViewProfileDialog(self.profiles,
            not self.embeddedShell, not self.embeddedFileBrowser)
        if dlg.exec_loop() == QDialog.Accepted:
            self.profiles = dlg.getProfiles()
            Preferences.setUI("ViewProfiles", self.profiles)
            if self.currentProfile == "edit":
                self.handleSetEditProfile()
            elif self.currentProfile == "debug":
                self.handleSetDebugProfile()
        
    def handleConfigShortcuts(self):
        """
        Private slot to configure the keyboard shortcuts.
        """
        self.shortcutsDialog.show()
        
    def handleExportShortcuts(self):
        """
        Private slot to export the keyboard shortcuts.
        """
        selectedFilter = QString('')
        fn = KQFileDialog.getSaveFileName(\
            QString.null,
            self.trUtf8("Eric3 keyboard shortcut file (*.e3k);;"
                "Compressed Eric3 keyboard shortcut file (*.e3kz)"),
            None, None,
            self.trUtf8("Export Keyboard Shortcuts"),
            selectedFilter, 1)
            
        if fn.isEmpty():
            return
            
        ext = QFileInfo(fn).extension()
        if ext.isEmpty():
            ex = selectedFilter.section('(*',1,1).section(')',0,0)
            if not ex.isEmpty():
                fn.append(ex)
        fn = unicode(fn)
            
        res = Preferences.exportShortcuts(fn)
        if not res:
            KQMessageBox.critical(None,
                self.trUtf8("Export Keyboard Shortcuts"),
                self.trUtf8("<p>The keyboard shortcuts could not be written to file <b>%1</b>.</p>").arg(fn),
                self.trUtf8("&Abort"))

    def handleImportShortcuts(self):
        """
        Private slot to import the keyboard shortcuts.
        """
        fn = KQFileDialog.getOpenFileName(\
            QString.null,
            self.trUtf8("Eric3 keyboard shortcut file (*.e3k *.e3kz)"),
            None, None,
            self.trUtf8("Import Keyboard Shortcuts"),
            None, 1)
            
        if fn.isEmpty():
            return
            
        fn = unicode(fn)
            
        Preferences.importShortcuts(fn)

    def handleNewProject(self):
        """
        Public slot to handle the NewProject signal.
        """
        self.setWindowCaption(project = self.project.name)
        
    def handleProjectOpened(self):
        """
        Public slot to handle the projectOpened signal.
        """
        self.setWindowCaption(project = self.project.name)
        cap = self.getDebugServer().getClientCapabilities(self.project.pdata["PROGLANGUAGE"][0])
        self.utProjectAct.setEnabled(cap & HasUnittest)
        self.utProjectOpen = cap & HasUnittest
        self.taskViewer.setProjectOpen(1)
        
    def handleProjectClosed(self):
        """
        Public slot to handle the projectClosed signal.
        """
        self.setWindowCaption(project = "")
        self.utProjectAct.setEnabled(0)
        if not self.utEditorOpen:
            self.utRestartAct.setEnabled(0)
        self.utProjectOpen = 0
        self.taskViewer.clearProjectTasks()
        self.taskViewer.setProjectOpen(0)

    def handleProgramChange(self,fn):
        """
        Public slot to handle the programChange signal.
        
        This primarily is here to set the currentProg variable.
        
        @param fn filename to be set as current prog (string)
        """
        # Delete the old program if there was one.
        if self.currentProg is not None:
            del self.currentProg

        self.currentProg = os.path.normpath(fn)
        
    def handleLastEditorClosed(self):
        """
        Public slot to handle the lastEditorClosed signal.
        """
        self.extrasMenu.setItemEnabled(self.wizardsMenuItem, 0)
        self.menuBar().setItemEnabled(self.refactoringMenuItem, 0)
        self.scriptsExecDocAct.setEnabled(0)
        self.utScriptAct.setEnabled(0)
        self.utEditorOpen = 0
        if not self.utProjectOpen:
            self.utRestartAct.setEnabled(0)
        self.setWindowCaption(editor="")
        
    def handleEditorOpened(self, fn):
        """
        Public slot to handle the editorOpened signal.
        
        @param fn filename of the opened editor (string)
        """
        self.extrasMenu.setItemEnabled(self.wizardsMenuItem, 1)
        self.menuBar().setItemEnabled(self.refactoringMenuItem, 1)
        self.scriptsExecDocAct.setEnabled(1)
        
        if fn:
            if fn.endswith('.py') or self.viewmanager.getOpenEditor(fn).isPyFile():
                self.utScriptAct.setEnabled(1)
                self.utEditorOpen = 1
            elif fn.endswith('.rb'):
                cap = self.getDebugServer().getClientCapabilities('Ruby')
                self.utScriptAct.setEnabled(cap & HasUnittest)
                self.utEditorOpen = cap & HasUnittest
        
    def checkActions(self, editor):
        """
        Private slot to check some actions for their enable/disable status.
        
        @param editor editor window
        """
        if editor:
            fn = editor.getFileName()
        else:
            fn = None
            
        if fn and ((os.path.splitext(fn)[1] in ['.py', '.rb']) or editor.isPyFile()):
            ext = os.path.splitext(fn)[1]
            if ext == '.py':
                cap = self.getDebugServer().getClientCapabilities('Python')
            elif ext == '.rb':
                cap = self.getDebugServer().getClientCapabilities('Ruby')
            else:
                cap = 0
            self.utScriptAct.setEnabled(cap & HasUnittest)
        else:
            self.utScriptAct.setEnabled(0)
    
    def writeTasks(self):
        """
        Public method to write the tasks data to an XML file (.e3t).
        """
        try:
            fn = os.path.join(Utilities.getConfigDir(), "eric3tasks.e3t")
            f = open(fn, "wb")
            
            TasksWriter(f, 0).writeXML()
            
            f.close()
            
        except IOError:
            KQMessageBox.critical(None,
                self.trUtf8("Save tasks"),
                self.trUtf8("<p>The tasks file <b>%1</b> could not be written.</p>")
                    .arg(fn),
                self.trUtf8("&Abort"))
        
    def readTasks(self):
        """
        Private method to read in the tasks file (.e3t)
        """
        try:
            fn = os.path.join(Utilities.getConfigDir(), "eric3tasks.e3t")
            if not os.path.exists(fn):
                return
            f = open(fn, "rb")
            line = f.readline()
            dtdLine = f.readline()
            f.close()
        except IOError:
            KQMessageBox.critical(None,
                self.trUtf8("Read tasks"),
                self.trUtf8("<p>The tasks file <b>%1</b> could not be read.</p>").arg(fn),
                self.trUtf8("&Abort"))
            return
            
        # now read the file
        if line.startswith('<?xml'):
            parser = make_parser(dtdLine.startswith("<!DOCTYPE"))
            handler = TasksHandler(taskViewer=self.taskViewer)
            er = XMLEntityResolver()
            eh = XMLErrorHandler()
            
            parser.setContentHandler(handler)
            parser.setEntityResolver(er)
            parser.setErrorHandler(eh)
            
            try:
                f = open(fn, "rb")
                try:
                    parser.parse(f)
                finally:
                    f.close()
            except IOError:
                KQMessageBox.critical(None,
                    self.trUtf8("Read tasks"),
                    self.trUtf8("<p>The tasks file <b>%1</b> could not be read.</p>").arg(fn),
                    self.trUtf8("&Abort"))
            except XMLFatalParseError:
                pass
                
            eh.showParseMessages()
        else:
            KQMessageBox.critical(None,
                self.trUtf8("Read tasks"),
                self.trUtf8("<p>The tasks file <b>%1</b> has an unsupported format.</p>").arg(fn),
                self.trUtf8("&Abort"))
    
    def writeTemplates(self, filename=None):
        """
        Public method to write the templates data to an XML file (.e3c).
        
        @param filename name of a templates file to read (string or QString)
        """
        try:
            if filename is None:
                fn = os.path.join(Utilities.getConfigDir(), "eric3templates.e3c")
            else:
                fn = unicode(filename)
            f = open(fn, "wb")
            
            TemplatesWriter(f).writeXML()
            
            f.close()
            
        except IOError:
            KQMessageBox.critical(None,
                self.trUtf8("Save templates"),
                self.trUtf8("<p>The templates file <b>%1</b> could not be written.</p>")
                    .arg(fn),
                self.trUtf8("&Abort"))
        
    def readTemplates(self, filename=None):
        """
        Public method to read in the templates file (.e3c)
        
        @param filename name of a templates file to read (string or QString)
        """
        try:
            if filename is None:
                fn = os.path.join(Utilities.getConfigDir(), "eric3templates.e3c")
                if not os.path.exists(fn):
                    return
            else:
                fn = unicode(filename)
            f = open(fn, "rb")
            line = f.readline()
            dtdLine = f.readline()
            f.close()
        except IOError:
            KQMessageBox.critical(None,
                self.trUtf8("Read templates"),
                self.trUtf8("<p>The templates file <b>%1</b> could not be read.</p>")
                    .arg(fn),
                self.trUtf8("&Abort"))
            return
            
        # now read the file
        if line.startswith('<?xml'):
            parser = make_parser(dtdLine.startswith("<!DOCTYPE"))
            handler = TemplatesHandler(templateViewer = self.templateViewer)
            er = XMLEntityResolver()
            eh = XMLErrorHandler()
            
            parser.setContentHandler(handler)
            parser.setEntityResolver(er)
            parser.setErrorHandler(eh)
            
            try:
                f = open(fn, "rb")
                try:
                    parser.parse(f)
                finally:
                    f.close()
            except IOError:
                KQMessageBox.critical(None,
                    self.trUtf8("Read templates"),
                    self.trUtf8("<p>The templates file <b>%1</b> could not be read.</p>")
                        .arg(fn),
                    self.trUtf8("&Abort"))
            except XMLFatalParseError:
                pass
                
            eh.showParseMessages()
        else:
            KQMessageBox.critical(None,
                self.trUtf8("Read templates"),
                self.trUtf8("<p>The templates file <b>%1</b> has an unsupported format.</p>")
                    .arg(fn),
                self.trUtf8("&Abort"))
    
    ##########################################################
    ## Below are slots needed by the scripts menu
    ##########################################################
    
    def handleLoadScript(self):
        """
        Private slot to handle the load script menu action.
        """
        dlg = LoadScriptDialog()
        if dlg.exec_loop() == QDialog.Accepted:
            name, fname, execute, delete = dlg.getData()
            if fname == "":
                return      # no file name entered -> ignore the action
                
            if name == "":
                # empty script name -> execute it once and delete it
                execute = 1
                delete = 1
                name = "temp_script"
                
            try:
                f = open(fname)
                code = f.read()
                f.close()
            except IOError, e:
                KQMessageBox.critical(self,
                    self.trUtf8('Error loading script'),
                    self.trUtf8('<p>The script file <b>%1</b> could not be loaded.<br>'
                        'Problem: %2</p>')
                        .arg(fname).arg(unicode(e)))
                return
                
            try:
                self.scriptManager.addScript(name, code)
            except CompilationError, e:
                KQMessageBox.critical(self,
                    self.trUtf8('Error loading script'),
                    self.trUtf8('<p>The script file <b>%1</b> could not be loaded.<br>'
                        'Problem: %2</p>')
                        .arg(fname).arg(unicode(e)))
                return
                
            if execute:
                oldpwd = os.getcwd()
                os.chdir(os.path.dirname(fname))
                try:
                    self.scriptManager.executeScript(name)
                except ExecutionError, e:
                    KQMessageBox.critical(self,
                        self.trUtf8('Error loading script'),
                        self.trUtf8('<p>The script file <b>%1</b> could not be loaded.<br>'
                            'Problem: %2</p>')
                            .arg(fname).arg(unicode(e)))
                    delete = 1
                os.chdir(oldpwd)
                    
            if delete:
                self.scriptManager.deleteScript(name)
    
    def handleDeleteScript(self):
        """
        Public method to delete a script.
        """
        name, ok = self.scriptManager.getScriptName()
        if ok and not name.isEmpty():
            self.scriptManager.deleteScript(name)
    
    def handleExecuteScript(self):
        """
        Public method to execute a script.
        """
        name, ok = self.scriptManager.getScriptName()
        if ok and not name.isEmpty():
            try:
                self.scriptManager.executeScript(name)
            except ExecutionError, e:
                KQMessageBox.critical(self,
                    self.trUtf8('Error executing script'),
                    self.trUtf8('<p>The script <b>%1</b> could not be executed.<br>'
                        'Problem: %2</p>')
                        .arg(name).arg(unicode(e)))
        
    def handleExecuteDocumentAsScript(self):
        """
        Private slot to handle the execute document as script menu action.
        """
        aw = self.viewmanager.activeWindow()
        if aw is None:
            return
            
        code = aw.text()
        name = "temp_script"
        try:
            self.scriptManager.addScript(name, code)
            self.scriptManager.executeScript(name)
            self.scriptManager.deleteScript(name)
        except Error, e:
            KQMessageBox.critical(self,
                self.trUtf8('Error executing document'),
                self.trUtf8('<p>The current document could not be executed.<br>'
                    'Problem: %1</p>')
                    .arg(unicode(e)))
     
    def handleFirstScriptAdded(self):
        """
        Private slot to handle the firstScriptAdded signal
        """
        self.scriptsDeleteAct.setEnabled(1)
        self.scriptsExecAct.setEnabled(1)
        
    def handleLastScriptDeleted(self):
        """
        Private slot to handle the lastScriptDeleted signal
        """
        self.scriptsDeleteAct.setEnabled(0)
        self.scriptsExecAct.setEnabled(0)

    #################################################################
    ## Drag and Drop Support
    #################################################################
    
    def dragEnterEvent(self, event):
        """
        Protected method to handle the drag enter event.
        
        @param event the drag enter event (QDragEnterEvent)
        """
        self.inDragDrop = QUriDrag.canDecode(event)
        event.accept(self.inDragDrop)
        
    def dragMoveEvent(self, event):
        """
        Protected method to handle the drag move event.
        
        @param event the drag move event (QDragMoveEvent)
        """
        event.accept(self.inDragDrop)
        
    def dragLeaveEvent(self, event):
        """
        Protected method to handle the drag leave event.
        
        @param event the drag leave event (QDragLeaveEvent)
        """
        if self.inDragDrop:
            self.inDragDrop = 0
        
    def dropEvent(self, event):
        """
        Protected method to handle the drop event.
        
        @param event the drop event (QDropEvent)
        """
        if QUriDrag.canDecode(event):
            flist = QStringList()
            ok = QUriDrag.decodeLocalFiles(event, flist)
            if ok:
                event.acceptAction()
                for fname in flist:
                    if not QFileInfo(fname).isDir():
                        self.viewmanager.handlePythonFile(unicode(fname))
                    else:
                        KQMessageBox.information(None,
                            self.trUtf8("Drop Error"),
                            self.trUtf8("""<p><b>%1</b> is not a file.</p>""")
                                .arg(fname),
                            self.trUtf8("&OK"),
                            QString.null,
                            QString.null,
                            0, -1)
            del flist   # explicit destruction
        
        self.inDragDrop = 0
    
    ##########################################################
    ## Below are methods needed for shutting down the IDE
    ##########################################################

    def closeEvent(self, event):
        """
        Private event handler for the close event.
        
        This event handler saves the preferences.
        
        @param event close event (QCloseEvent)
        """
        if self.shutdown():
            event.accept()
        else:
            event.ignore()

    def shutdown(self):
        """
        Private method to perform all neccessary steps to close down the IDE.
        
        @return flag indicating success
        """
        if self.shutdownCalled:
            return 1
            
        if not self.project.closeProject():
            return 0
        
        if not self.viewmanager.closeViewManager():
            return 0
        
        self.writeTasks()
        self.writeTemplates()
        
        if not self.dbg.shutdownServer():
            return 0
        
        if self.SAServer is not None:
            self.SAServer.shutdown()
            self.SAServer = None
        
        s = self.geometry()
        p = self.frameGeometry()
        Preferences.setGeometry("MainGeometry", [p.x(),p.y(),s.width(),s.height()])
        if self.layout == 0:            # splitters
            if self.embeddedShell:
                h = self.hSplitter.sizes()
                v = self.vSplitter.sizes()
                Preferences.setGeometry("MainSplitter0", h + v)
            else:
                v = self.vSplitter.sizes()
                h1 = self.hSplitter1.sizes()
                h2 = self.hSplitter2.sizes()
                Preferences.setGeometry("MainSplitter1", v + h1 + h2)
        elif self.layout == 1:          # dockable windows
            if self.embeddedShell and self.embeddedFileBrowser:
                Preferences.setMainDockLayout(self, 0)
            elif not self.embeddedFileBrowser and not self.embeddedShell:
                Preferences.setMainDockLayout(self, 3)
            elif not self.embeddedShell:
                Preferences.setMainDockLayout(self, 1)
            else:
                Preferences.setMainDockLayout(self, 2)
        elif self.layout == 2:          # floating windows
            windows = {
                "ProjectBrowser": self.projectBrowser,
                "SBV": self.sbv,
                "LogViewer": self.logViewer,
                "Shell": self.shell,
                "FileBrowser" : self.browser,
                "TaskViewer" : self.taskViewer,
                "TemplateViewer" : self.templateViewer,
            }
            if self.embeddedShell:
                del windows["Shell"]
            if self.embeddedFileBrowser:
                del windows["FileBrowser"]
            [Preferences.setGeometry(name, self.getFloatingGeometry(w))
                for name, w in windows.items()]
            for window, i in zip(self.windows, range(len(self.windows))):
                if window is not None:
                    self.profiles[self.currentProfile][2][i] = \
                        self.getFloatingGeometry(window)[:4]

        self.browser.saveToplevelDirs()
        
        Preferences.savePreferences()
        Preferences.saveToolbarSettings(self, self.toolbars)
        Preferences.saveToolsMenu(self.toollist)
        self.shutdownCalled = 1
        return 1

    ###################################
    ## Below are some utility methods
    ###################################

    def getFloatingGeometry(self, w):
        """
        Private function to get the geometry of a floating windows.
        
        This function handles the upper left corner differently on
        win32 systems.
        
        @param w reference to the widget to be saved (QWidget)
        @return list giving the widget's geometry and it's visibility
        """
        g = w.geometry()
        s = w.size()
        p = w.pos()
        return [p.x(), p.y(), s.width(), s.height(), not w.isHidden()]
