16 QAction, QKeySequence, QActionGroup, QGuiApplication, QClipboard |
16 QAction, QKeySequence, QActionGroup, QGuiApplication, QClipboard |
17 ) |
17 ) |
18 from PyQt6.QtPdf import QPdfDocument, QPdfLink |
18 from PyQt6.QtPdf import QPdfDocument, QPdfLink |
19 from PyQt6.QtPdfWidgets import QPdfView |
19 from PyQt6.QtPdfWidgets import QPdfView |
20 from PyQt6.QtWidgets import ( |
20 from PyQt6.QtWidgets import ( |
21 QWhatsThis, QMenu, QTabWidget, QSplitter, QToolBar, QDialog |
21 QWhatsThis, QMenu, QTabWidget, QSplitter, QToolBar, QDialog, QInputDialog, |
|
22 QLineEdit |
22 ) |
23 ) |
23 |
24 |
24 from eric7 import Preferences |
25 from eric7 import Preferences |
25 from eric7.EricGui import EricPixmapCache |
26 from eric7.EricGui import EricPixmapCache |
26 from eric7.EricGui.EricAction import EricAction |
27 from eric7.EricGui.EricAction import EricAction |
27 from eric7.EricWidgets import EricFileDialog, EricMessageBox |
28 from eric7.EricWidgets import EricFileDialog, EricMessageBox |
28 from eric7.EricWidgets.EricMainWindow import EricMainWindow |
29 from eric7.EricWidgets.EricMainWindow import EricMainWindow |
29 from eric7.EricWidgets.EricStretchableSpacer import EricStretchableSpacer |
30 from eric7.EricWidgets.EricStretchableSpacer import EricStretchableSpacer |
30 from eric7.Globals import recentNamePdfFiles |
31 from eric7.Globals import recentNamePdfFiles |
31 from eric7.SystemUtilities import FileSystemUtilities |
32 from eric7.SystemUtilities import FileSystemUtilities, OSUtilities |
32 |
33 |
33 from .PdfPageSelector import PdfPageSelector |
34 from .PdfPageSelector import PdfPageSelector |
34 from .PdfZoomSelector import PdfZoomSelector |
35 from .PdfZoomSelector import PdfZoomSelector |
35 from .PdfToCWidget import PdfToCWidget |
36 from .PdfToCWidget import PdfToCWidget |
36 from .PdfInfoWidget import PdfInfoWidget |
37 from .PdfInfoWidget import PdfInfoWidget |
145 self.__zoomSelector.zoomFactorChanged.connect(self.__view.setZoomFactor) |
146 self.__zoomSelector.zoomFactorChanged.connect(self.__view.setZoomFactor) |
146 self.__view.zoomFactorChanged.connect(self.__zoomSelector.setZoomFactor) |
147 self.__view.zoomFactorChanged.connect(self.__zoomSelector.setZoomFactor) |
147 self.__view.zoomModeChanged.connect(self.__zoomSelector.setZoomMode) |
148 self.__view.zoomModeChanged.connect(self.__zoomSelector.setZoomMode) |
148 |
149 |
149 self.__tocWidget.topicActivated.connect(self.__tocActivated) |
150 self.__tocWidget.topicActivated.connect(self.__tocActivated) |
|
151 |
150 self.__searchWidget.searchResultActivated.connect(self.__handleSearchResult) |
152 self.__searchWidget.searchResultActivated.connect(self.__handleSearchResult) |
|
153 self.__searchWidget.searchNextAvailable.connect(self.searchNextAct.setEnabled) |
|
154 self.__searchWidget.searchPrevAvailable.connect(self.searchPrevAct.setEnabled) |
151 |
155 |
152 PdfViewerWindow.windows.append(self) |
156 PdfViewerWindow.windows.append(self) |
153 |
157 |
154 self.__restoreViewerState() |
158 self.__restoreViewerState() |
155 |
159 |
416 |
420 |
417 def __initViewActions(self): |
421 def __initViewActions(self): |
418 """ |
422 """ |
419 Private method to define the view related user interface actions. |
423 Private method to define the view related user interface actions. |
420 """ |
424 """ |
421 # TODO: add Fullscreen action |
425 self.fullScreenAct = EricAction( |
|
426 self.tr("Full Screen"), |
|
427 EricPixmapCache.getIcon("windowFullscreen"), |
|
428 self.tr("&Full Screen"), |
|
429 0, |
|
430 0, |
|
431 self, |
|
432 "pdfviewer_view_full_screen", |
|
433 ) |
|
434 if OSUtilities.isMacPlatform(): |
|
435 self.fullScreenAct.setShortcut(QKeySequence(self.tr("Meta+Ctrl+F"))) |
|
436 else: |
|
437 self.fullScreenAct.setShortcut(QKeySequence(self.tr("F11"))) |
|
438 self.fullScreenAct.setCheckable(True) |
|
439 self.fullScreenAct.triggered.connect(self.__toggleFullScreen) |
|
440 self.__actions.append(self.fullScreenAct) |
|
441 |
422 self.zoomInAct = EricAction( |
442 self.zoomInAct = EricAction( |
423 self.tr("Zoom in"), |
443 self.tr("Zoom in"), |
424 EricPixmapCache.getIcon("zoomIn"), |
444 EricPixmapCache.getIcon("zoomIn"), |
425 self.tr("Zoom &in"), |
445 self.tr("Zoom &in"), |
426 QKeySequence(self.tr("Ctrl++", "View|Zoom in")), |
446 QKeySequence(self.tr("Ctrl++", "View|Zoom in")), |
505 self, |
525 self, |
506 "pdfviewer_edit_copyallpage", |
526 "pdfviewer_edit_copyallpage", |
507 ) |
527 ) |
508 self.copyAllPageAct.triggered.connect(self.__copyAllTextOfPage) |
528 self.copyAllPageAct.triggered.connect(self.__copyAllTextOfPage) |
509 self.__actions.append(self.copyAllPageAct) |
529 self.__actions.append(self.copyAllPageAct) |
|
530 |
|
531 self.searchAct = EricAction( |
|
532 self.tr("Search"), |
|
533 EricPixmapCache.getIcon("find"), |
|
534 self.tr("&Search..."), |
|
535 QKeySequence(self.tr("Ctrl+F", "Edit|Search")), |
|
536 0, |
|
537 self, |
|
538 "pdfviewer_edit_search", |
|
539 ) |
|
540 self.searchAct.triggered.connect(self.__search) |
|
541 self.__actions.append(self.searchAct) |
|
542 |
|
543 self.searchNextAct = EricAction( |
|
544 self.tr("Search Next"), |
|
545 EricPixmapCache.getIcon("findNext"), |
|
546 self.tr("Search &Next"), |
|
547 QKeySequence(self.tr("F3", "Edit|Search Next")), |
|
548 0, |
|
549 self, |
|
550 "pdfviewer_edit_searchnext", |
|
551 ) |
|
552 self.searchNextAct.triggered.connect(self.__searchWidget.nextResult) |
|
553 self.__actions.append(self.searchNextAct) |
|
554 |
|
555 self.searchPrevAct = EricAction( |
|
556 self.tr("Search Previous"), |
|
557 EricPixmapCache.getIcon("findPrev"), |
|
558 self.tr("Search &Previous"), |
|
559 QKeySequence(self.tr("Shift+F3", "Edit|Search Previous")), |
|
560 0, |
|
561 self, |
|
562 "pdfviewer_edit_searchprevious", |
|
563 ) |
|
564 self.searchPrevAct.triggered.connect(self.__searchWidget.previousResult) |
|
565 self.__actions.append(self.searchPrevAct) |
|
566 |
|
567 self.searchNextAct.setEnabled(False) |
|
568 self.searchPrevAct.setEnabled(False) |
510 |
569 |
511 def __initSettingsActions(self): |
570 def __initSettingsActions(self): |
512 """ |
571 """ |
513 Private method to create the Settings actions. |
572 Private method to create the Settings actions. |
514 """ |
573 """ |
625 self.zoomOutAct.setEnabled(ready) |
684 self.zoomOutAct.setEnabled(ready) |
626 self.zoomResetAct.setEnabled(ready) |
685 self.zoomResetAct.setEnabled(ready) |
627 self.zoomPageWidthAct.setEnabled(ready) |
686 self.zoomPageWidthAct.setEnabled(ready) |
628 self.zoomWholePageAct.setEnabled(ready) |
687 self.zoomWholePageAct.setEnabled(ready) |
629 self.__zoomSelector.setEnabled(ready) |
688 self.__zoomSelector.setEnabled(ready) |
|
689 |
|
690 self.copyAllAct.setEnabled(ready) |
|
691 self.copyAllPageAct.setEnabled(ready) |
|
692 self.searchAct.setEnabled(ready) |
630 |
693 |
631 def __initMenus(self): |
694 def __initMenus(self): |
632 """ |
695 """ |
633 Private method to create the menus. |
696 Private method to create the menus. |
634 """ |
697 """ |
656 self.__recentMenu.aboutToShow.connect(self.__showRecentMenu) |
719 self.__recentMenu.aboutToShow.connect(self.__showRecentMenu) |
657 self.__recentMenu.triggered.connect(self.__openRecentPdfFile) |
720 self.__recentMenu.triggered.connect(self.__openRecentPdfFile) |
658 |
721 |
659 menu = mb.addMenu(self.tr("&View")) |
722 menu = mb.addMenu(self.tr("&View")) |
660 menu.setTearOffEnabled(True) |
723 menu.setTearOffEnabled(True) |
|
724 menu.addAction(self.fullScreenAct) |
|
725 menu.addSeparator() |
661 menu.addAction(self.zoomInAct) |
726 menu.addAction(self.zoomInAct) |
662 menu.addAction(self.zoomOutAct) |
727 menu.addAction(self.zoomOutAct) |
663 menu.addAction(self.zoomResetAct) |
728 menu.addAction(self.zoomResetAct) |
664 menu.addAction(self.zoomPageWidthAct) |
729 menu.addAction(self.zoomPageWidthAct) |
665 menu.addAction(self.zoomWholePageAct) |
730 menu.addAction(self.zoomWholePageAct) |
677 menu = mb.addMenu(self.tr("&Edit")) |
742 menu = mb.addMenu(self.tr("&Edit")) |
678 menu.setTearOffEnabled(True) |
743 menu.setTearOffEnabled(True) |
679 menu.addAction(self.copyAllAct) |
744 menu.addAction(self.copyAllAct) |
680 menu.addSeparator() |
745 menu.addSeparator() |
681 menu.addAction(self.copyAllPageAct) |
746 menu.addAction(self.copyAllPageAct) |
|
747 menu.addSeparator() |
|
748 menu.addAction(self.searchAct) |
|
749 menu.addAction(self.searchNextAct) |
|
750 menu.addAction(self.searchPrevAct) |
682 |
751 |
683 menu = mb.addMenu(self.tr("&Go To")) |
752 menu = mb.addMenu(self.tr("&Go To")) |
684 menu.setTearOffEnabled(True) |
753 menu.setTearOffEnabled(True) |
685 menu.addAction(self.previousPageAct) |
754 menu.addAction(self.previousPageAct) |
686 menu.addAction(self.nextPageAct) |
755 menu.addAction(self.nextPageAct) |
771 with contextlib.suppress(ValueError): |
840 with contextlib.suppress(ValueError): |
772 if self.__fromEric or len(PdfViewerWindow.windows) > 1: |
841 if self.__fromEric or len(PdfViewerWindow.windows) > 1: |
773 PdfViewerWindow.windows.remove(self) |
842 PdfViewerWindow.windows.remove(self) |
774 |
843 |
775 self.__saveRecent() |
844 self.__saveRecent() |
|
845 |
|
846 self.__documentInfoWidget.setDocument(None) |
776 |
847 |
777 evt.accept() |
848 evt.accept() |
778 self.viewerClosed.emit() |
849 self.viewerClosed.emit() |
779 |
850 |
780 def __saveViewerState(self): |
851 def __saveViewerState(self): |
853 Private method to load a PDF file. |
924 Private method to load a PDF file. |
854 |
925 |
855 @param fileName path of the PDF file to load |
926 @param fileName path of the PDF file to load |
856 @type str |
927 @type str |
857 """ |
928 """ |
858 # TODO: if error is QPdfDocument.Error.IncorrectPassword ask for PW and try |
929 canceled = False |
859 # again until cancelled |
930 err = QPdfDocument.Error.IncorrectPassword |
860 err = self.__pdfDocument.load(fileName) |
931 while not canceled and err == QPdfDocument.Error.IncorrectPassword: |
|
932 err = self.__pdfDocument.load(fileName) |
|
933 if err == QPdfDocument.Error.IncorrectPassword: |
|
934 password, ok = QInputDialog.getText( |
|
935 self, |
|
936 self.tr("Load PDF File"), |
|
937 self.tr("Enter password to read the document:"), |
|
938 QLineEdit.EchoMode.Password, |
|
939 ) |
|
940 if ok: |
|
941 self.__pdfDocument.setPassword(password) |
|
942 else: |
|
943 canceled = True |
861 if err != QPdfDocument.Error.None_: |
944 if err != QPdfDocument.Error.None_: |
862 EricMessageBox.critical( |
945 EricMessageBox.critical( |
863 self, |
946 self, |
864 self.tr("Load PDF File"), |
947 self.tr("Load PDF File"), |
865 self.tr( |
948 self.tr( |
994 @param link PDF link to navigate to |
1077 @param link PDF link to navigate to |
995 @type QPdfLink |
1078 @type QPdfLink |
996 """ |
1079 """ |
997 self.__view.pageNavigator().jump(link) |
1080 self.__view.pageNavigator().jump(link) |
998 |
1081 |
|
1082 @pyqtSlot() |
|
1083 def __search(self): |
|
1084 """ |
|
1085 Private slot to initiate a search. |
|
1086 """ |
|
1087 self.__info.setCurrentWidget(self.__searchWidget) |
|
1088 self.__searchWidget.activateSearch() |
|
1089 |
999 def __setCurrentFile(self, fileName): |
1090 def __setCurrentFile(self, fileName): |
1000 """ |
1091 """ |
1001 Private method to register the file name of the current file. |
1092 Private method to register the file name of the current file. |
1002 |
1093 |
1003 @param fileName name of the file to register |
1094 @param fileName name of the file to register |