remove context menu when running in release mode
[pykit.git] / PythonPublisher.cc
1 // $Id$
2 //
3 // Copyright (C) 2010
4 //     Stefan Bund <info@j32.de>
5
6 /** \file
7     \brief PythonPublisher non-inline non-template implementation */
8
9 #include "PythonPublisher.hh"
10 //#include "PythonPublisher.ih"
11
12 // Custom includes
13 #include <iostream>
14 #include <boost/python.hpp>
15 #include "Publisher.hh"
16 #include <QDesktopServices>
17
18 //#include "PythonPublisher.mpp"
19 #define prefix_
20 ///////////////////////////////cc.p////////////////////////////////////////
21
22 namespace py = boost::python;
23
24 struct pykit::PythonPublisher::Impl
25 {
26     boost::python::dict mainNamespace;
27     Publisher * pythonPublisher;
28 };
29
30 #define PYTHON_EXTERN_MODULE(module) \
31     extern "C" { void init ## module (); }
32 #define PYTHON_PREPARE_IMPORT(module) \
33     PyImport_AppendInittab(const_cast<char*>(#module), init ## module)
34
35 namespace {
36
37     struct PublisherPyWrapper
38         : public pykit::Publisher, py::wrapper<pykit::Publisher>
39     {
40         virtual void publish(pykit::Request & request)
41             { get_override("publish")(request); }
42     };
43
44     namespace pyconvert {
45
46         struct QString_PyUnicode
47         {
48             static PyObject * convert(QString const & s)
49                 {
50                     std::wstring ws (s.toStdWString());
51                     return PyUnicode_FromWideChar(ws.data(), ws.length());
52                 }
53         };
54
55         struct PyUnicode_QString
56         {
57             static void * convertible(PyObject * o)
58                 {
59                     return PyUnicode_Check(o) ? o : 0;
60                 }
61
62             static void construct(PyObject * o,
63                                   py::converter::rvalue_from_python_stage1_data * data)
64                 {
65                     unsigned length (PyUnicode_GetSize(o));
66                     std::wstring ws (length, 0);
67                     // Hmm ... I don't want to copy the stupid data TWICE but this
68                     // breaks the standard ... who cares ?
69                     PyUnicode_AsWideChar(reinterpret_cast<PyUnicodeObject *>(o),
70                                          const_cast<wchar_t*>(ws.data()),
71                                          length);
72                     void * storage (((py::converter::rvalue_from_python_storage<QString>*)
73                                      data)->storage.bytes);
74                     *(new (storage) QString()) = QString::fromStdWString(ws);
75                     data->convertible = storage;
76                 }
77
78             PyUnicode_QString()
79                 {
80                     py::converter::registry::push_back(
81                         &convertible,
82                         &construct,
83                         py::type_id<QString>());
84                 }
85         };
86
87         struct QByteArray_PyString
88         {
89             static PyObject * convert(QByteArray const & s)
90                 {
91                     return boost::python::incref(boost::python::object(s.constData()).ptr());
92                 }
93         };
94
95         struct PyString_QByteArray
96         {
97             static void * convertible(PyObject * o)
98                 {
99                     return PyString_Check(o) ? o : 0;
100                 }
101
102             static void construct(PyObject * o,
103                                   py::converter::rvalue_from_python_stage1_data * data)
104                 {
105                     unsigned length (PyString_Size(o));
106                     const char * value (PyString_AsString(o));
107                     void * storage (((py::converter::rvalue_from_python_storage<QByteArray>*)
108                                      data)->storage.bytes);
109                     new (storage) QByteArray(value,length);
110                     data->convertible = storage;
111                 }
112
113             PyString_QByteArray()
114                 {
115                     py::converter::registry::push_back(
116                         &convertible,
117                         &construct,
118                         py::type_id<QByteArray>());
119                 }
120         };
121
122     }
123
124     QString QUrl_toString_noargs(QUrl const & url)
125     { return url.toString(); }
126
127 }
128
129 #define MEMFNP(ret, cls, nam, arg) static_cast<ret (cls::*)arg>(&cls::nam)
130
131 BOOST_PYTHON_MODULE(_qt)
132 {
133     py::to_python_converter<QString, pyconvert::QString_PyUnicode>();
134     pyconvert::PyUnicode_QString register_PyUnicode_QString;
135
136     py::to_python_converter<QByteArray, pyconvert::QByteArray_PyString>();
137     pyconvert::PyString_QByteArray register_PyString_QByteArray;
138
139     // Missing converters:
140     //    QPair <-> tuple
141     //    QList <-> vector
142
143         // QUrl ()
144     py::class_<QUrl>("QUrl", py::init<>())
145         // QUrl ( const QString & url )
146         .def(py::init<QString const &>())
147         // QUrl ( const QUrl & other )
148         .def(py::init<QUrl const &>())
149         // QUrl ( const QString & url, ParsingMode parsingMode )
150         // .def(init<QString const &, ParsingMode>())
151         // ~QUrl ()
152         // void   addEncodedQueryItem ( const QByteArray & key, const QByteArray & value )
153         .def("addEncodedQueryItem",
154              MEMFNP(void, QUrl, addEncodedQueryItem,
155                     ( const QByteArray & key, const QByteArray & value )))
156         // void   addQueryItem ( const QString & key, const QString & value )
157         .def("addQueryItem",
158              MEMFNP(void, QUrl, addQueryItem,
159                     ( const QString & key, const QString & value )))
160         // QList<QByteArray>   allEncodedQueryItemValues ( const QByteArray & key ) const
161         // .def("allEncodedQueryItemValues",
162         //      MEMFNP(QList<QByteArray>, QUrl, allEncodedQueryItemValues,
163         //             ( const QByteArray & key ) const))
164         // QStringList   allQueryItemValues ( const QString & key ) const
165         // .def("allQueryItemValues",
166         //      MEMFNP(QStringList, QUrl, allQueryItemValues,
167         //             ( const QString & key ) const))
168         // QString   authority () const
169         .def("authority",
170              MEMFNP(QString, QUrl, authority,
171                     () const))
172         // void   clear ()
173         .def("clear",
174              MEMFNP(void, QUrl, clear,
175                     ()))
176         // QByteArray   encodedFragment () const
177         .def("encodedFragment",
178              MEMFNP(QByteArray, QUrl, encodedFragment,
179                     () const))
180         // QByteArray   encodedHost () const
181         .def("encodedHost",
182              MEMFNP(QByteArray, QUrl, encodedHost,
183                     () const))
184         // QByteArray   encodedPassword () const
185         .def("encodedPassword",
186              MEMFNP(QByteArray, QUrl, encodedPassword,
187                     () const))
188         // QByteArray   encodedPath () const
189         .def("encodedPath",
190              MEMFNP(QByteArray, QUrl, encodedPath,
191                     () const))
192         // QByteArray   encodedQuery () const
193         .def("encodedQuery",
194              MEMFNP(QByteArray, QUrl, encodedQuery,
195                     () const))
196         // QByteArray   encodedQueryItemValue ( const QByteArray & key ) const
197         .def("encodedQueryItemValue",
198              MEMFNP(QByteArray, QUrl, encodedQueryItemValue,
199                     ( const QByteArray & key ) const))
200         // QList<QPair<QByteArray, QByteArray> >   encodedQueryItems () const
201         // .def("encodedQueryItems",
202         //      MEMFNP(QList<QPair<QByteArray, QByteArray> >, QUrl, encodedQueryItems,
203         //             () const))
204         // QByteArray   encodedUserName () const
205         .def("encodedUserName",
206              MEMFNP(QByteArray, QUrl, encodedUserName,
207                     () const))
208         // QString   errorString () const
209         .def("errorString",
210              MEMFNP(QString, QUrl, errorString,
211                     () const))
212         // QString   fragment () const
213         .def("fragment",
214              MEMFNP(QString, QUrl, fragment,
215                     () const))
216         // bool   hasEncodedQueryItem ( const QByteArray & key ) const
217         .def("hasEncodedQueryItem",
218              MEMFNP(bool, QUrl, hasEncodedQueryItem,
219                     ( const QByteArray & key ) const))
220         // bool   hasFragment () const
221         .def("hasFragment",
222              MEMFNP(bool, QUrl, hasFragment,
223                     () const))
224         // bool   hasQuery () const
225         .def("hasQuery",
226              MEMFNP(bool, QUrl, hasQuery,
227                     () const))
228         // bool   hasQueryItem ( const QString & key ) const
229         .def("hasQueryItem",
230              MEMFNP(bool, QUrl, hasQueryItem,
231                     ( const QString & key ) const))
232         // QString   host () const
233         .def("host",
234              MEMFNP(QString, QUrl, host,
235                     () const))
236         // bool   isEmpty () const
237         .def("isEmpty",
238              MEMFNP(bool, QUrl, isEmpty,
239                     () const))
240         // bool   isParentOf ( const QUrl & childUrl ) const
241         .def("isParentOf",
242              MEMFNP(bool, QUrl, isParentOf,
243                     ( const QUrl & childUrl ) const))
244         // bool   isRelative () const
245         .def("isRelative",
246              MEMFNP(bool, QUrl, isRelative,
247                     () const))
248         // bool   isValid () const
249         .def("isValid",
250              MEMFNP(bool, QUrl, isValid,
251                     () const))
252         // QString   password () const
253         .def("password",
254              MEMFNP(QString, QUrl, password,
255                     () const))
256         // QString   path () const
257         .def("path",
258              MEMFNP(QString, QUrl, path,
259                     () const))
260         // int   port () const
261         .def("port",
262              MEMFNP(int, QUrl, port,
263                     () const))
264         // int   port ( int defaultPort ) const
265         .def("port",
266              MEMFNP(int, QUrl, port,
267                     ( int defaultPort ) const))
268         // QString   queryItemValue ( const QString & key ) const
269         .def("queryItemValue",
270              MEMFNP(QString, QUrl, queryItemValue,
271                     ( const QString & key ) const))
272         // QList<QPair<QString, QString> >   queryItems () const
273         // .def("queryItems",
274         //      MEMFNP(QList<QPair<QString, QString> >, QUrl, queryItems,
275         //             () const))
276         // char   queryPairDelimiter () const
277         .def("queryPairDelimiter",
278              MEMFNP(char, QUrl, queryPairDelimiter,
279                     () const))
280         // char   queryValueDelimiter () const
281         .def("queryValueDelimiter",
282              MEMFNP(char, QUrl, queryValueDelimiter,
283                     () const))
284         // void   removeAllEncodedQueryItems ( const QByteArray & key )
285         .def("removeAllEncodedQueryItems",
286              MEMFNP(void, QUrl, removeAllEncodedQueryItems,
287                     ( const QByteArray & key )))
288         // void   removeAllQueryItems ( const QString & key )
289         .def("removeAllQueryItems",
290              MEMFNP(void, QUrl, removeAllQueryItems,
291                     ( const QString & key )))
292         // void   removeEncodedQueryItem ( const QByteArray & key )
293         .def("removeEncodedQueryItem",
294              MEMFNP(void, QUrl, removeEncodedQueryItem,
295                     ( const QByteArray & key )))
296         // void   removeQueryItem ( const QString & key )
297         .def("removeQueryItem",
298              MEMFNP(void, QUrl, removeQueryItem,
299                     ( const QString & key )))
300         // QUrl   resolved ( const QUrl & relative ) const
301         .def("resolved",
302              MEMFNP(QUrl, QUrl, resolved,
303                     ( const QUrl & relative ) const))
304         // QString   scheme () const
305         .def("scheme",
306              MEMFNP(QString, QUrl, scheme,
307                     () const))
308         // void   setAuthority ( const QString & authority )
309         .def("setAuthority",
310              MEMFNP(void, QUrl, setAuthority,
311                     ( const QString & authority )))
312         // void   setEncodedFragment ( const QByteArray & fragment )
313         .def("setEncodedFragment",
314              MEMFNP(void, QUrl, setEncodedFragment,
315                     ( const QByteArray & fragment )))
316         // void   setEncodedHost ( const QByteArray & host )
317         .def("setEncodedHost",
318              MEMFNP(void, QUrl, setEncodedHost,
319                     ( const QByteArray & host )))
320         // void   setEncodedPassword ( const QByteArray & password )
321         .def("setEncodedPassword",
322              MEMFNP(void, QUrl, setEncodedPassword,
323                     ( const QByteArray & password )))
324         // void   setEncodedPath ( const QByteArray & path )
325         .def("setEncodedPath",
326              MEMFNP(void, QUrl, setEncodedPath,
327                     ( const QByteArray & path )))
328         // void   setEncodedQuery ( const QByteArray & query )
329         .def("setEncodedQuery",
330              MEMFNP(void, QUrl, setEncodedQuery,
331                     ( const QByteArray & query )))
332         // void   setEncodedQueryItems ( const QList<QPair<QByteArray, QByteArray> > & query )
333         // .def("setEncodedQueryItems",
334         //      MEMFNP(void, QUrl, setEncodedQueryItems,
335         //             ( const QList<QPair<QByteArray, QByteArray> > & query )))
336         // void   setEncodedUrl ( const QByteArray & encodedUrl )
337         .def("setEncodedUrl",
338              MEMFNP(void, QUrl, setEncodedUrl,
339                     ( const QByteArray & encodedUrl )))
340         // void   setEncodedUrl ( const QByteArray & encodedUrl, ParsingMode parsingMode )
341         // .def("setEncodedUrl",
342         //      MEMFNP(void, QUrl, setEncodedUrl,
343         //             ( const QByteArray & encodedUrl, ParsingMode parsingMode )))
344         // void   setEncodedUserName ( const QByteArray & userName )
345         .def("setEncodedUserName",
346              MEMFNP(void, QUrl, setEncodedUserName,
347                     ( const QByteArray & userName )))
348         // void   setFragment ( const QString & fragment )
349         .def("setFragment",
350              MEMFNP(void, QUrl, setFragment,
351                     ( const QString & fragment )))
352         // void   setHost ( const QString & host )
353         .def("setHost",
354              MEMFNP(void, QUrl, setHost,
355                     ( const QString & host )))
356         // void   setPassword ( const QString & password )
357         .def("setPassword",
358              MEMFNP(void, QUrl, setPassword,
359                     ( const QString & password )))
360         // void   setPath ( const QString & path )
361         .def("setPath",
362              MEMFNP(void, QUrl, setPath,
363                     ( const QString & path )))
364         // void   setPort ( int port )
365         .def("setPort",
366              MEMFNP(void, QUrl, setPort,
367                     ( int port )))
368         // void   setQueryDelimiters ( char valueDelimiter, char pairDelimiter )
369         .def("setQueryDelimiters",
370              MEMFNP(void, QUrl, setQueryDelimiters,
371                     ( char valueDelimiter, char pairDelimiter )))
372         // void   setQueryItems ( const QList<QPair<QString, QString> > & query )
373         // .def("setQueryItems",
374         //      MEMFNP(void, QUrl, setQueryItems,
375         //             ( const QList<QPair<QString, QString> > & query )))
376         // void   setScheme ( const QString & scheme )
377         .def("setScheme",
378              MEMFNP(void, QUrl, setScheme,
379                     ( const QString & scheme )))
380         // void   setUrl ( const QString & url )
381         .def("setUrl",
382              MEMFNP(void, QUrl, setUrl,
383                     ( const QString & url )))
384         // void   setUrl ( const QString & url, ParsingMode parsingMode )
385         // .def("setUrl",
386         //      MEMFNP(void, QUrl, setUrl,
387         //             ( const QString & url, ParsingMode parsingMode )))
388         // void   setUserInfo ( const QString & userInfo )
389         .def("setUserInfo",
390              MEMFNP(void, QUrl, setUserInfo,
391                     ( const QString & userInfo )))
392         // void   setUserName ( const QString & userName )
393         .def("setUserName",
394              MEMFNP(void, QUrl, setUserName,
395                     ( const QString & userName )))
396         // QByteArray   toEncoded ( FormattingOptions options = None ) const
397         // .def("toEncoded",
398         //      MEMFNP(QByteArray, QUrl, toEncoded,
399         //             ( FormattingOptions options = None ) const))
400         // QString   toLocalFile () const
401         .def("toLocalFile",
402              MEMFNP(QString, QUrl, toLocalFile,
403                     () const))
404         // QString   toString ( FormattingOptions options = None ) const
405         .def("__unicode__", &QUrl_toString_noargs)
406         // QString   userInfo () const
407         .def("userInfo",
408              MEMFNP(QString, QUrl, userInfo,
409                     () const))
410         // QString   userName () const
411         .def("userName",
412              MEMFNP(QString, QUrl, userName,
413                     () const))
414
415         // bool   operator!= ( const QUrl & url ) const
416         // QUrl &   operator= ( const QUrl & url )
417         // QUrl &   operator= ( const QString & url )
418         // bool   operator== ( const QUrl & url ) const
419         ;
420 }
421
422 BOOST_PYTHON_MODULE(_pykit)
423 {
424     py::class_<pykit::Request>("Request", py::no_init)
425         .def("write", &pykit::Request::write)
426         .def("reset", &pykit::Request::reset)
427         .def("setContentType", &pykit::Request::setContentType)
428         .def("setLocation", &pykit::Request::setLocation)
429         .def("setRawHeader", &pykit::Request::setHeader)
430         .def("setStatusCode", &pykit::Request::setStatusCode)
431         .def("url", &pykit::Request::url)
432         .def("postData", &pykit::Request::postData)
433         .def("operation", &pykit::Request::operation)
434         .def("postContentType", &pykit::Request::postContentType)
435         ;
436
437     py::class_<PublisherPyWrapper, boost::noncopyable>("Publisher")
438         .def("publish", py::pure_virtual(&pykit::Publisher::publish))
439         ;
440
441     py::def("openUrl", &QDesktopServices::openUrl);
442 }
443
444 PYTHON_EXTERN_MODULE(_httpapi);
445
446 prefix_ pykit::PythonPublisher::PythonPublisher()
447     : impl_ (new Impl)
448 {
449     try {
450         PYTHON_PREPARE_IMPORT(_pykit);
451         PYTHON_PREPARE_IMPORT(_qt);
452         PYTHON_PREPARE_IMPORT(_httpapi);
453         Py_Initialize();
454         py::object initModule = py::import("init");
455         impl_->mainNamespace = py::extract<py::dict>(initModule.attr("__dict__"));
456         impl_->pythonPublisher = py::extract<Publisher*>(impl_->mainNamespace["initialize"]());
457     }
458     catch (boost::python::error_already_set & ex) {
459         PyErr_Print();
460         throw;
461     }
462 }
463
464 prefix_ pykit::PythonPublisher::~PythonPublisher()
465 {
466     try {
467         impl_->mainNamespace["shutdown"]();
468     }
469     catch (...) {;}
470 }
471
472 prefix_ void pykit::PythonPublisher::publish(Request & request)
473 {
474     try {
475         impl_->pythonPublisher->publish(request);
476     }
477     catch (py::error_already_set & ex) {
478         PyErr_Print();
479     }
480 }
481
482 ///////////////////////////////cc.e////////////////////////////////////////
483 #undef prefix_
484 //#include "PythonPublisher.mpp"
485
486 \f
487 // Local Variables:
488 // mode: c++
489 // fill-column: 100
490 // comment-column: 40
491 // c-file-style: "j32"
492 // indent-tabs-mode: nil
493 // ispell-local-dictionary: "american"
494 // compile-command: "scons -U"
495 // End: