#!/usr/bin/env python
# -*- coding: utf-8 -*-

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

"""
Eric4 Python IDE

This is the main Python script that performs the neccessary initialization
of the IDE and starts the Qt event loop.
"""

import sys
import os
import traceback
from StringIO import StringIO
import time

from PyQt4.QtCore import QTextCodec, SIGNAL, SLOT, qWarning, \
    qVersion, PYQT_VERSION_STR,  QLibraryInfo
from PyQt4.QtGui import QApplication, QErrorMessage
from PyQt4.Qsci import QSCINTILLA_VERSION_STR

# disable the usage of KDE widgets, if requested
# Note 1: Qt widgets might still be KDE widgets,
#         if Qt was compiled with Qt-KDE-Integration
# Note 2: This is an experimental feature of SUSE 9.3.
#         Disable it by setting the environment
#         variable "QT_NO_KDE_INTEGRATION=1"
if "--nokde" in sys.argv:
    del sys.argv[sys.argv.index("--nokde")]
    os.environ["e4nokde"] = "1"

from KdeQt.KQApplication import KQApplication
import KdeQt

from UI.Info import Program, Version, BugAddress
from UI.SplashScreen import SplashScreen, NoneSplashScreen
from E4Gui.E4SingleApplication import E4SingleApplicationClient

from Refactoring.Refactoring import BRM_VERSION_STR

import Utilities
from Utilities import Startup

import Preferences


def handleSingleApplication(ddindex):
    """
    Global function to handle the single application mode.
    
    @param ddindex index of a '--' option in the options list
    """
    client = E4SingleApplicationClient()
    res = client.connect()
    if res > 0:
        if "--nosplash" in sys.argv and sys.argv.index("--nosplash") < ddindex:
            del sys.argv[sys.argv.index("--nosplash")]
        if "--nokde" in sys.argv and sys.argv.index("--nokde") < ddindex:
            del sys.argv[sys.argv.index("--nokde")]
        if len(sys.argv) > 1:
            client.processArgs(sys.argv[1:])
        sys.exit(0)
    elif res < 0:
        print "eric4: %s" % client.errstr()
        sys.exit(res)

def excepthook(excType, excValue, tracebackobj):
    """
    Global function to catch unhandled exceptions.
    
    @param excType exception type
    @param excValue exception value
    @param tracebackobj traceback object
    """
    separator = '-' * 80
    logFile = os.path.join(unicode(Utilities.getConfigDir()), "eric4_error.log")
    notice = \
        """An unhandled exception occurred. Please report the problem"""\
        """ using the error reporting dialog or via email to <%s>."""\
        """ A log has been written to "%s".\n\nError information:\n""" % \
        (BugAddress, logFile)
    timeString = time.strftime("%Y-%m-%d, %H:%M:%S")
    
    try:
        import sipconfig
        sip_version_str = sipconfig.Configuration().sip_version_str
    except ImportError:
        sip_version_str = "sip version not available"
    if KdeQt.isKDE():
        versionInfo = ("\n%s\nVersion Numbers:\n  Python %s\n" + \
            "  KDE %s\n  PyKDE %s\n  Qt %s\n" + \
            "  PyQt4 %s\n  sip %s\n  QScintilla %s\n  %s %s\n" + \
            "  Bicycle Repair Man %s\n\nPlatform: %s\n%s\n") % \
            (separator, sys.version.split()[0],
            str(KdeQt.kdeVersionString()), str(KdeQt.pyKdeVersionString()),
            str(qVersion()), str(PYQT_VERSION_STR), str(sip_version_str),
            str(QSCINTILLA_VERSION_STR),
            Program, Version, BRM_VERSION_STR, sys.platform, sys.version)
    else:
        versionInfo = ("\n%s\nVersion Numbers:\n  Python %s\n  Qt %s\n" + \
            "  PyQt4 %s\n  sip %s\n  QScintilla %s\n  %s %s\n" + \
            "  Bicycle Repair Man %s\n\nPlatform: %s\n%s\n") % \
            (separator, sys.version.split()[0],
            str(qVersion()), str(PYQT_VERSION_STR), str(sip_version_str),
            str(QSCINTILLA_VERSION_STR),
            Program, Version, BRM_VERSION_STR, sys.platform, sys.version)
    tbinfofile = StringIO()
    traceback.print_tb(tracebackobj, None, tbinfofile)
    tbinfofile.seek(0)
    tbinfo = tbinfofile.read()
    errmsg = '%s: \n%s' % (str(excType), str(excValue))
    sections = [separator, timeString, separator, errmsg, separator, tbinfo]
    msg = '\n'.join(sections)
    try:
        f = open(logFile, "w")
        f.write(msg)
        f.write(versionInfo)
        f.close()
    except IOError:
        pass
    qWarning(str(notice) + msg + versionInfo)

def main():
    """
    Main entry point into the application.
    """
    sys.excepthook = excepthook
    
    options = [\
        ("--nosplash", "don't show the splash screen"),
        ("--nokde" , "don't use KDE widgets"),
        ("--", "indicate that there are options for the program to be debugged"),
        ("", "(everything after that is considered arguments for this program)")
    ]
    kqOptions = [\
        ("nosplash", "don't show the splash screen"),
        ("nokde" , "don't use KDE widgets"),
        ("!+file","")
    ]
    appinfo = Startup.makeAppInfo(sys.argv,
                                  "Eric4",
                                  "[project | files... [--] [debug-options]]",
                                  "A Python IDE",
                                  options)
    ddindex = Startup.handleArgs(sys.argv, appinfo)
    
    if Preferences.getUI("SingleApplicationMode"):
        handleSingleApplication(ddindex)
        
    app = KQApplication(sys.argv, kqOptions)
    
    # set the searchpath for icons
    Startup.initializeResourceSearchPath()

    # generate and show a splash window, if not suppressed
    if "--nosplash" in sys.argv and sys.argv.index("--nosplash") < ddindex:
        del sys.argv[sys.argv.index("--nosplash")]
        splash = NoneSplashScreen()
    elif not Preferences.getUI("ShowSplash"):
        splash = NoneSplashScreen()
    else:
        splash = SplashScreen()

    # is there a set of filenames or options on the command line,
    # if so, pass them to the UI
    args = None
    if len(sys.argv) > 1:
        args = sys.argv[1:]
    
    # Set the applications string encoding
    try:
        sys.setappdefaultencoding(str(Preferences.getSystem("StringEncoding")))
    except:
        pass
    
    # get the Qt installation directory
    qtdir = Preferences.getQtDir()
    if qtdir is not None:
        if Preferences.getQt("ExportQtDir"):
            os.environ["QTDIR"] = str(qtdir)
    # get the Qt4 installation directory
    qt4dir = Preferences.getQt4Dir()
    if qt4dir is not None:
        if Preferences.getQt("ExportQt4Dir"):
            os.environ["QT4DIR"] = str(qt4dir)
    
    # get the Qt4 translations directory
    qt4TransDir = Preferences.getQt4TranslationsDir()
    if not qt4TransDir:
        qt4TransDir = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
    
    # Load translation files and install them
    loc = Startup.loadTranslators(qt4TransDir, app, ("qscintilla",))
    
    QTextCodec.setCodecForCStrings(QTextCodec.codecForName(\
        str(Preferences.getSystem("StringEncoding"))))
    
    splash.showMessage(QApplication.translate("eric4", "Importing packages..."))
    # We can only import these after creating the KQApplication because they
    # make Qt calls that need the KQApplication to exist.
    from UI.UserInterface import UserInterface

    splash.showMessage(QApplication.translate("eric4", "Generating Main Window..."))
    mw = UserInterface(loc, splash)
    app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
    mw.show()
    
    if splash:
        splash.finish(mw)
        del splash

    mw.processArgs(args)
    mw.performVersionCheck(False)
    mw.checkConfigurationStatus()
    
    # generate a graphical error handler
    eMsg = QErrorMessage.qtHandler()
    eMsg.setMinimumSize(600, 400)
    
    # start the event loop
    res = app.exec_()
    sys.exit(res)

if __name__ == '__main__':
    main()
