|
1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 # Copyright (c) 2002 - 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
5 # |
|
6 |
|
7 """ |
|
8 Eric4 Python IDE |
|
9 |
|
10 This is the main Python script that performs the necessary initialization |
|
11 of the IDE and starts the Qt event loop. |
|
12 """ |
|
13 |
|
14 import sys |
|
15 import os |
|
16 import traceback |
|
17 import cStringIO |
|
18 import time |
|
19 import logging |
|
20 |
|
21 import sip |
|
22 sip.setapi("QString", 2) |
|
23 |
|
24 from PyQt4.QtCore import QTextCodec, SIGNAL, SLOT, qWarning, \ |
|
25 QLibraryInfo, QTimer |
|
26 from PyQt4.QtGui import QApplication, QErrorMessage |
|
27 |
|
28 # some global variables needed to start the application |
|
29 args = None |
|
30 mainWindow = None |
|
31 splash = None |
|
32 |
|
33 # generate list of arguments to be remembered for a restart |
|
34 restartArgsList = ["--nosplash", "--plugin", "--debug", "--config"] |
|
35 restartArgs = [arg for arg in sys.argv[1:] if arg.split("=", 1)[0] in restartArgsList] |
|
36 |
|
37 if "--debug" in sys.argv: |
|
38 del sys.argv[sys.argv.index("--debug")] |
|
39 logging.basicConfig(level = logging.DEBUG) |
|
40 |
|
41 for arg in sys.argv: |
|
42 if arg.startswith("--config="): |
|
43 import Utilities |
|
44 configDir = arg.replace("--config=", "") |
|
45 Utilities.setConfigDir(configDir) |
|
46 sys.argv.remove(arg) |
|
47 break |
|
48 |
|
49 # make ThirdParty package available as a packages repository |
|
50 try: |
|
51 import pygments |
|
52 except ImportError: |
|
53 sys.path.insert(2, os.path.join(os.path.dirname(__file__), "ThirdParty", "Pygments")) |
|
54 |
|
55 from E4Gui.E4Application import E4Application |
|
56 |
|
57 from UI.Info import Program, Version, BugAddress |
|
58 from UI.SplashScreen import SplashScreen, NoneSplashScreen |
|
59 from E4Gui.E4SingleApplication import E4SingleApplicationClient |
|
60 |
|
61 import Utilities |
|
62 from Utilities import Startup |
|
63 |
|
64 logging.debug("Importing Preferences") |
|
65 import Preferences |
|
66 |
|
67 def handleSingleApplication(ddindex): |
|
68 """ |
|
69 Global function to handle the single application mode. |
|
70 |
|
71 @param ddindex index of a '--' option in the options list |
|
72 """ |
|
73 client = E4SingleApplicationClient() |
|
74 res = client.connect() |
|
75 if res > 0: |
|
76 if "--nosplash" in sys.argv and sys.argv.index("--nosplash") < ddindex: |
|
77 del sys.argv[sys.argv.index("--nosplash")] |
|
78 if "--noopen" in sys.argv and sys.argv.index("--noopen") < ddindex: |
|
79 del sys.argv[sys.argv.index("--noopen")] |
|
80 if "--debug" in sys.argv and sys.argv.index("--debug") < ddindex: |
|
81 del sys.argv[sys.argv.index("--debug")] |
|
82 for arg in sys.argv: |
|
83 if arg.startswith("--config="): |
|
84 sys.argv.remove(arg) |
|
85 break |
|
86 if len(sys.argv) > 1: |
|
87 client.processArgs(sys.argv[1:]) |
|
88 sys.exit(0) |
|
89 elif res < 0: |
|
90 print "eric4: %s" % client.errstr() |
|
91 sys.exit(res) |
|
92 |
|
93 def excepthook(excType, excValue, tracebackobj): |
|
94 """ |
|
95 Global function to catch unhandled exceptions. |
|
96 |
|
97 @param excType exception type |
|
98 @param excValue exception value |
|
99 @param tracebackobj traceback object |
|
100 """ |
|
101 separator = '-' * 80 |
|
102 logFile = os.path.join(unicode(Utilities.getConfigDir()), "eric4_error.log") |
|
103 notice = \ |
|
104 """An unhandled exception occurred. Please report the problem\n"""\ |
|
105 """using the error reporting dialog or via email to <%s>.\n"""\ |
|
106 """A log has been written to "%s".\n\nError information:\n""" % \ |
|
107 (BugAddress, logFile) |
|
108 timeString = time.strftime("%Y-%m-%d, %H:%M:%S") |
|
109 |
|
110 versionInfo = "\n%s\n%s" % (separator, Utilities.generateVersionInfo()) |
|
111 pluginVersionInfo = Utilities.generatePluginsVersionInfo() |
|
112 if pluginVersionInfo: |
|
113 versionInfo += "%s\n%s" % (separator, pluginVersionInfo) |
|
114 distroInfo = Utilities.generateDistroInfo() |
|
115 if distroInfo: |
|
116 versionInfo += "%s\n%s" % (separator, distroInfo) |
|
117 |
|
118 tbinfofile = cStringIO.StringIO() |
|
119 traceback.print_tb(tracebackobj, None, tbinfofile) |
|
120 tbinfofile.seek(0) |
|
121 tbinfo = tbinfofile.read() |
|
122 errmsg = '%s: \n%s' % (str(excType), str(excValue)) |
|
123 sections = [separator, timeString, separator, errmsg, separator, tbinfo] |
|
124 msg = '\n'.join(sections) |
|
125 try: |
|
126 f = open(logFile, "w") |
|
127 f.write(msg) |
|
128 f.write(versionInfo) |
|
129 f.close() |
|
130 except IOError: |
|
131 pass |
|
132 qWarning(str(notice) + str(msg) + str(versionInfo)) |
|
133 |
|
134 def uiStartUp(): |
|
135 """ |
|
136 Global function to finalize the start up of the main UI. |
|
137 |
|
138 Note: It is activated by a zero timeout single-shot timer. |
|
139 """ |
|
140 global args, mainWindow, splash |
|
141 |
|
142 if splash: |
|
143 splash.finish(mainWindow) |
|
144 del splash |
|
145 |
|
146 mainWindow.checkForErrorLog() |
|
147 mainWindow.processArgs(args) |
|
148 mainWindow.performVersionCheck(False) |
|
149 mainWindow.checkConfigurationStatus() |
|
150 |
|
151 def main(): |
|
152 """ |
|
153 Main entry point into the application. |
|
154 """ |
|
155 global args, mainWindow, splash, restartArgs |
|
156 |
|
157 sys.excepthook = excepthook |
|
158 |
|
159 options = [\ |
|
160 ("--config=configDir", |
|
161 "use the given directory as the one containing the config files"), |
|
162 ("--debug", "activate debugging output to the console"), |
|
163 ("--nosplash", "don't show the splash screen"), |
|
164 ("--noopen", "don't open anything at startup except that given in command"), |
|
165 ("--plugin=plugin-file", "load the given plugin file (plugin development)"), |
|
166 ("--start-session", "load the global session file"), |
|
167 ("--", "indicate that there are options for the program to be debugged"), |
|
168 ("", "(everything after that is considered arguments for this program)") |
|
169 ] |
|
170 appinfo = Startup.makeAppInfo(sys.argv, |
|
171 "Eric4", |
|
172 "[project | files... [--] [debug-options]]", |
|
173 "A Python IDE", |
|
174 options) |
|
175 ddindex = Startup.handleArgs(sys.argv, appinfo) |
|
176 |
|
177 if Preferences.getUI("SingleApplicationMode"): |
|
178 handleSingleApplication(ddindex) |
|
179 |
|
180 app = E4Application(sys.argv) |
|
181 |
|
182 # set the searchpath for icons |
|
183 Startup.initializeResourceSearchPath() |
|
184 |
|
185 # generate and show a splash window, if not suppressed |
|
186 if "--nosplash" in sys.argv and sys.argv.index("--nosplash") < ddindex: |
|
187 del sys.argv[sys.argv.index("--nosplash")] |
|
188 splash = NoneSplashScreen() |
|
189 elif not Preferences.getUI("ShowSplash"): |
|
190 splash = NoneSplashScreen() |
|
191 else: |
|
192 splash = SplashScreen() |
|
193 |
|
194 pluginFile = None |
|
195 noopen = False |
|
196 if "--noopen" in sys.argv and sys.argv.index("--noopen") < ddindex: |
|
197 del sys.argv[sys.argv.index("--noopen")] |
|
198 noopen = True |
|
199 for arg in sys.argv: |
|
200 if arg.startswith("--plugin=") and sys.argv.index(arg) < ddindex: |
|
201 # extract the plugin development option |
|
202 pluginFile = arg.replace("--plugin=", "") |
|
203 sys.argv.remove(arg) |
|
204 pluginFile = os.path.expanduser(pluginFile) |
|
205 pluginFile = Utilities.normabspath(pluginFile) |
|
206 break |
|
207 |
|
208 # is there a set of filenames or options on the command line, |
|
209 # if so, pass them to the UI |
|
210 if len(sys.argv) > 1: |
|
211 args = sys.argv[1:] |
|
212 |
|
213 # Set the applications string encoding |
|
214 try: |
|
215 sys.setappdefaultencoding(Preferences.getSystem("StringEncoding")) |
|
216 except AttributeError: |
|
217 pass |
|
218 |
|
219 # get the Qt4 translations directory |
|
220 qt4TransDir = Preferences.getQt4TranslationsDir() |
|
221 if not qt4TransDir: |
|
222 qt4TransDir = QLibraryInfo.location(QLibraryInfo.TranslationsPath) |
|
223 |
|
224 # Load translation files and install them |
|
225 loc = Startup.loadTranslators(qt4TransDir, app, ("qscintilla",)) |
|
226 |
|
227 QTextCodec.setCodecForCStrings(QTextCodec.codecForName(\ |
|
228 str(Preferences.getSystem("StringEncoding")))) |
|
229 |
|
230 splash.showMessage(QApplication.translate("eric4", "Importing packages...")) |
|
231 # We can only import these after creating the E4Application because they |
|
232 # make Qt calls that need the E4Application to exist. |
|
233 from UI.UserInterface import UserInterface |
|
234 |
|
235 splash.showMessage(QApplication.translate("eric4", "Generating Main Window...")) |
|
236 try: |
|
237 mainWindow = UserInterface(loc, splash, pluginFile, noopen, restartArgs) |
|
238 app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) |
|
239 mainWindow.show() |
|
240 |
|
241 QTimer.singleShot(0, uiStartUp) |
|
242 |
|
243 # generate a graphical error handler |
|
244 eMsg = QErrorMessage.qtHandler() |
|
245 eMsg.setMinimumSize(600, 400) |
|
246 |
|
247 # start the event loop |
|
248 res = app.exec_() |
|
249 logging.debug("Shutting down, result %d" % res) |
|
250 logging.shutdown() |
|
251 sys.exit(res) |
|
252 except Exception, err: |
|
253 raise err |
|
254 |
|
255 if __name__ == '__main__': |
|
256 main() |