source: visorpdf/sources/pdfmodel.cpp @ 8964fdc

Last change on this file since 8964fdc was 8964fdc, checked in by Pedro Buitrago <pbuitrago@…>, 8 years ago

Se realiza las modificaciones para agregar el nombre del proyecto murrupuy y la información sobre el proyecto

  • Property mode set to 100644
File size: 31.5 KB
Line 
1/*
2
3Copyright 2014 S. Razi Alavizadeh
4Copyright 2013-2014 Adam Reichold
5
6This file is part of qpdfview.
7
8qpdfview is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 2 of the License, or
11(at your option) any later version.
12
13qpdfview is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with qpdfview.  If not, see <http://www.gnu.org/licenses/>.
20
21*/
22
23#include "pdfmodel.h"
24
25#include <QCache>
26#include <QFormLayout>
27#include <QMessageBox>
28#include <QSettings>
29
30#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
31
32#include <poppler-qt5.h>
33
34#else
35
36#include <poppler-qt4.h>
37
38#endif // QT_VERSION
39
40#include <poppler-form.h>
41
42#include "annotationwidgets.h"
43#include "formfieldwidgets.h"
44
45#ifndef HAS_POPPLER_24
46
47#define LOCK_ANNOTATION QMutexLocker mutexLocker(m_mutex);
48#define LOCK_FORM_FIELD QMutexLocker mutexLocker(m_mutex);
49#define LOCK_PAGE QMutexLocker mutexLocker(m_mutex);
50#define LOCK_DOCUMENT QMutexLocker mutexLocker(&m_mutex);
51
52#else
53
54#define LOCK_ANNOTATION
55#define LOCK_FORM_FIELD
56#define LOCK_PAGE
57#define LOCK_DOCUMENT
58
59#endif // HAS_POPPLER_24
60
61namespace
62{
63
64using namespace qpdfview;
65using namespace qpdfview::Model;
66
67inline void appendRow(QStandardItemModel* model, const QString& key, const QString& value)
68{
69    model->appendRow(QList< QStandardItem* >() << new QStandardItem(key) << new QStandardItem(value));
70}
71
72void loadOutline(Poppler::Document* document, const QDomNode& node, QStandardItem* parent)
73{
74    const QDomElement element = node.toElement();
75
76    QStandardItem* item = new QStandardItem(element.tagName());
77    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
78
79    Poppler::LinkDestination* linkDestination = 0;
80
81    if(element.hasAttribute("Destination"))
82    {
83        linkDestination = new Poppler::LinkDestination(element.attribute("Destination"));
84    }
85    else if(element.hasAttribute("DestinationName"))
86    {
87        linkDestination = document->linkDestination(element.attribute("DestinationName"));
88    }
89
90    if(linkDestination != 0)
91    {
92        int page = linkDestination->pageNumber();
93        qreal left = qQNaN();
94        qreal top = qQNaN();
95
96        page = page >= 1 ? page : 1;
97        page = page <= document->numPages() ? page : document->numPages();
98
99        if(linkDestination->isChangeLeft())
100        {
101            left = linkDestination->left();
102
103            left = left >= 0.0 ? left : 0.0;
104            left = left <= 1.0 ? left : 1.0;
105        }
106
107        if(linkDestination->isChangeTop())
108        {
109            top = linkDestination->top();
110
111            top = top >= 0.0 ? top : 0.0;
112            top = top <= 1.0 ? top : 1.0;
113        }
114
115        delete linkDestination;
116
117        item->setData(page, Document::PageRole);
118        item->setData(left, Document::LeftRole);
119        item->setData(top, Document::TopRole);
120
121        QStandardItem* pageItem = item->clone();
122        pageItem->setText(QString::number(page));
123        pageItem->setTextAlignment(Qt::AlignRight);
124
125        parent->appendRow(QList< QStandardItem* >() << item << pageItem);
126    }
127    else
128    {
129        parent->appendRow(item);
130    }
131
132    const QDomNode& siblingNode = node.nextSibling();
133    if(!siblingNode.isNull())
134    {
135        loadOutline(document, siblingNode, parent);
136    }
137
138    const QDomNode& childNode = node.firstChild();
139    if(!childNode.isNull())
140    {
141        loadOutline(document, childNode, item);
142    }
143}
144
145inline void restoreRenderHint(Poppler::Document* document, const Poppler::Document::RenderHints hints, const Poppler::Document::RenderHint hint)
146{
147    document->setRenderHint(hint, hints.testFlag(hint));
148}
149
150typedef QSharedPointer< Poppler::TextBox > TextBox;
151typedef QList< TextBox > TextBoxList;
152
153QCache< const PdfPage*,  TextBoxList > textCache(1 << 12);
154QMutex textCacheMutex;
155
156#define LOCK_TEXT_CACHE QMutexLocker mutexLocker(&textCacheMutex);
157
158namespace Defaults
159{
160
161const bool antialiasing = true;
162const bool textAntialiasing = true;
163
164#ifdef HAS_POPPLER_18
165
166const int textHinting = 0;
167
168#else
169
170const bool textHinting = false;
171
172#endif // HAS_POPPLER_18
173
174#ifdef HAS_POPPLER_35
175
176const bool ignorePaperColor = false;
177
178#endif // HAS_POPPLER_35
179
180#ifdef HAS_POPPLER_22
181
182const bool overprintPreview = false;
183
184#endif // HAS_POPPLER_22
185
186#ifdef HAS_POPPLER_24
187
188const int thinLineMode = 0;
189
190#endif // HAS_POPPLER_24
191
192const int backend = 0;
193
194} // Defaults
195
196} // anonymous
197
198namespace qpdfview
199{
200
201namespace Model
202{
203
204PdfAnnotation::PdfAnnotation(QMutex* mutex, Poppler::Annotation* annotation) : Annotation(),
205    m_mutex(mutex),
206    m_annotation(annotation)
207{
208}
209
210PdfAnnotation::~PdfAnnotation()
211{
212    delete m_annotation;
213}
214
215QRectF PdfAnnotation::boundary() const
216{
217    LOCK_ANNOTATION
218
219    return m_annotation->boundary().normalized();
220}
221
222QString PdfAnnotation::contents() const
223{
224    LOCK_ANNOTATION
225
226    return m_annotation->contents();
227}
228
229QWidget* PdfAnnotation::createWidget()
230{
231    QWidget* widget = 0;
232
233    if(m_annotation->subType() == Poppler::Annotation::AText || m_annotation->subType() == Poppler::Annotation::AHighlight)
234    {
235        widget = new AnnotationWidget(m_mutex, m_annotation);
236
237        connect(widget, SIGNAL(wasModified()), SIGNAL(wasModified()));
238    }
239    else if(m_annotation->subType() == Poppler::Annotation::AFileAttachment)
240    {
241        widget = new FileAttachmentAnnotationWidget(m_mutex, static_cast< Poppler::FileAttachmentAnnotation* >(m_annotation));
242    }
243
244    connect(this, SIGNAL(destroyed()), widget, SLOT(deleteLater()));
245
246    return widget;
247}
248
249PdfFormField::PdfFormField(QMutex* mutex, Poppler::FormField* formField) : FormField(),
250    m_mutex(mutex),
251    m_formField(formField)
252{
253}
254
255PdfFormField::~PdfFormField()
256{
257    delete m_formField;
258}
259
260QRectF PdfFormField::boundary() const
261{
262    LOCK_FORM_FIELD
263
264    return m_formField->rect().normalized();
265}
266
267QString PdfFormField::name() const
268{
269    LOCK_FORM_FIELD
270
271    return m_formField->name();
272}
273
274QWidget* PdfFormField::createWidget()
275{
276    QWidget* widget = 0;
277
278    if(m_formField->type() == Poppler::FormField::FormText)
279    {
280        Poppler::FormFieldText* formFieldText = static_cast< Poppler::FormFieldText* >(m_formField);
281
282        if(formFieldText->textType() == Poppler::FormFieldText::Normal)
283        {
284            widget = new NormalTextFieldWidget(m_mutex, formFieldText);
285        }
286        else if(formFieldText->textType() == Poppler::FormFieldText::Multiline)
287        {
288            widget = new MultilineTextFieldWidget(m_mutex, formFieldText);
289        }
290    }
291    else if(m_formField->type() == Poppler::FormField::FormChoice)
292    {
293        Poppler::FormFieldChoice* formFieldChoice = static_cast< Poppler::FormFieldChoice* >(m_formField);
294
295        if(formFieldChoice->choiceType() == Poppler::FormFieldChoice::ComboBox)
296        {
297            widget = new ComboBoxChoiceFieldWidget(m_mutex, formFieldChoice);
298        }
299        else if(formFieldChoice->choiceType() == Poppler::FormFieldChoice::ListBox)
300        {
301            widget = new ListBoxChoiceFieldWidget(m_mutex, formFieldChoice);
302        }
303    }
304    else if(m_formField->type() == Poppler::FormField::FormButton)
305    {
306        Poppler::FormFieldButton* formFieldButton = static_cast< Poppler::FormFieldButton* >(m_formField);
307
308        if(formFieldButton->buttonType() == Poppler::FormFieldButton::CheckBox)
309        {
310            widget = new CheckBoxChoiceFieldWidget(m_mutex, formFieldButton);
311        }
312        else if(formFieldButton->buttonType() == Poppler::FormFieldButton::Radio)
313        {
314            widget = new RadioChoiceFieldWidget(m_mutex, formFieldButton);
315        }
316    }
317
318    connect(widget, SIGNAL(wasModified()), SIGNAL(wasModified()));
319
320    return widget;
321}
322
323PdfPage::PdfPage(QMutex* mutex, Poppler::Page* page) :
324    m_mutex(mutex),
325    m_page(page)
326{
327}
328
329PdfPage::~PdfPage()
330{
331    {
332        LOCK_TEXT_CACHE
333
334        textCache.remove(this);
335    }
336
337    delete m_page;
338}
339
340QSizeF PdfPage::size() const
341{
342    LOCK_PAGE
343
344    return m_page->pageSizeF();
345}
346
347QImage PdfPage::render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, const QRect& boundingRect) const
348{
349    LOCK_PAGE
350
351    Poppler::Page::Rotation rotate;
352
353    switch(rotation)
354    {
355    default:
356    case RotateBy0:
357        rotate = Poppler::Page::Rotate0;
358        break;
359    case RotateBy90:
360        rotate = Poppler::Page::Rotate90;
361        break;
362    case RotateBy180:
363        rotate = Poppler::Page::Rotate180;
364        break;
365    case RotateBy270:
366        rotate = Poppler::Page::Rotate270;
367        break;
368    }
369
370    int x = -1;
371    int y = -1;
372    int w = -1;
373    int h = -1;
374
375    if(!boundingRect.isNull())
376    {
377        x = boundingRect.x();
378        y = boundingRect.y();
379        w = boundingRect.width();
380        h = boundingRect.height();
381    }
382
383    return m_page->renderToImage(horizontalResolution, verticalResolution, x, y, w, h, rotate);
384}
385
386QString PdfPage::label() const
387{
388    LOCK_PAGE
389
390    return m_page->label();
391}
392
393QList< Link* > PdfPage::links() const
394{
395    LOCK_PAGE
396
397    QList< Link* > links;
398
399    foreach(const Poppler::Link* link, m_page->links())
400    {
401        const QRectF boundary = link->linkArea().normalized();
402
403        if(link->linkType() == Poppler::Link::Goto)
404        {
405            const Poppler::LinkGoto* linkGoto = static_cast< const Poppler::LinkGoto* >(link);
406
407            int page = linkGoto->destination().pageNumber();
408            qreal left = qQNaN();
409            qreal top = qQNaN();
410
411            page = page >= 1 ? page : 1;
412
413            if(linkGoto->destination().isChangeLeft())
414            {
415                left = linkGoto->destination().left();
416
417                left = left >= 0.0 ? left : 0.0;
418                left = left <= 1.0 ? left : 1.0;
419            }
420
421            if(linkGoto->destination().isChangeTop())
422            {
423                top = linkGoto->destination().top();
424
425                top = top >= 0.0 ? top : 0.0;
426                top = top <= 1.0 ? top : 1.0;
427            }
428
429            if(linkGoto->isExternal())
430            {
431                links.append(new Link(boundary, linkGoto->fileName(), page));
432            }
433            else
434            {
435                links.append(new Link(boundary, page, left, top));
436            }
437        }
438        else if(link->linkType() == Poppler::Link::Browse)
439        {
440            const Poppler::LinkBrowse* linkBrowse = static_cast< const Poppler::LinkBrowse* >(link);
441            const QString url = linkBrowse->url();
442
443            links.append(new Link(boundary, url));
444        }
445        else if(link->linkType() == Poppler::Link::Execute)
446        {
447            const Poppler::LinkExecute* linkExecute = static_cast< const Poppler::LinkExecute* >(link);
448            const QString url = linkExecute->fileName();
449
450            links.append(new Link(boundary, url));
451        }
452
453        delete link;
454    }
455
456    return links;
457}
458
459QString PdfPage::text(const QRectF& rect) const
460{
461    LOCK_PAGE
462
463    return m_page->text(rect).simplified();
464}
465
466QString PdfPage::cachedText(const QRectF& rect) const
467{
468    bool wasCached = false;
469    TextBoxList textBoxes;
470
471    {
472        LOCK_TEXT_CACHE
473
474        if(const TextBoxList* object = textCache.object(this))
475        {
476            wasCached = true;
477
478            textBoxes = *object;
479        }
480    }
481
482    if(!wasCached)
483    {
484        {
485            LOCK_PAGE
486
487            foreach(Poppler::TextBox* textBox, m_page->textList())
488            {
489                textBoxes.append(TextBox(textBox));
490            }
491        }
492
493        LOCK_TEXT_CACHE
494
495        textCache.insert(this, new TextBoxList(textBoxes), textBoxes.count());
496    }
497
498    QString text;
499
500    foreach(const TextBox& textBox, textBoxes)
501    {
502        if(!rect.intersects(textBox->boundingBox()))
503        {
504            continue;
505        }
506
507        const QString& characters = textBox->text();
508
509        for(int index = 0; index < characters.length(); ++index)
510        {
511            if(rect.intersects(textBox->charBoundingBox(index)))
512            {
513                text.append(characters.at(index));
514            }
515        }
516
517        if(textBox->hasSpaceAfter())
518        {
519            text.append(QLatin1Char(' '));
520        }
521    }
522
523    return text.simplified();
524}
525
526QList< QRectF > PdfPage::search(const QString& text, bool matchCase, bool wholeWords) const
527{
528    LOCK_PAGE
529
530    QList< QRectF > results;
531
532#if defined(HAS_POPPLER_31)
533
534    const Poppler::Page::SearchFlags flags((matchCase ? 0 : Poppler::Page::IgnoreCase) | (wholeWords ? Poppler::Page::WholeWords : 0));
535
536    results = m_page->search(text, flags);
537
538#elif defined(HAS_POPPLER_22)
539
540    const Poppler::Page::SearchMode mode = matchCase ? Poppler::Page::CaseSensitive : Poppler::Page::CaseInsensitive;
541
542    results = m_page->search(text, mode);
543
544#elif defined(HAS_POPPLER_14)
545
546    const Poppler::Page::SearchMode mode = matchCase ? Poppler::Page::CaseSensitive : Poppler::Page::CaseInsensitive;
547
548    double left = 0.0, top = 0.0, right = 0.0, bottom = 0.0;
549
550    while(m_page->search(text, left, top, right, bottom, Poppler::Page::NextResult, mode))
551    {
552        results.append(QRectF(left, top, right - left, bottom - top));
553    }
554
555#else
556
557    const Poppler::Page::SearchMode mode = matchCase ? Poppler::Page::CaseSensitive : Poppler::Page::CaseInsensitive;
558
559    QRectF rect;
560
561    while(m_page->search(text, rect, Poppler::Page::NextResult, mode))
562    {
563        results.append(rect);
564    }
565
566#endif // HAS_POPPLER_31 HAS_POPPLER_22 HAS_POPPLER_14
567
568    return results;
569}
570
571QList< Annotation* > PdfPage::annotations() const
572{
573    LOCK_PAGE
574
575    QList< Annotation* > annotations;
576
577    foreach(Poppler::Annotation* annotation, m_page->annotations())
578    {
579        if(annotation->subType() == Poppler::Annotation::AText || annotation->subType() == Poppler::Annotation::AHighlight || annotation->subType() == Poppler::Annotation::AFileAttachment)
580        {
581            annotations.append(new PdfAnnotation(m_mutex, annotation));
582            continue;
583        }
584
585        delete annotation;
586    }
587
588    return annotations;
589}
590
591bool PdfPage::canAddAndRemoveAnnotations() const
592{
593#ifdef HAS_POPPLER_20
594
595    return true;
596
597#else
598
599    QMessageBox::information(0, tr("Information"), tr("Version 0.20.1 or higher of the Poppler library is required to add or remove annotations."));
600
601    return false;
602
603#endif // HAS_POPPLER_20
604}
605
606Annotation* PdfPage::addTextAnnotation(const QRectF& boundary, const QColor& color)
607{
608    LOCK_PAGE
609
610#ifdef HAS_POPPLER_20
611
612    Poppler::Annotation::Style style;
613    style.setColor(color);
614
615    Poppler::Annotation::Popup popup;
616    popup.setFlags(Poppler::Annotation::Hidden | Poppler::Annotation::ToggleHidingOnMouse);
617
618    Poppler::Annotation* annotation = new Poppler::TextAnnotation(Poppler::TextAnnotation::Linked);
619
620    annotation->setBoundary(boundary);
621    annotation->setStyle(style);
622    annotation->setPopup(popup);
623
624    m_page->addAnnotation(annotation);
625
626    return new PdfAnnotation(m_mutex, annotation);
627
628#else
629
630    Q_UNUSED(boundary);
631    Q_UNUSED(color);
632
633    return 0;
634
635#endif // HAS_POPPLER_20
636}
637
638Annotation* PdfPage::addHighlightAnnotation(const QRectF& boundary, const QColor& color)
639{
640    LOCK_PAGE
641
642#ifdef HAS_POPPLER_20
643
644    Poppler::Annotation::Style style;
645    style.setColor(color);
646
647    Poppler::Annotation::Popup popup;
648    popup.setFlags(Poppler::Annotation::Hidden | Poppler::Annotation::ToggleHidingOnMouse);
649
650    Poppler::HighlightAnnotation* annotation = new Poppler::HighlightAnnotation();
651
652    Poppler::HighlightAnnotation::Quad quad;
653    quad.points[0] = boundary.topLeft();
654    quad.points[1] = boundary.topRight();
655    quad.points[2] = boundary.bottomRight();
656    quad.points[3] = boundary.bottomLeft();
657
658    annotation->setHighlightQuads(QList< Poppler::HighlightAnnotation::Quad >() << quad);
659
660    annotation->setBoundary(boundary);
661    annotation->setStyle(style);
662    annotation->setPopup(popup);
663
664    m_page->addAnnotation(annotation);
665
666    return new PdfAnnotation(m_mutex, annotation);
667
668#else
669
670    Q_UNUSED(boundary);
671    Q_UNUSED(color);
672
673    return 0;
674
675#endif // HAS_POPPLER_20
676
677}
678
679void PdfPage::removeAnnotation(Annotation* annotation)
680{
681    LOCK_PAGE
682
683#ifdef HAS_POPPLER_20
684
685    PdfAnnotation* pdfAnnotation = static_cast< PdfAnnotation* >(annotation);
686
687    m_page->removeAnnotation(pdfAnnotation->m_annotation);
688    pdfAnnotation->m_annotation = 0;
689
690#else
691
692    Q_UNUSED(annotation);
693
694#endif // HAS_POPPLER_20
695}
696
697QList< FormField* > PdfPage::formFields() const
698{
699    LOCK_PAGE
700
701    QList< FormField* > formFields;
702
703    foreach(Poppler::FormField* formField, m_page->formFields())
704    {
705        if(!formField->isVisible() || formField->isReadOnly())
706        {
707            delete formField;
708            continue;
709        }
710
711        if(formField->type() == Poppler::FormField::FormText)
712        {
713            Poppler::FormFieldText* formFieldText = static_cast< Poppler::FormFieldText* >(formField);
714
715            if(formFieldText->textType() == Poppler::FormFieldText::Normal || formFieldText->textType() == Poppler::FormFieldText::Multiline)
716            {
717                formFields.append(new PdfFormField(m_mutex, formField));
718                continue;
719            }
720        }
721        else if(formField->type() == Poppler::FormField::FormChoice)
722        {
723            Poppler::FormFieldChoice* formFieldChoice = static_cast< Poppler::FormFieldChoice* >(formField);
724
725            if(formFieldChoice->choiceType() == Poppler::FormFieldChoice::ListBox || formFieldChoice->choiceType() == Poppler::FormFieldChoice::ComboBox)
726            {
727                formFields.append(new PdfFormField(m_mutex, formField));
728                continue;
729            }
730        }
731        else if(formField->type() == Poppler::FormField::FormButton)
732        {
733            Poppler::FormFieldButton* formFieldButton = static_cast< Poppler::FormFieldButton* >(formField);
734
735            if(formFieldButton->buttonType() == Poppler::FormFieldButton::CheckBox || formFieldButton->buttonType() == Poppler::FormFieldButton::Radio)
736            {
737                formFields.append(new PdfFormField(m_mutex, formField));
738                continue;
739            }
740        }
741
742        delete formField;
743    }
744
745    return formFields;
746}
747
748PdfDocument::PdfDocument(Poppler::Document* document) :
749    m_mutex(),
750    m_document(document)
751{
752}
753
754PdfDocument::~PdfDocument()
755{
756    delete m_document;
757}
758
759int PdfDocument::numberOfPages() const
760{
761    LOCK_DOCUMENT
762
763    return m_document->numPages();
764}
765
766Page* PdfDocument::page(int index) const
767{
768    LOCK_DOCUMENT
769
770    Poppler::Page* page = m_document->page(index);
771
772    return page != 0 ? new PdfPage(&m_mutex, page) : 0;
773}
774
775bool PdfDocument::isLocked() const
776{
777    LOCK_DOCUMENT
778
779    return m_document->isLocked();
780}
781
782bool PdfDocument::unlock(const QString& password)
783{
784    LOCK_DOCUMENT
785
786    // Poppler drops render hints and backend after unlocking so we need to restore them.
787
788    const Poppler::Document::RenderHints hints = m_document->renderHints();
789    const Poppler::Document::RenderBackend backend = m_document->renderBackend();
790
791    const bool ok = m_document->unlock(password.toLatin1(), password.toLatin1());
792
793    restoreRenderHint(m_document, hints, Poppler::Document::Antialiasing);
794    restoreRenderHint(m_document, hints, Poppler::Document::TextAntialiasing);
795
796#ifdef HAS_POPPLER_14
797
798    restoreRenderHint(m_document, hints, Poppler::Document::TextHinting);
799
800#endif // HAS_POPPLER_14
801
802#ifdef HAS_POPPLER_18
803
804    restoreRenderHint(m_document, hints, Poppler::Document::TextSlightHinting);
805
806#endif // HAS_POPPLER_18
807
808#ifdef HAS_POPPLER_35
809
810    restoreRenderHint(m_document, hints, Poppler::Document::IgnorePaperColor);
811
812#endif // HAS_POPPLER_35
813
814#ifdef HAS_POPPLER_22
815
816    restoreRenderHint(m_document, hints, Poppler::Document::OverprintPreview);
817
818#endif // HAS_POPPLER_22
819
820#ifdef HAS_POPPLER_24
821
822    restoreRenderHint(m_document, hints, Poppler::Document::ThinLineSolid);
823    restoreRenderHint(m_document, hints, Poppler::Document::ThinLineShape);
824
825#endif // HAS_POPPLER_24
826
827    m_document->setRenderBackend(backend);
828
829    return ok;
830}
831
832QStringList PdfDocument::saveFilter() const
833{
834    return QStringList() << "Portable document format (*.pdf)";
835}
836
837bool PdfDocument::canSave() const
838{
839    return true;
840}
841
842bool PdfDocument::save(const QString& filePath, bool withChanges) const
843{
844    LOCK_DOCUMENT
845
846    QScopedPointer< Poppler::PDFConverter > pdfConverter(m_document->pdfConverter());
847
848    pdfConverter->setOutputFileName(filePath);
849
850    Poppler::PDFConverter::PDFOptions options = pdfConverter->pdfOptions();
851
852    if(withChanges)
853    {
854        options |= Poppler::PDFConverter::WithChanges;
855    }
856
857    pdfConverter->setPDFOptions(options);
858
859    return pdfConverter->convert();
860}
861
862bool PdfDocument::canBePrintedUsingCUPS() const
863{
864    return true;
865}
866
867void PdfDocument::setPaperColor(const QColor& paperColor)
868{
869    LOCK_DOCUMENT
870
871    m_document->setPaperColor(paperColor);
872}
873
874void PdfDocument::loadOutline(QStandardItemModel* outlineModel) const
875{
876    Document::loadOutline(outlineModel);
877
878    LOCK_DOCUMENT
879
880    if(QDomDocument* toc = m_document->toc())
881    {
882        ::loadOutline(m_document, toc->firstChild(), outlineModel->invisibleRootItem());
883
884        delete toc;
885    }
886}
887
888void PdfDocument::loadProperties(QStandardItemModel* propertiesModel) const
889{
890    Document::loadProperties(propertiesModel);
891
892    LOCK_DOCUMENT
893
894    foreach(const QString& key, m_document->infoKeys())
895    {
896        QString value = m_document->info(key);
897
898        if(value.startsWith("D:"))
899        {
900            value = m_document->date(key).toString();
901        }
902
903        appendRow(propertiesModel, key, value);
904    }
905
906    int pdfMajorVersion = 1;
907    int pdfMinorVersion = 0;
908    m_document->getPdfVersion(&pdfMajorVersion, &pdfMinorVersion);
909
910    appendRow(propertiesModel, tr("PDF version"), QString("%1.%2").arg(pdfMajorVersion).arg(pdfMinorVersion));
911
912    appendRow(propertiesModel, tr("Encrypted"), m_document->isEncrypted() ? tr("Yes") : tr("No"));
913    appendRow(propertiesModel, tr("Linearized"), m_document->isLinearized() ? tr("Yes") : tr("No"));
914}
915
916void PdfDocument::loadFonts(QStandardItemModel* fontsModel) const
917{
918    Document::loadFonts(fontsModel);
919
920    LOCK_DOCUMENT
921
922    const QList< Poppler::FontInfo > fonts = m_document->fonts();
923
924    fontsModel->setRowCount(fonts.count());
925    fontsModel->setColumnCount(5);
926
927    fontsModel->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Type") << tr("Embedded") << tr("Subset") << tr("File"));
928
929    for(int index = 0; index < fonts.count(); ++index)
930    {
931        const Poppler::FontInfo& font = fonts[index];
932
933        fontsModel->setItem(index, 0, new QStandardItem(font.name()));
934        fontsModel->setItem(index, 1, new QStandardItem(font.typeName()));
935        fontsModel->setItem(index, 2, new QStandardItem(font.isEmbedded() ? tr("Yes") : tr("No")));
936        fontsModel->setItem(index, 3, new QStandardItem(font.isSubset() ? tr("Yes") : tr("No")));
937        fontsModel->setItem(index, 4, new QStandardItem(font.file()));
938    }
939}
940
941bool PdfDocument::wantsContinuousMode() const
942{
943    LOCK_DOCUMENT
944
945    const Poppler::Document::PageLayout pageLayout = m_document->pageLayout();
946
947    return pageLayout == Poppler::Document::OneColumn
948        || pageLayout == Poppler::Document::TwoColumnLeft
949        || pageLayout == Poppler::Document::TwoColumnRight;
950}
951
952bool PdfDocument::wantsSinglePageMode() const
953{
954    LOCK_DOCUMENT
955
956    const Poppler::Document::PageLayout pageLayout = m_document->pageLayout();
957
958    return pageLayout == Poppler::Document::SinglePage
959        || pageLayout == Poppler::Document::OneColumn;
960}
961
962bool PdfDocument::wantsTwoPagesMode() const
963{
964    LOCK_DOCUMENT
965
966    const Poppler::Document::PageLayout pageLayout = m_document->pageLayout();
967
968    return pageLayout == Poppler::Document::TwoPageLeft
969        || pageLayout == Poppler::Document::TwoColumnLeft;
970}
971
972bool PdfDocument::wantsTwoPagesWithCoverPageMode() const
973{
974    LOCK_DOCUMENT
975
976    const Poppler::Document::PageLayout pageLayout = m_document->pageLayout();
977
978    return pageLayout == Poppler::Document::TwoPageRight
979        || pageLayout == Poppler::Document::TwoColumnRight;
980}
981
982bool PdfDocument::wantsRightToLeftMode() const
983{
984#ifdef HAS_POPPLER_26
985
986    return m_document->textDirection() == Qt::RightToLeft;
987
988#else
989
990    return false;
991
992#endif // HAS_POPPLER_26
993}
994
995} // Model
996
997PdfSettingsWidget::PdfSettingsWidget(QSettings* settings, QWidget* parent) : SettingsWidget(parent),
998    m_settings(settings)
999{
1000    m_layout = new QFormLayout(this);
1001
1002    // antialiasing
1003
1004    m_antialiasingCheckBox = new QCheckBox(this);
1005    m_antialiasingCheckBox->setChecked(m_settings->value("antialiasing", Defaults::antialiasing).toBool());
1006
1007    m_layout->addRow(tr("Antialiasing:"), m_antialiasingCheckBox);
1008
1009    // text antialising
1010
1011    m_textAntialiasingCheckBox = new QCheckBox(this);
1012    m_textAntialiasingCheckBox->setChecked(m_settings->value("textAntialiasing", Defaults::textAntialiasing).toBool());
1013
1014    m_layout->addRow(tr("Text antialiasing:"), m_textAntialiasingCheckBox);
1015
1016    // text hinting
1017
1018#ifdef HAS_POPPLER_18
1019
1020    m_textHintingComboBox = new QComboBox(this);
1021    m_textHintingComboBox->addItem(tr("None"));
1022    m_textHintingComboBox->addItem(tr("Full"));
1023    m_textHintingComboBox->addItem(tr("Reduced"));
1024    m_textHintingComboBox->setCurrentIndex(m_settings->value("textHinting", Defaults::textHinting).toInt());
1025
1026    m_layout->addRow(tr("Text hinting:"), m_textHintingComboBox);
1027
1028#else
1029
1030    m_textHintingCheckBox = new QCheckBox(this);
1031    m_textHintingCheckBox->setChecked(m_settings->value("textHinting", Defaults::textHinting).toBool());
1032
1033    m_layout->addRow(tr("Text hinting:"), m_textHintingCheckBox);
1034
1035#endif // HAS_POPPLER_18
1036
1037#ifdef HAS_POPPLER_35
1038
1039    m_ignorePaperColorCheckBox = new QCheckBox(this);
1040    m_ignorePaperColorCheckBox->setChecked(m_settings->value("ignorePaperColor", Defaults::ignorePaperColor).toBool());
1041
1042    m_layout->addRow(tr("Ignore paper color:"), m_ignorePaperColorCheckBox);
1043
1044#endif // HAS_POPPLER_35
1045
1046#ifdef HAS_POPPLER_22
1047
1048    // overprint preview
1049
1050    m_overprintPreviewCheckBox = new QCheckBox(this);
1051    m_overprintPreviewCheckBox->setChecked(m_settings->value("overprintPreview", Defaults::overprintPreview).toBool());
1052
1053    m_layout->addRow(tr("Overprint preview:"), m_overprintPreviewCheckBox);
1054
1055#endif // HAS_POPPLER_22
1056
1057#ifdef HAS_POPPLER_24
1058
1059    m_thinLineModeComboBox = new QComboBox(this);
1060    m_thinLineModeComboBox->addItem(tr("None"));
1061    m_thinLineModeComboBox->addItem(tr("Solid"));
1062    m_thinLineModeComboBox->addItem(tr("Shaped"));
1063    m_thinLineModeComboBox->setCurrentIndex(m_settings->value("thinLineMode", Defaults::thinLineMode).toInt());
1064
1065    m_layout->addRow(tr("Thin line mode:"), m_thinLineModeComboBox);
1066
1067#endif // HAS_POPPLER_24
1068
1069    m_backendComboBox = new QComboBox(this);
1070    m_backendComboBox->addItem(tr("Splash"));
1071    m_backendComboBox->addItem(tr("Arthur"));
1072    m_backendComboBox->setCurrentIndex(m_settings->value("backend", Defaults::backend).toInt());
1073
1074    m_layout->addRow(tr("Backend:"), m_backendComboBox);
1075}
1076
1077void PdfSettingsWidget::accept()
1078{
1079    m_settings->setValue("antialiasing", m_antialiasingCheckBox->isChecked());
1080    m_settings->setValue("textAntialiasing", m_textAntialiasingCheckBox->isChecked());
1081
1082#ifdef HAS_POPPLER_18
1083
1084    m_settings->setValue("textHinting", m_textHintingComboBox->currentIndex());
1085
1086#else
1087
1088    m_settings->setValue("textHinting", m_textHintingCheckBox->isChecked());
1089
1090#endif // HAS_POPPLER_18
1091
1092#ifdef HAS_POPPLER_35
1093
1094    m_settings->setValue("ignorePaperColor", m_ignorePaperColorCheckBox->isChecked());
1095
1096#endif // HAS_POPPLER_35
1097
1098#ifdef HAS_POPPLER_22
1099
1100    m_settings->setValue("overprintPreview", m_overprintPreviewCheckBox->isChecked());
1101
1102#endif // HAS_POPPLER_22
1103
1104#ifdef HAS_POPPLER_24
1105
1106    m_settings->setValue("thinLineMode", m_thinLineModeComboBox->currentIndex());
1107
1108#endif // HAS_POPPLER_24
1109
1110    m_settings->setValue("backend", m_backendComboBox->currentIndex());
1111}
1112
1113void PdfSettingsWidget::reset()
1114{
1115    m_antialiasingCheckBox->setChecked(Defaults::antialiasing);
1116    m_textAntialiasingCheckBox->setChecked(Defaults::textAntialiasing);
1117
1118#ifdef HAS_POPPLER_18
1119
1120    m_textHintingComboBox->setCurrentIndex(Defaults::textHinting);
1121
1122#else
1123
1124    m_textHintingCheckBox->setChecked(Defaults::textHinting);
1125
1126#endif // HAS_POPPLER_18
1127
1128#ifdef HAS_POPPLER_35
1129
1130    m_ignorePaperColorCheckBox->setChecked(Defaults::ignorePaperColor);
1131
1132#endif // HAS_POPPLER_35
1133
1134#ifdef HAS_POPPLER_22
1135
1136    m_overprintPreviewCheckBox->setChecked(Defaults::overprintPreview);
1137
1138#endif // HAS_POPPLER_22
1139
1140#ifdef HAS_POPPLER_24
1141
1142    m_thinLineModeComboBox->setCurrentIndex(Defaults::thinLineMode);
1143
1144#endif // HAS_POPPLER_24
1145
1146    m_backendComboBox->setCurrentIndex(Defaults::backend);
1147}
1148
1149PdfPlugin::PdfPlugin(QObject* parent) : QObject(parent)
1150{
1151    setObjectName("PdfPlugin");
1152
1153//    m_settings = new QSettings("qpdfview", "pdf-plugin", this);
1154    m_settings = new QSettings("murrupuy", "pdf-plugin", this);
1155
1156}
1157
1158Model::Document* PdfPlugin::loadDocument(const QString& filePath) const
1159{
1160    Poppler::Document* document = Poppler::Document::load(filePath);
1161
1162    if(document != 0)
1163    {
1164        document->setRenderHint(Poppler::Document::Antialiasing, m_settings->value("antialiasing", Defaults::antialiasing).toBool());
1165        document->setRenderHint(Poppler::Document::TextAntialiasing, m_settings->value("textAntialiasing", Defaults::textAntialiasing).toBool());
1166
1167#if defined(HAS_POPPLER_18)
1168
1169        switch(m_settings->value("textHinting", Defaults::textHinting).toInt())
1170        {
1171        default:
1172        case 0:
1173            document->setRenderHint(Poppler::Document::TextHinting, false);
1174            break;
1175        case 1:
1176            document->setRenderHint(Poppler::Document::TextHinting, true);
1177            document->setRenderHint(Poppler::Document::TextSlightHinting, false);
1178            break;
1179        case 2:
1180            document->setRenderHint(Poppler::Document::TextHinting, true);
1181            document->setRenderHint(Poppler::Document::TextSlightHinting, true);
1182            break;
1183        }
1184
1185#elif defined(HAS_POPPLER_14)
1186
1187        document->setRenderHint(Poppler::Document::TextHinting, m_settings->value("textHinting", Defaults::textHinting).toBool());
1188
1189#endif // HAS_POPPLER_18 HAS_POPPLER_14
1190
1191#ifdef HAS_POPPLER_35
1192
1193        document->setRenderHint(Poppler::Document::IgnorePaperColor, m_settings->value("ignorePaperColor", Defaults::ignorePaperColor).toBool());
1194
1195#endif // HAS_POPPLER_35
1196
1197#ifdef HAS_POPPLER_22
1198
1199        document->setRenderHint(Poppler::Document::OverprintPreview, m_settings->value("overprintPreview", Defaults::overprintPreview).toBool());
1200
1201#endif // HAS_POPPLER_22
1202
1203#ifdef HAS_POPPLER_24
1204
1205        switch(m_settings->value("thinLineMode", Defaults::thinLineMode).toInt())
1206        {
1207        default:
1208        case 0:
1209            document->setRenderHint(Poppler::Document::ThinLineSolid, false);
1210            document->setRenderHint(Poppler::Document::ThinLineShape, false);
1211            break;
1212        case 1:
1213            document->setRenderHint(Poppler::Document::ThinLineSolid, true);
1214            document->setRenderHint(Poppler::Document::ThinLineShape, false);
1215            break;
1216        case 2:
1217            document->setRenderHint(Poppler::Document::ThinLineSolid, false);
1218            document->setRenderHint(Poppler::Document::ThinLineShape, true);
1219            break;
1220        }
1221
1222#endif // HAS_POPPLER_24
1223
1224        switch(m_settings->value("backend", Defaults::backend).toInt())
1225        {
1226        default:
1227        case 0:
1228            document->setRenderBackend(Poppler::Document::SplashBackend);
1229            break;
1230        case 1:
1231            document->setRenderBackend(Poppler::Document::ArthurBackend);
1232            break;
1233        }
1234    }
1235
1236    return document != 0 ? new Model::PdfDocument(document) : 0;
1237}
1238
1239SettingsWidget* PdfPlugin::createSettingsWidget(QWidget* parent) const
1240{
1241    return new PdfSettingsWidget(m_settings, parent);
1242}
1243
1244} // qpdfview
1245
1246#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
1247
1248Q_EXPORT_PLUGIN2(qpdfview_pdf, qpdfview::PdfPlugin)
1249
1250#endif // QT_VERSION
Note: See TracBrowser for help on using the repository browser.