Project/ProjectFormsBrowser.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a class used to display the forms part of the project.
8 """
9
10 import os
11 import sys
12 import shutil
13
14 from PyQt4.QtCore import *
15 from PyQt4.QtGui import *
16
17 from E4Gui.E4Application import e4App
18
19 from ProjectBrowserModel import ProjectBrowserFileItem, \
20 ProjectBrowserSimpleDirectoryItem, ProjectBrowserDirectoryItem, \
21 ProjectBrowserFormType
22 from ProjectBaseBrowser import ProjectBaseBrowser
23
24 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
25 import UI.PixmapCache
26
27 import Preferences
28 import Utilities
29
30 from eric4config import getConfig
31
32 class ProjectFormsBrowser(ProjectBaseBrowser):
33 """
34 A class used to display the forms part of the project.
35
36 @signal appendStderr(string) emitted after something was received from
37 a QProcess on stderr
38 @signal sourceFile(string) emitted to open a forms file in an editor
39 @signal uipreview(string) emitted to preview a forms file
40 @signal trpreview(string list) emitted to preview form files in the
41 translations previewer
42 @signal closeSourceWindow(string) emitted after a file has been removed/deleted
43 from the project
44 @signal showMenu(string, QMenu) emitted when a menu is about to be shown. The name
45 of the menu and a reference to the menu are given.
46 @signal menusAboutToBeCreated emitted when the context menu are about to
47 be created. This is the right moment to add or remove hook methods.
48 """
49 def __init__(self, project, parent = None):
50 """
51 Constructor
52
53 @param project reference to the project object
54 @param parent parent widget of this browser (QWidget)
55 """
56 ProjectBaseBrowser.__init__(self, project, ProjectBrowserFormType, parent)
57
58 self.selectedItemsFilter = \
59 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]
60
61 self.setWindowTitle(self.trUtf8('Forms'))
62
63 self.setWhatsThis(self.trUtf8(
64 """<b>Project Forms Browser</b>"""
65 """<p>This allows to easily see all forms contained in the current"""
66 """ project. Several actions can be executed via the context menu.</p>"""
67 ))
68
69 # templates for Qt4
70 # these two lists have to stay in sync
71 self.templates4 = ['dialog4.tmpl', 'widget4.tmpl', 'mainwindow4.tmpl',
72 'dialogbuttonboxbottom4.tmpl', 'dialogbuttonboxright4.tmpl',
73 'dialogbuttonsbottom4.tmpl', 'dialogbuttonsbottomcenter4.tmpl',
74 'dialogbuttonsright4.tmpl']
75 self.templateTypes4 = [ \
76 self.trUtf8("Dialog"),
77 self.trUtf8("Widget"),
78 self.trUtf8("Main Window"),
79 self.trUtf8("Dialog with Buttonbox (Bottom)"),
80 self.trUtf8("Dialog with Buttonbox (Right)"),
81 self.trUtf8("Dialog with Buttons (Bottom)"),
82 self.trUtf8("Dialog with Buttons (Bottom-Center)"),
83 self.trUtf8("Dialog with Buttons (Right)"),
84 ]
85
86 self.compileProc = None
87
88 def _createPopupMenus(self):
89 """
90 Protected overloaded method to generate the popup menu.
91 """
92 self.menuActions = []
93 self.multiMenuActions = []
94 self.dirMenuActions = []
95 self.dirMultiMenuActions = []
96
97 self.emit(SIGNAL("menusAboutToBeCreated"))
98
99 self.menu = QMenu(self)
100 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
101 self.menu.addAction(self.trUtf8('Compile form'), self.__compileForm)
102 self.menu.addAction(self.trUtf8('Compile all forms'),
103 self.__compileAllForms)
104 self.menu.addAction(self.trUtf8('Generate Dialog Code...'),
105 self.__generateDialogCode)
106 self.menu.addSeparator()
107 self.menu.addAction(self.trUtf8('Open in Qt-Designer'), self.__openFile)
108 self.menu.addAction(self.trUtf8('Open in Editor'), self.__openFileInEditor)
109 self.menu.addSeparator()
110 self.menu.addAction(self.trUtf8('Preview form'), self.__UIPreview)
111 self.menu.addAction(self.trUtf8('Preview translations'), self.__TRPreview)
112 else:
113 if self.hooks["compileForm"] is not None:
114 self.menu.addAction(
115 self.hooksMenuEntries.get("compileForm",
116 self.trUtf8('Compile form')), self.__compileForm)
117 if self.hooks["compileAllForms"] is not None:
118 self.menu.addAction(
119 self.hooksMenuEntries.get("compileAllForms",
120 self.trUtf8('Compile all forms')),
121 self.__compileAllForms)
122 if self.hooks["generateDialogCode"] is not None:
123 self.menu.addAction(
124 self.hooksMenuEntries.get("generateDialogCode",
125 self.trUtf8('Generate Dialog Code...')),
126 self.__generateDialogCode)
127 if self.hooks["compileForm"] is not None or \
128 self.hooks["compileAllForms"] is not None or \
129 self.hooks["generateDialogCode"] is not None:
130 self.menu.addSeparator()
131 self.menu.addAction(self.trUtf8('Open'), self.__openFileInEditor)
132 self.menu.addSeparator()
133 act = self.menu.addAction(self.trUtf8('Rename file'), self._renameFile)
134 self.menuActions.append(act)
135 act = self.menu.addAction(self.trUtf8('Remove from project'), self._removeFile)
136 self.menuActions.append(act)
137 act = self.menu.addAction(self.trUtf8('Delete'), self.__deleteFile)
138 self.menuActions.append(act)
139 self.menu.addSeparator()
140 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
141 self.menu.addAction(self.trUtf8('New form...'), self.__newForm)
142 else:
143 if self.hooks["newForm"] is not None:
144 self.menu.addAction(
145 self.hooksMenuEntries.get("newForm",
146 self.trUtf8('New form...')), self.__newForm)
147 self.menu.addAction(self.trUtf8('Add forms...'), self.__addFormFiles)
148 self.menu.addAction(self.trUtf8('Add forms directory...'),
149 self.__addFormsDirectory)
150 self.menu.addSeparator()
151 self.menu.addAction(self.trUtf8('Copy Path to Clipboard'),
152 self._copyToClipboard)
153 self.menu.addSeparator()
154 self.menu.addAction(self.trUtf8('Expand all directories'),
155 self._expandAllDirs)
156 self.menu.addAction(self.trUtf8('Collapse all directories'),
157 self._collapseAllDirs)
158 self.menu.addSeparator()
159 self.menu.addAction(self.trUtf8('Configure...'), self._configure)
160
161 self.backMenu = QMenu(self)
162 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"] or \
163 self.hooks["compileAllForms"] is not None:
164 self.backMenu.addAction(self.trUtf8('Compile all forms'),
165 self.__compileAllForms)
166 self.backMenu.addSeparator()
167 self.backMenu.addAction(self.trUtf8('New form...'), self.__newForm)
168 else:
169 if self.hooks["newForm"] is not None:
170 self.backMenu.addAction(
171 self.hooksMenuEntries.get("newForm",
172 self.trUtf8('New form...')), self.__newForm)
173 self.backMenu.addAction(self.trUtf8('Add forms...'), self.project.addUiFiles)
174 self.backMenu.addAction(self.trUtf8('Add forms directory...'),
175 self.project.addUiDir)
176 self.backMenu.addSeparator()
177 self.backMenu.addAction(self.trUtf8('Expand all directories'),
178 self._expandAllDirs)
179 self.backMenu.addAction(self.trUtf8('Collapse all directories'),
180 self._collapseAllDirs)
181 self.backMenu.addSeparator()
182 self.backMenu.addAction(self.trUtf8('Configure...'), self._configure)
183 self.backMenu.setEnabled(False)
184
185 # create the menu for multiple selected files
186 self.multiMenu = QMenu(self)
187 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
188 act = self.multiMenu.addAction(self.trUtf8('Compile forms'),
189 self.__compileSelectedForms)
190 self.multiMenu.addSeparator()
191 self.multiMenu.addAction(self.trUtf8('Open in Qt-Designer'),
192 self.__openFile)
193 self.multiMenu.addAction(self.trUtf8('Open in Editor'),
194 self.__openFileInEditor)
195 self.multiMenu.addSeparator()
196 self.multiMenu.addAction(self.trUtf8('Preview translations'),
197 self.__TRPreview)
198 else:
199 if self.hooks["compileSelectedForms"] is not None:
200 act = self.multiMenu.addAction(
201 self.hooksMenuEntries.get("compileSelectedForms",
202 self.trUtf8('Compile forms')),
203 self.__compileSelectedForms)
204 self.multiMenu.addSeparator()
205 self.multiMenu.addAction(self.trUtf8('Open'), self.__openFileInEditor)
206 self.multiMenu.addSeparator()
207 act = self.multiMenu.addAction(self.trUtf8('Remove from project'),
208 self._removeFile)
209 self.multiMenuActions.append(act)
210 act = self.multiMenu.addAction(self.trUtf8('Delete'), self.__deleteFile)
211 self.multiMenuActions.append(act)
212 self.multiMenu.addSeparator()
213 self.multiMenu.addAction(self.trUtf8('Expand all directories'),
214 self._expandAllDirs)
215 self.multiMenu.addAction(self.trUtf8('Collapse all directories'),
216 self._collapseAllDirs)
217 self.multiMenu.addSeparator()
218 self.multiMenu.addAction(self.trUtf8('Configure...'), self._configure)
219
220 self.dirMenu = QMenu(self)
221 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
222 self.dirMenu.addAction(self.trUtf8('Compile all forms'),
223 self.__compileAllForms)
224 self.dirMenu.addSeparator()
225 else:
226 if self.hooks["compileAllForms"] is not None:
227 self.dirMenu.addAction(
228 self.hooksMenuEntries.get("compileAllForms",
229 self.trUtf8('Compile all forms')),
230 self.__compileAllForms)
231 self.dirMenu.addSeparator()
232 act = self.dirMenu.addAction(self.trUtf8('Remove from project'), self._removeDir)
233 self.dirMenuActions.append(act)
234 self.dirMenu.addSeparator()
235 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
236 self.dirMenu.addAction(self.trUtf8('New form...'), self.__newForm)
237 else:
238 if self.hooks["newForm"] is not None:
239 self.dirMenu.addAction(
240 self.hooksMenuEntries.get("newForm",
241 self.trUtf8('New form...')), self.__newForm)
242 self.dirMenu.addAction(self.trUtf8('Add forms...'), self.__addFormFiles)
243 self.dirMenu.addAction(self.trUtf8('Add forms directory...'),
244 self.__addFormsDirectory)
245 self.dirMenu.addSeparator()
246 self.dirMenu.addAction(self.trUtf8('Copy Path to Clipboard'),
247 self._copyToClipboard)
248 self.dirMenu.addSeparator()
249 self.dirMenu.addAction(self.trUtf8('Expand all directories'),
250 self._expandAllDirs)
251 self.dirMenu.addAction(self.trUtf8('Collapse all directories'),
252 self._collapseAllDirs)
253 self.dirMenu.addSeparator()
254 self.dirMenu.addAction(self.trUtf8('Configure...'), self._configure)
255
256 self.dirMultiMenu = QMenu(self)
257 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
258 self.dirMultiMenu.addAction(self.trUtf8('Compile all forms'),
259 self.__compileAllForms)
260 self.dirMultiMenu.addSeparator()
261 else:
262 if self.hooks["compileAllForms"] is not None:
263 self.dirMultiMenu.addAction(
264 self.hooksMenuEntries.get("compileAllForms",
265 self.trUtf8('Compile all forms')),
266 self.__compileAllForms)
267 self.dirMultiMenu.addSeparator()
268 self.dirMultiMenu.addAction(self.trUtf8('Add forms...'),
269 self.project.addUiFiles)
270 self.dirMultiMenu.addAction(self.trUtf8('Add forms directory...'),
271 self.project.addUiDir)
272 self.dirMultiMenu.addSeparator()
273 self.dirMultiMenu.addAction(self.trUtf8('Expand all directories'),
274 self._expandAllDirs)
275 self.dirMultiMenu.addAction(self.trUtf8('Collapse all directories'),
276 self._collapseAllDirs)
277 self.dirMultiMenu.addSeparator()
278 self.dirMultiMenu.addAction(self.trUtf8('Configure...'), self._configure)
279
280 self.connect(self.menu, SIGNAL('aboutToShow()'),
281 self.__showContextMenu)
282 self.connect(self.multiMenu, SIGNAL('aboutToShow()'),
283 self.__showContextMenuMulti)
284 self.connect(self.dirMenu, SIGNAL('aboutToShow()'),
285 self.__showContextMenuDir)
286 self.connect(self.dirMultiMenu, SIGNAL('aboutToShow()'),
287 self.__showContextMenuDirMulti)
288 self.connect(self.backMenu, SIGNAL('aboutToShow()'),
289 self.__showContextMenuBack)
290 self.mainMenu = self.menu
291
292 def _contextMenuRequested(self, coord):
293 """
294 Protected slot to show the context menu.
295
296 @param coord the position of the mouse pointer (QPoint)
297 """
298 if not self.project.isOpen():
299 return
300
301 try:
302 categories = self.getSelectedItemsCountCategorized(\
303 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem])
304 cnt = categories["sum"]
305 if cnt <= 1:
306 index = self.indexAt(coord)
307 if index.isValid():
308 self._selectSingleItem(index)
309 categories = self.getSelectedItemsCountCategorized(\
310 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem])
311 cnt = categories["sum"]
312
313 bfcnt = categories[unicode(ProjectBrowserFileItem)]
314 sdcnt = categories[unicode(ProjectBrowserSimpleDirectoryItem)]
315 if cnt > 1 and cnt == bfcnt:
316 self.multiMenu.popup(self.mapToGlobal(coord))
317 elif cnt > 1 and cnt == sdcnt:
318 self.dirMultiMenu.popup(self.mapToGlobal(coord))
319 else:
320 index = self.indexAt(coord)
321 if cnt == 1 and index.isValid():
322 if bfcnt == 1:
323 self.menu.popup(self.mapToGlobal(coord))
324 elif sdcnt == 1:
325 self.dirMenu.popup(self.mapToGlobal(coord))
326 else:
327 self.backMenu.popup(self.mapToGlobal(coord))
328 else:
329 self.backMenu.popup(self.mapToGlobal(coord))
330 except:
331 pass
332
333 def __showContextMenu(self):
334 """
335 Private slot called by the menu aboutToShow signal.
336 """
337 ProjectBaseBrowser._showContextMenu(self, self.menu)
338
339 self.emit(SIGNAL("showMenu"), "Main", self.menu)
340
341 def __showContextMenuMulti(self):
342 """
343 Private slot called by the multiMenu aboutToShow signal.
344 """
345 ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu)
346
347 self.emit(SIGNAL("showMenu"), "MainMulti", self.multiMenu)
348
349 def __showContextMenuDir(self):
350 """
351 Private slot called by the dirMenu aboutToShow signal.
352 """
353 ProjectBaseBrowser._showContextMenuDir(self, self.dirMenu)
354
355 self.emit(SIGNAL("showMenu"), "MainDir", self.dirMenu)
356
357 def __showContextMenuDirMulti(self):
358 """
359 Private slot called by the dirMultiMenu aboutToShow signal.
360 """
361 ProjectBaseBrowser._showContextMenuDirMulti(self, self.dirMultiMenu)
362
363 self.emit(SIGNAL("showMenu"), "MainDirMulti", self.dirMultiMenu)
364
365 def __showContextMenuBack(self):
366 """
367 Private slot called by the backMenu aboutToShow signal.
368 """
369 ProjectBaseBrowser._showContextMenuBack(self, self.backMenu)
370
371 self.emit(SIGNAL("showMenu"), "MainBack", self.backMenu)
372
373 def __addFormFiles(self):
374 """
375 Private method to add form files to the project.
376 """
377 itm = self.model().item(self.currentIndex())
378 if isinstance(itm, ProjectBrowserFileItem):
379 dn = os.path.dirname(itm.fileName())
380 elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
381 isinstance(itm, ProjectBrowserDirectoryItem):
382 dn = itm.dirName()
383 else:
384 dn = None
385 self.project.addFiles('form', dn)
386
387 def __addFormsDirectory(self):
388 """
389 Private method to add form files of a directory to the project.
390 """
391 itm = self.model().item(self.currentIndex())
392 if isinstance(itm, ProjectBrowserFileItem):
393 dn = os.path.dirname(itm.fileName())
394 elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
395 isinstance(itm, ProjectBrowserDirectoryItem):
396 dn = itm.dirName()
397 else:
398 dn = None
399 self.project.addDirectory('form', dn)
400
401 def __openFile(self):
402 """
403 Private slot to handle the Open menu action.
404
405 This uses the projects UI type to determine the Qt Designer
406 version to use.
407 """
408 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
409 version = 4
410 else:
411 version = 0
412
413 itmList = self.getSelectedItems()
414 for itm in itmList[:]:
415 try:
416 if isinstance(itm, ProjectBrowserFileItem):
417 self.emit(SIGNAL('designerFile'), itm.fileName(), version)
418 except:
419 pass
420
421 def __openFileInEditor(self):
422 """
423 Private slot to handle the Open in Editor menu action.
424 """
425 itmList = self.getSelectedItems()
426 for itm in itmList[:]:
427 self.emit(SIGNAL('sourceFile'), itm.fileName())
428
429 def _openItem(self):
430 """
431 Protected slot to handle the open popup menu entry.
432 """
433 itmList = self.getSelectedItems()
434
435 for itm in itmList:
436 if isinstance(itm, ProjectBrowserFileItem):
437 if itm.isDesignerFile():
438 self.emit(SIGNAL('designerFile'), itm.fileName())
439 else:
440 self.emit(SIGNAL('sourceFile'), itm.fileName())
441
442 def __UIPreview(self):
443 """
444 Private slot to handle the Preview menu action.
445 """
446 itmList = self.getSelectedItems()
447 self.emit(SIGNAL('uipreview'), itmList[0].fileName())
448
449 def __TRPreview(self):
450 """
451 Private slot to handle the Preview translations action.
452 """
453 fileNames = []
454 for itm in self.getSelectedItems():
455 fileNames.append(itm.fileName())
456 trfiles = self.project.pdata["TRANSLATIONS"][:]
457 trfiles.sort()
458 fileNames.extend([os.path.join(self.project.ppath, trfile) \
459 for trfile in trfiles \
460 if trfile.endswith('.qm')])
461 self.emit(SIGNAL('trpreview'), fileNames)
462
463 def __newForm(self):
464 """
465 Private slot to handle the New Form menu action.
466 """
467 itm = self.model().item(self.currentIndex())
468 if itm is None:
469 path = self.project.ppath
470 else:
471 try:
472 path = os.path.dirname(itm.fileName())
473 except AttributeError:
474 path = os.path.join(self.project.ppath, itm.data(0))
475
476 if self.hooks["newForm"] is not None:
477 self.hooks["newForm"](path)
478 else:
479 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
480 self.__newUiForm(path)
481
482 def __newUiForm(self, path):
483 """
484 Private slot to handle the New Form menu action for Qt-related projects.
485
486 @param path full directory path for the new form file (string)
487 """
488 selectedForm, ok = QInputDialog.getItem(\
489 None,
490 self.trUtf8("New Form"),
491 self.trUtf8("Select a form type:"),
492 self.templateTypes4,
493 0, False)
494 if not ok:
495 # user pressed cancel
496 return
497
498 templateIndex = self.templateTypes4.index(selectedForm)
499 templateFile = os.path.join(getConfig('ericTemplatesDir'),
500 self.templates4[templateIndex])
501
502 fname, selectedFilter = QFileDialog.getSaveFileNameAndFilter(\
503 self,
504 self.trUtf8("New Form"),
505 path,
506 self.trUtf8("Qt User-Interface Files (*.ui);;All Files (*)"),
507 "",
508 QFileDialog.Options(QFileDialog.DontConfirmOverwrite))
509
510 if not fname:
511 # user aborted or didn't enter a filename
512 return
513
514 ext = QFileInfo(fname).suffix()
515 if not ext:
516 ex = selectedFilter.split("(*")[1].split(")")[0]
517 if ex:
518 fname += ex
519
520 if os.path.exists(fname):
521 res = QMessageBox.warning(self,
522 self.trUtf8("New Form"),
523 self.trUtf8("The file already exists! Overwrite it?"),
524 QMessageBox.StandardButtons(\
525 QMessageBox.No | \
526 QMessageBox.Yes),
527 QMessageBox.No)
528 if res != QMessageBox.Yes:
529 # user selected to not overwrite
530 return
531
532 try:
533 shutil.copy(templateFile, fname)
534 except IOError, e:
535 QMessageBox.critical(self,
536 self.trUtf8("New Form"),
537 self.trUtf8("<p>The new form file <b>{0}</b> could not be created.<br>"
538 "Problem: {1}</p>").format(fname, unicode(e)))
539 return
540
541 self.project.appendFile(fname)
542 self.emit(SIGNAL('designerFile'), fname)
543
544 def __deleteFile(self):
545 """
546 Private method to delete a form file from the project.
547 """
548 itmList = self.getSelectedItems()
549
550 files = []
551 fullNames = []
552 for itm in itmList:
553 fn2 = itm.fileName()
554 fullNames.append(fn2)
555 fn = fn2.replace(self.project.ppath + os.sep, '')
556 files.append(fn)
557
558 dlg = DeleteFilesConfirmationDialog(self.parent(),
559 self.trUtf8("Delete forms"),
560 self.trUtf8("Do you really want to delete these forms from the project?"),
561 files)
562
563 if dlg.exec_() == QDialog.Accepted:
564 for fn2, fn in zip(fullNames, files):
565 self.emit(SIGNAL('closeSourceWindow'), fn2)
566 self.project.deleteFile(fn)
567
568 ############################################################################
569 ## Methods to handle the various compile commands
570 ############################################################################
571
572 def __readStdout(self):
573 """
574 Private slot to handle the readyReadStandardOutput signal of the
575 pyuic/rbuic process.
576 """
577 if self.compileProc is None:
578 return
579 self.compileProc.setReadChannel(QProcess.StandardOutput)
580
581 while self.compileProc and self.compileProc.canReadLine():
582 self.buf += unicode(self.compileProc.readLine())
583
584 def __readStderr(self):
585 """
586 Private slot to handle the readyReadStandardError signal of the
587 pyuic/rbuic process.
588 """
589 if self.compileProc is None:
590 return
591
592 ioEncoding = str(Preferences.getSystem("IOEncoding"))
593
594 self.compileProc.setReadChannel(QProcess.StandardError)
595 while self.compileProc and self.compileProc.canReadLine():
596 s = self.uicompiler + ': '
597 error = unicode(self.compileProc.readLine(),
598 ioEncoding, 'replace')
599 s += error
600 self.emit(SIGNAL('appendStderr'), s)
601
602 def __compileUIDone(self, exitCode, exitStatus):
603 """
604 Private slot to handle the finished signal of the pyuic/rbuic process.
605
606 @param exitCode exit code of the process (integer)
607 @param exitStatus exit status of the process (QProcess.ExitStatus)
608 """
609 self.compileRunning = False
610 e4App().getObject("ViewManager").enableEditorsCheckFocusIn(True)
611 if exitStatus == QProcess.NormalExit and exitCode == 0 and self.buf:
612 ofn = os.path.join(self.project.ppath, self.compiledFile)
613 try:
614 f = open(ofn, "wb")
615 for line in self.buf.splitlines():
616 f.write(line.encode("utf8") + os.linesep)
617 f.close()
618 if self.compiledFile not in self.project.pdata["SOURCES"]:
619 self.project.appendFile(ofn)
620 if not self.noDialog:
621 QMessageBox.information(None,
622 self.trUtf8("Form Compilation"),
623 self.trUtf8("The compilation of the form file"
624 " was successful."))
625 except IOError, msg:
626 if not self.noDialog:
627 QMessageBox.information(None,
628 self.trUtf8("Form Compilation"),
629 self.trUtf8("<p>The compilation of the form file failed.</p>"
630 "<p>Reason: {0}</p>").format(unicode(msg)))
631 else:
632 if not self.noDialog:
633 QMessageBox.information(None,
634 self.trUtf8("Form Compilation"),
635 self.trUtf8("The compilation of the form file failed."))
636 self.compileProc = None
637
638 def __compileUI(self, fn, noDialog = False, progress = None):
639 """
640 Privat method to compile a .ui file to a .py/.rb file.
641
642 @param fn filename of the .ui file to be compiled
643 @param noDialog flag indicating silent operations
644 @param progress reference to the progress dialog
645 @return reference to the compile process (QProcess)
646 """
647 self.compileProc = QProcess()
648 args = []
649 self.buf = ""
650
651 if self.project.pdata["PROGLANGUAGE"][0] in ["Python", "Python3"]:
652 if self.project.getProjectType() in ["Qt4", "E4Plugin"]:
653 self.uicompiler = 'pyuic4'
654 if Utilities.isWindowsPlatform():
655 uic = self.uicompiler + '.bat'
656 else:
657 uic = self.uicompiler
658 elif self.project.getProjectType() == "PySide":
659 self.uicompiler = 'pyside-uic'
660 if Utilities.isWindowsPlatform():
661 uic = self.uicompiler + '.bat'
662 else:
663 uic = self.uicompiler
664 else:
665 return None
666 elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
667 if self.project.getProjectType() == "Qt4":
668 self.uicompiler = 'rbuic4'
669 if Utilities.isWindowsPlatform():
670 uic = self.uicompiler + '.exe'
671 else:
672 uic = self.uicompiler
673 else:
674 return None
675 else:
676 return None
677
678 ofn, ext = os.path.splitext(fn)
679 fn = os.path.join(self.project.ppath, fn)
680
681 if self.project.pdata["PROGLANGUAGE"][0] in ["Python", "Python3"]:
682 dirname, filename = os.path.split(ofn)
683 self.compiledFile = os.path.join(dirname, "Ui_" + filename + ".py")
684 args.append("-x")
685 elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
686 self.compiledFile = ofn + '.rb'
687 args.append('-x')
688
689 args.append(fn)
690 self.connect(self.compileProc, SIGNAL('finished(int, QProcess::ExitStatus)'),
691 self.__compileUIDone)
692 self.connect(self.compileProc, SIGNAL('readyReadStandardOutput()'),
693 self.__readStdout)
694 self.connect(self.compileProc, SIGNAL('readyReadStandardError()'),
695 self.__readStderr)
696
697 self.noDialog = noDialog
698 self.compileProc.start(uic, args)
699 procStarted = self.compileProc.waitForStarted()
700 if procStarted:
701 self.compileRunning = True
702 e4App().getObject("ViewManager").enableEditorsCheckFocusIn(False)
703 return self.compileProc
704 else:
705 self.compileRunning = False
706 if progress is not None:
707 progress.cancel()
708 QMessageBox.critical(self,
709 self.trUtf8('Process Generation Error'),
710 self.trUtf8(
711 'Could not start {0}.<br>'
712 'Ensure that it is in the search path.'
713 ).format(self.uicompiler))
714 return None
715
716 def __generateDialogCode(self):
717 """
718 Private method to generate dialog code for the form (Qt4 only)
719 """
720 itm = self.model().item(self.currentIndex())
721 fn = itm.fileName()
722
723 if self.hooks["generateDialogCode"] is not None:
724 self.hooks["generateDialogCode"](filename)
725 else:
726 from CreateDialogCodeDialog import CreateDialogCodeDialog
727
728 # change environment
729 sys.path.insert(0, self.project.getProjectPath())
730 cwd = os.getcwd()
731 os.chdir(os.path.dirname(os.path.abspath(fn)))
732
733 dlg = CreateDialogCodeDialog(fn, self.project, self)
734 if not dlg.initError():
735 dlg.exec_()
736
737 # reset the environment
738 os.chdir(cwd)
739 del sys.path[0]
740
741 def __compileForm(self):
742 """
743 Private method to compile a form to a source file.
744 """
745 itm = self.model().item(self.currentIndex())
746 fn2 = itm.fileName()
747 fn = fn2.replace(self.project.ppath + os.sep, '')
748 if self.hooks["compileForm"] is not None:
749 self.hooks["compileForm"](fn)
750 else:
751 self.__compileUI(fn)
752
753 def __compileAllForms(self):
754 """
755 Private method to compile all forms to source files.
756 """
757 if self.hooks["compileAllForms"] is not None:
758 self.hooks["compileAllForms"](self.project.pdata["FORMS"])
759 else:
760 numForms = len(self.project.pdata["FORMS"])
761 progress = QProgressDialog(self.trUtf8("Compiling forms..."),
762 self.trUtf8("Abort"), 0, numForms, self)
763 progress.setModal(True)
764 progress.setMinimumDuration(0)
765 i = 0
766
767 for fn in self.project.pdata["FORMS"]:
768 progress.setValue(i)
769 if progress.wasCanceled():
770 break
771
772 proc = self.__compileUI(fn, True, progress)
773 if proc is not None:
774 while proc.state() == QProcess.Running:
775 QApplication.processEvents()
776 QThread.msleep(300)
777 QApplication.processEvents()
778 else:
779 break
780 i += 1
781
782 progress.setValue(numForms)
783
784 def __compileSelectedForms(self):
785 """
786 Private method to compile selected forms to source files.
787 """
788 items = self.getSelectedItems()
789 files = [itm.fileName().replace(self.project.ppath + os.sep, '') \
790 for itm in items]
791
792 if self.hooks["compileSelectedForms"] is not None:
793 self.hooks["compileSelectedForms"](files)
794 else:
795 numForms = len(files)
796 progress = QProgressDialog(self.trUtf8("Compiling forms..."),
797 self.trUtf8("Abort"), 0, numForms, self)
798 progress.setModal(True)
799 progress.setMinimumDuration(0)
800 i = 0
801
802 for fn in files:
803 progress.setValue(i)
804 if progress.wasCanceled():
805 break
806
807 proc = self.__compileUI(fn, True, progress)
808 if proc is not None:
809 while proc.state() == QProcess.Running:
810 QApplication.processEvents()
811 QThread.msleep(300)
812 QApplication.processEvents()
813 else:
814 break
815 i += 1
816
817 progress.setValue(numForms)
818
819 def compileChangedForms(self):
820 """
821 Public method to compile all changed forms to source files.
822 """
823 if self.hooks["compileChangedForms"] is not None:
824 self.hooks["compileChangedForms"](self.project.pdata["FORMS"])
825 else:
826 if self.project.getProjectType() not in \
827 ["Qt4", "Qt4C", "E4Plugin", "PySide"]:
828 # ignore the request for non Qt projects
829 return
830
831 progress = QProgressDialog(self.trUtf8("Determining changed forms..."),
832 "", 0, 100)
833 progress.setMinimumDuration(0)
834 i = 0
835
836 # get list of changed forms
837 changedForms = []
838 progress.setMaximum(len(self.project.pdata["FORMS"]))
839 for fn in self.project.pdata["FORMS"]:
840 progress.setValue(i)
841 QApplication.processEvents()
842
843 ifn = os.path.join(self.project.ppath, fn)
844 if self.project.pdata["PROGLANGUAGE"][0] in ["Python", "Python3"]:
845 dirname, filename = os.path.split(os.path.splitext(ifn)[0])
846 ofn = os.path.join(dirname, "Ui_" + filename + ".py")
847 elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
848 ofn = os.path.splitext(ifn)[0] + '.rb'
849 if not os.path.exists(ofn) or \
850 os.stat(ifn).st_mtime > os.stat(ofn).st_mtime:
851 changedForms.append(fn)
852 i += 1
853 progress.setValue(i)
854 QApplication.processEvents()
855
856 if changedForms:
857 progress.setLabelText(self.trUtf8("Compiling changed forms..."))
858 progress.setMaximum(len(changedForms))
859 i = 0
860 progress.setValue(i)
861 QApplication.processEvents()
862 for fn in changedForms:
863 progress.setValue(i)
864 proc = self.__compileUI(fn, True, progress)
865 if proc is not None:
866 while proc.state() == QProcess.Running:
867 QApplication.processEvents()
868 QThread.msleep(300)
869 QApplication.processEvents()
870 else:
871 break
872 i += 1
873 progress.setValue(len(changedForms))
874 QApplication.processEvents()
875
876 def handlePreferencesChanged(self):
877 """
878 Public slot used to handle the preferencesChanged signal.
879 """
880 ProjectBaseBrowser.handlePreferencesChanged(self)
881
882 ############################################################################
883 ## Support for hooks below
884 ############################################################################
885
886 def _initHookMethods(self):
887 """
888 Protected method to initialize the hooks dictionary.
889
890 Supported hook methods are:
891 <ul>
892 <li>compileForm: takes filename as parameter</li>
893 <li>compileAllForms: takes list of filenames as parameter</li>
894 <li>compileSelectedForms: takes list of filenames as parameter</li>
895 <li>compileChangedForms: takes list of filenames as parameter</li>
896 <li>generateDialogCode: takes filename as parameter</li>
897 <li>newForm: takes full directory path of new file as parameter</li>
898 </ul>
899
900 <b>Note</b>: Filenames are relative to the project directory, if not
901 specified differently.
902 """
903 self.hooks = {
904 "compileForm" : None,
905 "compileAllForms" : None,
906 "compileChangedForms" : None,
907 "compileSelectedForms" : None,
908 "generateDialogCode" : None,
909 "newForm" : None,
910 }

eric ide

mercurial