eric6/Helpviewer/HelpTabWidget.py

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

eric ide

mercurial