src/eric7/UI/UserInterface.py

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

eric ide

mercurial