eric7/UI/UserInterface.py

branch
eric7
changeset 8312
800c432b34c8
parent 8304
c9738782e7a4
child 8314
e3642a6a1e71
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
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

eric ide

mercurial