eric6/UI/UserInterface.py

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

eric ide

mercurial