diff --git a/PdfForQtLib/PdfForQtLib.pro b/PdfForQtLib/PdfForQtLib.pro
index 5beb429..e22c314 100644
--- a/PdfForQtLib/PdfForQtLib.pro
+++ b/PdfForQtLib/PdfForQtLib.pro
@@ -36,6 +36,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
DESTDIR = $$OUT_PWD/..
SOURCES += \
+ sources/pdfitemmodels.cpp \
sources/pdfobject.cpp \
sources/pdfoptionalcontent.cpp \
sources/pdfparser.cpp \
@@ -61,6 +62,7 @@ SOURCES += \
sources/pdfimage.cpp
HEADERS += \
+ sources/pdfitemmodels.h \
sources/pdfobject.h \
sources/pdfoptionalcontent.h \
sources/pdfparser.h \
diff --git a/PdfForQtLib/sources/pdfitemmodels.cpp b/PdfForQtLib/sources/pdfitemmodels.cpp
new file mode 100644
index 0000000..513ec94
--- /dev/null
+++ b/PdfForQtLib/sources/pdfitemmodels.cpp
@@ -0,0 +1,275 @@
+// Copyright (C) 2019 Jakub Melka
+//
+// This file is part of PdfForQt.
+//
+// PdfForQt is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// PdfForQt is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDFForQt. If not, see .
+
+#include "pdfitemmodels.h"
+#include "pdfdocument.h"
+
+namespace pdf
+{
+
+PDFTreeItem::~PDFTreeItem()
+{
+ qDeleteAll(m_children);
+}
+
+PDFTreeItemModel::PDFTreeItemModel(QObject* parent) :
+ QAbstractItemModel(parent),
+ m_document(nullptr)
+{
+
+}
+
+void PDFTreeItemModel::setDocument(const PDFDocument* document)
+{
+ if (m_document != document)
+ {
+ m_document = document;
+ update();
+ }
+}
+
+bool PDFTreeItemModel::isEmpty() const
+{
+ return rowCount(QModelIndex()) == 0;
+}
+
+QModelIndex PDFTreeItemModel::index(int row, int column, const QModelIndex& parent) const
+{
+ if (hasIndex(row, column, parent))
+ {
+ const PDFTreeItem* parentItem = nullptr;
+
+ if (!parent.isValid())
+ {
+ parentItem = m_rootItem.get();
+ }
+ else
+ {
+ parentItem = static_cast(parent.internalPointer());
+ }
+
+ return createIndex(row, column, const_cast(parentItem->getChild(row)));
+ }
+
+ return QModelIndex();
+}
+
+QModelIndex PDFTreeItemModel::parent(const QModelIndex& child) const
+{
+ if (child.isValid())
+ {
+ const PDFTreeItem* childItem = static_cast(child.internalPointer());
+ const PDFTreeItem* parentItem = childItem->getParent();
+
+ if (parentItem != m_rootItem.get())
+ {
+ return createIndex(parentItem->getRow(), child.column(), const_cast(parentItem));
+ }
+ }
+
+ return QModelIndex();
+}
+
+int PDFTreeItemModel::rowCount(const QModelIndex& parent) const
+{
+ if (parent.isValid())
+ {
+ const PDFTreeItem* parentItem = static_cast(parent.internalPointer());
+ return parentItem->getChildCount();
+ }
+
+ return m_rootItem ? m_rootItem->getChildCount() : 0;
+}
+
+bool PDFTreeItemModel::hasChildren(const QModelIndex& parent) const
+{
+ return rowCount(parent) > 0;
+}
+
+Qt::ItemFlags PDFTreeItemModel::flags(const QModelIndex& index) const
+{
+ if (!index.isValid())
+ {
+ return Qt::NoItemFlags;
+ }
+
+ return QAbstractItemModel::flags(index);
+}
+
+
+int PDFOptionalContentTreeItemModel::columnCount(const QModelIndex& parent) const
+{
+ Q_UNUSED(parent);
+ return 1;
+}
+
+QVariant PDFOptionalContentTreeItemModel::data(const QModelIndex& index, int role) const
+{
+ if (!index.isValid())
+ {
+ return QVariant();
+ }
+
+ const PDFOptionalContentTreeItem* item = static_cast(index.internalPointer());
+ switch (role)
+ {
+ case Qt::DisplayRole:
+ return item->getText();
+
+ case Qt::CheckStateRole:
+ return Qt::Checked;
+
+ default:
+ break;
+ }
+
+ return QVariant();
+}
+
+void PDFOptionalContentTreeItemModel::update()
+{
+ beginResetModel();
+
+ PDFOptionalContentTreeItem* root = new PDFOptionalContentTreeItem(nullptr, PDFObjectReference(), QString(), false);
+ m_rootItem.reset(root);
+
+ if (m_document)
+ {
+ const PDFOptionalContentProperties* optionalContentProperties = m_document->getCatalog()->getOptionalContentProperties();
+ if (optionalContentProperties->isValid())
+ {
+ const PDFOptionalContentConfiguration& configuration = optionalContentProperties->getDefaultConfiguration();
+ const PDFObject& orderObject = m_document->getObject(configuration.getOrder());
+ const std::vector& ocgs = optionalContentProperties->getAllOptionalContentGroups();
+ const std::vector& locked = configuration.getLocked();
+
+ // We must detect cycles in the reference array
+ std::set lockedOptionalContentGroups(locked.cbegin(), locked.cend());
+ std::set optionalContentGroups(ocgs.cbegin(), ocgs.cend());
+ std::set processedReferences;
+
+ PDFDocumentDataLoaderDecorator loader(m_document);
+ std::function processObject = [&, this](const PDFObject& object) -> PDFOptionalContentTreeItem*
+ {
+ PDFObject dereferencedObject = object;
+ if (object.isReference())
+ {
+ PDFObjectReference reference = object.getReference();
+ if (optionalContentGroups.count(reference))
+ {
+ const PDFOptionalContentGroup& ocg = optionalContentProperties->getOptionalContentGroup(reference);
+ return new PDFOptionalContentTreeItem(nullptr, reference, ocg.getName(), lockedOptionalContentGroups.count(reference));
+ }
+ else if (!processedReferences.count(reference))
+ {
+ processedReferences.insert(reference);
+ dereferencedObject = m_document->getStorage().getObject(reference);
+ }
+ else
+ {
+ // Error - we have cyclic references
+ return nullptr;
+ }
+ }
+
+ if (dereferencedObject.isArray())
+ {
+ const PDFArray* array = dereferencedObject.getArray();
+ const size_t arraySize = array->getCount();
+
+ // We must have at least one item!
+ if (arraySize == 0)
+ {
+ return nullptr;
+ }
+
+ QString text;
+ size_t i = 0;
+
+ // Try to retrieve group name
+ const PDFObject& firstItem = m_document->getObject(array->getItem(0));
+ if (firstItem.isString())
+ {
+ text = loader.readTextString(firstItem, QString());
+ ++i;
+ }
+
+ std::unique_ptr parentItem(new PDFOptionalContentTreeItem(nullptr, PDFObjectReference(), text, false));
+ for (; i < arraySize; ++i)
+ {
+ if (PDFOptionalContentTreeItem* item = processObject(array->getItem(i)))
+ {
+ parentItem->addCreatedChild(item);
+ }
+ else
+ {
+ // Item cannot be parsed properly
+ return nullptr;
+ }
+ }
+
+ return parentItem.release();
+ }
+
+ return nullptr;
+ };
+
+ m_rootItem.reset(processObject(orderObject));
+ }
+ }
+
+ endResetModel();
+}
+
+Qt::ItemFlags PDFOptionalContentTreeItemModel::flags(const QModelIndex& index) const
+{
+ Qt::ItemFlags flags = PDFTreeItemModel::flags(index);
+
+ if (!index.isValid())
+ {
+ return flags;
+ }
+
+ const PDFOptionalContentTreeItem* item = static_cast(index.internalPointer());
+ if (item->getReference() != PDFObjectReference())
+ {
+ flags = flags | Qt::ItemIsUserCheckable | Qt::ItemNeverHasChildren;
+
+ if (item->isLocked())
+ {
+ flags &= ~Qt::ItemIsEnabled;
+ }
+ }
+
+ return flags;
+}
+
+QString PDFOptionalContentTreeItem::getText() const
+{
+ if (!m_text.isEmpty())
+ {
+ return m_text;
+ }
+ else if (getParent())
+ {
+ return static_cast(getParent())->getText();
+ }
+
+ return QString();
+}
+
+} // namespace pdf
diff --git a/PdfForQtLib/sources/pdfitemmodels.h b/PdfForQtLib/sources/pdfitemmodels.h
new file mode 100644
index 0000000..f4bc239
--- /dev/null
+++ b/PdfForQtLib/sources/pdfitemmodels.h
@@ -0,0 +1,123 @@
+// Copyright (C) 2019 Jakub Melka
+//
+// This file is part of PdfForQt.
+//
+// PdfForQt is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// PdfForQt is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with PDFForQt. If not, see .
+
+#ifndef PDFITEMMODELS_H
+#define PDFITEMMODELS_H
+
+#include "pdfglobal.h"
+#include "pdfobject.h"
+
+#include
+
+namespace pdf
+{
+class PDFDocument;
+
+/// Represents tree item in the GUI tree
+class PDFTreeItem
+{
+public:
+ inline explicit PDFTreeItem() = default;
+ inline explicit PDFTreeItem(PDFTreeItem* parent) : m_parent(parent) { }
+ virtual ~PDFTreeItem();
+
+ template
+ inline T* addChild(Arguments&&... arguments)
+ {
+ T* item = new T(this, std::forward(arguments)...);
+ m_children.push_back(item);
+ return item;
+ }
+
+ void addCreatedChild(PDFTreeItem* item)
+ {
+ item->m_parent = this;
+ m_children.push_back(item);
+ }
+
+ int getRow() const { return m_parent->m_children.indexOf(const_cast(this)); }
+ int getChildCount() const { return m_children.size(); }
+ const PDFTreeItem* getChild(int index) const { return m_children.at(index); }
+ const PDFTreeItem* getParent() const { return m_parent; }
+
+private:
+ PDFTreeItem* m_parent = nullptr;
+ QList m_children;
+};
+
+/// Root of all tree item models
+class PDFFORQTLIBSHARED_EXPORT PDFTreeItemModel : public QAbstractItemModel
+{
+public:
+ explicit PDFTreeItemModel(QObject* parent);
+
+ void setDocument(const pdf::PDFDocument* document);
+
+ bool isEmpty() const;
+
+ 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 bool hasChildren(const QModelIndex& parent) const override;
+ virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
+ virtual void update() = 0;
+
+protected:
+ const PDFDocument* m_document;
+ std::unique_ptr m_rootItem;
+};
+
+class PDFOptionalContentTreeItem : public PDFTreeItem
+{
+public:
+ inline explicit PDFOptionalContentTreeItem(PDFOptionalContentTreeItem* parent, PDFObjectReference reference, QString text, bool locked) :
+ PDFTreeItem(parent),
+ m_reference(reference),
+ m_text(qMove(text)),
+ m_locked(locked)
+ {
+
+ }
+
+ PDFObjectReference getReference() const { return m_reference; }
+ QString getText() const;
+ bool isLocked() const { return m_locked; }
+
+private:
+ PDFObjectReference m_reference; ///< Reference to optional content group
+ QString m_text; ///< Node display name
+ bool m_locked; ///< Node is locked (user can't change it)
+};
+
+class PDFFORQTLIBSHARED_EXPORT PDFOptionalContentTreeItemModel : public PDFTreeItemModel
+{
+public:
+ inline explicit PDFOptionalContentTreeItemModel(QObject* parent) :
+ PDFTreeItemModel(parent)
+ {
+
+ }
+
+ virtual int columnCount(const QModelIndex& parent) const override;
+ virtual QVariant data(const QModelIndex& index, int role) const override;
+ virtual void update() override;
+ virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
+};
+
+} // namespace pdf
+
+#endif // PDFITEMMODELS_H
diff --git a/PdfForQtLib/sources/pdfoptionalcontent.cpp b/PdfForQtLib/sources/pdfoptionalcontent.cpp
index fa308c0..25d1715 100644
--- a/PdfForQtLib/sources/pdfoptionalcontent.cpp
+++ b/PdfForQtLib/sources/pdfoptionalcontent.cpp
@@ -34,6 +34,15 @@ PDFOptionalContentProperties PDFOptionalContentProperties::create(const PDFDocum
PDFDocumentDataLoaderDecorator loader(document);
properties.m_allOptionalContentGroups = loader.readReferenceArrayFromDictionary(dictionary, "OCGs");
+ for (const PDFObjectReference& reference : properties.m_allOptionalContentGroups)
+ {
+ const PDFObject& object = document->getStorage().getObject(reference);
+ if (!object.isNull())
+ {
+ properties.m_optionalContentGroups[reference] = PDFOptionalContentGroup::create(document, object);
+ }
+ }
+
if (dictionary->hasKey("D"))
{
properties.m_defaultConfiguration = PDFOptionalContentConfiguration::create(document, dictionary->get("D"));
@@ -178,4 +187,91 @@ PDFOptionalContentConfiguration::UsageApplication PDFOptionalContentConfiguratio
return result;
}
+PDFOptionalContentGroup::PDFOptionalContentGroup() :
+ m_usageZoomMin(0),
+ m_usageZoomMax(std::numeric_limits::infinity()),
+ m_usagePrintState(OCState::Unknown),
+ m_usageViewState(OCState::Unknown),
+ m_usageExportState(OCState::Unknown)
+{
+
+}
+
+PDFOptionalContentGroup PDFOptionalContentGroup::create(const PDFDocument* document, const PDFObject& object)
+{
+ PDFOptionalContentGroup result;
+
+ const PDFObject& dereferencedObject = document->getObject(object);
+ if (!dereferencedObject.isDictionary())
+ {
+ throw PDFParserException(PDFTranslationContext::tr("Invalid optional content group."));
+ }
+
+ PDFDocumentDataLoaderDecorator loader(document);
+
+ const PDFDictionary* dictionary = dereferencedObject.getDictionary();
+ result.m_name = loader.readTextStringFromDictionary(dictionary, "Name", QString());
+
+ if (dictionary->hasKey("Intent"))
+ {
+ const PDFObject& nameOrNames = document->getObject(dictionary->get("Intent"));
+
+ if (nameOrNames.isName())
+ {
+ result.m_intents = { loader.readName(nameOrNames) };
+ }
+ else if (nameOrNames.isArray())
+ {
+ result.m_intents = loader.readNameArray(nameOrNames);
+ }
+ else if (!nameOrNames.isNull())
+ {
+ throw PDFParserException(PDFTranslationContext::tr("Invalid optional content group."));
+ }
+ }
+
+ const PDFObject& usageDictionaryObject = dictionary->get("Usage");
+ if (usageDictionaryObject.isDictionary())
+ {
+ const PDFDictionary* usageDictionary = usageDictionaryObject.getDictionary();
+
+ result.m_creatorInfo = document->getObject(usageDictionary->get("CreatorInfo"));
+ result.m_language = document->getObject(usageDictionary->get("Language"));
+
+ const PDFObject& zoomDictionary = document->getObject(usageDictionary->get("Zoom"));
+ if (zoomDictionary.isDictionary())
+ {
+ result.m_usageZoomMin = loader.readNumberFromDictionary(usageDictionary, "min", result.m_usageZoomMin);
+ result.m_usageZoomMax = loader.readNumberFromDictionary(usageDictionary, "max", result.m_usageZoomMax);
+ }
+
+ auto readState = [document, usageDictionary, &loader](const char* dictionaryKey, const char* key) -> OCState
+ {
+ const PDFObject& stateDictionaryObject = document->getObject(usageDictionary->get(dictionaryKey));
+ if (stateDictionaryObject.isDictionary())
+ {
+ const PDFDictionary* stateDictionary = stateDictionaryObject.getDictionary();
+ QByteArray stateName = loader.readNameFromDictionary(stateDictionary, key);
+
+ if (stateName == "ON")
+ {
+ return OCState::ON;
+ }
+ if (stateName == "OFF")
+ {
+ return OCState::OFF;
+ }
+ }
+
+ return OCState::Unknown;
+ };
+
+ result.m_usageViewState = readState("View", "ViewState");
+ result.m_usagePrintState = readState("Print", "PrintState");
+ result.m_usageExportState = readState("Export", "ExportState");
+ }
+
+ return result;
+}
+
} // namespace pdf
diff --git a/PdfForQtLib/sources/pdfoptionalcontent.h b/PdfForQtLib/sources/pdfoptionalcontent.h
index 8b762e9..dd63598 100644
--- a/PdfForQtLib/sources/pdfoptionalcontent.h
+++ b/PdfForQtLib/sources/pdfoptionalcontent.h
@@ -26,6 +26,42 @@ namespace pdf
class PDFDocument;
+/// State of the optional content group, or result of expression
+enum class OCState
+{
+ ON,
+ OFF,
+ Unknown
+};
+
+constexpr OCState operator &(OCState left, OCState right)
+{
+ if (left == OCState::Unknown)
+ {
+ return right;
+ }
+ if (right == OCState::Unknown)
+ {
+ return left;
+ }
+
+ return (left == OCState::ON && right == OCState::ON) ? OCState::ON : OCState::OFF;
+}
+
+constexpr OCState operator |(OCState left, OCState right)
+{
+ if (left == OCState::Unknown)
+ {
+ return right;
+ }
+ if (right == OCState::Unknown)
+ {
+ return left;
+ }
+
+ return (left == OCState::ON || right == OCState::ON) ? OCState::ON : OCState::OFF;
+}
+
/// Configuration of optional content configuration.
class PDFOptionalContentConfiguration
{
@@ -57,6 +93,18 @@ public:
/// \param object Object containing documents optional content configuration
static PDFOptionalContentConfiguration create(const PDFDocument* document, const PDFObject& object);
+ const QString& getName() const { return m_name; }
+ const QString& getCreator() const { return m_creator; }
+ BaseState getBaseState() const { return m_baseState; }
+ const std::vector& getOnArray() const { return m_OnArray; }
+ const std::vector& getOffArray() const { return m_OffArray; }
+ const std::vector& getIntents() const { return m_intents; }
+ const std::vector& getUsageApplications() const { return m_usageApplications; }
+ const PDFObject& getOrder() const { return m_order; }
+ ListMode getListMode() const { return m_listMode; }
+ const std::vector>& getRadioButtonGroups() const { return m_radioButtonGroups; }
+ const std::vector& getLocked() const { return m_locked; }
+
private:
/// Creates usage application
/// \param document Document
@@ -76,6 +124,43 @@ private:
std::vector m_locked;
};
+/// Class reprezenting optional content group - it contains properties of the group,
+/// such as name, usage etc.
+class PDFOptionalContentGroup
+{
+public:
+ explicit PDFOptionalContentGroup();
+
+ /// Creates optional content group from the object. Object must be valid optional
+ /// content group, if it is invalid, then exception is thrown.
+ /// \param document Document
+ /// \param object Object containing optional content group
+ static PDFOptionalContentGroup create(const PDFDocument* document, const PDFObject& object);
+
+ PDFObjectReference getReference() const { return m_reference; }
+ const QString& getName() const { return m_name; }
+ const std::vector& getIntents() const { return m_intents; }
+ PDFObject getCreatorInfo() const { return m_creatorInfo; }
+ PDFObject getLanguage() const { return m_language; }
+ PDFReal getUsageZoomMin() const { return m_usageZoomMin; }
+ PDFReal getUsageZoomMax() const { return m_usageZoomMax; }
+ OCState getUsagePrintState() const { return m_usagePrintState; }
+ OCState getUsageViewState() const { return m_usageViewState; }
+ OCState getUsageExportState() const { return m_usageExportState; }
+
+private:
+ PDFObjectReference m_reference;
+ QString m_name;
+ std::vector m_intents;
+ PDFObject m_creatorInfo;
+ PDFObject m_language;
+ PDFReal m_usageZoomMin;
+ PDFReal m_usageZoomMax;
+ OCState m_usagePrintState;
+ OCState m_usageViewState;
+ OCState m_usageExportState;
+};
+
/// Object containing properties of the optional content of the PDF document. It contains
/// for example all documents optional content groups.
class PDFOptionalContentProperties
@@ -84,7 +169,7 @@ public:
explicit PDFOptionalContentProperties() = default;
/// Returns, if object is valid - at least one optional content group exists
- bool isValid() const { return !m_allOptionalContentGroups.empty(); }
+ bool isValid() const { return !m_allOptionalContentGroups.empty() && m_allOptionalContentGroups.size() == m_optionalContentGroups.size(); }
/// Creates new optional content properties from the object. If object is not valid,
/// then exception is thrown.
@@ -92,10 +177,15 @@ public:
/// \param object Object containing documents optional content properties
static PDFOptionalContentProperties create(const PDFDocument* document, const PDFObject& object);
+ const std::vector& getAllOptionalContentGroups() const { return m_allOptionalContentGroups; }
+ const PDFOptionalContentConfiguration& getDefaultConfiguration() const { return m_defaultConfiguration; }
+ const PDFOptionalContentGroup& getOptionalContentGroup(PDFObjectReference reference) const { return m_optionalContentGroups.at(reference); }
+
private:
std::vector m_allOptionalContentGroups;
PDFOptionalContentConfiguration m_defaultConfiguration;
std::vector m_configurations;
+ std::map m_optionalContentGroups;
};
} // namespace pdf
diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp
index c8b1c46..8cd6a55 100644
--- a/PdfForQtViewer/pdfviewermainwindow.cpp
+++ b/PdfForQtViewer/pdfviewermainwindow.cpp
@@ -25,6 +25,7 @@
#include "pdfdrawspacecontroller.h"
#include "pdfrenderingerrorswidget.h"
#include "pdffont.h"
+#include "pdfitemmodels.h"
#include
#include
@@ -33,6 +34,10 @@
#include
#include
#include
+#include
+#include
+#include
+#include
namespace pdfviewer
{
@@ -40,7 +45,10 @@ namespace pdfviewer
PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::PDFViewerMainWindow),
- m_pdfWidget(nullptr)
+ m_pdfWidget(nullptr),
+ m_optionalContentDockWidget(nullptr),
+ m_optionalContentTreeView(nullptr),
+ m_optionalContentTreeModel(nullptr)
{
ui->setupUi(this);
@@ -77,6 +85,19 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
setCentralWidget(m_pdfWidget);
setFocusProxy(m_pdfWidget);
+ m_optionalContentDockWidget = new QDockWidget(tr("Optional Content"), this);
+ m_optionalContentDockWidget->setObjectName("OptionalContentDockWidget");
+ m_optionalContentDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ m_optionalContentTreeView = new QTreeView(m_optionalContentDockWidget);
+ m_optionalContentTreeView->header()->hide();
+ m_optionalContentTreeModel = new pdf::PDFOptionalContentTreeItemModel(m_optionalContentTreeView);
+ m_optionalContentTreeView->setModel(m_optionalContentTreeModel);
+ m_optionalContentDockWidget->setWidget(m_optionalContentTreeView);
+ addDockWidget(Qt::LeftDockWidgetArea, m_optionalContentDockWidget);
+
+ ui->menuView->addSeparator();
+ ui->menuView->addAction(m_optionalContentDockWidget->toggleViewAction());
+
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::pageLayoutChanged, this, &PDFViewerMainWindow::updatePageLayoutActions);
connect(m_pdfWidget, &pdf::PDFWidget::pageRenderingErrorsChanged, this, &PDFViewerMainWindow::onPageRenderingErrorsChanged, Qt::QueuedConnection);
@@ -234,6 +255,18 @@ void PDFViewerMainWindow::openDocument(const QString& fileName)
void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
{
m_pdfWidget->setDocument(document);
+ m_optionalContentTreeModel->setDocument(document);
+ m_optionalContentTreeView->expandAll();
+
+ if (m_optionalContentTreeModel->isEmpty())
+ {
+ m_optionalContentDockWidget->hide();
+ }
+ else
+ {
+ m_optionalContentDockWidget->show();
+ }
+
updateTitle();
}
diff --git a/PdfForQtViewer/pdfviewermainwindow.h b/PdfForQtViewer/pdfviewermainwindow.h
index 1dc3810..2f0baf3 100644
--- a/PdfForQtViewer/pdfviewermainwindow.h
+++ b/PdfForQtViewer/pdfviewermainwindow.h
@@ -21,6 +21,7 @@
#include "pdfcatalog.h"
#include "pdfrenderer.h"
+#include
#include
#include
@@ -33,6 +34,7 @@ namespace pdf
{
class PDFWidget;
class PDFDocument;
+class PDFOptionalContentTreeItemModel;
}
namespace pdfviewer
@@ -82,6 +84,9 @@ private:
QSharedPointer m_pdfDocument;
QString m_directory;
QString m_currentFile;
+ QDockWidget* m_optionalContentDockWidget;
+ QTreeView* m_optionalContentTreeView;
+ pdf::PDFOptionalContentTreeItemModel* m_optionalContentTreeModel;
};
} // namespace pdfviewer