//#include "MainWindow.ih"
// Custom includes
-#include <QWebView>
-#include "Publisher.hh"
+#include "Viewer.hh"
//#include "MainWindow.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ pykit::MainWindow::MainWindow(QUrl const & url, Publisher * publisher,
- QWidget * parent)
- : QMainWindow (parent)
+prefix_ pykit::MainWindow::MainWindow(QUrl const & url, Publisher * publisher,
+ QWidget * parent)
+ : QMainWindow (parent)
{
- //QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);
-
- QWebView *view = new QWebView;
- view->page()->setNetworkAccessManager(
- new InternalNetworkAccessManager(view->page()->networkAccessManager(), view, publisher));
-
- view->load(url);
-
+ Viewer * view = new Viewer(url, publisher, this);
setCentralWidget(view);
}
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Stefan Bund <info@j32.de>
+
+/** \file
+ \brief PDFWidget non-inline non-template implementation */
+
+#include "PDFWidget.hh"
+//#include "PDFWidget.ih"
+
+// Custom includes
+#include <iostream>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+//#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,
+ QWidget * parent)
+ : QLabel(parent), manager_ (manager), currentPage_ (0)
+{
+ document_.reset(Poppler::Document::load(document));
+ showPage();
+}
+
+prefix_ void pykit::PDFWidget::load(QUrl const & url)
+{
+ QNetworkRequest request (url);
+ QNetworkReply * reply (manager_->get(request));
+ connect(reply, SIGNAL(finished()), this, SLOT(netLoadDocument()));
+}
+
+prefix_ void pykit::PDFWidget::netLoadDocument()
+{
+ QNetworkReply * reply = static_cast<QNetworkReply*>(sender());
+ if (reply->error() != QNetworkReply::NoError)
+ return;
+ QByteArray data (reply->read(reply->size()));
+ document_.reset(Poppler::Document::loadFromData(data));
+ showPage();
+ reply->deleteLater();
+}
+
+prefix_ void pykit::PDFWidget::showPage()
+{
+ if (! document_)
+ return;
+ QImage image (document_->page(currentPage_)->renderToImage(
+ physicalDpiX(), physicalDpiY()));
+ setPixmap(QPixmap::fromImage(image));
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "PDFWidget.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "j32"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -U"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Stefan Bund <info@j32.de>
+
+/** \file
+ \brief PDFWidget public header */
+
+#ifndef HH_PyKit_PDFWidget_
+#define HH_PyKit_PDFWidget_ 1
+
+// Custom includes
+#include <poppler/qt4/poppler-qt4.h>
+#include <boost/scoped_ptr.hpp>
+#include <QLabel>
+#include <QString>
+#include <QWidget>
+#include <QNetworkAccessManager>
+#include <QUrl>
+
+//#include "PDFWidget.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace pykit {
+
+ class PDFWidget : public QLabel
+ {
+ Q_OBJECT;
+ public:
+ explicit PDFWidget(QNetworkAccessManager * manager, QWidget * parent = 0);
+ PDFWidget(QString const & document, QNetworkAccessManager * manager,
+ QWidget * parent = 0);
+
+ void load(QUrl const & url);
+
+ private slots:
+ void netLoadDocument();
+
+ private:
+ void showPage();
+
+ QNetworkAccessManager * manager_;
+ boost::scoped_ptr<Poppler::Document> document_;
+ int currentPage_;
+ };
+
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "PDFWidget.cci"
+//#include "PDFWidget.ct"
+//#include "PDFWidget.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "j32"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -U"
+// End:
void clearResponse();
protected:
- qint64 readData(char * data, qint64 maxSize);
- qint64 writeData(char const * data, qint64 maxSize);
+ virtual qint64 readData(char * data, qint64 maxSize);
+ virtual qint64 writeData(char const * data, qint64 maxSize);
signals:
void initSignal();
prefix_ void pykit::Request::write(std::string const & data)
{
- reply_.write(data.c_str());
+ reply_.write(QByteArray(data.data(),data.size()));
}
prefix_ void pykit::Request::reset()
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QBuffer>
+#include <boost/noncopyable.hpp>
//#include "Publisher.mpp"
///////////////////////////////hh.p////////////////////////////////////////
};
class Publisher
+ : boost::noncopyable
{
public:
virtual ~Publisher() {}
//#include "PythonPublisher.ih"
// Custom includes
+#include <iostream>
+#include <boost/python.hpp>
#include "Publisher.hh"
//#include "PythonPublisher.mpp"
namespace py = boost::python;
+struct pykit::PythonPublisher::Impl
+{
+ boost::python::dict mainNamespace;
+ Publisher * pythonPublisher;
+};
+
+#define PYTHON_PREPARE_IMPORT(module) \
+ PyImport_AppendInittab(const_cast<char*>(#module), init ## module)
+
namespace {
struct PublisherPyWrapper
static PyObject * convert(QString const & s)
{
std::wstring ws (s.toStdWString());
- return PyUnicode_FromWideChar(ws.c_str(), ws.length());
+ return PyUnicode_FromWideChar(ws.data(), ws.length());
}
};
static void construct(PyObject * o,
py::converter::rvalue_from_python_stage1_data * data)
{
+ unsigned length (PyString_Size(o));
const char * value (PyString_AsString(o));
void * storage (((py::converter::rvalue_from_python_storage<QByteArray>*)
data)->storage.bytes);
- new (storage) QByteArray(value);
+ new (storage) QByteArray(value,length);
data->convertible = storage;
}
}
prefix_ pykit::PythonPublisher::PythonPublisher(std::string initPy)
+ : impl_ (new Impl)
{
- PYTHON_PREPARE_IMPORT(_pykit);
- PYTHON_PREPARE_IMPORT(_qt);
- Py_Initialize();
- py::object mainModule_ = py::import("__main__");
- mainNamespace_ = py::extract<py::dict>(mainModule_.attr("__dict__"));
- mainNamespace_["__file__"] = py::str(initPy.c_str());
- py::object ignored (
- py::exec_file(initPy.c_str(), mainNamespace_, mainNamespace_));
- pythonPublisher_ = py::extract<Publisher*>(mainNamespace_["publisher"]);
+ try {
+ PYTHON_PREPARE_IMPORT(_pykit);
+ PYTHON_PREPARE_IMPORT(_qt);
+ Py_Initialize();
+ py::object mainModule_ = py::import("__main__");
+ impl_->mainNamespace = py::extract<py::dict>(mainModule_.attr("__dict__"));
+ impl_->mainNamespace["__file__"] = py::str(initPy.c_str());
+ py::object ignored (
+ py::exec_file(initPy.c_str(), impl_->mainNamespace, impl_->mainNamespace));
+ impl_->pythonPublisher = py::extract<Publisher*>(impl_->mainNamespace["publisher"]);
+ }
+ catch (boost::python::error_already_set & ex) {
+ PyErr_Print();
+ throw;
+ }
}
+prefix_ pykit::PythonPublisher::~PythonPublisher()
+{}
+
prefix_ void pykit::PythonPublisher::publish(Request & request)
{
try {
- pythonPublisher_->publish(request);
+ impl_->pythonPublisher->publish(request);
}
catch (py::error_already_set & ex) {
PyErr_Print();
#define HH_PyKit_PythonPublisher_ 1
// Custom includes
-#include <boost/python.hpp>
+#include <boost/scoped_ptr.hpp>
#include "Publisher.hh"
//#include "PythonPublisher.mpp"
: public Publisher
{
public:
- PythonPublisher(std::string initPy);
+ explicit PythonPublisher(std::string initPy);
+ ~PythonPublisher();
void publish(Request & request);
private:
- boost::python::dict mainNamespace_;
- Publisher * pythonPublisher_;
+ struct Impl;
+ boost::scoped_ptr<Impl> impl_;
};
-# define PYTHON_PREPARE_IMPORT(module) \
- PyImport_AppendInittab(const_cast<char*>(#module), init ## module)
-
}
///////////////////////////////hh.e////////////////////////////////////////
env.EnableQt4Modules([ 'QtWebKit', 'QtNetwork', 'QtSvg', 'QtXml', 'QtGui', 'QtCore' ])
env.Append(
- CXXFLAGS = [ '-Wall', '-Wextra' ],
- CPPPATH = [ '$LIBPYTHONINCLUDES' ],
- LIBS = [ '$LIBBOOSTPYTHON', '$LIBPYTHON' ]
+ CXXFLAGS = [ '-Wall', '-Wextra' ],
+ LIBS = [ '$BOOSTPYLIBS', '$POPPLERLIBS' ],
)
-sources = env.Qt4Glob()
-
-pykit = env.Program('pykit', sources)
+pykit = env.Program('pykit', env.Qt4Glob())
env.Default(pykit)
env = Environment(ENV = os.environ)
env.SetDefault(
- PYTHON = 'python',
- LIBPYTHON = 'python$PYTHONVERSION',
- LIBPYTHONINCLUDES = '/usr/include/python$PYTHONVERSION',
- LIBBOOSTPYTHON = 'boost_python'
+ BOOSTPYLIBS = [ 'boost_python' ],
+ POPPLERLIBS = [ 'poppler', 'poppler-qt4' ],
)
-env.SetDefault(
- PYTHONVERSION = os.popen(env.subst(
- """$PYTHON -c 'import sys; print".".join(map(str,sys.version_info[:2]))'""")).read(),
-)
+env.MergeFlags('!python-config --cflags')
+env.MergeFlags('!python-config --ldflags')
Export('env')
-
env.SConscript("SConscript")
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Stefan Bund <info@j32.de>
+
+/** \file
+ \brief Viewer non-inline non-template implementation */
+
+#include "Viewer.hh"
+//#include "Viewer.ih"
+
+// Custom includes
+#include <iostream>
+#include <QWebPluginFactory>
+#include "Publisher.hh"
+#include "PDFWidget.hh"
+
+//#include "Viewer.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+ class PDFWebPluginFactory
+ : public QWebPluginFactory
+ {
+ public:
+ PDFWebPluginFactory(QNetworkAccessManager * manager, QObject * parent = 0);
+
+ QObject * create(QString const & mimeType, QUrl const & url,
+ QStringList const & argumentNames, QStringList const & argumentValues)
+ const;
+ QList<QWebPluginFactory::Plugin> plugins() const;
+
+ private:
+ QNetworkAccessManager * manager_;
+ };
+
+}
+
+prefix_ PDFWebPluginFactory::PDFWebPluginFactory(QNetworkAccessManager * manager,
+ QObject * parent)
+ : QWebPluginFactory(parent), manager_ (manager)
+{}
+
+prefix_ QObject * PDFWebPluginFactory::create(QString const & mimeType, QUrl const & url,
+ QStringList const & /* argumentNames */,
+ QStringList const & /* argumentValues */)
+ const
+{
+ if (mimeType == "application/x-pdf") {
+ pykit::PDFWidget * plugin = new pykit::PDFWidget(manager_);
+ plugin->load(url);
+ return plugin;
+ }
+ return 0;
+}
+
+prefix_ QList<QWebPluginFactory::Plugin> PDFWebPluginFactory::plugins()
+ const
+{
+ QList<QWebPluginFactory::Plugin> plugins;
+
+ {
+ QWebPluginFactory::Plugin plugin;
+ plugin.name = "PDF viewer";
+ plugin.description = "View PDF files";
+ {
+ QWebPluginFactory::MimeType mimeType;
+ mimeType.name = "application/x-pdf";
+ mimeType.description = "PDF file";
+ plugin.mimeTypes += mimeType;
+ }
+ plugins += plugin;
+ }
+
+ return plugins;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// pykit::Viewer
+
+prefix_ pykit::Viewer::Viewer(QUrl const & url, Publisher * publisher, QWidget * parent)
+ : QWebView (parent)
+{
+ QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);
+ page()->setNetworkAccessManager(
+ new InternalNetworkAccessManager(page()->networkAccessManager(), this, publisher));
+ page()->setPluginFactory(new PDFWebPluginFactory (page()->networkAccessManager(), this));
+ load(url);
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Viewer.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "j32"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -U"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Stefan Bund <info@j32.de>
+
+/** \file
+ \brief Viewer public header */
+
+#ifndef HH_PyKit_Viewer_
+#define HH_PyKit_Viewer_ 1
+
+// Custom includes
+#include <QWebView>
+#include <QUrl>
+
+//#include "Viewer.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace pykit {
+
+ class Publisher;
+
+ class Viewer
+ : public QWebView
+ {
+ Q_OBJECT;
+ public:
+ Viewer(QUrl const & url, Publisher * publisher, QWidget * parent = 0);
+ };
+
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "Viewer.cci"
+//#include "Viewer.ct"
+//#include "Viewer.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "j32"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -U"
+// End:
#include <QApplication>
#include <QSplashScreen>
#include <QSettings>
-#include <boost/python.hpp>
#include <boost/scoped_ptr.hpp>
#include "MainWindow.hh"
#include "PythonPublisher.hh"
return app.exec();
}
- catch (boost::python::error_already_set & ex) {
- PyErr_Print();
- throw;
- }
catch (std::exception & ex) {
std::cerr << "Exception:\n" << ex.what() << "\n";
throw;
--- /dev/null
+;; Configuration file for cc-ide.el (Emacs C++ IDE extension, see http://g0dil.de)
+
+(defun check-namespace-indent (arg)
+ (save-excursion
+ (back-to-indentation)
+ (if (and (looking-at "namespace")
+ (looking-at ".*{")
+ (not (looking-at ".*}")))
+ [0] '+)))
+
+(defconst j32-c-style
+ '((c-basic-offset . 4)
+ (c-access-key . "\\(public\\|protected\\|private\\|signals\\|public\\s-*slots\\|protected\\s-*slots\\|private\\s-slots\\)\\s-*:")
+ (c-backslash-column . 98)
+ (c-cleanup-list . (empty-defun-braces
+ defun-close-semi
+ list-close-comma
+ scope-operator))
+ (c-hanging-braces-alist . ((namespace-open after)
+ (namespace-close before after)
+ (brace-list-open)
+ (brace-entry-open)
+ (substatement-open after)
+ (block-close . c-snug-do-while)
+ (extern-lang-open after)
+ (inexpr-class-open after)
+ (inexpr-class-close before)))
+ (c-offsets-alist . ((namespace-open . [0])
+ (namespace-close . [0])
+ (innamespace . check-namespace-indent)
+ (statement-block-intro . +)
+ (substatement-open . 0)
+ (label . 0)
+ (statement-cont . +))) ))
+
+(c-add-style "j32" j32-c-style)
+
+(set (make-local-variable 'ccide-file-vars)
+ '((fill-column . 100)
+ (comment-column . 40)
+ (c-file-style . "j32")
+ (indent-tabs-mode . nil)
+ (ispell-local-dictionary . "american")
+ (compile-command . "scons -U")))
+
+(set (make-local-variable 'ccide-project-name) "PyKit")
+
+(let ((local-conf (ccide-project-search-upwards "project-local.el")))
+ (if local-conf
+ (load-file local-conf)))
+
+(setq indent-tabs-mode nil) ;; needed since whitespace-mode caches this value ...
+(whitespace-mode 1)
+
+(message "Loaded project settings.")
+\f
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End: