From 19dd761f35ccfc370bf9c526449021f86fa3095d Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Wed, 30 Dec 2020 17:06:13 +0100 Subject: [PATCH] Copy Annotation onto Multiple Pages --- Pdf4QtLib/Pdf4QtLib.pro | 5 ++- Pdf4QtLib/sources/pdfannotation.cpp | 36 +++++++++++++++++++ Pdf4QtLib/sources/pdfdocumentbuilder.cpp | 30 ++++++++++++++++ Pdf4QtLib/sources/pdfdocumentbuilder.h | 5 +++ Pdf4QtLib/sources/pdfredact.cpp | 10 +++--- .../sources/pdfselectpagesdialog.cpp | 29 +++++++++------ .../sources/pdfselectpagesdialog.h | 27 +++++++------- .../sources/pdfselectpagesdialog.ui | 16 +++------ .../RedactPlugin/RedactPlugin.pro | 9 ++--- .../RedactPlugin/redactplugin.cpp | 4 +-- 10 files changed, 124 insertions(+), 47 deletions(-) rename Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.cpp => Pdf4QtLib/sources/pdfselectpagesdialog.cpp (74%) rename Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.h => Pdf4QtLib/sources/pdfselectpagesdialog.h (63%) rename Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.ui => Pdf4QtLib/sources/pdfselectpagesdialog.ui (84%) diff --git a/Pdf4QtLib/Pdf4QtLib.pro b/Pdf4QtLib/Pdf4QtLib.pro index fd3d152..ec96324 100644 --- a/Pdf4QtLib/Pdf4QtLib.pro +++ b/Pdf4QtLib/Pdf4QtLib.pro @@ -76,6 +76,7 @@ SOURCES += \ sources/pdfprogress.cpp \ sources/pdfredact.cpp \ sources/pdfsecurityhandler.cpp \ + sources/pdfselectpagesdialog.cpp \ sources/pdfsignaturehandler.cpp \ sources/pdfsnapper.cpp \ sources/pdfstructuretree.cpp \ @@ -143,6 +144,7 @@ HEADERS += \ sources/pdfprogress.h \ sources/pdfredact.h \ sources/pdfsecurityhandler.h \ + sources/pdfselectpagesdialog.h \ sources/pdfsignaturehandler.h \ sources/pdfsignaturehandler_impl.h \ sources/pdfsnapper.h \ @@ -174,7 +176,8 @@ HEADERS += \ sources/pdfimage.h FORMS += \ - sources/pdfrenderingerrorswidget.ui + sources/pdfrenderingerrorswidget.ui \ + sources/pdfselectpagesdialog.ui RESOURCES += cmaps.qrc diff --git a/Pdf4QtLib/sources/pdfannotation.cpp b/Pdf4QtLib/sources/pdfannotation.cpp index a840891..2cd9ca5 100644 --- a/Pdf4QtLib/sources/pdfannotation.cpp +++ b/Pdf4QtLib/sources/pdfannotation.cpp @@ -29,6 +29,7 @@ #include "pdfpainterutils.h" #include "pdfdocumentbuilder.h" #include "pdfobjecteditorwidget.h" +#include "pdfselectpagesdialog.h" #include #include @@ -2010,7 +2011,42 @@ void PDFWidgetAnnotationManager::onShowPopupAnnotation() 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 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() diff --git a/Pdf4QtLib/sources/pdfdocumentbuilder.cpp b/Pdf4QtLib/sources/pdfdocumentbuilder.cpp index 39a5ac4..88882ad 100644 --- a/Pdf4QtLib/sources/pdfdocumentbuilder.cpp +++ b/Pdf4QtLib/sources/pdfdocumentbuilder.cpp @@ -1111,6 +1111,36 @@ PDFObjectReference PDFDocumentBuilder::getDocumentInfo() const 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 { if (const PDFDictionary* trailerDictionary = getDictionaryFromObject(m_storage.getTrailerDictionary())) diff --git a/Pdf4QtLib/sources/pdfdocumentbuilder.h b/Pdf4QtLib/sources/pdfdocumentbuilder.h index ec60226..4e7d159 100644 --- a/Pdf4QtLib/sources/pdfdocumentbuilder.h +++ b/Pdf4QtLib/sources/pdfdocumentbuilder.h @@ -416,6 +416,11 @@ public: /// Returns document info reference 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 */ /// Appends a new page after last page. diff --git a/Pdf4QtLib/sources/pdfredact.cpp b/Pdf4QtLib/sources/pdfredact.cpp index cde2ff1..92b0cbc 100644 --- a/Pdf4QtLib/sources/pdfredact.cpp +++ b/Pdf4QtLib/sources/pdfredact.cpp @@ -78,9 +78,7 @@ PDFDocument PDFRedact::perform(Options options) } builder.setPageRotation(newPageReference, page->getPageRotation()); - // TODO: Popisek redakce anotace, Overlay text // TODO: Redact searched text - // TODO: Duplikace redakce na vice stranek PDFPageContentStreamBuilder contentStreamBuilder(&builder); @@ -131,7 +129,12 @@ PDFDocument PDFRedact::perform(Options options) 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(); @@ -141,5 +144,4 @@ PDFDocument PDFRedact::perform(Options options) return optimizer.takeOptimizedDocument(); } - } // namespace pdf diff --git a/Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.cpp b/Pdf4QtLib/sources/pdfselectpagesdialog.cpp similarity index 74% rename from Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.cpp rename to Pdf4QtLib/sources/pdfselectpagesdialog.cpp index 8588258..421328f 100644 --- a/Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.cpp +++ b/Pdf4QtLib/sources/pdfselectpagesdialog.cpp @@ -15,24 +15,31 @@ // You should have received a copy of the GNU Lesser General Public License // along with Pdf4Qt. If not, see . -#include "selectpagestoredactdialog.h" -#include "ui_selectpagestoredactdialog.h" +#include "pdfselectpagesdialog.h" +#include "ui_pdfselectpagesdialog.h" #include "pdfwidgetutils.h" #include -namespace pdfplugin +namespace pdf { -SelectPagesToRedactDialog::SelectPagesToRedactDialog(pdf::PDFInteger pageCount, const std::vector& visiblePages, QWidget* parent) : +PDFSelectPagesDialog::PDFSelectPagesDialog(QString windowTitle, + QString groupBoxTitle, + pdf::PDFInteger pageCount, + const std::vector& visiblePages, + QWidget* parent) : QDialog(parent), - ui(new Ui::SelectPagesToRedactDialog), + ui(new Ui::PDFSelectPagesDialog), m_pageCount(pageCount), m_visiblePages(visiblePages) { ui->setupUi(this); + setWindowTitle(windowTitle); + ui->selectPagesGroupBox->setTitle(groupBoxTitle); + for (pdf::PDFInteger& pageIndex : m_visiblePages) { ++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)); updateUi(); } -SelectPagesToRedactDialog::~SelectPagesToRedactDialog() +PDFSelectPagesDialog::~PDFSelectPagesDialog() { delete ui; } -std::vector SelectPagesToRedactDialog::getSelectedPages() const +std::vector PDFSelectPagesDialog::getSelectedPages() const { std::vector result; @@ -98,12 +105,12 @@ std::vector SelectPagesToRedactDialog::getSelectedPages() const return result; } -void SelectPagesToRedactDialog::updateUi() +void PDFSelectPagesDialog::updateUi() { ui->customPageRangeEdit->setEnabled(ui->customPageRangeRadioButton->isChecked()); } -void SelectPagesToRedactDialog::accept() +void PDFSelectPagesDialog::accept() { if (ui->customPageRangeRadioButton->isChecked()) { @@ -125,4 +132,4 @@ void SelectPagesToRedactDialog::accept() QDialog::accept(); } -} // namespace pdfplugin +} // namespace pdf diff --git a/Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.h b/Pdf4QtLib/sources/pdfselectpagesdialog.h similarity index 63% rename from Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.h rename to Pdf4QtLib/sources/pdfselectpagesdialog.h index 62f7644..8a4fe4a 100644 --- a/Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.h +++ b/Pdf4QtLib/sources/pdfselectpagesdialog.h @@ -15,8 +15,8 @@ // You should have received a copy of the GNU Lesser General Public License // along with Pdf4Qt. If not, see . -#ifndef SELECTPAGESTOREDACTDIALOG_H -#define SELECTPAGESTOREDACTDIALOG_H +#ifndef PDFSELECTPAGESDIALOG_H +#define PDFSELECTPAGESDIALOG_H #include "pdfutils.h" @@ -24,19 +24,24 @@ namespace Ui { -class SelectPagesToRedactDialog; +class PDFSelectPagesDialog; } -namespace pdfplugin +namespace pdf { -class SelectPagesToRedactDialog : public QDialog +class Pdf4QtLIBSHARED_EXPORT PDFSelectPagesDialog : public QDialog { Q_OBJECT public: - explicit SelectPagesToRedactDialog(pdf::PDFInteger pageCount, const std::vector& visiblePages, QWidget* parent); - virtual ~SelectPagesToRedactDialog() override; + explicit PDFSelectPagesDialog(QString windowTitle, + QString groupBoxTitle, + pdf::PDFInteger pageCount, + const std::vector& visiblePages, + QWidget* parent); + + virtual ~PDFSelectPagesDialog() override; virtual void accept() override; @@ -45,15 +50,13 @@ public: private: void updateUi(); - Ui::SelectPagesToRedactDialog* ui; + Ui::PDFSelectPagesDialog* ui; pdf::PDFInteger m_pageCount; std::vector m_visiblePages; std::vector m_evenPages; std::vector m_oddPages; - - }; -} // namespace pdfplugin +} // namespace pdf -#endif // SELECTPAGESTOREDACTDIALOG_H +#endif // PDFSELECTPAGESDIALOG_H diff --git a/Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.ui b/Pdf4QtLib/sources/pdfselectpagesdialog.ui similarity index 84% rename from Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.ui rename to Pdf4QtLib/sources/pdfselectpagesdialog.ui index 6559f15..315f558 100644 --- a/Pdf4QtViewerPlugins/RedactPlugin/selectpagestoredactdialog.ui +++ b/Pdf4QtLib/sources/pdfselectpagesdialog.ui @@ -1,7 +1,7 @@ - SelectPagesToRedactDialog - + PDFSelectPagesDialog + 0 @@ -10,15 +10,9 @@ 218 - - Redact Pages - - - - Page Range to be Redacted - + @@ -94,7 +88,7 @@ buttonBox accepted() - SelectPagesToRedactDialog + PDFSelectPagesDialog accept() @@ -110,7 +104,7 @@ buttonBox rejected() - SelectPagesToRedactDialog + PDFSelectPagesDialog reject() diff --git a/Pdf4QtViewerPlugins/RedactPlugin/RedactPlugin.pro b/Pdf4QtViewerPlugins/RedactPlugin/RedactPlugin.pro index c03032a..f34a8f8 100644 --- a/Pdf4QtViewerPlugins/RedactPlugin/RedactPlugin.pro +++ b/Pdf4QtViewerPlugins/RedactPlugin/RedactPlugin.pro @@ -34,13 +34,11 @@ CONFIG += c++11 SOURCES += \ createredacteddocumentdialog.cpp \ - redactplugin.cpp \ - selectpagestoredactdialog.cpp + redactplugin.cpp HEADERS += \ createredacteddocumentdialog.h \ - redactplugin.h \ - selectpagestoredactdialog.h + redactplugin.h CONFIG += force_debug_info @@ -51,7 +49,6 @@ RESOURCES += \ icons.qrc FORMS += \ - createredacteddocumentdialog.ui \ - selectpagestoredactdialog.ui + createredacteddocumentdialog.ui diff --git a/Pdf4QtViewerPlugins/RedactPlugin/redactplugin.cpp b/Pdf4QtViewerPlugins/RedactPlugin/redactplugin.cpp index 088bcca..93f1744 100644 --- a/Pdf4QtViewerPlugins/RedactPlugin/redactplugin.cpp +++ b/Pdf4QtViewerPlugins/RedactPlugin/redactplugin.cpp @@ -16,7 +16,6 @@ // along with Pdf4Qt. If not, see . #include "redactplugin.h" -#include "selectpagestoredactdialog.h" #include "createredacteddocumentdialog.h" #include "pdfdrawwidget.h" @@ -24,6 +23,7 @@ #include "pdfdocumentbuilder.h" #include "pdfredact.h" #include "pdfdocumentwriter.h" +#include "pdfselectpagesdialog.h" #include #include @@ -96,7 +96,7 @@ void RedactPlugin::updateActions() 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) { std::vector selectedPages = dialog.getSelectedPages();