File: qpycore_chimera.h

package info (click to toggle)
python-qt4 4.7.3-1%2Bsqueeze1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 28,504 kB
  • ctags: 4,680
  • sloc: python: 28,738; cpp: 8,897; sh: 245; xml: 243; makefile: 150
file content (261 lines) | stat: -rw-r--r-- 8,826 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
// This is the interface of the Chimera and related classes.
//
// Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
// 
// This file is part of PyQt.
// 
// This file may be used under the terms of the GNU General Public
// License versions 2.0 or 3.0 as published by the Free Software
// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
// included in the packaging of this file.  Alternatively you may (at
// your option) use any later version of the GNU General Public
// License if such license has been publicly approved by Riverbank
// Computing Limited (or its successors, if any) and the KDE Free Qt
// Foundation. In addition, as a special exception, Riverbank gives you
// certain additional rights. These rights are described in the Riverbank
// GPL Exception version 1.1, which can be found in the file
// GPL_EXCEPTION.txt in this package.
// 
// Please review the following information to ensure GNU General
// Public Licensing requirements will be met:
// http://trolltech.com/products/qt/licenses/licensing/opensource/. If
// you are unsure which license is appropriate for your use, please
// review the following information:
// http://trolltech.com/products/qt/licenses/licensing/licensingoverview
// or contact the sales department at sales@riverbankcomputing.com.
// 
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.


#ifndef _QPYCORE_CHIMERA_H
#define _QPYCORE_CHIMERA_H


#include <Python.h>

#include <QByteArray>
#include <QHash>
#include <QMetaProperty>
#include <QVariant>

#include "qpycore_sip.h"


// This describes a type that can be understood by Python and C++ (specifically
// Qt's meta-type system).  The implementation assumes that the GIL is held.
class Chimera
{
public:
    // Destroy the type.
    ~Chimera();

    // Parses a Python object as a type.  Return 0 if there was an error.
    static const Chimera *parse(PyObject *obj);

    // Parses a Qt meta-property as a type.  Return 0 if there was an error.
    static const Chimera *parse(const QMetaProperty &mprop);

    class Signature
    {
    public:
        // Destroy the signature and any result type objects.
        ~Signature();

        // The list of parsed argument types.
        QList<const Chimera *> parsed_arguments;

        // The optional parsed result type.
        const Chimera *result;

        // The original normalised signature (possibly including a method name
        // but excluding a return type).
        QByteArray signature;

        // The optional docstring which will start with '\1' if it is auto
        // generated and so can be used in exceptions.
        const char *docstring;

        // Return the parsed signature wrapped in a Python object.  Ownership
        // of the signature is passed to the Python object.  Return 0 if there
        // was an error.
        static PyObject *toPyObject(Signature *parsed_signature);

        // Return the parsed signature extracted from a Python object.
        static Signature *fromPyObject(PyObject *py);

        // Return the name from the signature.
        QByteArray name() const {return name(signature);}

        // Return the name from a signature.
        static QByteArray name(const QByteArray &signature);

        // Return the arguments from the signature.
        QByteArray arguments() const {return arguments(signature);}

        // Return the arguments from a signature.
        static QByteArray arguments(const QByteArray &signature);

    private:
        friend class Chimera;

        // Set if the parsed arguments are cached.
        bool _cached;

        Signature(const QByteArray &sig, bool cached)
            : result(0), signature(sig), docstring(0), _cached(cached) {}

        Signature(const Signature &);
        Signature &operator=(const Signature &);
    };

    // Parses a normalised C++ signature.  Return 0 if there was an error.
    static Signature *parse(const QByteArray &sig, const char *context);

    // Parses a C++ signature given as a Python tuple of types and an optional
    // name.  Return 0 if there was an error.
    static Signature *parse(PyObject *types, const char *name,
            const char *context);

    // Raise an exception after parse() has failed.
    static void raiseParseException(PyObject *obj, const char *context);

    class Storage
    {
    public:
        // Destroy the type and any temporary data.
        ~Storage();

        // Return the parsed type.
        const Chimera *type() const {return _parsed_type;}

        // Return the address of the stored value.
        void *address();

        // Convert the stored value to a Python object.
        PyObject *toPyObject() const;

    private:
        friend class Chimera;

        // The parsed type.
        const Chimera *_parsed_type;

        // The storage for fundamental and value types.
        QVariant _value_storage;

        // The storage for pointer types.
        void *_ptr_storage;

        // The state of any temporary stored data.
        int _tmp_state;

        // Set if the value is valid.
        bool _valid;

        Storage(const Chimera *ct);
        Storage(const Chimera *ct, PyObject *py);

        // Return true if the value is valid.
        bool isValid() const {return _valid;}

        // Return true is the value is a pointer type.
        bool isPointerType() const;

        Storage(const Storage &);
        Storage &operator=(const Storage &);
    };

    // Convert a Python object to C++, allocating storage as necessary.  Return
    // 0 if there was an error.
    Storage *fromPyObjectToStorage(PyObject *py) const;

    // Create a storage instance for this type.
    Storage *storageFactory() const;

    // Convert a Python object to C++ at a given address.  Return false if
    // there was an error.
    bool fromPyObject(PyObject *py, void *cpp) const;

    // Convert a Python object to a QVariant.  Return false if there was an
    // error.
    bool fromPyObject(PyObject *py, QVariant *var) const;

    // Convert a Python object to a QVariant based on the type of the object.
    static QVariant fromAnyPyObject(PyObject *py, int *is_err);

    // Convert a QVariant to a Python object.
    PyObject *toPyObject(const QVariant &var) const;

    // Convert a C++ object at an arbitary address to a Python object.
    PyObject *toPyObject(void *cpp) const;

    // Convert a QVariant to a Python object based on the type of the object.
    static PyObject *toAnyPyObject(const QVariant &var);

    // Returns the Qt meta-type id.  It will be QMetaType::Void if the type
    // isn't known to Qt's meta-type system.
    int metatype() const {return _metatype;}

    // Returns the C++ name of the type.
    const QByteArray &name() const {return _name;}

    // Returns true if the type is an enum.
    bool isEnum() const {return (_type && sipTypeIsEnum(_type));}

    // Returns true if the type is a flag.
    bool isFlag() const {return _is_flag;}

    // Returns the SIP generated type structure.
    const sipTypeDef *typeDef() const {return _type;}

    // Register a type name as an int type.
    static void registerIntType(const char *name);

private:
    // The generated type structure.  This may be 0 if the type is known by Qt
    // but hasn't been wrapped.
    const sipTypeDef *_type;

    // The Qt meta-type.  This will always be valid but may refer to the
    // PyObject wrapper if the underlying type isn't known to Qt.
    int _metatype;

    // Set if the meta-type needn't be exact.
    bool _inexact;

    // Set if the the type is derived from QFlags.
    bool _is_flag;

    // The C++ name of the type.
    QByteArray _name;

    // The registered int types.
    static QList<QByteArray> _registered_int_types;

    // The cache of previously parsed argument type lists.
    static QHash<QByteArray, QList<const Chimera *> > _previously_parsed;

    Chimera();

    bool parse_cpp_type(const QByteArray &type);
    bool parse_py_type(PyTypeObject *type_obj);
    sipAssignFunc get_assign_helper() const;
    void set_flag();
    bool to_QVariantList(PyObject *py, QVariantList &cpp) const;
    bool to_QVariantMap(PyObject *py, QVariantMap &cpp) const;
#if QT_VERSION >= 0x040500
    bool to_QVariantHash(PyObject *py, QVariantHash &cpp) const;
#endif
    static bool add_variant_to_dict(PyObject *dict, const QString &key_ref,
            const QVariant &val_ref);
    static void raiseParseException(const char *type, const char *context);
    static QVariant keep_as_pyobject(PyObject *py);
    static int extract_raw_type(const QByteArray &type, QByteArray &raw_type);

    Chimera(const Chimera &);
    Chimera &operator=(const Chimera &);
};


#endif