|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2002 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the main user interface. |
|
8 """ |
|
9 |
|
10 import os |
|
11 import sys |
|
12 import logging |
|
13 import shutil |
|
14 import json |
|
15 import datetime |
|
16 import getpass |
|
17 import functools |
|
18 import contextlib |
|
19 |
|
20 from PyQt5.QtCore import ( |
|
21 pyqtSlot, QTimer, QFile, QFileInfo, pyqtSignal, PYQT_VERSION_STR, QDate, |
|
22 QIODevice, qVersion, QProcess, QSize, QUrl, QObject, Qt, QUuid, QThread, |
|
23 QUrlQuery |
|
24 ) |
|
25 from PyQt5.QtGui import QKeySequence, QDesktopServices |
|
26 from PyQt5.QtWidgets import ( |
|
27 QSizePolicy, QWidget, QWhatsThis, QToolBar, QDialog, QSplitter, |
|
28 QApplication, QMenu, QVBoxLayout, QDockWidget, QAction, QLabel |
|
29 ) |
|
30 from PyQt5.Qsci import QSCINTILLA_VERSION_STR |
|
31 from PyQt5.QtNetwork import ( |
|
32 QNetworkProxyFactory, QNetworkAccessManager, QNetworkRequest, QNetworkReply |
|
33 ) |
|
34 |
|
35 from .Info import Version, VersionOnly, BugAddress, Program, FeatureAddress |
|
36 from . import Config |
|
37 from .NotificationWidget import NotificationTypes |
|
38 |
|
39 from E5Gui.E5SingleApplication import E5SingleApplicationServer |
|
40 from E5Gui.E5Action import E5Action, createActionGroup |
|
41 from E5Gui.E5ToolBarManager import E5ToolBarManager |
|
42 from E5Gui import E5MessageBox, E5FileDialog, E5ErrorMessage |
|
43 from E5Gui.E5Application import e5App |
|
44 from E5Gui.E5MainWindow import E5MainWindow |
|
45 from E5Gui.E5ZoomWidget import E5ZoomWidget |
|
46 from E5Gui.E5ProgressDialog import E5ProgressDialog |
|
47 from E5Gui.E5ClickableLabel import E5ClickableLabel |
|
48 |
|
49 import Preferences |
|
50 import Utilities |
|
51 import Globals |
|
52 |
|
53 import UI.PixmapCache |
|
54 |
|
55 from Sessions.SessionFile import SessionFile |
|
56 |
|
57 from Tasks.TasksFile import TasksFile |
|
58 |
|
59 from E5Network.E5NetworkProxyFactory import ( |
|
60 E5NetworkProxyFactory, proxyAuthenticationRequired |
|
61 ) |
|
62 try: |
|
63 from E5Network.E5SslErrorHandler import E5SslErrorHandler, E5SslErrorState |
|
64 SSL_AVAILABLE = True |
|
65 except ImportError: |
|
66 SSL_AVAILABLE = False |
|
67 |
|
68 from eric6config import getConfig |
|
69 |
|
70 |
|
71 class Redirector(QObject): |
|
72 """ |
|
73 Helper class used to redirect stdout and stderr to the log window. |
|
74 |
|
75 @signal appendStderr(str) emitted to write data to stderr logger |
|
76 @signal appendStdout(str) emitted to write data to stdout logger |
|
77 """ |
|
78 appendStderr = pyqtSignal(str) |
|
79 appendStdout = pyqtSignal(str) |
|
80 |
|
81 def __init__(self, stderr, parent=None): |
|
82 """ |
|
83 Constructor |
|
84 |
|
85 @param stderr flag indicating stderr is being redirected |
|
86 @type bool |
|
87 @param parent reference to the parent object |
|
88 @type QObject |
|
89 """ |
|
90 super().__init__(parent) |
|
91 self.stderr = stderr |
|
92 self.buffer = '' |
|
93 |
|
94 def __nWrite(self, n): |
|
95 """ |
|
96 Private method used to write data. |
|
97 |
|
98 @param n max number of bytes to write |
|
99 """ |
|
100 if n: |
|
101 line = self.buffer[:n] |
|
102 if self.stderr: |
|
103 self.appendStderr.emit(line) |
|
104 else: |
|
105 self.appendStdout.emit(line) |
|
106 self.buffer = self.buffer[n:] |
|
107 |
|
108 def __bufferedWrite(self): |
|
109 """ |
|
110 Private method returning number of characters to write. |
|
111 |
|
112 @return number of characters buffered or length of buffered line |
|
113 (integer) |
|
114 """ |
|
115 return self.buffer.rfind('\n') + 1 |
|
116 |
|
117 def flush(self): |
|
118 """ |
|
119 Public method used to flush the buffered data. |
|
120 """ |
|
121 self.__nWrite(len(self.buffer)) |
|
122 |
|
123 def write(self, s): |
|
124 """ |
|
125 Public method used to write data. |
|
126 |
|
127 @param s data to be written (it must support the str-method) |
|
128 """ |
|
129 self.buffer += str(s) |
|
130 self.__nWrite(self.__bufferedWrite()) |
|
131 |
|
132 |
|
133 class UserInterface(E5MainWindow): |
|
134 """ |
|
135 Class implementing the main user interface. |
|
136 |
|
137 @signal appendStderr(str) emitted to write data to stderr logger |
|
138 @signal appendStdout(str) emitted to write data to stdout logger |
|
139 @signal preferencesChanged() emitted after the preferences were changed |
|
140 @signal reloadAPIs() emitted to reload the api information |
|
141 @signal showMenu(str, QMenu) emitted when a menu is about to be shown. The |
|
142 name of the menu and a reference to the menu are given. |
|
143 @signal masterPasswordChanged(str, str) emitted after the master |
|
144 password has been changed with the old and the new password |
|
145 """ |
|
146 appendStderr = pyqtSignal(str) |
|
147 appendStdout = pyqtSignal(str) |
|
148 preferencesChanged = pyqtSignal() |
|
149 reloadAPIs = pyqtSignal() |
|
150 showMenu = pyqtSignal(str, QMenu) |
|
151 masterPasswordChanged = pyqtSignal(str, str) |
|
152 |
|
153 maxFilePathLen = 100 |
|
154 maxMenuFilePathLen = 75 |
|
155 |
|
156 LeftSide = 1 |
|
157 BottomSide = 2 |
|
158 RightSide = 3 |
|
159 |
|
160 ErrorLogFileName = "eric6_error.log" |
|
161 |
|
162 def __init__(self, app, locale, splash, plugin, disabledPlugins, |
|
163 noOpenAtStartup, noCrashOpenAtStartup, disableCrashSession, |
|
164 restartArguments, originalPathString): |
|
165 """ |
|
166 Constructor |
|
167 |
|
168 @param app reference to the application object |
|
169 @type E5Application |
|
170 @param locale locale to be used by the UI |
|
171 @type str |
|
172 @param splash reference to the splashscreen |
|
173 @type UI.SplashScreen.SplashScreen |
|
174 @param plugin filename of a plug-in to be loaded (used for plugin |
|
175 development) |
|
176 @type str |
|
177 @param disabledPlugins list of plug-ins that have been disabled via |
|
178 the command line parameters '--disable-plugin=' |
|
179 @type list of str |
|
180 @param noOpenAtStartup flag indicating that the open at startup option |
|
181 should not be executed |
|
182 @type bool |
|
183 @param noCrashOpenAtStartup flag indicating to ignore any crash session |
|
184 file found at statup |
|
185 @type bool |
|
186 @param disableCrashSession flag indicating to disable the crash session |
|
187 support |
|
188 @type bool |
|
189 @param restartArguments list of command line parameters to be used for |
|
190 a restart |
|
191 @type list of str |
|
192 @param originalPathString original PATH environment variable |
|
193 @type str |
|
194 """ |
|
195 super().__init__() |
|
196 |
|
197 self.__restartArgs = restartArguments[:] |
|
198 |
|
199 self.setStyle(Preferences.getUI("Style"), |
|
200 Preferences.getUI("StyleSheet")) |
|
201 |
|
202 self.maxEditorPathLen = Preferences.getUI("CaptionFilenameLength") |
|
203 self.locale = locale |
|
204 self.__openAtStartup = not noOpenAtStartup |
|
205 self.__noCrashOpenAtStartup = noCrashOpenAtStartup |
|
206 self.__disableCrashSession = disableCrashSession |
|
207 self.__disabledPlugins = disabledPlugins[:] |
|
208 |
|
209 self.__originalPathString = originalPathString |
|
210 |
|
211 self.__layoutType = Preferences.getUI("LayoutType") |
|
212 |
|
213 self.passiveMode = Preferences.getDebugger("PassiveDbgEnabled") |
|
214 |
|
215 g = Preferences.getGeometry("MainGeometry") |
|
216 if g.isEmpty(): |
|
217 s = QSize(1280, 1024) |
|
218 self.resize(s) |
|
219 else: |
|
220 self.restoreGeometry(g) |
|
221 self.__startup = True |
|
222 |
|
223 if Preferences.getUI("UseSystemProxy"): |
|
224 QNetworkProxyFactory.setUseSystemConfiguration(True) |
|
225 else: |
|
226 self.__proxyFactory = E5NetworkProxyFactory() |
|
227 QNetworkProxyFactory.setApplicationProxyFactory( |
|
228 self.__proxyFactory) |
|
229 QNetworkProxyFactory.setUseSystemConfiguration(False) |
|
230 |
|
231 self.capProject = "" |
|
232 self.capEditor = "" |
|
233 self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename") |
|
234 |
|
235 QApplication.setWindowIcon(UI.PixmapCache.getIcon("eric")) |
|
236 self.setWindowIcon(UI.PixmapCache.getIcon("eric")) |
|
237 self.__setWindowCaption() |
|
238 |
|
239 # load the view profiles |
|
240 self.profiles = Preferences.getUI("ViewProfiles2") |
|
241 |
|
242 # Generate the conda interface |
|
243 from CondaInterface.Conda import Conda |
|
244 self.condaInterface = Conda(self) |
|
245 e5App().registerObject("Conda", self.condaInterface) |
|
246 |
|
247 # Generate the pip interface |
|
248 from PipInterface.Pip import Pip |
|
249 self.pipInterface = Pip(self) |
|
250 e5App().registerObject("Pip", self.pipInterface) |
|
251 |
|
252 # Generate the virtual environment manager |
|
253 from VirtualEnv.VirtualenvManager import VirtualenvManager |
|
254 self.virtualenvManager = VirtualenvManager(self) |
|
255 # register it early because it is needed very soon |
|
256 e5App().registerObject("VirtualEnvManager", self.virtualenvManager) |
|
257 |
|
258 # Generate an empty project object and multi project object |
|
259 from Project.Project import Project |
|
260 self.project = Project(self) |
|
261 e5App().registerObject("Project", self.project) |
|
262 |
|
263 from MultiProject.MultiProject import MultiProject |
|
264 self.multiProject = MultiProject(self.project, self) |
|
265 |
|
266 # Generate the debug server object |
|
267 from Debugger.DebugServer import DebugServer |
|
268 debugServer = DebugServer(self.__originalPathString, |
|
269 project=self.project, parent=self) |
|
270 |
|
271 # Create the background service object |
|
272 from Utilities.BackgroundService import BackgroundService |
|
273 self.backgroundService = BackgroundService(self) |
|
274 |
|
275 splash.showMessage(self.tr("Initializing Plugin Manager...")) |
|
276 |
|
277 # Initialize the Plugin Manager (Plugins are initialized later |
|
278 from PluginManager.PluginManager import PluginManager |
|
279 self.pluginManager = PluginManager(self, self.__disabledPlugins, |
|
280 develPlugin=plugin) |
|
281 |
|
282 splash.showMessage(self.tr("Generating Main User Interface...")) |
|
283 |
|
284 self.codeDocumentationViewer = None |
|
285 self.cooperation = None |
|
286 self.irc = None |
|
287 self.symbolsViewer = None |
|
288 self.browser = None |
|
289 self.templateViewer = None |
|
290 self.numbersViewer = None |
|
291 self.pipWidget = None |
|
292 self.condaWidget = None |
|
293 self.microPythonWidget = None |
|
294 |
|
295 self.__webBrowserProcess = None |
|
296 self.__webBrowserClient = None |
|
297 self.__webBrowserSAName = QUuid.createUuid().toString()[1:-1] |
|
298 |
|
299 # Create the main window now so that we can connect QActions to it. |
|
300 logging.debug("Creating Layout...") |
|
301 self.__createLayout(debugServer) |
|
302 self.__currentRightWidget = None |
|
303 self.__currentBottomWidget = None |
|
304 |
|
305 # Generate the debugger part of the ui |
|
306 logging.debug("Creating Debugger UI...") |
|
307 from Debugger.DebugUI import DebugUI |
|
308 self.debuggerUI = DebugUI(self, self.viewmanager, debugServer, |
|
309 self.debugViewer, self.project) |
|
310 self.debugViewer.setDebugger(self.debuggerUI) |
|
311 self.shell.setDebuggerUI(self.debuggerUI) |
|
312 |
|
313 # Generate the redirection helpers |
|
314 self.stdout = Redirector(False, self) |
|
315 self.stderr = Redirector(True, self) |
|
316 |
|
317 # set a few dialog members for non-modal dialogs created on demand |
|
318 self.programsDialog = None |
|
319 self.shortcutsDialog = None |
|
320 self.unittestDialog = None |
|
321 self.findFileNameDialog = None |
|
322 self.diffDlg = None |
|
323 self.compareDlg = None |
|
324 self.findFilesDialog = None |
|
325 self.replaceFilesDialog = None |
|
326 self.__notification = None |
|
327 self.__readingSession = False |
|
328 self.__versionsDialog = None |
|
329 self.__configurationDialog = None |
|
330 |
|
331 # now setup the connections |
|
332 splash.showMessage(self.tr("Setting up connections...")) |
|
333 |
|
334 self.debugViewer.exceptionLogger.sourceFile.connect( |
|
335 self.viewmanager.openSourceFile) |
|
336 |
|
337 self.debugViewer.sourceFile.connect(self.viewmanager.showDebugSource) |
|
338 |
|
339 self.taskViewer.displayFile.connect(self.viewmanager.openSourceFile) |
|
340 |
|
341 self.projectBrowser.psBrowser.sourceFile[str].connect( |
|
342 self.viewmanager.openSourceFile) |
|
343 self.projectBrowser.psBrowser.sourceFile[str, int].connect( |
|
344 self.viewmanager.openSourceFile) |
|
345 self.projectBrowser.psBrowser.sourceFile[str, list].connect( |
|
346 self.viewmanager.openSourceFile) |
|
347 self.projectBrowser.psBrowser.sourceFile[str, int, str].connect( |
|
348 self.viewmanager.openSourceFile) |
|
349 self.projectBrowser.psBrowser.closeSourceWindow.connect( |
|
350 self.viewmanager.closeWindow) |
|
351 self.projectBrowser.psBrowser.unittestOpen.connect( |
|
352 self.__unittestScript) |
|
353 |
|
354 self.projectBrowser.pfBrowser.designerFile.connect(self.__designer) |
|
355 self.projectBrowser.pfBrowser.sourceFile.connect( |
|
356 self.viewmanager.openSourceFile) |
|
357 self.projectBrowser.pfBrowser.uipreview.connect(self.__UIPreviewer) |
|
358 self.projectBrowser.pfBrowser.trpreview.connect(self.__TRPreviewer) |
|
359 self.projectBrowser.pfBrowser.closeSourceWindow.connect( |
|
360 self.viewmanager.closeWindow) |
|
361 self.projectBrowser.pfBrowser.appendStderr.connect(self.appendToStderr) |
|
362 |
|
363 self.projectBrowser.prBrowser.sourceFile.connect( |
|
364 self.viewmanager.openSourceFile) |
|
365 self.projectBrowser.prBrowser.closeSourceWindow.connect( |
|
366 self.viewmanager.closeWindow) |
|
367 self.projectBrowser.prBrowser.appendStderr.connect(self.appendToStderr) |
|
368 |
|
369 self.projectBrowser.ptBrowser.linguistFile.connect(self.__linguist) |
|
370 self.projectBrowser.ptBrowser.sourceFile.connect( |
|
371 self.viewmanager.openSourceFile) |
|
372 self.projectBrowser.ptBrowser.trpreview[list].connect( |
|
373 self.__TRPreviewer) |
|
374 self.projectBrowser.ptBrowser.trpreview[list, bool].connect( |
|
375 self.__TRPreviewer) |
|
376 self.projectBrowser.ptBrowser.closeSourceWindow.connect( |
|
377 self.viewmanager.closeWindow) |
|
378 self.projectBrowser.ptBrowser.appendStdout.connect(self.appendToStdout) |
|
379 self.projectBrowser.ptBrowser.appendStderr.connect(self.appendToStderr) |
|
380 |
|
381 self.projectBrowser.piBrowser.sourceFile[str].connect( |
|
382 self.viewmanager.openSourceFile) |
|
383 self.projectBrowser.piBrowser.sourceFile[str, int].connect( |
|
384 self.viewmanager.openSourceFile) |
|
385 self.projectBrowser.piBrowser.closeSourceWindow.connect( |
|
386 self.viewmanager.closeWindow) |
|
387 self.projectBrowser.piBrowser.appendStdout.connect(self.appendToStdout) |
|
388 self.projectBrowser.piBrowser.appendStderr.connect(self.appendToStderr) |
|
389 |
|
390 self.projectBrowser.ppBrowser.sourceFile[str].connect( |
|
391 self.viewmanager.openSourceFile) |
|
392 self.projectBrowser.ppBrowser.sourceFile[str, int].connect( |
|
393 self.viewmanager.openSourceFile) |
|
394 self.projectBrowser.ppBrowser.closeSourceWindow.connect( |
|
395 self.viewmanager.closeWindow) |
|
396 self.projectBrowser.ppBrowser.appendStdout.connect(self.appendToStdout) |
|
397 self.projectBrowser.ppBrowser.appendStderr.connect(self.appendToStderr) |
|
398 |
|
399 self.projectBrowser.poBrowser.sourceFile.connect( |
|
400 self.viewmanager.openSourceFile) |
|
401 self.projectBrowser.poBrowser.closeSourceWindow.connect( |
|
402 self.viewmanager.closeWindow) |
|
403 self.projectBrowser.poBrowser.pixmapEditFile.connect(self.__editPixmap) |
|
404 self.projectBrowser.poBrowser.pixmapFile.connect(self.__showPixmap) |
|
405 self.projectBrowser.poBrowser.svgFile.connect(self.__showSvg) |
|
406 self.projectBrowser.poBrowser.umlFile.connect(self.__showUml) |
|
407 self.projectBrowser.poBrowser.binaryFile.connect(self.__openHexEditor) |
|
408 |
|
409 self.project.sourceFile.connect(self.viewmanager.openSourceFile) |
|
410 self.project.designerFile.connect(self.__designer) |
|
411 self.project.linguistFile.connect(self.__linguist) |
|
412 self.project.projectOpened.connect(self.viewmanager.projectOpened) |
|
413 self.project.projectClosed.connect(self.viewmanager.projectClosed) |
|
414 self.project.projectFileRenamed.connect( |
|
415 self.viewmanager.projectFileRenamed) |
|
416 self.project.lexerAssociationsChanged.connect( |
|
417 self.viewmanager.projectLexerAssociationsChanged) |
|
418 self.project.newProject.connect(self.__newProject) |
|
419 self.project.projectOpened.connect(self.__projectOpened) |
|
420 self.project.projectOpened.connect(self.__activateProjectBrowser) |
|
421 self.project.projectClosed.connect(self.__projectClosed) |
|
422 self.project.projectClosed.connect( |
|
423 self.backgroundService.preferencesOrProjectChanged) |
|
424 self.project.projectOpened.connect(self.__writeCrashSession) |
|
425 self.project.projectClosed.connect(self.__writeCrashSession) |
|
426 self.project.appendStdout.connect(self.appendToStdout) |
|
427 self.project.appendStderr.connect(self.appendToStderr) |
|
428 |
|
429 self.multiProject.multiProjectOpened.connect( |
|
430 self.__activateMultiProjectBrowser) |
|
431 self.multiProject.multiProjectOpened.connect( |
|
432 self.__writeCrashSession) |
|
433 self.multiProject.multiProjectClosed.connect( |
|
434 self.__writeCrashSession) |
|
435 |
|
436 self.debuggerUI.resetUI.connect(self.viewmanager.handleResetUI) |
|
437 self.debuggerUI.resetUI.connect(self.debugViewer.handleResetUI) |
|
438 self.debuggerUI.resetUI.connect(self.__debuggingDone) |
|
439 self.debuggerUI.debuggingStarted.connect(self.__programChange) |
|
440 self.debuggerUI.debuggingStarted.connect(self.__debuggingStarted) |
|
441 self.debuggerUI.compileForms.connect( |
|
442 self.projectBrowser.pfBrowser.compileChangedForms) |
|
443 self.debuggerUI.compileResources.connect( |
|
444 self.projectBrowser.prBrowser.compileChangedResources) |
|
445 self.debuggerUI.executeMake.connect(self.project.executeMake) |
|
446 self.debuggerUI.appendStdout.connect(self.appendToStdout) |
|
447 |
|
448 debugServer.clientDisassembly.connect( |
|
449 self.debugViewer.disassemblyViewer.showDisassembly) |
|
450 debugServer.clientProcessStdout.connect(self.appendToStdout) |
|
451 debugServer.clientProcessStderr.connect(self.appendToStderr) |
|
452 debugServer.appendStdout.connect(self.appendToStdout) |
|
453 |
|
454 self.stdout.appendStdout.connect(self.appendToStdout) |
|
455 self.stderr.appendStderr.connect(self.appendToStderr) |
|
456 |
|
457 self.preferencesChanged.connect(self.viewmanager.preferencesChanged) |
|
458 self.reloadAPIs.connect(self.viewmanager.getAPIsManager().reloadAPIs) |
|
459 self.preferencesChanged.connect(self.logViewer.preferencesChanged) |
|
460 self.appendStdout.connect(self.logViewer.appendToStdout) |
|
461 self.appendStderr.connect(self.logViewer.appendToStderr) |
|
462 self.preferencesChanged.connect(self.shell.handlePreferencesChanged) |
|
463 self.preferencesChanged.connect(self.project.handlePreferencesChanged) |
|
464 self.preferencesChanged.connect( |
|
465 self.projectBrowser.handlePreferencesChanged) |
|
466 self.preferencesChanged.connect( |
|
467 self.projectBrowser.psBrowser.handlePreferencesChanged) |
|
468 self.preferencesChanged.connect( |
|
469 self.projectBrowser.pfBrowser.handlePreferencesChanged) |
|
470 self.preferencesChanged.connect( |
|
471 self.projectBrowser.prBrowser.handlePreferencesChanged) |
|
472 self.preferencesChanged.connect( |
|
473 self.projectBrowser.ptBrowser.handlePreferencesChanged) |
|
474 self.preferencesChanged.connect( |
|
475 self.projectBrowser.piBrowser.handlePreferencesChanged) |
|
476 self.preferencesChanged.connect( |
|
477 self.projectBrowser.ppBrowser.handlePreferencesChanged) |
|
478 self.preferencesChanged.connect( |
|
479 self.projectBrowser.poBrowser.handlePreferencesChanged) |
|
480 self.preferencesChanged.connect( |
|
481 self.taskViewer.handlePreferencesChanged) |
|
482 self.preferencesChanged.connect(self.pluginManager.preferencesChanged) |
|
483 self.preferencesChanged.connect(debugServer.preferencesChanged) |
|
484 self.preferencesChanged.connect(self.debugViewer.preferencesChanged) |
|
485 self.preferencesChanged.connect( |
|
486 self.backgroundService.preferencesOrProjectChanged) |
|
487 self.preferencesChanged.connect(self.__previewer.preferencesChanged) |
|
488 self.preferencesChanged.connect(self.__astViewer.preferencesChanged) |
|
489 self.preferencesChanged.connect(self.__disViewer.preferencesChanged) |
|
490 |
|
491 if self.browser is not None: |
|
492 self.browser.sourceFile[str].connect( |
|
493 self.viewmanager.openSourceFile) |
|
494 self.browser.sourceFile[str, int].connect( |
|
495 self.viewmanager.openSourceFile) |
|
496 self.browser.sourceFile[str, list].connect( |
|
497 self.viewmanager.openSourceFile) |
|
498 self.browser.sourceFile[str, int, str].connect( |
|
499 self.viewmanager.openSourceFile) |
|
500 self.browser.designerFile.connect(self.__designer) |
|
501 self.browser.linguistFile.connect(self.__linguist) |
|
502 self.browser.projectFile.connect(self.project.openProject) |
|
503 self.browser.multiProjectFile.connect( |
|
504 self.multiProject.openMultiProject) |
|
505 self.browser.pixmapEditFile.connect(self.__editPixmap) |
|
506 self.browser.pixmapFile.connect(self.__showPixmap) |
|
507 self.browser.svgFile.connect(self.__showSvg) |
|
508 self.browser.umlFile.connect(self.__showUml) |
|
509 self.browser.binaryFile.connect(self.__openHexEditor) |
|
510 self.browser.unittestOpen.connect(self.__unittestScript) |
|
511 self.browser.trpreview.connect(self.__TRPreviewer) |
|
512 |
|
513 self.debuggerUI.debuggingStarted.connect( |
|
514 self.browser.handleProgramChange) |
|
515 |
|
516 debugServer.clientInterpreterChanged.connect( |
|
517 self.browser.handleInterpreterChanged) |
|
518 |
|
519 self.preferencesChanged.connect( |
|
520 self.browser.handlePreferencesChanged) |
|
521 |
|
522 if self.codeDocumentationViewer is not None: |
|
523 self.preferencesChanged.connect( |
|
524 self.codeDocumentationViewer.preferencesChanged) |
|
525 |
|
526 self.viewmanager.editorSaved.connect(self.project.repopulateItem) |
|
527 self.viewmanager.lastEditorClosed.connect(self.__lastEditorClosed) |
|
528 self.viewmanager.editorOpened.connect(self.__editorOpened) |
|
529 self.viewmanager.changeCaption.connect(self.__setWindowCaption) |
|
530 self.viewmanager.checkActions.connect(self.__checkActions) |
|
531 self.viewmanager.editorChanged.connect( |
|
532 self.projectBrowser.handleEditorChanged) |
|
533 self.viewmanager.editorLineChanged.connect( |
|
534 self.projectBrowser.handleEditorLineChanged) |
|
535 self.viewmanager.editorOpened.connect(self.__writeCrashSession) |
|
536 self.viewmanager.editorClosed.connect(self.__writeCrashSession) |
|
537 self.viewmanager.editorRenamed.connect(self.__writeCrashSession) |
|
538 self.viewmanager.editorChanged.connect(self.__writeCrashSession) |
|
539 |
|
540 self.shell.zoomValueChanged.connect( |
|
541 lambda v: self.viewmanager.zoomValueChanged(v, self.shell)) |
|
542 |
|
543 if self.cooperation is not None: |
|
544 self.viewmanager.checkActions.connect( |
|
545 self.cooperation.checkEditorActions) |
|
546 self.preferencesChanged.connect( |
|
547 self.cooperation.preferencesChanged) |
|
548 self.cooperation.shareEditor.connect( |
|
549 self.viewmanager.shareEditor) |
|
550 self.cooperation.startEdit.connect( |
|
551 self.viewmanager.startSharedEdit) |
|
552 self.cooperation.sendEdit.connect( |
|
553 self.viewmanager.sendSharedEdit) |
|
554 self.cooperation.cancelEdit.connect( |
|
555 self.viewmanager.cancelSharedEdit) |
|
556 self.cooperation.connected.connect( |
|
557 self.viewmanager.shareConnected) |
|
558 self.cooperation.editorCommand.connect( |
|
559 self.viewmanager.receive) |
|
560 self.viewmanager.setCooperationClient( |
|
561 self.cooperation.getClient()) |
|
562 |
|
563 if self.symbolsViewer is not None: |
|
564 self.symbolsViewer.insertSymbol.connect( |
|
565 self.viewmanager.insertSymbol) |
|
566 |
|
567 if self.numbersViewer is not None: |
|
568 self.numbersViewer.insertNumber.connect( |
|
569 self.viewmanager.insertNumber) |
|
570 |
|
571 if self.irc is not None: |
|
572 self.irc.autoConnected.connect(self.__ircAutoConnected) |
|
573 |
|
574 # create the toolbar manager object |
|
575 self.toolbarManager = E5ToolBarManager(self, self) |
|
576 self.toolbarManager.setMainWindow(self) |
|
577 |
|
578 # Initialize the tool groups and list of started tools |
|
579 splash.showMessage(self.tr("Initializing Tools...")) |
|
580 self.toolGroups, self.currentToolGroup = Preferences.readToolGroups() |
|
581 self.toolProcs = [] |
|
582 self.__initExternalToolsActions() |
|
583 |
|
584 # redirect handling of http and https URLs to ourselves |
|
585 QDesktopServices.setUrlHandler("http", self.handleUrl) |
|
586 QDesktopServices.setUrlHandler("https", self.handleUrl) |
|
587 |
|
588 # register all relevant objects |
|
589 splash.showMessage(self.tr("Registering Objects...")) |
|
590 e5App().registerObject("UserInterface", self) |
|
591 e5App().registerObject("DebugUI", self.debuggerUI) |
|
592 e5App().registerObject("DebugServer", debugServer) |
|
593 e5App().registerObject("BackgroundService", self.backgroundService) |
|
594 e5App().registerObject("ViewManager", self.viewmanager) |
|
595 e5App().registerObject("ProjectBrowser", self.projectBrowser) |
|
596 e5App().registerObject("MultiProject", self.multiProject) |
|
597 e5App().registerObject("TaskViewer", self.taskViewer) |
|
598 if self.templateViewer is not None: |
|
599 e5App().registerObject("TemplateViewer", self.templateViewer) |
|
600 e5App().registerObject("Shell", self.shell) |
|
601 e5App().registerObject("PluginManager", self.pluginManager) |
|
602 e5App().registerObject("ToolbarManager", self.toolbarManager) |
|
603 if self.cooperation is not None: |
|
604 e5App().registerObject("Cooperation", self.cooperation) |
|
605 if self.irc is not None: |
|
606 e5App().registerObject("IRC", self.irc) |
|
607 if self.symbolsViewer is not None: |
|
608 e5App().registerObject("Symbols", self.symbolsViewer) |
|
609 if self.numbersViewer is not None: |
|
610 e5App().registerObject("Numbers", self.numbersViewer) |
|
611 if self.codeDocumentationViewer is not None: |
|
612 e5App().registerObject("DocuViewer", self.codeDocumentationViewer) |
|
613 if self.microPythonWidget is not None: |
|
614 e5App().registerObject("MicroPython", self.microPythonWidget) |
|
615 |
|
616 # list of web addresses serving the versions file |
|
617 self.__httpAlternatives = Preferences.getUI("VersionsUrls6") |
|
618 self.__inVersionCheck = False |
|
619 self.__versionCheckProgress = None |
|
620 |
|
621 # create the various JSON file interfaces |
|
622 self.__sessionFile = SessionFile(True) |
|
623 self.__tasksFile = TasksFile(True) |
|
624 |
|
625 # Initialize the actions, menus, toolbars and statusbar |
|
626 splash.showMessage(self.tr("Initializing Actions...")) |
|
627 self.__initActions() |
|
628 splash.showMessage(self.tr("Initializing Menus...")) |
|
629 self.__initMenus() |
|
630 splash.showMessage(self.tr("Initializing Toolbars...")) |
|
631 self.__initToolbars() |
|
632 splash.showMessage(self.tr("Initializing Statusbar...")) |
|
633 self.__initStatusbar() |
|
634 |
|
635 # connect the appFocusChanged signal after all actions are ready |
|
636 app.focusChanged.connect(self.viewmanager.appFocusChanged) |
|
637 |
|
638 # Initialize the instance variables. |
|
639 self.currentProg = None |
|
640 self.isProg = False |
|
641 self.utEditorOpen = False |
|
642 self.utProjectOpen = False |
|
643 |
|
644 self.inDragDrop = False |
|
645 self.setAcceptDrops(True) |
|
646 |
|
647 self.currentProfile = None |
|
648 |
|
649 self.shutdownCalled = False |
|
650 self.inCloseEvent = False |
|
651 |
|
652 # now redirect stdout and stderr |
|
653 # TODO: release - reenable redirection |
|
654 ## sys.stdout = self.stdout # __IGNORE_WARNING_M891__ |
|
655 ## sys.stderr = self.stderr # __IGNORE_WARNING_M891__ |
|
656 |
|
657 # now fire up the single application server |
|
658 if Preferences.getUI("SingleApplicationMode"): |
|
659 splash.showMessage( |
|
660 self.tr("Initializing Single Application Server...")) |
|
661 self.SAServer = E5SingleApplicationServer() |
|
662 else: |
|
663 self.SAServer = None |
|
664 |
|
665 # now finalize the plugin manager setup |
|
666 splash.showMessage(self.tr("Initializing Plugins...")) |
|
667 self.pluginManager.finalizeSetup() |
|
668 # now activate plugins having autoload set to True |
|
669 splash.showMessage(self.tr("Activating Plugins...")) |
|
670 self.pluginManager.activatePlugins() |
|
671 splash.showMessage(self.tr("Generating Plugins Toolbars...")) |
|
672 self.pluginManager.initPluginToolbars(self.toolbarManager) |
|
673 if Preferences.getPluginManager("StartupCleanup"): |
|
674 splash.showMessage(self.tr("Cleaning Plugins Download Area...")) |
|
675 from PluginManager.PluginRepositoryDialog import ( |
|
676 PluginRepositoryDownloadCleanup |
|
677 ) |
|
678 PluginRepositoryDownloadCleanup(quiet=True) |
|
679 |
|
680 # now read the keyboard shortcuts for all the actions |
|
681 from Preferences import Shortcuts |
|
682 Shortcuts.readShortcuts() |
|
683 |
|
684 # restore toolbar manager state |
|
685 splash.showMessage(self.tr("Restoring Toolbarmanager...")) |
|
686 self.toolbarManager.restoreState( |
|
687 Preferences.getUI("ToolbarManagerState")) |
|
688 |
|
689 if self.codeDocumentationViewer is not None: |
|
690 # finalize the initialization of the code documentation viewer |
|
691 self.codeDocumentationViewer.finalizeSetup() |
|
692 |
|
693 # now activate the initial view profile |
|
694 splash.showMessage(self.tr("Setting View Profile...")) |
|
695 self.__setEditProfile() |
|
696 |
|
697 # special treatment for the VCS toolbars |
|
698 for tb in self.getToolbarsByCategory("vcs"): |
|
699 tb.setVisible(False) |
|
700 tb.setEnabled(False) |
|
701 tb = self.getToolbar("vcs")[1] |
|
702 tb.setEnabled(True) |
|
703 if Preferences.getVCS("ShowVcsToolbar"): |
|
704 tb.setVisible(True) |
|
705 |
|
706 # now read the saved tasks |
|
707 splash.showMessage(self.tr("Reading Tasks...")) |
|
708 self.__readTasks() |
|
709 |
|
710 if self.templateViewer is not None: |
|
711 # now read the saved templates |
|
712 splash.showMessage(self.tr("Reading Templates...")) |
|
713 self.templateViewer.readTemplates() |
|
714 |
|
715 # now start the debug client with the most recently used virtual |
|
716 # environment |
|
717 splash.showMessage(self.tr("Starting Debugger...")) |
|
718 if Preferences.getShell("StartWithMostRecentlyUsedEnvironment"): |
|
719 debugServer.startClient( |
|
720 False, venvName=Preferences.getShell("LastVirtualEnvironment") |
|
721 ) |
|
722 else: |
|
723 debugServer.startClient(False) |
|
724 |
|
725 # attributes for the network objects |
|
726 self.__networkManager = QNetworkAccessManager(self) |
|
727 self.__networkManager.proxyAuthenticationRequired.connect( |
|
728 proxyAuthenticationRequired) |
|
729 if SSL_AVAILABLE: |
|
730 self.__sslErrorHandler = E5SslErrorHandler(self) |
|
731 self.__networkManager.sslErrors.connect(self.__sslErrors) |
|
732 self.__replies = [] |
|
733 |
|
734 # set spellchecker defaults |
|
735 from QScintilla.SpellChecker import SpellChecker |
|
736 SpellChecker.setDefaultLanguage( |
|
737 Preferences.getEditor("SpellCheckingDefaultLanguage")) |
|
738 |
|
739 # attributes for the last shown configuration page and the |
|
740 # extended configuration entries |
|
741 self.__lastConfigurationPageName = "" |
|
742 self.__expandedConfigurationEntries = [] |
|
743 |
|
744 # set the keyboard input interval |
|
745 interval = Preferences.getUI("KeyboardInputInterval") |
|
746 if interval > 0: |
|
747 QApplication.setKeyboardInputInterval(interval) |
|
748 |
|
749 def networkAccessManager(self): |
|
750 """ |
|
751 Public method to get a reference to the network access manager object. |
|
752 |
|
753 @return reference to the network access manager object |
|
754 @rtype QNetworkAccessManager |
|
755 """ |
|
756 return self.__networkManager |
|
757 |
|
758 def __createLayout(self, debugServer): |
|
759 """ |
|
760 Private method to create the layout of the various windows. |
|
761 |
|
762 @param debugServer reference to the debug server object |
|
763 @exception ValueError raised to indicate an invalid layout type |
|
764 """ |
|
765 # Create the view manager depending on the configuration setting |
|
766 logging.debug("Creating Viewmanager...") |
|
767 import ViewManager |
|
768 self.viewmanager = ViewManager.factory( |
|
769 self, self, debugServer, self.pluginManager) |
|
770 leftWidget = QWidget() |
|
771 layout = QVBoxLayout() |
|
772 layout.setContentsMargins(1, 1, 1, 1) |
|
773 layout.setSpacing(1) |
|
774 layout.addWidget(self.viewmanager.mainWidget()) |
|
775 layout.addWidget(self.viewmanager.searchWidget()) |
|
776 layout.addWidget(self.viewmanager.replaceWidget()) |
|
777 self.viewmanager.mainWidget().setSizePolicy( |
|
778 QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding) |
|
779 leftWidget.setLayout(layout) |
|
780 self.viewmanager.searchWidget().hide() |
|
781 self.viewmanager.replaceWidget().hide() |
|
782 |
|
783 splitter = QSplitter(Qt.Orientation.Horizontal) |
|
784 splitter.addWidget(leftWidget) |
|
785 self.setCentralWidget(splitter) |
|
786 |
|
787 # Create previewer |
|
788 logging.debug("Creating Previewer...") |
|
789 from .Previewer import Previewer |
|
790 self.__previewer = Previewer(self.viewmanager, splitter) |
|
791 splitter.addWidget(self.__previewer) |
|
792 |
|
793 # Create AST viewer |
|
794 logging.debug("Creating Python AST Viewer") |
|
795 from .PythonAstViewer import PythonAstViewer |
|
796 self.__astViewer = PythonAstViewer(self.viewmanager, splitter) |
|
797 splitter.addWidget(self.__astViewer) |
|
798 |
|
799 # Create DIS viewer |
|
800 logging.debug("Creating Python Disassembly Viewer") |
|
801 from .PythonDisViewer import PythonDisViewer |
|
802 self.__disViewer = PythonDisViewer(self.viewmanager, parent=splitter) |
|
803 splitter.addWidget(self.__disViewer) |
|
804 |
|
805 # Create layout with toolbox windows embedded in dock windows |
|
806 if self.__layoutType == "Toolboxes": |
|
807 logging.debug("Creating toolboxes...") |
|
808 self.__createToolboxesLayout(debugServer) |
|
809 |
|
810 # Create layout with sidebar windows embedded in dock windows |
|
811 elif self.__layoutType == "Sidebars": |
|
812 logging.debug("Creating sidebars...") |
|
813 self.__createSidebarsLayout(debugServer) |
|
814 |
|
815 else: |
|
816 raise ValueError("Wrong layout type given ({0})".format( |
|
817 self.__layoutType)) |
|
818 logging.debug("Created Layout") |
|
819 |
|
820 def __createToolboxesLayout(self, debugServer): |
|
821 """ |
|
822 Private method to create the Toolboxes layout. |
|
823 |
|
824 @param debugServer reference to the debug server object |
|
825 """ |
|
826 from E5Gui.E5ToolBox import E5VerticalToolBox, E5HorizontalToolBox |
|
827 |
|
828 logging.debug("Creating Toolboxes Layout...") |
|
829 |
|
830 # Create the left toolbox |
|
831 self.lToolboxDock = self.__createDockWindow("lToolboxDock") |
|
832 self.lToolbox = E5VerticalToolBox(self.lToolboxDock) |
|
833 self.__setupDockWindow(self.lToolboxDock, |
|
834 Qt.DockWidgetArea.LeftDockWidgetArea, |
|
835 self.lToolbox, |
|
836 self.tr("Left Toolbox")) |
|
837 |
|
838 # Create the horizontal toolbox |
|
839 self.hToolboxDock = self.__createDockWindow("hToolboxDock") |
|
840 self.hToolbox = E5HorizontalToolBox(self.hToolboxDock) |
|
841 self.__setupDockWindow(self.hToolboxDock, |
|
842 Qt.DockWidgetArea.BottomDockWidgetArea, |
|
843 self.hToolbox, |
|
844 self.tr("Horizontal Toolbox")) |
|
845 |
|
846 # Create the right toolbox |
|
847 self.rToolboxDock = self.__createDockWindow("rToolboxDock") |
|
848 self.rToolbox = E5VerticalToolBox(self.rToolboxDock) |
|
849 self.__setupDockWindow(self.rToolboxDock, |
|
850 Qt.DockWidgetArea.RightDockWidgetArea, |
|
851 self.rToolbox, |
|
852 self.tr("Right Toolbox")) |
|
853 |
|
854 #################################################### |
|
855 ## Populate the left toolbox |
|
856 #################################################### |
|
857 |
|
858 # Create the project browser |
|
859 logging.debug("Creating Project Browser...") |
|
860 from Project.ProjectBrowser import ProjectBrowser |
|
861 self.projectBrowser = ProjectBrowser(self.project) |
|
862 self.lToolbox.addItem(self.projectBrowser, |
|
863 UI.PixmapCache.getIcon("projectViewer"), |
|
864 self.tr("Project-Viewer")) |
|
865 |
|
866 # Create the multi project browser |
|
867 logging.debug("Creating Multiproject Browser...") |
|
868 from MultiProject.MultiProjectBrowser import MultiProjectBrowser |
|
869 self.multiProjectBrowser = MultiProjectBrowser(self.multiProject, |
|
870 self.project) |
|
871 self.lToolbox.addItem(self.multiProjectBrowser, |
|
872 UI.PixmapCache.getIcon("multiProjectViewer"), |
|
873 self.tr("Multiproject-Viewer")) |
|
874 |
|
875 if Preferences.getUI("ShowTemplateViewer"): |
|
876 # Create the template viewer part of the user interface |
|
877 logging.debug("Creating Template Viewer...") |
|
878 from Templates.TemplateViewer import TemplateViewer |
|
879 self.templateViewer = TemplateViewer(None, |
|
880 self.viewmanager) |
|
881 self.lToolbox.addItem(self.templateViewer, |
|
882 UI.PixmapCache.getIcon("templateViewer"), |
|
883 self.tr("Template-Viewer")) |
|
884 |
|
885 #################################################### |
|
886 ## Populate the right toolbox |
|
887 #################################################### |
|
888 |
|
889 if Preferences.getUI("ShowCodeDocumentationViewer"): |
|
890 # Create the code documentation viewer |
|
891 logging.debug("Creating Code Documentation Viewer...") |
|
892 from .CodeDocumentationViewer import CodeDocumentationViewer |
|
893 self.codeDocumentationViewer = CodeDocumentationViewer(self) |
|
894 self.rToolbox.addItem(self.codeDocumentationViewer, |
|
895 UI.PixmapCache.getIcon("codeDocuViewer"), |
|
896 self.tr("Code Documentation Viewer")) |
|
897 |
|
898 # Create the debug viewer |
|
899 logging.debug("Creating Debug Viewer...") |
|
900 from Debugger.DebugViewer import DebugViewer |
|
901 self.debugViewer = DebugViewer(debugServer) |
|
902 self.rToolbox.addItem(self.debugViewer, |
|
903 UI.PixmapCache.getIcon("debugViewer"), |
|
904 self.tr("Debug-Viewer")) |
|
905 |
|
906 if Preferences.getUI("ShowPyPIPackageManager"): |
|
907 # Create the PyPI package manager |
|
908 logging.debug("Creating PyPI Package Manager...") |
|
909 from PipInterface.PipPackagesWidget import PipPackagesWidget |
|
910 self.pipWidget = PipPackagesWidget(self.pipInterface) |
|
911 self.rToolbox.addItem(self.pipWidget, |
|
912 UI.PixmapCache.getIcon("pypi"), |
|
913 self.tr("PyPI")) |
|
914 |
|
915 if Preferences.getUI("ShowCondaPackageManager"): |
|
916 # Create the conda package manager |
|
917 logging.debug("Creating Conda Package Manager...") |
|
918 from CondaInterface.CondaPackagesWidget import CondaPackagesWidget |
|
919 self.condaWidget = CondaPackagesWidget(self.condaInterface) |
|
920 self.rToolbox.addItem(self.condaWidget, |
|
921 UI.PixmapCache.getIcon("miniconda"), |
|
922 self.tr("Conda")) |
|
923 |
|
924 if Preferences.getUI("ShowCooperation"): |
|
925 # Create the chat part of the user interface |
|
926 logging.debug("Creating Chat Widget...") |
|
927 from Cooperation.ChatWidget import ChatWidget |
|
928 self.cooperation = ChatWidget(self) |
|
929 self.rToolbox.addItem(self.cooperation, |
|
930 UI.PixmapCache.getIcon("cooperation"), |
|
931 self.tr("Cooperation")) |
|
932 |
|
933 if Preferences.getUI("ShowIrc"): |
|
934 # Create the IRC part of the user interface |
|
935 logging.debug("Creating IRC Widget...") |
|
936 from Network.IRC.IrcWidget import IrcWidget |
|
937 self.irc = IrcWidget(self) |
|
938 self.rToolbox.addItem(self.irc, |
|
939 UI.PixmapCache.getIcon("irc"), |
|
940 self.tr("IRC")) |
|
941 |
|
942 if Preferences.getUI("ShowMicroPython"): |
|
943 # Create the MicroPython part of the user interface |
|
944 logging.debug("Creating MicroPython Widget...") |
|
945 from MicroPython.MicroPythonWidget import MicroPythonWidget |
|
946 self.microPythonWidget = MicroPythonWidget(self) |
|
947 self.rToolbox.addItem(self.microPythonWidget, |
|
948 UI.PixmapCache.getIcon("micropython"), |
|
949 self.tr("MicroPython")) |
|
950 |
|
951 #################################################### |
|
952 ## Populate the bottom toolbox |
|
953 #################################################### |
|
954 |
|
955 # Create the task viewer part of the user interface |
|
956 logging.debug("Creating Task Viewer...") |
|
957 from Tasks.TaskViewer import TaskViewer |
|
958 self.taskViewer = TaskViewer(None, self.project) |
|
959 self.hToolbox.addItem(self.taskViewer, |
|
960 UI.PixmapCache.getIcon("task"), |
|
961 self.tr("Task-Viewer")) |
|
962 |
|
963 # Create the log viewer part of the user interface |
|
964 logging.debug("Creating Log Viewer...") |
|
965 from .LogView import LogViewer |
|
966 self.logViewer = LogViewer(self) |
|
967 self.hToolbox.addItem(self.logViewer, |
|
968 UI.PixmapCache.getIcon("logViewer"), |
|
969 self.tr("Log-Viewer")) |
|
970 |
|
971 if Preferences.getUI("ShowFileBrowser"): |
|
972 # Create the file browser |
|
973 logging.debug("Creating File Browser...") |
|
974 from .Browser import Browser |
|
975 self.browser = Browser() |
|
976 self.lToolbox.addItem(self.browser, |
|
977 UI.PixmapCache.getIcon("browser"), |
|
978 self.tr("File-Browser")) |
|
979 |
|
980 if Preferences.getUI("ShowSymbolsViewer"): |
|
981 # Create the symbols viewer |
|
982 logging.debug("Creating Symbols Viewer...") |
|
983 from .SymbolsWidget import SymbolsWidget |
|
984 self.symbolsViewer = SymbolsWidget() |
|
985 self.lToolbox.addItem(self.symbolsViewer, |
|
986 UI.PixmapCache.getIcon("symbols"), |
|
987 self.tr("Symbols")) |
|
988 |
|
989 if Preferences.getUI("ShowNumbersViewer"): |
|
990 # Create the numbers viewer |
|
991 logging.debug("Creating Numbers Viewer...") |
|
992 from .NumbersWidget import NumbersWidget |
|
993 self.numbersViewer = NumbersWidget() |
|
994 self.hToolbox.addItem(self.numbersViewer, |
|
995 UI.PixmapCache.getIcon("numbers"), |
|
996 self.tr("Numbers")) |
|
997 |
|
998 #################################################### |
|
999 ## Populate the configurable widgets |
|
1000 #################################################### |
|
1001 |
|
1002 # Create the shell |
|
1003 logging.debug("Creating Shell...") |
|
1004 self.__shellPosition = Preferences.getUI("ShellPosition") |
|
1005 if self.__shellPosition == "left": |
|
1006 self.__shellParent = self.lToolboxDock |
|
1007 elif self.__shellPosition == "right": |
|
1008 self.__shellParent = self.rToolboxDock |
|
1009 else: |
|
1010 self.__shellParent = self.hToolboxDock |
|
1011 from QScintilla.Shell import ShellAssembly |
|
1012 self.shellAssembly = ShellAssembly( |
|
1013 debugServer, self.viewmanager, self.project, True) |
|
1014 self.shell = self.shellAssembly.shell() |
|
1015 self.__shellParent.widget().insertItem( |
|
1016 0, self.shellAssembly, UI.PixmapCache.getIcon("shell"), |
|
1017 self.tr("Shell")) |
|
1018 |
|
1019 #################################################### |
|
1020 ## Set the start index of each toolbox |
|
1021 #################################################### |
|
1022 |
|
1023 self.lToolbox.setCurrentIndex(0) |
|
1024 self.rToolbox.setCurrentIndex(0) |
|
1025 self.hToolbox.setCurrentIndex(0) |
|
1026 |
|
1027 def __createSidebarsLayout(self, debugServer): |
|
1028 """ |
|
1029 Private method to create the Sidebars layout. |
|
1030 |
|
1031 @param debugServer reference to the debug server object |
|
1032 """ |
|
1033 from E5Gui.E5SideBar import E5SideBar, E5SideBarSide |
|
1034 |
|
1035 logging.debug("Creating Sidebars Layout...") |
|
1036 |
|
1037 delay = Preferences.getUI("SidebarDelay") |
|
1038 # Create the left sidebar |
|
1039 self.leftSidebar = E5SideBar(E5SideBarSide.WEST, delay) |
|
1040 |
|
1041 # Create the bottom sidebar |
|
1042 self.bottomSidebar = E5SideBar(E5SideBarSide.SOUTH, delay) |
|
1043 |
|
1044 # Create the right sidebar |
|
1045 self.rightSidebar = E5SideBar(E5SideBarSide.EAST, delay) |
|
1046 |
|
1047 #################################################### |
|
1048 ## Populate the left side bar |
|
1049 #################################################### |
|
1050 |
|
1051 # Create the project browser |
|
1052 logging.debug("Creating Project Browser...") |
|
1053 from Project.ProjectBrowser import ProjectBrowser |
|
1054 self.projectBrowser = ProjectBrowser(self.project) |
|
1055 self.leftSidebar.addTab( |
|
1056 self.projectBrowser, |
|
1057 UI.PixmapCache.getIcon("projectViewer"), |
|
1058 self.tr("Project-Viewer")) |
|
1059 |
|
1060 # Create the multi project browser |
|
1061 logging.debug("Creating Multiproject Browser...") |
|
1062 from MultiProject.MultiProjectBrowser import MultiProjectBrowser |
|
1063 self.multiProjectBrowser = MultiProjectBrowser(self.multiProject, |
|
1064 self.project) |
|
1065 self.leftSidebar.addTab( |
|
1066 self.multiProjectBrowser, |
|
1067 UI.PixmapCache.getIcon("multiProjectViewer"), |
|
1068 self.tr("Multiproject-Viewer")) |
|
1069 |
|
1070 if Preferences.getUI("ShowTemplateViewer"): |
|
1071 # Create the template viewer part of the user interface |
|
1072 logging.debug("Creating Template Viewer...") |
|
1073 from Templates.TemplateViewer import TemplateViewer |
|
1074 self.templateViewer = TemplateViewer(None, |
|
1075 self.viewmanager) |
|
1076 self.leftSidebar.addTab( |
|
1077 self.templateViewer, |
|
1078 UI.PixmapCache.getIcon("templateViewer"), |
|
1079 self.tr("Template-Viewer")) |
|
1080 |
|
1081 #################################################### |
|
1082 ## Populate the right side bar |
|
1083 #################################################### |
|
1084 |
|
1085 if Preferences.getUI("ShowCodeDocumentationViewer"): |
|
1086 # Create the code documentation viewer |
|
1087 logging.debug("Creating Code Documentation Viewer...") |
|
1088 from .CodeDocumentationViewer import CodeDocumentationViewer |
|
1089 self.codeDocumentationViewer = CodeDocumentationViewer(self) |
|
1090 self.rightSidebar.addTab( |
|
1091 self.codeDocumentationViewer, |
|
1092 UI.PixmapCache.getIcon("codeDocuViewer"), |
|
1093 self.tr("Code Documentation Viewer")) |
|
1094 |
|
1095 # Create the debug viewer |
|
1096 logging.debug("Creating Debug Viewer...") |
|
1097 from Debugger.DebugViewer import DebugViewer |
|
1098 self.debugViewer = DebugViewer(debugServer) |
|
1099 self.rightSidebar.addTab( |
|
1100 self.debugViewer, UI.PixmapCache.getIcon("debugViewer"), |
|
1101 self.tr("Debug-Viewer")) |
|
1102 |
|
1103 if Preferences.getUI("ShowPyPIPackageManager"): |
|
1104 # Create the PyPI package manager |
|
1105 logging.debug("Creating PyPI Package Manager...") |
|
1106 from PipInterface.PipPackagesWidget import PipPackagesWidget |
|
1107 self.pipWidget = PipPackagesWidget(self.pipInterface) |
|
1108 self.rightSidebar.addTab( |
|
1109 self.pipWidget, UI.PixmapCache.getIcon("pypi"), |
|
1110 self.tr("PyPI")) |
|
1111 |
|
1112 if Preferences.getUI("ShowCondaPackageManager"): |
|
1113 # Create the conda package manager |
|
1114 logging.debug("Creating Conda Package Manager...") |
|
1115 from CondaInterface.CondaPackagesWidget import CondaPackagesWidget |
|
1116 self.condaWidget = CondaPackagesWidget(self.condaInterface) |
|
1117 self.rightSidebar.addTab( |
|
1118 self.condaWidget, UI.PixmapCache.getIcon("miniconda"), |
|
1119 self.tr("Conda")) |
|
1120 |
|
1121 if Preferences.getUI("ShowCooperation"): |
|
1122 # Create the chat part of the user interface |
|
1123 logging.debug("Creating Chat Widget...") |
|
1124 from Cooperation.ChatWidget import ChatWidget |
|
1125 self.cooperation = ChatWidget(self) |
|
1126 self.rightSidebar.addTab( |
|
1127 self.cooperation, UI.PixmapCache.getIcon("cooperation"), |
|
1128 self.tr("Cooperation")) |
|
1129 |
|
1130 if Preferences.getUI("ShowIrc"): |
|
1131 # Create the IRC part of the user interface |
|
1132 logging.debug("Creating IRC Widget...") |
|
1133 from Network.IRC.IrcWidget import IrcWidget |
|
1134 self.irc = IrcWidget(self) |
|
1135 self.rightSidebar.addTab( |
|
1136 self.irc, UI.PixmapCache.getIcon("irc"), |
|
1137 self.tr("IRC")) |
|
1138 |
|
1139 if Preferences.getUI("ShowMicroPython"): |
|
1140 # Create the MicroPython part of the user interface |
|
1141 logging.debug("Creating MicroPython Widget...") |
|
1142 from MicroPython.MicroPythonWidget import MicroPythonWidget |
|
1143 self.microPythonWidget = MicroPythonWidget(self) |
|
1144 self.rightSidebar.addTab( |
|
1145 self.microPythonWidget, UI.PixmapCache.getIcon("micropython"), |
|
1146 self.tr("MicroPython")) |
|
1147 |
|
1148 #################################################### |
|
1149 ## Populate the bottom side bar |
|
1150 #################################################### |
|
1151 |
|
1152 # Create the task viewer part of the user interface |
|
1153 logging.debug("Creating Task Viewer...") |
|
1154 from Tasks.TaskViewer import TaskViewer |
|
1155 self.taskViewer = TaskViewer(None, self.project) |
|
1156 self.bottomSidebar.addTab(self.taskViewer, |
|
1157 UI.PixmapCache.getIcon("task"), |
|
1158 self.tr("Task-Viewer")) |
|
1159 |
|
1160 # Create the log viewer part of the user interface |
|
1161 logging.debug("Creating Log Viewer...") |
|
1162 from .LogView import LogViewer |
|
1163 self.logViewer = LogViewer(self) |
|
1164 self.bottomSidebar.addTab(self.logViewer, |
|
1165 UI.PixmapCache.getIcon("logViewer"), |
|
1166 self.tr("Log-Viewer")) |
|
1167 |
|
1168 if Preferences.getUI("ShowFileBrowser"): |
|
1169 # Create the file browser |
|
1170 logging.debug("Creating File Browser...") |
|
1171 from .Browser import Browser |
|
1172 self.browser = Browser() |
|
1173 self.leftSidebar.addTab(self.browser, |
|
1174 UI.PixmapCache.getIcon("browser"), |
|
1175 self.tr("File-Browser")) |
|
1176 |
|
1177 if Preferences.getUI("ShowSymbolsViewer"): |
|
1178 # Create the symbols viewer |
|
1179 logging.debug("Creating Symbols Viewer...") |
|
1180 from .SymbolsWidget import SymbolsWidget |
|
1181 self.symbolsViewer = SymbolsWidget() |
|
1182 self.leftSidebar.addTab(self.symbolsViewer, |
|
1183 UI.PixmapCache.getIcon("symbols"), |
|
1184 self.tr("Symbols")) |
|
1185 |
|
1186 if Preferences.getUI("ShowNumbersViewer"): |
|
1187 # Create the numbers viewer |
|
1188 logging.debug("Creating Numbers Viewer...") |
|
1189 from .NumbersWidget import NumbersWidget |
|
1190 self.numbersViewer = NumbersWidget() |
|
1191 self.bottomSidebar.addTab(self.numbersViewer, |
|
1192 UI.PixmapCache.getIcon("numbers"), |
|
1193 self.tr("Numbers")) |
|
1194 |
|
1195 #################################################### |
|
1196 ## Populate the configurable widgets |
|
1197 #################################################### |
|
1198 |
|
1199 # Create the shell |
|
1200 logging.debug("Creating Shell...") |
|
1201 self.__shellPosition = Preferences.getUI("ShellPosition") |
|
1202 if self.__shellPosition == "left": |
|
1203 self.__shellParent = self.leftSidebar |
|
1204 elif self.__shellPosition == "right": |
|
1205 self.__shellParent = self.rightSidebar |
|
1206 else: |
|
1207 self.__shellParent = self.bottomSidebar |
|
1208 from QScintilla.Shell import ShellAssembly |
|
1209 self.shellAssembly = ShellAssembly( |
|
1210 debugServer, self.viewmanager, self.project, True) |
|
1211 self.shell = self.shellAssembly.shell() |
|
1212 self.__shellParent.insertTab(0, self.shellAssembly, |
|
1213 UI.PixmapCache.getIcon("shell"), |
|
1214 self.tr("Shell")) |
|
1215 |
|
1216 #################################################### |
|
1217 ## Set the start index of each side bar |
|
1218 #################################################### |
|
1219 |
|
1220 self.leftSidebar.setCurrentIndex(0) |
|
1221 self.rightSidebar.setCurrentIndex(0) |
|
1222 self.bottomSidebar.setCurrentIndex(0) |
|
1223 |
|
1224 # create the central widget |
|
1225 logging.debug("Creating central widget...") |
|
1226 cw = self.centralWidget() # save the current central widget |
|
1227 self.leftSplitter = QSplitter(Qt.Orientation.Horizontal) |
|
1228 self.rightSplitter = QSplitter(Qt.Orientation.Horizontal) |
|
1229 self.verticalSplitter = QSplitter(Qt.Orientation.Vertical) |
|
1230 self.verticalSplitter.addWidget(cw) |
|
1231 self.verticalSplitter.addWidget(self.bottomSidebar) |
|
1232 self.rightSplitter.addWidget(self.verticalSplitter) |
|
1233 self.rightSplitter.addWidget(self.rightSidebar) |
|
1234 self.leftSplitter.addWidget(self.leftSidebar) |
|
1235 self.leftSplitter.addWidget(self.rightSplitter) |
|
1236 self.setCentralWidget(self.leftSplitter) |
|
1237 |
|
1238 self.leftSidebar.setSplitter(self.leftSplitter) |
|
1239 self.rightSidebar.setSplitter(self.rightSplitter) |
|
1240 self.bottomSidebar.setSplitter(self.verticalSplitter) |
|
1241 |
|
1242 def addSideWidget(self, side, widget, icon, label): |
|
1243 """ |
|
1244 Public method to add a widget to the sides. |
|
1245 |
|
1246 @param side side to add the widget to |
|
1247 @type int (one of UserInterface.LeftSide, UserInterface.BottomSide, |
|
1248 UserInterface.RightSide) |
|
1249 @param widget reference to the widget to add |
|
1250 @type QWidget |
|
1251 @param icon icon to be used |
|
1252 @type QIcon |
|
1253 @param label label text to be shown |
|
1254 @type str |
|
1255 """ |
|
1256 if side in [UserInterface.LeftSide, UserInterface.BottomSide, |
|
1257 UserInterface.RightSide]: |
|
1258 if self.__layoutType == "Toolboxes": |
|
1259 if side == UserInterface.LeftSide: |
|
1260 self.lToolbox.addItem(widget, icon, label) |
|
1261 elif side == UserInterface.BottomSide: |
|
1262 self.hToolbox.addItem(widget, icon, label) |
|
1263 elif side == UserInterface.RightSide: |
|
1264 self.rToolbox.addItem(widget, icon, label) |
|
1265 elif self.__layoutType == "Sidebars": |
|
1266 if side == UserInterface.LeftSide: |
|
1267 self.leftSidebar.addTab(widget, icon, label) |
|
1268 elif side == UserInterface.BottomSide: |
|
1269 self.bottomSidebar.addTab(widget, icon, label) |
|
1270 elif side == UserInterface.RightSide: |
|
1271 self.rightSidebar.addTab(widget, icon, label) |
|
1272 |
|
1273 def removeSideWidget(self, widget): |
|
1274 """ |
|
1275 Public method to remove a widget added using addSideWidget(). |
|
1276 |
|
1277 @param widget reference to the widget to remove |
|
1278 @type QWidget |
|
1279 """ |
|
1280 if self.__layoutType == "Toolboxes": |
|
1281 for container in [self.lToolbox, self.hToolbox, self.rToolbox]: |
|
1282 index = container.indexOf(widget) |
|
1283 if index != -1: |
|
1284 container.removeItem(index) |
|
1285 elif self.__layoutType == "Sidebars": |
|
1286 for container in [self.leftSidebar, self.bottomSidebar, |
|
1287 self.rightSidebar]: |
|
1288 index = container.indexOf(widget) |
|
1289 if index != -1: |
|
1290 container.removeTab(index) |
|
1291 |
|
1292 def showSideWidget(self, widget): |
|
1293 """ |
|
1294 Public method to show a specific widget placed in the side widgets. |
|
1295 |
|
1296 @param widget reference to the widget to be shown |
|
1297 @type QWidget |
|
1298 """ |
|
1299 if self.__layoutType == "Toolboxes": |
|
1300 for dock in [self.lToolboxDock, self.hToolboxDock, |
|
1301 self.rToolboxDock]: |
|
1302 container = dock.widget() |
|
1303 index = container.indexOf(widget) |
|
1304 if index != -1: |
|
1305 dock.show() |
|
1306 container.setCurrentIndex(index) |
|
1307 dock.raise_() |
|
1308 elif self.__layoutType == "Sidebars": |
|
1309 for container in [self.leftSidebar, self.bottomSidebar, |
|
1310 self.rightSidebar]: |
|
1311 index = container.indexOf(widget) |
|
1312 if index != -1: |
|
1313 container.show() |
|
1314 container.setCurrentIndex(index) |
|
1315 container.raise_() |
|
1316 if container.isAutoHiding(): |
|
1317 container.setFocus() |
|
1318 |
|
1319 def showLogViewer(self): |
|
1320 """ |
|
1321 Public method to show the Log-Viewer. |
|
1322 """ |
|
1323 if Preferences.getUI("LogViewerAutoRaise"): |
|
1324 if self.__layoutType == "Toolboxes": |
|
1325 self.hToolboxDock.show() |
|
1326 self.hToolbox.setCurrentWidget(self.logViewer) |
|
1327 self.hToolboxDock.raise_() |
|
1328 elif self.__layoutType == "Sidebars": |
|
1329 self.bottomSidebar.show() |
|
1330 self.bottomSidebar.setCurrentWidget(self.logViewer) |
|
1331 self.bottomSidebar.raise_() |
|
1332 if self.bottomSidebar.isAutoHiding(): |
|
1333 self.bottomSidebar.setFocus() |
|
1334 |
|
1335 def __openOnStartup(self, startupType=None): |
|
1336 """ |
|
1337 Private method to open the last file, project or multiproject. |
|
1338 |
|
1339 @param startupType type of startup requested (string, one of |
|
1340 "Nothing", "File", "Project", "MultiProject" or "Session") |
|
1341 """ |
|
1342 startupTypeMapping = { |
|
1343 "Nothing": 0, |
|
1344 "File": 1, |
|
1345 "Project": 2, |
|
1346 "MultiProject": 3, |
|
1347 "Session": 4, |
|
1348 } |
|
1349 |
|
1350 if startupType is None: |
|
1351 startup = Preferences.getUI("OpenOnStartup") |
|
1352 else: |
|
1353 try: |
|
1354 startup = startupTypeMapping[startupType] |
|
1355 except KeyError: |
|
1356 startup = Preferences.getUI("OpenOnStartup") |
|
1357 |
|
1358 if startup == 0: |
|
1359 # open nothing |
|
1360 pass |
|
1361 elif startup == 1: |
|
1362 # open last file |
|
1363 recent = self.viewmanager.getMostRecent() |
|
1364 if recent is not None: |
|
1365 self.viewmanager.openFiles(recent) |
|
1366 elif startup == 2: |
|
1367 # open last project |
|
1368 recent = self.project.getMostRecent() |
|
1369 if recent is not None: |
|
1370 self.project.openProject(recent) |
|
1371 elif startup == 3: |
|
1372 # open last multiproject |
|
1373 recent = self.multiProject.getMostRecent() |
|
1374 if recent is not None: |
|
1375 self.multiProject.openMultiProject(recent) |
|
1376 elif startup == 4: |
|
1377 # open from session file |
|
1378 self.__readSession() |
|
1379 |
|
1380 def processArgs(self, args): |
|
1381 """ |
|
1382 Public method to process the command line args passed to the UI. |
|
1383 |
|
1384 @param args list of files to open<br /> |
|
1385 The args are processed one at a time. All arguments after a |
|
1386 '--' option are considered debug arguments to the program |
|
1387 for the debugger. All files named before the '--' option |
|
1388 are opened in a text editor, unless the argument ends in |
|
1389 .epj or .e4p, then it is opened as a project file. If it |
|
1390 ends in .emj, .e4m or .e5m, it is opened as a multi project. |
|
1391 """ |
|
1392 # check and optionally read a crash session and ignore any arguments |
|
1393 if self.__readCrashSession(): |
|
1394 return |
|
1395 |
|
1396 # no args, return |
|
1397 if args is None: |
|
1398 if self.__openAtStartup: |
|
1399 self.__openOnStartup() |
|
1400 return |
|
1401 |
|
1402 opens = 0 |
|
1403 |
|
1404 # holds space delimited list of command args, if any |
|
1405 argsStr = None |
|
1406 # flag indicating '--' options was found |
|
1407 ddseen = False |
|
1408 |
|
1409 argChars = ['-', '/'] if Utilities.isWindowsPlatform() else ['-'] |
|
1410 |
|
1411 for arg in args: |
|
1412 # handle a request to start with last session |
|
1413 if arg == '--start-file': |
|
1414 self.__openOnStartup("File") |
|
1415 # ignore all further arguments |
|
1416 return |
|
1417 elif arg == '--start-multi': |
|
1418 self.__openOnStartup("MultiProject") |
|
1419 # ignore all further arguments |
|
1420 return |
|
1421 elif arg == '--start-project': |
|
1422 self.__openOnStartup("Project") |
|
1423 # ignore all further arguments |
|
1424 return |
|
1425 elif arg == '--start-session': |
|
1426 self.__openOnStartup("Session") |
|
1427 # ignore all further arguments |
|
1428 return |
|
1429 |
|
1430 if arg == '--' and not ddseen: |
|
1431 ddseen = True |
|
1432 continue |
|
1433 |
|
1434 if arg[0] in argChars or ddseen: |
|
1435 if argsStr is None: |
|
1436 argsStr = arg |
|
1437 else: |
|
1438 argsStr = "{0} {1}".format(argsStr, arg) |
|
1439 continue |
|
1440 |
|
1441 try: |
|
1442 ext = os.path.splitext(arg)[1] |
|
1443 ext = os.path.normcase(ext) |
|
1444 except IndexError: |
|
1445 ext = "" |
|
1446 |
|
1447 if ext in ('.epj', '.e4p'): |
|
1448 self.project.openProject(arg) |
|
1449 opens += 1 |
|
1450 elif ext in ('.emj', '.e4m', '.e5m'): |
|
1451 self.multiProject.openMultiProject(arg) |
|
1452 opens += 1 |
|
1453 else: |
|
1454 self.viewmanager.openFiles(arg) |
|
1455 opens += 1 |
|
1456 |
|
1457 # store away any args we had |
|
1458 if argsStr is not None: |
|
1459 self.debuggerUI.setArgvHistory(argsStr) |
|
1460 |
|
1461 if opens == 0 and self.__openAtStartup: |
|
1462 # no files, project or multiproject was given |
|
1463 self.__openOnStartup() |
|
1464 |
|
1465 def processInstallInfoFile(self): |
|
1466 """ |
|
1467 Public method to process the file containing installation information. |
|
1468 """ |
|
1469 import Globals |
|
1470 |
|
1471 installInfoFile = Globals.getInstallInfoFilePath() |
|
1472 if not os.path.exists(installInfoFile): |
|
1473 filename = os.path.join(getConfig("ericDir"), "eric6install.json") |
|
1474 if os.path.exists(filename): |
|
1475 # eric was installed via the install.py script |
|
1476 shutil.copy2(filename, installInfoFile) |
|
1477 else: |
|
1478 filename = os.path.join(getConfig("ericDir"), |
|
1479 "eric6installpip.json") |
|
1480 if os.path.exists(filename): |
|
1481 # eric was installed via pip (i.e. eric-ide) |
|
1482 with contextlib.suppress(OSError): |
|
1483 installDateTime = datetime.datetime.now(tz=None) |
|
1484 with open(filename, "r") as infoFile: |
|
1485 installInfo = json.load(infoFile) |
|
1486 installInfo["guessed"] = True |
|
1487 installInfo["eric"] = getConfig("ericDir") |
|
1488 installInfo["virtualenv"] = ( |
|
1489 installInfo["eric"].startswith( |
|
1490 os.path.expanduser("~")) |
|
1491 ) |
|
1492 if installInfo["virtualenv"]: |
|
1493 installInfo["user"] = getpass.getuser() |
|
1494 installInfo["exe"] = sys.executable |
|
1495 installInfo["installed"] = True |
|
1496 installInfo["installed_on"] = installDateTime.strftime( |
|
1497 "%Y-%m-%d %H:%M:%S") |
|
1498 installInfo["sudo"] = not os.access( |
|
1499 installInfo["eric"], os.W_OK) |
|
1500 with open(installInfoFile, "w") as infoFile: |
|
1501 json.dump(installInfo, infoFile, indent=2) |
|
1502 else: |
|
1503 changed = False |
|
1504 with open(installInfoFile, "r") as infoFile: |
|
1505 installInfo = json.load(infoFile) |
|
1506 |
|
1507 # 1. adapt stored file to latest format |
|
1508 if "install_cwd" not in installInfo: |
|
1509 installInfo["install_cwd"] = "" |
|
1510 installInfo["install_cwd_edited"] = False |
|
1511 changed = True |
|
1512 if "installed_on" not in installInfo: |
|
1513 installInfo["installed_on"] = "" |
|
1514 changed = True |
|
1515 |
|
1516 # 2. merge new data into stored file |
|
1517 filename = os.path.join(getConfig("ericDir"), "eric6install.json") |
|
1518 if os.path.exists(filename): |
|
1519 # eric was updated via the install.py script |
|
1520 if ( |
|
1521 os.path.getmtime(filename) > |
|
1522 os.path.getmtime(installInfoFile) |
|
1523 ): |
|
1524 if not installInfo["edited"]: |
|
1525 shutil.copy2(filename, installInfoFile) |
|
1526 else: |
|
1527 with open(filename, "r") as infoFile: |
|
1528 installInfo2 = json.load(infoFile) |
|
1529 if not installInfo["install_cwd_edited"]: |
|
1530 installInfo2["install_cwd"] = installInfo[ |
|
1531 "install_cwd"] |
|
1532 if not installInfo["exe_edited"]: |
|
1533 installInfo2["exe"] = installInfo["exe"] |
|
1534 if not installInfo["argv_edited"]: |
|
1535 installInfo2["argv"] = installInfo["argv"] |
|
1536 if not installInfo["eric_edited"]: |
|
1537 installInfo2["eric"] = installInfo["eric"] |
|
1538 installInfo = installInfo2 |
|
1539 changed = True |
|
1540 else: |
|
1541 filename = os.path.join(getConfig("ericDir"), |
|
1542 "eric6installpip.json") |
|
1543 if os.path.exists(filename): |
|
1544 # eric was updated via pip (i.e. eric-ide) |
|
1545 # just update the installation date and time |
|
1546 installDateTime = datetime.datetime.now(tz=None) |
|
1547 installInfo["installed_on"] = installDateTime.strftime( |
|
1548 "%Y-%m-%d %H:%M:%S") |
|
1549 changed = True |
|
1550 |
|
1551 if changed: |
|
1552 with open(installInfoFile, "w") as infoFile: |
|
1553 json.dump(installInfo, infoFile, indent=2) |
|
1554 |
|
1555 def __createDockWindow(self, name): |
|
1556 """ |
|
1557 Private method to create a dock window with common properties. |
|
1558 |
|
1559 @param name object name of the new dock window (string) |
|
1560 @return the generated dock window (QDockWindow) |
|
1561 """ |
|
1562 dock = QDockWidget() |
|
1563 dock.setObjectName(name) |
|
1564 dock.setFeatures( |
|
1565 QDockWidget.DockWidgetFeatures( |
|
1566 QDockWidget.DockWidgetFeature.DockWidgetClosable | |
|
1567 QDockWidget.DockWidgetFeature.DockWidgetMovable | |
|
1568 QDockWidget.DockWidgetFeature.DockWidgetFloatable |
|
1569 ) |
|
1570 ) |
|
1571 return dock |
|
1572 |
|
1573 def __setupDockWindow(self, dock, where, widget, caption): |
|
1574 """ |
|
1575 Private method to configure the dock window created with |
|
1576 __createDockWindow(). |
|
1577 |
|
1578 @param dock the dock window (QDockWindow) |
|
1579 @param where dock area to be docked to (Qt.DockWidgetArea) |
|
1580 @param widget widget to be shown in the dock window (QWidget) |
|
1581 @param caption caption of the dock window (string) |
|
1582 """ |
|
1583 if caption is None: |
|
1584 caption = "" |
|
1585 self.addDockWidget(where, dock) |
|
1586 dock.setWidget(widget) |
|
1587 dock.setWindowTitle(caption) |
|
1588 dock.show() |
|
1589 |
|
1590 def __setWindowCaption(self, editor=None, project=None): |
|
1591 """ |
|
1592 Private method to set the caption of the Main Window. |
|
1593 |
|
1594 @param editor filename to be displayed (string) |
|
1595 @param project project name to be displayed (string) |
|
1596 """ |
|
1597 if editor is not None and self.captionShowsFilename: |
|
1598 self.capEditor = Utilities.compactPath(editor, self.maxFilePathLen) |
|
1599 if project is not None: |
|
1600 self.capProject = project |
|
1601 |
|
1602 if self.passiveMode: |
|
1603 if not self.capProject and not self.capEditor: |
|
1604 self.setWindowTitle( |
|
1605 self.tr("{0} - Passive Mode").format(Program)) |
|
1606 elif self.capProject and not self.capEditor: |
|
1607 self.setWindowTitle( |
|
1608 self.tr("{0} - {1} - Passive Mode") |
|
1609 .format(self.capProject, Program)) |
|
1610 elif not self.capProject and self.capEditor: |
|
1611 self.setWindowTitle( |
|
1612 self.tr("{0} - {1} - Passive Mode") |
|
1613 .format(self.capEditor, Program)) |
|
1614 else: |
|
1615 self.setWindowTitle( |
|
1616 self.tr("{0} - {1} - {2} - Passive Mode") |
|
1617 .format(self.capProject, self.capEditor, Program)) |
|
1618 else: |
|
1619 if not self.capProject and not self.capEditor: |
|
1620 self.setWindowTitle(Program) |
|
1621 elif self.capProject and not self.capEditor: |
|
1622 self.setWindowTitle( |
|
1623 "{0} - {1}".format(self.capProject, Program)) |
|
1624 elif not self.capProject and self.capEditor: |
|
1625 self.setWindowTitle( |
|
1626 "{0} - {1}".format(self.capEditor, Program)) |
|
1627 else: |
|
1628 self.setWindowTitle("{0} - {1} - {2}".format( |
|
1629 self.capProject, self.capEditor, Program)) |
|
1630 |
|
1631 def __initActions(self): |
|
1632 """ |
|
1633 Private method to define the user interface actions. |
|
1634 """ |
|
1635 self.actions = [] |
|
1636 self.wizardsActions = [] |
|
1637 |
|
1638 self.exitAct = E5Action( |
|
1639 self.tr('Quit'), |
|
1640 UI.PixmapCache.getIcon("exit"), |
|
1641 self.tr('&Quit'), |
|
1642 QKeySequence(self.tr("Ctrl+Q", "File|Quit")), |
|
1643 0, self, 'quit') |
|
1644 self.exitAct.setStatusTip(self.tr('Quit the IDE')) |
|
1645 self.exitAct.setWhatsThis(self.tr( |
|
1646 """<b>Quit the IDE</b>""" |
|
1647 """<p>This quits the IDE. Any unsaved changes may be saved""" |
|
1648 """ first. Any Python program being debugged will be stopped""" |
|
1649 """ and the preferences will be written to disc.</p>""" |
|
1650 )) |
|
1651 self.exitAct.triggered.connect(self.__quit) |
|
1652 self.exitAct.setMenuRole(QAction.MenuRole.QuitRole) |
|
1653 self.actions.append(self.exitAct) |
|
1654 |
|
1655 self.restartAct = E5Action( |
|
1656 self.tr('Restart'), |
|
1657 UI.PixmapCache.getIcon("restart"), |
|
1658 self.tr('Restart'), |
|
1659 QKeySequence(self.tr("Ctrl+Shift+Q", "File|Quit")), |
|
1660 0, self, 'restart_eric') |
|
1661 self.restartAct.setStatusTip(self.tr('Restart the IDE')) |
|
1662 self.restartAct.setWhatsThis(self.tr( |
|
1663 """<b>Restart the IDE</b>""" |
|
1664 """<p>This restarts the IDE. Any unsaved changes may be saved""" |
|
1665 """ first. Any Python program being debugged will be stopped""" |
|
1666 """ and the preferences will be written to disc.</p>""" |
|
1667 )) |
|
1668 self.restartAct.triggered.connect(self.__restart) |
|
1669 self.actions.append(self.restartAct) |
|
1670 |
|
1671 self.saveSessionAct = E5Action( |
|
1672 self.tr('Save session'), |
|
1673 self.tr('Save session...'), |
|
1674 0, 0, self, 'save_session_to_file') |
|
1675 self.saveSessionAct.setStatusTip(self.tr('Save session')) |
|
1676 self.saveSessionAct.setWhatsThis(self.tr( |
|
1677 """<b>Save session...</b>""" |
|
1678 """<p>This saves the current session to disk. A dialog is""" |
|
1679 """ opened to select the file name.</p>""" |
|
1680 )) |
|
1681 self.saveSessionAct.triggered.connect(self.__saveSessionToFile) |
|
1682 self.actions.append(self.saveSessionAct) |
|
1683 |
|
1684 self.loadSessionAct = E5Action( |
|
1685 self.tr('Load session'), |
|
1686 self.tr('Load session...'), |
|
1687 0, 0, self, 'load_session_from_file') |
|
1688 self.loadSessionAct.setStatusTip(self.tr('Load session')) |
|
1689 self.loadSessionAct.setWhatsThis(self.tr( |
|
1690 """<b>Load session...</b>""" |
|
1691 """<p>This loads a session saved to disk previously. A dialog is""" |
|
1692 """ opened to select the file name.</p>""" |
|
1693 )) |
|
1694 self.loadSessionAct.triggered.connect(self.__loadSessionFromFile) |
|
1695 self.actions.append(self.loadSessionAct) |
|
1696 |
|
1697 self.newWindowAct = E5Action( |
|
1698 self.tr('New Window'), |
|
1699 UI.PixmapCache.getIcon("newWindow"), |
|
1700 self.tr('New &Window'), |
|
1701 QKeySequence(self.tr("Ctrl+Shift+N", "File|New Window")), |
|
1702 0, self, 'new_window') |
|
1703 self.newWindowAct.setStatusTip(self.tr( |
|
1704 'Open a new eric instance')) |
|
1705 self.newWindowAct.setWhatsThis(self.tr( |
|
1706 """<b>New Window</b>""" |
|
1707 """<p>This opens a new instance of the eric IDE.</p>""" |
|
1708 )) |
|
1709 self.newWindowAct.triggered.connect(self.__newWindow) |
|
1710 self.actions.append(self.newWindowAct) |
|
1711 self.newWindowAct.setEnabled( |
|
1712 not Preferences.getUI("SingleApplicationMode")) |
|
1713 |
|
1714 self.viewProfileActGrp = createActionGroup(self, "viewprofiles", True) |
|
1715 |
|
1716 self.setEditProfileAct = E5Action( |
|
1717 self.tr('Edit Profile'), |
|
1718 UI.PixmapCache.getIcon("viewProfileEdit"), |
|
1719 self.tr('Edit Profile'), |
|
1720 0, 0, |
|
1721 self.viewProfileActGrp, 'edit_profile', True) |
|
1722 self.setEditProfileAct.setStatusTip(self.tr( |
|
1723 'Activate the edit view profile')) |
|
1724 self.setEditProfileAct.setWhatsThis(self.tr( |
|
1725 """<b>Edit Profile</b>""" |
|
1726 """<p>Activate the "Edit View Profile". Windows being shown,""" |
|
1727 """ if this profile is active, may be configured with the""" |
|
1728 """ "View Profile Configuration" dialog.</p>""" |
|
1729 )) |
|
1730 self.setEditProfileAct.triggered.connect(self.__setEditProfile) |
|
1731 self.actions.append(self.setEditProfileAct) |
|
1732 |
|
1733 self.setDebugProfileAct = E5Action( |
|
1734 self.tr('Debug Profile'), |
|
1735 UI.PixmapCache.getIcon("viewProfileDebug"), |
|
1736 self.tr('Debug Profile'), |
|
1737 0, 0, |
|
1738 self.viewProfileActGrp, 'debug_profile', True) |
|
1739 self.setDebugProfileAct.setStatusTip( |
|
1740 self.tr('Activate the debug view profile')) |
|
1741 self.setDebugProfileAct.setWhatsThis(self.tr( |
|
1742 """<b>Debug Profile</b>""" |
|
1743 """<p>Activate the "Debug View Profile". Windows being shown,""" |
|
1744 """ if this profile is active, may be configured with the""" |
|
1745 """ "View Profile Configuration" dialog.</p>""" |
|
1746 )) |
|
1747 self.setDebugProfileAct.triggered.connect(self.setDebugProfile) |
|
1748 self.actions.append(self.setDebugProfileAct) |
|
1749 |
|
1750 self.pbActivateAct = E5Action( |
|
1751 self.tr('Project-Viewer'), |
|
1752 self.tr('&Project-Viewer'), |
|
1753 QKeySequence(self.tr("Alt+Shift+P")), |
|
1754 0, self, |
|
1755 'project_viewer_activate') |
|
1756 self.pbActivateAct.setStatusTip(self.tr( |
|
1757 "Switch the input focus to the Project-Viewer window.")) |
|
1758 self.pbActivateAct.setWhatsThis(self.tr( |
|
1759 """<b>Activate Project-Viewer</b>""" |
|
1760 """<p>This switches the input focus to the Project-Viewer""" |
|
1761 """ window.</p>""" |
|
1762 )) |
|
1763 self.pbActivateAct.triggered.connect(self.__activateProjectBrowser) |
|
1764 self.actions.append(self.pbActivateAct) |
|
1765 self.addAction(self.pbActivateAct) |
|
1766 |
|
1767 self.mpbActivateAct = E5Action( |
|
1768 self.tr('Multiproject-Viewer'), |
|
1769 self.tr('&Multiproject-Viewer'), |
|
1770 QKeySequence(self.tr("Alt+Shift+M")), |
|
1771 0, self, |
|
1772 'multi_project_viewer_activate') |
|
1773 self.mpbActivateAct.setStatusTip(self.tr( |
|
1774 "Switch the input focus to the Multiproject-Viewer window.")) |
|
1775 self.mpbActivateAct.setWhatsThis(self.tr( |
|
1776 """<b>Activate Multiproject-Viewer</b>""" |
|
1777 """<p>This switches the input focus to the Multiproject-Viewer""" |
|
1778 """ window.</p>""" |
|
1779 )) |
|
1780 self.mpbActivateAct.triggered.connect( |
|
1781 self.__activateMultiProjectBrowser) |
|
1782 self.actions.append(self.mpbActivateAct) |
|
1783 self.addAction(self.mpbActivateAct) |
|
1784 |
|
1785 self.debugViewerActivateAct = E5Action( |
|
1786 self.tr('Debug-Viewer'), |
|
1787 self.tr('&Debug-Viewer'), |
|
1788 QKeySequence(self.tr("Alt+Shift+D")), |
|
1789 0, self, |
|
1790 'debug_viewer_activate') |
|
1791 self.debugViewerActivateAct.setStatusTip(self.tr( |
|
1792 "Switch the input focus to the Debug-Viewer window.")) |
|
1793 self.debugViewerActivateAct.setWhatsThis(self.tr( |
|
1794 """<b>Activate Debug-Viewer</b>""" |
|
1795 """<p>This switches the input focus to the Debug-Viewer""" |
|
1796 """ window.</p>""" |
|
1797 )) |
|
1798 self.debugViewerActivateAct.triggered.connect( |
|
1799 self.activateDebugViewer) |
|
1800 self.actions.append(self.debugViewerActivateAct) |
|
1801 self.addAction(self.debugViewerActivateAct) |
|
1802 |
|
1803 self.shellActivateAct = E5Action( |
|
1804 self.tr('Shell'), |
|
1805 self.tr('&Shell'), |
|
1806 QKeySequence(self.tr("Alt+Shift+S")), |
|
1807 0, self, |
|
1808 'interpreter_shell_activate') |
|
1809 self.shellActivateAct.setStatusTip(self.tr( |
|
1810 "Switch the input focus to the Shell window.")) |
|
1811 self.shellActivateAct.setWhatsThis(self.tr( |
|
1812 """<b>Activate Shell</b>""" |
|
1813 """<p>This switches the input focus to the Shell window.</p>""" |
|
1814 )) |
|
1815 self.shellActivateAct.triggered.connect(self.__activateShell) |
|
1816 self.actions.append(self.shellActivateAct) |
|
1817 self.addAction(self.shellActivateAct) |
|
1818 |
|
1819 if self.browser is not None: |
|
1820 self.browserActivateAct = E5Action( |
|
1821 self.tr('File-Browser'), |
|
1822 self.tr('&File-Browser'), |
|
1823 QKeySequence(self.tr("Alt+Shift+F")), |
|
1824 0, self, |
|
1825 'file_browser_activate') |
|
1826 self.browserActivateAct.setStatusTip(self.tr( |
|
1827 "Switch the input focus to the File-Browser window.")) |
|
1828 self.browserActivateAct.setWhatsThis(self.tr( |
|
1829 """<b>Activate File-Browser</b>""" |
|
1830 """<p>This switches the input focus to the File-Browser""" |
|
1831 """ window.</p>""" |
|
1832 )) |
|
1833 self.browserActivateAct.triggered.connect(self.__activateBrowser) |
|
1834 self.actions.append(self.browserActivateAct) |
|
1835 self.addAction(self.browserActivateAct) |
|
1836 |
|
1837 self.logViewerActivateAct = E5Action( |
|
1838 self.tr('Log-Viewer'), |
|
1839 self.tr('Lo&g-Viewer'), |
|
1840 QKeySequence(self.tr("Alt+Shift+G")), |
|
1841 0, self, |
|
1842 'log_viewer_activate') |
|
1843 self.logViewerActivateAct.setStatusTip(self.tr( |
|
1844 "Switch the input focus to the Log-Viewer window.")) |
|
1845 self.logViewerActivateAct.setWhatsThis(self.tr( |
|
1846 """<b>Activate Log-Viewer</b>""" |
|
1847 """<p>This switches the input focus to the Log-Viewer""" |
|
1848 """ window.</p>""" |
|
1849 )) |
|
1850 self.logViewerActivateAct.triggered.connect( |
|
1851 self.__activateLogViewer) |
|
1852 self.actions.append(self.logViewerActivateAct) |
|
1853 self.addAction(self.logViewerActivateAct) |
|
1854 |
|
1855 self.taskViewerActivateAct = E5Action( |
|
1856 self.tr('Task-Viewer'), |
|
1857 self.tr('&Task-Viewer'), |
|
1858 QKeySequence(self.tr("Alt+Shift+T")), |
|
1859 0, self, |
|
1860 'task_viewer_activate') |
|
1861 self.taskViewerActivateAct.setStatusTip(self.tr( |
|
1862 "Switch the input focus to the Task-Viewer window.")) |
|
1863 self.taskViewerActivateAct.setWhatsThis(self.tr( |
|
1864 """<b>Activate Task-Viewer</b>""" |
|
1865 """<p>This switches the input focus to the Task-Viewer""" |
|
1866 """ window.</p>""" |
|
1867 )) |
|
1868 self.taskViewerActivateAct.triggered.connect( |
|
1869 self.__activateTaskViewer) |
|
1870 self.actions.append(self.taskViewerActivateAct) |
|
1871 self.addAction(self.taskViewerActivateAct) |
|
1872 |
|
1873 if self.templateViewer is not None: |
|
1874 self.templateViewerActivateAct = E5Action( |
|
1875 self.tr('Template-Viewer'), |
|
1876 self.tr('Templ&ate-Viewer'), |
|
1877 QKeySequence(self.tr("Alt+Shift+A")), |
|
1878 0, self, |
|
1879 'template_viewer_activate') |
|
1880 self.templateViewerActivateAct.setStatusTip(self.tr( |
|
1881 "Switch the input focus to the Template-Viewer window.")) |
|
1882 self.templateViewerActivateAct.setWhatsThis(self.tr( |
|
1883 """<b>Activate Template-Viewer</b>""" |
|
1884 """<p>This switches the input focus to the Template-Viewer""" |
|
1885 """ window.</p>""" |
|
1886 )) |
|
1887 self.templateViewerActivateAct.triggered.connect( |
|
1888 self.__activateTemplateViewer) |
|
1889 self.actions.append(self.templateViewerActivateAct) |
|
1890 self.addAction(self.templateViewerActivateAct) |
|
1891 |
|
1892 self.ltAct = E5Action( |
|
1893 self.tr('Left Toolbox'), |
|
1894 self.tr('&Left Toolbox'), 0, 0, self, 'vertical_toolbox', True) |
|
1895 self.ltAct.setStatusTip(self.tr('Toggle the Left Toolbox window')) |
|
1896 self.ltAct.setWhatsThis(self.tr( |
|
1897 """<b>Toggle the Left Toolbox window</b>""" |
|
1898 """<p>If the Left Toolbox window is hidden then display it.""" |
|
1899 """ If it is displayed then close it.</p>""" |
|
1900 )) |
|
1901 self.ltAct.triggered.connect(self.__toggleLeftToolbox) |
|
1902 self.actions.append(self.ltAct) |
|
1903 |
|
1904 self.rtAct = E5Action( |
|
1905 self.tr('Right Toolbox'), |
|
1906 self.tr('&Right Toolbox'), |
|
1907 0, 0, self, 'vertical_toolbox', True) |
|
1908 self.rtAct.setStatusTip(self.tr('Toggle the Right Toolbox window')) |
|
1909 self.rtAct.setWhatsThis(self.tr( |
|
1910 """<b>Toggle the Right Toolbox window</b>""" |
|
1911 """<p>If the Right Toolbox window is hidden then display it.""" |
|
1912 """ If it is displayed then close it.</p>""" |
|
1913 )) |
|
1914 self.rtAct.triggered.connect(self.__toggleRightToolbox) |
|
1915 self.actions.append(self.rtAct) |
|
1916 |
|
1917 self.htAct = E5Action( |
|
1918 self.tr('Horizontal Toolbox'), |
|
1919 self.tr('&Horizontal Toolbox'), 0, 0, self, |
|
1920 'horizontal_toolbox', True) |
|
1921 self.htAct.setStatusTip(self.tr( |
|
1922 'Toggle the Horizontal Toolbox window')) |
|
1923 self.htAct.setWhatsThis(self.tr( |
|
1924 """<b>Toggle the Horizontal Toolbox window</b>""" |
|
1925 """<p>If the Horizontal Toolbox window is hidden then display""" |
|
1926 """ it. If it is displayed then close it.</p>""" |
|
1927 )) |
|
1928 self.htAct.triggered.connect(self.__toggleHorizontalToolbox) |
|
1929 self.actions.append(self.htAct) |
|
1930 |
|
1931 self.lsbAct = E5Action( |
|
1932 self.tr('Left Sidebar'), |
|
1933 self.tr('&Left Sidebar'), |
|
1934 0, 0, self, 'left_sidebar', True) |
|
1935 self.lsbAct.setStatusTip(self.tr('Toggle the left sidebar window')) |
|
1936 self.lsbAct.setWhatsThis(self.tr( |
|
1937 """<b>Toggle the left sidebar window</b>""" |
|
1938 """<p>If the left sidebar window is hidden then display it.""" |
|
1939 """ If it is displayed then close it.</p>""" |
|
1940 )) |
|
1941 self.lsbAct.triggered.connect(self.__toggleLeftSidebar) |
|
1942 self.actions.append(self.lsbAct) |
|
1943 |
|
1944 self.rsbAct = E5Action( |
|
1945 self.tr('Right Sidebar'), |
|
1946 self.tr('&Right Sidebar'), |
|
1947 0, 0, self, 'right_sidebar', True) |
|
1948 self.rsbAct.setStatusTip(self.tr( |
|
1949 'Toggle the right sidebar window')) |
|
1950 self.rsbAct.setWhatsThis(self.tr( |
|
1951 """<b>Toggle the right sidebar window</b>""" |
|
1952 """<p>If the right sidebar window is hidden then display it.""" |
|
1953 """ If it is displayed then close it.</p>""" |
|
1954 )) |
|
1955 self.rsbAct.triggered.connect(self.__toggleRightSidebar) |
|
1956 self.actions.append(self.rsbAct) |
|
1957 |
|
1958 self.bsbAct = E5Action( |
|
1959 self.tr('Bottom Sidebar'), |
|
1960 self.tr('&Bottom Sidebar'), 0, 0, self, |
|
1961 'bottom_sidebar', True) |
|
1962 self.bsbAct.setStatusTip(self.tr( |
|
1963 'Toggle the bottom sidebar window')) |
|
1964 self.bsbAct.setWhatsThis(self.tr( |
|
1965 """<b>Toggle the bottom sidebar window</b>""" |
|
1966 """<p>If the bottom sidebar window is hidden then display it.""" |
|
1967 """ If it is displayed then close it.</p>""" |
|
1968 )) |
|
1969 self.bsbAct.triggered.connect(self.__toggleBottomSidebar) |
|
1970 self.actions.append(self.bsbAct) |
|
1971 |
|
1972 if self.cooperation is not None: |
|
1973 self.cooperationViewerActivateAct = E5Action( |
|
1974 self.tr('Cooperation-Viewer'), |
|
1975 self.tr('Co&operation-Viewer'), |
|
1976 QKeySequence(self.tr("Alt+Shift+O")), |
|
1977 0, self, |
|
1978 'cooperation_viewer_activate') |
|
1979 self.cooperationViewerActivateAct.setStatusTip(self.tr( |
|
1980 "Switch the input focus to the Cooperation-Viewer window.")) |
|
1981 self.cooperationViewerActivateAct.setWhatsThis(self.tr( |
|
1982 """<b>Activate Cooperation-Viewer</b>""" |
|
1983 """<p>This switches the input focus to the""" |
|
1984 """ Cooperation-Viewer window.</p>""" |
|
1985 )) |
|
1986 self.cooperationViewerActivateAct.triggered.connect( |
|
1987 self.activateCooperationViewer) |
|
1988 self.actions.append(self.cooperationViewerActivateAct) |
|
1989 self.addAction(self.cooperationViewerActivateAct) |
|
1990 |
|
1991 if self.irc is not None: |
|
1992 self.ircActivateAct = E5Action( |
|
1993 self.tr('IRC'), |
|
1994 self.tr('&IRC'), |
|
1995 QKeySequence(self.tr("Ctrl+Alt+Shift+I")), |
|
1996 0, self, |
|
1997 'irc_widget_activate') |
|
1998 self.ircActivateAct.setStatusTip(self.tr( |
|
1999 "Switch the input focus to the IRC window.")) |
|
2000 self.ircActivateAct.setWhatsThis(self.tr( |
|
2001 """<b>Activate IRC</b>""" |
|
2002 """<p>This switches the input focus to the IRC window.</p>""" |
|
2003 )) |
|
2004 self.ircActivateAct.triggered.connect( |
|
2005 self.__activateIRC) |
|
2006 self.actions.append(self.ircActivateAct) |
|
2007 self.addAction(self.ircActivateAct) |
|
2008 |
|
2009 if self.symbolsViewer is not None: |
|
2010 self.symbolsViewerActivateAct = E5Action( |
|
2011 self.tr('Symbols-Viewer'), |
|
2012 self.tr('S&ymbols-Viewer'), |
|
2013 QKeySequence(self.tr("Alt+Shift+Y")), |
|
2014 0, self, |
|
2015 'symbols_viewer_activate') |
|
2016 self.symbolsViewerActivateAct.setStatusTip(self.tr( |
|
2017 "Switch the input focus to the Symbols-Viewer window.")) |
|
2018 self.symbolsViewerActivateAct.setWhatsThis(self.tr( |
|
2019 """<b>Activate Symbols-Viewer</b>""" |
|
2020 """<p>This switches the input focus to the Symbols-Viewer""" |
|
2021 """ window.</p>""" |
|
2022 )) |
|
2023 self.symbolsViewerActivateAct.triggered.connect( |
|
2024 self.__activateSymbolsViewer) |
|
2025 self.actions.append(self.symbolsViewerActivateAct) |
|
2026 self.addAction(self.symbolsViewerActivateAct) |
|
2027 |
|
2028 if self.numbersViewer is not None: |
|
2029 self.numbersViewerActivateAct = E5Action( |
|
2030 self.tr('Numbers-Viewer'), |
|
2031 self.tr('Num&bers-Viewer'), |
|
2032 QKeySequence(self.tr("Alt+Shift+B")), |
|
2033 0, self, |
|
2034 'numbers_viewer_activate') |
|
2035 self.numbersViewerActivateAct.setStatusTip(self.tr( |
|
2036 "Switch the input focus to the Numbers-Viewer window.")) |
|
2037 self.numbersViewerActivateAct.setWhatsThis(self.tr( |
|
2038 """<b>Activate Numbers-Viewer</b>""" |
|
2039 """<p>This switches the input focus to the Numbers-Viewer""" |
|
2040 """ window.</p>""" |
|
2041 )) |
|
2042 self.numbersViewerActivateAct.triggered.connect( |
|
2043 self.__activateNumbersViewer) |
|
2044 self.actions.append(self.numbersViewerActivateAct) |
|
2045 self.addAction(self.numbersViewerActivateAct) |
|
2046 |
|
2047 if self.codeDocumentationViewer is not None: |
|
2048 self.codeDocumentationViewerActivateAct = E5Action( |
|
2049 self.tr('Code Documentation Viewer'), |
|
2050 self.tr('Code Documentation Viewer'), |
|
2051 QKeySequence(self.tr("Ctrl+Alt+Shift+D")), |
|
2052 0, self, |
|
2053 'code_documentation_viewer_activate') |
|
2054 self.codeDocumentationViewerActivateAct.setStatusTip(self.tr( |
|
2055 "Switch the input focus to the Code Documentation Viewer" |
|
2056 " window.")) |
|
2057 self.codeDocumentationViewerActivateAct.setWhatsThis(self.tr( |
|
2058 """<b>Code Documentation Viewer</b>""" |
|
2059 """<p>This switches the input focus to the Code""" |
|
2060 """ Documentation Viewer window.</p>""" |
|
2061 )) |
|
2062 self.codeDocumentationViewerActivateAct.triggered.connect( |
|
2063 self.activateCodeDocumentationViewer) |
|
2064 self.actions.append(self.codeDocumentationViewerActivateAct) |
|
2065 self.addAction(self.codeDocumentationViewerActivateAct) |
|
2066 |
|
2067 if self.pipWidget is not None: |
|
2068 self.pipWidgetActivateAct = E5Action( |
|
2069 self.tr('PyPI'), |
|
2070 self.tr('PyPI'), |
|
2071 QKeySequence(self.tr("Ctrl+Alt+Shift+P")), |
|
2072 0, self, |
|
2073 'pip_widget_activate') |
|
2074 self.pipWidgetActivateAct.setStatusTip(self.tr( |
|
2075 "Switch the input focus to the PyPI window.")) |
|
2076 self.pipWidgetActivateAct.setWhatsThis(self.tr( |
|
2077 """<b>PyPI</b>""" |
|
2078 """<p>This switches the input focus to the PyPI window.</p>""" |
|
2079 )) |
|
2080 self.pipWidgetActivateAct.triggered.connect( |
|
2081 self.__activatePipWidget) |
|
2082 self.actions.append(self.pipWidgetActivateAct) |
|
2083 self.addAction(self.pipWidgetActivateAct) |
|
2084 |
|
2085 if self.condaWidget is not None: |
|
2086 self.condaWidgetActivateAct = E5Action( |
|
2087 self.tr('Conda'), |
|
2088 self.tr('Conda'), |
|
2089 QKeySequence(self.tr("Ctrl+Alt+Shift+C")), |
|
2090 0, self, |
|
2091 'conda_widget_activate') |
|
2092 self.condaWidgetActivateAct.setStatusTip(self.tr( |
|
2093 "Switch the input focus to the Conda window.")) |
|
2094 self.condaWidgetActivateAct.setWhatsThis(self.tr( |
|
2095 """<b>Conda</b>""" |
|
2096 """<p>This switches the input focus to the Conda window.</p>""" |
|
2097 )) |
|
2098 self.condaWidgetActivateAct.triggered.connect( |
|
2099 self.__activateCondaWidget) |
|
2100 self.actions.append(self.condaWidgetActivateAct) |
|
2101 self.addAction(self.condaWidgetActivateAct) |
|
2102 |
|
2103 if self.microPythonWidget is not None: |
|
2104 self.microPythonWidgetActivateAct = E5Action( |
|
2105 self.tr('MicroPython'), |
|
2106 self.tr('MicroPython'), |
|
2107 QKeySequence(self.tr("Ctrl+Alt+Shift+M")), |
|
2108 0, self, |
|
2109 'micropython_widget_activate') |
|
2110 self.microPythonWidgetActivateAct.setStatusTip(self.tr( |
|
2111 "Switch the input focus to the MicroPython window.")) |
|
2112 self.microPythonWidgetActivateAct.setWhatsThis(self.tr( |
|
2113 """<b>MicroPython</b>""" |
|
2114 """<p>This switches the input focus to the MicroPython""" |
|
2115 """ window.</p>""" |
|
2116 )) |
|
2117 self.microPythonWidgetActivateAct.triggered.connect( |
|
2118 self.__activateMicroPython) |
|
2119 self.actions.append(self.microPythonWidgetActivateAct) |
|
2120 self.addAction(self.microPythonWidgetActivateAct) |
|
2121 |
|
2122 self.whatsThisAct = E5Action( |
|
2123 self.tr('What\'s This?'), |
|
2124 UI.PixmapCache.getIcon("whatsThis"), |
|
2125 self.tr('&What\'s This?'), |
|
2126 QKeySequence(self.tr("Shift+F1")), |
|
2127 0, self, 'whatsThis') |
|
2128 self.whatsThisAct.setStatusTip(self.tr('Context sensitive help')) |
|
2129 self.whatsThisAct.setWhatsThis(self.tr( |
|
2130 """<b>Display context sensitive help</b>""" |
|
2131 """<p>In What's This? mode, the mouse cursor shows an arrow with""" |
|
2132 """ a question mark, and you can click on the interface elements""" |
|
2133 """ to get a short description of what they do and how to use""" |
|
2134 """ them. In dialogs, this feature can be accessed using the""" |
|
2135 """ context help button in the titlebar.</p>""" |
|
2136 )) |
|
2137 self.whatsThisAct.triggered.connect(self.__whatsThis) |
|
2138 self.actions.append(self.whatsThisAct) |
|
2139 |
|
2140 self.helpviewerAct = E5Action( |
|
2141 self.tr('Helpviewer'), |
|
2142 UI.PixmapCache.getIcon("help"), |
|
2143 self.tr('&Helpviewer...'), |
|
2144 QKeySequence(self.tr("F1")), |
|
2145 0, self, 'helpviewer') |
|
2146 self.helpviewerAct.setStatusTip(self.tr( |
|
2147 'Open the helpviewer window')) |
|
2148 self.helpviewerAct.setWhatsThis(self.tr( |
|
2149 """<b>Helpviewer</b>""" |
|
2150 """<p>Display the eric web browser. This window will show""" |
|
2151 """ HTML help files and help from Qt help collections. It""" |
|
2152 """ has the capability to navigate to links, set bookmarks,""" |
|
2153 """ print the displayed help and some more features. You may""" |
|
2154 """ use it to browse the internet as well</p><p>If called""" |
|
2155 """ with a word selected, this word is search in the Qt help""" |
|
2156 """ collection.</p>""" |
|
2157 )) |
|
2158 self.helpviewerAct.triggered.connect(self.__helpViewer) |
|
2159 self.actions.append(self.helpviewerAct) |
|
2160 |
|
2161 self.__initQtDocActions() |
|
2162 self.__initPythonDocActions() |
|
2163 self.__initEricDocAction() |
|
2164 self.__initPySideDocActions() |
|
2165 |
|
2166 self.versionAct = E5Action( |
|
2167 self.tr('Show Versions'), |
|
2168 self.tr('Show &Versions'), |
|
2169 0, 0, self, 'show_versions') |
|
2170 self.versionAct.setStatusTip(self.tr( |
|
2171 'Display version information')) |
|
2172 self.versionAct.setWhatsThis(self.tr( |
|
2173 """<b>Show Versions</b>""" |
|
2174 """<p>Display version information.</p>""" |
|
2175 )) |
|
2176 self.versionAct.triggered.connect(self.__showVersions) |
|
2177 self.actions.append(self.versionAct) |
|
2178 |
|
2179 self.checkUpdateAct = E5Action( |
|
2180 self.tr('Check for Updates'), |
|
2181 self.tr('Check for &Updates...'), 0, 0, self, 'check_updates') |
|
2182 self.checkUpdateAct.setStatusTip(self.tr('Check for Updates')) |
|
2183 self.checkUpdateAct.setWhatsThis(self.tr( |
|
2184 """<b>Check for Updates...</b>""" |
|
2185 """<p>Checks the internet for updates of eric.</p>""" |
|
2186 )) |
|
2187 self.checkUpdateAct.triggered.connect(self.performVersionCheck) |
|
2188 self.actions.append(self.checkUpdateAct) |
|
2189 |
|
2190 self.showVersionsAct = E5Action( |
|
2191 self.tr('Show downloadable versions'), |
|
2192 self.tr('Show &downloadable versions...'), |
|
2193 0, 0, self, 'show_downloadable_versions') |
|
2194 self.showVersionsAct.setStatusTip( |
|
2195 self.tr('Show the versions available for download')) |
|
2196 self.showVersionsAct.setWhatsThis(self.tr( |
|
2197 """<b>Show downloadable versions...</b>""" |
|
2198 """<p>Shows the eric versions available for download """ |
|
2199 """from the internet.</p>""" |
|
2200 )) |
|
2201 self.showVersionsAct.triggered.connect( |
|
2202 self.showAvailableVersionsInfo) |
|
2203 self.actions.append(self.showVersionsAct) |
|
2204 |
|
2205 self.showErrorLogAct = E5Action( |
|
2206 self.tr('Show Error Log'), |
|
2207 self.tr('Show Error &Log...'), |
|
2208 0, 0, self, 'show_error_log') |
|
2209 self.showErrorLogAct.setStatusTip(self.tr('Show Error Log')) |
|
2210 self.showErrorLogAct.setWhatsThis(self.tr( |
|
2211 """<b>Show Error Log...</b>""" |
|
2212 """<p>Opens a dialog showing the most recent error log.</p>""" |
|
2213 )) |
|
2214 self.showErrorLogAct.triggered.connect(self.__showErrorLog) |
|
2215 self.actions.append(self.showErrorLogAct) |
|
2216 |
|
2217 self.showInstallInfoAct = E5Action( |
|
2218 self.tr('Show Install Info'), |
|
2219 self.tr('Show Install &Info...'), |
|
2220 0, 0, self, 'show_install_info') |
|
2221 self.showInstallInfoAct.setStatusTip(self.tr( |
|
2222 'Show Installation Information')) |
|
2223 self.showInstallInfoAct.setWhatsThis(self.tr( |
|
2224 """<b>Show Install Info...</b>""" |
|
2225 """<p>Opens a dialog showing some information about the""" |
|
2226 """ installation process.</p>""" |
|
2227 )) |
|
2228 self.showInstallInfoAct.triggered.connect(self.__showInstallInfo) |
|
2229 self.actions.append(self.showInstallInfoAct) |
|
2230 |
|
2231 self.reportBugAct = E5Action( |
|
2232 self.tr('Report Bug'), |
|
2233 self.tr('Report &Bug...'), |
|
2234 0, 0, self, 'report_bug') |
|
2235 self.reportBugAct.setStatusTip(self.tr('Report a bug')) |
|
2236 self.reportBugAct.setWhatsThis(self.tr( |
|
2237 """<b>Report Bug...</b>""" |
|
2238 """<p>Opens a dialog to report a bug.</p>""" |
|
2239 )) |
|
2240 self.reportBugAct.triggered.connect(self.__reportBug) |
|
2241 self.actions.append(self.reportBugAct) |
|
2242 |
|
2243 self.requestFeatureAct = E5Action( |
|
2244 self.tr('Request Feature'), |
|
2245 self.tr('Request &Feature...'), |
|
2246 0, 0, self, 'request_feature') |
|
2247 self.requestFeatureAct.setStatusTip(self.tr( |
|
2248 'Send a feature request')) |
|
2249 self.requestFeatureAct.setWhatsThis(self.tr( |
|
2250 """<b>Request Feature...</b>""" |
|
2251 """<p>Opens a dialog to send a feature request.</p>""" |
|
2252 )) |
|
2253 self.requestFeatureAct.triggered.connect(self.__requestFeature) |
|
2254 self.actions.append(self.requestFeatureAct) |
|
2255 |
|
2256 self.utActGrp = createActionGroup(self) |
|
2257 |
|
2258 self.utDialogAct = E5Action( |
|
2259 self.tr('Unittest'), |
|
2260 UI.PixmapCache.getIcon("unittest"), |
|
2261 self.tr('&Unittest...'), |
|
2262 0, 0, self.utActGrp, 'unittest') |
|
2263 self.utDialogAct.setStatusTip(self.tr('Start unittest dialog')) |
|
2264 self.utDialogAct.setWhatsThis(self.tr( |
|
2265 """<b>Unittest</b>""" |
|
2266 """<p>Perform unit tests. The dialog gives you the""" |
|
2267 """ ability to select and run a unittest suite.</p>""" |
|
2268 )) |
|
2269 self.utDialogAct.triggered.connect(self.__unittest) |
|
2270 self.actions.append(self.utDialogAct) |
|
2271 |
|
2272 self.utRestartAct = E5Action( |
|
2273 self.tr('Unittest Restart'), |
|
2274 UI.PixmapCache.getIcon("unittestRestart"), |
|
2275 self.tr('&Restart Unittest...'), |
|
2276 0, 0, self.utActGrp, 'unittest_restart') |
|
2277 self.utRestartAct.setStatusTip(self.tr('Restart last unittest')) |
|
2278 self.utRestartAct.setWhatsThis(self.tr( |
|
2279 """<b>Restart Unittest</b>""" |
|
2280 """<p>Restart the unittest performed last.</p>""" |
|
2281 )) |
|
2282 self.utRestartAct.triggered.connect(self.__unittestRestart) |
|
2283 self.utRestartAct.setEnabled(False) |
|
2284 self.actions.append(self.utRestartAct) |
|
2285 |
|
2286 self.utRerunFailedAct = E5Action( |
|
2287 self.tr('Unittest Rerun Failed'), |
|
2288 UI.PixmapCache.getIcon("unittestRerunFailed"), |
|
2289 self.tr('Rerun Failed Tests...'), |
|
2290 0, 0, self.utActGrp, 'unittest_rerun_failed') |
|
2291 self.utRerunFailedAct.setStatusTip(self.tr( |
|
2292 'Rerun failed tests of the last run')) |
|
2293 self.utRerunFailedAct.setWhatsThis(self.tr( |
|
2294 """<b>Rerun Failed Tests</b>""" |
|
2295 """<p>Rerun all tests that failed during the last unittest""" |
|
2296 """ run.</p>""" |
|
2297 )) |
|
2298 self.utRerunFailedAct.triggered.connect(self.__unittestRerunFailed) |
|
2299 self.utRerunFailedAct.setEnabled(False) |
|
2300 self.actions.append(self.utRerunFailedAct) |
|
2301 |
|
2302 self.utScriptAct = E5Action( |
|
2303 self.tr('Unittest Script'), |
|
2304 UI.PixmapCache.getIcon("unittestScript"), |
|
2305 self.tr('Unittest &Script...'), |
|
2306 0, 0, self.utActGrp, 'unittest_script') |
|
2307 self.utScriptAct.setStatusTip(self.tr( |
|
2308 'Run unittest with current script')) |
|
2309 self.utScriptAct.setWhatsThis(self.tr( |
|
2310 """<b>Unittest Script</b>""" |
|
2311 """<p>Run unittest with current script.</p>""" |
|
2312 )) |
|
2313 self.utScriptAct.triggered.connect(self.__unittestScript) |
|
2314 self.utScriptAct.setEnabled(False) |
|
2315 self.actions.append(self.utScriptAct) |
|
2316 |
|
2317 self.utProjectAct = E5Action( |
|
2318 self.tr('Unittest Project'), |
|
2319 UI.PixmapCache.getIcon("unittestProject"), |
|
2320 self.tr('Unittest &Project...'), |
|
2321 0, 0, self.utActGrp, 'unittest_project') |
|
2322 self.utProjectAct.setStatusTip(self.tr( |
|
2323 'Run unittest with current project')) |
|
2324 self.utProjectAct.setWhatsThis(self.tr( |
|
2325 """<b>Unittest Project</b>""" |
|
2326 """<p>Run unittest with current project.</p>""" |
|
2327 )) |
|
2328 self.utProjectAct.triggered.connect(self.__unittestProject) |
|
2329 self.utProjectAct.setEnabled(False) |
|
2330 self.actions.append(self.utProjectAct) |
|
2331 |
|
2332 # check for Qt5 designer and linguist |
|
2333 if Utilities.isWindowsPlatform(): |
|
2334 designerExe = os.path.join( |
|
2335 Utilities.getQtBinariesPath(), |
|
2336 "{0}.exe".format(Utilities.generateQtToolName("designer"))) |
|
2337 elif Utilities.isMacPlatform(): |
|
2338 designerExe = Utilities.getQtMacBundle("designer") |
|
2339 else: |
|
2340 designerExe = os.path.join( |
|
2341 Utilities.getQtBinariesPath(), |
|
2342 Utilities.generateQtToolName("designer")) |
|
2343 if os.path.exists(designerExe): |
|
2344 self.designer4Act = E5Action( |
|
2345 self.tr('Qt-Designer'), |
|
2346 UI.PixmapCache.getIcon("designer4"), |
|
2347 self.tr('Qt-&Designer...'), |
|
2348 0, 0, self, 'qt_designer4') |
|
2349 self.designer4Act.setStatusTip(self.tr('Start Qt-Designer')) |
|
2350 self.designer4Act.setWhatsThis(self.tr( |
|
2351 """<b>Qt-Designer</b>""" |
|
2352 """<p>Start Qt-Designer.</p>""" |
|
2353 )) |
|
2354 self.designer4Act.triggered.connect(self.__designer) |
|
2355 self.actions.append(self.designer4Act) |
|
2356 else: |
|
2357 self.designer4Act = None |
|
2358 |
|
2359 if Utilities.isWindowsPlatform(): |
|
2360 linguistExe = os.path.join( |
|
2361 Utilities.getQtBinariesPath(), |
|
2362 "{0}.exe".format(Utilities.generateQtToolName("linguist"))) |
|
2363 elif Utilities.isMacPlatform(): |
|
2364 linguistExe = Utilities.getQtMacBundle("linguist") |
|
2365 else: |
|
2366 linguistExe = os.path.join( |
|
2367 Utilities.getQtBinariesPath(), |
|
2368 Utilities.generateQtToolName("linguist")) |
|
2369 if os.path.exists(linguistExe): |
|
2370 self.linguist4Act = E5Action( |
|
2371 self.tr('Qt-Linguist'), |
|
2372 UI.PixmapCache.getIcon("linguist4"), |
|
2373 self.tr('Qt-&Linguist...'), |
|
2374 0, 0, self, 'qt_linguist4') |
|
2375 self.linguist4Act.setStatusTip(self.tr('Start Qt-Linguist')) |
|
2376 self.linguist4Act.setWhatsThis(self.tr( |
|
2377 """<b>Qt-Linguist</b>""" |
|
2378 """<p>Start Qt-Linguist.</p>""" |
|
2379 )) |
|
2380 self.linguist4Act.triggered.connect(self.__linguist) |
|
2381 self.actions.append(self.linguist4Act) |
|
2382 else: |
|
2383 self.linguist4Act = None |
|
2384 |
|
2385 self.uipreviewerAct = E5Action( |
|
2386 self.tr('UI Previewer'), |
|
2387 UI.PixmapCache.getIcon("uiPreviewer"), |
|
2388 self.tr('&UI Previewer...'), |
|
2389 0, 0, self, 'ui_previewer') |
|
2390 self.uipreviewerAct.setStatusTip(self.tr('Start the UI Previewer')) |
|
2391 self.uipreviewerAct.setWhatsThis(self.tr( |
|
2392 """<b>UI Previewer</b>""" |
|
2393 """<p>Start the UI Previewer.</p>""" |
|
2394 )) |
|
2395 self.uipreviewerAct.triggered.connect(self.__UIPreviewer) |
|
2396 self.actions.append(self.uipreviewerAct) |
|
2397 |
|
2398 self.trpreviewerAct = E5Action( |
|
2399 self.tr('Translations Previewer'), |
|
2400 UI.PixmapCache.getIcon("trPreviewer"), |
|
2401 self.tr('&Translations Previewer...'), |
|
2402 0, 0, self, 'tr_previewer') |
|
2403 self.trpreviewerAct.setStatusTip(self.tr( |
|
2404 'Start the Translations Previewer')) |
|
2405 self.trpreviewerAct.setWhatsThis(self.tr( |
|
2406 """<b>Translations Previewer</b>""" |
|
2407 """<p>Start the Translations Previewer.</p>""" |
|
2408 )) |
|
2409 self.trpreviewerAct.triggered.connect(self.__TRPreviewer) |
|
2410 self.actions.append(self.trpreviewerAct) |
|
2411 |
|
2412 self.diffAct = E5Action( |
|
2413 self.tr('Compare Files'), |
|
2414 UI.PixmapCache.getIcon("diffFiles"), |
|
2415 self.tr('&Compare Files...'), |
|
2416 0, 0, self, 'diff_files') |
|
2417 self.diffAct.setStatusTip(self.tr('Compare two files')) |
|
2418 self.diffAct.setWhatsThis(self.tr( |
|
2419 """<b>Compare Files</b>""" |
|
2420 """<p>Open a dialog to compare two files.</p>""" |
|
2421 )) |
|
2422 self.diffAct.triggered.connect(self.__compareFiles) |
|
2423 self.actions.append(self.diffAct) |
|
2424 |
|
2425 self.compareAct = E5Action( |
|
2426 self.tr('Compare Files side by side'), |
|
2427 UI.PixmapCache.getIcon("compareFiles"), |
|
2428 self.tr('Compare &Files side by side...'), |
|
2429 0, 0, self, 'compare_files') |
|
2430 self.compareAct.setStatusTip(self.tr('Compare two files')) |
|
2431 self.compareAct.setWhatsThis(self.tr( |
|
2432 """<b>Compare Files side by side</b>""" |
|
2433 """<p>Open a dialog to compare two files and show the result""" |
|
2434 """ side by side.</p>""" |
|
2435 )) |
|
2436 self.compareAct.triggered.connect(self.__compareFilesSbs) |
|
2437 self.actions.append(self.compareAct) |
|
2438 |
|
2439 self.sqlBrowserAct = E5Action( |
|
2440 self.tr('SQL Browser'), |
|
2441 UI.PixmapCache.getIcon("sqlBrowser"), |
|
2442 self.tr('SQL &Browser...'), |
|
2443 0, 0, self, 'sql_browser') |
|
2444 self.sqlBrowserAct.setStatusTip(self.tr('Browse a SQL database')) |
|
2445 self.sqlBrowserAct.setWhatsThis(self.tr( |
|
2446 """<b>SQL Browser</b>""" |
|
2447 """<p>Browse a SQL database.</p>""" |
|
2448 )) |
|
2449 self.sqlBrowserAct.triggered.connect(self.__sqlBrowser) |
|
2450 self.actions.append(self.sqlBrowserAct) |
|
2451 |
|
2452 self.miniEditorAct = E5Action( |
|
2453 self.tr('Mini Editor'), |
|
2454 UI.PixmapCache.getIcon("editor"), |
|
2455 self.tr('Mini &Editor...'), |
|
2456 0, 0, self, 'mini_editor') |
|
2457 self.miniEditorAct.setStatusTip(self.tr('Mini Editor')) |
|
2458 self.miniEditorAct.setWhatsThis(self.tr( |
|
2459 """<b>Mini Editor</b>""" |
|
2460 """<p>Open a dialog with a simplified editor.</p>""" |
|
2461 )) |
|
2462 self.miniEditorAct.triggered.connect(self.__openMiniEditor) |
|
2463 self.actions.append(self.miniEditorAct) |
|
2464 |
|
2465 self.hexEditorAct = E5Action( |
|
2466 self.tr('Hex Editor'), |
|
2467 UI.PixmapCache.getIcon("hexEditor"), |
|
2468 self.tr('&Hex Editor...'), |
|
2469 0, 0, self, 'hex_editor') |
|
2470 self.hexEditorAct.setStatusTip(self.tr( |
|
2471 'Start the eric Hex Editor')) |
|
2472 self.hexEditorAct.setWhatsThis(self.tr( |
|
2473 """<b>Hex Editor</b>""" |
|
2474 """<p>Starts the eric Hex Editor for viewing or editing""" |
|
2475 """ binary files.</p>""" |
|
2476 )) |
|
2477 self.hexEditorAct.triggered.connect(self.__openHexEditor) |
|
2478 self.actions.append(self.hexEditorAct) |
|
2479 |
|
2480 self.webBrowserAct = E5Action( |
|
2481 self.tr('eric Web Browser'), |
|
2482 UI.PixmapCache.getIcon("ericWeb"), |
|
2483 self.tr('eric &Web Browser...'), |
|
2484 0, 0, self, 'web_browser') |
|
2485 self.webBrowserAct.setStatusTip(self.tr( |
|
2486 'Start the eric Web Browser')) |
|
2487 self.webBrowserAct.setWhatsThis(self.tr( |
|
2488 """<b>eric Web Browser</b>""" |
|
2489 """<p>Browse the Internet with the eric Web Browser.</p>""" |
|
2490 )) |
|
2491 self.webBrowserAct.triggered.connect(self.__startWebBrowser) |
|
2492 self.actions.append(self.webBrowserAct) |
|
2493 |
|
2494 self.iconEditorAct = E5Action( |
|
2495 self.tr('Icon Editor'), |
|
2496 UI.PixmapCache.getIcon("iconEditor"), |
|
2497 self.tr('&Icon Editor...'), |
|
2498 0, 0, self, 'icon_editor') |
|
2499 self.iconEditorAct.setStatusTip(self.tr( |
|
2500 'Start the eric Icon Editor')) |
|
2501 self.iconEditorAct.setWhatsThis(self.tr( |
|
2502 """<b>Icon Editor</b>""" |
|
2503 """<p>Starts the eric Icon Editor for editing simple icons.</p>""" |
|
2504 )) |
|
2505 self.iconEditorAct.triggered.connect(self.__editPixmap) |
|
2506 self.actions.append(self.iconEditorAct) |
|
2507 |
|
2508 self.snapshotAct = E5Action( |
|
2509 self.tr('Snapshot'), |
|
2510 UI.PixmapCache.getIcon("ericSnap"), |
|
2511 self.tr('&Snapshot...'), |
|
2512 0, 0, self, 'snapshot') |
|
2513 self.snapshotAct.setStatusTip(self.tr( |
|
2514 'Take snapshots of a screen region')) |
|
2515 self.snapshotAct.setWhatsThis(self.tr( |
|
2516 """<b>Snapshot</b>""" |
|
2517 """<p>This opens a dialog to take snapshots of a screen""" |
|
2518 """ region.</p>""" |
|
2519 )) |
|
2520 self.snapshotAct.triggered.connect(self.__snapshot) |
|
2521 self.actions.append(self.snapshotAct) |
|
2522 |
|
2523 self.prefAct = E5Action( |
|
2524 self.tr('Preferences'), |
|
2525 UI.PixmapCache.getIcon("configure"), |
|
2526 self.tr('&Preferences...'), |
|
2527 0, 0, self, 'preferences') |
|
2528 self.prefAct.setStatusTip(self.tr( |
|
2529 'Set the prefered configuration')) |
|
2530 self.prefAct.setWhatsThis(self.tr( |
|
2531 """<b>Preferences</b>""" |
|
2532 """<p>Set the configuration items of the application""" |
|
2533 """ with your prefered values.</p>""" |
|
2534 )) |
|
2535 self.prefAct.triggered.connect(self.showPreferences) |
|
2536 self.prefAct.setMenuRole(QAction.MenuRole.PreferencesRole) |
|
2537 self.actions.append(self.prefAct) |
|
2538 |
|
2539 self.prefExportAct = E5Action( |
|
2540 self.tr('Export Preferences'), |
|
2541 UI.PixmapCache.getIcon("configureExport"), |
|
2542 self.tr('E&xport Preferences...'), |
|
2543 0, 0, self, 'export_preferences') |
|
2544 self.prefExportAct.setStatusTip(self.tr( |
|
2545 'Export the current configuration')) |
|
2546 self.prefExportAct.setWhatsThis(self.tr( |
|
2547 """<b>Export Preferences</b>""" |
|
2548 """<p>Export the current configuration to a file.</p>""" |
|
2549 )) |
|
2550 self.prefExportAct.triggered.connect(self.__exportPreferences) |
|
2551 self.actions.append(self.prefExportAct) |
|
2552 |
|
2553 self.prefImportAct = E5Action( |
|
2554 self.tr('Import Preferences'), |
|
2555 UI.PixmapCache.getIcon("configureImport"), |
|
2556 self.tr('I&mport Preferences...'), |
|
2557 0, 0, self, 'import_preferences') |
|
2558 self.prefImportAct.setStatusTip(self.tr( |
|
2559 'Import a previously exported configuration')) |
|
2560 self.prefImportAct.setWhatsThis(self.tr( |
|
2561 """<b>Import Preferences</b>""" |
|
2562 """<p>Import a previously exported configuration.</p>""" |
|
2563 )) |
|
2564 self.prefImportAct.triggered.connect(self.__importPreferences) |
|
2565 self.actions.append(self.prefImportAct) |
|
2566 |
|
2567 self.reloadAPIsAct = E5Action( |
|
2568 self.tr('Reload APIs'), |
|
2569 self.tr('Reload &APIs'), |
|
2570 0, 0, self, 'reload_apis') |
|
2571 self.reloadAPIsAct.setStatusTip(self.tr( |
|
2572 'Reload the API information')) |
|
2573 self.reloadAPIsAct.setWhatsThis(self.tr( |
|
2574 """<b>Reload APIs</b>""" |
|
2575 """<p>Reload the API information.</p>""" |
|
2576 )) |
|
2577 self.reloadAPIsAct.triggered.connect(self.__reloadAPIs) |
|
2578 self.actions.append(self.reloadAPIsAct) |
|
2579 |
|
2580 self.showExternalToolsAct = E5Action( |
|
2581 self.tr('Show external tools'), |
|
2582 UI.PixmapCache.getIcon("showPrograms"), |
|
2583 self.tr('Show external &tools'), |
|
2584 0, 0, self, 'show_external_tools') |
|
2585 self.showExternalToolsAct.setStatusTip(self.tr( |
|
2586 'Show external tools')) |
|
2587 self.showExternalToolsAct.setWhatsThis(self.tr( |
|
2588 """<b>Show external tools</b>""" |
|
2589 """<p>Opens a dialog to show the path and versions of all""" |
|
2590 """ extenal tools used by eric.</p>""" |
|
2591 )) |
|
2592 self.showExternalToolsAct.triggered.connect( |
|
2593 self.__showExternalTools) |
|
2594 self.actions.append(self.showExternalToolsAct) |
|
2595 |
|
2596 self.configViewProfilesAct = E5Action( |
|
2597 self.tr('View Profiles'), |
|
2598 UI.PixmapCache.getIcon("configureViewProfiles"), |
|
2599 self.tr('&View Profiles...'), |
|
2600 0, 0, self, 'view_profiles') |
|
2601 self.configViewProfilesAct.setStatusTip(self.tr( |
|
2602 'Configure view profiles')) |
|
2603 self.configViewProfilesAct.setWhatsThis(self.tr( |
|
2604 """<b>View Profiles</b>""" |
|
2605 """<p>Configure the view profiles. With this dialog you may""" |
|
2606 """ set the visibility of the various windows for the""" |
|
2607 """ predetermined view profiles.</p>""" |
|
2608 )) |
|
2609 self.configViewProfilesAct.triggered.connect( |
|
2610 self.__configViewProfiles) |
|
2611 self.actions.append(self.configViewProfilesAct) |
|
2612 |
|
2613 self.configToolBarsAct = E5Action( |
|
2614 self.tr('Toolbars'), |
|
2615 UI.PixmapCache.getIcon("toolbarsConfigure"), |
|
2616 self.tr('Tool&bars...'), |
|
2617 0, 0, self, 'configure_toolbars') |
|
2618 self.configToolBarsAct.setStatusTip(self.tr('Configure toolbars')) |
|
2619 self.configToolBarsAct.setWhatsThis(self.tr( |
|
2620 """<b>Toolbars</b>""" |
|
2621 """<p>Configure the toolbars. With this dialog you may""" |
|
2622 """ change the actions shown on the various toolbars and""" |
|
2623 """ define your own toolbars.</p>""" |
|
2624 )) |
|
2625 self.configToolBarsAct.triggered.connect(self.__configToolBars) |
|
2626 self.actions.append(self.configToolBarsAct) |
|
2627 |
|
2628 self.shortcutsAct = E5Action( |
|
2629 self.tr('Keyboard Shortcuts'), |
|
2630 UI.PixmapCache.getIcon("configureShortcuts"), |
|
2631 self.tr('Keyboard &Shortcuts...'), |
|
2632 0, 0, self, 'keyboard_shortcuts') |
|
2633 self.shortcutsAct.setStatusTip(self.tr( |
|
2634 'Set the keyboard shortcuts')) |
|
2635 self.shortcutsAct.setWhatsThis(self.tr( |
|
2636 """<b>Keyboard Shortcuts</b>""" |
|
2637 """<p>Set the keyboard shortcuts of the application""" |
|
2638 """ with your prefered values.</p>""" |
|
2639 )) |
|
2640 self.shortcutsAct.triggered.connect(self.__configShortcuts) |
|
2641 self.actions.append(self.shortcutsAct) |
|
2642 |
|
2643 self.exportShortcutsAct = E5Action( |
|
2644 self.tr('Export Keyboard Shortcuts'), |
|
2645 UI.PixmapCache.getIcon("exportShortcuts"), |
|
2646 self.tr('&Export Keyboard Shortcuts...'), |
|
2647 0, 0, self, 'export_keyboard_shortcuts') |
|
2648 self.exportShortcutsAct.setStatusTip(self.tr( |
|
2649 'Export the keyboard shortcuts')) |
|
2650 self.exportShortcutsAct.setWhatsThis(self.tr( |
|
2651 """<b>Export Keyboard Shortcuts</b>""" |
|
2652 """<p>Export the keyboard shortcuts of the application.</p>""" |
|
2653 )) |
|
2654 self.exportShortcutsAct.triggered.connect(self.__exportShortcuts) |
|
2655 self.actions.append(self.exportShortcutsAct) |
|
2656 |
|
2657 self.importShortcutsAct = E5Action( |
|
2658 self.tr('Import Keyboard Shortcuts'), |
|
2659 UI.PixmapCache.getIcon("importShortcuts"), |
|
2660 self.tr('&Import Keyboard Shortcuts...'), |
|
2661 0, 0, self, 'import_keyboard_shortcuts') |
|
2662 self.importShortcutsAct.setStatusTip(self.tr( |
|
2663 'Import the keyboard shortcuts')) |
|
2664 self.importShortcutsAct.setWhatsThis(self.tr( |
|
2665 """<b>Import Keyboard Shortcuts</b>""" |
|
2666 """<p>Import the keyboard shortcuts of the application.</p>""" |
|
2667 )) |
|
2668 self.importShortcutsAct.triggered.connect(self.__importShortcuts) |
|
2669 self.actions.append(self.importShortcutsAct) |
|
2670 |
|
2671 if SSL_AVAILABLE: |
|
2672 self.certificatesAct = E5Action( |
|
2673 self.tr('Manage SSL Certificates'), |
|
2674 UI.PixmapCache.getIcon("certificates"), |
|
2675 self.tr('Manage SSL Certificates...'), |
|
2676 0, 0, self, 'manage_ssl_certificates') |
|
2677 self.certificatesAct.setStatusTip(self.tr( |
|
2678 'Manage the saved SSL certificates')) |
|
2679 self.certificatesAct.setWhatsThis(self.tr( |
|
2680 """<b>Manage SSL Certificates...</b>""" |
|
2681 """<p>Opens a dialog to manage the saved SSL certificates.""" |
|
2682 """</p>""" |
|
2683 )) |
|
2684 self.certificatesAct.triggered.connect( |
|
2685 self.__showCertificatesDialog) |
|
2686 self.actions.append(self.certificatesAct) |
|
2687 |
|
2688 self.editMessageFilterAct = E5Action( |
|
2689 self.tr('Edit Message Filters'), |
|
2690 UI.PixmapCache.getIcon("warning"), |
|
2691 self.tr('Edit Message Filters...'), |
|
2692 0, 0, self, 'manage_message_filters') |
|
2693 self.editMessageFilterAct.setStatusTip(self.tr( |
|
2694 'Edit the message filters used to suppress unwanted messages')) |
|
2695 self.editMessageFilterAct.setWhatsThis(self.tr( |
|
2696 """<b>Edit Message Filters</b>""" |
|
2697 """<p>Opens a dialog to edit the message filters used to""" |
|
2698 """ suppress unwanted messages been shown in an error""" |
|
2699 """ window.</p>""" |
|
2700 )) |
|
2701 self.editMessageFilterAct.triggered.connect( |
|
2702 E5ErrorMessage.editMessageFilters) |
|
2703 self.actions.append(self.editMessageFilterAct) |
|
2704 |
|
2705 self.clearPrivateDataAct = E5Action( |
|
2706 self.tr('Clear private data'), |
|
2707 UI.PixmapCache.getIcon("clearPrivateData"), |
|
2708 self.tr('Clear private data'), |
|
2709 0, 0, |
|
2710 self, 'clear_private_data') |
|
2711 self.clearPrivateDataAct.setStatusTip(self.tr( |
|
2712 'Clear private data')) |
|
2713 self.clearPrivateDataAct.setWhatsThis(self.tr( |
|
2714 """<b>Clear private data</b>""" |
|
2715 """<p>Clears the private data like the various list of""" |
|
2716 """ recently opened files, projects or multi projects.</p>""" |
|
2717 )) |
|
2718 self.clearPrivateDataAct.triggered.connect( |
|
2719 self.__clearPrivateData) |
|
2720 self.actions.append(self.clearPrivateDataAct) |
|
2721 |
|
2722 self.viewmanagerActivateAct = E5Action( |
|
2723 self.tr('Activate current editor'), |
|
2724 self.tr('Activate current editor'), |
|
2725 QKeySequence(self.tr("Alt+Shift+E")), |
|
2726 0, self, 'viewmanager_activate') |
|
2727 self.viewmanagerActivateAct.triggered.connect( |
|
2728 self.__activateViewmanager) |
|
2729 self.actions.append(self.viewmanagerActivateAct) |
|
2730 self.addAction(self.viewmanagerActivateAct) |
|
2731 |
|
2732 self.nextTabAct = E5Action( |
|
2733 self.tr('Show next'), |
|
2734 self.tr('Show next'), |
|
2735 QKeySequence(self.tr('Ctrl+Alt+Tab')), 0, |
|
2736 self, 'view_next_tab') |
|
2737 self.nextTabAct.triggered.connect(self.__showNext) |
|
2738 self.actions.append(self.nextTabAct) |
|
2739 self.addAction(self.nextTabAct) |
|
2740 |
|
2741 self.prevTabAct = E5Action( |
|
2742 self.tr('Show previous'), |
|
2743 self.tr('Show previous'), |
|
2744 QKeySequence(self.tr('Shift+Ctrl+Alt+Tab')), 0, |
|
2745 self, 'view_previous_tab') |
|
2746 self.prevTabAct.triggered.connect(self.__showPrevious) |
|
2747 self.actions.append(self.prevTabAct) |
|
2748 self.addAction(self.prevTabAct) |
|
2749 |
|
2750 self.switchTabAct = E5Action( |
|
2751 self.tr('Switch between tabs'), |
|
2752 self.tr('Switch between tabs'), |
|
2753 QKeySequence(self.tr('Ctrl+1')), 0, |
|
2754 self, 'switch_tabs') |
|
2755 self.switchTabAct.triggered.connect(self.__switchTab) |
|
2756 self.actions.append(self.switchTabAct) |
|
2757 self.addAction(self.switchTabAct) |
|
2758 |
|
2759 self.pluginInfoAct = E5Action( |
|
2760 self.tr('Plugin Infos'), |
|
2761 UI.PixmapCache.getIcon("plugin"), |
|
2762 self.tr('&Plugin Infos...'), 0, 0, self, 'plugin_infos') |
|
2763 self.pluginInfoAct.setStatusTip(self.tr('Show Plugin Infos')) |
|
2764 self.pluginInfoAct.setWhatsThis(self.tr( |
|
2765 """<b>Plugin Infos...</b>""" |
|
2766 """<p>This opens a dialog, that show some information about""" |
|
2767 """ loaded plugins.</p>""" |
|
2768 )) |
|
2769 self.pluginInfoAct.triggered.connect(self.__showPluginInfo) |
|
2770 self.actions.append(self.pluginInfoAct) |
|
2771 |
|
2772 self.pluginInstallAct = E5Action( |
|
2773 self.tr('Install Plugins'), |
|
2774 UI.PixmapCache.getIcon("pluginInstall"), |
|
2775 self.tr('&Install Plugins...'), |
|
2776 0, 0, self, 'plugin_install') |
|
2777 self.pluginInstallAct.setStatusTip(self.tr('Install Plugins')) |
|
2778 self.pluginInstallAct.setWhatsThis(self.tr( |
|
2779 """<b>Install Plugins...</b>""" |
|
2780 """<p>This opens a dialog to install or update plugins.</p>""" |
|
2781 )) |
|
2782 self.pluginInstallAct.triggered.connect(self.__installPlugins) |
|
2783 self.actions.append(self.pluginInstallAct) |
|
2784 |
|
2785 self.pluginDeinstallAct = E5Action( |
|
2786 self.tr('Uninstall Plugin'), |
|
2787 UI.PixmapCache.getIcon("pluginUninstall"), |
|
2788 self.tr('&Uninstall Plugin...'), |
|
2789 0, 0, self, 'plugin_deinstall') |
|
2790 self.pluginDeinstallAct.setStatusTip(self.tr('Uninstall Plugin')) |
|
2791 self.pluginDeinstallAct.setWhatsThis(self.tr( |
|
2792 """<b>Uninstall Plugin...</b>""" |
|
2793 """<p>This opens a dialog to uninstall a plugin.</p>""" |
|
2794 )) |
|
2795 self.pluginDeinstallAct.triggered.connect(self.__deinstallPlugin) |
|
2796 self.actions.append(self.pluginDeinstallAct) |
|
2797 |
|
2798 self.pluginRepoAct = E5Action( |
|
2799 self.tr('Plugin Repository'), |
|
2800 UI.PixmapCache.getIcon("pluginRepository"), |
|
2801 self.tr('Plugin &Repository...'), |
|
2802 0, 0, self, 'plugin_repository') |
|
2803 self.pluginRepoAct.setStatusTip(self.tr( |
|
2804 'Show Plugins available for download')) |
|
2805 self.pluginRepoAct.setWhatsThis(self.tr( |
|
2806 """<b>Plugin Repository...</b>""" |
|
2807 """<p>This opens a dialog, that shows a list of plugins """ |
|
2808 """available on the Internet.</p>""" |
|
2809 )) |
|
2810 self.pluginRepoAct.triggered.connect(self.showPluginsAvailable) |
|
2811 self.actions.append(self.pluginRepoAct) |
|
2812 |
|
2813 self.virtualenvManagerAct = E5Action( |
|
2814 self.tr('Virtualenv Manager'), |
|
2815 UI.PixmapCache.getIcon("virtualenv"), |
|
2816 self.tr('&Virtualenv Manager...'), |
|
2817 0, 0, self, |
|
2818 'virtualenv_manager') |
|
2819 self.virtualenvManagerAct.setStatusTip(self.tr( |
|
2820 'Virtualenv Manager')) |
|
2821 self.virtualenvManagerAct.setWhatsThis(self.tr( |
|
2822 """<b>Virtualenv Manager</b>""" |
|
2823 """<p>This opens a dialog to manage the defined Python virtual""" |
|
2824 """ environments.</p>""" |
|
2825 )) |
|
2826 self.virtualenvManagerAct.triggered.connect( |
|
2827 self.virtualenvManager.showVirtualenvManagerDialog) |
|
2828 self.actions.append(self.virtualenvManagerAct) |
|
2829 |
|
2830 self.virtualenvConfigAct = E5Action( |
|
2831 self.tr('Virtualenv Configurator'), |
|
2832 UI.PixmapCache.getIcon("virtualenvConfig"), |
|
2833 self.tr('Virtualenv &Configurator...'), |
|
2834 0, 0, self, |
|
2835 'virtualenv_configurator') |
|
2836 self.virtualenvConfigAct.setStatusTip(self.tr( |
|
2837 'Virtualenv Configurator')) |
|
2838 self.virtualenvConfigAct.setWhatsThis(self.tr( |
|
2839 """<b>Virtualenv Configurator</b>""" |
|
2840 """<p>This opens a dialog for entering all the parameters""" |
|
2841 """ needed to create a Python virtual environment using""" |
|
2842 """ virtualenv or pyvenv.</p>""" |
|
2843 )) |
|
2844 self.virtualenvConfigAct.triggered.connect( |
|
2845 self.virtualenvManager.createVirtualEnv) |
|
2846 self.actions.append(self.virtualenvConfigAct) |
|
2847 |
|
2848 # initialize viewmanager actions |
|
2849 self.viewmanager.initActions() |
|
2850 |
|
2851 # initialize debugger actions |
|
2852 self.debuggerUI.initActions() |
|
2853 |
|
2854 # initialize project actions |
|
2855 self.project.initActions() |
|
2856 |
|
2857 # initialize multi project actions |
|
2858 self.multiProject.initActions() |
|
2859 |
|
2860 def __initQtDocActions(self): |
|
2861 """ |
|
2862 Private slot to initialize the action to show the Qt documentation. |
|
2863 """ |
|
2864 self.qt5DocAct = E5Action( |
|
2865 self.tr('Qt5 Documentation'), |
|
2866 self.tr('Qt5 Documentation'), |
|
2867 0, 0, self, 'qt5_documentation') |
|
2868 self.qt5DocAct.setStatusTip(self.tr('Open Qt5 Documentation')) |
|
2869 self.qt5DocAct.setWhatsThis(self.tr( |
|
2870 """<b>Qt5 Documentation</b>""" |
|
2871 """<p>Display the Qt5 Documentation. Dependent upon your""" |
|
2872 """ settings, this will either show the help in Eric's internal""" |
|
2873 """ help viewer/web browser, or execute a web browser or Qt""" |
|
2874 """ Assistant. </p>""" |
|
2875 )) |
|
2876 self.qt5DocAct.triggered.connect(lambda: self.__showQtDoc(5)) |
|
2877 self.actions.append(self.qt5DocAct) |
|
2878 |
|
2879 self.qt6DocAct = E5Action( |
|
2880 self.tr('Qt6 Documentation'), |
|
2881 self.tr('Qt6 Documentation'), |
|
2882 0, 0, self, 'qt6_documentation') |
|
2883 self.qt6DocAct.setStatusTip(self.tr('Open Qt6 Documentation')) |
|
2884 self.qt6DocAct.setWhatsThis(self.tr( |
|
2885 """<b>Qt6 Documentation</b>""" |
|
2886 """<p>Display the Qt6 Documentation. Dependent upon your""" |
|
2887 """ settings, this will either show the help in Eric's internal""" |
|
2888 """ help viewer/web browser, or execute a web browser or Qt""" |
|
2889 """ Assistant. </p>""" |
|
2890 )) |
|
2891 self.qt6DocAct.triggered.connect(lambda: self.__showQtDoc(6)) |
|
2892 self.actions.append(self.qt6DocAct) |
|
2893 |
|
2894 self.pyqt5DocAct = E5Action( |
|
2895 self.tr('PyQt5 Documentation'), |
|
2896 self.tr('PyQt5 Documentation'), |
|
2897 0, 0, self, 'pyqt5_documentation') |
|
2898 self.pyqt5DocAct.setStatusTip(self.tr( |
|
2899 'Open PyQt5 Documentation')) |
|
2900 self.pyqt5DocAct.setWhatsThis(self.tr( |
|
2901 """<b>PyQt5 Documentation</b>""" |
|
2902 """<p>Display the PyQt5 Documentation. Dependent upon your""" |
|
2903 """ settings, this will either show the help in Eric's""" |
|
2904 """ internal help viewer/web browser, or execute a web""" |
|
2905 """ browser or Qt Assistant. </p>""" |
|
2906 )) |
|
2907 self.pyqt5DocAct.triggered.connect( |
|
2908 lambda: self.__showPyQtDoc(variant=5)) |
|
2909 self.actions.append(self.pyqt5DocAct) |
|
2910 |
|
2911 self.pyqt6DocAct = E5Action( |
|
2912 self.tr('PyQt6 Documentation'), |
|
2913 self.tr('PyQt6 Documentation'), |
|
2914 0, 0, self, 'pyqt6_documentation') |
|
2915 self.pyqt6DocAct.setStatusTip(self.tr( |
|
2916 'Open PyQt6 Documentation')) |
|
2917 self.pyqt6DocAct.setWhatsThis(self.tr( |
|
2918 """<b>PyQt6 Documentation</b>""" |
|
2919 """<p>Display the PyQt6 Documentation. Dependent upon your""" |
|
2920 """ settings, this will either show the help in Eric's""" |
|
2921 """ internal help viewer/web browser, or execute a web""" |
|
2922 """ browser or Qt Assistant. </p>""" |
|
2923 )) |
|
2924 self.pyqt6DocAct.triggered.connect( |
|
2925 lambda: self.__showPyQtDoc(variant=6)) |
|
2926 self.actions.append(self.pyqt6DocAct) |
|
2927 |
|
2928 def __initPythonDocActions(self): |
|
2929 """ |
|
2930 Private slot to initialize the actions to show the Python |
|
2931 documentation. |
|
2932 """ |
|
2933 self.pythonDocAct = E5Action( |
|
2934 self.tr('Python 3 Documentation'), |
|
2935 self.tr('Python 3 Documentation'), |
|
2936 0, 0, self, 'python3_documentation') |
|
2937 self.pythonDocAct.setStatusTip(self.tr( |
|
2938 'Open Python 3 Documentation')) |
|
2939 self.pythonDocAct.setWhatsThis(self.tr( |
|
2940 """<b>Python 3 Documentation</b>""" |
|
2941 """<p>Display the Python 3 documentation. If no documentation""" |
|
2942 """ directory is configured, the location of the Python 3""" |
|
2943 """ documentation is assumed to be the doc directory underneath""" |
|
2944 """ the location of the Python 3 executable on Windows and""" |
|
2945 """ <i>/usr/share/doc/packages/python/html</i> on Unix. Set""" |
|
2946 """ PYTHON3DOCDIR in your environment to override this.</p>""" |
|
2947 )) |
|
2948 self.pythonDocAct.triggered.connect(self.__showPythonDoc) |
|
2949 self.actions.append(self.pythonDocAct) |
|
2950 |
|
2951 def __initEricDocAction(self): |
|
2952 """ |
|
2953 Private slot to initialize the action to show the eric documentation. |
|
2954 """ |
|
2955 self.ericDocAct = E5Action( |
|
2956 self.tr("Eric API Documentation"), |
|
2957 self.tr('Eric API Documentation'), |
|
2958 0, 0, self, 'eric_documentation') |
|
2959 self.ericDocAct.setStatusTip(self.tr( |
|
2960 "Open Eric API Documentation")) |
|
2961 self.ericDocAct.setWhatsThis(self.tr( |
|
2962 """<b>Eric API Documentation</b>""" |
|
2963 """<p>Display the Eric API documentation. The location for the""" |
|
2964 """ documentation is the Documentation/Source subdirectory of""" |
|
2965 """ the eric installation directory.</p>""" |
|
2966 )) |
|
2967 self.ericDocAct.triggered.connect(self.__showEricDoc) |
|
2968 self.actions.append(self.ericDocAct) |
|
2969 |
|
2970 def __initPySideDocActions(self): |
|
2971 """ |
|
2972 Private slot to initialize the actions to show the PySide |
|
2973 documentation. |
|
2974 """ |
|
2975 if Utilities.checkPyside(variant=2): |
|
2976 self.pyside2DocAct = E5Action( |
|
2977 self.tr('PySide2 Documentation'), |
|
2978 self.tr('PySide2 Documentation'), |
|
2979 0, 0, self, 'pyside2_documentation') |
|
2980 self.pyside2DocAct.setStatusTip(self.tr( |
|
2981 'Open PySide2 Documentation')) |
|
2982 self.pyside2DocAct.setWhatsThis(self.tr( |
|
2983 """<b>PySide2 Documentation</b>""" |
|
2984 """<p>Display the PySide2 Documentation. Dependent upon your""" |
|
2985 """ settings, this will either show the help in Eric's""" |
|
2986 """ internal help viewer/web browser, or execute a web""" |
|
2987 """ browser or Qt Assistant. </p>""" |
|
2988 )) |
|
2989 self.pyside2DocAct.triggered.connect( |
|
2990 lambda: self.__showPySideDoc(variant=2)) |
|
2991 self.actions.append(self.pyside2DocAct) |
|
2992 else: |
|
2993 self.pyside2DocAct = None |
|
2994 |
|
2995 if Utilities.checkPyside(variant=6): |
|
2996 self.pyside6DocAct = E5Action( |
|
2997 self.tr('PySide6 Documentation'), |
|
2998 self.tr('PySide6 Documentation'), |
|
2999 0, 0, self, 'pyside6_documentation') |
|
3000 self.pyside6DocAct.setStatusTip(self.tr( |
|
3001 'Open PySide6 Documentation')) |
|
3002 self.pyside6DocAct.setWhatsThis(self.tr( |
|
3003 """<b>PySide6 Documentation</b>""" |
|
3004 """<p>Display the PySide6 Documentation. Dependent upon your""" |
|
3005 """ settings, this will either show the help in Eric's""" |
|
3006 """ internal help viewer/web browser, or execute a web""" |
|
3007 """ browser or Qt Assistant. </p>""" |
|
3008 )) |
|
3009 self.pyside6DocAct.triggered.connect( |
|
3010 lambda: self.__showPySideDoc(variant=6)) |
|
3011 self.actions.append(self.pyside6DocAct) |
|
3012 else: |
|
3013 self.pyside6DocAct = None |
|
3014 |
|
3015 def __initMenus(self): |
|
3016 """ |
|
3017 Private slot to create the menus. |
|
3018 """ |
|
3019 self.__menus = {} |
|
3020 mb = self.menuBar() |
|
3021 if ( |
|
3022 Utilities.isLinuxPlatform() and |
|
3023 not Preferences.getUI("UseNativeMenuBar") |
|
3024 ): |
|
3025 mb.setNativeMenuBar(False) |
|
3026 |
|
3027 ############################################################## |
|
3028 ## File menu |
|
3029 ############################################################## |
|
3030 |
|
3031 self.__menus["file"] = self.viewmanager.initFileMenu() |
|
3032 mb.addMenu(self.__menus["file"]) |
|
3033 self.__menus["file"].addSeparator() |
|
3034 self.__menus["file"].addAction(self.saveSessionAct) |
|
3035 self.__menus["file"].addAction(self.loadSessionAct) |
|
3036 self.__menus["file"].addSeparator() |
|
3037 self.__menus["file"].addAction(self.restartAct) |
|
3038 self.__menus["file"].addAction(self.exitAct) |
|
3039 act = self.__menus["file"].actions()[0] |
|
3040 sep = self.__menus["file"].insertSeparator(act) |
|
3041 self.__menus["file"].insertAction(sep, self.newWindowAct) |
|
3042 self.__menus["file"].aboutToShow.connect(self.__showFileMenu) |
|
3043 |
|
3044 ############################################################## |
|
3045 ## Edit menu |
|
3046 ############################################################## |
|
3047 |
|
3048 self.__menus["edit"] = self.viewmanager.initEditMenu() |
|
3049 mb.addMenu(self.__menus["edit"]) |
|
3050 |
|
3051 ############################################################## |
|
3052 ## Search menu |
|
3053 ############################################################## |
|
3054 |
|
3055 self.__menus["search"] = self.viewmanager.initSearchMenu() |
|
3056 mb.addMenu(self.__menus["search"]) |
|
3057 |
|
3058 ############################################################## |
|
3059 ## View menu |
|
3060 ############################################################## |
|
3061 |
|
3062 self.__menus["view"] = self.viewmanager.initViewMenu() |
|
3063 mb.addMenu(self.__menus["view"]) |
|
3064 |
|
3065 ############################################################## |
|
3066 ## Bookmarks menu |
|
3067 ############################################################## |
|
3068 |
|
3069 self.__menus["bookmarks"] = self.viewmanager.initBookmarkMenu() |
|
3070 mb.addMenu(self.__menus["bookmarks"]) |
|
3071 self.__menus["bookmarks"].setTearOffEnabled(True) |
|
3072 |
|
3073 ############################################################## |
|
3074 ## Multiproject menu |
|
3075 ############################################################## |
|
3076 |
|
3077 self.__menus["multiproject"] = self.multiProject.initMenu() |
|
3078 mb.addMenu(self.__menus["multiproject"]) |
|
3079 |
|
3080 ############################################################## |
|
3081 ## Project menu |
|
3082 ############################################################## |
|
3083 |
|
3084 self.__menus["project"], self.__menus["project_tools"] = ( |
|
3085 self.project.initMenus() |
|
3086 ) |
|
3087 mb.addMenu(self.__menus["project"]) |
|
3088 mb.addMenu(self.__menus["project_tools"]) |
|
3089 |
|
3090 ############################################################## |
|
3091 ## Start and Debug menus |
|
3092 ############################################################## |
|
3093 |
|
3094 self.__menus["start"], self.__menus["debug"] = ( |
|
3095 self.debuggerUI.initMenus() |
|
3096 ) |
|
3097 mb.addMenu(self.__menus["start"]) |
|
3098 mb.addMenu(self.__menus["debug"]) |
|
3099 |
|
3100 ############################################################## |
|
3101 ## Extras menu |
|
3102 ############################################################## |
|
3103 |
|
3104 self.__menus["extras"] = QMenu(self.tr('E&xtras'), self) |
|
3105 self.__menus["extras"].setTearOffEnabled(True) |
|
3106 self.__menus["extras"].aboutToShow.connect(self.__showExtrasMenu) |
|
3107 mb.addMenu(self.__menus["extras"]) |
|
3108 self.viewmanager.addToExtrasMenu(self.__menus["extras"]) |
|
3109 |
|
3110 ############################################################## |
|
3111 ## Extras/Wizards menu |
|
3112 ############################################################## |
|
3113 |
|
3114 self.__menus["wizards"] = QMenu(self.tr('Wi&zards'), self) |
|
3115 self.__menus["wizards"].setTearOffEnabled(True) |
|
3116 self.__menus["wizards"].aboutToShow.connect(self.__showWizardsMenu) |
|
3117 self.wizardsMenuAct = self.__menus["extras"].addMenu( |
|
3118 self.__menus["wizards"]) |
|
3119 self.wizardsMenuAct.setEnabled(False) |
|
3120 |
|
3121 ############################################################## |
|
3122 ## Extras/Macros menu |
|
3123 ############################################################## |
|
3124 |
|
3125 self.__menus["macros"] = self.viewmanager.initMacroMenu() |
|
3126 self.__menus["extras"].addMenu(self.__menus["macros"]) |
|
3127 self.__menus["extras"].addSeparator() |
|
3128 |
|
3129 ############################################################## |
|
3130 ## Extras/VirtualEnv Manager menu entries |
|
3131 ############################################################## |
|
3132 |
|
3133 self.__menus["extras"].addAction(self.virtualenvManagerAct) |
|
3134 self.__menus["extras"].addAction(self.virtualenvConfigAct) |
|
3135 self.__menus["extras"].addSeparator() |
|
3136 |
|
3137 ############################################################## |
|
3138 ## Extras/Plugins menu |
|
3139 ############################################################## |
|
3140 |
|
3141 pluginsMenu = QMenu(self.tr('P&lugins'), self) |
|
3142 pluginsMenu.setIcon(UI.PixmapCache.getIcon("plugin")) |
|
3143 pluginsMenu.setTearOffEnabled(True) |
|
3144 pluginsMenu.addAction(self.pluginInfoAct) |
|
3145 pluginsMenu.addAction(self.pluginInstallAct) |
|
3146 pluginsMenu.addAction(self.pluginDeinstallAct) |
|
3147 pluginsMenu.addSeparator() |
|
3148 pluginsMenu.addAction(self.pluginRepoAct) |
|
3149 pluginsMenu.addSeparator() |
|
3150 pluginsMenu.addAction( |
|
3151 self.tr("Configure..."), self.__pluginsConfigure) |
|
3152 |
|
3153 self.__menus["extras"].addMenu(pluginsMenu) |
|
3154 self.__menus["extras"].addSeparator() |
|
3155 |
|
3156 ############################################################## |
|
3157 ## Extras/Unittest menu |
|
3158 ############################################################## |
|
3159 |
|
3160 self.__menus["unittest"] = QMenu(self.tr('&Unittest'), self) |
|
3161 self.__menus["unittest"].setTearOffEnabled(True) |
|
3162 self.__menus["unittest"].addAction(self.utDialogAct) |
|
3163 self.__menus["unittest"].addSeparator() |
|
3164 self.__menus["unittest"].addAction(self.utRestartAct) |
|
3165 self.__menus["unittest"].addAction(self.utRerunFailedAct) |
|
3166 self.__menus["unittest"].addSeparator() |
|
3167 self.__menus["unittest"].addAction(self.utScriptAct) |
|
3168 self.__menus["unittest"].addAction(self.utProjectAct) |
|
3169 |
|
3170 self.__menus["extras"].addMenu(self.__menus["unittest"]) |
|
3171 self.__menus["extras"].addSeparator() |
|
3172 |
|
3173 ############################################################## |
|
3174 ## Extras/Builtin,Plugin,User tools menus |
|
3175 ############################################################## |
|
3176 |
|
3177 self.toolGroupsMenu = QMenu(self.tr("Select Tool Group"), self) |
|
3178 self.toolGroupsMenu.aboutToShow.connect(self.__showToolGroupsMenu) |
|
3179 self.toolGroupsMenu.triggered.connect(self.__toolGroupSelected) |
|
3180 self.toolGroupsMenuTriggered = False |
|
3181 self.__initToolsMenus(self.__menus["extras"]) |
|
3182 self.__menus["extras"].addSeparator() |
|
3183 |
|
3184 ############################################################## |
|
3185 ## Settings menu |
|
3186 ############################################################## |
|
3187 |
|
3188 self.__menus["settings"] = QMenu(self.tr('Se&ttings'), self) |
|
3189 mb.addMenu(self.__menus["settings"]) |
|
3190 self.__menus["settings"].setTearOffEnabled(True) |
|
3191 |
|
3192 self.__menus["settings"].addAction(self.prefAct) |
|
3193 self.__menus["settings"].addAction(self.prefExportAct) |
|
3194 self.__menus["settings"].addAction(self.prefImportAct) |
|
3195 self.__menus["settings"].addSeparator() |
|
3196 self.__menus["settings"].addAction(self.reloadAPIsAct) |
|
3197 self.__menus["settings"].addSeparator() |
|
3198 self.__menus["settings"].addAction(self.configViewProfilesAct) |
|
3199 self.__menus["settings"].addAction(self.configToolBarsAct) |
|
3200 self.__menus["settings"].addSeparator() |
|
3201 self.__menus["settings"].addAction(self.shortcutsAct) |
|
3202 self.__menus["settings"].addAction(self.exportShortcutsAct) |
|
3203 self.__menus["settings"].addAction(self.importShortcutsAct) |
|
3204 self.__menus["settings"].addSeparator() |
|
3205 self.__menus["settings"].addAction(self.showExternalToolsAct) |
|
3206 if SSL_AVAILABLE: |
|
3207 self.__menus["settings"].addSeparator() |
|
3208 self.__menus["settings"].addAction(self.certificatesAct) |
|
3209 self.__menus["settings"].addSeparator() |
|
3210 self.__menus["settings"].addAction(self.editMessageFilterAct) |
|
3211 self.__menus["settings"].addSeparator() |
|
3212 self.__menus["settings"].addAction(self.clearPrivateDataAct) |
|
3213 |
|
3214 ############################################################## |
|
3215 ## Window menu |
|
3216 ############################################################## |
|
3217 |
|
3218 self.__menus["window"] = QMenu(self.tr('&Window'), self) |
|
3219 mb.addMenu(self.__menus["window"]) |
|
3220 self.__menus["window"].setTearOffEnabled(True) |
|
3221 self.__menus["window"].aboutToShow.connect(self.__showWindowMenu) |
|
3222 |
|
3223 ############################################################## |
|
3224 ## Window/Windows menu |
|
3225 ############################################################## |
|
3226 |
|
3227 self.__menus["subwindow"] = QMenu(self.tr("&Windows"), |
|
3228 self.__menus["window"]) |
|
3229 self.__menus["subwindow"].setTearOffEnabled(True) |
|
3230 # central park |
|
3231 self.__menus["subwindow"].addSection(self.tr("Central Park")) |
|
3232 self.__menus["subwindow"].addAction(self.viewmanagerActivateAct) |
|
3233 # left side |
|
3234 self.__menus["subwindow"].addSection(self.tr("Left Side")) |
|
3235 if self.__shellPosition == "left": |
|
3236 self.__menus["subwindow"].addAction(self.shellActivateAct) |
|
3237 self.__menus["subwindow"].addAction(self.pbActivateAct) |
|
3238 self.__menus["subwindow"].addAction(self.mpbActivateAct) |
|
3239 if self.templateViewer is not None: |
|
3240 self.__menus["subwindow"].addAction(self.templateViewerActivateAct) |
|
3241 if self.browser is not None: |
|
3242 self.__menus["subwindow"].addAction(self.browserActivateAct) |
|
3243 if self.symbolsViewer is not None: |
|
3244 self.__menus["subwindow"].addAction(self.symbolsViewerActivateAct) |
|
3245 # bottom side |
|
3246 self.__menus["subwindow"].addSection(self.tr("Bottom Side")) |
|
3247 if self.__shellPosition == "bottom": |
|
3248 self.__menus["subwindow"].addAction(self.shellActivateAct) |
|
3249 self.__menus["subwindow"].addAction(self.taskViewerActivateAct) |
|
3250 self.__menus["subwindow"].addAction(self.logViewerActivateAct) |
|
3251 if self.numbersViewer is not None: |
|
3252 self.__menus["subwindow"].addAction(self.numbersViewerActivateAct) |
|
3253 self.__menus["subwindow"].addSection(self.tr("Right Side")) |
|
3254 # right side |
|
3255 if self.__shellPosition == "right": |
|
3256 self.__menus["subwindow"].addAction(self.shellActivateAct) |
|
3257 if self.codeDocumentationViewer is not None: |
|
3258 self.__menus["subwindow"].addAction( |
|
3259 self.codeDocumentationViewerActivateAct) |
|
3260 self.__menus["subwindow"].addAction(self.debugViewerActivateAct) |
|
3261 if self.pipWidget is not None: |
|
3262 self.__menus["subwindow"].addAction(self.pipWidgetActivateAct) |
|
3263 if self.condaWidget is not None: |
|
3264 self.__menus["subwindow"].addAction(self.condaWidgetActivateAct) |
|
3265 if self.cooperation is not None: |
|
3266 self.__menus["subwindow"].addAction( |
|
3267 self.cooperationViewerActivateAct) |
|
3268 if self.irc is not None: |
|
3269 self.__menus["subwindow"].addAction(self.ircActivateAct) |
|
3270 if self.microPythonWidget is not None: |
|
3271 self.__menus["subwindow"].addAction( |
|
3272 self.microPythonWidgetActivateAct) |
|
3273 self.__menus["subwindow"].addSection(self.tr("Plug-ins")) |
|
3274 |
|
3275 ############################################################## |
|
3276 ## Window/Toolbars menu |
|
3277 ############################################################## |
|
3278 |
|
3279 self.__menus["toolbars"] = QMenu( |
|
3280 self.tr("&Toolbars"), self.__menus["window"]) |
|
3281 self.__menus["toolbars"].setTearOffEnabled(True) |
|
3282 self.__menus["toolbars"].aboutToShow.connect(self.__showToolbarsMenu) |
|
3283 self.__menus["toolbars"].triggered.connect(self.__TBMenuTriggered) |
|
3284 |
|
3285 self.__showWindowMenu() # to initialize these actions |
|
3286 |
|
3287 mb.addSeparator() |
|
3288 |
|
3289 ############################################################## |
|
3290 ## Help menu |
|
3291 ############################################################## |
|
3292 |
|
3293 self.__menus["help"] = QMenu(self.tr('&Help'), self) |
|
3294 mb.addMenu(self.__menus["help"]) |
|
3295 self.__menus["help"].setTearOffEnabled(True) |
|
3296 if self.helpviewerAct: |
|
3297 self.__menus["help"].addAction(self.helpviewerAct) |
|
3298 self.__menus["help"].addSeparator() |
|
3299 self.__menus["help"].addAction(self.ericDocAct) |
|
3300 self.__menus["help"].addAction(self.pythonDocAct) |
|
3301 self.__menus["help"].addAction(self.qt5DocAct) |
|
3302 self.__menus["help"].addAction(self.qt6DocAct) |
|
3303 self.__menus["help"].addAction(self.pyqt5DocAct) |
|
3304 self.__menus["help"].addAction(self.pyqt6DocAct) |
|
3305 if self.pyside2DocAct is not None: |
|
3306 self.__menus["help"].addAction(self.pyside2DocAct) |
|
3307 if self.pyside6DocAct is not None: |
|
3308 self.__menus["help"].addAction(self.pyside6DocAct) |
|
3309 self.__menus["help"].addSeparator() |
|
3310 self.__menus["help"].addAction(self.versionAct) |
|
3311 self.__menus["help"].addSeparator() |
|
3312 self.__menus["help"].addAction(self.checkUpdateAct) |
|
3313 self.__menus["help"].addAction(self.showVersionsAct) |
|
3314 self.__menus["help"].addSeparator() |
|
3315 self.__menus["help"].addAction(self.showInstallInfoAct) |
|
3316 self.__menus["help"].addSeparator() |
|
3317 self.__menus["help"].addAction(self.showErrorLogAct) |
|
3318 self.__menus["help"].addAction(self.reportBugAct) |
|
3319 self.__menus["help"].addAction(self.requestFeatureAct) |
|
3320 self.__menus["help"].addSeparator() |
|
3321 self.__menus["help"].addAction(self.whatsThisAct) |
|
3322 self.__menus["help"].aboutToShow.connect(self.__showHelpMenu) |
|
3323 |
|
3324 def getToolBarIconSize(self): |
|
3325 """ |
|
3326 Public method to get the toolbar icon size. |
|
3327 |
|
3328 @return toolbar icon size (QSize) |
|
3329 """ |
|
3330 return Config.ToolBarIconSize |
|
3331 |
|
3332 def __initToolbars(self): |
|
3333 """ |
|
3334 Private slot to create the toolbars. |
|
3335 """ |
|
3336 filetb = self.viewmanager.initFileToolbar(self.toolbarManager) |
|
3337 edittb = self.viewmanager.initEditToolbar(self.toolbarManager) |
|
3338 searchtb = self.viewmanager.initSearchToolbar(self.toolbarManager) |
|
3339 viewtb = self.viewmanager.initViewToolbar(self.toolbarManager) |
|
3340 starttb, debugtb = self.debuggerUI.initToolbars(self.toolbarManager) |
|
3341 multiprojecttb = self.multiProject.initToolbar(self.toolbarManager) |
|
3342 projecttb, vcstb = self.project.initToolbars(self.toolbarManager) |
|
3343 toolstb = QToolBar(self.tr("Tools"), self) |
|
3344 unittesttb = QToolBar(self.tr("Unittest"), self) |
|
3345 bookmarktb = self.viewmanager.initBookmarkToolbar(self.toolbarManager) |
|
3346 spellingtb = self.viewmanager.initSpellingToolbar(self.toolbarManager) |
|
3347 settingstb = QToolBar(self.tr("Settings"), self) |
|
3348 helptb = QToolBar(self.tr("Help"), self) |
|
3349 profilestb = QToolBar(self.tr("Profiles"), self) |
|
3350 pluginstb = QToolBar(self.tr("Plugins"), self) |
|
3351 |
|
3352 toolstb.setIconSize(Config.ToolBarIconSize) |
|
3353 unittesttb.setIconSize(Config.ToolBarIconSize) |
|
3354 settingstb.setIconSize(Config.ToolBarIconSize) |
|
3355 helptb.setIconSize(Config.ToolBarIconSize) |
|
3356 profilestb.setIconSize(Config.ToolBarIconSize) |
|
3357 pluginstb.setIconSize(Config.ToolBarIconSize) |
|
3358 |
|
3359 toolstb.setObjectName("ToolsToolbar") |
|
3360 unittesttb.setObjectName("UnittestToolbar") |
|
3361 settingstb.setObjectName("SettingsToolbar") |
|
3362 helptb.setObjectName("HelpToolbar") |
|
3363 profilestb.setObjectName("ProfilesToolbar") |
|
3364 pluginstb.setObjectName("PluginsToolbar") |
|
3365 |
|
3366 toolstb.setToolTip(self.tr("Tools")) |
|
3367 unittesttb.setToolTip(self.tr("Unittest")) |
|
3368 settingstb.setToolTip(self.tr("Settings")) |
|
3369 helptb.setToolTip(self.tr("Help")) |
|
3370 profilestb.setToolTip(self.tr("Profiles")) |
|
3371 pluginstb.setToolTip(self.tr("Plugins")) |
|
3372 |
|
3373 filetb.addSeparator() |
|
3374 filetb.addAction(self.restartAct) |
|
3375 filetb.addAction(self.exitAct) |
|
3376 act = filetb.actions()[0] |
|
3377 sep = filetb.insertSeparator(act) |
|
3378 filetb.insertAction(sep, self.newWindowAct) |
|
3379 self.toolbarManager.addToolBar(filetb, filetb.windowTitle()) |
|
3380 |
|
3381 # setup the unittest toolbar |
|
3382 unittesttb.addAction(self.utDialogAct) |
|
3383 unittesttb.addSeparator() |
|
3384 unittesttb.addAction(self.utRestartAct) |
|
3385 unittesttb.addAction(self.utRerunFailedAct) |
|
3386 unittesttb.addSeparator() |
|
3387 unittesttb.addAction(self.utScriptAct) |
|
3388 unittesttb.addAction(self.utProjectAct) |
|
3389 self.toolbarManager.addToolBar(unittesttb, unittesttb.windowTitle()) |
|
3390 |
|
3391 # setup the tools toolbar |
|
3392 if self.designer4Act is not None: |
|
3393 toolstb.addAction(self.designer4Act) |
|
3394 if self.linguist4Act is not None: |
|
3395 toolstb.addAction(self.linguist4Act) |
|
3396 toolstb.addAction(self.uipreviewerAct) |
|
3397 toolstb.addAction(self.trpreviewerAct) |
|
3398 toolstb.addSeparator() |
|
3399 toolstb.addAction(self.diffAct) |
|
3400 toolstb.addAction(self.compareAct) |
|
3401 toolstb.addSeparator() |
|
3402 toolstb.addAction(self.sqlBrowserAct) |
|
3403 toolstb.addSeparator() |
|
3404 toolstb.addAction(self.miniEditorAct) |
|
3405 toolstb.addAction(self.hexEditorAct) |
|
3406 toolstb.addAction(self.iconEditorAct) |
|
3407 toolstb.addAction(self.snapshotAct) |
|
3408 toolstb.addSeparator() |
|
3409 toolstb.addAction(self.virtualenvManagerAct) |
|
3410 toolstb.addAction(self.virtualenvConfigAct) |
|
3411 if self.webBrowserAct: |
|
3412 toolstb.addSeparator() |
|
3413 toolstb.addAction(self.webBrowserAct) |
|
3414 self.toolbarManager.addToolBar(toolstb, toolstb.windowTitle()) |
|
3415 |
|
3416 # setup the settings toolbar |
|
3417 settingstb.addAction(self.prefAct) |
|
3418 settingstb.addAction(self.configViewProfilesAct) |
|
3419 settingstb.addAction(self.configToolBarsAct) |
|
3420 settingstb.addAction(self.shortcutsAct) |
|
3421 settingstb.addAction(self.showExternalToolsAct) |
|
3422 self.toolbarManager.addToolBar(settingstb, settingstb.windowTitle()) |
|
3423 self.toolbarManager.addActions([ |
|
3424 self.exportShortcutsAct, |
|
3425 self.importShortcutsAct, |
|
3426 self.prefExportAct, |
|
3427 self.prefImportAct, |
|
3428 self.showExternalToolsAct, |
|
3429 self.editMessageFilterAct, |
|
3430 self.clearPrivateDataAct, |
|
3431 ], settingstb.windowTitle()) |
|
3432 if SSL_AVAILABLE: |
|
3433 self.toolbarManager.addAction( |
|
3434 self.certificatesAct, settingstb.windowTitle()) |
|
3435 |
|
3436 # setup the help toolbar |
|
3437 helptb.addAction(self.whatsThisAct) |
|
3438 self.toolbarManager.addToolBar(helptb, helptb.windowTitle()) |
|
3439 if self.helpviewerAct: |
|
3440 self.toolbarManager.addAction(self.helpviewerAct, |
|
3441 helptb.windowTitle()) |
|
3442 |
|
3443 # setup the view profiles toolbar |
|
3444 profilestb.addActions(self.viewProfileActGrp.actions()) |
|
3445 self.toolbarManager.addToolBar(profilestb, profilestb.windowTitle()) |
|
3446 |
|
3447 # setup the plugins toolbar |
|
3448 pluginstb.addAction(self.pluginInfoAct) |
|
3449 pluginstb.addAction(self.pluginInstallAct) |
|
3450 pluginstb.addAction(self.pluginDeinstallAct) |
|
3451 pluginstb.addSeparator() |
|
3452 pluginstb.addAction(self.pluginRepoAct) |
|
3453 self.toolbarManager.addToolBar(pluginstb, pluginstb.windowTitle()) |
|
3454 |
|
3455 # add the various toolbars |
|
3456 self.addToolBar(filetb) |
|
3457 self.addToolBar(edittb) |
|
3458 self.addToolBar(searchtb) |
|
3459 self.addToolBar(viewtb) |
|
3460 self.addToolBar(starttb) |
|
3461 self.addToolBar(debugtb) |
|
3462 self.addToolBar(multiprojecttb) |
|
3463 self.addToolBar(projecttb) |
|
3464 self.addToolBar(vcstb) |
|
3465 self.addToolBar(Qt.ToolBarArea.RightToolBarArea, settingstb) |
|
3466 self.addToolBar(Qt.ToolBarArea.RightToolBarArea, toolstb) |
|
3467 self.addToolBar(helptb) |
|
3468 self.addToolBar(bookmarktb) |
|
3469 self.addToolBar(spellingtb) |
|
3470 self.addToolBar(unittesttb) |
|
3471 self.addToolBar(profilestb) |
|
3472 self.addToolBar(pluginstb) |
|
3473 |
|
3474 # hide toolbars not wanted in the initial layout |
|
3475 searchtb.hide() |
|
3476 viewtb.hide() |
|
3477 debugtb.hide() |
|
3478 multiprojecttb.hide() |
|
3479 helptb.hide() |
|
3480 spellingtb.hide() |
|
3481 unittesttb.hide() |
|
3482 pluginstb.hide() |
|
3483 |
|
3484 # just add new toolbars to the end of the list |
|
3485 self.__toolbars = {} |
|
3486 self.__toolbars["file"] = [filetb.windowTitle(), filetb, ""] |
|
3487 self.__toolbars["edit"] = [edittb.windowTitle(), edittb, ""] |
|
3488 self.__toolbars["search"] = [searchtb.windowTitle(), searchtb, ""] |
|
3489 self.__toolbars["view"] = [viewtb.windowTitle(), viewtb, ""] |
|
3490 self.__toolbars["start"] = [starttb.windowTitle(), starttb, ""] |
|
3491 self.__toolbars["debug"] = [debugtb.windowTitle(), debugtb, ""] |
|
3492 self.__toolbars["project"] = [projecttb.windowTitle(), projecttb, ""] |
|
3493 self.__toolbars["tools"] = [toolstb.windowTitle(), toolstb, ""] |
|
3494 self.__toolbars["help"] = [helptb.windowTitle(), helptb, ""] |
|
3495 self.__toolbars["settings"] = [settingstb.windowTitle(), settingstb, |
|
3496 ""] |
|
3497 self.__toolbars["bookmarks"] = [bookmarktb.windowTitle(), bookmarktb, |
|
3498 ""] |
|
3499 self.__toolbars["unittest"] = [unittesttb.windowTitle(), unittesttb, |
|
3500 ""] |
|
3501 self.__toolbars["view_profiles"] = [profilestb.windowTitle(), |
|
3502 profilestb, ""] |
|
3503 self.__toolbars["plugins"] = [pluginstb.windowTitle(), pluginstb, ""] |
|
3504 self.__toolbars["multiproject"] = [multiprojecttb.windowTitle(), |
|
3505 multiprojecttb, ""] |
|
3506 self.__toolbars["spelling"] = [spellingtb.windowTitle(), spellingtb, |
|
3507 ""] |
|
3508 self.__toolbars["vcs"] = [vcstb.windowTitle(), vcstb, "vcs"] |
|
3509 |
|
3510 def __initDebugToolbarsLayout(self): |
|
3511 """ |
|
3512 Private slot to initialize the toolbars layout for the debug profile. |
|
3513 """ |
|
3514 # Step 1: set the edit profile to be sure |
|
3515 self.__setEditProfile() |
|
3516 |
|
3517 # Step 2: switch to debug profile and do the layout |
|
3518 initSize = self.size() |
|
3519 self.setDebugProfile() |
|
3520 self.__toolbars["project"][1].hide() |
|
3521 self.__toolbars["debug"][1].show() |
|
3522 self.resize(initSize) |
|
3523 |
|
3524 # Step 3: switch back to edit profile |
|
3525 self.__setEditProfile() |
|
3526 |
|
3527 def __initStatusbar(self): |
|
3528 """ |
|
3529 Private slot to set up the status bar. |
|
3530 """ |
|
3531 self.__statusBar = self.statusBar() |
|
3532 self.__statusBar.setSizeGripEnabled(True) |
|
3533 |
|
3534 self.sbLanguage = E5ClickableLabel(self.__statusBar) |
|
3535 self.__statusBar.addPermanentWidget(self.sbLanguage) |
|
3536 self.sbLanguage.setWhatsThis(self.tr( |
|
3537 """<p>This part of the status bar displays the""" |
|
3538 """ current editors language.</p>""" |
|
3539 )) |
|
3540 |
|
3541 self.sbEncoding = E5ClickableLabel(self.__statusBar) |
|
3542 self.__statusBar.addPermanentWidget(self.sbEncoding) |
|
3543 self.sbEncoding.setWhatsThis(self.tr( |
|
3544 """<p>This part of the status bar displays the""" |
|
3545 """ current editors encoding.</p>""" |
|
3546 )) |
|
3547 |
|
3548 self.sbEol = E5ClickableLabel(self.__statusBar) |
|
3549 self.__statusBar.addPermanentWidget(self.sbEol) |
|
3550 self.sbEol.setWhatsThis(self.tr( |
|
3551 """<p>This part of the status bar displays the""" |
|
3552 """ current editors eol setting.</p>""" |
|
3553 )) |
|
3554 |
|
3555 self.sbWritable = QLabel(self.__statusBar) |
|
3556 self.__statusBar.addPermanentWidget(self.sbWritable) |
|
3557 self.sbWritable.setWhatsThis(self.tr( |
|
3558 """<p>This part of the status bar displays an indication of the""" |
|
3559 """ current editors files writability.</p>""" |
|
3560 )) |
|
3561 |
|
3562 self.sbLine = QLabel(self.__statusBar) |
|
3563 self.__statusBar.addPermanentWidget(self.sbLine) |
|
3564 self.sbLine.setWhatsThis(self.tr( |
|
3565 """<p>This part of the status bar displays the line number of""" |
|
3566 """ the current editor.</p>""" |
|
3567 )) |
|
3568 |
|
3569 self.sbPos = QLabel(self.__statusBar) |
|
3570 self.__statusBar.addPermanentWidget(self.sbPos) |
|
3571 self.sbPos.setWhatsThis(self.tr( |
|
3572 """<p>This part of the status bar displays the cursor position""" |
|
3573 """ of the current editor.</p>""" |
|
3574 )) |
|
3575 |
|
3576 self.sbZoom = E5ZoomWidget( |
|
3577 UI.PixmapCache.getPixmap("zoomOut"), |
|
3578 UI.PixmapCache.getPixmap("zoomIn"), |
|
3579 UI.PixmapCache.getPixmap("zoomReset"), |
|
3580 self.__statusBar) |
|
3581 self.__statusBar.addPermanentWidget(self.sbZoom) |
|
3582 self.sbZoom.setWhatsThis(self.tr( |
|
3583 """<p>This part of the status bar allows zooming the current""" |
|
3584 """ editor or shell.</p>""" |
|
3585 )) |
|
3586 |
|
3587 self.viewmanager.setSbInfo( |
|
3588 self.sbLine, self.sbPos, self.sbWritable, self.sbEncoding, |
|
3589 self.sbLanguage, self.sbEol, self.sbZoom) |
|
3590 |
|
3591 from VCS.StatusMonitorLed import StatusMonitorLedWidget |
|
3592 self.sbVcsMonitorLed = StatusMonitorLedWidget( |
|
3593 self.project, self.__statusBar) |
|
3594 self.__statusBar.addPermanentWidget(self.sbVcsMonitorLed) |
|
3595 |
|
3596 def __initExternalToolsActions(self): |
|
3597 """ |
|
3598 Private slot to create actions for the configured external tools. |
|
3599 """ |
|
3600 self.toolGroupActions = {} |
|
3601 for toolGroup in self.toolGroups: |
|
3602 category = self.tr("External Tools/{0}").format(toolGroup[0]) |
|
3603 for tool in toolGroup[1]: |
|
3604 if tool['menutext'] != '--': |
|
3605 act = QAction(UI.PixmapCache.getIcon(tool['icon']), |
|
3606 tool['menutext'], self) |
|
3607 act.setObjectName("{0}@@{1}".format(toolGroup[0], |
|
3608 tool['menutext'])) |
|
3609 act.triggered.connect( |
|
3610 functools.partial(self.__toolActionTriggered, act)) |
|
3611 self.toolGroupActions[act.objectName()] = act |
|
3612 |
|
3613 self.toolbarManager.addAction(act, category) |
|
3614 |
|
3615 def __updateExternalToolsActions(self): |
|
3616 """ |
|
3617 Private method to update the external tools actions for the current |
|
3618 tool group. |
|
3619 """ |
|
3620 toolGroup = self.toolGroups[self.currentToolGroup] |
|
3621 groupkey = "{0}@@".format(toolGroup[0]) |
|
3622 groupActionKeys = [] |
|
3623 # step 1: get actions for this group |
|
3624 for key in self.toolGroupActions: |
|
3625 if key.startswith(groupkey): |
|
3626 groupActionKeys.append(key) |
|
3627 |
|
3628 # step 2: build keys for all actions i.a.w. current configuration |
|
3629 ckeys = [] |
|
3630 for tool in toolGroup[1]: |
|
3631 if tool['menutext'] != '--': |
|
3632 ckeys.append("{0}@@{1}".format(toolGroup[0], tool['menutext'])) |
|
3633 |
|
3634 # step 3: remove all actions not configured any more |
|
3635 for key in groupActionKeys: |
|
3636 if key not in ckeys: |
|
3637 self.toolbarManager.removeAction(self.toolGroupActions[key]) |
|
3638 self.toolGroupActions[key].triggered.disconnect() |
|
3639 del self.toolGroupActions[key] |
|
3640 |
|
3641 # step 4: add all newly configured tools |
|
3642 category = self.tr("External Tools/{0}").format(toolGroup[0]) |
|
3643 for tool in toolGroup[1]: |
|
3644 if tool['menutext'] != '--': |
|
3645 key = "{0}@@{1}".format(toolGroup[0], tool['menutext']) |
|
3646 if key not in groupActionKeys: |
|
3647 act = QAction(UI.PixmapCache.getIcon(tool['icon']), |
|
3648 tool['menutext'], self) |
|
3649 act.setObjectName(key) |
|
3650 act.triggered.connect( |
|
3651 functools.partial(self.__toolActionTriggered, act)) |
|
3652 self.toolGroupActions[key] = act |
|
3653 |
|
3654 self.toolbarManager.addAction(act, category) |
|
3655 |
|
3656 def __showFileMenu(self): |
|
3657 """ |
|
3658 Private slot to display the File menu. |
|
3659 """ |
|
3660 self.showMenu.emit("File", self.__menus["file"]) |
|
3661 |
|
3662 def __showExtrasMenu(self): |
|
3663 """ |
|
3664 Private slot to display the Extras menu. |
|
3665 """ |
|
3666 self.showMenu.emit("Extras", self.__menus["extras"]) |
|
3667 |
|
3668 def __showWizardsMenu(self): |
|
3669 """ |
|
3670 Private slot to display the Wizards menu. |
|
3671 """ |
|
3672 self.showMenu.emit("Wizards", self.__menus["wizards"]) |
|
3673 |
|
3674 def __showHelpMenu(self): |
|
3675 """ |
|
3676 Private slot to display the Help menu. |
|
3677 """ |
|
3678 self.checkUpdateAct.setEnabled(not self.__inVersionCheck) |
|
3679 self.showVersionsAct.setEnabled(not self.__inVersionCheck) |
|
3680 self.showErrorLogAct.setEnabled(self.__hasErrorLog()) |
|
3681 |
|
3682 infoFileName = Globals.getInstallInfoFilePath() |
|
3683 self.showInstallInfoAct.setEnabled(os.path.exists(infoFileName)) |
|
3684 |
|
3685 self.showMenu.emit("Help", self.__menus["help"]) |
|
3686 |
|
3687 def __showSettingsMenu(self): |
|
3688 """ |
|
3689 Private slot to show the Settings menu. |
|
3690 """ |
|
3691 self.editMessageFilterAct.setEnabled( |
|
3692 E5ErrorMessage.messageHandlerInstalled()) |
|
3693 |
|
3694 self.showMenu.emit("Settings", self.__menus["settings"]) |
|
3695 |
|
3696 def __showNext(self): |
|
3697 """ |
|
3698 Private slot used to show the next tab or file. |
|
3699 """ |
|
3700 fwidget = QApplication.focusWidget() |
|
3701 while fwidget and not hasattr(fwidget, 'nextTab'): |
|
3702 fwidget = fwidget.parent() |
|
3703 if fwidget: |
|
3704 fwidget.nextTab() |
|
3705 |
|
3706 def __showPrevious(self): |
|
3707 """ |
|
3708 Private slot used to show the previous tab or file. |
|
3709 """ |
|
3710 fwidget = QApplication.focusWidget() |
|
3711 while fwidget and not hasattr(fwidget, 'prevTab'): |
|
3712 fwidget = fwidget.parent() |
|
3713 if fwidget: |
|
3714 fwidget.prevTab() |
|
3715 |
|
3716 def __switchTab(self): |
|
3717 """ |
|
3718 Private slot used to switch between the current and the previous |
|
3719 current tab. |
|
3720 """ |
|
3721 fwidget = QApplication.focusWidget() |
|
3722 while fwidget and not hasattr(fwidget, 'switchTab'): |
|
3723 fwidget = fwidget.parent() |
|
3724 if fwidget: |
|
3725 fwidget.switchTab() |
|
3726 |
|
3727 def __whatsThis(self): |
|
3728 """ |
|
3729 Private slot called in to enter Whats This mode. |
|
3730 """ |
|
3731 QWhatsThis.enterWhatsThisMode() |
|
3732 |
|
3733 def __showVersions(self): |
|
3734 """ |
|
3735 Private slot to handle the Versions dialog. |
|
3736 """ |
|
3737 try: |
|
3738 try: |
|
3739 from PyQt5 import sip |
|
3740 except ImportError: |
|
3741 import sip |
|
3742 sip_version_str = sip.SIP_VERSION_STR |
|
3743 except (ImportError, AttributeError): |
|
3744 sip_version_str = "sip version not available" |
|
3745 |
|
3746 sizeStr = "64-Bit" if sys.maxsize > 2**32 else "32-Bit" |
|
3747 |
|
3748 versionText = self.tr( |
|
3749 """<h2>Version Numbers</h2>""" |
|
3750 """<table>""") |
|
3751 versionText += ( |
|
3752 """<tr><td><b>Python</b></td><td>{0}, {1}</td></tr>""" |
|
3753 ).format(sys.version.split()[0], sizeStr) |
|
3754 versionText += ( |
|
3755 """<tr><td><b>Qt</b></td><td>{0}</td></tr>""" |
|
3756 ).format(qVersion()) |
|
3757 versionText += ( |
|
3758 """<tr><td><b>PyQt</b></td><td>{0}</td></tr>""" |
|
3759 ).format(PYQT_VERSION_STR) |
|
3760 with contextlib.suppress(ImportError, AttributeError): |
|
3761 from PyQt5 import QtChart |
|
3762 versionText += ( |
|
3763 """<tr><td><b>PyQtChart</b></td><td>{0}</td></tr>""" |
|
3764 ).format(QtChart.PYQT_CHART_VERSION_STR) |
|
3765 with contextlib.suppress(ImportError, AttributeError): |
|
3766 from PyQt5 import QtWebEngine |
|
3767 versionText += ( |
|
3768 """<tr><td><b>PyQtWebEngine</b></td><td>{0}</td></tr>""" |
|
3769 ).format(QtWebEngine.PYQT_WEBENGINE_VERSION_STR) |
|
3770 versionText += ( |
|
3771 """<tr><td><b>QScintilla</b></td><td>{0}</td></tr>""" |
|
3772 ).format(QSCINTILLA_VERSION_STR) |
|
3773 versionText += ( |
|
3774 """<tr><td><b>sip</b></td><td>{0}</td></tr>""" |
|
3775 ).format(sip_version_str) |
|
3776 with contextlib.suppress(ImportError): |
|
3777 from WebBrowser.Tools import WebBrowserTools |
|
3778 chromeVersion = WebBrowserTools.getWebEngineVersions()[0] |
|
3779 versionText += ( |
|
3780 """<tr><td><b>WebEngine</b></td><td>{0}</td></tr>""" |
|
3781 ).format(chromeVersion) |
|
3782 versionText += ("""<tr><td><b>{0}</b></td><td>{1}</td></tr>""" |
|
3783 ).format(Program, Version) |
|
3784 versionText += self.tr("""</table>""") |
|
3785 |
|
3786 E5MessageBox.about(self, Program, versionText) |
|
3787 |
|
3788 def __reportBug(self): |
|
3789 """ |
|
3790 Private slot to handle the Report Bug dialog. |
|
3791 """ |
|
3792 self.showEmailDialog("bug") |
|
3793 |
|
3794 def __requestFeature(self): |
|
3795 """ |
|
3796 Private slot to handle the Feature Request dialog. |
|
3797 """ |
|
3798 self.showEmailDialog("feature") |
|
3799 |
|
3800 def showEmailDialog(self, mode, attachFile=None, deleteAttachFile=False): |
|
3801 """ |
|
3802 Public slot to show the email dialog in a given mode. |
|
3803 |
|
3804 @param mode mode of the email dialog (string, "bug" or "feature") |
|
3805 @param attachFile name of a file to attach to the email (string) |
|
3806 @param deleteAttachFile flag indicating to delete the attached file |
|
3807 after it has been sent (boolean) |
|
3808 """ |
|
3809 if Preferences.getUser("UseSystemEmailClient"): |
|
3810 self.__showSystemEmailClient(mode, attachFile, deleteAttachFile) |
|
3811 else: |
|
3812 if not Preferences.getUser("UseGoogleMailOAuth2") and ( |
|
3813 Preferences.getUser("Email") == "" or |
|
3814 Preferences.getUser("MailServer") == ""): |
|
3815 E5MessageBox.critical( |
|
3816 self, |
|
3817 self.tr("Report Bug"), |
|
3818 self.tr( |
|
3819 """Email address or mail server address is empty.""" |
|
3820 """ Please configure your Email settings in the""" |
|
3821 """ Preferences Dialog.""")) |
|
3822 self.showPreferences("emailPage") |
|
3823 return |
|
3824 |
|
3825 from .EmailDialog import EmailDialog |
|
3826 self.dlg = EmailDialog(mode=mode) |
|
3827 if attachFile is not None: |
|
3828 self.dlg.attachFile(attachFile, deleteAttachFile) |
|
3829 self.dlg.show() |
|
3830 |
|
3831 def __showSystemEmailClient(self, mode, attachFile=None, |
|
3832 deleteAttachFile=False): |
|
3833 """ |
|
3834 Private slot to show the system email dialog. |
|
3835 |
|
3836 @param mode mode of the email dialog (string, "bug" or "feature") |
|
3837 @param attachFile name of a file to put into the body of the |
|
3838 email (string) |
|
3839 @param deleteAttachFile flag indicating to delete the file after |
|
3840 it has been read (boolean) |
|
3841 """ |
|
3842 address = FeatureAddress if mode == "feature" else BugAddress |
|
3843 subject = "[eric] " |
|
3844 if attachFile is not None: |
|
3845 with open(attachFile, "r", encoding="utf-8") as f: |
|
3846 body = f.read() |
|
3847 if deleteAttachFile: |
|
3848 os.remove(attachFile) |
|
3849 else: |
|
3850 body = "\r\n----\r\n{0}\r\n----\r\n{1}\r\n----\r\n{2}".format( |
|
3851 Utilities.generateVersionInfo("\r\n"), |
|
3852 Utilities.generatePluginsVersionInfo("\r\n"), |
|
3853 Utilities.generateDistroInfo("\r\n")) |
|
3854 |
|
3855 url = QUrl("mailto:{0}".format(address)) |
|
3856 urlQuery = QUrlQuery(url) |
|
3857 urlQuery.addQueryItem("subject", subject) |
|
3858 urlQuery.addQueryItem("body", body) |
|
3859 url.setQuery(urlQuery) |
|
3860 QDesktopServices.openUrl(url) |
|
3861 |
|
3862 def checkForErrorLog(self): |
|
3863 """ |
|
3864 Public method to check for the presence of an error log and ask the |
|
3865 user, what to do with it. |
|
3866 """ |
|
3867 if Preferences.getUI("CheckErrorLog"): |
|
3868 logFile = os.path.join(Utilities.getConfigDir(), |
|
3869 self.ErrorLogFileName) |
|
3870 if os.path.exists(logFile): |
|
3871 from .ErrorLogDialog import ErrorLogDialog |
|
3872 dlg = ErrorLogDialog(logFile, False, self) |
|
3873 dlg.exec() |
|
3874 |
|
3875 def __hasErrorLog(self): |
|
3876 """ |
|
3877 Private method to check, if an error log file exists. |
|
3878 |
|
3879 @return flag indicating the existence of an error log file (boolean) |
|
3880 """ |
|
3881 logFile = os.path.join(Utilities.getConfigDir(), |
|
3882 self.ErrorLogFileName) |
|
3883 return os.path.exists(logFile) |
|
3884 |
|
3885 def __showErrorLog(self): |
|
3886 """ |
|
3887 Private slot to show the most recent error log message. |
|
3888 """ |
|
3889 logFile = os.path.join(Utilities.getConfigDir(), |
|
3890 self.ErrorLogFileName) |
|
3891 if os.path.exists(logFile): |
|
3892 from .ErrorLogDialog import ErrorLogDialog |
|
3893 dlg = ErrorLogDialog(logFile, True, self) |
|
3894 dlg.show() |
|
3895 |
|
3896 def __showInstallInfo(self): |
|
3897 """ |
|
3898 Private slot to show a dialog containing information about the |
|
3899 installation process. |
|
3900 """ |
|
3901 from .InstallInfoDialog import InstallInfoDialog |
|
3902 dlg = InstallInfoDialog(self) |
|
3903 if dlg.wasLoaded(): |
|
3904 dlg.exec() |
|
3905 |
|
3906 def __compareFiles(self): |
|
3907 """ |
|
3908 Private slot to handle the Compare Files dialog. |
|
3909 """ |
|
3910 aw = self.viewmanager.activeWindow() |
|
3911 fn = aw and aw.getFileName() or None |
|
3912 if self.diffDlg is None: |
|
3913 from .DiffDialog import DiffDialog |
|
3914 self.diffDlg = DiffDialog() |
|
3915 self.diffDlg.show(fn) |
|
3916 |
|
3917 def __compareFilesSbs(self): |
|
3918 """ |
|
3919 Private slot to handle the Compare Files dialog. |
|
3920 """ |
|
3921 aw = self.viewmanager.activeWindow() |
|
3922 fn = aw and aw.getFileName() or None |
|
3923 if self.compareDlg is None: |
|
3924 from .CompareDialog import CompareDialog |
|
3925 self.compareDlg = CompareDialog() |
|
3926 self.compareDlg.show(fn) |
|
3927 |
|
3928 def __openMiniEditor(self): |
|
3929 """ |
|
3930 Private slot to show a mini editor window. |
|
3931 """ |
|
3932 from QScintilla.MiniEditor import MiniEditor |
|
3933 editor = MiniEditor(parent=self) |
|
3934 editor.show() |
|
3935 |
|
3936 def addE5Actions(self, actions, actionType): |
|
3937 """ |
|
3938 Public method to add actions to the list of actions. |
|
3939 |
|
3940 @param actions list of actions to be added (list of E5Action) |
|
3941 @param actionType string denoting the action set to add to. |
|
3942 It must be one of "ui" or "wizards". |
|
3943 """ |
|
3944 if actionType == 'ui': |
|
3945 self.actions.extend(actions) |
|
3946 elif actionType == 'wizards': |
|
3947 self.wizardsActions.extend(actions) |
|
3948 |
|
3949 def removeE5Actions(self, actions, actionType='ui'): |
|
3950 """ |
|
3951 Public method to remove actions from the list of actions. |
|
3952 |
|
3953 @param actions list of actions (list of E5Action) |
|
3954 @param actionType string denoting the action set to remove from. |
|
3955 It must be one of "ui" or "wizards". |
|
3956 """ |
|
3957 for act in actions: |
|
3958 with contextlib.suppress(ValueError): |
|
3959 if actionType == 'ui': |
|
3960 self.actions.remove(act) |
|
3961 elif actionType == 'wizards': |
|
3962 self.wizardsActions.remove(act) |
|
3963 |
|
3964 def getActions(self, actionType): |
|
3965 """ |
|
3966 Public method to get a list of all actions. |
|
3967 |
|
3968 @param actionType string denoting the action set to get. |
|
3969 It must be one of "ui" or "wizards". |
|
3970 @return list of all actions (list of E5Action) |
|
3971 """ |
|
3972 if actionType == 'ui': |
|
3973 return self.actions[:] |
|
3974 elif actionType == 'wizards': |
|
3975 return self.wizardsActions[:] |
|
3976 else: |
|
3977 return [] |
|
3978 |
|
3979 def getMenuAction(self, menuName, actionName): |
|
3980 """ |
|
3981 Public method to get a reference to an action of a menu. |
|
3982 |
|
3983 @param menuName name of the menu to search in (string) |
|
3984 @param actionName object name of the action to search for |
|
3985 (string) |
|
3986 @return reference to the menu action (QAction) |
|
3987 """ |
|
3988 try: |
|
3989 menu = self.__menus[menuName] |
|
3990 except KeyError: |
|
3991 return None |
|
3992 |
|
3993 for act in menu.actions(): |
|
3994 if act.objectName() == actionName: |
|
3995 return act |
|
3996 |
|
3997 return None |
|
3998 |
|
3999 def getMenuBarAction(self, menuName): |
|
4000 """ |
|
4001 Public method to get a reference to an action of the main menu. |
|
4002 |
|
4003 @param menuName name of the menu to search in (string) |
|
4004 @return reference to the menu bar action (QAction) |
|
4005 """ |
|
4006 try: |
|
4007 menu = self.__menus[menuName] |
|
4008 except KeyError: |
|
4009 return None |
|
4010 |
|
4011 return menu.menuAction() |
|
4012 |
|
4013 def getMenu(self, name): |
|
4014 """ |
|
4015 Public method to get a reference to a specific menu. |
|
4016 |
|
4017 @param name name of the menu (string) |
|
4018 @return reference to the menu (QMenu) |
|
4019 """ |
|
4020 try: |
|
4021 return self.__menus[name] |
|
4022 except KeyError: |
|
4023 return None |
|
4024 |
|
4025 def registerToolbar(self, name, text, toolbar, category=""): |
|
4026 """ |
|
4027 Public method to register a toolbar. |
|
4028 |
|
4029 This method must be called in order to make a toolbar manageable by the |
|
4030 UserInterface object. |
|
4031 |
|
4032 @param name name of the toolbar. This is used as the key into |
|
4033 the dictionary of toolbar references. |
|
4034 @type str |
|
4035 @param text user visible text for the toolbar entry |
|
4036 @type str |
|
4037 @param toolbar reference to the toolbar to be registered |
|
4038 @type QToolBar |
|
4039 @param category toolbar category |
|
4040 @type str |
|
4041 @exception KeyError raised, if a toolbar with the given name was |
|
4042 already registered |
|
4043 """ |
|
4044 if name in self.__toolbars: |
|
4045 raise KeyError("Toolbar '{0}' already registered.".format(name)) |
|
4046 |
|
4047 self.__toolbars[name] = [text, toolbar, category] |
|
4048 |
|
4049 def reregisterToolbar(self, name, text, category=""): |
|
4050 """ |
|
4051 Public method to change the visible text for the named toolbar. |
|
4052 |
|
4053 @param name name of the toolbar to be changed |
|
4054 @type str |
|
4055 @param text new user visible text for the toolbar entry |
|
4056 @type str |
|
4057 @param category new toolbar category for the toolbar entry |
|
4058 @type str |
|
4059 """ |
|
4060 if name in self.__toolbars: |
|
4061 self.__toolbars[name][0] = text |
|
4062 self.__toolbars[name][2] = category |
|
4063 |
|
4064 def unregisterToolbar(self, name): |
|
4065 """ |
|
4066 Public method to unregister a toolbar. |
|
4067 |
|
4068 @param name name of the toolbar (string). |
|
4069 """ |
|
4070 if name in self.__toolbars: |
|
4071 del self.__toolbars[name] |
|
4072 |
|
4073 def getToolbar(self, name): |
|
4074 """ |
|
4075 Public method to get a reference to a specific toolbar. |
|
4076 |
|
4077 @param name name of the toolbar (string) |
|
4078 @return reference to the toolbar entry (tuple of string and QToolBar) |
|
4079 """ |
|
4080 try: |
|
4081 return self.__toolbars[name] |
|
4082 except KeyError: |
|
4083 return None |
|
4084 |
|
4085 def getToolbarsByCategory(self, category): |
|
4086 """ |
|
4087 Public method to get a list of toolbars belonging to a given toolbar |
|
4088 category. |
|
4089 |
|
4090 @param category toolbar category |
|
4091 @type str |
|
4092 @return list of toolbars |
|
4093 @rtype list of QToolBar |
|
4094 """ |
|
4095 toolbars = [] |
|
4096 for tbName in self.__toolbars: |
|
4097 with contextlib.suppress(IndexError): |
|
4098 if self.__toolbars[tbName][2] == category: |
|
4099 toolbars.append(self.__toolbars[tbName][1]) |
|
4100 |
|
4101 return toolbars |
|
4102 |
|
4103 def getLocale(self): |
|
4104 """ |
|
4105 Public method to get the locale of the IDE. |
|
4106 |
|
4107 @return locale of the IDE (string or None) |
|
4108 """ |
|
4109 return self.locale |
|
4110 |
|
4111 def __quit(self): |
|
4112 """ |
|
4113 Private method to quit the application. |
|
4114 """ |
|
4115 if self.__shutdown(): |
|
4116 e5App().closeAllWindows() |
|
4117 |
|
4118 @pyqtSlot() |
|
4119 def __restart(self, ask=False): |
|
4120 """ |
|
4121 Private method to restart the application. |
|
4122 |
|
4123 @param ask flag indicating to ask the user for permission |
|
4124 @type bool |
|
4125 """ |
|
4126 res = ( |
|
4127 E5MessageBox.yesNo( |
|
4128 self, |
|
4129 self.tr("Restart application"), |
|
4130 self.tr( |
|
4131 """The application needs to be restarted. Do it now?"""), |
|
4132 yesDefault=True) |
|
4133 if ask else |
|
4134 True |
|
4135 ) |
|
4136 |
|
4137 if res and self.__shutdown(): |
|
4138 e5App().closeAllWindows() |
|
4139 program = sys.executable |
|
4140 eric6 = os.path.join(getConfig("ericDir"), "eric6.py") |
|
4141 args = [eric6] |
|
4142 args.append("--start-session") |
|
4143 args.extend(self.__restartArgs) |
|
4144 QProcess.startDetached(program, args) |
|
4145 |
|
4146 def __newWindow(self): |
|
4147 """ |
|
4148 Private slot to start a new instance of eric. |
|
4149 """ |
|
4150 if not Preferences.getUI("SingleApplicationMode"): |
|
4151 # start eric without any arguments |
|
4152 program = sys.executable |
|
4153 eric6 = os.path.join(getConfig("ericDir"), "eric6.py") |
|
4154 args = [eric6] |
|
4155 QProcess.startDetached(program, args) |
|
4156 |
|
4157 def __initToolsMenus(self, menu): |
|
4158 """ |
|
4159 Private slot to initialize the various tool menus. |
|
4160 |
|
4161 @param menu reference to the parent menu |
|
4162 @type QMenu |
|
4163 """ |
|
4164 btMenu = QMenu(self.tr("&Builtin Tools"), self) |
|
4165 if self.designer4Act is not None: |
|
4166 btMenu.addAction(self.designer4Act) |
|
4167 if self.linguist4Act is not None: |
|
4168 btMenu.addAction(self.linguist4Act) |
|
4169 btMenu.addAction(self.uipreviewerAct) |
|
4170 btMenu.addAction(self.trpreviewerAct) |
|
4171 btMenu.addAction(self.diffAct) |
|
4172 btMenu.addAction(self.compareAct) |
|
4173 btMenu.addAction(self.sqlBrowserAct) |
|
4174 btMenu.addAction(self.miniEditorAct) |
|
4175 btMenu.addAction(self.hexEditorAct) |
|
4176 btMenu.addAction(self.iconEditorAct) |
|
4177 btMenu.addAction(self.snapshotAct) |
|
4178 if self.webBrowserAct: |
|
4179 btMenu.addAction(self.webBrowserAct) |
|
4180 |
|
4181 ptMenu = QMenu(self.tr("&Plugin Tools"), self) |
|
4182 ptMenu.aboutToShow.connect(self.__showPluginToolsMenu) |
|
4183 |
|
4184 utMenu = QMenu(self.tr("&User Tools"), self) |
|
4185 utMenu.triggered.connect(self.__toolExecute) |
|
4186 utMenu.aboutToShow.connect(self.__showUserToolsMenu) |
|
4187 |
|
4188 menu.addMenu(btMenu) |
|
4189 menu.addMenu(ptMenu) |
|
4190 menu.addMenu(utMenu) |
|
4191 |
|
4192 self.__menus["builtin_tools"] = btMenu |
|
4193 self.__menus["plugin_tools"] = ptMenu |
|
4194 self.__menus["user_tools"] = utMenu |
|
4195 |
|
4196 def __showPluginToolsMenu(self): |
|
4197 """ |
|
4198 Private slot to show the Plugin Tools menu. |
|
4199 """ |
|
4200 self.showMenu.emit("PluginTools", self.__menus["plugin_tools"]) |
|
4201 |
|
4202 def __showUserToolsMenu(self): |
|
4203 """ |
|
4204 Private slot to display the User Tools menu. |
|
4205 """ |
|
4206 self.__menus["user_tools"].clear() |
|
4207 |
|
4208 self.__menus["user_tools"].addMenu(self.toolGroupsMenu) |
|
4209 act = self.__menus["user_tools"].addAction( |
|
4210 self.tr("Configure Tool Groups ..."), |
|
4211 self.__toolGroupsConfiguration) |
|
4212 act.setData(-1) |
|
4213 act = self.__menus["user_tools"].addAction( |
|
4214 self.tr("Configure current Tool Group ..."), |
|
4215 self.__toolsConfiguration) |
|
4216 act.setData(-2) |
|
4217 act.setEnabled(self.currentToolGroup >= 0) |
|
4218 self.__menus["user_tools"].addSeparator() |
|
4219 |
|
4220 # add the configurable entries |
|
4221 try: |
|
4222 for idx, tool in enumerate( |
|
4223 self.toolGroups[self.currentToolGroup][1] |
|
4224 ): |
|
4225 if tool['menutext'] == '--': |
|
4226 self.__menus["user_tools"].addSeparator() |
|
4227 else: |
|
4228 act = self.__menus["user_tools"].addAction( |
|
4229 UI.PixmapCache.getIcon(tool['icon']), |
|
4230 tool['menutext']) |
|
4231 act.setData(idx) |
|
4232 except IndexError: |
|
4233 # the current tool group might have been deleted |
|
4234 act = self.__menus["user_tools"].addAction( |
|
4235 self.tr("No User Tools Configured")) |
|
4236 act.setData(-3) |
|
4237 |
|
4238 def __showToolGroupsMenu(self): |
|
4239 """ |
|
4240 Private slot to display the Tool Groups menu. |
|
4241 """ |
|
4242 self.toolGroupsMenu.clear() |
|
4243 |
|
4244 # add the configurable tool groups |
|
4245 if self.toolGroups: |
|
4246 for idx, toolGroup in enumerate(self.toolGroups): |
|
4247 act = self.toolGroupsMenu.addAction(toolGroup[0]) |
|
4248 act.setData(idx) |
|
4249 if self.currentToolGroup == idx: |
|
4250 font = act.font() |
|
4251 font.setBold(True) |
|
4252 act.setFont(font) |
|
4253 else: |
|
4254 act = self.toolGroupsMenu.addAction( |
|
4255 self.tr("No User Tools Configured")) |
|
4256 act.setData(-3) |
|
4257 |
|
4258 def __toolGroupSelected(self, act): |
|
4259 """ |
|
4260 Private slot to set the current tool group. |
|
4261 |
|
4262 @param act reference to the action that was triggered (QAction) |
|
4263 """ |
|
4264 self.toolGroupsMenuTriggered = True |
|
4265 idx = act.data() |
|
4266 if idx is not None: |
|
4267 self.currentToolGroup = idx |
|
4268 |
|
4269 def __showWindowMenu(self): |
|
4270 """ |
|
4271 Private slot to display the Window menu. |
|
4272 """ |
|
4273 self.__menus["window"].clear() |
|
4274 |
|
4275 self.__menus["window"].addActions(self.viewProfileActGrp.actions()) |
|
4276 self.__menus["window"].addSeparator() |
|
4277 |
|
4278 if self.__layoutType == "Toolboxes": |
|
4279 self.__menus["window"].addAction(self.ltAct) |
|
4280 self.ltAct.setChecked(not self.lToolboxDock.isHidden()) |
|
4281 self.__menus["window"].addAction(self.rtAct) |
|
4282 self.rtAct.setChecked(not self.lToolboxDock.isHidden()) |
|
4283 self.__menus["window"].addAction(self.htAct) |
|
4284 self.htAct.setChecked(not self.hToolboxDock.isHidden()) |
|
4285 elif self.__layoutType == "Sidebars": |
|
4286 self.__menus["window"].addAction(self.lsbAct) |
|
4287 self.lsbAct.setChecked(not self.leftSidebar.isHidden()) |
|
4288 self.__menus["window"].addAction(self.rsbAct) |
|
4289 self.rsbAct.setChecked(not self.rightSidebar.isHidden()) |
|
4290 self.__menus["window"].addAction(self.bsbAct) |
|
4291 self.bsbAct.setChecked(not self.bottomSidebar.isHidden()) |
|
4292 |
|
4293 # Insert menu entry for sub-windows |
|
4294 self.__menus["window"].addSeparator() |
|
4295 self.__menus["window"].addMenu(self.__menus["subwindow"]) |
|
4296 |
|
4297 # Insert menu entry for toolbar settings |
|
4298 self.__menus["window"].addSeparator() |
|
4299 self.__menus["window"].addMenu(self.__menus["toolbars"]) |
|
4300 |
|
4301 # Now do any Source Viewer related stuff. |
|
4302 self.viewmanager.showWindowMenu(self.__menus["window"]) |
|
4303 |
|
4304 self.showMenu.emit("Window", self.__menus["window"]) |
|
4305 |
|
4306 def __showSubWindowMenu(self): |
|
4307 """ |
|
4308 Private slot to display the Window menu of the Window menu. |
|
4309 """ |
|
4310 self.showMenu.emit("Subwindows", self.__menus["subwindow"]) |
|
4311 |
|
4312 def __populateToolbarsMenu(self, menu): |
|
4313 """ |
|
4314 Private method to populate a toolbars menu. |
|
4315 |
|
4316 @param menu reference to the menu to be populated (QMenu) |
|
4317 """ |
|
4318 menu.clear() |
|
4319 |
|
4320 for name, (text, tb, _category) in sorted( |
|
4321 self.__toolbars.items(), key=lambda t: t[1][0] |
|
4322 ): |
|
4323 act = menu.addAction(text) |
|
4324 act.setCheckable(True) |
|
4325 act.setChecked(not tb.isHidden()) |
|
4326 act.setData(name) |
|
4327 menu.addSeparator() |
|
4328 act = menu.addAction(self.tr("&Show all")) |
|
4329 act.setData("__SHOW__") |
|
4330 act = menu.addAction(self.tr("&Hide all")) |
|
4331 act.setData("__HIDE__") |
|
4332 |
|
4333 def createPopupMenu(self): |
|
4334 """ |
|
4335 Public method to create the toolbars menu for Qt. |
|
4336 |
|
4337 @return toolbars menu (QMenu) |
|
4338 """ |
|
4339 menu = QMenu(self) |
|
4340 menu.triggered.connect(self.__TBPopupMenuTriggered) |
|
4341 |
|
4342 self.__populateToolbarsMenu(menu) |
|
4343 |
|
4344 return menu |
|
4345 |
|
4346 def __showToolbarsMenu(self): |
|
4347 """ |
|
4348 Private slot to display the Toolbars menu. |
|
4349 """ |
|
4350 self.__populateToolbarsMenu(self.__menus["toolbars"]) |
|
4351 |
|
4352 def __TBMenuTriggered(self, act): |
|
4353 """ |
|
4354 Private method to handle the toggle of a toolbar via the Window-> |
|
4355 Toolbars submenu. |
|
4356 |
|
4357 @param act reference to the action that was triggered (QAction) |
|
4358 """ |
|
4359 name = act.data() |
|
4360 if name: |
|
4361 if name == "__SHOW__": |
|
4362 for _text, tb, _category in self.__toolbars.values(): |
|
4363 tb.show() |
|
4364 if self.__menus["toolbars"].isTearOffMenuVisible(): |
|
4365 self.__menus["toolbars"].hideTearOffMenu() |
|
4366 elif name == "__HIDE__": |
|
4367 for _text, tb, _category in self.__toolbars.values(): |
|
4368 tb.hide() |
|
4369 if self.__menus["toolbars"].isTearOffMenuVisible(): |
|
4370 self.__menus["toolbars"].hideTearOffMenu() |
|
4371 else: |
|
4372 tb = self.__toolbars[name][1] |
|
4373 if act.isChecked(): |
|
4374 tb.show() |
|
4375 tb.setEnabled(True) |
|
4376 else: |
|
4377 tb.hide() |
|
4378 |
|
4379 def __TBPopupMenuTriggered(self, act): |
|
4380 """ |
|
4381 Private method to handle the toggle of a toolbar via the QMainWindow |
|
4382 Toolbars popup menu. |
|
4383 |
|
4384 @param act reference to the action that was triggered (QAction) |
|
4385 """ |
|
4386 name = act.data() |
|
4387 if name: |
|
4388 if name == "__SHOW__": |
|
4389 for _text, tb, _category in self.__toolbars.values(): |
|
4390 tb.show() |
|
4391 elif name == "__HIDE__": |
|
4392 for _text, tb, _category in self.__toolbars.values(): |
|
4393 tb.hide() |
|
4394 else: |
|
4395 tb = self.__toolbars[name][1] |
|
4396 if act.isChecked(): |
|
4397 tb.show() |
|
4398 tb.setEnabled(True) |
|
4399 else: |
|
4400 tb.hide() |
|
4401 if self.__menus["toolbars"].isTearOffMenuVisible(): |
|
4402 self.__menus["toolbars"].hideTearOffMenu() |
|
4403 |
|
4404 def __saveCurrentViewProfile(self, save): |
|
4405 """ |
|
4406 Private slot to save the window geometries of the active profile. |
|
4407 |
|
4408 @param save flag indicating that the current profile should |
|
4409 be saved (boolean) |
|
4410 """ |
|
4411 if self.currentProfile and save: |
|
4412 # step 1: save the window geometries of the active profile |
|
4413 if self.__layoutType in ["Toolboxes", "Sidebars"]: |
|
4414 state = self.saveState() |
|
4415 self.profiles[self.currentProfile][0] = state |
|
4416 if self.__layoutType == "Sidebars": |
|
4417 state = self.leftSplitter.saveState() |
|
4418 self.profiles[self.currentProfile][2][0] = state |
|
4419 state = self.verticalSplitter.saveState() |
|
4420 self.profiles[self.currentProfile][2][1] = state |
|
4421 state = self.leftSidebar.saveState() |
|
4422 self.profiles[self.currentProfile][2][2] = state |
|
4423 state = self.bottomSidebar.saveState() |
|
4424 self.profiles[self.currentProfile][2][3] = state |
|
4425 state = self.rightSplitter.saveState() |
|
4426 self.profiles[self.currentProfile][2][4] = state |
|
4427 state = self.rightSidebar.saveState() |
|
4428 self.profiles[self.currentProfile][2][5] = state |
|
4429 # step 2: save the visibility of the windows of the active profile |
|
4430 if self.__layoutType == "Toolboxes": |
|
4431 self.profiles[self.currentProfile][1][0] = ( |
|
4432 self.lToolboxDock.isVisible() |
|
4433 ) |
|
4434 self.profiles[self.currentProfile][1][1] = ( |
|
4435 self.hToolboxDock.isVisible() |
|
4436 ) |
|
4437 self.profiles[self.currentProfile][1][2] = ( |
|
4438 self.rToolboxDock.isVisible() |
|
4439 ) |
|
4440 elif self.__layoutType == "Sidebars": |
|
4441 self.profiles[self.currentProfile][1][0] = ( |
|
4442 self.leftSidebar.isVisible() |
|
4443 ) |
|
4444 self.profiles[self.currentProfile][1][1] = ( |
|
4445 self.bottomSidebar.isVisible() |
|
4446 ) |
|
4447 self.profiles[self.currentProfile][1][2] = ( |
|
4448 self.rightSidebar.isVisible() |
|
4449 ) |
|
4450 Preferences.setUI("ViewProfiles2", self.profiles) |
|
4451 |
|
4452 def __activateViewProfile(self, name, save=True): |
|
4453 """ |
|
4454 Private slot to activate a view profile. |
|
4455 |
|
4456 @param name name of the profile to be activated (string) |
|
4457 @param save flag indicating that the current profile should |
|
4458 be saved (boolean) |
|
4459 """ |
|
4460 if self.currentProfile != name or not save: |
|
4461 # step 1: save the active profile |
|
4462 self.__saveCurrentViewProfile(save) |
|
4463 |
|
4464 # step 2: set the window geometries of the new profile |
|
4465 if self.__layoutType in ["Toolboxes", "Sidebars"]: |
|
4466 state = self.profiles[name][0] |
|
4467 if not state.isEmpty(): |
|
4468 self.restoreState(state) |
|
4469 if self.__layoutType == "Sidebars": |
|
4470 state = self.profiles[name][2][0] |
|
4471 if not state.isEmpty(): |
|
4472 self.leftSplitter.restoreState(state) |
|
4473 state = self.profiles[name][2][1] |
|
4474 if not state.isEmpty(): |
|
4475 self.verticalSplitter.restoreState(state) |
|
4476 state = self.profiles[name][2][2] |
|
4477 if not state.isEmpty(): |
|
4478 self.leftSidebar.restoreState(state) |
|
4479 state = self.profiles[name][2][3] |
|
4480 if not state.isEmpty(): |
|
4481 self.bottomSidebar.restoreState(state) |
|
4482 state = self.profiles[name][2][4] |
|
4483 if not state.isEmpty(): |
|
4484 self.rightSplitter.restoreState(state) |
|
4485 state = self.profiles[name][2][5] |
|
4486 if not state.isEmpty(): |
|
4487 self.rightSidebar.restoreState(state) |
|
4488 |
|
4489 if self.__layoutType == "Toolboxes": |
|
4490 # set the corner usages |
|
4491 self.setCorner(Qt.Corner.TopLeftCorner, |
|
4492 Qt.DockWidgetArea.LeftDockWidgetArea) |
|
4493 self.setCorner(Qt.Corner.BottomLeftCorner, |
|
4494 Qt.DockWidgetArea.LeftDockWidgetArea) |
|
4495 self.setCorner(Qt.Corner.TopRightCorner, |
|
4496 Qt.DockWidgetArea.RightDockWidgetArea) |
|
4497 self.setCorner(Qt.Corner.BottomRightCorner, |
|
4498 Qt.DockWidgetArea.RightDockWidgetArea) |
|
4499 |
|
4500 # step 3: activate the windows of the new profile |
|
4501 if self.__layoutType == "Toolboxes": |
|
4502 self.lToolboxDock.setVisible(self.profiles[name][1][0]) |
|
4503 self.hToolboxDock.setVisible(self.profiles[name][1][1]) |
|
4504 self.rToolboxDock.setVisible(self.profiles[name][1][2]) |
|
4505 elif self.__layoutType == "Sidebars": |
|
4506 self.leftSidebar.setVisible(self.profiles[name][1][0]) |
|
4507 self.bottomSidebar.setVisible(self.profiles[name][1][1]) |
|
4508 self.rightSidebar.setVisible(self.profiles[name][1][2]) |
|
4509 |
|
4510 # step 4: remember the new profile |
|
4511 self.currentProfile = name |
|
4512 |
|
4513 # step 5: make sure that cursor of the shell is visible |
|
4514 self.shell.ensureCursorVisible() |
|
4515 |
|
4516 # step 6: make sure, that the toolbars and window menu are |
|
4517 # shown correctly |
|
4518 if self.__menus["toolbars"].isTearOffMenuVisible(): |
|
4519 self.__showToolbarsMenu() |
|
4520 if self.__menus["window"].isTearOffMenuVisible(): |
|
4521 self.__showWindowMenu() |
|
4522 |
|
4523 def __debuggingStarted(self): |
|
4524 """ |
|
4525 Private slot to handle the start of a debugging session. |
|
4526 """ |
|
4527 self.setDebugProfile() |
|
4528 if self.__layoutType == "Toolboxes": |
|
4529 self.__currentRightWidget = self.rToolbox.currentWidget() |
|
4530 self.rToolbox.setCurrentWidget(self.debugViewer) |
|
4531 self.__currentBottomWidget = self.hToolbox.currentWidget() |
|
4532 self.hToolbox.setCurrentWidget(self.shellAssembly) |
|
4533 elif self.__layoutType == "Sidebars": |
|
4534 self.__currentRightWidget = self.rightSidebar.currentWidget() |
|
4535 self.rightSidebar.setCurrentWidget(self.debugViewer) |
|
4536 self.__currentBottomWidget = self.bottomSidebar.currentWidget() |
|
4537 self.bottomSidebar.setCurrentWidget(self.shellAssembly) |
|
4538 |
|
4539 def __debuggingDone(self): |
|
4540 """ |
|
4541 Private slot to handle the end of a debugging session. |
|
4542 """ |
|
4543 self.__setEditProfile() |
|
4544 if self.__layoutType == "Toolboxes": |
|
4545 if self.__currentRightWidget: |
|
4546 self.rToolbox.setCurrentWidget(self.__currentRightWidget) |
|
4547 if self.__currentBottomWidget: |
|
4548 self.hToolbox.setCurrentWidget(self.__currentBottomWidget) |
|
4549 elif self.__layoutType == "Sidebars": |
|
4550 if self.__currentRightWidget: |
|
4551 self.rightSidebar.setCurrentWidget(self.__currentRightWidget) |
|
4552 if self.__currentBottomWidget: |
|
4553 self.bottomSidebar.setCurrentWidget(self.__currentBottomWidget) |
|
4554 self.__currentRightWidget = None |
|
4555 self.__currentBottomWidget = None |
|
4556 self.__activateViewmanager() |
|
4557 |
|
4558 @pyqtSlot() |
|
4559 def __setEditProfile(self, save=True): |
|
4560 """ |
|
4561 Private slot to activate the edit view profile. |
|
4562 |
|
4563 @param save flag indicating that the current profile should |
|
4564 be saved (boolean) |
|
4565 """ |
|
4566 self.__activateViewProfile("edit", save) |
|
4567 self.setEditProfileAct.setChecked(True) |
|
4568 |
|
4569 @pyqtSlot() |
|
4570 def setDebugProfile(self, save=True): |
|
4571 """ |
|
4572 Public slot to activate the debug view profile. |
|
4573 |
|
4574 @param save flag indicating that the current profile should |
|
4575 be saved (boolean) |
|
4576 """ |
|
4577 self.viewmanager.searchWidget().hide() |
|
4578 self.viewmanager.replaceWidget().hide() |
|
4579 self.__activateViewProfile("debug", save) |
|
4580 self.setDebugProfileAct.setChecked(True) |
|
4581 |
|
4582 def getViewProfile(self): |
|
4583 """ |
|
4584 Public method to get the current view profile. |
|
4585 |
|
4586 @return the name of the current view profile (string) |
|
4587 """ |
|
4588 return self.currentProfile |
|
4589 |
|
4590 def getLayoutType(self): |
|
4591 """ |
|
4592 Public method to get the current layout type. |
|
4593 |
|
4594 @return current layout type |
|
4595 @rtype str |
|
4596 """ |
|
4597 return self.__layoutType |
|
4598 |
|
4599 def __activateProjectBrowser(self): |
|
4600 """ |
|
4601 Private slot to handle the activation of the project browser. |
|
4602 """ |
|
4603 if self.__layoutType == "Toolboxes": |
|
4604 self.lToolboxDock.show() |
|
4605 self.lToolbox.setCurrentWidget(self.projectBrowser) |
|
4606 elif self.__layoutType == "Sidebars": |
|
4607 self.leftSidebar.show() |
|
4608 self.leftSidebar.setCurrentWidget(self.projectBrowser) |
|
4609 self.projectBrowser.currentWidget().setFocus( |
|
4610 Qt.FocusReason.ActiveWindowFocusReason) |
|
4611 |
|
4612 def __activateMultiProjectBrowser(self): |
|
4613 """ |
|
4614 Private slot to handle the activation of the project browser. |
|
4615 """ |
|
4616 if self.__layoutType == "Toolboxes": |
|
4617 self.lToolboxDock.show() |
|
4618 self.lToolbox.setCurrentWidget(self.multiProjectBrowser) |
|
4619 elif self.__layoutType == "Sidebars": |
|
4620 self.leftSidebar.show() |
|
4621 self.leftSidebar.setCurrentWidget(self.multiProjectBrowser) |
|
4622 self.multiProjectBrowser.setFocus( |
|
4623 Qt.FocusReason.ActiveWindowFocusReason) |
|
4624 |
|
4625 def activateDebugViewer(self): |
|
4626 """ |
|
4627 Public slot to handle the activation of the debug viewer. |
|
4628 """ |
|
4629 if self.__layoutType == "Toolboxes": |
|
4630 self.rToolboxDock.show() |
|
4631 self.rToolbox.setCurrentWidget(self.debugViewer) |
|
4632 elif self.__layoutType == "Sidebars": |
|
4633 self.rightSidebar.show() |
|
4634 self.rightSidebar.setCurrentWidget(self.debugViewer) |
|
4635 self.debugViewer.currentWidget().setFocus( |
|
4636 Qt.FocusReason.ActiveWindowFocusReason) |
|
4637 |
|
4638 def __activateShell(self): |
|
4639 """ |
|
4640 Private slot to handle the activation of the Shell window. |
|
4641 """ |
|
4642 if self.__layoutType == "Toolboxes": |
|
4643 self.__shellParent.show() |
|
4644 self.__shellParent.widget().setCurrentWidget(self.shellAssembly) |
|
4645 elif self.__layoutType == "Sidebars": |
|
4646 self.__shellParent.show() |
|
4647 self.__shellParent.setCurrentWidget(self.shellAssembly) |
|
4648 self.shell.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4649 |
|
4650 def __activateLogViewer(self): |
|
4651 """ |
|
4652 Private slot to handle the activation of the Log Viewer. |
|
4653 """ |
|
4654 if self.__layoutType == "Toolboxes": |
|
4655 self.hToolboxDock.show() |
|
4656 self.hToolbox.setCurrentWidget(self.logViewer) |
|
4657 elif self.__layoutType == "Sidebars": |
|
4658 self.bottomSidebar.show() |
|
4659 self.bottomSidebar.setCurrentWidget(self.logViewer) |
|
4660 self.logViewer.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4661 |
|
4662 def __activateTaskViewer(self): |
|
4663 """ |
|
4664 Private slot to handle the activation of the Task Viewer. |
|
4665 """ |
|
4666 if self.__layoutType == "Toolboxes": |
|
4667 self.hToolboxDock.show() |
|
4668 self.hToolbox.setCurrentWidget(self.taskViewer) |
|
4669 elif self.__layoutType == "Sidebars": |
|
4670 self.bottomSidebar.show() |
|
4671 self.bottomSidebar.setCurrentWidget(self.taskViewer) |
|
4672 self.taskViewer.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4673 |
|
4674 def __activateTemplateViewer(self): |
|
4675 """ |
|
4676 Private slot to handle the activation of the Template Viewer. |
|
4677 """ |
|
4678 if self.templateViewer is not None: |
|
4679 if self.__layoutType == "Toolboxes": |
|
4680 self.lToolboxDock.show() |
|
4681 self.lToolbox.setCurrentWidget(self.templateViewer) |
|
4682 elif self.__layoutType == "Sidebars": |
|
4683 self.leftSidebar.show() |
|
4684 self.leftSidebar.setCurrentWidget(self.templateViewer) |
|
4685 self.templateViewer.setFocus( |
|
4686 Qt.FocusReason.ActiveWindowFocusReason) |
|
4687 |
|
4688 def __activateBrowser(self): |
|
4689 """ |
|
4690 Private slot to handle the activation of the file browser. |
|
4691 """ |
|
4692 if self.browser is not None: |
|
4693 if self.__layoutType == "Toolboxes": |
|
4694 self.lToolboxDock.show() |
|
4695 self.lToolbox.setCurrentWidget(self.browser) |
|
4696 elif self.__layoutType == "Sidebars": |
|
4697 self.leftSidebar.show() |
|
4698 self.leftSidebar.setCurrentWidget(self.browser) |
|
4699 self.browser.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4700 |
|
4701 def __toggleLeftToolbox(self): |
|
4702 """ |
|
4703 Private slot to handle the toggle of the Left Toolbox window. |
|
4704 """ |
|
4705 hasFocus = self.lToolbox.currentWidget().hasFocus() |
|
4706 shown = self.__toggleWindow(self.lToolboxDock) |
|
4707 if shown: |
|
4708 self.lToolbox.currentWidget().setFocus( |
|
4709 Qt.FocusReason.ActiveWindowFocusReason) |
|
4710 else: |
|
4711 if hasFocus: |
|
4712 self.__activateViewmanager() |
|
4713 |
|
4714 def __toggleRightToolbox(self): |
|
4715 """ |
|
4716 Private slot to handle the toggle of the Right Toolbox window. |
|
4717 """ |
|
4718 hasFocus = self.rToolbox.currentWidget().hasFocus() |
|
4719 shown = self.__toggleWindow(self.rToolboxDock) |
|
4720 if shown: |
|
4721 self.rToolbox.currentWidget().setFocus( |
|
4722 Qt.FocusReason.ActiveWindowFocusReason) |
|
4723 else: |
|
4724 if hasFocus: |
|
4725 self.__activateViewmanager() |
|
4726 |
|
4727 def __toggleHorizontalToolbox(self): |
|
4728 """ |
|
4729 Private slot to handle the toggle of the Horizontal Toolbox window. |
|
4730 """ |
|
4731 hasFocus = self.hToolbox.currentWidget().hasFocus() |
|
4732 shown = self.__toggleWindow(self.hToolboxDock) |
|
4733 if shown: |
|
4734 self.hToolbox.currentWidget().setFocus( |
|
4735 Qt.FocusReason.ActiveWindowFocusReason) |
|
4736 else: |
|
4737 if hasFocus: |
|
4738 self.__activateViewmanager() |
|
4739 |
|
4740 def __toggleLeftSidebar(self): |
|
4741 """ |
|
4742 Private slot to handle the toggle of the left sidebar window. |
|
4743 """ |
|
4744 hasFocus = self.leftSidebar.currentWidget().hasFocus() |
|
4745 shown = self.__toggleWindow(self.leftSidebar) |
|
4746 if shown: |
|
4747 self.leftSidebar.currentWidget().setFocus( |
|
4748 Qt.FocusReason.ActiveWindowFocusReason) |
|
4749 else: |
|
4750 if hasFocus: |
|
4751 self.__activateViewmanager() |
|
4752 |
|
4753 def __toggleRightSidebar(self): |
|
4754 """ |
|
4755 Private slot to handle the toggle of the right sidebar window. |
|
4756 """ |
|
4757 hasFocus = self.rightSidebar.currentWidget().hasFocus() |
|
4758 shown = self.__toggleWindow(self.rightSidebar) |
|
4759 if shown: |
|
4760 self.rightSidebar.currentWidget().setFocus( |
|
4761 Qt.FocusReason.ActiveWindowFocusReason) |
|
4762 else: |
|
4763 if hasFocus: |
|
4764 self.__activateViewmanager() |
|
4765 |
|
4766 def __toggleBottomSidebar(self): |
|
4767 """ |
|
4768 Private slot to handle the toggle of the bottom sidebar window. |
|
4769 """ |
|
4770 hasFocus = self.bottomSidebar.currentWidget().hasFocus() |
|
4771 shown = self.__toggleWindow(self.bottomSidebar) |
|
4772 if shown: |
|
4773 self.bottomSidebar.currentWidget().setFocus( |
|
4774 Qt.FocusReason.ActiveWindowFocusReason) |
|
4775 else: |
|
4776 if hasFocus: |
|
4777 self.__activateViewmanager() |
|
4778 |
|
4779 def activateCooperationViewer(self): |
|
4780 """ |
|
4781 Public slot to handle the activation of the cooperation window. |
|
4782 """ |
|
4783 if self.cooperation is not None: |
|
4784 if self.__layoutType == "Toolboxes": |
|
4785 self.rToolboxDock.show() |
|
4786 self.rToolbox.setCurrentWidget(self.cooperation) |
|
4787 elif self.__layoutType == "Sidebars": |
|
4788 self.rightSidebar.show() |
|
4789 self.rightSidebar.setCurrentWidget(self.cooperation) |
|
4790 self.cooperation.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4791 |
|
4792 def __activateIRC(self): |
|
4793 """ |
|
4794 Private slot to handle the activation of the IRC window. |
|
4795 """ |
|
4796 if self.irc is not None: |
|
4797 if self.__layoutType == "Toolboxes": |
|
4798 self.rToolboxDock.show() |
|
4799 self.rToolbox.setCurrentWidget(self.irc) |
|
4800 elif self.__layoutType == "Sidebars": |
|
4801 self.rightSidebar.show() |
|
4802 self.rightSidebar.setCurrentWidget(self.irc) |
|
4803 self.irc.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4804 |
|
4805 def __activateSymbolsViewer(self): |
|
4806 """ |
|
4807 Private slot to handle the activation of the Symbols Viewer. |
|
4808 """ |
|
4809 if self.symbolsViewer is not None: |
|
4810 if self.__layoutType == "Toolboxes": |
|
4811 self.lToolboxDock.show() |
|
4812 self.lToolbox.setCurrentWidget(self.symbolsViewer) |
|
4813 elif self.__layoutType == "Sidebars": |
|
4814 self.leftSidebar.show() |
|
4815 self.leftSidebar.setCurrentWidget(self.symbolsViewer) |
|
4816 self.symbolsViewer.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4817 |
|
4818 def __activateNumbersViewer(self): |
|
4819 """ |
|
4820 Private slot to handle the activation of the Numbers Viewer. |
|
4821 """ |
|
4822 if self.numbersViewer is not None: |
|
4823 if self.__layoutType == "Toolboxes": |
|
4824 self.hToolboxDock.show() |
|
4825 self.hToolbox.setCurrentWidget(self.numbersViewer) |
|
4826 elif self.__layoutType == "Sidebars": |
|
4827 self.bottomSidebar.show() |
|
4828 self.bottomSidebar.setCurrentWidget(self.numbersViewer) |
|
4829 self.numbersViewer.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4830 |
|
4831 def __activateViewmanager(self): |
|
4832 """ |
|
4833 Private slot to handle the activation of the current editor. |
|
4834 """ |
|
4835 aw = self.viewmanager.activeWindow() |
|
4836 if aw is not None: |
|
4837 aw.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4838 |
|
4839 def activateCodeDocumentationViewer(self, switchFocus=True): |
|
4840 """ |
|
4841 Public slot to handle the activation of the Code Documentation Viewer. |
|
4842 |
|
4843 @param switchFocus flag indicating to transfer the input focus |
|
4844 @type bool |
|
4845 """ |
|
4846 if self.codeDocumentationViewer is not None: |
|
4847 if self.__layoutType == "Toolboxes": |
|
4848 self.rToolboxDock.show() |
|
4849 self.rToolbox.setCurrentWidget(self.codeDocumentationViewer) |
|
4850 elif self.__layoutType == "Sidebars": |
|
4851 self.rightSidebar.show() |
|
4852 self.rightSidebar.setCurrentWidget( |
|
4853 self.codeDocumentationViewer) |
|
4854 if switchFocus: |
|
4855 self.codeDocumentationViewer.setFocus( |
|
4856 Qt.FocusReason.ActiveWindowFocusReason) |
|
4857 |
|
4858 def __activatePipWidget(self): |
|
4859 """ |
|
4860 Private slot to handle the activation of the PyPI manager widget. |
|
4861 """ |
|
4862 if self.pipWidget is not None: |
|
4863 if self.__layoutType == "Toolboxes": |
|
4864 self.rToolboxDock.show() |
|
4865 self.rToolbox.setCurrentWidget(self.pipWidget) |
|
4866 elif self.__layoutType == "Sidebars": |
|
4867 self.rightSidebar.show() |
|
4868 self.rightSidebar.setCurrentWidget(self.pipWidget) |
|
4869 self.pipWidget.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4870 |
|
4871 def __activateCondaWidget(self): |
|
4872 """ |
|
4873 Private slot to handle the activation of the Conda manager widget. |
|
4874 """ |
|
4875 if self.condaWidget is not None: |
|
4876 if self.__layoutType == "Toolboxes": |
|
4877 self.rToolboxDock.show() |
|
4878 self.rToolbox.setCurrentWidget(self.condaWidget) |
|
4879 elif self.__layoutType == "Sidebars": |
|
4880 self.rightSidebar.show() |
|
4881 self.rightSidebar.setCurrentWidget(self.condaWidget) |
|
4882 self.condaWidget.setFocus(Qt.FocusReason.ActiveWindowFocusReason) |
|
4883 |
|
4884 def __activateMicroPython(self): |
|
4885 """ |
|
4886 Private slot to handle the activation of the MicroPython widget. |
|
4887 """ |
|
4888 if self.microPythonWidget is not None: |
|
4889 if self.__layoutType == "Toolboxes": |
|
4890 self.rToolboxDock.show() |
|
4891 self.rToolbox.setCurrentWidget(self.microPythonWidget) |
|
4892 elif self.__layoutType == "Sidebars": |
|
4893 self.rightSidebar.show() |
|
4894 self.rightSidebar.setCurrentWidget(self.microPythonWidget) |
|
4895 self.microPythonWidget.setFocus( |
|
4896 Qt.FocusReason.ActiveWindowFocusReason) |
|
4897 |
|
4898 def __toggleWindow(self, w): |
|
4899 """ |
|
4900 Private method to toggle a workspace editor window. |
|
4901 |
|
4902 @param w reference to the workspace editor window |
|
4903 @return flag indicating, if the window was shown (boolean) |
|
4904 """ |
|
4905 if w.isHidden(): |
|
4906 w.show() |
|
4907 return True |
|
4908 else: |
|
4909 w.hide() |
|
4910 return False |
|
4911 |
|
4912 def __toolsConfiguration(self): |
|
4913 """ |
|
4914 Private slot to handle the tools configuration menu entry. |
|
4915 """ |
|
4916 from Preferences.ToolConfigurationDialog import ToolConfigurationDialog |
|
4917 dlg = ToolConfigurationDialog( |
|
4918 self.toolGroups[self.currentToolGroup][1], self) |
|
4919 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
4920 self.toolGroups[self.currentToolGroup][1] = dlg.getToollist() |
|
4921 self.__updateExternalToolsActions() |
|
4922 |
|
4923 def __toolGroupsConfiguration(self): |
|
4924 """ |
|
4925 Private slot to handle the tool groups configuration menu entry. |
|
4926 """ |
|
4927 from Preferences.ToolGroupConfigurationDialog import ( |
|
4928 ToolGroupConfigurationDialog |
|
4929 ) |
|
4930 dlg = ToolGroupConfigurationDialog( |
|
4931 self.toolGroups, self.currentToolGroup, self) |
|
4932 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
4933 self.toolGroups, self.currentToolGroup = dlg.getToolGroups() |
|
4934 |
|
4935 def __createUnitTestDialog(self): |
|
4936 """ |
|
4937 Private slot to generate the unit test dialog on demand. |
|
4938 """ |
|
4939 if self.unittestDialog is None: |
|
4940 from PyUnit.UnittestDialog import UnittestDialog |
|
4941 self.unittestDialog = UnittestDialog( |
|
4942 None, self.debuggerUI.debugServer, self) |
|
4943 self.unittestDialog.unittestFile.connect( |
|
4944 self.viewmanager.setFileLine) |
|
4945 self.unittestDialog.unittestStopped.connect(self.__unittestStopped) |
|
4946 |
|
4947 def __unittestStopped(self): |
|
4948 """ |
|
4949 Private slot to handle the end of a unit test run. |
|
4950 """ |
|
4951 self.utRerunFailedAct.setEnabled(self.unittestDialog.hasFailedTests()) |
|
4952 self.utRestartAct.setEnabled(True) |
|
4953 |
|
4954 def __unittest(self): |
|
4955 """ |
|
4956 Private slot for displaying the unittest dialog. |
|
4957 """ |
|
4958 self.__createUnitTestDialog() |
|
4959 self.unittestDialog.show() |
|
4960 self.unittestDialog.raise_() |
|
4961 |
|
4962 @pyqtSlot() |
|
4963 @pyqtSlot(str) |
|
4964 def __unittestScript(self, prog=None): |
|
4965 """ |
|
4966 Private slot for displaying the unittest dialog and run the current |
|
4967 script. |
|
4968 |
|
4969 @param prog the python program to be opened |
|
4970 """ |
|
4971 if prog is None: |
|
4972 aw = self.viewmanager.activeWindow() |
|
4973 fn = aw.getFileName() |
|
4974 tfn = Utilities.getTestFileName(fn) |
|
4975 if os.path.exists(tfn): |
|
4976 prog = tfn |
|
4977 else: |
|
4978 prog = fn |
|
4979 |
|
4980 self.__unittest() |
|
4981 self.unittestDialog.setProjectMode(False) |
|
4982 self.unittestDialog.insertProg(prog) |
|
4983 self.utRestartAct.setEnabled(False) |
|
4984 self.utRerunFailedAct.setEnabled(False) |
|
4985 |
|
4986 def __unittestProject(self): |
|
4987 """ |
|
4988 Private slot for displaying the unittest dialog and run the current |
|
4989 project. |
|
4990 """ |
|
4991 prog = None |
|
4992 fn = self.project.getMainScript(True) |
|
4993 if fn: |
|
4994 tfn = Utilities.getTestFileName(fn) |
|
4995 if os.path.exists(tfn): |
|
4996 prog = tfn |
|
4997 else: |
|
4998 prog = fn |
|
4999 |
|
5000 self.__unittest() |
|
5001 self.unittestDialog.setProjectMode(True) |
|
5002 self.unittestDialog.insertProg(prog) |
|
5003 self.utRestartAct.setEnabled(False) |
|
5004 self.utRerunFailedAct.setEnabled(False) |
|
5005 |
|
5006 def __unittestRestart(self): |
|
5007 """ |
|
5008 Private slot to display the unittest dialog and rerun the last |
|
5009 unit test. |
|
5010 """ |
|
5011 self.__unittest() |
|
5012 self.unittestDialog.startTests() |
|
5013 |
|
5014 def __unittestRerunFailed(self): |
|
5015 """ |
|
5016 Private slot to display the unittest dialog and rerun all failed tests |
|
5017 of the last run. |
|
5018 """ |
|
5019 self.__unittest() |
|
5020 self.unittestDialog.startTests(failedOnly=True) |
|
5021 |
|
5022 @pyqtSlot() |
|
5023 @pyqtSlot(str) |
|
5024 def __designer(self, fn=None): |
|
5025 """ |
|
5026 Private slot to start the Qt-Designer executable. |
|
5027 |
|
5028 @param fn filename of the form to be opened |
|
5029 @type str |
|
5030 """ |
|
5031 args = [] |
|
5032 if fn is not None: |
|
5033 try: |
|
5034 if os.path.isfile(fn) and os.path.getsize(fn): |
|
5035 args.append(fn) |
|
5036 else: |
|
5037 E5MessageBox.critical( |
|
5038 self, |
|
5039 self.tr('Problem'), |
|
5040 self.tr( |
|
5041 '<p>The file <b>{0}</b> does not exist or' |
|
5042 ' is zero length.</p>') |
|
5043 .format(fn)) |
|
5044 return |
|
5045 except OSError: |
|
5046 E5MessageBox.critical( |
|
5047 self, |
|
5048 self.tr('Problem'), |
|
5049 self.tr( |
|
5050 '<p>The file <b>{0}</b> does not exist or' |
|
5051 ' is zero length.</p>') |
|
5052 .format(fn)) |
|
5053 return |
|
5054 |
|
5055 if Utilities.isMacPlatform(): |
|
5056 designer, args = Utilities.prepareQtMacBundle( |
|
5057 "designer", args) |
|
5058 else: |
|
5059 designer = os.path.join( |
|
5060 Utilities.getQtBinariesPath(), |
|
5061 Utilities.generateQtToolName("designer")) |
|
5062 if Utilities.isWindowsPlatform(): |
|
5063 designer += '.exe' |
|
5064 |
|
5065 if designer: |
|
5066 proc = QProcess() |
|
5067 if not proc.startDetached(designer, args): |
|
5068 E5MessageBox.critical( |
|
5069 self, |
|
5070 self.tr('Process Generation Error'), |
|
5071 self.tr( |
|
5072 '<p>Could not start Qt-Designer.<br>' |
|
5073 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5074 ).format(designer) |
|
5075 ) |
|
5076 else: |
|
5077 E5MessageBox.critical( |
|
5078 self, |
|
5079 self.tr('Process Generation Error'), |
|
5080 self.tr( |
|
5081 '<p>Could not find the Qt-Designer executable.<br>' |
|
5082 'Ensure that it is installed and optionally configured on' |
|
5083 ' the Qt configuration page.</p>' |
|
5084 ) |
|
5085 ) |
|
5086 |
|
5087 @pyqtSlot() |
|
5088 @pyqtSlot(str) |
|
5089 def __linguist(self, fn=None): |
|
5090 """ |
|
5091 Private slot to start the Qt-Linguist executable. |
|
5092 |
|
5093 @param fn filename of the translation file to be opened |
|
5094 @type str |
|
5095 """ |
|
5096 args = [] |
|
5097 if fn is not None: |
|
5098 fn = fn.replace('.qm', '.ts') |
|
5099 try: |
|
5100 if ( |
|
5101 os.path.isfile(fn) and |
|
5102 os.path.getsize(fn) and |
|
5103 fn not in args |
|
5104 ): |
|
5105 args.append(fn) |
|
5106 else: |
|
5107 E5MessageBox.critical( |
|
5108 self, |
|
5109 self.tr('Problem'), |
|
5110 self.tr( |
|
5111 '<p>The file <b>{0}</b> does not exist or' |
|
5112 ' is zero length.</p>') |
|
5113 .format(fn)) |
|
5114 return |
|
5115 except OSError: |
|
5116 E5MessageBox.critical( |
|
5117 self, |
|
5118 self.tr('Problem'), |
|
5119 self.tr( |
|
5120 '<p>The file <b>{0}</b> does not exist or' |
|
5121 ' is zero length.</p>') |
|
5122 .format(fn)) |
|
5123 return |
|
5124 |
|
5125 if Utilities.isMacPlatform(): |
|
5126 linguist, args = Utilities.prepareQtMacBundle( |
|
5127 "linguist", args) |
|
5128 else: |
|
5129 linguist = os.path.join( |
|
5130 Utilities.getQtBinariesPath(), |
|
5131 Utilities.generateQtToolName("linguist")) |
|
5132 if Utilities.isWindowsPlatform(): |
|
5133 linguist += '.exe' |
|
5134 |
|
5135 if linguist: |
|
5136 proc = QProcess() |
|
5137 if not proc.startDetached(linguist, args): |
|
5138 E5MessageBox.critical( |
|
5139 self, |
|
5140 self.tr('Process Generation Error'), |
|
5141 self.tr( |
|
5142 '<p>Could not start Qt-Linguist.<br>' |
|
5143 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5144 ).format(linguist) |
|
5145 ) |
|
5146 else: |
|
5147 E5MessageBox.critical( |
|
5148 self, |
|
5149 self.tr('Process Generation Error'), |
|
5150 self.tr( |
|
5151 '<p>Could not find the Qt-Linguist executable.<br>' |
|
5152 'Ensure that it is installed and optionally configured on' |
|
5153 ' the Qt configuration page.</p>' |
|
5154 ) |
|
5155 ) |
|
5156 |
|
5157 def __assistant(self, home=None): |
|
5158 """ |
|
5159 Private slot to start the Qt-Assistant executable. |
|
5160 |
|
5161 @param home full pathname of a file to display |
|
5162 @type str |
|
5163 """ |
|
5164 args = [] |
|
5165 if home: |
|
5166 args.append('-showUrl') |
|
5167 args.append(home) |
|
5168 |
|
5169 if Utilities.isMacPlatform(): |
|
5170 assistant, args = Utilities.prepareQtMacBundle( |
|
5171 "assistant", args) |
|
5172 else: |
|
5173 assistant = os.path.join( |
|
5174 Utilities.getQtBinariesPath(), |
|
5175 Utilities.generateQtToolName("assistant")) |
|
5176 if Utilities.isWindowsPlatform(): |
|
5177 assistant += '.exe' |
|
5178 |
|
5179 if assistant: |
|
5180 proc = QProcess() |
|
5181 if not proc.startDetached(assistant, args): |
|
5182 E5MessageBox.critical( |
|
5183 self, |
|
5184 self.tr('Process Generation Error'), |
|
5185 self.tr( |
|
5186 '<p>Could not start Qt-Assistant.<br>' |
|
5187 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5188 ).format(assistant) |
|
5189 ) |
|
5190 else: |
|
5191 E5MessageBox.critical( |
|
5192 self, |
|
5193 self.tr('Process Generation Error'), |
|
5194 self.tr( |
|
5195 '<p>Could not find the Qt-Assistant executable.<br>' |
|
5196 'Ensure that it is installed and optionally configured on' |
|
5197 ' the Qt configuration page.</p>' |
|
5198 ) |
|
5199 ) |
|
5200 |
|
5201 def __startWebBrowser(self): |
|
5202 """ |
|
5203 Private slot to start the eric web browser. |
|
5204 """ |
|
5205 self.launchHelpViewer("") |
|
5206 |
|
5207 def __customViewer(self, home=None): |
|
5208 """ |
|
5209 Private slot to start a custom viewer. |
|
5210 |
|
5211 @param home full pathname of a file to display (string) |
|
5212 """ |
|
5213 customViewer = Preferences.getHelp("CustomViewer") |
|
5214 if not customViewer: |
|
5215 E5MessageBox.information( |
|
5216 self, |
|
5217 self.tr("Help"), |
|
5218 self.tr( |
|
5219 """Currently no custom viewer is selected.""" |
|
5220 """ Please use the preferences dialog to specify one.""")) |
|
5221 return |
|
5222 |
|
5223 proc = QProcess() |
|
5224 args = [] |
|
5225 if home: |
|
5226 args.append(home) |
|
5227 |
|
5228 if not proc.startDetached(customViewer, args): |
|
5229 E5MessageBox.critical( |
|
5230 self, |
|
5231 self.tr('Process Generation Error'), |
|
5232 self.tr( |
|
5233 '<p>Could not start custom viewer.<br>' |
|
5234 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5235 ).format(customViewer)) |
|
5236 |
|
5237 def __chmViewer(self, home=None): |
|
5238 """ |
|
5239 Private slot to start the win help viewer to show *.chm files. |
|
5240 |
|
5241 @param home full pathname of a file to display (string) |
|
5242 """ |
|
5243 if home: |
|
5244 proc = QProcess() |
|
5245 args = [] |
|
5246 args.append(home) |
|
5247 |
|
5248 if not proc.startDetached("hh", args): |
|
5249 E5MessageBox.critical( |
|
5250 self, |
|
5251 self.tr('Process Generation Error'), |
|
5252 self.tr( |
|
5253 '<p>Could not start the help viewer.<br>' |
|
5254 'Ensure that it is available as <b>hh</b>.</p>' |
|
5255 )) |
|
5256 |
|
5257 @pyqtSlot() |
|
5258 @pyqtSlot(str) |
|
5259 def __UIPreviewer(self, fn=None): |
|
5260 """ |
|
5261 Private slot to start the UI Previewer executable. |
|
5262 |
|
5263 @param fn filename of the form to be previewed (string) |
|
5264 """ |
|
5265 proc = QProcess() |
|
5266 |
|
5267 viewer = os.path.join(getConfig("ericDir"), "eric6_uipreviewer.py") |
|
5268 |
|
5269 args = [] |
|
5270 args.append(viewer) |
|
5271 |
|
5272 if fn is not None: |
|
5273 try: |
|
5274 if os.path.isfile(fn) and os.path.getsize(fn): |
|
5275 args.append(fn) |
|
5276 else: |
|
5277 E5MessageBox.critical( |
|
5278 self, |
|
5279 self.tr('Problem'), |
|
5280 self.tr( |
|
5281 '<p>The file <b>{0}</b> does not exist or' |
|
5282 ' is zero length.</p>') |
|
5283 .format(fn)) |
|
5284 return |
|
5285 except OSError: |
|
5286 E5MessageBox.critical( |
|
5287 self, |
|
5288 self.tr('Problem'), |
|
5289 self.tr( |
|
5290 '<p>The file <b>{0}</b> does not exist or' |
|
5291 ' is zero length.</p>') |
|
5292 .format(fn)) |
|
5293 return |
|
5294 |
|
5295 if ( |
|
5296 not os.path.isfile(viewer) or |
|
5297 not proc.startDetached(sys.executable, args) |
|
5298 ): |
|
5299 E5MessageBox.critical( |
|
5300 self, |
|
5301 self.tr('Process Generation Error'), |
|
5302 self.tr( |
|
5303 '<p>Could not start UI Previewer.<br>' |
|
5304 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5305 ).format(viewer)) |
|
5306 |
|
5307 @pyqtSlot() |
|
5308 @pyqtSlot(str) |
|
5309 @pyqtSlot(str, bool) |
|
5310 def __TRPreviewer(self, fileNames=None, ignore=False): |
|
5311 """ |
|
5312 Private slot to start the Translation Previewer executable. |
|
5313 |
|
5314 @param fileNames filenames of forms and/or translations to be previewed |
|
5315 (list of strings) |
|
5316 @param ignore flag indicating non existing files should be ignored |
|
5317 (boolean) |
|
5318 """ |
|
5319 proc = QProcess() |
|
5320 |
|
5321 viewer = os.path.join(getConfig("ericDir"), "eric6_trpreviewer.py") |
|
5322 |
|
5323 args = [] |
|
5324 args.append(viewer) |
|
5325 |
|
5326 if fileNames is not None: |
|
5327 for fn in fileNames: |
|
5328 try: |
|
5329 if os.path.isfile(fn) and os.path.getsize(fn): |
|
5330 args.append(fn) |
|
5331 else: |
|
5332 if not ignore: |
|
5333 E5MessageBox.critical( |
|
5334 self, |
|
5335 self.tr('Problem'), |
|
5336 self.tr( |
|
5337 '<p>The file <b>{0}</b> does not exist or' |
|
5338 ' is zero length.</p>') |
|
5339 .format(fn)) |
|
5340 return |
|
5341 except OSError: |
|
5342 if not ignore: |
|
5343 E5MessageBox.critical( |
|
5344 self, |
|
5345 self.tr('Problem'), |
|
5346 self.tr( |
|
5347 '<p>The file <b>{0}</b> does not exist or' |
|
5348 ' is zero length.</p>') |
|
5349 .format(fn)) |
|
5350 return |
|
5351 |
|
5352 if ( |
|
5353 not os.path.isfile(viewer) or |
|
5354 not proc.startDetached(sys.executable, args) |
|
5355 ): |
|
5356 E5MessageBox.critical( |
|
5357 self, |
|
5358 self.tr('Process Generation Error'), |
|
5359 self.tr( |
|
5360 '<p>Could not start Translation Previewer.<br>' |
|
5361 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5362 ).format(viewer)) |
|
5363 |
|
5364 def __sqlBrowser(self): |
|
5365 """ |
|
5366 Private slot to start the SQL browser tool. |
|
5367 """ |
|
5368 proc = QProcess() |
|
5369 |
|
5370 browser = os.path.join(getConfig("ericDir"), "eric6_sqlbrowser.py") |
|
5371 |
|
5372 args = [] |
|
5373 args.append(browser) |
|
5374 |
|
5375 if ( |
|
5376 not os.path.isfile(browser) or |
|
5377 not proc.startDetached(sys.executable, args) |
|
5378 ): |
|
5379 E5MessageBox.critical( |
|
5380 self, |
|
5381 self.tr('Process Generation Error'), |
|
5382 self.tr( |
|
5383 '<p>Could not start SQL Browser.<br>' |
|
5384 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5385 ).format(browser)) |
|
5386 |
|
5387 @pyqtSlot() |
|
5388 @pyqtSlot(str) |
|
5389 def __openHexEditor(self, fn=""): |
|
5390 """ |
|
5391 Private slot to open the hex editor window. |
|
5392 |
|
5393 @param fn filename of the file to show (string) |
|
5394 """ |
|
5395 from HexEdit.HexEditMainWindow import HexEditMainWindow |
|
5396 dlg = HexEditMainWindow(fn, self, fromEric=True, project=self.project) |
|
5397 dlg.show() |
|
5398 |
|
5399 @pyqtSlot() |
|
5400 @pyqtSlot(str) |
|
5401 def __editPixmap(self, fn=""): |
|
5402 """ |
|
5403 Private slot to show a pixmap in a dialog. |
|
5404 |
|
5405 @param fn filename of the file to show (string) |
|
5406 """ |
|
5407 from IconEditor.IconEditorWindow import IconEditorWindow |
|
5408 dlg = IconEditorWindow(fn, self, fromEric=True, project=self.project) |
|
5409 dlg.show() |
|
5410 |
|
5411 @pyqtSlot() |
|
5412 @pyqtSlot(str) |
|
5413 def __showPixmap(self, fn): |
|
5414 """ |
|
5415 Private slot to show a pixmap in a dialog. |
|
5416 |
|
5417 @param fn filename of the file to show (string) |
|
5418 """ |
|
5419 from Graphics.PixmapDiagram import PixmapDiagram |
|
5420 dlg = PixmapDiagram(fn, self) |
|
5421 if dlg.getStatus(): |
|
5422 dlg.show() |
|
5423 |
|
5424 @pyqtSlot() |
|
5425 @pyqtSlot(str) |
|
5426 def __showSvg(self, fn): |
|
5427 """ |
|
5428 Private slot to show a SVG file in a dialog. |
|
5429 |
|
5430 @param fn filename of the file to show (string) |
|
5431 """ |
|
5432 from Graphics.SvgDiagram import SvgDiagram |
|
5433 dlg = SvgDiagram(fn, self) |
|
5434 dlg.show() |
|
5435 |
|
5436 @pyqtSlot(str) |
|
5437 def __showUml(self, fn): |
|
5438 """ |
|
5439 Private slot to show an eric graphics file in a dialog. |
|
5440 |
|
5441 @param fn name of the file to be shown |
|
5442 @type str |
|
5443 """ |
|
5444 from Graphics.UMLDialog import UMLDialog, UMLDialogType |
|
5445 dlg = UMLDialog(UMLDialogType.NO_DIAGRAM, self.project, parent=self) |
|
5446 if dlg.load(fn): |
|
5447 dlg.show(fromFile=True) |
|
5448 |
|
5449 def __snapshot(self): |
|
5450 """ |
|
5451 Private slot to start the snapshot tool. |
|
5452 """ |
|
5453 proc = QProcess() |
|
5454 |
|
5455 snap = os.path.join(getConfig("ericDir"), "eric6_snap.py") |
|
5456 |
|
5457 args = [] |
|
5458 args.append(snap) |
|
5459 |
|
5460 if ( |
|
5461 not os.path.isfile(snap) or |
|
5462 not proc.startDetached(sys.executable, args) |
|
5463 ): |
|
5464 E5MessageBox.critical( |
|
5465 self, |
|
5466 self.tr('Process Generation Error'), |
|
5467 self.tr( |
|
5468 '<p>Could not start Snapshot tool.<br>' |
|
5469 'Ensure that it is available as <b>{0}</b>.</p>' |
|
5470 ).format(snap)) |
|
5471 |
|
5472 def __toolActionTriggered(self, act): |
|
5473 """ |
|
5474 Private slot called by external tools toolbar actions. |
|
5475 |
|
5476 @param act reference to the action that triggered the slot |
|
5477 @type QAction |
|
5478 """ |
|
5479 toolGroupName, toolMenuText = act.objectName().split('@@', 1) |
|
5480 for toolGroup in self.toolGroups: |
|
5481 if toolGroup[0] == toolGroupName: |
|
5482 for tool in toolGroup[1]: |
|
5483 if tool['menutext'] == toolMenuText: |
|
5484 self.__startToolProcess(tool) |
|
5485 return |
|
5486 |
|
5487 E5MessageBox.information( |
|
5488 self, |
|
5489 self.tr("External Tools"), |
|
5490 self.tr( |
|
5491 """No tool entry found for external tool '{0}' """ |
|
5492 """in tool group '{1}'.""") |
|
5493 .format(toolMenuText, toolGroupName)) |
|
5494 return |
|
5495 |
|
5496 E5MessageBox.information( |
|
5497 self, |
|
5498 self.tr("External Tools"), |
|
5499 self.tr("""No toolgroup entry '{0}' found.""") |
|
5500 .format(toolGroupName) |
|
5501 ) |
|
5502 |
|
5503 def __toolExecute(self, act): |
|
5504 """ |
|
5505 Private slot to execute a particular tool. |
|
5506 |
|
5507 @param act reference to the action that was triggered (QAction) |
|
5508 """ |
|
5509 if self.toolGroupsMenuTriggered: |
|
5510 # ignore actions triggered from the select tool group submenu |
|
5511 self.toolGroupsMenuTriggered = False |
|
5512 return |
|
5513 |
|
5514 if self.currentToolGroup < 0: |
|
5515 # it was an action not to be handled here |
|
5516 return |
|
5517 |
|
5518 idx = act.data() |
|
5519 if idx is not None and idx >= 0: |
|
5520 tool = self.toolGroups[self.currentToolGroup][1][idx] |
|
5521 self.__startToolProcess(tool) |
|
5522 |
|
5523 def __startToolProcess(self, tool): |
|
5524 """ |
|
5525 Private slot to start an external tool process. |
|
5526 |
|
5527 @param tool list of tool entries |
|
5528 """ |
|
5529 proc = QProcess() |
|
5530 procData = (None,) |
|
5531 program = tool['executable'] |
|
5532 args = [] |
|
5533 argv = Utilities.parseOptionString(tool['arguments']) |
|
5534 args.extend(argv) |
|
5535 t = self.tr("Starting process '{0} {1}'.\n" |
|
5536 ).format(program, tool['arguments']) |
|
5537 self.appendToStdout(t) |
|
5538 |
|
5539 proc.finished.connect(self.__toolFinished) |
|
5540 if tool['redirect'] != 'no': |
|
5541 proc.readyReadStandardOutput.connect(self.__processToolStdout) |
|
5542 proc.readyReadStandardError.connect(self.__processToolStderr) |
|
5543 if tool['redirect'] in ["insert", "replaceSelection"]: |
|
5544 aw = self.viewmanager.activeWindow() |
|
5545 procData = (aw, tool['redirect'], []) |
|
5546 if aw is not None: |
|
5547 aw.beginUndoAction() |
|
5548 |
|
5549 proc.start(program, args) |
|
5550 if not proc.waitForStarted(): |
|
5551 E5MessageBox.critical( |
|
5552 self, |
|
5553 self.tr('Process Generation Error'), |
|
5554 self.tr( |
|
5555 '<p>Could not start the tool entry <b>{0}</b>.<br>' |
|
5556 'Ensure that it is available as <b>{1}</b>.</p>') |
|
5557 .format(tool['menutext'], tool['executable'])) |
|
5558 else: |
|
5559 self.toolProcs.append((program, proc, procData)) |
|
5560 if tool['redirect'] == 'no': |
|
5561 proc.closeReadChannel(QProcess.ProcessChannel.StandardOutput) |
|
5562 proc.closeReadChannel(QProcess.ProcessChannel.StandardError) |
|
5563 proc.closeWriteChannel() |
|
5564 |
|
5565 def __processToolStdout(self): |
|
5566 """ |
|
5567 Private slot to handle the readyReadStdout signal of a tool process. |
|
5568 """ |
|
5569 ioEncoding = Preferences.getSystem("IOEncoding") |
|
5570 |
|
5571 # loop through all running tool processes |
|
5572 for program, toolProc, toolProcData in self.toolProcs: |
|
5573 toolProc.setReadChannel(QProcess.ProcessChannel.StandardOutput) |
|
5574 |
|
5575 if ( |
|
5576 toolProcData[0] is None or |
|
5577 toolProcData[1] not in ["insert", "replaceSelection"] |
|
5578 ): |
|
5579 # not connected to an editor or wrong mode |
|
5580 while toolProc.canReadLine(): |
|
5581 output = str(toolProc.readLine(), ioEncoding, 'replace') |
|
5582 s = "{0} - {1}".format(program, output) |
|
5583 self.appendToStdout(s) |
|
5584 else: |
|
5585 if toolProcData[1] == "insert": |
|
5586 text = str(toolProc.readAll(), ioEncoding, 'replace') |
|
5587 toolProcData[0].insert(text) |
|
5588 elif toolProcData[1] == "replaceSelection": |
|
5589 text = str(toolProc.readAll(), ioEncoding, 'replace') |
|
5590 toolProcData[2].append(text) |
|
5591 |
|
5592 def __processToolStderr(self): |
|
5593 """ |
|
5594 Private slot to handle the readyReadStderr signal of a tool process. |
|
5595 """ |
|
5596 ioEncoding = Preferences.getSystem("IOEncoding") |
|
5597 |
|
5598 # loop through all running tool processes |
|
5599 for program, toolProc, _toolProcData in self.toolProcs: |
|
5600 toolProc.setReadChannel(QProcess.ProcessChannel.StandardError) |
|
5601 |
|
5602 while toolProc.canReadLine(): |
|
5603 error = str(toolProc.readLine(), ioEncoding, 'replace') |
|
5604 s = "{0} - {1}".format(program, error) |
|
5605 self.appendToStderr(s) |
|
5606 |
|
5607 def __toolFinished(self, exitCode, exitStatus): |
|
5608 """ |
|
5609 Private slot to handle the finished signal of a tool process. |
|
5610 |
|
5611 @param exitCode exit code of the process (integer) |
|
5612 @param exitStatus exit status of the process (QProcess.ExitStatus) |
|
5613 """ |
|
5614 exitedProcs = [] |
|
5615 |
|
5616 # loop through all running tool processes |
|
5617 for program, toolProc, toolProcData in self.toolProcs: |
|
5618 if toolProc.state() == QProcess.ProcessState.NotRunning: |
|
5619 exitedProcs.append((program, toolProc, toolProcData)) |
|
5620 if toolProcData[0] is not None: |
|
5621 if toolProcData[1] == "replaceSelection": |
|
5622 text = ''.join(toolProcData[2]) |
|
5623 toolProcData[0].replace(text) |
|
5624 toolProcData[0].endUndoAction() |
|
5625 |
|
5626 # now delete the exited procs from the list of running processes |
|
5627 for proc in exitedProcs: |
|
5628 self.toolProcs.remove(proc) |
|
5629 t = self.tr("Process '{0}' has exited.\n").format(proc[0]) |
|
5630 self.appendToStdout(t) |
|
5631 |
|
5632 def __showPythonDoc(self): |
|
5633 """ |
|
5634 Private slot to show the Python 3 documentation. |
|
5635 """ |
|
5636 pythonDocDir = Preferences.getHelp("PythonDocDir") |
|
5637 if not pythonDocDir: |
|
5638 if Utilities.isWindowsPlatform(): |
|
5639 venvName = Preferences.getDebugger("Python3VirtualEnv") |
|
5640 interpreter = ( |
|
5641 e5App().getObject("VirtualEnvManager") |
|
5642 .getVirtualenvInterpreter(venvName) |
|
5643 ) |
|
5644 if interpreter: |
|
5645 default = os.path.join(os.path.dirname(interpreter), "doc") |
|
5646 else: |
|
5647 default = "" |
|
5648 pythonDocDir = Utilities.getEnvironmentEntry( |
|
5649 "PYTHON3DOCDIR", default) |
|
5650 else: |
|
5651 pythonDocDir = Utilities.getEnvironmentEntry( |
|
5652 "PYTHON3DOCDIR", |
|
5653 '/usr/share/doc/packages/python3/html') |
|
5654 if not pythonDocDir.startswith(("http://", "https://", "qthelp://")): |
|
5655 if pythonDocDir.startswith("file://"): |
|
5656 pythonDocDir = pythonDocDir[7:] |
|
5657 if not os.path.splitext(pythonDocDir)[1]: |
|
5658 home = Utilities.normjoinpath(pythonDocDir, 'index.html') |
|
5659 |
|
5660 if Utilities.isWindowsPlatform() and not os.path.exists(home): |
|
5661 pyversion = sys.hexversion >> 16 |
|
5662 vers = "{0:d}{1:d}".format((pyversion >> 8) & 0xff, |
|
5663 pyversion & 0xff) |
|
5664 home = os.path.join( |
|
5665 pythonDocDir, "python{0}.chm".format(vers)) |
|
5666 else: |
|
5667 home = pythonDocDir |
|
5668 |
|
5669 if not os.path.exists(home): |
|
5670 E5MessageBox.warning( |
|
5671 self, |
|
5672 self.tr("Documentation Missing"), |
|
5673 self.tr("""<p>The documentation starting point""" |
|
5674 """ "<b>{0}</b>" could not be found.</p>""") |
|
5675 .format(home)) |
|
5676 return |
|
5677 |
|
5678 if not home.endswith(".chm"): |
|
5679 if Utilities.isWindowsPlatform(): |
|
5680 home = "file:///" + Utilities.fromNativeSeparators(home) |
|
5681 else: |
|
5682 home = "file://" + home |
|
5683 else: |
|
5684 home = pythonDocDir |
|
5685 |
|
5686 if home.endswith(".chm"): |
|
5687 self.__chmViewer(home) |
|
5688 else: |
|
5689 hvType = Preferences.getWebBrowser("HelpViewerType") |
|
5690 if hvType == 1: |
|
5691 self.launchHelpViewer(home) |
|
5692 elif hvType == 2: |
|
5693 if home.startswith("qthelp://"): |
|
5694 self.__assistant(home) |
|
5695 else: |
|
5696 self.__webBrowser(home) |
|
5697 elif hvType == 3: |
|
5698 self.__webBrowser(home) |
|
5699 else: |
|
5700 self.__customViewer(home) |
|
5701 |
|
5702 def __showQtDoc(self, version): |
|
5703 """ |
|
5704 Private method to show the Qt documentation. |
|
5705 |
|
5706 @param version Qt version to show documentation for |
|
5707 @type int |
|
5708 """ |
|
5709 if version in [5, 6]: |
|
5710 qtDocDir = Preferences.getQtDocDir(version) |
|
5711 else: |
|
5712 return |
|
5713 |
|
5714 if qtDocDir.startswith("qthelp://"): |
|
5715 if not os.path.splitext(qtDocDir)[1]: |
|
5716 home = qtDocDir + "/index.html" |
|
5717 else: |
|
5718 home = qtDocDir |
|
5719 elif qtDocDir.startswith(("http://", "https://")): |
|
5720 home = qtDocDir |
|
5721 else: |
|
5722 if qtDocDir.startswith("file://"): |
|
5723 qtDocDir = qtDocDir[7:] |
|
5724 if not os.path.splitext(qtDocDir)[1]: |
|
5725 home = Utilities.normjoinpath(qtDocDir, 'index.html') |
|
5726 else: |
|
5727 home = qtDocDir |
|
5728 |
|
5729 if not os.path.exists(home): |
|
5730 E5MessageBox.warning( |
|
5731 self, |
|
5732 self.tr("Documentation Missing"), |
|
5733 self.tr("""<p>The documentation starting point""" |
|
5734 """ "<b>{0}</b>" could not be found.</p>""") |
|
5735 .format(home)) |
|
5736 return |
|
5737 |
|
5738 if Utilities.isWindowsPlatform(): |
|
5739 home = "file:///" + Utilities.fromNativeSeparators(home) |
|
5740 else: |
|
5741 home = "file://" + home |
|
5742 |
|
5743 hvType = Preferences.getWebBrowser("HelpViewerType") |
|
5744 if hvType == 1: |
|
5745 self.launchHelpViewer(home) |
|
5746 elif hvType == 2: |
|
5747 if home.startswith("qthelp://"): |
|
5748 self.__assistant(home) |
|
5749 else: |
|
5750 self.__webBrowser(home) |
|
5751 elif hvType == 3: |
|
5752 self.__webBrowser(home) |
|
5753 else: |
|
5754 self.__customViewer(home) |
|
5755 |
|
5756 def __showPyQtDoc(self, variant=5): |
|
5757 """ |
|
5758 Private slot to show the PyQt5/6 documentation. |
|
5759 |
|
5760 @param variant PyQt variant to show documentation for (5 or 6) |
|
5761 @type int or str |
|
5762 """ |
|
5763 pyqtDocDir = Preferences.getHelp("PyQt{0}DocDir".format(variant)) |
|
5764 if not pyqtDocDir: |
|
5765 pyqtDocDir = Utilities.getEnvironmentEntry( |
|
5766 "PYQT{0}DOCDIR".format(variant), None) |
|
5767 |
|
5768 if not pyqtDocDir: |
|
5769 E5MessageBox.warning( |
|
5770 self, |
|
5771 self.tr("Documentation"), |
|
5772 self.tr("""<p>The PyQt{0} documentation starting point""" |
|
5773 """ has not been configured.</p>""").format(variant)) |
|
5774 return |
|
5775 |
|
5776 if not pyqtDocDir.startswith(("http://", "https://", "qthelp://")): |
|
5777 home = "" |
|
5778 if pyqtDocDir: |
|
5779 if pyqtDocDir.startswith("file://"): |
|
5780 pyqtDocDir = pyqtDocDir[7:] |
|
5781 if not os.path.splitext(pyqtDocDir)[1]: |
|
5782 possibleHomes = [ |
|
5783 Utilities.normjoinpath( |
|
5784 pyqtDocDir, 'index.html'), |
|
5785 Utilities.normjoinpath( |
|
5786 pyqtDocDir, 'class_reference.html'), |
|
5787 ] |
|
5788 for possibleHome in possibleHomes: |
|
5789 if os.path.exists(possibleHome): |
|
5790 home = possibleHome |
|
5791 break |
|
5792 else: |
|
5793 home = pyqtDocDir |
|
5794 |
|
5795 if not home or not os.path.exists(home): |
|
5796 E5MessageBox.warning( |
|
5797 self, |
|
5798 self.tr("Documentation Missing"), |
|
5799 self.tr("""<p>The documentation starting point""" |
|
5800 """ "<b>{0}</b>" could not be found.</p>""") |
|
5801 .format(home)) |
|
5802 return |
|
5803 |
|
5804 if Utilities.isWindowsPlatform(): |
|
5805 home = "file:///" + Utilities.fromNativeSeparators(home) |
|
5806 else: |
|
5807 home = "file://" + home |
|
5808 else: |
|
5809 home = pyqtDocDir |
|
5810 |
|
5811 hvType = Preferences.getWebBrowser("HelpViewerType") |
|
5812 if hvType == 1: |
|
5813 self.launchHelpViewer(home) |
|
5814 elif hvType == 2: |
|
5815 if home.startswith("qthelp://"): |
|
5816 self.__assistant(home) |
|
5817 else: |
|
5818 self.__webBrowser(home) |
|
5819 elif hvType == 3: |
|
5820 self.__webBrowser(home) |
|
5821 else: |
|
5822 self.__customViewer(home) |
|
5823 |
|
5824 def __showEricDoc(self): |
|
5825 """ |
|
5826 Private slot to show the Eric documentation. |
|
5827 """ |
|
5828 home = Preferences.getHelp("EricDocDir") |
|
5829 if not home: |
|
5830 home = Utilities.normjoinpath( |
|
5831 getConfig('ericDocDir'), "Source", "index.html") |
|
5832 |
|
5833 if not home.startswith(("http://", "https://", "qthelp://")): |
|
5834 if not os.path.exists(home): |
|
5835 E5MessageBox.warning( |
|
5836 self, |
|
5837 self.tr("Documentation Missing"), |
|
5838 self.tr("""<p>The documentation starting point""" |
|
5839 """ "<b>{0}</b>" could not be found.</p>""") |
|
5840 .format(home)) |
|
5841 return |
|
5842 |
|
5843 if Utilities.isWindowsPlatform(): |
|
5844 home = "file:///" + Utilities.fromNativeSeparators(home) |
|
5845 else: |
|
5846 home = "file://" + home |
|
5847 |
|
5848 hvType = Preferences.getWebBrowser("HelpViewerType") |
|
5849 if hvType == 1: |
|
5850 self.launchHelpViewer(home) |
|
5851 elif hvType == 2: |
|
5852 if home.startswith("qthelp://"): |
|
5853 self.__assistant(home) |
|
5854 else: |
|
5855 self.__webBrowser(home) |
|
5856 elif hvType == 3: |
|
5857 self.__webBrowser(home) |
|
5858 else: |
|
5859 self.__customViewer(home) |
|
5860 |
|
5861 def __showPySideDoc(self, variant=2): |
|
5862 """ |
|
5863 Private slot to show the PySide2/PySide6 documentation. |
|
5864 |
|
5865 @param variant PySide variant (2 or 6) |
|
5866 @type int or str |
|
5867 """ |
|
5868 pysideDocDir = Preferences.getHelp("PySide{0}DocDir".format(variant)) |
|
5869 if not pysideDocDir: |
|
5870 pysideDocDir = Utilities.getEnvironmentEntry( |
|
5871 "PYSIDE{0}DOCDIR".format(variant), None) |
|
5872 |
|
5873 if not pysideDocDir: |
|
5874 E5MessageBox.warning( |
|
5875 self, |
|
5876 self.tr("Documentation"), |
|
5877 self.tr("""<p>The PySide{0} documentation starting point""" |
|
5878 """ has not been configured.</p>""").format( |
|
5879 variant) |
|
5880 ) |
|
5881 return |
|
5882 |
|
5883 if not pysideDocDir.startswith(("http://", "https://", "qthelp://")): |
|
5884 if pysideDocDir.startswith("file://"): |
|
5885 pysideDocDir = pysideDocDir[7:] |
|
5886 if not os.path.splitext(pysideDocDir)[1]: |
|
5887 home = Utilities.normjoinpath(pysideDocDir, 'index.html') |
|
5888 else: |
|
5889 home = pysideDocDir |
|
5890 if not os.path.exists(home): |
|
5891 E5MessageBox.warning( |
|
5892 self, |
|
5893 self.tr("Documentation Missing"), |
|
5894 self.tr("""<p>The documentation starting point""" |
|
5895 """ "<b>{0}</b>" could not be found.</p>""") |
|
5896 .format(home)) |
|
5897 return |
|
5898 |
|
5899 if Utilities.isWindowsPlatform(): |
|
5900 home = "file:///" + Utilities.fromNativeSeparators(home) |
|
5901 else: |
|
5902 home = "file://" + home |
|
5903 else: |
|
5904 home = pysideDocDir |
|
5905 |
|
5906 hvType = Preferences.getWebBrowser("HelpViewerType") |
|
5907 if hvType == 1: |
|
5908 self.launchHelpViewer(home) |
|
5909 elif hvType == 2: |
|
5910 if home.startswith("qthelp://"): |
|
5911 self.__assistant(home) |
|
5912 else: |
|
5913 self.__webBrowser(home) |
|
5914 elif hvType == 3: |
|
5915 self.__webBrowser(home) |
|
5916 else: |
|
5917 self.__customViewer(home) |
|
5918 |
|
5919 @pyqtSlot(QUrl) |
|
5920 def handleUrl(self, url): |
|
5921 """ |
|
5922 Public slot to handle opening a URL. |
|
5923 |
|
5924 @param url URL to be shown |
|
5925 @type QUrl |
|
5926 """ |
|
5927 self.launchHelpViewer(url) |
|
5928 |
|
5929 def launchHelpViewer(self, home, searchWord=None, useSingle=False): |
|
5930 """ |
|
5931 Public slot to start the help viewer/web browser. |
|
5932 |
|
5933 @param home filename of file to be shown or URL to be opened |
|
5934 @type str or QUrl |
|
5935 @param searchWord word to search for |
|
5936 @type str |
|
5937 @param useSingle flag indicating to use a single browser window |
|
5938 @type bool |
|
5939 """ |
|
5940 if isinstance(home, QUrl): |
|
5941 home = home.toString(QUrl.UrlFormattingOption.None_) |
|
5942 |
|
5943 if len(home) > 0: |
|
5944 homeUrl = QUrl(home) |
|
5945 if not homeUrl.scheme(): |
|
5946 home = QUrl.fromLocalFile(home).toString() |
|
5947 |
|
5948 launchResult = self.__launchExternalWebBrowser( |
|
5949 home, searchWord=searchWord) |
|
5950 if not launchResult: |
|
5951 self.__webBrowser(home) |
|
5952 |
|
5953 def __launchExternalWebBrowser(self, home, searchWord=None): |
|
5954 """ |
|
5955 Private method to start an external web browser and communicate with |
|
5956 it. |
|
5957 |
|
5958 @param home filename of file to be shown or URL to be opened |
|
5959 @type str |
|
5960 @param searchWord word to search for |
|
5961 @type str |
|
5962 @return flag indicating a successful launch |
|
5963 @rtype bool |
|
5964 """ |
|
5965 clientArgs = [] |
|
5966 if searchWord: |
|
5967 clientArgs.append("--search={0}".format(searchWord)) |
|
5968 |
|
5969 if self.__webBrowserProcess is None: |
|
5970 webBrowsers = [ |
|
5971 os.path.join( |
|
5972 os.path.dirname(__file__), "..", "eric6_browser.py"), |
|
5973 # QtWebEngine based web browser |
|
5974 ] |
|
5975 process = QProcess() |
|
5976 for browser in webBrowsers: |
|
5977 args = [ |
|
5978 browser, |
|
5979 "--quiet", |
|
5980 "--qthelp", |
|
5981 "--single", |
|
5982 "--name={0}".format(self.__webBrowserSAName), |
|
5983 home |
|
5984 ] |
|
5985 process.start(sys.executable, args) |
|
5986 if not process.waitForStarted(): |
|
5987 E5MessageBox.warning( |
|
5988 self, |
|
5989 self.tr("Start Web Browser"), |
|
5990 self.tr("""The eric web browser could not be""" |
|
5991 """ started.""")) |
|
5992 return False |
|
5993 |
|
5994 res = self.__connectToWebBrowser(process) |
|
5995 if res == 1: |
|
5996 # connection unsuccessful |
|
5997 return False |
|
5998 elif res == 0: |
|
5999 # successful |
|
6000 break |
|
6001 elif res == -1: |
|
6002 # web browser did not start |
|
6003 continue |
|
6004 else: |
|
6005 return False |
|
6006 |
|
6007 process.finished.connect(self.__webBrowserFinished) |
|
6008 self.__webBrowserProcess = process |
|
6009 |
|
6010 else: |
|
6011 clientArgs.append("--newtab={0}".format(home)) |
|
6012 |
|
6013 if clientArgs and self.__webBrowserClient: |
|
6014 self.__webBrowserClient.processArgs(clientArgs, disconnect=False) |
|
6015 |
|
6016 return True |
|
6017 |
|
6018 def __connectToWebBrowser(self, process): |
|
6019 """ |
|
6020 Private method to connect to a started web browser. |
|
6021 |
|
6022 @param process reference to the started web browser process |
|
6023 @type QProcess |
|
6024 @return error indication (1 = connection not possible, 0 = ok, |
|
6025 -1 = server exited with an error code) |
|
6026 @rtype int |
|
6027 """ |
|
6028 from WebBrowser.WebBrowserSingleApplication import ( |
|
6029 WebBrowserSingleApplicationClient |
|
6030 ) |
|
6031 |
|
6032 webBrowserClient = WebBrowserSingleApplicationClient( |
|
6033 self.__webBrowserSAName) |
|
6034 connectCount = 30 |
|
6035 while connectCount: |
|
6036 res = webBrowserClient.connect() |
|
6037 if res != 0: |
|
6038 break |
|
6039 else: |
|
6040 connectCount -= 1 |
|
6041 QThread.msleep(1000) |
|
6042 QApplication.processEvents() |
|
6043 if ( |
|
6044 process.state() == QProcess.ProcessState.NotRunning and |
|
6045 process.exitStatus() == QProcess.ExitStatus.NormalExit and |
|
6046 process.exitCode() == 100 |
|
6047 ): |
|
6048 # Process exited prematurely due to missing pre-requisites |
|
6049 return -1 |
|
6050 if res <= 0: |
|
6051 E5MessageBox.warning( |
|
6052 self, |
|
6053 self.tr("Start Web Browser"), |
|
6054 self.tr("""<p>The eric web browser is not started.</p>""" |
|
6055 """<p>Reason: {0}</p>""").format( |
|
6056 webBrowserClient.errstr()) |
|
6057 ) |
|
6058 return 1 |
|
6059 |
|
6060 self.__webBrowserClient = webBrowserClient |
|
6061 return 0 |
|
6062 |
|
6063 def __webBrowserFinished(self): |
|
6064 """ |
|
6065 Private slot handling the end of the external web browser process. |
|
6066 """ |
|
6067 self.__webBrowserProcess = None |
|
6068 self.__webBrowserClient = None |
|
6069 |
|
6070 def __webBrowserShutdown(self): |
|
6071 """ |
|
6072 Private method to shut down the web browser. |
|
6073 """ |
|
6074 self.__webBrowserClient.processArgs(["--shutdown"], disconnect=False) |
|
6075 |
|
6076 def __helpViewer(self): |
|
6077 """ |
|
6078 Private slot to start an empty help viewer/web browser. |
|
6079 """ |
|
6080 searchWord = self.viewmanager.textForFind(False) |
|
6081 if searchWord == "": |
|
6082 searchWord = None |
|
6083 |
|
6084 self.launchHelpViewer("", searchWord=searchWord) |
|
6085 |
|
6086 def __webBrowser(self, home=""): |
|
6087 """ |
|
6088 Private slot to start the eric web browser. |
|
6089 |
|
6090 @param home full pathname of a file to display (string) |
|
6091 """ |
|
6092 started = QDesktopServices.openUrl(QUrl(home)) |
|
6093 if not started: |
|
6094 E5MessageBox.critical( |
|
6095 self, |
|
6096 self.tr('Open Browser'), |
|
6097 self.tr('Could not start a web browser')) |
|
6098 |
|
6099 @pyqtSlot() |
|
6100 @pyqtSlot(str) |
|
6101 def showPreferences(self, pageName=None): |
|
6102 """ |
|
6103 Public slot to set the preferences. |
|
6104 |
|
6105 @param pageName name of the configuration page to show (string) |
|
6106 """ |
|
6107 if self.__configurationDialog is None: |
|
6108 # only one invocation at a time is allowed |
|
6109 from Preferences.ConfigurationDialog import ConfigurationDialog |
|
6110 self.__configurationDialog = ConfigurationDialog( |
|
6111 self, 'Configuration', |
|
6112 expandedEntries=self.__expandedConfigurationEntries, |
|
6113 ) |
|
6114 self.__configurationDialog.preferencesChanged.connect( |
|
6115 self.__preferencesChanged) |
|
6116 self.__configurationDialog.masterPasswordChanged.connect( |
|
6117 self.__masterPasswordChanged) |
|
6118 self.__configurationDialog.show() |
|
6119 if pageName is not None: |
|
6120 self.__configurationDialog.showConfigurationPageByName( |
|
6121 pageName) |
|
6122 elif self.__lastConfigurationPageName: |
|
6123 self.__configurationDialog.showConfigurationPageByName( |
|
6124 self.__lastConfigurationPageName) |
|
6125 else: |
|
6126 self.__configurationDialog.showConfigurationPageByName("empty") |
|
6127 self.__configurationDialog.exec() |
|
6128 QApplication.processEvents() |
|
6129 if ( |
|
6130 self.__configurationDialog.result() == |
|
6131 QDialog.DialogCode.Accepted |
|
6132 ): |
|
6133 self.__configurationDialog.setPreferences() |
|
6134 Preferences.syncPreferences() |
|
6135 self.__preferencesChanged() |
|
6136 self.__lastConfigurationPageName = ( |
|
6137 self.__configurationDialog.getConfigurationPageName() |
|
6138 ) |
|
6139 self.__expandedConfigurationEntries = ( |
|
6140 self.__configurationDialog.getExpandedEntries() |
|
6141 ) |
|
6142 |
|
6143 self.__configurationDialog.deleteLater() |
|
6144 self.__configurationDialog = None |
|
6145 |
|
6146 def __exportPreferences(self): |
|
6147 """ |
|
6148 Private slot to export the current preferences. |
|
6149 """ |
|
6150 Preferences.exportPreferences() |
|
6151 |
|
6152 def __importPreferences(self): |
|
6153 """ |
|
6154 Private slot to import preferences. |
|
6155 """ |
|
6156 Preferences.importPreferences() |
|
6157 self.__preferencesChanged() |
|
6158 |
|
6159 def __preferencesChanged(self): |
|
6160 """ |
|
6161 Private slot to handle a change of the preferences. |
|
6162 """ |
|
6163 self.setStyle(Preferences.getUI("Style"), |
|
6164 Preferences.getUI("StyleSheet")) |
|
6165 |
|
6166 if Preferences.getUI("SingleApplicationMode"): |
|
6167 if self.SAServer is None: |
|
6168 self.SAServer = E5SingleApplicationServer() |
|
6169 else: |
|
6170 if self.SAServer is not None: |
|
6171 self.SAServer.shutdown() |
|
6172 self.SAServer = None |
|
6173 self.newWindowAct.setEnabled( |
|
6174 not Preferences.getUI("SingleApplicationMode")) |
|
6175 |
|
6176 self.maxEditorPathLen = Preferences.getUI("CaptionFilenameLength") |
|
6177 self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename") |
|
6178 if not self.captionShowsFilename: |
|
6179 self.__setWindowCaption(editor="") |
|
6180 else: |
|
6181 aw = self.viewmanager.activeWindow() |
|
6182 fn = aw and aw.getFileName() or None |
|
6183 if fn: |
|
6184 self.__setWindowCaption(editor=fn) |
|
6185 else: |
|
6186 self.__setWindowCaption(editor="") |
|
6187 |
|
6188 self.__httpAlternatives = Preferences.getUI("VersionsUrls6") |
|
6189 self.performVersionCheck(False) |
|
6190 |
|
6191 from QScintilla.SpellChecker import SpellChecker |
|
6192 SpellChecker.setDefaultLanguage( |
|
6193 Preferences.getEditor("SpellCheckingDefaultLanguage")) |
|
6194 |
|
6195 if self.__layoutType == "Sidebars": |
|
6196 delay = Preferences.getUI("SidebarDelay") |
|
6197 self.leftSidebar.setDelay(delay) |
|
6198 self.bottomSidebar.setDelay(delay) |
|
6199 self.rightSidebar.setDelay(delay) |
|
6200 |
|
6201 if Preferences.getUI("UseSystemProxy"): |
|
6202 QNetworkProxyFactory.setUseSystemConfiguration(True) |
|
6203 else: |
|
6204 self.__proxyFactory = E5NetworkProxyFactory() |
|
6205 QNetworkProxyFactory.setApplicationProxyFactory( |
|
6206 self.__proxyFactory) |
|
6207 QNetworkProxyFactory.setUseSystemConfiguration(False) |
|
6208 |
|
6209 from HexEdit.HexEditMainWindow import HexEditMainWindow |
|
6210 for hexEditor in HexEditMainWindow.windows: |
|
6211 hexEditor.preferencesChanged() |
|
6212 |
|
6213 # set the keyboard input interval |
|
6214 interval = Preferences.getUI("KeyboardInputInterval") |
|
6215 if interval > 0: |
|
6216 QApplication.setKeyboardInputInterval(interval) |
|
6217 else: |
|
6218 QApplication.setKeyboardInputInterval(-1) |
|
6219 |
|
6220 if not self.__disableCrashSession: |
|
6221 if Preferences.getUI("CrashSessionEnabled"): |
|
6222 self.__writeCrashSession() |
|
6223 else: |
|
6224 self.__deleteCrashSession() |
|
6225 |
|
6226 self.preferencesChanged.emit() |
|
6227 |
|
6228 def __masterPasswordChanged(self, oldPassword, newPassword): |
|
6229 """ |
|
6230 Private slot to handle the change of the master password. |
|
6231 |
|
6232 @param oldPassword current master password (string) |
|
6233 @param newPassword new master password (string) |
|
6234 """ |
|
6235 import Globals |
|
6236 |
|
6237 self.masterPasswordChanged.emit(oldPassword, newPassword) |
|
6238 Preferences.convertPasswords(oldPassword, newPassword) |
|
6239 variant = Globals.getWebBrowserSupport() |
|
6240 if variant == "QtWebEngine": |
|
6241 from WebBrowser.Passwords.PasswordManager import ( |
|
6242 PasswordManager |
|
6243 ) |
|
6244 pwManager = PasswordManager() |
|
6245 pwManager.masterPasswordChanged(oldPassword, newPassword) |
|
6246 Utilities.crypto.changeRememberedMaster(newPassword) |
|
6247 |
|
6248 def __reloadAPIs(self): |
|
6249 """ |
|
6250 Private slot to reload the api information. |
|
6251 """ |
|
6252 self.reloadAPIs.emit() |
|
6253 |
|
6254 def __showExternalTools(self): |
|
6255 """ |
|
6256 Private slot to display a dialog show a list of external tools used |
|
6257 by eric. |
|
6258 """ |
|
6259 if self.programsDialog is None: |
|
6260 from Preferences.ProgramsDialog import ProgramsDialog |
|
6261 self.programsDialog = ProgramsDialog(self) |
|
6262 self.programsDialog.show() |
|
6263 |
|
6264 def __configViewProfiles(self): |
|
6265 """ |
|
6266 Private slot to configure the various view profiles. |
|
6267 """ |
|
6268 from Preferences.ViewProfileDialog import ViewProfileDialog |
|
6269 dlg = ViewProfileDialog(self.__layoutType, self.profiles['edit'][1], |
|
6270 self.profiles['debug'][1]) |
|
6271 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
6272 edit, debug = dlg.getVisibilities() |
|
6273 self.profiles['edit'][1] = edit |
|
6274 self.profiles['debug'][1] = debug |
|
6275 Preferences.setUI("ViewProfiles2", self.profiles) |
|
6276 if self.currentProfile == "edit": |
|
6277 self.__setEditProfile(False) |
|
6278 elif self.currentProfile == "debug": |
|
6279 self.setDebugProfile(False) |
|
6280 |
|
6281 def __configToolBars(self): |
|
6282 """ |
|
6283 Private slot to configure the various toolbars. |
|
6284 """ |
|
6285 from E5Gui.E5ToolBarDialog import E5ToolBarDialog |
|
6286 dlg = E5ToolBarDialog(self.toolbarManager) |
|
6287 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
6288 Preferences.setUI( |
|
6289 "ToolbarManagerState", self.toolbarManager.saveState()) |
|
6290 |
|
6291 def __configShortcuts(self): |
|
6292 """ |
|
6293 Private slot to configure the keyboard shortcuts. |
|
6294 """ |
|
6295 if self.shortcutsDialog is None: |
|
6296 from Preferences.ShortcutsDialog import ShortcutsDialog |
|
6297 self.shortcutsDialog = ShortcutsDialog(self) |
|
6298 self.shortcutsDialog.populate() |
|
6299 self.shortcutsDialog.show() |
|
6300 |
|
6301 def __exportShortcuts(self): |
|
6302 """ |
|
6303 Private slot to export the keyboard shortcuts. |
|
6304 """ |
|
6305 fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( |
|
6306 None, |
|
6307 self.tr("Export Keyboard Shortcuts"), |
|
6308 "", |
|
6309 self.tr("Keyboard Shortcuts File (*.ekj);;" |
|
6310 "XML Keyboard Shortcuts File (*.e4k)"), |
|
6311 "", |
|
6312 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) |
|
6313 |
|
6314 if not fn: |
|
6315 return |
|
6316 |
|
6317 ext = QFileInfo(fn).suffix() |
|
6318 if not ext: |
|
6319 ex = selectedFilter.split("(*")[1].split(")")[0] |
|
6320 if ex: |
|
6321 fn += ex |
|
6322 |
|
6323 ok = ( |
|
6324 E5MessageBox.yesNo( |
|
6325 self, |
|
6326 self.tr("Export Keyboard Shortcuts"), |
|
6327 self.tr("""<p>The keyboard shortcuts file <b>{0}</b> exists""" |
|
6328 """ already. Overwrite it?</p>""").format(fn)) |
|
6329 if os.path.exists(fn) else |
|
6330 True |
|
6331 ) |
|
6332 |
|
6333 if ok: |
|
6334 from Preferences import Shortcuts |
|
6335 Shortcuts.exportShortcuts(fn) |
|
6336 |
|
6337 def __importShortcuts(self): |
|
6338 """ |
|
6339 Private slot to import the keyboard shortcuts. |
|
6340 """ |
|
6341 fn = E5FileDialog.getOpenFileName( |
|
6342 None, |
|
6343 self.tr("Import Keyboard Shortcuts"), |
|
6344 "", |
|
6345 self.tr("Keyboard Shortcuts File (*.ekj);;" |
|
6346 "XML Keyboard shortcut file (*.e4k)")) |
|
6347 |
|
6348 if fn: |
|
6349 from Preferences import Shortcuts |
|
6350 Shortcuts.importShortcuts(fn) |
|
6351 |
|
6352 def __showCertificatesDialog(self): |
|
6353 """ |
|
6354 Private slot to show the certificates management dialog. |
|
6355 """ |
|
6356 from E5Network.E5SslCertificatesDialog import E5SslCertificatesDialog |
|
6357 |
|
6358 dlg = E5SslCertificatesDialog(self) |
|
6359 dlg.exec() |
|
6360 |
|
6361 def __clearPrivateData(self): |
|
6362 """ |
|
6363 Private slot to clear the private data lists. |
|
6364 """ |
|
6365 from .ClearPrivateDataDialog import ClearPrivateDataDialog |
|
6366 dlg = ClearPrivateDataDialog(self) |
|
6367 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
6368 # recent files, recent projects, recent multi projects, |
|
6369 # debug histories, shell histories |
|
6370 (files, projects, multiProjects, debug, shell, vcs, plugins) = ( |
|
6371 dlg.getData() |
|
6372 ) |
|
6373 if files: |
|
6374 # clear list of recently opened files |
|
6375 self.viewmanager.clearRecent() |
|
6376 if projects: |
|
6377 # clear list of recently opened projects and other histories |
|
6378 self.project.clearHistories() |
|
6379 if multiProjects: |
|
6380 # clear list of recently opened multi projects |
|
6381 self.multiProject.clearRecent() |
|
6382 if debug: |
|
6383 # clear the various debug histories |
|
6384 self.debuggerUI.clearHistories() |
|
6385 if shell: |
|
6386 # clear the shell histories |
|
6387 self.shell.clearAllHistories() |
|
6388 if vcs: |
|
6389 # clear the VCS related histories |
|
6390 self.pluginManager.clearPluginsPrivateData("version_control") |
|
6391 if plugins: |
|
6392 # clear private data of plug-ins not covered above |
|
6393 self.pluginManager.clearPluginsPrivateData("") |
|
6394 |
|
6395 Preferences.syncPreferences() |
|
6396 |
|
6397 def __newProject(self): |
|
6398 """ |
|
6399 Private slot to handle the NewProject signal. |
|
6400 """ |
|
6401 self.__setWindowCaption(project=self.project.name) |
|
6402 |
|
6403 def __projectOpened(self): |
|
6404 """ |
|
6405 Private slot to handle the projectOpened signal. |
|
6406 """ |
|
6407 from Debugger.DebugClientCapabilities import HasUnittest |
|
6408 self.__setWindowCaption(project=self.project.name) |
|
6409 cap = e5App().getObject("DebugServer").getClientCapabilities( |
|
6410 self.project.getProjectLanguage()) |
|
6411 self.utProjectAct.setEnabled(cap & HasUnittest) |
|
6412 self.utProjectOpen = cap & HasUnittest |
|
6413 |
|
6414 def __projectClosed(self): |
|
6415 """ |
|
6416 Private slot to handle the projectClosed signal. |
|
6417 """ |
|
6418 self.__setWindowCaption(project="") |
|
6419 self.utProjectAct.setEnabled(False) |
|
6420 if not self.utEditorOpen: |
|
6421 self.utRestartAct.setEnabled(False) |
|
6422 self.utRerunFailedAct.setEnabled(False) |
|
6423 self.utProjectOpen = False |
|
6424 |
|
6425 def __programChange(self, fn): |
|
6426 """ |
|
6427 Private slot to handle the programChange signal. |
|
6428 |
|
6429 This primarily is here to set the currentProg variable. |
|
6430 |
|
6431 @param fn filename to be set as current prog (string) |
|
6432 """ |
|
6433 # Delete the old program if there was one. |
|
6434 if self.currentProg is not None: |
|
6435 del self.currentProg |
|
6436 |
|
6437 self.currentProg = os.path.normpath(fn) |
|
6438 |
|
6439 def __lastEditorClosed(self): |
|
6440 """ |
|
6441 Private slot to handle the lastEditorClosed signal. |
|
6442 """ |
|
6443 self.wizardsMenuAct.setEnabled(False) |
|
6444 self.utScriptAct.setEnabled(False) |
|
6445 self.utEditorOpen = False |
|
6446 if not self.utProjectOpen: |
|
6447 self.utRestartAct.setEnabled(False) |
|
6448 self.utRerunFailedAct.setEnabled(False) |
|
6449 self.__setWindowCaption(editor="") |
|
6450 |
|
6451 def __editorOpened(self, fn): |
|
6452 """ |
|
6453 Private slot to handle the editorOpened signal. |
|
6454 |
|
6455 @param fn filename of the opened editor (string) |
|
6456 """ |
|
6457 self.wizardsMenuAct.setEnabled( |
|
6458 len(self.__menus["wizards"].actions()) > 0) |
|
6459 |
|
6460 if fn and str(fn) != "None": |
|
6461 dbs = e5App().getObject("DebugServer") |
|
6462 for language in dbs.getSupportedLanguages(): |
|
6463 exts = dbs.getExtensions(language) |
|
6464 if fn.endswith(exts): |
|
6465 from Debugger.DebugClientCapabilities import HasUnittest |
|
6466 cap = dbs.getClientCapabilities(language) |
|
6467 self.utScriptAct.setEnabled(cap & HasUnittest) |
|
6468 self.utEditorOpen = cap & HasUnittest |
|
6469 return |
|
6470 |
|
6471 if self.viewmanager.getOpenEditor(fn).isPyFile(): |
|
6472 self.utScriptAct.setEnabled(True) |
|
6473 self.utEditorOpen = True |
|
6474 |
|
6475 def __checkActions(self, editor): |
|
6476 """ |
|
6477 Private slot to check some actions for their enable/disable status. |
|
6478 |
|
6479 @param editor editor window |
|
6480 """ |
|
6481 fn = editor.getFileName() if editor else None |
|
6482 |
|
6483 if fn: |
|
6484 dbs = e5App().getObject("DebugServer") |
|
6485 for language in dbs.getSupportedLanguages(): |
|
6486 exts = dbs.getExtensions(language) |
|
6487 if fn.endswith(exts): |
|
6488 from Debugger.DebugClientCapabilities import HasUnittest |
|
6489 cap = dbs.getClientCapabilities(language) |
|
6490 self.utScriptAct.setEnabled(cap & HasUnittest) |
|
6491 self.utEditorOpen = cap & HasUnittest |
|
6492 return |
|
6493 |
|
6494 if editor.isPyFile(): |
|
6495 self.utScriptAct.setEnabled(True) |
|
6496 self.utEditorOpen = True |
|
6497 return |
|
6498 |
|
6499 self.utScriptAct.setEnabled(False) |
|
6500 |
|
6501 def __writeTasks(self): |
|
6502 """ |
|
6503 Private slot to write the tasks data to a JSON file (.etj). |
|
6504 """ |
|
6505 fn = os.path.join(Utilities.getConfigDir(), "eric6tasks.etj") |
|
6506 self.__tasksFile.writeFile(fn) |
|
6507 |
|
6508 def __readTasks(self): |
|
6509 """ |
|
6510 Private slot to read in the tasks file (.etj or .e6t). |
|
6511 """ |
|
6512 fn = os.path.join(Utilities.getConfigDir(), "eric6tasks.etj") |
|
6513 if os.path.exists(fn): |
|
6514 # try new style JSON file first |
|
6515 self.__tasksFile.readFile(fn) |
|
6516 else: |
|
6517 # try old style XML file second |
|
6518 fn = os.path.join(Utilities.getConfigDir(), "eric6tasks.e6t") |
|
6519 if os.path.exists(fn): |
|
6520 f = QFile(fn) |
|
6521 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
|
6522 from E5XML.TasksReader import TasksReader |
|
6523 reader = TasksReader(f, viewer=self.taskViewer) |
|
6524 reader.readXML() |
|
6525 f.close() |
|
6526 else: |
|
6527 E5MessageBox.critical( |
|
6528 self, |
|
6529 self.tr("Read Tasks"), |
|
6530 self.tr( |
|
6531 "<p>The tasks file <b>{0}</b> could not be" |
|
6532 " read.</p>") |
|
6533 .format(fn)) |
|
6534 |
|
6535 def __writeSession(self, filename="", crashSession=False): |
|
6536 """ |
|
6537 Private slot to write the session data to a JSON file (.esj). |
|
6538 |
|
6539 @param filename name of a session file to write |
|
6540 @type str |
|
6541 @param crashSession flag indicating to write a crash session file |
|
6542 @type bool |
|
6543 @return flag indicating success |
|
6544 @rtype bool |
|
6545 """ |
|
6546 if filename: |
|
6547 fn = filename |
|
6548 elif crashSession: |
|
6549 fn = os.path.join(Utilities.getConfigDir(), |
|
6550 "eric6_crash_session.esj") |
|
6551 else: |
|
6552 fn = os.path.join(Utilities.getConfigDir(), |
|
6553 "eric6session.esj") |
|
6554 |
|
6555 if fn.endswith(".esj"): |
|
6556 res = self.__sessionFile.writeFile(fn) |
|
6557 else: |
|
6558 f = QFile(fn) |
|
6559 if f.open(QIODevice.OpenModeFlag.WriteOnly): |
|
6560 from E5XML.SessionWriter import SessionWriter |
|
6561 SessionWriter(f, None).writeXML() |
|
6562 f.close() |
|
6563 res = True |
|
6564 else: |
|
6565 E5MessageBox.critical( |
|
6566 self, |
|
6567 self.tr("Save Session"), |
|
6568 self.tr("<p>The session file <b>{0}</b> could not be" |
|
6569 " written.</p>") |
|
6570 .format(fn)) |
|
6571 res = False |
|
6572 |
|
6573 return res |
|
6574 |
|
6575 def __readSession(self, filename=""): |
|
6576 """ |
|
6577 Private slot to read in the session file (.esj or .e5s). |
|
6578 |
|
6579 @param filename name of a session file to read |
|
6580 @type str |
|
6581 @return flag indicating success |
|
6582 @rtype bool |
|
6583 """ |
|
6584 if filename: |
|
6585 fn = filename |
|
6586 else: |
|
6587 fn = os.path.join(Utilities.getConfigDir(), |
|
6588 "eric6session.esj") |
|
6589 if not os.path.exists(fn): |
|
6590 fn = os.path.join(Utilities.getConfigDir(), |
|
6591 "eric6session.e5s") |
|
6592 if not os.path.exists(fn): |
|
6593 E5MessageBox.critical( |
|
6594 self, |
|
6595 self.tr("Read Session"), |
|
6596 self.tr("<p>The session file <b>{0}</b> could not" |
|
6597 " be read.</p>") |
|
6598 .format(fn)) |
|
6599 fn = "" |
|
6600 |
|
6601 res = False |
|
6602 if fn: |
|
6603 if fn.endswith(".esj"): |
|
6604 # new JSON based format |
|
6605 self.__readingSession = True |
|
6606 res = self.__sessionFile.readFile(fn) |
|
6607 self.__readingSession = False |
|
6608 else: |
|
6609 # old XML based format |
|
6610 f = QFile(fn) |
|
6611 if f.open(QIODevice.OpenModeFlag.ReadOnly): |
|
6612 from E5XML.SessionReader import SessionReader |
|
6613 self.__readingSession = True |
|
6614 reader = SessionReader(f, True) |
|
6615 reader.readXML() |
|
6616 self.__readingSession = False |
|
6617 f.close() |
|
6618 res = True |
|
6619 else: |
|
6620 E5MessageBox.critical( |
|
6621 self, |
|
6622 self.tr("Read session"), |
|
6623 self.tr("<p>The session file <b>{0}</b> could not be" |
|
6624 " read.</p>") |
|
6625 .format(fn)) |
|
6626 |
|
6627 # Write a crash session after a session was read. |
|
6628 self.__writeCrashSession() |
|
6629 |
|
6630 return res |
|
6631 |
|
6632 def __saveSessionToFile(self): |
|
6633 """ |
|
6634 Private slot to save a session to disk. |
|
6635 """ |
|
6636 sessionFile, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( |
|
6637 self, |
|
6638 self.tr("Save Session"), |
|
6639 Utilities.getHomeDir(), |
|
6640 self.tr("eric Session Files (*.esj);;" |
|
6641 "eric XML Session Files (*.e5s)"), |
|
6642 "") |
|
6643 |
|
6644 if not sessionFile: |
|
6645 return |
|
6646 |
|
6647 ext = QFileInfo(sessionFile).suffix() |
|
6648 if not ext: |
|
6649 ex = selectedFilter.split("(*")[1].split(")")[0] |
|
6650 if ex: |
|
6651 sessionFile += ex |
|
6652 |
|
6653 self.__writeSession(filename=sessionFile) |
|
6654 |
|
6655 def __loadSessionFromFile(self): |
|
6656 """ |
|
6657 Private slot to load a session from disk. |
|
6658 """ |
|
6659 sessionFile = E5FileDialog.getOpenFileName( |
|
6660 self, |
|
6661 self.tr("Load session"), |
|
6662 Utilities.getHomeDir(), |
|
6663 self.tr("eric Session Files (*.esj);;" |
|
6664 "eric XML Session Files (*.e5s)")) |
|
6665 |
|
6666 if not sessionFile: |
|
6667 return |
|
6668 |
|
6669 self.__readSession(filename=sessionFile) |
|
6670 |
|
6671 def __deleteCrashSession(self): |
|
6672 """ |
|
6673 Private slot to delete the crash session file. |
|
6674 """ |
|
6675 for ext in (".esj", ".e5s"): |
|
6676 fn = os.path.join(Utilities.getConfigDir(), |
|
6677 f"eric6_crash_session{ext}") |
|
6678 if os.path.exists(fn): |
|
6679 with contextlib.suppress(OSError): |
|
6680 os.remove(fn) |
|
6681 |
|
6682 def __writeCrashSession(self): |
|
6683 """ |
|
6684 Private slot to write a crash session file. |
|
6685 """ |
|
6686 if ( |
|
6687 not self.__readingSession and |
|
6688 not self.__disableCrashSession and |
|
6689 Preferences.getUI("CrashSessionEnabled") |
|
6690 ): |
|
6691 self.__writeSession(crashSession=True) |
|
6692 |
|
6693 def __readCrashSession(self): |
|
6694 """ |
|
6695 Private method to check for and read a crash session. |
|
6696 |
|
6697 @return flag indicating a crash session file was found and read |
|
6698 @rtype bool |
|
6699 """ |
|
6700 res = False |
|
6701 if ( |
|
6702 not self.__disableCrashSession and |
|
6703 not self.__noCrashOpenAtStartup and |
|
6704 Preferences.getUI("OpenCrashSessionOnStartup") |
|
6705 ): |
|
6706 fn = os.path.join(Utilities.getConfigDir(), |
|
6707 "eric6_crash_session.esj") |
|
6708 if os.path.exists(fn): |
|
6709 yes = E5MessageBox.yesNo( |
|
6710 self, |
|
6711 self.tr("Crash Session found!"), |
|
6712 self.tr("""A session file of a crashed session was""" |
|
6713 """ found. Shall this session be restored?""")) |
|
6714 if yes: |
|
6715 res = self.__readSession(filename=fn) |
|
6716 |
|
6717 return res |
|
6718 |
|
6719 def showFindFileByNameDialog(self): |
|
6720 """ |
|
6721 Public slot to show the Find File by Name dialog. |
|
6722 """ |
|
6723 if self.findFileNameDialog is None: |
|
6724 from .FindFileNameDialog import FindFileNameDialog |
|
6725 self.findFileNameDialog = FindFileNameDialog(self.project) |
|
6726 self.findFileNameDialog.sourceFile.connect( |
|
6727 self.viewmanager.openSourceFile) |
|
6728 self.findFileNameDialog.designerFile.connect(self.__designer) |
|
6729 self.findFileNameDialog.show() |
|
6730 self.findFileNameDialog.raise_() |
|
6731 self.findFileNameDialog.activateWindow() |
|
6732 |
|
6733 def showFindFilesDialog(self, txt="", searchDir="", openFiles=False): |
|
6734 """ |
|
6735 Public slot to show the Find In Files dialog. |
|
6736 |
|
6737 @param txt text to search for (string) |
|
6738 @param searchDir directory to search in (string) |
|
6739 @param openFiles flag indicating to operate on open files (boolean) |
|
6740 """ |
|
6741 if self.findFilesDialog is None: |
|
6742 from .FindFileDialog import FindFileDialog |
|
6743 self.findFilesDialog = FindFileDialog(self.project) |
|
6744 self.findFilesDialog.sourceFile.connect( |
|
6745 self.viewmanager.openSourceFile) |
|
6746 self.findFilesDialog.designerFile.connect(self.__designer) |
|
6747 if searchDir: |
|
6748 self.findFilesDialog.setSearchDirectory(searchDir) |
|
6749 self.findFilesDialog.show(txt) |
|
6750 if openFiles: |
|
6751 self.findFilesDialog.setOpenFiles() |
|
6752 self.findFilesDialog.raise_() |
|
6753 self.findFilesDialog.activateWindow() |
|
6754 |
|
6755 def showReplaceFilesDialog(self, txt="", searchDir="", openFiles=False): |
|
6756 """ |
|
6757 Public slot to show the Find & Replace In Files dialog. |
|
6758 |
|
6759 @param txt text to search for (string) |
|
6760 @param searchDir directory to search in (string) |
|
6761 @param openFiles flag indicating to operate on open files (boolean) |
|
6762 """ |
|
6763 if self.replaceFilesDialog is None: |
|
6764 from .FindFileDialog import FindFileDialog |
|
6765 self.replaceFilesDialog = FindFileDialog( |
|
6766 self.project, replaceMode=True) |
|
6767 self.replaceFilesDialog.sourceFile.connect( |
|
6768 self.viewmanager.openSourceFile) |
|
6769 self.replaceFilesDialog.designerFile.connect(self.__designer) |
|
6770 if searchDir: |
|
6771 self.replaceFilesDialog.setSearchDirectory(searchDir) |
|
6772 self.replaceFilesDialog.show(txt) |
|
6773 if openFiles: |
|
6774 self.replaceFilesDialog.setOpenFiles() |
|
6775 self.replaceFilesDialog.raise_() |
|
6776 self.replaceFilesDialog.activateWindow() |
|
6777 |
|
6778 ########################################################## |
|
6779 ## Below are slots to handle StdOut and StdErr |
|
6780 ########################################################## |
|
6781 |
|
6782 def appendToStdout(self, s): |
|
6783 """ |
|
6784 Public slot to append text to the stdout log viewer tab. |
|
6785 |
|
6786 @param s output to be appended (string) |
|
6787 """ |
|
6788 self.appendStdout.emit(s) |
|
6789 |
|
6790 def appendToStderr(self, s): |
|
6791 """ |
|
6792 Public slot to append text to the stderr log viewer tab. |
|
6793 |
|
6794 @param s output to be appended (string) |
|
6795 """ |
|
6796 self.appendStderr.emit(s) |
|
6797 |
|
6798 ########################################################## |
|
6799 ## Below are slots needed by the plugin menu |
|
6800 ########################################################## |
|
6801 |
|
6802 def __showPluginInfo(self): |
|
6803 """ |
|
6804 Private slot to show the plugin info dialog. |
|
6805 """ |
|
6806 from PluginManager.PluginInfoDialog import PluginInfoDialog |
|
6807 self.__pluginInfoDialog = PluginInfoDialog(self.pluginManager, self) |
|
6808 self.__pluginInfoDialog.show() |
|
6809 |
|
6810 @pyqtSlot() |
|
6811 def __installPlugins(self, pluginFileNames=None): |
|
6812 """ |
|
6813 Private slot to show a dialog to install a new plugin. |
|
6814 |
|
6815 @param pluginFileNames list of plugin files suggested for |
|
6816 installation list of strings |
|
6817 """ |
|
6818 from PluginManager.PluginInstallDialog import PluginInstallDialog |
|
6819 self.__pluginInstallDialog = PluginInstallDialog( |
|
6820 self.pluginManager, |
|
6821 [] if pluginFileNames is None else pluginFileNames[:], |
|
6822 self) |
|
6823 self.__pluginInstallDialog.setModal(False) |
|
6824 self.__pluginInstallDialog.finished.connect( |
|
6825 self.__pluginInstallFinished) |
|
6826 self.__pluginInstallDialog.show() |
|
6827 |
|
6828 @pyqtSlot() |
|
6829 def __pluginInstallFinished(self): |
|
6830 """ |
|
6831 Private slot to handle the finishing of the plugin install dialog. |
|
6832 """ |
|
6833 if self.__pluginInstallDialog.restartNeeded(): |
|
6834 self.__pluginInstallDialog.deleteLater() |
|
6835 del self.__pluginInstallDialog |
|
6836 self.__restart(ask=True) |
|
6837 |
|
6838 def __deinstallPlugin(self): |
|
6839 """ |
|
6840 Private slot to show a dialog to uninstall a plugin. |
|
6841 """ |
|
6842 from PluginManager.PluginUninstallDialog import PluginUninstallDialog |
|
6843 dlg = PluginUninstallDialog(self.pluginManager, self) |
|
6844 dlg.exec() |
|
6845 |
|
6846 def showPluginsAvailable(self): |
|
6847 """ |
|
6848 Public slot to show the plugins available for download. |
|
6849 """ |
|
6850 from PluginManager.PluginRepositoryDialog import PluginRepositoryDialog |
|
6851 dlg = PluginRepositoryDialog(self.pluginManager, self) |
|
6852 res = dlg.exec() |
|
6853 if res == (QDialog.DialogCode.Accepted + 1): |
|
6854 self.__installPlugins(dlg.getDownloadedPlugins()) |
|
6855 |
|
6856 def __pluginsConfigure(self): |
|
6857 """ |
|
6858 Private slot to show the plugin manager configuration page. |
|
6859 """ |
|
6860 self.showPreferences("pluginManagerPage") |
|
6861 |
|
6862 def checkPluginUpdatesAvailable(self): |
|
6863 """ |
|
6864 Public method to check the availability of updates of plug-ins. |
|
6865 """ |
|
6866 self.pluginManager.checkPluginUpdatesAvailable() |
|
6867 |
|
6868 ################################################################# |
|
6869 ## Drag and Drop Support |
|
6870 ################################################################# |
|
6871 |
|
6872 def dragEnterEvent(self, event): |
|
6873 """ |
|
6874 Protected method to handle the drag enter event. |
|
6875 |
|
6876 @param event the drag enter event (QDragEnterEvent) |
|
6877 """ |
|
6878 self.inDragDrop = event.mimeData().hasUrls() |
|
6879 if self.inDragDrop: |
|
6880 event.acceptProposedAction() |
|
6881 |
|
6882 def dragMoveEvent(self, event): |
|
6883 """ |
|
6884 Protected method to handle the drag move event. |
|
6885 |
|
6886 @param event the drag move event (QDragMoveEvent) |
|
6887 """ |
|
6888 if self.inDragDrop: |
|
6889 event.acceptProposedAction() |
|
6890 |
|
6891 def dragLeaveEvent(self, event): |
|
6892 """ |
|
6893 Protected method to handle the drag leave event. |
|
6894 |
|
6895 @param event the drag leave event (QDragLeaveEvent) |
|
6896 """ |
|
6897 if self.inDragDrop: |
|
6898 self.inDragDrop = False |
|
6899 |
|
6900 def dropEvent(self, event): |
|
6901 """ |
|
6902 Protected method to handle the drop event. |
|
6903 |
|
6904 @param event the drop event (QDropEvent) |
|
6905 """ |
|
6906 if event.mimeData().hasUrls(): |
|
6907 event.acceptProposedAction() |
|
6908 for url in event.mimeData().urls(): |
|
6909 fname = url.toLocalFile() |
|
6910 if fname: |
|
6911 if QFileInfo(fname).isFile(): |
|
6912 self.viewmanager.openSourceFile(fname) |
|
6913 else: |
|
6914 E5MessageBox.information( |
|
6915 self, |
|
6916 self.tr("Drop Error"), |
|
6917 self.tr("""<p><b>{0}</b> is not a file.</p>""") |
|
6918 .format(fname)) |
|
6919 |
|
6920 self.inDragDrop = False |
|
6921 |
|
6922 ########################################################## |
|
6923 ## Below are methods needed for shutting down the IDE |
|
6924 ########################################################## |
|
6925 |
|
6926 def closeEvent(self, event): |
|
6927 """ |
|
6928 Protected event handler for the close event. |
|
6929 |
|
6930 This event handler saves the preferences. |
|
6931 |
|
6932 @param event close event (QCloseEvent) |
|
6933 """ |
|
6934 if self.__shutdown(): |
|
6935 event.accept() |
|
6936 if not self.inCloseEvent: |
|
6937 self.inCloseEvent = True |
|
6938 QTimer.singleShot(0, e5App().closeAllWindows) |
|
6939 else: |
|
6940 event.ignore() |
|
6941 |
|
6942 def __shutdown(self): |
|
6943 """ |
|
6944 Private method to perform all necessary steps to close down the IDE. |
|
6945 |
|
6946 @return flag indicating success |
|
6947 """ |
|
6948 if self.shutdownCalled: |
|
6949 return True |
|
6950 |
|
6951 if self.__webBrowserProcess is not None: |
|
6952 self.__webBrowserShutdown() |
|
6953 |
|
6954 if self.irc is not None and not self.irc.shutdown(): |
|
6955 return False |
|
6956 |
|
6957 sessionCreated = self.__writeSession() |
|
6958 |
|
6959 self.__astViewer.hide() |
|
6960 |
|
6961 if not self.project.closeProject(): |
|
6962 return False |
|
6963 |
|
6964 if not self.multiProject.closeMultiProject(): |
|
6965 return False |
|
6966 |
|
6967 if not self.viewmanager.closeViewManager(): |
|
6968 return False |
|
6969 |
|
6970 if sessionCreated and not self.__disableCrashSession: |
|
6971 self.__deleteCrashSession() |
|
6972 |
|
6973 if self.codeDocumentationViewer is not None: |
|
6974 self.codeDocumentationViewer.shutdown() |
|
6975 |
|
6976 self.__previewer.shutdown() |
|
6977 |
|
6978 self.__astViewer.shutdown() |
|
6979 |
|
6980 self.shell.closeShell() |
|
6981 |
|
6982 self.__writeTasks() |
|
6983 |
|
6984 if self.templateViewer is not None: |
|
6985 self.templateViewer.save() |
|
6986 |
|
6987 if not self.debuggerUI.shutdownServer(): |
|
6988 return False |
|
6989 self.debuggerUI.shutdown() |
|
6990 |
|
6991 self.backgroundService.shutdown() |
|
6992 |
|
6993 if self.cooperation is not None: |
|
6994 self.cooperation.shutdown() |
|
6995 |
|
6996 self.pluginManager.doShutdown() |
|
6997 |
|
6998 self.virtualenvManager.shutdown() |
|
6999 |
|
7000 if self.__layoutType == "Sidebars": |
|
7001 self.leftSidebar.shutdown() |
|
7002 self.bottomSidebar.shutdown() |
|
7003 self.rightSidebar.shutdown() |
|
7004 |
|
7005 if self.SAServer is not None: |
|
7006 self.SAServer.shutdown() |
|
7007 self.SAServer = None |
|
7008 |
|
7009 # set proxy factory to None to avoid crashes |
|
7010 QNetworkProxyFactory.setApplicationProxyFactory(None) |
|
7011 |
|
7012 Preferences.setGeometry("MainMaximized", self.isMaximized()) |
|
7013 if not self.isMaximized(): |
|
7014 Preferences.setGeometry("MainGeometry", self.saveGeometry()) |
|
7015 |
|
7016 if self.browser is not None: |
|
7017 self.browser.saveToplevelDirs() |
|
7018 |
|
7019 Preferences.setUI( |
|
7020 "ToolbarManagerState", self.toolbarManager.saveState()) |
|
7021 self.__saveCurrentViewProfile(True) |
|
7022 Preferences.saveToolGroups(self.toolGroups, self.currentToolGroup) |
|
7023 Preferences.syncPreferences() |
|
7024 self.shutdownCalled = True |
|
7025 return True |
|
7026 |
|
7027 ############################################## |
|
7028 ## Below are methods to check for new versions |
|
7029 ############################################## |
|
7030 |
|
7031 def showAvailableVersionsInfo(self): |
|
7032 """ |
|
7033 Public method to show the eric versions available for download. |
|
7034 """ |
|
7035 self.performVersionCheck(manual=True, showVersions=True) |
|
7036 |
|
7037 @pyqtSlot() |
|
7038 def performVersionCheck(self, manual=True, alternative=0, |
|
7039 showVersions=False): |
|
7040 """ |
|
7041 Public method to check the internet for an eric update. |
|
7042 |
|
7043 @param manual flag indicating an invocation via the menu (boolean) |
|
7044 @param alternative index of server to download from (integer) |
|
7045 @param showVersions flag indicating the show versions mode (boolean) |
|
7046 """ |
|
7047 if not manual: |
|
7048 if VersionOnly.startswith("@@"): |
|
7049 return |
|
7050 else: |
|
7051 period = Preferences.getUI("PerformVersionCheck") |
|
7052 if period == 0: |
|
7053 return |
|
7054 elif period in [2, 3, 4]: |
|
7055 lastCheck = Preferences.Prefs.settings.value( |
|
7056 "Updates/LastCheckDate", QDate(1970, 1, 1)) |
|
7057 if lastCheck.isValid(): |
|
7058 now = QDate.currentDate() |
|
7059 if ( |
|
7060 (period == 2 and lastCheck.day() == now.day()) or |
|
7061 (period == 3 and lastCheck.daysTo(now) < 7) or |
|
7062 (period == 4 and (lastCheck.daysTo(now) < |
|
7063 lastCheck.daysInMonth())) |
|
7064 ): |
|
7065 # daily, weekly, monthly |
|
7066 return |
|
7067 |
|
7068 self.__inVersionCheck = True |
|
7069 self.manualUpdatesCheck = manual |
|
7070 self.showAvailableVersions = showVersions |
|
7071 self.httpAlternative = alternative |
|
7072 url = QUrl(self.__httpAlternatives[alternative]) |
|
7073 self.__versionCheckCanceled = False |
|
7074 if manual: |
|
7075 if self.__versionCheckProgress is None: |
|
7076 self.__versionCheckProgress = E5ProgressDialog( |
|
7077 "", self.tr("&Cancel"), |
|
7078 0, len(self.__httpAlternatives), |
|
7079 self.tr("%v/%m"), self) |
|
7080 self.__versionCheckProgress.setWindowTitle( |
|
7081 self.tr("Version Check")) |
|
7082 self.__versionCheckProgress.setMinimumDuration(0) |
|
7083 self.__versionCheckProgress.canceled.connect( |
|
7084 self.__versionsDownloadCanceled) |
|
7085 self.__versionCheckProgress.setLabelText( |
|
7086 self.tr("Trying host {0}").format(url.host())) |
|
7087 self.__versionCheckProgress.setValue(alternative) |
|
7088 request = QNetworkRequest(url) |
|
7089 request.setAttribute( |
|
7090 QNetworkRequest.Attribute.CacheLoadControlAttribute, |
|
7091 QNetworkRequest.CacheLoadControl.AlwaysNetwork) |
|
7092 reply = self.__networkManager.get(request) |
|
7093 reply.finished.connect(lambda: self.__versionsDownloadDone(reply)) |
|
7094 self.__replies.append(reply) |
|
7095 |
|
7096 @pyqtSlot() |
|
7097 def __versionsDownloadDone(self, reply): |
|
7098 """ |
|
7099 Private slot called, after the versions file has been downloaded |
|
7100 from the internet. |
|
7101 |
|
7102 @param reply reference to the network reply |
|
7103 @type QNetworkReply |
|
7104 """ |
|
7105 if self.__versionCheckCanceled: |
|
7106 self.__inVersionCheck = False |
|
7107 if self.__versionCheckProgress is not None: |
|
7108 self.__versionCheckProgress.reset() |
|
7109 self.__versionCheckProgress = None |
|
7110 return |
|
7111 |
|
7112 reply.deleteLater() |
|
7113 if reply in self.__replies: |
|
7114 self.__replies.remove(reply) |
|
7115 if reply.error() == QNetworkReply.NetworkError.NoError: |
|
7116 ioEncoding = Preferences.getSystem("IOEncoding") |
|
7117 versions = str(reply.readAll(), ioEncoding, 'replace').splitlines() |
|
7118 reply.close() |
|
7119 if ( |
|
7120 reply.error() != QNetworkReply.NetworkError.NoError or |
|
7121 len(versions) == 0 or |
|
7122 versions[0].startswith("<") |
|
7123 ): |
|
7124 # network error or an error page |
|
7125 self.httpAlternative += 1 |
|
7126 if self.httpAlternative >= len(self.__httpAlternatives): |
|
7127 self.__inVersionCheck = False |
|
7128 if self.__versionCheckProgress is not None: |
|
7129 self.__versionCheckProgress.reset() |
|
7130 self.__versionCheckProgress = None |
|
7131 firstFailure = Preferences.Prefs.settings.value( |
|
7132 "Updates/FirstFailedCheckDate", QDate.currentDate()) |
|
7133 failedDuration = firstFailure.daysTo(QDate.currentDate()) |
|
7134 Preferences.Prefs.settings.setValue( |
|
7135 "Updates/FirstFailedCheckDate", firstFailure) |
|
7136 if self.manualUpdatesCheck: |
|
7137 E5MessageBox.warning( |
|
7138 self, |
|
7139 self.tr("Error getting versions information"), |
|
7140 self.tr("""The versions information could not be""" |
|
7141 """ downloaded.""" |
|
7142 """ Please go online and try again.""")) |
|
7143 elif failedDuration > 7: |
|
7144 E5MessageBox.warning( |
|
7145 self, |
|
7146 self.tr("Error getting versions information"), |
|
7147 self.tr("""The versions information could not be""" |
|
7148 """ downloaded for the last 7 days.""" |
|
7149 """ Please go online and try again.""")) |
|
7150 return |
|
7151 else: |
|
7152 self.performVersionCheck(self.manualUpdatesCheck, |
|
7153 self.httpAlternative, |
|
7154 self.showAvailableVersions) |
|
7155 return |
|
7156 |
|
7157 self.__inVersionCheck = False |
|
7158 if self.__versionCheckProgress is not None: |
|
7159 self.__versionCheckProgress.reset() |
|
7160 self.__versionCheckProgress = None |
|
7161 self.__updateVersionsUrls(versions) |
|
7162 if self.showAvailableVersions: |
|
7163 self.__showAvailableVersionInfos(versions) |
|
7164 else: |
|
7165 Preferences.Prefs.settings.remove("Updates/FirstFailedCheckDate") |
|
7166 Preferences.Prefs.settings.setValue( |
|
7167 "Updates/LastCheckDate", QDate.currentDate()) |
|
7168 self.__versionCheckResult(versions) |
|
7169 |
|
7170 def __updateVersionsUrls(self, versions): |
|
7171 """ |
|
7172 Private method to update the URLs from which to retrieve the versions |
|
7173 file. |
|
7174 |
|
7175 @param versions contents of the downloaded versions file (list of |
|
7176 strings) |
|
7177 """ |
|
7178 if len(versions) > 5 and versions[4] == "---": |
|
7179 line = 5 |
|
7180 urls = [] |
|
7181 while line < len(versions): |
|
7182 urls.append(versions[line]) |
|
7183 line += 1 |
|
7184 |
|
7185 Preferences.setUI("VersionsUrls6", urls) |
|
7186 |
|
7187 def __versionCheckResult(self, versions): |
|
7188 """ |
|
7189 Private method to show the result of the version check action. |
|
7190 |
|
7191 @param versions contents of the downloaded versions file (list of |
|
7192 strings) |
|
7193 """ |
|
7194 url = "" |
|
7195 try: |
|
7196 if "snapshot-" in VersionOnly: |
|
7197 # check snapshot version like snapshot-20170810 |
|
7198 if "snapshot-" in versions[2]: |
|
7199 installedSnapshotDate = VersionOnly.rsplit("-", 1)[-1] |
|
7200 availableSnapshotDate = versions[2].rsplit("-", 1)[-1] |
|
7201 if availableSnapshotDate > installedSnapshotDate: |
|
7202 res = E5MessageBox.yesNo( |
|
7203 self, |
|
7204 self.tr("Update available"), |
|
7205 self.tr( |
|
7206 """The update to <b>{0}</b> of eric is""" |
|
7207 """ available at <b>{1}</b>. Would you like""" |
|
7208 """ to get it?""") |
|
7209 .format(versions[2], versions[3]), |
|
7210 yesDefault=True) |
|
7211 url = res and versions[3] or '' |
|
7212 else: |
|
7213 if self.manualUpdatesCheck: |
|
7214 E5MessageBox.information( |
|
7215 self, |
|
7216 self.tr("Update Check"), |
|
7217 self.tr( |
|
7218 """You are using a snapshot release of""" |
|
7219 """ eric. A more up-to-date stable release""" |
|
7220 """ might be available.""")) |
|
7221 elif VersionOnly.startswith(("rev_", "@@")): |
|
7222 # check installation from source |
|
7223 if self.manualUpdatesCheck: |
|
7224 E5MessageBox.information( |
|
7225 self, |
|
7226 self.tr("Update Check"), |
|
7227 self.tr( |
|
7228 """You installed eric directly from the source""" |
|
7229 """ code. There is no possibility to check""" |
|
7230 """ for the availability of an update.""")) |
|
7231 else: |
|
7232 # check release version |
|
7233 installedVersionTuple = self.__versionToTuple(VersionOnly) |
|
7234 availableVersionTuple = self.__versionToTuple(versions[0]) |
|
7235 if availableVersionTuple > installedVersionTuple: |
|
7236 res = E5MessageBox.yesNo( |
|
7237 self, |
|
7238 self.tr("Update available"), |
|
7239 self.tr( |
|
7240 """The update to <b>{0}</b> of eric is""" |
|
7241 """ available at <b>{1}</b>. Would you like""" |
|
7242 """ to get it?""") |
|
7243 .format(versions[0], versions[1]), |
|
7244 yesDefault=True) |
|
7245 url = res and versions[1] or '' |
|
7246 else: |
|
7247 if self.manualUpdatesCheck: |
|
7248 E5MessageBox.information( |
|
7249 self, |
|
7250 self.tr("eric is up to date"), |
|
7251 self.tr( |
|
7252 """You are using the latest version of""" |
|
7253 """ eric""")) |
|
7254 except (IndexError, TypeError): |
|
7255 E5MessageBox.warning( |
|
7256 self, |
|
7257 self.tr("Error during updates check"), |
|
7258 self.tr("""Could not perform updates check.""")) |
|
7259 |
|
7260 if url: |
|
7261 QDesktopServices.openUrl(QUrl(url)) |
|
7262 |
|
7263 @pyqtSlot() |
|
7264 def __versionsDownloadCanceled(self): |
|
7265 """ |
|
7266 Private slot called to cancel the version check. |
|
7267 """ |
|
7268 if self.__replies: |
|
7269 self.__versionCheckCanceled = True |
|
7270 self.__replies[-1].abort() |
|
7271 |
|
7272 def __showAvailableVersionInfos(self, versions): |
|
7273 """ |
|
7274 Private method to show the versions available for download. |
|
7275 |
|
7276 @param versions contents of the downloaded versions file (list of |
|
7277 strings) |
|
7278 """ |
|
7279 versionText = self.tr( |
|
7280 """<h3>Available versions</h3>""" |
|
7281 """<table>""") |
|
7282 line = 0 |
|
7283 while line < len(versions): |
|
7284 if versions[line] == "---": |
|
7285 break |
|
7286 |
|
7287 versionText += ( |
|
7288 """<tr><td>{0}</td><td><a href="{1}">{2}</a></td></tr>""" |
|
7289 ).format( |
|
7290 versions[line], versions[line + 1], |
|
7291 'sourceforge' in versions[line + 1] and |
|
7292 "SourceForge" or versions[line + 1]) |
|
7293 line += 2 |
|
7294 versionText += self.tr("""</table>""") |
|
7295 |
|
7296 self.__versionsDialog = E5MessageBox.E5MessageBox( |
|
7297 E5MessageBox.NoIcon, |
|
7298 Program, |
|
7299 versionText, |
|
7300 modal=False, |
|
7301 buttons=E5MessageBox.Ok, |
|
7302 parent=self |
|
7303 ) |
|
7304 self.__versionsDialog.setIconPixmap( |
|
7305 UI.PixmapCache.getPixmap("eric").scaled(64, 64)) |
|
7306 self.__versionsDialog.show() |
|
7307 |
|
7308 def __sslErrors(self, reply, errors): |
|
7309 """ |
|
7310 Private slot to handle SSL errors. |
|
7311 |
|
7312 @param reply reference to the reply object (QNetworkReply) |
|
7313 @param errors list of SSL errors (list of QSslError) |
|
7314 """ |
|
7315 ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0] |
|
7316 if ignored == E5SslErrorState.NOT_IGNORED: |
|
7317 self.__downloadCancelled = True |
|
7318 |
|
7319 ####################################### |
|
7320 ## Below are methods for various checks |
|
7321 ####################################### |
|
7322 |
|
7323 def checkConfigurationStatus(self): |
|
7324 """ |
|
7325 Public method to check, if eric has been configured. If it is not, |
|
7326 the configuration dialog is shown. |
|
7327 """ |
|
7328 if not Preferences.isConfigured(): |
|
7329 self.__initDebugToolbarsLayout() |
|
7330 |
|
7331 E5MessageBox.information( |
|
7332 self, |
|
7333 self.tr("First time usage"), |
|
7334 self.tr("""eric has not been configured yet. """ |
|
7335 """The configuration dialog will be started.""")) |
|
7336 self.showPreferences() |
|
7337 |
|
7338 def checkProjectsWorkspace(self): |
|
7339 """ |
|
7340 Public method to check, if a projects workspace has been configured. If |
|
7341 it has not, a dialog is shown. |
|
7342 """ |
|
7343 if not Preferences.isConfigured(): |
|
7344 # eric hasn't been configured at all |
|
7345 self.checkConfigurationStatus() |
|
7346 |
|
7347 workspace = Preferences.getMultiProject("Workspace") |
|
7348 if workspace == "": |
|
7349 default = Utilities.getHomeDir() |
|
7350 workspace = E5FileDialog.getExistingDirectory( |
|
7351 None, |
|
7352 self.tr("Select Workspace Directory"), |
|
7353 default, |
|
7354 E5FileDialog.Options(E5FileDialog.Option(0))) |
|
7355 Preferences.setMultiProject("Workspace", workspace) |
|
7356 |
|
7357 def versionIsNewer(self, required, snapshot=None): |
|
7358 """ |
|
7359 Public method to check, if the eric version is good compared to |
|
7360 the required version. |
|
7361 |
|
7362 @param required required version (string) |
|
7363 @param snapshot required snapshot version (string) |
|
7364 @return flag indicating, that the version is newer than the required |
|
7365 one (boolean) |
|
7366 """ |
|
7367 if VersionOnly.startswith("@@"): |
|
7368 # development version, always newer |
|
7369 return True |
|
7370 |
|
7371 if VersionOnly.startswith("rev_"): |
|
7372 # installed from cloned sources, always newer |
|
7373 return True |
|
7374 |
|
7375 if "snapshot-" in VersionOnly: |
|
7376 # check snapshot version |
|
7377 if snapshot is None: |
|
7378 return True |
|
7379 else: |
|
7380 vers = VersionOnly.split("snapshot-")[1] |
|
7381 return vers > snapshot |
|
7382 |
|
7383 versionTuple = self.__versionToTuple(VersionOnly) |
|
7384 if isinstance(required, str): |
|
7385 required = self.__versionToTuple(required) |
|
7386 try: |
|
7387 res = versionTuple > required |
|
7388 except TypeError: |
|
7389 # some mismatching types, assume newer |
|
7390 res = True |
|
7391 return res |
|
7392 |
|
7393 def __versionToTuple(self, version): |
|
7394 """ |
|
7395 Private method to convert a version string into a tuple. |
|
7396 |
|
7397 @param version version string |
|
7398 @type str |
|
7399 @return version tuple |
|
7400 @rtype tuple of int |
|
7401 """ |
|
7402 versionParts = [] |
|
7403 for part in version.split("."): |
|
7404 part = part.strip() |
|
7405 if part: |
|
7406 try: |
|
7407 part = int(part) |
|
7408 except ValueError: |
|
7409 # not an integer, ignore |
|
7410 continue |
|
7411 versionParts.append(part) |
|
7412 return tuple(versionParts) |
|
7413 |
|
7414 ################################# |
|
7415 ## Below are some utility methods |
|
7416 ################################# |
|
7417 |
|
7418 def __getFloatingGeometry(self, w): |
|
7419 """ |
|
7420 Private method to get the geometry of a floating windows. |
|
7421 |
|
7422 @param w reference to the widget to be saved (QWidget) |
|
7423 @return list giving the widget's geometry and its visibility |
|
7424 """ |
|
7425 s = w.size() |
|
7426 p = w.pos() |
|
7427 return [p.x(), p.y(), s.width(), s.height(), not w.isHidden()] |
|
7428 |
|
7429 def getOriginalPathString(self): |
|
7430 """ |
|
7431 Public method to get the original PATH environment variable |
|
7432 (i.e. before modifications by eric and PyQt5). |
|
7433 |
|
7434 @return original PATH environment variable |
|
7435 @rtype str |
|
7436 """ |
|
7437 return self.__originalPathString |
|
7438 |
|
7439 ############################ |
|
7440 ## some event handlers below |
|
7441 ############################ |
|
7442 |
|
7443 def showEvent(self, evt): |
|
7444 """ |
|
7445 Protected method to handle the show event. |
|
7446 |
|
7447 @param evt reference to the show event (QShowEvent) |
|
7448 """ |
|
7449 if self.__startup: |
|
7450 if Preferences.getGeometry("MainMaximized"): |
|
7451 self.setWindowState( |
|
7452 Qt.WindowStates(Qt.WindowState.WindowMaximized)) |
|
7453 self.__startup = False |
|
7454 |
|
7455 ########################################## |
|
7456 ## Support for desktop notifications below |
|
7457 ########################################## |
|
7458 |
|
7459 def showNotification(self, icon, heading, text, |
|
7460 kind=NotificationTypes.INFORMATION, timeout=None): |
|
7461 """ |
|
7462 Public method to show a desktop notification. |
|
7463 |
|
7464 @param icon icon to be shown in the notification |
|
7465 @type QPixmap |
|
7466 @param heading heading of the notification |
|
7467 @type str |
|
7468 @param text text of the notification |
|
7469 @type str |
|
7470 @param kind kind of notification to be shown |
|
7471 @type NotificationTypes |
|
7472 @param timeout time in seconds the notification should be shown |
|
7473 (None = use configured timeout, 0 = indefinitely) |
|
7474 @type int |
|
7475 """ |
|
7476 if self.__notification is None: |
|
7477 from .NotificationWidget import NotificationWidget |
|
7478 self.__notification = NotificationWidget(parent=self) |
|
7479 if timeout is None: |
|
7480 timeout = Preferences.getUI("NotificationTimeout") |
|
7481 self.__notification.showNotification(icon, heading, text, kind=kind, |
|
7482 timeout=timeout) |
|
7483 |
|
7484 ######################### |
|
7485 ## Support for IRC below |
|
7486 ######################### |
|
7487 |
|
7488 def autoConnectIrc(self): |
|
7489 """ |
|
7490 Public method to initiate the IRC auto connection. |
|
7491 """ |
|
7492 if self.irc is not None: |
|
7493 self.irc.autoConnect() |
|
7494 |
|
7495 def __ircAutoConnected(self): |
|
7496 """ |
|
7497 Private slot handling the automatic connection of the IRC client. |
|
7498 """ |
|
7499 self.__activateIRC() |
|
7500 |
|
7501 ############################################### |
|
7502 ## Support for Code Documentation Viewer below |
|
7503 ############################################### |
|
7504 |
|
7505 def documentationViewer(self): |
|
7506 """ |
|
7507 Public method to provide a reference to the code documentation viewer. |
|
7508 |
|
7509 @return reference to the code documentation viewer |
|
7510 @rtype CodeDocumentationViewer |
|
7511 """ |
|
7512 return self.codeDocumentationViewer |