Sat, 05 Dec 2020 12:29:26 +0100
Merged with default branch to prepare a new release.
# -*- coding: utf-8 -*- # Copyright (c) 2002 - 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the main user interface. """ import os import sys import logging import shutil import json import datetime import getpass from PyQt5.QtCore import ( pyqtSlot, QTimer, QFile, QFileInfo, pyqtSignal, PYQT_VERSION_STR, QDate, QIODevice, qVersion, QProcess, QSize, QUrl, QObject, Qt, QUuid, QThread, QUrlQuery ) from PyQt5.QtGui import QKeySequence, QDesktopServices from PyQt5.QtWidgets import ( QSizePolicy, QWidget, QWhatsThis, QToolBar, QDialog, QSplitter, QApplication, QMenu, QVBoxLayout, QDockWidget, QAction, QLabel ) from PyQt5.Qsci import QSCINTILLA_VERSION_STR from PyQt5.QtNetwork import ( QNetworkProxyFactory, QNetworkAccessManager, QNetworkRequest, QNetworkReply ) from .Info import Version, VersionOnly, BugAddress, Program, FeatureAddress from . import Config from E5Gui.E5SingleApplication import E5SingleApplicationServer from E5Gui.E5Action import E5Action, createActionGroup from E5Gui.E5ToolBarManager import E5ToolBarManager from E5Gui import E5MessageBox, E5FileDialog, E5ErrorMessage from E5Gui.E5Application import e5App from E5Gui.E5MainWindow import E5MainWindow from E5Gui.E5ZoomWidget import E5ZoomWidget from E5Gui.E5ProgressDialog import E5ProgressDialog from E5Gui.E5ClickableLabel import E5ClickableLabel import Preferences import Utilities import Globals import UI.PixmapCache from E5Network.E5NetworkIcon import E5NetworkIcon from E5Network.E5NetworkProxyFactory import ( E5NetworkProxyFactory, proxyAuthenticationRequired ) try: from E5Network.E5SslErrorHandler import E5SslErrorHandler SSL_AVAILABLE = True except ImportError: SSL_AVAILABLE = False from eric6config import getConfig class Redirector(QObject): """ Helper class used to redirect stdout and stderr to the log window. @signal appendStderr(str) emitted to write data to stderr logger @signal appendStdout(str) emitted to write data to stdout logger """ appendStderr = pyqtSignal(str) appendStdout = pyqtSignal(str) def __init__(self, stderr, parent=None): """ Constructor @param stderr flag indicating stderr is being redirected @type bool @param parent reference to the parent object @type QObject """ super(Redirector, self).__init__(parent) self.stderr = stderr self.buffer = '' def __nWrite(self, n): """ Private method used to write data. @param n max number of bytes to write """ if n: line = self.buffer[:n] if self.stderr: self.appendStderr.emit(line) else: self.appendStdout.emit(line) self.buffer = self.buffer[n:] def __bufferedWrite(self): """ Private method returning number of characters to write. @return number of characters buffered or length of buffered line (integer) """ return self.buffer.rfind('\n') + 1 def flush(self): """ Public method used to flush the buffered data. """ self.__nWrite(len(self.buffer)) def write(self, s): """ Public method used to write data. @param s data to be written (it must support the str-method) """ self.buffer += str(s) self.__nWrite(self.__bufferedWrite()) class UserInterface(E5MainWindow): """ Class implementing the main user interface. @signal appendStderr(str) emitted to write data to stderr logger @signal appendStdout(str) emitted to write data to stdout logger @signal preferencesChanged() emitted after the preferences were changed @signal reloadAPIs() emitted to reload the api information @signal showMenu(str, QMenu) emitted when a menu is about to be shown. The name of the menu and a reference to the menu are given. @signal masterPasswordChanged(str, str) emitted after the master password has been changed with the old and the new password @signal onlineStateChanged(online) emitted to indicate a change of the network state """ appendStderr = pyqtSignal(str) appendStdout = pyqtSignal(str) preferencesChanged = pyqtSignal() reloadAPIs = pyqtSignal() showMenu = pyqtSignal(str, QMenu) masterPasswordChanged = pyqtSignal(str, str) onlineStateChanged = pyqtSignal(bool) maxFilePathLen = 100 maxMenuFilePathLen = 75 LeftSide = 1 BottomSide = 2 RightSide = 3 ErrorLogFileName = "eric6_error.log" def __init__(self, app, locale, splash, plugin, disabledPlugins, noOpenAtStartup, noCrashOpenAtStartup, disableCrashSession, restartArguments, originalPathString): """ Constructor @param app reference to the application object @type E5Application @param locale locale to be used by the UI @type str @param splash reference to the splashscreen @type UI.SplashScreen.SplashScreen @param plugin filename of a plug-in to be loaded (used for plugin development) @type str @param disabledPlugins list of plug-ins that have been disabled via the command line parameters '--disable-plugin=' @type list of str @param noOpenAtStartup flag indicating that the open at startup option should not be executed @type bool @param noCrashOpenAtStartup flag indicating to ignore any crash session file found at statup @type bool @param disableCrashSession flag indicating to disable the crash session support @type bool @param restartArguments list of command line parameters to be used for a restart @type list of str @param originalPathString original PATH environment variable @type str """ super(UserInterface, self).__init__() self.__restartArgs = restartArguments[:] self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) self.maxEditorPathLen = Preferences.getUI("CaptionFilenameLength") self.locale = locale self.__noOpenAtStartup = noOpenAtStartup self.__noCrashOpenAtStartup = noCrashOpenAtStartup self.__disableCrashSession = disableCrashSession self.__disabledPlugins = disabledPlugins[:] self.__originalPathString = originalPathString self.__layoutType = Preferences.getUI("LayoutType") self.passiveMode = Preferences.getDebugger("PassiveDbgEnabled") g = Preferences.getGeometry("MainGeometry") if g.isEmpty(): s = QSize(1280, 1024) self.resize(s) else: self.restoreGeometry(g) self.__startup = True if Preferences.getUI("UseSystemProxy"): QNetworkProxyFactory.setUseSystemConfiguration(True) else: self.__proxyFactory = E5NetworkProxyFactory() QNetworkProxyFactory.setApplicationProxyFactory( self.__proxyFactory) QNetworkProxyFactory.setUseSystemConfiguration(False) self.capProject = "" self.capEditor = "" self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename") QApplication.setWindowIcon(UI.PixmapCache.getIcon("eric")) self.setWindowIcon(UI.PixmapCache.getIcon("eric")) self.__setWindowCaption() # load the view profiles self.profiles = Preferences.getUI("ViewProfiles2") # Generate the conda interface from CondaInterface.Conda import Conda self.condaInterface = Conda(self) e5App().registerObject("Conda", self.condaInterface) # Generate the pip interface from PipInterface.Pip import Pip self.pipInterface = Pip(self) e5App().registerObject("Pip", self.pipInterface) # Generate the virtual environment manager from VirtualEnv.VirtualenvManager import VirtualenvManager self.virtualenvManager = VirtualenvManager(self) # register it early because it is needed very soon e5App().registerObject("VirtualEnvManager", self.virtualenvManager) # Generate the debug server object from Debugger.DebugServer import DebugServer debugServer = DebugServer(self.__originalPathString) # Create the background service object from Utilities.BackgroundService import BackgroundService self.backgroundService = BackgroundService() # Generate an empty project object and multi project object from Project.Project import Project self.project = Project(self) e5App().registerObject("Project", self.project) from MultiProject.MultiProject import MultiProject self.multiProject = MultiProject(self.project, self) splash.showMessage(self.tr("Initializing Plugin Manager...")) # Initialize the Plugin Manager (Plugins are initialized later from PluginManager.PluginManager import PluginManager self.pluginManager = PluginManager(self, self.__disabledPlugins, develPlugin=plugin) splash.showMessage(self.tr("Generating Main User Interface...")) self.codeDocumentationViewer = None self.cooperation = None self.irc = None self.symbolsViewer = None self.browser = None self.templateViewer = None self.numbersViewer = None self.pipWidget = None self.condaWidget = None self.microPythonWidget = None self.__webBrowserProcess = None self.__webBrowserClient = None self.__webBrowserSAName = QUuid.createUuid().toString()[1:-1] # Create the main window now so that we can connect QActions to it. logging.debug("Creating Layout...") self.__createLayout(debugServer) self.__currentRightWidget = None self.__currentBottomWidget = None # Generate the debugger part of the ui logging.debug("Creating Debugger UI...") from Debugger.DebugUI import DebugUI self.debuggerUI = DebugUI(self, self.viewmanager, debugServer, self.debugViewer, self.project) self.debugViewer.setDebugger(self.debuggerUI) self.shell.setDebuggerUI(self.debuggerUI) # Generate the redirection helpers self.stdout = Redirector(False, self) self.stderr = Redirector(True, self) # set a few dialog members for non-modal dialogs created on demand self.programsDialog = None self.shortcutsDialog = None self.unittestDialog = None self.findFileNameDialog = None self.diffDlg = None self.compareDlg = None self.findFilesDialog = None self.replaceFilesDialog = None self.__notification = None self.__readingSession = False self.__versionsDialog = None self.__configurationDialog = None # now setup the connections splash.showMessage(self.tr("Setting up connections...")) self.debugViewer.exceptionLogger.sourceFile.connect( self.viewmanager.openSourceFile) self.debugViewer.sourceFile.connect(self.viewmanager.showDebugSource) self.taskViewer.displayFile.connect(self.viewmanager.openSourceFile) self.projectBrowser.psBrowser.sourceFile[str].connect( self.viewmanager.openSourceFile) self.projectBrowser.psBrowser.sourceFile[str, int].connect( self.viewmanager.openSourceFile) self.projectBrowser.psBrowser.sourceFile[str, list].connect( self.viewmanager.openSourceFile) self.projectBrowser.psBrowser.sourceFile[str, int, str].connect( self.viewmanager.openSourceFile) self.projectBrowser.psBrowser.closeSourceWindow.connect( self.viewmanager.closeWindow) self.projectBrowser.psBrowser.unittestOpen.connect( self.__unittestScript) self.projectBrowser.pfBrowser.designerFile.connect(self.__designer) self.projectBrowser.pfBrowser.sourceFile.connect( self.viewmanager.openSourceFile) self.projectBrowser.pfBrowser.uipreview.connect(self.__UIPreviewer) self.projectBrowser.pfBrowser.trpreview.connect(self.__TRPreviewer) self.projectBrowser.pfBrowser.closeSourceWindow.connect( self.viewmanager.closeWindow) self.projectBrowser.pfBrowser.appendStderr.connect(self.appendToStderr) self.projectBrowser.prBrowser.sourceFile.connect( self.viewmanager.openSourceFile) self.projectBrowser.prBrowser.closeSourceWindow.connect( self.viewmanager.closeWindow) self.projectBrowser.prBrowser.appendStderr.connect(self.appendToStderr) self.projectBrowser.ptBrowser.linguistFile.connect(self.__linguist) self.projectBrowser.ptBrowser.sourceFile.connect( self.viewmanager.openSourceFile) self.projectBrowser.ptBrowser.trpreview[list].connect( self.__TRPreviewer) self.projectBrowser.ptBrowser.trpreview[list, bool].connect( self.__TRPreviewer) self.projectBrowser.ptBrowser.closeSourceWindow.connect( self.viewmanager.closeWindow) self.projectBrowser.ptBrowser.appendStdout.connect(self.appendToStdout) self.projectBrowser.ptBrowser.appendStderr.connect(self.appendToStderr) self.projectBrowser.piBrowser.sourceFile[str].connect( self.viewmanager.openSourceFile) self.projectBrowser.piBrowser.sourceFile[str, int].connect( self.viewmanager.openSourceFile) self.projectBrowser.piBrowser.closeSourceWindow.connect( self.viewmanager.closeWindow) self.projectBrowser.piBrowser.appendStdout.connect(self.appendToStdout) self.projectBrowser.piBrowser.appendStderr.connect(self.appendToStderr) self.projectBrowser.ppBrowser.sourceFile[str].connect( self.viewmanager.openSourceFile) self.projectBrowser.ppBrowser.sourceFile[str, int].connect( self.viewmanager.openSourceFile) self.projectBrowser.ppBrowser.closeSourceWindow.connect( self.viewmanager.closeWindow) self.projectBrowser.ppBrowser.appendStdout.connect(self.appendToStdout) self.projectBrowser.ppBrowser.appendStderr.connect(self.appendToStderr) self.projectBrowser.poBrowser.sourceFile.connect( self.viewmanager.openSourceFile) self.projectBrowser.poBrowser.closeSourceWindow.connect( self.viewmanager.closeWindow) self.projectBrowser.poBrowser.pixmapEditFile.connect(self.__editPixmap) self.projectBrowser.poBrowser.pixmapFile.connect(self.__showPixmap) self.projectBrowser.poBrowser.svgFile.connect(self.__showSvg) self.projectBrowser.poBrowser.binaryFile.connect(self.__openHexEditor) self.project.sourceFile.connect(self.viewmanager.openSourceFile) self.project.designerFile.connect(self.__designer) self.project.linguistFile.connect(self.__linguist) self.project.projectOpened.connect(self.viewmanager.projectOpened) self.project.projectClosed.connect(self.viewmanager.projectClosed) self.project.projectFileRenamed.connect( self.viewmanager.projectFileRenamed) self.project.lexerAssociationsChanged.connect( self.viewmanager.projectLexerAssociationsChanged) self.project.newProject.connect(self.__newProject) self.project.projectOpened.connect(self.__projectOpened) self.project.projectOpened.connect(self.__activateProjectBrowser) self.project.projectClosed.connect(self.__projectClosed) self.project.projectClosed.connect( self.backgroundService.preferencesOrProjectChanged) self.project.projectOpened.connect(self.__writeCrashSession) self.project.projectClosed.connect(self.__writeCrashSession) self.project.appendStdout.connect(self.appendToStdout) self.project.appendStderr.connect(self.appendToStderr) self.multiProject.multiProjectOpened.connect( self.__activateMultiProjectBrowser) self.multiProject.multiProjectOpened.connect( self.__writeCrashSession) self.multiProject.multiProjectClosed.connect( self.__writeCrashSession) self.debuggerUI.resetUI.connect(self.viewmanager.handleResetUI) self.debuggerUI.resetUI.connect(self.debugViewer.handleResetUI) self.debuggerUI.resetUI.connect(self.__debuggingDone) self.debuggerUI.debuggingStarted.connect( self.debugViewer.exceptionLogger.debuggingStarted) self.debuggerUI.debuggingStarted.connect( self.debugViewer.handleDebuggingStarted) self.debuggerUI.debuggingStarted.connect(self.__programChange) self.debuggerUI.debuggingStarted.connect(self.__debuggingStarted) self.debuggerUI.compileForms.connect( self.projectBrowser.pfBrowser.compileChangedForms) self.debuggerUI.compileResources.connect( self.projectBrowser.prBrowser.compileChangedResources) self.debuggerUI.executeMake.connect(self.project.executeMake) self.debuggerUI.appendStdout.connect(self.appendToStdout) debugServer.passiveDebugStarted.connect( self.debugViewer.exceptionLogger.debuggingStarted) debugServer.passiveDebugStarted.connect( self.debugViewer.handleDebuggingStarted) debugServer.clientException.connect( self.debugViewer.exceptionLogger.addException) debugServer.clientLine.connect( self.debugViewer.breakpointViewer.highlightBreakpoint) debugServer.clientDisassembly.connect( self.debugViewer.disassemblyViewer.showDisassembly) debugServer.clientProcessStdout.connect(self.appendToStdout) debugServer.clientProcessStderr.connect(self.appendToStderr) debugServer.appendStdout.connect(self.appendToStdout) self.stdout.appendStdout.connect(self.appendToStdout) self.stderr.appendStderr.connect(self.appendToStderr) self.preferencesChanged.connect(self.viewmanager.preferencesChanged) self.reloadAPIs.connect(self.viewmanager.getAPIsManager().reloadAPIs) self.preferencesChanged.connect(self.logViewer.preferencesChanged) self.appendStdout.connect(self.logViewer.appendToStdout) self.appendStderr.connect(self.logViewer.appendToStderr) self.preferencesChanged.connect(self.shell.handlePreferencesChanged) self.preferencesChanged.connect(self.project.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.psBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.pfBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.prBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.ptBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.piBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.ppBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.projectBrowser.poBrowser.handlePreferencesChanged) self.preferencesChanged.connect( self.taskViewer.handlePreferencesChanged) self.preferencesChanged.connect(self.pluginManager.preferencesChanged) self.preferencesChanged.connect(debugServer.preferencesChanged) self.preferencesChanged.connect(self.debugViewer.preferencesChanged) self.preferencesChanged.connect( self.backgroundService.preferencesOrProjectChanged) self.preferencesChanged.connect(self.__previewer.preferencesChanged) self.preferencesChanged.connect(self.__astViewer.preferencesChanged) self.preferencesChanged.connect(self.__disViewer.preferencesChanged) if self.browser is not None: self.browser.sourceFile[str].connect( self.viewmanager.openSourceFile) self.browser.sourceFile[str, int].connect( self.viewmanager.openSourceFile) self.browser.sourceFile[str, list].connect( self.viewmanager.openSourceFile) self.browser.sourceFile[str, int, str].connect( self.viewmanager.openSourceFile) self.browser.designerFile.connect(self.__designer) self.browser.linguistFile.connect(self.__linguist) self.browser.projectFile.connect(self.project.openProject) self.browser.multiProjectFile.connect( self.multiProject.openMultiProject) self.browser.pixmapEditFile.connect(self.__editPixmap) self.browser.pixmapFile.connect(self.__showPixmap) self.browser.svgFile.connect(self.__showSvg) self.browser.binaryFile.connect(self.__openHexEditor) self.browser.unittestOpen.connect(self.__unittestScript) self.browser.trpreview.connect(self.__TRPreviewer) self.debuggerUI.debuggingStarted.connect( self.browser.handleProgramChange) debugServer.clientInterpreterChanged.connect( self.browser.handleInterpreterChanged) self.preferencesChanged.connect( self.browser.handlePreferencesChanged) if self.codeDocumentationViewer is not None: self.preferencesChanged.connect( self.codeDocumentationViewer.preferencesChanged) self.viewmanager.editorSaved.connect(self.project.repopulateItem) self.viewmanager.lastEditorClosed.connect(self.__lastEditorClosed) self.viewmanager.editorOpened.connect(self.__editorOpened) self.viewmanager.changeCaption.connect(self.__setWindowCaption) self.viewmanager.checkActions.connect(self.__checkActions) self.viewmanager.editorChanged.connect( self.projectBrowser.handleEditorChanged) self.viewmanager.editorLineChanged.connect( self.projectBrowser.handleEditorLineChanged) self.viewmanager.editorOpened.connect(self.__writeCrashSession) self.viewmanager.editorClosed.connect(self.__writeCrashSession) self.viewmanager.editorRenamed.connect(self.__writeCrashSession) self.viewmanager.editorChanged.connect(self.__writeCrashSession) self.shell.zoomValueChanged.connect( lambda v: self.viewmanager.zoomValueChanged(v, self.shell)) if self.cooperation is not None: self.viewmanager.checkActions.connect( self.cooperation.checkEditorActions) self.preferencesChanged.connect( self.cooperation.preferencesChanged) self.cooperation.shareEditor.connect( self.viewmanager.shareEditor) self.cooperation.startEdit.connect( self.viewmanager.startSharedEdit) self.cooperation.sendEdit.connect( self.viewmanager.sendSharedEdit) self.cooperation.cancelEdit.connect( self.viewmanager.cancelSharedEdit) self.cooperation.connected.connect( self.viewmanager.shareConnected) self.cooperation.editorCommand.connect( self.viewmanager.receive) self.viewmanager.setCooperationClient( self.cooperation.getClient()) if self.symbolsViewer is not None: self.symbolsViewer.insertSymbol.connect( self.viewmanager.insertSymbol) if self.numbersViewer is not None: self.numbersViewer.insertNumber.connect( self.viewmanager.insertNumber) if self.irc is not None: self.irc.autoConnected.connect(self.__ircAutoConnected) # create the toolbar manager object self.toolbarManager = E5ToolBarManager(self, self) self.toolbarManager.setMainWindow(self) # Initialize the tool groups and list of started tools splash.showMessage(self.tr("Initializing Tools...")) self.toolGroups, self.currentToolGroup = Preferences.readToolGroups() self.toolProcs = [] self.__initExternalToolsActions() # redirect handling of http and https URLs to ourselves QDesktopServices.setUrlHandler("http", self.handleUrl) QDesktopServices.setUrlHandler("https", self.handleUrl) # register all relevant objects splash.showMessage(self.tr("Registering Objects...")) e5App().registerObject("UserInterface", self) e5App().registerObject("DebugUI", self.debuggerUI) e5App().registerObject("DebugServer", debugServer) e5App().registerObject("BackgroundService", self.backgroundService) e5App().registerObject("ViewManager", self.viewmanager) e5App().registerObject("ProjectBrowser", self.projectBrowser) e5App().registerObject("MultiProject", self.multiProject) e5App().registerObject("TaskViewer", self.taskViewer) if self.templateViewer is not None: e5App().registerObject("TemplateViewer", self.templateViewer) e5App().registerObject("Shell", self.shell) e5App().registerObject("PluginManager", self.pluginManager) e5App().registerObject("ToolbarManager", self.toolbarManager) if self.cooperation is not None: e5App().registerObject("Cooperation", self.cooperation) if self.irc is not None: e5App().registerObject("IRC", self.irc) if self.symbolsViewer is not None: e5App().registerObject("Symbols", self.symbolsViewer) if self.numbersViewer is not None: e5App().registerObject("Numbers", self.numbersViewer) if self.codeDocumentationViewer is not None: e5App().registerObject("DocuViewer", self.codeDocumentationViewer) if self.microPythonWidget is not None: e5App().registerObject("MicroPython", self.microPythonWidget) # list of web addresses serving the versions file self.__httpAlternatives = Preferences.getUI("VersionsUrls6") self.__inVersionCheck = False self.__versionCheckProgress = None # Initialize the actions, menus, toolbars and statusbar splash.showMessage(self.tr("Initializing Actions...")) self.__initActions() splash.showMessage(self.tr("Initializing Menus...")) self.__initMenus() splash.showMessage(self.tr("Initializing Toolbars...")) self.__initToolbars() splash.showMessage(self.tr("Initializing Statusbar...")) self.__initStatusbar() # connect the appFocusChanged signal after all actions are ready app.focusChanged.connect(self.viewmanager.appFocusChanged) # Initialize the instance variables. self.currentProg = None self.isProg = False self.utEditorOpen = False self.utProjectOpen = False self.inDragDrop = False self.setAcceptDrops(True) self.currentProfile = None self.shutdownCalled = False self.inCloseEvent = False # now redirect stdout and stderr sys.stdout = self.stdout sys.stderr = self.stderr # now fire up the single application server if Preferences.getUI("SingleApplicationMode"): splash.showMessage( self.tr("Initializing Single Application Server...")) self.SAServer = E5SingleApplicationServer() else: self.SAServer = None # now finalize the plugin manager setup splash.showMessage(self.tr("Initializing Plugins...")) self.pluginManager.finalizeSetup() # now activate plugins having autoload set to True splash.showMessage(self.tr("Activating Plugins...")) self.pluginManager.activatePlugins() splash.showMessage(self.tr("Generating Plugins Toolbars...")) self.pluginManager.initPluginToolbars(self.toolbarManager) if Preferences.getPluginManager("StartupCleanup"): splash.showMessage(self.tr("Cleaning Plugins Download Area...")) from PluginManager.PluginRepositoryDialog import ( PluginRepositoryDownloadCleanup ) PluginRepositoryDownloadCleanup(quiet=True) # now read the keyboard shortcuts for all the actions from Preferences import Shortcuts Shortcuts.readShortcuts() # restore toolbar manager state splash.showMessage(self.tr("Restoring Toolbarmanager...")) self.toolbarManager.restoreState( Preferences.getUI("ToolbarManagerState")) if self.codeDocumentationViewer is not None: # finalize the initialization of the code documentation viewer self.codeDocumentationViewer.finalizeSetup() # now activate the initial view profile splash.showMessage(self.tr("Setting View Profile...")) self.__setEditProfile() # special treatment for the VCS toolbars for tb in self.getToolbarsByCategory("vcs"): tb.setVisible(False) tb.setEnabled(False) tb = self.getToolbar("vcs")[1] tb.setEnabled(True) if Preferences.getVCS("ShowVcsToolbar"): tb.setVisible(True) # now read the saved tasks splash.showMessage(self.tr("Reading Tasks...")) self.__readTasks() if self.templateViewer is not None: # now read the saved templates splash.showMessage(self.tr("Reading Templates...")) self.templateViewer.readTemplates() # now start the debug client with the most recently used virtual # environment splash.showMessage(self.tr("Starting Debugger...")) if Preferences.getShell("StartWithMostRecentlyUsedEnvironment"): debugServer.startClient( False, venvName=Preferences.getShell("LastVirtualEnvironment") ) else: debugServer.startClient(False) # attributes for the network objects self.__networkManager = QNetworkAccessManager(self) self.__networkManager.proxyAuthenticationRequired.connect( proxyAuthenticationRequired) if SSL_AVAILABLE: self.__sslErrorHandler = E5SslErrorHandler(self) self.__networkManager.sslErrors.connect(self.__sslErrors) self.__replies = [] # set spellchecker defaults from QScintilla.SpellChecker import SpellChecker SpellChecker.setDefaultLanguage( Preferences.getEditor("SpellCheckingDefaultLanguage")) # attributes for the last shown configuration page and the # extended configuration entries self.__lastConfigurationPageName = "" self.__expandedConfigurationEntries = [] # set the keyboard input interval interval = Preferences.getUI("KeyboardInputInterval") if interval > 0: QApplication.setKeyboardInputInterval(interval) def networkAccessManager(self): """ Public method to get a reference to the network access manager object. @return reference to the network access manager object @rtype QNetworkAccessManager """ return self.__networkManager def __createLayout(self, debugServer): """ Private method to create the layout of the various windows. @param debugServer reference to the debug server object @exception ValueError raised to indicate an invalid layout type """ # Create the view manager depending on the configuration setting logging.debug("Creating Viewmanager...") import ViewManager self.viewmanager = ViewManager.factory( self, self, debugServer, self.pluginManager) leftWidget = QWidget() layout = QVBoxLayout() layout.setContentsMargins(1, 1, 1, 1) layout.setSpacing(1) layout.addWidget(self.viewmanager.mainWidget()) layout.addWidget(self.viewmanager.searchWidget()) layout.addWidget(self.viewmanager.replaceWidget()) self.viewmanager.mainWidget().setSizePolicy( QSizePolicy.Preferred, QSizePolicy.Expanding) leftWidget.setLayout(layout) self.viewmanager.searchWidget().hide() self.viewmanager.replaceWidget().hide() splitter = QSplitter(Qt.Horizontal) splitter.addWidget(leftWidget) self.setCentralWidget(splitter) # Create previewer logging.debug("Creating Previewer...") from .Previewer import Previewer self.__previewer = Previewer(self.viewmanager, splitter) splitter.addWidget(self.__previewer) # Create AST viewer logging.debug("Creating Python AST Viewer") from .PythonAstViewer import PythonAstViewer self.__astViewer = PythonAstViewer(self.viewmanager, splitter) splitter.addWidget(self.__astViewer) # Create DIS viewer logging.debug("Creating Python Disassembly Viewer") from .PythonDisViewer import PythonDisViewer self.__disViewer = PythonDisViewer(self.viewmanager, parent=splitter) splitter.addWidget(self.__disViewer) # Create layout with toolbox windows embedded in dock windows if self.__layoutType == "Toolboxes": logging.debug("Creating toolboxes...") self.__createToolboxesLayout(debugServer) # Create layout with sidebar windows embedded in dock windows elif self.__layoutType == "Sidebars": logging.debug("Creating sidebars...") self.__createSidebarsLayout(debugServer) else: raise ValueError("Wrong layout type given ({0})".format( self.__layoutType)) logging.debug("Created Layout") def __createToolboxesLayout(self, debugServer): """ Private method to create the Toolboxes layout. @param debugServer reference to the debug server object """ from E5Gui.E5ToolBox import E5VerticalToolBox, E5HorizontalToolBox logging.debug("Creating Toolboxes Layout...") # Create the left toolbox self.lToolboxDock = self.__createDockWindow("lToolboxDock") self.lToolbox = E5VerticalToolBox(self.lToolboxDock) self.__setupDockWindow(self.lToolboxDock, Qt.LeftDockWidgetArea, self.lToolbox, self.tr("Left Toolbox")) # Create the horizontal toolbox self.hToolboxDock = self.__createDockWindow("hToolboxDock") self.hToolbox = E5HorizontalToolBox(self.hToolboxDock) self.__setupDockWindow(self.hToolboxDock, Qt.BottomDockWidgetArea, self.hToolbox, self.tr("Horizontal Toolbox")) # Create the right toolbox self.rToolboxDock = self.__createDockWindow("rToolboxDock") self.rToolbox = E5VerticalToolBox(self.rToolboxDock) self.__setupDockWindow(self.rToolboxDock, Qt.RightDockWidgetArea, self.rToolbox, self.tr("Right Toolbox")) #################################################### ## Populate the left toolbox #################################################### # Create the project browser logging.debug("Creating Project Browser...") from Project.ProjectBrowser import ProjectBrowser self.projectBrowser = ProjectBrowser(self.project) self.lToolbox.addItem(self.projectBrowser, UI.PixmapCache.getIcon("projectViewer"), self.tr("Project-Viewer")) # Create the multi project browser logging.debug("Creating Multiproject Browser...") from MultiProject.MultiProjectBrowser import MultiProjectBrowser self.multiProjectBrowser = MultiProjectBrowser(self.multiProject, self.project) self.lToolbox.addItem(self.multiProjectBrowser, UI.PixmapCache.getIcon("multiProjectViewer"), self.tr("Multiproject-Viewer")) if Preferences.getUI("ShowTemplateViewer"): # Create the template viewer part of the user interface logging.debug("Creating Template Viewer...") from Templates.TemplateViewer import TemplateViewer self.templateViewer = TemplateViewer(None, self.viewmanager) self.lToolbox.addItem(self.templateViewer, UI.PixmapCache.getIcon("templateViewer"), self.tr("Template-Viewer")) #################################################### ## Populate the right toolbox #################################################### if Preferences.getUI("ShowCodeDocumentationViewer"): # Create the code documentation viewer logging.debug("Creating Code Documentation Viewer...") from .CodeDocumentationViewer import CodeDocumentationViewer self.codeDocumentationViewer = CodeDocumentationViewer(self) self.rToolbox.addItem(self.codeDocumentationViewer, UI.PixmapCache.getIcon("codeDocuViewer"), self.tr("Code Documentation Viewer")) # Create the debug viewer logging.debug("Creating Debug Viewer...") from Debugger.DebugViewer import DebugViewer self.debugViewer = DebugViewer(debugServer) self.rToolbox.addItem(self.debugViewer, UI.PixmapCache.getIcon("debugViewer"), self.tr("Debug-Viewer")) if Preferences.getUI("ShowPyPIPackageManager"): # Create the PyPI package manager logging.debug("Creating PyPI Package Manager...") from PipInterface.PipPackagesWidget import PipPackagesWidget self.pipWidget = PipPackagesWidget(self.pipInterface) self.rToolbox.addItem(self.pipWidget, UI.PixmapCache.getIcon("pypi"), self.tr("PyPI")) if Preferences.getUI("ShowCondaPackageManager"): # Create the conda package manager logging.debug("Creating Conda Package Manager...") from CondaInterface.CondaPackagesWidget import CondaPackagesWidget self.condaWidget = CondaPackagesWidget(self.condaInterface) self.rToolbox.addItem(self.condaWidget, UI.PixmapCache.getIcon("miniconda"), self.tr("Conda")) if Preferences.getUI("ShowCooperation"): # Create the chat part of the user interface logging.debug("Creating Chat Widget...") from Cooperation.ChatWidget import ChatWidget self.cooperation = ChatWidget(self) self.rToolbox.addItem(self.cooperation, UI.PixmapCache.getIcon("cooperation"), self.tr("Cooperation")) if Preferences.getUI("ShowIrc"): # Create the IRC part of the user interface logging.debug("Creating IRC Widget...") from Network.IRC.IrcWidget import IrcWidget self.irc = IrcWidget(self) self.rToolbox.addItem(self.irc, UI.PixmapCache.getIcon("irc"), self.tr("IRC")) if Preferences.getUI("ShowMicroPython"): # Create the MicroPython part of the user interface logging.debug("Creating MicroPython Widget...") from MicroPython.MicroPythonWidget import MicroPythonWidget self.microPythonWidget = MicroPythonWidget(self) self.rToolbox.addItem(self.microPythonWidget, UI.PixmapCache.getIcon("micropython"), self.tr("MicroPython")) #################################################### ## Populate the bottom toolbox #################################################### # Create the task viewer part of the user interface logging.debug("Creating Task Viewer...") from Tasks.TaskViewer import TaskViewer self.taskViewer = TaskViewer(None, self.project) self.hToolbox.addItem(self.taskViewer, UI.PixmapCache.getIcon("task"), self.tr("Task-Viewer")) # Create the log viewer part of the user interface logging.debug("Creating Log Viewer...") from .LogView import LogViewer self.logViewer = LogViewer(self) self.hToolbox.addItem(self.logViewer, UI.PixmapCache.getIcon("logViewer"), self.tr("Log-Viewer")) if Preferences.getUI("ShowFileBrowser"): # Create the file browser logging.debug("Creating File Browser...") from .Browser import Browser self.browser = Browser() self.lToolbox.addItem(self.browser, UI.PixmapCache.getIcon("browser"), self.tr("File-Browser")) if Preferences.getUI("ShowSymbolsViewer"): # Create the symbols viewer logging.debug("Creating Symbols Viewer...") from .SymbolsWidget import SymbolsWidget self.symbolsViewer = SymbolsWidget() self.lToolbox.addItem(self.symbolsViewer, UI.PixmapCache.getIcon("symbols"), self.tr("Symbols")) if Preferences.getUI("ShowNumbersViewer"): # Create the numbers viewer logging.debug("Creating Numbers Viewer...") from .NumbersWidget import NumbersWidget self.numbersViewer = NumbersWidget() self.hToolbox.addItem(self.numbersViewer, UI.PixmapCache.getIcon("numbers"), self.tr("Numbers")) #################################################### ## Populate the configurable widgets #################################################### # Create the shell logging.debug("Creating Shell...") self.__shellPosition = Preferences.getUI("ShellPosition") if self.__shellPosition == "left": self.__shellParent = self.lToolboxDock elif self.__shellPosition == "right": self.__shellParent = self.rToolboxDock else: self.__shellParent = self.hToolboxDock from QScintilla.Shell import ShellAssembly self.shellAssembly = ShellAssembly( debugServer, self.viewmanager, self.project, True) self.shell = self.shellAssembly.shell() self.__shellParent.widget().insertItem( 0, self.shellAssembly, UI.PixmapCache.getIcon("shell"), self.tr("Shell")) #################################################### ## Set the start index of each toolbox #################################################### self.lToolbox.setCurrentIndex(0) self.rToolbox.setCurrentIndex(0) self.hToolbox.setCurrentIndex(0) def __createSidebarsLayout(self, debugServer): """ Private method to create the Sidebars layout. @param debugServer reference to the debug server object """ from E5Gui.E5SideBar import E5SideBar logging.debug("Creating Sidebars Layout...") delay = Preferences.getUI("SidebarDelay") # Create the left sidebar self.leftSidebar = E5SideBar(E5SideBar.West, delay) # Create the bottom sidebar self.bottomSidebar = E5SideBar(E5SideBar.South, delay) # Create the right sidebar self.rightSidebar = E5SideBar(E5SideBar.East, delay) #################################################### ## Populate the left side bar #################################################### # Create the project browser logging.debug("Creating Project Browser...") from Project.ProjectBrowser import ProjectBrowser self.projectBrowser = ProjectBrowser(self.project) self.leftSidebar.addTab( self.projectBrowser, UI.PixmapCache.getIcon("projectViewer"), self.tr("Project-Viewer")) # Create the multi project browser logging.debug("Creating Multiproject Browser...") from MultiProject.MultiProjectBrowser import MultiProjectBrowser self.multiProjectBrowser = MultiProjectBrowser(self.multiProject, self.project) self.leftSidebar.addTab( self.multiProjectBrowser, UI.PixmapCache.getIcon("multiProjectViewer"), self.tr("Multiproject-Viewer")) if Preferences.getUI("ShowTemplateViewer"): # Create the template viewer part of the user interface logging.debug("Creating Template Viewer...") from Templates.TemplateViewer import TemplateViewer self.templateViewer = TemplateViewer(None, self.viewmanager) self.leftSidebar.addTab( self.templateViewer, UI.PixmapCache.getIcon("templateViewer"), self.tr("Template-Viewer")) #################################################### ## Populate the right side bar #################################################### if Preferences.getUI("ShowCodeDocumentationViewer"): # Create the code documentation viewer logging.debug("Creating Code Documentation Viewer...") from .CodeDocumentationViewer import CodeDocumentationViewer self.codeDocumentationViewer = CodeDocumentationViewer(self) self.rightSidebar.addTab( self.codeDocumentationViewer, UI.PixmapCache.getIcon("codeDocuViewer"), self.tr("Code Documentation Viewer")) # Create the debug viewer logging.debug("Creating Debug Viewer...") from Debugger.DebugViewer import DebugViewer self.debugViewer = DebugViewer(debugServer) self.rightSidebar.addTab( self.debugViewer, UI.PixmapCache.getIcon("debugViewer"), self.tr("Debug-Viewer")) if Preferences.getUI("ShowPyPIPackageManager"): # Create the PyPI package manager logging.debug("Creating PyPI Package Manager...") from PipInterface.PipPackagesWidget import PipPackagesWidget self.pipWidget = PipPackagesWidget(self.pipInterface) self.rightSidebar.addTab( self.pipWidget, UI.PixmapCache.getIcon("pypi"), self.tr("PyPI")) if Preferences.getUI("ShowCondaPackageManager"): # Create the conda package manager logging.debug("Creating Conda Package Manager...") from CondaInterface.CondaPackagesWidget import CondaPackagesWidget self.condaWidget = CondaPackagesWidget(self.condaInterface) self.rightSidebar.addTab( self.condaWidget, UI.PixmapCache.getIcon("miniconda"), self.tr("Conda")) if Preferences.getUI("ShowCooperation"): # Create the chat part of the user interface logging.debug("Creating Chat Widget...") from Cooperation.ChatWidget import ChatWidget self.cooperation = ChatWidget(self) self.rightSidebar.addTab( self.cooperation, UI.PixmapCache.getIcon("cooperation"), self.tr("Cooperation")) if Preferences.getUI("ShowIrc"): # Create the IRC part of the user interface logging.debug("Creating IRC Widget...") from Network.IRC.IrcWidget import IrcWidget self.irc = IrcWidget(self) self.rightSidebar.addTab( self.irc, UI.PixmapCache.getIcon("irc"), self.tr("IRC")) if Preferences.getUI("ShowMicroPython"): # Create the MicroPython part of the user interface logging.debug("Creating MicroPython Widget...") from MicroPython.MicroPythonWidget import MicroPythonWidget self.microPythonWidget = MicroPythonWidget(self) self.rightSidebar.addTab( self.microPythonWidget, UI.PixmapCache.getIcon("micropython"), self.tr("MicroPython")) #################################################### ## Populate the bottom side bar #################################################### # Create the task viewer part of the user interface logging.debug("Creating Task Viewer...") from Tasks.TaskViewer import TaskViewer self.taskViewer = TaskViewer(None, self.project) self.bottomSidebar.addTab(self.taskViewer, UI.PixmapCache.getIcon("task"), self.tr("Task-Viewer")) # Create the log viewer part of the user interface logging.debug("Creating Log Viewer...") from .LogView import LogViewer self.logViewer = LogViewer(self) self.bottomSidebar.addTab(self.logViewer, UI.PixmapCache.getIcon("logViewer"), self.tr("Log-Viewer")) if Preferences.getUI("ShowFileBrowser"): # Create the file browser logging.debug("Creating File Browser...") from .Browser import Browser self.browser = Browser() self.leftSidebar.addTab(self.browser, UI.PixmapCache.getIcon("browser"), self.tr("File-Browser")) if Preferences.getUI("ShowSymbolsViewer"): # Create the symbols viewer logging.debug("Creating Symbols Viewer...") from .SymbolsWidget import SymbolsWidget self.symbolsViewer = SymbolsWidget() self.leftSidebar.addTab(self.symbolsViewer, UI.PixmapCache.getIcon("symbols"), self.tr("Symbols")) if Preferences.getUI("ShowNumbersViewer"): # Create the numbers viewer logging.debug("Creating Numbers Viewer...") from .NumbersWidget import NumbersWidget self.numbersViewer = NumbersWidget() self.bottomSidebar.addTab(self.numbersViewer, UI.PixmapCache.getIcon("numbers"), self.tr("Numbers")) #################################################### ## Populate the configurable widgets #################################################### # Create the shell logging.debug("Creating Shell...") self.__shellPosition = Preferences.getUI("ShellPosition") if self.__shellPosition == "left": self.__shellParent = self.leftSidebar elif self.__shellPosition == "right": self.__shellParent = self.rightSidebar else: self.__shellParent = self.bottomSidebar from QScintilla.Shell import ShellAssembly self.shellAssembly = ShellAssembly( debugServer, self.viewmanager, self.project, True) self.shell = self.shellAssembly.shell() self.__shellParent.insertTab(0, self.shellAssembly, UI.PixmapCache.getIcon("shell"), self.tr("Shell")) #################################################### ## Set the start index of each side bar #################################################### self.leftSidebar.setCurrentIndex(0) self.rightSidebar.setCurrentIndex(0) self.bottomSidebar.setCurrentIndex(0) # create the central widget logging.debug("Creating central widget...") cw = self.centralWidget() # save the current central widget self.leftSplitter = QSplitter(Qt.Horizontal) self.rightSplitter = QSplitter(Qt.Horizontal) self.verticalSplitter = QSplitter(Qt.Vertical) self.verticalSplitter.addWidget(cw) self.verticalSplitter.addWidget(self.bottomSidebar) self.rightSplitter.addWidget(self.verticalSplitter) self.rightSplitter.addWidget(self.rightSidebar) self.leftSplitter.addWidget(self.leftSidebar) self.leftSplitter.addWidget(self.rightSplitter) self.setCentralWidget(self.leftSplitter) self.leftSidebar.setSplitter(self.leftSplitter) self.rightSidebar.setSplitter(self.rightSplitter) self.bottomSidebar.setSplitter(self.verticalSplitter) def addSideWidget(self, side, widget, icon, label): """ Public method to add a widget to the sides. @param side side to add the widget to @type int (one of UserInterface.LeftSide, UserInterface.BottomSide, UserInterface.RightSide) @param widget reference to the widget to add @type QWidget @param icon icon to be used @type QIcon @param label label text to be shown @type str """ if side in [UserInterface.LeftSide, UserInterface.BottomSide, UserInterface.RightSide]: if self.__layoutType == "Toolboxes": if side == UserInterface.LeftSide: self.lToolbox.addItem(widget, icon, label) elif side == UserInterface.BottomSide: self.hToolbox.addItem(widget, icon, label) elif side == UserInterface.RightSide: self.rToolbox.addItem(widget, icon, label) elif self.__layoutType == "Sidebars": if side == UserInterface.LeftSide: self.leftSidebar.addTab(widget, icon, label) elif side == UserInterface.BottomSide: self.bottomSidebar.addTab(widget, icon, label) elif side == UserInterface.RightSide: self.rightSidebar.addTab(widget, icon, label) def removeSideWidget(self, widget): """ Public method to remove a widget added using addSideWidget(). @param widget reference to the widget to remove @type QWidget """ if self.__layoutType == "Toolboxes": for container in [self.lToolbox, self.hToolbox, self.rToolbox]: index = container.indexOf(widget) if index != -1: container.removeItem(index) elif self.__layoutType == "Sidebars": for container in [self.leftSidebar, self.bottomSidebar, self.rightSidebar]: index = container.indexOf(widget) if index != -1: container.removeTab(index) def showSideWidget(self, widget): """ Public method to show a specific widget placed in the side widgets. @param widget reference to the widget to be shown @type QWidget """ if self.__layoutType == "Toolboxes": for dock in [self.lToolboxDock, self.hToolboxDock, self.rToolboxDock]: container = dock.widget() index = container.indexOf(widget) if index != -1: dock.show() container.setCurrentIndex(index) dock.raise_() elif self.__layoutType == "Sidebars": for container in [self.leftSidebar, self.bottomSidebar, self.rightSidebar]: index = container.indexOf(widget) if index != -1: container.show() container.setCurrentIndex(index) container.raise_() if container.isAutoHiding(): container.setFocus() def showLogViewer(self): """ Public method to show the Log-Viewer. """ if Preferences.getUI("LogViewerAutoRaise"): if self.__layoutType == "Toolboxes": self.hToolboxDock.show() self.hToolbox.setCurrentWidget(self.logViewer) self.hToolboxDock.raise_() elif self.__layoutType == "Sidebars": self.bottomSidebar.show() self.bottomSidebar.setCurrentWidget(self.logViewer) self.bottomSidebar.raise_() if self.bottomSidebar.isAutoHiding(): self.bottomSidebar.setFocus() def __openOnStartup(self, startupType=None): """ Private method to open the last file, project or multiproject. @param startupType type of startup requested (string, one of "Nothing", "File", "Project", "MultiProject" or "Session") """ startupTypeMapping = { "Nothing": 0, "File": 1, "Project": 2, "MultiProject": 3, "Session": 4, } if startupType is None: startup = Preferences.getUI("OpenOnStartup") else: try: startup = startupTypeMapping[startupType] except KeyError: startup = Preferences.getUI("OpenOnStartup") if startup == 0: # open nothing pass elif startup == 1: # open last file recent = self.viewmanager.getMostRecent() if recent is not None: self.viewmanager.openFiles(recent) elif startup == 2: # open last project recent = self.project.getMostRecent() if recent is not None: self.project.openProject(recent) elif startup == 3: # open last multiproject recent = self.multiProject.getMostRecent() if recent is not None: self.multiProject.openMultiProject(recent) elif startup == 4: # open from session file self.__readSession() def processArgs(self, args): """ Public method to process the command line args passed to the UI. @param args list of files to open<br /> The args are processed one at a time. All arguments after a '--' option are considered debug arguments to the program for the debugger. All files named before the '--' option are opened in a text editor, unless the argument ends in .e4p, then it is opened as a project file. If it ends in .e4m or .e5m, it is opened as a multiproject. """ # check and optionally read a crash session and ignore any arguments if self.__readCrashSession(): return # no args, return if args is None: if not self.__noOpenAtStartup: self.__openOnStartup() return opens = 0 # holds space delimited list of command args, if any argsStr = None # flag indicating '--' options was found ddseen = False if Utilities.isWindowsPlatform(): argChars = ['-', '/'] else: argChars = ['-'] for arg in args: # handle a request to start with last session if arg == '--start-file': self.__openOnStartup("File") # ignore all further arguments return elif arg == '--start-multi': self.__openOnStartup("MultiProject") # ignore all further arguments return elif arg == '--start-project': self.__openOnStartup("Project") # ignore all further arguments return elif arg == '--start-session': self.__openOnStartup("Session") # ignore all further arguments return if arg == '--' and not ddseen: ddseen = True continue if arg[0] in argChars or ddseen: if argsStr is None: argsStr = arg else: argsStr = "{0} {1}".format(argsStr, arg) continue try: ext = os.path.splitext(arg)[1] ext = os.path.normcase(ext) except IndexError: ext = "" if ext in ['.e4p']: self.project.openProject(arg) opens += 1 elif ext in ['.e4m', '.e5m']: self.multiProject.openMultiProject(arg) opens += 1 else: self.viewmanager.openFiles(arg) opens += 1 # store away any args we had if argsStr is not None: self.debuggerUI.setArgvHistory(argsStr) if opens == 0: # no files, project or multiproject was given if not self.__noOpenAtStartup: self.__openOnStartup() def processInstallInfoFile(self): """ Public method to process the file containing installation information. """ import Globals installInfoFile = Globals.getInstallInfoFilePath() if not os.path.exists(installInfoFile): filename = os.path.join(getConfig("ericDir"), "eric6install.json") if os.path.exists(filename): # eric was installed via the install.py script shutil.copy2(filename, installInfoFile) else: filename = os.path.join(getConfig("ericDir"), "eric6installpip.json") if os.path.exists(filename): # eric was installed via pip (i.e. eric-ide) try: installDateTime = datetime.datetime.now(tz=None) with open(filename, "r") as infoFile: installInfo = json.load(infoFile) installInfo["guessed"] = True installInfo["eric"] = getConfig("ericDir") installInfo["virtualenv"] = ( installInfo["eric"].startswith( os.path.expanduser("~")) ) if installInfo["virtualenv"]: installInfo["user"] = getpass.getuser() installInfo["exe"] = sys.executable installInfo["installed"] = True installInfo["installed_on"] = installDateTime.strftime( "%Y-%m-%d %H:%M:%S") installInfo["sudo"] = not os.access( installInfo["eric"], os.W_OK) with open(installInfoFile, "w") as infoFile: json.dump(installInfo, infoFile, indent=2) except OSError: # ignore this pass else: changed = False with open(installInfoFile, "r") as infoFile: installInfo = json.load(infoFile) # 1. adapt stored file to latest format if "install_cwd" not in installInfo: installInfo["install_cwd"] = "" installInfo["install_cwd_edited"] = False changed = True if "installed_on" not in installInfo: installInfo["installed_on"] = "" changed = True # 2. merge new data into stored file filename = os.path.join(getConfig("ericDir"), "eric6install.json") if os.path.exists(filename): # eric was updated via the install.py script if ( os.path.getmtime(filename) > os.path.getmtime(installInfoFile) ): if not installInfo["edited"]: shutil.copy2(filename, installInfoFile) else: with open(filename, "r") as infoFile: installInfo2 = json.load(infoFile) if not installInfo["install_cwd_edited"]: installInfo2["install_cwd"] = installInfo[ "install_cwd"] if not installInfo["exe_edited"]: installInfo2["exe"] = installInfo["exe"] if not installInfo["argv_edited"]: installInfo2["argv"] = installInfo["argv"] if not installInfo["eric_edited"]: installInfo2["eric"] = installInfo["eric"] installInfo = installInfo2 changed = True else: filename = os.path.join(getConfig("ericDir"), "eric6installpip.json") if os.path.exists(filename): # eric was updated via pip (i.e. eric-ide) # just update the installation date and time installDateTime = datetime.datetime.now(tz=None) installInfo["installed_on"] = installDateTime.strftime( "%Y-%m-%d %H:%M:%S") changed = True if changed: with open(installInfoFile, "w") as infoFile: json.dump(installInfo, infoFile, indent=2) def __createDockWindow(self, name): """ Private method to create a dock window with common properties. @param name object name of the new dock window (string) @return the generated dock window (QDockWindow) """ dock = QDockWidget() dock.setObjectName(name) dock.setFeatures( QDockWidget.DockWidgetFeatures(QDockWidget.AllDockWidgetFeatures)) return dock def __setupDockWindow(self, dock, where, widget, caption): """ Private method to configure the dock window created with __createDockWindow(). @param dock the dock window (QDockWindow) @param where dock area to be docked to (Qt.DockWidgetArea) @param widget widget to be shown in the dock window (QWidget) @param caption caption of the dock window (string) """ if caption is None: caption = "" self.addDockWidget(where, dock) dock.setWidget(widget) dock.setWindowTitle(caption) dock.show() def __setWindowCaption(self, editor=None, project=None): """ Private method to set the caption of the Main Window. @param editor filename to be displayed (string) @param project project name to be displayed (string) """ if editor is not None and self.captionShowsFilename: self.capEditor = Utilities.compactPath(editor, self.maxFilePathLen) if project is not None: self.capProject = project if self.passiveMode: if not self.capProject and not self.capEditor: self.setWindowTitle( self.tr("{0} - Passive Mode").format(Program)) elif self.capProject and not self.capEditor: self.setWindowTitle( self.tr("{0} - {1} - Passive Mode") .format(self.capProject, Program)) elif not self.capProject and self.capEditor: self.setWindowTitle( self.tr("{0} - {1} - Passive Mode") .format(self.capEditor, Program)) else: self.setWindowTitle( self.tr("{0} - {1} - {2} - Passive Mode") .format(self.capProject, self.capEditor, Program)) else: if not self.capProject and not self.capEditor: self.setWindowTitle(Program) elif self.capProject and not self.capEditor: self.setWindowTitle( "{0} - {1}".format(self.capProject, Program)) elif not self.capProject and self.capEditor: self.setWindowTitle( "{0} - {1}".format(self.capEditor, Program)) else: self.setWindowTitle("{0} - {1} - {2}".format( self.capProject, self.capEditor, Program)) def __initActions(self): """ Private method to define the user interface actions. """ self.actions = [] self.wizardsActions = [] self.exitAct = E5Action( self.tr('Quit'), UI.PixmapCache.getIcon("exit"), self.tr('&Quit'), QKeySequence(self.tr("Ctrl+Q", "File|Quit")), 0, self, 'quit') self.exitAct.setStatusTip(self.tr('Quit the IDE')) self.exitAct.setWhatsThis(self.tr( """<b>Quit the IDE</b>""" """<p>This quits the IDE. Any unsaved changes may be saved""" """ first. Any Python program being debugged will be stopped""" """ and the preferences will be written to disc.</p>""" )) self.exitAct.triggered.connect(self.__quit) self.exitAct.setMenuRole(QAction.QuitRole) self.actions.append(self.exitAct) self.restartAct = E5Action( self.tr('Restart'), UI.PixmapCache.getIcon("restart"), self.tr('Restart'), QKeySequence(self.tr("Ctrl+Shift+Q", "File|Quit")), 0, self, 'restart_eric') self.restartAct.setStatusTip(self.tr('Restart the IDE')) self.restartAct.setWhatsThis(self.tr( """<b>Restart the IDE</b>""" """<p>This restarts the IDE. Any unsaved changes may be saved""" """ first. Any Python program being debugged will be stopped""" """ and the preferences will be written to disc.</p>""" )) self.restartAct.triggered.connect(self.__restart) self.actions.append(self.restartAct) self.saveSessionAct = E5Action( self.tr('Save session'), self.tr('Save session...'), 0, 0, self, 'save_session_to_file') self.saveSessionAct.setStatusTip(self.tr('Save session')) self.saveSessionAct.setWhatsThis(self.tr( """<b>Save session...</b>""" """<p>This saves the current session to disk. A dialog is""" """ opened to select the file name.</p>""" )) self.saveSessionAct.triggered.connect(self.__saveSessionToFile) self.actions.append(self.saveSessionAct) self.loadSessionAct = E5Action( self.tr('Load session'), self.tr('Load session...'), 0, 0, self, 'load_session_from_file') self.loadSessionAct.setStatusTip(self.tr('Load session')) self.loadSessionAct.setWhatsThis(self.tr( """<b>Load session...</b>""" """<p>This loads a session saved to disk previously. A dialog is""" """ opened to select the file name.</p>""" )) self.loadSessionAct.triggered.connect(self.__loadSessionFromFile) self.actions.append(self.loadSessionAct) self.newWindowAct = E5Action( self.tr('New Window'), UI.PixmapCache.getIcon("newWindow"), self.tr('New &Window'), QKeySequence(self.tr("Ctrl+Shift+N", "File|New Window")), 0, self, 'new_window') self.newWindowAct.setStatusTip(self.tr( 'Open a new eric6 instance')) self.newWindowAct.setWhatsThis(self.tr( """<b>New Window</b>""" """<p>This opens a new instance of the eric6 IDE.</p>""" )) self.newWindowAct.triggered.connect(self.__newWindow) self.actions.append(self.newWindowAct) self.newWindowAct.setEnabled( not Preferences.getUI("SingleApplicationMode")) self.viewProfileActGrp = createActionGroup(self, "viewprofiles", True) self.setEditProfileAct = E5Action( self.tr('Edit Profile'), UI.PixmapCache.getIcon("viewProfileEdit"), self.tr('Edit Profile'), 0, 0, self.viewProfileActGrp, 'edit_profile', True) self.setEditProfileAct.setStatusTip(self.tr( 'Activate the edit view profile')) self.setEditProfileAct.setWhatsThis(self.tr( """<b>Edit Profile</b>""" """<p>Activate the "Edit View Profile". Windows being shown,""" """ if this profile is active, may be configured with the""" """ "View Profile Configuration" dialog.</p>""" )) self.setEditProfileAct.triggered.connect(self.__setEditProfile) self.actions.append(self.setEditProfileAct) self.setDebugProfileAct = E5Action( self.tr('Debug Profile'), UI.PixmapCache.getIcon("viewProfileDebug"), self.tr('Debug Profile'), 0, 0, self.viewProfileActGrp, 'debug_profile', True) self.setDebugProfileAct.setStatusTip( self.tr('Activate the debug view profile')) self.setDebugProfileAct.setWhatsThis(self.tr( """<b>Debug Profile</b>""" """<p>Activate the "Debug View Profile". Windows being shown,""" """ if this profile is active, may be configured with the""" """ "View Profile Configuration" dialog.</p>""" )) self.setDebugProfileAct.triggered.connect(self.setDebugProfile) self.actions.append(self.setDebugProfileAct) self.pbActivateAct = E5Action( self.tr('Project-Viewer'), self.tr('&Project-Viewer'), QKeySequence(self.tr("Alt+Shift+P")), 0, self, 'project_viewer_activate') self.pbActivateAct.setStatusTip(self.tr( "Switch the input focus to the Project-Viewer window.")) self.pbActivateAct.setWhatsThis(self.tr( """<b>Activate Project-Viewer</b>""" """<p>This switches the input focus to the Project-Viewer""" """ window.</p>""" )) self.pbActivateAct.triggered.connect(self.__activateProjectBrowser) self.actions.append(self.pbActivateAct) self.addAction(self.pbActivateAct) self.mpbActivateAct = E5Action( self.tr('Multiproject-Viewer'), self.tr('&Multiproject-Viewer'), QKeySequence(self.tr("Alt+Shift+M")), 0, self, 'multi_project_viewer_activate') self.mpbActivateAct.setStatusTip(self.tr( "Switch the input focus to the Multiproject-Viewer window.")) self.mpbActivateAct.setWhatsThis(self.tr( """<b>Activate Multiproject-Viewer</b>""" """<p>This switches the input focus to the Multiproject-Viewer""" """ window.</p>""" )) self.mpbActivateAct.triggered.connect( self.__activateMultiProjectBrowser) self.actions.append(self.mpbActivateAct) self.addAction(self.mpbActivateAct) self.debugViewerActivateAct = E5Action( self.tr('Debug-Viewer'), self.tr('&Debug-Viewer'), QKeySequence(self.tr("Alt+Shift+D")), 0, self, 'debug_viewer_activate') self.debugViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Debug-Viewer window.")) self.debugViewerActivateAct.setWhatsThis(self.tr( """<b>Activate Debug-Viewer</b>""" """<p>This switches the input focus to the Debug-Viewer""" """ window.</p>""" )) self.debugViewerActivateAct.triggered.connect( self.activateDebugViewer) self.actions.append(self.debugViewerActivateAct) self.addAction(self.debugViewerActivateAct) self.shellActivateAct = E5Action( self.tr('Shell'), self.tr('&Shell'), QKeySequence(self.tr("Alt+Shift+S")), 0, self, 'interpreter_shell_activate') self.shellActivateAct.setStatusTip(self.tr( "Switch the input focus to the Shell window.")) self.shellActivateAct.setWhatsThis(self.tr( """<b>Activate Shell</b>""" """<p>This switches the input focus to the Shell window.</p>""" )) self.shellActivateAct.triggered.connect(self.__activateShell) self.actions.append(self.shellActivateAct) self.addAction(self.shellActivateAct) if self.browser is not None: self.browserActivateAct = E5Action( self.tr('File-Browser'), self.tr('&File-Browser'), QKeySequence(self.tr("Alt+Shift+F")), 0, self, 'file_browser_activate') self.browserActivateAct.setStatusTip(self.tr( "Switch the input focus to the File-Browser window.")) self.browserActivateAct.setWhatsThis(self.tr( """<b>Activate File-Browser</b>""" """<p>This switches the input focus to the File-Browser""" """ window.</p>""" )) self.browserActivateAct.triggered.connect(self.__activateBrowser) self.actions.append(self.browserActivateAct) self.addAction(self.browserActivateAct) self.logViewerActivateAct = E5Action( self.tr('Log-Viewer'), self.tr('Lo&g-Viewer'), QKeySequence(self.tr("Alt+Shift+G")), 0, self, 'log_viewer_activate') self.logViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Log-Viewer window.")) self.logViewerActivateAct.setWhatsThis(self.tr( """<b>Activate Log-Viewer</b>""" """<p>This switches the input focus to the Log-Viewer""" """ window.</p>""" )) self.logViewerActivateAct.triggered.connect( self.__activateLogViewer) self.actions.append(self.logViewerActivateAct) self.addAction(self.logViewerActivateAct) self.taskViewerActivateAct = E5Action( self.tr('Task-Viewer'), self.tr('&Task-Viewer'), QKeySequence(self.tr("Alt+Shift+T")), 0, self, 'task_viewer_activate') self.taskViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Task-Viewer window.")) self.taskViewerActivateAct.setWhatsThis(self.tr( """<b>Activate Task-Viewer</b>""" """<p>This switches the input focus to the Task-Viewer""" """ window.</p>""" )) self.taskViewerActivateAct.triggered.connect( self.__activateTaskViewer) self.actions.append(self.taskViewerActivateAct) self.addAction(self.taskViewerActivateAct) if self.templateViewer is not None: self.templateViewerActivateAct = E5Action( self.tr('Template-Viewer'), self.tr('Templ&ate-Viewer'), QKeySequence(self.tr("Alt+Shift+A")), 0, self, 'template_viewer_activate') self.templateViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Template-Viewer window.")) self.templateViewerActivateAct.setWhatsThis(self.tr( """<b>Activate Template-Viewer</b>""" """<p>This switches the input focus to the Template-Viewer""" """ window.</p>""" )) self.templateViewerActivateAct.triggered.connect( self.__activateTemplateViewer) self.actions.append(self.templateViewerActivateAct) self.addAction(self.templateViewerActivateAct) self.ltAct = E5Action( self.tr('Left Toolbox'), self.tr('&Left Toolbox'), 0, 0, self, 'vertical_toolbox', True) self.ltAct.setStatusTip(self.tr('Toggle the Left Toolbox window')) self.ltAct.setWhatsThis(self.tr( """<b>Toggle the Left Toolbox window</b>""" """<p>If the Left Toolbox window is hidden then display it.""" """ If it is displayed then close it.</p>""" )) self.ltAct.triggered.connect(self.__toggleLeftToolbox) self.actions.append(self.ltAct) self.rtAct = E5Action( self.tr('Right Toolbox'), self.tr('&Right Toolbox'), 0, 0, self, 'vertical_toolbox', True) self.rtAct.setStatusTip(self.tr('Toggle the Right Toolbox window')) self.rtAct.setWhatsThis(self.tr( """<b>Toggle the Right Toolbox window</b>""" """<p>If the Right Toolbox window is hidden then display it.""" """ If it is displayed then close it.</p>""" )) self.rtAct.triggered.connect(self.__toggleRightToolbox) self.actions.append(self.rtAct) self.htAct = E5Action( self.tr('Horizontal Toolbox'), self.tr('&Horizontal Toolbox'), 0, 0, self, 'horizontal_toolbox', True) self.htAct.setStatusTip(self.tr( 'Toggle the Horizontal Toolbox window')) self.htAct.setWhatsThis(self.tr( """<b>Toggle the Horizontal Toolbox window</b>""" """<p>If the Horizontal Toolbox window is hidden then display""" """ it. If it is displayed then close it.</p>""" )) self.htAct.triggered.connect(self.__toggleHorizontalToolbox) self.actions.append(self.htAct) self.lsbAct = E5Action( self.tr('Left Sidebar'), self.tr('&Left Sidebar'), 0, 0, self, 'left_sidebar', True) self.lsbAct.setStatusTip(self.tr('Toggle the left sidebar window')) self.lsbAct.setWhatsThis(self.tr( """<b>Toggle the left sidebar window</b>""" """<p>If the left sidebar window is hidden then display it.""" """ If it is displayed then close it.</p>""" )) self.lsbAct.triggered.connect(self.__toggleLeftSidebar) self.actions.append(self.lsbAct) self.rsbAct = E5Action( self.tr('Right Sidebar'), self.tr('&Right Sidebar'), 0, 0, self, 'right_sidebar', True) self.rsbAct.setStatusTip(self.tr( 'Toggle the right sidebar window')) self.rsbAct.setWhatsThis(self.tr( """<b>Toggle the right sidebar window</b>""" """<p>If the right sidebar window is hidden then display it.""" """ If it is displayed then close it.</p>""" )) self.rsbAct.triggered.connect(self.__toggleRightSidebar) self.actions.append(self.rsbAct) self.bsbAct = E5Action( self.tr('Bottom Sidebar'), self.tr('&Bottom Sidebar'), 0, 0, self, 'bottom_sidebar', True) self.bsbAct.setStatusTip(self.tr( 'Toggle the bottom sidebar window')) self.bsbAct.setWhatsThis(self.tr( """<b>Toggle the bottom sidebar window</b>""" """<p>If the bottom sidebar window is hidden then display it.""" """ If it is displayed then close it.</p>""" )) self.bsbAct.triggered.connect(self.__toggleBottomSidebar) self.actions.append(self.bsbAct) if self.cooperation is not None: self.cooperationViewerActivateAct = E5Action( self.tr('Cooperation-Viewer'), self.tr('Co&operation-Viewer'), QKeySequence(self.tr("Alt+Shift+O")), 0, self, 'cooperation_viewer_activate') self.cooperationViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Cooperation-Viewer window.")) self.cooperationViewerActivateAct.setWhatsThis(self.tr( """<b>Activate Cooperation-Viewer</b>""" """<p>This switches the input focus to the""" """ Cooperation-Viewer window.</p>""" )) self.cooperationViewerActivateAct.triggered.connect( self.activateCooperationViewer) self.actions.append(self.cooperationViewerActivateAct) self.addAction(self.cooperationViewerActivateAct) if self.irc is not None: self.ircActivateAct = E5Action( self.tr('IRC'), self.tr('&IRC'), QKeySequence(self.tr("Ctrl+Alt+Shift+I")), 0, self, 'irc_widget_activate') self.ircActivateAct.setStatusTip(self.tr( "Switch the input focus to the IRC window.")) self.ircActivateAct.setWhatsThis(self.tr( """<b>Activate IRC</b>""" """<p>This switches the input focus to the IRC window.</p>""" )) self.ircActivateAct.triggered.connect( self.__activateIRC) self.actions.append(self.ircActivateAct) self.addAction(self.ircActivateAct) if self.symbolsViewer is not None: self.symbolsViewerActivateAct = E5Action( self.tr('Symbols-Viewer'), self.tr('S&ymbols-Viewer'), QKeySequence(self.tr("Alt+Shift+Y")), 0, self, 'symbols_viewer_activate') self.symbolsViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Symbols-Viewer window.")) self.symbolsViewerActivateAct.setWhatsThis(self.tr( """<b>Activate Symbols-Viewer</b>""" """<p>This switches the input focus to the Symbols-Viewer""" """ window.</p>""" )) self.symbolsViewerActivateAct.triggered.connect( self.__activateSymbolsViewer) self.actions.append(self.symbolsViewerActivateAct) self.addAction(self.symbolsViewerActivateAct) if self.numbersViewer is not None: self.numbersViewerActivateAct = E5Action( self.tr('Numbers-Viewer'), self.tr('Num&bers-Viewer'), QKeySequence(self.tr("Alt+Shift+B")), 0, self, 'numbers_viewer_activate') self.numbersViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Numbers-Viewer window.")) self.numbersViewerActivateAct.setWhatsThis(self.tr( """<b>Activate Numbers-Viewer</b>""" """<p>This switches the input focus to the Numbers-Viewer""" """ window.</p>""" )) self.numbersViewerActivateAct.triggered.connect( self.__activateNumbersViewer) self.actions.append(self.numbersViewerActivateAct) self.addAction(self.numbersViewerActivateAct) if self.codeDocumentationViewer is not None: self.codeDocumentationViewerActivateAct = E5Action( self.tr('Code Documentation Viewer'), self.tr('Code Documentation Viewer'), QKeySequence(self.tr("Ctrl+Alt+Shift+D")), 0, self, 'code_documentation_viewer_activate') self.codeDocumentationViewerActivateAct.setStatusTip(self.tr( "Switch the input focus to the Code Documentation Viewer" " window.")) self.codeDocumentationViewerActivateAct.setWhatsThis(self.tr( """<b>Code Documentation Viewer</b>""" """<p>This switches the input focus to the Code""" """ Documentation Viewer window.</p>""" )) self.codeDocumentationViewerActivateAct.triggered.connect( self.activateCodeDocumentationViewer) self.actions.append(self.codeDocumentationViewerActivateAct) self.addAction(self.codeDocumentationViewerActivateAct) if self.pipWidget is not None: self.pipWidgetActivateAct = E5Action( self.tr('PyPI'), self.tr('PyPI'), QKeySequence(self.tr("Ctrl+Alt+Shift+P")), 0, self, 'pip_widget_activate') self.pipWidgetActivateAct.setStatusTip(self.tr( "Switch the input focus to the PyPI window.")) self.pipWidgetActivateAct.setWhatsThis(self.tr( """<b>PyPI</b>""" """<p>This switches the input focus to the PyPI window.</p>""" )) self.pipWidgetActivateAct.triggered.connect( self.__activatePipWidget) self.actions.append(self.pipWidgetActivateAct) self.addAction(self.pipWidgetActivateAct) if self.condaWidget is not None: self.condaWidgetActivateAct = E5Action( self.tr('Conda'), self.tr('Conda'), QKeySequence(self.tr("Ctrl+Alt+Shift+C")), 0, self, 'conda_widget_activate') self.condaWidgetActivateAct.setStatusTip(self.tr( "Switch the input focus to the Conda window.")) self.condaWidgetActivateAct.setWhatsThis(self.tr( """<b>Conda</b>""" """<p>This switches the input focus to the Conda window.</p>""" )) self.condaWidgetActivateAct.triggered.connect( self.__activateCondaWidget) self.actions.append(self.condaWidgetActivateAct) self.addAction(self.condaWidgetActivateAct) if self.microPythonWidget is not None: self.microPythonWidgetActivateAct = E5Action( self.tr('MicroPython'), self.tr('MicroPython'), QKeySequence(self.tr("Ctrl+Alt+Shift+M")), 0, self, 'micropython_widget_activate') self.microPythonWidgetActivateAct.setStatusTip(self.tr( "Switch the input focus to the MicroPython window.")) self.microPythonWidgetActivateAct.setWhatsThis(self.tr( """<b>MicroPython</b>""" """<p>This switches the input focus to the MicroPython""" """ window.</p>""" )) self.microPythonWidgetActivateAct.triggered.connect( self.__activateMicroPython) self.actions.append(self.microPythonWidgetActivateAct) self.addAction(self.microPythonWidgetActivateAct) self.whatsThisAct = E5Action( self.tr('What\'s This?'), UI.PixmapCache.getIcon("whatsThis"), self.tr('&What\'s This?'), QKeySequence(self.tr("Shift+F1")), 0, self, 'whatsThis') self.whatsThisAct.setStatusTip(self.tr('Context sensitive help')) self.whatsThisAct.setWhatsThis(self.tr( """<b>Display context sensitive help</b>""" """<p>In What's This? mode, the mouse cursor shows an arrow with""" """ a question mark, and you can click on the interface elements""" """ to get a short description of what they do and how to use""" """ them. In dialogs, this feature can be accessed using the""" """ context help button in the titlebar.</p>""" )) self.whatsThisAct.triggered.connect(self.__whatsThis) self.actions.append(self.whatsThisAct) self.helpviewerAct = E5Action( self.tr('Helpviewer'), UI.PixmapCache.getIcon("help"), self.tr('&Helpviewer...'), QKeySequence(self.tr("F1")), 0, self, 'helpviewer') self.helpviewerAct.setStatusTip(self.tr( 'Open the helpviewer window')) self.helpviewerAct.setWhatsThis(self.tr( """<b>Helpviewer</b>""" """<p>Display the eric6 web browser. This window will show""" """ HTML help files and help from Qt help collections. It""" """ has the capability to navigate to links, set bookmarks,""" """ print the displayed help and some more features. You may""" """ use it to browse the internet as well</p><p>If called""" """ with a word selected, this word is search in the Qt help""" """ collection.</p>""" )) self.helpviewerAct.triggered.connect(self.__helpViewer) self.actions.append(self.helpviewerAct) self.__initQtDocActions() self.__initPythonDocActions() self.__initEricDocAction() self.__initPySideDocActions() self.versionAct = E5Action( self.tr('Show Versions'), self.tr('Show &Versions'), 0, 0, self, 'show_versions') self.versionAct.setStatusTip(self.tr( 'Display version information')) self.versionAct.setWhatsThis(self.tr( """<b>Show Versions</b>""" """<p>Display version information.</p>""" )) self.versionAct.triggered.connect(self.__showVersions) self.actions.append(self.versionAct) self.checkUpdateAct = E5Action( self.tr('Check for Updates'), self.tr('Check for &Updates...'), 0, 0, self, 'check_updates') self.checkUpdateAct.setStatusTip(self.tr('Check for Updates')) self.checkUpdateAct.setWhatsThis(self.tr( """<b>Check for Updates...</b>""" """<p>Checks the internet for updates of eric6.</p>""" )) self.checkUpdateAct.triggered.connect(self.performVersionCheck) self.actions.append(self.checkUpdateAct) self.showVersionsAct = E5Action( self.tr('Show downloadable versions'), self.tr('Show &downloadable versions...'), 0, 0, self, 'show_downloadable_versions') self.showVersionsAct.setStatusTip( self.tr('Show the versions available for download')) self.showVersionsAct.setWhatsThis(self.tr( """<b>Show downloadable versions...</b>""" """<p>Shows the eric6 versions available for download """ """from the internet.</p>""" )) self.showVersionsAct.triggered.connect( self.showAvailableVersionsInfo) self.actions.append(self.showVersionsAct) self.showErrorLogAct = E5Action( self.tr('Show Error Log'), self.tr('Show Error &Log...'), 0, 0, self, 'show_error_log') self.showErrorLogAct.setStatusTip(self.tr('Show Error Log')) self.showErrorLogAct.setWhatsThis(self.tr( """<b>Show Error Log...</b>""" """<p>Opens a dialog showing the most recent error log.</p>""" )) self.showErrorLogAct.triggered.connect(self.__showErrorLog) self.actions.append(self.showErrorLogAct) self.showInstallInfoAct = E5Action( self.tr('Show Install Info'), self.tr('Show Install &Info...'), 0, 0, self, 'show_install_info') self.showInstallInfoAct.setStatusTip(self.tr( 'Show Installation Information')) self.showInstallInfoAct.setWhatsThis(self.tr( """<b>Show Install Info...</b>""" """<p>Opens a dialog showing some information about the""" """ installation process.</p>""" )) self.showInstallInfoAct.triggered.connect(self.__showInstallInfo) self.actions.append(self.showInstallInfoAct) self.reportBugAct = E5Action( self.tr('Report Bug'), self.tr('Report &Bug...'), 0, 0, self, 'report_bug') self.reportBugAct.setStatusTip(self.tr('Report a bug')) self.reportBugAct.setWhatsThis(self.tr( """<b>Report Bug...</b>""" """<p>Opens a dialog to report a bug.</p>""" )) self.reportBugAct.triggered.connect(self.__reportBug) self.actions.append(self.reportBugAct) self.requestFeatureAct = E5Action( self.tr('Request Feature'), self.tr('Request &Feature...'), 0, 0, self, 'request_feature') self.requestFeatureAct.setStatusTip(self.tr( 'Send a feature request')) self.requestFeatureAct.setWhatsThis(self.tr( """<b>Request Feature...</b>""" """<p>Opens a dialog to send a feature request.</p>""" )) self.requestFeatureAct.triggered.connect(self.__requestFeature) self.actions.append(self.requestFeatureAct) self.utActGrp = createActionGroup(self) self.utDialogAct = E5Action( self.tr('Unittest'), UI.PixmapCache.getIcon("unittest"), self.tr('&Unittest...'), 0, 0, self.utActGrp, 'unittest') self.utDialogAct.setStatusTip(self.tr('Start unittest dialog')) self.utDialogAct.setWhatsThis(self.tr( """<b>Unittest</b>""" """<p>Perform unit tests. The dialog gives you the""" """ ability to select and run a unittest suite.</p>""" )) self.utDialogAct.triggered.connect(self.__unittest) self.actions.append(self.utDialogAct) self.utRestartAct = E5Action( self.tr('Unittest Restart'), UI.PixmapCache.getIcon("unittestRestart"), self.tr('&Restart Unittest...'), 0, 0, self.utActGrp, 'unittest_restart') self.utRestartAct.setStatusTip(self.tr('Restart last unittest')) self.utRestartAct.setWhatsThis(self.tr( """<b>Restart Unittest</b>""" """<p>Restart the unittest performed last.</p>""" )) self.utRestartAct.triggered.connect(self.__unittestRestart) self.utRestartAct.setEnabled(False) self.actions.append(self.utRestartAct) self.utRerunFailedAct = E5Action( self.tr('Unittest Rerun Failed'), UI.PixmapCache.getIcon("unittestRerunFailed"), self.tr('Rerun Failed Tests...'), 0, 0, self.utActGrp, 'unittest_rerun_failed') self.utRerunFailedAct.setStatusTip(self.tr( 'Rerun failed tests of the last run')) self.utRerunFailedAct.setWhatsThis(self.tr( """<b>Rerun Failed Tests</b>""" """<p>Rerun all tests that failed during the last unittest""" """ run.</p>""" )) self.utRerunFailedAct.triggered.connect(self.__unittestRerunFailed) self.utRerunFailedAct.setEnabled(False) self.actions.append(self.utRerunFailedAct) self.utScriptAct = E5Action( self.tr('Unittest Script'), UI.PixmapCache.getIcon("unittestScript"), self.tr('Unittest &Script...'), 0, 0, self.utActGrp, 'unittest_script') self.utScriptAct.setStatusTip(self.tr( 'Run unittest with current script')) self.utScriptAct.setWhatsThis(self.tr( """<b>Unittest Script</b>""" """<p>Run unittest with current script.</p>""" )) self.utScriptAct.triggered.connect(self.__unittestScript) self.utScriptAct.setEnabled(False) self.actions.append(self.utScriptAct) self.utProjectAct = E5Action( self.tr('Unittest Project'), UI.PixmapCache.getIcon("unittestProject"), self.tr('Unittest &Project...'), 0, 0, self.utActGrp, 'unittest_project') self.utProjectAct.setStatusTip(self.tr( 'Run unittest with current project')) self.utProjectAct.setWhatsThis(self.tr( """<b>Unittest Project</b>""" """<p>Run unittest with current project.</p>""" )) self.utProjectAct.triggered.connect(self.__unittestProject) self.utProjectAct.setEnabled(False) self.actions.append(self.utProjectAct) # check for Qt5 designer and linguist if Utilities.isWindowsPlatform(): designerExe = os.path.join( Utilities.getQtBinariesPath(), "{0}.exe".format(Utilities.generateQtToolName("designer"))) elif Utilities.isMacPlatform(): designerExe = Utilities.getQtMacBundle("designer") else: designerExe = os.path.join( Utilities.getQtBinariesPath(), Utilities.generateQtToolName("designer")) if os.path.exists(designerExe): self.designer4Act = E5Action( self.tr('Qt-Designer'), UI.PixmapCache.getIcon("designer4"), self.tr('Qt-&Designer...'), 0, 0, self, 'qt_designer4') self.designer4Act.setStatusTip(self.tr('Start Qt-Designer')) self.designer4Act.setWhatsThis(self.tr( """<b>Qt-Designer</b>""" """<p>Start Qt-Designer.</p>""" )) self.designer4Act.triggered.connect(self.__designer) self.actions.append(self.designer4Act) else: self.designer4Act = None if Utilities.isWindowsPlatform(): linguistExe = os.path.join( Utilities.getQtBinariesPath(), "{0}.exe".format(Utilities.generateQtToolName("linguist"))) elif Utilities.isMacPlatform(): linguistExe = Utilities.getQtMacBundle("linguist") else: linguistExe = os.path.join( Utilities.getQtBinariesPath(), Utilities.generateQtToolName("linguist")) if os.path.exists(linguistExe): self.linguist4Act = E5Action( self.tr('Qt-Linguist'), UI.PixmapCache.getIcon("linguist4"), self.tr('Qt-&Linguist...'), 0, 0, self, 'qt_linguist4') self.linguist4Act.setStatusTip(self.tr('Start Qt-Linguist')) self.linguist4Act.setWhatsThis(self.tr( """<b>Qt-Linguist</b>""" """<p>Start Qt-Linguist.</p>""" )) self.linguist4Act.triggered.connect(self.__linguist) self.actions.append(self.linguist4Act) else: self.linguist4Act = None self.uipreviewerAct = E5Action( self.tr('UI Previewer'), UI.PixmapCache.getIcon("uiPreviewer"), self.tr('&UI Previewer...'), 0, 0, self, 'ui_previewer') self.uipreviewerAct.setStatusTip(self.tr('Start the UI Previewer')) self.uipreviewerAct.setWhatsThis(self.tr( """<b>UI Previewer</b>""" """<p>Start the UI Previewer.</p>""" )) self.uipreviewerAct.triggered.connect(self.__UIPreviewer) self.actions.append(self.uipreviewerAct) self.trpreviewerAct = E5Action( self.tr('Translations Previewer'), UI.PixmapCache.getIcon("trPreviewer"), self.tr('&Translations Previewer...'), 0, 0, self, 'tr_previewer') self.trpreviewerAct.setStatusTip(self.tr( 'Start the Translations Previewer')) self.trpreviewerAct.setWhatsThis(self.tr( """<b>Translations Previewer</b>""" """<p>Start the Translations Previewer.</p>""" )) self.trpreviewerAct.triggered.connect(self.__TRPreviewer) self.actions.append(self.trpreviewerAct) self.diffAct = E5Action( self.tr('Compare Files'), UI.PixmapCache.getIcon("diffFiles"), self.tr('&Compare Files...'), 0, 0, self, 'diff_files') self.diffAct.setStatusTip(self.tr('Compare two files')) self.diffAct.setWhatsThis(self.tr( """<b>Compare Files</b>""" """<p>Open a dialog to compare two files.</p>""" )) self.diffAct.triggered.connect(self.__compareFiles) self.actions.append(self.diffAct) self.compareAct = E5Action( self.tr('Compare Files side by side'), UI.PixmapCache.getIcon("compareFiles"), self.tr('Compare &Files side by side...'), 0, 0, self, 'compare_files') self.compareAct.setStatusTip(self.tr('Compare two files')) self.compareAct.setWhatsThis(self.tr( """<b>Compare Files side by side</b>""" """<p>Open a dialog to compare two files and show the result""" """ side by side.</p>""" )) self.compareAct.triggered.connect(self.__compareFilesSbs) self.actions.append(self.compareAct) self.sqlBrowserAct = E5Action( self.tr('SQL Browser'), UI.PixmapCache.getIcon("sqlBrowser"), self.tr('SQL &Browser...'), 0, 0, self, 'sql_browser') self.sqlBrowserAct.setStatusTip(self.tr('Browse a SQL database')) self.sqlBrowserAct.setWhatsThis(self.tr( """<b>SQL Browser</b>""" """<p>Browse a SQL database.</p>""" )) self.sqlBrowserAct.triggered.connect(self.__sqlBrowser) self.actions.append(self.sqlBrowserAct) self.miniEditorAct = E5Action( self.tr('Mini Editor'), UI.PixmapCache.getIcon("editor"), self.tr('Mini &Editor...'), 0, 0, self, 'mini_editor') self.miniEditorAct.setStatusTip(self.tr('Mini Editor')) self.miniEditorAct.setWhatsThis(self.tr( """<b>Mini Editor</b>""" """<p>Open a dialog with a simplified editor.</p>""" )) self.miniEditorAct.triggered.connect(self.__openMiniEditor) self.actions.append(self.miniEditorAct) self.hexEditorAct = E5Action( self.tr('Hex Editor'), UI.PixmapCache.getIcon("hexEditor"), self.tr('&Hex Editor...'), 0, 0, self, 'hex_editor') self.hexEditorAct.setStatusTip(self.tr( 'Start the eric6 Hex Editor')) self.hexEditorAct.setWhatsThis(self.tr( """<b>Hex Editor</b>""" """<p>Starts the eric6 Hex Editor for viewing or editing""" """ binary files.</p>""" )) self.hexEditorAct.triggered.connect(self.__openHexEditor) self.actions.append(self.hexEditorAct) self.webBrowserAct = E5Action( self.tr('eric6 Web Browser'), UI.PixmapCache.getIcon("ericWeb"), self.tr('eric6 &Web Browser...'), 0, 0, self, 'web_browser') self.webBrowserAct.setStatusTip(self.tr( 'Start the eric6 Web Browser')) self.webBrowserAct.setWhatsThis(self.tr( """<b>eric6 Web Browser</b>""" """<p>Browse the Internet with the eric6 Web Browser.</p>""" )) self.webBrowserAct.triggered.connect(self.__startWebBrowser) self.actions.append(self.webBrowserAct) ## else: ## self.webBrowserAct = None self.iconEditorAct = E5Action( self.tr('Icon Editor'), UI.PixmapCache.getIcon("iconEditor"), self.tr('&Icon Editor...'), 0, 0, self, 'icon_editor') self.iconEditorAct.setStatusTip(self.tr( 'Start the eric6 Icon Editor')) self.iconEditorAct.setWhatsThis(self.tr( """<b>Icon Editor</b>""" """<p>Starts the eric6 Icon Editor for editing simple icons.</p>""" )) self.iconEditorAct.triggered.connect(self.__editPixmap) self.actions.append(self.iconEditorAct) self.snapshotAct = E5Action( self.tr('Snapshot'), UI.PixmapCache.getIcon("ericSnap"), self.tr('&Snapshot...'), 0, 0, self, 'snapshot') self.snapshotAct.setStatusTip(self.tr( 'Take snapshots of a screen region')) self.snapshotAct.setWhatsThis(self.tr( """<b>Snapshot</b>""" """<p>This opens a dialog to take snapshots of a screen""" """ region.</p>""" )) self.snapshotAct.triggered.connect(self.__snapshot) self.actions.append(self.snapshotAct) self.prefAct = E5Action( self.tr('Preferences'), UI.PixmapCache.getIcon("configure"), self.tr('&Preferences...'), 0, 0, self, 'preferences') self.prefAct.setStatusTip(self.tr( 'Set the prefered configuration')) self.prefAct.setWhatsThis(self.tr( """<b>Preferences</b>""" """<p>Set the configuration items of the application""" """ with your prefered values.</p>""" )) self.prefAct.triggered.connect(self.showPreferences) self.prefAct.setMenuRole(QAction.PreferencesRole) self.actions.append(self.prefAct) self.prefExportAct = E5Action( self.tr('Export Preferences'), UI.PixmapCache.getIcon("configureExport"), self.tr('E&xport Preferences...'), 0, 0, self, 'export_preferences') self.prefExportAct.setStatusTip(self.tr( 'Export the current configuration')) self.prefExportAct.setWhatsThis(self.tr( """<b>Export Preferences</b>""" """<p>Export the current configuration to a file.</p>""" )) self.prefExportAct.triggered.connect(self.__exportPreferences) self.actions.append(self.prefExportAct) self.prefImportAct = E5Action( self.tr('Import Preferences'), UI.PixmapCache.getIcon("configureImport"), self.tr('I&mport Preferences...'), 0, 0, self, 'import_preferences') self.prefImportAct.setStatusTip(self.tr( 'Import a previously exported configuration')) self.prefImportAct.setWhatsThis(self.tr( """<b>Import Preferences</b>""" """<p>Import a previously exported configuration.</p>""" )) self.prefImportAct.triggered.connect(self.__importPreferences) self.actions.append(self.prefImportAct) self.reloadAPIsAct = E5Action( self.tr('Reload APIs'), self.tr('Reload &APIs'), 0, 0, self, 'reload_apis') self.reloadAPIsAct.setStatusTip(self.tr( 'Reload the API information')) self.reloadAPIsAct.setWhatsThis(self.tr( """<b>Reload APIs</b>""" """<p>Reload the API information.</p>""" )) self.reloadAPIsAct.triggered.connect(self.__reloadAPIs) self.actions.append(self.reloadAPIsAct) self.showExternalToolsAct = E5Action( self.tr('Show external tools'), UI.PixmapCache.getIcon("showPrograms"), self.tr('Show external &tools'), 0, 0, self, 'show_external_tools') self.showExternalToolsAct.setStatusTip(self.tr( 'Show external tools')) self.showExternalToolsAct.setWhatsThis(self.tr( """<b>Show external tools</b>""" """<p>Opens a dialog to show the path and versions of all""" """ extenal tools used by eric6.</p>""" )) self.showExternalToolsAct.triggered.connect( self.__showExternalTools) self.actions.append(self.showExternalToolsAct) self.configViewProfilesAct = E5Action( self.tr('View Profiles'), UI.PixmapCache.getIcon("configureViewProfiles"), self.tr('&View Profiles...'), 0, 0, self, 'view_profiles') self.configViewProfilesAct.setStatusTip(self.tr( 'Configure view profiles')) self.configViewProfilesAct.setWhatsThis(self.tr( """<b>View Profiles</b>""" """<p>Configure the view profiles. With this dialog you may""" """ set the visibility of the various windows for the""" """ predetermined view profiles.</p>""" )) self.configViewProfilesAct.triggered.connect( self.__configViewProfiles) self.actions.append(self.configViewProfilesAct) self.configToolBarsAct = E5Action( self.tr('Toolbars'), UI.PixmapCache.getIcon("toolbarsConfigure"), self.tr('Tool&bars...'), 0, 0, self, 'configure_toolbars') self.configToolBarsAct.setStatusTip(self.tr('Configure toolbars')) self.configToolBarsAct.setWhatsThis(self.tr( """<b>Toolbars</b>""" """<p>Configure the toolbars. With this dialog you may""" """ change the actions shown on the various toolbars and""" """ define your own toolbars.</p>""" )) self.configToolBarsAct.triggered.connect(self.__configToolBars) self.actions.append(self.configToolBarsAct) self.shortcutsAct = E5Action( self.tr('Keyboard Shortcuts'), UI.PixmapCache.getIcon("configureShortcuts"), self.tr('Keyboard &Shortcuts...'), 0, 0, self, 'keyboard_shortcuts') self.shortcutsAct.setStatusTip(self.tr( 'Set the keyboard shortcuts')) self.shortcutsAct.setWhatsThis(self.tr( """<b>Keyboard Shortcuts</b>""" """<p>Set the keyboard shortcuts of the application""" """ with your prefered values.</p>""" )) self.shortcutsAct.triggered.connect(self.__configShortcuts) self.actions.append(self.shortcutsAct) self.exportShortcutsAct = E5Action( self.tr('Export Keyboard Shortcuts'), UI.PixmapCache.getIcon("exportShortcuts"), self.tr('&Export Keyboard Shortcuts...'), 0, 0, self, 'export_keyboard_shortcuts') self.exportShortcutsAct.setStatusTip(self.tr( 'Export the keyboard shortcuts')) self.exportShortcutsAct.setWhatsThis(self.tr( """<b>Export Keyboard Shortcuts</b>""" """<p>Export the keyboard shortcuts of the application.</p>""" )) self.exportShortcutsAct.triggered.connect(self.__exportShortcuts) self.actions.append(self.exportShortcutsAct) self.importShortcutsAct = E5Action( self.tr('Import Keyboard Shortcuts'), UI.PixmapCache.getIcon("importShortcuts"), self.tr('&Import Keyboard Shortcuts...'), 0, 0, self, 'import_keyboard_shortcuts') self.importShortcutsAct.setStatusTip(self.tr( 'Import the keyboard shortcuts')) self.importShortcutsAct.setWhatsThis(self.tr( """<b>Import Keyboard Shortcuts</b>""" """<p>Import the keyboard shortcuts of the application.</p>""" )) self.importShortcutsAct.triggered.connect(self.__importShortcuts) self.actions.append(self.importShortcutsAct) if SSL_AVAILABLE: self.certificatesAct = E5Action( self.tr('Manage SSL Certificates'), UI.PixmapCache.getIcon("certificates"), self.tr('Manage SSL Certificates...'), 0, 0, self, 'manage_ssl_certificates') self.certificatesAct.setStatusTip(self.tr( 'Manage the saved SSL certificates')) self.certificatesAct.setWhatsThis(self.tr( """<b>Manage SSL Certificates...</b>""" """<p>Opens a dialog to manage the saved SSL certificates.""" """</p>""" )) self.certificatesAct.triggered.connect( self.__showCertificatesDialog) self.actions.append(self.certificatesAct) self.editMessageFilterAct = E5Action( self.tr('Edit Message Filters'), UI.PixmapCache.getIcon("warning"), self.tr('Edit Message Filters...'), 0, 0, self, 'manage_message_filters') self.editMessageFilterAct.setStatusTip(self.tr( 'Edit the message filters used to suppress unwanted messages')) self.editMessageFilterAct.setWhatsThis(self.tr( """<b>Edit Message Filters</b>""" """<p>Opens a dialog to edit the message filters used to""" """ suppress unwanted messages been shown in an error""" """ window.</p>""" )) self.editMessageFilterAct.triggered.connect( E5ErrorMessage.editMessageFilters) self.actions.append(self.editMessageFilterAct) self.clearPrivateDataAct = E5Action( self.tr('Clear private data'), UI.PixmapCache.getIcon("clearPrivateData"), self.tr('Clear private data'), 0, 0, self, 'clear_private_data') self.clearPrivateDataAct.setStatusTip(self.tr( 'Clear private data')) self.clearPrivateDataAct.setWhatsThis(self.tr( """<b>Clear private data</b>""" """<p>Clears the private data like the various list of""" """ recently opened files, projects or multi projects.</p>""" )) self.clearPrivateDataAct.triggered.connect( self.__clearPrivateData) self.actions.append(self.clearPrivateDataAct) self.viewmanagerActivateAct = E5Action( self.tr('Activate current editor'), self.tr('Activate current editor'), QKeySequence(self.tr("Alt+Shift+E")), 0, self, 'viewmanager_activate') self.viewmanagerActivateAct.triggered.connect( self.__activateViewmanager) self.actions.append(self.viewmanagerActivateAct) self.addAction(self.viewmanagerActivateAct) self.nextTabAct = E5Action( self.tr('Show next'), self.tr('Show next'), QKeySequence(self.tr('Ctrl+Alt+Tab')), 0, self, 'view_next_tab') self.nextTabAct.triggered.connect(self.__showNext) self.actions.append(self.nextTabAct) self.addAction(self.nextTabAct) self.prevTabAct = E5Action( self.tr('Show previous'), self.tr('Show previous'), QKeySequence(self.tr('Shift+Ctrl+Alt+Tab')), 0, self, 'view_previous_tab') self.prevTabAct.triggered.connect(self.__showPrevious) self.actions.append(self.prevTabAct) self.addAction(self.prevTabAct) self.switchTabAct = E5Action( self.tr('Switch between tabs'), self.tr('Switch between tabs'), QKeySequence(self.tr('Ctrl+1')), 0, self, 'switch_tabs') self.switchTabAct.triggered.connect(self.__switchTab) self.actions.append(self.switchTabAct) self.addAction(self.switchTabAct) self.pluginInfoAct = E5Action( self.tr('Plugin Infos'), UI.PixmapCache.getIcon("plugin"), self.tr('&Plugin Infos...'), 0, 0, self, 'plugin_infos') self.pluginInfoAct.setStatusTip(self.tr('Show Plugin Infos')) self.pluginInfoAct.setWhatsThis(self.tr( """<b>Plugin Infos...</b>""" """<p>This opens a dialog, that show some information about""" """ loaded plugins.</p>""" )) self.pluginInfoAct.triggered.connect(self.__showPluginInfo) self.actions.append(self.pluginInfoAct) self.pluginInstallAct = E5Action( self.tr('Install Plugins'), UI.PixmapCache.getIcon("pluginInstall"), self.tr('&Install Plugins...'), 0, 0, self, 'plugin_install') self.pluginInstallAct.setStatusTip(self.tr('Install Plugins')) self.pluginInstallAct.setWhatsThis(self.tr( """<b>Install Plugins...</b>""" """<p>This opens a dialog to install or update plugins.</p>""" )) self.pluginInstallAct.triggered.connect(self.__installPlugins) self.actions.append(self.pluginInstallAct) self.pluginDeinstallAct = E5Action( self.tr('Uninstall Plugin'), UI.PixmapCache.getIcon("pluginUninstall"), self.tr('&Uninstall Plugin...'), 0, 0, self, 'plugin_deinstall') self.pluginDeinstallAct.setStatusTip(self.tr('Uninstall Plugin')) self.pluginDeinstallAct.setWhatsThis(self.tr( """<b>Uninstall Plugin...</b>""" """<p>This opens a dialog to uninstall a plugin.</p>""" )) self.pluginDeinstallAct.triggered.connect(self.__deinstallPlugin) self.actions.append(self.pluginDeinstallAct) self.pluginRepoAct = E5Action( self.tr('Plugin Repository'), UI.PixmapCache.getIcon("pluginRepository"), self.tr('Plugin &Repository...'), 0, 0, self, 'plugin_repository') self.pluginRepoAct.setStatusTip(self.tr( 'Show Plugins available for download')) self.pluginRepoAct.setWhatsThis(self.tr( """<b>Plugin Repository...</b>""" """<p>This opens a dialog, that shows a list of plugins """ """available on the Internet.</p>""" )) self.pluginRepoAct.triggered.connect(self.showPluginsAvailable) self.actions.append(self.pluginRepoAct) self.virtualenvManagerAct = E5Action( self.tr('Virtualenv Manager'), UI.PixmapCache.getIcon("virtualenv"), self.tr('&Virtualenv Manager...'), 0, 0, self, 'virtualenv_manager') self.virtualenvManagerAct.setStatusTip(self.tr( 'Virtualenv Manager')) self.virtualenvManagerAct.setWhatsThis(self.tr( """<b>Virtualenv Manager</b>""" """<p>This opens a dialog to manage the defined Python virtual""" """ environments.</p>""" )) self.virtualenvManagerAct.triggered.connect( self.virtualenvManager.showVirtualenvManagerDialog) self.actions.append(self.virtualenvManagerAct) self.virtualenvConfigAct = E5Action( self.tr('Virtualenv Configurator'), UI.PixmapCache.getIcon("virtualenvConfig"), self.tr('Virtualenv &Configurator...'), 0, 0, self, 'virtualenv_configurator') self.virtualenvConfigAct.setStatusTip(self.tr( 'Virtualenv Configurator')) self.virtualenvConfigAct.setWhatsThis(self.tr( """<b>Virtualenv Configurator</b>""" """<p>This opens a dialog for entering all the parameters""" """ needed to create a Python virtual environment using""" """ virtualenv or pyvenv.</p>""" )) self.virtualenvConfigAct.triggered.connect( self.virtualenvManager.createVirtualEnv) self.actions.append(self.virtualenvConfigAct) # initialize viewmanager actions self.viewmanager.initActions() # initialize debugger actions self.debuggerUI.initActions() # initialize project actions self.project.initActions() # initialize multi project actions self.multiProject.initActions() def __initQtDocActions(self): """ Private slot to initialize the action to show the Qt documentation. """ self.qt5DocAct = E5Action( self.tr('Qt5 Documentation'), self.tr('Qt&5 Documentation'), 0, 0, self, 'qt5_documentation') self.qt5DocAct.setStatusTip(self.tr('Open Qt5 Documentation')) self.qt5DocAct.setWhatsThis(self.tr( """<b>Qt5 Documentation</b>""" """<p>Display the Qt5 Documentation. Dependent upon your""" """ settings, this will either show the help in Eric's internal""" """ help viewer/web browser, or execute a web browser or Qt""" """ Assistant. </p>""" )) self.qt5DocAct.triggered.connect(self.__showQt5Doc) self.actions.append(self.qt5DocAct) self.pyqt5DocAct = E5Action( self.tr('PyQt5 Documentation'), self.tr('PyQt&5 Documentation'), 0, 0, self, 'pyqt5_documentation') self.pyqt5DocAct.setStatusTip(self.tr( 'Open PyQt5 Documentation')) self.pyqt5DocAct.setWhatsThis(self.tr( """<b>PyQt5 Documentation</b>""" """<p>Display the PyQt5 Documentation. Dependent upon your""" """ settings, this will either show the help in Eric's""" """ internal help viewer/web browser, or execute a web""" """ browser or Qt Assistant. </p>""" )) self.pyqt5DocAct.triggered.connect(self.__showPyQt5Doc) self.actions.append(self.pyqt5DocAct) def __initPythonDocActions(self): """ Private slot to initialize the actions to show the Python documentation. """ self.pythonDocAct = E5Action( self.tr('Python 3 Documentation'), self.tr('Python &3 Documentation'), 0, 0, self, 'python3_documentation') self.pythonDocAct.setStatusTip(self.tr( 'Open Python 3 Documentation')) self.pythonDocAct.setWhatsThis(self.tr( """<b>Python 3 Documentation</b>""" """<p>Display the Python 3 documentation. If no documentation""" """ directory is configured, the location of the Python 3""" """ documentation is assumed to be the doc directory underneath""" """ the location of the Python 3 executable on Windows and""" """ <i>/usr/share/doc/packages/python/html</i> on Unix. Set""" """ PYTHON3DOCDIR in your environment to override this.</p>""" )) self.pythonDocAct.triggered.connect(self.__showPythonDoc) self.actions.append(self.pythonDocAct) def __initEricDocAction(self): """ Private slot to initialize the action to show the eric6 documentation. """ self.ericDocAct = E5Action( self.tr("Eric API Documentation"), self.tr('&Eric API Documentation'), 0, 0, self, 'eric_documentation') self.ericDocAct.setStatusTip(self.tr( "Open Eric API Documentation")) self.ericDocAct.setWhatsThis(self.tr( """<b>Eric API Documentation</b>""" """<p>Display the Eric API documentation. The location for the""" """ documentation is the Documentation/Source subdirectory of""" """ the eric6 installation directory.</p>""" )) self.ericDocAct.triggered.connect(self.__showEricDoc) self.actions.append(self.ericDocAct) def __initPySideDocActions(self): """ Private slot to initialize the actions to show the PySide documentation. """ if Utilities.checkPyside(): self.pyside2DocAct = E5Action( self.tr('PySide2 Documentation'), self.tr('PySide&2 Documentation'), 0, 0, self, 'pyside2_documentation') self.pyside2DocAct.setStatusTip(self.tr( 'Open PySide2 Documentation')) self.pyside2DocAct.setWhatsThis(self.tr( """<b>PySide2 Documentation</b>""" """<p>Display the PySide2 Documentation. Dependent upon your""" """ settings, this will either show the help in Eric's""" """ internal help viewer/web browser, or execute a web""" """ browser or Qt Assistant. </p>""" )) self.pyside2DocAct.triggered.connect( lambda: self.__showPySideDoc("2")) self.actions.append(self.pyside2DocAct) else: self.pyside2DocAct = None def __initMenus(self): """ Private slot to create the menus. """ self.__menus = {} mb = self.menuBar() if ( Utilities.isLinuxPlatform() and not Preferences.getUI("UseNativeMenuBar") ): mb.setNativeMenuBar(False) ############################################################## ## File menu ############################################################## self.__menus["file"] = self.viewmanager.initFileMenu() mb.addMenu(self.__menus["file"]) self.__menus["file"].addSeparator() self.__menus["file"].addAction(self.saveSessionAct) self.__menus["file"].addAction(self.loadSessionAct) self.__menus["file"].addSeparator() self.__menus["file"].addAction(self.restartAct) self.__menus["file"].addAction(self.exitAct) act = self.__menus["file"].actions()[0] sep = self.__menus["file"].insertSeparator(act) self.__menus["file"].insertAction(sep, self.newWindowAct) self.__menus["file"].aboutToShow.connect(self.__showFileMenu) ############################################################## ## Edit menu ############################################################## self.__menus["edit"] = self.viewmanager.initEditMenu() mb.addMenu(self.__menus["edit"]) ############################################################## ## Search menu ############################################################## self.__menus["search"] = self.viewmanager.initSearchMenu() mb.addMenu(self.__menus["search"]) ############################################################## ## View menu ############################################################## self.__menus["view"] = self.viewmanager.initViewMenu() mb.addMenu(self.__menus["view"]) ############################################################## ## Bookmarks menu ############################################################## self.__menus["bookmarks"] = self.viewmanager.initBookmarkMenu() mb.addMenu(self.__menus["bookmarks"]) self.__menus["bookmarks"].setTearOffEnabled(True) ############################################################## ## Multiproject menu ############################################################## self.__menus["multiproject"] = self.multiProject.initMenu() mb.addMenu(self.__menus["multiproject"]) ############################################################## ## Project menu ############################################################## self.__menus["project"], self.__menus["project_tools"] = ( self.project.initMenus() ) mb.addMenu(self.__menus["project"]) mb.addMenu(self.__menus["project_tools"]) ############################################################## ## Start and Debug menus ############################################################## self.__menus["start"], self.__menus["debug"] = ( self.debuggerUI.initMenus() ) mb.addMenu(self.__menus["start"]) mb.addMenu(self.__menus["debug"]) ############################################################## ## Extras menu ############################################################## self.__menus["extras"] = QMenu(self.tr('E&xtras'), self) self.__menus["extras"].setTearOffEnabled(True) self.__menus["extras"].aboutToShow.connect(self.__showExtrasMenu) mb.addMenu(self.__menus["extras"]) self.viewmanager.addToExtrasMenu(self.__menus["extras"]) ############################################################## ## Extras/Wizards menu ############################################################## self.__menus["wizards"] = QMenu(self.tr('Wi&zards'), self) self.__menus["wizards"].setTearOffEnabled(True) self.__menus["wizards"].aboutToShow.connect(self.__showWizardsMenu) self.wizardsMenuAct = self.__menus["extras"].addMenu( self.__menus["wizards"]) self.wizardsMenuAct.setEnabled(False) ############################################################## ## Extras/Macros menu ############################################################## self.__menus["macros"] = self.viewmanager.initMacroMenu() self.__menus["extras"].addMenu(self.__menus["macros"]) self.__menus["extras"].addSeparator() ############################################################## ## Extras/VirtualEnv Manager menu entries ############################################################## self.__menus["extras"].addAction(self.virtualenvManagerAct) self.__menus["extras"].addAction(self.virtualenvConfigAct) self.__menus["extras"].addSeparator() ############################################################## ## Extras/Plugins menu ############################################################## pluginsMenu = QMenu(self.tr('P&lugins'), self) pluginsMenu.setIcon(UI.PixmapCache.getIcon("plugin")) pluginsMenu.setTearOffEnabled(True) pluginsMenu.addAction(self.pluginInfoAct) pluginsMenu.addAction(self.pluginInstallAct) pluginsMenu.addAction(self.pluginDeinstallAct) pluginsMenu.addSeparator() pluginsMenu.addAction(self.pluginRepoAct) pluginsMenu.addSeparator() pluginsMenu.addAction( self.tr("Configure..."), self.__pluginsConfigure) self.__menus["extras"].addMenu(pluginsMenu) self.__menus["extras"].addSeparator() ############################################################## ## Extras/Unittest menu ############################################################## self.__menus["unittest"] = QMenu(self.tr('&Unittest'), self) self.__menus["unittest"].setTearOffEnabled(True) self.__menus["unittest"].addAction(self.utDialogAct) self.__menus["unittest"].addSeparator() self.__menus["unittest"].addAction(self.utRestartAct) self.__menus["unittest"].addAction(self.utRerunFailedAct) self.__menus["unittest"].addSeparator() self.__menus["unittest"].addAction(self.utScriptAct) self.__menus["unittest"].addAction(self.utProjectAct) self.__menus["extras"].addMenu(self.__menus["unittest"]) self.__menus["extras"].addSeparator() ############################################################## ## Extras/Builtin,Plugin,User tools menus ############################################################## self.toolGroupsMenu = QMenu(self.tr("Select Tool Group"), self) self.toolGroupsMenu.aboutToShow.connect(self.__showToolGroupsMenu) self.toolGroupsMenu.triggered.connect(self.__toolGroupSelected) self.toolGroupsMenuTriggered = False self.__initToolsMenus(self.__menus["extras"]) self.__menus["extras"].addSeparator() ############################################################## ## Settings menu ############################################################## self.__menus["settings"] = QMenu(self.tr('Se&ttings'), self) mb.addMenu(self.__menus["settings"]) self.__menus["settings"].setTearOffEnabled(True) self.__menus["settings"].addAction(self.prefAct) self.__menus["settings"].addAction(self.prefExportAct) self.__menus["settings"].addAction(self.prefImportAct) self.__menus["settings"].addSeparator() self.__menus["settings"].addAction(self.reloadAPIsAct) self.__menus["settings"].addSeparator() self.__menus["settings"].addAction(self.configViewProfilesAct) self.__menus["settings"].addAction(self.configToolBarsAct) self.__menus["settings"].addSeparator() self.__menus["settings"].addAction(self.shortcutsAct) self.__menus["settings"].addAction(self.exportShortcutsAct) self.__menus["settings"].addAction(self.importShortcutsAct) self.__menus["settings"].addSeparator() self.__menus["settings"].addAction(self.showExternalToolsAct) if SSL_AVAILABLE: self.__menus["settings"].addSeparator() self.__menus["settings"].addAction(self.certificatesAct) self.__menus["settings"].addSeparator() self.__menus["settings"].addAction(self.editMessageFilterAct) self.__menus["settings"].addSeparator() self.__menus["settings"].addAction(self.clearPrivateDataAct) ############################################################## ## Window menu ############################################################## self.__menus["window"] = QMenu(self.tr('&Window'), self) mb.addMenu(self.__menus["window"]) self.__menus["window"].setTearOffEnabled(True) self.__menus["window"].aboutToShow.connect(self.__showWindowMenu) ############################################################## ## Window/Windows menu ############################################################## self.__menus["subwindow"] = QMenu(self.tr("&Windows"), self.__menus["window"]) self.__menus["subwindow"].setTearOffEnabled(True) # central park self.__menus["subwindow"].addSection(self.tr("Central Park")) self.__menus["subwindow"].addAction(self.viewmanagerActivateAct) # left side self.__menus["subwindow"].addSection(self.tr("Left Side")) if self.__shellPosition == "left": self.__menus["subwindow"].addAction(self.shellActivateAct) self.__menus["subwindow"].addAction(self.pbActivateAct) self.__menus["subwindow"].addAction(self.mpbActivateAct) if self.templateViewer is not None: self.__menus["subwindow"].addAction(self.templateViewerActivateAct) if self.browser is not None: self.__menus["subwindow"].addAction(self.browserActivateAct) if self.symbolsViewer is not None: self.__menus["subwindow"].addAction(self.symbolsViewerActivateAct) # bottom side self.__menus["subwindow"].addSection(self.tr("Bottom Side")) if self.__shellPosition == "bottom": self.__menus["subwindow"].addAction(self.shellActivateAct) self.__menus["subwindow"].addAction(self.taskViewerActivateAct) self.__menus["subwindow"].addAction(self.logViewerActivateAct) if self.numbersViewer is not None: self.__menus["subwindow"].addAction(self.numbersViewerActivateAct) self.__menus["subwindow"].addSection(self.tr("Right Side")) # right side if self.__shellPosition == "right": self.__menus["subwindow"].addAction(self.shellActivateAct) if self.codeDocumentationViewer is not None: self.__menus["subwindow"].addAction( self.codeDocumentationViewerActivateAct) self.__menus["subwindow"].addAction(self.debugViewerActivateAct) if self.pipWidget is not None: self.__menus["subwindow"].addAction(self.pipWidgetActivateAct) if self.condaWidget is not None: self.__menus["subwindow"].addAction(self.condaWidgetActivateAct) if self.cooperation is not None: self.__menus["subwindow"].addAction( self.cooperationViewerActivateAct) if self.irc is not None: self.__menus["subwindow"].addAction(self.ircActivateAct) if self.microPythonWidget is not None: self.__menus["subwindow"].addAction( self.microPythonWidgetActivateAct) self.__menus["subwindow"].addSection(self.tr("Plug-ins")) ############################################################## ## Window/Toolbars menu ############################################################## self.__menus["toolbars"] = QMenu( self.tr("&Toolbars"), self.__menus["window"]) self.__menus["toolbars"].setTearOffEnabled(True) self.__menus["toolbars"].aboutToShow.connect(self.__showToolbarsMenu) self.__menus["toolbars"].triggered.connect(self.__TBMenuTriggered) self.__showWindowMenu() # to initialize these actions mb.addSeparator() ############################################################## ## Help menu ############################################################## self.__menus["help"] = QMenu(self.tr('&Help'), self) mb.addMenu(self.__menus["help"]) self.__menus["help"].setTearOffEnabled(True) if self.helpviewerAct: self.__menus["help"].addAction(self.helpviewerAct) self.__menus["help"].addSeparator() self.__menus["help"].addAction(self.ericDocAct) self.__menus["help"].addAction(self.pythonDocAct) self.__menus["help"].addAction(self.qt5DocAct) if self.pyqt5DocAct is not None: self.__menus["help"].addAction(self.pyqt5DocAct) if self.pyside2DocAct is not None: self.__menus["help"].addAction(self.pyside2DocAct) self.__menus["help"].addSeparator() self.__menus["help"].addAction(self.versionAct) self.__menus["help"].addSeparator() self.__menus["help"].addAction(self.checkUpdateAct) self.__menus["help"].addAction(self.showVersionsAct) self.__menus["help"].addSeparator() self.__menus["help"].addAction(self.showInstallInfoAct) self.__menus["help"].addSeparator() self.__menus["help"].addAction(self.showErrorLogAct) self.__menus["help"].addAction(self.reportBugAct) self.__menus["help"].addAction(self.requestFeatureAct) self.__menus["help"].addSeparator() self.__menus["help"].addAction(self.whatsThisAct) self.__menus["help"].aboutToShow.connect(self.__showHelpMenu) def getToolBarIconSize(self): """ Public method to get the toolbar icon size. @return toolbar icon size (QSize) """ return Config.ToolBarIconSize def __initToolbars(self): """ Private slot to create the toolbars. """ filetb = self.viewmanager.initFileToolbar(self.toolbarManager) edittb = self.viewmanager.initEditToolbar(self.toolbarManager) searchtb, quicksearchtb = self.viewmanager.initSearchToolbars( self.toolbarManager) viewtb = self.viewmanager.initViewToolbar(self.toolbarManager) starttb, debugtb = self.debuggerUI.initToolbars(self.toolbarManager) multiprojecttb = self.multiProject.initToolbar(self.toolbarManager) projecttb, vcstb = self.project.initToolbars(self.toolbarManager) toolstb = QToolBar(self.tr("Tools"), self) unittesttb = QToolBar(self.tr("Unittest"), self) bookmarktb = self.viewmanager.initBookmarkToolbar(self.toolbarManager) spellingtb = self.viewmanager.initSpellingToolbar(self.toolbarManager) settingstb = QToolBar(self.tr("Settings"), self) helptb = QToolBar(self.tr("Help"), self) profilestb = QToolBar(self.tr("Profiles"), self) pluginstb = QToolBar(self.tr("Plugins"), self) toolstb.setIconSize(Config.ToolBarIconSize) unittesttb.setIconSize(Config.ToolBarIconSize) settingstb.setIconSize(Config.ToolBarIconSize) helptb.setIconSize(Config.ToolBarIconSize) profilestb.setIconSize(Config.ToolBarIconSize) pluginstb.setIconSize(Config.ToolBarIconSize) toolstb.setObjectName("ToolsToolbar") unittesttb.setObjectName("UnittestToolbar") settingstb.setObjectName("SettingsToolbar") helptb.setObjectName("HelpToolbar") profilestb.setObjectName("ProfilesToolbar") pluginstb.setObjectName("PluginsToolbar") toolstb.setToolTip(self.tr("Tools")) unittesttb.setToolTip(self.tr("Unittest")) settingstb.setToolTip(self.tr("Settings")) helptb.setToolTip(self.tr("Help")) profilestb.setToolTip(self.tr("Profiles")) pluginstb.setToolTip(self.tr("Plugins")) filetb.addSeparator() filetb.addAction(self.restartAct) filetb.addAction(self.exitAct) act = filetb.actions()[0] sep = filetb.insertSeparator(act) filetb.insertAction(sep, self.newWindowAct) self.toolbarManager.addToolBar(filetb, filetb.windowTitle()) # setup the unittest toolbar unittesttb.addAction(self.utDialogAct) unittesttb.addSeparator() unittesttb.addAction(self.utRestartAct) unittesttb.addAction(self.utRerunFailedAct) unittesttb.addSeparator() unittesttb.addAction(self.utScriptAct) unittesttb.addAction(self.utProjectAct) self.toolbarManager.addToolBar(unittesttb, unittesttb.windowTitle()) # setup the tools toolbar if self.designer4Act is not None: toolstb.addAction(self.designer4Act) if self.linguist4Act is not None: toolstb.addAction(self.linguist4Act) toolstb.addAction(self.uipreviewerAct) toolstb.addAction(self.trpreviewerAct) toolstb.addSeparator() toolstb.addAction(self.diffAct) toolstb.addAction(self.compareAct) toolstb.addSeparator() toolstb.addAction(self.sqlBrowserAct) toolstb.addSeparator() toolstb.addAction(self.miniEditorAct) toolstb.addAction(self.hexEditorAct) toolstb.addAction(self.iconEditorAct) toolstb.addAction(self.snapshotAct) toolstb.addSeparator() toolstb.addAction(self.virtualenvManagerAct) toolstb.addAction(self.virtualenvConfigAct) if self.webBrowserAct: toolstb.addSeparator() toolstb.addAction(self.webBrowserAct) self.toolbarManager.addToolBar(toolstb, toolstb.windowTitle()) # setup the settings toolbar settingstb.addAction(self.prefAct) settingstb.addAction(self.configViewProfilesAct) settingstb.addAction(self.configToolBarsAct) settingstb.addAction(self.shortcutsAct) settingstb.addAction(self.showExternalToolsAct) self.toolbarManager.addToolBar(settingstb, settingstb.windowTitle()) self.toolbarManager.addActions([ self.exportShortcutsAct, self.importShortcutsAct, self.prefExportAct, self.prefImportAct, self.showExternalToolsAct, self.editMessageFilterAct, self.clearPrivateDataAct, ], settingstb.windowTitle()) if SSL_AVAILABLE: self.toolbarManager.addAction( self.certificatesAct, settingstb.windowTitle()) # setup the help toolbar helptb.addAction(self.whatsThisAct) self.toolbarManager.addToolBar(helptb, helptb.windowTitle()) if self.helpviewerAct: self.toolbarManager.addAction(self.helpviewerAct, helptb.windowTitle()) # setup the view profiles toolbar profilestb.addActions(self.viewProfileActGrp.actions()) self.toolbarManager.addToolBar(profilestb, profilestb.windowTitle()) # setup the plugins toolbar pluginstb.addAction(self.pluginInfoAct) pluginstb.addAction(self.pluginInstallAct) pluginstb.addAction(self.pluginDeinstallAct) pluginstb.addSeparator() pluginstb.addAction(self.pluginRepoAct) self.toolbarManager.addToolBar(pluginstb, pluginstb.windowTitle()) # add the various toolbars self.addToolBar(filetb) self.addToolBar(edittb) self.addToolBar(searchtb) self.addToolBar(quicksearchtb) self.addToolBar(viewtb) self.addToolBar(starttb) self.addToolBar(debugtb) self.addToolBar(multiprojecttb) self.addToolBar(projecttb) self.addToolBar(vcstb) self.addToolBar(Qt.RightToolBarArea, settingstb) self.addToolBar(Qt.RightToolBarArea, toolstb) self.addToolBar(helptb) self.addToolBar(bookmarktb) self.addToolBar(spellingtb) self.addToolBar(unittesttb) self.addToolBar(profilestb) self.addToolBar(pluginstb) # hide toolbars not wanted in the initial layout searchtb.hide() quicksearchtb.hide() viewtb.hide() debugtb.hide() multiprojecttb.hide() helptb.hide() spellingtb.hide() unittesttb.hide() pluginstb.hide() # just add new toolbars to the end of the list self.__toolbars = {} self.__toolbars["file"] = [filetb.windowTitle(), filetb, ""] self.__toolbars["edit"] = [edittb.windowTitle(), edittb, ""] self.__toolbars["search"] = [searchtb.windowTitle(), searchtb, ""] self.__toolbars["view"] = [viewtb.windowTitle(), viewtb, ""] self.__toolbars["start"] = [starttb.windowTitle(), starttb, ""] self.__toolbars["debug"] = [debugtb.windowTitle(), debugtb, ""] self.__toolbars["project"] = [projecttb.windowTitle(), projecttb, ""] self.__toolbars["tools"] = [toolstb.windowTitle(), toolstb, ""] self.__toolbars["help"] = [helptb.windowTitle(), helptb, ""] self.__toolbars["settings"] = [settingstb.windowTitle(), settingstb, ""] self.__toolbars["bookmarks"] = [bookmarktb.windowTitle(), bookmarktb, ""] self.__toolbars["unittest"] = [unittesttb.windowTitle(), unittesttb, ""] self.__toolbars["view_profiles"] = [profilestb.windowTitle(), profilestb, ""] self.__toolbars["plugins"] = [pluginstb.windowTitle(), pluginstb, ""] self.__toolbars["quicksearch"] = [quicksearchtb.windowTitle(), quicksearchtb, ""] self.__toolbars["multiproject"] = [multiprojecttb.windowTitle(), multiprojecttb, ""] self.__toolbars["spelling"] = [spellingtb.windowTitle(), spellingtb, ""] self.__toolbars["vcs"] = [vcstb.windowTitle(), vcstb, "vcs"] def __initDebugToolbarsLayout(self): """ Private slot to initialize the toolbars layout for the debug profile. """ # Step 1: set the edit profile to be sure self.__setEditProfile() # Step 2: switch to debug profile and do the layout initSize = self.size() self.setDebugProfile() self.__toolbars["project"][1].hide() self.__toolbars["debug"][1].show() self.resize(initSize) # Step 3: switch back to edit profile self.__setEditProfile() def __initStatusbar(self): """ Private slot to set up the status bar. """ self.__statusBar = self.statusBar() self.__statusBar.setSizeGripEnabled(True) self.sbLanguage = E5ClickableLabel(self.__statusBar) self.__statusBar.addPermanentWidget(self.sbLanguage) self.sbLanguage.setWhatsThis(self.tr( """<p>This part of the status bar displays the""" """ current editors language.</p>""" )) self.sbEncoding = E5ClickableLabel(self.__statusBar) self.__statusBar.addPermanentWidget(self.sbEncoding) self.sbEncoding.setWhatsThis(self.tr( """<p>This part of the status bar displays the""" """ current editors encoding.</p>""" )) self.sbEol = E5ClickableLabel(self.__statusBar) self.__statusBar.addPermanentWidget(self.sbEol) self.sbEol.setWhatsThis(self.tr( """<p>This part of the status bar displays the""" """ current editors eol setting.</p>""" )) self.sbWritable = QLabel(self.__statusBar) self.__statusBar.addPermanentWidget(self.sbWritable) self.sbWritable.setWhatsThis(self.tr( """<p>This part of the status bar displays an indication of the""" """ current editors files writability.</p>""" )) self.sbLine = QLabel(self.__statusBar) self.__statusBar.addPermanentWidget(self.sbLine) self.sbLine.setWhatsThis(self.tr( """<p>This part of the status bar displays the line number of""" """ the current editor.</p>""" )) self.sbPos = QLabel(self.__statusBar) self.__statusBar.addPermanentWidget(self.sbPos) self.sbPos.setWhatsThis(self.tr( """<p>This part of the status bar displays the cursor position""" """ of the current editor.</p>""" )) self.sbZoom = E5ZoomWidget( UI.PixmapCache.getPixmap("zoomOut"), UI.PixmapCache.getPixmap("zoomIn"), UI.PixmapCache.getPixmap("zoomReset"), self.__statusBar) self.__statusBar.addPermanentWidget(self.sbZoom) self.sbZoom.setWhatsThis(self.tr( """<p>This part of the status bar allows zooming the current""" """ editor or shell.</p>""" )) self.viewmanager.setSbInfo( self.sbLine, self.sbPos, self.sbWritable, self.sbEncoding, self.sbLanguage, self.sbEol, self.sbZoom) from VCS.StatusMonitorLed import StatusMonitorLedWidget self.sbVcsMonitorLed = StatusMonitorLedWidget( self.project, self.__statusBar) self.__statusBar.addPermanentWidget(self.sbVcsMonitorLed) self.networkIcon = E5NetworkIcon(self.__statusBar) self.__statusBar.addPermanentWidget(self.networkIcon) self.networkIcon.onlineStateChanged.connect(self.onlineStateChanged) self.networkIcon.onlineStateChanged.connect(self.__onlineStateChanged) def __initExternalToolsActions(self): """ Private slot to create actions for the configured external tools. """ self.toolGroupActions = {} for toolGroup in self.toolGroups: category = self.tr("External Tools/{0}").format(toolGroup[0]) for tool in toolGroup[1]: if tool['menutext'] != '--': act = QAction(UI.PixmapCache.getIcon(tool['icon']), tool['menutext'], self) act.setObjectName("{0}@@{1}".format(toolGroup[0], tool['menutext'])) act.triggered.connect( lambda: self.__toolActionTriggered(act)) self.toolGroupActions[act.objectName()] = act self.toolbarManager.addAction(act, category) def __updateExternalToolsActions(self): """ Private method to update the external tools actions for the current tool group. """ toolGroup = self.toolGroups[self.currentToolGroup] groupkey = "{0}@@".format(toolGroup[0]) groupActionKeys = [] # step 1: get actions for this group for key in self.toolGroupActions: if key.startswith(groupkey): groupActionKeys.append(key) # step 2: build keys for all actions i.a.w. current configuration ckeys = [] for tool in toolGroup[1]: if tool['menutext'] != '--': ckeys.append("{0}@@{1}".format(toolGroup[0], tool['menutext'])) # step 3: remove all actions not configured any more for key in groupActionKeys: if key not in ckeys: self.toolbarManager.removeAction(self.toolGroupActions[key]) self.toolGroupActions[key].triggered.disconnect() del self.toolGroupActions[key] # step 4: add all newly configured tools category = self.tr("External Tools/{0}").format(toolGroup[0]) for tool in toolGroup[1]: if tool['menutext'] != '--': key = "{0}@@{1}".format(toolGroup[0], tool['menutext']) if key not in groupActionKeys: act = QAction(UI.PixmapCache.getIcon(tool['icon']), tool['menutext'], self) act.setObjectName(key) act.triggered.connect( lambda: self.__toolActionTriggered(act)) self.toolGroupActions[key] = act self.toolbarManager.addAction(act, category) def __showFileMenu(self): """ Private slot to display the File menu. """ self.showMenu.emit("File", self.__menus["file"]) def __showExtrasMenu(self): """ Private slot to display the Extras menu. """ self.showMenu.emit("Extras", self.__menus["extras"]) def __showWizardsMenu(self): """ Private slot to display the Wizards menu. """ self.showMenu.emit("Wizards", self.__menus["wizards"]) def __showHelpMenu(self): """ Private slot to display the Help menu. """ self.checkUpdateAct.setEnabled(not self.__inVersionCheck) self.showVersionsAct.setEnabled(not self.__inVersionCheck) self.showErrorLogAct.setEnabled(self.__hasErrorLog()) infoFileName = Globals.getInstallInfoFilePath() self.showInstallInfoAct.setEnabled(os.path.exists(infoFileName)) self.showMenu.emit("Help", self.__menus["help"]) def __showSettingsMenu(self): """ Private slot to show the Settings menu. """ self.editMessageFilterAct.setEnabled( E5ErrorMessage.messageHandlerInstalled()) self.showMenu.emit("Settings", self.__menus["settings"]) def __showNext(self): """ Private slot used to show the next tab or file. """ fwidget = QApplication.focusWidget() while fwidget and not hasattr(fwidget, 'nextTab'): fwidget = fwidget.parent() if fwidget: fwidget.nextTab() def __showPrevious(self): """ Private slot used to show the previous tab or file. """ fwidget = QApplication.focusWidget() while fwidget and not hasattr(fwidget, 'prevTab'): fwidget = fwidget.parent() if fwidget: fwidget.prevTab() def __switchTab(self): """ Private slot used to switch between the current and the previous current tab. """ fwidget = QApplication.focusWidget() while fwidget and not hasattr(fwidget, 'switchTab'): fwidget = fwidget.parent() if fwidget: fwidget.switchTab() def __whatsThis(self): """ Private slot called in to enter Whats This mode. """ QWhatsThis.enterWhatsThisMode() def __showVersions(self): """ Private slot to handle the Versions dialog. """ try: try: from PyQt5 import sip except ImportError: import sip sip_version_str = sip.SIP_VERSION_STR except (ImportError, AttributeError): sip_version_str = "sip version not available" if sys.maxsize > 2**32: sizeStr = "64-Bit" else: sizeStr = "32-Bit" versionText = self.tr( """<h2>Version Numbers</h2>""" """<table>""") versionText += ( """<tr><td><b>Python</b></td><td>{0}, {1}</td></tr>""" ).format(sys.version.split()[0], sizeStr) versionText += ( """<tr><td><b>Qt</b></td><td>{0}</td></tr>""" ).format(qVersion()) versionText += ( """<tr><td><b>PyQt</b></td><td>{0}</td></tr>""" ).format(PYQT_VERSION_STR) try: from PyQt5 import QtChart versionText += ( """<tr><td><b>PyQtChart</b></td><td>{0}</td></tr>""" ).format(QtChart.PYQT_CHART_VERSION_STR) except (ImportError, AttributeError): pass try: from PyQt5 import QtWebEngine versionText += ( """<tr><td><b>PyQtWebEngine</b></td><td>{0}</td></tr>""" ).format(QtWebEngine.PYQT_WEBENGINE_VERSION_STR) except (ImportError, AttributeError): pass versionText += ( """<tr><td><b>QScintilla</b></td><td>{0}</td></tr>""" ).format(QSCINTILLA_VERSION_STR) versionText += ( """<tr><td><b>sip</b></td><td>{0}</td></tr>""" ).format(sip_version_str) try: from WebBrowser.Tools import WebBrowserTools chromeVersion = WebBrowserTools.getWebEngineVersions()[0] versionText += ( """<tr><td><b>WebEngine</b></td><td>{0}</td></tr>""" ).format(chromeVersion) except ImportError: pass versionText += ("""<tr><td><b>{0}</b></td><td>{1}</td></tr>""" ).format(Program, Version) versionText += self.tr("""</table>""") E5MessageBox.about(self, Program, versionText) def __reportBug(self): """ Private slot to handle the Report Bug dialog. """ self.showEmailDialog("bug") def __requestFeature(self): """ Private slot to handle the Feature Request dialog. """ self.showEmailDialog("feature") def showEmailDialog(self, mode, attachFile=None, deleteAttachFile=False): """ Public slot to show the email dialog in a given mode. @param mode mode of the email dialog (string, "bug" or "feature") @param attachFile name of a file to attach to the email (string) @param deleteAttachFile flag indicating to delete the attached file after it has been sent (boolean) """ if Preferences.getUser("UseSystemEmailClient"): self.__showSystemEmailClient(mode, attachFile, deleteAttachFile) else: if not Preferences.getUser("UseGoogleMailOAuth2") and ( Preferences.getUser("Email") == "" or Preferences.getUser("MailServer") == ""): E5MessageBox.critical( self, self.tr("Report Bug"), self.tr( """Email address or mail server address is empty.""" """ Please configure your Email settings in the""" """ Preferences Dialog.""")) self.showPreferences("emailPage") return from .EmailDialog import EmailDialog self.dlg = EmailDialog(mode=mode) if attachFile is not None: self.dlg.attachFile(attachFile, deleteAttachFile) self.dlg.show() def __showSystemEmailClient(self, mode, attachFile=None, deleteAttachFile=False): """ Private slot to show the system email dialog. @param mode mode of the email dialog (string, "bug" or "feature") @param attachFile name of a file to put into the body of the email (string) @param deleteAttachFile flag indicating to delete the file after it has been read (boolean) """ if mode == "feature": address = FeatureAddress else: address = BugAddress subject = "[eric6] " if attachFile is not None: with open(attachFile, "r", encoding="utf-8") as f: body = f.read() if deleteAttachFile: os.remove(attachFile) else: body = "\r\n----\r\n{0}\r\n----\r\n{1}\r\n----\r\n{2}".format( Utilities.generateVersionInfo("\r\n"), Utilities.generatePluginsVersionInfo("\r\n"), Utilities.generateDistroInfo("\r\n")) url = QUrl("mailto:{0}".format(address)) urlQuery = QUrlQuery(url) urlQuery.addQueryItem("subject", subject) urlQuery.addQueryItem("body", body) url.setQuery(urlQuery) QDesktopServices.openUrl(url) def checkForErrorLog(self): """ Public method to check for the presence of an error log and ask the user, what to do with it. """ if Preferences.getUI("CheckErrorLog"): logFile = os.path.join(Utilities.getConfigDir(), self.ErrorLogFileName) if os.path.exists(logFile): from .ErrorLogDialog import ErrorLogDialog dlg = ErrorLogDialog(logFile, False, self) dlg.exec() def __hasErrorLog(self): """ Private method to check, if an error log file exists. @return flag indicating the existence of an error log file (boolean) """ logFile = os.path.join(Utilities.getConfigDir(), self.ErrorLogFileName) return os.path.exists(logFile) def __showErrorLog(self): """ Private slot to show the most recent error log message. """ logFile = os.path.join(Utilities.getConfigDir(), self.ErrorLogFileName) if os.path.exists(logFile): from .ErrorLogDialog import ErrorLogDialog dlg = ErrorLogDialog(logFile, True, self) dlg.show() def __showInstallInfo(self): """ Private slot to show a dialog containing information about the installation process. """ from .InstallInfoDialog import InstallInfoDialog dlg = InstallInfoDialog(self) if dlg.wasLoaded(): dlg.exec() def __compareFiles(self): """ Private slot to handle the Compare Files dialog. """ aw = self.viewmanager.activeWindow() fn = aw and aw.getFileName() or None if self.diffDlg is None: from .DiffDialog import DiffDialog self.diffDlg = DiffDialog() self.diffDlg.show(fn) def __compareFilesSbs(self): """ Private slot to handle the Compare Files dialog. """ aw = self.viewmanager.activeWindow() fn = aw and aw.getFileName() or None if self.compareDlg is None: from .CompareDialog import CompareDialog self.compareDlg = CompareDialog() self.compareDlg.show(fn) def __openMiniEditor(self): """ Private slot to show a mini editor window. """ from QScintilla.MiniEditor import MiniEditor editor = MiniEditor(parent=self) editor.show() def addE5Actions(self, actions, actionType): """ Public method to add actions to the list of actions. @param actions list of actions to be added (list of E5Action) @param actionType string denoting the action set to add to. It must be one of "ui" or "wizards". """ if actionType == 'ui': self.actions.extend(actions) elif actionType == 'wizards': self.wizardsActions.extend(actions) def removeE5Actions(self, actions, actionType='ui'): """ Public method to remove actions from the list of actions. @param actions list of actions (list of E5Action) @param actionType string denoting the action set to remove from. It must be one of "ui" or "wizards". """ for act in actions: try: if actionType == 'ui': self.actions.remove(act) elif actionType == 'wizards': self.wizardsActions.remove(act) except ValueError: pass def getActions(self, actionType): """ Public method to get a list of all actions. @param actionType string denoting the action set to get. It must be one of "ui" or "wizards". @return list of all actions (list of E5Action) """ if actionType == 'ui': return self.actions[:] elif actionType == 'wizards': return self.wizardsActions[:] else: return [] def getMenuAction(self, menuName, actionName): """ Public method to get a reference to an action of a menu. @param menuName name of the menu to search in (string) @param actionName object name of the action to search for (string) @return reference to the menu action (QAction) """ try: menu = self.__menus[menuName] except KeyError: return None for act in menu.actions(): if act.objectName() == actionName: return act return None def getMenuBarAction(self, menuName): """ Public method to get a reference to an action of the main menu. @param menuName name of the menu to search in (string) @return reference to the menu bar action (QAction) """ try: menu = self.__menus[menuName] except KeyError: return None return menu.menuAction() def getMenu(self, name): """ Public method to get a reference to a specific menu. @param name name of the menu (string) @return reference to the menu (QMenu) """ try: return self.__menus[name] except KeyError: return None def registerToolbar(self, name, text, toolbar, category=""): """ Public method to register a toolbar. This method must be called in order to make a toolbar manageable by the UserInterface object. @param name name of the toolbar. This is used as the key into the dictionary of toolbar references. @type str @param text user visible text for the toolbar entry @type str @param toolbar reference to the toolbar to be registered @type QToolBar @param category toolbar category @type str @exception KeyError raised, if a toolbar with the given name was already registered """ if name in self.__toolbars: raise KeyError("Toolbar '{0}' already registered.".format(name)) self.__toolbars[name] = [text, toolbar, category] def reregisterToolbar(self, name, text, category=""): """ Public method to change the visible text for the named toolbar. @param name name of the toolbar to be changed @type str @param text new user visible text for the toolbar entry @type str @param category new toolbar category for the toolbar entry @type str """ if name in self.__toolbars: self.__toolbars[name][0] = text self.__toolbars[name][2] = category def unregisterToolbar(self, name): """ Public method to unregister a toolbar. @param name name of the toolbar (string). """ if name in self.__toolbars: del self.__toolbars[name] def getToolbar(self, name): """ Public method to get a reference to a specific toolbar. @param name name of the toolbar (string) @return reference to the toolbar entry (tuple of string and QToolBar) """ try: return self.__toolbars[name] except KeyError: return None def getToolbarsByCategory(self, category): """ Public method to get a list of toolbars belonging to a given toolbar category. @param category toolbar category @type str @return list of toolbars @rtype list of QToolBar """ toolbars = [] for tbName in self.__toolbars: try: if self.__toolbars[tbName][2] == category: toolbars.append(self.__toolbars[tbName][1]) except IndexError: # backward compatibility; category is not yet supported pass return toolbars def getLocale(self): """ Public method to get the locale of the IDE. @return locale of the IDE (string or None) """ return self.locale def __quit(self): """ Private method to quit the application. """ if self.__shutdown(): e5App().closeAllWindows() @pyqtSlot() def __restart(self, ask=False): """ Private method to restart the application. @param ask flag indicating to ask the user for permission @type bool """ if ask: res = E5MessageBox.yesNo( self, self.tr("Restart application"), self.tr( """The application needs to be restarted. Do it now?"""), yesDefault=True) else: res = True if res and self.__shutdown(): e5App().closeAllWindows() program = sys.executable eric6 = os.path.join(getConfig("ericDir"), "eric6.py") args = [eric6] args.append("--start-session") args.extend(self.__restartArgs) QProcess.startDetached(program, args) def __newWindow(self): """ Private slot to start a new instance of eric6. """ if not Preferences.getUI("SingleApplicationMode"): # start eric6 without any arguments program = sys.executable eric6 = os.path.join(getConfig("ericDir"), "eric6.py") args = [eric6] QProcess.startDetached(program, args) def __initToolsMenus(self, menu): """ Private slot to initialize the various tool menus. @param menu reference to the parent menu @type QMenu """ btMenu = QMenu(self.tr("&Builtin Tools"), self) if self.designer4Act is not None: btMenu.addAction(self.designer4Act) if self.linguist4Act is not None: btMenu.addAction(self.linguist4Act) btMenu.addAction(self.uipreviewerAct) btMenu.addAction(self.trpreviewerAct) btMenu.addAction(self.diffAct) btMenu.addAction(self.compareAct) btMenu.addAction(self.sqlBrowserAct) btMenu.addAction(self.miniEditorAct) btMenu.addAction(self.hexEditorAct) btMenu.addAction(self.iconEditorAct) btMenu.addAction(self.snapshotAct) if self.webBrowserAct: btMenu.addAction(self.webBrowserAct) ptMenu = QMenu(self.tr("&Plugin Tools"), self) ptMenu.aboutToShow.connect(self.__showPluginToolsMenu) utMenu = QMenu(self.tr("&User Tools"), self) utMenu.triggered.connect(self.__toolExecute) utMenu.aboutToShow.connect(self.__showUserToolsMenu) menu.addMenu(btMenu) menu.addMenu(ptMenu) menu.addMenu(utMenu) self.__menus["builtin_tools"] = btMenu self.__menus["plugin_tools"] = ptMenu self.__menus["user_tools"] = utMenu def __showPluginToolsMenu(self): """ Private slot to show the Plugin Tools menu. """ self.showMenu.emit("PluginTools", self.__menus["plugin_tools"]) def __showUserToolsMenu(self): """ Private slot to display the User Tools menu. """ self.__menus["user_tools"].clear() self.__menus["user_tools"].addMenu(self.toolGroupsMenu) act = self.__menus["user_tools"].addAction( self.tr("Configure Tool Groups ..."), self.__toolGroupsConfiguration) act.setData(-1) act = self.__menus["user_tools"].addAction( self.tr("Configure current Tool Group ..."), self.__toolsConfiguration) act.setData(-2) act.setEnabled(self.currentToolGroup >= 0) self.__menus["user_tools"].addSeparator() # add the configurable entries idx = 0 try: for tool in self.toolGroups[self.currentToolGroup][1]: if tool['menutext'] == '--': self.__menus["user_tools"].addSeparator() else: act = self.__menus["user_tools"].addAction( UI.PixmapCache.getIcon(tool['icon']), tool['menutext']) act.setData(idx) idx += 1 except IndexError: # the current tool group might have been deleted act = self.__menus["user_tools"].addAction( self.tr("No User Tools Configured")) act.setData(-3) def __showToolGroupsMenu(self): """ Private slot to display the Tool Groups menu. """ self.toolGroupsMenu.clear() # add the configurable tool groups if self.toolGroups: idx = 0 for toolGroup in self.toolGroups: act = self.toolGroupsMenu.addAction(toolGroup[0]) act.setData(idx) if self.currentToolGroup == idx: font = act.font() font.setBold(True) act.setFont(font) idx += 1 else: act = self.toolGroupsMenu.addAction( self.tr("No User Tools Configured")) act.setData(-3) def __toolGroupSelected(self, act): """ Private slot to set the current tool group. @param act reference to the action that was triggered (QAction) """ self.toolGroupsMenuTriggered = True idx = act.data() if idx is not None: self.currentToolGroup = idx def __showWindowMenu(self): """ Private slot to display the Window menu. """ self.__menus["window"].clear() self.__menus["window"].addActions(self.viewProfileActGrp.actions()) self.__menus["window"].addSeparator() if self.__layoutType == "Toolboxes": self.__menus["window"].addAction(self.ltAct) self.ltAct.setChecked(not self.lToolboxDock.isHidden()) self.__menus["window"].addAction(self.rtAct) self.rtAct.setChecked(not self.lToolboxDock.isHidden()) self.__menus["window"].addAction(self.htAct) self.htAct.setChecked(not self.hToolboxDock.isHidden()) elif self.__layoutType == "Sidebars": self.__menus["window"].addAction(self.lsbAct) self.lsbAct.setChecked(not self.leftSidebar.isHidden()) self.__menus["window"].addAction(self.rsbAct) self.rsbAct.setChecked(not self.rightSidebar.isHidden()) self.__menus["window"].addAction(self.bsbAct) self.bsbAct.setChecked(not self.bottomSidebar.isHidden()) # Insert menu entry for sub-windows self.__menus["window"].addSeparator() self.__menus["window"].addMenu(self.__menus["subwindow"]) # Insert menu entry for toolbar settings self.__menus["window"].addSeparator() self.__menus["window"].addMenu(self.__menus["toolbars"]) # Now do any Source Viewer related stuff. self.viewmanager.showWindowMenu(self.__menus["window"]) self.showMenu.emit("Window", self.__menus["window"]) def __showSubWindowMenu(self): """ Private slot to display the Window menu of the Window menu. """ self.showMenu.emit("Subwindows", self.__menus["subwindow"]) def __populateToolbarsMenu(self, menu): """ Private method to populate a toolbars menu. @param menu reference to the menu to be populated (QMenu) """ menu.clear() for name, (text, tb, _category) in sorted( self.__toolbars.items(), key=lambda t: t[1][0] ): act = menu.addAction(text) act.setCheckable(True) act.setChecked(not tb.isHidden()) act.setData(name) menu.addSeparator() act = menu.addAction(self.tr("&Show all")) act.setData("__SHOW__") act = menu.addAction(self.tr("&Hide all")) act.setData("__HIDE__") def createPopupMenu(self): """ Public method to create the toolbars menu for Qt. @return toolbars menu (QMenu) """ menu = QMenu(self) menu.triggered.connect(self.__TBPopupMenuTriggered) self.__populateToolbarsMenu(menu) return menu def __showToolbarsMenu(self): """ Private slot to display the Toolbars menu. """ self.__populateToolbarsMenu(self.__menus["toolbars"]) def __TBMenuTriggered(self, act): """ Private method to handle the toggle of a toolbar via the Window-> Toolbars submenu. @param act reference to the action that was triggered (QAction) """ name = act.data() if name: if name == "__SHOW__": for _text, tb, _category in self.__toolbars.values(): tb.show() if self.__menus["toolbars"].isTearOffMenuVisible(): self.__menus["toolbars"].hideTearOffMenu() elif name == "__HIDE__": for _text, tb, _category in self.__toolbars.values(): tb.hide() if self.__menus["toolbars"].isTearOffMenuVisible(): self.__menus["toolbars"].hideTearOffMenu() else: tb = self.__toolbars[name][1] if act.isChecked(): tb.show() tb.setEnabled(True) else: tb.hide() def __TBPopupMenuTriggered(self, act): """ Private method to handle the toggle of a toolbar via the QMainWindow Toolbars popup menu. @param act reference to the action that was triggered (QAction) """ name = act.data() if name: if name == "__SHOW__": for _text, tb, _category in self.__toolbars.values(): tb.show() elif name == "__HIDE__": for _text, tb, _category in self.__toolbars.values(): tb.hide() else: tb = self.__toolbars[name][1] if act.isChecked(): tb.show() tb.setEnabled(True) else: tb.hide() if self.__menus["toolbars"].isTearOffMenuVisible(): self.__menus["toolbars"].hideTearOffMenu() def __saveCurrentViewProfile(self, save): """ Private slot to save the window geometries of the active profile. @param save flag indicating that the current profile should be saved (boolean) """ if self.currentProfile and save: # step 1: save the window geometries of the active profile if self.__layoutType in ["Toolboxes", "Sidebars"]: state = self.saveState() self.profiles[self.currentProfile][0] = state if self.__layoutType == "Sidebars": state = self.leftSplitter.saveState() self.profiles[self.currentProfile][2][0] = state state = self.verticalSplitter.saveState() self.profiles[self.currentProfile][2][1] = state state = self.leftSidebar.saveState() self.profiles[self.currentProfile][2][2] = state state = self.bottomSidebar.saveState() self.profiles[self.currentProfile][2][3] = state state = self.rightSplitter.saveState() self.profiles[self.currentProfile][2][4] = state state = self.rightSidebar.saveState() self.profiles[self.currentProfile][2][5] = state # step 2: save the visibility of the windows of the active profile if self.__layoutType == "Toolboxes": self.profiles[self.currentProfile][1][0] = ( self.lToolboxDock.isVisible() ) self.profiles[self.currentProfile][1][1] = ( self.hToolboxDock.isVisible() ) self.profiles[self.currentProfile][1][2] = ( self.rToolboxDock.isVisible() ) elif self.__layoutType == "Sidebars": self.profiles[self.currentProfile][1][0] = ( self.leftSidebar.isVisible() ) self.profiles[self.currentProfile][1][1] = ( self.bottomSidebar.isVisible() ) self.profiles[self.currentProfile][1][2] = ( self.rightSidebar.isVisible() ) Preferences.setUI("ViewProfiles2", self.profiles) def __activateViewProfile(self, name, save=True): """ Private slot to activate a view profile. @param name name of the profile to be activated (string) @param save flag indicating that the current profile should be saved (boolean) """ if self.currentProfile != name or not save: # step 1: save the active profile self.__saveCurrentViewProfile(save) # step 2: set the window geometries of the new profile if self.__layoutType in ["Toolboxes", "Sidebars"]: state = self.profiles[name][0] if not state.isEmpty(): self.restoreState(state) if self.__layoutType == "Sidebars": state = self.profiles[name][2][0] if not state.isEmpty(): self.leftSplitter.restoreState(state) state = self.profiles[name][2][1] if not state.isEmpty(): self.verticalSplitter.restoreState(state) state = self.profiles[name][2][2] if not state.isEmpty(): self.leftSidebar.restoreState(state) state = self.profiles[name][2][3] if not state.isEmpty(): self.bottomSidebar.restoreState(state) state = self.profiles[name][2][4] if not state.isEmpty(): self.rightSplitter.restoreState(state) state = self.profiles[name][2][5] if not state.isEmpty(): self.rightSidebar.restoreState(state) if self.__layoutType == "Toolboxes": # set the corner usages self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) self.setCorner(Qt.BottomRightCorner, Qt.RightDockWidgetArea) # step 3: activate the windows of the new profile if self.__layoutType == "Toolboxes": self.lToolboxDock.setVisible(self.profiles[name][1][0]) self.hToolboxDock.setVisible(self.profiles[name][1][1]) self.rToolboxDock.setVisible(self.profiles[name][1][2]) elif self.__layoutType == "Sidebars": self.leftSidebar.setVisible(self.profiles[name][1][0]) self.bottomSidebar.setVisible(self.profiles[name][1][1]) self.rightSidebar.setVisible(self.profiles[name][1][2]) # step 4: remember the new profile self.currentProfile = name # step 5: make sure that cursor of the shell is visible self.shell.ensureCursorVisible() # step 6: make sure, that the toolbars and window menu are # shown correctly if self.__menus["toolbars"].isTearOffMenuVisible(): self.__showToolbarsMenu() if self.__menus["window"].isTearOffMenuVisible(): self.__showWindowMenu() def __debuggingStarted(self): """ Private slot to handle the start of a debugging session. """ self.setDebugProfile() if self.__layoutType == "Toolboxes": self.__currentRightWidget = self.rToolbox.currentWidget() self.rToolbox.setCurrentWidget(self.debugViewer) self.__currentBottomWidget = self.hToolbox.currentWidget() self.hToolbox.setCurrentWidget(self.shellAssembly) elif self.__layoutType == "Sidebars": self.__currentRightWidget = self.rightSidebar.currentWidget() self.rightSidebar.setCurrentWidget(self.debugViewer) self.__currentBottomWidget = self.bottomSidebar.currentWidget() self.bottomSidebar.setCurrentWidget(self.shellAssembly) def __debuggingDone(self): """ Private slot to handle the end of a debugging session. """ self.__setEditProfile() if self.__layoutType == "Toolboxes": if self.__currentRightWidget: self.rToolbox.setCurrentWidget(self.__currentRightWidget) if self.__currentBottomWidget: self.hToolbox.setCurrentWidget(self.__currentBottomWidget) elif self.__layoutType == "Sidebars": if self.__currentRightWidget: self.rightSidebar.setCurrentWidget(self.__currentRightWidget) if self.__currentBottomWidget: self.bottomSidebar.setCurrentWidget(self.__currentBottomWidget) self.__currentRightWidget = None self.__currentBottomWidget = None self.__activateViewmanager() @pyqtSlot() def __setEditProfile(self, save=True): """ Private slot to activate the edit view profile. @param save flag indicating that the current profile should be saved (boolean) """ self.__activateViewProfile("edit", save) self.setEditProfileAct.setChecked(True) @pyqtSlot() def setDebugProfile(self, save=True): """ Public slot to activate the debug view profile. @param save flag indicating that the current profile should be saved (boolean) """ self.viewmanager.searchWidget().hide() self.viewmanager.replaceWidget().hide() self.__activateViewProfile("debug", save) self.setDebugProfileAct.setChecked(True) def getViewProfile(self): """ Public method to get the current view profile. @return the name of the current view profile (string) """ return self.currentProfile def getLayoutType(self): """ Public method to get the current layout type. @return current layout type @rtype str """ return self.__layoutType def __activateProjectBrowser(self): """ Private slot to handle the activation of the project browser. """ if self.__layoutType == "Toolboxes": self.lToolboxDock.show() self.lToolbox.setCurrentWidget(self.projectBrowser) elif self.__layoutType == "Sidebars": self.leftSidebar.show() self.leftSidebar.setCurrentWidget(self.projectBrowser) self.projectBrowser.currentWidget().setFocus( Qt.ActiveWindowFocusReason) def __activateMultiProjectBrowser(self): """ Private slot to handle the activation of the project browser. """ if self.__layoutType == "Toolboxes": self.lToolboxDock.show() self.lToolbox.setCurrentWidget(self.multiProjectBrowser) elif self.__layoutType == "Sidebars": self.leftSidebar.show() self.leftSidebar.setCurrentWidget(self.multiProjectBrowser) self.multiProjectBrowser.setFocus(Qt.ActiveWindowFocusReason) def activateDebugViewer(self): """ Public slot to handle the activation of the debug viewer. """ if self.__layoutType == "Toolboxes": self.rToolboxDock.show() self.rToolbox.setCurrentWidget(self.debugViewer) elif self.__layoutType == "Sidebars": self.rightSidebar.show() self.rightSidebar.setCurrentWidget(self.debugViewer) self.debugViewer.currentWidget().setFocus(Qt.ActiveWindowFocusReason) def __activateShell(self): """ Private slot to handle the activation of the Shell window. """ if self.__layoutType == "Toolboxes": self.__shellParent.show() self.__shellParent.widget().setCurrentWidget(self.shellAssembly) elif self.__layoutType == "Sidebars": self.__shellParent.show() self.__shellParent.setCurrentWidget(self.shellAssembly) self.shell.setFocus(Qt.ActiveWindowFocusReason) def __activateLogViewer(self): """ Private slot to handle the activation of the Log Viewer. """ if self.__layoutType == "Toolboxes": self.hToolboxDock.show() self.hToolbox.setCurrentWidget(self.logViewer) elif self.__layoutType == "Sidebars": self.bottomSidebar.show() self.bottomSidebar.setCurrentWidget(self.logViewer) self.logViewer.setFocus(Qt.ActiveWindowFocusReason) def __activateTaskViewer(self): """ Private slot to handle the activation of the Task Viewer. """ if self.__layoutType == "Toolboxes": self.hToolboxDock.show() self.hToolbox.setCurrentWidget(self.taskViewer) elif self.__layoutType == "Sidebars": self.bottomSidebar.show() self.bottomSidebar.setCurrentWidget(self.taskViewer) self.taskViewer.setFocus(Qt.ActiveWindowFocusReason) def __activateTemplateViewer(self): """ Private slot to handle the activation of the Template Viewer. """ if self.templateViewer is not None: if self.__layoutType == "Toolboxes": self.lToolboxDock.show() self.lToolbox.setCurrentWidget(self.templateViewer) elif self.__layoutType == "Sidebars": self.leftSidebar.show() self.leftSidebar.setCurrentWidget(self.templateViewer) self.templateViewer.setFocus(Qt.ActiveWindowFocusReason) def __activateBrowser(self): """ Private slot to handle the activation of the file browser. """ if self.browser is not None: if self.__layoutType == "Toolboxes": self.lToolboxDock.show() self.lToolbox.setCurrentWidget(self.browser) elif self.__layoutType == "Sidebars": self.leftSidebar.show() self.leftSidebar.setCurrentWidget(self.browser) self.browser.setFocus(Qt.ActiveWindowFocusReason) def __toggleLeftToolbox(self): """ Private slot to handle the toggle of the Left Toolbox window. """ hasFocus = self.lToolbox.currentWidget().hasFocus() shown = self.__toggleWindow(self.lToolboxDock) if shown: self.lToolbox.currentWidget().setFocus(Qt.ActiveWindowFocusReason) else: if hasFocus: self.__activateViewmanager() def __toggleRightToolbox(self): """ Private slot to handle the toggle of the Right Toolbox window. """ hasFocus = self.rToolbox.currentWidget().hasFocus() shown = self.__toggleWindow(self.rToolboxDock) if shown: self.rToolbox.currentWidget().setFocus(Qt.ActiveWindowFocusReason) else: if hasFocus: self.__activateViewmanager() def __toggleHorizontalToolbox(self): """ Private slot to handle the toggle of the Horizontal Toolbox window. """ hasFocus = self.hToolbox.currentWidget().hasFocus() shown = self.__toggleWindow(self.hToolboxDock) if shown: self.hToolbox.currentWidget().setFocus(Qt.ActiveWindowFocusReason) else: if hasFocus: self.__activateViewmanager() def __toggleLeftSidebar(self): """ Private slot to handle the toggle of the left sidebar window. """ hasFocus = self.leftSidebar.currentWidget().hasFocus() shown = self.__toggleWindow(self.leftSidebar) if shown: self.leftSidebar.currentWidget().setFocus( Qt.ActiveWindowFocusReason) else: if hasFocus: self.__activateViewmanager() def __toggleRightSidebar(self): """ Private slot to handle the toggle of the right sidebar window. """ hasFocus = self.rightSidebar.currentWidget().hasFocus() shown = self.__toggleWindow(self.rightSidebar) if shown: self.rightSidebar.currentWidget().setFocus( Qt.ActiveWindowFocusReason) else: if hasFocus: self.__activateViewmanager() def __toggleBottomSidebar(self): """ Private slot to handle the toggle of the bottom sidebar window. """ hasFocus = self.bottomSidebar.currentWidget().hasFocus() shown = self.__toggleWindow(self.bottomSidebar) if shown: self.bottomSidebar.currentWidget().setFocus( Qt.ActiveWindowFocusReason) else: if hasFocus: self.__activateViewmanager() def activateCooperationViewer(self): """ Public slot to handle the activation of the cooperation window. """ if self.cooperation is not None: if self.__layoutType == "Toolboxes": self.rToolboxDock.show() self.rToolbox.setCurrentWidget(self.cooperation) elif self.__layoutType == "Sidebars": self.rightSidebar.show() self.rightSidebar.setCurrentWidget(self.cooperation) self.cooperation.setFocus(Qt.ActiveWindowFocusReason) def __activateIRC(self): """ Private slot to handle the activation of the IRC window. """ if self.irc is not None: if self.__layoutType == "Toolboxes": self.rToolboxDock.show() self.rToolbox.setCurrentWidget(self.irc) elif self.__layoutType == "Sidebars": self.rightSidebar.show() self.rightSidebar.setCurrentWidget(self.irc) self.irc.setFocus(Qt.ActiveWindowFocusReason) def __activateSymbolsViewer(self): """ Private slot to handle the activation of the Symbols Viewer. """ if self.symbolsViewer is not None: if self.__layoutType == "Toolboxes": self.lToolboxDock.show() self.lToolbox.setCurrentWidget(self.symbolsViewer) elif self.__layoutType == "Sidebars": self.leftSidebar.show() self.leftSidebar.setCurrentWidget(self.symbolsViewer) self.symbolsViewer.setFocus(Qt.ActiveWindowFocusReason) def __activateNumbersViewer(self): """ Private slot to handle the activation of the Numbers Viewer. """ if self.numbersViewer is not None: if self.__layoutType == "Toolboxes": self.hToolboxDock.show() self.hToolbox.setCurrentWidget(self.numbersViewer) elif self.__layoutType == "Sidebars": self.bottomSidebar.show() self.bottomSidebar.setCurrentWidget(self.numbersViewer) self.numbersViewer.setFocus(Qt.ActiveWindowFocusReason) def __activateViewmanager(self): """ Private slot to handle the activation of the current editor. """ aw = self.viewmanager.activeWindow() if aw is not None: aw.setFocus(Qt.ActiveWindowFocusReason) def activateCodeDocumentationViewer(self, switchFocus=True): """ Public slot to handle the activation of the Code Documentation Viewer. @param switchFocus flag indicating to transfer the input focus @type bool """ if self.codeDocumentationViewer is not None: if self.__layoutType == "Toolboxes": self.rToolboxDock.show() self.rToolbox.setCurrentWidget(self.codeDocumentationViewer) elif self.__layoutType == "Sidebars": self.rightSidebar.show() self.rightSidebar.setCurrentWidget( self.codeDocumentationViewer) if switchFocus: self.codeDocumentationViewer.setFocus( Qt.ActiveWindowFocusReason) def __activatePipWidget(self): """ Private slot to handle the activation of the PyPI manager widget. """ if self.pipWidget is not None: if self.__layoutType == "Toolboxes": self.rToolboxDock.show() self.rToolbox.setCurrentWidget(self.pipWidget) elif self.__layoutType == "Sidebars": self.rightSidebar.show() self.rightSidebar.setCurrentWidget(self.pipWidget) self.pipWidget.setFocus(Qt.ActiveWindowFocusReason) def __activateCondaWidget(self): """ Private slot to handle the activation of the Conda manager widget. """ if self.condaWidget is not None: if self.__layoutType == "Toolboxes": self.rToolboxDock.show() self.rToolbox.setCurrentWidget(self.condaWidget) elif self.__layoutType == "Sidebars": self.rightSidebar.show() self.rightSidebar.setCurrentWidget(self.condaWidget) self.condaWidget.setFocus(Qt.ActiveWindowFocusReason) def __activateMicroPython(self): """ Private slot to handle the activation of the MicroPython widget. """ if self.microPythonWidget is not None: if self.__layoutType == "Toolboxes": self.rToolboxDock.show() self.rToolbox.setCurrentWidget(self.microPythonWidget) elif self.__layoutType == "Sidebars": self.rightSidebar.show() self.rightSidebar.setCurrentWidget(self.microPythonWidget) self.microPythonWidget.setFocus(Qt.ActiveWindowFocusReason) def __toggleWindow(self, w): """ Private method to toggle a workspace editor window. @param w reference to the workspace editor window @return flag indicating, if the window was shown (boolean) """ if w.isHidden(): w.show() return True else: w.hide() return False def __toolsConfiguration(self): """ Private slot to handle the tools configuration menu entry. """ from Preferences.ToolConfigurationDialog import ToolConfigurationDialog dlg = ToolConfigurationDialog( self.toolGroups[self.currentToolGroup][1], self) if dlg.exec() == QDialog.Accepted: self.toolGroups[self.currentToolGroup][1] = dlg.getToollist() self.__updateExternalToolsActions() def __toolGroupsConfiguration(self): """ Private slot to handle the tool groups configuration menu entry. """ from Preferences.ToolGroupConfigurationDialog import ( ToolGroupConfigurationDialog ) dlg = ToolGroupConfigurationDialog( self.toolGroups, self.currentToolGroup, self) if dlg.exec() == QDialog.Accepted: self.toolGroups, self.currentToolGroup = dlg.getToolGroups() def __createUnitTestDialog(self): """ Private slot to generate the unit test dialog on demand. """ if self.unittestDialog is None: from PyUnit.UnittestDialog import UnittestDialog self.unittestDialog = UnittestDialog( None, self.debuggerUI.debugServer, self) self.unittestDialog.unittestFile.connect( self.viewmanager.setFileLine) self.unittestDialog.unittestStopped.connect(self.__unittestStopped) def __unittestStopped(self): """ Private slot to handle the end of a unit test run. """ self.utRerunFailedAct.setEnabled(self.unittestDialog.hasFailedTests()) self.utRestartAct.setEnabled(True) def __unittest(self): """ Private slot for displaying the unittest dialog. """ self.__createUnitTestDialog() self.unittestDialog.show() self.unittestDialog.raise_() @pyqtSlot() @pyqtSlot(str) def __unittestScript(self, prog=None): """ Private slot for displaying the unittest dialog and run the current script. @param prog the python program to be opened """ if prog is None: aw = self.viewmanager.activeWindow() fn = aw.getFileName() tfn = Utilities.getTestFileName(fn) if os.path.exists(tfn): prog = tfn else: prog = fn self.__unittest() self.unittestDialog.setProjectMode(False) self.unittestDialog.insertProg(prog) self.utRestartAct.setEnabled(False) self.utRerunFailedAct.setEnabled(False) def __unittestProject(self): """ Private slot for displaying the unittest dialog and run the current project. """ prog = None fn = self.project.getMainScript(True) if fn: tfn = Utilities.getTestFileName(fn) if os.path.exists(tfn): prog = tfn else: prog = fn self.__unittest() self.unittestDialog.setProjectMode(True) self.unittestDialog.insertProg(prog) self.utRestartAct.setEnabled(False) self.utRerunFailedAct.setEnabled(False) def __unittestRestart(self): """ Private slot to display the unittest dialog and rerun the last unit test. """ self.__unittest() self.unittestDialog.startTests() def __unittestRerunFailed(self): """ Private slot to display the unittest dialog and rerun all failed tests of the last run. """ self.__unittest() self.unittestDialog.startTests(failedOnly=True) @pyqtSlot() @pyqtSlot(str) def __designer(self, fn=None): """ Private slot to start the Qt-Designer executable. @param fn filename of the form to be opened @type str """ args = [] if fn is not None: try: if os.path.isfile(fn) and os.path.getsize(fn): args.append(fn) else: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return except OSError: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return if Utilities.isMacPlatform(): designer, args = Utilities.prepareQtMacBundle( "designer", args) else: designer = os.path.join( Utilities.getQtBinariesPath(), Utilities.generateQtToolName("designer")) if Utilities.isWindowsPlatform(): designer += '.exe' if designer: proc = QProcess() if not proc.startDetached(designer, args): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start Qt-Designer.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(designer) ) else: E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not find the Qt-Designer executable.<br>' 'Ensure that it is installed and optionally configured on' ' the Qt configuration page.</p>' ) ) @pyqtSlot() @pyqtSlot(str) def __linguist(self, fn=None): """ Private slot to start the Qt-Linguist executable. @param fn filename of the translation file to be opened @type str """ args = [] if fn is not None: fn = fn.replace('.qm', '.ts') try: if ( os.path.isfile(fn) and os.path.getsize(fn) and fn not in args ): args.append(fn) else: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return except OSError: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return if Utilities.isMacPlatform(): linguist, args = Utilities.prepareQtMacBundle( "linguist", args) else: linguist = os.path.join( Utilities.getQtBinariesPath(), Utilities.generateQtToolName("linguist")) if Utilities.isWindowsPlatform(): linguist += '.exe' if linguist: proc = QProcess() if not proc.startDetached(linguist, args): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start Qt-Linguist.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(linguist) ) else: E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not find the Qt-Linguist executable.<br>' 'Ensure that it is installed and optionally configured on' ' the Qt configuration page.</p>' ) ) def __assistant(self, home=None): """ Private slot to start the Qt-Assistant executable. @param home full pathname of a file to display @type str """ args = [] if home: args.append('-showUrl') args.append(home) if Utilities.isMacPlatform(): assistant, args = Utilities.prepareQtMacBundle( "assistant", args) else: assistant = os.path.join( Utilities.getQtBinariesPath(), Utilities.generateQtToolName("assistant")) if Utilities.isWindowsPlatform(): assistant += '.exe' if assistant: proc = QProcess() if not proc.startDetached(assistant, args): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start Qt-Assistant.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(assistant) ) else: E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not find the Qt-Assistant executable.<br>' 'Ensure that it is installed and optionally configured on' ' the Qt configuration page.</p>' ) ) def __startWebBrowser(self): """ Private slot to start the eric6 web browser. """ self.launchHelpViewer("") def __customViewer(self, home=None): """ Private slot to start a custom viewer. @param home full pathname of a file to display (string) """ customViewer = Preferences.getHelp("CustomViewer") if not customViewer: E5MessageBox.information( self, self.tr("Help"), self.tr( """Currently no custom viewer is selected.""" """ Please use the preferences dialog to specify one.""")) return proc = QProcess() args = [] if home: args.append(home) if not proc.startDetached(customViewer, args): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start custom viewer.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(customViewer)) def __chmViewer(self, home=None): """ Private slot to start the win help viewer to show *.chm files. @param home full pathname of a file to display (string) """ if home: proc = QProcess() args = [] args.append(home) if not proc.startDetached("hh", args): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start the help viewer.<br>' 'Ensure that it is available as <b>hh</b>.</p>' )) @pyqtSlot() @pyqtSlot(str) def __UIPreviewer(self, fn=None): """ Private slot to start the UI Previewer executable. @param fn filename of the form to be previewed (string) """ proc = QProcess() viewer = os.path.join(getConfig("ericDir"), "eric6_uipreviewer.py") args = [] args.append(viewer) if fn is not None: try: if os.path.isfile(fn) and os.path.getsize(fn): args.append(fn) else: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return except OSError: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return if ( not os.path.isfile(viewer) or not proc.startDetached(sys.executable, args) ): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start UI Previewer.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(viewer)) @pyqtSlot() @pyqtSlot(str) @pyqtSlot(str, bool) def __TRPreviewer(self, fileNames=None, ignore=False): """ Private slot to start the Translation Previewer executable. @param fileNames filenames of forms and/or translations to be previewed (list of strings) @param ignore flag indicating non existing files should be ignored (boolean) """ proc = QProcess() viewer = os.path.join(getConfig("ericDir"), "eric6_trpreviewer.py") args = [] args.append(viewer) if fileNames is not None: for fn in fileNames: try: if os.path.isfile(fn) and os.path.getsize(fn): args.append(fn) else: if not ignore: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return except OSError: if not ignore: E5MessageBox.critical( self, self.tr('Problem'), self.tr( '<p>The file <b>{0}</b> does not exist or' ' is zero length.</p>') .format(fn)) return if ( not os.path.isfile(viewer) or not proc.startDetached(sys.executable, args) ): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start Translation Previewer.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(viewer)) def __sqlBrowser(self): """ Private slot to start the SQL browser tool. """ proc = QProcess() browser = os.path.join(getConfig("ericDir"), "eric6_sqlbrowser.py") args = [] args.append(browser) if ( not os.path.isfile(browser) or not proc.startDetached(sys.executable, args) ): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start SQL Browser.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(browser)) @pyqtSlot() @pyqtSlot(str) def __openHexEditor(self, fn=""): """ Private slot to open the hex editor window. @param fn filename of the file to show (string) """ from HexEdit.HexEditMainWindow import HexEditMainWindow dlg = HexEditMainWindow(fn, self, fromEric=True, project=self.project) dlg.show() @pyqtSlot() @pyqtSlot(str) def __editPixmap(self, fn=""): """ Private slot to show a pixmap in a dialog. @param fn filename of the file to show (string) """ from IconEditor.IconEditorWindow import IconEditorWindow dlg = IconEditorWindow(fn, self, fromEric=True, project=self.project) dlg.show() @pyqtSlot() @pyqtSlot(str) def __showPixmap(self, fn): """ Private slot to show a pixmap in a dialog. @param fn filename of the file to show (string) """ from Graphics.PixmapDiagram import PixmapDiagram dlg = PixmapDiagram(fn, self) if dlg.getStatus(): dlg.show() @pyqtSlot() @pyqtSlot(str) def __showSvg(self, fn): """ Private slot to show a SVG file in a dialog. @param fn filename of the file to show (string) """ from Graphics.SvgDiagram import SvgDiagram dlg = SvgDiagram(fn, self) dlg.show() def __snapshot(self): """ Private slot to start the snapshot tool. """ proc = QProcess() snap = os.path.join(getConfig("ericDir"), "eric6_snap.py") args = [] args.append(snap) if ( not os.path.isfile(snap) or not proc.startDetached(sys.executable, args) ): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start Snapshot tool.<br>' 'Ensure that it is available as <b>{0}</b>.</p>' ).format(snap)) def __toolActionTriggered(self, act): """ Private slot called by external tools toolbar actions. @param act reference to the action that triggered the slot @type QAction """ toolGroupName, toolMenuText = act.objectName().split('@@', 1) for toolGroup in self.toolGroups: if toolGroup[0] == toolGroupName: for tool in toolGroup[1]: if tool['menutext'] == toolMenuText: self.__startToolProcess(tool) return E5MessageBox.information( self, self.tr("External Tools"), self.tr( """No tool entry found for external tool '{0}' """ """in tool group '{1}'.""") .format(toolMenuText, toolGroupName)) return E5MessageBox.information( self, self.tr("External Tools"), self.tr("""No toolgroup entry '{0}' found.""") .format(toolGroupName) ) def __toolExecute(self, act): """ Private slot to execute a particular tool. @param act reference to the action that was triggered (QAction) """ if self.toolGroupsMenuTriggered: # ignore actions triggered from the select tool group submenu self.toolGroupsMenuTriggered = False return if self.currentToolGroup < 0: # it was an action not to be handled here return idx = act.data() if idx is not None and idx >= 0: tool = self.toolGroups[self.currentToolGroup][1][idx] self.__startToolProcess(tool) def __startToolProcess(self, tool): """ Private slot to start an external tool process. @param tool list of tool entries """ proc = QProcess() procData = (None,) program = tool['executable'] args = [] argv = Utilities.parseOptionString(tool['arguments']) args.extend(argv) t = self.tr("Starting process '{0} {1}'.\n" ).format(program, tool['arguments']) self.appendToStdout(t) proc.finished.connect(self.__toolFinished) if tool['redirect'] != 'no': proc.readyReadStandardOutput.connect(self.__processToolStdout) proc.readyReadStandardError.connect(self.__processToolStderr) if tool['redirect'] in ["insert", "replaceSelection"]: aw = self.viewmanager.activeWindow() procData = (aw, tool['redirect'], []) if aw is not None: aw.beginUndoAction() proc.start(program, args) if not proc.waitForStarted(): E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( '<p>Could not start the tool entry <b>{0}</b>.<br>' 'Ensure that it is available as <b>{1}</b>.</p>') .format(tool['menutext'], tool['executable'])) else: self.toolProcs.append((program, proc, procData)) if tool['redirect'] == 'no': proc.closeReadChannel(QProcess.StandardOutput) proc.closeReadChannel(QProcess.StandardError) proc.closeWriteChannel() def __processToolStdout(self): """ Private slot to handle the readyReadStdout signal of a tool process. """ ioEncoding = Preferences.getSystem("IOEncoding") # loop through all running tool processes for program, toolProc, toolProcData in self.toolProcs: toolProc.setReadChannel(QProcess.StandardOutput) if ( toolProcData[0] is None or toolProcData[1] not in ["insert", "replaceSelection"] ): # not connected to an editor or wrong mode while toolProc.canReadLine(): output = str(toolProc.readLine(), ioEncoding, 'replace') s = "{0} - {1}".format(program, output) self.appendToStdout(s) else: if toolProcData[1] == "insert": text = str(toolProc.readAll(), ioEncoding, 'replace') toolProcData[0].insert(text) elif toolProcData[1] == "replaceSelection": text = str(toolProc.readAll(), ioEncoding, 'replace') toolProcData[2].append(text) def __processToolStderr(self): """ Private slot to handle the readyReadStderr signal of a tool process. """ ioEncoding = Preferences.getSystem("IOEncoding") # loop through all running tool processes for program, toolProc, _toolProcData in self.toolProcs: toolProc.setReadChannel(QProcess.StandardError) while toolProc.canReadLine(): error = str(toolProc.readLine(), ioEncoding, 'replace') s = "{0} - {1}".format(program, error) self.appendToStderr(s) def __toolFinished(self, exitCode, exitStatus): """ Private slot to handle the finished signal of a tool process. @param exitCode exit code of the process (integer) @param exitStatus exit status of the process (QProcess.ExitStatus) """ exitedProcs = [] # loop through all running tool processes for program, toolProc, toolProcData in self.toolProcs: if toolProc.state() == QProcess.NotRunning: exitedProcs.append((program, toolProc, toolProcData)) if toolProcData[0] is not None: if toolProcData[1] == "replaceSelection": text = ''.join(toolProcData[2]) toolProcData[0].replace(text) toolProcData[0].endUndoAction() # now delete the exited procs from the list of running processes for proc in exitedProcs: self.toolProcs.remove(proc) t = self.tr("Process '{0}' has exited.\n").format(proc[0]) self.appendToStdout(t) def __showPythonDoc(self): """ Private slot to show the Python 3 documentation. """ pythonDocDir = Preferences.getHelp("PythonDocDir") if not pythonDocDir: if Utilities.isWindowsPlatform(): venvName = Preferences.getDebugger("Python3VirtualEnv") interpreter = ( e5App().getObject("VirtualEnvManager") .getVirtualenvInterpreter(venvName) ) if interpreter: default = os.path.join(os.path.dirname(interpreter), "doc") else: default = "" pythonDocDir = Utilities.getEnvironmentEntry( "PYTHON3DOCDIR", default) else: pythonDocDir = Utilities.getEnvironmentEntry( "PYTHON3DOCDIR", '/usr/share/doc/packages/python3/html') if not pythonDocDir.startswith(("http://", "https://", "qthelp://")): if pythonDocDir.startswith("file://"): pythonDocDir = pythonDocDir[7:] if not os.path.splitext(pythonDocDir)[1]: home = Utilities.normjoinpath(pythonDocDir, 'index.html') if Utilities.isWindowsPlatform() and not os.path.exists(home): pyversion = sys.hexversion >> 16 vers = "{0:d}{1:d}".format((pyversion >> 8) & 0xff, pyversion & 0xff) home = os.path.join( pythonDocDir, "python{0}.chm".format(vers)) else: home = pythonDocDir if not os.path.exists(home): E5MessageBox.warning( self, self.tr("Documentation Missing"), self.tr("""<p>The documentation starting point""" """ "<b>{0}</b>" could not be found.</p>""") .format(home)) return if not home.endswith(".chm"): if Utilities.isWindowsPlatform(): home = "file:///" + Utilities.fromNativeSeparators(home) else: home = "file://" + home else: home = pythonDocDir if home.endswith(".chm"): self.__chmViewer(home) else: hvType = Preferences.getWebBrowser("HelpViewerType") if hvType == 1: self.launchHelpViewer(home) elif hvType == 2: if home.startswith("qthelp://"): self.__assistant(home) else: self.__webBrowser(home) elif hvType == 3: self.__webBrowser(home) else: self.__customViewer(home) def __showQt5Doc(self): """ Private slot to show the Qt5 documentation. """ self.__showQtDoc(5) def __showQtDoc(self, version): """ Private method to show the Qt documentation. @param version Qt version to show documentation for (integer) """ if version == 5: qtDocDir = Preferences.getQt5DocDir() if qtDocDir.startswith("qthelp://"): if not os.path.splitext(qtDocDir)[1]: home = qtDocDir + "/index.html" else: home = qtDocDir elif qtDocDir.startswith(("http://", "https://")): home = qtDocDir else: if qtDocDir.startswith("file://"): qtDocDir = qtDocDir[7:] if not os.path.splitext(qtDocDir)[1]: home = Utilities.normjoinpath(qtDocDir, 'index.html') else: home = qtDocDir if not os.path.exists(home): E5MessageBox.warning( self, self.tr("Documentation Missing"), self.tr("""<p>The documentation starting point""" """ "<b>{0}</b>" could not be found.</p>""") .format(home)) return if Utilities.isWindowsPlatform(): home = "file:///" + Utilities.fromNativeSeparators(home) else: home = "file://" + home hvType = Preferences.getWebBrowser("HelpViewerType") if hvType == 1: self.launchHelpViewer(home) elif hvType == 2: if home.startswith("qthelp://"): self.__assistant(home) else: self.__webBrowser(home) elif hvType == 3: self.__webBrowser(home) else: self.__customViewer(home) def __showPyQt5Doc(self): """ Private slot to show the PyQt5 documentation. """ pyqt5DocDir = Preferences.getHelp("PyQt5DocDir") if not pyqt5DocDir: pyqt5DocDir = Utilities.getEnvironmentEntry("PYQT5DOCDIR", None) if not pyqt5DocDir: E5MessageBox.warning( self, self.tr("Documentation"), self.tr("""<p>The PyQt5 documentation starting point""" """ has not been configured.</p>""")) return if not pyqt5DocDir.startswith(("http://", "https://", "qthelp://")): home = "" if pyqt5DocDir: if pyqt5DocDir.startswith("file://"): pyqt5DocDir = pyqt5DocDir[7:] if not os.path.splitext(pyqt5DocDir)[1]: possibleHomes = [ Utilities.normjoinpath( pyqt5DocDir, 'index.html'), Utilities.normjoinpath( pyqt5DocDir, 'class_reference.html'), ] for possibleHome in possibleHomes: if os.path.exists(possibleHome): home = possibleHome break else: home = pyqt5DocDir if not home or not os.path.exists(home): E5MessageBox.warning( self, self.tr("Documentation Missing"), self.tr("""<p>The documentation starting point""" """ "<b>{0}</b>" could not be found.</p>""") .format(home)) return if Utilities.isWindowsPlatform(): home = "file:///" + Utilities.fromNativeSeparators(home) else: home = "file://" + home else: home = pyqt5DocDir hvType = Preferences.getWebBrowser("HelpViewerType") if hvType == 1: self.launchHelpViewer(home) elif hvType == 2: if home.startswith("qthelp://"): self.__assistant(home) else: self.__webBrowser(home) elif hvType == 3: self.__webBrowser(home) else: self.__customViewer(home) def __showEricDoc(self): """ Private slot to show the Eric documentation. """ home = Preferences.getHelp("EricDocDir") if not home: home = Utilities.normjoinpath( getConfig('ericDocDir'), "Source", "index.html") if not home.startswith(("http://", "https://", "qthelp://")): if not os.path.exists(home): E5MessageBox.warning( self, self.tr("Documentation Missing"), self.tr("""<p>The documentation starting point""" """ "<b>{0}</b>" could not be found.</p>""") .format(home)) return if Utilities.isWindowsPlatform(): home = "file:///" + Utilities.fromNativeSeparators(home) else: home = "file://" + home hvType = Preferences.getWebBrowser("HelpViewerType") if hvType == 1: self.launchHelpViewer(home) elif hvType == 2: if home.startswith("qthelp://"): self.__assistant(home) else: self.__webBrowser(home) elif hvType == 3: self.__webBrowser(home) else: self.__customViewer(home) def __showPySideDoc(self, variant="2"): """ Private slot to show the PySide2 documentation. @param variant PySide variant (2) @type str """ pysideDocDir = Preferences.getHelp("PySide2DocDir") if not pysideDocDir: pysideDocDir = Utilities.getEnvironmentEntry( "PYSIDE2DOCDIR", None) if not pysideDocDir: E5MessageBox.warning( self, self.tr("Documentation"), self.tr("""<p>The PySide{0} documentation starting point""" """ has not been configured.</p>""").format( variant) ) return if not pysideDocDir.startswith(("http://", "https://", "qthelp://")): if pysideDocDir.startswith("file://"): pysideDocDir = pysideDocDir[7:] if not os.path.splitext(pysideDocDir)[1]: home = Utilities.normjoinpath(pysideDocDir, 'index.html') else: home = pysideDocDir if not os.path.exists(home): E5MessageBox.warning( self, self.tr("Documentation Missing"), self.tr("""<p>The documentation starting point""" """ "<b>{0}</b>" could not be found.</p>""") .format(home)) return if Utilities.isWindowsPlatform(): home = "file:///" + Utilities.fromNativeSeparators(home) else: home = "file://" + home else: home = pysideDocDir hvType = Preferences.getWebBrowser("HelpViewerType") if hvType == 1: self.launchHelpViewer(home) elif hvType == 2: if home.startswith("qthelp://"): self.__assistant(home) else: self.__webBrowser(home) elif hvType == 3: self.__webBrowser(home) else: self.__customViewer(home) @pyqtSlot(QUrl) def handleUrl(self, url): """ Public slot to handle opening a URL. @param url URL to be shown @type QUrl """ self.launchHelpViewer(url) def launchHelpViewer(self, home, searchWord=None, useSingle=False): """ Public slot to start the help viewer/web browser. @param home filename of file to be shown or URL to be opened @type str or QUrl @keyparam searchWord word to search for @type str @keyparam useSingle flag indicating to use a single browser window @type bool """ if isinstance(home, QUrl): home = home.toString(QUrl.None_) if len(home) > 0: homeUrl = QUrl(home) if not homeUrl.scheme(): home = QUrl.fromLocalFile(home).toString() launchResult = self.__launchExternalWebBrowser( home, searchWord=searchWord) if not launchResult: self.__webBrowser(home) def __launchExternalWebBrowser(self, home, searchWord=None): """ Private method to start an external web browser and communicate with it. @param home filename of file to be shown or URL to be opened @type str @keyparam searchWord word to search for @type str @return flag indicating a successful launch @rtype bool """ clientArgs = [] if searchWord: clientArgs.append("--search={0}".format(searchWord)) if self.__webBrowserProcess is None: webBrowsers = [ os.path.join( os.path.dirname(__file__), "..", "eric6_browser.py"), # QtWebEngine based web browser ] process = QProcess() for browser in webBrowsers: args = [ browser, "--quiet", "--qthelp", "--single", "--name={0}".format(self.__webBrowserSAName), home ] process.start(sys.executable, args) if not process.waitForStarted(): E5MessageBox.warning( self, self.tr("Start Web Browser"), self.tr("""The eric6 web browser could not be""" """ started.""")) return False res = self.__connectToWebBrowser(process) if res == 1: # connection unsuccessful return False elif res == 0: # successful break else: return False process.finished.connect(self.__webBrowserFinished) self.__webBrowserProcess = process else: clientArgs.append("--newtab={0}".format(home)) if clientArgs: self.__webBrowserClient.processArgs(clientArgs, disconnect=False) return True def __connectToWebBrowser(self, process): """ Private method to connect to a started web browser. @param process reference to the started web browser process @type QProcess @return error indication (1 = connection not possible, 0 = ok, -1 = server exited with an error code) @rtype int """ from WebBrowser.WebBrowserSingleApplication import ( WebBrowserSingleApplicationClient ) webBrowserClient = WebBrowserSingleApplicationClient( self.__webBrowserSAName) connectCount = 30 while connectCount: res = webBrowserClient.connect() if res != 0: break else: connectCount -= 1 QThread.msleep(1000) QApplication.processEvents() if ( process.state() == QProcess.NotRunning and process.exitStatus() == QProcess.NormalExit and process.exitCode() == 100 ): # Process exited prematurely due to missing pre-requisites return -1 if res <= 0: E5MessageBox.warning( self, self.tr("Start Web Browser"), self.tr("""<p>The eric6 web browser is not started.</p>""" """<p>Reason: {0}</p>""").format( webBrowserClient.errstr()) ) return 1 self.__webBrowserClient = webBrowserClient return 0 def __webBrowserFinished(self): """ Private slot handling the end of the external web browser process. """ self.__webBrowserProcess = None self.__webBrowserClient = None def __webBrowserShutdown(self): """ Private method to shut down the web browser. """ self.__webBrowserClient.processArgs(["--shutdown"], disconnect=False) def __helpViewer(self): """ Private slot to start an empty help viewer/web browser. """ searchWord = self.viewmanager.textForFind(False) if searchWord == "": searchWord = None self.launchHelpViewer("", searchWord=searchWord) def __webBrowser(self, home=""): """ Private slot to start the eric6 web browser. @param home full pathname of a file to display (string) """ started = QDesktopServices.openUrl(QUrl(home)) if not started: E5MessageBox.critical( self, self.tr('Open Browser'), self.tr('Could not start a web browser')) @pyqtSlot() @pyqtSlot(str) def showPreferences(self, pageName=None): """ Public slot to set the preferences. @param pageName name of the configuration page to show (string) """ if self.__configurationDialog is None: # only one invocation at a time is allowed from Preferences.ConfigurationDialog import ConfigurationDialog self.__configurationDialog = ConfigurationDialog( self, 'Configuration', expandedEntries=self.__expandedConfigurationEntries, ) self.__configurationDialog.preferencesChanged.connect( self.__preferencesChanged) self.__configurationDialog.masterPasswordChanged.connect( self.__masterPasswordChanged) self.__configurationDialog.show() if pageName is not None: self.__configurationDialog.showConfigurationPageByName( pageName) elif self.__lastConfigurationPageName: self.__configurationDialog.showConfigurationPageByName( self.__lastConfigurationPageName) else: self.__configurationDialog.showConfigurationPageByName("empty") self.__configurationDialog.exec() QApplication.processEvents() if self.__configurationDialog.result() == QDialog.Accepted: self.__configurationDialog.setPreferences() Preferences.syncPreferences() self.__preferencesChanged() self.__lastConfigurationPageName = ( self.__configurationDialog.getConfigurationPageName() ) self.__expandedConfigurationEntries = ( self.__configurationDialog.getExpandedEntries() ) self.__configurationDialog.deleteLater() self.__configurationDialog = None def __exportPreferences(self): """ Private slot to export the current preferences. """ Preferences.exportPreferences() def __importPreferences(self): """ Private slot to import preferences. """ Preferences.importPreferences() self.__preferencesChanged() def __preferencesChanged(self): """ Private slot to handle a change of the preferences. """ self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) if Preferences.getUI("SingleApplicationMode"): if self.SAServer is None: self.SAServer = E5SingleApplicationServer() else: if self.SAServer is not None: self.SAServer.shutdown() self.SAServer = None self.newWindowAct.setEnabled( not Preferences.getUI("SingleApplicationMode")) self.maxEditorPathLen = Preferences.getUI("CaptionFilenameLength") self.captionShowsFilename = Preferences.getUI("CaptionShowsFilename") if not self.captionShowsFilename: self.__setWindowCaption(editor="") else: aw = self.viewmanager.activeWindow() fn = aw and aw.getFileName() or None if fn: self.__setWindowCaption(editor=fn) else: self.__setWindowCaption(editor="") self.__httpAlternatives = Preferences.getUI("VersionsUrls6") self.performVersionCheck(False) from QScintilla.SpellChecker import SpellChecker SpellChecker.setDefaultLanguage( Preferences.getEditor("SpellCheckingDefaultLanguage")) if self.__layoutType == "Sidebars": delay = Preferences.getUI("SidebarDelay") self.leftSidebar.setDelay(delay) self.bottomSidebar.setDelay(delay) self.rightSidebar.setDelay(delay) if Preferences.getUI("UseSystemProxy"): QNetworkProxyFactory.setUseSystemConfiguration(True) else: self.__proxyFactory = E5NetworkProxyFactory() QNetworkProxyFactory.setApplicationProxyFactory( self.__proxyFactory) QNetworkProxyFactory.setUseSystemConfiguration(False) from HexEdit.HexEditMainWindow import HexEditMainWindow for hexEditor in HexEditMainWindow.windows: hexEditor.preferencesChanged() # set the keyboard input interval interval = Preferences.getUI("KeyboardInputInterval") if interval > 0: QApplication.setKeyboardInputInterval(interval) else: QApplication.setKeyboardInputInterval(-1) if not self.__disableCrashSession: if Preferences.getUI("CrashSessionEnabled"): self.__writeCrashSession() else: self.__deleteCrashSession() self.preferencesChanged.emit() def __masterPasswordChanged(self, oldPassword, newPassword): """ Private slot to handle the change of the master password. @param oldPassword current master password (string) @param newPassword new master password (string) """ import Globals self.masterPasswordChanged.emit(oldPassword, newPassword) Preferences.convertPasswords(oldPassword, newPassword) variant = Globals.getWebBrowserSupport() if variant == "QtWebEngine": from WebBrowser.Passwords.PasswordManager import ( PasswordManager ) pwManager = PasswordManager() pwManager.masterPasswordChanged(oldPassword, newPassword) Utilities.crypto.changeRememberedMaster(newPassword) def __reloadAPIs(self): """ Private slot to reload the api information. """ self.reloadAPIs.emit() def __showExternalTools(self): """ Private slot to display a dialog show a list of external tools used by eric6. """ if self.programsDialog is None: from Preferences.ProgramsDialog import ProgramsDialog self.programsDialog = ProgramsDialog(self) self.programsDialog.show() def __configViewProfiles(self): """ Private slot to configure the various view profiles. """ from Preferences.ViewProfileDialog import ViewProfileDialog dlg = ViewProfileDialog(self.__layoutType, self.profiles['edit'][1], self.profiles['debug'][1]) if dlg.exec() == QDialog.Accepted: edit, debug = dlg.getVisibilities() self.profiles['edit'][1] = edit self.profiles['debug'][1] = debug Preferences.setUI("ViewProfiles2", self.profiles) if self.currentProfile == "edit": self.__setEditProfile(False) elif self.currentProfile == "debug": self.setDebugProfile(False) def __configToolBars(self): """ Private slot to configure the various toolbars. """ from E5Gui.E5ToolBarDialog import E5ToolBarDialog dlg = E5ToolBarDialog(self.toolbarManager) if dlg.exec() == QDialog.Accepted: Preferences.setUI( "ToolbarManagerState", self.toolbarManager.saveState()) def __configShortcuts(self): """ Private slot to configure the keyboard shortcuts. """ if self.shortcutsDialog is None: from Preferences.ShortcutsDialog import ShortcutsDialog self.shortcutsDialog = ShortcutsDialog(self) self.shortcutsDialog.populate() self.shortcutsDialog.show() def __exportShortcuts(self): """ Private slot to export the keyboard shortcuts. """ fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( None, self.tr("Export Keyboard Shortcuts"), "", self.tr("Keyboard shortcut file (*.e4k)"), "", E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) if not fn: return ext = QFileInfo(fn).suffix() if not ext: ex = selectedFilter.split("(*")[1].split(")")[0] if ex: fn += ex from Preferences import Shortcuts Shortcuts.exportShortcuts(fn) def __importShortcuts(self): """ Private slot to import the keyboard shortcuts. """ fn = E5FileDialog.getOpenFileName( None, self.tr("Import Keyboard Shortcuts"), "", self.tr("Keyboard shortcut file (*.e4k)")) if fn: from Preferences import Shortcuts Shortcuts.importShortcuts(fn) def __showCertificatesDialog(self): """ Private slot to show the certificates management dialog. """ from E5Network.E5SslCertificatesDialog import E5SslCertificatesDialog dlg = E5SslCertificatesDialog(self) dlg.exec() def __clearPrivateData(self): """ Private slot to clear the private data lists. """ from .ClearPrivateDataDialog import ClearPrivateDataDialog dlg = ClearPrivateDataDialog(self) if dlg.exec() == QDialog.Accepted: # recent files, recent projects, recent multi projects, # debug histories, shell histories (files, projects, multiProjects, debug, shell, vcs, plugins) = ( dlg.getData() ) if files: # clear list of recently opened files self.viewmanager.clearRecent() if projects: # clear list of recently opened projects and other histories self.project.clearHistories() if multiProjects: # clear list of recently opened multi projects self.multiProject.clearRecent() if debug: # clear the various debug histories self.debuggerUI.clearHistories() if shell: # clear the shell histories self.shell.clearAllHistories() if vcs: # clear the VCS related histories self.pluginManager.clearPluginsPrivateData("version_control") if plugins: # clear private data of plug-ins not covered above self.pluginManager.clearPluginsPrivateData("") Preferences.syncPreferences() def __newProject(self): """ Private slot to handle the NewProject signal. """ self.__setWindowCaption(project=self.project.name) def __projectOpened(self): """ Private slot to handle the projectOpened signal. """ from Debugger.DebugClientCapabilities import HasUnittest self.__setWindowCaption(project=self.project.name) cap = e5App().getObject("DebugServer").getClientCapabilities( self.project.getProjectLanguage()) self.utProjectAct.setEnabled(cap & HasUnittest) self.utProjectOpen = cap & HasUnittest def __projectClosed(self): """ Private slot to handle the projectClosed signal. """ self.__setWindowCaption(project="") self.utProjectAct.setEnabled(False) if not self.utEditorOpen: self.utRestartAct.setEnabled(False) self.utRerunFailedAct.setEnabled(False) self.utProjectOpen = False def __programChange(self, fn): """ Private slot to handle the programChange signal. This primarily is here to set the currentProg variable. @param fn filename to be set as current prog (string) """ # Delete the old program if there was one. if self.currentProg is not None: del self.currentProg self.currentProg = os.path.normpath(fn) def __lastEditorClosed(self): """ Private slot to handle the lastEditorClosed signal. """ self.wizardsMenuAct.setEnabled(False) self.utScriptAct.setEnabled(False) self.utEditorOpen = False if not self.utProjectOpen: self.utRestartAct.setEnabled(False) self.utRerunFailedAct.setEnabled(False) self.__setWindowCaption(editor="") def __editorOpened(self, fn): """ Private slot to handle the editorOpened signal. @param fn filename of the opened editor (string) """ self.wizardsMenuAct.setEnabled( len(self.__menus["wizards"].actions()) > 0) if fn and str(fn) != "None": dbs = e5App().getObject("DebugServer") for language in dbs.getSupportedLanguages(): exts = dbs.getExtensions(language) if fn.endswith(exts): from Debugger.DebugClientCapabilities import HasUnittest cap = dbs.getClientCapabilities(language) self.utScriptAct.setEnabled(cap & HasUnittest) self.utEditorOpen = cap & HasUnittest return if self.viewmanager.getOpenEditor(fn).isPyFile(): self.utScriptAct.setEnabled(True) self.utEditorOpen = True def __checkActions(self, editor): """ Private slot to check some actions for their enable/disable status. @param editor editor window """ if editor: fn = editor.getFileName() else: fn = None if fn: dbs = e5App().getObject("DebugServer") for language in dbs.getSupportedLanguages(): exts = dbs.getExtensions(language) if fn.endswith(exts): from Debugger.DebugClientCapabilities import HasUnittest cap = dbs.getClientCapabilities(language) self.utScriptAct.setEnabled(cap & HasUnittest) self.utEditorOpen = cap & HasUnittest return if editor.isPyFile(): self.utScriptAct.setEnabled(True) self.utEditorOpen = True return self.utScriptAct.setEnabled(False) def __writeTasks(self): """ Private slot to write the tasks data to an XML file (.e6t). """ fn = os.path.join(Utilities.getConfigDir(), "eric6tasks.e6t") f = QFile(fn) ok = f.open(QIODevice.WriteOnly) if not ok: E5MessageBox.critical( self, self.tr("Save tasks"), self.tr( "<p>The tasks file <b>{0}</b> could not be written.</p>") .format(fn)) return from E5XML.TasksWriter import TasksWriter TasksWriter(f, False).writeXML() f.close() def __readTasks(self): """ Private slot to read in the tasks file (.e6t). """ fn = os.path.join(Utilities.getConfigDir(), "eric6tasks.e6t") if not os.path.exists(fn): # try again with the old extension fn = os.path.join(Utilities.getConfigDir(), "eric6tasks.e4t") if not os.path.exists(fn): return f = QFile(fn) if f.open(QIODevice.ReadOnly): from E5XML.TasksReader import TasksReader reader = TasksReader(f, viewer=self.taskViewer) reader.readXML() f.close() else: E5MessageBox.critical( self, self.tr("Read tasks"), self.tr( "<p>The tasks file <b>{0}</b> could not be read.</p>") .format(fn)) def __writeSession(self, filename="", crashSession=False): """ Private slot to write the session data to an XML file (.e5s). @param filename name of a session file to write @type str @param crashSession flag indicating to write a crash session file @type bool @return flag indicating success @rtype bool """ res = False if filename: fn = filename elif crashSession: fn = os.path.join(Utilities.getConfigDir(), "eric6_crash_session.e5s") else: fn = os.path.join(Utilities.getConfigDir(), "eric6session.e5s") f = QFile(fn) if f.open(QIODevice.WriteOnly): from E5XML.SessionWriter import SessionWriter SessionWriter(f, None).writeXML() f.close() res = True else: E5MessageBox.critical( self, self.tr("Save session"), self.tr("<p>The session file <b>{0}</b> could not be" " written.</p>") .format(fn)) return res def __readSession(self, filename=""): """ Private slot to read in the session file (.e5s or .e4s). @param filename name of a session file to read @type str @return flag indicating success @rtype bool """ if filename: fn = filename else: fn = os.path.join(Utilities.getConfigDir(), "eric6session.e5s") if not os.path.exists(fn): fn = os.path.join(Utilities.getConfigDir(), "eric6session.e4s") if not os.path.exists(fn): E5MessageBox.critical( self, self.tr("Read session"), self.tr("<p>The session file <b>{0}</b> could not" " be read.</p>") .format(fn)) fn = "" res = False if fn: f = QFile(fn) if f.open(QIODevice.ReadOnly): from E5XML.SessionReader import SessionReader self.__readingSession = True reader = SessionReader(f, True) reader.readXML() self.__readingSession = False f.close() res = True else: E5MessageBox.critical( self, self.tr("Read session"), self.tr("<p>The session file <b>{0}</b> could not be" " read.</p>") .format(fn)) # Write a crash session after a session was read. self.__writeCrashSession() return res def __saveSessionToFile(self): """ Private slot to save a session to disk. """ sessionFile, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( self, self.tr("Save session"), Utilities.getHomeDir(), self.tr("eric6 Session Files (*.e5s)"), "") if not sessionFile: return ext = QFileInfo(sessionFile).suffix() if not ext: ex = selectedFilter.split("(*")[1].split(")")[0] if ex: sessionFile += ex self.__writeSession(filename=sessionFile) def __loadSessionFromFile(self): """ Private slot to load a session from disk. """ sessionFile = E5FileDialog.getOpenFileName( self, self.tr("Load session"), Utilities.getHomeDir(), self.tr("eric6 Session Files (*.e5s)")) if not sessionFile: return self.__readSession(filename=sessionFile) def __deleteCrashSession(self): """ Private slot to delete the crash session file. """ fn = os.path.join(Utilities.getConfigDir(), "eric6_crash_session.e5s") if os.path.exists(fn): try: os.remove(fn) except OSError: # ignore it silently pass def __writeCrashSession(self): """ Private slot to write a crash session file. """ if ( not self.__readingSession and not self.__disableCrashSession and Preferences.getUI("CrashSessionEnabled") ): self.__writeSession(crashSession=True) def __readCrashSession(self): """ Private method to check for and read a crash session. @return flag indicating a crash session file was found and read @rtype bool """ res = False if ( not self.__disableCrashSession and not self.__noCrashOpenAtStartup and Preferences.getUI("OpenCrashSessionOnStartup") ): fn = os.path.join(Utilities.getConfigDir(), "eric6_crash_session.e5s") if os.path.exists(fn): yes = E5MessageBox.yesNo( self, self.tr("Crash Session found!"), self.tr("""A session file of a crashed session was""" """ found. Shall this session be restored?""")) if yes: res = self.__readSession(filename=fn) return res def showFindFileByNameDialog(self): """ Public slot to show the Find File by Name dialog. """ if self.findFileNameDialog is None: from .FindFileNameDialog import FindFileNameDialog self.findFileNameDialog = FindFileNameDialog(self.project) self.findFileNameDialog.sourceFile.connect( self.viewmanager.openSourceFile) self.findFileNameDialog.designerFile.connect(self.__designer) self.findFileNameDialog.show() self.findFileNameDialog.raise_() self.findFileNameDialog.activateWindow() def showFindFilesDialog(self, txt="", searchDir="", openFiles=False): """ Public slot to show the Find In Files dialog. @keyparam txt text to search for (string) @keyparam searchDir directory to search in (string) @keyparam openFiles flag indicating to operate on open files (boolean) """ if self.findFilesDialog is None: from .FindFileDialog import FindFileDialog self.findFilesDialog = FindFileDialog(self.project) self.findFilesDialog.sourceFile.connect( self.viewmanager.openSourceFile) self.findFilesDialog.designerFile.connect(self.__designer) if searchDir: self.findFilesDialog.setSearchDirectory(searchDir) self.findFilesDialog.show(txt) if openFiles: self.findFilesDialog.setOpenFiles() self.findFilesDialog.raise_() self.findFilesDialog.activateWindow() def showReplaceFilesDialog(self, txt="", searchDir="", openFiles=False): """ Public slot to show the Find & Replace In Files dialog. @keyparam txt text to search for (string) @keyparam searchDir directory to search in (string) @keyparam openFiles flag indicating to operate on open files (boolean) """ if self.replaceFilesDialog is None: from .FindFileDialog import FindFileDialog self.replaceFilesDialog = FindFileDialog( self.project, replaceMode=True) self.replaceFilesDialog.sourceFile.connect( self.viewmanager.openSourceFile) self.replaceFilesDialog.designerFile.connect(self.__designer) if searchDir: self.replaceFilesDialog.setSearchDirectory(searchDir) self.replaceFilesDialog.show(txt) if openFiles: self.replaceFilesDialog.setOpenFiles() self.replaceFilesDialog.raise_() self.replaceFilesDialog.activateWindow() ########################################################## ## Below are slots to handle StdOut and StdErr ########################################################## def appendToStdout(self, s): """ Public slot to append text to the stdout log viewer tab. @param s output to be appended (string) """ self.appendStdout.emit(s) def appendToStderr(self, s): """ Public slot to append text to the stderr log viewer tab. @param s output to be appended (string) """ self.appendStderr.emit(s) ########################################################## ## Below are slots needed by the plugin menu ########################################################## def __showPluginInfo(self): """ Private slot to show the plugin info dialog. """ from PluginManager.PluginInfoDialog import PluginInfoDialog self.__pluginInfoDialog = PluginInfoDialog(self.pluginManager, self) self.__pluginInfoDialog.show() @pyqtSlot() def __installPlugins(self, pluginFileNames=None): """ Private slot to show a dialog to install a new plugin. @param pluginFileNames list of plugin files suggested for installation list of strings """ from PluginManager.PluginInstallDialog import PluginInstallDialog dlg = PluginInstallDialog( self.pluginManager, [] if pluginFileNames is None else pluginFileNames[:], self) dlg.exec() if dlg.restartNeeded(): self.__restart(ask=True) def __deinstallPlugin(self): """ Private slot to show a dialog to uninstall a plugin. """ from PluginManager.PluginUninstallDialog import PluginUninstallDialog dlg = PluginUninstallDialog(self.pluginManager, self) dlg.exec() def showPluginsAvailable(self): """ Public slot to show the plugins available for download. """ from PluginManager.PluginRepositoryDialog import PluginRepositoryDialog dlg = PluginRepositoryDialog(self.pluginManager, self) res = dlg.exec() if res == (QDialog.Accepted + 1): self.__installPlugins(dlg.getDownloadedPlugins()) def __pluginsConfigure(self): """ Private slot to show the plugin manager configuration page. """ self.showPreferences("pluginManagerPage") def checkPluginUpdatesAvailable(self): """ Public method to check the availability of updates of plug-ins. """ if self.isOnline(): self.pluginManager.checkPluginUpdatesAvailable() ################################################################# ## Drag and Drop Support ################################################################# def dragEnterEvent(self, event): """ Protected method to handle the drag enter event. @param event the drag enter event (QDragEnterEvent) """ self.inDragDrop = event.mimeData().hasUrls() if self.inDragDrop: event.acceptProposedAction() def dragMoveEvent(self, event): """ Protected method to handle the drag move event. @param event the drag move event (QDragMoveEvent) """ if self.inDragDrop: event.acceptProposedAction() def dragLeaveEvent(self, event): """ Protected method to handle the drag leave event. @param event the drag leave event (QDragLeaveEvent) """ if self.inDragDrop: self.inDragDrop = False def dropEvent(self, event): """ Protected method to handle the drop event. @param event the drop event (QDropEvent) """ if event.mimeData().hasUrls(): event.acceptProposedAction() for url in event.mimeData().urls(): fname = url.toLocalFile() if fname: if QFileInfo(fname).isFile(): self.viewmanager.openSourceFile(fname) else: E5MessageBox.information( self, self.tr("Drop Error"), self.tr("""<p><b>{0}</b> is not a file.</p>""") .format(fname)) self.inDragDrop = False ########################################################## ## Below are methods needed for shutting down the IDE ########################################################## def closeEvent(self, event): """ Protected event handler for the close event. This event handler saves the preferences. @param event close event (QCloseEvent) """ if self.__shutdown(): event.accept() if not self.inCloseEvent: self.inCloseEvent = True QTimer.singleShot(0, e5App().closeAllWindows) else: event.ignore() def __shutdown(self): """ Private method to perform all necessary steps to close down the IDE. @return flag indicating success """ if self.shutdownCalled: return True if self.__webBrowserProcess is not None: self.__webBrowserShutdown() if self.irc is not None: if not self.irc.shutdown(): return False sessionCreated = self.__writeSession() self.__astViewer.hide() if not self.project.closeProject(): return False if not self.multiProject.closeMultiProject(): return False if not self.viewmanager.closeViewManager(): return False if sessionCreated and not self.__disableCrashSession: self.__deleteCrashSession() if self.codeDocumentationViewer is not None: self.codeDocumentationViewer.shutdown() self.__previewer.shutdown() self.__astViewer.shutdown() self.shell.closeShell() self.__writeTasks() if self.templateViewer is not None: self.templateViewer.save() if not self.debuggerUI.shutdownServer(): return False self.debuggerUI.shutdown() self.backgroundService.shutdown() if self.cooperation is not None: self.cooperation.shutdown() self.pluginManager.doShutdown() self.virtualenvManager.shutdown() if self.__layoutType == "Sidebars": self.leftSidebar.shutdown() self.bottomSidebar.shutdown() self.rightSidebar.shutdown() if self.SAServer is not None: self.SAServer.shutdown() self.SAServer = None # set proxy factory to None to avoid crashes QNetworkProxyFactory.setApplicationProxyFactory(None) Preferences.setGeometry("MainMaximized", self.isMaximized()) if not self.isMaximized(): Preferences.setGeometry("MainGeometry", self.saveGeometry()) if self.browser is not None: self.browser.saveToplevelDirs() Preferences.setUI( "ToolbarManagerState", self.toolbarManager.saveState()) self.__saveCurrentViewProfile(True) Preferences.saveToolGroups(self.toolGroups, self.currentToolGroup) Preferences.syncPreferences() self.shutdownCalled = True return True def isOnline(self): """ Public method to get the online state. @return online state @rtype bool """ return self.networkIcon.isOnline() def __onlineStateChanged(self, online): """ Private slot handling changes in online state. @param online flag indicating the online state @type bool """ if online: self.performVersionCheck(False) ############################################## ## Below are methods to check for new versions ############################################## def showAvailableVersionsInfo(self): """ Public method to show the eric6 versions available for download. """ self.performVersionCheck(manual=True, showVersions=True) @pyqtSlot() def performVersionCheck(self, manual=True, alternative=0, showVersions=False): """ Public method to check the internet for an eric6 update. @param manual flag indicating an invocation via the menu (boolean) @param alternative index of server to download from (integer) @keyparam showVersions flag indicating the show versions mode (boolean) """ if self.isOnline(): if not manual: if VersionOnly.startswith("@@"): return else: period = Preferences.getUI("PerformVersionCheck") if period == 0: return elif period in [2, 3, 4]: lastCheck = Preferences.Prefs.settings.value( "Updates/LastCheckDate", QDate(1970, 1, 1)) if lastCheck.isValid(): now = QDate.currentDate() if period == 2 and lastCheck.day() == now.day(): # daily return elif period == 3 and lastCheck.daysTo(now) < 7: # weekly return elif period == 4 and (lastCheck.daysTo(now) < lastCheck.daysInMonth()): # monthly return self.__inVersionCheck = True self.manualUpdatesCheck = manual self.showAvailableVersions = showVersions self.httpAlternative = alternative url = QUrl(self.__httpAlternatives[alternative]) self.__versionCheckCanceled = False if manual: if self.__versionCheckProgress is None: self.__versionCheckProgress = E5ProgressDialog( "", self.tr("&Cancel"), 0, len(self.__httpAlternatives), self.tr("%v/%m"), self) self.__versionCheckProgress.setWindowTitle( self.tr("Version Check")) self.__versionCheckProgress.setMinimumDuration(0) self.__versionCheckProgress.canceled.connect( self.__versionsDownloadCanceled) self.__versionCheckProgress.setLabelText( self.tr("Trying host {0}").format(url.host())) self.__versionCheckProgress.setValue(alternative) request = QNetworkRequest(url) request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) reply = self.__networkManager.get(request) reply.finished.connect(lambda: self.__versionsDownloadDone(reply)) self.__replies.append(reply) else: if manual: E5MessageBox.warning( self, self.tr("Error getting versions information"), self.tr("""The versions information cannot not be""" """ downloaded because you are <b>offline</b>.""" """ Please go online and try again.""")) @pyqtSlot() def __versionsDownloadDone(self, reply): """ Private slot called, after the versions file has been downloaded from the internet. @param reply reference to the network reply @type QNetworkReply """ if self.__versionCheckCanceled: self.__inVersionCheck = False if self.__versionCheckProgress is not None: self.__versionCheckProgress.reset() self.__versionCheckProgress = None return reply.deleteLater() if reply in self.__replies: self.__replies.remove(reply) if reply.error() == QNetworkReply.NoError: ioEncoding = Preferences.getSystem("IOEncoding") versions = str(reply.readAll(), ioEncoding, 'replace').splitlines() reply.close() if ( reply.error() != QNetworkReply.NoError or len(versions) == 0 or versions[0].startswith("<") ): # network error or an error page self.httpAlternative += 1 if self.httpAlternative >= len(self.__httpAlternatives): self.__inVersionCheck = False if self.__versionCheckProgress is not None: self.__versionCheckProgress.reset() self.__versionCheckProgress = None firstFailure = Preferences.Prefs.settings.value( "Updates/FirstFailedCheckDate", QDate.currentDate()) failedDuration = firstFailure.daysTo(QDate.currentDate()) Preferences.Prefs.settings.setValue( "Updates/FirstFailedCheckDate", firstFailure) if self.manualUpdatesCheck: E5MessageBox.warning( self, self.tr("Error getting versions information"), self.tr("""The versions information could not be""" """ downloaded.""" """ Please go online and try again.""")) elif failedDuration > 7: E5MessageBox.warning( self, self.tr("Error getting versions information"), self.tr("""The versions information could not be""" """ downloaded for the last 7 days.""" """ Please go online and try again.""")) return else: self.performVersionCheck(self.manualUpdatesCheck, self.httpAlternative, self.showAvailableVersions) return self.__inVersionCheck = False if self.__versionCheckProgress is not None: self.__versionCheckProgress.reset() self.__versionCheckProgress = None self.__updateVersionsUrls(versions) if self.showAvailableVersions: self.__showAvailableVersionInfos(versions) else: Preferences.Prefs.settings.remove("Updates/FirstFailedCheckDate") Preferences.Prefs.settings.setValue( "Updates/LastCheckDate", QDate.currentDate()) self.__versionCheckResult(versions) def __updateVersionsUrls(self, versions): """ Private method to update the URLs from which to retrieve the versions file. @param versions contents of the downloaded versions file (list of strings) """ if len(versions) > 5 and versions[4] == "---": line = 5 urls = [] while line < len(versions): urls.append(versions[line]) line += 1 Preferences.setUI("VersionsUrls6", urls) def __versionCheckResult(self, versions): """ Private method to show the result of the version check action. @param versions contents of the downloaded versions file (list of strings) """ url = "" try: if "snapshot-" in VersionOnly: # check snapshot version like snapshot-20170810 if "snapshot-" in versions[2]: installedSnapshotDate = VersionOnly.rsplit("-", 1)[-1] availableSnapshotDate = versions[2].rsplit("-", 1)[-1] if availableSnapshotDate > installedSnapshotDate: res = E5MessageBox.yesNo( self, self.tr("Update available"), self.tr( """The update to <b>{0}</b> of eric6 is""" """ available at <b>{1}</b>. Would you like""" """ to get it?""") .format(versions[2], versions[3]), yesDefault=True) url = res and versions[3] or '' else: if self.manualUpdatesCheck: E5MessageBox.information( self, self.tr("Update Check"), self.tr( """You are using a snapshot release of""" """ eric6. A more up-to-date stable release""" """ might be available.""")) elif VersionOnly.startswith(("rev_", "@@")): # check installation from source if self.manualUpdatesCheck: E5MessageBox.information( self, self.tr("Update Check"), self.tr( """You installed eric directly from the source""" """ code. There is no possibility to check""" """ for the availability of an update.""")) else: # check release version installedVersionTuple = self.__versionToTuple(VersionOnly) availableVersionTuple = self.__versionToTuple(versions[0]) if availableVersionTuple > installedVersionTuple: res = E5MessageBox.yesNo( self, self.tr("Update available"), self.tr( """The update to <b>{0}</b> of eric6 is""" """ available at <b>{1}</b>. Would you like""" """ to get it?""") .format(versions[0], versions[1]), yesDefault=True) url = res and versions[1] or '' else: if self.manualUpdatesCheck: E5MessageBox.information( self, self.tr("Eric6 is up to date"), self.tr( """You are using the latest version of""" """ eric6""")) except (IndexError, TypeError): E5MessageBox.warning( self, self.tr("Error during updates check"), self.tr("""Could not perform updates check.""")) if url: QDesktopServices.openUrl(QUrl(url)) @pyqtSlot() def __versionsDownloadCanceled(self): """ Private slot called to cancel the version check. """ if self.__replies: self.__versionCheckCanceled = True self.__replies[-1].abort() def __showAvailableVersionInfos(self, versions): """ Private method to show the versions available for download. @param versions contents of the downloaded versions file (list of strings) """ versionText = self.tr( """<h3>Available versions</h3>""" """<table>""") line = 0 while line < len(versions): if versions[line] == "---": break versionText += ( """<tr><td>{0}</td><td><a href="{1}">{2}</a></td></tr>""" ).format( versions[line], versions[line + 1], 'sourceforge' in versions[line + 1] and "SourceForge" or versions[line + 1]) line += 2 versionText += self.tr("""</table>""") self.__versionsDialog = E5MessageBox.E5MessageBox( E5MessageBox.NoIcon, Program, versionText, modal=False, buttons=E5MessageBox.Ok, parent=self ) self.__versionsDialog.setIconPixmap( UI.PixmapCache.getPixmap("eric").scaled(64, 64)) self.__versionsDialog.show() def __sslErrors(self, reply, errors): """ Private slot to handle SSL errors. @param reply reference to the reply object (QNetworkReply) @param errors list of SSL errors (list of QSslError) """ ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0] if ignored == E5SslErrorHandler.NotIgnored: self.__downloadCancelled = True ####################################### ## Below are methods for various checks ####################################### def checkConfigurationStatus(self): """ Public method to check, if eric6 has been configured. If it is not, the configuration dialog is shown. """ if not Preferences.isConfigured(): self.__initDebugToolbarsLayout() E5MessageBox.information( self, self.tr("First time usage"), self.tr("""eric6 has not been configured yet. """ """The configuration dialog will be started.""")) self.showPreferences() def checkProjectsWorkspace(self): """ Public method to check, if a projects workspace has been configured. If it has not, a dialog is shown. """ if not Preferences.isConfigured(): # eric hasn't been configured at all self.checkConfigurationStatus() workspace = Preferences.getMultiProject("Workspace") if workspace == "": default = Utilities.getHomeDir() workspace = E5FileDialog.getExistingDirectory( None, self.tr("Select Workspace Directory"), default, E5FileDialog.Options(E5FileDialog.Option(0))) Preferences.setMultiProject("Workspace", workspace) def versionIsNewer(self, required, snapshot=None): """ Public method to check, if the eric6 version is good compared to the required version. @param required required version (string) @param snapshot required snapshot version (string) @return flag indicating, that the version is newer than the required one (boolean) """ if VersionOnly.startswith("@@"): # development version, always newer return True if VersionOnly.startswith("rev_"): # installed from cloned sources, always newer return True if "snapshot-" in VersionOnly: # check snapshot version if snapshot is None: return True else: vers = VersionOnly.split("snapshot-")[1] return vers > snapshot versionTuple = self.__versionToTuple(VersionOnly) if isinstance(required, str): required = self.__versionToTuple(required) try: res = versionTuple > required except TypeError: # some mismatching types, assume newer res = True return res def __versionToTuple(self, version): """ Private method to convert a version string into a tuple. @param version version string @type str @return version tuple @rtype tuple of int """ versionParts = [] for part in version.split("."): part = part.strip() if part: try: part = int(part) except ValueError: # not an integer, ignore continue versionParts.append(part) return tuple(versionParts) ################################# ## Below are some utility methods ################################# def __getFloatingGeometry(self, w): """ Private method to get the geometry of a floating windows. @param w reference to the widget to be saved (QWidget) @return list giving the widget's geometry and its visibility """ s = w.size() p = w.pos() return [p.x(), p.y(), s.width(), s.height(), not w.isHidden()] def getOriginalPathString(self): """ Public method to get the original PATH environment variable (i.e. before modifications by eric6 and PyQt5). @return original PATH environment variable @rtype str """ return self.__originalPathString ############################ ## some event handlers below ############################ def showEvent(self, evt): """ Protected method to handle the show event. @param evt reference to the show event (QShowEvent) """ if self.__startup: if Preferences.getGeometry("MainMaximized"): self.setWindowState(Qt.WindowStates(Qt.WindowMaximized)) self.__startup = False ########################################## ## Support for desktop notifications below ########################################## def showNotification(self, icon, heading, text, timeout=None): """ Public method to show a desktop notification. @param icon icon to be shown in the notification @type QPixmap @param heading heading of the notification @type str @param text text of the notification @type str @param timeout time in seconds the notification should be shown (None = use configured timeout, 0 = indefinitely) @type int """ if Preferences.getUI("NotificationsEnabled"): if self.__notification is None: from .NotificationWidget import NotificationWidget self.__notification = NotificationWidget(parent=self) self.__notification.setPixmap(icon) self.__notification.setHeading(heading) self.__notification.setText(text) if timeout is None: timeout = Preferences.getUI("NotificationTimeout") self.__notification.setTimeout(timeout) self.__notification.move(Preferences.getUI("NotificationPosition")) self.__notification.show() def notificationsEnabled(self): """ Public method to check, if notifications are enabled. @return flag indicating, if notifications are enabled (boolean) """ return Preferences.getUI("NotificationsEnabled") ######################### ## Support for IRC below ######################### def autoConnectIrc(self): """ Public method to initiate the IRC auto connection. """ if self.irc is not None: self.irc.autoConnect() def __ircAutoConnected(self): """ Private slot handling the automatic connection of the IRC client. """ self.__activateIRC() ############################################### ## Support for Code Documentation Viewer below ############################################### def documentationViewer(self): """ Public method to provide a reference to the code documentation viewer. @return reference to the code documentation viewer @rtype CodeDocumentationViewer """ return self.codeDocumentationViewer