|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2013 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the Django project support. |
|
8 """ |
|
9 |
|
10 import sys |
|
11 import os |
|
12 |
|
13 from PyQt4.QtCore import QObject |
|
14 from PyQt4.QtGui import QMenu, QInputDialog, QLineEdit |
|
15 |
|
16 from E5Gui.E5Application import e5App |
|
17 from E5Gui import E5MessageBox |
|
18 from E5Gui.E5Action import E5Action |
|
19 |
|
20 from .DjangoDialog import DjangoDialog |
|
21 |
|
22 import Preferences |
|
23 import Utilities |
|
24 |
|
25 |
|
26 class DjangoNoSiteSelectedException(Exception): |
|
27 """ |
|
28 Exception thrown to signal, that there is no current site. |
|
29 """ |
|
30 pass |
|
31 |
|
32 |
|
33 class Project(QObject): |
|
34 """ |
|
35 Class implementing the Django project support. |
|
36 """ |
|
37 RecentApplicationsKey = "Django/RecentApplications" |
|
38 |
|
39 def __init__(self, plugin, parent=None): |
|
40 """ |
|
41 Constructor |
|
42 |
|
43 @param plugin reference to the plugin object |
|
44 @param parent parent (QObject) |
|
45 """ |
|
46 super().__init__(parent) |
|
47 |
|
48 self.__plugin = plugin |
|
49 self.__ui = parent |
|
50 self.__e5project = e5App().getObject("Project") |
|
51 self.__hooksInstalled = False |
|
52 |
|
53 self.__mainMenu = None |
|
54 |
|
55 self.__serverProc = None |
|
56 self.__testServerProc = None |
|
57 |
|
58 self.__recentApplications = [] |
|
59 self.__loadRecentApplications() |
|
60 |
|
61 def initActions(self): |
|
62 """ |
|
63 Public method to define the Pyramid actions. |
|
64 """ |
|
65 self.actions = [] |
|
66 |
|
67 self.selectSiteAct = E5Action(self.trUtf8('Current Project'), |
|
68 "", |
|
69 0, 0, |
|
70 self,'django_current_project') |
|
71 self.selectSiteAct.setStatusTip(self.trUtf8( |
|
72 'Selects the current project')) |
|
73 self.selectSiteAct.setWhatsThis(self.trUtf8( |
|
74 """<b>Current Project</b>""" |
|
75 """<p>Selects the current project. Used for multi-project """ |
|
76 """Django projects to switch between the projects.</p>""" |
|
77 )) |
|
78 self.selectSiteAct.triggered[()].connect(self.__selectSite) |
|
79 self.actions.append(self.selectSiteAct) |
|
80 self.__setCurrentSite(None) |
|
81 |
|
82 ############################## |
|
83 ## start actions below ## |
|
84 ############################## |
|
85 |
|
86 self.startProjectAct = E5Action(self.trUtf8('Start Project'), |
|
87 self.trUtf8('Start &Project'), |
|
88 0, 0, |
|
89 self,'django_start_project') |
|
90 self.startProjectAct.setStatusTip(self.trUtf8( |
|
91 'Starts a new Django project')) |
|
92 self.startProjectAct.setWhatsThis(self.trUtf8( |
|
93 """<b>Start Project</b>""" |
|
94 """<p>Starts a new Django project using "django-admin.py startproject".</p>""" |
|
95 )) |
|
96 self.startProjectAct.triggered[()].connect(self.__startProject) |
|
97 self.actions.append(self.startProjectAct) |
|
98 |
|
99 self.startGlobalApplicationAct = E5Action( |
|
100 self.trUtf8('Start Application (global)'), |
|
101 self.trUtf8('Start Application (&global)'), |
|
102 0, 0, |
|
103 self,'django_start_global_application') |
|
104 self.startGlobalApplicationAct.setStatusTip(self.trUtf8( |
|
105 'Starts a new global Django application')) |
|
106 self.startGlobalApplicationAct.setWhatsThis(self.trUtf8( |
|
107 """<b>Start Application (global)</b>""" |
|
108 """<p>Starts a new global Django application using""" |
|
109 """ "django-admin.py startapp".</p>""" |
|
110 )) |
|
111 self.startGlobalApplicationAct.triggered[()].connect( |
|
112 self.__startGlobalApplication) |
|
113 self.actions.append(self.startGlobalApplicationAct) |
|
114 |
|
115 self.startLocalApplicationAct = E5Action( |
|
116 self.trUtf8('Start Application (local)'), |
|
117 self.trUtf8('Start Application (&local)'), |
|
118 0, 0, |
|
119 self,'django_start_local_application') |
|
120 self.startLocalApplicationAct.setStatusTip(self.trUtf8( |
|
121 'Starts a new local Django application')) |
|
122 self.startLocalApplicationAct.setWhatsThis(self.trUtf8( |
|
123 """<b>Start Application (local)</b>""" |
|
124 """<p>Starts a new local Django application using""" |
|
125 """ "manage.py startapp".</p>""" |
|
126 )) |
|
127 self.startLocalApplicationAct.triggered[()].connect( |
|
128 self.__startLocalApplication) |
|
129 self.actions.append(self.startLocalApplicationAct) |
|
130 |
|
131 ## ############################## |
|
132 ## ## run actions below ## |
|
133 ## ############################## |
|
134 ## |
|
135 ## self.runServerAct = E4Action(self.trUtf8('Run Server'), |
|
136 ## self.trUtf8('Run &Server'), |
|
137 ## 0, 0, |
|
138 ## self,'django_run_server') |
|
139 ## self.runServerAct.setStatusTip(self.trUtf8( |
|
140 ## 'Starts the Django Web server')) |
|
141 ## self.runServerAct.setWhatsThis(self.trUtf8( |
|
142 ## """<b>Run Server</b>""" |
|
143 ## """<p>Starts the Django Web server using "manage.py runserver".</p>""" |
|
144 ## )) |
|
145 ## self.connect(self.runServerAct, SIGNAL('triggered()'), self.__runServer) |
|
146 ## self.actions.append(self.runServerAct) |
|
147 ## |
|
148 ## self.runBrowserAct = E4Action(self.trUtf8('Run Web-Browser'), |
|
149 ## self.trUtf8('Run &Web-Browser'), |
|
150 ## 0, 0, |
|
151 ## self,'django_run_browser') |
|
152 ## self.runBrowserAct.setStatusTip(self.trUtf8( |
|
153 ## 'Starts the default Web-Browser with the URL of the Django Web server')) |
|
154 ## self.runBrowserAct.setWhatsThis(self.trUtf8( |
|
155 ## """<b>Run Web-Browser</b>""" |
|
156 ## """<p>Starts the default Web-Browser with the URL of the """ |
|
157 ## """Django Web server.</p>""" |
|
158 ## )) |
|
159 ## self.connect(self.runBrowserAct, SIGNAL('triggered()'), self.__runBrowser) |
|
160 ## self.actions.append(self.runBrowserAct) |
|
161 ## |
|
162 ## ############################## |
|
163 ## ## caching actions below ## |
|
164 ## ############################## |
|
165 ## |
|
166 ## self.createCacheTableAct = E4Action(self.trUtf8('Create Cache Tables'), |
|
167 ## self.trUtf8('C&reate Cache Tables'), |
|
168 ## 0, 0, |
|
169 ## self,'django_create_cache_tables') |
|
170 ## self.createCacheTableAct.setStatusTip(self.trUtf8( |
|
171 ## 'Creates the tables needed to use the SQL cache backend')) |
|
172 ## self.createCacheTableAct.setWhatsThis(self.trUtf8( |
|
173 ## """<b>Create Cache Tables</b>""" |
|
174 ## """<p>Creates the tables needed to use the SQL cache backend.</p>""" |
|
175 ## )) |
|
176 ## self.connect(self.createCacheTableAct, SIGNAL('triggered()'), |
|
177 ## self.__createCacheTables) |
|
178 ## self.actions.append(self.createCacheTableAct) |
|
179 ## |
|
180 ############################## |
|
181 ## help action below ## |
|
182 ############################## |
|
183 |
|
184 self.helpAct = E5Action(self.trUtf8('Help'), |
|
185 self.trUtf8('&Help'), |
|
186 0, 0, |
|
187 self,'django_help') |
|
188 self.helpAct.setStatusTip(self.trUtf8( |
|
189 'Shows the Django help index')) |
|
190 self.helpAct.setWhatsThis(self.trUtf8( |
|
191 """<b>Help</b>""" |
|
192 """<p>Shows the Django help index page.</p>""" |
|
193 )) |
|
194 self.helpAct.triggered[()].connect(self.__showHelpIndex) |
|
195 self.actions.append(self.helpAct) |
|
196 |
|
197 ############################## |
|
198 ## about action below ## |
|
199 ############################## |
|
200 |
|
201 self.aboutDjangoAct = E5Action(self.trUtf8('About Django'), |
|
202 self.trUtf8('About D&jango'), |
|
203 0, 0, |
|
204 self,'django_about') |
|
205 self.aboutDjangoAct.setStatusTip(self.trUtf8( |
|
206 'Shows some information about Django')) |
|
207 self.aboutDjangoAct.setWhatsThis(self.trUtf8( |
|
208 """<b>About Django</b>""" |
|
209 """<p>Shows some information about Django.</p>""" |
|
210 )) |
|
211 self.aboutDjangoAct.triggered[()].connect(self.__djangoInfo) |
|
212 self.actions.append(self.aboutDjangoAct) |
|
213 ## |
|
214 ## self.__initDatabaseActions() |
|
215 ## self.__initDatabaseSqlActions() |
|
216 ## self.__initToolsActions() |
|
217 ## self.__initTestingActions() |
|
218 ## |
|
219 ## def __initDatabaseActions(self): |
|
220 ## """ |
|
221 ## Private method to define the database related actions. |
|
222 ## """ |
|
223 ## self.syncDatabaseAct = E4Action(self.trUtf8('Synchronize'), |
|
224 ## self.trUtf8('&Synchronize'), |
|
225 ## 0, 0, |
|
226 ## self,'django_database_syncdb') |
|
227 ## self.syncDatabaseAct.setStatusTip(self.trUtf8( |
|
228 ## 'Synchronizes the database')) |
|
229 ## self.syncDatabaseAct.setWhatsThis(self.trUtf8( |
|
230 ## """<b>Synchronize</b>""" |
|
231 ## """<p>Synchronizes the database.</p>""" |
|
232 ## )) |
|
233 ## self.connect(self.syncDatabaseAct, SIGNAL('triggered()'), |
|
234 ## self.__databaseSynchronize) |
|
235 ## self.actions.append(self.syncDatabaseAct) |
|
236 ## |
|
237 ## self.inspectDatabaseAct = E4Action(self.trUtf8('Introspect'), |
|
238 ## self.trUtf8('&Introspect'), |
|
239 ## 0, 0, |
|
240 ## self,'django_database_inspect') |
|
241 ## self.inspectDatabaseAct.setStatusTip(self.trUtf8( |
|
242 ## 'Introspects the database tables and outputs a Django model module')) |
|
243 ## self.inspectDatabaseAct.setWhatsThis(self.trUtf8( |
|
244 ## """<b>Introspect</b>""" |
|
245 ## """<p>Introspects the database tables and outputs a """ |
|
246 ## """Django model module.</p>""" |
|
247 ## )) |
|
248 ## self.connect(self.inspectDatabaseAct, SIGNAL('triggered()'), |
|
249 ## self.__databaseInspect) |
|
250 ## self.actions.append(self.inspectDatabaseAct) |
|
251 ## |
|
252 ## self.flushDatabaseAct = E4Action(self.trUtf8('Flush'), |
|
253 ## self.trUtf8('&Flush'), |
|
254 ## 0, 0, |
|
255 ## self,'django_database_flush') |
|
256 ## self.flushDatabaseAct.setStatusTip(self.trUtf8( |
|
257 ## 'Returns all database tables to the state just after their installation')) |
|
258 ## self.flushDatabaseAct.setWhatsThis(self.trUtf8( |
|
259 ## """<b>Flush</b>""" |
|
260 ## """<p>Returns all database tables to the state """ |
|
261 ## """just after their installation.</p>""" |
|
262 ## )) |
|
263 ## self.connect(self.flushDatabaseAct, SIGNAL('triggered()'), |
|
264 ## self.__databaseFlush) |
|
265 ## self.actions.append(self.flushDatabaseAct) |
|
266 ## |
|
267 ## self.resetDatabaseAct = E4Action(self.trUtf8('Reset Application(s)'), |
|
268 ## self.trUtf8('&Reset Application(s)'), |
|
269 ## 0, 0, |
|
270 ## self,'django_database_reset_application') |
|
271 ## self.resetDatabaseAct.setStatusTip(self.trUtf8( |
|
272 ## 'Resets the database tables of one or more applications')) |
|
273 ## self.resetDatabaseAct.setWhatsThis(self.trUtf8( |
|
274 ## """<b>Reset Application(s)</b>""" |
|
275 ## """<p>Resets the database tables of one or more applications.</p>""" |
|
276 ## )) |
|
277 ## self.connect(self.resetDatabaseAct, SIGNAL('triggered()'), |
|
278 ## self.__databaseReset) |
|
279 ## self.actions.append(self.resetDatabaseAct) |
|
280 ## |
|
281 ## self.databaseClientAct = E4Action(self.trUtf8('Start Client Console'), |
|
282 ## self.trUtf8('Start &Client Console'), |
|
283 ## 0, 0, |
|
284 ## self,'django_database_client') |
|
285 ## self.databaseClientAct.setStatusTip(self.trUtf8( |
|
286 ## 'Starts a console window for the database client')) |
|
287 ## self.databaseClientAct.setWhatsThis(self.trUtf8( |
|
288 ## """<b>Start Client Console</b>""" |
|
289 ## """<p>Starts a console window for the database client.</p>""" |
|
290 ## )) |
|
291 ## self.connect(self.databaseClientAct, SIGNAL('triggered()'), |
|
292 ## self.__runDatabaseClient) |
|
293 ## self.actions.append(self.databaseClientAct) |
|
294 ## |
|
295 ## def __initDatabaseSqlActions(self): |
|
296 ## """ |
|
297 ## Private method to define the database SQL related actions. |
|
298 ## """ |
|
299 ## self.databaseSqlCreateTablesAct = E4Action(self.trUtf8('Create Tables'), |
|
300 ## self.trUtf8('Create &Tables'), |
|
301 ## 0, 0, |
|
302 ## self,'django_database_sql_create_tables') |
|
303 ## self.databaseSqlCreateTablesAct.setStatusTip(self.trUtf8( |
|
304 ## 'Prints the CREATE TABLE SQL statements for one or more applications')) |
|
305 ## self.databaseSqlCreateTablesAct.setWhatsThis(self.trUtf8( |
|
306 ## """<b>Create Tables</b>""" |
|
307 ## """<p>Prints the CREATE TABLE SQL statements for one or """ |
|
308 ## """more applications.</p>""" |
|
309 ## )) |
|
310 ## self.connect(self.databaseSqlCreateTablesAct, SIGNAL('triggered()'), |
|
311 ## self.__databaseSqlCreateTables) |
|
312 ## self.actions.append(self.databaseSqlCreateTablesAct) |
|
313 ## |
|
314 ## self.databaseSqlCreateIndexesAct = E4Action(self.trUtf8('Create Indexes'), |
|
315 ## self.trUtf8('Create &Indexes'), |
|
316 ## 0, 0, |
|
317 ## self,'django_database_sql_create_indexes') |
|
318 ## self.databaseSqlCreateIndexesAct.setStatusTip(self.trUtf8( |
|
319 ## 'Prints the CREATE INDEX SQL statements for one or more applications')) |
|
320 ## self.databaseSqlCreateIndexesAct.setWhatsThis(self.trUtf8( |
|
321 ## """<b>Create Indexes</b>""" |
|
322 ## """<p>Prints the CREATE INDEX SQL statements for one or """ |
|
323 ## """more applications.</p>""" |
|
324 ## )) |
|
325 ## self.connect(self.databaseSqlCreateIndexesAct, SIGNAL('triggered()'), |
|
326 ## self.__databaseSqlCreateIndexes) |
|
327 ## self.actions.append(self.databaseSqlCreateIndexesAct) |
|
328 ## |
|
329 ## self.databaseSqlCreateEverythingAct = E4Action(self.trUtf8('Create Everything'), |
|
330 ## self.trUtf8('Create &Everything'), |
|
331 ## 0, 0, |
|
332 ## self,'django_database_sql_create_everything') |
|
333 ## self.databaseSqlCreateEverythingAct.setStatusTip(self.trUtf8( |
|
334 ## 'Prints the CREATE ... SQL statements for one or more applications')) |
|
335 ## self.databaseSqlCreateEverythingAct.setWhatsThis(self.trUtf8( |
|
336 ## """<b>Create Everything</b>""" |
|
337 ## """<p>Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL """ |
|
338 ## """statements for one or more applications.</p>""" |
|
339 ## )) |
|
340 ## self.connect(self.databaseSqlCreateEverythingAct, SIGNAL('triggered()'), |
|
341 ## self.__databaseSqlCreateEverything) |
|
342 ## self.actions.append(self.databaseSqlCreateEverythingAct) |
|
343 ## |
|
344 ## self.databaseSqlCustomAct = E4Action(self.trUtf8('Custom Statements'), |
|
345 ## self.trUtf8('&Custom Statements'), |
|
346 ## 0, 0, |
|
347 ## self,'django_database_sql_custom') |
|
348 ## self.databaseSqlCustomAct.setStatusTip(self.trUtf8( |
|
349 ## 'Prints the custom table modifying SQL statements for ' |
|
350 ## 'one or more applications')) |
|
351 ## self.databaseSqlCustomAct.setWhatsThis(self.trUtf8( |
|
352 ## """<b>Custom Statements</b>""" |
|
353 ## """<p>Prints the custom table modifying SQL statements """ |
|
354 ## """for one or more applications.</p>""" |
|
355 ## )) |
|
356 ## self.connect(self.databaseSqlCustomAct, SIGNAL('triggered()'), |
|
357 ## self.__databaseSqlCustom) |
|
358 ## self.actions.append(self.databaseSqlCustomAct) |
|
359 ## |
|
360 ## self.databaseSqlDropTablesAct = E4Action(self.trUtf8('Drop Tables'), |
|
361 ## self.trUtf8('&Drop Tables'), |
|
362 ## 0, 0, |
|
363 ## self,'django_database_sql_drop_tables') |
|
364 ## self.databaseSqlDropTablesAct.setStatusTip(self.trUtf8( |
|
365 ## 'Prints the DROP TABLE SQL statements for ' |
|
366 ## 'one or more applications')) |
|
367 ## self.databaseSqlDropTablesAct.setWhatsThis(self.trUtf8( |
|
368 ## """<b>Drop Tables</b>""" |
|
369 ## """<p>Prints the DROP TABLE SQL statements """ |
|
370 ## """for one or more applications.</p>""" |
|
371 ## )) |
|
372 ## self.connect(self.databaseSqlDropTablesAct, SIGNAL('triggered()'), |
|
373 ## self.__databaseSqlDropTables) |
|
374 ## self.actions.append(self.databaseSqlDropTablesAct) |
|
375 ## |
|
376 ## self.databaseSqlFlushAct = E4Action(self.trUtf8('Flush Database'), |
|
377 ## self.trUtf8('&Flush Database'), |
|
378 ## 0, 0, |
|
379 ## self,'django_database_sql_flush_database') |
|
380 ## self.databaseSqlFlushAct.setStatusTip(self.trUtf8( |
|
381 ## 'Prints a list of statements to return all database tables to the state ' |
|
382 ## 'just after their installation')) |
|
383 ## self.databaseSqlFlushAct.setWhatsThis(self.trUtf8( |
|
384 ## """<b>Flush Database</b>""" |
|
385 ## """<p>Prints a list of statements to return all database tables to """ |
|
386 ## """the state just after their installation.</p>""" |
|
387 ## )) |
|
388 ## self.connect(self.databaseSqlFlushAct, SIGNAL('triggered()'), |
|
389 ## self.__databaseSqlFlushDatabase) |
|
390 ## self.actions.append(self.databaseSqlFlushAct) |
|
391 ## |
|
392 ## self.databaseSqlResetApplAct = E4Action(self.trUtf8('Reset Application(s)'), |
|
393 ## self.trUtf8('Reset &Application(s)'), |
|
394 ## 0, 0, |
|
395 ## self,'django_database_sql_reset_application') |
|
396 ## self.databaseSqlResetApplAct.setStatusTip(self.trUtf8( |
|
397 ## 'Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for ' |
|
398 ## 'one or more applications')) |
|
399 ## self.databaseSqlResetApplAct.setWhatsThis(self.trUtf8( |
|
400 ## """<b>Reset Application(s)</b>""" |
|
401 ## """<p>Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for """ |
|
402 ## """one or more applications.</p>""" |
|
403 ## )) |
|
404 ## self.connect(self.databaseSqlResetApplAct, SIGNAL('triggered()'), |
|
405 ## self.__databaseSqlResetApplication) |
|
406 ## self.actions.append(self.databaseSqlResetApplAct) |
|
407 ## |
|
408 ## self.databaseSqlResetSeqAct = E4Action(self.trUtf8('Reset Sequences'), |
|
409 ## self.trUtf8('Reset &Sequences'), |
|
410 ## 0, 0, |
|
411 ## self,'django_database_sql_reset_sequences') |
|
412 ## self.databaseSqlResetSeqAct.setStatusTip(self.trUtf8( |
|
413 ## 'Prints the SQL statements for resetting sequences for ' |
|
414 ## 'one or more applications')) |
|
415 ## self.databaseSqlResetSeqAct.setWhatsThis(self.trUtf8( |
|
416 ## """<b>Reset Sequences</b>""" |
|
417 ## """<p>Prints the SQL statements for resetting sequences for """ |
|
418 ## """one or more applications.</p>""" |
|
419 ## )) |
|
420 ## self.connect(self.databaseSqlResetSeqAct, SIGNAL('triggered()'), |
|
421 ## self.__databaseSqlResetSequences) |
|
422 ## self.actions.append(self.databaseSqlResetSeqAct) |
|
423 ## |
|
424 ## def __initToolsActions(self): |
|
425 ## """ |
|
426 ## Private method to define the tool actions. |
|
427 ## """ |
|
428 ## self.diffSettingsAct = E4Action(self.trUtf8('Diff Settings'), |
|
429 ## self.trUtf8('&Diff Settings'), |
|
430 ## 0, 0, |
|
431 ## self,'django_tools_diffsettings') |
|
432 ## self.diffSettingsAct.setStatusTip(self.trUtf8( |
|
433 ## 'Shows the modification made to the settings')) |
|
434 ## self.diffSettingsAct.setWhatsThis(self.trUtf8( |
|
435 ## """<b>Diff Settings</b>""" |
|
436 ## """<p>Shows the modification made to the settings.</p>""" |
|
437 ## )) |
|
438 ## self.connect(self.diffSettingsAct, SIGNAL('triggered()'), |
|
439 ## self.__diffSettings) |
|
440 ## self.actions.append(self.diffSettingsAct) |
|
441 ## |
|
442 ## self.cleanupAct = E4Action(self.trUtf8('Cleanup'), |
|
443 ## self.trUtf8('&Cleanup'), |
|
444 ## 0, 0, |
|
445 ## self,'django_tools_cleanup') |
|
446 ## self.cleanupAct.setStatusTip(self.trUtf8( |
|
447 ## 'Cleans out old data from the database')) |
|
448 ## self.cleanupAct.setWhatsThis(self.trUtf8( |
|
449 ## """<b>Cleanup</b>""" |
|
450 ## """<p>Cleans out old data from the database.</p>""" |
|
451 ## )) |
|
452 ## self.connect(self.cleanupAct, SIGNAL('triggered()'), |
|
453 ## self.__cleanup) |
|
454 ## self.actions.append(self.cleanupAct) |
|
455 ## |
|
456 ## self.validateAct = E4Action(self.trUtf8('Validate'), |
|
457 ## self.trUtf8('&Validate'), |
|
458 ## 0, 0, |
|
459 ## self,'django_tools_validate') |
|
460 ## self.validateAct.setStatusTip(self.trUtf8( |
|
461 ## 'Validates all installed models')) |
|
462 ## self.validateAct.setWhatsThis(self.trUtf8( |
|
463 ## """<b>Validate</b>""" |
|
464 ## """<p>Validates all installed models.</p>""" |
|
465 ## )) |
|
466 ## self.connect(self.validateAct, SIGNAL('triggered()'), |
|
467 ## self.__validate) |
|
468 ## self.actions.append(self.validateAct) |
|
469 ## |
|
470 ## self.adminindexAct = E4Action(self.trUtf8('Admin Index'), |
|
471 ## self.trUtf8('&Admin Index'), |
|
472 ## 0, 0, |
|
473 ## self,'django_tools_adminindex') |
|
474 ## self.adminindexAct.setStatusTip(self.trUtf8( |
|
475 ## 'Prints the admin-index template snippet')) |
|
476 ## self.adminindexAct.setWhatsThis(self.trUtf8( |
|
477 ## """<b>Admin Index</b>""" |
|
478 ## """<p>Prints the admin-index template snippet.</p>""" |
|
479 ## )) |
|
480 ## self.connect(self.adminindexAct, SIGNAL('triggered()'), |
|
481 ## self.__adminIndex) |
|
482 ## self.actions.append(self.adminindexAct) |
|
483 ## |
|
484 ## self.runPythonShellAct = E4Action(self.trUtf8('Start Python Console'), |
|
485 ## self.trUtf8('Start &Python Console'), |
|
486 ## 0, 0, |
|
487 ## self,'django_tools_pythonconsole') |
|
488 ## self.runPythonShellAct.setStatusTip(self.trUtf8( |
|
489 ## 'Starts a Python interactive interpreter')) |
|
490 ## self.runPythonShellAct.setWhatsThis(self.trUtf8( |
|
491 ## """<b>Start Python Console</b>""" |
|
492 ## """<p>Starts a Python interactive interpreter.</p>""" |
|
493 ## )) |
|
494 ## self.connect(self.runPythonShellAct, SIGNAL('triggered()'), |
|
495 ## self.__runPythonShell) |
|
496 ## self.actions.append(self.runPythonShellAct) |
|
497 ## |
|
498 ## def __initTestingActions(self): |
|
499 ## """ |
|
500 ## Private method to define the testing actions. |
|
501 ## """ |
|
502 ## self.dumpDataAct = E4Action(self.trUtf8('Dump Data'), |
|
503 ## self.trUtf8('&Dump Data'), |
|
504 ## 0, 0, |
|
505 ## self,'django_tools_dumpdata') |
|
506 ## self.dumpDataAct.setStatusTip(self.trUtf8( |
|
507 ## 'Dump the database data to a fixture')) |
|
508 ## self.dumpDataAct.setWhatsThis(self.trUtf8( |
|
509 ## """<b>Dump Data</b>""" |
|
510 ## """<p>Dump the database data to a fixture.</p>""" |
|
511 ## )) |
|
512 ## self.connect(self.dumpDataAct, SIGNAL('triggered()'), |
|
513 ## self.__dumpData) |
|
514 ## self.actions.append(self.dumpDataAct) |
|
515 ## |
|
516 ## self.loadDataAct = E4Action(self.trUtf8('Load Data'), |
|
517 ## self.trUtf8('&Load Data'), |
|
518 ## 0, 0, |
|
519 ## self,'django_tools_loaddata') |
|
520 ## self.loadDataAct.setStatusTip(self.trUtf8( |
|
521 ## 'Load data from fixture files')) |
|
522 ## self.loadDataAct.setWhatsThis(self.trUtf8( |
|
523 ## """<b>Load Data</b>""" |
|
524 ## """<p>Load data from fixture files.</p>""" |
|
525 ## )) |
|
526 ## self.connect(self.loadDataAct, SIGNAL('triggered()'), |
|
527 ## self.__loadData) |
|
528 ## self.actions.append(self.loadDataAct) |
|
529 ## |
|
530 ## self.runTestAct = E4Action(self.trUtf8('Run Testsuite'), |
|
531 ## self.trUtf8('Run &Testsuite'), |
|
532 ## 0, 0, |
|
533 ## self,'django_tools_run_test') |
|
534 ## self.runTestAct.setStatusTip(self.trUtf8( |
|
535 ## 'Run the test suite for applications or the whole site')) |
|
536 ## self.runTestAct.setWhatsThis(self.trUtf8( |
|
537 ## """<b>Run Testsuite</b>""" |
|
538 ## """<p>Run the test suite for applications or the whole site.</p>""" |
|
539 ## )) |
|
540 ## self.connect(self.runTestAct, SIGNAL('triggered()'), |
|
541 ## self.__runTestSuite) |
|
542 ## self.actions.append(self.runTestAct) |
|
543 ## |
|
544 ## self.runTestServerAct = E4Action(self.trUtf8('Run Testserver'), |
|
545 ## self.trUtf8('Run Test&server'), |
|
546 ## 0, 0, |
|
547 ## self,'django_tools_run_test_server') |
|
548 ## self.runTestServerAct.setStatusTip(self.trUtf8( |
|
549 ## 'Run a development server with data from a set of fixtures')) |
|
550 ## self.runTestServerAct.setWhatsThis(self.trUtf8( |
|
551 ## """<b>Run Testserver</b>""" |
|
552 ## """<p>Run a development server with data from a set of fixtures.</p>""" |
|
553 ## )) |
|
554 ## self.connect(self.runTestServerAct, SIGNAL('triggered()'), |
|
555 ## self.__runTestServer) |
|
556 ## self.actions.append(self.runTestServerAct) |
|
557 ## |
|
558 def initMenu(self): |
|
559 """ |
|
560 Public slot to initialize the Django menu. |
|
561 |
|
562 @return the menu generated (QMenu) |
|
563 """ |
|
564 menu = QMenu(self.trUtf8('D&jango'), self.__ui) |
|
565 menu.setTearOffEnabled(True) |
|
566 |
|
567 menu.addAction(self.selectSiteAct) |
|
568 menu.addSeparator() |
|
569 ## menu.addAction(self.runServerAct) |
|
570 ## menu.addAction(self.runBrowserAct) |
|
571 menu.addSeparator() |
|
572 menu.addAction(self.startProjectAct) |
|
573 menu.addAction(self.startGlobalApplicationAct) |
|
574 menu.addAction(self.startLocalApplicationAct) |
|
575 menu.addSeparator() |
|
576 menu.addMenu(self.__initDatabaseMenu()) |
|
577 menu.addSeparator() |
|
578 menu.addMenu(self.__initToolsMenu()) |
|
579 menu.addSeparator() |
|
580 ## menu.addAction(self.createCacheTableAct) |
|
581 menu.addSeparator() |
|
582 menu.addMenu(self.__initTestingMenu()) |
|
583 menu.addSeparator() |
|
584 menu.addAction(self.aboutDjangoAct) |
|
585 menu.addSeparator() |
|
586 menu.addAction(self.helpAct) |
|
587 |
|
588 self.__mainMenu = menu |
|
589 |
|
590 return menu |
|
591 |
|
592 def __initDatabaseMenu(self): |
|
593 """ |
|
594 Private slot to initialize the database menu. |
|
595 |
|
596 @return the menu generated (QMenu) |
|
597 """ |
|
598 menu = QMenu(self.trUtf8("&Database"), self.__ui) |
|
599 menu.setTearOffEnabled(True) |
|
600 |
|
601 ## menu.addAction(self.syncDatabaseAct) |
|
602 menu.addSeparator() |
|
603 ## menu.addAction(self.inspectDatabaseAct) |
|
604 menu.addSeparator() |
|
605 ## menu.addAction(self.flushDatabaseAct) |
|
606 ## menu.addAction(self.resetDatabaseAct) |
|
607 menu.addSeparator() |
|
608 ## menu.addAction(self.databaseClientAct) |
|
609 menu.addSeparator() |
|
610 menu.addMenu(self.__initDatabaseSqlMenu()) |
|
611 |
|
612 return menu |
|
613 |
|
614 def __initDatabaseSqlMenu(self): |
|
615 """ |
|
616 Private slot to initialize the database SQL submenu. |
|
617 |
|
618 @return the menu generated (QMenu) |
|
619 """ |
|
620 menu = QMenu(self.trUtf8("Show &SQL"), self.__ui) |
|
621 menu.setTearOffEnabled(True) |
|
622 |
|
623 ## menu.addAction(self.databaseSqlCreateTablesAct) |
|
624 ## menu.addAction(self.databaseSqlCreateIndexesAct) |
|
625 ## menu.addAction(self.databaseSqlCreateEverythingAct) |
|
626 menu.addSeparator() |
|
627 ## menu.addAction(self.databaseSqlCustomAct) |
|
628 menu.addSeparator() |
|
629 ## menu.addAction(self.databaseSqlDropTablesAct) |
|
630 menu.addSeparator() |
|
631 ## menu.addAction(self.databaseSqlFlushAct) |
|
632 ## menu.addAction(self.databaseSqlResetApplAct) |
|
633 ## menu.addAction(self.databaseSqlResetSeqAct) |
|
634 |
|
635 return menu |
|
636 |
|
637 def __initToolsMenu(self): |
|
638 """ |
|
639 Private slot to initialize the tools menu. |
|
640 |
|
641 @return the menu generated (QMenu) |
|
642 """ |
|
643 menu = QMenu(self.trUtf8("&Tools"), self.__ui) |
|
644 menu.setTearOffEnabled(True) |
|
645 |
|
646 ## menu.addAction(self.diffSettingsAct) |
|
647 ## menu.addAction(self.cleanupAct) |
|
648 ## menu.addAction(self.validateAct) |
|
649 ## menu.addAction(self.adminindexAct) |
|
650 menu.addSeparator() |
|
651 ## menu.addAction(self.runPythonShellAct) |
|
652 |
|
653 return menu |
|
654 |
|
655 def __initTestingMenu(self): |
|
656 """ |
|
657 Private slot to initialize the testing menu. |
|
658 |
|
659 @return the menu generated (QMenu) |
|
660 """ |
|
661 menu = QMenu(self.trUtf8("T&esting"), self.__ui) |
|
662 menu.setTearOffEnabled(True) |
|
663 |
|
664 ## menu.addAction(self.dumpDataAct) |
|
665 ## menu.addAction(self.loadDataAct) |
|
666 menu.addSeparator() |
|
667 ## menu.addAction(self.runTestAct) |
|
668 ## menu.addAction(self.runTestServerAct) |
|
669 |
|
670 return menu |
|
671 |
|
672 ################################################################## |
|
673 ## methods below implement the various hook related functions |
|
674 ################################################################## |
|
675 |
|
676 def projectOpenedHooks(self): |
|
677 """ |
|
678 Public method to add our hook methods. |
|
679 """ |
|
680 if self.__e5project.getProjectType() == "Django": |
|
681 self.__formsBrowser = \ |
|
682 e5App().getObject("ProjectBrowser").getProjectBrowser("forms") |
|
683 self.__formsBrowser.addHookMethodAndMenuEntry("newForm", |
|
684 self.newForm, self.trUtf8("New template...")) |
|
685 |
|
686 self.__e5project.projectLanguageAddedByCode.connect( |
|
687 self.__projectLanguageAdded) |
|
688 self.__translationsBrowser = \ |
|
689 e5App().getObject("ProjectBrowser").getProjectBrowser("translations") |
|
690 self.__translationsBrowser.addHookMethodAndMenuEntry("generateAll", |
|
691 self.updateCatalogs, self.trUtf8("Update all catalogs")) |
|
692 self.__translationsBrowser.addHookMethodAndMenuEntry("generateSelected", |
|
693 self.updateSelectedCatalogs, self.trUtf8("Update selected catalogs")) |
|
694 self.__translationsBrowser.addHookMethodAndMenuEntry("releaseAll", |
|
695 self.compileCatalogs, self.trUtf8("Compile all catalogs")) |
|
696 self.__translationsBrowser.addHookMethodAndMenuEntry("releaseSelected", |
|
697 self.compileSelectedCatalogs, |
|
698 self.trUtf8("Compile selected catalogs")) |
|
699 |
|
700 self.__hooksInstalled = True |
|
701 |
|
702 def projectClosedHooks(self): |
|
703 """ |
|
704 Public method to remove our hook methods. |
|
705 """ |
|
706 if self.__hooksInstalled: |
|
707 self.__formsBrowser.removeHookMethod("newForm") |
|
708 self.__formsBrowser = None |
|
709 |
|
710 self.__e5project.projectLanguageAddedByCode.disconnect( |
|
711 self.__projectLanguageAdded) |
|
712 self.__translationsBrowser.removeHookMethod("generateAll") |
|
713 self.__translationsBrowser.removeHookMethod("generateSelected") |
|
714 self.__translationsBrowser.removeHookMethod("releaseAll") |
|
715 self.__translationsBrowser.removeHookMethod("releaseSelected") |
|
716 self.__translationsBrowser = None |
|
717 |
|
718 self.__hooksInstalled = False |
|
719 |
|
720 def newForm(self, path): |
|
721 """ |
|
722 Public method to create a new form. |
|
723 |
|
724 @param path full directory path for the new form file (string) |
|
725 """ |
|
726 ## selectedFilter = QString("") |
|
727 ## filter = self.trUtf8("HTML Files (*.html);;All Files (*)") |
|
728 ## fname = KQFileDialog.getSaveFileName(\ |
|
729 ## self.__ui, |
|
730 ## self.trUtf8("New Form"), |
|
731 ## path, |
|
732 ## filter, |
|
733 ## selectedFilter, |
|
734 ## QFileDialog.Options(QFileDialog.DontConfirmOverwrite)) |
|
735 ## |
|
736 ## if fname.isEmpty(): |
|
737 ## # user aborted or didn't enter a filename |
|
738 ## return |
|
739 ## |
|
740 ## ext = QFileInfo(fname).suffix() |
|
741 ## if ext.isEmpty(): |
|
742 ## ex = selectedFilter.section('(*',1,1).section(')',0,0) |
|
743 ## if not ex.isEmpty(): |
|
744 ## fname.append(ex) |
|
745 ## |
|
746 ## fname = unicode(fname) |
|
747 ## if os.path.exists(fname): |
|
748 ## res = KQMessageBox.warning(self.__ui, |
|
749 ## self.trUtf8("New Form"), |
|
750 ## self.trUtf8("The file already exists! Overwrite it?"), |
|
751 ## QMessageBox.StandardButtons(\ |
|
752 ## QMessageBox.No | \ |
|
753 ## QMessageBox.Yes), |
|
754 ## QMessageBox.No) |
|
755 ## if res != QMessageBox.Yes: |
|
756 ## # user selected to not overwrite |
|
757 ## return |
|
758 ## |
|
759 ## try: |
|
760 ## f = open(fname, "wb") |
|
761 ## f.write('<html>\n') |
|
762 ## f.write(' <head>\n') |
|
763 ## f.write(' <meta content="" />\n') |
|
764 ## f.write(' <title></title>\n') |
|
765 ## f.write(' <style>\n') |
|
766 ## f.write(' </style>\n') |
|
767 ## f.write(' </head>\n') |
|
768 ## f.write('\n') |
|
769 ## f.write(' <body>\n') |
|
770 ## f.write(' </body>\n') |
|
771 ## f.write('</html>\n') |
|
772 ## f.close() |
|
773 ## except IOError, e: |
|
774 ## KQMessageBox.critical(self.__ui, |
|
775 ## self.trUtf8("New Form"), |
|
776 ## self.trUtf8("<p>The new form file <b>%1</b> could not be created.<br>" |
|
777 ## "Problem: %2</p>").arg(fname).arg(unicode(e))) |
|
778 ## return |
|
779 ## |
|
780 ## self.__e4project.appendFile(fname) |
|
781 ## self.__formsBrowser.emit(SIGNAL('sourceFile'), fname) |
|
782 |
|
783 ################################################################## |
|
784 ## slots below implement general functionality |
|
785 ################################################################## |
|
786 |
|
787 def projectClosed(self): |
|
788 """ |
|
789 Public method to handle the closing of a project. |
|
790 """ |
|
791 if self.__serverProc is not None: |
|
792 self.__serverProcFinished() |
|
793 self.__setCurrentSite(None) |
|
794 |
|
795 def __djangoInfo(self): |
|
796 """ |
|
797 Private slot to show some info about Django. |
|
798 """ |
|
799 from django import VERSION |
|
800 version = '.'.join([str(i) for i in VERSION[:-1]]) |
|
801 if VERSION[-1]: |
|
802 version += '-' + VERSION[-1] |
|
803 |
|
804 E5MessageBox.about(self.__ui, |
|
805 self.trUtf8("About Django"), |
|
806 self.trUtf8( |
|
807 "<p>Django is a high-level Python Web framework that encourages rapid " |
|
808 "development and clean, pragmatic design.</p>" |
|
809 "<p><table>" |
|
810 "<tr><td>Version:</td><td>{0}</td></tr>" |
|
811 "<tr><td>URL:</td><td><a href=\"http://www.djangoproject.com\">" |
|
812 "http://www.djangoproject.com</a></td></tr>" |
|
813 "</table></p>" |
|
814 ).format(version) |
|
815 ) |
|
816 |
|
817 ## def getDjangoVersion(self): |
|
818 ## """ |
|
819 ## Public method to get the Django version. |
|
820 ## |
|
821 ## @return Django version as a tuple |
|
822 ## """ |
|
823 ## from django import VERSION |
|
824 ## return VERSION |
|
825 ## |
|
826 ## def __getApplications(self): |
|
827 ## """ |
|
828 ## Private method to ask the user for a list of application names. |
|
829 ## |
|
830 ## @return list of application names (QStringList) |
|
831 ## """ |
|
832 ## applStr, ok = KQInputDialog.getItem(\ |
|
833 ## self.__ui, |
|
834 ## self.trUtf8("Select Applications"), |
|
835 ## self.trUtf8("Enter the list of applications separated by spaces."), |
|
836 ## self.getRecentApplications(), |
|
837 ## 0, True) |
|
838 ## if ok and not applStr.isEmpty(): |
|
839 ## self.setMostRecentApplication(applStr) |
|
840 ## return applStr.split(" ", QString.SkipEmptyParts) |
|
841 ## else: |
|
842 ## return QStringList() |
|
843 ## |
|
844 def __loadRecentApplications(self): |
|
845 """ |
|
846 Private method to load the recently used applications list. |
|
847 """ |
|
848 self.__recentApplications = [] |
|
849 Preferences.Prefs.rsettings.sync() |
|
850 ra = Preferences.Prefs.rsettings.value(self.RecentApplicationsKey) |
|
851 if ra is not None: |
|
852 maxRecentApps = self.__plugin.getPreferences("RecentNumberApps") |
|
853 self.__recentApplications = ra[:maxRecentApps] |
|
854 |
|
855 def __saveRecentApplications(self): |
|
856 """ |
|
857 Private method to save the list of recently used applications list. |
|
858 """ |
|
859 Preferences.Prefs.rsettings.setValue(self.RecentApplicationsKey, |
|
860 self.__recentApplications) |
|
861 Preferences.Prefs.rsettings.sync() |
|
862 |
|
863 def getRecentApplications(self): |
|
864 """ |
|
865 Public method to get the list of recent applications. |
|
866 |
|
867 @return list of recent applications entries (list of strings) |
|
868 """ |
|
869 self.__loadRecentApplications() |
|
870 return self.__recentApplications |
|
871 |
|
872 def setMostRecentApplication(self, applStr): |
|
873 """ |
|
874 Public method to set the most recently used applications entry. |
|
875 |
|
876 @param applStr applications entry (string) |
|
877 """ |
|
878 if applStr in self.__recentApplications: |
|
879 self.__recentApplications.remove(applStr) |
|
880 self.__recentApplications.insert(0, applStr) |
|
881 |
|
882 maxRecentApps = self.__plugin.getPreferences("RecentNumberApps") |
|
883 if len(self.__recentApplications) > maxRecentApps: |
|
884 self.__recentApplications = self.recent[:maxRecentApps] |
|
885 self.__saveRecentApplications() |
|
886 |
|
887 def getProjectPath(self): |
|
888 """ |
|
889 Public method to get the path of the eric5 project. |
|
890 |
|
891 @return path of the eric5 project (string) |
|
892 """ |
|
893 return self.__e5project.getProjectPath() |
|
894 |
|
895 def __getPythonExecutable(self): |
|
896 """ |
|
897 Private method to determine the name of the Python executable. |
|
898 |
|
899 @return Python executable (string) |
|
900 """ |
|
901 return sys.executable.replace("pythonw", "python") |
|
902 |
|
903 def __showHelpIndex(self): |
|
904 """ |
|
905 Private slot to show the help index page. |
|
906 """ |
|
907 page = os.path.join(os.path.dirname(__file__), |
|
908 "Documentation", "help", "index.html") |
|
909 self.__ui.launchHelpViewer(page) |
|
910 |
|
911 ################################################################## |
|
912 ## slots below implement creation functions |
|
913 ################################################################## |
|
914 |
|
915 ## def startProjectOrApplication(self): |
|
916 ## """ |
|
917 ## Public slot to start a new Django project or application. |
|
918 ## """ |
|
919 ## if self.__e4project.getProjectType() == "Django": |
|
920 ## projectStr = self.trUtf8("Project") |
|
921 ## applStr = self.trUtf8("Application") |
|
922 ## selections = QStringList() << QString("") << projectStr << applStr |
|
923 ## selection, ok = KQInputDialog.getItem(\ |
|
924 ## self.__ui, |
|
925 ## self.trUtf8("Start Django"), |
|
926 ## self.trUtf8("Select if this project should be a " |
|
927 ## "Django Project or Application.<br />" |
|
928 ## "Select the empty entry for none."), |
|
929 ## selections, |
|
930 ## 0, False) |
|
931 ## if ok and not selection.isEmpty(): |
|
932 ## if selection == projectStr: |
|
933 ## path, projectName = os.path.split(self.__e4project.getProjectPath()) |
|
934 ## self.__createProject(projectName, path) |
|
935 ## elif selection == applStr: |
|
936 ## path, applName = os.path.split(self.__e4project.getProjectPath()) |
|
937 ## self.__createApplication(applName, path) |
|
938 ## |
|
939 def __createProject(self, projectName, path): |
|
940 """ |
|
941 Private slot to create a new Django project. |
|
942 |
|
943 @param projectName name of the new project (string) |
|
944 @param path the directory where the project should be created |
|
945 (string) |
|
946 @return flag indicating a successful creation (boolean) |
|
947 """ |
|
948 title = self.trUtf8("Start Django Project") |
|
949 |
|
950 args = [] |
|
951 if Utilities.isWindowsPlatform(): |
|
952 args.append(self.__getPythonExecutable()) |
|
953 args.append(os.path.join(sys.exec_prefix, "Scripts", "django-admin.py")) |
|
954 else: |
|
955 if Utilities.isinpath("django-admin.py"): |
|
956 args.append("django-admin.py") |
|
957 elif Utilities.isinpath("django-admin"): |
|
958 args.append("django-admin") |
|
959 else: |
|
960 # fall back |
|
961 args.append("django-admin.py") |
|
962 args.append("startproject") |
|
963 args.append(projectName) |
|
964 |
|
965 dia = DjangoDialog(title, |
|
966 msgSuccess = self.trUtf8("Django project created successfully.")) |
|
967 res = dia.startProcess(args, path) |
|
968 if res: |
|
969 dia.exec_() |
|
970 |
|
971 # create the base directory for translations |
|
972 i18nPath = os.path.join(path, projectName, "locale") |
|
973 if not os.path.exists(i18nPath): |
|
974 os.makedirs(i18nPath) |
|
975 |
|
976 if os.path.join(path, projectName) == self.__e5project.getProjectPath(): |
|
977 self.__setCurrentSite("") |
|
978 else: |
|
979 self.__setCurrentSite(projectName) |
|
980 |
|
981 return res |
|
982 |
|
983 def __startProject(self): |
|
984 """ |
|
985 Private slot to start a new Django project. |
|
986 """ |
|
987 projectName, ok = QInputDialog.getText( |
|
988 self.__ui, |
|
989 self.trUtf8("Start Django Project"), |
|
990 self.trUtf8("Enter the name of the new Django project."), |
|
991 QLineEdit.Normal) |
|
992 if ok and projectName != "": |
|
993 res = self.__createProject(projectName, self.__e5project.getProjectPath()) |
|
994 if res: |
|
995 # search for new files and add them to the project |
|
996 sitePath = os.path.join(self.__e5project.getProjectPath(), |
|
997 projectName) |
|
998 for entry in os.walk(sitePath): |
|
999 for fileName in entry[2]: |
|
1000 fullName = os.path.join(entry[0], fileName) |
|
1001 self.__e5project.appendFile(fullName) |
|
1002 |
|
1003 def __createApplication(self, applName, path, isGlobal = True): |
|
1004 """ |
|
1005 Private slot to create a new Django application. |
|
1006 |
|
1007 @param applName name of the new application (string) |
|
1008 @param path the directory where the application should be created |
|
1009 (string) |
|
1010 @param isGlobal flag indicating a standalone Django application (boolean) |
|
1011 @return flag indicating a successful creation (boolean) |
|
1012 """ |
|
1013 title = self.trUtf8("Start Django Application") |
|
1014 |
|
1015 args = [] |
|
1016 if isGlobal: |
|
1017 if Utilities.isWindowsPlatform(): |
|
1018 args.append(self.__getPythonExecutable()) |
|
1019 args.append(os.path.join(sys.exec_prefix, "Scripts", "django-admin.py")) |
|
1020 else: |
|
1021 if Utilities.isinpath("django-admin.py"): |
|
1022 args.append("django-admin.py") |
|
1023 elif Utilities.isinpath("django-admin"): |
|
1024 args.append("django-admin") |
|
1025 else: |
|
1026 # fall back |
|
1027 args.append("django-admin.py") |
|
1028 else: |
|
1029 args.append(self.__getPythonExecutable()) |
|
1030 args.append("manage.py") |
|
1031 try: |
|
1032 path = self.__sitePath() |
|
1033 except DjangoNoSiteSelectedException: |
|
1034 return False |
|
1035 args.append("startapp") |
|
1036 args.append(applName) |
|
1037 |
|
1038 dia = DjangoDialog(title, |
|
1039 msgSuccess = self.trUtf8("Django application created successfully.")) |
|
1040 res = dia.startProcess(args, path) |
|
1041 if res: |
|
1042 dia.exec_() |
|
1043 return res |
|
1044 |
|
1045 def __startGlobalApplication(self): |
|
1046 """ |
|
1047 Private slot to start a new global Django application. |
|
1048 """ |
|
1049 applName, ok = QInputDialog.getText( |
|
1050 self.__ui, |
|
1051 self.trUtf8("Start Global Django Application"), |
|
1052 self.trUtf8("Enter the name of the new global Django application."), |
|
1053 QLineEdit.Normal) |
|
1054 if ok and applName != "": |
|
1055 res = self.__createApplication(applName, self.__e5project.getProjectPath()) |
|
1056 if res: |
|
1057 # search for new files and add them to the project |
|
1058 appPath = os.path.join(self.__e5project.getProjectPath(), applName) |
|
1059 for entry in os.walk(appPath): |
|
1060 for fileName in entry[2]: |
|
1061 fullName = os.path.join(entry[0], fileName) |
|
1062 self.__e5project.appendFile(fullName) |
|
1063 |
|
1064 def __startLocalApplication(self): |
|
1065 """ |
|
1066 Private slot to start a new local Django application. |
|
1067 """ |
|
1068 applName, ok = QInputDialog.getText( |
|
1069 self.__ui, |
|
1070 self.trUtf8("Start Local Django Application"), |
|
1071 self.trUtf8("Enter the name of the new local Django application."), |
|
1072 QLineEdit.Normal) |
|
1073 if ok and applName != "": |
|
1074 res = self.__createApplication(applName, "", False) |
|
1075 if res: |
|
1076 try: |
|
1077 # search for new files and add them to the project |
|
1078 appPath = os.path.join(self.__sitePath(), applName) |
|
1079 for entry in os.walk(appPath): |
|
1080 for fileName in entry[2]: |
|
1081 fullName = os.path.join(entry[0], fileName) |
|
1082 self.__e5project.appendFile(fullName) |
|
1083 except DjangoNoSiteSelectedException: |
|
1084 return |
|
1085 |
|
1086 ################################################################## |
|
1087 ## methods below implement site related functions |
|
1088 ################################################################## |
|
1089 |
|
1090 def __findSites(self): |
|
1091 """ |
|
1092 Private method to determine the relative path to all manage.py scripts. |
|
1093 |
|
1094 @return list of sites (list of strings) |
|
1095 """ |
|
1096 sites = [] |
|
1097 for file in sorted(self.__e5project.getSources()): |
|
1098 if os.path.basename(file) == "manage.py": |
|
1099 sites.append(os.path.dirname(file)) |
|
1100 return sites |
|
1101 |
|
1102 def __selectSite(self): |
|
1103 """ |
|
1104 Private method to select a site to work with. |
|
1105 |
|
1106 @return selected site (string) |
|
1107 """ |
|
1108 sites = self.__findSites() |
|
1109 if len(sites) == 1: |
|
1110 site = sites[0] |
|
1111 else: |
|
1112 if self.__currentSite is not None: |
|
1113 if self.__currentSite in sites: |
|
1114 cur = sites.index(self.__currentSite) |
|
1115 else: |
|
1116 cur = 0 |
|
1117 else: |
|
1118 cur = 0 |
|
1119 site, ok = QInputDialog.getItem( |
|
1120 self.__ui, |
|
1121 self.trUtf8("Select Project"), |
|
1122 self.trUtf8("Select the Django project to work with."), |
|
1123 sites, |
|
1124 cur, False) |
|
1125 if not ok: |
|
1126 site = None |
|
1127 self.__setCurrentSite(site) |
|
1128 |
|
1129 def __sitePath(self): |
|
1130 """ |
|
1131 Private method to calculate the full path of the Django site. |
|
1132 |
|
1133 @exception DjangoNoSiteSelectedException raised, if no site is selected |
|
1134 @return path of the site (string) |
|
1135 """ |
|
1136 if self.__currentSite is None: |
|
1137 self.__selectSite() |
|
1138 |
|
1139 if self.__currentSite is None: |
|
1140 raise DjangoNoSiteSelectedException |
|
1141 else: |
|
1142 return os.path.join(self.__e5project.getProjectPath(), |
|
1143 self.__currentSite) |
|
1144 |
|
1145 def __setCurrentSite(self, site): |
|
1146 """ |
|
1147 Private slot to set the current site. |
|
1148 |
|
1149 @param site name of the site (string) |
|
1150 """ |
|
1151 self.__currentSite = site |
|
1152 if self.__currentSite is None: |
|
1153 curSite = self.trUtf8("None") |
|
1154 elif self.__currentSite == "": |
|
1155 curSite = self.trUtf8("Project") |
|
1156 else: |
|
1157 curSite = self.__currentSite |
|
1158 self.selectSiteAct.setText( |
|
1159 self.trUtf8('&Current Django project ({0})').format(curSite)) |
|
1160 |
|
1161 if self.__currentSite is None: |
|
1162 self.__e5project.pdata["TRANSLATIONPATTERN"] = [] |
|
1163 else: |
|
1164 self.__e5project.pdata["TRANSLATIONPATTERN"] = [ |
|
1165 os.path.join(site, "locale", "%language%", "LC_MESSAGES", "django.po") |
|
1166 ] |
|
1167 |
|
1168 def __site(self): |
|
1169 """ |
|
1170 Private method to get the name of the current site. |
|
1171 |
|
1172 @exception DjangoNoSiteSelectedException raised, if no site is selected |
|
1173 @return name of the site (string) |
|
1174 """ |
|
1175 if self.__currentSite is None: |
|
1176 self.__selectSite() |
|
1177 |
|
1178 if self.__currentSite is None: |
|
1179 raise DjangoNoSiteSelectedException |
|
1180 else: |
|
1181 return self.__currentSite |
|
1182 |
|
1183 ################################################################## |
|
1184 ## slots below implement run functions |
|
1185 ################################################################## |
|
1186 |
|
1187 ## def __runServer(self): |
|
1188 ## """ |
|
1189 ## Private slot to start the Django Web server. |
|
1190 ## """ |
|
1191 ## consoleCmd = unicode(self.__plugin.getPreferences("ConsoleCommand")) |
|
1192 ## if consoleCmd: |
|
1193 ## args = Utilities.parseOptionString(consoleCmd) |
|
1194 ## args[0] = Utilities.getExecutablePath(args[0]) |
|
1195 ## args.append(self.__getPythonExecutable()) |
|
1196 ## args.append("manage.py") |
|
1197 ## args.append("runserver") |
|
1198 ## addr = self.__plugin.getPreferences("ServerAddress") |
|
1199 ## if addr: |
|
1200 ## args.append(addr) |
|
1201 ## |
|
1202 ## try: |
|
1203 ## if Utilities.isWindowsPlatform(): |
|
1204 ## serverProcStarted, pid = \ |
|
1205 ## QProcess.startDetached(args[0], args[1:], self.__sitePath()) |
|
1206 ## else: |
|
1207 ## if self.__serverProc is not None: |
|
1208 ## self.__serverProcFinished() |
|
1209 ## |
|
1210 ## self.__serverProc = QProcess() |
|
1211 ## self.connect(self.__serverProc, |
|
1212 ## SIGNAL('finished(int, QProcess::ExitStatus)'), |
|
1213 ## self.__serverProcFinished) |
|
1214 ## self.__serverProc.setWorkingDirectory(self.__sitePath()) |
|
1215 ## self.__serverProc.start(args[0], args[1:]) |
|
1216 ## serverProcStarted = self.__serverProc.waitForStarted() |
|
1217 ## if not serverProcStarted: |
|
1218 ## KQMessageBox.critical(None, |
|
1219 ## self.trUtf8('Process Generation Error'), |
|
1220 ## self.trUtf8('The Django server could not be started.')) |
|
1221 ## except DjangoNoSiteSelectedException: |
|
1222 ## pass |
|
1223 ## |
|
1224 ## def __serverProcFinished(self): |
|
1225 ## """ |
|
1226 ## Private slot connected to the finished signal. |
|
1227 ## """ |
|
1228 ## if self.__serverProc is not None and \ |
|
1229 ## self.__serverProc.state() != QProcess.NotRunning: |
|
1230 ## self.__serverProc.terminate() |
|
1231 ## QTimer.singleShot(2000, self.__serverProc, SLOT('kill()')) |
|
1232 ## self.__serverProc.waitForFinished(3000) |
|
1233 ## self.__serverProc = None |
|
1234 ## |
|
1235 ## def __runBrowser(self): |
|
1236 ## """ |
|
1237 ## Private slot to start the default web browser with the server URL. |
|
1238 ## """ |
|
1239 ## addr = self.__plugin.getPreferences("ServerAddress") |
|
1240 ## if addr: |
|
1241 ## if ':' in addr: |
|
1242 ## port = addr.split(':')[1] |
|
1243 ## else: |
|
1244 ## port = addr |
|
1245 ## else: |
|
1246 ## port = QString("8000") |
|
1247 ## url = QUrl(QString("http://127.0.0.1:%1").arg(port)) |
|
1248 ## res = QDesktopServices.openUrl(url) |
|
1249 ## if not res: |
|
1250 ## KQMessageBox.critical(None, |
|
1251 ## self.trUtf8('Run Web-Browser'), |
|
1252 ## self.trUtf8('Could not start the web-browser for the url "%1".')\ |
|
1253 ## .arg(url.toString())) |
|
1254 |
|
1255 ################################################################## |
|
1256 ## slots below implement database related functions |
|
1257 ################################################################## |
|
1258 |
|
1259 ## def __databaseSynchronize(self): |
|
1260 ## """ |
|
1261 ## Private slot to synchronize the database. |
|
1262 ## """ |
|
1263 ## consoleCmd = unicode(self.__plugin.getPreferences("ConsoleCommandNoClose")) |
|
1264 ## if consoleCmd: |
|
1265 ## proc = QProcess() |
|
1266 ## args = Utilities.parseOptionString(consoleCmd) |
|
1267 ## args[0] = Utilities.getExecutablePath(args[0]) |
|
1268 ## args.append(self.__getPythonExecutable()) |
|
1269 ## args.append("manage.py") |
|
1270 ## args.append("syncdb") |
|
1271 ## try: |
|
1272 ## wd = self.__sitePath() |
|
1273 ## started, pid = QProcess.startDetached(args[0], args[1:], wd) |
|
1274 ## if not started: |
|
1275 ## KQMessageBox.critical(None, |
|
1276 ## self.trUtf8('Process Generation Error'), |
|
1277 ## self.trUtf8('The Django process could not be started.')) |
|
1278 ## except DjangoNoSiteSelectedException: |
|
1279 ## pass |
|
1280 ## |
|
1281 ## def __databaseInspect(self): |
|
1282 ## """ |
|
1283 ## Private slot to introspect the database and output a Django model module. |
|
1284 ## """ |
|
1285 ## title = self.trUtf8("Introspect Database") |
|
1286 ## |
|
1287 ## args = QStringList() |
|
1288 ## args.append(self.__getPythonExecutable()) |
|
1289 ## args.append("manage.py") |
|
1290 ## args.append("inspectdb") |
|
1291 ## |
|
1292 ## try: |
|
1293 ## path = self.__sitePath() |
|
1294 ## except DjangoNoSiteSelectedException: |
|
1295 ## return |
|
1296 ## |
|
1297 ## dia = DjangoDialog(title, fixed = True, linewrap = False) |
|
1298 ## res = dia.startProcess(args, path, False) |
|
1299 ## if res: |
|
1300 ## dia.exec_() |
|
1301 ## |
|
1302 ## def __databaseFlush(self): |
|
1303 ## """ |
|
1304 ## Private slot to return all database tables to the state just after their |
|
1305 ## installation. |
|
1306 ## """ |
|
1307 ## try: |
|
1308 ## path = self.__sitePath() |
|
1309 ## except DjangoNoSiteSelectedException: |
|
1310 ## return |
|
1311 ## |
|
1312 ## title = self.trUtf8("Flush Database") |
|
1313 ## |
|
1314 ## res = KQMessageBox.question(self.__ui, |
|
1315 ## title, |
|
1316 ## self.trUtf8("""Flushing the database will destroy all data. Are you sure?"""), |
|
1317 ## QMessageBox.StandardButtons(\ |
|
1318 ## QMessageBox.No | \ |
|
1319 ## QMessageBox.Yes), |
|
1320 ## QMessageBox.No) |
|
1321 ## if res == QMessageBox.No: |
|
1322 ## return |
|
1323 ## |
|
1324 ## args = QStringList() |
|
1325 ## args.append(self.__getPythonExecutable()) |
|
1326 ## args.append("manage.py") |
|
1327 ## args.append("flush") |
|
1328 ## args.append("--noinput") |
|
1329 ## |
|
1330 ## dia = DjangoDialog(title, |
|
1331 ## msgSuccess = self.trUtf8("Database tables flushed successfully.")) |
|
1332 ## res = dia.startProcess(args, path) |
|
1333 ## if res: |
|
1334 ## dia.exec_() |
|
1335 ## |
|
1336 ## def __databaseReset(self): |
|
1337 ## """ |
|
1338 ## Private slot to reset the database tables of one or more applications. |
|
1339 ## """ |
|
1340 ## try: |
|
1341 ## path = self.__sitePath() |
|
1342 ## except DjangoNoSiteSelectedException: |
|
1343 ## return |
|
1344 ## |
|
1345 ## title = self.trUtf8("Reset Application(s)") |
|
1346 ## |
|
1347 ## apps = self.__getApplications() |
|
1348 ## if apps.isEmpty(): |
|
1349 ## return |
|
1350 ## |
|
1351 ## res = KQMessageBox.question(self.__ui, |
|
1352 ## title, |
|
1353 ## self.trUtf8("""Resetting the database tables for the applications '%1' """ |
|
1354 ## """will destroy all data. Are you sure?""")\ |
|
1355 ## .arg(apps.join(", ")), |
|
1356 ## QMessageBox.StandardButtons(\ |
|
1357 ## QMessageBox.No | \ |
|
1358 ## QMessageBox.Yes), |
|
1359 ## QMessageBox.No) |
|
1360 ## if res == QMessageBox.No: |
|
1361 ## return |
|
1362 ## |
|
1363 ## args = QStringList() |
|
1364 ## args.append(self.__getPythonExecutable()) |
|
1365 ## args.append("manage.py") |
|
1366 ## args.append("reset") |
|
1367 ## args.append("--noinput") |
|
1368 ## args += apps |
|
1369 ## |
|
1370 ## dia = DjangoDialog(title, |
|
1371 ## msgSuccess = self.trUtf8("Database tables for applications '%1' reset " |
|
1372 ## "successfully.").arg(apps.join(", ")) |
|
1373 ## ) |
|
1374 ## res = dia.startProcess(args, path) |
|
1375 ## if res: |
|
1376 ## dia.exec_() |
|
1377 ## |
|
1378 ## def __runDatabaseClient(self): |
|
1379 ## """ |
|
1380 ## Private slot to start a database client for a Django project. |
|
1381 ## """ |
|
1382 ## consoleCmd = unicode(self.__plugin.getPreferences("ConsoleCommand")) |
|
1383 ## if consoleCmd: |
|
1384 ## proc = QProcess() |
|
1385 ## args = Utilities.parseOptionString(consoleCmd) |
|
1386 ## args[0] = Utilities.getExecutablePath(args[0]) |
|
1387 ## args.append(self.__getPythonExecutable()) |
|
1388 ## args.append("manage.py") |
|
1389 ## args.append("dbshell") |
|
1390 ## try: |
|
1391 ## wd = self.__sitePath() |
|
1392 ## started, pid = QProcess.startDetached(args[0], args[1:], wd) |
|
1393 ## if not started: |
|
1394 ## KQMessageBox.critical(None, |
|
1395 ## self.trUtf8('Process Generation Error'), |
|
1396 ## self.trUtf8('The Django process could not be started.')) |
|
1397 ## except DjangoNoSiteSelectedException: |
|
1398 ## pass |
|
1399 |
|
1400 ####################################################################### |
|
1401 ## slots below implement database functions outputting SQL statements |
|
1402 ####################################################################### |
|
1403 |
|
1404 ## def __sqlCommand(self, title, command, requestApps = True): |
|
1405 ## """ |
|
1406 ## Private method to perform an SQL creation function. |
|
1407 ## |
|
1408 ## @param title dialog title (string or QString) |
|
1409 ## @param command Django sql... command (string or QString) |
|
1410 ## @param requestApps flag indicating to request a list of applications |
|
1411 ## to work on (boolean) |
|
1412 ## """ |
|
1413 ## try: |
|
1414 ## path = self.__sitePath() |
|
1415 ## except DjangoNoSiteSelectedException: |
|
1416 ## return |
|
1417 ## |
|
1418 ## if requestApps: |
|
1419 ## apps = self.__getApplications() |
|
1420 ## if apps.isEmpty(): |
|
1421 ## return |
|
1422 ## else: |
|
1423 ## apps = QStringList() |
|
1424 ## |
|
1425 ## args = QStringList() |
|
1426 ## args.append(self.__getPythonExecutable()) |
|
1427 ## args.append("manage.py") |
|
1428 ## args.append(command) |
|
1429 ## args += apps |
|
1430 ## |
|
1431 ## fileFilter = self.trUtf8("SQL Files (*.sql)") |
|
1432 ## |
|
1433 ## dia = DjangoDialog(title, fixed = True, linewrap = False, |
|
1434 ## saveFilters = fileFilter) |
|
1435 ## res = dia.startProcess(args, path, False) |
|
1436 ## if res: |
|
1437 ## dia.exec_() |
|
1438 ## |
|
1439 ## def __databaseSqlCreateTables(self): |
|
1440 ## """ |
|
1441 ## Private slot to print the CREATE TABLE SQL statements for one |
|
1442 ## or more applications. |
|
1443 ## """ |
|
1444 ## self.__sqlCommand(self.trUtf8("Create Tables"), "sql") |
|
1445 ## |
|
1446 ## def __databaseSqlCreateIndexes(self): |
|
1447 ## """ |
|
1448 ## Private slot to print the CREATE INDEX SQL statements for one |
|
1449 ## or more applications. |
|
1450 ## """ |
|
1451 ## self.__sqlCommand(self.trUtf8("Create Indexes"), "sqlindexes") |
|
1452 ## |
|
1453 ## def __databaseSqlCreateEverything(self): |
|
1454 ## """ |
|
1455 ## Private slot to print the CREATE TABLE, custom SQL and |
|
1456 ## CREATE INDEX SQL statements for one or more applications. |
|
1457 ## """ |
|
1458 ## self.__sqlCommand(self.trUtf8("Create Everything"), "sqlall") |
|
1459 ## |
|
1460 ## def __databaseSqlCustom(self): |
|
1461 ## """ |
|
1462 ## Private slot to print the custom table modifying SQL statements |
|
1463 ## for one or more applications. |
|
1464 ## """ |
|
1465 ## self.__sqlCommand(self.trUtf8("Custom Statements"), "sqlcustom") |
|
1466 ## |
|
1467 ## def __databaseSqlDropTables(self): |
|
1468 ## """ |
|
1469 ## Private slot to print the DROP TABLE SQL statements for one or |
|
1470 ## more applications. |
|
1471 ## """ |
|
1472 ## self.__sqlCommand(self.trUtf8("Drop Tables"), "sqlclear") |
|
1473 ## |
|
1474 ## def __databaseSqlFlushDatabase(self): |
|
1475 ## """ |
|
1476 ## Private slot to print a list of statements to return all database |
|
1477 ## tables to their initial state. |
|
1478 ## """ |
|
1479 ## self.__sqlCommand(self.trUtf8("Flush Database"), "sqlflush", False) |
|
1480 ## |
|
1481 ## def __databaseSqlResetApplication(self): |
|
1482 ## """ |
|
1483 ## Private slot to print the DROP TABLE SQL, then the CREATE TABLE SQL |
|
1484 ## for one or more applications. |
|
1485 ## """ |
|
1486 ## self.__sqlCommand(self.trUtf8("Reset Application(s)"), "sqlreset") |
|
1487 ## |
|
1488 ## def __databaseSqlResetSequences(self): |
|
1489 ## """ |
|
1490 ## Private slot to print the SQL statements for resetting sequences for |
|
1491 ## one or more applications. |
|
1492 ## """ |
|
1493 ## self.__sqlCommand(self.trUtf8("Reset Sequences"), "sqlsequencereset") |
|
1494 |
|
1495 ################################################################## |
|
1496 ## slots below implement some tool functions |
|
1497 ################################################################## |
|
1498 |
|
1499 ## def __diffSettings(self): |
|
1500 ## """ |
|
1501 ## Private slot to show the changes made to the settings.py file. |
|
1502 ## """ |
|
1503 ## title = self.trUtf8("Diff Settings") |
|
1504 ## |
|
1505 ## args = QStringList() |
|
1506 ## args.append(self.__getPythonExecutable()) |
|
1507 ## args.append("manage.py") |
|
1508 ## args.append("diffsettings") |
|
1509 ## |
|
1510 ## try: |
|
1511 ## path = self.__sitePath() |
|
1512 ## except DjangoNoSiteSelectedException: |
|
1513 ## return |
|
1514 ## |
|
1515 ## dia = DjangoDialog(title, fixed = True, linewrap = False) |
|
1516 ## res = dia.startProcess(args, path, False) |
|
1517 ## if res: |
|
1518 ## dia.exec_() |
|
1519 ## |
|
1520 ## def __cleanup(self): |
|
1521 ## """ |
|
1522 ## Private slot to clean out old data from the database. |
|
1523 ## """ |
|
1524 ## title = self.trUtf8("Cleanup") |
|
1525 ## |
|
1526 ## args = QStringList() |
|
1527 ## args.append(self.__getPythonExecutable()) |
|
1528 ## args.append("manage.py") |
|
1529 ## args.append("cleanup") |
|
1530 ## |
|
1531 ## try: |
|
1532 ## path = self.__sitePath() |
|
1533 ## except DjangoNoSiteSelectedException: |
|
1534 ## return |
|
1535 ## |
|
1536 ## dia = DjangoDialog(title, |
|
1537 ## msgSuccess = self.trUtf8("Database cleaned up successfully.")) |
|
1538 ## res = dia.startProcess(args, path) |
|
1539 ## if res: |
|
1540 ## dia.exec_() |
|
1541 ## |
|
1542 ## def __validate(self): |
|
1543 ## """ |
|
1544 ## Private slot to validate all installed models. |
|
1545 ## """ |
|
1546 ## title = self.trUtf8("Validate") |
|
1547 ## |
|
1548 ## args = QStringList() |
|
1549 ## args.append(self.__getPythonExecutable()) |
|
1550 ## args.append("manage.py") |
|
1551 ## args.append("validate") |
|
1552 ## |
|
1553 ## try: |
|
1554 ## path = self.__sitePath() |
|
1555 ## except DjangoNoSiteSelectedException: |
|
1556 ## return |
|
1557 ## |
|
1558 ## dia = DjangoDialog(title) |
|
1559 ## res = dia.startProcess(args, path) |
|
1560 ## if res: |
|
1561 ## dia.exec_() |
|
1562 ## |
|
1563 ## def __adminIndex(self): |
|
1564 ## """ |
|
1565 ## Private slot to print the admin-index template snippet. |
|
1566 ## """ |
|
1567 ## apps = self.__getApplications() |
|
1568 ## if apps.isEmpty(): |
|
1569 ## return |
|
1570 ## |
|
1571 ## title = self.trUtf8("Print admin-index") |
|
1572 ## |
|
1573 ## args = QStringList() |
|
1574 ## args.append(self.__getPythonExecutable()) |
|
1575 ## args.append("manage.py") |
|
1576 ## args.append("adminindex") |
|
1577 ## args += apps |
|
1578 ## |
|
1579 ## try: |
|
1580 ## path = self.__sitePath() |
|
1581 ## except DjangoNoSiteSelectedException: |
|
1582 ## return |
|
1583 ## |
|
1584 ## dia = DjangoDialog(title, fixed = True, linewrap = False) |
|
1585 ## res = dia.startProcess(args, path, False) |
|
1586 ## if res: |
|
1587 ## dia.exec_() |
|
1588 ## |
|
1589 ## def __runPythonShell(self): |
|
1590 ## """ |
|
1591 ## Private slot to start a Python console for a Django project. |
|
1592 ## """ |
|
1593 ## consoleCmd = unicode(self.__plugin.getPreferences("ConsoleCommand")) |
|
1594 ## if consoleCmd: |
|
1595 ## proc = QProcess() |
|
1596 ## args = Utilities.parseOptionString(consoleCmd) |
|
1597 ## args[0] = Utilities.getExecutablePath(args[0]) |
|
1598 ## args.append(self.__getPythonExecutable()) |
|
1599 ## args.append("manage.py") |
|
1600 ## args.append("shell") |
|
1601 ## if self.__plugin.getPreferences("UsePlainPython"): |
|
1602 ## args.append("--plain") |
|
1603 ## try: |
|
1604 ## wd = self.__sitePath() |
|
1605 ## started, pid = QProcess.startDetached(args[0], args[1:], wd) |
|
1606 ## if not started: |
|
1607 ## KQMessageBox.critical(None, |
|
1608 ## self.trUtf8('Process Generation Error'), |
|
1609 ## self.trUtf8('The Django process could not be started.')) |
|
1610 ## except DjangoNoSiteSelectedException: |
|
1611 ## pass |
|
1612 |
|
1613 ################################################################## |
|
1614 ## slots below implement caching functions |
|
1615 ################################################################## |
|
1616 |
|
1617 ## def __createCacheTables(self): |
|
1618 ## """ |
|
1619 ## Private slot to create the tables for the SQL caching backend. |
|
1620 ## """ |
|
1621 ## title = self.trUtf8("Create Cache Tables") |
|
1622 ## |
|
1623 ## try: |
|
1624 ## wd = self.__sitePath() |
|
1625 ## except DjangoNoSiteSelectedException: |
|
1626 ## return |
|
1627 ## |
|
1628 ## tblStr, ok = KQInputDialog.getText(\ |
|
1629 ## self.__ui, |
|
1630 ## title, |
|
1631 ## self.trUtf8("Enter the names of the cache tables separated by spaces."), |
|
1632 ## QLineEdit.Normal) |
|
1633 ## if ok and not tblStr.isEmpty(): |
|
1634 ## tableNames = tblStr.split(" ", QString.SkipEmptyParts) |
|
1635 ## |
|
1636 ## args = QStringList() |
|
1637 ## args.append(self.__getPythonExecutable()) |
|
1638 ## args.append("manage.py") |
|
1639 ## args.append("createcachetable") |
|
1640 ## args += tableNames |
|
1641 ## |
|
1642 ## dia = DjangoDialog(title, |
|
1643 ## msgSuccess = self.trUtf8("Cache tables created successfully.")) |
|
1644 ## res = dia.startProcess(args, wd) |
|
1645 ## if res: |
|
1646 ## dia.exec_() |
|
1647 |
|
1648 ################################################################## |
|
1649 ## slots below implement testing functions |
|
1650 ################################################################## |
|
1651 |
|
1652 ## def __dumpData(self): |
|
1653 ## """ |
|
1654 ## Private slot to dump the database data to a fixture. |
|
1655 ## """ |
|
1656 ## title = self.trUtf8("Dump Data") |
|
1657 ## |
|
1658 ## try: |
|
1659 ## wd = self.__sitePath() |
|
1660 ## except DjangoNoSiteSelectedException: |
|
1661 ## return |
|
1662 ## |
|
1663 ## dlg = DjangoDumpdataDataDialog(self, self.__ui) |
|
1664 ## if dlg.exec_() == QDialog.Accepted: |
|
1665 ## appls, excls, format = dlg.getData() |
|
1666 ## |
|
1667 ## args = QStringList() |
|
1668 ## args.append(self.__getPythonExecutable()) |
|
1669 ## args.append("manage.py") |
|
1670 ## args.append("dumpdata") |
|
1671 ## args.append("--format=%s" % format) |
|
1672 ## args.append("--indent=2") |
|
1673 ## for excl in excls: |
|
1674 ## args.append("--exclude=%s" % excl) |
|
1675 ## if not appls.isEmpty(): |
|
1676 ## args += appls |
|
1677 ## |
|
1678 ## if format == "json": |
|
1679 ## fileFilters = self.trUtf8("JSON Files (*.json)") |
|
1680 ## elif format == "xml": |
|
1681 ## fileFilters = self.trUtf8("XML Files (*.xml)") |
|
1682 ## elif format == "yaml": |
|
1683 ## fileFilters = self.trUtf8("YAML Files (*.yaml)") |
|
1684 ## |
|
1685 ## dia = DjangoDialog(title, fixed = True, linewrap = False, |
|
1686 ## saveFilters = fileFilters) |
|
1687 ## res = dia.startProcess(args, wd, showCommand = False) |
|
1688 ## if res: |
|
1689 ## dia.exec_() |
|
1690 ## |
|
1691 ## def __loadData(self): |
|
1692 ## """ |
|
1693 ## Private slot to load data from fixture files. |
|
1694 ## """ |
|
1695 ## title = self.trUtf8("Load Data") |
|
1696 ## |
|
1697 ## try: |
|
1698 ## wd = self.__sitePath() |
|
1699 ## except DjangoNoSiteSelectedException: |
|
1700 ## return |
|
1701 ## |
|
1702 ## dlg = DjangoLoaddataDataDialog(self, self.__ui) |
|
1703 ## if dlg.exec_() == QDialog.Accepted: |
|
1704 ## fixtures = dlg.getData() |
|
1705 ## |
|
1706 ## args = QStringList() |
|
1707 ## args.append(self.__getPythonExecutable()) |
|
1708 ## args.append("manage.py") |
|
1709 ## args.append("loaddata") |
|
1710 ## args += fixtures |
|
1711 ## |
|
1712 ## dia = DjangoDialog(title) |
|
1713 ## res = dia.startProcess(args, wd) |
|
1714 ## if res: |
|
1715 ## dia.exec_() |
|
1716 ## |
|
1717 ## def __runTestSuite(self): |
|
1718 ## """ |
|
1719 ## Private slot to run the test suite for applications or the whole site. |
|
1720 ## """ |
|
1721 ## consoleCmd = unicode(self.__plugin.getPreferences("ConsoleCommandNoClose")) |
|
1722 ## if consoleCmd: |
|
1723 ## try: |
|
1724 ## wd = self.__sitePath() |
|
1725 ## except DjangoNoSiteSelectedException: |
|
1726 ## return |
|
1727 ## |
|
1728 ## proc = QProcess() |
|
1729 ## args = Utilities.parseOptionString(consoleCmd) |
|
1730 ## args[0] = Utilities.getExecutablePath(args[0]) |
|
1731 ## args.append(self.__getPythonExecutable()) |
|
1732 ## args.append("manage.py") |
|
1733 ## args.append("test") |
|
1734 ## args += self.__getApplications() |
|
1735 ## |
|
1736 ## started, pid = QProcess.startDetached(args[0], args[1:], wd) |
|
1737 ## if not started: |
|
1738 ## KQMessageBox.critical(None, |
|
1739 ## self.trUtf8('Process Generation Error'), |
|
1740 ## self.trUtf8('The Django process could not be started.')) |
|
1741 ## |
|
1742 ## def __runTestServer(self): |
|
1743 ## """ |
|
1744 ## Private slot to run a development server with data from a set of fixtures. |
|
1745 ## """ |
|
1746 ## consoleCmd = unicode(self.__plugin.getPreferences("ConsoleCommand")) |
|
1747 ## if consoleCmd: |
|
1748 ## dlg = DjangoLoaddataDataDialog(self, self.__ui) |
|
1749 ## if dlg.exec_() == QDialog.Accepted: |
|
1750 ## fixtures = dlg.getData() |
|
1751 ## |
|
1752 ## args = Utilities.parseOptionString(consoleCmd) |
|
1753 ## args[0] = Utilities.getExecutablePath(args[0]) |
|
1754 ## args.append(self.__getPythonExecutable()) |
|
1755 ## args.append("manage.py") |
|
1756 ## args.append("testserver") |
|
1757 ## addr = self.__plugin.getPreferences("ServerAddress") |
|
1758 ## if addr: |
|
1759 ## args.append("--addrport=%s" % addr) |
|
1760 ## args += fixtures |
|
1761 ## |
|
1762 ## try: |
|
1763 ## if Utilities.isWindowsPlatform(): |
|
1764 ## serverProcStarted, pid = \ |
|
1765 ## QProcess.startDetached(args[0], args[1:], self.__sitePath()) |
|
1766 ## else: |
|
1767 ## if self.__testServerProc is not None: |
|
1768 ## self.__testServerProcFinished() |
|
1769 ## |
|
1770 ## self.__testServerProc = QProcess() |
|
1771 ## self.connect(self.__testServerProc, |
|
1772 ## SIGNAL('finished(int, QProcess::ExitStatus)'), |
|
1773 ## self.__serverProcFinished) |
|
1774 ## |
|
1775 ## self.__testServerProc.setWorkingDirectory(self.__sitePath()) |
|
1776 ## self.__testServerProc.start(args[0], args[1:]) |
|
1777 ## serverProcStarted = self.__testServerProc.waitForStarted() |
|
1778 ## if not serverProcStarted: |
|
1779 ## KQMessageBox.critical(None, |
|
1780 ## self.trUtf8('Process Generation Error'), |
|
1781 ## self.trUtf8('The Django test server could not be started.')) |
|
1782 ## except DjangoNoSiteSelectedException: |
|
1783 ## pass |
|
1784 ## |
|
1785 ## def __testServerProcFinished(self): |
|
1786 ## """ |
|
1787 ## Private slot connected to the finished signal of the test server. |
|
1788 ## """ |
|
1789 ## if self.__testServerProc is not None and \ |
|
1790 ## self.__testServerProc.state() != QProcess.NotRunning: |
|
1791 ## self.__testServerProc.terminate() |
|
1792 ## QTimer.singleShot(2000, self.__testServerProc, SLOT('kill()')) |
|
1793 ## self.__testServerProc.waitForFinished(3000) |
|
1794 ## self.__testServerProc = None |
|
1795 |
|
1796 ################################################################## |
|
1797 ## slots below implement translation functions |
|
1798 ################################################################## |
|
1799 |
|
1800 ## def __getLocale(self, filename): |
|
1801 ## """ |
|
1802 ## Private method to extract the locale out of a file name. |
|
1803 ## |
|
1804 ## @param filename name of the file used for extraction (string or QString) |
|
1805 ## @return extracted locale (string) or None |
|
1806 ## """ |
|
1807 ## if self.__e4project.pdata["TRANSLATIONPATTERN"]: |
|
1808 ## pattern = unicode(self.__e4project.pdata["TRANSLATIONPATTERN"][0])\ |
|
1809 ## .replace("%language%", "(.*?)") |
|
1810 ## match = re.search(pattern, unicode(filename)) |
|
1811 ## if match is not None: |
|
1812 ## loc = match.group(1) |
|
1813 ## return loc |
|
1814 ## else: |
|
1815 ## loc = None |
|
1816 ## else: |
|
1817 ## loc = None |
|
1818 ## |
|
1819 ## return loc |
|
1820 ## |
|
1821 ## def __normalizeList(self, filenames): |
|
1822 ## """ |
|
1823 ## Private method to normalize a list of file names. |
|
1824 ## |
|
1825 ## @param filenames list of file names to normalize (list of string or QString) |
|
1826 ## @return normalized file names (list of string) |
|
1827 ## """ |
|
1828 ## nfilenames = [] |
|
1829 ## for filename in filenames: |
|
1830 ## filename = unicode(filename) |
|
1831 ## if filename.endswith(".mo"): |
|
1832 ## filename = filename.replace(".mo", ".po") |
|
1833 ## if filename not in nfilenames: |
|
1834 ## nfilenames.append(filename) |
|
1835 ## |
|
1836 ## return nfilenames |
|
1837 ## |
|
1838 ## def __siteFilteredList(self, filenames): |
|
1839 ## """ |
|
1840 ## Private method to filter a list of file names by site. |
|
1841 ## |
|
1842 ## @param filenames list of file names to be filtered (list of string or QString) |
|
1843 ## @return file names belonging to the current site (list of string) |
|
1844 ## """ |
|
1845 ## site = self.__site() |
|
1846 ## nfilenames = [] |
|
1847 ## for filename in filenames: |
|
1848 ## filename = unicode(filename) |
|
1849 ## if site == "" or filename.startswith(site + os.sep): |
|
1850 ## nfilenames.append(filename) |
|
1851 ## |
|
1852 ## return nfilenames |
|
1853 |
|
1854 def __projectLanguageAdded(self, code): |
|
1855 """ |
|
1856 Private slot handling the addition of a new language. |
|
1857 |
|
1858 @param code language code of the new language (string or QString) |
|
1859 """ |
|
1860 ## title = self.trUtf8("Initializing message catalog for '%1'").arg(code) |
|
1861 ## |
|
1862 ## args = QStringList() |
|
1863 ## args.append(self.__getPythonExecutable()) |
|
1864 ## args.append("manage.py") |
|
1865 ## args.append("makemessages") |
|
1866 ## args.append("-l") |
|
1867 ## args.append(code) |
|
1868 ## |
|
1869 ## try: |
|
1870 ## wd = self.__sitePath() |
|
1871 ## except DjangoNoSiteSelectedException: |
|
1872 ## KQMessageBox.warning(None, |
|
1873 ## title, |
|
1874 ## self.trUtf8('No current site selected or no site created yet.' |
|
1875 ## ' Aborting...')) |
|
1876 ## return |
|
1877 ## |
|
1878 ## dia = DjangoDialog(title, |
|
1879 ## msgSuccess = \ |
|
1880 ## self.trUtf8("\nMessage catalog initialized successfully.")) |
|
1881 ## res = dia.startProcess(args, wd) |
|
1882 ## if res: |
|
1883 ## dia.exec_() |
|
1884 ## |
|
1885 ## langFile = self.__e4project.pdata["TRANSLATIONPATTERN"][0]\ |
|
1886 ## .replace("%language%", code) |
|
1887 ## self.__e4project.appendFile(langFile) |
|
1888 |
|
1889 def updateSelectedCatalogs(self, filenames): |
|
1890 """ |
|
1891 Public method to update the message catalogs. |
|
1892 |
|
1893 @param filenames list of filenames |
|
1894 """ |
|
1895 ## title = self.trUtf8("Updating message catalogs") |
|
1896 ## |
|
1897 ## try: |
|
1898 ## wd = self.__sitePath() |
|
1899 ## except DjangoNoSiteSelectedException: |
|
1900 ## KQMessageBox.warning(None, |
|
1901 ## title, |
|
1902 ## self.trUtf8('No current site selected or no site created yet.' |
|
1903 ## ' Aborting...')) |
|
1904 ## return |
|
1905 ## |
|
1906 ## argsLists = [] |
|
1907 ## |
|
1908 ## for filename in self.__normalizeList(self.__siteFilteredList(filenames)): |
|
1909 ## locale = self.__getLocale(filename) |
|
1910 ## if locale: |
|
1911 ## args = QStringList() |
|
1912 ## args.append(self.__getPythonExecutable()) |
|
1913 ## args.append("manage.py") |
|
1914 ## args.append("makemessages") |
|
1915 ## args.append("-l") |
|
1916 ## args.append(locale) |
|
1917 ## argsLists.append(args) |
|
1918 ## |
|
1919 ## if len(argsLists) == 0: |
|
1920 ## KQMessageBox.warning(None, |
|
1921 ## title, |
|
1922 ## self.trUtf8('No locales detected.' |
|
1923 ## ' Aborting...')) |
|
1924 ## return |
|
1925 ## |
|
1926 ## dia = DjangoDialog(title, |
|
1927 ## msgSuccess = \ |
|
1928 ## self.trUtf8("\nMessage catalogs updated successfully.")) |
|
1929 ## res = dia.startBatchProcesses(argsLists, wd) |
|
1930 ## if res: |
|
1931 ## dia.exec_() |
|
1932 |
|
1933 def updateCatalogs(self, filenames): |
|
1934 """ |
|
1935 Public method to update the message catalogs. |
|
1936 |
|
1937 @param filenames list of filenames (not used) |
|
1938 """ |
|
1939 ## title = self.trUtf8("Updating message catalogs") |
|
1940 ## |
|
1941 ## args = QStringList() |
|
1942 ## args.append(self.__getPythonExecutable()) |
|
1943 ## args.append("manage.py") |
|
1944 ## args.append("makemessages") |
|
1945 ## args.append("-a") |
|
1946 ## |
|
1947 ## try: |
|
1948 ## wd = self.__sitePath() |
|
1949 ## except DjangoNoSiteSelectedException: |
|
1950 ## KQMessageBox.warning(None, |
|
1951 ## title, |
|
1952 ## self.trUtf8('No current site selected or no site created yet.' |
|
1953 ## ' Aborting...')) |
|
1954 ## return |
|
1955 ## |
|
1956 ## dia = DjangoDialog(title, |
|
1957 ## msgSuccess = \ |
|
1958 ## self.trUtf8("\nMessage catalogs updated successfully.")) |
|
1959 ## res = dia.startProcess(args, wd) |
|
1960 ## if res: |
|
1961 ## dia.exec_() |
|
1962 |
|
1963 def compileSelectedCatalogs(self, filenames): |
|
1964 """ |
|
1965 Public method to update the message catalogs. |
|
1966 |
|
1967 @param filenames list of filenames |
|
1968 """ |
|
1969 ## title = self.trUtf8("Compiling message catalogs") |
|
1970 ## |
|
1971 ## try: |
|
1972 ## wd = self.__sitePath() |
|
1973 ## except DjangoNoSiteSelectedException: |
|
1974 ## KQMessageBox.warning(None, |
|
1975 ## title, |
|
1976 ## self.trUtf8('No current site selected or no site created yet.' |
|
1977 ## ' Aborting...')) |
|
1978 ## return |
|
1979 ## |
|
1980 ## argsLists = [] |
|
1981 ## |
|
1982 ## for filename in self.__normalizeList(self.__siteFilteredList(filenames)): |
|
1983 ## locale = self.__getLocale(filename) |
|
1984 ## if locale: |
|
1985 ## args = QStringList() |
|
1986 ## args.append(self.__getPythonExecutable()) |
|
1987 ## args.append("manage.py") |
|
1988 ## args.append("compilemessages") |
|
1989 ## args.append("-l") |
|
1990 ## args.append(locale) |
|
1991 ## argsLists.append(args) |
|
1992 ## |
|
1993 ## if len(argsLists) == 0: |
|
1994 ## KQMessageBox.warning(None, |
|
1995 ## title, |
|
1996 ## self.trUtf8('No locales detected.' |
|
1997 ## ' Aborting...')) |
|
1998 ## return |
|
1999 ## |
|
2000 ## dia = DjangoDialog(title, |
|
2001 ## msgSuccess = \ |
|
2002 ## self.trUtf8("\nMessage catalogs compiled successfully.")) |
|
2003 ## res = dia.startBatchProcesses(argsLists, wd, mergedOutput = True) |
|
2004 ## if res: |
|
2005 ## dia.exec_() |
|
2006 ## |
|
2007 ## for entry in os.walk(self.__sitePath()): |
|
2008 ## for fileName in entry[2]: |
|
2009 ## fullName = os.path.join(entry[0], fileName) |
|
2010 ## if fullName.endswith('.mo'): |
|
2011 ## self.__e4project.appendFile(fullName) |
|
2012 |
|
2013 def compileCatalogs(self, filenames): |
|
2014 """ |
|
2015 Public method to compile the message catalogs. |
|
2016 |
|
2017 @param filenames list of filenames (not used) |
|
2018 """ |
|
2019 ## title = self.trUtf8("Compiling message catalogs") |
|
2020 ## |
|
2021 ## args = QStringList() |
|
2022 ## args.append(self.__getPythonExecutable()) |
|
2023 ## args.append("manage.py") |
|
2024 ## args.append("compilemessages") |
|
2025 ## |
|
2026 ## try: |
|
2027 ## wd = self.__sitePath() |
|
2028 ## except DjangoNoSiteSelectedException: |
|
2029 ## KQMessageBox.warning(None, |
|
2030 ## title, |
|
2031 ## self.trUtf8('No current site selected or no site created yet.' |
|
2032 ## ' Aborting...')) |
|
2033 ## return |
|
2034 ## |
|
2035 ## dia = DjangoDialog(title, |
|
2036 ## msgSuccess = \ |
|
2037 ## self.trUtf8("\nMessage catalogs compiled successfully.")) |
|
2038 ## res = dia.startProcess(args, wd, mergedOutput = True) |
|
2039 ## if res: |
|
2040 ## dia.exec_() |
|
2041 ## |
|
2042 ## for entry in os.walk(self.__sitePath()): |
|
2043 ## for fileName in entry[2]: |
|
2044 ## fullName = os.path.join(entry[0], fileName) |
|
2045 ## if fullName.endswith('.mo'): |
|
2046 ## self.__e4project.appendFile(fullName) |