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

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

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

import os
import sys

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.Qsci import QSCINTILLA_VERSION_STR
from PyQt4.QtNetwork import QHttp

from KdeQt import KQFileDialog, KQMessageBox
from KdeQt.KQProgressDialog import KQProgressDialog
from KdeQt.KQApplication import e4App
import KdeQt

from Debugger.DebugUI import DebugUI
from Debugger.DebugServer import DebugServer
from Debugger.DebugViewer import DebugViewer
from Debugger.DebugClientCapabilities import HasUnittest

from QScintilla.Shell import Shell

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 Preferences.ToolConfigurationDialog import ToolConfigurationDialog
from Preferences.ToolGroupConfigurationDialog import ToolGroupConfigurationDialog
from Preferences.ProgramsDialog import ProgramsDialog

from Project.Project import Project
from Project.ProjectBrowser import ProjectBrowser

from Tasks.TaskViewer import TaskViewer

from Templates.TemplateViewer import TemplateViewer

from Browser import Browser
from Info import *
import Config
from EmailDialog import EmailDialog
from DiffDialog import DiffDialog
from CompareDialog import CompareDialog
from LogView import LogViewer
from FindFileDialog import FindFileDialog
from FindFileNameDialog import FindFileNameDialog
from AboutDialog import AboutDialog

from E4Gui.E4IconProvider import E4IconProvider
from E4Gui.E4SingleApplication import E4SingleApplicationServer
from E4Gui.E4Action import E4Action, E4ActionGroup

from VCS.StatusMonitorLed import StatusMonitorLed

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 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 ThirdParty.compactpath import compactpath, pathlabelwrap_qt4

from eric4config 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:
            line = self.buffer[:n]
            if self.stderr:
                e4App().getObject("UserInterface").showLogTab("stderr")
                self.emit(SIGNAL('appendStderr'), line)
            else:
                e4App().getObject("UserInterface").showLogTab("stdout")
                self.emit(SIGNAL('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(QString) emitted to write data to stderr logger
    @signal appendStdout(QString) emitted to write data to stdout logger
    @signal preferencesChanged() emitted after the preferences were changed
    @signal reloadAPIs() emitted to reload the api information
    """
    maxFilePathLen = 100
    maxSbFilePathLen = 150
    maxMenuFilePathLen = 75
    
    def __init__(self, locale, splash):
        """
        Constructor
        
        @param locale locale to be used by the UI (string)
        @param splash reference to the splashscreen (UI.SplashScreen.SplashScreen)
        """
        QMainWindow.__init__(self)
        
        self.defaultStyleName = QApplication.style().objectName()
        self.__setStyle()
        
        self.maxEditorPathLen = Preferences.getUI("CaptionFilenameLength")
        self.locale = locale
        
        self.layout, self.embeddedShell, self.embeddedFileBrowser = \
            Preferences.getUILayout()
        
        self.passiveMode = Preferences.getDebugger("PassiveDbgEnabled")
        
        g = Preferences.getGeometry("MainGeometry")
        if g.isEmpty():
            s = QSize(800, 600)
            self.resize(s)
        else:
            self.restoreGeometry(g)
            
        self.capProject = ""
        self.capEditor = ""
        self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename")
        
        QApplication.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
        self.__setWindowCaption()
        
        # load the view profiles
        self.profiles = Preferences.getUI("ViewProfiles")
        
        self.qtdir = Preferences.getQtDir()
        self.qt4dir = Preferences.getQt4Dir()

        if Preferences.getUI("UseIconProvider"):
            # Generate and set our icon provider for KQFileDialog
            self.iconProvider = E4IconProvider()
            KQFileDialog.setIconProvider(self.iconProvider)
        else:
            self.iconProvider = None
            KQFileDialog.setIconProvider(None)
        
        # Generate the debug server object
        debugServer = DebugServer()
        
        # Generate an empty project object
        self.project = Project(self)
        
        splash.showMessage(self.trUtf8("Generating Main User Interface..."))
        
        # Create the main window now so that we can connect QActions to it.
        self.__createLayout(debugServer)
        
        # Generate the debugger part of the ui
        self.debuggerUI = DebugUI(self, self.viewmanager, debugServer, 
                                  self.debugViewer, self.project)
        self.debugViewer.setDebugger(self.debuggerUI)
        self.shell.setDebuggerUI(self.debuggerUI)
        
        # Generate the redirection helpers
        self.stdout = Redirector(False)
        self.stderr = Redirector(True)
        
        # Genrae the programs dialog
        self.programsDialog = ProgramsDialog(self)
        
        # Generate the shortcuts configuration dialog
        self.shortcutsDialog = ShortcutsDialog(self, 'Shortcuts')
        
        # Generate the refactoring object
        self.refactoring = Refactoring(self)
            
        # now setup the connections
        splash.showMessage(self.trUtf8("Setting up connections..."))
        self.connect(self.browser, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.browser, SIGNAL('designerFile'),
                     self.__designer)
        self.connect(self.browser, SIGNAL('linguistFile'),
                     self.__linguist4)
        self.connect(self.browser, SIGNAL('projectFile'),
                     self.project.openProject)
        self.connect(self.browser, SIGNAL('pixmapFile'),
                     self.__showPixmap)
        self.connect(self.browser, SIGNAL('unittestOpen'),
                     self.__unittestScript)
        self.connect(self.browser, SIGNAL('trpreview'),
                     self.__TRPreviewer)
        
        self.connect(self.debugViewer.exceptionLogger, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        
        self.connect(self.debugViewer, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        
        self.connect(self.taskViewer, SIGNAL('displayFile'),
                     self.viewmanager.openSourceFile)
        
        self.connect(self.projectBrowser.psBrowser, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.projectBrowser.psBrowser, SIGNAL('closeSourceWindow'),
                     self.viewmanager.closeWindow)
        self.connect(self.projectBrowser.psBrowser, SIGNAL('unittestOpen'),
                     self.__unittestScript)
        
        self.connect(self.projectBrowser.pfBrowser, SIGNAL('designerFile'),
                     self.__designer)
        self.connect(self.projectBrowser.pfBrowser, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.projectBrowser.pfBrowser, SIGNAL('uipreview'),
                     self.__UIPreviewer)
        self.connect(self.projectBrowser.pfBrowser, SIGNAL('trpreview'),
                     self.__TRPreviewer)
        self.connect(self.projectBrowser.pfBrowser, SIGNAL('closeSourceWindow'),
                     self.viewmanager.closeWindow)
        self.connect(self.projectBrowser.pfBrowser, SIGNAL('appendStdout'),
                     self.logViewer.appendToStdout)
        self.connect(self.projectBrowser.pfBrowser, SIGNAL('appendStderr'),
                     self.logViewer.appendToStderr)
        
        self.connect(self.projectBrowser.prBrowser, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.projectBrowser.prBrowser, SIGNAL('closeSourceWindow'),
                     self.viewmanager.closeWindow)
        self.connect(self.projectBrowser.prBrowser, SIGNAL('appendStdout'),
                     self.logViewer.appendToStdout)
        self.connect(self.projectBrowser.prBrowser, SIGNAL('appendStderr'),
                     self.logViewer.appendToStderr)
        
        self.connect(self.projectBrowser.ptBrowser, SIGNAL('linguistFile'),
                     self.__linguist4)
        self.connect(self.projectBrowser.ptBrowser, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.projectBrowser.ptBrowser, SIGNAL('trpreview'),
                     self.__TRPreviewer)
        self.connect(self.projectBrowser.ptBrowser, SIGNAL('closeSourceWindow'),
                     self.viewmanager.closeWindow)
        self.connect(self.projectBrowser.ptBrowser, SIGNAL('appendStdout'),
                     self.logViewer.appendToStdout)
        self.connect(self.projectBrowser.ptBrowser, SIGNAL('appendStderr'),
                     self.logViewer.appendToStderr)
        
        self.connect(self.projectBrowser.piBrowser, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.projectBrowser.piBrowser, SIGNAL('closeSourceWindow'),
                     self.viewmanager.closeWindow)
        self.connect(self.projectBrowser.piBrowser, SIGNAL('appendStdout'),
                     self.logViewer.appendToStdout)
        self.connect(self.projectBrowser.piBrowser, SIGNAL('appendStderr'),
                     self.logViewer.appendToStderr)
        
        self.connect(self.projectBrowser.poBrowser, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.projectBrowser.poBrowser, SIGNAL('closeSourceWindow'),
                     self.viewmanager.closeWindow)
        self.connect(self.projectBrowser.poBrowser, SIGNAL('pixmapFile'),
                     self.__showPixmap)
        
        self.connect(self.project, SIGNAL('sourceFile'),
                    self.viewmanager.openFiles)
        self.connect(self.project, SIGNAL('newProject'),
                     self.viewmanager.newProject)
        self.connect(self.project, SIGNAL('projectOpened'),
                     self.viewmanager.projectOpened)
        self.connect(self.project, SIGNAL('projectClosed'),
                     self.viewmanager.projectClosed)
        self.connect(self.project, SIGNAL('projectFileRenamed'),
                     self.viewmanager.projectFileRenamed)
        self.connect(self.project, SIGNAL('newProject'),
                     self.__newProject)
        self.connect(self.project, SIGNAL('projectOpened'),
                     self.__projectOpened)
        self.connect(self.project, SIGNAL('projectClosed'),
                     self.__projectClosed)
        
        self.connect(self.debuggerUI, SIGNAL('resetUI'),
                     self.viewmanager.handleResetUI)
        self.connect(self.debuggerUI, SIGNAL('resetUI'),
                     self.debugViewer.handleResetUI)
        self.connect(self.debuggerUI, SIGNAL('resetUI'),
                     self.__setEditProfile)
        self.connect(self.debuggerUI, SIGNAL('clientStack'),
                     self.debugViewer.handleClientStack)
        self.connect(self.debuggerUI, SIGNAL('debuggingStarted'),
                     self.browser.handleProgramChange)
        self.connect(self.debuggerUI, SIGNAL('debuggingStarted'),
                     self.debugViewer.exceptionLogger.debuggingStarted)
        self.connect(self.debuggerUI, SIGNAL('debuggingStarted'),
                     self.debugViewer.handleDebuggingStarted)
        self.connect(self.debuggerUI, SIGNAL('debuggingStarted'),
                     self.__programChange)
        self.connect(self.debuggerUI, SIGNAL('debuggingStarted'),
                     self.setDebugProfile)
        self.connect(self.debuggerUI, SIGNAL('compileForms'),
                     self.projectBrowser.pfBrowser.compileChangedForms)
        self.connect(self.debuggerUI, SIGNAL('compileResources'),
                     self.projectBrowser.prBrowser.compileChangedResources)
        
        self.connect(debugServer, SIGNAL('clientStack'),
                     self.debugViewer.handleClientStack)
        self.connect(debugServer, SIGNAL('passiveDebugStarted'),
                     self.debugViewer.exceptionLogger.debuggingStarted)
        self.connect(debugServer, SIGNAL('passiveDebugStarted'),
                     self.debugViewer.handleDebuggingStarted)
        self.connect(debugServer, SIGNAL('clientException'),
                     self.debugViewer.exceptionLogger.addException)
        self.connect(debugServer, SIGNAL('clientLine'),
                     self.debugViewer.breakpointViewer.highlightBreakpoint)
        
        self.connect(self.stdout, SIGNAL('appendStdout'),
                     self.logViewer.appendToStdout)
        
        self.connect(self.stderr, SIGNAL('appendStderr'),
                     self.logViewer.appendToStderr)
        
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.viewmanager.preferencesChanged)
        self.connect(self, SIGNAL('reloadAPIs'),
                     self.viewmanager.getAPIsManager().reloadAPIs)
        self.connect(self, SIGNAL('appendStdout'),
                     self.logViewer.appendToStdout)
        self.connect(self, SIGNAL('appendStderr'),
                     self.logViewer.appendToStderr)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.shell.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.project.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.projectBrowser.psBrowser.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.projectBrowser.pfBrowser.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.projectBrowser.prBrowser.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.projectBrowser.ptBrowser.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.projectBrowser.piBrowser.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.projectBrowser.poBrowser.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.browser.handlePreferencesChanged)
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.taskViewer.handlePreferencesChanged)
        
        self.connect(self.viewmanager, SIGNAL('editorSaved'),
                     self.project.repopulateItem)
        self.connect(self.viewmanager, SIGNAL('lastEditorClosed'),
                     self.__lastEditorClosed)
        self.connect(self.viewmanager, SIGNAL('editorOpened'),
                     self.__editorOpened)
        self.connect(self.viewmanager, SIGNAL('changeCaption'),
                     self.__setWindowCaption)
        self.connect(self.viewmanager, SIGNAL('checkActions'),
                     self.__checkActions)
        self.connect(self.viewmanager, SIGNAL('editorChanged'),
                     self.projectBrowser.handleEditorChanged)
        
        self.connect(self, SIGNAL('preferencesChanged'),
                     self.refactoring.handlePreferencesChanged)
        self.connect(self.project, SIGNAL('projectOpened'),
                     self.refactoring.handleProjectOpened)
        self.connect(self.project, SIGNAL('projectClosed'),
                     self.refactoring.handleProjectClosed)
        self.connect(self.project, SIGNAL('newProject'),
                     self.refactoring.handleProjectOpened)
        
        # Generate the unittest dialog
        self.unittestDialog = UnittestDialog(None, self.debuggerUI.debugServer, self)
        self.connect(self.unittestDialog, SIGNAL('unittestFile'),
                     self.viewmanager.setFileLine)
        
        # Generate the find in project files dialog
        self.findFilesDialog = FindFileDialog(self.project)
        self.connect(self.findFilesDialog, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.findFilesDialog, SIGNAL('designerFile'),
                     self.__designer)
        
        # generate the find file dialog
        self.findFileNameDialog = FindFileNameDialog(self.project)
        self.connect(self.findFileNameDialog, SIGNAL('sourceFile'),
                     self.viewmanager.openSourceFile)
        self.connect(self.findFileNameDialog, SIGNAL('designerFile'),
                     self.__designer)
        
        # generate the diff dialogs
        self.diffDlg = DiffDialog()
        self.compareDlg = CompareDialog()
        
        # generate the wizards
        splash.showMessage(self.trUtf8("Loading Wizards..."))
        self.wizards = Wizards(self.locale, self)
        
        # Initialize the tool groups and list of started tools
        splash.showMessage(self.trUtf8("Initializing Tools..."))
        self.toolGroups, self.currentToolGroup = Preferences.readToolGroups()
        self.toolProcs = []
        
        # create a dummy help window for shortcuts handling
        self.dummyHelpViewer = HelpWindow(None, '.', None, 'help viewer', True)
        
        # register all relevant objects
        splash.showMessage(self.trUtf8("Registering Objects..."))
        e4App().registerObject("UserInterface", self)
        e4App().registerObject("DebugUI", self.debuggerUI)
        e4App().registerObject("DebugServer", debugServer)
        e4App().registerObject("ViewManager", self.viewmanager)
        e4App().registerObject("Project", self.project)
        e4App().registerObject("ProjectBrowser", self.projectBrowser)
        e4App().registerObject("Wizards", self.wizards)
        e4App().registerObject("Refactoring", self.refactoring)
        e4App().registerObject("TaskViewer", self.taskViewer)
        e4App().registerObject("TemplateViewer", self.templateViewer)
        e4App().registerObject("Shell", self.shell)
        e4App().registerObject("FindFilesDialog", self.findFilesDialog)
        e4App().registerObject("DummyHelpViewer", self.dummyHelpViewer)
        
        # initialize the character tables dialog attribute
        self.chartablesDlg = None
        
        # Initialize the actions, menues, toolbar and statusbar
        splash.showMessage(self.trUtf8("Initializing Actions..."))
        self.__initActions()
        splash.showMessage(self.trUtf8("Initializing Menus..."))
        self.__initMenus()
        splash.showMessage(self.trUtf8("Initializing Toolbars..."))
        self.__initToolbars()
        splash.showMessage(self.trUtf8("Initializing Statusbar..."))
        self.__initStatusbar()
        
        # Initialise the instance variables.
        self.currentProg = None
        self.isProg = False
        self.utEditorOpen = False
        self.utProjectOpen = False
        
        self.inDragDrop = False
        self.setAcceptDrops(True)
        
        self.currentProfile = None
        
        self.shutdownCalled = False
        self.inCloseEevent = False

        # 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.showMessage(self.trUtf8("Initializing Single Application Server..."))
            self.SAServer = E4SingleApplicationServer()
        else:
            self.SAServer = None
            
        # now fire up the scripting stuff
        splash.showMessage(self.trUtf8("Initializing Scripting..."))
        self.scriptManager = Scripting.init(self)
        self.connect(self.scriptManager, SIGNAL("firstScriptAdded"),
            self.__firstScriptAdded)
        self.connect(self.scriptManager, SIGNAL("lastScriptDeleted"),
            self.__lastScriptDeleted)
        Scripting.runStartupScripts(self)
        
        # now activate the initial view profile
        self.__setEditProfile()
        
        # now read the saved tasks
        self.__readTasks()
        
        # now read the saved templates
        self.templateViewer.readTemplates()
        
        # now start the debug client
        debugServer.startClient(False)
        
        # attribute for the http client object
        self.http = None
        
        # attribute for the help window
        self.helpWindow = None
        
        # list of web addresses serving the versions file
        self.__httpAlternatives = [
            {"host" : "die-offenbachs.homelinux.org", 
             "port" : 80, 
             "url"  : "/eric/snapshots4/versions", 
            }, 
            
            {"host" : "www.die-offenbachs.de", 
             "port" : 80, 
             "url"  : "/eric/snapshots4/versions", 
            }, 
        ]
        self.__inVersionCheck = False
        self.__versionCheckProgress = None
        
    def __setStyle(self):
        """
        Private slot to set the style of the interface.
        """
        # step 1: set the style
        style = None
        styleName = Preferences.getUI("Style")
        if styleName != "System" and styleName in QStyleFactory.keys():
            style = QStyleFactory.create(styleName)
        if style is None:
            style = QStyleFactory.create(self.defaultStyleName)
        if style is not None:
            QApplication.setStyle(style)
        
        # step 2: set a style sheet
        styleSheetFile = unicode(Preferences.getUI("StyleSheet"))
        if styleSheetFile:
            try:
                f = open(styleSheetFile, "rb")
                styleSheet = f.read()
                f.close()
            except IOError, msg:
                KQMessageBox.warning(None,
                    self.trUtf8("Loading Style Sheet"),
                    self.trUtf8("""<p>The Qt Style Sheet file <b>%1</b> could"""
                                """ not be read.<br>Reason: %2</p>"""),
                    QMessageBox.StandardButtons(\
                        QMessageBox.Ok))
                return
        else:
            styleSheet = ""
            
        e4App().setStyleSheet(styleSheet)
        
    def __createLayout(self, debugServer):
        """
        Private method to create the layout of the various windows.
        
        @param debugServer reference to the debug server object
        """
        # Create layout with movable dock windows
        if self.layout == "DockWindows":
            # Create the view manager depending on the configuration setting
            self.viewmanager = ViewManager.factory(self, self, debugServer)
            self.setCentralWidget(self.viewmanager)

            # Create the project browser
            self.projectBrowserDock = self.__createDockWindow("ProjectBrowserDock")
            self.projectBrowser = ProjectBrowser(self.project, 
                self.qtdir, self.qt4dir, self.projectBrowserDock,
                embeddedBrowser=(self.embeddedFileBrowser == 2))
            self.__setupDockWindow(self.projectBrowserDock, Qt.LeftDockWidgetArea,
                                 self.projectBrowser, self.trUtf8("Project-Viewer"))

            # Create the debug viewer maybe without the embedded shell
            self.debugViewerDock = self.__createDockWindow("DebugViewerDock")
            self.debugViewer = DebugViewer(debugServer, True, self.viewmanager, 
                self.debugViewerDock,
                embeddedShell=self.embeddedShell, 
                embeddedBrowser=(self.embeddedFileBrowser == 1))
            self.__setupDockWindow(self.debugViewerDock, Qt.RightDockWidgetArea,
                                 self.debugViewer, self.trUtf8("Debug-Viewer"))

            # Create the log viewer part of the user interface
            self.logViewerDock = self.__createDockWindow("LogViewerDock")
            self.logViewer = LogViewer(self.logViewerDock)
            self.__setupDockWindow(self.logViewerDock, Qt.BottomDockWidgetArea,
                                 self.logViewer, self.trUtf8("Log-Viewer"))

            # Create the task viewer part of the user interface
            self.taskViewerDock = self.__createDockWindow("TaskViewerDock")
            self.taskViewer = TaskViewer(self.taskViewerDock, self.project)
            self.__setupDockWindow(self.taskViewerDock, Qt.BottomDockWidgetArea,
                                 self.taskViewer, self.trUtf8("Task-Viewer"))
            
            # Create the template viewer part of the user interface
            self.templateViewerDock = self.__createDockWindow("TemplateViewerDock")
            self.templateViewer = TemplateViewer(self.templateViewerDock, 
                                                 self.viewmanager)
            self.__setupDockWindow(self.templateViewerDock, Qt.RightDockWidgetArea,
                                 self.templateViewer, self.trUtf8("Template-Viewer"))
            
            self.dockwindows = {}
            self.dockwindows[0] = \
                (self.trUtf8('Project-Viewer'), self.projectBrowserDock)
            self.dockwindows[1] = \
                (self.trUtf8('Debug-Viewer'), self.debugViewerDock)
            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.debugViewerDock, 
                None, self.logViewerDock, self.taskViewerDock, self.templateViewerDock]
            
            if self.embeddedShell:
                self.shell = self.debugViewer.shell
            else:
                # Create the shell
                self.shellDock = self.__createDockWindow("ShellDock")
                self.shell = Shell(debugServer, self.viewmanager, self.shellDock)
                self.__setupDockWindow(self.shellDock, Qt.BottomDockWidgetArea,
                                     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("BrowserDock")
                self.browser = Browser(self.browserDock)
                self.__setupDockWindow(self.browserDock, Qt.RightDockWidgetArea,
                                     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.debugViewer.browser
            else:                               # embedded in project browser
                self.browser = self.projectBrowser.fileBrowser

        # Create layout with floating windows
        elif self.layout == "FloatingWindows":
            # Create the view manager depending on the configuration setting
            self.viewmanager = ViewManager.factory(self, self, debugServer)
            self.setCentralWidget(self.viewmanager)

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

            # Create the debug viewer maybe without the embedded shell
            self.debugViewer = DebugViewer(debugServer, False, self.viewmanager, None,
                embeddedShell=self.embeddedShell, 
                embeddedBrowser=(self.embeddedFileBrowser == 1))
            self.debugViewer.setWindowTitle(self.trUtf8("Debug-Viewer"))

            # Create the log viewer part of the user interface
            self.logViewer = LogViewer(None)
            self.logViewer.setWindowTitle(self.trUtf8("Log-Viewer"))
    
            # Create the task viewer part of the user interface
            self.taskViewer = TaskViewer(None, self.project)
            self.taskViewer.setWindowTitle(self.trUtf8("Task-Viewer"))
            
            # Create the template viewer part of the user interface
            self.templateViewer = TemplateViewer(None, self.viewmanager)
            self.templateViewer.setWindowTitle(self.trUtf8("Template-Viewer"))
            
            self.windows = [self.projectBrowser, None, self.debugViewer, 
                None, self.logViewer, self.taskViewer, self.templateViewer]
            
            if self.embeddedShell:
                self.shell = self.debugViewer.shell
            else:
                # Create the shell
                self.shell = Shell(debugServer, self.viewmanager, None)
                self.windows[3] = self.shell
            
            if self.embeddedFileBrowser == 0:   # separate window
                # Create the file browser
                self.browser = Browser(None)
                self.browser.setWindowTitle(self.trUtf8("File-Browser"))
                self.windows[1] = self.browser
            elif self.embeddedFileBrowser == 1: # embedded in debug browser
                self.browser = self.debugViewer.browser
            else:                               # embedded in project browser
                self.browser = self.projectBrowser.fileBrowser
        else:
            raise RuntimeError("wrong layout type given (%s)" % self.layout)
        
    def showLogTab(self, tabname):
        """
        Public method to show a particular Log-Viewer tab.
        
        @param tabname string naming the tab to be shown (string)
        """
        self.logViewer.showLogTab(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, .e3pz, .e4p or .e4pz, 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 = False
        
        if sys.platform == 'win32':
            argChars = ['-', '/']
        else:
            argChars = ['-']

        for arg in args:
            if arg == '--' and not ddseen:
                ddseen = True
                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 ['.e4p', '.e4pz', '.e3p', '.e3pz']:
                self.project.openProject(arg)
            else:
                self.viewmanager.openFiles(arg)

        # store away any args we had
        if argsStr is not None:
            self.debuggerUI.setArgvHistory(argsStr)
        
    def __createDockWindow(self, name):
        """
        Private method to create a dock window with common properties.
        
        @param name object name of the new dock window (string or QString)
        @return the generated dock window (QDockWindow)
        """
        dock = QDockWidget()
        dock.setObjectName(name)
        dock.setFeatures(\
            QDockWidget.DockWidgetFeatures(QDockWidget.AllDockWidgetFeatures))
        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 (Qt.DockWidgetArea)
        @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()
        self.addDockWidget(where, dock)
        dock.setWidget(widget)
        dock.setWindowTitle(caption)
        dock.show()

    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 = \
                compactpath.compactPath(unicode(editor), self.maxFilePathLen)
        if project is not None:
            self.capProject = unicode(project)
        
        if self.passiveMode:
            if not self.capProject and not self.capEditor:
                self.setWindowTitle(self.trUtf8("%1 - Passive Mode").arg(Program))
            elif self.capProject and not self.capEditor:
                self.setWindowTitle(self.trUtf8("%1 - %2 - Passive Mode")\
                    .arg(self.capProject)\
                    .arg(Program))
            elif not self.capProject and self.capEditor:
                self.setWindowTitle(self.trUtf8("%1 - %2 - Passive Mode")\
                    .arg(self.capEditor)\
                    .arg(Program))
            else:
                self.setWindowTitle(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.setWindowTitle(Program)
            elif self.capProject and not self.capEditor:
                self.setWindowTitle("%s - %s" % (self.capProject, Program))
            elif not self.capProject and self.capEditor:
                self.setWindowTitle("%s - %s" % (self.capEditor, Program))
            else:
                self.setWindowTitle("%s - %s - %s" % \
                    (self.capProject, self.capEditor, Program))
        
    def __initActions(self):
        """
        Private method to define the user interface actions.
        """
        self.actions = []
        
        self.exitAct = E4Action(self.trUtf8('Quit'),
                UI.PixmapCache.getIcon("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('triggered()'), self.__quit)
        self.actions.append(self.exitAct)

        self.viewProfileActGrp = E4ActionGroup(self, "viewprofiles", True)
        
        self.setEditProfileAct = E4Action(self.trUtf8('Edit Profile'),
                UI.PixmapCache.getIcon("viewProfileEdit.png"),
                self.trUtf8('Edit Profile'),
                0, 0,
                self.viewProfileActGrp, 'edit_profile', True)
        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('triggered()'), self.__setEditProfile)
        self.actions.append(self.setEditProfileAct)
        
        self.setDebugProfileAct = E4Action(self.trUtf8('Debug Profile'),
                UI.PixmapCache.getIcon("viewProfileDebug.png"),
                self.trUtf8('Debug Profile'),
                0, 0,
                self.viewProfileActGrp, 'debug_profile', True)
        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('triggered()'),
            self.setDebugProfile)
        self.actions.append(self.setDebugProfileAct)
        
        self.pbAct = E4Action(self.trUtf8('Project-Viewer'),
                self.trUtf8('&Project-Viewer'), 0, 0, self, 'project_viewer', True)
        self.pbAct.setStatusTip(self.trUtf8('Toggle the Project-Viewer window'))
        self.pbAct.setWhatsThis(self.trUtf8(
            """<b>Toggle the Project-Viewer window</b>"""
            """<p>If the Project-Viewer window is hidden then display it."""
            """ If it is displayed then close it.</p>"""
        ))
        self.pbAct.connectIt(SIGNAL('triggered()'), self.__toggleProjectBrowser)
        self.actions.append(self.pbAct)
        
        self.pbActivateAct = E4Action(self.trUtf8('Activate Project-Viewer'),
                self.trUtf8('Activate Project-Viewer'),
                QKeySequence(self.trUtf8("Alt+Shift+P")),
                0, self,
                'project_viewer_activate', True)
        self.pbActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateProjectBrowser)
        self.actions.append(self.pbActivateAct)

        self.debugViewerAct = E4Action(self.trUtf8('Debug-Browser'),
                self.trUtf8('&Debug-Browser'), 0, 0, self, 'debug_viewer', True)
        self.debugViewerAct.setStatusTip(self.trUtf8('Toggle the Debug-Browser window'))
        self.debugViewerAct.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.debugViewerAct.connectIt(SIGNAL('triggered()'), self.__toggleDebugViewer)
        self.actions.append(self.debugViewerAct)
        
        self.debugViewerActivateAct = E4Action(self.trUtf8('Activate Debug-Browser'),
                self.trUtf8('Activate Debug-Browser'),
                QKeySequence(self.trUtf8("Alt+Shift+D")),
                0, self,
                'debug_viewer_activate', True)
        self.debugViewerActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateDebugViewer)
        self.actions.append(self.debugViewerActivateAct)

        self.shellAct = E4Action(self.trUtf8('Shell'),
                self.trUtf8('&Shell'), 0, 0, self, 'interprter_shell', True)
        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>"""
        ))
        if not self.embeddedShell:
            self.shellAct.connectIt(SIGNAL('triggered()'), self.__toggleShell)
        self.actions.append(self.shellAct)

        self.shellActivateAct = E4Action(self.trUtf8('Activate Shell'),
                self.trUtf8('Activate Shell'),
                QKeySequence(self.trUtf8("Alt+Shift+S")),
                0, self,
                'interprter_shell_activate', True)
        self.shellActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateShell)
        self.actions.append(self.shellActivateAct)

        self.browserAct = E4Action(self.trUtf8('File-Browser'),
                self.trUtf8('File-&Browser'), 0, 0, self, 'file_browser', True)
        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>"""
        ))
        if not self.embeddedFileBrowser:
            self.browserAct.connectIt(SIGNAL('triggered()'), self.__toggleBrowser)
        self.actions.append(self.browserAct)

        self.browserActivateAct = E4Action(self.trUtf8('Activate File-Browser'),
                self.trUtf8('Activate File-Browser'),
                QKeySequence(self.trUtf8("Alt+Shift+F")),
                0, self,
                'file_browser_activate', True)
        self.browserActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateBrowser)
        self.actions.append(self.browserActivateAct)

        self.logViewerAct = E4Action(self.trUtf8('Log-Viewer'),
                self.trUtf8('&Log-Viewer'), 0, 0, self, 'log_viewer', True)
        self.logViewerAct.setStatusTip(self.trUtf8('Toggle the Log-Viewer window'))
        self.logViewerAct.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.logViewerAct.connectIt(SIGNAL('triggered()'), self.__toggleLogViewer)
        self.actions.append(self.logViewerAct)

        self.logViewerActivateAct = E4Action(self.trUtf8('Activate Log-Viewer'),
                self.trUtf8('Activate Log-Viewer'),
                QKeySequence(self.trUtf8("Alt+Shift+G")),
                0, self,
                'log_viewer_activate', True)
        self.logViewerActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateLogViewer)
        self.actions.append(self.logViewerActivateAct)

        self.taskViewerAct = E4Action(self.trUtf8('Task-Viewer'),
                self.trUtf8('T&ask-Viewer'), 0, 0, self, 'task_viewer', True)
        self.taskViewerAct.setStatusTip(self.trUtf8('Toggle the Task-Viewer window'))
        self.taskViewerAct.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.taskViewerAct.connectIt(SIGNAL('triggered()'), self.__toggleTaskViewer)
        self.actions.append(self.taskViewerAct)

        self.taskViewerActivateAct = E4Action(self.trUtf8('Activate Task-Viewer'),
                self.trUtf8('Activate Task-Viewer'),
                QKeySequence(self.trUtf8("Alt+Shift+T")),
                0, self,
                'task_viewer_activate',1)
        self.taskViewerActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateTaskViewer)
        self.actions.append(self.taskViewerActivateAct)

        self.templateViewerAct = E4Action(self.trUtf8('Template-Viewer'),
                self.trUtf8('Te&mplate-Viewer'), 0, 0, self, 'template_viewer', True)
        self.templateViewerAct.setStatusTip(\
            self.trUtf8('Toggle the Template-Viewer window'))
        self.templateViewerAct.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.templateViewerAct.connectIt(SIGNAL('triggered()'), 
            self.__toggleTemplateViewer)
        self.actions.append(self.templateViewerAct)

        self.templateViewerActivateAct = E4Action(self.trUtf8('Activate Template-Viewer'),
                self.trUtf8('Activate Template-Viewer'),
                QKeySequence(self.trUtf8("Alt+Shift+M")),
                0, self,
                'template_viewer_activate',1)
        self.templateViewerActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateTemplateViewer)
        self.actions.append(self.templateViewerActivateAct)

        self.whatsThisAct = E4Action(self.trUtf8('What\'s This?'),
                UI.PixmapCache.getIcon("whatsThis.png"),
                self.trUtf8('&What\'s This?'), 
                QKeySequence(self.trUtf8("Shift+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('triggered()'), self.__whatsThis)
        self.actions.append(self.whatsThisAct)

        self.helpviewerAct = E4Action(self.trUtf8('Helpviewer'),
                UI.PixmapCache.getIcon("help.png"),
                self.trUtf8('&Helpviewer...'), 
                QKeySequence(self.trUtf8("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('triggered()'), self.__helpViewer)
        self.actions.append(self.helpviewerAct)
        
        self.__initQtDocActions()
        self.__initPythonDocAction()
        self.__initEricDocAction()
      
        self.aboutAct = E4Action(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('triggered()'), self.__about)
        self.actions.append(self.aboutAct)

        self.aboutQtAct = E4Action(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('triggered()'), self.__aboutQt)
        self.actions.append(self.aboutQtAct)
        
        if KdeQt.isKDE():
            self.aboutKdeAct = E4Action(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('triggered()'), self.__aboutKde)
            self.actions.append(self.aboutKdeAct)
        else:
            self.aboutKdeAct = None

        self.versionAct = E4Action(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('triggered()'), self.__showVersions)
        self.actions.append(self.versionAct)

        self.checkUpdateAct = E4Action(self.trUtf8('Check for Updates'),
                self.trUtf8('Check for &Updates...'), 0, 0, self, 'check_updates')
        self.checkUpdateAct.setStatusTip(self.trUtf8('Check for Updates'))
        self.checkUpdateAct.setWhatsThis(self.trUtf8(
            """<b>Check for Updates...</b>"""
            """<p>Checks the internet for updates of eric4.</p>"""
                             ))
        self.checkUpdateAct.connectIt(SIGNAL('triggered()'), self.performVersionCheck)
        self.actions.append(self.checkUpdateAct)

        self.reportBugAct = E4Action(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('triggered()'), self.__reportBug)
        self.actions.append(self.reportBugAct)

        self.utActGrp = E4ActionGroup(self)
        
        self.utDialogAct = E4Action(self.trUtf8('Unittest'), 
                UI.PixmapCache.getIcon("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('triggered()'), self.__unittest)
        self.actions.append(self.utDialogAct)

        self.utRestartAct = E4Action(self.trUtf8('Unittest Restart'),
            UI.PixmapCache.getIcon("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('triggered()'), self.__unittestRestart)
        self.utRestartAct.setEnabled(False)
        self.actions.append(self.utRestartAct)
        
        self.utScriptAct = E4Action(self.trUtf8('Unittest Script'),
            UI.PixmapCache.getIcon("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('triggered()'), self.__unittestScript)
        self.utScriptAct.setEnabled(False)
        self.actions.append(self.utScriptAct)
        
        self.utProjectAct = E4Action(self.trUtf8('Unittest Project'),
            UI.PixmapCache.getIcon("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('triggered()'), self.__unittestProject)
        self.utProjectAct.setEnabled(False)
        self.actions.append(self.utProjectAct)
        
        if self.qtdir is None:
            self.qtActGrp = None
        else:
            self.qtActGrp = E4ActionGroup(self)
            
            act = E4Action(self.trUtf8('Qt-Designer'), 
                    UI.PixmapCache.getIcon("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('triggered()'), self.__designer)
            self.actions.append(act)
            
            act = E4Action(self.trUtf8('Qt-Linguist'), 
                    UI.PixmapCache.getIcon("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('triggered()'), self.__linguist)
            self.actions.append(act)
            
        # check for Qt4 designer and linguist
        designerExe = sys.platform == 'win32' and \
            "%s.exe" % Utilities.generateQtToolName("designer") or \
            Utilities.generateQtToolName("designer")
        if Utilities.isinpath(designerExe):
            if not self.qtActGrp:
                self.qtActGrp = E4ActionGroup(self)
            act = E4Action(self.trUtf8('Qt-Designer 4'), 
                    UI.PixmapCache.getIcon("designer4.png"),
                    self.trUtf8('Designer 4...'), 0, 0, self.qtActGrp, 'qt_designer4')
            act.setStatusTip(self.trUtf8('Start Qt-Designer 4'))
            act.setWhatsThis(self.trUtf8(
                """<b>Qt-Designer 4</b>"""
                """<p>Start Qt-Designer 4.</p>"""
            ))
            act.connectIt(SIGNAL('triggered()'), self.__designer4)
            self.actions.append(act)
        
        linguistExe = sys.platform == 'win32' and \
            "%s.exe" % Utilities.generateQtToolName("linguist") or \
            Utilities.generateQtToolName("linguist")
        if Utilities.isinpath(linguistExe):
            if not self.qtActGrp:
                self.qtActGrp = E4ActionGroup(self)
            act = E4Action(self.trUtf8('Qt-Linguist 4'), 
                    UI.PixmapCache.getIcon("linguist4.png"),
                    self.trUtf8('Linguist 4...'), 0, 0, self.qtActGrp, 'qt_linguist4')
            act.setStatusTip(self.trUtf8('Start Qt-Linguist 4'))
            act.setWhatsThis(self.trUtf8(
                """<b>Qt-Linguist 4</b>"""
                """<p>Start Qt-Linguist 4.</p>"""
            ))
            act.connectIt(SIGNAL('triggered()'), self.__linguist4)
            self.actions.append(act)
        
        self.uipreviewerAct = E4Action(self.trUtf8('UI Previewer'), 
                UI.PixmapCache.getIcon("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('triggered()'), self.__UIPreviewer)
        self.actions.append(self.uipreviewerAct)
        
        self.trpreviewerAct = E4Action(self.trUtf8('Translations Previewer'), 
                UI.PixmapCache.getIcon("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('triggered()'), self.__TRPreviewer)
        self.actions.append(self.trpreviewerAct)
        
        self.diffAct = E4Action(self.trUtf8('Compare Files'),
                UI.PixmapCache.getIcon("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('triggered()'), self.__compareFiles)
        self.actions.append(self.diffAct)

        self.compareAct = E4Action(self.trUtf8('Compare Files side by side'),
                UI.PixmapCache.getIcon("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('triggered()'), self.__compareFilesSbs)
        self.actions.append(self.compareAct)

        self.chartablesAct = E4Action(self.trUtf8('Character Tables'),
                UI.PixmapCache.getIcon("chartables.png"),
                self.trUtf8('Character &Tables...'), 0, 0, self, 'chartables')
        self.chartablesAct.setStatusTip(self.trUtf8('Show character tables dialog'))
        self.chartablesAct.setWhatsThis(self.trUtf8(
            """<b>Character Tables</b>"""
            """<p>Open a dialog to show and insert special characters.</p>"""
        ))
        self.chartablesAct.connectIt(SIGNAL('triggered()'), self.__showChartables)
        self.actions.append(self.chartablesAct)

        self.prefAct = E4Action(self.trUtf8('Preferences'),
                UI.PixmapCache.getIcon("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('triggered()'), self.__preferences)
        self.actions.append(self.prefAct)

        self.reloadAPIsAct = E4Action(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('triggered()'), self.__reloadAPIs)
        self.actions.append(self.reloadAPIsAct)

        self.showExternalToolsAct = E4Action(self.trUtf8('Show external tools'),
                UI.PixmapCache.getIcon("showPrograms.png"),
                self.trUtf8('Show external &tools'), 0, 0, self, 'show_external_tools')
        self.showExternalToolsAct.setStatusTip(self.trUtf8('Reload the API information'))
        self.showExternalToolsAct.setWhatsThis(self.trUtf8(
            """<b>Show external tools</b>"""
            """<p>Opens a dialog to show the path and versions of all"""
            """ extenal tools used by eric4.</p>"""
        ))
        self.showExternalToolsAct.connectIt(SIGNAL('triggered()'), 
            self.__showExternalTools)
        self.actions.append(self.showExternalToolsAct)

        self.configViewProfilesAct = E4Action(self.trUtf8('View Profiles'),
                UI.PixmapCache.getIcon("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('triggered()'), 
            self.__configViewProfiles)
        self.actions.append(self.configViewProfilesAct)

        self.shortcutsAct = E4Action(self.trUtf8('Keyboard Shortcuts'),
                UI.PixmapCache.getIcon("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('triggered()'), self.__configShortcuts)
        self.actions.append(self.shortcutsAct)

        self.exportShortcutsAct = E4Action(self.trUtf8('Export Keyboard Shortcuts'),
                UI.PixmapCache.getIcon("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('triggered()'), 
            self.__exportShortcuts)
        self.actions.append(self.exportShortcutsAct)

        self.importShortcutsAct = E4Action(self.trUtf8('Import Keyboard Shortcuts'),
                UI.PixmapCache.getIcon("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('triggered()'), 
            self.__importShortcuts)
        self.actions.append(self.importShortcutsAct)

        self.scriptsActGrp = E4ActionGroup(self)
        
        act = E4Action(self.trUtf8('Load Script'),
                self.trUtf8('&Load Script...'), 0, 0, self.scriptsActGrp, 'load_script')
        act.setStatusTip(self.trUtf8('Load an eric4 script'))
        act.setWhatsThis(self.trUtf8(
            """<b>Load Script</b>"""
            """<p>Load an eric4 script for later use.</p>"""
        ))
        act.connectIt(SIGNAL('triggered()'), self.__loadScript)
        self.actions.append(act)

        self.scriptsExecAct = E4Action(self.trUtf8('Execute Script'),
                self.trUtf8('&Execute Script...'), 
                0, 0, self.scriptsActGrp, 'execute_script')
        self.scriptsExecAct.setStatusTip(self.trUtf8('Execute an eric4 script'))
        self.scriptsExecAct.setWhatsThis(self.trUtf8(
            """<b>Execute Script</b>"""
            """<p>Execute an eric4 script.</p>"""
        ))
        self.scriptsExecAct.connectIt(SIGNAL('triggered()'), self.__executeScript)
        self.scriptsExecAct.setEnabled(False)
        self.actions.append(self.scriptsExecAct)
        
        self.scriptsDeleteAct = E4Action(self.trUtf8('Delete Script'),
                self.trUtf8('&Delete Script...'), 
                0, 0, self.scriptsActGrp, 'delete_script')
        self.scriptsDeleteAct.setStatusTip(self.trUtf8('Delete an eric4 script'))
        self.scriptsDeleteAct.setWhatsThis(self.trUtf8(
            """<b>Delete Script</b>"""
            """<p>Delete an eric4 script.</p>"""
        ))
        self.scriptsDeleteAct.connectIt(SIGNAL('triggered()'), self.__deleteScript)
        self.scriptsDeleteAct.setEnabled(False)
        self.actions.append(self.scriptsDeleteAct)
        
        self.scriptsExecDocAct = E4Action(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 eric4 script'))
        self.scriptsExecDocAct.setWhatsThis(self.trUtf8(
            """<b>Execute Document as Script</b>"""
            """<p>Execute the current document as an eric4 script.</p>"""
        ))
        self.scriptsExecDocAct.connectIt(SIGNAL('triggered()'), 
            self.__executeDocumentAsScript)
        self.scriptsExecDocAct.setEnabled(False)
        self.actions.append(self.scriptsExecDocAct)
        
        self.viewmanagerActivateAct = E4Action(self.trUtf8('Activate current editor'),
                self.trUtf8('Activate current editor'),
                QKeySequence(self.trUtf8("Alt+Shift+E")),
                0, self,
                'viewmanager_activate',1)
        self.viewmanagerActivateAct.connectIt(SIGNAL('triggered()'),
            self.__activateViewmanager)
        self.actions.append(self.viewmanagerActivateAct)

        self.nextTabAct = E4Action(self.trUtf8('Show next tab'), 
                      self.trUtf8('Show next tab'), 
                      QKeySequence(self.trUtf8('Ctrl+Alt+Tab')), 0,
                      self, 'view_next_tab')
        self.nextTabAct.connectIt( SIGNAL('triggered()'), self.__nextTab)
        self.actions.append(self.nextTabAct)
        
        self.prevTabAct = E4Action(self.trUtf8('Show previous tab'), 
                      self.trUtf8('Show previous tab'), 
                      QKeySequence(self.trUtf8('Shift+Ctrl+Alt+Tab')), 0,
                      self, 'view_previous_tab')
        self.prevTabAct.connectIt( SIGNAL('triggered()'), self.__prevTab)
        self.actions.append(self.prevTabAct)
        
        # initialize viewmanager actions
        self.viewmanager.initActions()
        
        # initialize debugger actions
        self.debuggerUI.initActions()
        
        # initialize project actions
        self.project.initActions()
        
        # initialize refactoring actions
        self.refactoring.initActions()
        
        # now read the keyboard shortcuts for the actions
        Preferences.readShortcuts()
    
    def __initQtDocActions(self):
        """
        Private slot to initilize the action to show the Qt documentation.
        """
        self.qtDocAct = E4Action(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"""
            """ a web browser or Qt Assistant. </p>"""
        ))
        self.qtDocAct.connectIt(SIGNAL('triggered()'), self.__showQtDoc)
        self.actions.append(self.qtDocAct)
      
        self.qt4DocAct = E4Action(self.trUtf8('Qt4 Documentation'),
                self.trUtf8('Qt&4 Documentation'), 0, 0, self, 'qt4_documentation')
        self.qt4DocAct.setStatusTip(self.trUtf8('Open Qt4 Documentation'))
        self.qt4DocAct.setWhatsThis(self.trUtf8(
            """<b>Qt4 Documentation</b>"""
            """<p>Display the Qt4 Documentation. Dependant upon your settings, this"""
            """ will either show the help in Eric's internal help viewer, or execute"""
            """ a web browser or Qt Assistant. </p>"""
        ))
        self.qt4DocAct.connectIt(SIGNAL('triggered()'), self.__showQt4Doc)
        self.actions.append(self.qt4DocAct)
      
        self.pyqt4DocAct = E4Action(self.trUtf8('PyQt4 Documentation'),
                self.trUtf8('P&yQt4 Documentation'), 0, 0, self, 'pyqt4_documentation')
        self.pyqt4DocAct.setStatusTip(self.trUtf8('Open PyQt4 Documentation'))
        self.pyqt4DocAct.setWhatsThis(self.trUtf8(
            """<b>PyQt4 Documentation</b>"""
            """<p>Display the PyQt4 Documentation. Dependant upon your settings, this"""
            """ will either show the help in Eric's internal help viewer, or execute"""
            """ a web browser or Qt Assistant. </p>"""
        ))
        self.pyqt4DocAct.connectIt(SIGNAL('triggered()'), self.__showPyQt4Doc)
        self.actions.append(self.pyqt4DocAct)
      
    def __initPythonDocAction(self):
        """
        Private slot to initilize the action to show the Python documentation.
        """
        self.pythonDocAct = E4Action(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('triggered()'),self.__showPythonDoc)
        self.actions.append(self.pythonDocAct)
        
    def __initEricDocAction(self):
        """
        Private slot to initialize the action to show the eric4 documentation.
        """
        self.ericDocAct = E4Action(self.trUtf8("Eric API Documentation"),
            self.trUtf8('&Eric API Documentation'), 0, 0, self, 'eric_documentation')
        self.ericDocAct.setStatusTip(self.trUtf8("Open Eric API Documentation"))
        self.ericDocAct.setWhatsThis(self.trUtf8(
            """<b>Eric API Documentation</b>"""
            """<p>Display the Eric API documentation."""
            """ The location for the documentation is the Documentation/Source"""
            """ subdirectory of the eric4 installation directory.</p>"""
        ))
        self.ericDocAct.connectIt(SIGNAL('triggered()'),self.__showEricDoc)
        self.actions.append(self.ericDocAct)
        
    def __initMenus(self):
        """
        Private slot to create the menus.
        """
        mb = self.menuBar()

        self.fileMenu = self.viewmanager.initFileMenu()
        mb.addMenu(self.fileMenu)
        self.fileMenu.addSeparator()
        self.exitAct.addTo(self.fileMenu)
        
        self.editMenu = self.viewmanager.initEditMenu()
        mb.addMenu(self.editMenu)
        
        self.viewMenu = self.viewmanager.initViewMenu()
        mb.addMenu(self.viewMenu)
        
        self.startMenu, self.debugMenu = self.debuggerUI.initMenus()
        mb.addMenu(self.startMenu)
        mb.addMenu(self.debugMenu)
        
        self.unittestMenu = QMenu(self.trUtf8('&Unittest'), self)
        self.unittestMenu.setTearOffEnabled(True)
        mb.addMenu(self.unittestMenu)
        self.utDialogAct.addTo(self.unittestMenu)
        self.unittestMenu.addSeparator()
        self.utRestartAct.addTo(self.unittestMenu)
        self.utScriptAct.addTo(self.unittestMenu)
        self.utProjectAct.addTo(self.unittestMenu)
        
        self.projectMenu = self.project.initMenu()
        mb.addMenu(self.projectMenu)
        
        self.refactoringMenu = self.refactoring.initMenu()
        self.refactoringMenuAct = mb.addMenu(self.refactoringMenu)
        self.refactoringMenuAct.setEnabled(False)
        
        self.extrasMenu = QMenu(self.trUtf8('E&xtras'), self)
        self.extrasMenu.setTearOffEnabled(True)
        mb.addMenu(self.extrasMenu)
        self.wizardsMenu = self.wizards.initMenu()
        self.wizardsMenuAct = self.extrasMenu.addMenu(self.wizardsMenu)
        self.wizardsMenuAct.setEnabled(False)
        self.macrosMenu = self.viewmanager.initMacroMenu()
        self.extrasMenu.addMenu(self.macrosMenu)
        self.scriptsMenu = QMenu(self.trUtf8("&Scripts"), self)
        self.scriptsMenu.setTearOffEnabled(True)
        self.scriptsActGrp.addTo(self.scriptsMenu)
        self.scriptsMenu.addSeparator()
        self.scriptsExecDocAct.addTo(self.scriptsMenu)
        self.scriptsMenu.addSeparator()
        self.extrasMenu.addMenu(self.scriptsMenu)
        self.toolsMenu = QMenu(self.trUtf8('&Tools'), self)
        self.connect(self.toolsMenu, SIGNAL('aboutToShow()'), 
            self.__showToolsMenu)
        self.connect(self.toolsMenu, SIGNAL('triggered(QAction *)'),
            self.__toolExecute)
        self.toolGroupsMenu = QMenu(self.trUtf8("Select Tool Group"), self)
        self.connect(self.toolGroupsMenu, SIGNAL('aboutToShow()'), 
            self.__showToolGroupsMenu)
        self.connect(self.toolGroupsMenu, SIGNAL('triggered(QAction *)'),
            self.__toolGroupSelected)
        self.toolGroupsMenuTriggered = False
        self.extrasMenu.addMenu(self.toolsMenu)
        
        self.settingsMenu = QMenu(self.trUtf8('Se&ttings'), self)
        mb.addMenu(self.settingsMenu)
        self.settingsMenu.setTearOffEnabled(True)
        self.prefAct.addTo(self.settingsMenu)
        self.reloadAPIsAct.addTo(self.settingsMenu)
        self.settingsMenu.addSeparator()
        self.configViewProfilesAct.addTo(self.settingsMenu)
        self.settingsMenu.addSeparator()
        self.shortcutsAct.addTo(self.settingsMenu)
        self.exportShortcutsAct.addTo(self.settingsMenu)
        self.importShortcutsAct.addTo(self.settingsMenu)
        self.settingsMenu.addSeparator()
        self.showExternalToolsAct.addTo(self.settingsMenu)
        
        self.windowMenu = QMenu(self.trUtf8('&Window'), self)
        mb.addMenu(self.windowMenu)
        self.windowMenu.setTearOffEnabled(True)
        self.connect(self.windowMenu, SIGNAL('aboutToShow()'), self.__showWindowMenu)
        
        self.toolbarsMenu = QMenu(self.trUtf8("&Toolbars"), self.windowMenu)
        self.connect(self.toolbarsMenu, SIGNAL('aboutToShow()'), 
            self.__showToolbarsMenu)
        self.connect(self.toolbarsMenu, SIGNAL('triggered(QAction *)'),
            self.__TBMenuTriggered)

        self.bookmarkMenu = self.viewmanager.initBookmarkMenu()
        mb.addMenu(self.bookmarkMenu)
        self.bookmarkMenu.setTearOffEnabled(True)

        mb.addSeparator()

        self.helpMenu = QMenu(self.trUtf8('&Help'), self)
        mb.addMenu(self.helpMenu)
        self.helpMenu.setTearOffEnabled(True)
        self.helpviewerAct.addTo(self.helpMenu)
        self.helpMenu.addSeparator()
        self.ericDocAct.addTo(self.helpMenu)
        self.pythonDocAct.addTo(self.helpMenu)
        self.qtDocAct.addTo(self.helpMenu)
        self.qt4DocAct.addTo(self.helpMenu)
        self.pyqt4DocAct.addTo(self.helpMenu)
        self.helpMenu.addSeparator()
        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.addSeparator()
        self.checkUpdateAct.addTo(self.helpMenu)
        self.reportBugAct.addTo(self.helpMenu)
        self.helpMenu.addSeparator()
        self.whatsThisAct.addTo(self.helpMenu)
        self.connect(self.helpMenu, SIGNAL('aboutToShow()'), 
            self.__showHelpMenu)

    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()
        starttb, debugtb = self.debuggerUI.initToolbars()
        projecttb = self.project.initToolbar()
        toolstb = QToolBar(self.trUtf8("Tools"), self)
        unittesttb = QToolBar(self.trUtf8("Unittest"), self)
        bookmarktb = self.viewmanager.initBookmarkToolbar()
        settingstb = QToolBar(self.trUtf8("Settings"), self)
        helptb = QToolBar(self.trUtf8("Help"), self)
        self.scriptsToolBar = QToolBar(self.trUtf8("Scripts"), self)
        profilestb = QToolBar(self.trUtf8("Profiles"), self)
        
        toolstb.setIconSize(Config.ToolBarIconSize)
        unittesttb.setIconSize(Config.ToolBarIconSize)
        settingstb.setIconSize(Config.ToolBarIconSize)
        helptb.setIconSize(Config.ToolBarIconSize)
        self.scriptsToolBar.setIconSize(Config.ToolBarIconSize)
        profilestb.setIconSize(Config.ToolBarIconSize)
        
        toolstb.setObjectName("ToolsToolbar")
        unittesttb.setObjectName("UnittestToolbar")
        settingstb.setObjectName("SettingsToolbar")
        helptb.setObjectName("HelpToolbar")
        self.scriptsToolBar.setObjectName("ScriptsToolbar")
        profilestb.setObjectName("ProfilesToolbar")
        
        toolstb.setToolTip(self.trUtf8("Tools"))
        unittesttb.setToolTip(self.trUtf8("Unittest"))
        settingstb.setToolTip(self.trUtf8("Settings"))
        helptb.setToolTip(self.trUtf8("Help"))
        self.scriptsToolBar.setToolTip(self.trUtf8("Scripts"))
        profilestb.setToolTip(self.trUtf8("Profiles"))
        
        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)
        toolstb.addSeparator()
        self.chartablesAct.addTo(toolstb)
        
        self.prefAct.addTo(settingstb)
        self.configViewProfilesAct.addTo(settingstb)
        self.shortcutsAct.addTo(settingstb)
        self.showExternalToolsAct.addTo(settingstb)
        
        self.whatsThisAct.addTo(helptb)
        
        self.viewProfileActGrp.addTo(profilestb)

        self.addToolBar(filetb)
        self.addToolBar(edittb)
        self.addToolBar(searchtb)
        self.addToolBar(viewtb)
        self.addToolBar(starttb)
        self.addToolBar(debugtb)
        self.addToolBar(projecttb)
        self.addToolBar(toolstb)
        self.addToolBar(helptb)
        self.addToolBar(settingstb)
        self.addToolBar(self.scriptsToolBar)
        self.addToolBar(bookmarktb)
        self.addToolBar(unittesttb)
        self.addToolBar(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('Start'), starttb)
        self.toolbars[5] = (self.trUtf8('Debug'), debugtb)
        self.toolbars[6] = (self.trUtf8('Project'), projecttb)
        self.toolbars[7] = (self.trUtf8('Tools'), toolstb)
        self.toolbars[8] = (self.trUtf8('Help'), helptb)
        self.toolbars[9] = (self.trUtf8('Settings'), settingstb)
        self.toolbars[10] = (self.trUtf8('Scripts'), self.scriptsToolBar)
        self.toolbars[11] = (self.trUtf8('Bookmarks'), bookmarktb)
        self.toolbars[12] = (self.trUtf8('Unittest'), unittesttb)
        self.toolbars[13] = (self.trUtf8('View Profiles'), profilestb)
        
    def __initStatusbar(self):
        """
        Private slot to set up the status bar.
        """
        self.__statusBar = self.statusBar()
        self.__statusBar.setSizeGripEnabled(False)

        self.sbWritable = QLabel(self.__statusBar)
        self.__statusBar.addPermanentWidget(self.sbWritable)
        self.sbWritable.setWhatsThis(self.trUtf8(
            """<p>This part of the status bar displays an indications of the"""
            """ current editors files writability.</p>"""
        ))

        self.sbFile = QLabel(self.__statusBar)
        self.sbFile.setMaximumWidth(500)
        self.sbFile.setMinimumWidth(100)
        self.__statusBar.addPermanentWidget(self.sbFile, True)
        self.sbFile.setWhatsThis(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.sbFileWrap = pathlabelwrap_qt4.PathLabelWrap(self.sbFile)

        self.sbLine = QLabel(self.__statusBar)
        self.__statusBar.addPermanentWidget(self.sbLine)
        self.sbLine.setWhatsThis(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(self.__statusBar)
        self.__statusBar.addPermanentWidget(self.sbPos)
        self.sbPos.setWhatsThis(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.sbFileWrap, self.sbLine, self.sbPos, 
                                   self.sbWritable)

        self.sbVcsMonitorLed = StatusMonitorLed(self.project, self.__statusBar)
        self.__statusBar.addPermanentWidget(self.sbVcsMonitorLed)

    def __showHelpMenu(self):
        """
        Private slot to display the Help menu.
        """
        self.checkUpdateAct.setEnabled(not self.__inVersionCheck)
    
    def __nextTab(self):
        """
        Private slot used to show the next tab.
        """
        fwidget = QApplication.focusWidget()
        while fwidget and not hasattr(fwidget, 'nextTab'):
            fwidget = fwidget.parent()
        if fwidget:
            fwidget.nextTab()

    def __prevTab(self):
        """
        Private slot used to show the previous tab.
        """
        fwidget = QApplication.focusWidget()
        while fwidget and not hasattr(fwidget, 'prevTab'):
            fwidget = fwidget.parent()
        if fwidget:
            fwidget.prevTab()
    
    def __whatsThis(self):
        """
        Private slot called in to enter Whats This mode.
        """
        QWhatsThis.enterWhatsThisMode()
        
    def __about(self):
        """
        Private slot to handle the About dialog.
        """
        dlg = AboutDialog(self)
        dlg.exec_()

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

    def __aboutKde(self):
        """
        Private slot to handle the About KDE dialog.
        """
        from kdeui import KAboutKDE
        dlg = KAboutKDE(self)
        dlg.exec_()
        
    def __showVersions(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>""")
            versionText.append(self.trUtf8(
                """<tr><td><b>Python</b></td><td>%1</td></tr>""")\
                .arg(sys.version.split()[0]))
            versionText.append(self.trUtf8(
                """<tr><td><b>KDE</b></td><td>%1</td></tr>""")\
                .arg(KdeQt.kdeVersionString()))
            versionText.append(self.trUtf8(
                """<tr><td><b>PyKDE</b></td><td>%1</td></tr>""")\
                .arg(KdeQt.pyKdeVersionString()))
            versionText.append(self.trUtf8(
                """<tr><td><b>Qt</b></td><td>%1</td></tr>""")\
                .arg(qVersion()))
            versionText.append(self.trUtf8(
                """<tr><td><b>PyQt</b></td><td>%1</td></tr>""")\
                .arg(PYQT_VERSION_STR))
            versionText.append(self.trUtf8(
                """<tr><td><b>sip</b></td><td>%1</td></tr>""")\
                .arg(sip_version_str))
            versionText.append(self.trUtf8(
                """<tr><td><b>QScintilla</b></td><td>%1</td></tr>""")\
                .arg(QSCINTILLA_VERSION_STR))
            versionText.append(self.trUtf8(
                """<tr><td><b>%1</b></td><td>%2</td></tr>""")\
                .arg(Program)\
                .arg(Version))
            versionText.append(self.trUtf8(
                """<tr><td><b>Bicycle Repair Man</b></td><td>%1</td></tr>""")\
                .arg(BRM_VERSION_STR))
            versionText.append(self.trUtf8("""</table>"""))
        else:
            versionText = self.trUtf8(
                """<h3>Version Numbers</h3>"""
                """<table>""")
            versionText.append(self.trUtf8(
                """<tr><td><b>Python</b></td><td>%1</td></tr>""")\
                .arg(sys.version.split()[0]))
            versionText.append(self.trUtf8(
                """<tr><td><b>Qt</b></td><td>%1</td></tr>""")\
                .arg(qVersion()))
            versionText.append(self.trUtf8(
                """<tr><td><b>PyQt</b></td><td>%1</td></tr>""")\
                .arg(PYQT_VERSION_STR))
            versionText.append(self.trUtf8(
                """<tr><td><b>sip</b></td><td>%1</td></tr>""")\
                .arg(sip_version_str))
            versionText.append(self.trUtf8(
                """<tr><td><b>QScintilla</b></td><td>%1</td></tr>""")\
                .arg(QSCINTILLA_VERSION_STR))
            versionText.append(self.trUtf8(
                """<tr><td><b>%1</b></td><td>%2</td></tr>""")\
                .arg(Program)\
                .arg(Version))
            versionText.append(self.trUtf8(
                """<tr><td><b>Bicycle Repair Man</b></td><td>%1</td></tr>""")\
                .arg(BRM_VERSION_STR))
            versionText.append(self.trUtf8("""</table>"""))
        
        KQMessageBox.about(self, Program, versionText)
        
    def __reportBug(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.__preferences("emailPage")
            return
            
        self.dlg = EmailDialog()
        self.dlg.show()
        
    def __compareFiles(self):
        """
        Private slot to handle the Compare Files dialog.
        """
        self.diffDlg.show()
        
    def __compareFilesSbs(self):
        """
        Private slot to handle the Compare Files dialog.
        """
        self.compareDlg.show()
        
    def __showChartables(self):
        """
        Private slot to show the character tables dialog.
        """
        if self.chartablesDlg is None:
            # generate the character tables dialog
            from ThirdParty.chartables.e4Chartables import E4CharTablesDialog
            self.chartablesDlg = E4CharTablesDialog(self.locale)
            self.connect(self.viewmanager, SIGNAL('editorOpened'),
                self.chartablesDlg.editorOpened)
            self.connect(self.viewmanager, SIGNAL('lastEditorClosed'),
                self.chartablesDlg.lastEditorClosed)
        self.chartablesDlg.show()

    def getActions(self):
        """
        Public method to get a list of all actions.
        
        @return list of all actions (list of E4Action)
        """
        return self.actions[:]
        
    def __quit(self):
        """
        Private method to quit the application.
        """
        if self.__shutdown():
            e4App().closeAllWindows()
        
    def __showToolsMenu(self):
        """
        Private slot to display the Tools menu.
        """
        self.toolsMenu.clear()
        
        self.toolsMenu.addMenu(self.toolGroupsMenu)
        act = self.toolsMenu.addAction(self.trUtf8("Configure Tool Groups ..."),
            self.__toolGroupsConfiguration)
        act.setData(QVariant(-1))
        act = self.toolsMenu.addAction(self.trUtf8("Configure current Tool Group ..."), 
            self.__toolsConfiguration)
        act.setData(QVariant(-2))
        self.toolsMenu.addSeparator()
        
        if self.currentToolGroup == -1:
            act.setEnabled(False)
            # add the default 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.chartablesAct.addTo(self.toolsMenu)
        else:
            # add the configurable entries
            idx = 0
            try:
                for tool in self.toolGroups[self.currentToolGroup][1]:
                    if tool['menutext'] == '--':
                        self.toolsMenu.addSeparator()
                    else:
                        act = self.toolsMenu.addAction(\
                            UI.PixmapCache.getIcon(tool['icon']), tool['menutext'])
                        act.setData(QVariant(idx))
                    idx = idx + 1
            except IndexError:
                # the current tool group might have been deleted
                pass
        
    def __showToolGroupsMenu(self):
        """
        Private slot to display the Tool Groups menu.
        """
        self.toolGroupsMenu.clear()
        
        # add the default entry
        act = self.toolGroupsMenu.addAction(self.trUtf8("&Builtin Tools"))
        act.setData(QVariant(-1))
        if self.currentToolGroup == -1:
            font = act.font()
            font.setBold(True)
            act.setFont(font)
        
        # add the configurable tool groups
        idx = 0
        for toolGroup in self.toolGroups:
            act = self.toolGroupsMenu.addAction(toolGroup[0])
            act.setData(QVariant(idx))
            if self.currentToolGroup == idx:
                font = act.font()
                font.setBold(True)
                act.setFont(font)
            idx = idx + 1
        
    def __toolGroupSelected(self, act):
        """
        Private slot to set the current tool group.
        
        @param act reference to the action that was triggered (QAction)
        """
        self.toolGroupsMenuTriggered = True
        idx, ok = act.data().toInt()
        if ok:
            self.currentToolGroup = idx
        
    def __showWindowMenu(self):
        """
        Private slot to display the Window menu.
        """
        self.windowMenu.clear()
        
        self.viewProfileActGrp.addTo(self.windowMenu)
        self.windowMenu.addSeparator()
        
        # Set the options according to what is being displayed.
        self.pbAct.addTo(self.windowMenu)
        if self.layout == "DockWindows":
            self.pbAct.setChecked(not self.projectBrowserDock.isHidden())
        else:
            self.pbAct.setChecked(not self.projectBrowser.isHidden())
        
        if not self.embeddedFileBrowser:
            self.browserAct.addTo(self.windowMenu)
            if self.layout == "DockWindows":
                self.browserAct.setChecked(not self.browserDock.isHidden())
            else:
                self.browserAct.setChecked(not self.browser.isHidden())
            
        self.debugViewerAct.addTo(self.windowMenu)
        if self.layout == "DockWindows":
            self.debugViewerAct.setChecked(not self.debugViewerDock.isHidden())
        else:
            self.debugViewerAct.setChecked(not self.debugViewer.isHidden())
        
        if not self.embeddedShell:
            self.shellAct.addTo(self.windowMenu)
            if self.layout == "DockWindows":
                self.shellAct.setChecked(not self.shellDock.isHidden())
            else:
                self.shellAct.setChecked(not self.shell.isHidden())
            
        self.logViewerAct.addTo(self.windowMenu)
        if self.layout == "DockWindows":
            self.logViewerAct.setChecked(not self.logViewerDock.isHidden())
        else:
            self.logViewerAct.setChecked(not self.logViewer.isHidden())
        
        self.taskViewerAct.addTo(self.windowMenu)
        if self.layout == "DockWindows":
            self.taskViewerAct.setChecked(not self.taskViewerDock.isHidden())
        else:
            self.taskViewerAct.setChecked(not self.taskViewer.isHidden())

        self.templateViewerAct.addTo(self.windowMenu)
        if self.layout == "DockWindows":
            self.templateViewerAct.setChecked(not self.templateViewerDock.isHidden())
        else:
            self.templateViewerAct.setChecked(not self.templateViewer.isHidden())

        # Insert menu entry for toolbar settings
        self.windowMenu.addSeparator()
        self.windowMenu.addMenu(self.toolbarsMenu)
        
        # Now do any Source Viewer related stuff.
        self.viewmanager.showWindowMenu(self.windowMenu)
        
    def __showToolbarsMenu(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:
            act = self.toolbarsMenu.addAction(text)
            act.setCheckable(True)
            act.setData(QVariant(ind))
            act.setChecked(not tb.isHidden())

    def __TBMenuTriggered(self, act):
        """
        Private method to handle the toggle of a toolbar.
        
        @param act reference to the action that was triggered (QAction)
        """
        idx, ok = act.data().toInt()
        if ok:
            tb = self.toolbars[idx][1]
            self.__toggleWindow(tb)
        
    def __saveCurrentViewProfile(self, save):
        """
        Private slot to save the window geometries of the active profile.
        
        @param save flag indicating that the current profile should
            be saved (boolean)
        """
        if self.currentProfile and save:
            # step 1: save the window geometries of the active profile
            if self.layout == "DockWindows":
                state = self.saveState()
                self.profiles[self.currentProfile][1] = str(state)
            elif self.layout == "FloatingWindows":
                state = self.saveState()
                self.profiles[self.currentProfile][3] = str(state)
                for window, i in zip(self.windows, range(len(self.windows))):
                    if window is not None:
                        self.profiles[self.currentProfile][2][i] = \
                            str(window.saveGeometry())
            # step 2: save the visibility of the windows of the active profile
            for window, i in zip(self.windows, range(len(self.windows))):
                if window is not None:
                    self.profiles[self.currentProfile][0][i] = window.isVisible()
    
    def __activateViewProfile(self, name, save = True):
        """
        Private slot to activate a view profile.
        
        @param name name of the profile to be activated (string)
        @param save flag indicating that the current profile should
            be saved (boolean)
        """
        if self.currentProfile != name:
            # step 1: save the active profile
            self.__saveCurrentViewProfile(save)
            
            # step 2: set the window geometries of the new profile
            if self.layout == "DockWindows":
                state = QByteArray(self.profiles[name][1])
                if not state.isEmpty():
                    self.restoreState(state)
            elif self.layout == "FloatingWindows":
                state = QByteArray(self.profiles[name][3])
                if not state.isEmpty():
                    self.restoreState(state)
                for window, i in zip(self.windows, range(len(self.windows))):
                    if window is not None:
                        geo = QByteArray(self.profiles[name][2][i])
                        if not geo.isEmpty():
                            window.restoreGeometry(geo)
                            pass
            
            # 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.setVisible(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 __setEditProfile(self, save = True):
        """
        Private slot to activate the edit view profile.
        
        @param save flag indicating that the current profile should
            be saved (boolean)
        """
        self.__activateViewProfile("edit", save)
        self.setEditProfileAct.setChecked(True)
        
    def setDebugProfile(self, save = True):
        """
        Public slot to activate the debug view profile.
        
        @param save flag indicating that the current profile should
            be saved (boolean)
        """
        self.__activateViewProfile("debug", save)
        self.setDebugProfileAct.setChecked(True)
        
    def getViewProfile(self):
        """
        Public method to get the current view profile.
        
        @return the name of the current view profile (string)
        """
        return self.currentProfile
        
    def __toggleProjectBrowser(self):
        """
        Private slot to handle the toggle of the Project Browser window.
        """
        if self.layout == "DockWindows":
            self.__toggleWindow(self.projectBrowserDock)
        else:
            self.__toggleWindow(self.projectBrowser)

    def __activateProjectBrowser(self):
        """
        Private slot to handle the activation of the project browser.
        """
        if self.layout == "DockWindows":
            self.projectBrowserDock.show()
        else:
            self.projectBrowser.show()
        self.projectBrowser.currentWidget().setFocus(Qt.ActiveWindowFocusReason)
        
    def __toggleDebugViewer(self):
        """
        Private slot to handle the toggle of the debug viewer.
        """
        if self.layout == "DockWindows":
            self.__toggleWindow(self.debugViewerDock)
        else:
            self.__toggleWindow(self.debugViewer)

    def __activateDebugViewer(self):
        """
        Private slot to handle the activation of the debug browser.
        """
        if self.layout == "DockWindows":
            self.debugViewerDock.show()
        else:
            self.debugViewer.show()
        self.debugViewer.currentWidget().setFocus(Qt.ActiveWindowFocusReason)
        
    def __toggleShell(self):
        """
        Private slot to handle the toggle of the Shell window .
        """
        if self.layout == "DockWindows":
            self.__toggleWindow(self.shellDock)
        else:
            self.__toggleWindow(self.shell)

    def __activateShell(self):
        """
        Private slot to handle the activation of the Shell window.
        """
        if self.embeddedShell:              # embedded in debug browser
            if self.layout == "DockWindows":
                self.debugViewerDock.show()
            else:
                self.debugViewer.show()
            self.debugViewer.setCurrentWidget(self.shell)
        else:                               # separate window
            if self.layout == "DockWindows":
                self.shellDock.show()
            else:
                self.shell.show()
        self.shell.setFocus(Qt.ActiveWindowFocusReason)
        
    def __toggleLogViewer(self):
        """
        Private slot to handle the toggle of the Log Viewer window.
        """
        if self.layout == "DockWindows":
            self.__toggleWindow(self.logViewerDock)
        else:
            self.__toggleWindow(self.logViewer)

    def __activateLogViewer(self):
        """
        Private slot to handle the activation of the Log Viewer.
        """
        if self.layout == "DockWindows":
            self.logViewerDock.show()
        else:
            self.logViewer.show()
        self.logViewer.currentWidget().setFocus(Qt.ActiveWindowFocusReason)
        
    def __toggleTaskViewer(self):
        """
        Private slot to handle the toggle of the Task Viewer window.
        """
        if self.layout == "DockWindows":
            self.__toggleWindow(self.taskViewerDock)
        else:
            self.__toggleWindow(self.taskViewer)

    def __activateTaskViewer(self):
        """
        Private slot to handle the activation of the Task Viewer.
        """
        if self.layout == "DockWindows":
            self.taskViewerDock.show()
        else:
            self.taskViewer.show()
        self.taskViewer.setFocus(Qt.ActiveWindowFocusReason)
        
    def __toggleTemplateViewer(self):
        """
        Private slot to handle the toggle of the Template Viewer window.
        """
        if self.layout == "DockWindows":
            self.__toggleWindow(self.templateViewerDock)
        else:
            self.__toggleWindow(self.templateViewer)

    def __activateTemplateViewer(self):
        """
        Private slot to handle the activation of the Template Viewer.
        """
        if self.layout == "DockWindows":
            self.templateViewerDock.show()
        else:
            self.templateViewer.show()
        self.templateViewer.setFocus(Qt.ActiveWindowFocusReason)
        
    def __toggleBrowser(self):
        """
        Private slot to handle the toggle of the File Browser window.
        """
        if self.layout == "DockWindows":
            self.__toggleWindow(self.browserDock)
        else:
            self.__toggleWindow(self.browser)

    def __activateBrowser(self):
        """
        Private slot to handle the activation of the file browser.
        """
        if self.embeddedFileBrowser == 0:   # separate window
            if self.layout == "DockWindows":
                self.browserDock.show()
            else:
                self.browser.show()
        elif self.embeddedFileBrowser == 1: # embedded in debug browser
            if self.layout == "DockWindows":
                self.debugViewerDock.show()
            else:
                self.debugViewer.show()
            self.debugViewer.setCurrentWidget(self.browser)
        else:                               # embedded in project browser
            if self.layout == "DockWindows":
                self.projectBrowserDock.show()
            else:
                self.projectBrowser.show()
            self.projectBrowser.setCurrentWidget(self.browser)
        self.browser.setFocus(Qt.ActiveWindowFocusReason)
        
    def __activateViewmanager(self):
        """
        Private slot to handle the activation of the current editor.
        """
        aw = self.viewmanager.activeWindow()
        if aw is not None:
            aw.setFocus(Qt.ActiveWindowFocusReason)
    
    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 __toolsConfiguration(self):
        """
        Private slot to handle the tools configuration menu entry.
        """
        dlg = ToolConfigurationDialog(self.toolGroups[self.currentToolGroup][1], self)
        if dlg.exec_() == QDialog.Accepted:
            self.toolGroups[self.currentToolGroup][1] = dlg.getToollist()
        
    def __toolGroupsConfiguration(self):
        """
        Private slot to handle the tool groups configuration menu entry.
        """
        dlg = ToolGroupConfigurationDialog(self.toolGroups, self.currentToolGroup, self)
        if dlg.exec_() == QDialog.Accepted:
            self.toolGroups, self.currentToolGroup = dlg.getToolGroups()
        
    def __unittest(self):
        """
        Private slot for displaying the unittest dialog.
        """
        self.unittestDialog.show()
        self.unittestDialog.raise_()

    def __unittestScript(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.raise_()
        self.utRestartAct.setEnabled(True)
        
    def __unittestProject(self):
        """
        Private slot for displaying the unittest dialog and run the current project.
        """
        fn = self.project.getMainScript(True)
        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"))
            return
        
        self.unittestDialog.insertProg(prog)
        self.unittestDialog.show()
        self.unittestDialog.raise_()
        self.utRestartAct.setEnabled(True)
        
    def __unittestRestart(self):
        """
        Private slot to display the unittest dialog and rerun the last test.
        """
        self.unittestDialog.show()
        self.unittestDialog.raise_()
        self.unittestDialog.on_startButton_clicked()
        
    def __designer(self, fn = None, version = 0):
        """
        Private slot to start the Qt-Designer executable.
        
        @param fn filename of the form to be opened
        @param version indication for the requested version (Qt 3 or Qt 4) (integer)
        """
        proc = QProcess()
        
        designer = ""
        if fn is not None and version == 0:
            # determine version from file, if not specified
            try:
                f = open(fn, "rb")
                uiLine = f.readline()
                f.close()
                if uiLine.find("version") == -1:
                    # it is an old version 3 UI file
                    designer = os.path.join(self.qtdir, 'bin', 
                        Utilities.generateQtToolName("designer", True))
                else:
                    if uiLine.split('"')[1].startswith("4."):
                        designer = Utilities.generateQtToolName("designer")
                    else:
                        designer = os.path.join(self.qtdir, 'bin', 
                            Utilities.generateQtToolName("designer", True))
            except IOError:
                pass
        if not designer:
            # determine from requested version
            if version == 4:
                designer = Utilities.generateQtToolName("designer")
            else:
                designer = os.path.join(self.qtdir, 'bin', 
                    Utilities.generateQtToolName("designer", True))
        if sys.platform == "win32":
            designer = designer + '.exe'
        args = QStringList()
        if fn is not None:
            fn = unicode(fn)
            try:
                if os.path.isfile(fn) and os.path.getsize(fn):
                    args.append(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.startDetached(designer, args):
            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))
        
    def __designer4(self):
        """
        Private slot to start the Qt-Designer 4 executable.
        """
        self.__designer(version=4)
        
    def __linguist(self, fn = None, version = 3):
        """
        Private slot to start the Qt-Linguist executable.
        
        @param fn filename of the translation file to be opened
        @param version indication for the requested version (Qt 3 or Qt 4) (integer)
        """
        proc = QProcess()
        
        if version == 4:
            linguist = Utilities.generateQtToolName("linguist")
        else:
            linguist = os.path.join(self.qtdir, 'bin', 
                Utilities.generateQtToolName("linguist", True))
        if sys.platform == "win32":
            linguist = linguist + '.exe'
        args = QStringList()
        if fn is not None:
            fn = unicode(fn).replace('.qm', '.ts')
            try:
                if os.path.isfile(fn) and os.path.getsize(fn):
                    args.append(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.startDetached(linguist, args):
            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))

    def __linguist4(self, fn = None):
        """
        Private slot to start the Qt-Linguist 4 executable.
        
        @param fn filename of the translation file to be opened
        """
        self.__linguist(fn, version = 4)

    def __assistant(self, home = None, version = 3):
        """
        Private slot to start the Qt-Assistant executable.
        
        @param home full pathname of a file to display (string or QString)
        @param version indication for the requested version (Qt 3 or Qt 4) (integer)
        """
        proc = QProcess()
        
        if version == 4:
            assistant = Utilities.generateQtToolName("assistant")
        else:
            assistant = os.path.join(self.qtdir, 'bin', 
                Utilities.generateQtToolName("assistant", True))
        if sys.platform == "win32":
            assistant = assistant + '.exe'
        args = QStringList()
        if home:
            args.append('-file')
            args.append(home)
        
        if not proc.startDetached(assistant, args):
            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))
        
    def __assistant4(self):
        """
        Private slot to start the Qt-Assistant 4 executable.
        """
        self.__assistant(version=4)
    
    def __webBrowser(self, home = None):
        """
        Private slot to start a web browser executable.
        
        @param home full pathname of a file to display (string or QString)
        """
        started = QDesktopServices.openUrl(QUrl(home))
        if not started:
            KQMessageBox.critical(self,
                self.trUtf8('Open Browser'),
                self.trUtf8('Could not start a web browser'))
        
    def __customViewer(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."""))
            return
            
        proc = QProcess()
        args = QStringList()
        if home:
            args.append(home)
        
        if not proc.startDetached(customViewer, args):
            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))
        
    def __chmViewer(self, home=None):
        """
        Private slot to start the win32 help viewer to show *.chm files.
        
        @param home full pathname of a file to display (string or QString)
        """
        if home:
            proc = QProcess()
            args = QStringList()
            args.append(home)
            
            if not proc.startDetached("hh", args):
                KQMessageBox.critical(self,
                    self.trUtf8('Process Generation Error'),
                    self.trUtf8(
                        '<p>Could not start the help viewer.<br>'
                        'Ensure that it is available as <b>hh</b>.</p>'
                    ))
        
    def __UIPreviewer(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"), "eric4-uipreviewer.py")
        
        args = QStringList()
        args.append(viewer)
        
        if fn is not None:
            fn = unicode(fn)
            try:
                if os.path.isfile(fn) and os.path.getsize(fn):
                    args.append(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.startDetached(sys.executable, args):
            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))
        
    def __TRPreviewer(self, fileNames = None, ignore = False):
        """
        Private slot to start the Translation Previewer executable.
        
        @param fileNames filenames of forms and/or translations to be previewed
        @param ignore flag indicating non existing files should be ignored (boolean)
        """
        proc = QProcess()
        
        viewer = os.path.join(getConfig("ericDir"), "eric4-trpreviewer.py")
        
        args = QStringList()
        args.append(viewer)
        
        if fileNames is not None:
            for fn in fileNames:
                fn = unicode(fn)
                try:
                    if os.path.isfile(fn) and os.path.getsize(fn):
                        args.append(fn)
                    else:
                        if not ignore:
                            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:
                    if not ignore:
                        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.startDetached(sys.executable, args):
            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))
        
    def __showPixmap(self, fn):
        """
        Private slot to show a pixmap in a dialog.
        """
        dlg = PixmapDiagram(fn, self)
        if dlg.getStatus():
            dlg.show()

    def __toolExecute(self, act):
        """
        Private slot to execute a particular tool.
        
        @param act reference to the action that was triggered (QAction)
        """
        if self.toolGroupsMenuTriggered:
            # ignore actions triggered from the select tool group submenu
            self.toolGroupsMenuTriggered = False
            return
        
        if self.currentToolGroup == -1:
            # it was a built in tool, don't handle it here
            return
        
        idx, ok = act.data().toInt()
        if ok and idx >= 0:
            tool = self.toolGroups[self.currentToolGroup][1]
            proc = QProcess()
            procData = (None,)
            program = unicode(tool[idx]['executable'])
            args = QStringList()
            argv = Utilities.parseOptionString(tool[idx]['arguments'])
            for arg in argv:
                args.append(arg)
            pl = QStringList(program) + args
            t = self.trUtf8("Starting process '%1 %2'.\n")\
                .arg(program)\
                .arg(tool[idx]['arguments'])
            self.emit(SIGNAL('appendStdout'), t)
            
            self.connect(proc, SIGNAL('finished(int, QProcess::ExitStatus)'), 
                self.__toolFinished)
            if tool[idx]['redirect'] != 'no':
                self.connect(proc, SIGNAL('readyReadStandardOutput()'), 
                    self.__processToolStdout)
                self.connect(proc, SIGNAL('readyReadStandardError()'), 
                    self.__processToolStderr)
                if tool[idx]['redirect'] in ["insert", "replaceSelection"]:
                    aw = self.viewmanager.activeWindow()
                    procData = (aw, tool[idx]['redirect'], [])
                    if aw is not None:
                        aw.beginUndoAction()
            
            proc.start(program, args)
            if not proc.waitForStarted():
                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(tool[idx]['menutext']).arg(tool[idx]['executable']))
            else:
                self.toolProcs.append((program, proc, procData))
                if tool[idx]['redirect'] == 'no':
                    proc.closeReadChannel(QProcess.StandardOutput)
                    proc.closeReadChannel(QProcess.StandardError)
                    proc.closeWriteChannel()
        
    def __processToolStdout(self):
        """
        Private slot to handle the readyReadStdout signal of a tool process.
        """
        # loop through all running tool processes
        for program, toolProc, toolProcData in self.toolProcs:
            toolProc.setReadChannel(QProcess.StandardOutput)
            
            if toolProcData[0] is None or \
               toolProcData[1] not in ["insert", "replaceSelection"]: 
                # not connected to an editor or wrong mode
                while toolProc.canReadLine():
                    s = QString("%s - " % program)
                    s.append(toolProc.readLine())
                    self.emit(SIGNAL('appendStdout'), s)
            else:
                if toolProcData[1] == "insert":
                    text = toolProc.readAll()
                    toolProcData[0].insert(text)
                elif toolProcData[1] == "replaceSelection":
                    text = toolProc.readAll()
                    toolProcData[2].append(unicode(text))
        
    def __processToolStderr(self):
        """
        Private slot to handle the readyReadStderr signal of a tool process.
        """
        # loop through all running tool processes
        for program, toolProc, toolProcData in self.toolProcs:
            toolProc.setReadChannel(QProcess.StandardError)
            
            while toolProc.canReadLine():
                s = QString("%s - " % program)
                s.append(toolProc.readLine())
                self.emit(SIGNAL('appendStderr'), s)
        
    def __toolFinished(self, exitCode, exitStatus):
        """
        Private slot to handle the finished signal of a tool process.
        
        @param exitCode exit code of the process (integer)
        @param exitStatus exit status of the process (QProcess.ExitStatus)
        """
        exitedProcs = []
        
        # loop through all running tool processes
        for program, toolProc, toolProcData in self.toolProcs:
            if toolProc.state() == QProcess.NotRunning:
                exitedProcs.append((program, toolProc, toolProcData))
                if toolProcData[0] is not None:
                    if toolProcData[1] == "replaceSelection":
                        text = ''.join(toolProcData[2])
                        toolProcData[0].replace(text)
                    toolProcData[0].endUndoAction()
        
        # now delete the exited procs from the list of running processes
        for proc in exitedProcs:
            self.toolProcs.remove(proc)
            t = self.trUtf8("Process '%1' has exited.\n").arg(proc[0])
            self.emit(SIGNAL('appendStdout'), t)
    
    def __showPythonDoc(self):
        """
        Private slot to show the Python documentation.
        """
        pythonDocDir = unicode(Preferences.getHelp("PythonDocDir"))
        if not pythonDocDir:
            if sys.platform == "win32":
                pythonDocDir = Utilities.getEnvironmentEntry("PYTHONDOCDIR", 
                    os.path.join(os.path.dirname(sys.executable), "doc"))
            else:
                pythonDocDir = Utilities.getEnvironmentEntry("PYTHONDOCDIR", 
                    '/usr/share/doc/packages/python/html')
        home = Utilities.normjoinpath(pythonDocDir, 'index.html')
        
        if sys.platform == "win32" and not os.path.exists(home):
            pyversion = sys.hexversion >> 16
            vers = "%d%d" % ((pyversion >> 8) & 0xff, pyversion & 0xff)
            home = os.path.join(pythonDocDir, "python%s.chm" % vers)
        
        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))
            return
        
        if home.endswith(".chm"):
            self.__chmViewer(home)
        else:
            hvType = Preferences.getHelp("HelpViewerType")
            if hvType == 1:
                self.launchHelpViewer(home)
            elif hvType == 2:
                self.__assistant(home)
            elif hvType == 3:
                self.__webBrowser(home)
            else:
                self.__customViewer(home)

    def __showQtDoc(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 = Utilities.getEnvironmentEntry("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))
            return
        
        hvType = Preferences.getHelp("HelpViewerType")
        if hvType == 1:
            self.launchHelpViewer(home)
        elif hvType == 2:
            self.__assistant(home)
        elif hvType == 3:
            self.__webBrowser(home)
        else:
            self.__customViewer(home)
        
    def __showQt4Doc(self):
        """
        Private slot to show the Qt4 documentation.
        """
        qt4DocDir = unicode(Preferences.getHelp("Qt4DocDir"))
        if not qt4DocDir:
            qt4DocDir = Utilities.getEnvironmentEntry("QT4DOCDIR", "")
        home = Utilities.normjoinpath(qt4DocDir, '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))
            return
        
        hvType = Preferences.getHelp("HelpViewerType")
        if hvType == 1:
            self.launchHelpViewer(home)
        elif hvType == 2:
            self.__assistant(home, version = 4)
        elif hvType == 3:
            self.__webBrowser(home)
        else:
            self.__customViewer(home)
        
    def __showPyQt4Doc(self):
        """
        Private slot to show the PyQt4 documentation.
        """
        pyqt4DocDir = unicode(Preferences.getHelp("PyQt4DocDir"))
        if not pyqt4DocDir:
            pyqt4DocDir = Utilities.getEnvironmentEntry("PYQT4DOCDIR", None)
        
        if not pyqt4DocDir:
            KQMessageBox.warning(None,
                self.trUtf8("Documentation"),
                self.trUtf8("""<p>The PyQt4 documentation starting point"""
                            """ has not been configured.</p>"""))
            return
        
        home = ""
        if pyqt4DocDir:
            possibleHomes = [\
                Utilities.normjoinpath(pyqt4DocDir, 'index.html'),
                Utilities.normjoinpath(pyqt4DocDir, 'pyqt4ref.html'),
                Utilities.normjoinpath(pyqt4DocDir, 'classes.html'),
            ]
            for possibleHome in possibleHomes:
                if os.path.exists(possibleHome):
                    home = possibleHome
                    break
        
        if not home or 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))
            return
        
        hvType = Preferences.getHelp("HelpViewerType")
        if hvType == 1:
            self.launchHelpViewer(home)
        elif hvType == 2:
            self.__assistant(home, version = 4)
        elif hvType == 3:
            self.__webBrowser(home)
        else:
            self.__customViewer(home)
        
    def __showEricDoc(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))
            return
        
        hvType = Preferences.getHelp("HelpViewerType")
        if hvType == 1:
            self.launchHelpViewer(home)
        elif hvType == 2:
            self.__assistant(home)
        elif hvType == 3:
            self.__webBrowser(home)
        else:
            self.__customViewer(home)
        
    def launchHelpViewer(self, home):
        """
        Public slot to start the help viewer.
        
        @param home filename of file to be shown
        """
        if not Preferences.getHelp("SingleHelpWindow") or self.helpWindow is None:
            help = HelpWindow(home, '.', None, 'help viewer', True)

            if QApplication.desktop().width() > 400 and \
               QApplication.desktop().height() > 500:
                help.show()
            else:
                help.showMaximized()
            
            if Preferences.getHelp("SingleHelpWindow"):
                self.helpWindow = help
                self.connect(self.helpWindow, SIGNAL("helpClosed"), self.__helpClosed)
        else:
            self.helpWindow.newTab(home)
            self.helpWindow.raise_()
    
    def __helpClosed(self):
        """
        Private slot to handle the helpClosed signal of the help window.
        """
        if Preferences.getHelp("SingleHelpWindow"):
            self.helpWindow = None
    
    def __helpViewer(self):
        """
        Private slot to start an empty help viewer.
        """
        self.launchHelpViewer("")   

    def __preferences(self, pageName = None):
        """
        Private slot to set the preferences.
        
        @param pageName name of the configuration page to show (string or QString)
        """
        dlg = ConfigurationDialog(self, 'Configuration', True)
        self.connect(dlg, SIGNAL('preferencesChanged'), 
                     self.__preferencesChanged)
        if pageName is not None:
            dlg.showConfigurationPageByName(pageName)
        dlg.exec_()
        QApplication.processEvents()
        if dlg.result() == QDialog.Accepted:
            dlg.setPreferences()
            Preferences.syncPreferences()
            self.__preferencesChanged()
        
    def __preferencesChanged(self):
        """
        Private slot to handle a change of the preferences.
        """
        self.__setStyle()
        
        if Preferences.getUI("SingleApplicationMode"):
            if self.SAServer is None:
                self.SAServer = E4SingleApplicationServer()
        else:
            if self.SAServer is not None:
                self.SAServer.shutdown()
                self.SAServer = None
        
        if Preferences.getUI("UseIconProvider"):
            if self.iconProvider is None:
                # Generate and set our icon provider for KQFileDialog
                self.iconProvider = E4IconProvider()
                KQFileDialog.setIconProvider(self.iconProvider)
        else:
            if self.iconProvider is not None:
                self.iconProvider = None
                KQFileDialog.setIconProvider(None)
        
        self.maxEditorPathLen = Preferences.getUI("CaptionFilenameLength")
        self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename")
        if not self.captionShowsFilename:
            self.__setWindowCaption(editor = "")
        else:
            aw = self.viewmanager.activeWindow()
            fn = aw and aw.getFileName() or None
            if fn:
                self.__setWindowCaption(editor = unicode(fn))
            else:
                self.__setWindowCaption(editor = "")
        
        self.qtdir = Preferences.getQtDir()
        self.qt4dir = Preferences.getQt4Dir()
        
        self.performVersionCheck(False)
        
        self.emit(SIGNAL('preferencesChanged'))
        
    def __reloadAPIs(self):
        """
        Private slot to reload the api information.
        """
        self.emit(SIGNAL('reloadAPIs'))
        
    def __showExternalTools(self):
        """
        Private slot to display a dialog show a list of external tools used by eric4.
        """
        self.programsDialog.show()
        
    def __configViewProfiles(self):
        """
        Private slot to configure the various view profiles.
        """
        dlg = ViewProfileDialog(self.profiles,
            not self.embeddedShell, not self.embeddedFileBrowser)
        if dlg.exec_() == QDialog.Accepted:
            self.profiles = dlg.getProfiles()
            Preferences.setUI("ViewProfiles", self.profiles)
            if self.currentProfile == "edit":
                self.__setEditProfile(False)
            elif self.currentProfile == "debug":
                self.setDebugProfile(False)
        
    def __configShortcuts(self):
        """
        Private slot to configure the keyboard shortcuts.
        """
        self.shortcutsDialog.show()
        
    def __exportShortcuts(self):
        """
        Private slot to export the keyboard shortcuts.
        """
        selectedFilter = QString("")
        fn = KQFileDialog.getSaveFileName(\
            None,
            self.trUtf8("Export Keyboard Shortcuts"),
            QString(),
            self.trUtf8("eric4 keyboard shortcut file (*.e4k);;"
                "Compressed eric4 keyboard shortcut file (*.e4kz)"),
            selectedFilter,
            QFileDialog.Options(QFileDialog.DontConfirmOverwrite))
        
        if fn.isEmpty():
            return
        
        ext = QFileInfo(fn).suffix()
        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))

    def __importShortcuts(self):
        """
        Private slot to import the keyboard shortcuts.
        """
        fn = KQFileDialog.getOpenFileName(\
            None,
            self.trUtf8("Import Keyboard Shortcuts"),
            QString(),
            self.trUtf8("eric4 keyboard shortcut file (*.e4k *.e4kz);;"
                "eric3 keyboard shortcut file (*.e3k *.e3kz)"))
        
        if fn.isEmpty():
            return
        
        fn = unicode(fn)
        
        Preferences.importShortcuts(fn)

    def __newProject(self):
        """
        Private slot to handle the NewProject signal.
        """
        self.__setWindowCaption(project = self.project.name)
        
    def __projectOpened(self):
        """
        Private slot to handle the projectOpened signal.
        """
        self.__setWindowCaption(project = self.project.name)
        cap = e4App().getObject("DebugServer")\
            .getClientCapabilities(self.project.pdata["PROGLANGUAGE"][0])
        self.utProjectAct.setEnabled(cap & HasUnittest)
        self.utProjectOpen = cap & HasUnittest
        
    def __projectClosed(self):
        """
        Private slot to handle the projectClosed signal.
        """
        self.__setWindowCaption(project = "")
        self.utProjectAct.setEnabled(False)
        if not self.utEditorOpen:
            self.utRestartAct.setEnabled(False)
        self.utProjectOpen = False
        
    def __programChange(self, fn):
        """
        Private slot to handle the programChange signal.
        
        This primarily is here to set the currentProg variable.
        
        @param fn filename to be set as current prog (QString)
        """
        # Delete the old program if there was one.
        if self.currentProg is not None:
            del self.currentProg

        self.currentProg = os.path.normpath(unicode(fn))
        
    def __lastEditorClosed(self):
        """
        Private slot to handle the lastEditorClosed signal.
        """
        self.wizardsMenuAct.setEnabled(False)
        self.refactoringMenuAct.setEnabled(False)
        self.scriptsExecDocAct.setEnabled(False)
        self.utScriptAct.setEnabled(False)
        self.utEditorOpen = False
        if not self.utProjectOpen:
            self.utRestartAct.setEnabled(False)
        self.__setWindowCaption(editor = "")
        
    def __editorOpened(self, fn):
        """
        Private slot to handle the editorOpened signal.
        
        @param fn filename of the opened editor (QString)
        """
        fn = unicode(fn)
        self.wizardsMenuAct.setEnabled(True)
        self.refactoringMenuAct.setEnabled(True)
        self.scriptsExecDocAct.setEnabled(True)
        
        if fn and unicode(fn) != "None":
            if fn.endswith('.py') or self.viewmanager.getOpenEditor(fn).isPyFile():
                self.utScriptAct.setEnabled(True)
                self.utEditorOpen = True
            elif fn.endswith('.rb'):
                cap = e4App().getObject("DebugServer").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 = e4App().getObject("DebugServer").getClientCapabilities('Python')
            elif ext == '.rb':
                cap = e4App().getObject("DebugServer").getClientCapabilities('Ruby')
            else:
                cap = 0
            self.utScriptAct.setEnabled(cap & HasUnittest)
        else:
            self.utScriptAct.setEnabled(False)
    
    def __writeTasks(self):
        """
        Private slot to write the tasks data to an XML file (.e4t).
        """
        try:
            fn = os.path.join(Utilities.getConfigDir(), "eric4tasks.e4t")
            f = open(fn, "wb")
            
            TasksWriter(f, False).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))
        
    def __readTasks(self):
        """
        Private slot to read in the tasks file (.e4t)
        """
        try:
            fn = os.path.join(Utilities.getConfigDir(), "eric4tasks.e4t")
            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))
            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))
                return
            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))
    
    ##########################################################
    ## Below are slots needed by the scripts menu
    ##########################################################
    
    def __loadScript(self):
        """
        Private slot to handle the load script menu action.
        """
        dlg = LoadScriptDialog()
        if dlg.exec_() == 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 = True
                delete = True
                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 = True
                os.chdir(oldpwd)
            
            if delete:
                self.scriptManager.deleteScript(name)
    
    def __deleteScript(self):
        """
        Private slot to delete a script.
        """
        name, ok = self.scriptManager.getScriptName()
        if ok and not name.isEmpty():
            self.scriptManager.deleteScript(name)
    
    def __executeScript(self):
        """
        Private slot 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 __executeDocumentAsScript(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 __firstScriptAdded(self):
        """
        Private slot to handle the firstScriptAdded signal
        """
        self.scriptsDeleteAct.setEnabled(True)
        self.scriptsExecAct.setEnabled(True)
        
    def __lastScriptDeleted(self):
        """
        Private slot to handle the lastScriptDeleted signal
        """
        self.scriptsDeleteAct.setEnabled(False)
        self.scriptsExecAct.setEnabled(False)

    #################################################################
    ## 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 = event.mimeData().hasUrls()
        if self.inDragDrop:
            event.acceptProposedAction()
        
    def dragMoveEvent(self, event):
        """
        Protected method to handle the drag move event.
        
        @param event the drag move event (QDragMoveEvent)
        """
        if self.inDragDrop:
            event.acceptProposedAction()
        
    def dragLeaveEvent(self, event):
        """
        Protected method to handle the drag leave event.
        
        @param event the drag leave event (QDragLeaveEvent)
        """
        if self.inDragDrop:
            self.inDragDrop = False
        
    def dropEvent(self, event):
        """
        Protected method to handle the drop event.
        
        @param event the drop event (QDropEvent)
        """
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
            for url in event.mimeData().urls():
                fname = url.toLocalFile()
                if not fname.isEmpty():
                    if QFileInfo(fname).isFile():
                        self.viewmanager.openSourceFile(unicode(fname))
                    else:
                        KQMessageBox.information(None,
                            self.trUtf8("Drop Error"),
                            self.trUtf8("""<p><b>%1</b> is not a file.</p>""")
                                .arg(fname))
        
        self.inDragDrop = False
    
    ##########################################################
    ## 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()
            if not self.inCloseEevent:
                self.inCloseEevent = True
                QTimer.singleShot(0, e4App().closeAllWindows)
        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 True
            
        if not self.project.closeProject():
            return False
        
        if not self.viewmanager.closeViewManager():
            return False
        
        self.shell.closeShell()
        
        self.__writeTasks()
        self.templateViewer.writeTemplates()
        
        if not self.debuggerUI.shutdownServer():
            return False
        self.debuggerUI.shutdown()
        
        if self.SAServer is not None:
            self.SAServer.shutdown()
            self.SAServer = None
        
        Preferences.setGeometry("MainGeometry", self.saveGeometry())
        if self.layout == "FloatingWindows":      # floating windows
            windows = {
                "ProjectBrowser": self.projectBrowser,
                "DebugViewer": self.debugViewer,
                "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"]
            for window, i in zip(self.windows, range(len(self.windows))):
                if window is not None:
                    self.profiles[self.currentProfile][2][i] = \
                        str(window.saveGeometry())

        self.browser.saveToplevelDirs()
        
        self.__saveCurrentViewProfile(True)
        Preferences.savePreferences()
        Preferences.saveToolGroups(self.toolGroups, self.currentToolGroup)
        self.shutdownCalled = True
        return True

    ##############################################
    ## Below are methods to check for new versions
    ##############################################

    def performVersionCheck(self, manual = True,  alternative = 0):
        """
        Public method to check the internet for an eric4 update.
        
        @param manual flag indicating an invocation via the menu (boolean)
        """
        if not manual:
            if Version.startswith("@@"):
                return
            else:
                period = Preferences.getUI("PerformVersionCheck")
                if period == 0:
                    return
                elif period in [2, 3, 4]:
                    lastCheck = Preferences.Prefs.settings.value(\
                        "Updates/LastCheckDate", QVariant(QDate(1970, 1, 1))).toDate()
                    if lastCheck.isValid():
                        now = QDate.currentDate()
                        if period == 2 and lastCheck.day() == now.day():
                            # daily
                            return
                        elif period == 3 and lastCheck.daysTo(now) < 7:
                            # weekly
                            return
                        elif period == 4 and lastCheck.month() == now.month():
                            # monthly
                            return
        
        self.__inVersionCheck = True
        self.manualUpdatesCheck = manual
        if self.http is None:
            self.http = QHttp()
            self.connect(self.http, SIGNAL("done(bool)"), self.__versionsDownloadDone)
        
        if Preferences.getUI("UseProxy"):
            host = Preferences.getUI("ProxyHost")
            if host.isEmpty():
                KQMessageBox.critical(None,
                    self.trUtf8("Error during updates check"),
                    self.trUtf8("""Proxy usage was activated"""
                                """ but no proxy host configured."""))
                return
            else:
                self.http.setProxy(host,
                    Preferences.getUI("ProxyPort"),
                    Preferences.getUI("ProxyUser"),
                    Preferences.getUI("ProxyPassword"))
        
        self.httpAlternative = alternative
        self.__versionCheckCanceled = False
        if manual:
            if self.__versionCheckProgress is None:
                self.__versionCheckProgress = \
                    KQProgressDialog("", self.trUtf8("&Cancel"),  
                                     0,  len(self.__httpAlternatives),  self)
                self.__versionCheckProgress.setMinimumDuration(0)
                self.connect(self.__versionCheckProgress, SIGNAL("canceled()"), 
                    self.__versionsDownloadCanceled)
            self.__versionCheckProgress.setLabelText(self.trUtf8("Trying host %1")\
                .arg(self.__httpAlternatives[alternative]["host"]))
            self.__versionCheckProgress.setValue(alternative)
        self.http.setHost(self.__httpAlternatives[alternative]["host"], 
                          self.__httpAlternatives[alternative]["port"])
        self.http.get(self.__httpAlternatives[alternative]["url"])
        
    def __versionsDownloadDone(self, error):
        """
        Private method called, after the versions file has been downloaded
        from the internet.
        
        @param error flag indicating an error condition (boolean)
        """
        if self.__versionCheckCanceled:
            self.__inVersionCheck = False
            if self.__versionCheckProgress is not None:
                self.__versionCheckProgress.reset()
                self.__versionCheckProgress = None
            return
        
        if error or self.http.lastResponse().statusCode() != 200:
            self.httpAlternative += 1
            if self.httpAlternative >= len(self.__httpAlternatives):
                self.__inVersionCheck = False
                if self.__versionCheckProgress is not None:
                    self.__versionCheckProgress.reset()
                    self.__versionCheckProgress = None
                KQMessageBox.warning(None,
                    self.trUtf8("Error during updates check"),
                    self.trUtf8("""Could not perform updates check."""))
                return
            else:
                self.http = None
                self.performVersionCheck(self.manualUpdatesCheck, self.httpAlternative)
                return
        
        self.__inVersionCheck = False
        if self.__versionCheckProgress is not None:
            self.__versionCheckProgress.reset()
            self.__versionCheckProgress = None
        Preferences.Prefs.settings.setValue(\
            "Updates/LastCheckDate", QVariant(QDate.currentDate()))
        versions = unicode(self.http.readAll()).splitlines()
        
        url = ""
        try:
            if "-snapshot-" in Version:
                # check snapshot version
                if versions[2] > Version:
                    res = KQMessageBox.information(None,
                        self.trUtf8("Update available"),
                        self.trUtf8("""The update to <b>%1</b> of eric4 is available"""
                                    """ at <b>%2</b>. Would you like to get it?""")\
                            .arg(versions[2]).arg(versions[3]),
                        QMessageBox.StandardButtons(\
                            QMessageBox.No | \
                            QMessageBox.Yes),
                        QMessageBox.Yes)
                    url = res == QMessageBox.Yes and versions[3] or ''
                elif versions[0] > Version:
                    res = KQMessageBox.information(None,
                        self.trUtf8("Update available"),
                        self.trUtf8("""The update to <b>%1</b> of eric4 is available"""
                                    """ at <b>%2</b>. Would you like to get it?""")\
                            .arg(versions[0]).arg(versions[1]),
                        QMessageBox.StandardButtons(\
                            QMessageBox.No | \
                            QMessageBox.Yes),
                        QMessageBox.Yes)
                    url = res == QMessageBox.Yes and versions[1] or ''
                else:
                    if self.manualUpdatesCheck:
                        KQMessageBox.information(None,
                            self.trUtf8("Eric4 is up to date"),
                            self.trUtf8("""You are using the latest version or eric4"""))
            else:
                # check release version
                if versions[0] > Version:
                    res = KQMessageBox.information(None,
                        self.trUtf8("Update available"),
                        self.trUtf8("""The update to <b>%1</b> of eric4 is available"""
                                    """ at <b>%2</b>. Would you like to get it?""")\
                            .arg(versions[0]).arg(versions[1]),
                        QMessageBox.StandardButtons(\
                            QMessageBox.No | \
                            QMessageBox.Yes),
                        QMessageBox.Yes)
                    url = res == QMessageBox.Yes and versions[1] or ''
                else:
                    if self.manualUpdatesCheck:
                        KQMessageBox.information(None,
                            self.trUtf8("Eric4 is up to date"),
                            self.trUtf8("""You are using the latest version or eric4"""))
        except IndexError:
            KQMessageBox.warning(None,
                self.trUtf8("Error during updates check"),
                self.trUtf8("""Could not perform updates check."""))
        
        if url:
            QDesktopServices.openUrl(QUrl(url))
        
    def __versionsDownloadCanceled(self):
        """
        Private method called to cancel the version check.
        """
        if self.http is not None:
            self.__versionCheckCanceled = True
            self.http.abort()
    
    ######################################################
    ## Below are methods to check the configuration status
    ######################################################

    def checkConfigurationStatus(self):
        """
        Public method to check, if eric4 has been configured. If it is not, 
        the configuration dialog is shown.
        """
        if not Preferences.isConfigured():
            KQMessageBox.information(None,
                self.trUtf8("First time usage"),
                self.trUtf8("""eric4 has not been configured yet. """
                            """The configuration dialog will be started."""),
                QMessageBox.StandardButtons(\
                    QMessageBox.Ok))
            self.__preferences()
    
    #################################
    ## Below are some utility methods
    #################################

    def __getFloatingGeometry(self, w):
        """
        Private method to get the geometry of a floating windows.
        
        @param w reference to the widget to be saved (QWidget)
        @return list giving the widget's geometry and it's visibility
        """
        s = w.size()
        p = w.pos()
        return [p.x(), p.y(), s.width(), s.height(), not w.isHidden()]
