GUI refactoring

This commit is contained in:
Jakub Melka 2019-11-28 18:20:32 +01:00
parent a857e061b8
commit 754b922ae2
10 changed files with 1909 additions and 24 deletions

View File

@ -213,9 +213,12 @@ public:
/// Returns the page
const PDFPage* getPage(size_t index) const { return &m_pages.at(index); }
/// Return optional content properties
/// Returns optional content properties
const PDFOptionalContentProperties* getOptionalContentProperties() const { return &m_optionalContentProperties; }
/// Returns root pointer for outline items
QSharedPointer<PDFOutlineItem> getOutlineRootPtr() const { return m_outlineRoot; }
/// Parses catalog from catalog dictionary. If object cannot be parsed, or error occurs,
/// then exception is thrown.
static PDFCatalog parse(const PDFObject& catalog, const PDFDocument* document);

View File

@ -18,6 +18,9 @@
#include "pdfitemmodels.h"
#include "pdfdocument.h"
#include <QFont>
#include <QApplication>
namespace pdf
{
@ -324,4 +327,92 @@ bool PDFOptionalContentTreeItemModel::setData(const QModelIndex& index, const QV
return false;
}
PDFOutlineTreeItem::PDFOutlineTreeItem(PDFOutlineTreeItem* parent, QSharedPointer<PDFOutlineItem> outlineItem) :
PDFTreeItem(parent),
m_outlineItem(qMove(outlineItem))
{
size_t childCount = m_outlineItem->getChildCount();
for (size_t i = 0; i < childCount; ++i)
{
addCreatedChild(new PDFOutlineTreeItem(nullptr, m_outlineItem->getChildPtr(i)));
}
}
int PDFOutlineTreeItemModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return 1;
}
QVariant PDFOutlineTreeItemModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
{
return QVariant();
}
const PDFOutlineTreeItem* item = static_cast<const PDFOutlineTreeItem*>(index.internalPointer());
const PDFOutlineItem* outlineItem = item->getOutlineItem();
switch (role)
{
case Qt::DisplayRole:
return outlineItem->getTitle();
case Qt::TextColorRole:
return outlineItem->getTextColor();
case Qt::FontRole:
{
QFont font = QApplication::font();
font.setBold(outlineItem->isFontBold());
font.setItalic(outlineItem->isFontItalics());
return font;
}
default:
break;
}
return QString();
}
void PDFOutlineTreeItemModel::update()
{
beginResetModel();
QSharedPointer<PDFOutlineItem> outlineRoot;
if (m_document)
{
outlineRoot = m_document->getCatalog()->getOutlineRootPtr();
}
if (outlineRoot)
{
m_rootItem.reset(new PDFOutlineTreeItem(nullptr, qMove(outlineRoot)));
}
else
{
m_rootItem.reset();
}
endResetModel();
}
Qt::ItemFlags PDFOutlineTreeItemModel::flags(const QModelIndex& index) const
{
Qt::ItemFlags flags = PDFTreeItemModel::flags(index);
if (!index.isValid())
{
return flags;
}
const PDFOutlineTreeItem* item = static_cast<const PDFOutlineTreeItem*>(index.internalPointer());
if (item->getChildCount() == 0)
{
flags = flags | Qt::ItemNeverHasChildren;
}
return flags;
}
} // namespace pdf

View File

@ -26,6 +26,7 @@
namespace pdf
{
class PDFDocument;
class PDFOutlineItem;
class PDFOptionalContentActivity;
/// Represents tree item in the GUI tree
@ -126,6 +127,28 @@ private:
PDFOptionalContentActivity* m_activity;
};
class PDFOutlineTreeItem : public PDFTreeItem
{
public:
explicit PDFOutlineTreeItem(PDFOutlineTreeItem* parent, QSharedPointer<PDFOutlineItem> outlineItem);
const PDFOutlineItem* getOutlineItem() const { return m_outlineItem.data(); }
private:
QSharedPointer<PDFOutlineItem> m_outlineItem;
};
class PDFFORQTLIBSHARED_EXPORT PDFOutlineTreeItemModel : public PDFTreeItemModel
{
public:
using PDFTreeItemModel::PDFTreeItemModel;
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

View File

@ -42,6 +42,7 @@ public:
size_t getChildCount() const { return m_children.size(); }
const PDFOutlineItem* getChild(size_t index) const { return m_children[index].get(); }
void addChild(QSharedPointer<PDFOutlineItem> child) { m_children.emplace_back(qMove(child)); }
QSharedPointer<PDFOutlineItem> getChildPtr(size_t index) const { return m_children[index]; }
static QSharedPointer<PDFOutlineItem> parse(const PDFDocument* document, const PDFObject& root);

View File

@ -35,18 +35,21 @@ LIBS += -lPDFForQtLib
SOURCES += \
main.cpp \
pdfaboutdialog.cpp \
pdfsidebarwidget.cpp \
pdfviewermainwindow.cpp \
pdfviewersettings.cpp \
pdfviewersettingsdialog.cpp
HEADERS += \
pdfaboutdialog.h \
pdfsidebarwidget.h \
pdfviewermainwindow.h \
pdfviewersettings.h \
pdfviewersettingsdialog.h
FORMS += \
pdfaboutdialog.ui \
pdfsidebarwidget.ui \
pdfviewermainwindow.ui \
pdfviewersettingsdialog.ui

View File

@ -0,0 +1,205 @@
// 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 <https://www.gnu.org/licenses/>.
#include "pdfsidebarwidget.h"
#include "ui_pdfsidebarwidget.h"
#include "pdfdocument.h"
#include "pdfitemmodels.h"
namespace pdfviewer
{
PDFSidebarWidget::PDFSidebarWidget(QWidget* parent) :
QWidget(parent),
ui(new Ui::PDFSidebarWidget),
m_outlineTreeModel(nullptr),
m_optionalContentTreeModel(nullptr),
m_document(nullptr),
m_optionalContentActivity(nullptr)
{
ui->setupUi(this);
// Outline
m_outlineTreeModel = new pdf::PDFOutlineTreeItemModel(this);
ui->bookmarksTreeView->setModel(m_outlineTreeModel);
ui->bookmarksTreeView->header()->hide();
// Optional content
ui->optionalContentTreeView->header()->hide();
m_optionalContentTreeModel = new pdf::PDFOptionalContentTreeItemModel(this);
ui->optionalContentTreeView->setModel(m_optionalContentTreeModel);
m_pageInfo[Invalid] = { nullptr, ui->emptyPage };
m_pageInfo[OptionalContent] = { ui->optionalContentButton, ui->optionalContentPage };
m_pageInfo[Bookmarks] = { ui->bookmarksButton, ui->bookmarksPage };
m_pageInfo[Thumbnails] = { ui->thumbnailsButton, ui->thumbnailsPage };
setAutoFillBackground(true);
selectPage(Invalid);
updateButtons();
}
PDFSidebarWidget::~PDFSidebarWidget()
{
delete ui;
}
void PDFSidebarWidget::setDocument(const pdf::PDFDocument* document, pdf::PDFOptionalContentActivity* optionalContentActivity)
{
m_document = document;
m_optionalContentActivity = optionalContentActivity;
// Update outline
m_outlineTreeModel->setDocument(document);
// Update optional content
m_optionalContentTreeModel->setDocument(document);
m_optionalContentTreeModel->setActivity(m_optionalContentActivity);
ui->optionalContentTreeView->expandAll();
Page preferred = Invalid;
if (m_document)
{
const pdf::PDFViewerPreferences::NonFullScreenPageMode pageMode = m_document->getCatalog()->getViewerPreferences()->getNonFullScreenPageMode();
switch (pageMode)
{
case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseOutline:
preferred = Bookmarks;
break;
case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseThumbnails:
preferred = Thumbnails;
break;
case pdf::PDFViewerPreferences::NonFullScreenPageMode::UseOptionalContent:
preferred = OptionalContent;
break;
default:
break;
}
}
// Update GUI
updateGUI(preferred);
updateButtons();
}
bool PDFSidebarWidget::isEmpty() const
{
for (int i = _BEGIN; i < _END; ++i)
{
if (!isEmpty(static_cast<Page>(i)))
{
return false;
}
}
return true;
}
bool PDFSidebarWidget::isEmpty(Page page) const
{
switch (page)
{
case Invalid:
return true;
case OptionalContent:
return m_optionalContentTreeModel->isEmpty();
case Bookmarks:
return m_outlineTreeModel->isEmpty();
case Thumbnails:
return true;
default:
Q_ASSERT(false);
break;
}
return true;
}
void PDFSidebarWidget::selectPage(Page page)
{
// Switch state of the buttons and select the page
for (const auto& pageInfo : m_pageInfo)
{
if (pageInfo.second.button)
{
pageInfo.second.button->setChecked(pageInfo.first == page);
}
if (pageInfo.first == page)
{
ui->stackedWidget->setCurrentWidget(pageInfo.second.page);
}
}
}
std::vector<PDFSidebarWidget::Page> PDFSidebarWidget::getValidPages() const
{
std::vector<PDFSidebarWidget::Page> result;
result.reserve(_END - _BEGIN + 1);
for (int i = _BEGIN; i < _END; ++i)
{
if (!isEmpty(static_cast<Page>(i)))
{
result.push_back(static_cast<Page>(i));
}
}
return result;
}
void PDFSidebarWidget::updateGUI(Page preferredPage)
{
if (preferredPage != Invalid && !isEmpty(preferredPage))
{
selectPage(preferredPage);
}
else
{
// Select first nonempty page
std::vector<Page> validPages = getValidPages();
if (!validPages.empty())
{
selectPage(validPages.front());
}
else
{
selectPage(Invalid);
}
}
}
void PDFSidebarWidget::updateButtons()
{
for (const auto& pageInfo : m_pageInfo)
{
if (pageInfo.second.button)
{
pageInfo.second.button->setEnabled(!isEmpty(pageInfo.first));
}
}
}
} // namespace pdfviewer

View File

@ -0,0 +1,95 @@
// 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 <https://www.gnu.org/licenses/>.
#ifndef PDFSIDEBARWIDGET_H
#define PDFSIDEBARWIDGET_H
#include <QWidget>
class QPushButton;
class QWidget;
namespace Ui
{
class PDFSidebarWidget;
}
namespace pdf
{
class PDFDocument;
class PDFOutlineTreeItemModel;
class PDFOptionalContentActivity;
class PDFOptionalContentTreeItemModel;
}
namespace pdfviewer
{
class PDFSidebarWidget : public QWidget
{
Q_OBJECT
public:
explicit PDFSidebarWidget(QWidget* parent = nullptr);
virtual ~PDFSidebarWidget() override;
enum Page
{
Invalid,
_BEGIN,
OptionalContent = _BEGIN,
Bookmarks,
Thumbnails,
_END
};
void setDocument(const pdf::PDFDocument* document, pdf::PDFOptionalContentActivity* optionalContentActivity);
/// Returns true, if all items in sidebar are empty
bool isEmpty() const;
/// Returns true, if page is empty
bool isEmpty(Page page) const;
/// Selects current page
void selectPage(Page page);
/// Returns list of valid pages (nonempty pages)
std::vector<Page> getValidPages() const;
private:
void updateGUI(Page preferredPage);
void updateButtons();
struct PageInfo
{
QPushButton* button = nullptr;
QWidget* page = nullptr;
};
Ui::PDFSidebarWidget* ui;
pdf::PDFOutlineTreeItemModel* m_outlineTreeModel;
pdf::PDFOptionalContentTreeItemModel* m_optionalContentTreeModel;
const pdf::PDFDocument* m_document;
pdf::PDFOptionalContentActivity* m_optionalContentActivity;
std::map<Page, PageInfo> m_pageInfo;
};
} // namespace pdfviewer
#endif // PDFSIDEBARWIDGET_H

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
#include "pdfaboutdialog.h"
#include "pdfviewersettingsdialog.h"
#include "pdfsidebarwidget.h"
#include "pdfdocumentreader.h"
#include "pdfvisitor.h"
@ -55,9 +56,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
ui(new Ui::PDFViewerMainWindow),
m_settings(new PDFViewerSettings(this)),
m_pdfWidget(nullptr),
m_optionalContentDockWidget(nullptr),
m_optionalContentTreeView(nullptr),
m_optionalContentTreeModel(nullptr),
m_sidebarDockWidget(nullptr),
m_optionalContentActivity(nullptr),
m_pageNumberSpinBox(nullptr),
m_pageNumberLabel(nullptr),
@ -143,16 +142,13 @@ 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);
m_optionalContentDockWidget->hide();
m_sidebarWidget = new PDFSidebarWidget(this);
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
m_sidebarDockWidget->setObjectName("SidebarDockWidget");
m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
m_sidebarDockWidget->setWidget(m_sidebarWidget);
addDockWidget(Qt::LeftDockWidgetArea, m_sidebarDockWidget);
m_sidebarDockWidget->hide();
ui->actionRenderOptionAntialiasing->setData(pdf::PDFRenderer::Antialiasing);
ui->actionRenderOptionTextAntialiasing->setData(pdf::PDFRenderer::TextAntialiasing);
@ -165,7 +161,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget *parent) :
}
ui->menuView->addSeparator();
ui->menuView->addAction(m_optionalContentDockWidget->toggleViewAction());
ui->menuView->addAction(m_sidebarDockWidget->toggleViewAction());
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::drawSpaceChanged, this, &PDFViewerMainWindow::onDrawSpaceChanged);
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::pageLayoutChanged, this, &PDFViewerMainWindow::onPageLayoutChanged);
@ -477,17 +473,15 @@ void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
}
m_pdfWidget->setDocument(document, m_optionalContentActivity);
m_optionalContentTreeModel->setDocument(document);
m_optionalContentTreeModel->setActivity(m_optionalContentActivity);
m_optionalContentTreeView->expandAll();
m_sidebarWidget->setDocument(document, m_optionalContentActivity);
if (m_optionalContentTreeModel->isEmpty())
if (m_sidebarWidget->isEmpty())
{
m_optionalContentDockWidget->hide();
m_sidebarDockWidget->hide();
}
else
{
m_optionalContentDockWidget->show();
m_sidebarDockWidget->show();
}
updateTitle();

View File

@ -48,6 +48,7 @@ class PDFOptionalContentTreeItemModel;
namespace pdfviewer
{
class PDFSidebarWidget;
class PDFViewerMainWindow : public QMainWindow
{
@ -112,9 +113,8 @@ private:
pdf::PDFWidget* m_pdfWidget;
QSharedPointer<pdf::PDFDocument> m_pdfDocument;
QString m_currentFile;
QDockWidget* m_optionalContentDockWidget;
QTreeView* m_optionalContentTreeView;
pdf::PDFOptionalContentTreeItemModel* m_optionalContentTreeModel;
PDFSidebarWidget* m_sidebarWidget;
QDockWidget* m_sidebarDockWidget;
pdf::PDFOptionalContentActivity* m_optionalContentActivity;
QSpinBox* m_pageNumberSpinBox;
QLabel* m_pageNumberLabel;