diff --git a/PdfForQtLib/sources/pdfcatalog.cpp b/PdfForQtLib/sources/pdfcatalog.cpp index 51d0704..eb0de9c 100644 --- a/PdfForQtLib/sources/pdfcatalog.cpp +++ b/PdfForQtLib/sources/pdfcatalog.cpp @@ -67,6 +67,48 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume catalogObject.m_outlineRoot = PDFOutlineItem::parse(document, catalogDictionary->get("Outlines")); } + if (catalogDictionary->hasKey("OpenAction")) + { + PDFObject openAction = document->getObject(catalogDictionary->get("OpenAction")); + if (openAction.isArray()) + { + catalogObject.m_openAction.reset(new PDFActionGoTo(PDFDestination::parse(document, openAction))); + } + if (openAction.isDictionary()) + { + catalogObject.m_openAction = PDFAction::parse(document, openAction); + } + } + + PDFDocumentDataLoaderDecorator loader(document); + if (catalogDictionary->hasKey("PageLayout")) + { + constexpr const std::array, 6> pageLayouts = { + std::pair{ "SinglePage", PageLayout::SinglePage }, + std::pair{ "OneColumn", PageLayout::OneColumn }, + std::pair{ "TwoColumnLeft", PageLayout::TwoColumnLeft }, + std::pair{ "TwoColumnRight", PageLayout::TwoColumnRight }, + std::pair{ "TwoPageLeft", PageLayout::TwoPagesLeft }, + std::pair{ "TwoPageRight", PageLayout::TwoPagesRight } + }; + + catalogObject.m_pageLayout = loader.readEnumByName(catalogDictionary->get("PageLayout"), pageLayouts.begin(), pageLayouts.end(), PageLayout::SinglePage); + } + + if (catalogDictionary->hasKey("PageMode")) + { + constexpr const std::array, 6> pageModes = { + std::pair{ "UseNone", PageMode::UseNone }, + std::pair{ "UseOutlines", PageMode::UseOutlines }, + std::pair{ "UseThumbs", PageMode::UseThumbnails }, + std::pair{ "FullScreen", PageMode::Fullscreen }, + std::pair{ "UseOC", PageMode::UseOptionalContent }, + std::pair{ "UseAttachments", PageMode::UseAttachments } + }; + + catalogObject.m_pageMode = loader.readEnumByName(catalogDictionary->get("PageMode"), pageModes.begin(), pageModes.end(), PageMode::UseNone); + } + return catalogObject; } diff --git a/PdfForQtLib/sources/pdfcatalog.h b/PdfForQtLib/sources/pdfcatalog.h index 099d86c..c7c937f 100644 --- a/PdfForQtLib/sources/pdfcatalog.h +++ b/PdfForQtLib/sources/pdfcatalog.h @@ -22,6 +22,7 @@ #include "pdfpage.h" #include "pdfoptionalcontent.h" #include "pdfoutline.h" +#include "pdfaction.h" #include @@ -219,6 +220,12 @@ public: /// Returns root pointer for outline items QSharedPointer getOutlineRootPtr() const { return m_outlineRoot; } + /// Returns action, which should be performed + const PDFAction* getOpenAction() const { return m_openAction.data(); } + + PageLayout getPageLayout() const { return m_pageLayout; } + PageMode getPageMode() const { return m_pageMode; } + /// Parses catalog from catalog dictionary. If object cannot be parsed, or error occurs, /// then exception is thrown. static PDFCatalog parse(const PDFObject& catalog, const PDFDocument* document); @@ -229,6 +236,9 @@ private: std::vector m_pageLabels; PDFOptionalContentProperties m_optionalContentProperties; QSharedPointer m_outlineRoot; + PDFActionPtr m_openAction; + PageLayout m_pageLayout = PageLayout::SinglePage; + PageMode m_pageMode = PageMode::UseNone; }; } // namespace pdf diff --git a/PdfForQtLib/sources/pdfitemmodels.cpp b/PdfForQtLib/sources/pdfitemmodels.cpp index f4c3450..e6c5bda 100644 --- a/PdfForQtLib/sources/pdfitemmodels.cpp +++ b/PdfForQtLib/sources/pdfitemmodels.cpp @@ -364,16 +364,26 @@ QVariant PDFOutlineTreeItemModel::data(const QModelIndex& index, int role) const case Qt::FontRole: { QFont font = QApplication::font(); + font.setPointSize(10); font.setBold(outlineItem->isFontBold()); font.setItalic(outlineItem->isFontItalics()); return font; } + case Qt::DecorationRole: + { + if (!m_icon.isNull()) + { + return m_icon; + } + break; + } + default: break; } - return QString(); + return QVariant(); } void PDFOutlineTreeItemModel::update() @@ -415,4 +425,16 @@ Qt::ItemFlags PDFOutlineTreeItemModel::flags(const QModelIndex& index) const return flags; } +const PDFAction* PDFOutlineTreeItemModel::getAction(const QModelIndex& index) const +{ + if (index.isValid()) + { + const PDFOutlineTreeItem* item = static_cast(index.internalPointer()); + const PDFOutlineItem* outlineItem = item->getOutlineItem(); + return outlineItem->getAction(); + } + + return nullptr; +} + } // namespace pdf diff --git a/PdfForQtLib/sources/pdfitemmodels.h b/PdfForQtLib/sources/pdfitemmodels.h index 3f55b91..891f11d 100644 --- a/PdfForQtLib/sources/pdfitemmodels.h +++ b/PdfForQtLib/sources/pdfitemmodels.h @@ -21,10 +21,12 @@ #include "pdfglobal.h" #include "pdfobject.h" +#include #include namespace pdf { +class PDFAction; class PDFDocument; class PDFOutlineItem; class PDFOptionalContentActivity; @@ -107,6 +109,7 @@ private: class PDFFORQTLIBSHARED_EXPORT PDFOptionalContentTreeItemModel : public PDFTreeItemModel { + Q_OBJECT public: inline explicit PDFOptionalContentTreeItemModel(QObject* parent) : PDFTreeItemModel(parent), @@ -140,13 +143,27 @@ private: class PDFFORQTLIBSHARED_EXPORT PDFOutlineTreeItemModel : public PDFTreeItemModel { + Q_OBJECT public: - using PDFTreeItemModel::PDFTreeItemModel; + PDFOutlineTreeItemModel(QIcon icon, QObject* parent) : + PDFTreeItemModel(parent), + m_icon(qMove(icon)) + { + + } virtual int columnCount(const QModelIndex& parent) const override; virtual QVariant data(const QModelIndex& index, int role) const override; virtual void update() override; virtual Qt::ItemFlags flags(const QModelIndex& index) const override; + + /// Returns action assigned to the index. If index is invalid, or + /// points to the invalid item, nullptr is returned. + /// \param index Index of the outline item + const PDFAction* getAction(const QModelIndex& index) const; + +private: + QIcon m_icon; }; } // namespace pdf diff --git a/PdfForQtViewer/pdfforqtviewer.qrc b/PdfForQtViewer/pdfforqtviewer.qrc index 5a857df..0708dc6 100644 --- a/PdfForQtViewer/pdfforqtviewer.qrc +++ b/PdfForQtViewer/pdfforqtviewer.qrc @@ -16,5 +16,6 @@ resources/settings.svg resources/zoom-in.svg resources/zoom-out.svg + resources/bookmark.svg diff --git a/PdfForQtViewer/pdfsidebarwidget.cpp b/PdfForQtViewer/pdfsidebarwidget.cpp index a6d5bc2..e632918 100644 --- a/PdfForQtViewer/pdfsidebarwidget.cpp +++ b/PdfForQtViewer/pdfsidebarwidget.cpp @@ -35,9 +35,11 @@ PDFSidebarWidget::PDFSidebarWidget(QWidget* parent) : ui->setupUi(this); // Outline - m_outlineTreeModel = new pdf::PDFOutlineTreeItemModel(this); + QIcon bookmarkIcon(":/resources/bookmark.svg"); + m_outlineTreeModel = new pdf::PDFOutlineTreeItemModel(qMove(bookmarkIcon), this); ui->bookmarksTreeView->setModel(m_outlineTreeModel); ui->bookmarksTreeView->header()->hide(); + connect(ui->bookmarksTreeView, &QTreeView::clicked, this, &PDFSidebarWidget::onOutlineItemClicked); // Optional content ui->optionalContentTreeView->header()->hide(); @@ -75,18 +77,18 @@ void PDFSidebarWidget::setDocument(const pdf::PDFDocument* document, pdf::PDFOpt Page preferred = Invalid; if (m_document) { - const pdf::PDFViewerPreferences::NonFullScreenPageMode pageMode = m_document->getCatalog()->getViewerPreferences()->getNonFullScreenPageMode(); + const pdf::PageMode pageMode = m_document->getCatalog()->getPageMode(); switch (pageMode) { - case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseOutline: + case pdf::PageMode::UseOutlines: preferred = Bookmarks; break; - case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseThumbnails: + case pdf::PageMode::UseThumbnails: preferred = Thumbnails; break; - case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseOptionalContent: + case pdf::PageMode::UseOptionalContent: preferred = OptionalContent; break; @@ -202,4 +204,12 @@ void PDFSidebarWidget::updateButtons() } } +void PDFSidebarWidget::onOutlineItemClicked(const QModelIndex& index) +{ + if (const pdf::PDFAction* action = m_outlineTreeModel->getAction(index)) + { + emit actionTriggered(action); + } +} + } // namespace pdfviewer diff --git a/PdfForQtViewer/pdfsidebarwidget.h b/PdfForQtViewer/pdfsidebarwidget.h index b8b710f..bcb9dca 100644 --- a/PdfForQtViewer/pdfsidebarwidget.h +++ b/PdfForQtViewer/pdfsidebarwidget.h @@ -31,6 +31,7 @@ class PDFSidebarWidget; namespace pdf { +class PDFAction; class PDFDocument; class PDFOutlineTreeItemModel; class PDFOptionalContentActivity; @@ -72,10 +73,15 @@ public: /// Returns list of valid pages (nonempty pages) std::vector getValidPages() const; +signals: + void actionTriggered(const pdf::PDFAction* action); + private: void updateGUI(Page preferredPage); void updateButtons(); + void onOutlineItemClicked(const QModelIndex& index); + struct PageInfo { QPushButton* button = nullptr; diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp index e0a8e98..3d8bdc2 100644 --- a/PdfForQtViewer/pdfviewermainwindow.cpp +++ b/PdfForQtViewer/pdfviewermainwindow.cpp @@ -149,6 +149,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) : m_sidebarDockWidget->setWidget(m_sidebarWidget); addDockWidget(Qt::LeftDockWidgetArea, m_sidebarDockWidget); m_sidebarDockWidget->hide(); + connect(m_sidebarWidget, &PDFSidebarWidget::actionTriggered, this, &PDFViewerMainWindow::onActionTriggered); ui->actionRenderOptionAntialiasing->setData(pdf::PDFRenderer::Antialiasing); ui->actionRenderOptionTextAntialiasing->setData(pdf::PDFRenderer::TextAntialiasing); @@ -248,6 +249,11 @@ void PDFViewerMainWindow::onPageZoomSpinboxEditingFinished() m_pdfWidget->getDrawWidgetProxy()->zoom(m_pageZoomSpinBox->value() / 100.0); } +void PDFViewerMainWindow::onActionTriggered(const pdf::PDFAction* action) +{ + +} + void PDFViewerMainWindow::onProgressStarted() { m_progressTaskbarIndicator->setRange(0, 100); @@ -486,6 +492,18 @@ void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document) updateTitle(); updateUI(true); + + if (m_pdfDocument) + { + const pdf::PDFCatalog* catalog = m_pdfDocument->getCatalog(); + setPageLayout(catalog->getPageLayout()); + updatePageLayoutActions(); + + if (const pdf::PDFAction* action = catalog->getOpenAction()) + { + onActionTriggered(action); + } + } } void PDFViewerMainWindow::closeDocument() diff --git a/PdfForQtViewer/pdfviewermainwindow.h b/PdfForQtViewer/pdfviewermainwindow.h index bf9b528..be3fb52 100644 --- a/PdfForQtViewer/pdfviewermainwindow.h +++ b/PdfForQtViewer/pdfviewermainwindow.h @@ -41,6 +41,7 @@ class PDFViewerMainWindow; namespace pdf { +class PDFAction; class PDFWidget; class PDFDocument; class PDFOptionalContentTreeItemModel; @@ -82,6 +83,7 @@ private: void onPageLayoutChanged(); void onPageNumberSpinboxEditingFinished(); void onPageZoomSpinboxEditingFinished(); + void onActionTriggered(const pdf::PDFAction* action); void onProgressStarted(); void onProgressStep(int percentage); diff --git a/PdfForQtViewer/resources/bookmark.svg b/PdfForQtViewer/resources/bookmark.svg new file mode 100644 index 0000000..83cd7b9 --- /dev/null +++ b/PdfForQtViewer/resources/bookmark.svg @@ -0,0 +1,84 @@ + + + + + + + + + + image/svg+xml + + + + + Jakub Melka + + + + + + + + + + + + + + + + + +