107
bool PageItem::invertColors()
109
return s_invertColors;
112
void PageItem::setInvertColors(bool invertColors)
114
s_invertColors = invertColors;
117
const Qt::KeyboardModifiers& PageItem::copyModifiers()
119
return s_copyModifiers;
122
void PageItem::setCopyModifiers(const Qt::KeyboardModifiers& copyModifiers)
124
s_copyModifiers = copyModifiers;
127
const Qt::KeyboardModifiers& PageItem::annotateModifiers()
129
return s_annotateModifiers;
132
void PageItem::setAnnotateModifiers(const Qt::KeyboardModifiers& annotateModifiers)
134
s_annotateModifiers = annotateModifiers;
137
PageItem::PageItem(QMutex* mutex, Poppler::Page* page, int index, QGraphicsItem* parent) : QGraphicsObject(parent),
119
const Qt::KeyboardModifiers& PageItem::copyToClipboardModifiers()
121
return s_copyToClipboardModifiers;
124
void PageItem::setCopyToClipboardModifiers(const Qt::KeyboardModifiers& copyToClipboardModifiers)
126
s_copyToClipboardModifiers = copyToClipboardModifiers;
129
const Qt::KeyboardModifiers& PageItem::addAnnotationModifiers()
131
return s_addAnnotationModifiers;
134
void PageItem::setAddAnnotationModifiers(const Qt::KeyboardModifiers& addAnnotationModifiers)
136
s_addAnnotationModifiers = addAnnotationModifiers;
139
const QIcon& PageItem::progressIcon()
141
return s_progressIcon;
144
void PageItem::setProgressIcon(const QIcon& progressIcon)
146
s_progressIcon = progressIcon;
149
const QIcon& PageItem::errorIcon()
154
void PageItem::setErrorIcon(const QIcon& errorIcon)
156
s_errorIcon = errorIcon;
159
PageItem::PageItem(Model::Page* page, int index, bool presentationMode, QGraphicsItem* parent) : QGraphicsObject(parent),
165
m_presentationMode(presentationMode),
166
m_invertColors(false),
145
168
m_rubberBandMode(ModifiersMode),
147
170
m_physicalDpiX(72),
148
171
m_physicalDpiY(72),
149
172
m_scaleFactor(1.0),
150
m_rotation(Poppler::Page::Rotate0),
173
m_rotation(RotateBy0),
152
175
m_normalizedTransform(),
153
176
m_boundingRect(),
157
180
setAcceptHoverEvents(true);
159
182
m_render = new QFutureWatcher< void >(this);
160
183
connect(m_render, SIGNAL(finished()), SLOT(on_render_finished()));
162
connect(this, SIGNAL(imageReady(int,int,qreal,Poppler::Page::Rotation,bool,QImage)), SLOT(on_imageReady(int,int,qreal,Poppler::Page::Rotation,bool,QImage)));
185
connect(this, SIGNAL(imageReady(int,int,qreal,Rotation,bool,bool,QImage)), SLOT(on_imageReady(int,int,qreal,Rotation,bool,bool,QImage)));
168
m_size = m_page->pageSizeF();
170
foreach(Poppler::Link* link, m_page->links())
172
if(link->linkType() == Poppler::Link::Goto)
174
if(!static_cast< Poppler::LinkGoto* >(link)->isExternal())
176
m_links.append(link);
180
else if(link->linkType() == Poppler::Link::Browse)
182
m_links.append(link);
189
foreach(Poppler::Annotation* annotation, m_page->annotations())
191
if(annotation->subType() == Poppler::Annotation::AText || annotation->subType() == Poppler::Annotation::AHighlight)
193
m_annotations.append(annotation);
200
foreach(Poppler::FormField* formField, m_page->formFields())
202
if(!formField->isVisible() || formField->isReadOnly())
208
switch(formField->type())
211
case Poppler::FormField::FormSignature:
214
case Poppler::FormField::FormText:
215
switch(static_cast< Poppler::FormFieldText* >(formField)->textType())
218
case Poppler::FormFieldText::FileSelect:
221
case Poppler::FormFieldText::Normal:
222
case Poppler::FormFieldText::Multiline:
223
m_formFields.append(formField);
228
case Poppler::FormField::FormChoice:
229
m_formFields.append(formField);
231
case Poppler::FormField::FormButton:
232
switch(static_cast< Poppler::FormFieldButton* >(formField)->buttonType())
235
case Poppler::FormFieldButton::Push:
238
case Poppler::FormFieldButton::CheckBox:
239
case Poppler::FormFieldButton::Radio:
240
m_formFields.append(formField);
190
m_size = m_page->size();
192
QTimer::singleShot(0, this, SLOT(loadInteractiveElements()));
248
194
prepareGeometry();
242
if(s_decoratePages && !m_presentationMode)
297
244
QColor paperColor = s_paperColor;
301
248
paperColor.setRgb(~paperColor.rgb());
304
251
painter->fillRect(m_boundingRect, QBrush(paperColor));
306
painter->drawImage(m_boundingRect.topLeft(), image);
308
painter->setPen(QPen(s_invertColors ? Qt::white : Qt::black));
256
qreal extent = qMin(0.1 * m_boundingRect.width(), 0.1 * m_boundingRect.height());
257
QRectF rect(m_boundingRect.left() + 0.01 * m_boundingRect.width(), m_boundingRect.top() + 0.01 * m_boundingRect.height(), extent, extent);
259
s_progressIcon.paint(painter, rect.toRect());
263
painter->drawPixmap(m_boundingRect.topLeft(), pixmap);
266
if(s_decoratePages && !m_presentationMode)
268
painter->setPen(QPen(m_invertColors ? Qt::white : Qt::black));
309
269
painter->drawRect(m_boundingRect);
313
painter->drawImage(m_boundingRect.topLeft(), image);
274
if(s_decorateLinks && !m_presentationMode && !m_links.isEmpty())
322
278
painter->setTransform(m_normalizedTransform, true);
323
279
painter->setPen(QPen(Qt::red));
325
foreach(Poppler::Link* link, m_links)
281
foreach(Model::Link* link, m_links)
327
painter->drawRect(link->linkArea().normalized());
283
painter->drawPath(link->boundary);
330
286
painter->restore();
354
painter->setTransform(m_transform, true);
356
QColor highlightColor = QApplication::palette().color(QPalette::Highlight);
358
highlightColor.setAlpha(127);
360
foreach(QRectF highlight, m_highlights)
308
if(!m_highlights.isEmpty())
362
painter->fillRect(highlight.normalized(), QBrush(highlightColor));
312
painter->setTransform(m_transform, true);
314
QColor highlightColor = widget->palette().color(QPalette::Highlight);
316
highlightColor.setAlpha(127);
318
foreach(QRectF highlight, m_highlights)
320
painter->fillRect(highlight.normalized(), QBrush(highlightColor));
369
328
if(!m_rubberBand.isNull())
372
pen.setColor(s_invertColors ? Qt::white : Qt::black);
331
pen.setColor(m_invertColors ? Qt::white : Qt::black);
373
332
pen.setStyle(Qt::DashLine);
375
334
painter->setPen(pen);
532
void PageItem::on_imageReady(int physicalDpiX, int physicalDpiY, qreal scaleFactor, Poppler::Page::Rotation rotation, bool prefetch, QImage image)
511
void PageItem::on_imageReady(int physicalDpiX, int physicalDpiY, qreal scaleFactor, Rotation rotation, bool invertColors, bool prefetch, QImage image)
534
if(m_physicalDpiX != physicalDpiX || m_physicalDpiY != physicalDpiY || !qFuzzyCompare(m_scaleFactor, scaleFactor) || m_rotation != rotation)
513
if(m_physicalDpiX != physicalDpiX || m_physicalDpiY != physicalDpiY || !qFuzzyCompare(m_scaleFactor, scaleFactor) || m_rotation != rotation || m_invertColors != invertColors)
541
image.invertPixels();
520
qreal extent = qMin(0.1 * m_boundingRect.width(), 0.1 * m_boundingRect.height());
521
QRectF rect(0.01 * m_boundingRect.width(), 0.01 * m_boundingRect.height(), extent, extent);
523
image = QImage(qFloor(0.01 * m_boundingRect.width() + extent), qFloor(0.01 * m_boundingRect.height() + extent), QImage::Format_ARGB32);
524
image.fill(Qt::transparent);
526
QPainter painter(&image);
527
s_errorIcon.paint(&painter, rect.toRect());
546
s_cache.insert(this, new QImage(image), image.byteCount());
532
QPixmap pixmap = QPixmap::fromImage(image);
534
int cost = pixmap.width() * pixmap.height() * pixmap.depth() / 8;
535
s_cache.insert(this, new QPixmap(pixmap), cost);
550
539
if(!m_render->isCanceled())
541
m_pixmap = QPixmap::fromImage(image);
567
foreach(Poppler::Link* link, m_links)
556
foreach(Model::Link* link, m_links)
569
if(m_normalizedTransform.mapRect(link->linkArea().normalized()).contains(event->pos()))
558
if(m_normalizedTransform.map(link->boundary).contains(event->pos()))
571
if(link->linkType() == Poppler::Link::Goto)
560
if(link->page != -1 && (link->urlOrFileName.isNull() || !m_presentationMode))
573
562
setCursor(Qt::PointingHandCursor);
574
QToolTip::showText(event->screenPos(), tr("Go to page %1.").arg(static_cast< Poppler::LinkGoto* >(link)->destination().pageNumber()));
564
if(link->urlOrFileName.isNull())
566
QToolTip::showText(event->screenPos(), tr("Go to page %1.").arg(link->page));
570
QToolTip::showText(event->screenPos(), tr("Go to page %1 of file '%2'.").arg(link->page).arg(link->urlOrFileName));
578
else if(link->linkType() == Poppler::Link::Browse)
575
else if(!link->urlOrFileName.isNull() && !m_presentationMode)
580
577
setCursor(Qt::PointingHandCursor);
581
QToolTip::showText(event->screenPos(), tr("Open %1.").arg(static_cast< Poppler::LinkBrowse* >(link)->url()));
578
QToolTip::showText(event->screenPos(), tr("Open '%1'.").arg(link->urlOrFileName));
585
if(m_presentationMode)
588
QToolTip::hideText();
590
foreach(Poppler::Annotation* annotation, m_annotations)
594
foreach(Model::Annotation* annotation, m_annotations)
592
if(m_normalizedTransform.mapRect(annotation->boundary().normalized()).contains(event->pos()))
596
if(m_normalizedTransform.mapRect(annotation->boundary()).contains(event->pos()))
594
598
setCursor(Qt::PointingHandCursor);
595
599
QToolTip::showText(event->screenPos(), annotation->contents());
657
foreach(Poppler::Link* link, m_links)
661
foreach(Model::Link* link, m_links)
659
if(m_normalizedTransform.mapRect(link->linkArea().normalized()).contains(event->pos()))
663
if(m_normalizedTransform.map(link->boundary).contains(event->pos()))
663
if(link->linkType() == Poppler::Link::Goto)
667
if(link->page != -1 && (link->urlOrFileName.isNull() || !m_presentationMode))
665
Poppler::LinkGoto* linkGoto = static_cast< Poppler::LinkGoto* >(link);
667
int page = linkGoto->destination().pageNumber();
668
qreal left = linkGoto->destination().isChangeLeft() ? linkGoto->destination().left() : 0.0;
669
qreal top = linkGoto->destination().isChangeTop() ? linkGoto->destination().top() : 0.0;
671
emit linkClicked(page, left, top);
669
if(link->urlOrFileName.isNull())
671
emit linkClicked(link->page, link->left, link->top);
675
emit linkClicked(link->urlOrFileName, link->page);
676
else if(link->linkType() == Poppler::Link::Browse)
681
else if(!link->urlOrFileName.isNull() && !m_presentationMode)
678
emit linkClicked(static_cast< Poppler::LinkBrowse* >(link)->url());
683
emit linkClicked(link->urlOrFileName);
809
void PageItem::loadInteractiveElements()
811
m_links = m_page->links();
813
if(!m_presentationMode)
815
m_annotations = m_page->annotations();
816
m_formFields = m_page->formFields();
787
822
void PageItem::copyToClipboard(const QPoint& screenPos)
789
QMenu* menu = new QMenu();
791
QAction* copyTextAction = menu->addAction(tr("Copy &text"));
792
QAction* copyImageAction = menu->addAction(tr("Copy &image"));
793
QAction* saveImageToFileAction = menu->addAction(tr("Save image to &file..."));
795
QAction* action = menu->exec(screenPos);
826
QAction* copyTextAction = menu.addAction(tr("Copy &text"));
827
QAction* copyImageAction = menu.addAction(tr("Copy &image"));
828
QAction* saveImageToFileAction = menu.addAction(tr("Save image to &file..."));
830
QAction* action = menu.exec(screenPos);
797
832
if(action == copyTextAction)
803
text = m_page->text(m_transform.inverted().mapRect(m_rubberBand));
834
QString text = m_page->text(m_transform.inverted().mapRect(m_rubberBand));
807
836
if(!text.isEmpty())
820
case Poppler::Page::Rotate0:
821
case Poppler::Page::Rotate90:
822
image = m_page->renderToImage(m_scaleFactor * m_physicalDpiX, m_scaleFactor * m_physicalDpiY, m_rubberBand.x(), m_rubberBand.y(), m_rubberBand.width(), m_rubberBand.height(), m_rotation);
824
case Poppler::Page::Rotate180:
825
case Poppler::Page::Rotate270:
826
image = m_page->renderToImage(m_scaleFactor * m_physicalDpiY, m_scaleFactor * m_physicalDpiX, m_rubberBand.x(), m_rubberBand.y(), m_rubberBand.width(), m_rubberBand.height(), m_rotation);
845
if(s_cache.contains(this))
847
image = s_cache.object(this)->copy(m_rubberBand.translated(-m_boundingRect.topLeft()).toRect()).toImage();
851
image = m_page->render(m_physicalDpiX * m_scaleFactor, m_scaleFactor * m_physicalDpiY, m_rotation, m_rubberBand.translated(-m_boundingRect.topLeft()).toRect());
832
854
if(!image.isNull())
853
873
void PageItem::addAnnotation(const QPoint& screenPos)
855
#ifdef HAS_POPPLER_20
857
QMenu* menu = new QMenu();
859
QAction* addTextAction = menu->addAction(tr("Add &text"));
860
QAction* addHighlightAction = menu->addAction(tr("Add &highlight"));
862
QAction* action = menu->exec(screenPos);
864
if(action == addTextAction || action == addHighlightAction)
866
QRectF boundary = m_normalizedTransform.inverted().mapRect(m_rubberBand);
868
Poppler::Annotation::Style style;
869
style.setColor(Qt::yellow);
871
Poppler::Annotation::Popup popup;
872
popup.setFlags(Poppler::Annotation::Hidden | Poppler::Annotation::ToggleHidingOnMouse);
874
Poppler::Annotation* annotation = 0;
876
if(action == addTextAction)
878
boundary.setWidth(24.0 / m_size.width());
879
boundary.setHeight(24.0 / m_size.height());
881
annotation = new Poppler::TextAnnotation(Poppler::TextAnnotation::Linked);
883
else if(action == addHighlightAction)
885
Poppler::HighlightAnnotation* highlightAnnotation = new Poppler::HighlightAnnotation();
887
Poppler::HighlightAnnotation::Quad quad;
888
quad.points[0] = boundary.topLeft();
889
quad.points[1] = boundary.topRight();
890
quad.points[2] = boundary.bottomRight();
891
quad.points[3] = boundary.bottomLeft();
893
highlightAnnotation->setHighlightQuads(QList< Poppler::HighlightAnnotation::Quad >() << quad);
895
annotation = highlightAnnotation;
898
annotation->setBoundary(boundary);
899
annotation->setStyle(style);
900
annotation->setPopup(popup);
904
m_annotations.append(annotation);
905
m_page->addAnnotation(annotation);
911
editAnnotation(annotation, screenPos);
920
QMessageBox::information(0, tr("Information"), tr("Version 0.20.1 or higher of the Poppler library is required to add or remove annotations."));
922
#endif // HAS_POPPLER_20
925
void PageItem::removeAnnotation(Poppler::Annotation* annotation, const QPoint& screenPos)
927
#ifdef HAS_POPPLER_20
929
QMenu* menu = new QMenu();
931
QAction* removeAnnotationAction = menu->addAction(tr("&Remove annotation"));
933
QAction* action = menu->exec(screenPos);
935
if(action == removeAnnotationAction)
939
m_annotations.removeAll(annotation);
940
m_page->removeAnnotation(annotation);
951
Q_UNUSED(annotation);
954
QMessageBox::information(0, tr("Information"), tr("Version 0.20.1 or higher of the Poppler library is required to add or remove annotations."));
956
#endif // HAS_POPPLER_20
959
void PageItem::editAnnotation(Poppler::Annotation* annotation, const QPoint& screenPos)
961
AnnotationDialog* annotationDialog = new AnnotationDialog(m_mutex, annotation);
963
annotationDialog->move(screenPos);
965
annotationDialog->setAttribute(Qt::WA_DeleteOnClose);
966
annotationDialog->show();
969
void PageItem::editFormField(Poppler::FormField* formField, const QPoint& screenPos)
971
if(formField->type() == Poppler::FormField::FormText || formField->type() == Poppler::FormField::FormChoice)
973
FormFieldDialog* formFieldDialog = new FormFieldDialog(m_mutex, formField);
975
formFieldDialog->move(screenPos);
977
formFieldDialog->setAttribute(Qt::WA_DeleteOnClose);
978
formFieldDialog->show();
875
if(m_page->canAddAndRemoveAnnotations())
879
QAction* addTextAction = menu.addAction(tr("Add &text"));
880
QAction* addHighlightAction = menu.addAction(tr("Add &highlight"));
882
QAction* action = menu.exec(screenPos);
884
if(action == addTextAction || action == addHighlightAction)
886
QRectF boundary = m_normalizedTransform.inverted().mapRect(m_rubberBand);
888
Model::Annotation* annotation = 0;
890
if(action == addTextAction)
892
boundary.setWidth(24.0 / m_size.width());
893
boundary.setHeight(24.0 / m_size.height());
895
annotation = m_page->addTextAnnotation(boundary);
897
else if(action == addHighlightAction)
899
annotation = m_page->addHighlightAnnotation(boundary);
902
m_annotations.append(annotation);
906
editAnnotation(annotation, screenPos);
911
void PageItem::removeAnnotation(Model::Annotation* annotation, const QPoint& screenPos)
913
if(m_page->canAddAndRemoveAnnotations())
917
QAction* removeAnnotationAction = menu.addAction(tr("&Remove annotation"));
919
QAction* action = menu.exec(screenPos);
921
if(action == removeAnnotationAction)
923
m_annotations.removeAll(annotation);
924
m_page->removeAnnotation(annotation);
931
void PageItem::editAnnotation(Model::Annotation* annotation, const QPoint& screenPos)
933
annotation->showDialog(screenPos);
936
void PageItem::editFormField(Model::FormField* formField, const QPoint& screenPos)
938
QDialog* formFieldDialog = formField->showDialog(screenPos);
940
if(formFieldDialog != 0)
980
942
connect(formFieldDialog, SIGNAL(destroyed()), SLOT(refresh()));
982
else if(formField->type() == Poppler::FormField::FormButton)
984
Poppler::FormFieldButton* formFieldButton = static_cast< Poppler::FormFieldButton* >(formField);
986
formFieldButton->setState(!formFieldButton->state());
1032
992
m_boundingRect.setHeight(qRound(m_boundingRect.height()));
1035
void PageItem::render(int physicalDpiX, int physicalDpiY, qreal scaleFactor, Poppler::Page::Rotation rotation, bool prefetch)
995
void PageItem::render(const RenderOptions& renderOptions)
1037
QMutexLocker mutexLocker(m_mutex);
1039
if(m_render->isCanceled() && !prefetch)
1048
case Poppler::Page::Rotate0:
1049
case Poppler::Page::Rotate90:
1050
image = m_page->renderToImage(scaleFactor * physicalDpiX, scaleFactor * physicalDpiY, -1, -1, -1, -1, rotation);
1052
case Poppler::Page::Rotate180:
1053
case Poppler::Page::Rotate270:
1054
image = m_page->renderToImage(scaleFactor * physicalDpiY, scaleFactor * physicalDpiX, -1, -1, -1, -1, rotation);
1058
if(m_render->isCanceled() && !prefetch)
1063
emit imageReady(physicalDpiX, physicalDpiY, scaleFactor, rotation, prefetch, image);
997
if(m_render->isCanceled() && !renderOptions.prefetch)
1002
QImage image = m_page->render(renderOptions.physicalDpiX * renderOptions.scaleFactor, renderOptions.physicalDpiY * renderOptions.scaleFactor, renderOptions.rotation);
1004
if(m_render->isCanceled() && !renderOptions.prefetch)
1009
if(renderOptions.invertColors)
1011
image.invertPixels();
1014
emit imageReady(renderOptions.physicalDpiX, renderOptions.physicalDpiY, renderOptions.scaleFactor, renderOptions.rotation, renderOptions.invertColors, renderOptions.prefetch, image);
1066
ThumbnailItem::ThumbnailItem(QMutex* mutex, Poppler::Page* page, int index, QGraphicsItem* parent) : PageItem(mutex, page, index, parent)
1017
ThumbnailItem::ThumbnailItem(Model::Page* page, int index, QGraphicsItem* parent) : PageItem(page, index, false, parent)
1068
1019
setAcceptHoverEvents(false);