From c1c59139b540e2098240839e4d168638f8c72097 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Wed, 13 Dec 2023 20:14:33 +0100 Subject: [PATCH 1/5] Issue #54: Rename bookmarks --- Pdf4QtDocPageOrganizer/CMakeLists.txt | 6 +- Pdf4QtDocPageOrganizer/mainwindow.cpp | 20 +++--- Pdf4QtDocPageOrganizer/mainwindow.h | 2 +- Pdf4QtDocPageOrganizer/mainwindow.ui | 8 +-- Pdf4QtDocPageOrganizer/pageitemmodel.cpp | 2 +- Pdf4QtDocPageOrganizer/pageitemmodel.h | 2 +- Pdf4QtDocPageOrganizer/resources.qrc | 2 +- ...roup-bookmarks.svg => regroup-outline.svg} | 0 ...g.cpp => selectoutlinetoregroupdialog.cpp} | 70 +++++++++---------- ...ialog.h => selectoutlinetoregroupdialog.h} | 16 ++--- ...log.ui => selectoutlinetoregroupdialog.ui} | 12 ++-- .../sources/pdfdocumentsanitizer.cpp | 6 +- Pdf4QtLibCore/sources/pdfdocumentsanitizer.h | 4 +- Pdf4QtViewer/pdf4qtviewer.qrc | 2 +- Pdf4QtViewer/pdfsanitizedocumentdialog.cpp | 2 +- Pdf4QtViewer/pdfsidebarwidget.cpp | 44 ++++++------ Pdf4QtViewer/pdfsidebarwidget.h | 4 +- Pdf4QtViewer/pdfsidebarwidget.ui | 12 ++-- .../resources/{bookmark.svg => outline.svg} | 0 19 files changed, 107 insertions(+), 107 deletions(-) rename Pdf4QtDocPageOrganizer/resources/{regroup-bookmarks.svg => regroup-outline.svg} (100%) rename Pdf4QtDocPageOrganizer/{selectbookmarkstoregroupdialog.cpp => selectoutlinetoregroupdialog.cpp} (52%) rename Pdf4QtDocPageOrganizer/{selectbookmarkstoregroupdialog.h => selectoutlinetoregroupdialog.h} (77%) rename Pdf4QtDocPageOrganizer/{selectbookmarkstoregroupdialog.ui => selectoutlinetoregroupdialog.ui} (80%) rename Pdf4QtViewer/resources/{bookmark.svg => outline.svg} (100%) diff --git a/Pdf4QtDocPageOrganizer/CMakeLists.txt b/Pdf4QtDocPageOrganizer/CMakeLists.txt index e803d2e..6372289 100644 --- a/Pdf4QtDocPageOrganizer/CMakeLists.txt +++ b/Pdf4QtDocPageOrganizer/CMakeLists.txt @@ -27,12 +27,12 @@ add_executable(Pdf4QtDocPageOrganizer pageitemdelegate.h pageitemmodel.cpp pageitemmodel.h - selectbookmarkstoregroupdialog.cpp - selectbookmarkstoregroupdialog.h + selectoutlinetoregroupdialog.cpp + selectoutlinetoregroupdialog.h aboutdialog.ui assembleoutputsettingsdialog.ui mainwindow.ui - selectbookmarkstoregroupdialog.ui + selectoutlinetoregroupdialog.ui resources.qrc icon.rc ) diff --git a/Pdf4QtDocPageOrganizer/mainwindow.cpp b/Pdf4QtDocPageOrganizer/mainwindow.cpp index 53a4fd4..6bddb87 100644 --- a/Pdf4QtDocPageOrganizer/mainwindow.cpp +++ b/Pdf4QtDocPageOrganizer/mainwindow.cpp @@ -20,7 +20,7 @@ #include "aboutdialog.h" #include "assembleoutputsettingsdialog.h" -#include "selectbookmarkstoregroupdialog.h" +#include "selectoutlinetoregroupdialog.h" #include "pdfaction.h" #include "pdfwidgetutils.h" @@ -94,7 +94,7 @@ MainWindow::MainWindow(QWidget* parent) : ui->actionInvert_Selection->setData(int(Operation::InvertSelection)); ui->actionRegroup_Even_Odd->setData(int(Operation::RegroupEvenOdd)); ui->actionRegroup_by_Page_Pairs->setData(int(Operation::RegroupPaired)); - ui->actionRegroup_by_Bookmarks->setData(int(Operation::RegroupBookmarks)); + ui->actionRegroup_by_Outline->setData(int(Operation::RegroupOutline)); ui->actionRegroup_by_Alternating_Pages->setData(int(Operation::RegroupAlternatingPages)); ui->actionRegroup_by_Alternating_Pages_Reversed_Order->setData(int(Operation::RegroupAlternatingPagesReversed)); ui->actionPrepare_Icon_Theme->setData(int(Operation::PrepareIconTheme)); @@ -132,7 +132,7 @@ MainWindow::MainWindow(QWidget* parent) : m_iconTheme.registerAction(ui->actionClear, ":/pdfdocpage/resources/clear.svg"); m_iconTheme.registerAction(ui->actionRegroup_Even_Odd, ":/pdfdocpage/resources/regroup-even-odd.svg"); m_iconTheme.registerAction(ui->actionRegroup_by_Page_Pairs, ":/pdfdocpage/resources/regroup-pairs.svg"); - m_iconTheme.registerAction(ui->actionRegroup_by_Bookmarks, ":/pdfdocpage/resources/regroup-bookmarks.svg"); + m_iconTheme.registerAction(ui->actionRegroup_by_Outline, ":/pdfdocpage/resources/regroup-outline.svg"); m_iconTheme.registerAction(ui->actionRegroup_by_Alternating_Pages, ":/pdfdocpage/resources/regroup-alternating.svg"); m_iconTheme.registerAction(ui->actionRegroup_by_Alternating_Pages_Reversed_Order, ":/pdfdocpage/resources/regroup-alternating-reversed.svg"); m_iconTheme.registerAction(ui->actionInvert_Selection, ":/pdfdocpage/resources/invert-selection.svg"); @@ -162,7 +162,7 @@ MainWindow::MainWindow(QWidget* parent) : selectToolbar->addActions({ ui->actionSelect_None, ui->actionSelect_All, ui->actionSelect_Even, ui->actionSelect_Odd, ui->actionSelect_Portrait, ui->actionSelect_Landscape, ui->actionInvert_Selection }); QToolBar* regroupToolbar = addToolBar(tr("Regroup")); regroupToolbar->setObjectName("regroup_toolbar"); - regroupToolbar->addActions({ ui->actionRegroup_Even_Odd, ui->actionRegroup_by_Page_Pairs, ui->actionRegroup_by_Bookmarks, ui->actionRegroup_by_Alternating_Pages, ui->actionRegroup_by_Alternating_Pages_Reversed_Order }); + regroupToolbar->addActions({ ui->actionRegroup_Even_Odd, ui->actionRegroup_by_Page_Pairs, ui->actionRegroup_by_Outline, ui->actionRegroup_by_Alternating_Pages, ui->actionRegroup_by_Alternating_Pages_Reversed_Order }); QToolBar* zoomToolbar = addToolBar(tr("Zoom")); zoomToolbar->setObjectName("zoom_toolbar"); zoomToolbar->addActions({ ui->actionZoom_In, ui->actionZoom_Out }); @@ -283,7 +283,7 @@ void MainWindow::onWorkspaceCustomContextMenuRequested(const QPoint& point) regroupMenu->addAction(ui->actionRegroup_by_Alternating_Pages); regroupMenu->addAction(ui->actionRegroup_by_Alternating_Pages_Reversed_Order); regroupMenu->addAction(ui->actionRegroup_by_Page_Pairs); - regroupMenu->addAction(ui->actionRegroup_by_Bookmarks); + regroupMenu->addAction(ui->actionRegroup_by_Outline); contextMenu->addSeparator(); contextMenu->addAction(ui->actionGroup); contextMenu->addAction(ui->actionUngroup); @@ -482,7 +482,7 @@ bool MainWindow::canPerformOperation(Operation operation) const case Operation::RegroupPaired: return !isModelEmpty && !selection.isEmpty(); - case Operation::RegroupBookmarks: + case Operation::RegroupOutline: { PageItemModel::SelectionInfo info = m_model->getSelectionInfo(selection); return info.isSingleDocument(); @@ -916,7 +916,7 @@ void MainWindow::performOperation(Operation operation) break; } - case Operation::RegroupBookmarks: + case Operation::RegroupOutline: { QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes(); @@ -929,9 +929,9 @@ void MainWindow::performOperation(Operation operation) if (it != documents.end()) { const pdf::PDFDocument* document = &it->second.document; - SelectBookmarksToRegroupDialog dialog(document, this); + SelectOutlineToRegroupDialog dialog(document, this); - if (dialog.exec() == SelectBookmarksToRegroupDialog::Accepted) + if (dialog.exec() == SelectOutlineToRegroupDialog::Accepted) { std::vector breakPageIndices; std::vector outlineItems = dialog.getSelectedOutlineItems(); @@ -972,7 +972,7 @@ void MainWindow::performOperation(Operation operation) std::sort(breakPageIndices.begin(), breakPageIndices.end()); breakPageIndices.erase(std::unique(breakPageIndices.begin(), breakPageIndices.end()), breakPageIndices.end()); - m_model->regroupBookmarks(indexes, breakPageIndices); + m_model->regroupOutline(indexes, breakPageIndices); } } } diff --git a/Pdf4QtDocPageOrganizer/mainwindow.h b/Pdf4QtDocPageOrganizer/mainwindow.h index 4404421..6e04e92 100644 --- a/Pdf4QtDocPageOrganizer/mainwindow.h +++ b/Pdf4QtDocPageOrganizer/mainwindow.h @@ -91,7 +91,7 @@ public: RegroupEvenOdd, RegroupPaired, - RegroupBookmarks, + RegroupOutline, RegroupAlternatingPages, RegroupAlternatingPagesReversed, diff --git a/Pdf4QtDocPageOrganizer/mainwindow.ui b/Pdf4QtDocPageOrganizer/mainwindow.ui index 5461425..acabce7 100644 --- a/Pdf4QtDocPageOrganizer/mainwindow.ui +++ b/Pdf4QtDocPageOrganizer/mainwindow.ui @@ -138,7 +138,7 @@ - + @@ -533,13 +533,13 @@ Regroup by Page Pairs - + - :/pdfdocpage/resources/regroup-bookmarks.svg:/pdfdocpage/resources/regroup-bookmarks.svg + :/pdfdocpage/resources/regroup-outline.svg:/pdfdocpage/resources/regroup-outline.svg - Regroup by Bookmarks + Regroup by Outline diff --git a/Pdf4QtDocPageOrganizer/pageitemmodel.cpp b/Pdf4QtDocPageOrganizer/pageitemmodel.cpp index 3fab2a6..edec5cd 100644 --- a/Pdf4QtDocPageOrganizer/pageitemmodel.cpp +++ b/Pdf4QtDocPageOrganizer/pageitemmodel.cpp @@ -703,7 +703,7 @@ void PageItemModel::regroupPaired(const QModelIndexList& list) } } -void PageItemModel::regroupBookmarks(const QModelIndexList& list, const std::vector& indices) +void PageItemModel::regroupOutline(const QModelIndexList& list, const std::vector& indices) { if (list.empty()) { diff --git a/Pdf4QtDocPageOrganizer/pageitemmodel.h b/Pdf4QtDocPageOrganizer/pageitemmodel.h index 11833cc..07a07ec 100644 --- a/Pdf4QtDocPageOrganizer/pageitemmodel.h +++ b/Pdf4QtDocPageOrganizer/pageitemmodel.h @@ -191,7 +191,7 @@ public: void regroupEvenOdd(const QModelIndexList& list); void regroupPaired(const QModelIndexList& list); - void regroupBookmarks(const QModelIndexList& list, const std::vector& indices); + void regroupOutline(const QModelIndexList& list, const std::vector& indices); void regroupAlternatingPages(const QModelIndexList& list, bool reversed); bool canUndo() const { return !m_undoSteps.empty(); } diff --git a/Pdf4QtDocPageOrganizer/resources.qrc b/Pdf4QtDocPageOrganizer/resources.qrc index ca37f56..c3703c6 100644 --- a/Pdf4QtDocPageOrganizer/resources.qrc +++ b/Pdf4QtDocPageOrganizer/resources.qrc @@ -33,12 +33,12 @@ resources/invert-selection.svg resources/regroup-alternating.svg resources/regroup-alternating-reversed.svg - resources/regroup-bookmarks.svg resources/regroup-even-odd.svg resources/regroup-pairs.svg resources/undo.svg resources/redo.svg resources/bookmark.svg resources/wallet.svg + resources/regroup-outline.svg diff --git a/Pdf4QtDocPageOrganizer/resources/regroup-bookmarks.svg b/Pdf4QtDocPageOrganizer/resources/regroup-outline.svg similarity index 100% rename from Pdf4QtDocPageOrganizer/resources/regroup-bookmarks.svg rename to Pdf4QtDocPageOrganizer/resources/regroup-outline.svg diff --git a/Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.cpp b/Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.cpp similarity index 52% rename from Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.cpp rename to Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.cpp index 59a4ed9..0483b82 100644 --- a/Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.cpp +++ b/Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.cpp @@ -15,8 +15,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with PDF4QT. If not, see . -#include "selectbookmarkstoregroupdialog.h" -#include "ui_selectbookmarkstoregroupdialog.h" +#include "selectoutlinetoregroupdialog.h" +#include "ui_selectoutlinetoregroupdialog.h" #include "pdfitemmodels.h" #include "pdfwidgetutils.h" @@ -26,9 +26,9 @@ namespace pdfdocpage { -SelectBookmarksToRegroupDialog::SelectBookmarksToRegroupDialog(const pdf::PDFDocument* document, QWidget* parent) : +SelectOutlineToRegroupDialog::SelectOutlineToRegroupDialog(const pdf::PDFDocument* document, QWidget* parent) : QDialog(parent), - ui(new Ui::SelectBookmarksToRegroupDialog), + ui(new Ui::SelectOutlineToRegroupDialog), m_document(document), m_model(nullptr) { @@ -36,53 +36,53 @@ SelectBookmarksToRegroupDialog::SelectBookmarksToRegroupDialog(const pdf::PDFDoc QIcon bookmarkIcon(":/pdfdocpage/resources/bookmark.svg"); m_model = new pdf::PDFSelectableOutlineTreeItemModel(qMove(bookmarkIcon), this); - ui->bookmarksView->setModel(m_model); - ui->bookmarksView->header()->hide(); + ui->outlineView->setModel(m_model); + ui->outlineView->header()->hide(); m_model->setDocument(pdf::PDFModifiedDocument(const_cast(document), nullptr)); - ui->bookmarksView->expandToDepth(2); - ui->bookmarksView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->bookmarksView, &QTreeView::customContextMenuRequested, this, &SelectBookmarksToRegroupDialog::onViewContextMenuRequested); + ui->outlineView->expandToDepth(2); + ui->outlineView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->outlineView, &QTreeView::customContextMenuRequested, this, &SelectOutlineToRegroupDialog::onViewContextMenuRequested); QSize size = pdf::PDFWidgetUtils::scaleDPI(this, QSize(400, 600)); setMinimumSize(size); pdf::PDFWidgetUtils::style(this); } -SelectBookmarksToRegroupDialog::~SelectBookmarksToRegroupDialog() +SelectOutlineToRegroupDialog::~SelectOutlineToRegroupDialog() { delete ui; } -std::vector SelectBookmarksToRegroupDialog::getSelectedOutlineItems() const +std::vector SelectOutlineToRegroupDialog::getSelectedOutlineItems() const { return m_model->getSelectedItems(); } -void SelectBookmarksToRegroupDialog::onViewContextMenuRequested(const QPoint& pos) +void SelectOutlineToRegroupDialog::onViewContextMenuRequested(const QPoint& pos) { QMenu menu; - menu.addAction(tr("Select All"), this, &SelectBookmarksToRegroupDialog::selectAll); - menu.addAction(tr("Deselect All"), this, &SelectBookmarksToRegroupDialog::deselectAll); - menu.addAction(tr("Invert Selection"), this, &SelectBookmarksToRegroupDialog::invertSelection); + menu.addAction(tr("Select All"), this, &SelectOutlineToRegroupDialog::selectAll); + menu.addAction(tr("Deselect All"), this, &SelectOutlineToRegroupDialog::deselectAll); + menu.addAction(tr("Invert Selection"), this, &SelectOutlineToRegroupDialog::invertSelection); menu.addSeparator(); - menu.addAction(tr("Select Level 1"), this, &SelectBookmarksToRegroupDialog::selectLevel1); - menu.addAction(tr("Select Level 2"), this, &SelectBookmarksToRegroupDialog::selectLevel2); + menu.addAction(tr("Select Level 1"), this, &SelectOutlineToRegroupDialog::selectLevel1); + menu.addAction(tr("Select Level 2"), this, &SelectOutlineToRegroupDialog::selectLevel2); - QModelIndex index = ui->bookmarksView->indexAt(pos); + QModelIndex index = ui->outlineView->indexAt(pos); if (index.isValid()) { m_menuIndex = index; menu.addSeparator(); - menu.addAction(tr("Select subtree"), this, &SelectBookmarksToRegroupDialog::selectSubtree); - menu.addAction(tr("Deselect subtree"), this, &SelectBookmarksToRegroupDialog::deselectSubtree); + menu.addAction(tr("Select subtree"), this, &SelectOutlineToRegroupDialog::selectSubtree); + menu.addAction(tr("Deselect subtree"), this, &SelectOutlineToRegroupDialog::deselectSubtree); } - menu.exec(ui->bookmarksView->mapToGlobal(pos)); + menu.exec(ui->outlineView->mapToGlobal(pos)); } -void SelectBookmarksToRegroupDialog::manipulateTree(const QModelIndex& index, +void SelectOutlineToRegroupDialog::manipulateTree(const QModelIndex& index, const std::function& manipulator) { if (index.isValid()) @@ -98,7 +98,7 @@ void SelectBookmarksToRegroupDialog::manipulateTree(const QModelIndex& index, } } -std::function SelectBookmarksToRegroupDialog::createCheckByDepthManipulator(int targetDepth) const +std::function SelectOutlineToRegroupDialog::createCheckByDepthManipulator(int targetDepth) const { auto manipulator = [this, targetDepth](QModelIndex index) { @@ -119,42 +119,42 @@ std::function SelectBookmarksToRegroupDialog::createCheckByD return manipulator; } -void SelectBookmarksToRegroupDialog::selectAll() +void SelectOutlineToRegroupDialog::selectAll() { - manipulateTree(ui->bookmarksView->rootIndex(), [this](QModelIndex index) { m_model->setData(index, Qt::Checked, Qt::CheckStateRole); }); + manipulateTree(ui->outlineView->rootIndex(), [this](QModelIndex index) { m_model->setData(index, Qt::Checked, Qt::CheckStateRole); }); } -void SelectBookmarksToRegroupDialog::deselectAll() +void SelectOutlineToRegroupDialog::deselectAll() { - manipulateTree(ui->bookmarksView->rootIndex(), [this](QModelIndex index) { m_model->setData(index, Qt::Unchecked, Qt::CheckStateRole); }); + manipulateTree(ui->outlineView->rootIndex(), [this](QModelIndex index) { m_model->setData(index, Qt::Unchecked, Qt::CheckStateRole); }); } -void SelectBookmarksToRegroupDialog::invertSelection() +void SelectOutlineToRegroupDialog::invertSelection() { auto manipulator = [this](QModelIndex index) { const bool isChecked = index.data(Qt::CheckStateRole).toInt() == Qt::Checked; m_model->setData(index, isChecked ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole); }; - manipulateTree(ui->bookmarksView->rootIndex(), manipulator); + manipulateTree(ui->outlineView->rootIndex(), manipulator); } -void SelectBookmarksToRegroupDialog::selectLevel1() +void SelectOutlineToRegroupDialog::selectLevel1() { - manipulateTree(ui->bookmarksView->rootIndex(), createCheckByDepthManipulator(1)); + manipulateTree(ui->outlineView->rootIndex(), createCheckByDepthManipulator(1)); } -void SelectBookmarksToRegroupDialog::selectLevel2() +void SelectOutlineToRegroupDialog::selectLevel2() { - manipulateTree(ui->bookmarksView->rootIndex(), createCheckByDepthManipulator(2)); + manipulateTree(ui->outlineView->rootIndex(), createCheckByDepthManipulator(2)); } -void SelectBookmarksToRegroupDialog::selectSubtree() +void SelectOutlineToRegroupDialog::selectSubtree() { manipulateTree(m_menuIndex, [this](QModelIndex index) { m_model->setData(index, Qt::Checked, Qt::CheckStateRole); }); } -void SelectBookmarksToRegroupDialog::deselectSubtree() +void SelectOutlineToRegroupDialog::deselectSubtree() { manipulateTree(m_menuIndex, [this](QModelIndex index) { m_model->setData(index, Qt::Unchecked, Qt::CheckStateRole); }); } diff --git a/Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.h b/Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.h similarity index 77% rename from Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.h rename to Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.h index 023f43d..9864738 100644 --- a/Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.h +++ b/Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.h @@ -15,8 +15,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with PDF4QT. If not, see . -#ifndef PDFDOCPAGEORGANIZER_SELECTBOOKMARKSTOREGROUPDIALOG_H -#define PDFDOCPAGEORGANIZER_SELECTBOOKMARKSTOREGROUPDIALOG_H +#ifndef PDFDOCPAGEORGANIZER_SELECTOUTLINETOREGROUPDIALOG_H +#define PDFDOCPAGEORGANIZER_SELECTOUTLINETOREGROUPDIALOG_H #include "pdfdocument.h" @@ -24,7 +24,7 @@ namespace Ui { -class SelectBookmarksToRegroupDialog; +class SelectOutlineToRegroupDialog; } namespace pdf @@ -35,13 +35,13 @@ class PDFSelectableOutlineTreeItemModel; namespace pdfdocpage { -class SelectBookmarksToRegroupDialog : public QDialog +class SelectOutlineToRegroupDialog : public QDialog { Q_OBJECT public: - explicit SelectBookmarksToRegroupDialog(const pdf::PDFDocument* document, QWidget* parent); - virtual ~SelectBookmarksToRegroupDialog() override; + explicit SelectOutlineToRegroupDialog(const pdf::PDFDocument* document, QWidget* parent); + virtual ~SelectOutlineToRegroupDialog() override; std::vector getSelectedOutlineItems() const; @@ -62,7 +62,7 @@ private: std::function createCheckByDepthManipulator(int targetDepth) const; - Ui::SelectBookmarksToRegroupDialog* ui; + Ui::SelectOutlineToRegroupDialog* ui; const pdf::PDFDocument* m_document; pdf::PDFSelectableOutlineTreeItemModel* m_model; QModelIndex m_menuIndex; @@ -70,4 +70,4 @@ private: } // namespace pdfdocpage -#endif // PDFDOCPAGEORGANIZER_SELECTBOOKMARKSTOREGROUPDIALOG_H +#endif // PDFDOCPAGEORGANIZER_SELECTOUTLINETOREGROUPDIALOG_H diff --git a/Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.ui b/Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.ui similarity index 80% rename from Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.ui rename to Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.ui index d7e5a99..8a15a9c 100644 --- a/Pdf4QtDocPageOrganizer/selectbookmarkstoregroupdialog.ui +++ b/Pdf4QtDocPageOrganizer/selectoutlinetoregroupdialog.ui @@ -1,7 +1,7 @@ - SelectBookmarksToRegroupDialog - + SelectOutlineToRegroupDialog + 0 @@ -11,11 +11,11 @@ - Select Bookmarks + Select Outline - + @@ -34,7 +34,7 @@ buttonBox accepted() - SelectBookmarksToRegroupDialog + SelectOutlineToRegroupDialog accept() @@ -50,7 +50,7 @@ buttonBox rejected() - SelectBookmarksToRegroupDialog + SelectOutlineToRegroupDialog reject() diff --git a/Pdf4QtLibCore/sources/pdfdocumentsanitizer.cpp b/Pdf4QtLibCore/sources/pdfdocumentsanitizer.cpp index a6d4b74..4926bbf 100644 --- a/Pdf4QtLibCore/sources/pdfdocumentsanitizer.cpp +++ b/Pdf4QtLibCore/sources/pdfdocumentsanitizer.cpp @@ -86,9 +86,9 @@ void PDFDocumentSanitizer::sanitize() performSanitizeMetadata(); } - if (m_flags.testFlag(Bookmarks)) + if (m_flags.testFlag(Outline)) { - performSanitizeBookmarks(); + performSanitizeOutline(); } if (m_flags.testFlag(FileAttachments)) @@ -163,7 +163,7 @@ void PDFDocumentSanitizer::performSanitizeMetadata() Q_EMIT sanitizationProgress(tr("Metadata streams removed: %1").arg(counter)); } -void PDFDocumentSanitizer::performSanitizeBookmarks() +void PDFDocumentSanitizer::performSanitizeOutline() { PDFDocumentBuilder builder(m_storage, PDFVersion(2, 0)); PDFObject catalogObject = builder.getObjectByReference(builder.getCatalogReference()); diff --git a/Pdf4QtLibCore/sources/pdfdocumentsanitizer.h b/Pdf4QtLibCore/sources/pdfdocumentsanitizer.h index 7eb2de7..828822a 100644 --- a/Pdf4QtLibCore/sources/pdfdocumentsanitizer.h +++ b/Pdf4QtLibCore/sources/pdfdocumentsanitizer.h @@ -38,7 +38,7 @@ public: None = 0x0000, ///< No sanitization is performed DocumentInfo = 0x0001, ///< Remove document information Metadata = 0x0002, ///< Remove all metadata streams in all objects - Bookmarks = 0x0004, ///< Remove bookmarks + Outline = 0x0004, ///< Remove outline FileAttachments = 0x0008, ///< Remove file attachments EmbeddedSearchIndex = 0x0010, ///< Remove embedded search index MarkupAnnotations = 0x0020, ///< Remove markup annotations from all pages @@ -82,7 +82,7 @@ signals: private: void performSanitizeDocumentInfo(); void performSanitizeMetadata(); - void performSanitizeBookmarks(); + void performSanitizeOutline(); void performSanitizeFileAttachments(); void performSanitizeEmbeddedSearchIndex(); void performSanitizeMarkupAnnotations(); diff --git a/Pdf4QtViewer/pdf4qtviewer.qrc b/Pdf4QtViewer/pdf4qtviewer.qrc index cca5713..9633962 100644 --- a/Pdf4QtViewer/pdf4qtviewer.qrc +++ b/Pdf4QtViewer/pdf4qtviewer.qrc @@ -15,7 +15,6 @@ resources/settings.svg resources/zoom-in.svg resources/zoom-out.svg - resources/bookmark.svg resources/security.svg resources/zoom-fit.svg resources/zoom-fit-horizontal.svg @@ -104,5 +103,6 @@ resources/sidebar-speech.svg resources/sidebar-thumbnails.svg resources/sidebar-visibility.svg + resources/outline.svg diff --git a/Pdf4QtViewer/pdfsanitizedocumentdialog.cpp b/Pdf4QtViewer/pdfsanitizedocumentdialog.cpp index 93e34e3..0fa4c6d 100644 --- a/Pdf4QtViewer/pdfsanitizedocumentdialog.cpp +++ b/Pdf4QtViewer/pdfsanitizedocumentdialog.cpp @@ -51,7 +51,7 @@ PDFSanitizeDocumentDialog::PDFSanitizeDocumentDialog(const pdf::PDFDocument* doc addCheckBox(tr("Remove document info"), pdf::PDFDocumentSanitizer::DocumentInfo); addCheckBox(tr("Remove all metadata"), pdf::PDFDocumentSanitizer::Metadata); - addCheckBox(tr("Remove outline (bookmarks)"), pdf::PDFDocumentSanitizer::Bookmarks); + addCheckBox(tr("Remove outline"), pdf::PDFDocumentSanitizer::Outline); addCheckBox(tr("Remove file attachments"), pdf::PDFDocumentSanitizer::FileAttachments); addCheckBox(tr("Remove embedded search index"), pdf::PDFDocumentSanitizer::EmbeddedSearchIndex); addCheckBox(tr("Remove comments and other markup annotations"), pdf::PDFDocumentSanitizer::MarkupAnnotations); diff --git a/Pdf4QtViewer/pdfsidebarwidget.cpp b/Pdf4QtViewer/pdfsidebarwidget.cpp index fe3d6dc..babe0a2 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.cpp +++ b/Pdf4QtViewer/pdfsidebarwidget.cpp @@ -81,26 +81,26 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, setStyleSheet(STYLESHEET); // Outline - QIcon bookmarkIcon(":/resources/bookmark.svg"); - m_outlineTreeModel = new pdf::PDFOutlineTreeItemModel(qMove(bookmarkIcon), editableOutline, this); - ui->bookmarksTreeView->setModel(m_outlineTreeModel); - ui->bookmarksTreeView->header()->hide(); + QIcon outlineIcon(":/resources/outline.svg"); + m_outlineTreeModel = new pdf::PDFOutlineTreeItemModel(qMove(outlineIcon), editableOutline, this); + ui->outlineTreeView->setModel(m_outlineTreeModel); + ui->outlineTreeView->header()->hide(); if (editableOutline) { - ui->bookmarksTreeView->setDragEnabled(true); - ui->bookmarksTreeView->setAcceptDrops(true); - ui->bookmarksTreeView->setDropIndicatorShown(true); - ui->bookmarksTreeView->setDragDropMode(QAbstractItemView::InternalMove); - ui->bookmarksTreeView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->bookmarksTreeView, &QTreeView::customContextMenuRequested, this, &PDFSidebarWidget::onBookmarksTreeViewContextMenuRequested); + ui->outlineTreeView->setDragEnabled(true); + ui->outlineTreeView->setAcceptDrops(true); + ui->outlineTreeView->setDropIndicatorShown(true); + ui->outlineTreeView->setDragDropMode(QAbstractItemView::InternalMove); + ui->outlineTreeView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->outlineTreeView, &QTreeView::customContextMenuRequested, this, &PDFSidebarWidget::onOutlineTreeViewContextMenuRequested); connect(m_outlineTreeModel, &pdf::PDFOutlineTreeItemModel::dataChanged, this, &PDFSidebarWidget::onOutlineItemsChanged); connect(m_outlineTreeModel, &pdf::PDFOutlineTreeItemModel::rowsInserted, this, &PDFSidebarWidget::onOutlineItemsChanged); connect(m_outlineTreeModel, &pdf::PDFOutlineTreeItemModel::rowsRemoved, this, &PDFSidebarWidget::onOutlineItemsChanged); connect(m_outlineTreeModel, &pdf::PDFOutlineTreeItemModel::rowsMoved, this, &PDFSidebarWidget::onOutlineItemsChanged); } - connect(ui->bookmarksTreeView, &QTreeView::clicked, this, &PDFSidebarWidget::onOutlineItemClicked); + connect(ui->outlineTreeView, &QTreeView::clicked, this, &PDFSidebarWidget::onOutlineItemClicked); // Thumbnails m_thumbnailsModel = new pdf::PDFThumbnailsItemModel(proxy, this); @@ -128,7 +128,7 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, m_pageInfo[Invalid] = { nullptr, ui->emptyPage }; m_pageInfo[OptionalContent] = { ui->optionalContentButton, ui->optionalContentPage }; - m_pageInfo[Bookmarks] = { ui->bookmarksButton, ui->bookmarksPage }; + m_pageInfo[Outline] = { ui->outlineButton, ui->outlinePage }; m_pageInfo[Thumbnails] = { ui->thumbnailsButton, ui->thumbnailsPage }; m_pageInfo[Attachments] = { ui->attachmentsButton, ui->attachmentsPage }; m_pageInfo[Speech] = { ui->speechButton, ui->speechPage }; @@ -189,7 +189,7 @@ void PDFSidebarWidget::setDocument(const pdf::PDFModifiedDocument& document, con switch (pageMode) { case pdf::PageMode::UseOutlines: - preferred = Bookmarks; + preferred = Outline; break; case pdf::PageMode::UseThumbnails: @@ -210,7 +210,7 @@ void PDFSidebarWidget::setDocument(const pdf::PDFModifiedDocument& document, con switch (nonFullscreenPageMode) { case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseOutline: - preferred = Bookmarks; + preferred = Outline; break; case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseThumbnails: @@ -259,7 +259,7 @@ bool PDFSidebarWidget::isEmpty(Page page) const case Invalid: return true; - case Bookmarks: + case Outline: return m_outlineTreeModel->isEmpty() && (!m_document || !m_outlineTreeModel->isEditable()); case Thumbnails: @@ -764,11 +764,11 @@ void PDFSidebarWidget::onSignatureCustomContextMenuRequested(const QPoint& pos) } } -void PDFSidebarWidget::onBookmarksTreeViewContextMenuRequested(const QPoint& pos) +void PDFSidebarWidget::onOutlineTreeViewContextMenuRequested(const QPoint& pos) { QMenu contextMenu; - QModelIndex index = ui->bookmarksTreeView->indexAt(pos); + QModelIndex index = ui->outlineTreeView->indexAt(pos); auto onFollow = [this, index]() { @@ -779,22 +779,22 @@ void PDFSidebarWidget::onBookmarksTreeViewContextMenuRequested(const QPoint& pos { if (index.isValid()) { - ui->bookmarksTreeView->model()->insertRow(index.row() + 1, index.parent()); + ui->outlineTreeView->model()->insertRow(index.row() + 1, index.parent()); } else { - ui->bookmarksTreeView->model()->insertRow(ui->bookmarksTreeView->model()->rowCount()); + ui->outlineTreeView->model()->insertRow(ui->outlineTreeView->model()->rowCount()); } }; auto onDelete = [this, index]() { - ui->bookmarksTreeView->model()->removeRow(index.row(), index.parent()); + ui->outlineTreeView->model()->removeRow(index.row(), index.parent()); }; auto onRename = [this, index]() { - ui->bookmarksTreeView->edit(index); + ui->outlineTreeView->edit(index); }; QAction* followAction = contextMenu.addAction(tr("Follow"), onFollow); @@ -927,7 +927,7 @@ void PDFSidebarWidget::onBookmarksTreeViewContextMenuRequested(const QPoint& pos submenu->addAction(tr("Fit Bounding Box Vertically"), createOnSetTarget(pdf::DestinationType::FitBV)); submenu->addAction(tr("XYZ"), createOnSetTarget(pdf::DestinationType::XYZ)); - contextMenu.exec(ui->bookmarksTreeView->mapToGlobal(pos)); + contextMenu.exec(ui->outlineTreeView->mapToGlobal(pos)); } void PDFSidebarWidget::onOutlineItemsChanged() diff --git a/Pdf4QtViewer/pdfsidebarwidget.h b/Pdf4QtViewer/pdfsidebarwidget.h index 1a215e3..e65aee4 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.h +++ b/Pdf4QtViewer/pdfsidebarwidget.h @@ -72,7 +72,7 @@ public: { Invalid, _BEGIN, - Bookmarks = _BEGIN, + Outline = _BEGIN, Thumbnails, OptionalContent, Attachments, @@ -113,7 +113,7 @@ private: void onAttachmentCustomContextMenuRequested(const QPoint& pos); void onThumbnailClicked(const QModelIndex& index); void onSignatureCustomContextMenuRequested(const QPoint &pos); - void onBookmarksTreeViewContextMenuRequested(const QPoint &pos); + void onOutlineTreeViewContextMenuRequested(const QPoint &pos); void onOutlineItemsChanged(); struct PageInfo diff --git a/Pdf4QtViewer/pdfsidebarwidget.ui b/Pdf4QtViewer/pdfsidebarwidget.ui index 6e148b0..f6f6d9f 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.ui +++ b/Pdf4QtViewer/pdfsidebarwidget.ui @@ -29,7 +29,7 @@ - + 96 @@ -42,7 +42,7 @@ - Bookmarks + Outline @@ -243,11 +243,11 @@ - 2 + 1 - - + + 0 @@ -264,7 +264,7 @@ 0 - + diff --git a/Pdf4QtViewer/resources/bookmark.svg b/Pdf4QtViewer/resources/outline.svg similarity index 100% rename from Pdf4QtViewer/resources/bookmark.svg rename to Pdf4QtViewer/resources/outline.svg From 7a5f37e38fd8e35fa75109cf6a2aaff358a1ac8f Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sat, 16 Dec 2023 20:23:53 +0100 Subject: [PATCH 2/5] Issue #54: Bookmarks page - model, bookmarks manager --- Pdf4QtViewer/CMakeLists.txt | 4 + Pdf4QtViewer/pdf4qtviewer.qrc | 1 + Pdf4QtViewer/pdfbookmarkmanager.cpp | 272 ++++++++++++++++++ Pdf4QtViewer/pdfbookmarkmanager.h | 74 +++++ Pdf4QtViewer/pdfbookmarkui.cpp | 173 +++++++++++ Pdf4QtViewer/pdfbookmarkui.h | 76 +++++ Pdf4QtViewer/pdfprogramcontroller.cpp | 15 + Pdf4QtViewer/pdfprogramcontroller.h | 4 + Pdf4QtViewer/pdfsidebarwidget.cpp | 13 + Pdf4QtViewer/pdfsidebarwidget.h | 6 + Pdf4QtViewer/pdfsidebarwidget.ui | 61 +++- Pdf4QtViewer/pdfviewermainwindow.cpp | 2 +- Pdf4QtViewer/pdfviewermainwindowlite.cpp | 2 +- Pdf4QtViewer/resources/sidebar-favourites.svg | 58 ++++ 14 files changed, 756 insertions(+), 5 deletions(-) create mode 100644 Pdf4QtViewer/pdfbookmarkmanager.cpp create mode 100644 Pdf4QtViewer/pdfbookmarkmanager.h create mode 100644 Pdf4QtViewer/pdfbookmarkui.cpp create mode 100644 Pdf4QtViewer/pdfbookmarkui.h create mode 100644 Pdf4QtViewer/resources/sidebar-favourites.svg diff --git a/Pdf4QtViewer/CMakeLists.txt b/Pdf4QtViewer/CMakeLists.txt index 40aeb89..e15e348 100644 --- a/Pdf4QtViewer/CMakeLists.txt +++ b/Pdf4QtViewer/CMakeLists.txt @@ -69,6 +69,10 @@ add_library(Pdf4QtViewer SHARED pdfcreatebitonaldocumentdialog.cpp pdfcreatebitonaldocumentdialog.h pdf4qtviewer.qrc + pdfbookmarkmanager.h + pdfbookmarkmanager.cpp + pdfbookmarkui.h + pdfbookmarkui.cpp ) add_compile_definitions(QT_INSTALL_DIRECTORY="${QT6_INSTALL_PREFIX}") diff --git a/Pdf4QtViewer/pdf4qtviewer.qrc b/Pdf4QtViewer/pdf4qtviewer.qrc index 9633962..b9d80e6 100644 --- a/Pdf4QtViewer/pdf4qtviewer.qrc +++ b/Pdf4QtViewer/pdf4qtviewer.qrc @@ -104,5 +104,6 @@ resources/sidebar-thumbnails.svg resources/sidebar-visibility.svg resources/outline.svg + resources/sidebar-favourites.svg diff --git a/Pdf4QtViewer/pdfbookmarkmanager.cpp b/Pdf4QtViewer/pdfbookmarkmanager.cpp new file mode 100644 index 0000000..8ae9a39 --- /dev/null +++ b/Pdf4QtViewer/pdfbookmarkmanager.cpp @@ -0,0 +1,272 @@ +// Copyright (C) 2023 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT 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 +// with the written consent of the copyright owner, any later version. +// +// PDF4QT 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 PDF4QT. If not, see . + +#include "pdfbookmarkmanager.h" +#include "pdfaction.h" + +#include +#include +#include + +namespace pdfviewer +{ + +class PDFBookmarkManagerHelper +{ +public: + constexpr PDFBookmarkManagerHelper() = delete; + + static QJsonObject convertBookmarkToJson(const PDFBookmarkManager::Bookmark& bookmark) + { + QJsonObject json; + json["isAuto"] = bookmark.isAuto; + json["name"] = bookmark.name; + json["pageIndex"] = bookmark.pageIndex; + return json; + } + + static PDFBookmarkManager::Bookmark convertJsonToBookmark(const QJsonObject& json) + { + PDFBookmarkManager::Bookmark bookmark; + bookmark.isAuto = json["isAuto"].toBool(); + bookmark.name = json["name"].toString(); + bookmark.pageIndex = json["pageIndex"].toInt(); + return bookmark; + } + + static QJsonObject convertBookmarksToJson(const PDFBookmarkManager::Bookmarks& bookmarks) + { + QJsonArray jsonArray; + + for (const auto& bookmark : bookmarks.bookmarks) + { + jsonArray.append(convertBookmarkToJson(bookmark)); + } + + QJsonObject jsonObject; + jsonObject["bookmarks"] = jsonArray; + return jsonObject; + } + + static PDFBookmarkManager::Bookmarks convertBookmarksFromJson(const QJsonObject& object) + { + PDFBookmarkManager::Bookmarks bookmarks; + + QJsonArray jsonArray = object["bookmarks"].toArray(); + + for (const auto& jsonValue : jsonArray) + { + bookmarks.bookmarks.push_back(convertJsonToBookmark(jsonValue.toObject())); + } + + return bookmarks; + } + + static QJsonDocument convertBookmarksMapToJsonDocument(const std::map& bookmarksMap) + { + QJsonObject mainObject; + for (const auto& pair : bookmarksMap) + { + mainObject[pair.first] = convertBookmarksToJson(pair.second); + } + return QJsonDocument(mainObject); + } + + static std::map convertBookmarksMapFromJsonDocument(const QJsonDocument &doc) + { + std::map container; + QJsonObject mainObject = doc.object(); + + for (auto it = mainObject.begin(); it != mainObject.end(); ++it) + { + container[it.key()] = convertBookmarksFromJson(it.value().toObject()); + } + + return container; + } +}; + +PDFBookmarkManager::PDFBookmarkManager(QObject* parent) : + BaseClass(parent) +{ + +} + +void PDFBookmarkManager::setDocument(const pdf::PDFModifiedDocument& document) +{ + Q_EMIT bookmarksAboutToBeChanged(); + + const bool init = !m_document; + m_document = document.getDocument(); + + QString key; + + if (document.hasPreserveView() && m_document) + { + // Pass the key + key = QString::fromLatin1(m_document->getSourceDataHash().toHex()); + + if (m_bookmarks.count(m_currentKey) && m_currentKey != key) + { + m_bookmarks[key] = m_bookmarks[m_currentKey]; + m_bookmarks.erase(m_currentKey); + } + } + + if (init && m_document) + { + key = QString::fromLatin1(m_document->getSourceDataHash().toHex()); + } + + if (key.isEmpty()) + { + key = "generic"; + } + + m_currentKey = key; + + if (document.hasReset() && !document.hasPreserveView()) + { + regenerateAutoBookmarks(); + } + + Q_EMIT bookmarksChanged(); +} + +void PDFBookmarkManager::saveToFile(QString fileName) +{ + QJsonDocument doc = PDFBookmarkManagerHelper::convertBookmarksMapToJsonDocument(m_bookmarks); + + // Příklad zápisu do souboru + QFile file(fileName); + if (file.open(QIODevice::WriteOnly)) + { + file.write(doc.toJson()); + file.close(); + } +} + +bool PDFBookmarkManager::loadFromFile(QString fileName) +{ + QFile file(fileName); + if (file.open(QIODevice::ReadOnly)) + { + QJsonDocument loadedDoc = QJsonDocument::fromJson(file.readAll()); + file.close(); + + m_bookmarks = PDFBookmarkManagerHelper::convertBookmarksMapFromJsonDocument(loadedDoc); + return true; + } + + return false; +} + +int PDFBookmarkManager::getBookmarkCount() const +{ + if (m_bookmarks.count(m_currentKey)) + { + return m_bookmarks.at(m_currentKey).bookmarks.size(); + } + + return 0; +} + +PDFBookmarkManager::Bookmark PDFBookmarkManager::getBookmark(int index) const +{ + if (m_bookmarks.count(m_currentKey)) + { + return m_bookmarks.at(m_currentKey).bookmarks.at(index); + } + + return Bookmark(); +} + +void PDFBookmarkManager::regenerateAutoBookmarks() +{ + if (!m_document) + { + return; + } + + // Create bookmarks for all main chapters + Bookmarks& bookmarks = m_bookmarks[m_currentKey]; + + for (auto it = bookmarks.bookmarks.begin(); it != bookmarks.bookmarks.end();) + { + if (it->isAuto) + { + it = bookmarks.bookmarks.erase(it); + } + else + { + ++it; + } + } + + if (auto outlineRoot = m_document->getCatalog()->getOutlineRootPtr()) + { + size_t childCount = outlineRoot->getChildCount(); + for (size_t i = 0; i < childCount; ++i) + { + Bookmark bookmark; + bookmark.isAuto = true; + bookmark.pageIndex = pdf::PDFCatalog::INVALID_PAGE_INDEX; + + const pdf::PDFOutlineItem* child = outlineRoot->getChild(i); + const pdf::PDFAction* action = child->getAction(); + + if (action) + { + for (const pdf::PDFAction* currentAction : action->getActionList()) + { + if (currentAction->getType() != pdf::ActionType::GoTo) + { + continue; + } + + const pdf::PDFActionGoTo* typedAction = dynamic_cast(currentAction); + pdf::PDFDestination destination = typedAction->getDestination(); + if (destination.getDestinationType() == pdf::DestinationType::Named) + { + if (const pdf::PDFDestination* targetDestination = m_document->getCatalog()->getNamedDestination(destination.getName())) + { + destination = *targetDestination; + } + } + + if (destination.getDestinationType() != pdf::DestinationType::Invalid && + destination.getPageReference() != pdf::PDFObjectReference()) + { + const size_t pageIndex = m_document->getCatalog()->getPageIndexFromPageReference(destination.getPageReference()); + if (pageIndex != pdf::PDFCatalog::INVALID_PAGE_INDEX) + { + bookmark.pageIndex = pageIndex; + bookmark.name = child->getTitle(); + } + } + } + } + + if (bookmark.pageIndex != pdf::PDFCatalog::INVALID_PAGE_INDEX) + { + bookmarks.bookmarks.emplace_back(std::move(bookmark)); + } + } + } +} + +} // namespace pdf diff --git a/Pdf4QtViewer/pdfbookmarkmanager.h b/Pdf4QtViewer/pdfbookmarkmanager.h new file mode 100644 index 0000000..fd68760 --- /dev/null +++ b/Pdf4QtViewer/pdfbookmarkmanager.h @@ -0,0 +1,74 @@ +// Copyright (C) 2023 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT 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 +// with the written consent of the copyright owner, any later version. +// +// PDF4QT 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 PDF4QT. If not, see . + +#ifndef PDFBOOKMARKMANAGER_H +#define PDFBOOKMARKMANAGER_H + +#include "pdfdocument.h" + +#include + +namespace pdfviewer +{ + +class PDFBookmarkManager : public QObject +{ + Q_OBJECT + +private: + using BaseClass = QObject; + +public: + PDFBookmarkManager(QObject* parent); + + void setDocument(const pdf::PDFModifiedDocument& document); + + void saveToFile(QString fileName); + bool loadFromFile(QString fileName); + + struct Bookmark + { + bool isAuto = false; + QString name; + pdf::PDFInteger pageIndex = -1; + }; + + int getBookmarkCount() const; + Bookmark getBookmark(int index) const; + +signals: + void bookmarksAboutToBeChanged(); + void bookmarksChanged(); + +private: + friend class PDFBookmarkManagerHelper; + + void regenerateAutoBookmarks(); + + struct Bookmarks + { + std::vector bookmarks; + }; + + pdf::PDFDocument* m_document; + QString m_currentKey; + std::map m_bookmarks; +}; + +} // namespace pdf + +#endif // PDFBOOKMARKMANAGER_H diff --git a/Pdf4QtViewer/pdfbookmarkui.cpp b/Pdf4QtViewer/pdfbookmarkui.cpp new file mode 100644 index 0000000..e53d278 --- /dev/null +++ b/Pdf4QtViewer/pdfbookmarkui.cpp @@ -0,0 +1,173 @@ +// Copyright (C) 2023 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT 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 +// with the written consent of the copyright owner, any later version. +// +// PDF4QT 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 PDF4QT. If not, see . + +#include "pdfbookmarkui.h" +#include "pdfwidgetutils.h" + +#include +#include + +namespace pdfviewer +{ + +PDFBookmarkItemModel::PDFBookmarkItemModel(PDFBookmarkManager* bookmarkManager, QObject* parent) : + BaseClass(parent), + m_bookmarkManager(bookmarkManager) +{ + connect(m_bookmarkManager, &PDFBookmarkManager::bookmarksAboutToBeChanged, this, &PDFBookmarkItemModel::beginResetModel); + connect(m_bookmarkManager, &PDFBookmarkManager::bookmarksChanged, this, &PDFBookmarkItemModel::endResetModel); +} + +QModelIndex PDFBookmarkItemModel::index(int row, int column, const QModelIndex& parent) const +{ + return createIndex(row, column, nullptr); +} + +QModelIndex PDFBookmarkItemModel::parent(const QModelIndex& child) const +{ + return QModelIndex(); +} + +int PDFBookmarkItemModel::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + { + return 0; + } + + return m_bookmarkManager ? m_bookmarkManager->getBookmarkCount() : 0; +} + +int PDFBookmarkItemModel::columnCount(const QModelIndex& parent) const +{ + return 1; +} + +QVariant PDFBookmarkItemModel::data(const QModelIndex& index, int role) const +{ + if (role == Qt::DisplayRole) + { + return m_bookmarkManager->getBookmark(index.row()).name; + } + + return QVariant(); +} + +PDFBookmarkItemDelegate::PDFBookmarkItemDelegate(PDFBookmarkManager* bookmarkManager, QObject* parent) : + BaseClass(parent), + m_bookmarkManager(bookmarkManager) +{ + +} + +void PDFBookmarkItemDelegate::paint(QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + QStyleOptionViewItem options = option; + initStyleOption(&options, index); + + PDFBookmarkManager::Bookmark bookmark = m_bookmarkManager->getBookmark(index.row()); + + options.text = QString(); + options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter); + + const int margin = pdf::PDFWidgetUtils::scaleDPI_x(option.widget, MARGIN); + const int iconSize = pdf::PDFWidgetUtils::scaleDPI_x(option.widget, ICON_SIZE); + + QRect rect = options.rect; + rect.marginsRemoved(QMargins(margin, margin, margin, margin)); + + QRect iconRect = rect; + iconRect.setWidth(iconSize); + iconRect.setHeight(iconSize); + iconRect.moveCenter(QPoint(rect.left() + iconSize / 2, rect.center().y())); + drawStar(*painter, iconRect.center(), iconRect.width() * 0.5, QColor(64, 64, 192)); + + QRect textRect = rect; + textRect.setLeft(iconRect.right() + margin); + + textRect.setHeight(options.fontMetrics.lineSpacing()); + + QFont font = options.font; + font.setBold(true); + + painter->setFont(font); + painter->drawText(textRect, getPageText(bookmark)); + + textRect.translate(0, textRect.height()); + + painter->setFont(options.font); + painter->drawText(textRect, bookmark.name); +} + +QSize PDFBookmarkItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + PDFBookmarkManager::Bookmark bookmark = m_bookmarkManager->getBookmark(index.row()); + + const int textWidthLine1 = option.fontMetrics.horizontalAdvance(getPageText(bookmark)); + const int textWidthLine2 = option.fontMetrics.horizontalAdvance(option.text); + const int textWidth = qMax(textWidthLine1, textWidthLine2); + const int textHeight = option.fontMetrics.lineSpacing() * 2; + + const int margin = pdf::PDFWidgetUtils::scaleDPI_x(option.widget, MARGIN); + const int iconSize = pdf::PDFWidgetUtils::scaleDPI_x(option.widget, ICON_SIZE); + + const int requiredWidth = 3 * margin + iconSize + textWidth; + const int requiredHeight = 2 * margin + qMax(iconSize, textHeight); + + return QSize(requiredWidth, requiredHeight); +} + +void PDFBookmarkItemDelegate::drawStar(QPainter& painter, const QPointF& center, double size, const QColor& color) const +{ + painter.save(); + + painter.setPen(Qt::NoPen); + painter.setBrush(color); + + QPainterPath path; + double angle = M_PI / 5; + + for (int i = 0; i < 10; ++i) + { + double radius = (i % 2 == 0) ? size : size / 2.5; + QPointF point(radius * cos(i * angle), radius * sin(i * angle)); + point += center; + + if (i == 0) + { + path.moveTo(point); + } + else + { + path.lineTo(point); + } + } + path.closeSubpath(); + + painter.drawPath(path); + + painter.restore(); +} + +QString PDFBookmarkItemDelegate::getPageText(const PDFBookmarkManager::Bookmark& bookmark) const +{ + return tr("Page %1").arg(bookmark.pageIndex + 1); +} + +} // namespace pdfviewer diff --git a/Pdf4QtViewer/pdfbookmarkui.h b/Pdf4QtViewer/pdfbookmarkui.h new file mode 100644 index 0000000..4aa8200 --- /dev/null +++ b/Pdf4QtViewer/pdfbookmarkui.h @@ -0,0 +1,76 @@ +// Copyright (C) 2023 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT 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 +// with the written consent of the copyright owner, any later version. +// +// PDF4QT 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 PDF4QT. If not, see . + +#ifndef PDFBOOKMARKUI_H +#define PDFBOOKMARKUI_H + +#include "pdfviewerglobal.h" +#include "pdfbookmarkmanager.h" + +#include +#include + +namespace pdfviewer +{ + +class PDFBookmarkItemModel : public QAbstractItemModel +{ + Q_OBJECT + +private: + using BaseClass = QAbstractItemModel; + +public: + PDFBookmarkItemModel(PDFBookmarkManager* bookmarkManager, QObject* parent); + + virtual QModelIndex index(int row, int column, const QModelIndex& parent) const override; + virtual QModelIndex parent(const QModelIndex& child) const override; + virtual int rowCount(const QModelIndex& parent) const override; + virtual int columnCount(const QModelIndex& parent) const override; + virtual QVariant data(const QModelIndex& index, int role) const override; + +private: + PDFBookmarkManager* m_bookmarkManager = nullptr; +}; + +class PDFBookmarkItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +private: + using BaseClass = QStyledItemDelegate; + +public: + PDFBookmarkItemDelegate(PDFBookmarkManager* bookmarkManager, QObject* parent); + + virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; + +private: + static constexpr int MARGIN = 6; + static constexpr int ICON_SIZE = 32; + + void drawStar(QPainter& painter, const QPointF& center, double size, const QColor& color) const; + + QString getPageText(const PDFBookmarkManager::Bookmark& bookmark) const; + + PDFBookmarkManager* m_bookmarkManager = nullptr; +}; + +} // namespace pdfviewer + +#endif // PDFBOOKMARKUI_H diff --git a/Pdf4QtViewer/pdfprogramcontroller.cpp b/Pdf4QtViewer/pdfprogramcontroller.cpp index 4b94c8d..8110c3b 100644 --- a/Pdf4QtViewer/pdfprogramcontroller.cpp +++ b/Pdf4QtViewer/pdfprogramcontroller.cpp @@ -361,6 +361,7 @@ PDFProgramController::PDFProgramController(QObject* parent) : m_toolManager(nullptr), m_annotationManager(nullptr), m_formManager(nullptr), + m_bookmarkManager(nullptr), m_isBusy(false), m_isFactorySettingsBeingRestored(false), m_progress(nullptr) @@ -375,6 +376,9 @@ PDFProgramController::~PDFProgramController() delete m_annotationManager; m_annotationManager = nullptr; + + delete m_bookmarkManager; + m_bookmarkManager = nullptr; } void PDFProgramController::initializeAnnotationManager() @@ -396,6 +400,11 @@ void PDFProgramController::initializeFormManager() connect(m_formManager, &pdf::PDFFormManager::documentModified, this, &PDFProgramController::onDocumentModified); } +void PDFProgramController::initializeBookmarkManager() +{ + m_bookmarkManager = new PDFBookmarkManager(this); +} + void PDFProgramController::initialize(Features features, QMainWindow* mainWindow, IMainWindow* mainWindowInterface, @@ -605,6 +614,7 @@ void PDFProgramController::initialize(Features features, } initializeAnnotationManager(); + initializeBookmarkManager(); if (features.testFlag(Forms)) { @@ -1915,6 +1925,11 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document, bool i m_annotationManager->setDocument(document); } + if (m_bookmarkManager) + { + m_bookmarkManager->setDocument(document); + } + if (m_formManager) { m_formManager->setDocument(document); diff --git a/Pdf4QtViewer/pdfprogramcontroller.h b/Pdf4QtViewer/pdfprogramcontroller.h index e179606..8be65c2 100644 --- a/Pdf4QtViewer/pdfprogramcontroller.h +++ b/Pdf4QtViewer/pdfprogramcontroller.h @@ -24,6 +24,7 @@ #include "pdfdocumentreader.h" #include "pdfdocumentpropertiesdialog.h" #include "pdfplugin.h" +#include "pdfbookmarkmanager.h" #include #include @@ -275,6 +276,7 @@ public: PDFViewerSettings* getSettings() const { return m_settings; } pdf::PDFDocument* getDocument() const { return m_pdfDocument.data(); } pdf::PDFCertificateStore* getCertificateStore() const { return const_cast(&m_certificateStore); } + PDFBookmarkManager* getBookmarkManager() const { return m_bookmarkManager; } PDFTextToSpeech* getTextToSpeech() const { return m_textToSpeech; } const std::vector* getSignatures() const { return &m_signatures; } @@ -326,6 +328,7 @@ private: void initializeToolManager(); void initializeAnnotationManager(); void initializeFormManager(); + void initializeBookmarkManager(); void onActionGoToDocumentStartTriggered(); void onActionGoToDocumentEndTriggered(); @@ -422,6 +425,7 @@ private: pdf::PDFToolManager* m_toolManager; pdf::PDFWidgetAnnotationManager* m_annotationManager; pdf::PDFWidgetFormManager* m_formManager; + PDFBookmarkManager* m_bookmarkManager; PDFFileInfo m_fileInfo; QFileSystemWatcher m_fileWatcher; diff --git a/Pdf4QtViewer/pdfsidebarwidget.cpp b/Pdf4QtViewer/pdfsidebarwidget.cpp index babe0a2..9fce464 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.cpp +++ b/Pdf4QtViewer/pdfsidebarwidget.cpp @@ -33,6 +33,7 @@ #include "pdfdrawspacecontroller.h" #include "pdfdocumentbuilder.h" #include "pdfwidgetutils.h" +#include "pdfbookmarkui.h" #include #include @@ -60,6 +61,7 @@ constexpr const char* STYLESHEET = PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, PDFTextToSpeech* textToSpeech, pdf::PDFCertificateStore* certificateStore, + PDFBookmarkManager* bookmarkManager, PDFViewerSettings* settings, bool editableOutline, QWidget* parent) : @@ -68,10 +70,12 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, m_proxy(proxy), m_textToSpeech(textToSpeech), m_certificateStore(certificateStore), + m_bookmarkManager(bookmarkManager), m_settings(settings), m_outlineTreeModel(nullptr), m_thumbnailsModel(nullptr), m_optionalContentTreeModel(nullptr), + m_bookmarkItemModel(nullptr), m_document(nullptr), m_optionalContentActivity(nullptr), m_attachmentsTreeModel(nullptr) @@ -126,6 +130,11 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, ui->attachmentsTreeView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->attachmentsTreeView, &QTreeView::customContextMenuRequested, this, &PDFSidebarWidget::onAttachmentCustomContextMenuRequested); + // Bookmarks + m_bookmarkItemModel = new PDFBookmarkItemModel(bookmarkManager, this); + ui->bookmarksView->setModel(m_bookmarkItemModel); + ui->bookmarksView->setItemDelegate(new PDFBookmarkItemDelegate(bookmarkManager, this)); + m_pageInfo[Invalid] = { nullptr, ui->emptyPage }; m_pageInfo[OptionalContent] = { ui->optionalContentButton, ui->optionalContentPage }; m_pageInfo[Outline] = { ui->outlineButton, ui->outlinePage }; @@ -133,6 +142,7 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, m_pageInfo[Attachments] = { ui->attachmentsButton, ui->attachmentsPage }; m_pageInfo[Speech] = { ui->speechButton, ui->speechPage }; m_pageInfo[Signatures] = { ui->signaturesButton, ui->signaturesPage }; + m_pageInfo[Bookmarks] = { ui->bookmarksButton, ui->bookmarksPage }; for (const auto& pageInfo : m_pageInfo) { @@ -271,6 +281,9 @@ bool PDFSidebarWidget::isEmpty(Page page) const case Attachments: return m_attachmentsTreeModel->isEmpty(); + case Bookmarks: + return !m_document || !m_bookmarkManager; + case Speech: return !m_textToSpeech->isValid(); diff --git a/Pdf4QtViewer/pdfsidebarwidget.h b/Pdf4QtViewer/pdfsidebarwidget.h index e65aee4..f7ee57b 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.h +++ b/Pdf4QtViewer/pdfsidebarwidget.h @@ -20,6 +20,7 @@ #define PDFSIDEBARWIDGET_H #include "pdfglobal.h" +#include "pdfbookmarkmanager.h" #include @@ -52,6 +53,7 @@ namespace pdfviewer { class PDFTextToSpeech; class PDFViewerSettings; +class PDFBookmarkItemModel; class PDFSidebarWidget : public QWidget { @@ -61,6 +63,7 @@ public: explicit PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, PDFTextToSpeech* textToSpeech, pdf::PDFCertificateStore* certificateStore, + PDFBookmarkManager* bookmarkManager, PDFViewerSettings* settings, bool editableOutline, QWidget* parent); @@ -78,6 +81,7 @@ public: Attachments, Speech, Signatures, + Bookmarks, _END }; @@ -126,10 +130,12 @@ private: pdf::PDFDrawWidgetProxy* m_proxy; PDFTextToSpeech* m_textToSpeech; pdf::PDFCertificateStore* m_certificateStore; + PDFBookmarkManager* m_bookmarkManager; PDFViewerSettings* m_settings; pdf::PDFOutlineTreeItemModel* m_outlineTreeModel; pdf::PDFThumbnailsItemModel* m_thumbnailsModel; pdf::PDFOptionalContentTreeItemModel* m_optionalContentTreeModel; + PDFBookmarkItemModel* m_bookmarkItemModel; const pdf::PDFDocument* m_document; pdf::PDFOptionalContentActivity* m_optionalContentActivity; pdf::PDFAttachmentsTreeItemModel* m_attachmentsTreeModel; diff --git a/Pdf4QtViewer/pdfsidebarwidget.ui b/Pdf4QtViewer/pdfsidebarwidget.ui index f6f6d9f..04ea4ef 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.ui +++ b/Pdf4QtViewer/pdfsidebarwidget.ui @@ -6,8 +6,8 @@ 0 0 - 339 - 584 + 388 + 681 @@ -225,6 +225,35 @@ + + + + + 96 + 0 + + + + Bookmarks + + + + :/resources/sidebar-favourites.svg:/resources/sidebar-favourites.svg + + + + 64 + 64 + + + + true + + + Qt::ToolButtonTextUnderIcon + + + @@ -243,7 +272,7 @@ - 1 + 5 @@ -383,6 +412,32 @@ + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QAbstractItemView::NoEditTriggers + + + true + + + + + diff --git a/Pdf4QtViewer/pdfviewermainwindow.cpp b/Pdf4QtViewer/pdfviewermainwindow.cpp index 3d8f231..50dd398 100644 --- a/Pdf4QtViewer/pdfviewermainwindow.cpp +++ b/Pdf4QtViewer/pdfviewermainwindow.cpp @@ -269,7 +269,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) : setCentralWidget(m_programController->getPdfWidget()); setFocusProxy(m_programController->getPdfWidget()); - m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getSettings(), true, this); + m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getBookmarkManager(), m_programController->getSettings(), true, this); m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this); m_sidebarDockWidget->setObjectName("SidebarDockWidget"); m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); diff --git a/Pdf4QtViewer/pdfviewermainwindowlite.cpp b/Pdf4QtViewer/pdfviewermainwindowlite.cpp index 28b6073..ed2713c 100644 --- a/Pdf4QtViewer/pdfviewermainwindowlite.cpp +++ b/Pdf4QtViewer/pdfviewermainwindowlite.cpp @@ -202,7 +202,7 @@ PDFViewerMainWindowLite::PDFViewerMainWindowLite(QWidget* parent) : setCentralWidget(m_programController->getPdfWidget()); setFocusProxy(m_programController->getPdfWidget()); - m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getSettings(), false, this); + m_sidebarWidget = new PDFSidebarWidget(m_programController->getPdfWidget()->getDrawWidgetProxy(), m_programController->getTextToSpeech(), m_programController->getCertificateStore(), m_programController->getBookmarkManager(), m_programController->getSettings(), false, this); m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this); m_sidebarDockWidget->setObjectName("SidebarDockWidget"); m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); diff --git a/Pdf4QtViewer/resources/sidebar-favourites.svg b/Pdf4QtViewer/resources/sidebar-favourites.svg new file mode 100644 index 0000000..f9804e2 --- /dev/null +++ b/Pdf4QtViewer/resources/sidebar-favourites.svg @@ -0,0 +1,58 @@ + + + + + + + + image/svg+xml + + + + + + + + + From e9ca3a4a821978ecc8c1d38a8b9a4e187cdcd868 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sun, 17 Dec 2023 18:11:49 +0100 Subject: [PATCH 3/5] Issue #54: Finishing of bookmarking --- Pdf4QtViewer/pdf4qtviewer.qrc | 3 + Pdf4QtViewer/pdfbookmarkmanager.cpp | 159 +++++++++++++----- Pdf4QtViewer/pdfbookmarkmanager.h | 15 +- Pdf4QtViewer/pdfbookmarkui.cpp | 39 ++++- Pdf4QtViewer/pdfprogramcontroller.cpp | 101 +++++++++++ Pdf4QtViewer/pdfprogramcontroller.h | 14 ++ Pdf4QtViewer/pdfsidebarwidget.cpp | 43 +++++ Pdf4QtViewer/pdfsidebarwidget.h | 4 + Pdf4QtViewer/pdfviewermainwindow.cpp | 6 + Pdf4QtViewer/pdfviewermainwindow.ui | 106 ++++++++++++ Pdf4QtViewer/pdfviewermainwindowlite.cpp | 6 + Pdf4QtViewer/pdfviewermainwindowlite.ui | 108 ++++++++++++ Pdf4QtViewer/pdfviewersettings.cpp | 11 +- Pdf4QtViewer/pdfviewersettings.h | 3 + Pdf4QtViewer/resources/bookmark-next.svg | 75 +++++++++ Pdf4QtViewer/resources/bookmark-previous.svg | 75 +++++++++ Pdf4QtViewer/resources/bookmark.svg | 70 ++++++++ Pdf4QtViewer/resources/sidebar-favourites.svg | 26 ++- 18 files changed, 808 insertions(+), 56 deletions(-) create mode 100644 Pdf4QtViewer/resources/bookmark-next.svg create mode 100644 Pdf4QtViewer/resources/bookmark-previous.svg create mode 100644 Pdf4QtViewer/resources/bookmark.svg diff --git a/Pdf4QtViewer/pdf4qtviewer.qrc b/Pdf4QtViewer/pdf4qtviewer.qrc index b9d80e6..37379d8 100644 --- a/Pdf4QtViewer/pdf4qtviewer.qrc +++ b/Pdf4QtViewer/pdf4qtviewer.qrc @@ -105,5 +105,8 @@ resources/sidebar-visibility.svg resources/outline.svg resources/sidebar-favourites.svg + resources/bookmark.svg + resources/bookmark-next.svg + resources/bookmark-previous.svg diff --git a/Pdf4QtViewer/pdfbookmarkmanager.cpp b/Pdf4QtViewer/pdfbookmarkmanager.cpp index 8ae9a39..b78c3f2 100644 --- a/Pdf4QtViewer/pdfbookmarkmanager.cpp +++ b/Pdf4QtViewer/pdfbookmarkmanager.cpp @@ -110,46 +110,23 @@ void PDFBookmarkManager::setDocument(const pdf::PDFModifiedDocument& document) { Q_EMIT bookmarksAboutToBeChanged(); - const bool init = !m_document; m_document = document.getDocument(); - QString key; - - if (document.hasPreserveView() && m_document) + if (document.hasReset()) { - // Pass the key - key = QString::fromLatin1(m_document->getSourceDataHash().toHex()); - - if (m_bookmarks.count(m_currentKey) && m_currentKey != key) + if (!document.hasPreserveView()) { - m_bookmarks[key] = m_bookmarks[m_currentKey]; - m_bookmarks.erase(m_currentKey); + m_bookmarks.bookmarks.clear(); + regenerateAutoBookmarks(); } } - if (init && m_document) - { - key = QString::fromLatin1(m_document->getSourceDataHash().toHex()); - } - - if (key.isEmpty()) - { - key = "generic"; - } - - m_currentKey = key; - - if (document.hasReset() && !document.hasPreserveView()) - { - regenerateAutoBookmarks(); - } - Q_EMIT bookmarksChanged(); } void PDFBookmarkManager::saveToFile(QString fileName) { - QJsonDocument doc = PDFBookmarkManagerHelper::convertBookmarksMapToJsonDocument(m_bookmarks); + QJsonDocument doc(PDFBookmarkManagerHelper::convertBookmarksToJson(m_bookmarks)); // Příklad zápisu do souboru QFile file(fileName); @@ -168,31 +145,130 @@ bool PDFBookmarkManager::loadFromFile(QString fileName) QJsonDocument loadedDoc = QJsonDocument::fromJson(file.readAll()); file.close(); - m_bookmarks = PDFBookmarkManagerHelper::convertBookmarksMapFromJsonDocument(loadedDoc); + Q_EMIT bookmarksAboutToBeChanged(); + m_bookmarks = PDFBookmarkManagerHelper::convertBookmarksFromJson(loadedDoc.object()); + Q_EMIT bookmarksChanged(); return true; } return false; } +bool PDFBookmarkManager::isEmpty() const +{ + return m_bookmarks.bookmarks.empty(); +} + int PDFBookmarkManager::getBookmarkCount() const { - if (m_bookmarks.count(m_currentKey)) - { - return m_bookmarks.at(m_currentKey).bookmarks.size(); - } - - return 0; + return static_cast(m_bookmarks.bookmarks.size()); } PDFBookmarkManager::Bookmark PDFBookmarkManager::getBookmark(int index) const { - if (m_bookmarks.count(m_currentKey)) + return m_bookmarks.bookmarks.at(index); +} + +void PDFBookmarkManager::toggleBookmark(pdf::PDFInteger pageIndex) +{ + Q_EMIT bookmarksAboutToBeChanged(); + + auto it = std::find_if(m_bookmarks.bookmarks.begin(), m_bookmarks.bookmarks.end(), [pageIndex](const auto& bookmark) { return bookmark.pageIndex == pageIndex; }); + if (it != m_bookmarks.bookmarks.cend()) { - return m_bookmarks.at(m_currentKey).bookmarks.at(index); + Bookmark& bookmark = *it; + if (bookmark.isAuto) + { + bookmark.isAuto = false; + } + else + { + m_bookmarks.bookmarks.erase(it); + } + } + else + { + Bookmark bookmark; + bookmark.isAuto = false; + bookmark.name = tr("User bookmark for page %1").arg(pageIndex + 1); + bookmark.pageIndex = pageIndex; + m_bookmarks.bookmarks.push_back(bookmark); + sortBookmarks(); } - return Bookmark(); + Q_EMIT bookmarksChanged(); +} + +void PDFBookmarkManager::setGenerateBookmarksAutomatically(bool generateBookmarksAutomatically) +{ + if (m_generateBookmarksAutomatically != generateBookmarksAutomatically) + { + Q_EMIT bookmarksAboutToBeChanged(); + m_generateBookmarksAutomatically = generateBookmarksAutomatically; + regenerateAutoBookmarks(); + Q_EMIT bookmarksChanged(); + } +} + +void PDFBookmarkManager::goToNextBookmark() +{ + if (isEmpty()) + { + return; + } + + m_currentBookmark = (m_currentBookmark + 1) % getBookmarkCount(); + goToCurrentBookmark(); +} + +void PDFBookmarkManager::goToPreviousBookmark() +{ + if (isEmpty()) + { + return; + } + + if (m_currentBookmark <= 0) + { + m_currentBookmark = getBookmarkCount() - 1; + } + else + { + --m_currentBookmark; + } + + goToCurrentBookmark(); +} + +void PDFBookmarkManager::goToCurrentBookmark() +{ + if (isEmpty()) + { + return; + } + + if (m_currentBookmark >= 0 && m_currentBookmark < getBookmarkCount()) + { + Q_EMIT bookmarkActivated(m_currentBookmark, m_bookmarks.bookmarks.at(m_currentBookmark)); + } +} + +void PDFBookmarkManager::goToBookmark(int index, bool force) +{ + if (m_currentBookmark != index || force) + { + m_currentBookmark = index; + goToCurrentBookmark(); + } +} + +void PDFBookmarkManager::sortBookmarks() +{ + auto predicate = [](const auto& l, const auto& r) + { + return l.pageIndex < r.pageIndex; + }; + std::sort(m_bookmarks.bookmarks.begin(), m_bookmarks.bookmarks.end(), predicate); } void PDFBookmarkManager::regenerateAutoBookmarks() @@ -203,7 +279,7 @@ void PDFBookmarkManager::regenerateAutoBookmarks() } // Create bookmarks for all main chapters - Bookmarks& bookmarks = m_bookmarks[m_currentKey]; + Bookmarks& bookmarks = m_bookmarks; for (auto it = bookmarks.bookmarks.begin(); it != bookmarks.bookmarks.end();) { @@ -217,6 +293,11 @@ void PDFBookmarkManager::regenerateAutoBookmarks() } } + if (!m_generateBookmarksAutomatically) + { + return; + } + if (auto outlineRoot = m_document->getCatalog()->getOutlineRootPtr()) { size_t childCount = outlineRoot->getChildCount(); diff --git a/Pdf4QtViewer/pdfbookmarkmanager.h b/Pdf4QtViewer/pdfbookmarkmanager.h index fd68760..ac7fc99 100644 --- a/Pdf4QtViewer/pdfbookmarkmanager.h +++ b/Pdf4QtViewer/pdfbookmarkmanager.h @@ -47,16 +47,26 @@ public: pdf::PDFInteger pageIndex = -1; }; + bool isEmpty() const; int getBookmarkCount() const; Bookmark getBookmark(int index) const; + void toggleBookmark(pdf::PDFInteger pageIndex); + void setGenerateBookmarksAutomatically(bool generateBookmarksAutomatically); + + void goToNextBookmark(); + void goToPreviousBookmark(); + void goToCurrentBookmark(); + void goToBookmark(int index, bool force); signals: void bookmarksAboutToBeChanged(); void bookmarksChanged(); + void bookmarkActivated(int index, Bookmark bookmark); private: friend class PDFBookmarkManagerHelper; + void sortBookmarks(); void regenerateAutoBookmarks(); struct Bookmarks @@ -65,8 +75,9 @@ private: }; pdf::PDFDocument* m_document; - QString m_currentKey; - std::map m_bookmarks; + Bookmarks m_bookmarks; + int m_currentBookmark = -1; + bool m_generateBookmarksAutomatically = true; }; } // namespace pdf diff --git a/Pdf4QtViewer/pdfbookmarkui.cpp b/Pdf4QtViewer/pdfbookmarkui.cpp index e53d278..48d52a0 100644 --- a/Pdf4QtViewer/pdfbookmarkui.cpp +++ b/Pdf4QtViewer/pdfbookmarkui.cpp @@ -17,6 +17,7 @@ #include "pdfbookmarkui.h" #include "pdfwidgetutils.h" +#include "pdfpainterutils.h" #include #include @@ -34,11 +35,17 @@ PDFBookmarkItemModel::PDFBookmarkItemModel(PDFBookmarkManager* bookmarkManager, QModelIndex PDFBookmarkItemModel::index(int row, int column, const QModelIndex& parent) const { + if (parent.isValid()) + { + return QModelIndex(); + } + return createIndex(row, column, nullptr); } QModelIndex PDFBookmarkItemModel::parent(const QModelIndex& child) const { + Q_UNUSED(child); return QModelIndex(); } @@ -54,6 +61,11 @@ int PDFBookmarkItemModel::rowCount(const QModelIndex& parent) const int PDFBookmarkItemModel::columnCount(const QModelIndex& parent) const { + if (parent.isValid()) + { + return 0; + } + return 1; } @@ -92,14 +104,22 @@ void PDFBookmarkItemDelegate::paint(QPainter* painter, QRect rect = options.rect; rect.marginsRemoved(QMargins(margin, margin, margin, margin)); + QColor color = bookmark.isAuto ? QColor(0, 123, 255) : QColor(255, 159, 0); + + if (options.state.testFlag(QStyle::State_Selected)) + { + color = Qt::yellow; + } + QRect iconRect = rect; iconRect.setWidth(iconSize); iconRect.setHeight(iconSize); iconRect.moveCenter(QPoint(rect.left() + iconSize / 2, rect.center().y())); - drawStar(*painter, iconRect.center(), iconRect.width() * 0.5, QColor(64, 64, 192)); + drawStar(*painter, iconRect.center(), iconRect.width() * 0.5, color); QRect textRect = rect; textRect.setLeft(iconRect.right() + margin); + textRect.moveTop(rect.top() + (rect.height() - 2 * options.fontMetrics.lineSpacing()) / 2); textRect.setHeight(options.fontMetrics.lineSpacing()); @@ -135,18 +155,19 @@ QSize PDFBookmarkItemDelegate::sizeHint(const QStyleOptionViewItem& option, cons void PDFBookmarkItemDelegate::drawStar(QPainter& painter, const QPointF& center, double size, const QColor& color) const { - painter.save(); + pdf::PDFPainterStateGuard guard(&painter); painter.setPen(Qt::NoPen); painter.setBrush(color); QPainterPath path; double angle = M_PI / 5; + double phase = -M_PI / 10; for (int i = 0; i < 10; ++i) { double radius = (i % 2 == 0) ? size : size / 2.5; - QPointF point(radius * cos(i * angle), radius * sin(i * angle)); + QPointF point(radius * cos(i * angle + phase), radius * sin(i * angle + phase)); point += center; if (i == 0) @@ -159,15 +180,19 @@ void PDFBookmarkItemDelegate::drawStar(QPainter& painter, const QPointF& center, } } path.closeSubpath(); - painter.drawPath(path); - - painter.restore(); } QString PDFBookmarkItemDelegate::getPageText(const PDFBookmarkManager::Bookmark& bookmark) const { - return tr("Page %1").arg(bookmark.pageIndex + 1); + if (bookmark.isAuto) + { + return tr("Page %1 | Generated").arg(bookmark.pageIndex + 1); + } + else + { + return tr("Page %1").arg(bookmark.pageIndex + 1); + } } } // namespace pdfviewer diff --git a/Pdf4QtViewer/pdfprogramcontroller.cpp b/Pdf4QtViewer/pdfprogramcontroller.cpp index 8110c3b..b2bf992 100644 --- a/Pdf4QtViewer/pdfprogramcontroller.cpp +++ b/Pdf4QtViewer/pdfprogramcontroller.cpp @@ -210,6 +210,9 @@ void PDFActionManager::initActions(QSize iconSize, bool initializeStampActions) setShortcut(GoToPreviousPage, QKeySequence::MoveToPreviousPage); setShortcut(GoToNextLine, QKeySequence::MoveToNextLine); setShortcut(GoToPreviousLine, QKeySequence::MoveToPreviousLine); + setShortcut(BookmarkPage, QKeySequence("Ctrl+M")); + setShortcut(BookmarkGoToNext, QKeySequence("Ctrl+.")); + setShortcut(BookmarkGoToPrevious, QKeySequence("Ctrl+,")); if (hasActions({ CreateStickyNoteComment, CreateStickyNoteHelp, CreateStickyNoteInsert, CreateStickyNoteKey, CreateStickyNoteNewParagraph, CreateStickyNoteNote, CreateStickyNoteParagraph })) { @@ -403,6 +406,8 @@ void PDFProgramController::initializeFormManager() void PDFProgramController::initializeBookmarkManager() { m_bookmarkManager = new PDFBookmarkManager(this); + connect(m_bookmarkManager, &PDFBookmarkManager::bookmarkActivated, this, &PDFProgramController::onBookmarkActivated); + updateBookmarkSettings(); } void PDFProgramController::initialize(Features features, @@ -581,6 +586,30 @@ void PDFProgramController::initialize(Features features, { connect(action, &QAction::triggered, this, &PDFProgramController::onActionAutomaticDocumentRefresh); } + if (QAction* action = m_actionManager->getAction(PDFActionManager::BookmarkPage)) + { + connect(action, &QAction::triggered, this, &PDFProgramController::onActionBookmarkPage); + } + if (QAction* action = m_actionManager->getAction(PDFActionManager::BookmarkGoToNext)) + { + connect(action, &QAction::triggered, this, &PDFProgramController::onActionBookmarkGoToNext); + } + if (QAction* action = m_actionManager->getAction(PDFActionManager::BookmarkGoToPrevious)) + { + connect(action, &QAction::triggered, this, &PDFProgramController::onActionBookmarkGoToPrevious); + } + if (QAction* action = m_actionManager->getAction(PDFActionManager::BookmarkExport)) + { + connect(action, &QAction::triggered, this, &PDFProgramController::onActionBookmarkExport); + } + if (QAction* action = m_actionManager->getAction(PDFActionManager::BookmarkImport)) + { + connect(action, &QAction::triggered, this, &PDFProgramController::onActionBookmarkImport); + } + if (QAction* action = m_actionManager->getAction(PDFActionManager::BookmarkGenerateAutomatically)) + { + connect(action, &QAction::triggered, this, &PDFProgramController::onActionBookmarkGenerateAutomatically); + } if (m_recentFileManager) { @@ -1559,6 +1588,8 @@ void PDFProgramController::readSettings(Settings settingsFlags) { m_formManager->setAppearanceFlags(m_settings->getSettings().m_formAppearanceFlags); } + + updateBookmarkSettings(); } if (settingsFlags.testFlag(PluginsSettings)) @@ -1712,6 +1743,13 @@ void PDFProgramController::onFileChanged(const QString& fileName) } } +void PDFProgramController::onBookmarkActivated(int index, PDFBookmarkManager::Bookmark bookmark) +{ + Q_UNUSED(index); + + m_pdfWidget->getDrawWidgetProxy()->goToPage(bookmark.pageIndex); +} + void PDFProgramController::updateFileInfo(const QString& fileName) { QFileInfo fileInfo(fileName); @@ -1996,6 +2034,22 @@ void PDFProgramController::updateRenderingOptionActions() } } +void PDFProgramController::updateBookmarkSettings() +{ + const bool enable = m_settings->getSettings().m_autoGenerateBookmarks; + + if (m_bookmarkManager) + { + m_bookmarkManager->setGenerateBookmarksAutomatically(enable); + } + + QAction* action = m_actionManager->getAction(PDFActionManager::BookmarkGenerateAutomatically); + if (action) + { + action->setChecked(enable); + } +} + void PDFProgramController::updateTitle() { if (m_pdfDocument) @@ -2550,6 +2604,53 @@ void PDFProgramController::onActionAutomaticDocumentRefresh() updateFileWatcher(); } +void PDFProgramController::onActionBookmarkPage() +{ + std::vector currentPages = m_pdfWidget->getDrawWidget()->getCurrentPages(); + if (!currentPages.empty()) + { + m_bookmarkManager->toggleBookmark(currentPages.front()); + } +} + +void PDFProgramController::onActionBookmarkGoToNext() +{ + m_bookmarkManager->goToNextBookmark(); +} + +void PDFProgramController::onActionBookmarkGoToPrevious() +{ + m_bookmarkManager->goToPreviousBookmark(); +} + +void PDFProgramController::onActionBookmarkExport() +{ + QFileInfo fileInfo(m_fileInfo.originalFileName); + QString saveFileName = QFileDialog::getSaveFileName(m_mainWindow, tr("Export Bookmarks As"), fileInfo.dir().absoluteFilePath(m_fileInfo.originalFileName).replace(".pdf", ".json"), tr("JSON (*.json);;All files (*.*)")); + if (!saveFileName.isEmpty()) + { + m_bookmarkManager->saveToFile(saveFileName); + } +} + +void PDFProgramController::onActionBookmarkImport() +{ + QFileInfo fileInfo(m_fileInfo.originalFileName); + QString fileName = QFileDialog::getOpenFileName(m_mainWindow, tr("Select PDF document"), fileInfo.dir().absolutePath(), tr("JSON (*.json)")); + if (!fileName.isEmpty()) + { + m_bookmarkManager->loadFromFile(fileName); + } +} + +void PDFProgramController::onActionBookmarkGenerateAutomatically(bool checked) +{ + auto settings = m_settings->getSettings(); + settings.m_autoGenerateBookmarks = checked; + m_settings->setSettings(settings); + m_bookmarkManager->setGenerateBookmarksAutomatically(checked); +} + void PDFProgramController::onPageRenderingErrorsChanged(pdf::PDFInteger pageIndex, int errorsCount) { if (errorsCount > 0) diff --git a/Pdf4QtViewer/pdfprogramcontroller.h b/Pdf4QtViewer/pdfprogramcontroller.h index 8be65c2..76507c5 100644 --- a/Pdf4QtViewer/pdfprogramcontroller.h +++ b/Pdf4QtViewer/pdfprogramcontroller.h @@ -178,6 +178,12 @@ public: ToolScreenshot, ToolExtractImage, DeveloperCreateInstaller, + BookmarkPage, + BookmarkGoToNext, + BookmarkGoToPrevious, + BookmarkExport, + BookmarkImport, + BookmarkGenerateAutomatically, LastAction }; @@ -367,6 +373,12 @@ private: void onActionGetSource(); void onActionBecomeSponsor(); void onActionAutomaticDocumentRefresh(); + void onActionBookmarkPage(); + void onActionBookmarkGoToNext(); + void onActionBookmarkGoToPrevious(); + void onActionBookmarkExport(); + void onActionBookmarkImport(); + void onActionBookmarkGenerateAutomatically(bool checked); void onDrawSpaceChanged(); void onPageLayoutChanged(); @@ -377,6 +389,7 @@ private: void onViewerSettingsChanged(); void onColorManagementSystemChanged(); void onFileChanged(const QString& fileName); + void onBookmarkActivated(int index, PDFBookmarkManager::Bookmark bookmark); void updateMagnifierToolSettings(); void updateUndoRedoSettings(); @@ -384,6 +397,7 @@ private: void updateTitle(); void updatePageLayoutActions(); void updateRenderingOptionActions(); + void updateBookmarkSettings(); void setPageLayout(pdf::PageLayout pageLayout); void updateFileInfo(const QString& fileName); diff --git a/Pdf4QtViewer/pdfsidebarwidget.cpp b/Pdf4QtViewer/pdfsidebarwidget.cpp index 9fce464..45eb3aa 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.cpp +++ b/Pdf4QtViewer/pdfsidebarwidget.cpp @@ -134,6 +134,9 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, m_bookmarkItemModel = new PDFBookmarkItemModel(bookmarkManager, this); ui->bookmarksView->setModel(m_bookmarkItemModel); ui->bookmarksView->setItemDelegate(new PDFBookmarkItemDelegate(bookmarkManager, this)); + connect(m_bookmarkManager, &PDFBookmarkManager::bookmarkActivated, this, &PDFSidebarWidget::onBookmarkActivated); + connect(ui->bookmarksView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PDFSidebarWidget::onBookmarsCurrentIndexChanged); + connect(ui->bookmarksView, &QListView::clicked, this, &PDFSidebarWidget::onBookmarkClicked); m_pageInfo[Invalid] = { nullptr, ui->emptyPage }; m_pageInfo[OptionalContent] = { ui->optionalContentButton, ui->optionalContentPage }; @@ -956,6 +959,46 @@ void PDFSidebarWidget::onOutlineItemsChanged() } } +void PDFSidebarWidget::onBookmarkActivated(int index, PDFBookmarkManager::Bookmark bookmark) +{ + if (m_bookmarkChangeInProgress) + { + return; + } + + pdf::PDFTemporaryValueChange guard(&m_bookmarkChangeInProgress, true); + QModelIndex currentIndex = m_bookmarkItemModel->index(index, 0, QModelIndex()); + ui->bookmarksView->selectionModel()->select(currentIndex, QItemSelectionModel::SelectCurrent); + ui->bookmarksView->setCurrentIndex(currentIndex); +} + +void PDFSidebarWidget::onBookmarsCurrentIndexChanged(const QModelIndex& current, const QModelIndex& previous) +{ + Q_UNUSED(previous); + + if (m_bookmarkChangeInProgress) + { + return; + } + + pdf::PDFTemporaryValueChange guard(&m_bookmarkChangeInProgress, true); + m_bookmarkManager->goToBookmark(current.row(), false); +} + +void PDFSidebarWidget::onBookmarkClicked(const QModelIndex& index) +{ + if (m_bookmarkChangeInProgress) + { + return; + } + + if (index == ui->bookmarksView->currentIndex()) + { + pdf::PDFTemporaryValueChange guard(&m_bookmarkChangeInProgress, true); + m_bookmarkManager->goToCurrentBookmark(); + } +} + void PDFSidebarWidget::paintEvent(QPaintEvent* event) { Q_UNUSED(event); diff --git a/Pdf4QtViewer/pdfsidebarwidget.h b/Pdf4QtViewer/pdfsidebarwidget.h index f7ee57b..069ab5e 100644 --- a/Pdf4QtViewer/pdfsidebarwidget.h +++ b/Pdf4QtViewer/pdfsidebarwidget.h @@ -119,6 +119,9 @@ private: void onSignatureCustomContextMenuRequested(const QPoint &pos); void onOutlineTreeViewContextMenuRequested(const QPoint &pos); void onOutlineItemsChanged(); + void onBookmarkActivated(int index, PDFBookmarkManager::Bookmark bookmark); + void onBookmarsCurrentIndexChanged(const QModelIndex& current, const QModelIndex& previous); + void onBookmarkClicked(const QModelIndex& index); struct PageInfo { @@ -142,6 +145,7 @@ private: std::map m_pageInfo; std::vector m_signatures; std::vector m_certificateInfos; + bool m_bookmarkChangeInProgress = false; }; } // namespace pdfviewer diff --git a/Pdf4QtViewer/pdfviewermainwindow.cpp b/Pdf4QtViewer/pdfviewermainwindow.cpp index 50dd398..156c65e 100644 --- a/Pdf4QtViewer/pdfviewermainwindow.cpp +++ b/Pdf4QtViewer/pdfviewermainwindow.cpp @@ -194,6 +194,12 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) : m_actionManager->setAction(PDFActionManager::ToolScreenshot, ui->actionScreenshot); m_actionManager->setAction(PDFActionManager::ToolExtractImage, ui->actionExtractImage); m_actionManager->setAction(PDFActionManager::DeveloperCreateInstaller, ui->actionDeveloperCreateInstaller); + m_actionManager->setAction(PDFActionManager::BookmarkPage, ui->actionBookmarkPage); + m_actionManager->setAction(PDFActionManager::BookmarkGoToNext, ui->actionGotoNextBookmark); + m_actionManager->setAction(PDFActionManager::BookmarkGoToPrevious, ui->actionGotoPreviousBookmark); + m_actionManager->setAction(PDFActionManager::BookmarkExport, ui->actionBookmarkExport); + m_actionManager->setAction(PDFActionManager::BookmarkImport, ui->actionBookmarkImport); + m_actionManager->setAction(PDFActionManager::BookmarkGenerateAutomatically, ui->actionBookmarkAutoGenerate); m_actionManager->initActions(pdf::PDFWidgetUtils::scaleDPI(this, QSize(24, 24)), true); for (QAction* action : m_programController->getRecentFileManager()->getActions()) diff --git a/Pdf4QtViewer/pdfviewermainwindow.ui b/Pdf4QtViewer/pdfviewermainwindow.ui index ba41469..ba7a134 100644 --- a/Pdf4QtViewer/pdfviewermainwindow.ui +++ b/Pdf4QtViewer/pdfviewermainwindow.ui @@ -46,12 +46,25 @@ Go To + + + Bookmark Settings + + + + + + + + + + @@ -1051,6 +1064,99 @@ Convert the colored images to monochromatic to create a bitonal document. + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Bookmark Page + + + Bookmark Page + + + Bookmark page for fast navigation. + + + + + + :/resources/bookmark-next.svg:/resources/bookmark-next.svg + + + Go to Next Bookmark + + + Go to Next Bookmark + + + Navigates to the next bookmarked page. + + + + + + :/resources/bookmark-previous.svg:/resources/bookmark-previous.svg + + + Go to Previous Bookmark + + + Go to Previous Bookmark + + + Navigates to the previous bookmarked page. + + + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Export Bookmarks + + + Export Bookmarks + + + Export bookmarks to the file. + + + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Import Bookmarks + + + Import Bookmarks + + + Import bookmarks from the file. + + + + + true + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Generate Bookmarks Automatically + + + Generate Bookmarks Automatically + + + If checked, bookmarks for main document chapters are generated automatically. + + diff --git a/Pdf4QtViewer/pdfviewermainwindowlite.cpp b/Pdf4QtViewer/pdfviewermainwindowlite.cpp index ed2713c..5528af5 100644 --- a/Pdf4QtViewer/pdfviewermainwindowlite.cpp +++ b/Pdf4QtViewer/pdfviewermainwindowlite.cpp @@ -151,6 +151,12 @@ PDFViewerMainWindowLite::PDFViewerMainWindowLite(QWidget* parent) : m_actionManager->setAction(PDFActionManager::PageLayoutTwoPages, ui->actionPageLayoutTwoPages); m_actionManager->setAction(PDFActionManager::PageLayoutTwoColumns, ui->actionPageLayoutTwoColumns); m_actionManager->setAction(PDFActionManager::PageLayoutFirstPageOnRightSide, ui->actionFirstPageOnRightSide); + m_actionManager->setAction(PDFActionManager::BookmarkPage, ui->actionBookmarkPage); + m_actionManager->setAction(PDFActionManager::BookmarkGoToNext, ui->actionGotoNextBookmark); + m_actionManager->setAction(PDFActionManager::BookmarkGoToPrevious, ui->actionGotoPreviousBookmark); + m_actionManager->setAction(PDFActionManager::BookmarkExport, ui->actionBookmarkExport); + m_actionManager->setAction(PDFActionManager::BookmarkImport, ui->actionBookmarkImport); + m_actionManager->setAction(PDFActionManager::BookmarkGenerateAutomatically, ui->actionBookmarkAutoGenerate); m_actionManager->initActions(pdf::PDFWidgetUtils::scaleDPI(this, QSize(24, 24)), true); for (QAction* action : m_programController->getRecentFileManager()->getActions()) diff --git a/Pdf4QtViewer/pdfviewermainwindowlite.ui b/Pdf4QtViewer/pdfviewermainwindowlite.ui index a5b8e7c..2142345 100644 --- a/Pdf4QtViewer/pdfviewermainwindowlite.ui +++ b/Pdf4QtViewer/pdfviewermainwindowlite.ui @@ -42,12 +42,26 @@ Go To + + + Bookmark Settings + + + + + + + + + + + @@ -543,6 +557,100 @@ Become a Sponsor + + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Bookmark Page + + + Bookmark Page + + + Bookmark page for fast navigation. + + + + + + :/resources/bookmark-next.svg:/resources/bookmark-next.svg + + + Go to Next Bookmark + + + Go to Next Bookmark + + + Navigates to the next bookmarked page. + + + + + + :/resources/bookmark-previous.svg:/resources/bookmark-previous.svg + + + Go to Previous Bookmark + + + Go to Previous Bookmark + + + Navigates to the previous bookmarked page. + + + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Export Bookmarks + + + Export Bookmarks + + + Export bookmarks to the file. + + + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Import Bookmarks + + + Import Bookmarks + + + Import bookmarks from the file. + + + + + true + + + + :/resources/bookmark.svg:/resources/bookmark.svg + + + Generate Bookmarks Automatically + + + Generate Bookmarks Automatically + + + If checked, bookmarks for main document chapters are generated automatically. + + diff --git a/Pdf4QtViewer/pdfviewersettings.cpp b/Pdf4QtViewer/pdfviewersettings.cpp index 329c97c..02ce814 100644 --- a/Pdf4QtViewer/pdfviewersettings.cpp +++ b/Pdf4QtViewer/pdfviewersettings.cpp @@ -104,6 +104,10 @@ void PDFViewerSettings::readSettings(QSettings& settings, const pdf::PDFCMSSetti m_settings.m_signatureUseSystemStore = settings.value("signatureUseSystemStore", defaultSettings.m_signatureUseSystemStore).toBool(); settings.endGroup(); + settings.beginGroup("Bookmarks"); + m_settings.m_autoGenerateBookmarks = settings.value("autoGenerateBookmarks", defaultSettings.m_autoGenerateBookmarks).toBool(); + settings.endGroup(); + Q_EMIT settingsChanged(); } @@ -174,6 +178,10 @@ void PDFViewerSettings::writeSettings(QSettings& settings) settings.setValue("signatureIgnoreCertificateValidityTime", m_settings.m_signatureIgnoreCertificateValidityTime); settings.setValue("signatureUseSystemStore", m_settings.m_signatureUseSystemStore); settings.endGroup(); + + settings.beginGroup("Bookmarks"); + settings.setValue("autoGenerateBookmarks", m_settings.m_autoGenerateBookmarks); + settings.endGroup(); } QString PDFViewerSettings::getDirectory() const @@ -287,7 +295,8 @@ PDFViewerSettings::Settings::Settings() : m_signatureVerificationEnabled(true), m_signatureTreatWarningsAsErrors(false), m_signatureIgnoreCertificateValidityTime(false), - m_signatureUseSystemStore(true) + m_signatureUseSystemStore(true), + m_autoGenerateBookmarks(true) { } diff --git a/Pdf4QtViewer/pdfviewersettings.h b/Pdf4QtViewer/pdfviewersettings.h index eb6f90d..90e2769 100644 --- a/Pdf4QtViewer/pdfviewersettings.h +++ b/Pdf4QtViewer/pdfviewersettings.h @@ -91,6 +91,9 @@ public: bool m_signatureTreatWarningsAsErrors; bool m_signatureIgnoreCertificateValidityTime; bool m_signatureUseSystemStore; + + // Bookmarks settings + bool m_autoGenerateBookmarks; }; const Settings& getSettings() const { return m_settings; } diff --git a/Pdf4QtViewer/resources/bookmark-next.svg b/Pdf4QtViewer/resources/bookmark-next.svg new file mode 100644 index 0000000..4f2b635 --- /dev/null +++ b/Pdf4QtViewer/resources/bookmark-next.svg @@ -0,0 +1,75 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/Pdf4QtViewer/resources/bookmark-previous.svg b/Pdf4QtViewer/resources/bookmark-previous.svg new file mode 100644 index 0000000..0a8b2b6 --- /dev/null +++ b/Pdf4QtViewer/resources/bookmark-previous.svg @@ -0,0 +1,75 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/Pdf4QtViewer/resources/bookmark.svg b/Pdf4QtViewer/resources/bookmark.svg new file mode 100644 index 0000000..6a0f488 --- /dev/null +++ b/Pdf4QtViewer/resources/bookmark.svg @@ -0,0 +1,70 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/Pdf4QtViewer/resources/sidebar-favourites.svg b/Pdf4QtViewer/resources/sidebar-favourites.svg index f9804e2..6a0f488 100644 --- a/Pdf4QtViewer/resources/sidebar-favourites.svg +++ b/Pdf4QtViewer/resources/sidebar-favourites.svg @@ -43,16 +43,28 @@ inkscape:window-height="2035" id="namedview817" showgrid="false" - inkscape:zoom="0.30348968" - inkscape:cx="-2950.1732" - inkscape:cy="277.06973" + inkscape:zoom="1.2139587" + inkscape:cx="535.31725" + inkscape:cy="132.65123" inkscape:window-x="-13" inkscape:window-y="-13" inkscape:window-maximized="1" inkscape:current-layer="svg815" /> + sodipodi:type="star" + style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:26.45669291;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" + id="path839" + sodipodi:sides="5" + sodipodi:cx="259.20364" + sodipodi:cy="269.65189" + sodipodi:r1="203.30641" + sodipodi:r2="101.65321" + sodipodi:arg1="-1.585122" + sodipodi:arg2="-0.95680346" + inkscape:flatsided="false" + inkscape:rounded="0" + inkscape:randomized="0" + d="m 256.29124,66.366336 61.47844,120.198874 133.87003,17.49813 -95.31804,95.61296 24.7264,132.72518 L 260.65984,371.29467 142.07158,435.82522 162.9856,302.44616 64.967615,209.60305 198.28142,188.27708 Z" + inkscape:transform-center-x="0.89998123" + inkscape:transform-center-y="-18.55611" /> From e87b14dc3af78b6a8891370b06422688d65b322e Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sun, 17 Dec 2023 18:14:25 +0100 Subject: [PATCH 4/5] Issue #54: Final bugfix --- Pdf4QtViewer/pdfprogramcontroller.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Pdf4QtViewer/pdfprogramcontroller.cpp b/Pdf4QtViewer/pdfprogramcontroller.cpp index b2bf992..63a881b 100644 --- a/Pdf4QtViewer/pdfprogramcontroller.cpp +++ b/Pdf4QtViewer/pdfprogramcontroller.cpp @@ -2625,6 +2625,11 @@ void PDFProgramController::onActionBookmarkGoToPrevious() void PDFProgramController::onActionBookmarkExport() { + if (!m_pdfDocument) + { + return; + } + QFileInfo fileInfo(m_fileInfo.originalFileName); QString saveFileName = QFileDialog::getSaveFileName(m_mainWindow, tr("Export Bookmarks As"), fileInfo.dir().absoluteFilePath(m_fileInfo.originalFileName).replace(".pdf", ".json"), tr("JSON (*.json);;All files (*.*)")); if (!saveFileName.isEmpty()) @@ -2635,6 +2640,11 @@ void PDFProgramController::onActionBookmarkExport() void PDFProgramController::onActionBookmarkImport() { + if (!m_pdfDocument) + { + return; + } + QFileInfo fileInfo(m_fileInfo.originalFileName); QString fileName = QFileDialog::getOpenFileName(m_mainWindow, tr("Select PDF document"), fileInfo.dir().absolutePath(), tr("JSON (*.json)")); if (!fileName.isEmpty()) From 1ed7a1235780697fe6ab49163c15e0258bd81c81 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sun, 17 Dec 2023 18:38:45 +0100 Subject: [PATCH 5/5] Issue #54: Linux compilation --- Pdf4QtViewer/pdfbookmarkmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pdf4QtViewer/pdfbookmarkmanager.cpp b/Pdf4QtViewer/pdfbookmarkmanager.cpp index b78c3f2..c3d97d4 100644 --- a/Pdf4QtViewer/pdfbookmarkmanager.cpp +++ b/Pdf4QtViewer/pdfbookmarkmanager.cpp @@ -35,7 +35,7 @@ public: QJsonObject json; json["isAuto"] = bookmark.isAuto; json["name"] = bookmark.name; - json["pageIndex"] = bookmark.pageIndex; + json["pageIndex"] = static_cast(bookmark.pageIndex); return json; } @@ -44,7 +44,7 @@ public: PDFBookmarkManager::Bookmark bookmark; bookmark.isAuto = json["isAuto"].toBool(); bookmark.name = json["name"].toString(); - bookmark.pageIndex = json["pageIndex"].toInt(); + bookmark.pageIndex = json["pageIndex"].toInteger(); return bookmark; }