Add PDFWidget JavaScript API
Stefan Bund [Wed, 15 Dec 2010 14:30:18 +0000 (15:30 +0100)]
PDFWidget.cc
PDFWidget.hh
Viewer.cc

index a768e4f..e27939b 100644 (file)
 #include <iostream>
 #include <QNetworkRequest>
 #include <QNetworkReply>
+#include <QKeyEvent>
+#include <QWebView>
+#include <QWebFrame>
 
 //#include "PDFWidget.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ pykit::PDFWidget::PDFWidget(QNetworkAccessManager * manager, QWidget * parent)
-    : QLabel(parent), manager_ (manager), currentPage_ (0)
-{}
-
-prefix_ pykit::PDFWidget::PDFWidget(QString const & document, QNetworkAccessManager * manager,
+prefix_ pykit::PDFWidget::PDFWidget(QString const & id, QNetworkAccessManager * manager,
                                     QWidget * parent)
-    : QLabel(parent), manager_ (manager), currentPage_ (0)
+    : QLabel(parent), id_ (id), manager_ (manager), currentPage_ (0), dpi_ (96.0), x_ (0), y_ (0)
+
+{
+    QWebView * webView (dynamic_cast<QWebView*>(parent));
+    if (webView && !id_.isEmpty())
+        webView->page()->mainFrame()->addToJavaScriptWindowObject(id_,this);
+}
+
+prefix_ pykit::PDFWidget::PDFWidget(QString const & id, QString const & document,
+                                    QNetworkAccessManager * manager, QWidget * parent)
+    : QLabel(parent), id_ (id), manager_ (manager), currentPage_ (0), dpi_ (96.0), x_ (0), y_ (0)
+
 {
+    setFocusPolicy(Qt::WheelFocus);
     document_.reset(Poppler::Document::load(document));
+    QWebView * webView (dynamic_cast<QWebView*>(parent));
+    if (webView && !id_.isEmpty())
+        webView->page()->mainFrame()->addToJavaScriptWindowObject(id_,this);
     documentSetup();
-    showPage();
 }
 
 prefix_ void pykit::PDFWidget::load(QUrl const & url)
@@ -38,6 +51,134 @@ prefix_ void pykit::PDFWidget::load(QUrl const & url)
     connect(reply, SIGNAL(finished()), this, SLOT(netLoadDocument()));
 }
 
+prefix_ void pykit::PDFWidget::zoomIn()
+{
+    zoomMode_ = Manual;
+    double n (dpi_ + ZoomStepDpi);
+    if (n > ZoomMaxDpi)
+        n = ZoomMaxDpi;
+    if (n != dpi_) {
+        dpi_ = n;
+        showPage();
+    }
+}
+
+prefix_ void pykit::PDFWidget::zoomOut()
+{
+    zoomMode_ = Manual;
+    double n (dpi_ - ZoomStepDpi);
+    if (n < ZoomMinDpi)
+        n = ZoomMinDpi;
+    if (n != dpi_) {
+        dpi_ = n;
+        showPage();
+    }
+}
+
+prefix_ void pykit::PDFWidget::zoomDPI(double dpi)
+{
+    zoomMode_ = Manual;
+    if (dpi < ZoomMinDpi)
+        dpi = ZoomMinDpi;
+    if (dpi > ZoomMaxDpi)
+        dpi = ZoomMaxDpi;
+    if (dpi != dpi_) {
+        dpi_ = dpi;
+        showPage();
+    }
+}
+
+prefix_ int pykit::PDFWidget::zoomWidth(int w)
+{
+    zoomMode_ = Width;
+    if (! document_)
+        return 0;
+    if (w == -1)
+        w = width();
+    QSizeF pageSize (document_->page(currentPage_)->pageSizeF());
+    double n = 72.0 * w / pageSize.width();
+    if (n > ZoomMaxDpi)
+        n = ZoomMaxDpi;
+    if (n < ZoomMinDpi)
+        n = ZoomMinDpi;
+    if (n != dpi_) {
+        dpi_ = n;
+        showPage();
+    }
+    return pageSize.height() * dpi_ / 72.0;
+}
+
+prefix_ int pykit::PDFWidget::zoomHeight()
+{
+    zoomMode_ = Height;
+    if (! document_)
+        return 0;
+    QSizeF pageSize (document_->page(currentPage_)->pageSizeF());
+    double n = 72.0 * height() / pageSize.height();
+    if (n > ZoomMaxDpi)
+        n = ZoomMaxDpi;
+    if (n < ZoomMinDpi)
+        n = ZoomMinDpi;
+    if (n != dpi_) {
+        dpi_ = n;
+        showPage();
+    }
+    return pageSize.width() * dpi_ / 72.0;
+}
+
+prefix_ void pykit::PDFWidget::zoomFit()
+{
+    zoomMode_ = Fit;
+    if (! document_)
+        return;
+    QSizeF pageSize (document_->page(currentPage_)->pageSizeF());
+    double xres = 72.0 * width() / pageSize.width();
+    double yres = 72.0 * height() / pageSize.height();
+    double n = xres < yres ? xres : yres;
+    if (n > ZoomMaxDpi)
+        n = ZoomMaxDpi;
+    if (n < ZoomMinDpi)
+        n = ZoomMinDpi;
+    if (n != dpi_) {
+        dpi_ = n;
+        showPage();
+    }
+}
+
+prefix_ int pykit::PDFWidget::getPDFWidth()
+{
+    if (! document_)
+        return 0;
+    QSizeF pageSize (document_->page(currentPage_)->pageSizeF());
+    return pageSize.width() * dpi_ / 72.0;
+}
+
+prefix_ int pykit::PDFWidget::getPDFHeight()
+{
+    if (! document_)
+        return 0;
+    QSizeF pageSize (document_->page(currentPage_)->pageSizeF());
+    return pageSize.height() * dpi_ / 72.0;
+}
+
+prefix_ void pykit::PDFWidget::resizeEvent(QResizeEvent *)
+{
+    switch (zoomMode_) {
+    case Manual:
+        break;
+    case Width:
+        zoomWidth();
+        break;
+    case Height:
+        zoomHeight();
+        break;
+    case Fit:
+        zoomFit();
+        break;
+    }
+    showPage();
+}
+
 prefix_ void pykit::PDFWidget::netLoadDocument()
 {
     QNetworkReply * reply = static_cast<QNetworkReply*>(sender());
@@ -46,15 +187,18 @@ prefix_ void pykit::PDFWidget::netLoadDocument()
     QByteArray data (reply->read(reply->size()));
     document_.reset(Poppler::Document::loadFromData(data));
     documentSetup();
-    showPage();
     reply->deleteLater();
 }
 
 prefix_ void pykit::PDFWidget::documentSetup()
 {
+    if (! document_)
+        return;
     document_->setRenderHint(Poppler::Document::Antialiasing, true);
     document_->setRenderHint(Poppler::Document::TextAntialiasing, true);
     document_->setRenderHint(Poppler::Document::TextHinting, false);
+    zoomFit();
+    showPage();
 }
 
 prefix_ void pykit::PDFWidget::showPage()
@@ -62,7 +206,7 @@ prefix_ void pykit::PDFWidget::showPage()
     if (! document_)
         return;
     QImage image (document_->page(currentPage_)->renderToImage(
-                      physicalDpiX(), physicalDpiY()));
+                      dpi_, dpi_, x_, y_, width(), height()));
     setPixmap(QPixmap::fromImage(image));
 }
 
@@ -78,5 +222,5 @@ prefix_ void pykit::PDFWidget::showPage()
 // c-file-style: "j32"
 // indent-tabs-mode: nil
 // ispell-local-dictionary: "american"
-// compile-command: "scons -U"
+// compile-command: "make"
 // End:
index bbb7e51..9a82461 100644 (file)
@@ -27,12 +27,28 @@ namespace pykit {
     {
         Q_OBJECT;
     public:
-        explicit PDFWidget(QNetworkAccessManager * manager, QWidget * parent = 0);
-        PDFWidget(QString const & document, QNetworkAccessManager * manager,
+        explicit PDFWidget(QString const & id, QNetworkAccessManager * manager,
+                           QWidget * parent = 0);
+        PDFWidget(QString const & id, QString const & document, QNetworkAccessManager * manager,
                   QWidget * parent = 0);
 
         void load(QUrl const & url);
 
+    public slots:
+        void zoomIn();
+        void zoomOut();
+        void zoomDPI(double dpi);
+
+        int zoomWidth(int w = -1);
+        int zoomHeight();
+        void zoomFit();
+
+        int getPDFWidth();
+        int getPDFHeight();
+
+    protected:
+        virtual void resizeEvent(QResizeEvent * event);
+
     private slots:
         void netLoadDocument();
 
@@ -40,9 +56,19 @@ namespace pykit {
         void documentSetup();
         void showPage();
 
+        enum ZoomMode { Manual, Width, Height, Fit };
+        static double const ZoomStepDpi = 20.0;
+        static double const ZoomMaxDpi = 200.0;
+        static double const ZoomMinDpi = 50.0;
+
+        QString id_;
         QNetworkAccessManager * manager_;
         boost::scoped_ptr<Poppler::Document> document_;
         int currentPage_;
+        ZoomMode zoomMode_;
+        double dpi_;
+        int x_;
+        int y_;
     };
 
 }
index c9101ee..7c726c9 100644 (file)
--- a/Viewer.cc
+++ b/Viewer.cc
@@ -48,12 +48,17 @@ prefix_ PDFWebPluginFactory::PDFWebPluginFactory(QNetworkAccessManager * manager
 {}
 
 prefix_ QObject * PDFWebPluginFactory::create(QString const & mimeType, QUrl const & url,
-                                              QStringList const & /* argumentNames */,
-                                              QStringList const & /* argumentValues */)
+                                              QStringList const & argumentNames,
+                                              QStringList const & argumentValues)
     const
 {
     if (mimeType == "application/pdf") {
-        pykit::PDFWidget * plugin = new pykit::PDFWidget(manager_);
+        int idix (argumentNames.indexOf("id"));
+        QString id;
+        if (idix>0)
+            id = argumentValues[idix];
+        pykit::PDFWidget * plugin = new pykit::PDFWidget(
+            id, manager_, dynamic_cast<QWidget*>(parent()));
         plugin->load(url);
         return plugin;
     }