Back to index

scribus-ng  1.3.4.dfsg+svn20071115
scripter2_qttype_qstring.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 #include "cmdvar.h"
00008 
00009 #include "qstring.h"
00010 #include <wchar.h>
00011 
00012 
00013 
00014 // Shamelessly cribbed from code in python-qt4
00015 // Originally by Eric Jardim <ericjardim@gmail.com>
00016 // Rewritten by Craig Ringer <craig@postnewspapers.com.au>
00017 // Ported to Scribus and Qt3 by Craig Ringer <craig@postnewspapers.com.au>
00018 
00019 using namespace boost::python;
00023 struct QString_to_python_unicode
00024 {
00025     static PyObject*
00026     convert(QString const& s)
00027     {
00028         //FIXME: Done with Python/C API, needs Boost::Python-ifying
00029         //FIXME: UCS-4 case can probably be done a lot more effciently.
00030 #if defined(Py_UNICODE_WIDE)
00031         //qDebug("Py_UNICODE_WIDE");
00032         int unichars = s.length();
00033         Py_UNICODE* buf = new Py_UNICODE[unichars];
00034         for (int i = 0; i < unichars; i++)
00035             buf[i] = s.at(i).unicode();
00036         PyObject* tempObj = PyUnicode_FromUnicode(buf, unichars);
00037         delete[] buf;
00038         return tempObj;
00039 #else
00040         return PyUnicode_FromUnicode(s.utf16(), s.length());
00041 #endif
00042     }
00043 };
00044 
00045 
00049 struct QString_from_python_str_or_unicode
00050 {
00051     QString_from_python_str_or_unicode()
00052     {
00053         boost::python::converter::registry::push_back(  &convertible,
00054                                                         &construct,
00055                                                         boost::python::type_id<QString>() );
00056     }
00057 
00058     static void*
00059     convertible(PyObject* obj_ptr)
00060     {
00061         if (! (PyUnicode_Check(obj_ptr) || PyString_Check(obj_ptr)) )
00062                 return 0;
00063         return obj_ptr;
00064     }
00065 
00066     static void
00067     construct(  PyObject* obj_ptr,
00068                 boost::python::converter::rvalue_from_python_stage1_data* data)
00069     {
00070         // First, convert the input to Python `unicode'.
00071         PyObject* temp_obj_ptr;
00072         if (PyString_Check(obj_ptr))
00073         {
00074             // Coerce the `str' to `unicode' using sysdefaultencoding. UnicodeDecodeError
00075             // is thrown if the string doesn't make sense in that encoding.
00076             temp_obj_ptr = PyUnicode_FromObject(obj_ptr); // new reference
00077             if (temp_obj_ptr == 0)
00078             {
00079                 boost::python::throw_error_already_set();
00080             }
00081         }
00082         else
00083         {
00084             temp_obj_ptr = obj_ptr;
00085             Py_INCREF(temp_obj_ptr); // to balance DECREF at end
00086         }
00087 
00088         // FIXME: This implementation is probably rather inefficient
00089         Py_UNICODE* value = PyUnicode_AsUnicode(temp_obj_ptr);
00090         if (value == 0)
00091         {
00092             boost::python::throw_error_already_set();
00093         }
00094         int unichars = PyUnicode_GET_SIZE(temp_obj_ptr);
00095 #if defined(Py_UNICODE_WIDE)
00096 
00097         // Python is using a 4-byte unsigned buffer of UCS-4
00098         // FIXME: Qt doesn't give us any direct way to load UCS-4, so we're doing
00099         //        it a rather clunky way that can probably be improved.
00100         // FIXME: Qt can't represent UCS-4 characters; we need to check for this
00101         //        and throw an exception.
00102         QString tempString("");
00103         int i;
00104         for (i = 0; i < unichars; i++)
00105             tempString.append(QChar(value[i]));
00106 #else
00107         // Python is using a 2-byte unsigned buffer of UCS-2 with
00108         // limited support for UTF-16
00109         QString tempString(QString::fromUtf16(value, unichars));
00110 #endif
00111         Py_DECREF(temp_obj_ptr);
00112         void* storage = ((boost::python::converter::rvalue_from_python_storage<QString>*) data)->storage.bytes;
00113         new (storage) QString(tempString);
00114         data->convertible = storage;
00115     }
00116 };
00117 
00118 void export_QString()
00119 {
00120        boost::python::to_python_converter<QString, QString_to_python_unicode>();
00121        QString_from_python_str_or_unicode();
00122 }
00123 
00124