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