2020-01-03 18:11:03 +01:00
// Copyright (C) 2019-2020 Jakub Melka
2019-01-27 17:55:22 +01:00
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
2018-11-21 19:30:15 +01:00
# include "pdfviewermainwindow.h"
# include "ui_pdfviewermainwindow.h"
2019-11-10 14:17:54 +01:00
# include "pdfaboutdialog.h"
2019-11-28 18:20:32 +01:00
# include "pdfsidebarwidget.h"
2020-01-03 18:11:03 +01:00
# include "pdfadvancedfindwidget.h"
2019-12-20 18:56:03 +01:00
# include "pdfviewersettingsdialog.h"
# include "pdfdocumentpropertiesdialog.h"
2020-02-08 18:09:46 +01:00
# include "pdfrendertoimagesdialog.h"
2020-05-31 18:31:59 +02:00
# include "pdfoptimizedocumentdialog.h"
2019-09-06 19:07:52 +02:00
2018-11-21 19:30:15 +01:00
# include "pdfdocumentreader.h"
2018-12-01 11:36:07 +01:00
# include "pdfvisitor.h"
2019-01-20 17:55:06 +01:00
# include "pdfstreamfilters.h"
2019-01-27 17:55:22 +01:00
# include "pdfdrawwidget.h"
2019-02-02 18:10:00 +01:00
# include "pdfdrawspacecontroller.h"
2019-02-24 19:42:00 +01:00
# include "pdfrenderingerrorswidget.h"
2019-04-27 14:14:07 +02:00
# include "pdffont.h"
2019-07-01 19:53:38 +02:00
# include "pdfitemmodels.h"
2019-11-06 18:25:46 +01:00
# include "pdfutils.h"
2019-12-22 18:03:19 +01:00
# include "pdfsendmail.h"
2020-01-18 14:55:26 +01:00
# include "pdfexecutionpolicy.h"
2020-01-25 17:36:25 +01:00
# include "pdfwidgetutils.h"
2020-06-07 17:46:49 +02:00
# include "pdfdocumentwriter.h"
2020-06-14 18:40:42 +02:00
# include "pdfsignaturehandler.h"
2018-11-21 19:30:15 +01:00
2020-02-03 19:45:17 +01:00
# include <QPainter>
2019-01-27 17:55:22 +01:00
# include <QSettings>
2018-11-21 19:30:15 +01:00
# include <QFileDialog>
# include <QMessageBox>
2019-01-27 17:55:22 +01:00
# include <QCloseEvent>
# include <QApplication>
# include <QDesktopWidget>
# include <QStandardPaths>
2019-07-01 19:53:38 +02:00
# include <QDockWidget>
# include <QTreeView>
# include <QLayout>
# include <QHeaderView>
2019-08-10 17:24:12 +02:00
# include <QInputDialog>
2019-11-06 18:25:46 +01:00
# include <QSpinBox>
# include <QLabel>
# include <QDoubleSpinBox>
2019-11-30 16:26:32 +01:00
# include <QDesktopServices>
2020-06-07 17:46:49 +02:00
# include <QFileDialog>
2020-06-28 18:55:09 +02:00
# include <QLockFile>
2020-02-03 19:45:17 +01:00
# include <QtPrintSupport/QPrinter>
# include <QtPrintSupport/QPrintDialog>
2019-12-23 15:58:40 +01:00
# include <QtConcurrent/QtConcurrent>
2020-11-17 18:28:34 +01:00
# include <QPluginLoader>
2019-11-30 16:26:32 +01:00
# ifdef Q_OS_WIN
# include "Windows.h"
# endif
2018-11-21 19:30:15 +01:00
namespace pdfviewer
{
2019-12-24 17:29:40 +01:00
PDFViewerMainWindow : : PDFViewerMainWindow ( QWidget * parent ) :
2018-11-21 19:30:15 +01:00
QMainWindow ( parent ) ,
2019-01-27 17:55:22 +01:00
ui ( new Ui : : PDFViewerMainWindow ) ,
2019-12-24 17:29:40 +01:00
m_CMSManager ( new pdf : : PDFCMSManager ( this ) ) ,
2020-02-01 11:56:40 +01:00
m_recentFileManager ( new PDFRecentFileManager ( this ) ) ,
2019-07-06 15:55:37 +02:00
m_settings ( new PDFViewerSettings ( this ) ) ,
2019-07-01 19:53:38 +02:00
m_pdfWidget ( nullptr ) ,
2020-01-03 18:11:03 +01:00
m_sidebarWidget ( nullptr ) ,
2019-11-28 18:20:32 +01:00
m_sidebarDockWidget ( nullptr ) ,
2020-01-03 18:11:03 +01:00
m_advancedFindWidget ( nullptr ) ,
m_advancedFindDockWidget ( nullptr ) ,
2019-11-06 18:25:46 +01:00
m_optionalContentActivity ( nullptr ) ,
m_pageNumberSpinBox ( nullptr ) ,
m_pageNumberLabel ( nullptr ) ,
m_pageZoomSpinBox ( nullptr ) ,
2019-11-09 17:27:17 +01:00
m_isLoadingUI ( false ) ,
m_progress ( new pdf : : PDFProgress ( this ) ) ,
m_taskbarButton ( new QWinTaskbarButton ( this ) ) ,
2020-01-01 18:23:18 +01:00
m_progressTaskbarIndicator ( nullptr ) ,
2020-05-30 18:31:50 +02:00
m_futureWatcher ( nullptr ) ,
2020-01-01 18:23:18 +01:00
m_progressDialog ( nullptr ) ,
2020-01-12 18:46:59 +01:00
m_isBusy ( false ) ,
2020-01-26 17:06:50 +01:00
m_isChangingProgressStep ( false ) ,
2020-02-18 20:21:18 +01:00
m_toolManager ( nullptr ) ,
2020-03-07 17:38:50 +01:00
m_annotationManager ( nullptr ) ,
2020-04-22 20:00:44 +02:00
m_formManager ( nullptr ) ,
2020-05-03 18:52:22 +02:00
m_textToSpeech ( new PDFTextToSpeech ( this ) ) ,
m_undoRedoManager ( new PDFUndoRedoManager ( this ) )
2018-11-21 19:30:15 +01:00
{
ui - > setupUi ( this ) ;
2020-11-07 12:03:43 +01:00
setAcceptDrops ( true ) ;
2020-01-25 17:36:25 +01:00
// Initialize toolbar icon size
2020-02-23 18:59:54 +01:00
QSize iconSize = pdf : : PDFWidgetUtils : : scaleDPI ( this , QSize ( 24 , 24 ) ) ;
2020-01-25 17:36:25 +01:00
ui - > mainToolBar - > setIconSize ( iconSize ) ;
2019-11-09 17:27:17 +01:00
// Initialize task bar progress
m_progressTaskbarIndicator = m_taskbarButton - > progress ( ) ;
2019-01-27 17:55:22 +01:00
// Initialize shortcuts
ui - > actionOpen - > setShortcut ( QKeySequence : : Open ) ;
ui - > actionClose - > setShortcut ( QKeySequence : : Close ) ;
ui - > actionQuit - > setShortcut ( QKeySequence : : Quit ) ;
2019-12-14 19:09:34 +01:00
ui - > actionZoom_In - > setShortcut ( QKeySequence : : ZoomIn ) ;
ui - > actionZoom_Out - > setShortcut ( QKeySequence : : ZoomOut ) ;
2020-01-03 18:11:03 +01:00
ui - > actionFind - > setShortcut ( QKeySequence : : Find ) ;
2020-01-12 18:46:59 +01:00
ui - > actionFindPrevious - > setShortcut ( QKeySequence : : FindPrevious ) ;
ui - > actionFindNext - > setShortcut ( QKeySequence : : FindNext ) ;
2020-01-25 17:36:25 +01:00
ui - > actionSelectTextAll - > setShortcut ( QKeySequence : : SelectAll ) ;
ui - > actionDeselectText - > setShortcut ( QKeySequence : : Deselect ) ;
2020-01-26 17:06:50 +01:00
ui - > actionCopyText - > setShortcut ( QKeySequence : : Copy ) ;
2020-02-01 17:28:02 +01:00
ui - > actionRotateRight - > setShortcut ( QKeySequence ( " Ctrl+Shift++ " ) ) ;
ui - > actionRotateLeft - > setShortcut ( QKeySequence ( " Ctrl+Shift+- " ) ) ;
2020-02-03 19:45:17 +01:00
ui - > actionPrint - > setShortcut ( QKeySequence : : Print ) ;
2020-04-25 18:15:12 +02:00
ui - > actionUndo - > setShortcut ( QKeySequence : : Undo ) ;
ui - > actionRedo - > setShortcut ( QKeySequence : : Redo ) ;
2020-06-07 17:46:49 +02:00
ui - > actionSave - > setShortcut ( QKeySequence : : Save ) ;
ui - > actionSave_As - > setShortcut ( QKeySequence : : SaveAs ) ;
2019-01-27 17:55:22 +01:00
2020-02-01 11:56:40 +01:00
for ( QAction * action : m_recentFileManager - > getActions ( ) )
{
ui - > menuFile - > insertAction ( ui - > actionQuit , action ) ;
}
ui - > menuFile - > insertSeparator ( ui - > actionQuit ) ;
2018-11-21 19:30:15 +01:00
connect ( ui - > actionOpen , & QAction : : triggered , this , & PDFViewerMainWindow : : onActionOpenTriggered ) ;
2019-01-27 17:55:22 +01:00
connect ( ui - > actionClose , & QAction : : triggered , this , & PDFViewerMainWindow : : onActionCloseTriggered ) ;
connect ( ui - > actionQuit , & QAction : : triggered , this , & PDFViewerMainWindow : : onActionQuitTriggered ) ;
2020-02-01 11:56:40 +01:00
connect ( m_recentFileManager , & PDFRecentFileManager : : fileOpenRequest , this , & PDFViewerMainWindow : : openDocument ) ;
2019-01-27 17:55:22 +01:00
2019-12-16 19:46:29 +01:00
auto createGoToAction = [ this ] ( QMenu * menu , QString name , QString text , QKeySequence : : StandardKey key , pdf : : PDFDrawWidgetProxy : : Operation operation , QString iconPath )
2019-02-02 18:10:00 +01:00
{
2019-11-06 18:25:46 +01:00
QIcon icon ;
icon . addFile ( iconPath ) ;
QAction * action = new QAction ( icon , text , this ) ;
2019-12-16 19:46:29 +01:00
action - > setObjectName ( name ) ;
2019-02-02 18:10:00 +01:00
action - > setShortcut ( key ) ;
menu - > addAction ( action ) ;
auto onTriggered = [ this , operation ] ( )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( operation ) ;
} ;
connect ( action , & QAction : : triggered , this , onTriggered ) ;
2019-11-06 18:25:46 +01:00
return action ;
2019-02-02 18:10:00 +01:00
} ;
2019-12-16 19:46:29 +01:00
QAction * actionGoToDocumentStart = createGoToAction ( ui - > menuGoTo , " actionGoToDocumentStart " , tr ( " Go to document start " ) , QKeySequence : : MoveToStartOfDocument , pdf : : PDFDrawWidgetProxy : : NavigateDocumentStart , " :/resources/previous-start.svg " ) ;
QAction * actionGoToDocumentEnd = createGoToAction ( ui - > menuGoTo , " actionGoToDocumentEnd " , tr ( " Go to document end " ) , QKeySequence : : MoveToEndOfDocument , pdf : : PDFDrawWidgetProxy : : NavigateDocumentEnd , " :/resources/next-end.svg " ) ;
QAction * actionGoToNextPage = createGoToAction ( ui - > menuGoTo , " actionGoToNextPage " , tr ( " Go to next page " ) , QKeySequence : : MoveToNextPage , pdf : : PDFDrawWidgetProxy : : NavigateNextPage , " :/resources/next-page.svg " ) ;
QAction * actionGoToPreviousPage = createGoToAction ( ui - > menuGoTo , " actionGoToPreviousPage " , tr ( " Go to previous page " ) , QKeySequence : : MoveToPreviousPage , pdf : : PDFDrawWidgetProxy : : NavigatePreviousPage , " :/resources/previous-page.svg " ) ;
createGoToAction ( ui - > menuGoTo , " actionGoToNextLine " , tr ( " Go to next line " ) , QKeySequence : : MoveToNextLine , pdf : : PDFDrawWidgetProxy : : NavigateNextStep , " :/resources/next.svg " ) ;
createGoToAction ( ui - > menuGoTo , " actionGoToPreviousLine " , tr ( " Go to previous line " ) , QKeySequence : : MoveToPreviousLine , pdf : : PDFDrawWidgetProxy : : NavigatePreviousStep , " :/resources/previous.svg " ) ;
2019-11-06 18:25:46 +01:00
m_pageNumberSpinBox = new QSpinBox ( this ) ;
m_pageNumberLabel = new QLabel ( this ) ;
m_pageNumberSpinBox - > setFixedWidth ( adjustDpiX ( 80 ) ) ;
2019-11-09 15:11:57 +01:00
m_pageNumberSpinBox - > setAlignment ( Qt : : AlignCenter ) ;
connect ( m_pageNumberSpinBox , & QSpinBox : : editingFinished , this , & PDFViewerMainWindow : : onPageNumberSpinboxEditingFinished ) ;
2019-11-06 18:25:46 +01:00
// Page control
ui - > mainToolBar - > addSeparator ( ) ;
ui - > mainToolBar - > addAction ( actionGoToDocumentStart ) ;
ui - > mainToolBar - > addAction ( actionGoToPreviousPage ) ;
ui - > mainToolBar - > addWidget ( m_pageNumberSpinBox ) ;
ui - > mainToolBar - > addWidget ( m_pageNumberLabel ) ;
ui - > mainToolBar - > addAction ( actionGoToNextPage ) ;
ui - > mainToolBar - > addAction ( actionGoToDocumentEnd ) ;
// Zoom
ui - > mainToolBar - > addSeparator ( ) ;
ui - > mainToolBar - > addAction ( ui - > actionZoom_In ) ;
ui - > mainToolBar - > addAction ( ui - > actionZoom_Out ) ;
m_pageZoomSpinBox = new QDoubleSpinBox ( this ) ;
m_pageZoomSpinBox - > setMinimum ( pdf : : PDFDrawWidgetProxy : : getMinZoom ( ) * 100 ) ;
m_pageZoomSpinBox - > setMaximum ( pdf : : PDFDrawWidgetProxy : : getMaxZoom ( ) * 100 ) ;
m_pageZoomSpinBox - > setDecimals ( 2 ) ;
m_pageZoomSpinBox - > setSuffix ( tr ( " % " ) ) ;
m_pageZoomSpinBox - > setFixedWidth ( adjustDpiX ( 80 ) ) ;
2019-11-09 15:11:57 +01:00
m_pageZoomSpinBox - > setAlignment ( Qt : : AlignVCenter | Qt : : AlignRight ) ;
connect ( m_pageZoomSpinBox , & QDoubleSpinBox : : editingFinished , this , & PDFViewerMainWindow : : onPageZoomSpinboxEditingFinished ) ;
2019-11-06 18:25:46 +01:00
ui - > mainToolBar - > addWidget ( m_pageZoomSpinBox ) ;
2019-12-01 13:02:25 +01:00
// Fit page, width, height
ui - > mainToolBar - > addAction ( ui - > actionFitPage ) ;
ui - > mainToolBar - > addAction ( ui - > actionFitWidth ) ;
ui - > mainToolBar - > addAction ( ui - > actionFitHeight ) ;
2020-01-25 17:36:25 +01:00
ui - > mainToolBar - > addSeparator ( ) ;
// Tools
ui - > mainToolBar - > addAction ( ui - > actionSelectText ) ;
2020-02-22 18:27:33 +01:00
ui - > mainToolBar - > addAction ( ui - > actionMagnifier ) ;
2020-02-23 18:59:54 +01:00
ui - > mainToolBar - > addAction ( ui - > actionScreenshot ) ;
2020-02-29 14:26:36 +01:00
ui - > mainToolBar - > addAction ( ui - > actionExtractImage ) ;
2019-12-01 13:02:25 +01:00
2019-11-06 18:25:46 +01:00
connect ( ui - > actionZoom_In , & QAction : : triggered , this , [ this ] { m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomIn ) ; } ) ;
connect ( ui - > actionZoom_Out , & QAction : : triggered , this , [ this ] { m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomOut ) ; } ) ;
2019-02-02 18:10:00 +01:00
2019-09-08 11:13:59 +02:00
readSettings ( ) ;
2019-12-25 17:56:17 +01:00
m_pdfWidget = new pdf : : PDFWidget ( m_CMSManager , m_settings - > getRendererEngine ( ) , m_settings - > isMultisampleAntialiasingEnabled ( ) ? m_settings - > getRendererSamples ( ) : - 1 , this ) ;
2019-01-27 17:55:22 +01:00
setCentralWidget ( m_pdfWidget ) ;
setFocusProxy ( m_pdfWidget ) ;
2019-12-15 19:28:25 +01:00
m_pdfWidget - > updateCacheLimits ( m_settings - > getCompiledPageCacheLimit ( ) * 1024 , m_settings - > getThumbnailsCacheLimit ( ) , m_settings - > getFontCacheLimit ( ) , m_settings - > getInstancedFontCacheLimit ( ) ) ;
2020-01-01 18:23:18 +01:00
m_pdfWidget - > getDrawWidgetProxy ( ) - > setProgress ( m_progress ) ;
2020-02-18 20:21:18 +01:00
m_textToSpeech - > setProxy ( m_pdfWidget - > getDrawWidgetProxy ( ) ) ;
2019-01-27 17:55:22 +01:00
2020-06-27 17:28:03 +02:00
m_sidebarWidget = new PDFSidebarWidget ( m_pdfWidget - > getDrawWidgetProxy ( ) , m_textToSpeech , & m_certificateStore , m_settings , this ) ;
2019-11-28 18:20:32 +01:00
m_sidebarDockWidget = new QDockWidget ( tr ( " Sidebar " ) , this ) ;
m_sidebarDockWidget - > setObjectName ( " SidebarDockWidget " ) ;
m_sidebarDockWidget - > setAllowedAreas ( Qt : : LeftDockWidgetArea | Qt : : RightDockWidgetArea ) ;
m_sidebarDockWidget - > setWidget ( m_sidebarWidget ) ;
addDockWidget ( Qt : : LeftDockWidgetArea , m_sidebarDockWidget ) ;
m_sidebarDockWidget - > hide ( ) ;
2019-11-29 19:10:29 +01:00
connect ( m_sidebarWidget , & PDFSidebarWidget : : actionTriggered , this , & PDFViewerMainWindow : : onActionTriggered ) ;
2020-02-18 20:21:18 +01:00
m_textToSpeech - > setSettings ( m_settings ) ;
2019-07-01 19:53:38 +02:00
2020-01-03 18:11:03 +01:00
m_advancedFindWidget = new PDFAdvancedFindWidget ( m_pdfWidget - > getDrawWidgetProxy ( ) , this ) ;
m_advancedFindDockWidget = new QDockWidget ( tr ( " Advanced find " ) , this ) ;
m_advancedFindDockWidget - > setObjectName ( " AdvancedFind " ) ;
m_advancedFindDockWidget - > setAllowedAreas ( Qt : : TopDockWidgetArea | Qt : : BottomDockWidgetArea ) ;
m_advancedFindDockWidget - > setWidget ( m_advancedFindWidget ) ;
addDockWidget ( Qt : : BottomDockWidgetArea , m_advancedFindDockWidget ) ;
m_advancedFindDockWidget - > hide ( ) ;
QAction * toggleAdvancedFindAction = m_advancedFindDockWidget - > toggleViewAction ( ) ;
toggleAdvancedFindAction - > setObjectName ( " actionAdvancedFind " ) ;
toggleAdvancedFindAction - > setText ( tr ( " Advanced Find " ) ) ;
toggleAdvancedFindAction - > setShortcut ( QKeySequence ( " Ctrl+Shift+F " ) ) ;
2020-01-12 18:46:59 +01:00
toggleAdvancedFindAction - > setIcon ( QIcon ( " :/resources/find-advanced.svg " ) ) ;
2020-01-03 18:11:03 +01:00
ui - > menuEdit - > insertAction ( nullptr , toggleAdvancedFindAction ) ;
2019-07-06 15:55:37 +02:00
ui - > actionRenderOptionAntialiasing - > setData ( pdf : : PDFRenderer : : Antialiasing ) ;
ui - > actionRenderOptionTextAntialiasing - > setData ( pdf : : PDFRenderer : : TextAntialiasing ) ;
ui - > actionRenderOptionSmoothPictures - > setData ( pdf : : PDFRenderer : : SmoothImages ) ;
ui - > actionRenderOptionIgnoreOptionalContentSettings - > setData ( pdf : : PDFRenderer : : IgnoreOptionalContent ) ;
2020-04-11 13:56:05 +02:00
ui - > actionRenderOptionDisplayAnnotations - > setData ( pdf : : PDFRenderer : : DisplayAnnotations ) ;
2020-01-28 19:17:45 +01:00
ui - > actionInvertColors - > setData ( pdf : : PDFRenderer : : InvertColors ) ;
2019-12-29 17:25:18 +01:00
ui - > actionShow_Text_Blocks - > setData ( pdf : : PDFRenderer : : DebugTextBlocks ) ;
ui - > actionShow_Text_Lines - > setData ( pdf : : PDFRenderer : : DebugTextLines ) ;
2019-07-06 15:55:37 +02:00
for ( QAction * action : getRenderingOptionActions ( ) )
{
connect ( action , & QAction : : triggered , this , & PDFViewerMainWindow : : onRenderingOptionTriggered ) ;
}
2019-07-01 19:53:38 +02:00
ui - > menuView - > addSeparator ( ) ;
2019-11-28 18:20:32 +01:00
ui - > menuView - > addAction ( m_sidebarDockWidget - > toggleViewAction ( ) ) ;
2019-12-16 19:46:29 +01:00
m_sidebarDockWidget - > toggleViewAction ( ) - > setObjectName ( " actionSidebar " ) ;
2019-07-01 19:53:38 +02:00
2020-01-12 18:46:59 +01:00
// Initialize tools
2020-01-25 17:36:25 +01:00
pdf : : PDFToolManager : : Actions actions ;
actions . findPrevAction = ui - > actionFindPrevious ;
actions . findNextAction = ui - > actionFindNext ;
actions . selectTextToolAction = ui - > actionSelectText ;
actions . selectAllAction = ui - > actionSelectTextAll ;
actions . deselectAction = ui - > actionDeselectText ;
2020-01-26 17:06:50 +01:00
actions . copyTextAction = ui - > actionCopyText ;
2020-02-22 18:27:33 +01:00
actions . magnifierAction = ui - > actionMagnifier ;
2020-02-23 18:59:54 +01:00
actions . screenshotToolAction = ui - > actionScreenshot ;
2020-02-29 14:26:36 +01:00
actions . extractImageAction = ui - > actionExtractImage ;
2020-01-25 17:36:25 +01:00
m_toolManager = new pdf : : PDFToolManager ( m_pdfWidget - > getDrawWidgetProxy ( ) , actions , this , this ) ;
m_pdfWidget - > setToolManager ( m_toolManager ) ;
2020-02-22 18:27:33 +01:00
updateMagnifierToolSettings ( ) ;
2020-02-29 14:40:29 +01:00
connect ( m_toolManager , & pdf : : PDFToolManager : : messageDisplayRequest , statusBar ( ) , & QStatusBar : : showMessage ) ;
2020-01-12 18:46:59 +01:00
2020-04-11 13:56:05 +02:00
m_annotationManager = new pdf : : PDFWidgetAnnotationManager ( m_pdfWidget - > getDrawWidgetProxy ( ) , this ) ;
2020-04-13 16:25:32 +02:00
connect ( m_annotationManager , & pdf : : PDFWidgetAnnotationManager : : actionTriggered , this , & PDFViewerMainWindow : : onActionTriggered ) ;
2020-04-20 19:03:32 +02:00
m_pdfWidget - > setAnnotationManager ( m_annotationManager ) ;
2020-03-07 17:38:50 +01:00
2020-04-22 20:00:44 +02:00
m_formManager = new pdf : : PDFFormManager ( m_pdfWidget - > getDrawWidgetProxy ( ) , this ) ;
m_formManager - > setAnnotationManager ( m_annotationManager ) ;
m_formManager - > setAppearanceFlags ( m_settings - > getSettings ( ) . m_formAppearanceFlags ) ;
m_annotationManager - > setFormManager ( m_formManager ) ;
2020-04-26 19:43:45 +02:00
m_pdfWidget - > setFormManager ( m_formManager ) ;
2020-04-28 19:55:30 +02:00
connect ( m_formManager , & pdf : : PDFFormManager : : actionTriggered , this , & PDFViewerMainWindow : : onActionTriggered ) ;
2020-05-02 18:04:25 +02:00
connect ( m_formManager , & pdf : : PDFFormManager : : documentModified , this , & PDFViewerMainWindow : : onDocumentModified ) ;
2020-04-22 20:00:44 +02:00
2019-11-06 18:25:46 +01:00
connect ( m_pdfWidget - > getDrawWidgetProxy ( ) , & pdf : : PDFDrawWidgetProxy : : drawSpaceChanged , this , & PDFViewerMainWindow : : onDrawSpaceChanged ) ;
connect ( m_pdfWidget - > getDrawWidgetProxy ( ) , & pdf : : PDFDrawWidgetProxy : : pageLayoutChanged , this , & PDFViewerMainWindow : : onPageLayoutChanged ) ;
2019-02-24 19:42:00 +01:00
connect ( m_pdfWidget , & pdf : : PDFWidget : : pageRenderingErrorsChanged , this , & PDFViewerMainWindow : : onPageRenderingErrorsChanged , Qt : : QueuedConnection ) ;
2019-07-06 15:55:37 +02:00
connect ( m_settings , & PDFViewerSettings : : settingsChanged , this , & PDFViewerMainWindow : : onViewerSettingsChanged ) ;
2019-11-09 17:27:17 +01:00
connect ( m_progress , & pdf : : PDFProgress : : progressStarted , this , & PDFViewerMainWindow : : onProgressStarted ) ;
connect ( m_progress , & pdf : : PDFProgress : : progressStep , this , & PDFViewerMainWindow : : onProgressStep ) ;
connect ( m_progress , & pdf : : PDFProgress : : progressFinished , this , & PDFViewerMainWindow : : onProgressFinished ) ;
2019-12-23 15:58:40 +01:00
connect ( this , & PDFViewerMainWindow : : queryPasswordRequest , this , & PDFViewerMainWindow : : onQueryPasswordRequest , Qt : : BlockingQueuedConnection ) ;
2020-01-25 17:36:25 +01:00
connect ( ui - > actionFind , & QAction : : triggered , this , [ this ] { m_toolManager - > setActiveTool ( m_toolManager - > getFindTextTool ( ) ) ; } ) ;
2019-02-03 13:57:37 +01:00
2020-05-03 18:52:22 +02:00
// Connect undo/redo manager
connect ( m_undoRedoManager , & PDFUndoRedoManager : : undoRedoStateChanged , this , & PDFViewerMainWindow : : updateUndoRedoActions ) ;
connect ( m_undoRedoManager , & PDFUndoRedoManager : : documentChangeRequest , this , & PDFViewerMainWindow : : onDocumentUndoRedo ) ;
connect ( ui - > actionUndo , & QAction : : triggered , m_undoRedoManager , & PDFUndoRedoManager : : doUndo ) ;
connect ( ui - > actionRedo , & QAction : : triggered , m_undoRedoManager , & PDFUndoRedoManager : : doRedo ) ;
updateUndoRedoSettings ( ) ;
2019-12-16 19:46:29 +01:00
readActionSettings ( ) ;
2019-02-03 13:57:37 +01:00
updatePageLayoutActions ( ) ;
2019-11-06 18:25:46 +01:00
updateUI ( true ) ;
2019-12-14 19:09:34 +01:00
onViewerSettingsChanged ( ) ;
2019-12-23 15:58:40 +01:00
updateActionsAvailability ( ) ;
2020-11-17 18:28:34 +01:00
loadPlugins ( ) ;
}
void PDFViewerMainWindow : : loadPlugins ( )
{
QDir directory ( QApplication : : applicationDirPath ( ) + " /pdfplugins " ) ;
QStringList availablePlugins = directory . entryList ( QStringList ( " *.dll " ) ) ;
for ( const QString & availablePlugin : availablePlugins )
{
QString pluginFileName = directory . absoluteFilePath ( availablePlugin ) ;
QPluginLoader loader ( pluginFileName ) ;
if ( loader . load ( ) )
{
QJsonObject metaData = loader . metaData ( ) ;
m_plugins . emplace_back ( pdf : : PDFPluginInfo : : loadFromJson ( & metaData ) ) ;
if ( ! m_enabledPlugins . contains ( m_plugins . back ( ) . name ) )
{
loader . unload ( ) ;
continue ;
}
pdf : : PDFPlugin * plugin = qobject_cast < pdf : : PDFPlugin * > ( loader . instance ( ) ) ;
if ( plugin )
{
m_loadedPlugins . push_back ( std : : make_pair ( m_plugins . back ( ) , plugin ) ) ;
}
}
}
auto comparator = [ ] ( const std : : pair < pdf : : PDFPluginInfo , pdf : : PDFPlugin * > & l , const std : : pair < pdf : : PDFPluginInfo , pdf : : PDFPlugin * > & r )
{
return l . first . name < r . first . name ;
} ;
std : : sort ( m_loadedPlugins . begin ( ) , m_loadedPlugins . end ( ) , comparator ) ;
for ( const auto & plugin : m_loadedPlugins )
{
plugin . second - > setWidget ( m_pdfWidget ) ;
2020-11-19 19:54:33 +01:00
std : : vector < QAction * > actions = plugin . second - > getActions ( ) ;
if ( ! actions . empty ( ) )
{
QMenu * menu = ui - > menuTools - > addMenu ( plugin . first . name ) ;
for ( QAction * action : actions )
{
menu - > addAction ( action ) ;
}
}
2020-11-17 18:28:34 +01:00
}
2018-11-21 19:30:15 +01:00
}
PDFViewerMainWindow : : ~ PDFViewerMainWindow ( )
{
2020-04-22 20:00:44 +02:00
delete m_formManager ;
m_formManager = nullptr ;
2020-03-07 17:38:50 +01:00
delete m_annotationManager ;
m_annotationManager = nullptr ;
2018-11-21 19:30:15 +01:00
delete ui ;
}
void PDFViewerMainWindow : : onActionOpenTriggered ( )
{
2019-07-06 15:55:37 +02:00
QString fileName = QFileDialog : : getOpenFileName ( this , tr ( " Select PDF document " ) , m_settings - > getDirectory ( ) , tr ( " PDF document (*.pdf) " ) ) ;
2018-11-21 19:30:15 +01:00
if ( ! fileName . isEmpty ( ) )
{
2019-01-27 17:55:22 +01:00
openDocument ( fileName ) ;
}
}
2018-11-21 19:30:15 +01:00
2019-01-27 17:55:22 +01:00
void PDFViewerMainWindow : : onActionCloseTriggered ( )
{
closeDocument ( ) ;
}
2019-01-20 17:55:06 +01:00
2019-01-27 17:55:22 +01:00
void PDFViewerMainWindow : : onActionQuitTriggered ( )
{
close ( ) ;
}
2019-01-20 17:55:06 +01:00
2019-02-24 19:42:00 +01:00
void PDFViewerMainWindow : : onPageRenderingErrorsChanged ( pdf : : PDFInteger pageIndex , int errorsCount )
{
if ( errorsCount > 0 )
{
statusBar ( ) - > showMessage ( tr ( " Rendering of page %1: %2 errors occured. " ) . arg ( pageIndex + 1 ) . arg ( errorsCount ) , 4000 ) ;
}
}
2019-11-06 18:25:46 +01:00
void PDFViewerMainWindow : : onDrawSpaceChanged ( )
{
updateUI ( false ) ;
}
void PDFViewerMainWindow : : onPageLayoutChanged ( )
{
updateUI ( false ) ;
updatePageLayoutActions ( ) ;
}
2019-11-09 15:11:57 +01:00
void PDFViewerMainWindow : : onPageNumberSpinboxEditingFinished ( )
{
if ( m_isLoadingUI )
{
return ;
}
if ( m_pageNumberSpinBox - > hasFocus ( ) )
{
m_pdfWidget - > setFocus ( ) ;
}
m_pdfWidget - > getDrawWidgetProxy ( ) - > goToPage ( m_pageNumberSpinBox - > value ( ) - 1 ) ;
}
void PDFViewerMainWindow : : onPageZoomSpinboxEditingFinished ( )
{
if ( m_isLoadingUI )
{
return ;
}
if ( m_pageZoomSpinBox - > hasFocus ( ) )
{
m_pdfWidget - > setFocus ( ) ;
}
m_pdfWidget - > getDrawWidgetProxy ( ) - > zoom ( m_pageZoomSpinBox - > value ( ) / 100.0 ) ;
}
2019-11-29 19:10:29 +01:00
void PDFViewerMainWindow : : onActionTriggered ( const pdf : : PDFAction * action )
{
2019-11-30 16:26:32 +01:00
Q_ASSERT ( action ) ;
2019-11-29 19:10:29 +01:00
2019-11-30 16:26:32 +01:00
for ( const pdf : : PDFAction * currentAction : action - > getActionList ( ) )
{
switch ( action - > getType ( ) )
{
case pdf : : ActionType : : GoTo :
{
const pdf : : PDFActionGoTo * typedAction = dynamic_cast < const pdf : : PDFActionGoTo * > ( currentAction ) ;
pdf : : PDFDestination destination = typedAction - > getDestination ( ) ;
if ( destination . getDestinationType ( ) = = pdf : : DestinationType : : Named )
{
2020-08-01 18:24:33 +02:00
if ( const pdf : : PDFDestination * targetDestination = m_pdfDocument - > getCatalog ( ) - > getNamedDestination ( destination . getName ( ) ) )
2019-11-30 16:26:32 +01:00
{
destination = * targetDestination ;
}
else
{
destination = pdf : : PDFDestination ( ) ;
QMessageBox : : critical ( this , tr ( " Go to action " ) , tr ( " Failed to go to destination '%1'. Destination wasn't found. " ) . arg ( pdf : : PDFEncoding : : convertTextString ( destination . getName ( ) ) ) ) ;
}
}
if ( destination . getDestinationType ( ) ! = pdf : : DestinationType : : Invalid & &
destination . getPageReference ( ) ! = pdf : : PDFObjectReference ( ) )
{
const size_t pageIndex = m_pdfDocument - > getCatalog ( ) - > getPageIndexFromPageReference ( destination . getPageReference ( ) ) ;
if ( pageIndex ! = pdf : : PDFCatalog : : INVALID_PAGE_INDEX )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > goToPage ( pageIndex ) ;
2019-12-01 13:02:25 +01:00
switch ( destination . getDestinationType ( ) )
{
case pdf : : DestinationType : : Fit :
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomFit ) ;
break ;
case pdf : : DestinationType : : FitH :
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomFitWidth ) ;
break ;
case pdf : : DestinationType : : FitV :
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomFitHeight ) ;
break ;
default :
break ;
}
2019-11-30 16:26:32 +01:00
}
}
break ;
}
case pdf : : ActionType : : Launch :
{
if ( ! m_settings - > getSettings ( ) . m_allowLaunchApplications )
{
// Launching of applications is disabled -> continue to next action
continue ;
}
const pdf : : PDFActionLaunch * typedAction = dynamic_cast < const pdf : : PDFActionLaunch * > ( currentAction ) ;
# ifdef Q_OS_WIN
const pdf : : PDFActionLaunch : : Win & winSpecification = typedAction - > getWinSpecification ( ) ;
if ( ! winSpecification . file . isEmpty ( ) )
{
QString message = tr ( " Would you like to launch application '%1' in working directory '%2' with parameters '%3'? " ) . arg ( QString : : fromLatin1 ( winSpecification . file ) , QString : : fromLatin1 ( winSpecification . directory ) , QString : : fromLatin1 ( winSpecification . parameters ) ) ;
if ( QMessageBox : : question ( this , tr ( " Launch application " ) , message ) = = QMessageBox : : Yes )
{
auto getStringOrNULL = [ ] ( const QByteArray & array ) - > LPCSTR
{
if ( ! array . isEmpty ( ) )
{
return array . data ( ) ;
}
return NULL ;
} ;
const HINSTANCE result = : : ShellExecuteA ( NULL , getStringOrNULL ( winSpecification . operation ) , getStringOrNULL ( winSpecification . file ) , getStringOrNULL ( winSpecification . parameters ) , getStringOrNULL ( winSpecification . directory ) , SW_SHOWNORMAL ) ;
if ( result < = HINSTANCE ( 32 ) )
{
// Error occured
QMessageBox : : warning ( this , tr ( " Launch application " ) , tr ( " Executing application failed. Error code is %1. " ) . arg ( reinterpret_cast < intptr_t > ( result ) ) ) ;
}
}
// Continue next action
continue ;
}
const pdf : : PDFFileSpecification & fileSpecification = typedAction - > getFileSpecification ( ) ;
QString plaftormFileName = fileSpecification . getPlatformFileName ( ) ;
if ( ! plaftormFileName . isEmpty ( ) )
{
QString message = tr ( " Would you like to launch application '%1'? " ) . arg ( plaftormFileName ) ;
if ( QMessageBox : : question ( this , tr ( " Launch application " ) , message ) = = QMessageBox : : Yes )
{
const HINSTANCE result = : : ShellExecuteW ( NULL , NULL , plaftormFileName . toStdWString ( ) . c_str ( ) , NULL , NULL , SW_SHOWNORMAL ) ;
if ( result < = HINSTANCE ( 32 ) )
{
// Error occured
QMessageBox : : warning ( this , tr ( " Launch application " ) , tr ( " Executing application failed. Error code is %1. " ) . arg ( reinterpret_cast < intptr_t > ( result ) ) ) ;
}
}
// Continue next action
continue ;
}
# endif
break ;
}
case pdf : : ActionType : : URI :
{
if ( ! m_settings - > getSettings ( ) . m_allowLaunchURI )
{
// Launching of URI is disabled -> continue to next action
continue ;
}
const pdf : : PDFActionURI * typedAction = dynamic_cast < const pdf : : PDFActionURI * > ( currentAction ) ;
QByteArray URI = m_pdfDocument - > getCatalog ( ) - > getBaseURI ( ) + typedAction - > getURI ( ) ;
2020-09-05 18:38:46 +02:00
QString urlString = QString : : fromUtf8 ( URI ) ;
2019-11-30 16:26:32 +01:00
QString message = tr ( " Would you like to open URL '%1'? " ) . arg ( urlString ) ;
if ( QMessageBox : : question ( this , tr ( " Open URL " ) , message ) = = QMessageBox : : Yes )
{
if ( ! QDesktopServices : : openUrl ( QUrl ( urlString ) ) )
{
// Error occured
QMessageBox : : warning ( this , tr ( " Open URL " ) , tr ( " Opening url '%1' failed. " ) . arg ( urlString ) ) ;
}
}
break ;
}
case pdf : : ActionType : : Named :
{
const pdf : : PDFActionNamed * typedAction = dynamic_cast < const pdf : : PDFActionNamed * > ( currentAction ) ;
switch ( typedAction - > getNamedActionType ( ) )
{
case pdf : : PDFActionNamed : : NamedActionType : : NextPage :
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : NavigateNextPage ) ;
break ;
case pdf : : PDFActionNamed : : NamedActionType : : PrevPage :
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : NavigatePreviousPage ) ;
break ;
case pdf : : PDFActionNamed : : NamedActionType : : FirstPage :
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : NavigateDocumentStart ) ;
break ;
case pdf : : PDFActionNamed : : NamedActionType : : LastPage :
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : NavigateDocumentEnd ) ;
break ;
default :
break ;
}
break ;
}
case pdf : : ActionType : : SetOCGState :
{
const pdf : : PDFActionSetOCGState * typedAction = dynamic_cast < const pdf : : PDFActionSetOCGState * > ( currentAction ) ;
const pdf : : PDFActionSetOCGState : : StateChangeItems & stateChanges = typedAction - > getStateChangeItems ( ) ;
const bool isRadioButtonsPreserved = typedAction - > isRadioButtonsPreserved ( ) ;
if ( m_optionalContentActivity )
{
for ( const pdf : : PDFActionSetOCGState : : StateChangeItem & stateChange : stateChanges )
{
pdf : : OCState newState = pdf : : OCState : : Unknown ;
switch ( stateChange . first )
{
case pdf : : PDFActionSetOCGState : : SwitchType : : ON :
newState = pdf : : OCState : : ON ;
break ;
case pdf : : PDFActionSetOCGState : : SwitchType : : OFF :
newState = pdf : : OCState : : OFF ;
break ;
case pdf : : PDFActionSetOCGState : : SwitchType : : Toggle :
{
pdf : : OCState oldState = m_optionalContentActivity - > getState ( stateChange . second ) ;
switch ( oldState )
{
case pdf : : OCState : : ON :
newState = pdf : : OCState : : OFF ;
break ;
case pdf : : OCState : : OFF :
newState = pdf : : OCState : : ON ;
break ;
case pdf : : OCState : : Unknown :
break ;
default :
Q_ASSERT ( false ) ;
break ;
}
break ;
}
default :
Q_ASSERT ( false ) ;
}
if ( newState ! = pdf : : OCState : : Unknown )
{
m_optionalContentActivity - > setState ( stateChange . second , newState , isRadioButtonsPreserved ) ;
}
}
}
break ;
}
2020-05-28 19:06:27 +02:00
case pdf : : ActionType : : ResetForm :
{
m_formManager - > performResetAction ( dynamic_cast < const pdf : : PDFActionResetForm * > ( action ) ) ;
break ;
}
2019-11-30 16:26:32 +01:00
default :
break ;
}
}
2019-11-29 19:10:29 +01:00
}
2020-01-01 18:23:18 +01:00
void PDFViewerMainWindow : : onProgressStarted ( pdf : : ProgressStartupInfo info )
2019-11-09 17:27:17 +01:00
{
2020-01-01 18:23:18 +01:00
Q_ASSERT ( ! m_progressDialog ) ;
if ( info . showDialog )
{
m_progressDialog = new QProgressDialog ( info . text , QString ( ) , 0 , 100 , this ) ;
m_progressDialog - > setWindowModality ( Qt : : WindowModal ) ;
m_progressDialog - > setCancelButton ( nullptr ) ;
}
2019-11-09 17:27:17 +01:00
m_progressTaskbarIndicator - > setRange ( 0 , 100 ) ;
m_progressTaskbarIndicator - > reset ( ) ;
m_progressTaskbarIndicator - > show ( ) ;
2020-01-01 18:23:18 +01:00
m_isBusy = true ;
updateActionsAvailability ( ) ;
2019-11-09 17:27:17 +01:00
}
void PDFViewerMainWindow : : onProgressStep ( int percentage )
{
2020-01-26 17:06:50 +01:00
if ( m_isChangingProgressStep )
{
return ;
}
pdf : : PDFTemporaryValueChange guard ( & m_isChangingProgressStep , true ) ;
2020-01-01 18:23:18 +01:00
if ( m_progressDialog )
{
m_progressDialog - > setValue ( percentage ) ;
}
2019-11-09 17:27:17 +01:00
m_progressTaskbarIndicator - > setValue ( percentage ) ;
}
void PDFViewerMainWindow : : onProgressFinished ( )
{
2020-01-01 18:23:18 +01:00
if ( m_progressDialog )
{
m_progressDialog - > hide ( ) ;
m_progressDialog - > deleteLater ( ) ;
m_progressDialog = nullptr ;
}
2019-11-09 17:27:17 +01:00
m_progressTaskbarIndicator - > hide ( ) ;
2020-01-01 18:23:18 +01:00
m_isBusy = false ;
updateActionsAvailability ( ) ;
2019-11-09 17:27:17 +01:00
}
2019-01-27 17:55:22 +01:00
void PDFViewerMainWindow : : readSettings ( )
{
2019-07-06 15:55:37 +02:00
QSettings settings ( QSettings : : IniFormat , QSettings : : UserScope , QCoreApplication : : organizationName ( ) , QCoreApplication : : applicationName ( ) ) ;
2019-01-27 17:55:22 +01:00
QByteArray geometry = settings . value ( " geometry " , QByteArray ( ) ) . toByteArray ( ) ;
if ( geometry . isEmpty ( ) )
{
QRect availableGeometry = QApplication : : desktop ( ) - > availableGeometry ( this ) ;
QRect windowRect ( 0 , 0 , availableGeometry . width ( ) / 2 , availableGeometry . height ( ) / 2 ) ;
windowRect = windowRect . translated ( availableGeometry . center ( ) - windowRect . center ( ) ) ;
setGeometry ( windowRect ) ;
}
else
{
restoreGeometry ( geometry ) ;
}
QByteArray state = settings . value ( " windowState " , QByteArray ( ) ) . toByteArray ( ) ;
if ( ! state . isEmpty ( ) )
{
restoreState ( state ) ;
}
2019-12-24 17:29:40 +01:00
m_settings - > readSettings ( settings , m_CMSManager - > getDefaultSettings ( ) ) ;
2019-12-25 14:34:37 +01:00
m_CMSManager - > setSettings ( m_settings - > getColorManagementSystemSettings ( ) ) ;
2020-02-18 20:21:18 +01:00
m_textToSpeech - > setSettings ( m_settings ) ;
2020-04-22 20:00:44 +02:00
if ( m_formManager )
{
m_formManager - > setAppearanceFlags ( m_settings - > getSettings ( ) . m_formAppearanceFlags ) ;
}
2020-11-17 18:28:34 +01:00
// Load allowed plugins
settings . beginGroup ( " Plugins " ) ;
m_enabledPlugins = settings . value ( " EnabledPlugins " ) . toStringList ( ) ;
settings . endGroup ( ) ;
2019-12-16 19:46:29 +01:00
}
void PDFViewerMainWindow : : readActionSettings ( )
{
QSettings settings ( QSettings : : IniFormat , QSettings : : UserScope , QCoreApplication : : organizationName ( ) , QCoreApplication : : applicationName ( ) ) ;
// Load action shortcuts
settings . beginGroup ( " Actions " ) ;
for ( QAction * action : getActions ( ) )
{
QString name = action - > objectName ( ) ;
if ( ! name . isEmpty ( ) & & settings . contains ( name ) )
{
QKeySequence sequence = QKeySequence : : fromString ( settings . value ( name , action - > shortcut ( ) . toString ( QKeySequence : : PortableText ) ) . toString ( ) , QKeySequence : : PortableText ) ;
action - > setShortcut ( sequence ) ;
}
}
settings . endGroup ( ) ;
2020-02-01 11:56:40 +01:00
// Load recent files
settings . beginGroup ( " RecentFiles " ) ;
m_recentFileManager - > setRecentFilesLimit ( settings . value ( " MaximumRecentFilesCount " , PDFRecentFileManager : : getDefaultRecentFiles ( ) ) . toInt ( ) ) ;
m_recentFileManager - > setRecentFiles ( settings . value ( " RecentFileList " , QStringList ( ) ) . toStringList ( ) ) ;
settings . endGroup ( ) ;
2020-06-28 18:55:09 +02:00
// Load trusted certificates
2020-09-27 18:02:57 +02:00
m_certificateStore . loadDefaultUserCertificates ( ) ;
2019-01-27 17:55:22 +01:00
}
void PDFViewerMainWindow : : writeSettings ( )
{
2019-07-06 15:55:37 +02:00
QSettings settings ( QSettings : : IniFormat , QSettings : : UserScope , QCoreApplication : : organizationName ( ) , QCoreApplication : : applicationName ( ) ) ;
2019-01-27 17:55:22 +01:00
settings . setValue ( " geometry " , saveGeometry ( ) ) ;
settings . setValue ( " windowState " , saveState ( ) ) ;
2019-07-06 15:55:37 +02:00
m_settings - > writeSettings ( settings ) ;
2019-12-16 19:46:29 +01:00
// Save action shortcuts
settings . beginGroup ( " Actions " ) ;
for ( QAction * action : getActions ( ) )
{
QString name = action - > objectName ( ) ;
if ( ! name . isEmpty ( ) )
{
QString accelerator = action - > shortcut ( ) . toString ( QKeySequence : : PortableText ) ;
settings . setValue ( name , accelerator ) ;
}
}
settings . endGroup ( ) ;
2020-02-01 11:56:40 +01:00
// Save recent files
settings . beginGroup ( " RecentFiles " ) ;
settings . setValue ( " MaximumRecentFilesCount " , m_recentFileManager - > getRecentFilesLimit ( ) ) ;
settings . setValue ( " RecentFileList " , m_recentFileManager - > getRecentFiles ( ) ) ;
settings . endGroup ( ) ;
2020-06-28 18:55:09 +02:00
2020-11-17 18:28:34 +01:00
// Save allowed plugins
settings . beginGroup ( " Plugins " ) ;
settings . setValue ( " EnabledPlugins " , m_enabledPlugins ) ;
settings . endGroup ( ) ;
2020-06-28 18:55:09 +02:00
// Save trusted certificates
2020-09-27 18:02:57 +02:00
m_certificateStore . saveDefaultUserCertificates ( ) ;
2019-01-27 17:55:22 +01:00
}
void PDFViewerMainWindow : : updateTitle ( )
{
if ( m_pdfDocument )
{
QString title = m_pdfDocument - > getInfo ( ) - > title ;
if ( title . isEmpty ( ) )
2019-01-20 17:55:06 +01:00
{
2020-06-07 17:46:49 +02:00
title = m_fileInfo . fileName ;
2019-01-20 17:55:06 +01:00
}
2020-06-07 17:46:49 +02:00
setWindowTitle ( tr ( " %1 - PDF Viewer " ) . arg ( m_fileInfo . fileName ) ) ;
2019-01-27 17:55:22 +01:00
}
else
{
setWindowTitle ( tr ( " PDF Viewer " ) ) ;
}
}
2019-02-03 13:57:37 +01:00
void PDFViewerMainWindow : : updatePageLayoutActions ( )
{
for ( QAction * action : { ui - > actionPageLayoutContinuous , ui - > actionPageLayoutSinglePage , ui - > actionPageLayoutTwoColumns , ui - > actionPageLayoutTwoPages } )
{
action - > setChecked ( false ) ;
}
const pdf : : PageLayout pageLayout = m_pdfWidget - > getDrawWidgetProxy ( ) - > getPageLayout ( ) ;
switch ( pageLayout )
{
case pdf : : PageLayout : : SinglePage :
ui - > actionPageLayoutSinglePage - > setChecked ( true ) ;
break ;
case pdf : : PageLayout : : OneColumn :
ui - > actionPageLayoutContinuous - > setChecked ( true ) ;
break ;
case pdf : : PageLayout : : TwoColumnLeft :
case pdf : : PageLayout : : TwoColumnRight :
ui - > actionPageLayoutTwoColumns - > setChecked ( true ) ;
ui - > actionFirstPageOnRightSide - > setChecked ( pageLayout = = pdf : : PageLayout : : TwoColumnRight ) ;
break ;
case pdf : : PageLayout : : TwoPagesLeft :
case pdf : : PageLayout : : TwoPagesRight :
ui - > actionPageLayoutTwoPages - > setChecked ( true ) ;
ui - > actionFirstPageOnRightSide - > setChecked ( pageLayout = = pdf : : PageLayout : : TwoPagesRight ) ;
break ;
default :
Q_ASSERT ( false ) ;
}
}
2019-07-06 15:55:37 +02:00
void PDFViewerMainWindow : : updateRenderingOptionActions ( )
{
const pdf : : PDFRenderer : : Features features = m_settings - > getFeatures ( ) ;
for ( QAction * action : getRenderingOptionActions ( ) )
{
action - > setChecked ( features . testFlag ( static_cast < pdf : : PDFRenderer : : Feature > ( action - > data ( ) . toInt ( ) ) ) ) ;
}
}
2019-11-06 18:25:46 +01:00
void PDFViewerMainWindow : : updateUI ( bool fullUpdate )
{
pdf : : PDFTemporaryValueChange guard ( & m_isLoadingUI , true ) ;
if ( fullUpdate )
{
if ( m_pdfDocument )
{
size_t pageCount = m_pdfDocument - > getCatalog ( ) - > getPageCount ( ) ;
m_pageNumberSpinBox - > setMinimum ( 1 ) ;
m_pageNumberSpinBox - > setMaximum ( static_cast < int > ( pageCount ) ) ;
m_pageNumberSpinBox - > setEnabled ( true ) ;
m_pageNumberLabel - > setText ( tr ( " / %1 " ) . arg ( pageCount ) ) ;
}
else
{
m_pageNumberSpinBox - > setEnabled ( false ) ;
m_pageNumberLabel - > setText ( QString ( ) ) ;
}
2019-12-20 18:56:03 +01:00
ui - > actionProperties - > setEnabled ( m_pdfDocument ) ;
2019-12-22 18:03:19 +01:00
ui - > actionSend_by_E_Mail - > setEnabled ( m_pdfDocument ) ;
2019-11-06 18:25:46 +01:00
}
2019-11-09 15:11:57 +01:00
else
{
std : : vector < pdf : : PDFInteger > currentPages = m_pdfWidget - > getDrawWidget ( ) - > getCurrentPages ( ) ;
if ( ! currentPages . empty ( ) )
{
m_pageNumberSpinBox - > setValue ( currentPages . front ( ) + 1 ) ;
2019-12-15 17:46:58 +01:00
// Prefetch pages, if it is enabled
if ( m_settings - > isPagePrefetchingEnabled ( ) )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > prefetchPages ( currentPages . back ( ) ) ;
}
2019-11-09 15:11:57 +01:00
}
2019-12-08 19:20:36 +01:00
m_sidebarWidget - > setCurrentPages ( currentPages ) ;
2019-11-09 15:11:57 +01:00
}
2019-11-06 18:25:46 +01:00
m_pageZoomSpinBox - > setValue ( m_pdfWidget - > getDrawWidgetProxy ( ) - > getZoom ( ) * 100 ) ;
}
2019-12-23 15:58:40 +01:00
void PDFViewerMainWindow : : updateActionsAvailability ( )
{
2020-05-30 18:31:50 +02:00
const bool isBusy = ( m_futureWatcher & & m_futureWatcher - > isRunning ( ) ) | | m_isBusy ;
2019-12-23 15:58:40 +01:00
const bool hasDocument = m_pdfDocument ;
2020-01-01 18:23:18 +01:00
const bool hasValidDocument = ! isBusy & & hasDocument ;
2020-02-03 19:45:17 +01:00
bool canPrint = false ;
if ( m_pdfDocument )
{
const pdf : : PDFObjectStorage & storage = m_pdfDocument - > getStorage ( ) ;
const pdf : : PDFSecurityHandler * securityHandler = storage . getSecurityHandler ( ) ;
canPrint = securityHandler - > isAllowed ( pdf : : PDFSecurityHandler : : Permission : : PrintLowResolution ) | |
securityHandler - > isAllowed ( pdf : : PDFSecurityHandler : : Permission : : PrintHighResolution ) ;
}
2019-12-23 15:58:40 +01:00
2020-01-01 18:23:18 +01:00
ui - > actionOpen - > setEnabled ( ! isBusy ) ;
2019-12-23 15:58:40 +01:00
ui - > actionClose - > setEnabled ( hasValidDocument ) ;
2020-01-01 18:23:18 +01:00
ui - > actionQuit - > setEnabled ( ! isBusy ) ;
ui - > actionOptions - > setEnabled ( ! isBusy ) ;
ui - > actionAbout - > setEnabled ( ! isBusy ) ;
2019-12-23 15:58:40 +01:00
ui - > actionFitPage - > setEnabled ( hasValidDocument ) ;
ui - > actionFitWidth - > setEnabled ( hasValidDocument ) ;
ui - > actionFitHeight - > setEnabled ( hasValidDocument ) ;
ui - > actionRendering_Errors - > setEnabled ( hasValidDocument ) ;
2020-01-12 18:46:59 +01:00
ui - > actionFind - > setEnabled ( hasValidDocument ) ;
2020-02-03 19:45:17 +01:00
ui - > actionPrint - > setEnabled ( hasValidDocument & & canPrint ) ;
2020-02-08 18:09:46 +01:00
ui - > actionRender_to_Images - > setEnabled ( hasValidDocument & & canPrint ) ;
2020-05-31 18:31:59 +02:00
ui - > actionOptimize - > setEnabled ( hasValidDocument ) ;
2020-06-07 17:46:49 +02:00
ui - > actionSave - > setEnabled ( hasValidDocument ) ;
ui - > actionSave_As - > setEnabled ( hasValidDocument ) ;
2020-01-01 18:23:18 +01:00
setEnabled ( ! isBusy ) ;
2020-05-03 18:52:22 +02:00
updateUndoRedoActions ( ) ;
2019-12-23 15:58:40 +01:00
}
2019-07-06 15:55:37 +02:00
void PDFViewerMainWindow : : onViewerSettingsChanged ( )
{
2019-09-08 11:13:59 +02:00
m_pdfWidget - > updateRenderer ( m_settings - > getRendererEngine ( ) , m_settings - > isMultisampleAntialiasingEnabled ( ) ? m_settings - > getRendererSamples ( ) : - 1 ) ;
2019-12-15 19:28:25 +01:00
m_pdfWidget - > updateCacheLimits ( m_settings - > getCompiledPageCacheLimit ( ) * 1024 , m_settings - > getThumbnailsCacheLimit ( ) , m_settings - > getFontCacheLimit ( ) , m_settings - > getInstancedFontCacheLimit ( ) ) ;
2019-07-06 15:55:37 +02:00
m_pdfWidget - > getDrawWidgetProxy ( ) - > setFeatures ( m_settings - > getFeatures ( ) ) ;
2019-09-28 18:26:31 +02:00
m_pdfWidget - > getDrawWidgetProxy ( ) - > setPreferredMeshResolutionRatio ( m_settings - > getPreferredMeshResolutionRatio ( ) ) ;
m_pdfWidget - > getDrawWidgetProxy ( ) - > setMinimalMeshResolutionRatio ( m_settings - > getMinimalMeshResolutionRatio ( ) ) ;
m_pdfWidget - > getDrawWidgetProxy ( ) - > setColorTolerance ( m_settings - > getColorTolerance ( ) ) ;
2020-04-11 13:56:05 +02:00
m_annotationManager - > setFeatures ( m_settings - > getFeatures ( ) ) ;
m_annotationManager - > setMeshQualitySettings ( m_pdfWidget - > getDrawWidgetProxy ( ) - > getMeshQualitySettings ( ) ) ;
2020-01-18 14:55:26 +01:00
pdf : : PDFExecutionPolicy : : setStrategy ( m_settings - > getMultithreadingStrategy ( ) ) ;
2019-12-15 19:28:25 +01:00
2019-07-06 15:55:37 +02:00
updateRenderingOptionActions ( ) ;
}
void PDFViewerMainWindow : : onRenderingOptionTriggered ( bool checked )
{
QAction * action = qobject_cast < QAction * > ( sender ( ) ) ;
Q_ASSERT ( action ) ;
pdf : : PDFRenderer : : Features features = m_settings - > getFeatures ( ) ;
features . setFlag ( static_cast < pdf : : PDFRenderer : : Feature > ( action - > data ( ) . toInt ( ) ) , checked ) ;
m_settings - > setFeatures ( features ) ;
}
2020-06-07 17:46:49 +02:00
void PDFViewerMainWindow : : updateFileInfo ( const QString & fileName )
2019-01-27 17:55:22 +01:00
{
2019-12-20 18:56:03 +01:00
QFileInfo fileInfo ( fileName ) ;
2019-12-22 18:03:19 +01:00
m_fileInfo . originalFileName = fileName ;
2019-12-20 18:56:03 +01:00
m_fileInfo . fileName = fileInfo . fileName ( ) ;
m_fileInfo . path = fileInfo . path ( ) ;
m_fileInfo . fileSize = fileInfo . size ( ) ;
m_fileInfo . writable = fileInfo . isWritable ( ) ;
m_fileInfo . creationTime = fileInfo . created ( ) ;
m_fileInfo . lastModifiedTime = fileInfo . lastModified ( ) ;
m_fileInfo . lastReadTime = fileInfo . lastRead ( ) ;
2020-06-07 17:46:49 +02:00
}
void PDFViewerMainWindow : : openDocument ( const QString & fileName )
{
// First close old document
closeDocument ( ) ;
updateFileInfo ( fileName ) ;
2019-12-20 18:56:03 +01:00
2019-12-23 15:58:40 +01:00
QApplication : : setOverrideCursor ( Qt : : WaitCursor ) ;
auto readDocument = [ this , fileName ] ( ) - > AsyncReadingResult
2019-08-10 17:24:12 +02:00
{
2019-12-23 15:58:40 +01:00
AsyncReadingResult result ;
auto queryPassword = [ this ] ( bool * ok )
{
QString result ;
* ok = false ;
emit queryPasswordRequest ( & result , ok ) ;
return result ;
} ;
// Try to open a new document
2020-09-17 19:17:16 +02:00
pdf : : PDFDocumentReader reader ( m_progress , qMove ( queryPassword ) , true ) ;
2019-12-23 15:58:40 +01:00
pdf : : PDFDocument document = reader . readFromFile ( fileName ) ;
result . errorMessage = reader . getErrorMessage ( ) ;
result . result = reader . getReadingResult ( ) ;
if ( result . result = = pdf : : PDFDocumentReader : : Result : : OK )
{
2020-06-14 18:40:42 +02:00
// Verify signatures
2020-06-27 17:28:03 +02:00
pdf : : PDFSignatureHandler : : Parameters parameters ;
parameters . store = & m_certificateStore ;
2020-07-04 15:10:28 +02:00
parameters . dss = & document . getCatalog ( ) - > getDocumentSecurityStore ( ) ;
2020-06-27 17:28:03 +02:00
parameters . enableVerification = m_settings - > getSettings ( ) . m_signatureVerificationEnabled ;
parameters . ignoreExpirationDate = m_settings - > getSettings ( ) . m_signatureIgnoreCertificateValidityTime ;
parameters . useSystemCertificateStore = m_settings - > getSettings ( ) . m_signatureUseSystemStore ;
2020-06-14 18:40:42 +02:00
pdf : : PDFForm form = pdf : : PDFForm : : parse ( & document , document . getCatalog ( ) - > getFormObject ( ) ) ;
2020-06-27 17:28:03 +02:00
result . signatures = pdf : : PDFSignatureHandler : : verifySignatures ( form , reader . getSource ( ) , parameters ) ;
2019-12-23 15:58:40 +01:00
result . document . reset ( new pdf : : PDFDocument ( qMove ( document ) ) ) ;
}
return result ;
2019-08-10 17:24:12 +02:00
} ;
2019-12-23 15:58:40 +01:00
m_future = QtConcurrent : : run ( readDocument ) ;
2020-05-30 18:31:50 +02:00
m_futureWatcher = new QFutureWatcher < AsyncReadingResult > ( ) ;
connect ( m_futureWatcher , & QFutureWatcher < AsyncReadingResult > : : finished , this , & PDFViewerMainWindow : : onDocumentReadingFinished ) ;
m_futureWatcher - > setFuture ( m_future ) ;
2019-12-23 15:58:40 +01:00
updateActionsAvailability ( ) ;
}
2019-08-10 17:24:12 +02:00
2019-12-23 15:58:40 +01:00
void PDFViewerMainWindow : : onDocumentReadingFinished ( )
{
2019-01-27 17:55:22 +01:00
QApplication : : restoreOverrideCursor ( ) ;
2019-12-23 15:58:40 +01:00
AsyncReadingResult result = m_future . result ( ) ;
2020-05-30 18:31:50 +02:00
m_future = QFuture < AsyncReadingResult > ( ) ;
m_futureWatcher - > deleteLater ( ) ;
m_futureWatcher = nullptr ;
2019-12-23 15:58:40 +01:00
switch ( result . result )
2019-01-27 17:55:22 +01:00
{
2019-08-12 12:02:40 +02:00
case pdf : : PDFDocumentReader : : Result : : OK :
{
// Mark current directory as this
2019-12-23 15:58:40 +01:00
QFileInfo fileInfo ( m_fileInfo . originalFileName ) ;
2019-08-12 12:02:40 +02:00
m_settings - > setDirectory ( fileInfo . dir ( ) . absolutePath ( ) ) ;
2019-01-27 17:55:22 +01:00
2020-02-01 11:56:40 +01:00
// We add file to recent files only, if we have successfully read the document
m_recentFileManager - > addRecentFile ( m_fileInfo . originalFileName ) ;
2020-06-20 18:20:57 +02:00
m_pdfDocument = qMove ( result . document ) ;
m_signatures = qMove ( result . signatures ) ;
2020-04-25 14:21:06 +02:00
pdf : : PDFModifiedDocument document ( m_pdfDocument . data ( ) , m_optionalContentActivity ) ;
setDocument ( document ) ;
2019-01-27 17:55:22 +01:00
2020-09-08 15:27:40 +02:00
pdf : : PDFDocumentRequirements requirements = pdf : : PDFDocumentRequirements : : parse ( & m_pdfDocument - > getStorage ( ) , m_pdfDocument - > getCatalog ( ) - > getRequirements ( ) ) ;
2020-11-19 19:54:33 +01:00
constexpr pdf : : PDFDocumentRequirements : : Requirements requirementFlags = pdf : : PDFDocumentRequirements : : Requirements ( pdf : : PDFDocumentRequirements : : OCInteract |
pdf : : PDFDocumentRequirements : : OCAutoStates |
pdf : : PDFDocumentRequirements : : Navigation |
pdf : : PDFDocumentRequirements : : Attachment |
pdf : : PDFDocumentRequirements : : DigSigValidation |
pdf : : PDFDocumentRequirements : : Encryption ) ;
2020-09-08 15:27:40 +02:00
pdf : : PDFDocumentRequirements : : ValidationResult requirementResult = requirements . validate ( requirementFlags ) ;
if ( requirementResult . isError ( ) )
{
QMessageBox : : critical ( this , tr ( " PDF Viewer " ) , requirementResult . message ) ;
}
else if ( requirementResult . isWarning ( ) )
{
QMessageBox : : warning ( this , tr ( " PDF Viewer " ) , requirementResult . message ) ;
}
2019-12-23 15:58:40 +01:00
statusBar ( ) - > showMessage ( tr ( " Document '%1' was successfully loaded! " ) . arg ( m_fileInfo . fileName ) , 4000 ) ;
2019-08-12 12:02:40 +02:00
break ;
}
case pdf : : PDFDocumentReader : : Result : : Failed :
{
2019-12-23 15:58:40 +01:00
QMessageBox : : critical ( this , tr ( " PDF Viewer " ) , tr ( " Document read error: %1 " ) . arg ( result . errorMessage ) ) ;
2019-08-12 12:02:40 +02:00
break ;
}
case pdf : : PDFDocumentReader : : Result : : Cancelled :
break ; // Do nothing, user cancelled the document reading
2018-11-21 19:30:15 +01:00
}
2020-01-12 18:46:59 +01:00
updateActionsAvailability ( ) ;
2018-11-21 19:30:15 +01:00
}
2020-05-03 18:52:22 +02:00
void PDFViewerMainWindow : : onDocumentModified ( pdf : : PDFModifiedDocument document )
{
// We will create undo/redo step from old document, with flags from the new,
// because new document is modification of old document with flags.
Q_ASSERT ( m_pdfDocument ) ;
m_undoRedoManager - > createUndo ( document , m_pdfDocument ) ;
m_pdfDocument = document ;
document . setOptionalContentActivity ( m_optionalContentActivity ) ;
setDocument ( document ) ;
}
void PDFViewerMainWindow : : onDocumentUndoRedo ( pdf : : PDFModifiedDocument document )
2020-05-02 18:04:25 +02:00
{
m_pdfDocument = document ;
2020-05-03 18:52:22 +02:00
document . setOptionalContentActivity ( m_optionalContentActivity ) ;
setDocument ( document ) ;
2020-05-02 18:04:25 +02:00
}
2020-04-25 14:21:06 +02:00
void PDFViewerMainWindow : : setDocument ( pdf : : PDFModifiedDocument document )
2019-01-27 17:55:22 +01:00
{
2020-04-25 14:21:06 +02:00
if ( document . hasReset ( ) )
2019-07-02 16:20:12 +02:00
{
2020-04-25 14:21:06 +02:00
if ( m_optionalContentActivity )
{
// We use deleteLater, because we want to avoid consistency problem with model
// (we set document to the model before activity).
m_optionalContentActivity - > deleteLater ( ) ;
m_optionalContentActivity = nullptr ;
}
2019-07-02 16:20:12 +02:00
2020-04-25 14:21:06 +02:00
if ( document )
{
m_optionalContentActivity = new pdf : : PDFOptionalContentActivity ( document , pdf : : OCUsage : : View , this ) ;
}
2020-05-03 18:52:22 +02:00
m_undoRedoManager - > clear ( ) ;
2020-04-25 14:21:06 +02:00
}
else if ( m_optionalContentActivity )
2019-07-02 16:20:12 +02:00
{
2020-04-25 14:21:06 +02:00
Q_ASSERT ( document ) ;
m_optionalContentActivity - > setDocument ( document ) ;
2019-07-02 16:20:12 +02:00
}
2020-04-25 14:21:06 +02:00
document . setOptionalContentActivity ( m_optionalContentActivity ) ;
m_annotationManager - > setDocument ( document ) ;
2020-04-22 20:00:44 +02:00
m_formManager - > setDocument ( document ) ;
2020-01-12 18:46:59 +01:00
m_toolManager - > setDocument ( document ) ;
2020-02-18 20:21:18 +01:00
m_textToSpeech - > setDocument ( document ) ;
2020-04-25 14:21:06 +02:00
m_pdfWidget - > setDocument ( document ) ;
2020-06-20 18:20:57 +02:00
m_sidebarWidget - > setDocument ( document , m_signatures ) ;
2020-01-03 18:11:03 +01:00
m_advancedFindWidget - > setDocument ( document ) ;
2019-07-01 19:53:38 +02:00
2019-11-28 18:20:32 +01:00
if ( m_sidebarWidget - > isEmpty ( ) )
2019-07-01 19:53:38 +02:00
{
2019-11-28 18:20:32 +01:00
m_sidebarDockWidget - > hide ( ) ;
2019-07-01 19:53:38 +02:00
}
else
{
2019-11-28 18:20:32 +01:00
m_sidebarDockWidget - > show ( ) ;
2019-07-01 19:53:38 +02:00
}
2020-01-03 18:11:03 +01:00
if ( ! document )
{
m_advancedFindDockWidget - > hide ( ) ;
}
2019-01-27 17:55:22 +01:00
updateTitle ( ) ;
2019-11-06 18:25:46 +01:00
updateUI ( true ) ;
2019-11-29 19:10:29 +01:00
2020-05-03 18:52:22 +02:00
if ( m_pdfDocument & & document . hasReset ( ) )
2019-11-29 19:10:29 +01:00
{
const pdf : : PDFCatalog * catalog = m_pdfDocument - > getCatalog ( ) ;
setPageLayout ( catalog - > getPageLayout ( ) ) ;
updatePageLayoutActions ( ) ;
if ( const pdf : : PDFAction * action = catalog - > getOpenAction ( ) )
{
onActionTriggered ( action ) ;
}
}
2019-12-23 15:58:40 +01:00
updateActionsAvailability ( ) ;
2019-01-27 17:55:22 +01:00
}
void PDFViewerMainWindow : : closeDocument ( )
{
2020-06-20 18:20:57 +02:00
m_signatures . clear ( ) ;
2020-04-25 14:21:06 +02:00
setDocument ( pdf : : PDFModifiedDocument ( ) ) ;
2019-01-27 17:55:22 +01:00
m_pdfDocument . reset ( ) ;
2019-12-23 18:00:34 +01:00
updateActionsAvailability ( ) ;
2019-01-27 17:55:22 +01:00
}
2019-02-03 13:57:37 +01:00
void PDFViewerMainWindow : : setPageLayout ( pdf : : PageLayout pageLayout )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > setPageLayout ( pageLayout ) ;
}
2019-07-06 15:55:37 +02:00
std : : vector < QAction * > PDFViewerMainWindow : : getRenderingOptionActions ( ) const
{
2019-12-29 17:25:18 +01:00
return { ui - > actionRenderOptionAntialiasing ,
ui - > actionRenderOptionTextAntialiasing ,
ui - > actionRenderOptionSmoothPictures ,
ui - > actionRenderOptionIgnoreOptionalContentSettings ,
2020-04-11 13:56:05 +02:00
ui - > actionRenderOptionDisplayAnnotations ,
2019-12-29 17:25:18 +01:00
ui - > actionShow_Text_Blocks ,
2020-01-28 19:17:45 +01:00
ui - > actionShow_Text_Lines ,
ui - > actionInvertColors } ;
2019-07-06 15:55:37 +02:00
}
2019-12-16 19:46:29 +01:00
QList < QAction * > PDFViewerMainWindow : : getActions ( ) const
{
return findChildren < QAction * > ( QString ( ) , Qt : : FindChildrenRecursively ) ;
}
2019-11-06 18:25:46 +01:00
int PDFViewerMainWindow : : adjustDpiX ( int value )
{
const int physicalDpiX = this - > physicalDpiX ( ) ;
const int adjustedValue = ( value * physicalDpiX ) / 96 ;
return adjustedValue ;
}
2019-01-27 17:55:22 +01:00
void PDFViewerMainWindow : : closeEvent ( QCloseEvent * event )
{
2020-05-30 18:31:50 +02:00
if ( m_futureWatcher & & m_futureWatcher - > isRunning ( ) )
2019-12-23 15:58:40 +01:00
{
// Jakub Melka: Do not allow to close the application, if document
// reading is running.
event - > ignore ( ) ;
}
else
{
writeSettings ( ) ;
closeDocument ( ) ;
event - > accept ( ) ;
}
2019-01-27 17:55:22 +01:00
}
2019-11-09 17:27:17 +01:00
void PDFViewerMainWindow : : showEvent ( QShowEvent * event )
{
Q_UNUSED ( event ) ;
m_taskbarButton - > setWindow ( windowHandle ( ) ) ;
}
2019-12-23 15:58:40 +01:00
void PDFViewerMainWindow : : onQueryPasswordRequest ( QString * password , bool * ok )
{
* password = QInputDialog : : getText ( this , tr ( " Encrypted document " ) , tr ( " Enter password to access document content " ) , QLineEdit : : Password , QString ( ) , ok ) ;
}
2019-02-03 13:57:37 +01:00
void PDFViewerMainWindow : : on_actionPageLayoutSinglePage_triggered ( )
{
setPageLayout ( pdf : : PageLayout : : SinglePage ) ;
}
void PDFViewerMainWindow : : on_actionPageLayoutContinuous_triggered ( )
{
setPageLayout ( pdf : : PageLayout : : OneColumn ) ;
}
void PDFViewerMainWindow : : on_actionPageLayoutTwoPages_triggered ( )
{
setPageLayout ( ui - > actionFirstPageOnRightSide - > isChecked ( ) ? pdf : : PageLayout : : TwoPagesRight : pdf : : PageLayout : : TwoPagesLeft ) ;
}
void PDFViewerMainWindow : : on_actionPageLayoutTwoColumns_triggered ( )
{
setPageLayout ( ui - > actionFirstPageOnRightSide - > isChecked ( ) ? pdf : : PageLayout : : TwoColumnRight : pdf : : PageLayout : : TwoColumnLeft ) ;
}
void PDFViewerMainWindow : : on_actionFirstPageOnRightSide_triggered ( )
{
switch ( m_pdfWidget - > getDrawWidgetProxy ( ) - > getPageLayout ( ) )
{
case pdf : : PageLayout : : SinglePage :
case pdf : : PageLayout : : OneColumn :
break ;
case pdf : : PageLayout : : TwoColumnLeft :
case pdf : : PageLayout : : TwoColumnRight :
on_actionPageLayoutTwoColumns_triggered ( ) ;
break ;
case pdf : : PageLayout : : TwoPagesLeft :
case pdf : : PageLayout : : TwoPagesRight :
on_actionPageLayoutTwoPages_triggered ( ) ;
break ;
default :
Q_ASSERT ( false ) ;
}
}
2019-12-01 13:02:25 +01:00
void PDFViewerMainWindow : : on_actionFitPage_triggered ( )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomFit ) ;
}
void PDFViewerMainWindow : : on_actionFitWidth_triggered ( )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomFitWidth ) ;
}
void PDFViewerMainWindow : : on_actionFitHeight_triggered ( )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : ZoomFitHeight ) ;
}
2019-02-24 19:42:00 +01:00
void PDFViewerMainWindow : : on_actionRendering_Errors_triggered ( )
{
pdf : : PDFRenderingErrorsWidget renderingErrorsDialog ( this , m_pdfWidget ) ;
renderingErrorsDialog . exec ( ) ;
}
2020-02-22 18:27:33 +01:00
void PDFViewerMainWindow : : updateMagnifierToolSettings ( )
{
pdf : : PDFMagnifierTool * magnifierTool = m_toolManager - > getMagnifierTool ( ) ;
2020-02-23 18:59:54 +01:00
magnifierTool - > setMagnifierSize ( pdf : : PDFWidgetUtils : : scaleDPI_x ( this , m_settings - > getSettings ( ) . m_magnifierSize ) ) ;
2020-02-22 18:27:33 +01:00
magnifierTool - > setMagnifierZoom ( m_settings - > getSettings ( ) . m_magnifierZoom ) ;
}
2020-05-03 18:52:22 +02:00
void PDFViewerMainWindow : : updateUndoRedoSettings ( )
{
const PDFViewerSettings : : Settings & settings = m_settings - > getSettings ( ) ;
m_undoRedoManager - > setMaximumSteps ( settings . m_maximumUndoSteps , settings . m_maximumRedoSteps ) ;
}
void PDFViewerMainWindow : : updateUndoRedoActions ( )
{
2020-05-30 18:31:50 +02:00
const bool isBusy = ( m_futureWatcher & & m_futureWatcher - > isRunning ( ) ) | | m_isBusy ;
2020-05-03 18:52:22 +02:00
const bool canUndo = ! isBusy & & m_undoRedoManager - > canUndo ( ) ;
const bool canRedo = ! isBusy & & m_undoRedoManager - > canRedo ( ) ;
ui - > actionUndo - > setEnabled ( canUndo ) ;
ui - > actionRedo - > setEnabled ( canRedo ) ;
}
2019-09-06 19:07:52 +02:00
void PDFViewerMainWindow : : on_actionOptions_triggered ( )
2019-07-06 15:55:37 +02:00
{
2020-02-01 11:56:40 +01:00
PDFViewerSettingsDialog : : OtherSettings otherSettings ;
otherSettings . maximumRecentFileCount = m_recentFileManager - > getRecentFilesLimit ( ) ;
2020-11-17 18:28:34 +01:00
PDFViewerSettingsDialog dialog ( m_settings - > getSettings ( ) , m_settings - > getColorManagementSystemSettings ( ) ,
otherSettings , m_certificateStore , getActions ( ) , m_CMSManager ,
m_enabledPlugins , m_plugins , this ) ;
2019-09-07 19:01:54 +02:00
if ( dialog . exec ( ) = = QDialog : : Accepted )
{
2020-11-17 18:28:34 +01:00
const bool pluginsChanged = m_enabledPlugins ! = dialog . getEnabledPlugins ( ) ;
2019-09-07 19:01:54 +02:00
m_settings - > setSettings ( dialog . getSettings ( ) ) ;
2019-12-24 17:29:40 +01:00
m_settings - > setColorManagementSystemSettings ( dialog . getCMSSettings ( ) ) ;
2019-12-25 14:34:37 +01:00
m_CMSManager - > setSettings ( m_settings - > getColorManagementSystemSettings ( ) ) ;
2020-02-01 11:56:40 +01:00
m_recentFileManager - > setRecentFilesLimit ( dialog . getOtherSettings ( ) . maximumRecentFileCount ) ;
2020-02-18 20:21:18 +01:00
m_textToSpeech - > setSettings ( m_settings ) ;
2020-04-22 20:00:44 +02:00
m_formManager - > setAppearanceFlags ( m_settings - > getSettings ( ) . m_formAppearanceFlags ) ;
2020-06-28 18:55:09 +02:00
m_certificateStore = dialog . getCertificateStore ( ) ;
2020-11-17 18:28:34 +01:00
m_enabledPlugins = dialog . getEnabledPlugins ( ) ;
2020-02-22 18:27:33 +01:00
updateMagnifierToolSettings ( ) ;
2020-05-03 18:52:22 +02:00
updateUndoRedoSettings ( ) ;
2020-11-17 18:28:34 +01:00
if ( pluginsChanged )
{
QMessageBox : : information ( this , tr ( " Plugins " ) , tr ( " Plugin on/off state has been changed. Please restart application to apply settings. " ) ) ;
}
2019-09-07 19:01:54 +02:00
}
2019-07-06 15:55:37 +02:00
}
2019-12-20 18:56:03 +01:00
void PDFViewerMainWindow : : on_actionProperties_triggered ( )
{
Q_ASSERT ( m_pdfDocument ) ;
PDFDocumentPropertiesDialog documentPropertiesDialog ( m_pdfDocument . data ( ) , & m_fileInfo , this ) ;
documentPropertiesDialog . exec ( ) ;
}
2019-11-10 14:17:54 +01:00
void PDFViewerMainWindow : : on_actionAbout_triggered ( )
{
PDFAboutDialog dialog ( this ) ;
dialog . exec ( ) ;
}
2019-12-22 18:03:19 +01:00
void PDFViewerMainWindow : : on_actionSend_by_E_Mail_triggered ( )
{
Q_ASSERT ( m_pdfDocument ) ;
QString subject = m_pdfDocument - > getInfo ( ) - > title ;
if ( subject . isEmpty ( ) )
{
subject = m_fileInfo . fileName ;
}
if ( ! PDFSendMail : : sendMail ( this , subject , m_fileInfo . originalFileName ) )
{
QMessageBox : : critical ( this , tr ( " Error " ) , tr ( " Error while starting email client occured! " ) ) ;
}
}
2020-02-01 17:28:02 +01:00
void PDFViewerMainWindow : : on_actionRotateRight_triggered ( )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : RotateRight ) ;
}
void PDFViewerMainWindow : : on_actionRotateLeft_triggered ( )
{
m_pdfWidget - > getDrawWidgetProxy ( ) - > performOperation ( pdf : : PDFDrawWidgetProxy : : RotateLeft ) ;
}
2020-02-03 19:45:17 +01:00
void PDFViewerMainWindow : : on_actionPrint_triggered ( )
{
// Are we allowed to print in high resolution? If yes, then print in high resolution,
// otherwise print in low resolution. If this action is triggered, then print operation
// should be allowed (at least print in low resolution).
const pdf : : PDFObjectStorage & storage = m_pdfDocument - > getStorage ( ) ;
const pdf : : PDFSecurityHandler * securityHandler = storage . getSecurityHandler ( ) ;
QPrinter : : PrinterMode printerMode = QPrinter : : HighResolution ;
if ( ! securityHandler - > isAllowed ( pdf : : PDFSecurityHandler : : Permission : : PrintHighResolution ) )
{
printerMode = QPrinter : : ScreenResolution ;
}
// Run print dialog
QPrinter printer ( printerMode ) ;
QPrintDialog printDialog ( & printer , this ) ;
printDialog . setOptions ( QPrintDialog : : PrintPageRange | QPrintDialog : : PrintShowPageSize | QPrintDialog : : PrintCollateCopies | QPrintDialog : : PrintSelection ) ;
printDialog . setOption ( QPrintDialog : : PrintCurrentPage , m_pdfWidget - > getDrawWidget ( ) - > getCurrentPages ( ) . size ( ) = = 1 ) ;
printDialog . setMinMax ( 1 , int ( m_pdfDocument - > getCatalog ( ) - > getPageCount ( ) ) ) ;
if ( printDialog . exec ( ) = = QPrintDialog : : Accepted )
{
std : : vector < pdf : : PDFInteger > pageIndices ;
switch ( printDialog . printRange ( ) )
{
case QAbstractPrintDialog : : AllPages :
{
pageIndices . resize ( m_pdfDocument - > getCatalog ( ) - > getPageCount ( ) , 0 ) ;
std : : iota ( pageIndices . begin ( ) , pageIndices . end ( ) , 0 ) ;
break ;
}
case QAbstractPrintDialog : : Selection :
case QAbstractPrintDialog : : CurrentPage :
{
pageIndices = m_pdfWidget - > getDrawWidget ( ) - > getCurrentPages ( ) ;
break ;
}
case QAbstractPrintDialog : : PageRange :
{
const pdf : : PDFInteger fromPage = printDialog . fromPage ( ) ;
const pdf : : PDFInteger toPage = printDialog . toPage ( ) ;
const pdf : : PDFInteger pageCount = toPage - fromPage + 1 ;
if ( pageCount > 0 )
{
pageIndices . resize ( pageCount , 0 ) ;
std : : iota ( pageIndices . begin ( ) , pageIndices . end ( ) , fromPage - 1 ) ;
}
break ;
}
default :
Q_ASSERT ( false ) ;
break ;
}
if ( pageIndices . empty ( ) )
{
// Nothing to be printed
return ;
}
pdf : : ProgressStartupInfo info ;
info . showDialog = true ;
info . text = tr ( " Printing document " ) ;
m_progress - > start ( pageIndices . size ( ) , qMove ( info ) ) ;
printer . setFullPage ( true ) ;
QPainter painter ( & printer ) ;
const pdf : : PDFCatalog * catalog = m_pdfDocument - > getCatalog ( ) ;
pdf : : PDFDrawWidgetProxy * proxy = m_pdfWidget - > getDrawWidgetProxy ( ) ;
pdf : : PDFOptionalContentActivity optionalContentActivity ( m_pdfDocument . data ( ) , pdf : : OCUsage : : Print , nullptr ) ;
pdf : : PDFCMSPointer cms = proxy - > getCMSManager ( ) - > getCurrentCMS ( ) ;
pdf : : PDFRenderer renderer ( m_pdfDocument . get ( ) , proxy - > getFontCache ( ) , cms . data ( ) , & optionalContentActivity , proxy - > getFeatures ( ) , proxy - > getMeshQualitySettings ( ) ) ;
const pdf : : PDFInteger lastPage = pageIndices . back ( ) ;
for ( const pdf : : PDFInteger pageIndex : pageIndices )
{
const pdf : : PDFPage * page = catalog - > getPage ( pageIndex ) ;
Q_ASSERT ( page ) ;
QRectF mediaBox = page - > getRotatedMediaBox ( ) ;
QRectF paperRect = printer . paperRect ( ) ;
QSizeF scaledSize = mediaBox . size ( ) . scaled ( paperRect . size ( ) , Qt : : KeepAspectRatio ) ;
mediaBox . setSize ( scaledSize ) ;
mediaBox . moveCenter ( paperRect . center ( ) ) ;
renderer . render ( & painter , mediaBox , pageIndex ) ;
m_progress - > step ( ) ;
if ( pageIndex ! = lastPage )
{
if ( ! printer . newPage ( ) )
{
break ;
}
}
}
painter . end ( ) ;
m_progress - > finish ( ) ;
}
}
2020-02-08 18:09:46 +01:00
void PDFViewerMainWindow : : on_actionRender_to_Images_triggered ( )
{
2020-02-09 16:06:29 +01:00
PDFRenderToImagesDialog dialog ( m_pdfDocument . data ( ) , m_pdfWidget - > getDrawWidgetProxy ( ) , m_progress , this ) ;
dialog . exec ( ) ;
2020-02-08 18:09:46 +01:00
}
2020-05-31 18:31:59 +02:00
void PDFViewerMainWindow : : on_actionOptimize_triggered ( )
{
PDFOptimizeDocumentDialog dialog ( m_pdfDocument . data ( ) , this ) ;
if ( dialog . exec ( ) = = QDialog : : Accepted )
{
2020-06-06 16:30:06 +02:00
pdf : : PDFDocumentPointer pointer ( new pdf : : PDFDocument ( dialog . takeOptimizedDocument ( ) ) ) ;
pdf : : PDFModifiedDocument document ( qMove ( pointer ) , m_optionalContentActivity , pdf : : PDFModifiedDocument : : Reset ) ;
onDocumentModified ( qMove ( document ) ) ;
2020-05-31 18:31:59 +02:00
}
}
2020-06-07 17:46:49 +02:00
void PDFViewerMainWindow : : on_actionSave_As_triggered ( )
{
QFileInfo fileInfo ( m_fileInfo . originalFileName ) ;
QString saveFileName = QFileDialog : : getSaveFileName ( this , tr ( " Save As " ) , fileInfo . dir ( ) . absoluteFilePath ( m_fileInfo . originalFileName ) , tr ( " Portable Document (*.pdf);;All files (*.*) " ) ) ;
if ( ! saveFileName . isEmpty ( ) )
{
saveDocument ( saveFileName ) ;
}
}
void PDFViewerMainWindow : : on_actionSave_triggered ( )
{
saveDocument ( m_fileInfo . originalFileName ) ;
}
2020-05-31 18:31:59 +02:00
2020-06-07 17:46:49 +02:00
void PDFViewerMainWindow : : saveDocument ( const QString & fileName )
{
pdf : : PDFDocumentWriter writer ( nullptr ) ;
pdf : : PDFOperationResult result = writer . write ( fileName , m_pdfDocument . data ( ) , true ) ;
if ( result )
{
updateFileInfo ( fileName ) ;
updateTitle ( ) ;
m_recentFileManager - > addRecentFile ( fileName ) ;
}
else
{
QMessageBox : : critical ( this , tr ( " Error " ) , result . getErrorMessage ( ) ) ;
}
}
2020-11-07 12:03:43 +01:00
void PDFViewerMainWindow : : dragEnterEvent ( QDragEnterEvent * event )
{
if ( event - > mimeData ( ) - > hasUrls ( ) )
{
event - > setDropAction ( Qt : : LinkAction ) ;
event - > accept ( ) ;
}
}
void PDFViewerMainWindow : : dragMoveEvent ( QDragMoveEvent * event )
{
if ( event - > mimeData ( ) - > hasUrls ( ) )
{
event - > setDropAction ( Qt : : LinkAction ) ;
event - > accept ( ) ;
}
}
void PDFViewerMainWindow : : dropEvent ( QDropEvent * event )
{
if ( event - > mimeData ( ) - > hasUrls ( ) )
{
QList < QUrl > urls = event - > mimeData ( ) - > urls ( ) ;
if ( urls . size ( ) = = 1 )
{
openDocument ( urls . front ( ) . toLocalFile ( ) ) ;
event - > acceptProposedAction ( ) ;
}
}
}
2020-06-07 17:46:49 +02:00
} // namespace pdfviewer