Finishing of attachments

This commit is contained in:
Jakub Melka 2019-12-03 19:24:43 +01:00
parent 159fc9f815
commit 5eed274863
6 changed files with 92 additions and 4 deletions

View File

@ -296,7 +296,7 @@ private:
};
/// PDF document main class.
class PDFDocument
class PDFFORQTLIBSHARED_EXPORT PDFDocument
{
Q_DECLARE_TR_FUNCTIONS(pdf::PDFDocument)

View File

@ -37,6 +37,7 @@ public:
const QDateTime& getCreationDate() const { return m_creationDate; }
const QDateTime& getModifiedDate() const { return m_modifiedDate; }
const QByteArray& getChecksum() const { return m_checksum; }
const PDFStream* getStream() const { return m_stream.getStream(); }
static PDFEmbeddedFile parse(const PDFDocument* document, PDFObject object);

View File

@ -565,7 +565,8 @@ void PDFAttachmentsTreeItemModel::update()
auto it = subroots.find(fileTypeName);
if (it == subroots.cend())
{
subroot = new PDFAttachmentsTreeItem(nullptr, icon, fileTypeDescription, QString(), nullptr);
QIcon folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirIcon);
subroot = new PDFAttachmentsTreeItem(nullptr, qMove(folderIcon), fileTypeDescription, QString(), nullptr);
root->addCreatedChild(subroot);
subroots[fileTypeName] = subroot;
}
@ -585,7 +586,32 @@ void PDFAttachmentsTreeItemModel::update()
Qt::ItemFlags PDFAttachmentsTreeItemModel::flags(const QModelIndex& index) const
{
return PDFTreeItemModel::flags(index);
if (!index.isValid())
{
return Qt::NoItemFlags;
}
if (rowCount(index) > 0)
{
return Qt::ItemIsEnabled;
}
if (index.column() == Title)
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren;
}
return Qt::ItemIsEnabled | Qt::ItemNeverHasChildren;
}
const PDFFileSpecification* PDFAttachmentsTreeItemModel::getFileSpecification(const QModelIndex& index) const
{
if (index.isValid())
{
return static_cast<const PDFAttachmentsTreeItem*>(index.internalPointer())->getFileSpecification();
}
return nullptr;
}
} // namespace pdf

View File

@ -213,6 +213,8 @@ public:
virtual QVariant data(const QModelIndex& index, int role) const override;
virtual void update() override;
virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
const PDFFileSpecification* getFileSpecification(const QModelIndex& index) const;
};
} // namespace pdf

View File

@ -20,6 +20,13 @@
#include "pdfdocument.h"
#include "pdfitemmodels.h"
#include "pdfexception.h"
#include <QMenu>
#include <QAction>
#include <QFileDialog>
#include <QStandardPaths>
#include <QMessageBox>
namespace pdfviewer
{
@ -52,7 +59,9 @@ PDFSidebarWidget::PDFSidebarWidget(QWidget* parent) :
m_attachmentsTreeModel = new pdf::PDFAttachmentsTreeItemModel(this);
ui->attachmentsTreeView->setModel(m_attachmentsTreeModel);
ui->attachmentsTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->attachmentsTreeView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->attachmentsTreeView->setSelectionBehavior(QAbstractItemView::SelectItems);
ui->attachmentsTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->attachmentsTreeView, &QTreeView::customContextMenuRequested, this, &PDFSidebarWidget::onAttachmentCustomContextMenuRequested);
m_pageInfo[Invalid] = { nullptr, ui->emptyPage };
m_pageInfo[OptionalContent] = { ui->optionalContentButton, ui->optionalContentPage };
@ -233,4 +242,53 @@ void PDFSidebarWidget::onOutlineItemClicked(const QModelIndex& index)
}
}
void PDFSidebarWidget::onAttachmentCustomContextMenuRequested(const QPoint& pos)
{
if (const pdf::PDFFileSpecification* fileSpecification = m_attachmentsTreeModel->getFileSpecification(ui->attachmentsTreeView->indexAt(pos)))
{
QMenu menu(this);
QAction* action = new QAction(QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton, nullptr, ui->attachmentsTreeView), tr("Save to File..."), &menu);
auto onSaveTriggered = [this, fileSpecification]()
{
const pdf::PDFEmbeddedFile* platformFile = fileSpecification->getPlatformFile();
if (platformFile && platformFile->isValid())
{
QString defaultFileName = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + QDir::separator() + fileSpecification->getPlatformFileName();
QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save attachment"), defaultFileName);
if (!saveFileName.isEmpty())
{
try
{
QByteArray data = m_document->getDecodedStream(platformFile->getStream());
QFile file(saveFileName);
if (file.open(QFile::WriteOnly | QFile::Truncate))
{
file.write(data);
file.close();
}
else
{
QMessageBox::critical(this, tr("Error"), tr("Failed to save attachment to file. %1").arg(file.errorString()));
}
}
catch (pdf::PDFException e)
{
QMessageBox::critical(this, tr("Error"), tr("Failed to save attachment to file. %1").arg(e.getMessage()));
}
}
}
else
{
QMessageBox::critical(this, tr("Error"), tr("Failed to save attachment to file. Attachment is corrupted."));
}
};
connect(action, &QAction::triggered, this, onSaveTriggered);
menu.addAction(action);
menu.exec(ui->attachmentsTreeView->viewport()->mapToGlobal(pos));
}
}
} // namespace pdfviewer

View File

@ -83,6 +83,7 @@ private:
void updateButtons();
void onOutlineItemClicked(const QModelIndex& index);
void onAttachmentCustomContextMenuRequested(const QPoint& pos);
struct PageInfo
{