mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-04-12 17:41:49 +02:00
DocDiff application: draw differences onto pages
This commit is contained in:
parent
bafcc36d3f
commit
e838f5130a
@ -46,7 +46,8 @@ SOURCES += \
|
|||||||
differencesdockwidget.cpp \
|
differencesdockwidget.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
mainwindow.cpp \
|
mainwindow.cpp \
|
||||||
settingsdockwidget.cpp
|
settingsdockwidget.cpp \
|
||||||
|
utils.cpp
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
aboutdialog.ui \
|
aboutdialog.ui \
|
||||||
@ -59,7 +60,8 @@ HEADERS += \
|
|||||||
differencesdockwidget.h \
|
differencesdockwidget.h \
|
||||||
mainwindow.h \
|
mainwindow.h \
|
||||||
settings.h \
|
settings.h \
|
||||||
settingsdockwidget.h
|
settingsdockwidget.h \
|
||||||
|
utils.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc
|
resources.qrc
|
||||||
|
@ -52,7 +52,8 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||||||
m_diff(nullptr),
|
m_diff(nullptr),
|
||||||
m_isChangingProgressStep(false),
|
m_isChangingProgressStep(false),
|
||||||
m_dontDisplayErrorMessage(false),
|
m_dontDisplayErrorMessage(false),
|
||||||
m_diffNavigator(nullptr)
|
m_diffNavigator(nullptr),
|
||||||
|
m_drawInterface(&m_settings, &m_documentMapper, &m_filteredDiffResult)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||||||
m_pdfWidget = new pdf::PDFWidget(m_cmsManager, pdf::RendererEngine::Software, 1, ui->documentFrame);
|
m_pdfWidget = new pdf::PDFWidget(m_cmsManager, pdf::RendererEngine::Software, 1, ui->documentFrame);
|
||||||
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
|
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
|
||||||
ui->documentFrame->layout()->addWidget(m_pdfWidget);
|
ui->documentFrame->layout()->addWidget(m_pdfWidget);
|
||||||
|
m_pdfWidget->getDrawWidgetProxy()->registerDrawInterface(&m_drawInterface);
|
||||||
|
|
||||||
ui->menuView->addSeparator();
|
ui->menuView->addSeparator();
|
||||||
ui->menuView->addAction(m_settingsDockWidget->toggleViewAction());
|
ui->menuView->addAction(m_settingsDockWidget->toggleViewAction());
|
||||||
@ -752,255 +754,4 @@ void MainWindow::onProgressFinished()
|
|||||||
m_progressTaskbarIndicator->hide();
|
m_progressTaskbarIndicator->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
|
|
||||||
bool filterDifferences,
|
|
||||||
const pdf::PDFDiffResult& diff,
|
|
||||||
const pdf::PDFDocument* leftDocument,
|
|
||||||
const pdf::PDFDocument* rightDocument,
|
|
||||||
const pdf::PDFDocument* currentDocument)
|
|
||||||
{
|
|
||||||
m_layout.clear();
|
|
||||||
|
|
||||||
m_leftPageIndices.clear();
|
|
||||||
m_rightPageIndices.clear();
|
|
||||||
|
|
||||||
m_allLeft = false;
|
|
||||||
m_allRight = false;
|
|
||||||
|
|
||||||
if (!leftDocument || !rightDocument || !currentDocument)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jakub Melka
|
|
||||||
pdf::PDFDiffResult::PageSequence pageSequence = diff.getPageSequence();
|
|
||||||
const bool isEmpty = pageSequence.empty();
|
|
||||||
|
|
||||||
if (filterDifferences)
|
|
||||||
{
|
|
||||||
pdf::PDFDiffResult::PageSequence filteredPageSequence;
|
|
||||||
|
|
||||||
std::vector<pdf::PDFInteger> leftPageIndices = diff.getChangedLeftPageIndices();
|
|
||||||
std::vector<pdf::PDFInteger> rightPageIndices = diff.getChangedRightPageIndices();
|
|
||||||
|
|
||||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
|
||||||
{
|
|
||||||
const bool isLeftModified = std::binary_search(leftPageIndices.cbegin(), leftPageIndices.cend(), item.leftPage);
|
|
||||||
const bool isRightModified = std::binary_search(rightPageIndices.cbegin(), rightPageIndices.cend(), item.rightPage);
|
|
||||||
|
|
||||||
if (isLeftModified || isRightModified)
|
|
||||||
{
|
|
||||||
filteredPageSequence.push_back(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pageSequence = std::move(filteredPageSequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case ComparedDocumentMapper::Mode::Left:
|
|
||||||
{
|
|
||||||
Q_ASSERT(leftDocument == currentDocument);
|
|
||||||
|
|
||||||
m_allLeft = true;
|
|
||||||
double yPos = 0.0;
|
|
||||||
const pdf::PDFCatalog* catalog = leftDocument->getCatalog();
|
|
||||||
|
|
||||||
if (isEmpty)
|
|
||||||
{
|
|
||||||
// Just copy all pages
|
|
||||||
const size_t pageCount = catalog->getPageCount();
|
|
||||||
for (size_t i = 0; i < pageCount; ++i)
|
|
||||||
{
|
|
||||||
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
|
||||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
m_layout.emplace_back(0, i, rect);
|
|
||||||
yPos += pageSize.height() + 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
|
||||||
{
|
|
||||||
if (item.leftPage == -1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
|
||||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
m_layout.emplace_back(0, item.leftPage, rect);
|
|
||||||
yPos += pageSize.height() + 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ComparedDocumentMapper::Mode::Right:
|
|
||||||
{
|
|
||||||
Q_ASSERT(rightDocument == currentDocument);
|
|
||||||
|
|
||||||
m_allRight = true;
|
|
||||||
double yPos = 0.0;
|
|
||||||
const pdf::PDFCatalog* catalog = rightDocument->getCatalog();
|
|
||||||
|
|
||||||
if (isEmpty)
|
|
||||||
{
|
|
||||||
// Just copy all pages
|
|
||||||
const size_t pageCount = catalog->getPageCount();
|
|
||||||
for (size_t i = 0; i < pageCount; ++i)
|
|
||||||
{
|
|
||||||
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
|
||||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
m_layout.emplace_back(0, i, rect);
|
|
||||||
yPos += pageSize.height() + 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
|
||||||
{
|
|
||||||
if (item.rightPage == -1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSizeF pageSize = catalog->getPage(item.rightPage)->getRotatedMediaBoxMM().size();
|
|
||||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
m_layout.emplace_back(0, item.rightPage, rect);
|
|
||||||
yPos += pageSize.height() + 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ComparedDocumentMapper::Mode::Combined:
|
|
||||||
case ComparedDocumentMapper::Mode::Overlay:
|
|
||||||
{
|
|
||||||
double yPos = 0.0;
|
|
||||||
const pdf::PDFCatalog* catalog = currentDocument->getCatalog();
|
|
||||||
pdf::PDFInteger offset = leftDocument->getCatalog()->getPageCount();
|
|
||||||
|
|
||||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
|
||||||
{
|
|
||||||
double yAdvance = 0.0;
|
|
||||||
|
|
||||||
if (item.leftPage != -1)
|
|
||||||
{
|
|
||||||
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
|
||||||
QRectF rect;
|
|
||||||
if (mode == ComparedDocumentMapper::Mode::Combined)
|
|
||||||
{
|
|
||||||
rect = QRectF(-pageSize.width() - 5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
}
|
|
||||||
m_layout.emplace_back(0, item.leftPage, rect);
|
|
||||||
yAdvance = pageSize.height() + 5;
|
|
||||||
m_leftPageIndices[item.leftPage] = item.leftPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.rightPage != -1)
|
|
||||||
{
|
|
||||||
pdf::PDFInteger rightPageIndex = item.rightPage + offset;
|
|
||||||
QSizeF pageSize = catalog->getPage(rightPageIndex)->getRotatedMediaBoxMM().size();
|
|
||||||
QRectF rect;
|
|
||||||
if (mode == ComparedDocumentMapper::Mode::Combined)
|
|
||||||
{
|
|
||||||
rect = QRectF(5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
|
||||||
}
|
|
||||||
m_layout.emplace_back(0, rightPageIndex, rect);
|
|
||||||
yAdvance = qMax(yAdvance, pageSize.height() + 5);
|
|
||||||
m_rightPageIndices[rightPageIndex] = item.rightPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
yPos += yAdvance;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
Q_ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf::PDFInteger ComparedDocumentMapper::getLeftPageIndex(pdf::PDFInteger pageIndex) const
|
|
||||||
{
|
|
||||||
if (m_allLeft)
|
|
||||||
{
|
|
||||||
return pageIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = m_leftPageIndices.find(pageIndex);
|
|
||||||
if (it != m_leftPageIndices.cend())
|
|
||||||
{
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf::PDFInteger ComparedDocumentMapper::getRightPageIndex(pdf::PDFInteger pageIndex) const
|
|
||||||
{
|
|
||||||
if (m_allRight)
|
|
||||||
{
|
|
||||||
return pageIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = m_rightPageIndices.find(pageIndex);
|
|
||||||
if (it != m_rightPageIndices.cend())
|
|
||||||
{
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const
|
|
||||||
{
|
|
||||||
if (m_allLeft)
|
|
||||||
{
|
|
||||||
return leftPageIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& indexItem : m_leftPageIndices)
|
|
||||||
{
|
|
||||||
if (indexItem.second == leftPageIndex)
|
|
||||||
{
|
|
||||||
return indexItem.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const
|
|
||||||
{
|
|
||||||
if (m_allRight)
|
|
||||||
{
|
|
||||||
return rightPageIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& indexItem : m_rightPageIndices)
|
|
||||||
{
|
|
||||||
if (indexItem.second == rightPageIndex)
|
|
||||||
{
|
|
||||||
return indexItem.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace pdfdocdiff
|
} // namespace pdfdocdiff
|
||||||
|
@ -18,14 +18,12 @@
|
|||||||
#ifndef PDFDOCDIFF_MAINWINDOW_H
|
#ifndef PDFDOCDIFF_MAINWINDOW_H
|
||||||
#define PDFDOCDIFF_MAINWINDOW_H
|
#define PDFDOCDIFF_MAINWINDOW_H
|
||||||
|
|
||||||
#include "settings.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "pdfdocument.h"
|
#include "pdfdocument.h"
|
||||||
#include "pdfdiff.h"
|
|
||||||
#include "pdfdrawwidget.h"
|
#include "pdfdrawwidget.h"
|
||||||
#include "pdfcms.h"
|
#include "pdfcms.h"
|
||||||
#include "pdfoptionalcontent.h"
|
#include "pdfoptionalcontent.h"
|
||||||
#include "pdfdrawspacecontroller.h"
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSignalMapper>
|
#include <QSignalMapper>
|
||||||
@ -43,55 +41,6 @@ namespace pdfdocdiff
|
|||||||
class SettingsDockWidget;
|
class SettingsDockWidget;
|
||||||
class DifferencesDockWidget;
|
class DifferencesDockWidget;
|
||||||
|
|
||||||
class ComparedDocumentMapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum class Mode
|
|
||||||
{
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
Combined,
|
|
||||||
Overlay
|
|
||||||
};
|
|
||||||
|
|
||||||
void update(Mode mode,
|
|
||||||
bool filterDifferences,
|
|
||||||
const pdf::PDFDiffResult& diff,
|
|
||||||
const pdf::PDFDocument* leftDocument,
|
|
||||||
const pdf::PDFDocument* rightDocument,
|
|
||||||
const pdf::PDFDocument* currentDocument);
|
|
||||||
|
|
||||||
const pdf::PDFDrawSpaceController::LayoutItems& getLayout() const { return m_layout; }
|
|
||||||
void setPageSequence(const pdf::PDFDiffResult::PageSequence& sequence) { m_pageSequence = sequence; }
|
|
||||||
|
|
||||||
/// Returns left page index (that means page index in left document),
|
|
||||||
/// if it doesn't exist, -1 is returned.
|
|
||||||
/// \param pageIndex Actual page index
|
|
||||||
pdf::PDFInteger getLeftPageIndex(pdf::PDFInteger pageIndex) const;
|
|
||||||
|
|
||||||
/// Returns right page index (that means page index in right document),
|
|
||||||
/// if it doesn't exist, -1 is returned.
|
|
||||||
/// \param pageIndex Actual page index
|
|
||||||
pdf::PDFInteger getRightPageIndex(pdf::PDFInteger pageIndex) const;
|
|
||||||
|
|
||||||
/// Returns actual page index from left page index, or -1.
|
|
||||||
/// \param leftPageIndex Left page index
|
|
||||||
pdf::PDFInteger getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const;
|
|
||||||
|
|
||||||
/// Returns actual page index from right page index, or -1.
|
|
||||||
/// \param rightPageIndex Right page index
|
|
||||||
pdf::PDFInteger getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
pdf::PDFDrawSpaceController::LayoutItems m_layout;
|
|
||||||
bool m_allLeft = false;
|
|
||||||
bool m_allRight = false;
|
|
||||||
std::map<pdf::PDFInteger, pdf::PDFInteger> m_leftPageIndices;
|
|
||||||
std::map<pdf::PDFInteger, pdf::PDFInteger> m_rightPageIndices;
|
|
||||||
pdf::PDFDiffResult::PageSequence m_pageSequence;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -190,6 +139,7 @@ private:
|
|||||||
pdf::PDFDiffResult m_filteredDiffResult; ///< Difference result with filters applied
|
pdf::PDFDiffResult m_filteredDiffResult; ///< Difference result with filters applied
|
||||||
pdf::PDFDiffResultNavigator m_diffNavigator; ///< Difference navigator
|
pdf::PDFDiffResultNavigator m_diffNavigator; ///< Difference navigator
|
||||||
ComparedDocumentMapper m_documentMapper;
|
ComparedDocumentMapper m_documentMapper;
|
||||||
|
DifferencesDrawInterface m_drawInterface;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdfdocdiff
|
} // namespace pdfdocdiff
|
||||||
|
378
Pdf4QtDocDiff/utils.cpp
Normal file
378
Pdf4QtDocDiff/utils.cpp
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
// Copyright (C) 2021 Jakub Melka
|
||||||
|
//
|
||||||
|
// This file is part of PDF4QT.
|
||||||
|
//
|
||||||
|
// PDF4QT 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
|
||||||
|
// with the written consent of the copyright owner, any later version.
|
||||||
|
//
|
||||||
|
// PDF4QT 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 PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace pdfdocdiff
|
||||||
|
{
|
||||||
|
|
||||||
|
void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
|
||||||
|
bool filterDifferences,
|
||||||
|
const pdf::PDFDiffResult& diff,
|
||||||
|
const pdf::PDFDocument* leftDocument,
|
||||||
|
const pdf::PDFDocument* rightDocument,
|
||||||
|
const pdf::PDFDocument* currentDocument)
|
||||||
|
{
|
||||||
|
m_layout.clear();
|
||||||
|
|
||||||
|
m_leftPageIndices.clear();
|
||||||
|
m_rightPageIndices.clear();
|
||||||
|
|
||||||
|
m_allLeft = false;
|
||||||
|
m_allRight = false;
|
||||||
|
|
||||||
|
if (!leftDocument || !rightDocument || !currentDocument)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jakub Melka
|
||||||
|
pdf::PDFDiffResult::PageSequence pageSequence = diff.getPageSequence();
|
||||||
|
const bool isEmpty = pageSequence.empty();
|
||||||
|
|
||||||
|
if (filterDifferences)
|
||||||
|
{
|
||||||
|
pdf::PDFDiffResult::PageSequence filteredPageSequence;
|
||||||
|
|
||||||
|
std::vector<pdf::PDFInteger> leftPageIndices = diff.getChangedLeftPageIndices();
|
||||||
|
std::vector<pdf::PDFInteger> rightPageIndices = diff.getChangedRightPageIndices();
|
||||||
|
|
||||||
|
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||||
|
{
|
||||||
|
const bool isLeftModified = std::binary_search(leftPageIndices.cbegin(), leftPageIndices.cend(), item.leftPage);
|
||||||
|
const bool isRightModified = std::binary_search(rightPageIndices.cbegin(), rightPageIndices.cend(), item.rightPage);
|
||||||
|
|
||||||
|
if (isLeftModified || isRightModified)
|
||||||
|
{
|
||||||
|
filteredPageSequence.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pageSequence = std::move(filteredPageSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case ComparedDocumentMapper::Mode::Left:
|
||||||
|
{
|
||||||
|
Q_ASSERT(leftDocument == currentDocument);
|
||||||
|
|
||||||
|
m_allLeft = true;
|
||||||
|
double yPos = 0.0;
|
||||||
|
const pdf::PDFCatalog* catalog = leftDocument->getCatalog();
|
||||||
|
|
||||||
|
if (isEmpty)
|
||||||
|
{
|
||||||
|
// Just copy all pages
|
||||||
|
const size_t pageCount = catalog->getPageCount();
|
||||||
|
for (size_t i = 0; i < pageCount; ++i)
|
||||||
|
{
|
||||||
|
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
||||||
|
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
m_layout.emplace_back(0, i, rect);
|
||||||
|
yPos += pageSize.height() + 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||||
|
{
|
||||||
|
if (item.leftPage == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
||||||
|
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
m_layout.emplace_back(0, item.leftPage, rect);
|
||||||
|
yPos += pageSize.height() + 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ComparedDocumentMapper::Mode::Right:
|
||||||
|
{
|
||||||
|
Q_ASSERT(rightDocument == currentDocument);
|
||||||
|
|
||||||
|
m_allRight = true;
|
||||||
|
double yPos = 0.0;
|
||||||
|
const pdf::PDFCatalog* catalog = rightDocument->getCatalog();
|
||||||
|
|
||||||
|
if (isEmpty)
|
||||||
|
{
|
||||||
|
// Just copy all pages
|
||||||
|
const size_t pageCount = catalog->getPageCount();
|
||||||
|
for (size_t i = 0; i < pageCount; ++i)
|
||||||
|
{
|
||||||
|
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
||||||
|
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
m_layout.emplace_back(0, i, rect);
|
||||||
|
yPos += pageSize.height() + 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||||
|
{
|
||||||
|
if (item.rightPage == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF pageSize = catalog->getPage(item.rightPage)->getRotatedMediaBoxMM().size();
|
||||||
|
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
m_layout.emplace_back(0, item.rightPage, rect);
|
||||||
|
yPos += pageSize.height() + 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ComparedDocumentMapper::Mode::Combined:
|
||||||
|
case ComparedDocumentMapper::Mode::Overlay:
|
||||||
|
{
|
||||||
|
double yPos = 0.0;
|
||||||
|
const pdf::PDFCatalog* catalog = currentDocument->getCatalog();
|
||||||
|
pdf::PDFInteger offset = leftDocument->getCatalog()->getPageCount();
|
||||||
|
|
||||||
|
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||||
|
{
|
||||||
|
double yAdvance = 0.0;
|
||||||
|
|
||||||
|
if (item.leftPage != -1)
|
||||||
|
{
|
||||||
|
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
||||||
|
QRectF rect;
|
||||||
|
if (mode == ComparedDocumentMapper::Mode::Combined)
|
||||||
|
{
|
||||||
|
rect = QRectF(-pageSize.width() - 5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
}
|
||||||
|
m_layout.emplace_back(0, item.leftPage, rect);
|
||||||
|
yAdvance = pageSize.height() + 5;
|
||||||
|
m_leftPageIndices[item.leftPage] = item.leftPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.rightPage != -1)
|
||||||
|
{
|
||||||
|
pdf::PDFInteger rightPageIndex = item.rightPage + offset;
|
||||||
|
QSizeF pageSize = catalog->getPage(rightPageIndex)->getRotatedMediaBoxMM().size();
|
||||||
|
QRectF rect;
|
||||||
|
if (mode == ComparedDocumentMapper::Mode::Combined)
|
||||||
|
{
|
||||||
|
rect = QRectF(5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||||
|
}
|
||||||
|
m_layout.emplace_back(0, rightPageIndex, rect);
|
||||||
|
yAdvance = qMax(yAdvance, pageSize.height() + 5);
|
||||||
|
m_rightPageIndices[rightPageIndex] = item.rightPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
yPos += yAdvance;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf::PDFInteger ComparedDocumentMapper::getLeftPageIndex(pdf::PDFInteger pageIndex) const
|
||||||
|
{
|
||||||
|
if (m_allLeft)
|
||||||
|
{
|
||||||
|
return pageIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_leftPageIndices.find(pageIndex);
|
||||||
|
if (it != m_leftPageIndices.cend())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf::PDFInteger ComparedDocumentMapper::getRightPageIndex(pdf::PDFInteger pageIndex) const
|
||||||
|
{
|
||||||
|
if (m_allRight)
|
||||||
|
{
|
||||||
|
return pageIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_rightPageIndices.find(pageIndex);
|
||||||
|
if (it != m_rightPageIndices.cend())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const
|
||||||
|
{
|
||||||
|
if (m_allLeft)
|
||||||
|
{
|
||||||
|
return leftPageIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& indexItem : m_leftPageIndices)
|
||||||
|
{
|
||||||
|
if (indexItem.second == leftPageIndex)
|
||||||
|
{
|
||||||
|
return indexItem.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const
|
||||||
|
{
|
||||||
|
if (m_allRight)
|
||||||
|
{
|
||||||
|
return rightPageIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& indexItem : m_rightPageIndices)
|
||||||
|
{
|
||||||
|
if (indexItem.second == rightPageIndex)
|
||||||
|
{
|
||||||
|
return indexItem.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DifferencesDrawInterface::DifferencesDrawInterface(const Settings* settings,
|
||||||
|
const ComparedDocumentMapper* mapper,
|
||||||
|
const pdf::PDFDiffResult* diffResult) :
|
||||||
|
m_settings(settings),
|
||||||
|
m_mapper(mapper),
|
||||||
|
m_diffResult(diffResult)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DifferencesDrawInterface::drawPage(QPainter* painter,
|
||||||
|
pdf::PDFInteger pageIndex,
|
||||||
|
const pdf::PDFPrecompiledPage* compiledPage,
|
||||||
|
pdf::PDFTextLayoutGetter& layoutGetter,
|
||||||
|
const QMatrix& pagePointToDevicePointMatrix,
|
||||||
|
QList<pdf::PDFRenderError>& errors) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(compiledPage);
|
||||||
|
Q_UNUSED(layoutGetter);
|
||||||
|
Q_UNUSED(errors);
|
||||||
|
|
||||||
|
const size_t differencesCount = m_diffResult->getDifferencesCount();
|
||||||
|
const pdf::PDFInteger leftPageIndex = m_mapper->getLeftPageIndex(pageIndex);
|
||||||
|
const pdf::PDFInteger rightPageIndex = m_mapper->getRightPageIndex(pageIndex);
|
||||||
|
|
||||||
|
if (leftPageIndex != -1)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < differencesCount; ++i)
|
||||||
|
{
|
||||||
|
auto leftRectangles = m_diffResult->getLeftRectangles(i);
|
||||||
|
for (auto it = leftRectangles.first; it != leftRectangles.second; ++it)
|
||||||
|
{
|
||||||
|
const auto& item = *it;
|
||||||
|
if (item.first == leftPageIndex)
|
||||||
|
{
|
||||||
|
drawRectangle(painter, pagePointToDevicePointMatrix, item.second, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightPageIndex != -1)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < differencesCount; ++i)
|
||||||
|
{
|
||||||
|
auto rightRectangles = m_diffResult->getRightRectangles(i);
|
||||||
|
for (auto it = rightRectangles.first; it != rightRectangles.second; ++it)
|
||||||
|
{
|
||||||
|
const auto& item = *it;
|
||||||
|
if (item.first == rightPageIndex)
|
||||||
|
{
|
||||||
|
drawRectangle(painter, pagePointToDevicePointMatrix, item.second, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor DifferencesDrawInterface::getColorForIndex(size_t index) const
|
||||||
|
{
|
||||||
|
QColor color;
|
||||||
|
|
||||||
|
const size_t resultIndex = index;
|
||||||
|
|
||||||
|
if (m_diffResult->isReplaceDifference(resultIndex))
|
||||||
|
{
|
||||||
|
color = m_settings->colorReplaced;
|
||||||
|
}
|
||||||
|
else if (m_diffResult->isRemoveDifference(resultIndex))
|
||||||
|
{
|
||||||
|
color = m_settings->colorRemoved;
|
||||||
|
}
|
||||||
|
else if (m_diffResult->isAddDifference(resultIndex))
|
||||||
|
{
|
||||||
|
color = m_settings->colorAdded;
|
||||||
|
}
|
||||||
|
else if (m_diffResult->isPageMoveDifference(resultIndex))
|
||||||
|
{
|
||||||
|
color = m_settings->colorPageMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DifferencesDrawInterface::drawPostRendering(QPainter* painter, QRect rect) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(painter);
|
||||||
|
Q_UNUSED(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DifferencesDrawInterface::drawRectangle(QPainter* painter,
|
||||||
|
const QMatrix& pagePointToDevicePointMatrix,
|
||||||
|
const QRectF& rect,
|
||||||
|
size_t resultIndex) const
|
||||||
|
{
|
||||||
|
QColor color = getColorForIndex(resultIndex);
|
||||||
|
color.setAlphaF(0.3);
|
||||||
|
|
||||||
|
QRectF resultRect = pagePointToDevicePointMatrix.mapRect(rect);
|
||||||
|
painter->fillRect(resultRect, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pdfdocdiff
|
107
Pdf4QtDocDiff/utils.h
Normal file
107
Pdf4QtDocDiff/utils.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright (C) 2021 Jakub Melka
|
||||||
|
//
|
||||||
|
// This file is part of PDF4QT.
|
||||||
|
//
|
||||||
|
// PDF4QT 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
|
||||||
|
// with the written consent of the copyright owner, any later version.
|
||||||
|
//
|
||||||
|
// PDF4QT 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 PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
#include "pdfdiff.h"
|
||||||
|
#include "pdfdrawspacecontroller.h"
|
||||||
|
#include "pdfdocumentdrawinterface.h"
|
||||||
|
|
||||||
|
namespace pdfdocdiff
|
||||||
|
{
|
||||||
|
|
||||||
|
class ComparedDocumentMapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class Mode
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Combined,
|
||||||
|
Overlay
|
||||||
|
};
|
||||||
|
|
||||||
|
void update(Mode mode,
|
||||||
|
bool filterDifferences,
|
||||||
|
const pdf::PDFDiffResult& diff,
|
||||||
|
const pdf::PDFDocument* leftDocument,
|
||||||
|
const pdf::PDFDocument* rightDocument,
|
||||||
|
const pdf::PDFDocument* currentDocument);
|
||||||
|
|
||||||
|
const pdf::PDFDrawSpaceController::LayoutItems& getLayout() const { return m_layout; }
|
||||||
|
void setPageSequence(const pdf::PDFDiffResult::PageSequence& sequence) { m_pageSequence = sequence; }
|
||||||
|
|
||||||
|
/// Returns left page index (that means page index in left document),
|
||||||
|
/// if it doesn't exist, -1 is returned.
|
||||||
|
/// \param pageIndex Actual page index
|
||||||
|
pdf::PDFInteger getLeftPageIndex(pdf::PDFInteger pageIndex) const;
|
||||||
|
|
||||||
|
/// Returns right page index (that means page index in right document),
|
||||||
|
/// if it doesn't exist, -1 is returned.
|
||||||
|
/// \param pageIndex Actual page index
|
||||||
|
pdf::PDFInteger getRightPageIndex(pdf::PDFInteger pageIndex) const;
|
||||||
|
|
||||||
|
/// Returns actual page index from left page index, or -1.
|
||||||
|
/// \param leftPageIndex Left page index
|
||||||
|
pdf::PDFInteger getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const;
|
||||||
|
|
||||||
|
/// Returns actual page index from right page index, or -1.
|
||||||
|
/// \param rightPageIndex Right page index
|
||||||
|
pdf::PDFInteger getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pdf::PDFDrawSpaceController::LayoutItems m_layout;
|
||||||
|
bool m_allLeft = false;
|
||||||
|
bool m_allRight = false;
|
||||||
|
std::map<pdf::PDFInteger, pdf::PDFInteger> m_leftPageIndices;
|
||||||
|
std::map<pdf::PDFInteger, pdf::PDFInteger> m_rightPageIndices;
|
||||||
|
pdf::PDFDiffResult::PageSequence m_pageSequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DifferencesDrawInterface : public pdf::IDocumentDrawInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DifferencesDrawInterface(const Settings* settings,
|
||||||
|
const ComparedDocumentMapper* mapper,
|
||||||
|
const pdf::PDFDiffResult* diffResult);
|
||||||
|
|
||||||
|
virtual void drawPage(QPainter* painter, pdf::PDFInteger pageIndex,
|
||||||
|
const pdf::PDFPrecompiledPage* compiledPage,
|
||||||
|
pdf::PDFTextLayoutGetter& layoutGetter,
|
||||||
|
const QMatrix& pagePointToDevicePointMatrix,
|
||||||
|
QList<pdf::PDFRenderError>& errors) const override;
|
||||||
|
virtual void drawPostRendering(QPainter* painter, QRect rect) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void drawRectangle(QPainter* painter,
|
||||||
|
const QMatrix& pagePointToDevicePointMatrix,
|
||||||
|
const QRectF& rect,
|
||||||
|
size_t resultIndex) const;
|
||||||
|
|
||||||
|
QColor getColorForIndex(size_t index) const;
|
||||||
|
|
||||||
|
const Settings* m_settings;
|
||||||
|
const ComparedDocumentMapper* m_mapper;
|
||||||
|
const pdf::PDFDiffResult* m_diffResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pdfdocdiff
|
||||||
|
|
||||||
|
#endif // UTILS_H
|
@ -1180,6 +1180,42 @@ PDFInteger PDFDiffResult::getRightPage(size_t index) const
|
|||||||
return m_differences[index].pageIndex2;
|
return m_differences[index].pageIndex2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<PDFDiffResult::RectInfosIt, PDFDiffResult::RectInfosIt> PDFDiffResult::getLeftRectangles(size_t index) const
|
||||||
|
{
|
||||||
|
if (index >= m_differences.size())
|
||||||
|
{
|
||||||
|
return std::make_pair(m_rects.cend(), m_rects.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Difference& difference = m_differences[index];
|
||||||
|
if (difference.leftRectCount > 0)
|
||||||
|
{
|
||||||
|
auto it = std::next(m_rects.cbegin(), difference.leftRectIndex);
|
||||||
|
auto itEnd = std::next(it, difference.leftRectCount);
|
||||||
|
return std::make_pair(it, itEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(m_rects.cend(), m_rects.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<PDFDiffResult::RectInfosIt, PDFDiffResult::RectInfosIt> PDFDiffResult::getRightRectangles(size_t index) const
|
||||||
|
{
|
||||||
|
if (index >= m_differences.size())
|
||||||
|
{
|
||||||
|
return std::make_pair(m_rects.cend(), m_rects.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Difference& difference = m_differences[index];
|
||||||
|
if (difference.rightRectCount > 0)
|
||||||
|
{
|
||||||
|
auto it = std::next(m_rects.cbegin(), difference.rightRectIndex);
|
||||||
|
auto itEnd = std::next(it, difference.rightRectCount);
|
||||||
|
return std::make_pair(it, itEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(m_rects.cend(), m_rects.cend());
|
||||||
|
}
|
||||||
|
|
||||||
bool PDFDiffResult::isPageMoveDifference(size_t index) const
|
bool PDFDiffResult::isPageMoveDifference(size_t index) const
|
||||||
{
|
{
|
||||||
return getTypeFlags(index) & FLAGS_TYPE_PAGE_MOVE;
|
return getTypeFlags(index) & FLAGS_TYPE_PAGE_MOVE;
|
||||||
|
@ -68,6 +68,7 @@ public:
|
|||||||
using PageSequence = std::vector<PageSequenceItem>;
|
using PageSequence = std::vector<PageSequenceItem>;
|
||||||
|
|
||||||
using RectInfos = std::vector<std::pair<PDFInteger, QRectF>>;
|
using RectInfos = std::vector<std::pair<PDFInteger, QRectF>>;
|
||||||
|
using RectInfosIt = typename RectInfos::const_iterator;
|
||||||
|
|
||||||
void setResult(PDFOperationResult result) { m_result = std::move(result); }
|
void setResult(PDFOperationResult result) { m_result = std::move(result); }
|
||||||
const PDFOperationResult& getResult() const { return m_result; }
|
const PDFOperationResult& getResult() const { return m_result; }
|
||||||
@ -95,6 +96,12 @@ public:
|
|||||||
/// \param index Index
|
/// \param index Index
|
||||||
PDFInteger getRightPage(size_t index) const;
|
PDFInteger getRightPage(size_t index) const;
|
||||||
|
|
||||||
|
/// Returns iterator range for rectangles of "left" pages of an item
|
||||||
|
std::pair<RectInfosIt, RectInfosIt> getLeftRectangles(size_t index) const;
|
||||||
|
|
||||||
|
/// Returns iterator range for rectangles of "right" pages of an item
|
||||||
|
std::pair<RectInfosIt, RectInfosIt> getRightRectangles(size_t index) const;
|
||||||
|
|
||||||
bool isPageMoveDifference(size_t index) const;
|
bool isPageMoveDifference(size_t index) const;
|
||||||
bool isAddDifference(size_t index) const;
|
bool isAddDifference(size_t index) const;
|
||||||
bool isRemoveDifference(size_t index) const;
|
bool isRemoveDifference(size_t index) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user