From: Stefan Bund Date: Wed, 20 Oct 2010 10:54:47 +0000 (+0200) Subject: initial release X-Git-Url: http://g0dil.de/git?p=pykit.git;a=commitdiff_plain;h=beb767655c7a9b20a2c6a28831284127f393343f initial release --- beb767655c7a9b20a2c6a28831284127f393343f diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f1142b --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +*~ +moc_* +.sconsign* +*.moc +/pykit diff --git a/MainWindow.cc b/MainWindow.cc new file mode 100644 index 0000000..59913c7 --- /dev/null +++ b/MainWindow.cc @@ -0,0 +1,48 @@ +// $Id$ +// +// Copyright (C) 2010 +// Stefan Bund + +/** \file + \brief MainWindow non-inline non-template implementation */ + +#include "MainWindow.hh" +//#include "MainWindow.ih" + +// Custom includes +#include +#include "Publisher.hh" + +//#include "MainWindow.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +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); + + setCentralWidget(view); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "MainWindow.mpp" + + +// 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: diff --git a/MainWindow.hh b/MainWindow.hh new file mode 100644 index 0000000..86baff4 --- /dev/null +++ b/MainWindow.hh @@ -0,0 +1,46 @@ +// $Id$ +// +// Copyright (C) 2010 +// Stefan Bund + +/** \file + \brief MainWindow public header */ + +#ifndef HH_PyKit_MainWindow_ +#define HH_PyKit_MainWindow_ 1 + +// Custom includes +#include +#include + +//#include "MainWindow.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace pykit { + + class Publisher; + + class MainWindow : public QMainWindow + { + Q_OBJECT; + public: + MainWindow(QUrl const & url, Publisher * publisher, QWidget * parent = 0); + }; +} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "MainWindow.cci" +//#include "MainWindow.ct" +//#include "MainWindow.cti" +#endif + + +// 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: diff --git a/Publisher.cc b/Publisher.cc new file mode 100644 index 0000000..02c3521 --- /dev/null +++ b/Publisher.cc @@ -0,0 +1,231 @@ +// $Id$ +// +// Copyright (C) 2010 + +/** \file + \brief InternalNetworkAccessManager non-inline non-template implementation */ + +#include "Publisher.hh" +//#include "Publisher.ih" + +// Custom includes +#include +#include +#include +#include "Publisher.hh" +#include + +//#include "Publisher.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// pykit::detail::InternalServerReply + +namespace pykit { +namespace detail { + + class InternalServerReply + : public QNetworkReply + { + Q_OBJECT; + public: + InternalServerReply(QNetworkAccessManager::Operation operation, + QNetworkRequest const & networkRequest, + Publisher * publisher); + + // Forwarded to buffer + virtual bool atEnd() const; + virtual qint64 bytesAvailable() const; + virtual qint64 bytesToWrite() const; + virtual bool canReadLine() const; + virtual bool isSequential() const; + virtual qint64 pos() const; + virtual bool reset(); + virtual bool seek(qint64 pos); + virtual qint64 size() const; + virtual bool waitForBytesWritten(int msecs); + virtual bool waitForReadyRead(int msecs); + + virtual void abort(); + + using QNetworkReply::setHeader; + + void clearResponse(); + + protected: + qint64 readData(char * data, qint64 maxSize); + qint64 writeData(char const * data, qint64 maxSize); + + signals: + void initSignal(); + + private slots: + void initSlot(); + + private: + QBuffer buffer_; + }; + +}} + +prefix_ pykit::detail::InternalServerReply:: +InternalServerReply(QNetworkAccessManager::Operation operation, + QNetworkRequest const & networkRequest, Publisher * publisher) +{ + setRequest(networkRequest); + setOperation(operation); + setUrl(networkRequest.url()); + open(ReadWrite | Unbuffered); + buffer_.open(ReadWrite | Unbuffered); + + Request request (*this); + publisher->publish(request); + + seek(0); + setHeader(QNetworkRequest::ContentLengthHeader, QVariant(size())); + setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/html; charset=UTF-8")); + + // The following rigamole is needed to delay emitting readyRead() / finished() after until the + // connections to those signals have been set up. + // + // We use a queued signal here. This will call initSlot after processing has returned to the + // event loop. + connect(this, SIGNAL(initSignal()), this, SLOT(initSlot()), Qt::QueuedConnection); + emit initSignal(); +} + +prefix_ void pykit::detail::InternalServerReply::initSlot() +{ + emit readyRead(); + emit finished(); +} + +prefix_ bool pykit::detail::InternalServerReply::atEnd() + const +{ return buffer_.atEnd(); } + +prefix_ qint64 pykit::detail::InternalServerReply::bytesAvailable() + const +{ return buffer_.bytesAvailable(); } + +prefix_ qint64 pykit::detail::InternalServerReply::bytesToWrite() + const +{ return buffer_.bytesToWrite(); } + +prefix_ bool pykit::detail::InternalServerReply::canReadLine() + const +{ return buffer_.canReadLine(); } + +prefix_ bool pykit::detail::InternalServerReply::isSequential() + const +{ return buffer_.isSequential(); } + +prefix_ qint64 pykit::detail::InternalServerReply::pos() + const +{ return buffer_.pos(); } + +prefix_ bool pykit::detail::InternalServerReply::reset() +{ return buffer_.reset(); } + +prefix_ bool pykit::detail::InternalServerReply::seek(qint64 pos) +{ return buffer_.seek(pos); } + +prefix_ qint64 pykit::detail::InternalServerReply::size() + const +{ return buffer_.size(); } + +prefix_ bool pykit::detail::InternalServerReply::waitForBytesWritten(int msecs) +{ return buffer_.waitForBytesWritten(msecs); } + +prefix_ bool pykit::detail::InternalServerReply::waitForReadyRead(int msecs) +{ return buffer_.waitForReadyRead(msecs); } + +prefix_ qint64 pykit::detail::InternalServerReply::readData(char * data, qint64 maxSize) +{ return buffer_.read(data,maxSize); } + +prefix_ qint64 pykit::detail::InternalServerReply::writeData(char const * data, qint64 maxSize) +{ return buffer_.write(data,maxSize); } + +prefix_ void pykit::detail::InternalServerReply::abort() +{} + +prefix_ void pykit::detail::InternalServerReply::clearResponse() +{ + buffer_.buffer().clear(); +} + +/////////////////////////////////////////////////////////////////////////// +// pykit::Request + +prefix_ void pykit::Request::write(std::string const & data) +{ + reply_.write(data.c_str()); +} + +prefix_ void pykit::Request::reset() +{ + reply_.clearResponse(); +} + +prefix_ void pykit::Request::setContentType(std::string const & contentType) +{ + reply_.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType.c_str())); +} + +prefix_ void pykit::Request::setLocation(std::string const & location) +{ + reply_.setHeader(QNetworkRequest::LocationHeader, QVariant(location.c_str())); +} + +prefix_ QUrl pykit::Request::url() + const +{ + return reply_.url(); +} + +prefix_ pykit::Request::Request(detail::InternalServerReply & reply) + : reply_ (reply) +{} + +/////////////////////////////////////////////////////////////////////////// +// pykit::InternalNetworkAccessManager + +prefix_ pykit::InternalNetworkAccessManager:: +InternalNetworkAccessManager(QNetworkAccessManager * manager, QObject * parent, + Publisher * publisher) + : QNetworkAccessManager(parent), publisher_ (publisher) +{ + setCache(manager->cache()); + setCookieJar(manager->cookieJar()); + setProxy(manager->proxy()); + setProxyFactory(manager->proxyFactory()); +} + +prefix_ QNetworkReply * +pykit::InternalNetworkAccessManager::createRequest(Operation operation, + QNetworkRequest const & request, + QIODevice * device) +{ + if (request.url().scheme() != "srv") + return QNetworkAccessManager::createRequest(operation, request, device); + + return new detail::InternalServerReply(operation, request, publisher_); +} + +#include "Publisher.moc" + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "Publisher.mpp" + + +// 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: diff --git a/Publisher.hh b/Publisher.hh new file mode 100644 index 0000000..5e95625 --- /dev/null +++ b/Publisher.hh @@ -0,0 +1,83 @@ +// $Id$ +// +// Copyright (C) 2010 +// Stefan Bund + +/** \file + \brief InternalNetworkAccessManager public header */ + +#ifndef HH_PyKit_Publisher_ +#define HH_PyKit_Publisher_ 1 + +// Custom includes +#include +#include +#include +#include + +//#include "Publisher.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace pykit { + + namespace detail { class InternalServerReply; } + + class Request + { + public: + void write(std::string const & data); + void reset(); + + void setContentType(std::string const & contentType); + void setLocation(std::string const & location); + + QUrl url() const; + + private: + Request(detail::InternalServerReply & reply); + + detail::InternalServerReply & reply_; + + friend class detail::InternalServerReply; + }; + + class Publisher + { + public: + virtual ~Publisher() {} + virtual void publish(Request & request) = 0; + }; + + class InternalNetworkAccessManager + : public QNetworkAccessManager + { + Q_OBJECT; + public: + InternalNetworkAccessManager(QNetworkAccessManager * manager, QObject * parent, + Publisher * publisher); + + QNetworkReply * createRequest(Operation operation, QNetworkRequest const & request, + QIODevice * device); + + private: + Publisher * publisher_; + }; + +} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "Publisher.cci" +//#include "Publisher.ct" +//#include "Publisher.cti" +#endif + + +// 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: diff --git a/PythonPublisher.cc b/PythonPublisher.cc new file mode 100644 index 0000000..c75fc88 --- /dev/null +++ b/PythonPublisher.cc @@ -0,0 +1,458 @@ +// $Id$ +// +// Copyright (C) 2010 +// Stefan Bund + +/** \file + \brief PythonPublisher non-inline non-template implementation */ + +#include "PythonPublisher.hh" +//#include "PythonPublisher.ih" + +// Custom includes +#include "Publisher.hh" + +//#include "PythonPublisher.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace py = boost::python; + +namespace { + + struct PublisherPyWrapper + : public pykit::Publisher, py::wrapper + { + virtual void publish(pykit::Request & request) + { get_override("publish")(request); } + }; + + namespace pyconvert { + + struct QString_PyUnicode + { + static PyObject * convert(QString const & s) + { + std::wstring ws (s.toStdWString()); + return PyUnicode_FromWideChar(ws.c_str(), ws.length()); + } + }; + + struct PyUnicode_QString + { + static void * convertible(PyObject * o) + { + return PyUnicode_Check(o) ? o : 0; + } + + static void construct(PyObject * o, + py::converter::rvalue_from_python_stage1_data * data) + { + unsigned length (PyUnicode_GetSize(o)); + std::wstring ws (length, 0); + // Hmm ... I don't want to copy the stupid data TWICE but this + // breaks the standard ... who cares ? + PyUnicode_AsWideChar(reinterpret_cast(o), + const_cast(ws.data()), + length); + void * storage (((py::converter::rvalue_from_python_storage*) + data)->storage.bytes); + *(new (storage) QString()) = QString::fromStdWString(ws); + data->convertible = storage; + } + + PyUnicode_QString() + { + py::converter::registry::push_back( + &convertible, + &construct, + py::type_id()); + } + }; + + struct QByteArray_PyString + { + static PyObject * convert(QByteArray const & s) + { + return boost::python::incref(boost::python::object(s.constData()).ptr()); + } + }; + + struct PyString_QByteArray + { + static void * convertible(PyObject * o) + { + return PyString_Check(o) ? o : 0; + } + + static void construct(PyObject * o, + py::converter::rvalue_from_python_stage1_data * data) + { + const char * value (PyString_AsString(o)); + void * storage (((py::converter::rvalue_from_python_storage*) + data)->storage.bytes); + new (storage) QByteArray(value); + data->convertible = storage; + } + + PyString_QByteArray() + { + py::converter::registry::push_back( + &convertible, + &construct, + py::type_id()); + } + }; + + } + + QString QUrl_toString_noargs(QUrl const & url) + { return url.toString(); } + +} + +#define MEMFNP(ret, cls, nam, arg) static_cast(&cls::nam) + +BOOST_PYTHON_MODULE(_qt) +{ + py::to_python_converter(); + pyconvert::PyUnicode_QString register_PyUnicode_QString; + + py::to_python_converter(); + pyconvert::PyString_QByteArray register_PyString_QByteArray; + + // Missing converters: + // QPair <-> tuple + // QList <-> vector + + // QUrl () + py::class_("QUrl", py::init<>()) + // QUrl ( const QString & url ) + .def(py::init()) + // QUrl ( const QUrl & other ) + .def(py::init()) + // QUrl ( const QString & url, ParsingMode parsingMode ) + // .def(init()) + // ~QUrl () + // void addEncodedQueryItem ( const QByteArray & key, const QByteArray & value ) + .def("addEncodedQueryItem", + MEMFNP(void, QUrl, addEncodedQueryItem, + ( const QByteArray & key, const QByteArray & value ))) + // void addQueryItem ( const QString & key, const QString & value ) + .def("addQueryItem", + MEMFNP(void, QUrl, addQueryItem, + ( const QString & key, const QString & value ))) + // QList allEncodedQueryItemValues ( const QByteArray & key ) const + // .def("allEncodedQueryItemValues", + // MEMFNP(QList, QUrl, allEncodedQueryItemValues, + // ( const QByteArray & key ) const)) + // QStringList allQueryItemValues ( const QString & key ) const + // .def("allQueryItemValues", + // MEMFNP(QStringList, QUrl, allQueryItemValues, + // ( const QString & key ) const)) + // QString authority () const + .def("authority", + MEMFNP(QString, QUrl, authority, + () const)) + // void clear () + .def("clear", + MEMFNP(void, QUrl, clear, + ())) + // QByteArray encodedFragment () const + .def("encodedFragment", + MEMFNP(QByteArray, QUrl, encodedFragment, + () const)) + // QByteArray encodedHost () const + .def("encodedHost", + MEMFNP(QByteArray, QUrl, encodedHost, + () const)) + // QByteArray encodedPassword () const + .def("encodedPassword", + MEMFNP(QByteArray, QUrl, encodedPassword, + () const)) + // QByteArray encodedPath () const + .def("encodedPath", + MEMFNP(QByteArray, QUrl, encodedPath, + () const)) + // QByteArray encodedQuery () const + .def("encodedQuery", + MEMFNP(QByteArray, QUrl, encodedQuery, + () const)) + // QByteArray encodedQueryItemValue ( const QByteArray & key ) const + .def("encodedQueryItemValue", + MEMFNP(QByteArray, QUrl, encodedQueryItemValue, + ( const QByteArray & key ) const)) + // QList > encodedQueryItems () const + // .def("encodedQueryItems", + // MEMFNP(QList >, QUrl, encodedQueryItems, + // () const)) + // QByteArray encodedUserName () const + .def("encodedUserName", + MEMFNP(QByteArray, QUrl, encodedUserName, + () const)) + // QString errorString () const + .def("errorString", + MEMFNP(QString, QUrl, errorString, + () const)) + // QString fragment () const + .def("fragment", + MEMFNP(QString, QUrl, fragment, + () const)) + // bool hasEncodedQueryItem ( const QByteArray & key ) const + .def("hasEncodedQueryItem", + MEMFNP(bool, QUrl, hasEncodedQueryItem, + ( const QByteArray & key ) const)) + // bool hasFragment () const + .def("hasFragment", + MEMFNP(bool, QUrl, hasFragment, + () const)) + // bool hasQuery () const + .def("hasQuery", + MEMFNP(bool, QUrl, hasQuery, + () const)) + // bool hasQueryItem ( const QString & key ) const + .def("hasQueryItem", + MEMFNP(bool, QUrl, hasQueryItem, + ( const QString & key ) const)) + // QString host () const + .def("host", + MEMFNP(QString, QUrl, host, + () const)) + // bool isEmpty () const + .def("isEmpty", + MEMFNP(bool, QUrl, isEmpty, + () const)) + // bool isParentOf ( const QUrl & childUrl ) const + .def("isParentOf", + MEMFNP(bool, QUrl, isParentOf, + ( const QUrl & childUrl ) const)) + // bool isRelative () const + .def("isRelative", + MEMFNP(bool, QUrl, isRelative, + () const)) + // bool isValid () const + .def("isValid", + MEMFNP(bool, QUrl, isValid, + () const)) + // QString password () const + .def("password", + MEMFNP(QString, QUrl, password, + () const)) + // QString path () const + .def("path", + MEMFNP(QString, QUrl, path, + () const)) + // int port () const + .def("port", + MEMFNP(int, QUrl, port, + () const)) + // int port ( int defaultPort ) const + .def("port", + MEMFNP(int, QUrl, port, + ( int defaultPort ) const)) + // QString queryItemValue ( const QString & key ) const + .def("queryItemValue", + MEMFNP(QString, QUrl, queryItemValue, + ( const QString & key ) const)) + // QList > queryItems () const + // .def("queryItems", + // MEMFNP(QList >, QUrl, queryItems, + // () const)) + // char queryPairDelimiter () const + .def("queryPairDelimiter", + MEMFNP(char, QUrl, queryPairDelimiter, + () const)) + // char queryValueDelimiter () const + .def("queryValueDelimiter", + MEMFNP(char, QUrl, queryValueDelimiter, + () const)) + // void removeAllEncodedQueryItems ( const QByteArray & key ) + .def("removeAllEncodedQueryItems", + MEMFNP(void, QUrl, removeAllEncodedQueryItems, + ( const QByteArray & key ))) + // void removeAllQueryItems ( const QString & key ) + .def("removeAllQueryItems", + MEMFNP(void, QUrl, removeAllQueryItems, + ( const QString & key ))) + // void removeEncodedQueryItem ( const QByteArray & key ) + .def("removeEncodedQueryItem", + MEMFNP(void, QUrl, removeEncodedQueryItem, + ( const QByteArray & key ))) + // void removeQueryItem ( const QString & key ) + .def("removeQueryItem", + MEMFNP(void, QUrl, removeQueryItem, + ( const QString & key ))) + // QUrl resolved ( const QUrl & relative ) const + .def("resolved", + MEMFNP(QUrl, QUrl, resolved, + ( const QUrl & relative ) const)) + // QString scheme () const + .def("scheme", + MEMFNP(QString, QUrl, scheme, + () const)) + // void setAuthority ( const QString & authority ) + .def("setAuthority", + MEMFNP(void, QUrl, setAuthority, + ( const QString & authority ))) + // void setEncodedFragment ( const QByteArray & fragment ) + .def("setEncodedFragment", + MEMFNP(void, QUrl, setEncodedFragment, + ( const QByteArray & fragment ))) + // void setEncodedHost ( const QByteArray & host ) + .def("setEncodedHost", + MEMFNP(void, QUrl, setEncodedHost, + ( const QByteArray & host ))) + // void setEncodedPassword ( const QByteArray & password ) + .def("setEncodedPassword", + MEMFNP(void, QUrl, setEncodedPassword, + ( const QByteArray & password ))) + // void setEncodedPath ( const QByteArray & path ) + .def("setEncodedPath", + MEMFNP(void, QUrl, setEncodedPath, + ( const QByteArray & path ))) + // void setEncodedQuery ( const QByteArray & query ) + .def("setEncodedQuery", + MEMFNP(void, QUrl, setEncodedQuery, + ( const QByteArray & query ))) + // void setEncodedQueryItems ( const QList > & query ) + // .def("setEncodedQueryItems", + // MEMFNP(void, QUrl, setEncodedQueryItems, + // ( const QList > & query ))) + // void setEncodedUrl ( const QByteArray & encodedUrl ) + .def("setEncodedUrl", + MEMFNP(void, QUrl, setEncodedUrl, + ( const QByteArray & encodedUrl ))) + // void setEncodedUrl ( const QByteArray & encodedUrl, ParsingMode parsingMode ) + // .def("setEncodedUrl", + // MEMFNP(void, QUrl, setEncodedUrl, + // ( const QByteArray & encodedUrl, ParsingMode parsingMode ))) + // void setEncodedUserName ( const QByteArray & userName ) + .def("setEncodedUserName", + MEMFNP(void, QUrl, setEncodedUserName, + ( const QByteArray & userName ))) + // void setFragment ( const QString & fragment ) + .def("setFragment", + MEMFNP(void, QUrl, setFragment, + ( const QString & fragment ))) + // void setHost ( const QString & host ) + .def("setHost", + MEMFNP(void, QUrl, setHost, + ( const QString & host ))) + // void setPassword ( const QString & password ) + .def("setPassword", + MEMFNP(void, QUrl, setPassword, + ( const QString & password ))) + // void setPath ( const QString & path ) + .def("setPath", + MEMFNP(void, QUrl, setPath, + ( const QString & path ))) + // void setPort ( int port ) + .def("setPort", + MEMFNP(void, QUrl, setPort, + ( int port ))) + // void setQueryDelimiters ( char valueDelimiter, char pairDelimiter ) + .def("setQueryDelimiters", + MEMFNP(void, QUrl, setQueryDelimiters, + ( char valueDelimiter, char pairDelimiter ))) + // void setQueryItems ( const QList > & query ) + // .def("setQueryItems", + // MEMFNP(void, QUrl, setQueryItems, + // ( const QList > & query ))) + // void setScheme ( const QString & scheme ) + .def("setScheme", + MEMFNP(void, QUrl, setScheme, + ( const QString & scheme ))) + // void setUrl ( const QString & url ) + .def("setUrl", + MEMFNP(void, QUrl, setUrl, + ( const QString & url ))) + // void setUrl ( const QString & url, ParsingMode parsingMode ) + // .def("setUrl", + // MEMFNP(void, QUrl, setUrl, + // ( const QString & url, ParsingMode parsingMode ))) + // void setUserInfo ( const QString & userInfo ) + .def("setUserInfo", + MEMFNP(void, QUrl, setUserInfo, + ( const QString & userInfo ))) + // void setUserName ( const QString & userName ) + .def("setUserName", + MEMFNP(void, QUrl, setUserName, + ( const QString & userName ))) + // QByteArray toEncoded ( FormattingOptions options = None ) const + // .def("toEncoded", + // MEMFNP(QByteArray, QUrl, toEncoded, + // ( FormattingOptions options = None ) const)) + // QString toLocalFile () const + .def("toLocalFile", + MEMFNP(QString, QUrl, toLocalFile, + () const)) + // QString toString ( FormattingOptions options = None ) const + .def("__unicode__", &QUrl_toString_noargs) + // QString userInfo () const + .def("userInfo", + MEMFNP(QString, QUrl, userInfo, + () const)) + // QString userName () const + .def("userName", + MEMFNP(QString, QUrl, userName, + () const)) + + // bool operator!= ( const QUrl & url ) const + // QUrl & operator= ( const QUrl & url ) + // QUrl & operator= ( const QString & url ) + // bool operator== ( const QUrl & url ) const + ; +} + +BOOST_PYTHON_MODULE(_pykit) +{ + py::class_("Request", py::no_init) + .def("write", &pykit::Request::write) + .def("reset", &pykit::Request::reset) + .def("setContentType", &pykit::Request::setContentType) + .def("setLocation", &pykit::Request::setLocation) + .def("url", &pykit::Request::url) + ; + + py::class_("Publisher") + .def("publish", py::pure_virtual(&pykit::Publisher::publish)) + ; +} + +prefix_ pykit::PythonPublisher::PythonPublisher(std::string initPy) +{ + PYTHON_PREPARE_IMPORT(_pykit); + PYTHON_PREPARE_IMPORT(_qt); + Py_Initialize(); + py::object mainModule_ = py::import("__main__"); + mainNamespace_ = py::extract(mainModule_.attr("__dict__")); + mainNamespace_["__file__"] = py::str(initPy.c_str()); + py::object ignored ( + py::exec_file(initPy.c_str(), mainNamespace_, mainNamespace_)); + pythonPublisher_ = py::extract(mainNamespace_["publisher"]); +} + +prefix_ void pykit::PythonPublisher::publish(Request & request) +{ + try { + pythonPublisher_->publish(request); + } + catch (py::error_already_set & ex) { + PyErr_Print(); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "PythonPublisher.mpp" + + +// 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: diff --git a/PythonPublisher.hh b/PythonPublisher.hh new file mode 100644 index 0000000..b00c983 --- /dev/null +++ b/PythonPublisher.hh @@ -0,0 +1,54 @@ +// $Id$ +// +// Copyright (C) 2010 +// Stefan Bund + +/** \file + \brief PythonPublisher public header */ + +#ifndef HH_PyKit_PythonPublisher_ +#define HH_PyKit_PythonPublisher_ 1 + +// Custom includes +#include +#include "Publisher.hh" + +//#include "PythonPublisher.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace pykit { + + class PythonPublisher + : public Publisher + { + public: + PythonPublisher(std::string initPy); + + void publish(Request & request); + + private: + boost::python::dict mainNamespace_; + Publisher * pythonPublisher_; + }; + +# define PYTHON_PREPARE_IMPORT(module) \ + PyImport_AppendInittab(const_cast(#module), init ## module) + +} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "PythonPublisher.cci" +//#include "PythonPublisher.ct" +//#include "PythonPublisher.cti" +#endif + + +// 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: diff --git a/SConscript b/SConscript new file mode 100644 index 0000000..5503bac --- /dev/null +++ b/SConscript @@ -0,0 +1,17 @@ +# -*- python -*- + +Import('env') + +# QtSvg and QtXml are needed by some plugins ... +env.EnableQt4Modules([ 'QtWebKit', 'QtNetwork', 'QtSvg', 'QtXml', 'QtGui', 'QtCore' ]) + +env.Append( + CXXFLAGS = [ '-Wall', '-Wextra' ], + CPPPATH = [ '$LIBPYTHONINCLUDES' ], + LIBS = [ '$LIBBOOSTPYTHON', '$LIBPYTHON' ] +) + +sources = env.Qt4Glob() + +pykit = env.Program('pykit', sources) +env.Default(pykit) diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..4fae7cb --- /dev/null +++ b/SConstruct @@ -0,0 +1,22 @@ +# -*- python -*- + +import os + +env = Environment(ENV = os.environ) +env.Tool('qt4',['../site_scons/qtscons']) + +env.SetDefault( + PYTHON = 'python', + LIBPYTHON = 'python$PYTHONVERSION', + LIBPYTHONINCLUDES = '/usr/include/python$PYTHONVERSION', + LIBBOOSTPYTHON = 'boost_python' +) + +env.SetDefault( + PYTHONVERSION = os.popen(env.subst( + """$PYTHON -c 'import sys; print".".join(map(str,sys.version_info[:2]))'""")).read(), +) + +Export('env') + +env.SConscript("SConscript") diff --git a/init.py b/init.py new file mode 100644 index 0000000..b0981f9 --- /dev/null +++ b/init.py @@ -0,0 +1,8 @@ +import _pykit, _qt + +class Publisher(_pykit.Publisher): + def publish(self, request): + request.setContentType('text/html') + request.write("

PyKit up and running

") + +publisher = Publisher() diff --git a/main.cc b/main.cc new file mode 100644 index 0000000..84a675f --- /dev/null +++ b/main.cc @@ -0,0 +1,94 @@ +// $Id$ +// +// Copyright (C) 2010 +// Stefan Bund + +/** \file + \brief main non-inline non-template implementation */ + +//#include "main.hh" +//#include "main.ih" + +// Custom includes +#include +#include +#include +#include +#include +#include +#include +#include "MainWindow.hh" +#include "PythonPublisher.hh" + +//#include "main.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +int main(int argc, char *argv[]) +{ + try { + QApplication app (argc, argv); + + QSettings settings ("pykit.ini", QSettings::IniFormat); + QStringList arguments (app.arguments()); + settings.beginGroup("AppData"); + + app.setApplicationName(settings.value("name").toString()); + app.setApplicationVersion(settings.value("version").toString()); + app.setOrganizationDomain(settings.value("organization").toString()); + app.setOrganizationName(settings.value("organization").toString()); + + QString splashPath (settings.value("splash").toString()); + boost::scoped_ptr splash; + if (!splashPath.isEmpty()) { + QPixmap splashPixmap (settings.value("splash").toString()); + splash.reset(new QSplashScreen (splashPixmap)); + splash->show(); + } + + QString iconPath (settings.value("icon").toString()); + + settings.endGroup(); + settings.beginGroup("Viewer"); + + pykit::PythonPublisher publisher (settings.value("init").toString().toStdString()); + + QString url (settings.value("home").toString()); + if (arguments.size()>1) + url = arguments.at(1); + pykit::MainWindow window (QUrl(url), &publisher); + window.setWindowTitle(app.applicationName()); + if (!iconPath.isEmpty()) + window.setWindowIcon(QIcon(iconPath)); + window.setWindowIconText(window.windowTitle()); + + window.show(); + if (splash) + splash->finish(&window); + + 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; + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "main.mpp" + + +// 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: diff --git a/pykit.ini b/pykit.ini new file mode 100644 index 0000000..d490f6f --- /dev/null +++ b/pykit.ini @@ -0,0 +1,8 @@ +[AppData] +name=PyKit +version=0.1 +organization=g0dil.de + +[Viewer] +init=init.py +home=srv:///