eric6/Tools/TRPreviewer.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2004 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the TR Previewer main window.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13
14 from PyQt5.QtCore import QDir, QTimer, QFileInfo, pyqtSignal, QEvent, QSize, \
15 QTranslator, QObject, Qt, QCoreApplication
16 from PyQt5.QtGui import QKeySequence
17 from PyQt5.QtWidgets import QSizePolicy, QSpacerItem, QWidget, QHBoxLayout, \
18 QWhatsThis, QMdiArea, qApp, QApplication, QComboBox, QVBoxLayout, \
19 QAction, QLabel
20 from PyQt5 import uic
21
22
23 from E5Gui import E5MessageBox, E5FileDialog
24 from E5Gui.E5MainWindow import E5MainWindow
25
26 import UI.PixmapCache
27 import UI.Config
28
29 import Preferences
30
31
32 noTranslationName = QCoreApplication.translate(
33 "TRPreviewer", "<No translation>")
34
35
36 class TRPreviewer(E5MainWindow):
37 """
38 Class implementing the UI Previewer main window.
39 """
40 def __init__(self, filenames=None, parent=None, name=None):
41 """
42 Constructor
43
44 @param filenames filenames of form and/or translation files to load
45 @param parent parent widget of this window (QWidget)
46 @param name name of this window (string)
47 """
48 self.mainWidget = None
49 self.currentFile = QDir.currentPath()
50
51 super(TRPreviewer, self).__init__(parent)
52 if not name:
53 self.setObjectName("TRPreviewer")
54 else:
55 self.setObjectName(name)
56
57 self.setStyle(Preferences.getUI("Style"),
58 Preferences.getUI("StyleSheet"))
59
60 self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint()))
61 self.statusBar()
62
63 self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
64 self.setWindowTitle(self.tr("Translations Previewer"))
65
66 self.cw = QWidget(self)
67 self.cw.setObjectName("qt_central_widget")
68
69 self.TRPreviewerLayout = QVBoxLayout(self.cw)
70 self.TRPreviewerLayout.setContentsMargins(6, 6, 6, 6)
71 self.TRPreviewerLayout.setSpacing(6)
72 self.TRPreviewerLayout.setObjectName("TRPreviewerLayout")
73
74 self.languageLayout = QHBoxLayout()
75 self.languageLayout.setContentsMargins(0, 0, 0, 0)
76 self.languageLayout.setSpacing(6)
77 self.languageLayout.setObjectName("languageLayout")
78
79 self.languageLabel = QLabel(
80 self.tr("Select language file"), self.cw)
81 self.languageLabel.setObjectName("languageLabel")
82 self.languageLayout.addWidget(self.languageLabel)
83
84 self.languageCombo = QComboBox(self.cw)
85 self.languageCombo.setObjectName("languageCombo")
86 self.languageCombo.setEditable(False)
87 self.languageCombo.setToolTip(self.tr("Select language file"))
88 self.languageCombo.setSizePolicy(
89 QSizePolicy.Expanding, QSizePolicy.Preferred)
90 self.languageLayout.addWidget(self.languageCombo)
91
92 languageSpacer = QSpacerItem(
93 40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
94 self.languageLayout.addItem(languageSpacer)
95 self.TRPreviewerLayout.addLayout(self.languageLayout)
96
97 self.preview = WidgetArea(self.cw)
98 self.preview.setObjectName("preview")
99 self.TRPreviewerLayout.addWidget(self.preview)
100 self.preview.lastWidgetClosed.connect(self.__updateActions)
101
102 self.setCentralWidget(self.cw)
103
104 self.languageCombo.activated[str].connect(self.setTranslation)
105
106 self.translations = TranslationsDict(self.languageCombo, self)
107 self.translations.translationChanged.connect(
108 self.preview.rebuildWidgets)
109
110 self.__initActions()
111 self.__initMenus()
112 self.__initToolbars()
113
114 self.__updateActions()
115
116 # fire up the single application server
117 from .TRSingleApplication import TRSingleApplicationServer
118 self.SAServer = TRSingleApplicationServer(self)
119 self.SAServer.loadForm.connect(self.preview.loadWidget)
120 self.SAServer.loadTranslation.connect(self.translations.add)
121
122 # defere loading of a UI file until we are shown
123 self.filesToLoad = [] if filenames is None else filenames[:]
124
125 def show(self):
126 """
127 Public slot to show this dialog.
128
129 This overloaded slot loads a UI file to be previewed after
130 the main window has been shown. This way, previewing a dialog
131 doesn't interfere with showing the main window.
132 """
133 super(TRPreviewer, self).show()
134 if self.filesToLoad:
135 filenames, self.filesToLoad = (self.filesToLoad[:], [])
136 first = True
137 for fn in filenames:
138 fi = QFileInfo(fn)
139 if fi.suffix().lower() == 'ui':
140 self.preview.loadWidget(fn)
141 elif fi.suffix().lower() == 'qm':
142 self.translations.add(fn, first)
143 first = False
144
145 self.__updateActions()
146
147 def closeEvent(self, event):
148 """
149 Protected event handler for the close event.
150
151 @param event close event (QCloseEvent)
152 """
153 if self.SAServer is not None:
154 self.SAServer.shutdown()
155 self.SAServer = None
156 event.accept()
157
158 def __initActions(self):
159 """
160 Private method to define the user interface actions.
161 """
162 self.openUIAct = QAction(
163 UI.PixmapCache.getIcon("openUI.png"),
164 self.tr('&Open UI Files...'), self)
165 self.openUIAct.setStatusTip(self.tr('Open UI files for display'))
166 self.openUIAct.setWhatsThis(self.tr(
167 """<b>Open UI Files</b>"""
168 """<p>This opens some UI files for display.</p>"""
169 ))
170 self.openUIAct.triggered.connect(self.__openWidget)
171
172 self.openQMAct = QAction(
173 UI.PixmapCache.getIcon("openQM.png"),
174 self.tr('Open &Translation Files...'), self)
175 self.openQMAct.setStatusTip(self.tr(
176 'Open Translation files for display'))
177 self.openQMAct.setWhatsThis(self.tr(
178 """<b>Open Translation Files</b>"""
179 """<p>This opens some translation files for display.</p>"""
180 ))
181 self.openQMAct.triggered.connect(self.__openTranslation)
182
183 self.reloadAct = QAction(
184 UI.PixmapCache.getIcon("reload.png"),
185 self.tr('&Reload Translations'), self)
186 self.reloadAct.setStatusTip(self.tr(
187 'Reload the loaded translations'))
188 self.reloadAct.setWhatsThis(self.tr(
189 """<b>Reload Translations</b>"""
190 """<p>This reloads the translations for the loaded"""
191 """ languages.</p>"""
192 ))
193 self.reloadAct.triggered.connect(self.translations.reload)
194
195 self.exitAct = QAction(
196 UI.PixmapCache.getIcon("exit.png"), self.tr('&Quit'), self)
197 self.exitAct.setShortcut(QKeySequence(
198 self.tr("Ctrl+Q", "File|Quit")))
199 self.exitAct.setStatusTip(self.tr('Quit the application'))
200 self.exitAct.setWhatsThis(self.tr(
201 """<b>Quit</b>"""
202 """<p>Quit the application.</p>"""
203 ))
204 self.exitAct.triggered.connect(qApp.closeAllWindows)
205
206 self.whatsThisAct = QAction(
207 UI.PixmapCache.getIcon("whatsThis.png"),
208 self.tr('&What\'s This?'), self)
209 self.whatsThisAct.setShortcut(QKeySequence(self.tr("Shift+F1")))
210 self.whatsThisAct.setStatusTip(self.tr('Context sensitive help'))
211 self.whatsThisAct.setWhatsThis(self.tr(
212 """<b>Display context sensitive help</b>"""
213 """<p>In What's This? mode, the mouse cursor shows an arrow"""
214 """ with a question mark, and you can click on the interface"""
215 """ elements to get a short description of what they do and"""
216 """ how to use them. In dialogs, this feature can be accessed"""
217 """ using the context help button in the titlebar.</p>"""
218 ))
219 self.whatsThisAct.triggered.connect(self.__whatsThis)
220
221 self.aboutAct = QAction(self.tr('&About'), self)
222 self.aboutAct.setStatusTip(self.tr(
223 'Display information about this software'))
224 self.aboutAct.setWhatsThis(self.tr(
225 """<b>About</b>"""
226 """<p>Display some information about this software.</p>"""
227 ))
228 self.aboutAct.triggered.connect(self.__about)
229
230 self.aboutQtAct = QAction(self.tr('About &Qt'), self)
231 self.aboutQtAct.setStatusTip(
232 self.tr('Display information about the Qt toolkit'))
233 self.aboutQtAct.setWhatsThis(self.tr(
234 """<b>About Qt</b>"""
235 """<p>Display some information about the Qt toolkit.</p>"""
236 ))
237 self.aboutQtAct.triggered.connect(self.__aboutQt)
238
239 self.tileAct = QAction(self.tr('&Tile'), self)
240 self.tileAct.setStatusTip(self.tr('Tile the windows'))
241 self.tileAct.setWhatsThis(self.tr(
242 """<b>Tile the windows</b>"""
243 """<p>Rearrange and resize the windows so that they are"""
244 """ tiled.</p>"""
245 ))
246 self.tileAct.triggered.connect(self.preview.tileSubWindows)
247
248 self.cascadeAct = QAction(self.tr('&Cascade'), self)
249 self.cascadeAct.setStatusTip(self.tr('Cascade the windows'))
250 self.cascadeAct.setWhatsThis(self.tr(
251 """<b>Cascade the windows</b>"""
252 """<p>Rearrange and resize the windows so that they are"""
253 """ cascaded.</p>"""
254 ))
255 self.cascadeAct.triggered.connect(self.preview.cascadeSubWindows)
256
257 self.closeAct = QAction(
258 UI.PixmapCache.getIcon("close.png"), self.tr('&Close'), self)
259 self.closeAct.setShortcut(QKeySequence(self.tr(
260 "Ctrl+W", "File|Close")))
261 self.closeAct.setStatusTip(self.tr('Close the current window'))
262 self.closeAct.setWhatsThis(self.tr(
263 """<b>Close Window</b>"""
264 """<p>Close the current window.</p>"""
265 ))
266 self.closeAct.triggered.connect(self.preview.closeWidget)
267
268 self.closeAllAct = QAction(self.tr('Clos&e All'), self)
269 self.closeAllAct.setStatusTip(self.tr('Close all windows'))
270 self.closeAllAct.setWhatsThis(self.tr(
271 """<b>Close All Windows</b>"""
272 """<p>Close all windows.</p>"""
273 ))
274 self.closeAllAct.triggered.connect(self.preview.closeAllWidgets)
275
276 def __initMenus(self):
277 """
278 Private method to create the menus.
279 """
280 mb = self.menuBar()
281
282 menu = mb.addMenu(self.tr('&File'))
283 menu.setTearOffEnabled(True)
284 menu.addAction(self.openUIAct)
285 menu.addAction(self.openQMAct)
286 menu.addAction(self.reloadAct)
287 menu.addSeparator()
288 menu.addAction(self.closeAct)
289 menu.addAction(self.closeAllAct)
290 menu.addSeparator()
291 menu.addAction(self.exitAct)
292
293 self.windowMenu = mb.addMenu(self.tr('&Window'))
294 self.windowMenu.setTearOffEnabled(True)
295 self.windowMenu.aboutToShow.connect(self.__showWindowMenu)
296 self.windowMenu.triggered.connect(self.preview.toggleSelectedWidget)
297
298 mb.addSeparator()
299
300 menu = mb.addMenu(self.tr('&Help'))
301 menu.setTearOffEnabled(True)
302 menu.addAction(self.aboutAct)
303 menu.addAction(self.aboutQtAct)
304 menu.addSeparator()
305 menu.addAction(self.whatsThisAct)
306
307 def __initToolbars(self):
308 """
309 Private method to create the toolbars.
310 """
311 filetb = self.addToolBar(self.tr("File"))
312 filetb.setIconSize(UI.Config.ToolBarIconSize)
313 filetb.addAction(self.openUIAct)
314 filetb.addAction(self.openQMAct)
315 filetb.addAction(self.reloadAct)
316 filetb.addSeparator()
317 filetb.addAction(self.closeAct)
318 filetb.addSeparator()
319 filetb.addAction(self.exitAct)
320
321 helptb = self.addToolBar(self.tr("Help"))
322 helptb.setIconSize(UI.Config.ToolBarIconSize)
323 helptb.addAction(self.whatsThisAct)
324
325 def __whatsThis(self):
326 """
327 Private slot called in to enter Whats This mode.
328 """
329 QWhatsThis.enterWhatsThisMode()
330
331 def __updateActions(self):
332 """
333 Private slot to update the actions state.
334 """
335 if self.preview.hasWidgets():
336 self.closeAct.setEnabled(True)
337 self.closeAllAct.setEnabled(True)
338 self.tileAct.setEnabled(True)
339 self.cascadeAct.setEnabled(True)
340 else:
341 self.closeAct.setEnabled(False)
342 self.closeAllAct.setEnabled(False)
343 self.tileAct.setEnabled(False)
344 self.cascadeAct.setEnabled(False)
345
346 if self.translations.hasTranslations():
347 self.reloadAct.setEnabled(True)
348 else:
349 self.reloadAct.setEnabled(False)
350
351 def __about(self):
352 """
353 Private slot to show the about information.
354 """
355 E5MessageBox.about(
356 self,
357 self.tr("TR Previewer"),
358 self.tr(
359 """<h3> About TR Previewer </h3>"""
360 """<p>The TR Previewer loads and displays Qt User-Interface"""
361 """ files and translation files and shows dialogs for a"""
362 """ selected language.</p>"""
363 )
364 )
365
366 def __aboutQt(self):
367 """
368 Private slot to show info about Qt.
369 """
370 E5MessageBox.aboutQt(self, self.tr("TR Previewer"))
371
372 def __openWidget(self):
373 """
374 Private slot to handle the Open Dialog action.
375 """
376 fileNameList = E5FileDialog.getOpenFileNames(
377 None,
378 self.tr("Select UI files"),
379 "",
380 self.tr("Qt User-Interface Files (*.ui)"))
381
382 for fileName in fileNameList:
383 self.preview.loadWidget(fileName)
384
385 self.__updateActions()
386
387 def __openTranslation(self):
388 """
389 Private slot to handle the Open Translation action.
390 """
391 fileNameList = E5FileDialog.getOpenFileNames(
392 None,
393 self.tr("Select translation files"),
394 "",
395 self.tr("Qt Translation Files (*.qm)"))
396
397 first = True
398 for fileName in fileNameList:
399 self.translations.add(fileName, first)
400 first = False
401
402 self.__updateActions()
403
404 def setTranslation(self, name):
405 """
406 Public slot to activate a translation.
407
408 @param name name (language) of the translation (string)
409 """
410 self.translations.set(name)
411
412 def __showWindowMenu(self):
413 """
414 Private slot to handle the aboutToShow signal of the window menu.
415 """
416 self.windowMenu.clear()
417 self.windowMenu.addAction(self.tileAct)
418 self.windowMenu.addAction(self.cascadeAct)
419 self.windowMenu.addSeparator()
420
421 self.preview.showWindowMenu(self.windowMenu)
422
423 def reloadTranslations(self):
424 """
425 Public slot to reload all translations.
426 """
427 self.translations.reload()
428
429
430 class Translation(object):
431 """
432 Class to store the properties of a translation.
433 """
434 def __init__(self):
435 """
436 Constructor
437 """
438 self.fileName = None
439 self.name = None
440 self.translator = None
441
442
443 class TranslationsDict(QObject):
444 """
445 Class to store all loaded translations.
446
447 @signal translationChanged() emit after a translator was set
448 """
449 translationChanged = pyqtSignal()
450
451 def __init__(self, selector, parent):
452 """
453 Constructor
454
455 @param selector reference to the QComboBox used to show the
456 available languages (QComboBox)
457 @param parent parent widget (QWidget)
458 """
459 super(TranslationsDict, self).__init__(parent)
460
461 self.selector = selector
462 self.currentTranslator = None
463 self.selector.addItem(noTranslationName)
464 self.translations = [] # list of Translation objects
465
466 def add(self, fileName, setTranslation=True):
467 """
468 Public method to add a translation to the list.
469
470 If the translation file (*.qm) has not been loaded yet, it will
471 be loaded automatically.
472
473 @param fileName name of the translation file to be added (string)
474 @param setTranslation flag indicating, if this should be set as
475 the active translation (boolean)
476 """
477 if not self.__haveFileName(fileName):
478 ntr = Translation()
479 ntr.fileName = fileName
480 ntr.name = self.__uniqueName(fileName)
481 if ntr.name is None:
482 E5MessageBox.warning(
483 self.parent(),
484 self.tr("Set Translator"),
485 self.tr(
486 """<p>The translation filename <b>{0}</b>"""
487 """ is invalid.</p>""").format(fileName))
488 return
489
490 ntr.translator = self.loadTransFile(fileName)
491 if ntr.translator is None:
492 return
493
494 self.selector.addItem(ntr.name)
495 self.translations.append(ntr)
496
497 if setTranslation:
498 tr = self.__findFileName(fileName)
499 self.set(tr.name)
500
501 def set(self, name):
502 """
503 Public slot to set a translator by name.
504
505 @param name name (language) of the translator to set (string)
506 """
507 nTranslator = None
508
509 if name != noTranslationName:
510 trans = self.__findName(name)
511 if trans is None:
512 E5MessageBox.warning(
513 self.parent(),
514 self.tr("Set Translator"),
515 self.tr(
516 """<p>The translator <b>{0}</b> is not known.</p>""")
517 .format(name))
518 return
519
520 nTranslator = trans.translator
521
522 if nTranslator == self.currentTranslator:
523 return
524
525 if self.currentTranslator is not None:
526 QApplication.removeTranslator(self.currentTranslator)
527 if nTranslator is not None:
528 QApplication.installTranslator(nTranslator)
529 self.currentTranslator = nTranslator
530
531 self.selector.blockSignals(True)
532 self.selector.setCurrentIndex(self.selector.findText(name))
533 self.selector.blockSignals(False)
534
535 self.translationChanged.emit()
536
537 def reload(self):
538 """
539 Public method to reload all translators.
540 """
541 cname = self.selector.currentText()
542 if self.currentTranslator is not None:
543 QApplication.removeTranslator(self.currentTranslator)
544 self.currentTranslator = None
545
546 fileNames = []
547 for trans in self.translations:
548 trans.translator = None
549 fileNames.append(trans.fileName)
550 self.translations = []
551 self.selector.clear()
552
553 self.selector.addItem(noTranslationName)
554
555 for fileName in fileNames:
556 self.add(fileName, False)
557
558 if self.__haveName(cname):
559 self.set(cname)
560 else:
561 self.set(noTranslationName)
562
563 def __findFileName(self, transFileName):
564 """
565 Private method to find a translation by file name.
566
567 @param transFileName file name of the translation file (string)
568 @return reference to a translation object or None
569 """
570 for trans in self.translations:
571 if trans.fileName == transFileName:
572 return trans
573 return None
574
575 def __findName(self, name):
576 """
577 Private method to find a translation by name.
578
579 @param name name (language) of the translation (string)
580 @return reference to a translation object or None
581 """
582 for trans in self.translations:
583 if trans.name == name:
584 return trans
585 return None
586
587 def __haveFileName(self, transFileName):
588 """
589 Private method to check for the presence of a translation.
590
591 @param transFileName file name of the translation file (string)
592 @return flag indicating the presence of the translation (boolean)
593 """
594 return self.__findFileName(transFileName) is not None
595
596 def __haveName(self, name):
597 """
598 Private method to check for the presence of a named translation.
599
600 @param name name (language) of the translation (string)
601 @return flag indicating the presence of the translation (boolean)
602 """
603 return self.__findName(name) is not None
604
605 def __uniqueName(self, transFileName):
606 """
607 Private method to generate a unique name.
608
609 @param transFileName file name of the translation file (string)
610 @return unique name (string or None)
611 """
612 name = os.path.basename(transFileName)
613 if not name:
614 return None
615
616 uname = name
617 cnt = 1
618 while self.__haveName(uname):
619 cnt += 1
620 uname = "{0} <{1}>".format(name, cnt)
621
622 return uname
623
624 def __del(self, name):
625 """
626 Private method to delete a translator from the list of available
627 translators.
628
629 @param name name of the translator to delete (string)
630 """
631 if name == noTranslationName:
632 return
633
634 trans = self.__findName(name)
635 if trans is None:
636 return
637
638 if self.selector().currentText() == name:
639 self.set(noTranslationName)
640
641 self.translations.remove(trans)
642 del trans
643
644 def loadTransFile(self, transFileName):
645 """
646 Public slot to load a translation file.
647
648 @param transFileName file name of the translation file (string)
649 @return reference to the new translator object (QTranslator)
650 """
651 tr = QTranslator()
652 if tr.load(transFileName):
653 return tr
654
655 E5MessageBox.warning(
656 self.parent(),
657 self.tr("Load Translator"),
658 self.tr("""<p>The translation file <b>{0}</b> could"""
659 """ not be loaded.</p>""").format(transFileName))
660 return None
661
662 def hasTranslations(self):
663 """
664 Public method to check for loaded translations.
665
666 @return flag signaling if any translation was loaded (boolean)
667 """
668 return len(self.translations) > 0
669
670
671 class WidgetView(QWidget):
672 """
673 Class to show a dynamically loaded widget (or dialog).
674 """
675 def __init__(self, uiFileName, parent=None, name=None):
676 """
677 Constructor
678
679 @param uiFileName name of the UI file to load (string)
680 @param parent parent widget (QWidget)
681 @param name name of this widget (string)
682 """
683 super(WidgetView, self).__init__(parent)
684 if name:
685 self.setObjectName(name)
686 self.setWindowTitle(name)
687
688 self.__widget = None
689 self.__uiFileName = uiFileName
690 self.__layout = QHBoxLayout(self)
691 self.__valid = False
692 self.__timer = QTimer(self)
693 self.__timer.setSingleShot(True)
694 self.__timer.timeout.connect(self.buildWidget)
695
696 def isValid(self):
697 """
698 Public method to return the validity of this widget view.
699
700 @return flag indicating the validity (boolean)
701 """
702 return self.__valid
703
704 def uiFileName(self):
705 """
706 Public method to retrieve the name of the UI file.
707
708 @return filename of the loaded UI file (string)
709 """
710 return self.__uiFileName
711
712 def buildWidget(self):
713 """
714 Public slot to load a UI file.
715 """
716 if self.__widget:
717 self.__widget.close()
718 self.__layout.removeWidget(self.__widget)
719 del self.__widget
720 self.__widget = None
721
722 try:
723 self.__widget = uic.loadUi(self.__uiFileName)
724 except Exception:
725 pass
726
727 if not self.__widget:
728 E5MessageBox.warning(
729 self,
730 self.tr("Load UI File"),
731 self.tr(
732 """<p>The file <b>{0}</b> could not be loaded.</p>""")
733 .format(self.__uiFileName))
734 self.__valid = False
735 return
736
737 self.__widget.setParent(self)
738 self.__layout.addWidget(self.__widget)
739 self.__widget.show()
740 self.__valid = True
741 self.adjustSize()
742
743 self.__timer.stop()
744
745 def __rebuildWidget(self):
746 """
747 Private method to schedule a rebuild of the widget.
748 """
749 self.__timer.start(0)
750
751
752 class WidgetArea(QMdiArea):
753 """
754 Specialized MDI area to show the loaded widgets.
755
756 @signal lastWidgetClosed() emitted after the last widget was closed
757 @signal rebuildWidgets() emitted to indicate a change of loaded widgets
758 """
759 lastWidgetClosed = pyqtSignal()
760 rebuildWidgets = pyqtSignal()
761
762 def __init__(self, parent=None):
763 """
764 Constructor
765
766 @param parent parent widget (QWidget)
767 """
768 super(WidgetArea, self).__init__(parent)
769
770 self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
771 self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
772
773 self.widgets = []
774
775 def loadWidget(self, uiFileName):
776 """
777 Public slot to load a UI file.
778
779 @param uiFileName name of the UI file to load (string)
780 """
781 wview = self.__findWidget(uiFileName)
782 if wview is None:
783 name = os.path.basename(uiFileName)
784 if not name:
785 E5MessageBox.warning(
786 self,
787 self.tr("Load UI File"),
788 self.tr(
789 """<p>The file <b>{0}</b> could not be loaded.</p>""")
790 .format(uiFileName))
791 return
792
793 uname = name
794 cnt = 1
795 while self.findChild(WidgetView, uname) is not None:
796 cnt += 1
797 uname = "{0} <{1}>".format(name, cnt)
798 name = uname
799
800 wview = WidgetView(uiFileName, self, name)
801 wview.buildWidget()
802 if not wview.isValid():
803 del wview
804 return
805
806 self.rebuildWidgets.connect(wview.buildWidget)
807 wview.installEventFilter(self)
808
809 win = self.addSubWindow(wview)
810 self.widgets.append(win)
811
812 wview.showNormal()
813
814 def eventFilter(self, obj, ev):
815 """
816 Public method called to filter an event.
817
818 @param obj object, that generated the event (QObject)
819 @param ev the event, that was generated by object (QEvent)
820 @return flag indicating if event was filtered out
821 """
822 if obj in self.widgets and ev.type() == QEvent.Close:
823 try:
824 self.widgets.remove(obj)
825 if len(self.widgets) == 0:
826 self.lastWidgetClosed.emit()
827 except ValueError:
828 pass
829
830 return QMdiArea.eventFilter(self, obj, ev)
831
832 def __findWidget(self, uiFileName):
833 """
834 Private method to find a specific widget view.
835
836 @param uiFileName filename of the loaded UI file (string)
837 @return reference to the widget (WidgetView) or None
838 """
839 wviewList = self.findChildren(WidgetView)
840 if wviewList is None:
841 return None
842
843 for wview in wviewList:
844 if wview.uiFileName() == uiFileName:
845 return wview
846
847 return None
848
849 def closeWidget(self):
850 """
851 Public slot to close the active window.
852 """
853 aw = self.activeSubWindow()
854 if aw is not None:
855 aw.close()
856
857 def closeAllWidgets(self):
858 """
859 Public slot to close all windows.
860 """
861 for w in self.widgets[:]:
862 w.close()
863
864 def showWindowMenu(self, windowMenu):
865 """
866 Public method to set up the widgets part of the Window menu.
867
868 @param windowMenu reference to the window menu
869 """
870 idx = 0
871 for wid in self.widgets:
872 act = windowMenu.addAction(wid.windowTitle())
873 act.setData(idx)
874 act.setCheckable(True)
875 act.setChecked(not wid.isHidden())
876 idx = idx + 1
877
878 def toggleSelectedWidget(self, act):
879 """
880 Public method to handle the toggle of a window.
881
882 @param act reference to the action that triggered (QAction)
883 """
884 idx = act.data()
885 if idx is not None:
886 self.__toggleWidget(self.widgets[idx])
887
888 def __toggleWidget(self, w):
889 """
890 Private method to toggle a workspace window.
891
892 @param w window to be toggled
893 """
894 if w.isHidden():
895 w.show()
896 else:
897 w.hide()
898
899 def hasWidgets(self):
900 """
901 Public method to check for loaded widgets.
902
903 @return flag signaling if any widget was loaded (boolean)
904 """
905 return len(self.widgets) > 0

eric ide

mercurial