Copy Annotation onto Multiple Pages

This commit is contained in:
Jakub Melka
2020-12-30 17:06:13 +01:00
parent 6f0b72ba3b
commit 19dd761f35
10 changed files with 124 additions and 47 deletions

View File

@ -76,6 +76,7 @@ SOURCES += \
sources/pdfprogress.cpp \ sources/pdfprogress.cpp \
sources/pdfredact.cpp \ sources/pdfredact.cpp \
sources/pdfsecurityhandler.cpp \ sources/pdfsecurityhandler.cpp \
sources/pdfselectpagesdialog.cpp \
sources/pdfsignaturehandler.cpp \ sources/pdfsignaturehandler.cpp \
sources/pdfsnapper.cpp \ sources/pdfsnapper.cpp \
sources/pdfstructuretree.cpp \ sources/pdfstructuretree.cpp \
@ -143,6 +144,7 @@ HEADERS += \
sources/pdfprogress.h \ sources/pdfprogress.h \
sources/pdfredact.h \ sources/pdfredact.h \
sources/pdfsecurityhandler.h \ sources/pdfsecurityhandler.h \
sources/pdfselectpagesdialog.h \
sources/pdfsignaturehandler.h \ sources/pdfsignaturehandler.h \
sources/pdfsignaturehandler_impl.h \ sources/pdfsignaturehandler_impl.h \
sources/pdfsnapper.h \ sources/pdfsnapper.h \
@ -174,7 +176,8 @@ HEADERS += \
sources/pdfimage.h sources/pdfimage.h
FORMS += \ FORMS += \
sources/pdfrenderingerrorswidget.ui sources/pdfrenderingerrorswidget.ui \
sources/pdfselectpagesdialog.ui
RESOURCES += cmaps.qrc RESOURCES += cmaps.qrc

View File

@ -29,6 +29,7 @@
#include "pdfpainterutils.h" #include "pdfpainterutils.h"
#include "pdfdocumentbuilder.h" #include "pdfdocumentbuilder.h"
#include "pdfobjecteditorwidget.h" #include "pdfobjecteditorwidget.h"
#include "pdfselectpagesdialog.h"
#include <QMenu> #include <QMenu>
#include <QDialog> #include <QDialog>
@ -2010,7 +2011,42 @@ void PDFWidgetAnnotationManager::onShowPopupAnnotation()
void PDFWidgetAnnotationManager::onCopyAnnotation() void PDFWidgetAnnotationManager::onCopyAnnotation()
{ {
pdf::PDFSelectPagesDialog dialog(tr("Copy Annotation"), tr("Copy Annotation onto Multiple Pages"),
m_document->getCatalog()->getPageCount(), m_proxy->getWidget()->getDrawWidget()->getCurrentPages(), m_proxy->getWidget());
if (dialog.exec() == QDialog::Accepted)
{
std::vector<PDFInteger> pages = dialog.getSelectedPages();
const PDFInteger currentPageIndex = m_document->getCatalog()->getPageIndexFromPageReference(m_editableAnnotationPage);
for (PDFInteger& pageIndex : pages)
{
--pageIndex;
}
auto it = std::find(pages.begin(), pages.end(), currentPageIndex);
if (it != pages.end())
{
pages.erase(it);
}
if (pages.empty())
{
return;
}
PDFDocumentModifier modifier(m_document);
modifier.markAnnotationsChanged();
for (const PDFInteger pageIndex : pages)
{
modifier.getBuilder()->copyAnnotation(m_document->getCatalog()->getPage(pageIndex)->getPageReference(), m_editableAnnotation);
}
if (modifier.finalize())
{
emit documentModified(PDFModifiedDocument(modifier.getDocument(), nullptr, modifier.getFlags()));
}
}
} }
void PDFWidgetAnnotationManager::onEditAnnotation() void PDFWidgetAnnotationManager::onEditAnnotation()

View File

@ -1111,6 +1111,36 @@ PDFObjectReference PDFDocumentBuilder::getDocumentInfo() const
return PDFObjectReference(); return PDFObjectReference();
} }
void PDFDocumentBuilder::copyAnnotation(PDFObjectReference pageReference, PDFObjectReference annotationReference)
{
PDFObjectReference copiedAnnotation = addObject(getObjectByReference(annotationReference));
PDFObjectFactory factory;
factory.beginDictionary();
factory.beginDictionaryItem("P");
factory << pageReference;
factory.endDictionaryItem();
factory.beginDictionaryItem("Popup");
factory << PDFObject();
factory.endDictionaryItem();
factory.beginDictionaryItem("IRT");
factory << PDFObject();
factory.endDictionaryItem();
factory.endDictionary();
mergeTo(copiedAnnotation, factory.takeObject());
factory.beginDictionary();
factory.beginDictionaryItem("Annots");
factory.beginArray();
factory << copiedAnnotation;
factory.endArray();
factory.endDictionaryItem();
factory.endDictionary();
PDFObject pageAnnots = factory.takeObject();
appendTo(pageReference, pageAnnots);
}
PDFObjectReference PDFDocumentBuilder::getCatalogReference() const PDFObjectReference PDFDocumentBuilder::getCatalogReference() const
{ {
if (const PDFDictionary* trailerDictionary = getDictionaryFromObject(m_storage.getTrailerDictionary())) if (const PDFDictionary* trailerDictionary = getDictionaryFromObject(m_storage.getTrailerDictionary()))

View File

@ -416,6 +416,11 @@ public:
/// Returns document info reference /// Returns document info reference
PDFObjectReference getDocumentInfo() const; PDFObjectReference getDocumentInfo() const;
/// Copies existing annotation to another page
/// \param pageReference Page reference (onto which is annotation copied)
/// \param annotationReference Annotation reference
void copyAnnotation(PDFObjectReference pageReference, PDFObjectReference annotationReference);
/* START GENERATED CODE */ /* START GENERATED CODE */
/// Appends a new page after last page. /// Appends a new page after last page.

View File

@ -78,9 +78,7 @@ PDFDocument PDFRedact::perform(Options options)
} }
builder.setPageRotation(newPageReference, page->getPageRotation()); builder.setPageRotation(newPageReference, page->getPageRotation());
// TODO: Popisek redakce anotace, Overlay text
// TODO: Redact searched text // TODO: Redact searched text
// TODO: Duplikace redakce na vice stranek
PDFPageContentStreamBuilder contentStreamBuilder(&builder); PDFPageContentStreamBuilder contentStreamBuilder(&builder);
@ -131,7 +129,12 @@ PDFDocument PDFRedact::perform(Options options)
if (options.testFlag(CopyOutline)) if (options.testFlag(CopyOutline))
{ {
builder.setOutline(m_document->getCatalog()->getOutlineRootPtr().data()); const PDFOutlineItem* outlineItem = m_document->getCatalog()->getOutlineRootPtr().data();
if (outlineItem)
{
builder.setOutline(outlineItem);
}
} }
PDFDocument redactedDocument = builder.build(); PDFDocument redactedDocument = builder.build();
@ -141,5 +144,4 @@ PDFDocument PDFRedact::perform(Options options)
return optimizer.takeOptimizedDocument(); return optimizer.takeOptimizedDocument();
} }
} // namespace pdf } // namespace pdf

View File

@ -15,24 +15,31 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>. // along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#include "selectpagestoredactdialog.h" #include "pdfselectpagesdialog.h"
#include "ui_selectpagestoredactdialog.h" #include "ui_pdfselectpagesdialog.h"
#include "pdfwidgetutils.h" #include "pdfwidgetutils.h"
#include <QMessageBox> #include <QMessageBox>
namespace pdfplugin namespace pdf
{ {
SelectPagesToRedactDialog::SelectPagesToRedactDialog(pdf::PDFInteger pageCount, const std::vector<pdf::PDFInteger>& visiblePages, QWidget* parent) : PDFSelectPagesDialog::PDFSelectPagesDialog(QString windowTitle,
QString groupBoxTitle,
pdf::PDFInteger pageCount,
const std::vector<pdf::PDFInteger>& visiblePages,
QWidget* parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::SelectPagesToRedactDialog), ui(new Ui::PDFSelectPagesDialog),
m_pageCount(pageCount), m_pageCount(pageCount),
m_visiblePages(visiblePages) m_visiblePages(visiblePages)
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowTitle(windowTitle);
ui->selectPagesGroupBox->setTitle(groupBoxTitle);
for (pdf::PDFInteger& pageIndex : m_visiblePages) for (pdf::PDFInteger& pageIndex : m_visiblePages)
{ {
++pageIndex; ++pageIndex;
@ -53,18 +60,18 @@ SelectPagesToRedactDialog::SelectPagesToRedactDialog(pdf::PDFInteger pageCount,
} }
} }
connect(ui->customPageRangeRadioButton, &QRadioButton::toggled, this, &SelectPagesToRedactDialog::updateUi); connect(ui->customPageRangeRadioButton, &QRadioButton::toggled, this, &PDFSelectPagesDialog::updateUi);
setMinimumWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, 400)); setMinimumWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, 400));
updateUi(); updateUi();
} }
SelectPagesToRedactDialog::~SelectPagesToRedactDialog() PDFSelectPagesDialog::~PDFSelectPagesDialog()
{ {
delete ui; delete ui;
} }
std::vector<pdf::PDFInteger> SelectPagesToRedactDialog::getSelectedPages() const std::vector<pdf::PDFInteger> PDFSelectPagesDialog::getSelectedPages() const
{ {
std::vector<pdf::PDFInteger> result; std::vector<pdf::PDFInteger> result;
@ -98,12 +105,12 @@ std::vector<pdf::PDFInteger> SelectPagesToRedactDialog::getSelectedPages() const
return result; return result;
} }
void SelectPagesToRedactDialog::updateUi() void PDFSelectPagesDialog::updateUi()
{ {
ui->customPageRangeEdit->setEnabled(ui->customPageRangeRadioButton->isChecked()); ui->customPageRangeEdit->setEnabled(ui->customPageRangeRadioButton->isChecked());
} }
void SelectPagesToRedactDialog::accept() void PDFSelectPagesDialog::accept()
{ {
if (ui->customPageRangeRadioButton->isChecked()) if (ui->customPageRangeRadioButton->isChecked())
{ {
@ -125,4 +132,4 @@ void SelectPagesToRedactDialog::accept()
QDialog::accept(); QDialog::accept();
} }
} // namespace pdfplugin } // namespace pdf

View File

@ -15,8 +15,8 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>. // along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#ifndef SELECTPAGESTOREDACTDIALOG_H #ifndef PDFSELECTPAGESDIALOG_H
#define SELECTPAGESTOREDACTDIALOG_H #define PDFSELECTPAGESDIALOG_H
#include "pdfutils.h" #include "pdfutils.h"
@ -24,19 +24,24 @@
namespace Ui namespace Ui
{ {
class SelectPagesToRedactDialog; class PDFSelectPagesDialog;
} }
namespace pdfplugin namespace pdf
{ {
class SelectPagesToRedactDialog : public QDialog class Pdf4QtLIBSHARED_EXPORT PDFSelectPagesDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SelectPagesToRedactDialog(pdf::PDFInteger pageCount, const std::vector<pdf::PDFInteger>& visiblePages, QWidget* parent); explicit PDFSelectPagesDialog(QString windowTitle,
virtual ~SelectPagesToRedactDialog() override; QString groupBoxTitle,
pdf::PDFInteger pageCount,
const std::vector<pdf::PDFInteger>& visiblePages,
QWidget* parent);
virtual ~PDFSelectPagesDialog() override;
virtual void accept() override; virtual void accept() override;
@ -45,15 +50,13 @@ public:
private: private:
void updateUi(); void updateUi();
Ui::SelectPagesToRedactDialog* ui; Ui::PDFSelectPagesDialog* ui;
pdf::PDFInteger m_pageCount; pdf::PDFInteger m_pageCount;
std::vector<pdf::PDFInteger> m_visiblePages; std::vector<pdf::PDFInteger> m_visiblePages;
std::vector<pdf::PDFInteger> m_evenPages; std::vector<pdf::PDFInteger> m_evenPages;
std::vector<pdf::PDFInteger> m_oddPages; std::vector<pdf::PDFInteger> m_oddPages;
}; };
} // namespace pdfplugin } // namespace pdf
#endif // SELECTPAGESTOREDACTDIALOG_H #endif // PDFSELECTPAGESDIALOG_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>SelectPagesToRedactDialog</class> <class>PDFSelectPagesDialog</class>
<widget class="QDialog" name="SelectPagesToRedactDialog"> <widget class="QDialog" name="PDFSelectPagesDialog">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -10,15 +10,9 @@
<height>218</height> <height>218</height>
</rect> </rect>
</property> </property>
<property name="windowTitle">
<string>Redact Pages</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QGroupBox" name="selectPagesToRedact"> <widget class="QGroupBox" name="selectPagesGroupBox">
<property name="title">
<string>Page Range to be Redacted</string>
</property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2"> <item row="1" column="0" colspan="2">
<widget class="QRadioButton" name="allPagesRadioButton"> <widget class="QRadioButton" name="allPagesRadioButton">
@ -94,7 +88,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>SelectPagesToRedactDialog</receiver> <receiver>PDFSelectPagesDialog</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -110,7 +104,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>SelectPagesToRedactDialog</receiver> <receiver>PDFSelectPagesDialog</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

View File

@ -34,13 +34,11 @@ CONFIG += c++11
SOURCES += \ SOURCES += \
createredacteddocumentdialog.cpp \ createredacteddocumentdialog.cpp \
redactplugin.cpp \ redactplugin.cpp
selectpagestoredactdialog.cpp
HEADERS += \ HEADERS += \
createredacteddocumentdialog.h \ createredacteddocumentdialog.h \
redactplugin.h \ redactplugin.h
selectpagestoredactdialog.h
CONFIG += force_debug_info CONFIG += force_debug_info
@ -51,7 +49,6 @@ RESOURCES += \
icons.qrc icons.qrc
FORMS += \ FORMS += \
createredacteddocumentdialog.ui \ createredacteddocumentdialog.ui
selectpagestoredactdialog.ui

View File

@ -16,7 +16,6 @@
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>. // along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#include "redactplugin.h" #include "redactplugin.h"
#include "selectpagestoredactdialog.h"
#include "createredacteddocumentdialog.h" #include "createredacteddocumentdialog.h"
#include "pdfdrawwidget.h" #include "pdfdrawwidget.h"
@ -24,6 +23,7 @@
#include "pdfdocumentbuilder.h" #include "pdfdocumentbuilder.h"
#include "pdfredact.h" #include "pdfredact.h"
#include "pdfdocumentwriter.h" #include "pdfdocumentwriter.h"
#include "pdfselectpagesdialog.h"
#include <QAction> #include <QAction>
#include <QMessageBox> #include <QMessageBox>
@ -96,7 +96,7 @@ void RedactPlugin::updateActions()
void RedactPlugin::onRedactPageTriggered() void RedactPlugin::onRedactPageTriggered()
{ {
pdfplugin::SelectPagesToRedactDialog dialog(m_document->getCatalog()->getPageCount(), m_widget->getDrawWidget()->getCurrentPages(), m_widget); pdf::PDFSelectPagesDialog dialog(tr("Redact Pages"), tr("Page Range to be Redacted"), m_document->getCatalog()->getPageCount(), m_widget->getDrawWidget()->getCurrentPages(), m_widget);
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
std::vector<pdf::PDFInteger> selectedPages = dialog.getSelectedPages(); std::vector<pdf::PDFInteger> selectedPages = dialog.getSelectedPages();