eric6/UI/UserInterface.py

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

eric ide

mercurial