typo fix
[pykit.git] / PDFWidget.cc
1 // $Id$
2 //
3 // Copyright (C) 2010
4 //     Stefan Bund <info@j32.de>
5
6 /** \file
7     \brief PDFWidget non-inline non-template implementation */
8
9 #include "PDFWidget.hh"
10 //#include "PDFWidget.ih"
11
12 // Custom includes
13 #include <iostream>
14 #include <boost/foreach.hpp>
15 #include <QNetworkRequest>
16 #include <QNetworkReply>
17 #include <QKeyEvent>
18 #include <QWebView>
19 #include <QWebFrame>
20 #include <QApplication>
21 #include <QClipboard>
22
23 //#include "PDFWidget.mpp"
24 #define prefix_
25 ///////////////////////////////cc.p////////////////////////////////////////
26
27 prefix_ pykit::PDFWidget::PDFWidget(QString const & id, QNetworkAccessManager * manager,
28                                     QWidget * parent)
29     : QLabel(parent), id_ (id), manager_ (manager), currentPage_ (0), rubberBand_ (0)
30
31 {
32     QWebView * webView (dynamic_cast<QWebView*>(parent));
33     if (webView && !id_.isEmpty())
34         webView->page()->mainFrame()->addToJavaScriptWindowObject(id_, this);
35 }
36
37 prefix_ pykit::PDFWidget::PDFWidget(QString const & id, QString const & document,
38                                     QNetworkAccessManager * manager, QWidget * parent)
39     : QLabel(parent), id_ (id), manager_ (manager), currentPage_ (0), rubberBand_ (0)
40
41 {
42     setFocusPolicy(Qt::WheelFocus);
43     document_.reset(Poppler::Document::load(document));
44     QWebView * webView (dynamic_cast<QWebView*>(parent));
45     if (webView && !id_.isEmpty())
46         webView->page()->mainFrame()->addToJavaScriptWindowObject(id_, this);
47     documentSetup();
48 }
49
50 prefix_ pykit::PDFWidget::~PDFWidget()
51 {
52     if (rubberBand_)
53         delete rubberBand_;
54 }
55
56
57 prefix_ void pykit::PDFWidget::load(QUrl const & url)
58 {
59     QNetworkRequest request (url);
60     QNetworkReply * reply (manager_->get(request));
61     connect(reply, SIGNAL(finished()), this, SLOT(netLoadDocument()));
62 }
63
64 prefix_ void pykit::PDFWidget::resizeEvent(QResizeEvent *)
65 {
66     if (! document_)
67         return;
68     QSizeF pageSize (document_->page(currentPage_)->pageSizeF());
69     double n = 72.0 * width() / pageSize.width();
70     if (n != dpi_) {
71         dpi_ = n;
72         showPage();
73     }
74 }
75
76 prefix_ void pykit::PDFWidget::mousePressEvent(QMouseEvent * event)
77 {
78     origin_ = event->pos();
79     if (! rubberBand_)
80         rubberBand_ = new QRubberBand(QRubberBand::Rectangle, this);
81     rubberBand_->setGeometry(QRect(origin_, QSize()));
82     rubberBand_->show();
83 }
84
85 prefix_ void pykit::PDFWidget::mouseMoveEvent(QMouseEvent * event)
86 {
87     if (rubberBand_)
88         rubberBand_->setGeometry(QRect(origin_, event->pos()).normalized());
89 }
90
91 prefix_ void pykit::PDFWidget::mouseReleaseEvent(QMouseEvent *)
92 {
93     if (rubberBand_) {
94         QMatrix matrix (dpi_ / 72.0, 0, 0, dpi_ / 72.0, 0, 0);
95         QRectF rect (matrix.inverted().mapRect(QRect(rubberBand_->pos(), rubberBand_->size())));
96         QString text = document_->page(currentPage_)->text(rect);
97         if (! text.isEmpty())
98             QApplication::clipboard()->setText(text);
99     }
100 }
101
102 prefix_ void pykit::PDFWidget::netLoadDocument()
103 {
104     QNetworkReply * reply = static_cast<QNetworkReply*>(sender());
105     if (reply->error() != QNetworkReply::NoError)
106         return;
107     QByteArray data (reply->read(reply->size()));
108     document_.reset(Poppler::Document::loadFromData(data));
109     documentSetup();
110     reply->deleteLater();
111 }
112
113 prefix_ void pykit::PDFWidget::documentSetup()
114 {
115     if (! document_)
116         return;
117     document_->setRenderHint(Poppler::Document::Antialiasing, true);
118     document_->setRenderHint(Poppler::Document::TextAntialiasing, true);
119     document_->setRenderHint(Poppler::Document::TextHinting, false);
120     resizeEvent(0);
121     Poppler::Page::SearchDirection dir (Poppler::Page::FromTop);
122     highlightAreas_.clear();
123     BOOST_FOREACH(QString const & str, highlightStrings_) {
124         QRectF highlightArea;
125         while (document_->page(currentPage_)->search(str, highlightArea, dir,
126                                                      Poppler::Page::CaseInsensitive)) {
127             highlightAreas_.push_back(highlightArea);
128             dir = Poppler::Page::NextResult;
129         }
130     }
131     showPage();
132 }
133
134 prefix_ void pykit::PDFWidget::highlightString(QString const & str)
135 {
136     highlightStrings_.append(str);
137     documentSetup();
138 }
139
140 prefix_ void pykit::PDFWidget::showPage()
141 {
142     if (! document_)
143         return;
144     QImage image (document_->page(currentPage_)->renderToImage(
145                       dpi_, dpi_, 0, 0, width(), height()));
146     QMatrix matrix (dpi_ / 72.0, 0, 0, dpi_ / 72.0, 0, 0);
147
148     QPainter painter;
149     painter.begin(&image);
150     painter.setCompositionMode(QPainter::CompositionMode_Darken);
151     BOOST_FOREACH(QRectF const & highlightArea, highlightAreas_) {
152         QRect highlightRect = matrix.mapRect(highlightArea).toRect();
153         highlightRect.adjust(-2, -2, 2, 1);
154         painter.fillRect(highlightRect, QColor(244, 229, 0));
155     }
156     painter.end();
157
158     setPixmap(QPixmap::fromImage(image));
159 }
160
161 ///////////////////////////////cc.e////////////////////////////////////////
162 #undef prefix_
163 //#include "PDFWidget.mpp"
164
165 \f
166 // Local Variables:
167 // mode: c++
168 // fill-column: 100
169 // comment-column: 40
170 // c-file-style: "j32"
171 // indent-tabs-mode: nil
172 // ispell-local-dictionary: "american"
173 // compile-command: "make"
174 // End: