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 @@
+
+
+
+