src/eric7/UI/UserInterface.py

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

eric ide

mercurial