31 import UI.Config |
46 import UI.Config |
32 |
47 |
33 import Preferences |
48 import Preferences |
34 |
49 |
35 |
50 |
36 noTranslationName = QCoreApplication.translate( |
51 noTranslationName = QCoreApplication.translate("TRPreviewer", "<No translation>") |
37 "TRPreviewer", "<No translation>") |
|
38 |
52 |
39 |
53 |
40 class TRPreviewer(EricMainWindow): |
54 class TRPreviewer(EricMainWindow): |
41 """ |
55 """ |
42 Class implementing the UI Previewer main window. |
56 Class implementing the UI Previewer main window. |
43 """ |
57 """ |
|
58 |
44 def __init__(self, filenames=None, parent=None, name=None): |
59 def __init__(self, filenames=None, parent=None, name=None): |
45 """ |
60 """ |
46 Constructor |
61 Constructor |
47 |
62 |
48 @param filenames filenames of form and/or translation files to load |
63 @param filenames filenames of form and/or translation files to load |
49 @param parent parent widget of this window (QWidget) |
64 @param parent parent widget of this window (QWidget) |
50 @param name name of this window (string) |
65 @param name name of this window (string) |
51 """ |
66 """ |
52 self.mainWidget = None |
67 self.mainWidget = None |
53 self.currentFile = QDir.currentPath() |
68 self.currentFile = QDir.currentPath() |
54 |
69 |
55 super().__init__(parent) |
70 super().__init__(parent) |
56 if not name: |
71 if not name: |
57 self.setObjectName("TRPreviewer") |
72 self.setObjectName("TRPreviewer") |
58 else: |
73 else: |
59 self.setObjectName(name) |
74 self.setObjectName(name) |
60 |
75 |
61 self.setStyle(Preferences.getUI("Style"), |
76 self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) |
62 Preferences.getUI("StyleSheet")) |
77 |
63 |
|
64 self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint())) |
78 self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint())) |
65 self.statusBar() |
79 self.statusBar() |
66 |
80 |
67 self.setWindowIcon(UI.PixmapCache.getIcon("eric")) |
81 self.setWindowIcon(UI.PixmapCache.getIcon("eric")) |
68 self.setWindowTitle(self.tr("Translations Previewer")) |
82 self.setWindowTitle(self.tr("Translations Previewer")) |
69 |
83 |
70 self.cw = QWidget(self) |
84 self.cw = QWidget(self) |
71 self.cw.setObjectName("qt_central_widget") |
85 self.cw.setObjectName("qt_central_widget") |
72 |
86 |
73 self.TRPreviewerLayout = QVBoxLayout(self.cw) |
87 self.TRPreviewerLayout = QVBoxLayout(self.cw) |
74 self.TRPreviewerLayout.setContentsMargins(6, 6, 6, 6) |
88 self.TRPreviewerLayout.setContentsMargins(6, 6, 6, 6) |
75 self.TRPreviewerLayout.setSpacing(6) |
89 self.TRPreviewerLayout.setSpacing(6) |
76 self.TRPreviewerLayout.setObjectName("TRPreviewerLayout") |
90 self.TRPreviewerLayout.setObjectName("TRPreviewerLayout") |
77 |
91 |
78 self.languageLayout = QHBoxLayout() |
92 self.languageLayout = QHBoxLayout() |
79 self.languageLayout.setContentsMargins(0, 0, 0, 0) |
93 self.languageLayout.setContentsMargins(0, 0, 0, 0) |
80 self.languageLayout.setSpacing(6) |
94 self.languageLayout.setSpacing(6) |
81 self.languageLayout.setObjectName("languageLayout") |
95 self.languageLayout.setObjectName("languageLayout") |
82 |
96 |
83 self.languageLabel = QLabel( |
97 self.languageLabel = QLabel(self.tr("Select language file"), self.cw) |
84 self.tr("Select language file"), self.cw) |
|
85 self.languageLabel.setObjectName("languageLabel") |
98 self.languageLabel.setObjectName("languageLabel") |
86 self.languageLayout.addWidget(self.languageLabel) |
99 self.languageLayout.addWidget(self.languageLabel) |
87 |
100 |
88 self.languageCombo = QComboBox(self.cw) |
101 self.languageCombo = QComboBox(self.cw) |
89 self.languageCombo.setObjectName("languageCombo") |
102 self.languageCombo.setObjectName("languageCombo") |
90 self.languageCombo.setEditable(False) |
103 self.languageCombo.setEditable(False) |
91 self.languageCombo.setToolTip(self.tr("Select language file")) |
104 self.languageCombo.setToolTip(self.tr("Select language file")) |
92 self.languageCombo.setSizePolicy( |
105 self.languageCombo.setSizePolicy( |
93 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) |
106 QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred |
|
107 ) |
94 self.languageLayout.addWidget(self.languageCombo) |
108 self.languageLayout.addWidget(self.languageCombo) |
95 |
109 |
96 languageSpacer = QSpacerItem( |
110 languageSpacer = QSpacerItem( |
97 40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) |
111 40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum |
|
112 ) |
98 self.languageLayout.addItem(languageSpacer) |
113 self.languageLayout.addItem(languageSpacer) |
99 self.TRPreviewerLayout.addLayout(self.languageLayout) |
114 self.TRPreviewerLayout.addLayout(self.languageLayout) |
100 |
115 |
101 self.preview = WidgetArea(self.cw) |
116 self.preview = WidgetArea(self.cw) |
102 self.preview.setObjectName("preview") |
117 self.preview.setObjectName("preview") |
103 self.TRPreviewerLayout.addWidget(self.preview) |
118 self.TRPreviewerLayout.addWidget(self.preview) |
104 self.preview.lastWidgetClosed.connect(self.__updateActions) |
119 self.preview.lastWidgetClosed.connect(self.__updateActions) |
105 |
120 |
106 self.setCentralWidget(self.cw) |
121 self.setCentralWidget(self.cw) |
107 |
122 |
108 self.languageCombo.activated[int].connect(self.__setTranslation) |
123 self.languageCombo.activated[int].connect(self.__setTranslation) |
109 |
124 |
110 self.translations = TranslationsDict(self.languageCombo, self) |
125 self.translations = TranslationsDict(self.languageCombo, self) |
111 self.translations.translationChanged.connect( |
126 self.translations.translationChanged.connect(self.preview.rebuildWidgets) |
112 self.preview.rebuildWidgets) |
127 |
113 |
|
114 self.__initActions() |
128 self.__initActions() |
115 self.__initMenus() |
129 self.__initMenus() |
116 self.__initToolbars() |
130 self.__initToolbars() |
117 |
131 |
118 self.__updateActions() |
132 self.__updateActions() |
119 |
133 |
120 # fire up the single application server |
134 # fire up the single application server |
121 from .TRSingleApplication import TRSingleApplicationServer |
135 from .TRSingleApplication import TRSingleApplicationServer |
|
136 |
122 self.SAServer = TRSingleApplicationServer(self) |
137 self.SAServer = TRSingleApplicationServer(self) |
123 self.SAServer.loadForm.connect(self.preview.loadWidget) |
138 self.SAServer.loadForm.connect(self.preview.loadWidget) |
124 self.SAServer.loadTranslation.connect(self.translations.add) |
139 self.SAServer.loadTranslation.connect(self.translations.add) |
125 |
140 |
126 # defere loading of a UI file until we are shown |
141 # defere loading of a UI file until we are shown |
127 self.filesToLoad = [] if filenames is None else filenames[:] |
142 self.filesToLoad = [] if filenames is None else filenames[:] |
128 |
143 |
129 def show(self): |
144 def show(self): |
130 """ |
145 """ |
131 Public slot to show this dialog. |
146 Public slot to show this dialog. |
132 |
147 |
133 This overloaded slot loads a UI file to be previewed after |
148 This overloaded slot loads a UI file to be previewed after |
134 the main window has been shown. This way, previewing a dialog |
149 the main window has been shown. This way, previewing a dialog |
135 doesn't interfere with showing the main window. |
150 doesn't interfere with showing the main window. |
136 """ |
151 """ |
137 super().show() |
152 super().show() |
138 if self.filesToLoad: |
153 if self.filesToLoad: |
139 filenames, self.filesToLoad = (self.filesToLoad[:], []) |
154 filenames, self.filesToLoad = (self.filesToLoad[:], []) |
140 first = True |
155 first = True |
141 for fn in filenames: |
156 for fn in filenames: |
142 fpath = pathlib.Path(fn) |
157 fpath = pathlib.Path(fn) |
143 if fpath.suffix.lower() == '.ui': |
158 if fpath.suffix.lower() == ".ui": |
144 self.preview.loadWidget(fn) |
159 self.preview.loadWidget(fn) |
145 elif fpath.suffix.lower() == '.qm': |
160 elif fpath.suffix.lower() == ".qm": |
146 self.translations.add(fn, first) |
161 self.translations.add(fn, first) |
147 first = False |
162 first = False |
148 |
163 |
149 self.__updateActions() |
164 self.__updateActions() |
150 |
165 |
151 def closeEvent(self, event): |
166 def closeEvent(self, event): |
152 """ |
167 """ |
153 Protected event handler for the close event. |
168 Protected event handler for the close event. |
154 |
169 |
155 @param event close event (QCloseEvent) |
170 @param event close event (QCloseEvent) |
156 """ |
171 """ |
157 if self.SAServer is not None: |
172 if self.SAServer is not None: |
158 self.SAServer.shutdown() |
173 self.SAServer.shutdown() |
159 self.SAServer = None |
174 self.SAServer = None |
160 event.accept() |
175 event.accept() |
161 |
176 |
162 def __initActions(self): |
177 def __initActions(self): |
163 """ |
178 """ |
164 Private method to define the user interface actions. |
179 Private method to define the user interface actions. |
165 """ |
180 """ |
166 self.openUIAct = QAction( |
181 self.openUIAct = QAction( |
167 UI.PixmapCache.getIcon("openUI"), |
182 UI.PixmapCache.getIcon("openUI"), self.tr("&Open UI Files..."), self |
168 self.tr('&Open UI Files...'), self) |
183 ) |
169 self.openUIAct.setStatusTip(self.tr('Open UI files for display')) |
184 self.openUIAct.setStatusTip(self.tr("Open UI files for display")) |
170 self.openUIAct.setWhatsThis(self.tr( |
185 self.openUIAct.setWhatsThis( |
171 """<b>Open UI Files</b>""" |
186 self.tr( |
172 """<p>This opens some UI files for display.</p>""" |
187 """<b>Open UI Files</b>""" |
173 )) |
188 """<p>This opens some UI files for display.</p>""" |
|
189 ) |
|
190 ) |
174 self.openUIAct.triggered.connect(self.__openWidget) |
191 self.openUIAct.triggered.connect(self.__openWidget) |
175 |
192 |
176 self.openQMAct = QAction( |
193 self.openQMAct = QAction( |
177 UI.PixmapCache.getIcon("openQM"), |
194 UI.PixmapCache.getIcon("openQM"), |
178 self.tr('Open &Translation Files...'), self) |
195 self.tr("Open &Translation Files..."), |
179 self.openQMAct.setStatusTip(self.tr( |
196 self, |
180 'Open Translation files for display')) |
197 ) |
181 self.openQMAct.setWhatsThis(self.tr( |
198 self.openQMAct.setStatusTip(self.tr("Open Translation files for display")) |
182 """<b>Open Translation Files</b>""" |
199 self.openQMAct.setWhatsThis( |
183 """<p>This opens some translation files for display.</p>""" |
200 self.tr( |
184 )) |
201 """<b>Open Translation Files</b>""" |
|
202 """<p>This opens some translation files for display.</p>""" |
|
203 ) |
|
204 ) |
185 self.openQMAct.triggered.connect(self.__openTranslation) |
205 self.openQMAct.triggered.connect(self.__openTranslation) |
186 |
206 |
187 self.reloadAct = QAction( |
207 self.reloadAct = QAction( |
188 UI.PixmapCache.getIcon("reload"), |
208 UI.PixmapCache.getIcon("reload"), self.tr("&Reload Translations"), self |
189 self.tr('&Reload Translations'), self) |
209 ) |
190 self.reloadAct.setStatusTip(self.tr( |
210 self.reloadAct.setStatusTip(self.tr("Reload the loaded translations")) |
191 'Reload the loaded translations')) |
211 self.reloadAct.setWhatsThis( |
192 self.reloadAct.setWhatsThis(self.tr( |
212 self.tr( |
193 """<b>Reload Translations</b>""" |
213 """<b>Reload Translations</b>""" |
194 """<p>This reloads the translations for the loaded""" |
214 """<p>This reloads the translations for the loaded""" |
195 """ languages.</p>""" |
215 """ languages.</p>""" |
196 )) |
216 ) |
|
217 ) |
197 self.reloadAct.triggered.connect(self.translations.reload) |
218 self.reloadAct.triggered.connect(self.translations.reload) |
198 |
219 |
199 self.exitAct = QAction( |
220 self.exitAct = QAction(UI.PixmapCache.getIcon("exit"), self.tr("&Quit"), self) |
200 UI.PixmapCache.getIcon("exit"), self.tr('&Quit'), self) |
221 self.exitAct.setShortcut(QKeySequence(self.tr("Ctrl+Q", "File|Quit"))) |
201 self.exitAct.setShortcut(QKeySequence( |
222 self.exitAct.setStatusTip(self.tr("Quit the application")) |
202 self.tr("Ctrl+Q", "File|Quit"))) |
223 self.exitAct.setWhatsThis( |
203 self.exitAct.setStatusTip(self.tr('Quit the application')) |
224 self.tr("""<b>Quit</b>""" """<p>Quit the application.</p>""") |
204 self.exitAct.setWhatsThis(self.tr( |
225 ) |
205 """<b>Quit</b>""" |
|
206 """<p>Quit the application.</p>""" |
|
207 )) |
|
208 self.exitAct.triggered.connect(ericApp().closeAllWindows) |
226 self.exitAct.triggered.connect(ericApp().closeAllWindows) |
209 |
227 |
210 self.whatsThisAct = QAction( |
228 self.whatsThisAct = QAction( |
211 UI.PixmapCache.getIcon("whatsThis"), |
229 UI.PixmapCache.getIcon("whatsThis"), self.tr("&What's This?"), self |
212 self.tr('&What\'s This?'), self) |
230 ) |
213 self.whatsThisAct.setShortcut(QKeySequence(self.tr("Shift+F1"))) |
231 self.whatsThisAct.setShortcut(QKeySequence(self.tr("Shift+F1"))) |
214 self.whatsThisAct.setStatusTip(self.tr('Context sensitive help')) |
232 self.whatsThisAct.setStatusTip(self.tr("Context sensitive help")) |
215 self.whatsThisAct.setWhatsThis(self.tr( |
233 self.whatsThisAct.setWhatsThis( |
216 """<b>Display context sensitive help</b>""" |
234 self.tr( |
217 """<p>In What's This? mode, the mouse cursor shows an arrow""" |
235 """<b>Display context sensitive help</b>""" |
218 """ with a question mark, and you can click on the interface""" |
236 """<p>In What's This? mode, the mouse cursor shows an arrow""" |
219 """ elements to get a short description of what they do and""" |
237 """ with a question mark, and you can click on the interface""" |
220 """ how to use them. In dialogs, this feature can be accessed""" |
238 """ elements to get a short description of what they do and""" |
221 """ using the context help button in the titlebar.</p>""" |
239 """ how to use them. In dialogs, this feature can be accessed""" |
222 )) |
240 """ using the context help button in the titlebar.</p>""" |
|
241 ) |
|
242 ) |
223 self.whatsThisAct.triggered.connect(self.__whatsThis) |
243 self.whatsThisAct.triggered.connect(self.__whatsThis) |
224 |
244 |
225 self.aboutAct = QAction(self.tr('&About'), self) |
245 self.aboutAct = QAction(self.tr("&About"), self) |
226 self.aboutAct.setStatusTip(self.tr( |
246 self.aboutAct.setStatusTip(self.tr("Display information about this software")) |
227 'Display information about this software')) |
247 self.aboutAct.setWhatsThis( |
228 self.aboutAct.setWhatsThis(self.tr( |
248 self.tr( |
229 """<b>About</b>""" |
249 """<b>About</b>""" |
230 """<p>Display some information about this software.</p>""" |
250 """<p>Display some information about this software.</p>""" |
231 )) |
251 ) |
|
252 ) |
232 self.aboutAct.triggered.connect(self.__about) |
253 self.aboutAct.triggered.connect(self.__about) |
233 |
254 |
234 self.aboutQtAct = QAction(self.tr('About &Qt'), self) |
255 self.aboutQtAct = QAction(self.tr("About &Qt"), self) |
235 self.aboutQtAct.setStatusTip( |
256 self.aboutQtAct.setStatusTip( |
236 self.tr('Display information about the Qt toolkit')) |
257 self.tr("Display information about the Qt toolkit") |
237 self.aboutQtAct.setWhatsThis(self.tr( |
258 ) |
238 """<b>About Qt</b>""" |
259 self.aboutQtAct.setWhatsThis( |
239 """<p>Display some information about the Qt toolkit.</p>""" |
260 self.tr( |
240 )) |
261 """<b>About Qt</b>""" |
|
262 """<p>Display some information about the Qt toolkit.</p>""" |
|
263 ) |
|
264 ) |
241 self.aboutQtAct.triggered.connect(self.__aboutQt) |
265 self.aboutQtAct.triggered.connect(self.__aboutQt) |
242 |
266 |
243 self.tileAct = QAction(self.tr('&Tile'), self) |
267 self.tileAct = QAction(self.tr("&Tile"), self) |
244 self.tileAct.setStatusTip(self.tr('Tile the windows')) |
268 self.tileAct.setStatusTip(self.tr("Tile the windows")) |
245 self.tileAct.setWhatsThis(self.tr( |
269 self.tileAct.setWhatsThis( |
246 """<b>Tile the windows</b>""" |
270 self.tr( |
247 """<p>Rearrange and resize the windows so that they are""" |
271 """<b>Tile the windows</b>""" |
248 """ tiled.</p>""" |
272 """<p>Rearrange and resize the windows so that they are""" |
249 )) |
273 """ tiled.</p>""" |
|
274 ) |
|
275 ) |
250 self.tileAct.triggered.connect(self.preview.tileSubWindows) |
276 self.tileAct.triggered.connect(self.preview.tileSubWindows) |
251 |
277 |
252 self.cascadeAct = QAction(self.tr('&Cascade'), self) |
278 self.cascadeAct = QAction(self.tr("&Cascade"), self) |
253 self.cascadeAct.setStatusTip(self.tr('Cascade the windows')) |
279 self.cascadeAct.setStatusTip(self.tr("Cascade the windows")) |
254 self.cascadeAct.setWhatsThis(self.tr( |
280 self.cascadeAct.setWhatsThis( |
255 """<b>Cascade the windows</b>""" |
281 self.tr( |
256 """<p>Rearrange and resize the windows so that they are""" |
282 """<b>Cascade the windows</b>""" |
257 """ cascaded.</p>""" |
283 """<p>Rearrange and resize the windows so that they are""" |
258 )) |
284 """ cascaded.</p>""" |
|
285 ) |
|
286 ) |
259 self.cascadeAct.triggered.connect(self.preview.cascadeSubWindows) |
287 self.cascadeAct.triggered.connect(self.preview.cascadeSubWindows) |
260 |
288 |
261 self.closeAct = QAction( |
289 self.closeAct = QAction( |
262 UI.PixmapCache.getIcon("close"), self.tr('&Close'), self) |
290 UI.PixmapCache.getIcon("close"), self.tr("&Close"), self |
263 self.closeAct.setShortcut(QKeySequence(self.tr( |
291 ) |
264 "Ctrl+W", "File|Close"))) |
292 self.closeAct.setShortcut(QKeySequence(self.tr("Ctrl+W", "File|Close"))) |
265 self.closeAct.setStatusTip(self.tr('Close the current window')) |
293 self.closeAct.setStatusTip(self.tr("Close the current window")) |
266 self.closeAct.setWhatsThis(self.tr( |
294 self.closeAct.setWhatsThis( |
267 """<b>Close Window</b>""" |
295 self.tr("""<b>Close Window</b>""" """<p>Close the current window.</p>""") |
268 """<p>Close the current window.</p>""" |
296 ) |
269 )) |
|
270 self.closeAct.triggered.connect(self.preview.closeWidget) |
297 self.closeAct.triggered.connect(self.preview.closeWidget) |
271 |
298 |
272 self.closeAllAct = QAction(self.tr('Clos&e All'), self) |
299 self.closeAllAct = QAction(self.tr("Clos&e All"), self) |
273 self.closeAllAct.setStatusTip(self.tr('Close all windows')) |
300 self.closeAllAct.setStatusTip(self.tr("Close all windows")) |
274 self.closeAllAct.setWhatsThis(self.tr( |
301 self.closeAllAct.setWhatsThis( |
275 """<b>Close All Windows</b>""" |
302 self.tr("""<b>Close All Windows</b>""" """<p>Close all windows.</p>""") |
276 """<p>Close all windows.</p>""" |
303 ) |
277 )) |
|
278 self.closeAllAct.triggered.connect(self.preview.closeAllWidgets) |
304 self.closeAllAct.triggered.connect(self.preview.closeAllWidgets) |
279 |
305 |
280 def __initMenus(self): |
306 def __initMenus(self): |
281 """ |
307 """ |
282 Private method to create the menus. |
308 Private method to create the menus. |
283 """ |
309 """ |
284 mb = self.menuBar() |
310 mb = self.menuBar() |
285 |
311 |
286 menu = mb.addMenu(self.tr('&File')) |
312 menu = mb.addMenu(self.tr("&File")) |
287 menu.setTearOffEnabled(True) |
313 menu.setTearOffEnabled(True) |
288 menu.addAction(self.openUIAct) |
314 menu.addAction(self.openUIAct) |
289 menu.addAction(self.openQMAct) |
315 menu.addAction(self.openQMAct) |
290 menu.addAction(self.reloadAct) |
316 menu.addAction(self.reloadAct) |
291 menu.addSeparator() |
317 menu.addSeparator() |
292 menu.addAction(self.closeAct) |
318 menu.addAction(self.closeAct) |
293 menu.addAction(self.closeAllAct) |
319 menu.addAction(self.closeAllAct) |
294 menu.addSeparator() |
320 menu.addSeparator() |
295 menu.addAction(self.exitAct) |
321 menu.addAction(self.exitAct) |
296 |
322 |
297 self.windowMenu = mb.addMenu(self.tr('&Window')) |
323 self.windowMenu = mb.addMenu(self.tr("&Window")) |
298 self.windowMenu.setTearOffEnabled(True) |
324 self.windowMenu.setTearOffEnabled(True) |
299 self.windowMenu.aboutToShow.connect(self.__showWindowMenu) |
325 self.windowMenu.aboutToShow.connect(self.__showWindowMenu) |
300 self.windowMenu.triggered.connect(self.preview.toggleSelectedWidget) |
326 self.windowMenu.triggered.connect(self.preview.toggleSelectedWidget) |
301 |
327 |
302 mb.addSeparator() |
328 mb.addSeparator() |
303 |
329 |
304 menu = mb.addMenu(self.tr('&Help')) |
330 menu = mb.addMenu(self.tr("&Help")) |
305 menu.setTearOffEnabled(True) |
331 menu.setTearOffEnabled(True) |
306 menu.addAction(self.aboutAct) |
332 menu.addAction(self.aboutAct) |
307 menu.addAction(self.aboutQtAct) |
333 menu.addAction(self.aboutQtAct) |
308 menu.addSeparator() |
334 menu.addSeparator() |
309 menu.addAction(self.whatsThisAct) |
335 menu.addAction(self.whatsThisAct) |
488 EricMessageBox.warning( |
518 EricMessageBox.warning( |
489 self.parent(), |
519 self.parent(), |
490 self.tr("Set Translator"), |
520 self.tr("Set Translator"), |
491 self.tr( |
521 self.tr( |
492 """<p>The translation filename <b>{0}</b>""" |
522 """<p>The translation filename <b>{0}</b>""" |
493 """ is invalid.</p>""").format(fileName)) |
523 """ is invalid.</p>""" |
|
524 ).format(fileName), |
|
525 ) |
494 return |
526 return |
495 |
527 |
496 ntr.translator = self.loadTransFile(fileName) |
528 ntr.translator = self.loadTransFile(fileName) |
497 if ntr.translator is None: |
529 if ntr.translator is None: |
498 return |
530 return |
499 |
531 |
500 self.selector.addItem(ntr.name) |
532 self.selector.addItem(ntr.name) |
501 self.translations.append(ntr) |
533 self.translations.append(ntr) |
502 |
534 |
503 if setTranslation: |
535 if setTranslation: |
504 tr = self.__findFileName(fileName) |
536 tr = self.__findFileName(fileName) |
505 self.set(tr.name) |
537 self.set(tr.name) |
506 |
538 |
507 def set(self, name): |
539 def set(self, name): |
508 """ |
540 """ |
509 Public slot to set a translator by name. |
541 Public slot to set a translator by name. |
510 |
542 |
511 @param name name (language) of the translator to set (string) |
543 @param name name (language) of the translator to set (string) |
512 """ |
544 """ |
513 nTranslator = None |
545 nTranslator = None |
514 |
546 |
515 if name != noTranslationName: |
547 if name != noTranslationName: |
516 trans = self.__findName(name) |
548 trans = self.__findName(name) |
517 if trans is None: |
549 if trans is None: |
518 EricMessageBox.warning( |
550 EricMessageBox.warning( |
519 self.parent(), |
551 self.parent(), |
520 self.tr("Set Translator"), |
552 self.tr("Set Translator"), |
521 self.tr( |
553 self.tr( |
522 """<p>The translator <b>{0}</b> is not known.</p>""") |
554 """<p>The translator <b>{0}</b> is not known.</p>""" |
523 .format(name)) |
555 ).format(name), |
|
556 ) |
524 return |
557 return |
525 |
558 |
526 nTranslator = trans.translator |
559 nTranslator = trans.translator |
527 |
560 |
528 if nTranslator == self.currentTranslator: |
561 if nTranslator == self.currentTranslator: |
529 return |
562 return |
530 |
563 |
531 if self.currentTranslator is not None: |
564 if self.currentTranslator is not None: |
532 QApplication.removeTranslator(self.currentTranslator) |
565 QApplication.removeTranslator(self.currentTranslator) |
533 if nTranslator is not None: |
566 if nTranslator is not None: |
534 QApplication.installTranslator(nTranslator) |
567 QApplication.installTranslator(nTranslator) |
535 self.currentTranslator = nTranslator |
568 self.currentTranslator = nTranslator |
536 |
569 |
537 self.selector.blockSignals(True) |
570 self.selector.blockSignals(True) |
538 self.selector.setCurrentIndex(self.selector.findText(name)) |
571 self.selector.setCurrentIndex(self.selector.findText(name)) |
539 self.selector.blockSignals(False) |
572 self.selector.blockSignals(False) |
540 |
573 |
541 self.translationChanged.emit() |
574 self.translationChanged.emit() |
542 |
575 |
543 def reload(self): |
576 def reload(self): |
544 """ |
577 """ |
545 Public method to reload all translators. |
578 Public method to reload all translators. |
546 """ |
579 """ |
547 cname = self.selector.currentText() |
580 cname = self.selector.currentText() |
548 if self.currentTranslator is not None: |
581 if self.currentTranslator is not None: |
549 QApplication.removeTranslator(self.currentTranslator) |
582 QApplication.removeTranslator(self.currentTranslator) |
550 self.currentTranslator = None |
583 self.currentTranslator = None |
551 |
584 |
552 fileNames = [] |
585 fileNames = [] |
553 for trans in self.translations: |
586 for trans in self.translations: |
554 trans.translator = None |
587 trans.translator = None |
555 fileNames.append(trans.fileName) |
588 fileNames.append(trans.fileName) |
556 self.translations = [] |
589 self.translations = [] |
557 self.selector.clear() |
590 self.selector.clear() |
558 |
591 |
559 self.selector.addItem(noTranslationName) |
592 self.selector.addItem(noTranslationName) |
560 |
593 |
561 for fileName in fileNames: |
594 for fileName in fileNames: |
562 self.add(fileName, False) |
595 self.add(fileName, False) |
563 |
596 |
564 if self.__haveName(cname): |
597 if self.__haveName(cname): |
565 self.set(cname) |
598 self.set(cname) |
566 else: |
599 else: |
567 self.set(noTranslationName) |
600 self.set(noTranslationName) |
568 |
601 |
569 def __findFileName(self, transFileName): |
602 def __findFileName(self, transFileName): |
570 """ |
603 """ |
571 Private method to find a translation by file name. |
604 Private method to find a translation by file name. |
572 |
605 |
573 @param transFileName file name of the translation file (string) |
606 @param transFileName file name of the translation file (string) |
574 @return reference to a translation object or None |
607 @return reference to a translation object or None |
575 """ |
608 """ |
576 for trans in self.translations: |
609 for trans in self.translations: |
577 if trans.fileName == transFileName: |
610 if trans.fileName == transFileName: |
578 return trans |
611 return trans |
579 return None |
612 return None |
580 |
613 |
581 def __findName(self, name): |
614 def __findName(self, name): |
582 """ |
615 """ |
583 Private method to find a translation by name. |
616 Private method to find a translation by name. |
584 |
617 |
585 @param name name (language) of the translation (string) |
618 @param name name (language) of the translation (string) |
586 @return reference to a translation object or None |
619 @return reference to a translation object or None |
587 """ |
620 """ |
588 for trans in self.translations: |
621 for trans in self.translations: |
589 if trans.name == name: |
622 if trans.name == name: |
590 return trans |
623 return trans |
591 return None |
624 return None |
592 |
625 |
593 def __haveFileName(self, transFileName): |
626 def __haveFileName(self, transFileName): |
594 """ |
627 """ |
595 Private method to check for the presence of a translation. |
628 Private method to check for the presence of a translation. |
596 |
629 |
597 @param transFileName file name of the translation file (string) |
630 @param transFileName file name of the translation file (string) |
598 @return flag indicating the presence of the translation (boolean) |
631 @return flag indicating the presence of the translation (boolean) |
599 """ |
632 """ |
600 return self.__findFileName(transFileName) is not None |
633 return self.__findFileName(transFileName) is not None |
601 |
634 |
602 def __haveName(self, name): |
635 def __haveName(self, name): |
603 """ |
636 """ |
604 Private method to check for the presence of a named translation. |
637 Private method to check for the presence of a named translation. |
605 |
638 |
606 @param name name (language) of the translation (string) |
639 @param name name (language) of the translation (string) |
607 @return flag indicating the presence of the translation (boolean) |
640 @return flag indicating the presence of the translation (boolean) |
608 """ |
641 """ |
609 return self.__findName(name) is not None |
642 return self.__findName(name) is not None |
610 |
643 |
611 def __uniqueName(self, transFileName): |
644 def __uniqueName(self, transFileName): |
612 """ |
645 """ |
613 Private method to generate a unique name. |
646 Private method to generate a unique name. |
614 |
647 |
615 @param transFileName file name of the translation file (string) |
648 @param transFileName file name of the translation file (string) |
616 @return unique name (string or None) |
649 @return unique name (string or None) |
617 """ |
650 """ |
618 name = os.path.basename(transFileName) |
651 name = os.path.basename(transFileName) |
619 if not name: |
652 if not name: |
620 return None |
653 return None |
621 |
654 |
622 uname = name |
655 uname = name |
623 cnt = 1 |
656 cnt = 1 |
624 while self.__haveName(uname): |
657 while self.__haveName(uname): |
625 cnt += 1 |
658 cnt += 1 |
626 uname = "{0} <{1}>".format(name, cnt) |
659 uname = "{0} <{1}>".format(name, cnt) |
627 |
660 |
628 return uname |
661 return uname |
629 |
662 |
630 def __del(self, name): |
663 def __del(self, name): |
631 """ |
664 """ |
632 Private method to delete a translator from the list of available |
665 Private method to delete a translator from the list of available |
633 translators. |
666 translators. |
634 |
667 |
635 @param name name of the translator to delete (string) |
668 @param name name of the translator to delete (string) |
636 """ |
669 """ |
637 if name == noTranslationName: |
670 if name == noTranslationName: |
638 return |
671 return |
639 |
672 |
640 trans = self.__findName(name) |
673 trans = self.__findName(name) |
641 if trans is None: |
674 if trans is None: |
642 return |
675 return |
643 |
676 |
644 if self.selector().currentText() == name: |
677 if self.selector().currentText() == name: |
645 self.set(noTranslationName) |
678 self.set(noTranslationName) |
646 |
679 |
647 self.translations.remove(trans) |
680 self.translations.remove(trans) |
648 del trans |
681 del trans |
649 |
682 |
650 def loadTransFile(self, transFileName): |
683 def loadTransFile(self, transFileName): |
651 """ |
684 """ |
652 Public slot to load a translation file. |
685 Public slot to load a translation file. |
653 |
686 |
654 @param transFileName file name of the translation file (string) |
687 @param transFileName file name of the translation file (string) |
655 @return reference to the new translator object (QTranslator) |
688 @return reference to the new translator object (QTranslator) |
656 """ |
689 """ |
657 tr = QTranslator() |
690 tr = QTranslator() |
658 if tr.load(transFileName): |
691 if tr.load(transFileName): |
659 return tr |
692 return tr |
660 |
693 |
661 EricMessageBox.warning( |
694 EricMessageBox.warning( |
662 self.parent(), |
695 self.parent(), |
663 self.tr("Load Translator"), |
696 self.tr("Load Translator"), |
664 self.tr("""<p>The translation file <b>{0}</b> could""" |
697 self.tr( |
665 """ not be loaded.</p>""").format(transFileName)) |
698 """<p>The translation file <b>{0}</b> could""" """ not be loaded.</p>""" |
|
699 ).format(transFileName), |
|
700 ) |
666 return None |
701 return None |
667 |
702 |
668 def hasTranslations(self): |
703 def hasTranslations(self): |
669 """ |
704 """ |
670 Public method to check for loaded translations. |
705 Public method to check for loaded translations. |
671 |
706 |
672 @return flag signaling if any translation was loaded (boolean) |
707 @return flag signaling if any translation was loaded (boolean) |
673 """ |
708 """ |
674 return len(self.translations) > 0 |
709 return len(self.translations) > 0 |
675 |
710 |
676 |
711 |
677 class WidgetView(QWidget): |
712 class WidgetView(QWidget): |
678 """ |
713 """ |
679 Class to show a dynamically loaded widget (or dialog). |
714 Class to show a dynamically loaded widget (or dialog). |
680 """ |
715 """ |
|
716 |
681 def __init__(self, uiFileName, parent=None, name=None): |
717 def __init__(self, uiFileName, parent=None, name=None): |
682 """ |
718 """ |
683 Constructor |
719 Constructor |
684 |
720 |
685 @param uiFileName name of the UI file to load (string) |
721 @param uiFileName name of the UI file to load (string) |
686 @param parent parent widget (QWidget) |
722 @param parent parent widget (QWidget) |
687 @param name name of this widget (string) |
723 @param name name of this widget (string) |
688 """ |
724 """ |
689 super().__init__(parent) |
725 super().__init__(parent) |
690 if name: |
726 if name: |
691 self.setObjectName(name) |
727 self.setObjectName(name) |
692 self.setWindowTitle(name) |
728 self.setWindowTitle(name) |
693 |
729 |
694 self.__widget = None |
730 self.__widget = None |
695 self.__uiFileName = uiFileName |
731 self.__uiFileName = uiFileName |
696 self.__layout = QHBoxLayout(self) |
732 self.__layout = QHBoxLayout(self) |
697 self.__valid = False |
733 self.__valid = False |
698 self.__timer = QTimer(self) |
734 self.__timer = QTimer(self) |
699 self.__timer.setSingleShot(True) |
735 self.__timer.setSingleShot(True) |
700 self.__timer.timeout.connect(self.buildWidget) |
736 self.__timer.timeout.connect(self.buildWidget) |
701 |
737 |
702 def isValid(self): |
738 def isValid(self): |
703 """ |
739 """ |
704 Public method to return the validity of this widget view. |
740 Public method to return the validity of this widget view. |
705 |
741 |
706 @return flag indicating the validity (boolean) |
742 @return flag indicating the validity (boolean) |
707 """ |
743 """ |
708 return self.__valid |
744 return self.__valid |
709 |
745 |
710 def uiFileName(self): |
746 def uiFileName(self): |
711 """ |
747 """ |
712 Public method to retrieve the name of the UI file. |
748 Public method to retrieve the name of the UI file. |
713 |
749 |
714 @return filename of the loaded UI file (string) |
750 @return filename of the loaded UI file (string) |
715 """ |
751 """ |
716 return self.__uiFileName |
752 return self.__uiFileName |
717 |
753 |
718 def buildWidget(self): |
754 def buildWidget(self): |
719 """ |
755 """ |
720 Public slot to load a UI file. |
756 Public slot to load a UI file. |
721 """ |
757 """ |
722 if self.__widget: |
758 if self.__widget: |
723 self.__widget.close() |
759 self.__widget.close() |
724 self.__layout.removeWidget(self.__widget) |
760 self.__layout.removeWidget(self.__widget) |
725 del self.__widget |
761 del self.__widget |
726 self.__widget = None |
762 self.__widget = None |
727 |
763 |
728 with contextlib.suppress(Exception): |
764 with contextlib.suppress(Exception): |
729 self.__widget = uic.loadUi(self.__uiFileName) |
765 self.__widget = uic.loadUi(self.__uiFileName) |
730 |
766 |
731 if not self.__widget: |
767 if not self.__widget: |
732 EricMessageBox.warning( |
768 EricMessageBox.warning( |
733 self, |
769 self, |
734 self.tr("Load UI File"), |
770 self.tr("Load UI File"), |
735 self.tr( |
771 self.tr("""<p>The file <b>{0}</b> could not be loaded.</p>""").format( |
736 """<p>The file <b>{0}</b> could not be loaded.</p>""") |
772 self.__uiFileName |
737 .format(self.__uiFileName)) |
773 ), |
|
774 ) |
738 self.__valid = False |
775 self.__valid = False |
739 return |
776 return |
740 |
777 |
741 self.__widget.setParent(self) |
778 self.__widget.setParent(self) |
742 self.__layout.addWidget(self.__widget) |
779 self.__layout.addWidget(self.__widget) |
743 self.__widget.show() |
780 self.__widget.show() |
744 self.__valid = True |
781 self.__valid = True |
745 self.adjustSize() |
782 self.adjustSize() |
746 |
783 |
747 self.__timer.stop() |
784 self.__timer.stop() |
748 |
785 |
749 def __rebuildWidget(self): |
786 def __rebuildWidget(self): |
750 """ |
787 """ |
751 Private method to schedule a rebuild of the widget. |
788 Private method to schedule a rebuild of the widget. |
752 """ |
789 """ |
753 self.__timer.start(0) |
790 self.__timer.start(0) |
754 |
791 |
755 |
792 |
756 class WidgetArea(QMdiArea): |
793 class WidgetArea(QMdiArea): |
757 """ |
794 """ |
758 Specialized MDI area to show the loaded widgets. |
795 Specialized MDI area to show the loaded widgets. |
759 |
796 |
760 @signal lastWidgetClosed() emitted after the last widget was closed |
797 @signal lastWidgetClosed() emitted after the last widget was closed |
761 @signal rebuildWidgets() emitted to indicate a change of loaded widgets |
798 @signal rebuildWidgets() emitted to indicate a change of loaded widgets |
762 """ |
799 """ |
|
800 |
763 lastWidgetClosed = pyqtSignal() |
801 lastWidgetClosed = pyqtSignal() |
764 rebuildWidgets = pyqtSignal() |
802 rebuildWidgets = pyqtSignal() |
765 |
803 |
766 def __init__(self, parent=None): |
804 def __init__(self, parent=None): |
767 """ |
805 """ |
768 Constructor |
806 Constructor |
769 |
807 |
770 @param parent parent widget (QWidget) |
808 @param parent parent widget (QWidget) |
771 """ |
809 """ |
772 super().__init__(parent) |
810 super().__init__(parent) |
773 |
811 |
774 self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) |
812 self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) |
775 self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) |
813 self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) |
776 |
814 |
777 self.widgets = [] |
815 self.widgets = [] |
778 |
816 |
779 def loadWidget(self, uiFileName): |
817 def loadWidget(self, uiFileName): |
780 """ |
818 """ |
781 Public slot to load a UI file. |
819 Public slot to load a UI file. |
782 |
820 |
783 @param uiFileName name of the UI file to load (string) |
821 @param uiFileName name of the UI file to load (string) |
784 """ |
822 """ |
785 wview = self.__findWidget(uiFileName) |
823 wview = self.__findWidget(uiFileName) |
786 if wview is None: |
824 if wview is None: |
787 name = os.path.basename(uiFileName) |
825 name = os.path.basename(uiFileName) |
788 if not name: |
826 if not name: |
789 EricMessageBox.warning( |
827 EricMessageBox.warning( |
790 self, |
828 self, |
791 self.tr("Load UI File"), |
829 self.tr("Load UI File"), |
792 self.tr( |
830 self.tr( |
793 """<p>The file <b>{0}</b> could not be loaded.</p>""") |
831 """<p>The file <b>{0}</b> could not be loaded.</p>""" |
794 .format(uiFileName)) |
832 ).format(uiFileName), |
|
833 ) |
795 return |
834 return |
796 |
835 |
797 uname = name |
836 uname = name |
798 cnt = 1 |
837 cnt = 1 |
799 while self.findChild(WidgetView, uname) is not None: |
838 while self.findChild(WidgetView, uname) is not None: |
800 cnt += 1 |
839 cnt += 1 |
801 uname = "{0} <{1}>".format(name, cnt) |
840 uname = "{0} <{1}>".format(name, cnt) |
802 name = uname |
841 name = uname |
803 |
842 |
804 wview = WidgetView(uiFileName, self, name) |
843 wview = WidgetView(uiFileName, self, name) |
805 wview.buildWidget() |
844 wview.buildWidget() |
806 if not wview.isValid(): |
845 if not wview.isValid(): |
807 del wview |
846 del wview |
808 return |
847 return |
809 |
848 |
810 self.rebuildWidgets.connect(wview.buildWidget) |
849 self.rebuildWidgets.connect(wview.buildWidget) |
811 wview.installEventFilter(self) |
850 wview.installEventFilter(self) |
812 |
851 |
813 win = self.addSubWindow(wview) |
852 win = self.addSubWindow(wview) |
814 self.widgets.append(win) |
853 self.widgets.append(win) |
815 |
854 |
816 wview.showNormal() |
855 wview.showNormal() |
817 |
856 |
818 def eventFilter(self, obj, ev): |
857 def eventFilter(self, obj, ev): |
819 """ |
858 """ |
820 Public method called to filter an event. |
859 Public method called to filter an event. |
821 |
860 |
822 @param obj object, that generated the event (QObject) |
861 @param obj object, that generated the event (QObject) |
823 @param ev the event, that was generated by object (QEvent) |
862 @param ev the event, that was generated by object (QEvent) |
824 @return flag indicating if event was filtered out |
863 @return flag indicating if event was filtered out |
825 """ |
864 """ |
826 if obj in self.widgets and ev.type() == QEvent.Type.Close: |
865 if obj in self.widgets and ev.type() == QEvent.Type.Close: |
827 with contextlib.suppress(ValueError): |
866 with contextlib.suppress(ValueError): |
828 self.widgets.remove(obj) |
867 self.widgets.remove(obj) |
829 if len(self.widgets) == 0: |
868 if len(self.widgets) == 0: |
830 self.lastWidgetClosed.emit() |
869 self.lastWidgetClosed.emit() |
831 |
870 |
832 return QMdiArea.eventFilter(self, obj, ev) |
871 return QMdiArea.eventFilter(self, obj, ev) |
833 |
872 |
834 def __findWidget(self, uiFileName): |
873 def __findWidget(self, uiFileName): |
835 """ |
874 """ |
836 Private method to find a specific widget view. |
875 Private method to find a specific widget view. |
837 |
876 |
838 @param uiFileName filename of the loaded UI file (string) |
877 @param uiFileName filename of the loaded UI file (string) |
839 @return reference to the widget (WidgetView) or None |
878 @return reference to the widget (WidgetView) or None |
840 """ |
879 """ |
841 wviewList = self.findChildren(WidgetView) |
880 wviewList = self.findChildren(WidgetView) |
842 if wviewList is None: |
881 if wviewList is None: |
843 return None |
882 return None |
844 |
883 |
845 for wview in wviewList: |
884 for wview in wviewList: |
846 if wview.uiFileName() == uiFileName: |
885 if wview.uiFileName() == uiFileName: |
847 return wview |
886 return wview |
848 |
887 |
849 return None |
888 return None |
850 |
889 |
851 def closeWidget(self): |
890 def closeWidget(self): |
852 """ |
891 """ |
853 Public slot to close the active window. |
892 Public slot to close the active window. |
854 """ |
893 """ |
855 aw = self.activeSubWindow() |
894 aw = self.activeSubWindow() |
856 if aw is not None: |
895 if aw is not None: |
857 aw.close() |
896 aw.close() |
858 |
897 |
859 def closeAllWidgets(self): |
898 def closeAllWidgets(self): |
860 """ |
899 """ |
861 Public slot to close all windows. |
900 Public slot to close all windows. |
862 """ |
901 """ |
863 for w in self.widgets[:]: |
902 for w in self.widgets[:]: |
864 w.close() |
903 w.close() |
865 |
904 |
866 def showWindowMenu(self, windowMenu): |
905 def showWindowMenu(self, windowMenu): |
867 """ |
906 """ |
868 Public method to set up the widgets part of the Window menu. |
907 Public method to set up the widgets part of the Window menu. |
869 |
908 |
870 @param windowMenu reference to the window menu |
909 @param windowMenu reference to the window menu |
871 """ |
910 """ |
872 for idx, wid in enumerate(self.widgets): |
911 for idx, wid in enumerate(self.widgets): |
873 act = windowMenu.addAction(wid.windowTitle()) |
912 act = windowMenu.addAction(wid.windowTitle()) |
874 act.setData(idx) |
913 act.setData(idx) |
875 act.setCheckable(True) |
914 act.setCheckable(True) |
876 act.setChecked(not wid.isHidden()) |
915 act.setChecked(not wid.isHidden()) |
877 |
916 |
878 def toggleSelectedWidget(self, act): |
917 def toggleSelectedWidget(self, act): |
879 """ |
918 """ |
880 Public method to handle the toggle of a window. |
919 Public method to handle the toggle of a window. |
881 |
920 |
882 @param act reference to the action that triggered (QAction) |
921 @param act reference to the action that triggered (QAction) |
883 """ |
922 """ |
884 idx = act.data() |
923 idx = act.data() |
885 if idx is not None: |
924 if idx is not None: |
886 self.__toggleWidget(self.widgets[idx]) |
925 self.__toggleWidget(self.widgets[idx]) |
887 |
926 |
888 def __toggleWidget(self, w): |
927 def __toggleWidget(self, w): |
889 """ |
928 """ |
890 Private method to toggle a workspace window. |
929 Private method to toggle a workspace window. |
891 |
930 |
892 @param w window to be toggled |
931 @param w window to be toggled |
893 """ |
932 """ |
894 if w.isHidden(): |
933 if w.isHidden(): |
895 w.show() |
934 w.show() |
896 else: |
935 else: |
897 w.hide() |
936 w.hide() |
898 |
937 |
899 def hasWidgets(self): |
938 def hasWidgets(self): |
900 """ |
939 """ |
901 Public method to check for loaded widgets. |
940 Public method to check for loaded widgets. |
902 |
941 |
903 @return flag signaling if any widget was loaded (boolean) |
942 @return flag signaling if any widget was loaded (boolean) |
904 """ |
943 """ |
905 return len(self.widgets) > 0 |
944 return len(self.widgets) > 0 |