mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Copy Annotation onto Multiple Pages
This commit is contained in:
@ -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
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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()))
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
@ -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
|
@ -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">
|
@ -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
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
Reference in New Issue
Block a user