2021-05-24 07:25:56 +00:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: 2004 Enrico Ros <eros.kde@email.it>
|
2021-06-03 18:33:18 +00:00
|
|
|
|
|
|
|
Work sponsored by the LiMux project of the city of Munich:
|
2021-05-24 11:41:08 +00:00
|
|
|
SPDX-FileCopyrightText: 2017 Klarälvdalens Datakonsult AB a KDAB Group company <info@kdab.com>
|
2021-05-24 07:25:56 +00:00
|
|
|
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2004-09-08 12:41:14 +00:00
|
|
|
|
2007-04-19 18:30:20 +00:00
|
|
|
#include "page.h"
|
|
|
|
#include "page_p.h"
|
|
|
|
|
2004-11-06 01:19:35 +00:00
|
|
|
// qt/kde includes
|
2018-08-31 09:23:45 +00:00
|
|
|
#include <QDomDocument>
|
|
|
|
#include <QDomElement>
|
|
|
|
#include <QHash>
|
|
|
|
#include <QPixmap>
|
|
|
|
#include <QSet>
|
|
|
|
#include <QString>
|
|
|
|
#include <QUuid>
|
|
|
|
#include <QVariant>
|
2006-09-21 08:45:36 +00:00
|
|
|
|
2018-08-31 09:23:45 +00:00
|
|
|
#include <QDebug>
|
2004-09-08 12:41:14 +00:00
|
|
|
|
|
|
|
// local includes
|
2007-04-20 11:26:05 +00:00
|
|
|
#include "action.h"
|
2006-09-21 08:45:36 +00:00
|
|
|
#include "annotations.h"
|
2007-07-17 18:10:25 +00:00
|
|
|
#include "annotations_p.h"
|
2008-01-20 16:39:21 +00:00
|
|
|
#include "debug_p.h"
|
2012-05-06 17:54:42 +00:00
|
|
|
#include "document.h"
|
2012-05-13 22:50:41 +00:00
|
|
|
#include "document_p.h"
|
2007-02-25 00:07:59 +00:00
|
|
|
#include "form.h"
|
2007-07-04 11:41:45 +00:00
|
|
|
#include "form_p.h"
|
2012-07-11 05:14:50 +00:00
|
|
|
#include "observer.h"
|
2007-03-24 10:47:22 +00:00
|
|
|
#include "pagecontroller_p.h"
|
2007-01-05 23:12:06 +00:00
|
|
|
#include "pagesize.h"
|
2005-01-02 22:33:28 +00:00
|
|
|
#include "pagetransition.h"
|
2007-07-04 14:39:52 +00:00
|
|
|
#include "rotationjob_p.h"
|
2007-09-03 19:58:30 +00:00
|
|
|
#include "textpage_p.h"
|
2012-11-08 20:29:09 +00:00
|
|
|
#include "tile.h"
|
2012-08-17 18:23:58 +00:00
|
|
|
#include "tilesmanager_p.h"
|
2013-12-29 22:27:30 +00:00
|
|
|
#include "utils_p.h"
|
2004-09-08 12:41:14 +00:00
|
|
|
|
2009-03-23 12:05:00 +00:00
|
|
|
#include <limits>
|
|
|
|
|
2007-03-30 14:27:22 +00:00
|
|
|
#ifdef PAGE_PROFILE
|
2018-08-31 09:23:45 +00:00
|
|
|
#include <QTime>
|
2007-03-30 14:27:22 +00:00
|
|
|
#endif
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
using namespace Okular;
|
|
|
|
|
2013-06-23 17:19:25 +00:00
|
|
|
static const double distanceConsideredEqual = 25; // 5px
|
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
static void deleteObjectRects(QList<ObjectRect *> &rects, const QSet<ObjectRect::ObjectType> &which)
|
2006-09-19 17:17:29 +00:00
|
|
|
{
|
2022-03-31 14:16:40 +00:00
|
|
|
QList<ObjectRect *>::iterator it = rects.begin();
|
|
|
|
for (; it != rects.end();) {
|
2006-09-19 17:17:29 +00:00
|
|
|
if (which.contains((*it)->objectType())) {
|
|
|
|
delete *it;
|
|
|
|
it = rects.erase(it);
|
|
|
|
} else {
|
|
|
|
++it;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
|
|
|
}
|
2006-09-19 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
2007-03-24 00:18:54 +00:00
|
|
|
PagePrivate::PagePrivate(Page *page, uint n, double w, double h, Rotation o)
|
2014-02-19 22:40:43 +00:00
|
|
|
: m_page(page)
|
|
|
|
, m_number(n)
|
|
|
|
, m_orientation(o)
|
2017-09-05 21:27:18 +00:00
|
|
|
, m_width(w)
|
|
|
|
, m_height(h)
|
|
|
|
, m_doc(nullptr)
|
|
|
|
, m_boundingBox(0, 0, 1, 1)
|
2012-04-13 18:02:34 +00:00
|
|
|
, m_rotation(Rotation0)
|
2017-09-05 21:27:18 +00:00
|
|
|
, m_text(nullptr)
|
|
|
|
, m_transition(nullptr)
|
|
|
|
, m_textSelections(nullptr)
|
|
|
|
, m_openingAction(nullptr)
|
|
|
|
, m_closingAction(nullptr)
|
|
|
|
, m_duration(-1)
|
2008-05-18 23:06:21 +00:00
|
|
|
, m_isBoundingBoxKnown(false)
|
2006-11-23 19:25:52 +00:00
|
|
|
{
|
2007-03-24 00:18:54 +00:00
|
|
|
// avoid Division-By-Zero problems in the program
|
|
|
|
if (m_width <= 0) {
|
|
|
|
m_width = 1;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-11-23 19:25:52 +00:00
|
|
|
|
2007-03-24 00:18:54 +00:00
|
|
|
if (m_height <= 0) {
|
|
|
|
m_height = 1;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-03-24 00:18:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PagePrivate::~PagePrivate()
|
|
|
|
{
|
|
|
|
qDeleteAll(formfields);
|
|
|
|
delete m_openingAction;
|
|
|
|
delete m_closingAction;
|
|
|
|
delete m_text;
|
|
|
|
delete m_transition;
|
|
|
|
}
|
2006-11-23 19:25:52 +00:00
|
|
|
|
2017-03-02 23:32:08 +00:00
|
|
|
PagePrivate *PagePrivate::get(Page *page)
|
|
|
|
{
|
2017-12-05 22:07:10 +00:00
|
|
|
return page ? page->d : nullptr;
|
2017-03-02 23:32:08 +00:00
|
|
|
}
|
2006-11-23 19:25:52 +00:00
|
|
|
|
2007-03-24 10:47:22 +00:00
|
|
|
void PagePrivate::imageRotationDone(RotationJob *job)
|
2006-11-23 19:25:52 +00:00
|
|
|
{
|
2014-02-19 22:40:43 +00:00
|
|
|
TilesManager *tm = tilesManager(job->observer());
|
2012-08-17 17:25:58 +00:00
|
|
|
if (tm) {
|
|
|
|
QPixmap *pixmap = new QPixmap(QPixmap::fromImage(job->image()));
|
2018-02-01 18:42:37 +00:00
|
|
|
tm->setPixmap(pixmap, job->rect(), job->isPartialUpdate());
|
2012-08-17 17:25:58 +00:00
|
|
|
delete pixmap;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-24 21:58:53 +00:00
|
|
|
QMap<DocumentObserver *, PixmapObject>::iterator it = m_pixmaps.find(job->observer());
|
2007-03-25 22:36:41 +00:00
|
|
|
if (it != m_pixmaps.end()) {
|
|
|
|
PixmapObject &object = it.value();
|
2006-11-23 19:25:52 +00:00
|
|
|
(*object.m_pixmap) = QPixmap::fromImage(job->image());
|
|
|
|
object.m_rotation = job->rotation();
|
2020-02-23 23:12:53 +00:00
|
|
|
object.m_isPartialPixmap = job->isPartialUpdate();
|
2006-11-23 19:25:52 +00:00
|
|
|
} else {
|
2007-03-25 22:36:41 +00:00
|
|
|
PixmapObject object;
|
2006-11-23 19:25:52 +00:00
|
|
|
object.m_pixmap = new QPixmap(QPixmap::fromImage(job->image()));
|
|
|
|
object.m_rotation = job->rotation();
|
2020-02-23 23:12:53 +00:00
|
|
|
object.m_isPartialPixmap = job->isPartialUpdate();
|
2006-11-23 19:25:52 +00:00
|
|
|
|
2013-02-24 21:58:53 +00:00
|
|
|
m_pixmaps.insert(job->observer(), object);
|
2006-11-23 19:25:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-08 15:06:02 +00:00
|
|
|
QTransform PagePrivate::rotationMatrix() const
|
2006-11-23 19:25:52 +00:00
|
|
|
{
|
2013-12-29 22:27:30 +00:00
|
|
|
return Okular::buildRotationMatrix(m_rotation);
|
2006-11-23 19:25:52 +00:00
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
/** class Page **/
|
2004-12-10 16:04:45 +00:00
|
|
|
|
2019-12-20 15:40:59 +00:00
|
|
|
Page::Page(uint pageNumber, double w, double h, Rotation o)
|
|
|
|
: d(new PagePrivate(this, pageNumber, w, h, o))
|
2004-09-08 12:41:14 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
Page::~Page()
|
2004-09-08 12:41:14 +00:00
|
|
|
{
|
2017-10-26 07:47:18 +00:00
|
|
|
if (d) {
|
|
|
|
deletePixmaps();
|
|
|
|
deleteRects();
|
|
|
|
d->deleteHighlights();
|
|
|
|
deleteAnnotations();
|
|
|
|
d->deleteTextSelections();
|
|
|
|
deleteSourceReferences();
|
|
|
|
|
|
|
|
delete d;
|
|
|
|
}
|
2006-11-23 19:25:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Page::number() const
|
|
|
|
{
|
|
|
|
return d->m_number;
|
|
|
|
}
|
|
|
|
|
2007-01-05 17:09:47 +00:00
|
|
|
Rotation Page::orientation() const
|
2006-11-23 19:25:52 +00:00
|
|
|
{
|
|
|
|
return d->m_orientation;
|
|
|
|
}
|
|
|
|
|
2007-01-05 17:09:47 +00:00
|
|
|
Rotation Page::rotation() const
|
2006-11-23 19:25:52 +00:00
|
|
|
{
|
|
|
|
return d->m_rotation;
|
|
|
|
}
|
|
|
|
|
2007-01-05 17:09:47 +00:00
|
|
|
Rotation Page::totalOrientation() const
|
2006-11-23 19:25:52 +00:00
|
|
|
{
|
2007-01-05 17:09:47 +00:00
|
|
|
return (Rotation)(((int)d->m_orientation + (int)d->m_rotation) % 4);
|
2004-09-08 12:41:14 +00:00
|
|
|
}
|
|
|
|
|
2006-11-23 19:25:52 +00:00
|
|
|
double Page::width() const
|
|
|
|
{
|
|
|
|
return d->m_width;
|
|
|
|
}
|
|
|
|
|
|
|
|
double Page::height() const
|
|
|
|
{
|
|
|
|
return d->m_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
double Page::ratio() const
|
|
|
|
{
|
|
|
|
return d->m_height / d->m_width;
|
|
|
|
}
|
2004-09-15 20:45:00 +00:00
|
|
|
|
2008-05-18 23:06:21 +00:00
|
|
|
NormalizedRect Page::boundingBox() const
|
|
|
|
{
|
|
|
|
return d->m_boundingBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Page::isBoundingBoxKnown() const
|
|
|
|
{
|
|
|
|
return d->m_isBoundingBoxKnown;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Page::setBoundingBox(const NormalizedRect &bbox)
|
|
|
|
{
|
|
|
|
if (d->m_isBoundingBoxKnown && d->m_boundingBox == bbox) {
|
|
|
|
return;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2008-05-18 23:06:21 +00:00
|
|
|
|
|
|
|
// Allow tiny rounding errors (happens during rotation)
|
|
|
|
static const double epsilon = 0.00001;
|
|
|
|
Q_ASSERT(bbox.left >= -epsilon && bbox.top >= -epsilon && bbox.right <= 1 + epsilon && bbox.bottom <= 1 + epsilon);
|
|
|
|
|
|
|
|
d->m_boundingBox = bbox & NormalizedRect(0., 0., 1., 1.);
|
|
|
|
d->m_isBoundingBoxKnown = true;
|
|
|
|
}
|
|
|
|
|
2013-02-24 21:58:53 +00:00
|
|
|
bool Page::hasPixmap(DocumentObserver *observer, int width, int height, const NormalizedRect &rect) const
|
2004-09-16 21:04:49 +00:00
|
|
|
{
|
2014-02-19 22:40:43 +00:00
|
|
|
TilesManager *tm = d->tilesManager(observer);
|
2012-07-12 05:20:03 +00:00
|
|
|
if (tm) {
|
2012-07-11 05:14:50 +00:00
|
|
|
if (width != tm->width() || height != tm->height()) {
|
2012-07-07 17:40:52 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tm->hasPixmap(rect);
|
|
|
|
}
|
|
|
|
|
2013-02-24 21:58:53 +00:00
|
|
|
QMap<DocumentObserver *, PagePrivate::PixmapObject>::const_iterator it = d->m_pixmaps.constFind(observer);
|
2007-08-13 22:25:27 +00:00
|
|
|
if (it == d->m_pixmaps.constEnd()) {
|
2004-09-16 21:04:49 +00:00
|
|
|
return false;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-11-03 17:57:32 +00:00
|
|
|
|
2004-12-21 12:38:52 +00:00
|
|
|
if (width == -1 || height == -1) {
|
|
|
|
return true;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-11-03 17:57:32 +00:00
|
|
|
|
2020-02-23 23:12:53 +00:00
|
|
|
if (it.value().m_isPartialPixmap) {
|
|
|
|
return false;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2020-02-23 23:12:53 +00:00
|
|
|
|
2006-11-24 21:42:56 +00:00
|
|
|
const QPixmap *pixmap = it.value().m_pixmap;
|
2006-11-03 17:57:32 +00:00
|
|
|
|
2012-08-24 16:31:01 +00:00
|
|
|
return (pixmap->width() == width && pixmap->height() == height);
|
2004-09-16 21:04:49 +00:00
|
|
|
}
|
|
|
|
|
2022-11-24 00:52:53 +00:00
|
|
|
void Page::setPageSize(DocumentObserver *observer, int width, int height)
|
|
|
|
{
|
|
|
|
TilesManager *tm = d->tilesManager(observer);
|
|
|
|
if (tm) {
|
|
|
|
tm->setSize(width, height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-23 16:09:26 +00:00
|
|
|
bool Page::hasTextPage() const
|
2004-12-10 16:04:45 +00:00
|
|
|
{
|
2017-09-05 21:27:18 +00:00
|
|
|
return d->m_text != nullptr;
|
2004-12-10 16:04:45 +00:00
|
|
|
}
|
|
|
|
|
2024-03-04 12:22:25 +00:00
|
|
|
std::unique_ptr<RegularAreaRect> Page::wordAt(const NormalizedPoint &p) const
|
2012-03-25 21:48:07 +00:00
|
|
|
{
|
|
|
|
if (d->m_text) {
|
2024-03-04 12:22:25 +00:00
|
|
|
return d->m_text->wordAt(p);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2012-03-25 21:48:07 +00:00
|
|
|
|
2017-09-05 21:27:18 +00:00
|
|
|
return nullptr;
|
2012-03-25 21:48:07 +00:00
|
|
|
}
|
|
|
|
|
2024-03-04 12:22:25 +00:00
|
|
|
std::unique_ptr<RegularAreaRect> Page::textArea(const TextSelection &selection) const
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
{
|
2006-11-23 19:25:52 +00:00
|
|
|
if (d->m_text) {
|
|
|
|
return d->m_text->textArea(selection);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-11-23 17:11:04 +00:00
|
|
|
|
2017-09-05 21:27:18 +00:00
|
|
|
return nullptr;
|
- GIGANTIC 2700 line diff with LOTS OF FEATURES!
- 1. editor-like text selection, and I do mean it, its not pseudo-editor
(like the ones acroread and kviewshell have) it doesnt intersect the
selection area with words under it, no, it does a lot more, including
work on cursors and searching for the text area closest to the given
cursor
- 2. rotation support, change the orientation of the documents if
you need too :)
- 3. the kfaxview backend works beautifully, porting kviewshell backends
is damn easy ! djvu and dvi will be next!
- 4. Hardware Blending of selection rectangles! We now use XRender
instead of KImageEffect, makes a damn faster blend!
- 5. Overview mode - as seen in Kviewshell, but quite a bit extended,
the kviewshell is only one state, while we support it in both
continous and non-continous form
- BTW. I coded all those features myself, (apart from kfaxview backend library)
it is an impressive bit right? but oKular cant be run by only one person,
join in on the fun! i can introduce you into the code just mail niedakh@gmail.com
svn path=/trunk/playground/graphics/oKular/kpdf/; revision=509871
2006-02-15 18:54:49 +00:00
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
bool Page::hasObjectRect(double x, double y, double xScale, double yScale) const
|
2004-09-16 21:04:49 +00:00
|
|
|
{
|
2006-09-19 17:17:29 +00:00
|
|
|
if (m_rects.isEmpty()) {
|
2004-10-02 14:30:30 +00:00
|
|
|
return false;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-11-23 19:25:52 +00:00
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
for (ObjectRect *rect : m_rects) {
|
|
|
|
if (rect->distanceSqr(x, y, xScale, yScale) < distanceConsideredEqual) {
|
2004-10-02 14:30:30 +00:00
|
|
|
return true;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
|
|
|
}
|
2006-11-23 19:25:52 +00:00
|
|
|
|
2004-10-02 14:30:30 +00:00
|
|
|
return false;
|
2004-09-16 21:04:49 +00:00
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
bool Page::hasHighlights(int s_id) const
|
2004-10-20 16:27:20 +00:00
|
|
|
{
|
2005-02-08 15:24:23 +00:00
|
|
|
// simple case: have no highlights
|
|
|
|
if (m_highlights.isEmpty()) {
|
|
|
|
return false;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-02-08 15:24:23 +00:00
|
|
|
// simple case: we have highlights and no id to match
|
|
|
|
if (s_id == -1) {
|
|
|
|
return true;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-02-08 15:24:23 +00:00
|
|
|
// iterate on the highlights list to find an entry by id
|
2022-03-31 14:16:40 +00:00
|
|
|
for (HighlightAreaRect *highlight : m_highlights) {
|
|
|
|
if (highlight->s_id == s_id) {
|
2005-02-08 15:24:23 +00:00
|
|
|
return true;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
|
|
|
}
|
2005-02-08 15:24:23 +00:00
|
|
|
return false;
|
2004-10-20 16:27:20 +00:00
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
bool Page::hasTransition() const
|
2005-01-02 20:32:58 +00:00
|
|
|
{
|
2017-09-05 21:27:18 +00:00
|
|
|
return d->m_transition != nullptr;
|
2004-11-06 00:56:55 +00:00
|
|
|
}
|
|
|
|
|
2006-11-23 19:25:52 +00:00
|
|
|
bool Page::hasAnnotations() const
|
|
|
|
{
|
|
|
|
return !m_annotations.isEmpty();
|
|
|
|
}
|
2004-09-08 12:41:14 +00:00
|
|
|
|
2006-11-23 16:54:28 +00:00
|
|
|
RegularAreaRect *Page::findText(int id, const QString &text, SearchDirection direction, Qt::CaseSensitivity caseSensitivity, const RegularAreaRect *lastRect) const
|
2004-09-08 12:41:14 +00:00
|
|
|
{
|
2017-09-05 21:27:18 +00:00
|
|
|
RegularAreaRect *rect = nullptr;
|
2007-09-03 19:38:46 +00:00
|
|
|
if (text.isEmpty() || !d->m_text) {
|
2006-11-23 16:54:28 +00:00
|
|
|
return rect;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-11-23 16:54:28 +00:00
|
|
|
|
2006-11-23 19:25:52 +00:00
|
|
|
rect = d->m_text->findText(id, text, direction, caseSensitivity, lastRect);
|
2006-11-23 16:54:28 +00:00
|
|
|
return rect;
|
2005-02-08 15:24:23 +00:00
|
|
|
}
|
|
|
|
|
2006-11-23 17:11:04 +00:00
|
|
|
QString Page::text(const RegularAreaRect *area) const
|
2009-11-12 21:48:43 +00:00
|
|
|
{
|
|
|
|
return text(area, TextPage::AnyPixelTextAreaInclusionBehaviour);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Page::text(const RegularAreaRect *area, TextPage::TextAreaInclusionBehaviour b) const
|
2005-02-08 15:24:23 +00:00
|
|
|
{
|
2006-11-23 16:54:28 +00:00
|
|
|
QString ret;
|
2005-07-15 18:20:57 +00:00
|
|
|
|
2006-11-23 19:25:52 +00:00
|
|
|
if (!d->m_text) {
|
2006-11-23 16:54:28 +00:00
|
|
|
return ret;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-07-15 18:20:57 +00:00
|
|
|
|
2007-01-31 14:29:28 +00:00
|
|
|
if (area) {
|
|
|
|
RegularAreaRect rotatedArea = *area;
|
|
|
|
rotatedArea.transform(d->rotationMatrix().inverted());
|
2006-12-29 18:18:07 +00:00
|
|
|
|
2009-11-12 21:48:43 +00:00
|
|
|
ret = d->m_text->text(&rotatedArea, b);
|
2007-01-31 14:29:28 +00:00
|
|
|
} else {
|
2017-09-05 21:27:18 +00:00
|
|
|
ret = d->m_text->text(nullptr, b);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-07-15 18:20:57 +00:00
|
|
|
|
2006-11-23 16:54:28 +00:00
|
|
|
return ret;
|
2005-02-08 15:24:23 +00:00
|
|
|
}
|
|
|
|
|
2011-10-31 15:33:03 +00:00
|
|
|
TextEntity::List Page::words(const RegularAreaRect *area, TextPage::TextAreaInclusionBehaviour b) const
|
|
|
|
{
|
|
|
|
TextEntity::List ret;
|
|
|
|
|
|
|
|
if (!d->m_text) {
|
|
|
|
return ret;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2011-10-31 15:33:03 +00:00
|
|
|
|
|
|
|
if (area) {
|
|
|
|
RegularAreaRect rotatedArea = *area;
|
|
|
|
rotatedArea.transform(d->rotationMatrix().inverted());
|
|
|
|
|
|
|
|
ret = d->m_text->words(&rotatedArea, b);
|
|
|
|
} else {
|
2017-09-05 21:27:18 +00:00
|
|
|
ret = d->m_text->words(nullptr, b);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2011-10-31 15:33:03 +00:00
|
|
|
|
2020-01-02 23:16:36 +00:00
|
|
|
for (auto &retI : ret) {
|
2024-02-07 14:07:08 +00:00
|
|
|
retI = TextEntity(retI.text(), Okular::NormalizedRect(retI.transformedArea(d->rotationMatrix())));
|
2011-10-31 15:33:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-05-01 23:36:57 +00:00
|
|
|
void PagePrivate::rotateAt(Rotation orientation)
|
2006-10-08 15:07:23 +00:00
|
|
|
{
|
2007-05-01 23:36:57 +00:00
|
|
|
if (orientation == m_rotation) {
|
2006-10-08 15:07:23 +00:00
|
|
|
return;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-10-08 15:07:23 +00:00
|
|
|
|
2007-09-03 23:47:12 +00:00
|
|
|
deleteTextSelections();
|
2006-11-23 22:14:04 +00:00
|
|
|
|
2007-05-01 23:36:57 +00:00
|
|
|
if (((int)m_orientation + (int)m_rotation) % 2 != ((int)m_orientation + (int)orientation) % 2) {
|
2023-01-26 13:53:23 +00:00
|
|
|
std::swap(m_width, m_height);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-10-08 15:07:23 +00:00
|
|
|
|
2007-09-03 18:32:07 +00:00
|
|
|
Rotation oldRotation = m_rotation;
|
2007-05-01 23:36:57 +00:00
|
|
|
m_rotation = orientation;
|
2006-11-20 07:53:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Rotate the images of the page.
|
|
|
|
*/
|
2013-02-24 21:58:53 +00:00
|
|
|
QMapIterator<DocumentObserver *, PagePrivate::PixmapObject> it(m_pixmaps);
|
2006-10-25 15:35:53 +00:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
|
2007-03-25 22:36:41 +00:00
|
|
|
const PagePrivate::PixmapObject &object = it.value();
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2007-05-01 23:36:57 +00:00
|
|
|
RotationJob *job = new RotationJob(object.m_pixmap->toImage(), object.m_rotation, m_rotation, it.key());
|
|
|
|
job->setPage(this);
|
2013-07-30 15:00:32 +00:00
|
|
|
m_doc->m_pageController->addRotationJob(job);
|
2006-10-25 15:35:53 +00:00
|
|
|
}
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2012-08-17 17:25:58 +00:00
|
|
|
/**
|
2012-11-08 19:46:47 +00:00
|
|
|
* Rotate tiles manager
|
2012-08-17 17:25:58 +00:00
|
|
|
*/
|
2014-02-19 22:40:43 +00:00
|
|
|
QMapIterator<const DocumentObserver *, TilesManager *> i(m_tilesManagers);
|
|
|
|
while (i.hasNext()) {
|
|
|
|
i.next();
|
|
|
|
|
|
|
|
TilesManager *tm = i.value();
|
|
|
|
if (tm) {
|
|
|
|
tm->setRotation(m_rotation);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2014-02-19 22:40:43 +00:00
|
|
|
}
|
2012-08-17 17:25:58 +00:00
|
|
|
|
2006-11-20 07:53:32 +00:00
|
|
|
/**
|
|
|
|
* Rotate the object rects on the page.
|
|
|
|
*/
|
2012-09-08 15:06:02 +00:00
|
|
|
const QTransform matrix = rotationMatrix();
|
2023-12-19 08:58:22 +00:00
|
|
|
for (ObjectRect *objRect : std::as_const(m_page->m_rects)) {
|
2020-02-20 09:15:24 +00:00
|
|
|
objRect->transform(matrix);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-09-03 18:32:07 +00:00
|
|
|
|
2018-04-16 22:28:31 +00:00
|
|
|
const QTransform highlightRotationMatrix = Okular::buildRotationMatrix((Rotation)(((int)m_rotation - (int)oldRotation + 4) % 4));
|
2023-12-19 08:58:22 +00:00
|
|
|
for (HighlightAreaRect *hlar : std::as_const(m_page->m_highlights)) {
|
2020-02-20 09:15:24 +00:00
|
|
|
hlar->transform(highlightRotationMatrix);
|
2007-09-03 18:32:07 +00:00
|
|
|
}
|
2006-10-08 15:07:23 +00:00
|
|
|
}
|
|
|
|
|
2007-05-01 23:36:57 +00:00
|
|
|
void PagePrivate::changeSize(const PageSize &size)
|
2007-01-05 23:12:06 +00:00
|
|
|
{
|
2007-05-01 23:36:57 +00:00
|
|
|
if (size.isNull() || (size.width() == m_width && size.height() == m_height)) {
|
2007-01-05 23:12:06 +00:00
|
|
|
return;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-01-05 23:12:06 +00:00
|
|
|
|
2007-05-01 23:36:57 +00:00
|
|
|
m_page->deletePixmaps();
|
2007-01-05 23:12:06 +00:00
|
|
|
// deleteHighlights();
|
|
|
|
// deleteTextSelections();
|
|
|
|
|
2007-05-01 23:36:57 +00:00
|
|
|
m_width = size.width();
|
|
|
|
m_height = size.height();
|
|
|
|
if (m_rotation % 2) {
|
2023-01-26 13:53:23 +00:00
|
|
|
std::swap(m_width, m_height);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-01-05 23:12:06 +00:00
|
|
|
}
|
|
|
|
|
2006-11-23 17:11:04 +00:00
|
|
|
const ObjectRect *Page::objectRect(ObjectRect::ObjectType type, double x, double y, double xScale, double yScale) const
|
2005-02-08 15:24:23 +00:00
|
|
|
{
|
2013-07-01 20:04:42 +00:00
|
|
|
// Walk list in reverse order so that annotations in the foreground are preferred
|
2022-03-31 14:16:40 +00:00
|
|
|
QListIterator<ObjectRect *> it(m_rects);
|
2013-07-01 20:04:42 +00:00
|
|
|
it.toBack();
|
|
|
|
while (it.hasPrevious()) {
|
|
|
|
const ObjectRect *objrect = it.previous();
|
|
|
|
if ((objrect->objectType() == type) && objrect->distanceSqr(x, y, xScale, yScale) < distanceConsideredEqual) {
|
|
|
|
return objrect;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2013-07-01 20:04:42 +00:00
|
|
|
}
|
|
|
|
|
2017-09-05 21:27:18 +00:00
|
|
|
return nullptr;
|
2004-09-08 12:41:14 +00:00
|
|
|
}
|
|
|
|
|
2022-03-19 18:14:39 +00:00
|
|
|
QList<const ObjectRect *> Page::objectRects(ObjectRect::ObjectType type, double x, double y, double xScale, double yScale) const
|
2012-06-29 10:39:42 +00:00
|
|
|
{
|
2022-03-19 18:14:39 +00:00
|
|
|
QList<const ObjectRect *> result;
|
2012-06-29 10:39:42 +00:00
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
QListIterator<ObjectRect *> it(m_rects);
|
2013-07-01 20:04:42 +00:00
|
|
|
it.toBack();
|
|
|
|
while (it.hasPrevious()) {
|
|
|
|
const ObjectRect *objrect = it.previous();
|
|
|
|
if ((objrect->objectType() == type) && objrect->distanceSqr(x, y, xScale, yScale) < distanceConsideredEqual) {
|
|
|
|
result.append(objrect);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2013-07-01 20:04:42 +00:00
|
|
|
}
|
2012-06-29 10:39:42 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2009-03-23 12:05:00 +00:00
|
|
|
const ObjectRect *Page::nearestObjectRect(ObjectRect::ObjectType type, double x, double y, double xScale, double yScale, double *distance) const
|
|
|
|
{
|
2017-09-05 21:27:18 +00:00
|
|
|
ObjectRect *res = nullptr;
|
2009-03-23 12:05:00 +00:00
|
|
|
double minDistance = std::numeric_limits<double>::max();
|
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
for (ObjectRect *rect : m_rects) {
|
|
|
|
if (rect->objectType() == type) {
|
|
|
|
double d = rect->distanceSqr(x, y, xScale, yScale);
|
2009-03-23 12:05:00 +00:00
|
|
|
if (d < minDistance) {
|
2022-03-31 14:16:40 +00:00
|
|
|
res = rect;
|
2009-03-23 12:05:00 +00:00
|
|
|
minDistance = d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (distance) {
|
|
|
|
*distance = minDistance;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2009-03-23 12:05:00 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2006-11-23 17:11:04 +00:00
|
|
|
const PageTransition *Page::transition() const
|
2005-02-08 15:24:23 +00:00
|
|
|
{
|
2006-11-23 19:25:52 +00:00
|
|
|
return d->m_transition;
|
2005-02-08 15:24:23 +00:00
|
|
|
}
|
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
QList<Annotation *> Page::annotations() const
|
2006-10-09 18:02:59 +00:00
|
|
|
{
|
2006-11-23 19:25:52 +00:00
|
|
|
return m_annotations;
|
|
|
|
}
|
|
|
|
|
2017-10-25 13:21:46 +00:00
|
|
|
Annotation *Page::annotation(const QString &uniqueName) const
|
|
|
|
{
|
2019-12-09 13:16:55 +00:00
|
|
|
for (Annotation *a : m_annotations) {
|
2017-10-25 13:21:46 +00:00
|
|
|
if (a->uniqueName() == uniqueName) {
|
|
|
|
return a;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2017-10-25 13:21:46 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2007-04-20 12:37:12 +00:00
|
|
|
const Action *Page::pageAction(PageAction action) const
|
2006-11-23 19:25:52 +00:00
|
|
|
{
|
|
|
|
switch (action) {
|
2006-10-09 18:02:59 +00:00
|
|
|
case Page::Opening:
|
2006-11-23 19:25:52 +00:00
|
|
|
return d->m_openingAction;
|
2006-10-09 18:02:59 +00:00
|
|
|
break;
|
|
|
|
case Page::Closing:
|
2006-11-23 19:25:52 +00:00
|
|
|
return d->m_closingAction;
|
2006-10-09 18:02:59 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-11-23 19:25:52 +00:00
|
|
|
|
2017-09-05 21:27:18 +00:00
|
|
|
return nullptr;
|
2006-10-09 18:02:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-21 23:59:42 +00:00
|
|
|
QList<FormField *> Page::formFields() const
|
2007-02-25 00:07:59 +00:00
|
|
|
{
|
|
|
|
return d->formfields;
|
|
|
|
}
|
|
|
|
|
2013-02-24 21:58:53 +00:00
|
|
|
void Page::setPixmap(DocumentObserver *observer, QPixmap *pixmap, const NormalizedRect &rect)
|
2006-10-25 15:35:53 +00:00
|
|
|
{
|
2018-02-01 18:42:37 +00:00
|
|
|
d->setPixmap(observer, pixmap, rect, false /*isPartialPixmap*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PagePrivate::setPixmap(DocumentObserver *observer, QPixmap *pixmap, const NormalizedRect &rect, bool isPartialPixmap)
|
|
|
|
{
|
|
|
|
if (m_rotation == Rotation0) {
|
|
|
|
TilesManager *tm = tilesManager(observer);
|
2012-08-17 17:25:58 +00:00
|
|
|
if (tm) {
|
2018-02-01 18:42:37 +00:00
|
|
|
tm->setPixmap(pixmap, rect, isPartialPixmap);
|
2012-08-17 17:25:58 +00:00
|
|
|
delete pixmap;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-01 18:42:37 +00:00
|
|
|
QMap<DocumentObserver *, PagePrivate::PixmapObject>::iterator it = m_pixmaps.find(observer);
|
|
|
|
if (it != m_pixmaps.end()) {
|
2007-01-09 23:37:26 +00:00
|
|
|
delete it.value().m_pixmap;
|
|
|
|
} else {
|
2018-02-01 18:42:37 +00:00
|
|
|
it = m_pixmaps.insert(observer, PagePrivate::PixmapObject());
|
2007-01-09 23:37:26 +00:00
|
|
|
}
|
|
|
|
it.value().m_pixmap = pixmap;
|
2018-02-01 18:42:37 +00:00
|
|
|
it.value().m_rotation = m_rotation;
|
2020-02-23 23:12:53 +00:00
|
|
|
it.value().m_isPartialPixmap = isPartialPixmap;
|
2006-11-03 17:57:32 +00:00
|
|
|
} else {
|
2017-10-03 07:29:18 +00:00
|
|
|
// it can happen that we get a setPixmap while closing and thus the page controller is gone
|
2018-02-01 18:42:37 +00:00
|
|
|
if (m_doc->m_pageController) {
|
|
|
|
RotationJob *job = new RotationJob(pixmap->toImage(), Rotation0, m_rotation, observer);
|
|
|
|
job->setPage(this);
|
|
|
|
job->setRect(TilesManager::toRotatedRect(rect, m_rotation));
|
|
|
|
job->setIsPartialUpdate(isPartialPixmap);
|
|
|
|
m_doc->m_pageController->addRotationJob(job);
|
2017-10-03 07:29:18 +00:00
|
|
|
}
|
2006-11-20 07:53:32 +00:00
|
|
|
|
|
|
|
delete pixmap;
|
2006-11-03 17:57:32 +00:00
|
|
|
}
|
2004-09-08 12:41:14 +00:00
|
|
|
}
|
|
|
|
|
2006-11-23 19:25:52 +00:00
|
|
|
void Page::setTextPage(TextPage *textPage)
|
2004-09-08 12:41:14 +00:00
|
|
|
{
|
2006-11-23 19:25:52 +00:00
|
|
|
delete d->m_text;
|
2006-11-23 22:14:04 +00:00
|
|
|
|
2006-11-23 19:25:52 +00:00
|
|
|
d->m_text = textPage;
|
2007-09-03 18:32:07 +00:00
|
|
|
if (d->m_text) {
|
2017-12-05 22:07:10 +00:00
|
|
|
d->m_text->d->m_page = this;
|
2019-07-21 08:49:24 +00:00
|
|
|
// Correct/optimize text order for search and text selection
|
2011-10-17 17:09:26 +00:00
|
|
|
d->m_text->d->correctTextOrder();
|
2007-09-03 18:32:07 +00:00
|
|
|
}
|
2004-09-10 17:44:05 +00:00
|
|
|
}
|
2004-09-11 15:59:32 +00:00
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
void Page::setObjectRects(const QList<ObjectRect *> &rects)
|
2004-10-20 16:27:20 +00:00
|
|
|
{
|
2006-09-19 17:17:29 +00:00
|
|
|
QSet<ObjectRect::ObjectType> which;
|
2007-04-20 12:37:12 +00:00
|
|
|
which << ObjectRect::Action << ObjectRect::Image;
|
2006-09-19 17:17:29 +00:00
|
|
|
deleteObjectRects(m_rects, which);
|
2006-11-20 07:53:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Rotate the object rects of the page.
|
|
|
|
*/
|
2012-09-08 15:06:02 +00:00
|
|
|
const QTransform matrix = d->rotationMatrix();
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
for (ObjectRect *objectRect : rects) {
|
|
|
|
objectRect->transform(matrix);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-11-20 07:53:32 +00:00
|
|
|
|
2006-09-19 17:17:29 +00:00
|
|
|
m_rects << rects;
|
2004-10-20 16:27:20 +00:00
|
|
|
}
|
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
const QList<ObjectRect *> &Page::objectRects() const
|
2021-12-29 08:55:56 +00:00
|
|
|
{
|
|
|
|
return m_rects;
|
|
|
|
}
|
|
|
|
|
2007-05-05 18:07:34 +00:00
|
|
|
void PagePrivate::setHighlight(int s_id, RegularAreaRect *rect, const QColor &color)
|
2005-02-01 18:26:56 +00:00
|
|
|
{
|
2005-07-15 18:20:57 +00:00
|
|
|
HighlightAreaRect *hr = new HighlightAreaRect(rect);
|
2005-02-08 15:24:23 +00:00
|
|
|
hr->s_id = s_id;
|
|
|
|
hr->color = color;
|
2007-01-05 15:16:36 +00:00
|
|
|
|
2007-05-05 18:07:34 +00:00
|
|
|
m_page->m_highlights.append(hr);
|
2006-11-23 19:25:52 +00:00
|
|
|
}
|
2005-07-15 18:20:57 +00:00
|
|
|
|
2024-03-04 12:22:25 +00:00
|
|
|
void PagePrivate::setTextSelections(const RegularAreaRect &r, const QColor &color)
|
2006-09-26 22:22:01 +00:00
|
|
|
{
|
2007-09-03 23:47:12 +00:00
|
|
|
deleteTextSelections();
|
2024-03-04 12:22:25 +00:00
|
|
|
HighlightAreaRect *hr = new HighlightAreaRect(&r);
|
|
|
|
hr->s_id = -1;
|
|
|
|
hr->color = color;
|
|
|
|
m_textSelections = hr;
|
2006-09-26 22:22:01 +00:00
|
|
|
}
|
2005-02-01 18:26:56 +00:00
|
|
|
|
2022-03-21 23:59:42 +00:00
|
|
|
void Page::setSourceReferences(const QList<SourceRefObjectRect *> &refRects)
|
2006-11-17 22:15:15 +00:00
|
|
|
{
|
|
|
|
deleteSourceReferences();
|
2019-12-09 13:16:55 +00:00
|
|
|
for (SourceRefObjectRect *rect : refRects) {
|
2006-11-17 22:15:15 +00:00
|
|
|
m_rects << rect;
|
2019-12-09 13:16:55 +00:00
|
|
|
}
|
2006-11-17 22:15:15 +00:00
|
|
|
}
|
|
|
|
|
2006-12-31 14:41:34 +00:00
|
|
|
void Page::setDuration(double seconds)
|
2006-12-31 10:48:49 +00:00
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
d->m_duration = seconds;
|
2006-12-31 10:48:49 +00:00
|
|
|
}
|
|
|
|
|
2006-12-31 14:41:34 +00:00
|
|
|
double Page::duration() const
|
2006-12-31 10:48:49 +00:00
|
|
|
{
|
2007-01-02 17:05:49 +00:00
|
|
|
return d->m_duration;
|
2006-12-31 10:48:49 +00:00
|
|
|
}
|
|
|
|
|
2007-01-19 23:30:32 +00:00
|
|
|
void Page::setLabel(const QString &label)
|
|
|
|
{
|
|
|
|
d->m_label = label;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Page::label() const
|
|
|
|
{
|
|
|
|
return d->m_label;
|
|
|
|
}
|
|
|
|
|
2006-11-24 21:02:38 +00:00
|
|
|
const RegularAreaRect *Page::textSelection() const
|
|
|
|
{
|
2007-03-30 14:08:20 +00:00
|
|
|
return d->m_textSelections;
|
|
|
|
}
|
|
|
|
|
|
|
|
QColor Page::textSelectionColor() const
|
|
|
|
{
|
|
|
|
return d->m_textSelections ? d->m_textSelections->color : QColor();
|
2006-11-24 21:02:38 +00:00
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
void Page::addAnnotation(Annotation *annotation)
|
2005-02-18 18:24:45 +00:00
|
|
|
{
|
2012-04-13 18:02:34 +00:00
|
|
|
// Generate uniqueName: okular-{UUID}
|
2006-12-05 11:05:50 +00:00
|
|
|
if (annotation->uniqueName().isEmpty()) {
|
2016-07-11 20:07:57 +00:00
|
|
|
QString uniqueName = QStringLiteral("okular-") + QUuid::createUuid().toString();
|
2006-12-05 11:05:50 +00:00
|
|
|
annotation->setUniqueName(uniqueName);
|
2006-08-10 06:32:03 +00:00
|
|
|
}
|
2007-07-17 18:10:25 +00:00
|
|
|
annotation->d_ptr->m_page = d;
|
2005-02-18 18:24:45 +00:00
|
|
|
m_annotations.append(annotation);
|
2006-11-20 07:53:32 +00:00
|
|
|
|
|
|
|
AnnotationObjectRect *rect = new AnnotationObjectRect(annotation);
|
|
|
|
|
2007-10-07 11:00:57 +00:00
|
|
|
// Rotate the annotation on the page.
|
2012-09-08 15:06:02 +00:00
|
|
|
const QTransform matrix = d->rotationMatrix();
|
2007-10-07 15:10:58 +00:00
|
|
|
annotation->d_ptr->annotationTransform(matrix);
|
2006-11-20 07:53:32 +00:00
|
|
|
|
|
|
|
m_rects.append(rect);
|
2005-02-18 18:24:45 +00:00
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
bool Page::removeAnnotation(Annotation *annotation)
|
2006-08-10 06:32:03 +00:00
|
|
|
{
|
2012-05-13 22:50:41 +00:00
|
|
|
if (!d->m_doc->m_parent->canRemovePageAnnotation(annotation)) {
|
2006-09-14 18:42:28 +00:00
|
|
|
return false;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2006-09-14 18:42:28 +00:00
|
|
|
|
2022-03-31 14:16:40 +00:00
|
|
|
QList<Annotation *>::iterator aIt = m_annotations.begin();
|
|
|
|
for (; aIt != m_annotations.end(); ++aIt) {
|
2006-12-05 11:05:50 +00:00
|
|
|
if ((*aIt) && (*aIt)->uniqueName() == annotation->uniqueName()) {
|
2006-09-19 17:17:29 +00:00
|
|
|
int rectfound = false;
|
2022-03-31 14:16:40 +00:00
|
|
|
QList<ObjectRect *>::iterator it = m_rects.begin();
|
|
|
|
for (; it != m_rects.end() && !rectfound; ++it) {
|
2007-01-02 17:05:49 +00:00
|
|
|
if (((*it)->objectType() == ObjectRect::OAnnotation) && ((*it)->object() == (*aIt))) {
|
2006-09-19 17:17:29 +00:00
|
|
|
delete *it;
|
2006-12-23 14:57:22 +00:00
|
|
|
it = m_rects.erase(it);
|
2006-09-19 17:17:29 +00:00
|
|
|
rectfound = true;
|
|
|
|
}
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2014-09-11 17:36:01 +00:00
|
|
|
qCDebug(OkularCoreDebug) << "removed annotation:" << annotation->uniqueName();
|
2017-09-05 21:27:18 +00:00
|
|
|
annotation->d_ptr->m_page = nullptr;
|
2006-09-19 17:17:29 +00:00
|
|
|
m_annotations.erase(aIt);
|
2006-08-10 06:32:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-09-19 17:17:29 +00:00
|
|
|
|
2006-09-14 18:42:28 +00:00
|
|
|
return true;
|
2006-08-10 06:32:03 +00:00
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
void Page::setTransition(PageTransition *transition)
|
2005-01-02 20:32:58 +00:00
|
|
|
{
|
2006-11-23 19:25:52 +00:00
|
|
|
delete d->m_transition;
|
|
|
|
d->m_transition = transition;
|
2005-01-02 20:32:58 +00:00
|
|
|
}
|
|
|
|
|
2007-04-20 12:37:12 +00:00
|
|
|
void Page::setPageAction(PageAction action, Action *link)
|
2006-10-09 18:02:59 +00:00
|
|
|
{
|
2006-11-23 19:25:52 +00:00
|
|
|
switch (action) {
|
2006-10-09 18:02:59 +00:00
|
|
|
case Page::Opening:
|
2007-05-05 18:22:26 +00:00
|
|
|
delete d->m_openingAction;
|
2006-11-23 19:25:52 +00:00
|
|
|
d->m_openingAction = link;
|
2006-10-09 18:02:59 +00:00
|
|
|
break;
|
|
|
|
case Page::Closing:
|
2007-05-05 18:22:26 +00:00
|
|
|
delete d->m_closingAction;
|
2006-11-23 19:25:52 +00:00
|
|
|
d->m_closingAction = link;
|
2006-10-09 18:02:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 23:59:42 +00:00
|
|
|
void Page::setFormFields(const QList<FormField *> &fields)
|
2007-02-25 00:07:59 +00:00
|
|
|
{
|
|
|
|
qDeleteAll(d->formfields);
|
|
|
|
d->formfields = fields;
|
2023-12-19 08:58:22 +00:00
|
|
|
for (FormField *ff : std::as_const(d->formfields)) {
|
2020-02-20 09:15:24 +00:00
|
|
|
ff->d_ptr->setDefault();
|
2022-01-03 15:01:01 +00:00
|
|
|
ff->d_ptr->m_page = this;
|
2007-07-04 11:41:45 +00:00
|
|
|
}
|
2007-02-25 00:07:59 +00:00
|
|
|
}
|
|
|
|
|
2013-02-24 21:58:53 +00:00
|
|
|
void Page::deletePixmap(DocumentObserver *observer)
|
2006-11-03 17:57:32 +00:00
|
|
|
{
|
2014-02-19 22:40:43 +00:00
|
|
|
TilesManager *tm = d->tilesManager(observer);
|
|
|
|
if (tm) {
|
|
|
|
delete tm;
|
|
|
|
d->m_tilesManagers.remove(observer);
|
2012-07-16 15:57:51 +00:00
|
|
|
} else {
|
2013-02-24 21:58:53 +00:00
|
|
|
PagePrivate::PixmapObject object = d->m_pixmaps.take(observer);
|
2012-07-16 15:57:51 +00:00
|
|
|
delete object.m_pixmap;
|
|
|
|
}
|
2006-11-03 17:57:32 +00:00
|
|
|
}
|
2006-10-09 18:02:59 +00:00
|
|
|
|
2006-11-20 07:53:32 +00:00
|
|
|
void Page::deletePixmaps()
|
2004-12-21 12:38:52 +00:00
|
|
|
{
|
2013-02-24 21:58:53 +00:00
|
|
|
QMapIterator<DocumentObserver *, PagePrivate::PixmapObject> it(d->m_pixmaps);
|
2006-11-20 07:53:32 +00:00
|
|
|
while (it.hasNext()) {
|
|
|
|
it.next();
|
|
|
|
delete it.value().m_pixmap;
|
|
|
|
}
|
|
|
|
|
2007-03-25 22:36:41 +00:00
|
|
|
d->m_pixmaps.clear();
|
2014-02-19 22:40:43 +00:00
|
|
|
|
|
|
|
qDeleteAll(d->m_tilesManagers);
|
|
|
|
d->m_tilesManagers.clear();
|
2004-12-21 12:38:52 +00:00
|
|
|
}
|
|
|
|
|
2006-11-03 17:57:32 +00:00
|
|
|
void Page::deleteRects()
|
2004-11-12 10:58:33 +00:00
|
|
|
{
|
2006-09-19 17:17:29 +00:00
|
|
|
// delete ObjectRects of type Link and Image
|
|
|
|
QSet<ObjectRect::ObjectType> which;
|
2007-04-20 12:37:12 +00:00
|
|
|
which << ObjectRect::Action << ObjectRect::Image;
|
2006-09-19 17:17:29 +00:00
|
|
|
deleteObjectRects(m_rects, which);
|
2004-11-12 10:58:33 +00:00
|
|
|
}
|
|
|
|
|
2007-05-05 18:07:34 +00:00
|
|
|
void PagePrivate::deleteHighlights(int s_id)
|
2005-02-01 18:26:56 +00:00
|
|
|
{
|
|
|
|
// delete highlights by ID
|
2022-03-31 14:16:40 +00:00
|
|
|
QList<HighlightAreaRect *>::iterator it = m_page->m_highlights.begin();
|
|
|
|
while (it != m_page->m_highlights.end()) {
|
2005-07-15 18:20:57 +00:00
|
|
|
HighlightAreaRect *highlight = *it;
|
2005-02-08 15:24:23 +00:00
|
|
|
if (s_id == -1 || highlight->s_id == s_id) {
|
2007-05-05 18:07:34 +00:00
|
|
|
it = m_page->m_highlights.erase(it);
|
2005-02-01 18:26:56 +00:00
|
|
|
delete highlight;
|
|
|
|
} else {
|
|
|
|
++it;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-02-01 18:26:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-03 23:47:12 +00:00
|
|
|
void PagePrivate::deleteTextSelections()
|
2006-09-26 22:22:01 +00:00
|
|
|
{
|
2007-09-03 23:47:12 +00:00
|
|
|
delete m_textSelections;
|
2017-09-05 21:27:18 +00:00
|
|
|
m_textSelections = nullptr;
|
2006-09-26 22:22:01 +00:00
|
|
|
}
|
|
|
|
|
2006-11-17 22:15:15 +00:00
|
|
|
void Page::deleteSourceReferences()
|
|
|
|
{
|
|
|
|
deleteObjectRects(m_rects, QSet<ObjectRect::ObjectType>() << ObjectRect::SourceRef);
|
|
|
|
}
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
void Page::deleteAnnotations()
|
2005-02-18 18:24:45 +00:00
|
|
|
{
|
2006-09-19 17:17:29 +00:00
|
|
|
// delete ObjectRects of type Annotation
|
|
|
|
deleteObjectRects(m_rects, QSet<ObjectRect::ObjectType>() << ObjectRect::OAnnotation);
|
2005-02-18 18:24:45 +00:00
|
|
|
// delete all stored annotations
|
2020-02-20 09:15:24 +00:00
|
|
|
qDeleteAll(m_annotations);
|
2005-02-18 18:24:45 +00:00
|
|
|
m_annotations.clear();
|
|
|
|
}
|
|
|
|
|
2014-09-09 14:08:32 +00:00
|
|
|
bool PagePrivate::restoreLocalContents(const QDomNode &pageNode)
|
2005-03-13 13:14:44 +00:00
|
|
|
{
|
2014-09-09 14:08:32 +00:00
|
|
|
bool loadedAnything = false; // set if something actually gets loaded
|
|
|
|
|
2018-11-14 19:12:15 +00:00
|
|
|
// iterate over all children (annotationList, ...)
|
2005-03-13 13:14:44 +00:00
|
|
|
QDomNode childNode = pageNode.firstChild();
|
|
|
|
while (childNode.isElement()) {
|
|
|
|
QDomElement childElement = childNode.toElement();
|
|
|
|
childNode = childNode.nextSibling();
|
|
|
|
|
|
|
|
// parse annotationList child element
|
2015-10-29 12:37:11 +00:00
|
|
|
if (childElement.tagName() == QLatin1String("annotationList")) {
|
2007-03-30 14:27:22 +00:00
|
|
|
#ifdef PAGE_PROFILE
|
2006-11-15 15:48:49 +00:00
|
|
|
QTime time;
|
|
|
|
time.start();
|
2007-03-30 14:27:22 +00:00
|
|
|
#endif
|
2012-05-30 16:38:51 +00:00
|
|
|
// Clone annotationList as root node in restoredLocalAnnotationList
|
|
|
|
const QDomNode clonedNode = restoredLocalAnnotationList.importNode(childElement, true);
|
|
|
|
restoredLocalAnnotationList.appendChild(clonedNode);
|
2006-11-15 15:48:49 +00:00
|
|
|
|
2005-03-13 13:14:44 +00:00
|
|
|
// iterate over all annotations
|
|
|
|
QDomNode annotationNode = childElement.firstChild();
|
|
|
|
while (annotationNode.isElement()) {
|
|
|
|
// get annotation element and advance to next annot
|
|
|
|
QDomElement annotElement = annotationNode.toElement();
|
|
|
|
annotationNode = annotationNode.nextSibling();
|
|
|
|
|
2005-04-04 23:55:40 +00:00
|
|
|
// get annotation from the dom element
|
2005-04-07 19:27:54 +00:00
|
|
|
Annotation *annotation = AnnotationUtils::createAnnotation(annotElement);
|
2005-03-13 13:14:44 +00:00
|
|
|
|
|
|
|
// append annotation to the list or show warning
|
|
|
|
if (annotation) {
|
2013-04-05 22:22:48 +00:00
|
|
|
m_doc->performAddPageAnnotation(m_number, annotation);
|
2014-09-11 17:36:01 +00:00
|
|
|
qCDebug(OkularCoreDebug) << "restored annot:" << annotation->uniqueName();
|
2014-09-09 14:08:32 +00:00
|
|
|
loadedAnything = true;
|
2005-03-13 13:14:44 +00:00
|
|
|
} else {
|
2014-09-11 19:12:27 +00:00
|
|
|
qCWarning(OkularCoreDebug).nospace() << "page (" << m_number << "): can't restore an annotation from XML.";
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-03-13 13:14:44 +00:00
|
|
|
}
|
2007-03-30 14:27:22 +00:00
|
|
|
#ifdef PAGE_PROFILE
|
2014-09-11 17:36:01 +00:00
|
|
|
qCDebug(OkularCoreDebug).nospace() << "annots: XML Load time: " << time.elapsed() << "ms";
|
2007-03-30 14:27:22 +00:00
|
|
|
#endif
|
2005-03-13 13:14:44 +00:00
|
|
|
}
|
2007-07-04 11:41:45 +00:00
|
|
|
// parse formList child element
|
2015-10-29 12:37:11 +00:00
|
|
|
else if (childElement.tagName() == QLatin1String("forms")) {
|
2014-05-11 13:06:27 +00:00
|
|
|
// Clone forms as root node in restoredFormFieldList
|
|
|
|
const QDomNode clonedNode = restoredFormFieldList.importNode(childElement, true);
|
|
|
|
restoredFormFieldList.appendChild(clonedNode);
|
|
|
|
|
2007-08-26 23:31:01 +00:00
|
|
|
if (formfields.isEmpty()) {
|
|
|
|
continue;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-08-26 23:31:01 +00:00
|
|
|
|
2007-07-04 11:41:45 +00:00
|
|
|
QHash<int, FormField *> hashedforms;
|
2023-12-19 08:58:22 +00:00
|
|
|
for (FormField *ff : std::as_const(formfields)) {
|
2020-02-20 09:15:24 +00:00
|
|
|
hashedforms[ff->id()] = ff;
|
2007-07-04 11:41:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// iterate over all forms
|
|
|
|
QDomNode formsNode = childElement.firstChild();
|
|
|
|
while (formsNode.isElement()) {
|
|
|
|
// get annotation element and advance to next annot
|
|
|
|
QDomElement formElement = formsNode.toElement();
|
|
|
|
formsNode = formsNode.nextSibling();
|
|
|
|
|
2015-10-29 12:37:11 +00:00
|
|
|
if (formElement.tagName() != QLatin1String("form")) {
|
2007-07-04 11:41:45 +00:00
|
|
|
continue;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-07-04 11:41:45 +00:00
|
|
|
|
|
|
|
bool ok = true;
|
2015-10-29 12:37:11 +00:00
|
|
|
int index = formElement.attribute(QStringLiteral("id")).toInt(&ok);
|
2007-07-04 11:41:45 +00:00
|
|
|
if (!ok) {
|
|
|
|
continue;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-07-04 11:41:45 +00:00
|
|
|
|
2008-11-11 18:48:40 +00:00
|
|
|
QHash<int, FormField *>::const_iterator wantedIt = hashedforms.constFind(index);
|
|
|
|
if (wantedIt == hashedforms.constEnd()) {
|
2007-08-26 20:55:56 +00:00
|
|
|
continue;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-08-26 20:55:56 +00:00
|
|
|
|
2015-10-29 12:37:11 +00:00
|
|
|
QString value = formElement.attribute(QStringLiteral("value"));
|
2007-08-26 20:55:56 +00:00
|
|
|
(*wantedIt)->d_ptr->setValue(value);
|
2014-09-09 14:08:32 +00:00
|
|
|
loadedAnything = true;
|
2007-07-04 11:41:45 +00:00
|
|
|
}
|
|
|
|
}
|
2005-03-13 13:14:44 +00:00
|
|
|
}
|
2014-09-09 14:08:32 +00:00
|
|
|
|
|
|
|
return loadedAnything;
|
2005-03-13 13:14:44 +00:00
|
|
|
}
|
|
|
|
|
2008-11-14 23:38:02 +00:00
|
|
|
void PagePrivate::saveLocalContents(QDomNode &parentNode, QDomDocument &document, PageItems what) const
|
2005-03-13 13:14:44 +00:00
|
|
|
{
|
2005-04-07 19:27:54 +00:00
|
|
|
// create the page node and set the 'number' attribute
|
2015-10-29 12:37:11 +00:00
|
|
|
QDomElement pageElement = document.createElement(QStringLiteral("page"));
|
|
|
|
pageElement.setAttribute(QStringLiteral("number"), m_number);
|
2005-03-13 13:14:44 +00:00
|
|
|
|
2005-04-07 19:27:54 +00:00
|
|
|
// add annotations info if has got any
|
2012-05-30 16:38:51 +00:00
|
|
|
if ((what & AnnotationPageItems) && (what & OriginalAnnotationPageItems)) {
|
|
|
|
const QDomElement savedDocRoot = restoredLocalAnnotationList.documentElement();
|
|
|
|
if (!savedDocRoot.isNull()) {
|
|
|
|
// Import and append node in target document
|
|
|
|
const QDomNode importedNode = document.importNode(savedDocRoot, true);
|
|
|
|
pageElement.appendChild(importedNode);
|
|
|
|
}
|
|
|
|
} else if ((what & AnnotationPageItems) && !m_page->m_annotations.isEmpty()) {
|
2005-04-07 19:27:54 +00:00
|
|
|
// create the annotationList
|
2015-10-29 12:37:11 +00:00
|
|
|
QDomElement annotListElement = document.createElement(QStringLiteral("annotationList"));
|
2005-04-07 19:27:54 +00:00
|
|
|
|
|
|
|
// add every annotation to the annotationList
|
2023-12-19 08:58:22 +00:00
|
|
|
for (const Annotation *a : std::as_const(m_page->m_annotations)) {
|
2006-06-15 21:24:00 +00:00
|
|
|
// only save okular annotations (not the embedded in file ones)
|
2006-12-05 11:05:50 +00:00
|
|
|
if (!(a->flags() & Annotation::External)) {
|
2005-04-07 19:27:54 +00:00
|
|
|
// append an filled-up element called 'annotation' to the list
|
2015-10-29 12:37:11 +00:00
|
|
|
QDomElement annElement = document.createElement(QStringLiteral("annotation"));
|
2005-04-07 19:27:54 +00:00
|
|
|
AnnotationUtils::storeAnnotation(a, annElement, document);
|
|
|
|
annotListElement.appendChild(annElement);
|
2014-09-11 17:36:01 +00:00
|
|
|
qCDebug(OkularCoreDebug) << "save annotation:" << a->uniqueName();
|
2005-03-13 13:14:44 +00:00
|
|
|
}
|
|
|
|
}
|
2005-04-08 10:33:20 +00:00
|
|
|
|
|
|
|
// append the annotationList element if annotations have been set
|
|
|
|
if (annotListElement.hasChildNodes()) {
|
|
|
|
pageElement.appendChild(annotListElement);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-03-13 13:14:44 +00:00
|
|
|
}
|
2005-04-08 10:33:20 +00:00
|
|
|
|
2007-07-04 11:41:45 +00:00
|
|
|
// add forms info if has got any
|
2014-05-11 13:06:27 +00:00
|
|
|
if ((what & FormFieldPageItems) && (what & OriginalFormFieldPageItems)) {
|
|
|
|
const QDomElement savedDocRoot = restoredFormFieldList.documentElement();
|
|
|
|
if (!savedDocRoot.isNull()) {
|
|
|
|
// Import and append node in target document
|
|
|
|
const QDomNode importedNode = document.importNode(savedDocRoot, true);
|
|
|
|
pageElement.appendChild(importedNode);
|
|
|
|
}
|
|
|
|
} else if ((what & FormFieldPageItems) && !formfields.isEmpty()) {
|
2007-07-04 11:41:45 +00:00
|
|
|
// create the formList
|
2015-10-29 12:37:11 +00:00
|
|
|
QDomElement formListElement = document.createElement(QStringLiteral("forms"));
|
2007-07-04 11:41:45 +00:00
|
|
|
|
|
|
|
// add every form data to the formList
|
2022-03-21 23:59:42 +00:00
|
|
|
for (const FormField *f : formfields) {
|
2007-07-04 11:41:45 +00:00
|
|
|
QString newvalue = f->d_ptr->value();
|
|
|
|
if (f->d_ptr->m_default == newvalue) {
|
|
|
|
continue;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-07-04 11:41:45 +00:00
|
|
|
|
|
|
|
// append an filled-up element called 'annotation' to the list
|
2015-10-29 12:37:11 +00:00
|
|
|
QDomElement formElement = document.createElement(QStringLiteral("form"));
|
|
|
|
formElement.setAttribute(QStringLiteral("id"), f->id());
|
|
|
|
formElement.setAttribute(QStringLiteral("value"), newvalue);
|
2007-07-04 11:41:45 +00:00
|
|
|
formListElement.appendChild(formElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
// append the annotationList element if annotations have been set
|
|
|
|
if (formListElement.hasChildNodes()) {
|
|
|
|
pageElement.appendChild(formListElement);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2007-07-04 11:41:45 +00:00
|
|
|
}
|
|
|
|
|
2005-04-08 10:33:20 +00:00
|
|
|
// append the page element only if has children
|
|
|
|
if (pageElement.hasChildNodes()) {
|
|
|
|
parentNode.appendChild(pageElement);
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2005-03-13 13:14:44 +00:00
|
|
|
}
|
2007-03-25 22:36:41 +00:00
|
|
|
|
2013-02-24 21:58:53 +00:00
|
|
|
const QPixmap *Page::_o_nearestPixmap(DocumentObserver *observer, int w, int h) const
|
2007-03-25 22:36:41 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(h)
|
|
|
|
|
2017-09-05 21:27:18 +00:00
|
|
|
const QPixmap *pixmap = nullptr;
|
2007-03-25 22:36:41 +00:00
|
|
|
|
|
|
|
// if a pixmap is present for given id, use it
|
2013-02-24 21:58:53 +00:00
|
|
|
QMap<DocumentObserver *, PagePrivate::PixmapObject>::const_iterator itPixmap = d->m_pixmaps.constFind(observer);
|
2008-11-11 18:48:40 +00:00
|
|
|
if (itPixmap != d->m_pixmaps.constEnd()) {
|
2007-03-25 22:36:41 +00:00
|
|
|
pixmap = itPixmap.value().m_pixmap;
|
|
|
|
} else if (!d->m_pixmaps.isEmpty()) {
|
|
|
|
// else find the closest match using pixmaps of other IDs (great optim!)
|
|
|
|
int minDistance = -1;
|
2013-02-24 21:58:53 +00:00
|
|
|
QMap<DocumentObserver *, PagePrivate::PixmapObject>::const_iterator it = d->m_pixmaps.constBegin(), end = d->m_pixmaps.constEnd();
|
2007-03-25 22:36:41 +00:00
|
|
|
for (; it != end; ++it) {
|
|
|
|
int pixWidth = (*it).m_pixmap->width(), distance = pixWidth > w ? pixWidth - w : w - pixWidth;
|
|
|
|
if (minDistance == -1 || distance < minDistance) {
|
|
|
|
pixmap = (*it).m_pixmap;
|
|
|
|
minDistance = distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pixmap;
|
|
|
|
}
|
2012-07-07 17:40:52 +00:00
|
|
|
|
2014-02-19 22:40:43 +00:00
|
|
|
bool Page::hasTilesManager(const DocumentObserver *observer) const
|
2012-07-07 17:40:52 +00:00
|
|
|
{
|
2017-09-05 21:27:18 +00:00
|
|
|
return d->tilesManager(observer) != nullptr;
|
2012-11-08 20:29:09 +00:00
|
|
|
}
|
|
|
|
|
2014-02-19 22:40:43 +00:00
|
|
|
QList<Tile> Page::tilesAt(const DocumentObserver *observer, const NormalizedRect &rect) const
|
2012-11-08 20:29:09 +00:00
|
|
|
{
|
2014-02-19 22:40:43 +00:00
|
|
|
TilesManager *tm = d->m_tilesManagers.value(observer);
|
|
|
|
if (tm) {
|
|
|
|
return tm->tilesAt(rect, TilesManager::PixmapTile);
|
2012-11-08 20:29:09 +00:00
|
|
|
} else {
|
|
|
|
return QList<Tile>();
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2012-11-08 20:29:09 +00:00
|
|
|
}
|
|
|
|
|
2014-02-19 22:40:43 +00:00
|
|
|
TilesManager *PagePrivate::tilesManager(const DocumentObserver *observer) const
|
2012-11-08 20:29:09 +00:00
|
|
|
{
|
2014-02-19 22:40:43 +00:00
|
|
|
return m_tilesManagers.value(observer);
|
2012-07-07 17:40:52 +00:00
|
|
|
}
|
|
|
|
|
2014-02-19 22:40:43 +00:00
|
|
|
void PagePrivate::setTilesManager(const DocumentObserver *observer, TilesManager *tm)
|
2012-07-07 17:40:52 +00:00
|
|
|
{
|
2014-02-19 22:40:43 +00:00
|
|
|
TilesManager *old = m_tilesManagers.value(observer);
|
|
|
|
delete old;
|
2012-11-08 19:46:47 +00:00
|
|
|
|
2014-02-19 22:40:43 +00:00
|
|
|
m_tilesManagers.insert(observer, tm);
|
|
|
|
}
|
2017-10-26 07:47:18 +00:00
|
|
|
|
|
|
|
void PagePrivate::adoptGeneratedContents(PagePrivate *oldPage)
|
|
|
|
{
|
|
|
|
rotateAt(oldPage->m_rotation);
|
|
|
|
|
|
|
|
m_pixmaps = oldPage->m_pixmaps;
|
|
|
|
oldPage->m_pixmaps.clear();
|
|
|
|
|
|
|
|
m_tilesManagers = oldPage->m_tilesManagers;
|
|
|
|
oldPage->m_tilesManagers.clear();
|
|
|
|
|
|
|
|
m_boundingBox = oldPage->m_boundingBox;
|
|
|
|
m_isBoundingBoxKnown = oldPage->m_isBoundingBoxKnown;
|
|
|
|
m_text = oldPage->m_text;
|
|
|
|
oldPage->m_text = nullptr;
|
|
|
|
|
|
|
|
m_textSelections = oldPage->m_textSelections;
|
|
|
|
oldPage->m_textSelections = nullptr;
|
|
|
|
|
|
|
|
restoredLocalAnnotationList = oldPage->restoredLocalAnnotationList;
|
|
|
|
restoredFormFieldList = oldPage->restoredFormFieldList;
|
|
|
|
}
|
|
|
|
|
|
|
|
FormField *PagePrivate::findEquivalentForm(const Page *p, FormField *oldField)
|
|
|
|
{
|
|
|
|
// given how id is not very good of id (at least for pdf) we do a few passes
|
|
|
|
// same rect, type and id
|
2023-12-19 08:58:22 +00:00
|
|
|
for (FormField *f : std::as_const(p->d->formfields)) {
|
2017-10-26 07:47:18 +00:00
|
|
|
if (f->rect() == oldField->rect() && f->type() == oldField->type() && f->id() == oldField->id()) {
|
|
|
|
return f;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2017-10-26 07:47:18 +00:00
|
|
|
}
|
|
|
|
// same rect and type
|
2023-12-19 08:58:22 +00:00
|
|
|
for (FormField *f : std::as_const(p->d->formfields)) {
|
2017-10-26 07:47:18 +00:00
|
|
|
if (f->rect() == oldField->rect() && f->type() == oldField->type()) {
|
|
|
|
return f;
|
2022-03-08 10:10:43 +00:00
|
|
|
}
|
2017-10-26 07:47:18 +00:00
|
|
|
}
|
|
|
|
// fuzzy rect, same type and id
|
2023-12-19 08:58:22 +00:00
|
|
|
for (FormField *f : std::as_const(p->d->formfields)) {
|
2017-10-26 07:47:18 +00:00
|
|
|
if (f->type() == oldField->type() && f->id() == oldField->id() && qFuzzyCompare(f->rect().left, oldField->rect().left) && qFuzzyCompare(f->rect().top, oldField->rect().top) &&
|
|
|
|
qFuzzyCompare(f->rect().right, oldField->rect().right) && qFuzzyCompare(f->rect().bottom, oldField->rect().bottom)) {
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fuzzy rect and same type
|
2023-12-19 08:58:22 +00:00
|
|
|
for (FormField *f : std::as_const(p->d->formfields)) {
|
2017-10-26 07:47:18 +00:00
|
|
|
if (f->type() == oldField->type() && qFuzzyCompare(f->rect().left, oldField->rect().left) && qFuzzyCompare(f->rect().top, oldField->rect().top) && qFuzzyCompare(f->rect().right, oldField->rect().right) &&
|
|
|
|
qFuzzyCompare(f->rect().bottom, oldField->rect().bottom)) {
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|