Project/ProjectResourcesBrowser.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 resources 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 ProjectBrowserResourceType
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 ProjectResourcesBrowser(ProjectBaseBrowser):
33 """
34 A class used to display the resources 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 resources file in an editor
39 @signal closeSourceWindow(string) emitted after a file has been removed/deleted
40 from the project
41 @signal showMenu(string, QMenu) emitted when a menu is about to be shown. The name
42 of the menu and a reference to the menu are given.
43 """
44 RCFilenameFormatPython = "%s_rc.py"
45 RCFilenameFormatRuby = "%s_rc.rb"
46
47 def __init__(self, project, parent = None):
48 """
49 Constructor
50
51 @param project reference to the project object
52 @param parent parent widget of this browser (QWidget)
53 """
54 ProjectBaseBrowser.__init__(self, project, ProjectBrowserResourceType, parent)
55
56 self.selectedItemsFilter = \
57 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]
58
59 self.setWindowTitle(self.trUtf8('Resources'))
60
61 self.setWhatsThis(self.trUtf8(
62 """<b>Project Resources Browser</b>"""
63 """<p>This allows to easily see all resources contained in the current"""
64 """ project. Several actions can be executed via the context menu.</p>"""
65 ))
66
67 self.compileProc = None
68
69 def _createPopupMenus(self):
70 """
71 Protected overloaded method to generate the popup menu.
72 """
73 self.menuActions = []
74 self.multiMenuActions = []
75 self.dirMenuActions = []
76 self.dirMultiMenuActions = []
77
78 self.menu = QMenu(self)
79 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
80 self.menu.addAction(self.trUtf8('Compile resource'),
81 self.__compileResource)
82 self.menu.addAction(self.trUtf8('Compile all resources'),
83 self.__compileAllResources)
84 self.menu.addSeparator()
85 else:
86 if self.hooks["compileResource"] is not None:
87 self.menu.addAction(
88 self.hooksMenuEntries.get("compileResource",
89 self.trUtf8('Compile resource')),
90 self.__compileResource)
91 if self.hooks["compileAllResources"] is not None:
92 self.menu.addAction(
93 self.hooksMenuEntries.get("compileAllResources",
94 self.trUtf8('Compile all resources')),
95 self.__compileAllResources)
96 if self.hooks["compileResource"] is not None or \
97 self.hooks["compileAllResources"] is not None:
98 self.menu.addSeparator()
99 self.menu.addAction(self.trUtf8('Open'), self.__openFile)
100 self.menu.addSeparator()
101 act = self.menu.addAction(self.trUtf8('Rename file'), self._renameFile)
102 self.menuActions.append(act)
103 act = self.menu.addAction(self.trUtf8('Remove from project'), self._removeFile)
104 self.menuActions.append(act)
105 act = self.menu.addAction(self.trUtf8('Delete'), self.__deleteFile)
106 self.menuActions.append(act)
107 self.menu.addSeparator()
108 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
109 self.menu.addAction(self.trUtf8('New resource...'), self.__newResource)
110 else:
111 if self.hooks["newResource"] is not None:
112 self.menu.addAction(
113 self.hooksMenuEntries.get("newResource",
114 self.trUtf8('New resource...')), self.__newResource)
115 self.menu.addAction(self.trUtf8('Add resources...'), self.__addResourceFiles)
116 self.menu.addAction(self.trUtf8('Add resources directory...'),
117 self.__addResourcesDirectory)
118 self.menu.addSeparator()
119 self.menu.addAction(self.trUtf8('Copy Path to Clipboard'),
120 self._copyToClipboard)
121 self.menu.addSeparator()
122 self.menu.addAction(self.trUtf8('Expand all directories'),
123 self._expandAllDirs)
124 self.menu.addAction(self.trUtf8('Collapse all directories'),
125 self._collapseAllDirs)
126 self.menu.addSeparator()
127 self.menu.addAction(self.trUtf8('Configure...'), self._configure)
128
129 self.backMenu = QMenu(self)
130 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
131 self.backMenu.addAction(self.trUtf8('Compile all resources'),
132 self.__compileAllResources)
133 self.backMenu.addSeparator()
134 self.backMenu.addAction(self.trUtf8('New resource...'), self.__newResource)
135 else:
136 if self.hooks["compileAllResources"] is not None:
137 self.backMenu.addAction(
138 self.hooksMenuEntries.get("compileAllResources",
139 self.trUtf8('Compile all resources')),
140 self.__compileAllResources)
141 self.backMenu.addSeparator()
142 if self.hooks["newResource"] is not None:
143 self.backMenu.addAction(
144 self.hooksMenuEntries.get("newResource",
145 self.trUtf8('New resource...')), self.__newResource)
146 self.backMenu.addAction(self.trUtf8('Add resources...'),
147 self.project.addResourceFiles)
148 self.backMenu.addAction(self.trUtf8('Add resources directory...'),
149 self.project.addResourceDir)
150 self.backMenu.addSeparator()
151 self.backMenu.addAction(self.trUtf8('Expand all directories'),
152 self._expandAllDirs)
153 self.backMenu.addAction(self.trUtf8('Collapse all directories'),
154 self._collapseAllDirs)
155 self.backMenu.addSeparator()
156 self.backMenu.addAction(self.trUtf8('Configure...'), self._configure)
157 self.backMenu.setEnabled(False)
158
159 # create the menu for multiple selected files
160 self.multiMenu = QMenu(self)
161 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
162 act = self.multiMenu.addAction(self.trUtf8('Compile resources'),
163 self.__compileSelectedResources)
164 self.multiMenu.addSeparator()
165 else:
166 if self.hooks["compileSelectedResources"] is not None:
167 act = self.multiMenu.addAction(
168 self.hooksMenuEntries.get("compileSelectedResources",
169 self.trUtf8('Compile resources')),
170 self.__compileSelectedResources)
171 self.multiMenu.addSeparator()
172 self.multiMenu.addAction(self.trUtf8('Open'), self.__openFile)
173 self.multiMenu.addSeparator()
174 act = self.multiMenu.addAction(self.trUtf8('Remove from project'),
175 self._removeFile)
176 self.multiMenuActions.append(act)
177 act = self.multiMenu.addAction(self.trUtf8('Delete'), self.__deleteFile)
178 self.multiMenuActions.append(act)
179 self.multiMenu.addSeparator()
180 self.multiMenu.addAction(self.trUtf8('Expand all directories'),
181 self._expandAllDirs)
182 self.multiMenu.addAction(self.trUtf8('Collapse all directories'),
183 self._collapseAllDirs)
184 self.multiMenu.addSeparator()
185 self.multiMenu.addAction(self.trUtf8('Configure...'), self._configure)
186
187 self.dirMenu = QMenu(self)
188 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
189 self.dirMenu.addAction(self.trUtf8('Compile all resources'),
190 self.__compileAllResources)
191 self.dirMenu.addSeparator()
192 else:
193 if self.hooks["compileAllResources"] is not None:
194 self.dirMenu.addAction(
195 self.hooksMenuEntries.get("compileAllResources",
196 self.trUtf8('Compile all resources')),
197 self.__compileAllResources)
198 self.dirMenu.addSeparator()
199 act = self.dirMenu.addAction(self.trUtf8('Remove from project'), self._removeDir)
200 self.dirMenuActions.append(act)
201 self.dirMenu.addSeparator()
202 self.dirMenu.addAction(self.trUtf8('New resource...'), self.__newResource)
203 self.dirMenu.addAction(self.trUtf8('Add resources...'), self.__addResourceFiles)
204 self.dirMenu.addAction(self.trUtf8('Add resources directory...'),
205 self.__addResourcesDirectory)
206 self.dirMenu.addSeparator()
207 self.dirMenu.addAction(self.trUtf8('Copy Path to Clipboard'),
208 self._copyToClipboard)
209 self.dirMenu.addSeparator()
210 self.dirMenu.addAction(self.trUtf8('Expand all directories'),
211 self._expandAllDirs)
212 self.dirMenu.addAction(self.trUtf8('Collapse all directories'),
213 self._collapseAllDirs)
214 self.dirMenu.addSeparator()
215 self.dirMenu.addAction(self.trUtf8('Configure...'), self._configure)
216
217 self.dirMultiMenu = QMenu(self)
218 if self.project.getProjectType() in ["Qt4", "E4Plugin", "PySide"]:
219 self.dirMultiMenu.addAction(self.trUtf8('Compile all resources'),
220 self.__compileAllResources)
221 self.dirMultiMenu.addSeparator()
222 else:
223 if self.hooks["compileAllResources"] is not None:
224 self.dirMultiMenu.addAction(
225 self.hooksMenuEntries.get("compileAllResources",
226 self.trUtf8('Compile all resources')),
227 self.__compileAllResources)
228 self.dirMultiMenu.addSeparator()
229 self.dirMultiMenu.addAction(self.trUtf8('Add resources...'),
230 self.project.addResourceFiles)
231 self.dirMultiMenu.addAction(self.trUtf8('Add resources directory...'),
232 self.project.addResourceDir)
233 self.dirMultiMenu.addSeparator()
234 self.dirMultiMenu.addAction(self.trUtf8('Expand all directories'),
235 self._expandAllDirs)
236 self.dirMultiMenu.addAction(self.trUtf8('Collapse all directories'),
237 self._collapseAllDirs)
238 self.dirMultiMenu.addSeparator()
239 self.dirMultiMenu.addAction(self.trUtf8('Configure...'), self._configure)
240
241 self.connect(self.menu, SIGNAL('aboutToShow()'),
242 self.__showContextMenu)
243 self.connect(self.multiMenu, SIGNAL('aboutToShow()'),
244 self.__showContextMenuMulti)
245 self.connect(self.dirMenu, SIGNAL('aboutToShow()'),
246 self.__showContextMenuDir)
247 self.connect(self.dirMultiMenu, SIGNAL('aboutToShow()'),
248 self.__showContextMenuDirMulti)
249 self.connect(self.backMenu, SIGNAL('aboutToShow()'),
250 self.__showContextMenuBack)
251 self.mainMenu = self.menu
252
253 def _contextMenuRequested(self, coord):
254 """
255 Protected slot to show the context menu.
256
257 @param coord the position of the mouse pointer (QPoint)
258 """
259 if not self.project.isOpen():
260 return
261
262 try:
263 categories = self.getSelectedItemsCountCategorized(\
264 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem])
265 cnt = categories["sum"]
266 if cnt <= 1:
267 index = self.indexAt(coord)
268 if index.isValid():
269 self._selectSingleItem(index)
270 categories = self.getSelectedItemsCountCategorized(\
271 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem])
272 cnt = categories["sum"]
273
274 bfcnt = categories[unicode(ProjectBrowserFileItem)]
275 sdcnt = categories[unicode(ProjectBrowserSimpleDirectoryItem)]
276 if cnt > 1 and cnt == bfcnt:
277 self.multiMenu.popup(self.mapToGlobal(coord))
278 elif cnt > 1 and cnt == sdcnt:
279 self.dirMultiMenu.popup(self.mapToGlobal(coord))
280 else:
281 index = self.indexAt(coord)
282 if cnt == 1 and index.isValid():
283 if bfcnt == 1:
284 self.menu.popup(self.mapToGlobal(coord))
285 elif sdcnt == 1:
286 self.dirMenu.popup(self.mapToGlobal(coord))
287 else:
288 self.backMenu.popup(self.mapToGlobal(coord))
289 else:
290 self.backMenu.popup(self.mapToGlobal(coord))
291 except:
292 pass
293
294 def __showContextMenu(self):
295 """
296 Private slot called by the menu aboutToShow signal.
297 """
298 ProjectBaseBrowser._showContextMenu(self, self.menu)
299
300 self.emit(SIGNAL("showMenu"), "Main", self.menu)
301
302 def __showContextMenuMulti(self):
303 """
304 Private slot called by the multiMenu aboutToShow signal.
305 """
306 ProjectBaseBrowser._showContextMenuMulti(self, self.multiMenu)
307
308 self.emit(SIGNAL("showMenu"), "MainMulti", self.multiMenu)
309
310 def __showContextMenuDir(self):
311 """
312 Private slot called by the dirMenu aboutToShow signal.
313 """
314 ProjectBaseBrowser._showContextMenuDir(self, self.dirMenu)
315
316 self.emit(SIGNAL("showMenu"), "MainDir", self.dirMenu)
317
318 def __showContextMenuDirMulti(self):
319 """
320 Private slot called by the dirMultiMenu aboutToShow signal.
321 """
322 ProjectBaseBrowser._showContextMenuDirMulti(self, self.dirMultiMenu)
323
324 self.emit(SIGNAL("showMenu"), "MainDirMulti", self.dirMultiMenu)
325
326 def __showContextMenuBack(self):
327 """
328 Private slot called by the backMenu aboutToShow signal.
329 """
330 ProjectBaseBrowser._showContextMenuBack(self, self.backMenu)
331
332 self.emit(SIGNAL("showMenu"), "MainBack", self.backMenu)
333
334 def __addResourceFiles(self):
335 """
336 Private method to add resource files to the project.
337 """
338 itm = self.model().item(self.currentIndex())
339 if isinstance(itm, ProjectBrowserFileItem):
340 dn = os.path.dirname(itm.fileName())
341 elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
342 isinstance(itm, ProjectBrowserDirectoryItem):
343 dn = itm.dirName()
344 else:
345 dn = None
346 self.project.addFiles('resource', dn)
347
348 def __addResourcesDirectory(self):
349 """
350 Private method to add resource files of a directory to the project.
351 """
352 itm = self.model().item(self.currentIndex())
353 if isinstance(itm, ProjectBrowserFileItem):
354 dn = os.path.dirname(itm.fileName())
355 elif isinstance(itm, ProjectBrowserSimpleDirectoryItem) or \
356 isinstance(itm, ProjectBrowserDirectoryItem):
357 dn = itm.dirName()
358 else:
359 dn = None
360 self.project.addDirectory('resource', dn)
361
362 def _openItem(self):
363 """
364 Protected slot to handle the open popup menu entry.
365 """
366 self.__openFile()
367
368 def __openFile(self):
369 """
370 Private slot to handle the Open menu action.
371 """
372 itmList = self.getSelectedItems()
373 for itm in itmList[:]:
374 if isinstance(itm, ProjectBrowserFileItem):
375 self.emit(SIGNAL('sourceFile'), itm.fileName())
376
377 def __newResource(self):
378 """
379 Private slot to handle the New Resource menu action.
380 """
381 itm = self.model().item(self.currentIndex())
382 if itm is None:
383 path = self.project.ppath
384 else:
385 try:
386 path = os.path.dirname(itm.fileName())
387 except AttributeError:
388 path = os.path.join(self.project.ppath, itm.data(0))
389
390 if self.hooks["newResource"] is not None:
391 self.hooks["newResource"](path)
392 else:
393 fname, selectedFilter = QFileDialog.getSaveFileNameAndFilter(\
394 self,
395 self.trUtf8("New Resource"),
396 path,
397 self.trUtf8("Qt Resource Files (*.qrc)"),
398 "",
399 QFileDialog.Options(QFileDialog.DontConfirmOverwrite))
400
401 if not fname:
402 # user aborted or didn't enter a filename
403 return
404
405 ext = QFileInfo(fname).suffix()
406 if not ext:
407 ex = selectedFilter.split("(*")[1].split(")")[0]
408 if ex:
409 fname += ex
410
411 if os.path.exists(fname):
412 res = QMessageBox.warning(self,
413 self.trUtf8("New Resource"),
414 self.trUtf8("The file already exists! Overwrite it?"),
415 QMessageBox.StandardButtons(\
416 QMessageBox.No | \
417 QMessageBox.Yes),
418 QMessageBox.No)
419 if res != QMessageBox.Yes:
420 # user selected to not overwrite
421 return
422
423 try:
424 rcfile = open(fname, 'wb')
425 rcfile.write('<!DOCTYPE RCC>\n')
426 rcfile.write('<RCC version="1.0">\n')
427 rcfile.write('<qresource>\n')
428 rcfile.write('</qresource>\n')
429 rcfile.write('</RCC>\n')
430 rcfile.close()
431 except IOError, e:
432 QMessageBox.critical(self,
433 self.trUtf8("New Resource"),
434 self.trUtf8("<p>The new resource file <b>{0}</b> could not be created.<br>"
435 "Problem: {1}</p>").format(fname, unicode(e)))
436 return
437
438 self.project.appendFile(fname)
439 self.emit(SIGNAL('sourceFile'), fname)
440
441 def __deleteFile(self):
442 """
443 Private method to delete a resource file from the project.
444 """
445 itmList = self.getSelectedItems()
446
447 files = []
448 fullNames = []
449 for itm in itmList:
450 fn2 = itm.fileName()
451 fullNames.append(fn2)
452 fn = fn2.replace(self.project.ppath+os.sep, '')
453 files.append(fn)
454
455 dlg = DeleteFilesConfirmationDialog(self.parent(),
456 self.trUtf8("Delete resources"),
457 self.trUtf8("Do you really want to delete these resources from the project?"),
458 files)
459
460 if dlg.exec_() == QDialog.Accepted:
461 for fn2, fn in zip(fullNames, files):
462 self.emit(SIGNAL('closeSourceWindow'), fn2)
463 self.project.deleteFile(fn)
464
465 ############################################################################
466 ## Methods to handle the various compile commands
467 ############################################################################
468
469 def __readStdout(self):
470 """
471 Private slot to handle the readyReadStandardOutput signal of the
472 pyrcc4/rbrcc process.
473 """
474 if self.compileProc is None:
475 return
476 self.compileProc.setReadChannel(QProcess.StandardOutput)
477
478 while self.compileProc and self.compileProc.canReadLine():
479 self.buf += unicode(self.compileProc.readLine())
480
481 def __readStderr(self):
482 """
483 Private slot to handle the readyReadStandardError signal of the
484 pyrcc4/rbrcc process.
485 """
486 if self.compileProc is None:
487 return
488
489 ioEncoding = str(Preferences.getSystem("IOEncoding"))
490
491 self.compileProc.setReadChannel(QProcess.StandardError)
492 while self.compileProc and self.compileProc.canReadLine():
493 s = self.rccCompiler + ': '
494 error = unicode(self.compileProc.readLine(),
495 ioEncoding, 'replace')
496 s += error
497 self.emit(SIGNAL('appendStderr'), s)
498
499 def __compileQRCDone(self, exitCode, exitStatus):
500 """
501 Private slot to handle the finished signal of the compile process.
502
503 @param exitCode exit code of the process (integer)
504 @param exitStatus exit status of the process (QProcess.ExitStatus)
505 """
506 self.compileRunning = False
507 e4App().getObject("ViewManager").enableEditorsCheckFocusIn(True)
508 if exitStatus == QProcess.NormalExit and exitCode == 0 and self.buf:
509 ofn = os.path.join(self.project.ppath, self.compiledFile)
510 try:
511 f = open(ofn, "wb")
512 for line in self.buf.splitlines():
513 f.write(line.encode("utf8") + os.linesep)
514 f.close()
515 if self.compiledFile not in self.project.pdata["SOURCES"]:
516 self.project.appendFile(ofn)
517 if not self.noDialog:
518 QMessageBox.information(None,
519 self.trUtf8("Resource Compilation"),
520 self.trUtf8("The compilation of the resource file"
521 " was successful."))
522 except IOError, msg:
523 if not self.noDialog:
524 QMessageBox.information(None,
525 self.trUtf8("Resource Compilation"),
526 self.trUtf8("<p>The compilation of the resource file failed.</p>"
527 "<p>Reason: {0}</p>").format(unicode(msg)))
528 else:
529 if not self.noDialog:
530 QMessageBox.information(None,
531 self.trUtf8("Resource Compilation"),
532 self.trUtf8("The compilation of the resource file failed."))
533 self.compileProc = None
534
535 def __compileQRC(self, fn, noDialog = False, progress = None):
536 """
537 Privat method to compile a .qrc file to a .py file.
538
539 @param fn filename of the .ui file to be compiled
540 @param noDialog flag indicating silent operations
541 @param progress reference to the progress dialog
542 @return reference to the compile process (QProcess)
543 """
544 self.compileProc = QProcess()
545 args = []
546 self.buf = ""
547
548 if self.project.pdata["PROGLANGUAGE"][0] in ["Python", "Python3"]:
549 if self.project.getProjectType() in ["Qt4", "E4Plugin"]:
550 self.rccCompiler = 'pyrcc4'
551 if PYQT_VERSION >= 0x040500:
552 if self.project.pdata["PROGLANGUAGE"][0] == "Python":
553 args.append("-py2")
554 else:
555 args.append("-py3")
556 elif self.project.getProjectType() == "PySide":
557 self.rccCompiler = 'pyside-rcc4'
558 if self.project.pdata["PROGLANGUAGE"][0] == "Python":
559 args.append("-py2")
560 else:
561 args.append("-py3")
562 else:
563 return None
564 elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
565 if self.project.getProjectType() == "Qt4":
566 self.rccCompiler = 'rbrcc'
567 else:
568 return None
569 else:
570 return None
571
572 rcc = self.rccCompiler
573 if Utilities.isWindowsPlatform():
574 rcc = rcc + '.exe'
575
576 ofn, ext = os.path.splitext(fn)
577 fn = os.path.join(self.project.ppath, fn)
578
579 dirname, filename = os.path.split(ofn)
580 if self.project.pdata["PROGLANGUAGE"][0] in ["Python", "Python3"]:
581 self.compiledFile = os.path.join(dirname,
582 self.RCFilenameFormatPython % filename)
583 elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
584 self.compiledFile = os.path.join(
585 dirname, self.RCFilenameFormatRuby % filename)
586
587 args.append(fn)
588 self.connect(self.compileProc, SIGNAL('finished(int, QProcess::ExitStatus)'),
589 self.__compileQRCDone)
590 self.connect(self.compileProc, SIGNAL('readyReadStandardOutput()'),
591 self.__readStdout)
592 self.connect(self.compileProc, SIGNAL('readyReadStandardError()'),
593 self.__readStderr)
594
595 self.noDialog = noDialog
596 self.compileProc.start(rcc, args)
597 procStarted = self.compileProc.waitForStarted()
598 if procStarted:
599 self.compileRunning = True
600 e4App().getObject("ViewManager").enableEditorsCheckFocusIn(False)
601 return self.compileProc
602 else:
603 self.compileRunning = False
604 if progress is not None:
605 progress.cancel()
606 QMessageBox.critical(self,
607 self.trUtf8('Process Generation Error'),
608 self.trUtf8(
609 'Could not start {0}.<br>'
610 'Ensure that it is in the search path.'
611 ).format(self.rccCompiler))
612 return None
613
614 def __compileResource(self):
615 """
616 Private method to compile a resource to a source file.
617 """
618 itm = self.model().item(self.currentIndex())
619 fn2 = itm.fileName()
620 fn = fn2.replace(self.project.ppath+os.sep, '')
621 if self.hooks["compileResource"] is not None:
622 self.hooks["compileResource"](fn)
623 else:
624 self.__compileQRC(fn)
625
626 def __compileAllResources(self):
627 """
628 Private method to compile all resources to source files.
629 """
630 if self.hooks["compileAllResources"] is not None:
631 self.hooks["compileAllResources"](self.project.pdata["RESOURCES"])
632 else:
633 numResources = len(self.project.pdata["RESOURCES"])
634 progress = QProgressDialog(self.trUtf8("Compiling resources..."),
635 self.trUtf8("Abort"), 0, numResources, self)
636 progress.setModal(True)
637 progress.setMinimumDuration(0)
638 i = 0
639
640 for fn in self.project.pdata["RESOURCES"]:
641 progress.setValue(i)
642 if progress.wasCanceled():
643 break
644 proc = self.__compileQRC(fn, True, progress)
645 if proc is not None:
646 while proc.state() == QProcess.Running:
647 QApplication.processEvents()
648 QThread.msleep(300)
649 QApplication.processEvents()
650 else:
651 break
652 i += 1
653
654 progress.setValue(numResources)
655
656 def __compileSelectedResources(self):
657 """
658 Private method to compile selected resources to source files.
659 """
660 items = self.getSelectedItems()
661 files = [itm.fileName().replace(self.project.ppath+os.sep, '') \
662 for itm in items]
663
664 if self.hooks["compileSelectedResources"] is not None:
665 self.hooks["compileSelectedResources"](files)
666 else:
667 numResources = len(files)
668 progress = QProgressDialog(self.trUtf8("Compiling resources..."),
669 self.trUtf8("Abort"), 0, numResources, self)
670 progress.setModal(True)
671 progress.setMinimumDuration(0)
672 i = 0
673
674 for fn in files:
675 progress.setValue(i)
676 if progress.wasCanceled():
677 break
678 if not fn.endswith('.ui.h'):
679 proc = self.__compileQRC(fn, True, progress)
680 if proc is not None:
681 while proc.state() == QProcess.Running:
682 QApplication.processEvents()
683 QThread.msleep(300)
684 QApplication.processEvents()
685 else:
686 break
687 i += 1
688
689 progress.setValue(numResources)
690
691 def __checkResourcesNewer(self, filename, mtime):
692 """
693 Private method to check, if any file referenced in a resource
694 file is newer than a given time.
695
696 @param filename filename of the resource file (string)
697 @param mtime modification time to check against
698 @return flag indicating some file is newer (boolean)
699 """
700 try:
701 f = open(filename, "r")
702 buf = f.read()
703 f.close()
704 except IOError:
705 return False
706
707 lbuf = ""
708 for line in buf.splitlines():
709 line = line.strip()
710 if line.lower().startswith("<file>") or line.lower().startswith("<file "):
711 lbuf = line
712 elif lbuf:
713 lbuf = "%s%s" % (lbuf, line)
714 if lbuf.lower().endswith("</file>"):
715 rfile = lbuf.split(">", 1)[1].split("<", 1)[0]
716 if not os.path.isabs(rfile):
717 rfile = os.path.join(self.project.ppath, rfile)
718 if os.path.exists(rfile) and \
719 os.stat(rfile).st_mtime > mtime:
720 return True
721
722 lbuf = ""
723
724 return False
725
726 def compileChangedResources(self):
727 """
728 Public method to compile all changed resources to source files.
729 """
730 if self.hooks["compileChangedResources"] is not None:
731 self.hooks["compileChangedResources"](self.project.pdata["RESOURCES"])
732 else:
733 progress = QProgressDialog(self.trUtf8("Determining changed resources..."),
734 "", 0, 100)
735 progress.setMinimumDuration(0)
736 i = 0
737
738 # get list of changed resources
739 changedResources = []
740 progress.setMaximum(len(self.project.pdata["RESOURCES"]))
741 for fn in self.project.pdata["RESOURCES"]:
742 progress.setValue(i)
743 QApplication.processEvents()
744 ifn = os.path.join(self.project.ppath, fn)
745 if self.project.pdata["PROGLANGUAGE"][0] in ["Python", "Python3"]:
746 dirname, filename = os.path.split(os.path.splitext(ifn)[0])
747 ofn = os.path.join(dirname,
748 self.RCFilenameFormatPython % filename)
749 elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
750 dirname, filename = os.path.split(os.path.splitext(ifn)[0])
751 ofn = os.path.join(dirname,
752 self.RCFilenameFormatRuby % filename)
753 else:
754 return
755 if not os.path.exists(ofn) or \
756 os.stat(ifn).st_mtime > os.stat(ofn).st_mtime:
757 changedResources.append(fn)
758 elif self.__checkResourcesNewer(ifn, os.stat(ofn).st_mtime):
759 changedResources.append(fn)
760 i += 1
761 progress.setValue(i)
762 QApplication.processEvents()
763
764 if changedResources:
765 progress.setLabelText(self.trUtf8("Compiling changed resources..."))
766 progress.setMaximum(len(changedResources))
767 i = 0
768 progress.setValue(i)
769 QApplication.processEvents()
770 for fn in changedResources:
771 progress.setValue(i)
772 proc = self.__compileQRC(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 progress.setValue(len(changedResources))
782 QApplication.processEvents()
783
784 def handlePreferencesChanged(self):
785 """
786 Public slot used to handle the preferencesChanged signal.
787 """
788 ProjectBaseBrowser.handlePreferencesChanged(self)
789
790 ############################################################################
791 ## Support for hooks below
792 ############################################################################
793
794 def _initHookMethods(self):
795 """
796 Protected method to initialize the hooks dictionary.
797
798 Supported hook methods are:
799 <ul>
800 <li>compileResource: takes filename as parameter</li>
801 <li>compileAllResources: takes list of filenames as parameter</li>
802 <li>compileChangedResources: takes list of filenames as parameter</li>
803 <li>compileSelectedResources: takes list of all form filenames as parameter</li>
804 <li>newResource: takes full directory path of new file as parameter</li>
805 </ul>
806
807 <b>Note</b>: Filenames are relative to the project directory, if not
808 specified differently.
809 """
810 self.hooks = {
811 "compileResource" : None,
812 "compileAllResources" : None,
813 "compileChangedResources" : None,
814 "compileSelectedResources" : None,
815 "newResource" : None,
816 }

eric ide

mercurial