eric6/Helpviewer/HelpTabWidget.py

changeset 7220
5cf645f6daab
parent 7218
eaf2cf171f3a
parent 7211
1c97f3142fa8
child 7221
0485ccdf7877
equal deleted inserted replaced
7218:eaf2cf171f3a 7220:5cf645f6daab
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the central widget showing the web pages.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13
14 from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QUrl
15 from PyQt5.QtGui import QIcon
16 from PyQt5.QtWidgets import QWidget, QHBoxLayout, QMenu, QToolButton, QDialog
17 from PyQt5.QtPrintSupport import QPrinter, QPrintDialog
18 from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
19
20 from E5Gui.E5TabWidget import E5TabWidget
21 from E5Gui import E5MessageBox
22 from E5Gui.E5Application import e5App
23
24 from .HelpBrowserWV import HelpBrowser
25
26 import UI.PixmapCache
27
28 import Utilities
29 import Preferences
30 import Globals
31
32 from eric6config import getConfig
33
34
35 class HelpTabWidget(E5TabWidget):
36 """
37 Class implementing the central widget showing the web pages.
38
39 @signal sourceChanged(HelpBrowser, QUrl) emitted after the URL of a browser
40 has changed
41 @signal titleChanged(HelpBrowser, str) emitted after the title of a browser
42 has changed
43 @signal showMessage(str) emitted to show a message in the main window
44 status bar
45 @signal browserClosed(QWidget) emitted after a browser was closed
46 @signal browserZoomValueChanged(int) emitted to signal a change of the
47 current browser's zoom level
48 """
49 sourceChanged = pyqtSignal(HelpBrowser, QUrl)
50 titleChanged = pyqtSignal(HelpBrowser, str)
51 showMessage = pyqtSignal(str)
52 browserClosed = pyqtSignal(QWidget)
53 browserZoomValueChanged = pyqtSignal(int)
54
55 def __init__(self, parent):
56 """
57 Constructor
58
59 @param parent reference to the parent widget (QWidget)
60 """
61 E5TabWidget.__init__(self, parent, dnd=True)
62
63 from .HelpTabBar import HelpTabBar
64 self.__tabBar = HelpTabBar(self)
65 self.setCustomTabBar(True, self.__tabBar)
66
67 self.__mainWindow = parent
68
69 self.setUsesScrollButtons(True)
70 self.setDocumentMode(True)
71 self.setElideMode(Qt.ElideNone)
72
73 from .ClosedTabsManager import ClosedTabsManager
74 self.__closedTabsManager = ClosedTabsManager(self)
75 self.__closedTabsManager.closedTabAvailable.connect(
76 self.__closedTabAvailable)
77
78 from .UrlBar.StackedUrlBar import StackedUrlBar
79 self.__stackedUrlBar = StackedUrlBar(self)
80 self.__tabBar.tabMoved.connect(self.__stackedUrlBar.moveBar)
81
82 self.__tabContextMenuIndex = -1
83 self.currentChanged[int].connect(self.__currentChanged)
84 self.setTabContextMenuPolicy(Qt.CustomContextMenu)
85 self.customTabContextMenuRequested.connect(self.__showContextMenu)
86
87 self.__rightCornerWidget = QWidget(self)
88 self.__rightCornerWidgetLayout = QHBoxLayout(self.__rightCornerWidget)
89 self.__rightCornerWidgetLayout.setContentsMargins(0, 0, 0, 0)
90 self.__rightCornerWidgetLayout.setSpacing(0)
91
92 self.__navigationMenu = QMenu(self)
93 self.__navigationMenu.aboutToShow.connect(self.__showNavigationMenu)
94 self.__navigationMenu.triggered.connect(self.__navigationMenuTriggered)
95
96 self.__navigationButton = QToolButton(self)
97 self.__navigationButton.setIcon(
98 UI.PixmapCache.getIcon("1downarrow.png"))
99 self.__navigationButton.setToolTip(
100 self.tr("Show a navigation menu"))
101 self.__navigationButton.setPopupMode(QToolButton.InstantPopup)
102 self.__navigationButton.setMenu(self.__navigationMenu)
103 self.__navigationButton.setEnabled(False)
104 self.__rightCornerWidgetLayout.addWidget(self.__navigationButton)
105
106 self.__closedTabsMenu = QMenu(self)
107 self.__closedTabsMenu.aboutToShow.connect(
108 self.__aboutToShowClosedTabsMenu)
109
110 self.__closedTabsButton = QToolButton(self)
111 self.__closedTabsButton.setIcon(UI.PixmapCache.getIcon("trash.png"))
112 self.__closedTabsButton.setToolTip(
113 self.tr("Show a navigation menu for closed tabs"))
114 self.__closedTabsButton.setPopupMode(QToolButton.InstantPopup)
115 self.__closedTabsButton.setMenu(self.__closedTabsMenu)
116 self.__closedTabsButton.setEnabled(False)
117 self.__rightCornerWidgetLayout.addWidget(self.__closedTabsButton)
118
119 self.setTabsClosable(True)
120 self.tabCloseRequested.connect(self.closeBrowserAt)
121
122 self.setCornerWidget(self.__rightCornerWidget, Qt.TopRightCorner)
123
124 self.__newTabButton = QToolButton(self)
125 self.__newTabButton.setIcon(UI.PixmapCache.getIcon("plus.png"))
126 self.__newTabButton.setToolTip(
127 self.tr("Open a new help window tab"))
128 self.setCornerWidget(self.__newTabButton, Qt.TopLeftCorner)
129 self.__newTabButton.clicked.connect(self.__newBrowser)
130
131 self.__initTabContextMenu()
132
133 self.__historyCompleter = None
134
135 def __initTabContextMenu(self):
136 """
137 Private method to create the tab context menu.
138 """
139 self.__tabContextMenu = QMenu(self)
140 self.tabContextNewAct = self.__tabContextMenu.addAction(
141 UI.PixmapCache.getIcon("tabNew.png"),
142 self.tr('New Tab'), self.newBrowser)
143 self.__tabContextMenu.addSeparator()
144 self.leftMenuAct = self.__tabContextMenu.addAction(
145 UI.PixmapCache.getIcon("1leftarrow.png"),
146 self.tr('Move Left'), self.__tabContextMenuMoveLeft)
147 self.rightMenuAct = self.__tabContextMenu.addAction(
148 UI.PixmapCache.getIcon("1rightarrow.png"),
149 self.tr('Move Right'), self.__tabContextMenuMoveRight)
150 self.__tabContextMenu.addSeparator()
151 self.tabContextCloneAct = self.__tabContextMenu.addAction(
152 self.tr("Duplicate Page"), self.__tabContextMenuClone)
153 self.__tabContextMenu.addSeparator()
154 self.tabContextCloseAct = self.__tabContextMenu.addAction(
155 UI.PixmapCache.getIcon("tabClose.png"),
156 self.tr('Close'), self.__tabContextMenuClose)
157 self.tabContextCloseOthersAct = self.__tabContextMenu.addAction(
158 UI.PixmapCache.getIcon("tabCloseOther.png"),
159 self.tr("Close Others"), self.__tabContextMenuCloseOthers)
160 self.__tabContextMenu.addAction(
161 self.tr('Close All'), self.closeAllBrowsers)
162 self.__tabContextMenu.addSeparator()
163 self.__tabContextMenu.addAction(
164 UI.PixmapCache.getIcon("printPreview.png"),
165 self.tr('Print Preview'), self.__tabContextMenuPrintPreview)
166 self.__tabContextMenu.addAction(
167 UI.PixmapCache.getIcon("print.png"),
168 self.tr('Print'), self.__tabContextMenuPrint)
169 if Globals.isLinuxPlatform():
170 self.__tabContextMenu.addAction(
171 UI.PixmapCache.getIcon("printPdf.png"),
172 self.tr('Print as PDF'), self.__tabContextMenuPrintPdf)
173 self.__tabContextMenu.addSeparator()
174 self.__tabContextMenu.addAction(
175 UI.PixmapCache.getIcon("reload.png"),
176 self.tr('Reload All'), self.reloadAllBrowsers)
177 self.__tabContextMenu.addSeparator()
178 self.__tabContextMenu.addAction(
179 UI.PixmapCache.getIcon("addBookmark.png"),
180 self.tr('Bookmark All Tabs'), self.__mainWindow.bookmarkAll)
181
182 self.__tabBackContextMenu = QMenu(self)
183 self.__tabBackContextMenu.addAction(
184 self.tr('Close All'), self.closeAllBrowsers)
185 self.__tabBackContextMenu.addAction(
186 UI.PixmapCache.getIcon("reload.png"),
187 self.tr('Reload All'), self.reloadAllBrowsers)
188 self.__tabBackContextMenu.addAction(
189 UI.PixmapCache.getIcon("addBookmark.png"),
190 self.tr('Bookmark All Tabs'), self.__mainWindow.bookmarkAll)
191 self.__tabBackContextMenu.addSeparator()
192 self.__restoreClosedTabAct = self.__tabBackContextMenu.addAction(
193 UI.PixmapCache.getIcon("trash.png"),
194 self.tr('Restore Closed Tab'))
195 self.__restoreClosedTabAct.setEnabled(False)
196 self.__restoreClosedTabAct.setData(0)
197 self.__restoreClosedTabAct.triggered.connect(
198 lambda: self.restoreClosedTab(self.__restoreClosedTabAct))
199
200 def __showContextMenu(self, coord, index):
201 """
202 Private slot to show the tab context menu.
203
204 @param coord the position of the mouse pointer (QPoint)
205 @param index index of the tab the menu is requested for (integer)
206 """
207 coord = self.mapToGlobal(coord)
208 if index == -1:
209 self.__tabBackContextMenu.popup(coord)
210 else:
211 self.__tabContextMenuIndex = index
212 self.leftMenuAct.setEnabled(index > 0)
213 self.rightMenuAct.setEnabled(index < self.count() - 1)
214
215 self.tabContextCloseOthersAct.setEnabled(self.count() > 1)
216
217 self.__tabContextMenu.popup(coord)
218
219 def __tabContextMenuMoveLeft(self):
220 """
221 Private method to move a tab one position to the left.
222 """
223 self.moveTab(self.__tabContextMenuIndex,
224 self.__tabContextMenuIndex - 1)
225
226 def __tabContextMenuMoveRight(self):
227 """
228 Private method to move a tab one position to the right.
229 """
230 self.moveTab(self.__tabContextMenuIndex,
231 self.__tabContextMenuIndex + 1)
232
233 def __tabContextMenuClone(self):
234 """
235 Private method to clone the selected tab.
236 """
237 idx = self.__tabContextMenuIndex
238 if idx < 0:
239 idx = self.currentIndex()
240 if idx < 0 or idx > self.count():
241 return
242
243 req = QNetworkRequest(self.widget(idx).url())
244 req.setRawHeader(b"X-Eric6-UserLoadAction", b"1")
245 self.newBrowser(None, (req, QNetworkAccessManager.GetOperation, b""))
246
247 def __tabContextMenuClose(self):
248 """
249 Private method to close the selected tab.
250 """
251 self.closeBrowserAt(self.__tabContextMenuIndex)
252
253 def __tabContextMenuCloseOthers(self):
254 """
255 Private slot to close all other tabs.
256 """
257 index = self.__tabContextMenuIndex
258 for i in list(range(self.count() - 1, index, -1)) + \
259 list(range(index - 1, -1, -1)):
260 self.closeBrowserAt(i)
261
262 def __tabContextMenuPrint(self):
263 """
264 Private method to print the selected tab.
265 """
266 browser = self.widget(self.__tabContextMenuIndex)
267 self.printBrowser(browser)
268
269 def __tabContextMenuPrintPdf(self):
270 """
271 Private method to print the selected tab as PDF.
272 """
273 browser = self.widget(self.__tabContextMenuIndex)
274 self.printBrowserPdf(browser)
275
276 def __tabContextMenuPrintPreview(self):
277 """
278 Private method to show a print preview of the selected tab.
279 """
280 browser = self.widget(self.__tabContextMenuIndex)
281 self.printPreviewBrowser(browser)
282
283 @pyqtSlot()
284 def __newBrowser(self):
285 """
286 Private slot to open a new browser tab.
287 """
288 self.newBrowser()
289
290 def newBrowser(self, link=None, requestData=None, position=-1):
291 """
292 Public method to create a new web browser tab.
293
294 @param link link to be shown (string or QUrl)
295 @param requestData tuple containing the request data (QNetworkRequest,
296 QNetworkAccessManager.Operation, QByteArray)
297 @keyparam position position to create the new tab at or -1 to add it
298 to the end (integer)
299 """
300 if link is None:
301 linkName = ""
302 elif isinstance(link, QUrl):
303 linkName = link.toString()
304 else:
305 linkName = link
306
307 from .UrlBar.UrlBar import UrlBar
308 urlbar = UrlBar(self.__mainWindow, self)
309 if self.__historyCompleter is None:
310 import Helpviewer.HelpWindow
311 from .History.HistoryCompleter import HistoryCompletionModel, \
312 HistoryCompleter
313 self.__historyCompletionModel = HistoryCompletionModel(self)
314 self.__historyCompletionModel.setSourceModel(
315 Helpviewer.HelpWindow.HelpWindow.historyManager()
316 .historyFilterModel())
317 self.__historyCompleter = HistoryCompleter(
318 self.__historyCompletionModel, self)
319 self.__historyCompleter.activated[str].connect(self.__pathSelected)
320 urlbar.setCompleter(self.__historyCompleter)
321 urlbar.returnPressed.connect(
322 lambda: self.__lineEditReturnPressed(urlbar))
323 if position == -1:
324 self.__stackedUrlBar.addWidget(urlbar)
325 else:
326 self.__stackedUrlBar.insertWidget(position, urlbar)
327
328 browser = HelpBrowser(self.__mainWindow, self)
329 urlbar.setBrowser(browser)
330
331 browser.sourceChanged.connect(
332 lambda url: self.__sourceChanged(url, browser))
333 browser.titleChanged.connect(
334 lambda title: self.__titleChanged(title, browser))
335 browser.highlighted.connect(self.showMessage)
336 browser.backwardAvailable.connect(
337 self.__mainWindow.setBackwardAvailable)
338 browser.forwardAvailable.connect(self.__mainWindow.setForwardAvailable)
339 browser.loadStarted.connect(
340 lambda: self.__loadStarted(browser))
341 browser.loadFinished.connect(self.__loadFinished)
342 browser.iconChanged.connect(
343 lambda: self.__iconChanged(browser))
344 browser.search.connect(self.newBrowser)
345 browser.page().windowCloseRequested.connect(
346 lambda: self.__windowCloseRequested(browser.page()))
347 browser.page().printRequested.connect(self.__printRequested)
348 browser.zoomValueChanged.connect(self.browserZoomValueChanged)
349
350 if position == -1:
351 index = self.addTab(browser, self.tr("..."))
352 else:
353 index = self.insertTab(position, browser, self.tr("..."))
354 self.setCurrentIndex(index)
355
356 self.__mainWindow.closeAct.setEnabled(True)
357 self.__mainWindow.closeAllAct.setEnabled(True)
358 self.__navigationButton.setEnabled(True)
359
360 if not linkName and not requestData:
361 if Preferences.getHelp("StartupBehavior") == 0:
362 linkName = Preferences.getHelp("HomePage")
363 elif Preferences.getHelp("StartupBehavior") == 1:
364 linkName = "eric:speeddial"
365
366 if linkName:
367 browser.setSource(QUrl(linkName))
368 if not browser.documentTitle():
369 self.setTabText(index, self.__elide(linkName, Qt.ElideMiddle))
370 self.setTabToolTip(index, linkName)
371 else:
372 self.setTabText(
373 index,
374 self.__elide(browser.documentTitle().replace("&", "&&")))
375 self.setTabToolTip(index, browser.documentTitle())
376 elif requestData:
377 browser.load(*requestData)
378
379 def newBrowserAfter(self, browser, link=None, requestData=None):
380 """
381 Public method to create a new web browser tab after a given one.
382
383 @param browser reference to the browser to add after (HelpBrowser)
384 @param link link to be shown (string or QUrl)
385 @param requestData tuple containing the request data (QNetworkRequest,
386 QNetworkAccessManager.Operation, QByteArray)
387 """
388 if browser:
389 position = self.indexOf(browser) + 1
390 else:
391 position = -1
392 self.newBrowser(link, requestData, position)
393
394 def __showNavigationMenu(self):
395 """
396 Private slot to show the navigation button menu.
397 """
398 self.__navigationMenu.clear()
399 for index in range(self.count()):
400 act = self.__navigationMenu.addAction(
401 self.tabIcon(index), self.tabText(index))
402 act.setData(index)
403
404 def __navigationMenuTriggered(self, act):
405 """
406 Private slot called to handle the navigation button menu selection.
407
408 @param act reference to the selected action (QAction)
409 """
410 index = act.data()
411 if index is not None:
412 self.setCurrentIndex(index)
413
414 def __windowCloseRequested(self, page):
415 """
416 Private slot to handle the windowCloseRequested signal of a browser.
417
418 @param page reference to the web page
419 @type HelpWebPage
420 """
421 browser = page.view()
422 if browser is None:
423 return
424
425 index = self.indexOf(browser)
426 self.closeBrowserAt(index)
427
428 def reloadAllBrowsers(self):
429 """
430 Public slot to reload all browsers.
431 """
432 for index in range(self.count()):
433 browser = self.widget(index)
434 browser and browser.reload()
435
436 @pyqtSlot()
437 def closeBrowser(self):
438 """
439 Public slot called to handle the close action.
440 """
441 self.closeBrowserAt(self.currentIndex())
442
443 def closeAllBrowsers(self):
444 """
445 Public slot called to handle the close all action.
446 """
447 for index in range(self.count() - 1, -1, -1):
448 self.closeBrowserAt(index)
449
450 def closeBrowserAt(self, index):
451 """
452 Public slot to close a browser based on its index.
453
454 @param index index of browser to close (integer)
455 """
456 browser = self.widget(index)
457 if browser is None:
458 return
459
460 if browser.isModified():
461 ok = E5MessageBox.yesNo(
462 self,
463 self.tr("Do you really want to close this page?"),
464 self.tr("""You have modified this page and when closing it"""
465 """ you would lose the modification.\nDo you really"""
466 """ want to close this page?"""))
467 if not ok:
468 return
469
470 urlbar = self.__stackedUrlBar.widget(index)
471 self.__stackedUrlBar.removeWidget(urlbar)
472 urlbar.deleteLater()
473 del urlbar
474
475 self.__closedTabsManager.recordBrowser(browser, index)
476
477 browser.closeWebInspector()
478 browser.home()
479 self.removeTab(index)
480 self.browserClosed.emit(browser)
481 browser.deleteLater()
482 del browser
483
484 if self.count() == 0:
485 self.newBrowser()
486 else:
487 self.currentChanged[int].emit(self.currentIndex())
488
489 def currentBrowser(self):
490 """
491 Public method to get a reference to the current browser.
492
493 @return reference to the current browser (HelpBrowser)
494 """
495 return self.currentWidget()
496
497 def browserAt(self, index):
498 """
499 Public method to get a reference to the browser with the given index.
500
501 @param index index of the browser to get (integer)
502 @return reference to the indexed browser (HelpBrowser)
503 """
504 return self.widget(index)
505
506 def browsers(self):
507 """
508 Public method to get a list of references to all browsers.
509
510 @return list of references to browsers (list of HelpBrowser)
511 """
512 li = []
513 for index in range(self.count()):
514 li.append(self.widget(index))
515 return li
516
517 @pyqtSlot()
518 def printBrowser(self, browser=None):
519 """
520 Public slot called to print the displayed page.
521
522 @param browser reference to the browser to be printed (HelpBrowser)
523 """
524 if browser is None:
525 browser = self.currentBrowser()
526
527 self.__printRequested(browser.page().mainFrame())
528
529 def __printRequested(self, frame):
530 """
531 Private slot to handle a print request.
532
533 @param frame reference to the frame to be printed (QWebFrame)
534 """
535 printer = QPrinter(mode=QPrinter.HighResolution)
536 if Preferences.getPrinter("ColorMode"):
537 printer.setColorMode(QPrinter.Color)
538 else:
539 printer.setColorMode(QPrinter.GrayScale)
540 if Preferences.getPrinter("FirstPageFirst"):
541 printer.setPageOrder(QPrinter.FirstPageFirst)
542 else:
543 printer.setPageOrder(QPrinter.LastPageFirst)
544 printer.setPageMargins(
545 Preferences.getPrinter("LeftMargin") * 10,
546 Preferences.getPrinter("TopMargin") * 10,
547 Preferences.getPrinter("RightMargin") * 10,
548 Preferences.getPrinter("BottomMargin") * 10,
549 QPrinter.Millimeter
550 )
551 printerName = Preferences.getPrinter("PrinterName")
552 if printerName:
553 printer.setPrinterName(printerName)
554
555 printDialog = QPrintDialog(printer, self)
556 if printDialog.exec_() == QDialog.Accepted:
557 try:
558 frame.print_(printer)
559 except AttributeError:
560 E5MessageBox.critical(
561 self,
562 self.tr("eric6 Web Browser"),
563 self.tr(
564 """<p>Printing is not available due to a bug in"""
565 """ PyQt5. Please upgrade.</p>"""))
566 return
567
568 @pyqtSlot()
569 def printBrowserPdf(self, browser=None):
570 """
571 Public slot called to print the displayed page to PDF.
572
573 @param browser reference to the browser to be printed (HelpBrowser)
574 """
575 if browser is None:
576 browser = self.currentBrowser()
577
578 self.__printPdfRequested(browser.page().mainFrame())
579
580 def __printPdfRequested(self, frame):
581 """
582 Private slot to handle a print to PDF request.
583
584 @param frame reference to the frame to be printed (QWebFrame)
585 """
586 printer = QPrinter(mode=QPrinter.HighResolution)
587 if Preferences.getPrinter("ColorMode"):
588 printer.setColorMode(QPrinter.Color)
589 else:
590 printer.setColorMode(QPrinter.GrayScale)
591 printerName = Preferences.getPrinter("PrinterName")
592 if printerName:
593 printer.setPrinterName(printerName)
594 printer.setOutputFormat(QPrinter.PdfFormat)
595 name = frame.url().path().rsplit('/', 1)[-1]
596 if name:
597 name = name.rsplit('.', 1)[0]
598 name += '.pdf'
599 printer.setOutputFileName(name)
600
601 printDialog = QPrintDialog(printer, self)
602 if printDialog.exec_() == QDialog.Accepted:
603 try:
604 frame.print_(printer)
605 except AttributeError:
606 E5MessageBox.critical(
607 self,
608 self.tr("eric6 Web Browser"),
609 self.tr(
610 """<p>Printing is not available due to a bug in"""
611 """ PyQt5. Please upgrade.</p>"""))
612 return
613
614 @pyqtSlot()
615 def printPreviewBrowser(self, browser=None):
616 """
617 Public slot called to show a print preview of the displayed file.
618
619 @param browser reference to the browser to be printed (HelpBrowserWV)
620 """
621 from PyQt5.QtPrintSupport import QPrintPreviewDialog
622
623 if browser is None:
624 browser = self.currentBrowser()
625
626 printer = QPrinter(mode=QPrinter.HighResolution)
627 if Preferences.getPrinter("ColorMode"):
628 printer.setColorMode(QPrinter.Color)
629 else:
630 printer.setColorMode(QPrinter.GrayScale)
631 if Preferences.getPrinter("FirstPageFirst"):
632 printer.setPageOrder(QPrinter.FirstPageFirst)
633 else:
634 printer.setPageOrder(QPrinter.LastPageFirst)
635 printer.setPageMargins(
636 Preferences.getPrinter("LeftMargin") * 10,
637 Preferences.getPrinter("TopMargin") * 10,
638 Preferences.getPrinter("RightMargin") * 10,
639 Preferences.getPrinter("BottomMargin") * 10,
640 QPrinter.Millimeter
641 )
642 printerName = Preferences.getPrinter("PrinterName")
643 if printerName:
644 printer.setPrinterName(printerName)
645
646 self.__printPreviewBrowser = browser
647 preview = QPrintPreviewDialog(printer, self)
648 preview.paintRequested.connect(self.__printPreview)
649 preview.exec_()
650
651 def __printPreview(self, printer):
652 """
653 Private slot to generate a print preview.
654
655 @param printer reference to the printer object (QPrinter)
656 """
657 try:
658 self.__printPreviewBrowser.print_(printer)
659 except AttributeError:
660 E5MessageBox.critical(
661 self,
662 self.tr("eric6 Web Browser"),
663 self.tr(
664 """<p>Printing is not available due to a bug in PyQt5."""
665 """Please upgrade.</p>"""))
666 return
667
668 def __sourceChanged(self, url, browser):
669 """
670 Private slot to handle a change of a browsers source.
671
672 @param url URL of the new site
673 @type QUrl
674 @param browser reference to the web browser
675 @type HelpBrowser
676 """
677 self.sourceChanged.emit(browser, url)
678
679 def __titleChanged(self, title, browser):
680 """
681 Private slot to handle a change of a browsers title.
682
683 @param title new title
684 @type str
685 @param browser reference to the web browser
686 @type HelpBrowser
687 """
688 index = self.indexOf(browser)
689 if title == "":
690 title = browser.url().toString()
691
692 self.setTabText(index, self.__elide(title.replace("&", "&&")))
693 self.setTabToolTip(index, title)
694
695 self.titleChanged.emit(browser, title)
696
697 def __elide(self, txt, mode=Qt.ElideRight, length=40):
698 """
699 Private method to elide some text.
700
701 @param txt text to be elided (string)
702 @keyparam mode elide mode (Qt.TextElideMode)
703 @keyparam length amount of characters to be used (integer)
704 @return the elided text (string)
705 """
706 if mode == Qt.ElideNone or len(txt) < length:
707 return txt
708 elif mode == Qt.ElideLeft:
709 return "...{0}".format(txt[-length:])
710 elif mode == Qt.ElideMiddle:
711 return "{0}...{1}".format(txt[:length // 2], txt[-(length // 2):])
712 elif mode == Qt.ElideRight:
713 return "{0}...".format(txt[:length])
714 else:
715 # just in case
716 return txt
717
718 def preferencesChanged(self):
719 """
720 Public slot to handle a change of preferences.
721 """
722 for browser in self.browsers():
723 browser.preferencesChanged()
724
725 for urlbar in self.__stackedUrlBar.urlBars():
726 urlbar.preferencesChanged()
727
728 def __loadStarted(self, browser):
729 """
730 Private method to handle the loadStarted signal.
731
732 @param browser reference to the web browser
733 @type HelpBrowser
734 """
735 index = self.indexOf(browser)
736 anim = self.animationLabel(
737 index, os.path.join(getConfig("ericPixDir"), "loading.gif"),
738 100)
739 if not anim:
740 loading = QIcon(os.path.join(getConfig("ericPixDir"),
741 "loading.gif"))
742 self.setTabIcon(index, loading)
743 else:
744 self.setTabIcon(index, QIcon())
745 self.setTabText(index, self.tr("Loading..."))
746 self.setTabToolTip(index, self.tr("Loading..."))
747 self.showMessage.emit(self.tr("Loading..."))
748
749 self.__mainWindow.setLoadingActions(True)
750
751 def __loadFinished(self, ok):
752 """
753 Private method to handle the loadFinished signal.
754
755 @param ok flag indicating the result
756 @type bool
757 """
758 browser = self.sender()
759 if browser is None or not isinstance(browser, HelpBrowser):
760 return
761
762 import Helpviewer.HelpWindow
763 index = self.indexOf(browser)
764 self.resetAnimation(index)
765 self.setTabIcon(
766 index, Helpviewer.HelpWindow.HelpWindow.icon(browser.url()))
767 if ok:
768 self.showMessage.emit(self.tr("Finished loading"))
769 else:
770 self.showMessage.emit(self.tr("Failed to load"))
771
772 self.__mainWindow.setLoadingActions(False)
773
774 def __iconChanged(self, browser):
775 """
776 Private slot to handle the icon change.
777
778 @param browser reference to the web browser
779 @type HelpBrowser
780 """
781 import Helpviewer.HelpWindow
782 self.setTabIcon(
783 self.indexOf(browser),
784 Helpviewer.HelpWindow.HelpWindow.icon(browser.url()))
785 Helpviewer.HelpWindow.HelpWindow.bookmarksManager()\
786 .iconChanged(browser.url())
787
788 def getSourceFileList(self):
789 """
790 Public method to get a list of all opened source files.
791
792 @return dictionary with tab id as key and host/namespace as value
793 """
794 sourceList = {}
795 for i in range(self.count()):
796 browser = self.widget(i)
797 if browser is not None and \
798 browser.source().isValid():
799 sourceList[i] = browser.source().host()
800
801 return sourceList
802
803 def shallShutDown(self):
804 """
805 Public method to check, if the application should be shut down.
806
807 @return flag indicating a shut down (boolean)
808 """
809 if self.count() > 1 and Preferences.getHelp("WarnOnMultipleClose"):
810 mb = E5MessageBox.E5MessageBox(
811 E5MessageBox.Information,
812 self.tr("Are you sure you want to close the window?"),
813 self.tr("""Are you sure you want to close the window?\n"""
814 """You have %n tab(s) open.""", "", self.count()),
815 modal=True,
816 parent=self)
817 if self.__mainWindow.fromEric:
818 quitButton = mb.addButton(
819 self.tr("&Close"), E5MessageBox.AcceptRole)
820 quitButton.setIcon(UI.PixmapCache.getIcon("close.png"))
821 else:
822 quitButton = mb.addButton(
823 self.tr("&Quit"), E5MessageBox.AcceptRole)
824 quitButton.setIcon(UI.PixmapCache.getIcon("exit.png"))
825 closeTabButton = mb.addButton(
826 self.tr("C&lose Current Tab"), E5MessageBox.AcceptRole)
827 closeTabButton.setIcon(UI.PixmapCache.getIcon("tabClose.png"))
828 mb.addButton(E5MessageBox.Cancel)
829 mb.exec_()
830 if mb.clickedButton() == quitButton:
831 return True
832 else:
833 if mb.clickedButton() == closeTabButton:
834 self.closeBrowser()
835 return False
836
837 return True
838
839 def stackedUrlBar(self):
840 """
841 Public method to get a reference to the stacked url bar.
842
843 @return reference to the stacked url bar (StackedUrlBar)
844 """
845 return self.__stackedUrlBar
846
847 def currentUrlBar(self):
848 """
849 Public method to get a reference to the current url bar.
850
851 @return reference to the current url bar (UrlBar)
852 """
853 return self.__stackedUrlBar.currentWidget()
854
855 def __lineEditReturnPressed(self, edit):
856 """
857 Private slot to handle the entering of an URL.
858
859 @param edit reference to the line edit
860 @type UrlBar
861 """
862 url = self.__guessUrlFromPath(edit.text())
863 request = QNetworkRequest(url)
864 request.setRawHeader(b"X-Eric6-UserLoadAction", b"1")
865 if e5App().keyboardModifiers() == Qt.AltModifier:
866 self.newBrowser(
867 None, (request, QNetworkAccessManager.GetOperation, b""))
868 else:
869 self.currentBrowser().setSource(
870 None, (request, QNetworkAccessManager.GetOperation, b""))
871 self.currentBrowser().setFocus()
872
873 def __pathSelected(self, path):
874 """
875 Private slot called when a URL is selected from the completer.
876
877 @param path path to be shown (string)
878 """
879 url = self.__guessUrlFromPath(path)
880 self.currentBrowser().setSource(url)
881
882 def __guessUrlFromPath(self, path):
883 """
884 Private method to guess an URL given a path string.
885
886 @param path path string to guess an URL for (string)
887 @return guessed URL (QUrl)
888 """
889 manager = self.__mainWindow.openSearchManager()
890 path = Utilities.fromNativeSeparators(path)
891 url = manager.convertKeywordSearchToUrl(path)
892 if url.isValid():
893 return url
894
895 try:
896 url = QUrl.fromUserInput(path)
897 except AttributeError:
898 url = QUrl(path)
899
900 if url.scheme() == "about" and \
901 url.path() == "home":
902 url = QUrl("eric:home")
903
904 if url.scheme() in ["s", "search"]:
905 url = manager.currentEngine().searchUrl(url.path().strip())
906
907 if url.scheme() != "" and \
908 (url.host() != "" or url.path() != ""):
909 return url
910
911 urlString = Preferences.getHelp("DefaultScheme") + path.strip()
912 url = QUrl.fromEncoded(urlString.encode("utf-8"), QUrl.TolerantMode)
913
914 return url
915
916 def __currentChanged(self, index):
917 """
918 Private slot to handle an index change.
919
920 @param index new index (integer)
921 """
922 self.__stackedUrlBar.setCurrentIndex(index)
923
924 browser = self.browserAt(index)
925 if browser is not None:
926 if browser.url() == "" and browser.hasFocus():
927 self.__stackedUrlBar.currentWidget.setFocus()
928 elif browser.url() != "":
929 browser.setFocus()
930
931 def restoreClosedTab(self, act):
932 """
933 Public slot to restore the most recently closed tab.
934
935 @param act reference to the action that triggered
936 @type QAction
937 """
938 if not self.canRestoreClosedTab():
939 return
940
941 tab = self.__closedTabsManager.getClosedTabAt(act.data())
942
943 self.newBrowser(tab.url.toString(), position=tab.position)
944
945 def canRestoreClosedTab(self):
946 """
947 Public method to check, if closed tabs can be restored.
948
949 @return flag indicating that closed tabs can be restored (boolean)
950 """
951 return self.__closedTabsManager.isClosedTabAvailable()
952
953 def restoreAllClosedTabs(self):
954 """
955 Public slot to restore all closed tabs.
956 """
957 if not self.canRestoreClosedTab():
958 return
959
960 for tab in self.__closedTabsManager.allClosedTabs():
961 self.newBrowser(tab.url.toString(), position=tab.position)
962 self.__closedTabsManager.clearList()
963
964 def clearClosedTabsList(self):
965 """
966 Public slot to clear the list of closed tabs.
967 """
968 self.__closedTabsManager.clearList()
969
970 def __aboutToShowClosedTabsMenu(self):
971 """
972 Private slot to populate the closed tabs menu.
973 """
974 fm = self.__closedTabsMenu.fontMetrics()
975 maxWidth = fm.width('m') * 40
976
977 self.__closedTabsMenu.clear()
978 index = 0
979 for tab in self.__closedTabsManager.allClosedTabs():
980 title = fm.elidedText(tab.title, Qt.ElideRight, maxWidth)
981 act = self.__closedTabsMenu.addAction(
982 self.__mainWindow.icon(tab.url), title)
983 act.setData(index)
984 act.triggered.connect(lambda: self.restoreClosedTab(act))
985 index += 1
986 self.__closedTabsMenu.addSeparator()
987 self.__closedTabsMenu.addAction(
988 self.tr("Restore All Closed Tabs"), self.restoreAllClosedTabs)
989 self.__closedTabsMenu.addAction(
990 self.tr("Clear List"), self.clearClosedTabsList)
991
992 def closedTabsManager(self):
993 """
994 Public slot to get a reference to the closed tabs manager.
995
996 @return reference to the closed tabs manager (ClosedTabsManager)
997 """
998 return self.__closedTabsManager
999
1000 def __closedTabAvailable(self, avail):
1001 """
1002 Private slot to handle changes of the availability of closed tabs.
1003
1004 @param avail flag indicating the availability of closed tabs (boolean)
1005 """
1006 self.__closedTabsButton.setEnabled(avail)
1007 self.__restoreClosedTabAct.setEnabled(avail)

eric ide

mercurial