##// END OF EJS Templates
updated old license information and current date...
florianlink -
r133:26c5443b8486
parent child
Show More
@@ -1,43 +1,43
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file CustomObjects.cpp
35 // \file CustomObjects.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-4
38 // \date 2007-4
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "CustomObjects.h"
42 #include "CustomObjects.h"
43
43
@@ -1,149 +1,149
1 #ifndef _PYCUSTOMOBJECTS_H
1 #ifndef _PYCUSTOMOBJECTS_H
2 #define _PYCUSTOMOBJECTS_H
2 #define _PYCUSTOMOBJECTS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file CustomObjects.h
38 // \file CustomObjects.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2007-4
41 // \date 2007-4
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtCppWrapperFactory.h"
46 #include "PythonQtCppWrapperFactory.h"
47 #include <QObject>
47 #include <QObject>
48
48
49
49
50 // declare our own custom object
50 // declare our own custom object
51 class CustomObject {
51 class CustomObject {
52 public:
52 public:
53 CustomObject() {}
53 CustomObject() {}
54 CustomObject(const QString& first, const QString& last) { _firstName = first; _lastName = last; }
54 CustomObject(const QString& first, const QString& last) { _firstName = first; _lastName = last; }
55
55
56 QString _firstName;
56 QString _firstName;
57 QString _lastName;
57 QString _lastName;
58
58
59 };
59 };
60
60
61
61
62 // add a decorator that allows to access the CustomObject from PythonQt
62 // add a decorator that allows to access the CustomObject from PythonQt
63 class CustomObjectWrapper : public QObject {
63 class CustomObjectWrapper : public QObject {
64
64
65 Q_OBJECT
65 Q_OBJECT
66
66
67 public slots:
67 public slots:
68 // add a constructor
68 // add a constructor
69 CustomObject* new_CustomObject(const QString& first, const QString& last) { return new CustomObject(first, last); }
69 CustomObject* new_CustomObject(const QString& first, const QString& last) { return new CustomObject(first, last); }
70
70
71 // add a destructor
71 // add a destructor
72 void delete_CustomObject(CustomObject* o) { delete o; }
72 void delete_CustomObject(CustomObject* o) { delete o; }
73
73
74 // add access methods
74 // add access methods
75 QString firstName(CustomObject* o) { return o->_firstName; }
75 QString firstName(CustomObject* o) { return o->_firstName; }
76
76
77 QString lastName(CustomObject* o) { return o->_lastName; }
77 QString lastName(CustomObject* o) { return o->_lastName; }
78
78
79 void setFirstName(CustomObject* o, const QString& name) { o->_firstName = name; }
79 void setFirstName(CustomObject* o, const QString& name) { o->_firstName = name; }
80
80
81 void setLastName(CustomObject* o, const QString& name) { o->_lastName = name; }
81 void setLastName(CustomObject* o, const QString& name) { o->_lastName = name; }
82
82
83 };
83 };
84
84
85
85
86 //------------------------------------------------------------------------------------------------
86 //------------------------------------------------------------------------------------------------
87 // alternative: we create a wrapper factory, which creates a wrapper object for each CPP instance:
87 // alternative: we create a wrapper factory, which creates a wrapper object for each CPP instance:
88 //------------------------------------------------------------------------------------------------
88 //------------------------------------------------------------------------------------------------
89
89
90 // declare our own custom object
90 // declare our own custom object
91 class CustomObject2 {
91 class CustomObject2 {
92 public:
92 public:
93 CustomObject2() {}
93 CustomObject2() {}
94 CustomObject2(const QString& first, const QString& last) { _firstName = first; _lastName = last; }
94 CustomObject2(const QString& first, const QString& last) { _firstName = first; _lastName = last; }
95
95
96 QString _firstName;
96 QString _firstName;
97 QString _lastName;
97 QString _lastName;
98
98
99 };
99 };
100
100
101
101
102 // add a decorator that allows to access the CustomObject from PythonQt
102 // add a decorator that allows to access the CustomObject from PythonQt
103 class CustomObject2Wrapper : public QObject {
103 class CustomObject2Wrapper : public QObject {
104
104
105 Q_OBJECT
105 Q_OBJECT
106
106
107 public:
107 public:
108 CustomObject2Wrapper(CustomObject2* obj) { _ptr = obj; }
108 CustomObject2Wrapper(CustomObject2* obj) { _ptr = obj; }
109
109
110 public slots:
110 public slots:
111 // add access methods
111 // add access methods
112 QString firstName() { return _ptr->_firstName; }
112 QString firstName() { return _ptr->_firstName; }
113
113
114 QString lastName() { return _ptr->_lastName; }
114 QString lastName() { return _ptr->_lastName; }
115
115
116 void setFirstName(const QString& name) { _ptr->_firstName = name; }
116 void setFirstName(const QString& name) { _ptr->_firstName = name; }
117
117
118 void setLastName(const QString& name) { _ptr->_lastName = name; }
118 void setLastName(const QString& name) { _ptr->_lastName = name; }
119
119
120 private:
120 private:
121 CustomObject2* _ptr;
121 CustomObject2* _ptr;
122 };
122 };
123
123
124 // additional constructor/destructor for CustomObject2 (optional)
124 // additional constructor/destructor for CustomObject2 (optional)
125 class CustomObject2Constructor : public QObject {
125 class CustomObject2Constructor : public QObject {
126
126
127 Q_OBJECT
127 Q_OBJECT
128
128
129 public slots:
129 public slots:
130 // add a constructor
130 // add a constructor
131 CustomObject2* new_CustomObject2(const QString& first, const QString& last) { return new CustomObject2(first, last); }
131 CustomObject2* new_CustomObject2(const QString& first, const QString& last) { return new CustomObject2(first, last); }
132
132
133 // add a destructor
133 // add a destructor
134 void delete_CustomObject2(CustomObject2* o) { delete o; }
134 void delete_CustomObject2(CustomObject2* o) { delete o; }
135 };
135 };
136
136
137 // a factory that can create wrappers for CustomObject2
137 // a factory that can create wrappers for CustomObject2
138 class CustomFactory : public PythonQtCppWrapperFactory
138 class CustomFactory : public PythonQtCppWrapperFactory
139 {
139 {
140 public:
140 public:
141 virtual QObject* create(const QByteArray& name, void *ptr) {
141 virtual QObject* create(const QByteArray& name, void *ptr) {
142 if (name == "CustomObject2") {
142 if (name == "CustomObject2") {
143 return new CustomObject2Wrapper((CustomObject2*)ptr);
143 return new CustomObject2Wrapper((CustomObject2*)ptr);
144 }
144 }
145 return NULL;
145 return NULL;
146 }
146 }
147 };
147 };
148
148
149 #endif
149 #endif
@@ -1,84 +1,84
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PyGuiExample.cpp
35 // \file PyGuiExample.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "gui/PythonQtScriptingConsole.h"
43 #include "gui/PythonQtScriptingConsole.h"
44 #include "CustomObjects.h"
44 #include "CustomObjects.h"
45
45
46 #include <QApplication>
46 #include <QApplication>
47
47
48 int main( int argc, char **argv )
48 int main( int argc, char **argv )
49 {
49 {
50 QApplication qapp(argc, argv);
50 QApplication qapp(argc, argv);
51
51
52 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
52 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
53
53
54 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
54 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
55 PythonQtScriptingConsole console(NULL, mainContext);
55 PythonQtScriptingConsole console(NULL, mainContext);
56
56
57 // -----------------------------------------------------------------
57 // -----------------------------------------------------------------
58 // Alternative 1: make CustomObject known and use decorators for wrapping:
58 // Alternative 1: make CustomObject known and use decorators for wrapping:
59 // -----------------------------------------------------------------
59 // -----------------------------------------------------------------
60
60
61 // register the new object as a known classname and add it's wrapper object
61 // register the new object as a known classname and add it's wrapper object
62 PythonQt::self()->registerCPPClass("CustomObject", "","", PythonQtCreateObject<CustomObjectWrapper>);
62 PythonQt::self()->registerCPPClass("CustomObject", "","", PythonQtCreateObject<CustomObjectWrapper>);
63
63
64 // -----------------------------------------------------------------
64 // -----------------------------------------------------------------
65 // Alternative 2: make CustomObject2 known and use a wrapper factory for wrapping:
65 // Alternative 2: make CustomObject2 known and use a wrapper factory for wrapping:
66 // -----------------------------------------------------------------
66 // -----------------------------------------------------------------
67
67
68 // add a factory that can handle pointers to CustomObject2
68 // add a factory that can handle pointers to CustomObject2
69 PythonQt::self()->addWrapperFactory(new CustomFactory());
69 PythonQt::self()->addWrapperFactory(new CustomFactory());
70
70
71 // the following is optional and only needed if you want a constructor:
71 // the following is optional and only needed if you want a constructor:
72 // register the new object as a known classname
72 // register the new object as a known classname
73 PythonQt::self()->registerCPPClass("CustomObject2");
73 PythonQt::self()->registerCPPClass("CustomObject2");
74 // add a constructor for CustomObject2
74 // add a constructor for CustomObject2
75 PythonQt::self()->addClassDecorators(new CustomObject2Constructor());
75 PythonQt::self()->addClassDecorators(new CustomObject2Constructor());
76
76
77 mainContext.evalFile(":example.py");
77 mainContext.evalFile(":example.py");
78
78
79 console.appendCommandPrompt();
79 console.appendCommandPrompt();
80 console.show();
80 console.show();
81
81
82 return qapp.exec();
82 return qapp.exec();
83 }
83 }
84
84
@@ -1,43 +1,43
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file CustomObject.cpp
35 // \file CustomObject.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-4
38 // \date 2007-4
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "CustomObject.h"
42 #include "CustomObject.h"
43
43
@@ -1,85 +1,85
1 #ifndef _PYCUSTOMOBJECT_H
1 #ifndef _PYCUSTOMOBJECT_H
2 #define _PYCUSTOMOBJECT_H
2 #define _PYCUSTOMOBJECT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file CustomObject.h
38 // \file CustomObject.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2007-4
41 // \date 2007-4
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include <QObject>
46 #include <QObject>
47
47
48
48
49 // declare our own copyable custom object
49 // declare our own copyable custom object
50 class CustomObject {
50 class CustomObject {
51 public:
51 public:
52 CustomObject() {}
52 CustomObject() {}
53 CustomObject(const QString& first, const QString& last) { _firstName = first; _lastName = last; }
53 CustomObject(const QString& first, const QString& last) { _firstName = first; _lastName = last; }
54
54
55 QString _firstName;
55 QString _firstName;
56 QString _lastName;
56 QString _lastName;
57
57
58 };
58 };
59
59
60 // register it to the meta type system
60 // register it to the meta type system
61 Q_DECLARE_METATYPE(CustomObject)
61 Q_DECLARE_METATYPE(CustomObject)
62
62
63 // add a wrapper that allows to access the CustomObject from PythonQt
63 // add a wrapper that allows to access the CustomObject from PythonQt
64 class CustomObjectWrapper : public QObject {
64 class CustomObjectWrapper : public QObject {
65
65
66 Q_OBJECT
66 Q_OBJECT
67
67
68 public slots:
68 public slots:
69 // add a constructor
69 // add a constructor
70 CustomObject* new_CustomObject(const QString& first, const QString& last) { return new CustomObject(first, last); }
70 CustomObject* new_CustomObject(const QString& first, const QString& last) { return new CustomObject(first, last); }
71
71
72 // add access methods
72 // add access methods
73
73
74 QString firstName(CustomObject* o) { return o->_firstName; }
74 QString firstName(CustomObject* o) { return o->_firstName; }
75
75
76 QString lastName(CustomObject* o) { return o->_lastName; }
76 QString lastName(CustomObject* o) { return o->_lastName; }
77
77
78 void setFirstName(CustomObject* o, const QString& name) { o->_firstName = name; }
78 void setFirstName(CustomObject* o, const QString& name) { o->_firstName = name; }
79
79
80 void setLastName(CustomObject* o, const QString& name) { o->_lastName = name; }
80 void setLastName(CustomObject* o, const QString& name) { o->_lastName = name; }
81
81
82 };
82 };
83
83
84
84
85 #endif
85 #endif
@@ -1,69 +1,69
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PyGuiExample.cpp
35 // \file PyGuiExample.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "gui/PythonQtScriptingConsole.h"
43 #include "gui/PythonQtScriptingConsole.h"
44 #include "CustomObject.h"
44 #include "CustomObject.h"
45
45
46 #include <QApplication>
46 #include <QApplication>
47
47
48 int main( int argc, char **argv )
48 int main( int argc, char **argv )
49 {
49 {
50 QApplication qapp(argc, argv);
50 QApplication qapp(argc, argv);
51
51
52 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
52 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
53
53
54 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
54 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
55 PythonQtScriptingConsole console(NULL, mainContext);
55 PythonQtScriptingConsole console(NULL, mainContext);
56
56
57 // register the type with QMetaType
57 // register the type with QMetaType
58 qRegisterMetaType<CustomObject>("CustomObject");
58 qRegisterMetaType<CustomObject>("CustomObject");
59 // add a wrapper object for the new variant type
59 // add a wrapper object for the new variant type
60 PythonQt::self()->registerCPPClass("CustomObject","","", PythonQtCreateObject<CustomObjectWrapper>);
60 PythonQt::self()->registerCPPClass("CustomObject","","", PythonQtCreateObject<CustomObjectWrapper>);
61
61
62 mainContext.evalFile(":example.py");
62 mainContext.evalFile(":example.py");
63
63
64 console.appendCommandPrompt();
64 console.appendCommandPrompt();
65 console.show();
65 console.show();
66
66
67 return qapp.exec();
67 return qapp.exec();
68 }
68 }
69
69
@@ -1,43 +1,43
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PyExampleObject.cpp
35 // \file PyExampleObject.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-10
38 // \date 2006-10
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PyExampleDecorators.h"
42 #include "PyExampleDecorators.h"
43
43
@@ -1,95 +1,95
1 #ifndef _PYEXAMPLEDECORATORS_H
1 #ifndef _PYEXAMPLEDECORATORS_H
2 #define _PYEXAMPLEDECORATORS_H
2 #define _PYEXAMPLEDECORATORS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PyExampleDecorators.h
38 // \file PyExampleDecorators.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2007-4
41 // \date 2007-4
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include <QDebug>
46 #include <QDebug>
47 #include <QObject>
47 #include <QObject>
48 #include <QPushButton>
48 #include <QPushButton>
49
49
50 // an example CPP object
50 // an example CPP object
51 class YourCPPObject {
51 class YourCPPObject {
52 public:
52 public:
53 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
53 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
54
54
55 float doSomething(int arg1) { return arg1*a*b; };
55 float doSomething(int arg1) { return arg1*a*b; };
56
56
57 private:
57 private:
58
58
59 int a;
59 int a;
60 float b;
60 float b;
61 };
61 };
62
62
63 // an example decorator
63 // an example decorator
64 class PyExampleDecorators : public QObject
64 class PyExampleDecorators : public QObject
65 {
65 {
66 Q_OBJECT
66 Q_OBJECT
67
67
68 public slots:
68 public slots:
69 // add a constructor to QSize variant that takes a QPoint
69 // add a constructor to QSize variant that takes a QPoint
70 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
70 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
71
71
72 // add a constructor for QPushButton that takes a text and a parent widget
72 // add a constructor for QPushButton that takes a text and a parent widget
73 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
73 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
74
74
75 // add a constructor for a CPP object
75 // add a constructor for a CPP object
76 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
76 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
77
77
78 // add a destructor for a CPP object
78 // add a destructor for a CPP object
79 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
79 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
80
80
81 // add a static method to QWidget
81 // add a static method to QWidget
82 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
82 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
83
83
84 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
84 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
85 void move(QWidget* w, const QPoint& p) { w->move(p); }
85 void move(QWidget* w, const QPoint& p) { w->move(p); }
86
86
87 // add an additional slot to QWidget, overloading the above move method
87 // add an additional slot to QWidget, overloading the above move method
88 void move(QWidget* w, int x, int y) { w->move(x,y); }
88 void move(QWidget* w, int x, int y) { w->move(x,y); }
89
89
90 // add a method to your own CPP object
90 // add a method to your own CPP object
91 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
91 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
92 };
92 };
93
93
94
94
95 #endif
95 #endif
@@ -1,68 +1,68
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PyGuiExample.cpp
35 // \file PyGuiExample.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "gui/PythonQtScriptingConsole.h"
43 #include "gui/PythonQtScriptingConsole.h"
44 #include "PyExampleDecorators.h"
44 #include "PyExampleDecorators.h"
45
45
46 #include <QApplication>
46 #include <QApplication>
47
47
48 int main( int argc, char **argv )
48 int main( int argc, char **argv )
49 {
49 {
50 QApplication qapp(argc, argv);
50 QApplication qapp(argc, argv);
51
51
52 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
52 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
53
53
54 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
54 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
55 PythonQtScriptingConsole console(NULL, mainContext);
55 PythonQtScriptingConsole console(NULL, mainContext);
56
56
57 PythonQt::self()->addDecorators(new PyExampleDecorators());
57 PythonQt::self()->addDecorators(new PyExampleDecorators());
58 PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
58 PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
59 PythonQt::self()->registerCPPClass("YourCPPObject");
59 PythonQt::self()->registerCPPClass("YourCPPObject");
60
60
61 mainContext.evalFile(":example.py");
61 mainContext.evalFile(":example.py");
62
62
63 console.appendCommandPrompt();
63 console.appendCommandPrompt();
64 console.show();
64 console.show();
65
65
66 return qapp.exec();
66 return qapp.exec();
67 }
67 }
68
68
@@ -1,101 +1,101
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtTests.cpp
35 // \file PythonQtTests.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include <QApplication>
43 #include <QApplication>
44 #include <QTextBrowser>
44 #include <QTextBrowser>
45 #include <QLayout>
45 #include <QLayout>
46 #include <QGroupBox>
46 #include <QGroupBox>
47 #include <QPushButton>
47 #include <QPushButton>
48 #include <QLineEdit>
48 #include <QLineEdit>
49
49
50 int main( int argc, char **argv )
50 int main( int argc, char **argv )
51 {
51 {
52 QApplication qapp(argc, argv);
52 QApplication qapp(argc, argv);
53
53
54 // init PythonQt and Python
54 // init PythonQt and Python
55 PythonQt::init();
55 PythonQt::init();
56
56
57 // get the __main__ python module
57 // get the __main__ python module
58 PythonQtObjectPtr mainModule = PythonQt::self()->getMainModule();
58 PythonQtObjectPtr mainModule = PythonQt::self()->getMainModule();
59
59
60 // evaluate a simple python script and receive the result a qvariant:
60 // evaluate a simple python script and receive the result a qvariant:
61 QVariant result = mainModule.evalScript("19*2+4", Py_eval_input);
61 QVariant result = mainModule.evalScript("19*2+4", Py_eval_input);
62
62
63 // Create object from python, hold onto reference in C++:
63 // Create object from python, hold onto reference in C++:
64 PythonQtObjectPtr tag = mainModule.evalScript("EyeD3Tagger()\n", Py_eval_input);
64 PythonQtObjectPtr tag = mainModule.evalScript("EyeD3Tagger()\n", Py_eval_input);
65 Q_ASSERT(!tag.isNull());
65 Q_ASSERT(!tag.isNull());
66
66
67 // call python methods from C++
67 // call python methods from C++
68 tag.call("setFileName", QVariantList() << "t.mp3");
68 tag.call("setFileName", QVariantList() << "t.mp3");
69 QVariant fn = tag.call("fileName", QVariantList());
69 QVariant fn = tag.call("fileName", QVariantList());
70 Q_ASSERT(fn.toString() == QString("t.mp3"));
70 Q_ASSERT(fn.toString() == QString("t.mp3"));
71
71
72 // create a small Qt GUI
72 // create a small Qt GUI
73 QVBoxLayout* vbox = new QVBoxLayout;
73 QVBoxLayout* vbox = new QVBoxLayout;
74 QGroupBox* box = new QGroupBox;
74 QGroupBox* box = new QGroupBox;
75 QTextBrowser* browser = new QTextBrowser(box);
75 QTextBrowser* browser = new QTextBrowser(box);
76 QLineEdit* edit = new QLineEdit(box);
76 QLineEdit* edit = new QLineEdit(box);
77 QPushButton* button = new QPushButton(box);
77 QPushButton* button = new QPushButton(box);
78 button->setObjectName("button1");
78 button->setObjectName("button1");
79 edit->setObjectName("edit");
79 edit->setObjectName("edit");
80 browser->setObjectName("browser");
80 browser->setObjectName("browser");
81 vbox->addWidget(browser);
81 vbox->addWidget(browser);
82 vbox->addWidget(edit);
82 vbox->addWidget(edit);
83 vbox->addWidget(button);
83 vbox->addWidget(button);
84 box->setLayout(vbox);
84 box->setLayout(vbox);
85
85
86 // make the groupbox to the python under the name "box"
86 // make the groupbox to the python under the name "box"
87 mainModule.addObject("box", box);
87 mainModule.addObject("box", box);
88
88
89 // evaluate the python script which is defined in the resources
89 // evaluate the python script which is defined in the resources
90 mainModule.evalFile(":GettingStarted.py");
90 mainModule.evalFile(":GettingStarted.py");
91
91
92 // define a python method that appends the passed text to the browser
92 // define a python method that appends the passed text to the browser
93 mainModule.evalScript("def appendText(text):\n box.browser.append(text)");
93 mainModule.evalScript("def appendText(text):\n box.browser.append(text)");
94 // shows how to call the method with a text that will be append to the browser
94 // shows how to call the method with a text that will be append to the browser
95 mainModule.call("appendText", QVariantList() << "The ultimate answer is ");
95 mainModule.call("appendText", QVariantList() << "The ultimate answer is ");
96
96
97
97
98
98
99 return qapp.exec();
99 return qapp.exec();
100 }
100 }
101
101
@@ -1,68 +1,68
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PyGuiExample.cpp
35 // \file PyGuiExample.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQt_QtAll.h"
43 #include "PythonQt_QtAll.h"
44 #include "gui/PythonQtScriptingConsole.h"
44 #include "gui/PythonQtScriptingConsole.h"
45
45
46 #include <QApplication>
46 #include <QApplication>
47 #include <QWidget>
47 #include <QWidget>
48 #include <QMainWindow>
48 #include <QMainWindow>
49 #include <QPushButton>
49 #include <QPushButton>
50 #include <QLayout>
50 #include <QLayout>
51
51
52
52
53 int main( int argc, char **argv )
53 int main( int argc, char **argv )
54 {
54 {
55 QApplication qapp(argc, argv);
55 QApplication qapp(argc, argv);
56
56
57 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
57 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
58 PythonQt_QtAll::init();
58 PythonQt_QtAll::init();
59
59
60 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
60 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
61 PythonQtScriptingConsole console(NULL, mainContext);
61 PythonQtScriptingConsole console(NULL, mainContext);
62
62
63 mainContext.evalFile(":example.py");
63 mainContext.evalFile(":example.py");
64
64
65 console.show();
65 console.show();
66 return qapp.exec();
66 return qapp.exec();
67 }
67 }
68
68
@@ -1,90 +1,90
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PyGuiExample.cpp
35 // \file PyGuiExample.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQt_QtAll.h"
43 #include "PythonQt_QtAll.h"
44 #include "gui/PythonQtScriptingConsole.h"
44 #include "gui/PythonQtScriptingConsole.h"
45
45
46 #include <QApplication>
46 #include <QApplication>
47 #include <QDir>
47 #include <QDir>
48 #include <QMessageBox>
48 #include <QMessageBox>
49
49
50
50
51 int main( int argc, char **argv )
51 int main( int argc, char **argv )
52 {
52 {
53 QApplication qapp(argc, argv);
53 QApplication qapp(argc, argv);
54
54
55 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
55 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
56 PythonQt_QtAll::init();
56 PythonQt_QtAll::init();
57
57
58 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
58 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
59
59
60 bool showConsole = false;
60 bool showConsole = false;
61 QStringList files;
61 QStringList files;
62 for (int i = 1; i < argc; i++) {
62 for (int i = 1; i < argc; i++) {
63 QString arg = argv[i];
63 QString arg = argv[i];
64 QString argLower = arg.toLower();
64 QString argLower = arg.toLower();
65 if (argLower == "-console" || argLower == "-c") {
65 if (argLower == "-console" || argLower == "-c") {
66 showConsole = true;
66 showConsole = true;
67 } else {
67 } else {
68 QString file = arg;
68 QString file = arg;
69 QFileInfo info(file);
69 QFileInfo info(file);
70 if (info.exists()) {
70 if (info.exists()) {
71 files << info.absoluteFilePath();
71 files << info.absoluteFilePath();
72 // add the file's absolute path for local importing
72 // add the file's absolute path for local importing
73 PythonQt::self()->addSysPath(info.absolutePath());
73 PythonQt::self()->addSysPath(info.absolutePath());
74 } else {
74 } else {
75 QMessageBox::warning(NULL, "PyLauncher", QString("File does not exist: %1").arg(file));
75 QMessageBox::warning(NULL, "PyLauncher", QString("File does not exist: %1").arg(file));
76 }
76 }
77 }
77 }
78 }
78 }
79 PythonQtScriptingConsole console(NULL, mainContext);
79 PythonQtScriptingConsole console(NULL, mainContext);
80
80
81 foreach(QString file, files) {
81 foreach(QString file, files) {
82 mainContext.evalFile(file);
82 mainContext.evalFile(file);
83 }
83 }
84 if (showConsole || console.hadError()) {
84 if (showConsole || console.hadError()) {
85 console.show();
85 console.show();
86 }
86 }
87
87
88 return qapp.exec();
88 return qapp.exec();
89 }
89 }
90
90
@@ -1,87 +1,87
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PyExampleObject.cpp
35 // \file PyExampleObject.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-10
38 // \date 2006-10
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PyExampleObject.h"
42 #include "PyExampleObject.h"
43 #include <QMessageBox>
43 #include <QMessageBox>
44 #include <QDir>
44 #include <QDir>
45
45
46 PyExampleObject::PyExampleObject():QObject(NULL)
46 PyExampleObject::PyExampleObject():QObject(NULL)
47 {
47 {
48 }
48 }
49
49
50 PyObject* PyExampleObject::getMainModule() {
50 PyObject* PyExampleObject::getMainModule() {
51 return PythonQt::self()->getMainModule();
51 return PythonQt::self()->getMainModule();
52 }
52 }
53
53
54 void PyExampleObject::showInformation(const QString& str)
54 void PyExampleObject::showInformation(const QString& str)
55 {
55 {
56 QMessageBox::information ( NULL, "Test", str);
56 QMessageBox::information ( NULL, "Test", str);
57 }
57 }
58
58
59 QStringList PyExampleObject::readDirectory(const QString& dir)
59 QStringList PyExampleObject::readDirectory(const QString& dir)
60 {
60 {
61 QDir d(dir);
61 QDir d(dir);
62 return d.entryList();
62 return d.entryList();
63 }
63 }
64
64
65 QMainWindow* PyExampleObject::createWindow()
65 QMainWindow* PyExampleObject::createWindow()
66 {
66 {
67 QMainWindow* m = new QMainWindow();
67 QMainWindow* m = new QMainWindow();
68 QPushButton* b = new QPushButton(m);
68 QPushButton* b = new QPushButton(m);
69 b->setObjectName("button1");
69 b->setObjectName("button1");
70
70
71 m->show();
71 m->show();
72 return m;
72 return m;
73 }
73 }
74
74
75 QObject* PyExampleObject::findChild(QObject* o, const QString& name)
75 QObject* PyExampleObject::findChild(QObject* o, const QString& name)
76 {
76 {
77 return qFindChild<QObject*>(o, name);
77 return qFindChild<QObject*>(o, name);
78 }
78 }
79
79
80 QVariantMap PyExampleObject::testMap()
80 QVariantMap PyExampleObject::testMap()
81 {
81 {
82 QVariantMap m;
82 QVariantMap m;
83 m.insert("a", QStringList() << "test1" << "test2");
83 m.insert("a", QStringList() << "test1" << "test2");
84 m.insert("b", 12);
84 m.insert("b", 12);
85 m.insert("c", 12.);
85 m.insert("c", 12.);
86 return m;
86 return m;
87 }
87 }
@@ -1,79 +1,79
1 #ifndef _PYEXAMPLEOBJECT_H
1 #ifndef _PYEXAMPLEOBJECT_H
2 #define _PYEXAMPLEOBJECT_H
2 #define _PYEXAMPLEOBJECT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PyExampleObject.h
38 // \file PyExampleObject.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-10
41 // \date 2006-10
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46
46
47 #include <QObject>
47 #include <QObject>
48 #include <QStringList>
48 #include <QStringList>
49 #include <QMainWindow>
49 #include <QMainWindow>
50 #include <QPushButton>
50 #include <QPushButton>
51 #include <QVariant>
51 #include <QVariant>
52 #include <QLayout>
52 #include <QLayout>
53
53
54
54
55 class PyExampleObject : public QObject {
55 class PyExampleObject : public QObject {
56
56
57 Q_OBJECT
57 Q_OBJECT
58
58
59 public:
59 public:
60 PyExampleObject();
60 PyExampleObject();
61
61
62 public slots:
62 public slots:
63
63
64 //! example for passing a PyObject directly from Qt to Python (without extra mashalling)
64 //! example for passing a PyObject directly from Qt to Python (without extra mashalling)
65 PyObject* getMainModule();
65 PyObject* getMainModule();
66
66
67 void showInformation(const QString& str);
67 void showInformation(const QString& str);
68
68
69 QStringList readDirectory(const QString& dir);
69 QStringList readDirectory(const QString& dir);
70
70
71 QMainWindow* createWindow();
71 QMainWindow* createWindow();
72
72
73 QObject* findChild(QObject* o, const QString& name);
73 QObject* findChild(QObject* o, const QString& name);
74
74
75 QVariantMap testMap();
75 QVariantMap testMap();
76
76
77 };
77 };
78
78
79 #endif
79 #endif
@@ -1,74 +1,74
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtTests.cpp
35 // \file PythonQtTests.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQt_QtAll.h"
43 #include "PythonQt_QtAll.h"
44
44
45 #include "PyExampleObject.h"
45 #include "PyExampleObject.h"
46 #include "gui/PythonQtScriptingConsole.h"
46 #include "gui/PythonQtScriptingConsole.h"
47
47
48 #include <QApplication>
48 #include <QApplication>
49 #include <QWidget>
49 #include <QWidget>
50 #include <QMainWindow>
50 #include <QMainWindow>
51 #include <QPushButton>
51 #include <QPushButton>
52 #include <QLayout>
52 #include <QLayout>
53
53
54
54
55 int main( int argc, char **argv )
55 int main( int argc, char **argv )
56 {
56 {
57 QApplication qapp(argc, argv);
57 QApplication qapp(argc, argv);
58
58
59 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
59 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
60 PythonQt_QtAll::init();
60 PythonQt_QtAll::init();
61
61
62 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
62 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
63 PythonQtScriptingConsole console(NULL, mainContext);
63 PythonQtScriptingConsole console(NULL, mainContext);
64
64
65 // add a QObject to the namespace of the main python context
65 // add a QObject to the namespace of the main python context
66 PyExampleObject example;
66 PyExampleObject example;
67 mainContext.addObject("example", &example);
67 mainContext.addObject("example", &example);
68
68
69 mainContext.evalFile(":example.py");
69 mainContext.evalFile(":example.py");
70
70
71 console.show();
71 console.show();
72 return qapp.exec();
72 return qapp.exec();
73 }
73 }
74
74
@@ -1,67 +1,67
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 #include "PythonQt_QtAll.h"
33 #include "PythonQt_QtAll.h"
34
34
35 #include "PythonQt.h"
35 #include "PythonQt.h"
36
36
37 void PythonQt_init_QtGui(PyObject*);
37 void PythonQt_init_QtGui(PyObject*);
38 void PythonQt_init_QtSvg(PyObject*);
38 void PythonQt_init_QtSvg(PyObject*);
39 void PythonQt_init_QtSql(PyObject*);
39 void PythonQt_init_QtSql(PyObject*);
40 void PythonQt_init_QtNetwork(PyObject*);
40 void PythonQt_init_QtNetwork(PyObject*);
41 void PythonQt_init_QtCore(PyObject*);
41 void PythonQt_init_QtCore(PyObject*);
42 void PythonQt_init_QtWebKit(PyObject*);
42 void PythonQt_init_QtWebKit(PyObject*);
43 void PythonQt_init_QtOpenGL(PyObject*);
43 void PythonQt_init_QtOpenGL(PyObject*);
44 void PythonQt_init_QtXml(PyObject*);
44 void PythonQt_init_QtXml(PyObject*);
45 void PythonQt_init_QtXmlPatterns(PyObject*);
45 void PythonQt_init_QtXmlPatterns(PyObject*);
46 void PythonQt_init_QtUiTools(PyObject*);
46 void PythonQt_init_QtUiTools(PyObject*);
47 void PythonQt_init_QtPhonon(PyObject*);
47 void PythonQt_init_QtPhonon(PyObject*);
48
48
49 namespace PythonQt_QtAll
49 namespace PythonQt_QtAll
50 {
50 {
51 PYTHONQT_QTALL_EXPORT void init() {
51 PYTHONQT_QTALL_EXPORT void init() {
52 PythonQt_init_QtCore(0);
52 PythonQt_init_QtCore(0);
53 PythonQt_init_QtNetwork(0);
53 PythonQt_init_QtNetwork(0);
54 PythonQt_init_QtGui(0);
54 PythonQt_init_QtGui(0);
55 PythonQt_init_QtXml(0);
55 PythonQt_init_QtXml(0);
56 PythonQt_init_QtSvg(0);
56 PythonQt_init_QtSvg(0);
57 PythonQt_init_QtSql(0);
57 PythonQt_init_QtSql(0);
58 PythonQt_init_QtWebKit(0);
58 PythonQt_init_QtWebKit(0);
59 PythonQt_init_QtOpenGL(0);
59 PythonQt_init_QtOpenGL(0);
60 PythonQt_init_QtUiTools(0);
60 PythonQt_init_QtUiTools(0);
61 // Does not compile yet:
61 // Does not compile yet:
62 // PythonQt_init_QtXmlPatterns(0);
62 // PythonQt_init_QtXmlPatterns(0);
63 // PythonQt_init_QtPhonon(0);
63 // PythonQt_init_QtPhonon(0);
64 };
64 };
65 };
65 };
66
66
67
67
@@ -1,52 +1,52
1 #ifndef _PYTHONQT_QTALL_H
1 #ifndef _PYTHONQT_QTALL_H
2 #define _PYTHONQT_QTALL_H
2 #define _PYTHONQT_QTALL_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 #ifdef WIN32
36 #ifdef WIN32
37 #ifdef PYTHONQT_QTALL_EXPORTS
37 #ifdef PYTHONQT_QTALL_EXPORTS
38 #define PYTHONQT_QTALL_EXPORT __declspec(dllexport)
38 #define PYTHONQT_QTALL_EXPORT __declspec(dllexport)
39 #else
39 #else
40 #define PYTHONQT_QTALL_EXPORT __declspec(dllimport)
40 #define PYTHONQT_QTALL_EXPORT __declspec(dllimport)
41 #endif
41 #endif
42 #else
42 #else
43 #define PYTHONQT_QTALL_EXPORT
43 #define PYTHONQT_QTALL_EXPORT
44 #endif
44 #endif
45
45
46 namespace PythonQt_QtAll
46 namespace PythonQt_QtAll
47 {
47 {
48 //! initialize the Qt binding
48 //! initialize the Qt binding
49 PYTHONQT_QTALL_EXPORT void init();
49 PYTHONQT_QTALL_EXPORT void init();
50 };
50 };
51
51
52 #endif
52 #endif
@@ -1,1220 +1,1220
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtImporter.h"
43 #include "PythonQtImporter.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include "PythonQtMethodInfo.h"
45 #include "PythonQtMethodInfo.h"
46 #include "PythonQtSignalReceiver.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtStdOut.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
51 #include "PythonQtStdDecorators.h"
52 #include "PythonQtQFileImporter.h"
52 #include "PythonQtQFileImporter.h"
53 #include <pydebug.h>
53 #include <pydebug.h>
54 #include <vector>
54 #include <vector>
55
55
56 PythonQt* PythonQt::_self = NULL;
56 PythonQt* PythonQt::_self = NULL;
57 int PythonQt::_uniqueModuleCount = 0;
57 int PythonQt::_uniqueModuleCount = 0;
58
58
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
61
61
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
63 {
63 {
64 if (!_self) {
64 if (!_self) {
65 _self = new PythonQt(flags, pythonQtModuleName);
65 _self = new PythonQt(flags, pythonQtModuleName);
66
66
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
69
69
70 PythonQtRegisterToolClassesTemplateConverter(int);
70 PythonQtRegisterToolClassesTemplateConverter(int);
71 PythonQtRegisterToolClassesTemplateConverter(float);
71 PythonQtRegisterToolClassesTemplateConverter(float);
72 PythonQtRegisterToolClassesTemplateConverter(double);
72 PythonQtRegisterToolClassesTemplateConverter(double);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
77 // TODO: which other POD types should be available for QList etc.
77 // TODO: which other POD types should be available for QList etc.
78
78
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
80
80
81 PythonQt_init_QtCoreBuiltin(NULL);
81 PythonQt_init_QtCoreBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
83
83
84 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
84 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
85 PythonQtRegisterToolClassesTemplateConverter(QDate);
85 PythonQtRegisterToolClassesTemplateConverter(QDate);
86 PythonQtRegisterToolClassesTemplateConverter(QTime);
86 PythonQtRegisterToolClassesTemplateConverter(QTime);
87 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
87 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
88 PythonQtRegisterToolClassesTemplateConverter(QUrl);
88 PythonQtRegisterToolClassesTemplateConverter(QUrl);
89 PythonQtRegisterToolClassesTemplateConverter(QLocale);
89 PythonQtRegisterToolClassesTemplateConverter(QLocale);
90 PythonQtRegisterToolClassesTemplateConverter(QRect);
90 PythonQtRegisterToolClassesTemplateConverter(QRect);
91 PythonQtRegisterToolClassesTemplateConverter(QRectF);
91 PythonQtRegisterToolClassesTemplateConverter(QRectF);
92 PythonQtRegisterToolClassesTemplateConverter(QSize);
92 PythonQtRegisterToolClassesTemplateConverter(QSize);
93 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
93 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
94 PythonQtRegisterToolClassesTemplateConverter(QLine);
94 PythonQtRegisterToolClassesTemplateConverter(QLine);
95 PythonQtRegisterToolClassesTemplateConverter(QLineF);
95 PythonQtRegisterToolClassesTemplateConverter(QLineF);
96 PythonQtRegisterToolClassesTemplateConverter(QPoint);
96 PythonQtRegisterToolClassesTemplateConverter(QPoint);
97 PythonQtRegisterToolClassesTemplateConverter(QPointF);
97 PythonQtRegisterToolClassesTemplateConverter(QPointF);
98 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
98 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
99
99
100 PythonQtRegisterToolClassesTemplateConverter(QFont);
100 PythonQtRegisterToolClassesTemplateConverter(QFont);
101 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
101 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
102 PythonQtRegisterToolClassesTemplateConverter(QBrush);
102 PythonQtRegisterToolClassesTemplateConverter(QBrush);
103 PythonQtRegisterToolClassesTemplateConverter(QColor);
103 PythonQtRegisterToolClassesTemplateConverter(QColor);
104 PythonQtRegisterToolClassesTemplateConverter(QPalette);
104 PythonQtRegisterToolClassesTemplateConverter(QPalette);
105 PythonQtRegisterToolClassesTemplateConverter(QIcon);
105 PythonQtRegisterToolClassesTemplateConverter(QIcon);
106 PythonQtRegisterToolClassesTemplateConverter(QImage);
106 PythonQtRegisterToolClassesTemplateConverter(QImage);
107 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
107 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
108 PythonQtRegisterToolClassesTemplateConverter(QRegion);
108 PythonQtRegisterToolClassesTemplateConverter(QRegion);
109 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
109 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
110 PythonQtRegisterToolClassesTemplateConverter(QCursor);
110 PythonQtRegisterToolClassesTemplateConverter(QCursor);
111 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
111 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
112 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
112 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
113 PythonQtRegisterToolClassesTemplateConverter(QPen);
113 PythonQtRegisterToolClassesTemplateConverter(QPen);
114 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
114 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
115 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
115 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
116 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
116 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
117
117
118
118
119 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
119 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
120 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
120 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
121 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
121 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
122 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
122 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
123 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
123 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
124 for (unsigned int i = 0;i<16; i++) {
124 for (unsigned int i = 0;i<16; i++) {
125 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
125 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
126 if (obj) {
126 if (obj) {
127 PyModule_AddObject(pack, names[i], obj);
127 PyModule_AddObject(pack, names[i], obj);
128 Py_INCREF(obj);
128 Py_INCREF(obj);
129 PyModule_AddObject(pack2, names[i], obj);
129 PyModule_AddObject(pack2, names[i], obj);
130 } else {
130 } else {
131 std::cerr << "method not found " << names[i];
131 std::cerr << "method not found " << names[i];
132 }
132 }
133 }
133 }
134 }
134 }
135 }
135 }
136
136
137 void PythonQt::cleanup()
137 void PythonQt::cleanup()
138 {
138 {
139 if (_self) {
139 if (_self) {
140 delete _self;
140 delete _self;
141 _self = NULL;
141 _self = NULL;
142 }
142 }
143 }
143 }
144
144
145 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
145 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
146 {
146 {
147 _p = new PythonQtPrivate;
147 _p = new PythonQtPrivate;
148 _p->_initFlags = flags;
148 _p->_initFlags = flags;
149
149
150 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
150 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
151
151
152 Py_SetProgramName("PythonQt");
152 Py_SetProgramName("PythonQt");
153 if (flags & IgnoreSiteModule) {
153 if (flags & IgnoreSiteModule) {
154 // this prevents the automatic importing of Python site files
154 // this prevents the automatic importing of Python site files
155 Py_NoSiteFlag = 1;
155 Py_NoSiteFlag = 1;
156 }
156 }
157 Py_Initialize();
157 Py_Initialize();
158
158
159 // add our own python object types for qt object slots
159 // add our own python object types for qt object slots
160 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
160 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
161 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
161 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
162 }
162 }
163 Py_INCREF(&PythonQtSlotFunction_Type);
163 Py_INCREF(&PythonQtSlotFunction_Type);
164
164
165 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
165 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
166 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
166 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
167 // add our own python object types for classes
167 // add our own python object types for classes
168 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
168 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
169 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
169 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
170 }
170 }
171 Py_INCREF(&PythonQtClassWrapper_Type);
171 Py_INCREF(&PythonQtClassWrapper_Type);
172
172
173 // add our own python object types for CPP instances
173 // add our own python object types for CPP instances
174 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
174 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
175 PythonQt::handleError();
175 PythonQt::handleError();
176 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
176 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
177 }
177 }
178 Py_INCREF(&PythonQtInstanceWrapper_Type);
178 Py_INCREF(&PythonQtInstanceWrapper_Type);
179
179
180 // add our own python object types for redirection of stdout
180 // add our own python object types for redirection of stdout
181 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
181 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
182 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
182 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
183 }
183 }
184 Py_INCREF(&PythonQtStdOutRedirectType);
184 Py_INCREF(&PythonQtStdOutRedirectType);
185
185
186 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
186 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
187
187
188 _p->setupSharedLibrarySuffixes();
188 _p->setupSharedLibrarySuffixes();
189
189
190 }
190 }
191
191
192 PythonQt::~PythonQt() {
192 PythonQt::~PythonQt() {
193 delete _p;
193 delete _p;
194 _p = NULL;
194 _p = NULL;
195 }
195 }
196
196
197 PythonQtPrivate::~PythonQtPrivate() {
197 PythonQtPrivate::~PythonQtPrivate() {
198 delete _defaultImporter;
198 delete _defaultImporter;
199 _defaultImporter = NULL;
199 _defaultImporter = NULL;
200
200
201 {
201 {
202 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
202 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
203 while (i.hasNext()) {
203 while (i.hasNext()) {
204 delete i.next().value();
204 delete i.next().value();
205 }
205 }
206 }
206 }
207 PythonQtConv::global_valueStorage.clear();
207 PythonQtConv::global_valueStorage.clear();
208 PythonQtConv::global_ptrStorage.clear();
208 PythonQtConv::global_ptrStorage.clear();
209 PythonQtConv::global_variantStorage.clear();
209 PythonQtConv::global_variantStorage.clear();
210
210
211 PythonQtMethodInfo::cleanupCachedMethodInfos();
211 PythonQtMethodInfo::cleanupCachedMethodInfos();
212 }
212 }
213
213
214 PythonQtImportFileInterface* PythonQt::importInterface()
214 PythonQtImportFileInterface* PythonQt::importInterface()
215 {
215 {
216 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
216 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
217 }
217 }
218
218
219 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
219 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
220 {
220 {
221 if (_self->_p->_noLongerWrappedCB) {
221 if (_self->_p->_noLongerWrappedCB) {
222 (*_self->_p->_noLongerWrappedCB)(o);
222 (*_self->_p->_noLongerWrappedCB)(o);
223 };
223 };
224 }
224 }
225
225
226 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
226 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
227 {
227 {
228 _p->registerClass(metaobject, package, wrapperCreator, shell);
228 _p->registerClass(metaobject, package, wrapperCreator, shell);
229 }
229 }
230
230
231 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
231 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
232 {
232 {
233 // we register all classes in the hierarchy
233 // we register all classes in the hierarchy
234 const QMetaObject* m = metaobject;
234 const QMetaObject* m = metaobject;
235 bool first = true;
235 bool first = true;
236 while (m) {
236 while (m) {
237 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
237 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
238 if (!info->pythonQtClassWrapper()) {
238 if (!info->pythonQtClassWrapper()) {
239 info->setTypeSlots(typeSlots);
239 info->setTypeSlots(typeSlots);
240 info->setupQObject(m);
240 info->setupQObject(m);
241 createPythonQtClassWrapper(info, package, module);
241 createPythonQtClassWrapper(info, package, module);
242 if (m->superClass()) {
242 if (m->superClass()) {
243 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
243 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
244 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
244 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
245 }
245 }
246 }
246 }
247 if (first) {
247 if (first) {
248 first = false;
248 first = false;
249 if (wrapperCreator) {
249 if (wrapperCreator) {
250 info->setDecoratorProvider(wrapperCreator);
250 info->setDecoratorProvider(wrapperCreator);
251 }
251 }
252 if (shell) {
252 if (shell) {
253 info->setShellSetInstanceWrapperCB(shell);
253 info->setShellSetInstanceWrapperCB(shell);
254 }
254 }
255 }
255 }
256 m = m->superClass();
256 m = m->superClass();
257 }
257 }
258 }
258 }
259
259
260 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
260 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
261 {
261 {
262 PyObject* pack = module?module:packageByName(package);
262 PyObject* pack = module?module:packageByName(package);
263 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
263 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
264 PyModule_AddObject(pack, info->className(), pyobj);
264 PyModule_AddObject(pack, info->className(), pyobj);
265 if (!module && package && strncmp(package,"Qt",2)==0) {
265 if (!module && package && strncmp(package,"Qt",2)==0) {
266 // since PyModule_AddObject steals the reference, we need a incref once more...
266 // since PyModule_AddObject steals the reference, we need a incref once more...
267 Py_INCREF(pyobj);
267 Py_INCREF(pyobj);
268 // put all qt objects into Qt as well
268 // put all qt objects into Qt as well
269 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
269 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
270 }
270 }
271 info->setPythonQtClassWrapper(pyobj);
271 info->setPythonQtClassWrapper(pyobj);
272 }
272 }
273
273
274 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
274 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
275 {
275 {
276 if (!obj) {
276 if (!obj) {
277 Py_INCREF(Py_None);
277 Py_INCREF(Py_None);
278 return Py_None;
278 return Py_None;
279 }
279 }
280 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
280 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
281 if (!wrap) {
281 if (!wrap) {
282 // smuggling it in...
282 // smuggling it in...
283 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
283 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
284 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
284 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
285 registerClass(obj->metaObject());
285 registerClass(obj->metaObject());
286 classInfo = _knownClassInfos.value(obj->metaObject()->className());
286 classInfo = _knownClassInfos.value(obj->metaObject()->className());
287 }
287 }
288 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
288 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
289 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
289 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
290 } else {
290 } else {
291 Py_INCREF(wrap);
291 Py_INCREF(wrap);
292 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
292 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
293 }
293 }
294 return (PyObject*)wrap;
294 return (PyObject*)wrap;
295 }
295 }
296
296
297 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
297 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
298 {
298 {
299 if (!ptr) {
299 if (!ptr) {
300 Py_INCREF(Py_None);
300 Py_INCREF(Py_None);
301 return Py_None;
301 return Py_None;
302 }
302 }
303
303
304 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
304 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
305 if (!wrap) {
305 if (!wrap) {
306 PythonQtClassInfo* info = _knownClassInfos.value(name);
306 PythonQtClassInfo* info = _knownClassInfos.value(name);
307 if (!info) {
307 if (!info) {
308 // maybe it is a PyObject, which we can return directly
308 // maybe it is a PyObject, which we can return directly
309 if (name == "PyObject") {
309 if (name == "PyObject") {
310 PyObject* p = (PyObject*)ptr;
310 PyObject* p = (PyObject*)ptr;
311 Py_INCREF(p);
311 Py_INCREF(p);
312 return p;
312 return p;
313 }
313 }
314
314
315 // we do not know the metaobject yet, but we might know it by it's name:
315 // we do not know the metaobject yet, but we might know it by it's name:
316 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
316 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
317 // yes, we know it, so we can convert to QObject
317 // yes, we know it, so we can convert to QObject
318 QObject* qptr = (QObject*)ptr;
318 QObject* qptr = (QObject*)ptr;
319 registerClass(qptr->metaObject());
319 registerClass(qptr->metaObject());
320 info = _knownClassInfos.value(qptr->metaObject()->className());
320 info = _knownClassInfos.value(qptr->metaObject()->className());
321 }
321 }
322 }
322 }
323 if (info && info->isQObject()) {
323 if (info && info->isQObject()) {
324 QObject* qptr = (QObject*)ptr;
324 QObject* qptr = (QObject*)ptr;
325 // if the object is a derived object, we want to switch the class info to the one of the derived class:
325 // if the object is a derived object, we want to switch the class info to the one of the derived class:
326 if (name!=(qptr->metaObject()->className())) {
326 if (name!=(qptr->metaObject()->className())) {
327 registerClass(qptr->metaObject());
327 registerClass(qptr->metaObject());
328 info = _knownClassInfos.value(qptr->metaObject()->className());
328 info = _knownClassInfos.value(qptr->metaObject()->className());
329 }
329 }
330 wrap = createNewPythonQtInstanceWrapper(qptr, info);
330 wrap = createNewPythonQtInstanceWrapper(qptr, info);
331 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
331 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
332 return (PyObject*)wrap;
332 return (PyObject*)wrap;
333 }
333 }
334
334
335 // not a known QObject, so try our wrapper factory:
335 // not a known QObject, so try our wrapper factory:
336 QObject* wrapper = NULL;
336 QObject* wrapper = NULL;
337 for (int i=0; i<_cppWrapperFactories.size(); i++) {
337 for (int i=0; i<_cppWrapperFactories.size(); i++) {
338 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
338 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
339 if (wrapper) {
339 if (wrapper) {
340 break;
340 break;
341 }
341 }
342 }
342 }
343
343
344 if (info) {
344 if (info) {
345 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
345 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
346 ptr = info->castDownIfPossible(ptr, &info);
346 ptr = info->castDownIfPossible(ptr, &info);
347 }
347 }
348
348
349 if (!info || info->pythonQtClassWrapper()==NULL) {
349 if (!info || info->pythonQtClassWrapper()==NULL) {
350 // still unknown, register as CPP class
350 // still unknown, register as CPP class
351 registerCPPClass(name.constData());
351 registerCPPClass(name.constData());
352 info = _knownClassInfos.value(name);
352 info = _knownClassInfos.value(name);
353 }
353 }
354 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
354 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
355 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
355 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
356 info->setMetaObject(wrapper->metaObject());
356 info->setMetaObject(wrapper->metaObject());
357 }
357 }
358 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
358 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
359 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
359 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
360 } else {
360 } else {
361 Py_INCREF(wrap);
361 Py_INCREF(wrap);
362 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
362 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
363 }
363 }
364 return (PyObject*)wrap;
364 return (PyObject*)wrap;
365 }
365 }
366
366
367 PyObject* PythonQtPrivate::dummyTuple() {
367 PyObject* PythonQtPrivate::dummyTuple() {
368 static PyObject* dummyTuple = NULL;
368 static PyObject* dummyTuple = NULL;
369 if (dummyTuple==NULL) {
369 if (dummyTuple==NULL) {
370 dummyTuple = PyTuple_New(1);
370 dummyTuple = PyTuple_New(1);
371 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
371 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
372 }
372 }
373 return dummyTuple;
373 return dummyTuple;
374 }
374 }
375
375
376
376
377 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
377 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
378 // call the associated class type to create a new instance...
378 // call the associated class type to create a new instance...
379 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
379 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
380
380
381 result->setQObject(obj);
381 result->setQObject(obj);
382 result->_wrappedPtr = wrappedPtr;
382 result->_wrappedPtr = wrappedPtr;
383 result->_ownedByPythonQt = false;
383 result->_ownedByPythonQt = false;
384 result->_useQMetaTypeDestroy = false;
384 result->_useQMetaTypeDestroy = false;
385
385
386 if (wrappedPtr) {
386 if (wrappedPtr) {
387 _wrappedObjects.insert(wrappedPtr, result);
387 _wrappedObjects.insert(wrappedPtr, result);
388 } else {
388 } else {
389 _wrappedObjects.insert(obj, result);
389 _wrappedObjects.insert(obj, result);
390 if (obj->parent()== NULL && _wrappedCB) {
390 if (obj->parent()== NULL && _wrappedCB) {
391 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
391 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
392 (*_wrappedCB)(obj);
392 (*_wrappedCB)(obj);
393 }
393 }
394 }
394 }
395 return result;
395 return result;
396 }
396 }
397
397
398 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
398 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
399 PythonQtClassWrapper* result;
399 PythonQtClassWrapper* result;
400
400
401 PyObject* className = PyString_FromString(info->className());
401 PyObject* className = PyString_FromString(info->className());
402
402
403 PyObject* baseClasses = PyTuple_New(1);
403 PyObject* baseClasses = PyTuple_New(1);
404 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
404 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
405
405
406 PyObject* typeDict = PyDict_New();
406 PyObject* typeDict = PyDict_New();
407 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
407 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
408 PyDict_SetItemString(typeDict, "__module__", moduleName);
408 PyDict_SetItemString(typeDict, "__module__", moduleName);
409
409
410 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
410 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
411
411
412 // set the class info so that PythonQtClassWrapper_new can read it
412 // set the class info so that PythonQtClassWrapper_new can read it
413 _currentClassInfoForClassWrapperCreation = info;
413 _currentClassInfoForClassWrapperCreation = info;
414 // create the new type object by calling the type
414 // create the new type object by calling the type
415 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
415 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
416
416
417 Py_DECREF(baseClasses);
417 Py_DECREF(baseClasses);
418 Py_DECREF(typeDict);
418 Py_DECREF(typeDict);
419 Py_DECREF(args);
419 Py_DECREF(args);
420 Py_DECREF(className);
420 Py_DECREF(className);
421
421
422 return result;
422 return result;
423 }
423 }
424
424
425 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
425 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
426 {
426 {
427 PyObject* args = Py_BuildValue("(i)", enumValue);
427 PyObject* args = Py_BuildValue("(i)", enumValue);
428 PyObject* result = PyObject_Call(enumType, args, NULL);
428 PyObject* result = PyObject_Call(enumType, args, NULL);
429 Py_DECREF(args);
429 Py_DECREF(args);
430 return result;
430 return result;
431 }
431 }
432
432
433 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
433 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
434 PyObject* result;
434 PyObject* result;
435
435
436 PyObject* className = PyString_FromString(enumName);
436 PyObject* className = PyString_FromString(enumName);
437
437
438 PyObject* baseClasses = PyTuple_New(1);
438 PyObject* baseClasses = PyTuple_New(1);
439 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
439 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
440
440
441 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
441 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
442 PyObject* typeDict = PyDict_New();
442 PyObject* typeDict = PyDict_New();
443 PyDict_SetItemString(typeDict, "__module__", module);
443 PyDict_SetItemString(typeDict, "__module__", module);
444
444
445 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
445 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
446
446
447 // create the new int derived type object by calling the core type
447 // create the new int derived type object by calling the core type
448 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
448 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
449
449
450 Py_DECREF(baseClasses);
450 Py_DECREF(baseClasses);
451 Py_DECREF(typeDict);
451 Py_DECREF(typeDict);
452 Py_DECREF(args);
452 Py_DECREF(args);
453 Py_DECREF(className);
453 Py_DECREF(className);
454
454
455 return result;
455 return result;
456 }
456 }
457
457
458 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
458 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
459 {
459 {
460 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
460 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
461 if (!r) {
461 if (!r) {
462 r = new PythonQtSignalReceiver(obj);
462 r = new PythonQtSignalReceiver(obj);
463 _p->_signalReceivers.insert(obj, r);
463 _p->_signalReceivers.insert(obj, r);
464 }
464 }
465 return r;
465 return r;
466 }
466 }
467
467
468 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
468 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
469 {
469 {
470 bool flag = false;
470 bool flag = false;
471 PythonQtObjectPtr callable = lookupCallable(module, objectname);
471 PythonQtObjectPtr callable = lookupCallable(module, objectname);
472 if (callable) {
472 if (callable) {
473 PythonQtSignalReceiver* r = getSignalReceiver(obj);
473 PythonQtSignalReceiver* r = getSignalReceiver(obj);
474 flag = r->addSignalHandler(signal, callable);
474 flag = r->addSignalHandler(signal, callable);
475 if (!flag) {
475 if (!flag) {
476 // signal not found
476 // signal not found
477 }
477 }
478 } else {
478 } else {
479 // callable not found
479 // callable not found
480 }
480 }
481 return flag;
481 return flag;
482 }
482 }
483
483
484 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
484 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
485 {
485 {
486 bool flag = false;
486 bool flag = false;
487 PythonQtSignalReceiver* r = getSignalReceiver(obj);
487 PythonQtSignalReceiver* r = getSignalReceiver(obj);
488 if (r) {
488 if (r) {
489 flag = r->addSignalHandler(signal, receiver);
489 flag = r->addSignalHandler(signal, receiver);
490 }
490 }
491 return flag;
491 return flag;
492 }
492 }
493
493
494 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
494 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
495 {
495 {
496 bool flag = false;
496 bool flag = false;
497 PythonQtObjectPtr callable = lookupCallable(module, objectname);
497 PythonQtObjectPtr callable = lookupCallable(module, objectname);
498 if (callable) {
498 if (callable) {
499 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
499 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
500 if (r) {
500 if (r) {
501 flag = r->removeSignalHandler(signal, callable);
501 flag = r->removeSignalHandler(signal, callable);
502 }
502 }
503 } else {
503 } else {
504 // callable not found
504 // callable not found
505 }
505 }
506 return flag;
506 return flag;
507 }
507 }
508
508
509 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
509 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
510 {
510 {
511 bool flag = false;
511 bool flag = false;
512 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
512 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
513 if (r) {
513 if (r) {
514 flag = r->removeSignalHandler(signal, receiver);
514 flag = r->removeSignalHandler(signal, receiver);
515 }
515 }
516 return flag;
516 return flag;
517 }
517 }
518
518
519 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
519 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
520 {
520 {
521 PythonQtObjectPtr p = lookupObject(module, name);
521 PythonQtObjectPtr p = lookupObject(module, name);
522 if (p) {
522 if (p) {
523 if (PyCallable_Check(p)) {
523 if (PyCallable_Check(p)) {
524 return p;
524 return p;
525 }
525 }
526 }
526 }
527 PyErr_Clear();
527 PyErr_Clear();
528 return NULL;
528 return NULL;
529 }
529 }
530
530
531 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
531 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
532 {
532 {
533 QStringList l = name.split('.');
533 QStringList l = name.split('.');
534 PythonQtObjectPtr p = module;
534 PythonQtObjectPtr p = module;
535 PythonQtObjectPtr prev;
535 PythonQtObjectPtr prev;
536 QString s;
536 QString s;
537 QByteArray b;
537 QByteArray b;
538 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
538 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
539 prev = p;
539 prev = p;
540 b = (*i).toLatin1();
540 b = (*i).toLatin1();
541 if (PyDict_Check(p)) {
541 if (PyDict_Check(p)) {
542 p = PyDict_GetItemString(p, b.data());
542 p = PyDict_GetItemString(p, b.data());
543 } else {
543 } else {
544 p.setNewRef(PyObject_GetAttrString(p, b.data()));
544 p.setNewRef(PyObject_GetAttrString(p, b.data()));
545 }
545 }
546 }
546 }
547 PyErr_Clear();
547 PyErr_Clear();
548 return p;
548 return p;
549 }
549 }
550
550
551 PythonQtObjectPtr PythonQt::getMainModule() {
551 PythonQtObjectPtr PythonQt::getMainModule() {
552 //both borrowed
552 //both borrowed
553 PythonQtObjectPtr dict = PyImport_GetModuleDict();
553 PythonQtObjectPtr dict = PyImport_GetModuleDict();
554 return PyDict_GetItemString(dict, "__main__");
554 return PyDict_GetItemString(dict, "__main__");
555 }
555 }
556
556
557 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
557 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
558 QVariant result;
558 QVariant result;
559 if (pycode) {
559 if (pycode) {
560 PyObject* dict = NULL;
560 PyObject* dict = NULL;
561 if (PyModule_Check(object)) {
561 if (PyModule_Check(object)) {
562 dict = PyModule_GetDict(object);
562 dict = PyModule_GetDict(object);
563 } else if (PyDict_Check(object)) {
563 } else if (PyDict_Check(object)) {
564 dict = object;
564 dict = object;
565 }
565 }
566 PyObject* r = NULL;
566 PyObject* r = NULL;
567 if (dict) {
567 if (dict) {
568 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
568 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
569 }
569 }
570 if (r) {
570 if (r) {
571 result = PythonQtConv::PyObjToQVariant(r);
571 result = PythonQtConv::PyObjToQVariant(r);
572 Py_DECREF(r);
572 Py_DECREF(r);
573 } else {
573 } else {
574 handleError();
574 handleError();
575 }
575 }
576 } else {
576 } else {
577 handleError();
577 handleError();
578 }
578 }
579 return result;
579 return result;
580 }
580 }
581
581
582 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
582 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
583 {
583 {
584 QVariant result;
584 QVariant result;
585 PythonQtObjectPtr p;
585 PythonQtObjectPtr p;
586 PyObject* dict = NULL;
586 PyObject* dict = NULL;
587 if (PyModule_Check(object)) {
587 if (PyModule_Check(object)) {
588 dict = PyModule_GetDict(object);
588 dict = PyModule_GetDict(object);
589 } else if (PyDict_Check(object)) {
589 } else if (PyDict_Check(object)) {
590 dict = object;
590 dict = object;
591 }
591 }
592 if (dict) {
592 if (dict) {
593 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
593 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
594 }
594 }
595 if (p) {
595 if (p) {
596 result = PythonQtConv::PyObjToQVariant(p);
596 result = PythonQtConv::PyObjToQVariant(p);
597 } else {
597 } else {
598 handleError();
598 handleError();
599 }
599 }
600 return result;
600 return result;
601 }
601 }
602
602
603 void PythonQt::evalFile(PyObject* module, const QString& filename)
603 void PythonQt::evalFile(PyObject* module, const QString& filename)
604 {
604 {
605 PythonQtObjectPtr code = parseFile(filename);
605 PythonQtObjectPtr code = parseFile(filename);
606 if (code) {
606 if (code) {
607 evalCode(module, code);
607 evalCode(module, code);
608 } else {
608 } else {
609 handleError();
609 handleError();
610 }
610 }
611 }
611 }
612
612
613 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
613 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
614 {
614 {
615 PythonQtObjectPtr p;
615 PythonQtObjectPtr p;
616 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
616 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
617 if (!p) {
617 if (!p) {
618 handleError();
618 handleError();
619 }
619 }
620 return p;
620 return p;
621 }
621 }
622
622
623 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
623 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
624 {
624 {
625 PythonQtObjectPtr code = parseFile(filename);
625 PythonQtObjectPtr code = parseFile(filename);
626 PythonQtObjectPtr module = _p->createModule(name, code);
626 PythonQtObjectPtr module = _p->createModule(name, code);
627 return module;
627 return module;
628 }
628 }
629
629
630 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
630 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
631 {
631 {
632 PyErr_Clear();
632 PyErr_Clear();
633 QString scriptCode = script;
633 QString scriptCode = script;
634 if (scriptCode.isEmpty()) {
634 if (scriptCode.isEmpty()) {
635 // we always need at least a linefeed
635 // we always need at least a linefeed
636 scriptCode = "\n";
636 scriptCode = "\n";
637 }
637 }
638 PythonQtObjectPtr pycode;
638 PythonQtObjectPtr pycode;
639 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
639 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
640 PythonQtObjectPtr module = _p->createModule(name, pycode);
640 PythonQtObjectPtr module = _p->createModule(name, pycode);
641 return module;
641 return module;
642 }
642 }
643
643
644 PythonQtObjectPtr PythonQt::createUniqueModule()
644 PythonQtObjectPtr PythonQt::createUniqueModule()
645 {
645 {
646 static QString pyQtStr("PythonQt_module");
646 static QString pyQtStr("PythonQt_module");
647 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
647 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
648 return createModuleFromScript(moduleName);
648 return createModuleFromScript(moduleName);
649 }
649 }
650
650
651 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
651 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
652 {
652 {
653 if (PyModule_Check(object)) {
653 if (PyModule_Check(object)) {
654 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
654 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
655 } else if (PyDict_Check(object)) {
655 } else if (PyDict_Check(object)) {
656 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
656 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
657 } else {
657 } else {
658 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
658 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
659 }
659 }
660 }
660 }
661
661
662 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
662 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
663 {
663 {
664 if (PyModule_Check(object)) {
664 if (PyModule_Check(object)) {
665 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
665 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
666 } else if (PyDict_Check(object)) {
666 } else if (PyDict_Check(object)) {
667 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
667 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
668 } else {
668 } else {
669 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
669 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
670 }
670 }
671 }
671 }
672
672
673 void PythonQt::removeVariable(PyObject* object, const QString& name)
673 void PythonQt::removeVariable(PyObject* object, const QString& name)
674 {
674 {
675 if (PyDict_Check(object)) {
675 if (PyDict_Check(object)) {
676 PyDict_DelItemString(object, name.toLatin1().data());
676 PyDict_DelItemString(object, name.toLatin1().data());
677 } else {
677 } else {
678 PyObject_DelAttrString(object, name.toLatin1().data());
678 PyObject_DelAttrString(object, name.toLatin1().data());
679 }
679 }
680 }
680 }
681
681
682 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
682 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
683 {
683 {
684 QVariant result;
684 QVariant result;
685 PythonQtObjectPtr obj = lookupObject(object, objectname);
685 PythonQtObjectPtr obj = lookupObject(object, objectname);
686 if (obj) {
686 if (obj) {
687 result = PythonQtConv::PyObjToQVariant(obj);
687 result = PythonQtConv::PyObjToQVariant(obj);
688 }
688 }
689 return result;
689 return result;
690 }
690 }
691
691
692 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
692 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
693 {
693 {
694 QStringList results;
694 QStringList results;
695
695
696 PythonQtObjectPtr object;
696 PythonQtObjectPtr object;
697 if (objectname.isEmpty()) {
697 if (objectname.isEmpty()) {
698 object = module;
698 object = module;
699 } else {
699 } else {
700 object = lookupObject(module, objectname);
700 object = lookupObject(module, objectname);
701 if (!object && type == CallOverloads) {
701 if (!object && type == CallOverloads) {
702 PyObject* dict = lookupObject(module, "__builtins__");
702 PyObject* dict = lookupObject(module, "__builtins__");
703 if (dict) {
703 if (dict) {
704 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
704 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
705 }
705 }
706 }
706 }
707 }
707 }
708
708
709 if (object) {
709 if (object) {
710 if (type == CallOverloads) {
710 if (type == CallOverloads) {
711 if (PythonQtSlotFunction_Check(object)) {
711 if (PythonQtSlotFunction_Check(object)) {
712 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
712 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
713 PythonQtSlotInfo* info = o->m_ml;
713 PythonQtSlotInfo* info = o->m_ml;
714
714
715 while (info) {
715 while (info) {
716 results << info->fullSignature();
716 results << info->fullSignature();
717 info = info->nextInfo();
717 info = info->nextInfo();
718 }
718 }
719 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
719 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
720 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
720 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
721 PythonQtSlotInfo* info = o->classInfo()->constructors();
721 PythonQtSlotInfo* info = o->classInfo()->constructors();
722
722
723 while (info) {
723 while (info) {
724 results << info->fullSignature();
724 results << info->fullSignature();
725 info = info->nextInfo();
725 info = info->nextInfo();
726 }
726 }
727 } else {
727 } else {
728 //TODO: use pydoc!
728 //TODO: use pydoc!
729 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
729 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
730 if (doc) {
730 if (doc) {
731 results << PyString_AsString(doc);
731 results << PyString_AsString(doc);
732 Py_DECREF(doc);
732 Py_DECREF(doc);
733 }
733 }
734 }
734 }
735 } else {
735 } else {
736 PyObject* keys = NULL;
736 PyObject* keys = NULL;
737 bool isDict = false;
737 bool isDict = false;
738 if (PyDict_Check(object)) {
738 if (PyDict_Check(object)) {
739 keys = PyDict_Keys(object);
739 keys = PyDict_Keys(object);
740 isDict = true;
740 isDict = true;
741 } else {
741 } else {
742 keys = PyObject_Dir(object);
742 keys = PyObject_Dir(object);
743 }
743 }
744 if (keys) {
744 if (keys) {
745 int count = PyList_Size(keys);
745 int count = PyList_Size(keys);
746 PyObject* key;
746 PyObject* key;
747 PyObject* value;
747 PyObject* value;
748 QString keystr;
748 QString keystr;
749 for (int i = 0;i<count;i++) {
749 for (int i = 0;i<count;i++) {
750 key = PyList_GetItem(keys,i);
750 key = PyList_GetItem(keys,i);
751 if (isDict) {
751 if (isDict) {
752 value = PyDict_GetItem(object, key);
752 value = PyDict_GetItem(object, key);
753 Py_INCREF(value);
753 Py_INCREF(value);
754 } else {
754 } else {
755 value = PyObject_GetAttr(object, key);
755 value = PyObject_GetAttr(object, key);
756 }
756 }
757 if (!value) continue;
757 if (!value) continue;
758 keystr = PyString_AsString(key);
758 keystr = PyString_AsString(key);
759 static const QString underscoreStr("__tmp");
759 static const QString underscoreStr("__tmp");
760 if (!keystr.startsWith(underscoreStr)) {
760 if (!keystr.startsWith(underscoreStr)) {
761 switch (type) {
761 switch (type) {
762 case Anything:
762 case Anything:
763 results << keystr;
763 results << keystr;
764 break;
764 break;
765 case Class:
765 case Class:
766 if (value->ob_type == &PyClass_Type) {
766 if (value->ob_type == &PyClass_Type) {
767 results << keystr;
767 results << keystr;
768 }
768 }
769 break;
769 break;
770 case Variable:
770 case Variable:
771 if (value->ob_type != &PyClass_Type
771 if (value->ob_type != &PyClass_Type
772 && value->ob_type != &PyCFunction_Type
772 && value->ob_type != &PyCFunction_Type
773 && value->ob_type != &PyFunction_Type
773 && value->ob_type != &PyFunction_Type
774 && value->ob_type != &PyModule_Type
774 && value->ob_type != &PyModule_Type
775 ) {
775 ) {
776 results << keystr;
776 results << keystr;
777 }
777 }
778 break;
778 break;
779 case Function:
779 case Function:
780 if (value->ob_type == &PyFunction_Type ||
780 if (value->ob_type == &PyFunction_Type ||
781 value->ob_type == &PyMethod_Type
781 value->ob_type == &PyMethod_Type
782 ) {
782 ) {
783 results << keystr;
783 results << keystr;
784 }
784 }
785 break;
785 break;
786 case Module:
786 case Module:
787 if (value->ob_type == &PyModule_Type) {
787 if (value->ob_type == &PyModule_Type) {
788 results << keystr;
788 results << keystr;
789 }
789 }
790 break;
790 break;
791 default:
791 default:
792 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
792 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
793 }
793 }
794 }
794 }
795 Py_DECREF(value);
795 Py_DECREF(value);
796 }
796 }
797 Py_DECREF(keys);
797 Py_DECREF(keys);
798 }
798 }
799 }
799 }
800 }
800 }
801 return results;
801 return results;
802 }
802 }
803
803
804 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
804 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
805 {
805 {
806 PythonQtObjectPtr callable = lookupCallable(object, name);
806 PythonQtObjectPtr callable = lookupCallable(object, name);
807 if (callable) {
807 if (callable) {
808 return call(callable, args);
808 return call(callable, args);
809 } else {
809 } else {
810 return QVariant();
810 return QVariant();
811 }
811 }
812 }
812 }
813
813
814 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
814 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
815 {
815 {
816 QVariant r;
816 QVariant r;
817 PythonQtObjectPtr result;
817 PythonQtObjectPtr result;
818 result.setNewRef(callAndReturnPyObject(callable, args));
818 result.setNewRef(callAndReturnPyObject(callable, args));
819 if (result) {
819 if (result) {
820 r = PythonQtConv::PyObjToQVariant(result);
820 r = PythonQtConv::PyObjToQVariant(result);
821 } else {
821 } else {
822 PythonQt::self()->handleError();
822 PythonQt::self()->handleError();
823 }
823 }
824 return r;
824 return r;
825 }
825 }
826
826
827 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
827 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
828 {
828 {
829 PyObject* result = NULL;
829 PyObject* result = NULL;
830 if (callable) {
830 if (callable) {
831 PythonQtObjectPtr pargs;
831 PythonQtObjectPtr pargs;
832 int count = args.size();
832 int count = args.size();
833 if (count>0) {
833 if (count>0) {
834 pargs.setNewRef(PyTuple_New(count));
834 pargs.setNewRef(PyTuple_New(count));
835 }
835 }
836 bool err = false;
836 bool err = false;
837 // transform QVariants to Python
837 // transform QVariants to Python
838 for (int i = 0; i < count; i++) {
838 for (int i = 0; i < count; i++) {
839 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
839 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
840 if (arg) {
840 if (arg) {
841 // steals reference, no unref
841 // steals reference, no unref
842 PyTuple_SetItem(pargs, i,arg);
842 PyTuple_SetItem(pargs, i,arg);
843 } else {
843 } else {
844 err = true;
844 err = true;
845 break;
845 break;
846 }
846 }
847 }
847 }
848
848
849 if (!err) {
849 if (!err) {
850 PyErr_Clear();
850 PyErr_Clear();
851 result = PyObject_CallObject(callable, pargs);
851 result = PyObject_CallObject(callable, pargs);
852 }
852 }
853 }
853 }
854 return result;
854 return result;
855 }
855 }
856
856
857 void PythonQt::addInstanceDecorators(QObject* o)
857 void PythonQt::addInstanceDecorators(QObject* o)
858 {
858 {
859 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
859 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
860 }
860 }
861
861
862 void PythonQt::addClassDecorators(QObject* o)
862 void PythonQt::addClassDecorators(QObject* o)
863 {
863 {
864 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
864 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
865 }
865 }
866
866
867 void PythonQt::addDecorators(QObject* o)
867 void PythonQt::addDecorators(QObject* o)
868 {
868 {
869 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
869 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
870 }
870 }
871
871
872 void PythonQt::registerQObjectClassNames(const QStringList& names)
872 void PythonQt::registerQObjectClassNames(const QStringList& names)
873 {
873 {
874 _p->registerQObjectClassNames(names);
874 _p->registerQObjectClassNames(names);
875 }
875 }
876
876
877 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
877 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
878 {
878 {
879 _p->_importInterface = importInterface;
879 _p->_importInterface = importInterface;
880 PythonQtImport::init();
880 PythonQtImport::init();
881 }
881 }
882
882
883 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
883 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
884 {
884 {
885 _p->_importIgnorePaths = paths;
885 _p->_importIgnorePaths = paths;
886 }
886 }
887
887
888 const QStringList& PythonQt::getImporterIgnorePaths()
888 const QStringList& PythonQt::getImporterIgnorePaths()
889 {
889 {
890 return _p->_importIgnorePaths;
890 return _p->_importIgnorePaths;
891 }
891 }
892
892
893 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
893 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
894 {
894 {
895 _p->_cppWrapperFactories.append(factory);
895 _p->_cppWrapperFactories.append(factory);
896 }
896 }
897
897
898 //---------------------------------------------------------------------------------------------------
898 //---------------------------------------------------------------------------------------------------
899 PythonQtPrivate::PythonQtPrivate()
899 PythonQtPrivate::PythonQtPrivate()
900 {
900 {
901 _importInterface = NULL;
901 _importInterface = NULL;
902 _defaultImporter = new PythonQtQFileImporter;
902 _defaultImporter = new PythonQtQFileImporter;
903 _noLongerWrappedCB = NULL;
903 _noLongerWrappedCB = NULL;
904 _wrappedCB = NULL;
904 _wrappedCB = NULL;
905 _currentClassInfoForClassWrapperCreation = NULL;
905 _currentClassInfoForClassWrapperCreation = NULL;
906 }
906 }
907
907
908 void PythonQtPrivate::setupSharedLibrarySuffixes()
908 void PythonQtPrivate::setupSharedLibrarySuffixes()
909 {
909 {
910 _sharedLibrarySuffixes.clear();
910 _sharedLibrarySuffixes.clear();
911 PythonQtObjectPtr imp;
911 PythonQtObjectPtr imp;
912 imp.setNewRef(PyImport_ImportModule("imp"));
912 imp.setNewRef(PyImport_ImportModule("imp"));
913 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
913 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
914 QVariant result = imp.call("get_suffixes");
914 QVariant result = imp.call("get_suffixes");
915 foreach (QVariant entry, result.toList()) {
915 foreach (QVariant entry, result.toList()) {
916 QVariantList suffixEntry = entry.toList();
916 QVariantList suffixEntry = entry.toList();
917 if (suffixEntry.count()==3) {
917 if (suffixEntry.count()==3) {
918 int code = suffixEntry.at(2).toInt();
918 int code = suffixEntry.at(2).toInt();
919 if (code == cExtensionCode) {
919 if (code == cExtensionCode) {
920 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
920 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
921 }
921 }
922 }
922 }
923 }
923 }
924 }
924 }
925
925
926 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
926 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
927 {
927 {
928 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
928 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
929 _currentClassInfoForClassWrapperCreation = NULL;
929 _currentClassInfoForClassWrapperCreation = NULL;
930 return info;
930 return info;
931 }
931 }
932
932
933 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
933 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
934 {
934 {
935 o->setParent(this);
935 o->setParent(this);
936 int numMethods = o->metaObject()->methodCount();
936 int numMethods = o->metaObject()->methodCount();
937 for (int i = 0; i < numMethods; i++) {
937 for (int i = 0; i < numMethods; i++) {
938 QMetaMethod m = o->metaObject()->method(i);
938 QMetaMethod m = o->metaObject()->method(i);
939 if ((m.methodType() == QMetaMethod::Method ||
939 if ((m.methodType() == QMetaMethod::Method ||
940 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
940 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
941 if (qstrncmp(m.signature(), "new_", 4)==0) {
941 if (qstrncmp(m.signature(), "new_", 4)==0) {
942 if ((decoTypes & ConstructorDecorator) == 0) continue;
942 if ((decoTypes & ConstructorDecorator) == 0) continue;
943 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
943 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
944 if (info->parameters().at(0).isPointer) {
944 if (info->parameters().at(0).isPointer) {
945 QByteArray signature = m.signature();
945 QByteArray signature = m.signature();
946 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
946 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
947 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
947 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
948 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
948 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
949 classInfo->addConstructor(newSlot);
949 classInfo->addConstructor(newSlot);
950 }
950 }
951 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
951 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
952 if ((decoTypes & DestructorDecorator) == 0) continue;
952 if ((decoTypes & DestructorDecorator) == 0) continue;
953 QByteArray signature = m.signature();
953 QByteArray signature = m.signature();
954 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
954 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
955 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
955 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
956 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
956 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
957 classInfo->setDestructor(newSlot);
957 classInfo->setDestructor(newSlot);
958 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
958 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
959 if ((decoTypes & StaticDecorator) == 0) continue;
959 if ((decoTypes & StaticDecorator) == 0) continue;
960 QByteArray signature = m.signature();
960 QByteArray signature = m.signature();
961 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
961 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
962 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
962 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
963 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
963 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
964 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
964 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
965 classInfo->addDecoratorSlot(newSlot);
965 classInfo->addDecoratorSlot(newSlot);
966 } else {
966 } else {
967 if ((decoTypes & InstanceDecorator) == 0) continue;
967 if ((decoTypes & InstanceDecorator) == 0) continue;
968 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
968 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
969 if (info->parameters().count()>1) {
969 if (info->parameters().count()>1) {
970 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
970 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
971 if (p.isPointer) {
971 if (p.isPointer) {
972 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
972 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
973 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
973 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
974 classInfo->addDecoratorSlot(newSlot);
974 classInfo->addDecoratorSlot(newSlot);
975 }
975 }
976 }
976 }
977 }
977 }
978 }
978 }
979 }
979 }
980 }
980 }
981
981
982 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
982 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
983 {
983 {
984 foreach(QString name, names) {
984 foreach(QString name, names) {
985 _knownQObjectClassNames.insert(name.toLatin1(), true);
985 _knownQObjectClassNames.insert(name.toLatin1(), true);
986 }
986 }
987 }
987 }
988
988
989 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
989 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
990 {
990 {
991 _signalReceivers.remove(obj);
991 _signalReceivers.remove(obj);
992 }
992 }
993
993
994 bool PythonQt::handleError()
994 bool PythonQt::handleError()
995 {
995 {
996 bool flag = false;
996 bool flag = false;
997 if (PyErr_Occurred()) {
997 if (PyErr_Occurred()) {
998
998
999 // currently we just print the error and the stderr handler parses the errors
999 // currently we just print the error and the stderr handler parses the errors
1000 PyErr_Print();
1000 PyErr_Print();
1001
1001
1002 /*
1002 /*
1003 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1003 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1004 PyObject *ptype;
1004 PyObject *ptype;
1005 PyObject *pvalue;
1005 PyObject *pvalue;
1006 PyObject *ptraceback;
1006 PyObject *ptraceback;
1007 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1007 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1008
1008
1009 Py_XDECREF(ptype);
1009 Py_XDECREF(ptype);
1010 Py_XDECREF(pvalue);
1010 Py_XDECREF(pvalue);
1011 Py_XDECREF(ptraceback);
1011 Py_XDECREF(ptraceback);
1012 */
1012 */
1013 PyErr_Clear();
1013 PyErr_Clear();
1014 flag = true;
1014 flag = true;
1015 }
1015 }
1016 return flag;
1016 return flag;
1017 }
1017 }
1018
1018
1019 void PythonQt::addSysPath(const QString& path)
1019 void PythonQt::addSysPath(const QString& path)
1020 {
1020 {
1021 PythonQtObjectPtr sys;
1021 PythonQtObjectPtr sys;
1022 sys.setNewRef(PyImport_ImportModule("sys"));
1022 sys.setNewRef(PyImport_ImportModule("sys"));
1023 PythonQtObjectPtr obj = lookupObject(sys, "path");
1023 PythonQtObjectPtr obj = lookupObject(sys, "path");
1024 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1024 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1025 }
1025 }
1026
1026
1027 void PythonQt::overwriteSysPath(const QStringList& paths)
1027 void PythonQt::overwriteSysPath(const QStringList& paths)
1028 {
1028 {
1029 PythonQtObjectPtr sys;
1029 PythonQtObjectPtr sys;
1030 sys.setNewRef(PyImport_ImportModule("sys"));
1030 sys.setNewRef(PyImport_ImportModule("sys"));
1031 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1031 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1032 }
1032 }
1033
1033
1034 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1034 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1035 {
1035 {
1036 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1036 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1037 }
1037 }
1038
1038
1039 void PythonQt::stdOutRedirectCB(const QString& str)
1039 void PythonQt::stdOutRedirectCB(const QString& str)
1040 {
1040 {
1041 emit PythonQt::self()->pythonStdOut(str);
1041 emit PythonQt::self()->pythonStdOut(str);
1042 }
1042 }
1043
1043
1044 void PythonQt::stdErrRedirectCB(const QString& str)
1044 void PythonQt::stdErrRedirectCB(const QString& str)
1045 {
1045 {
1046 emit PythonQt::self()->pythonStdErr(str);
1046 emit PythonQt::self()->pythonStdErr(str);
1047 }
1047 }
1048
1048
1049 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1049 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1050 {
1050 {
1051 _p->_wrappedCB = cb;
1051 _p->_wrappedCB = cb;
1052 }
1052 }
1053
1053
1054 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1054 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1055 {
1055 {
1056 _p->_noLongerWrappedCB = cb;
1056 _p->_noLongerWrappedCB = cb;
1057 }
1057 }
1058
1058
1059
1059
1060
1060
1061 static PyMethodDef PythonQtMethods[] = {
1061 static PyMethodDef PythonQtMethods[] = {
1062 {NULL, NULL, 0, NULL}
1062 {NULL, NULL, 0, NULL}
1063 };
1063 };
1064
1064
1065 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1065 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1066 {
1066 {
1067 QByteArray name = "PythonQt";
1067 QByteArray name = "PythonQt";
1068 if (!pythonQtModuleName.isEmpty()) {
1068 if (!pythonQtModuleName.isEmpty()) {
1069 name = pythonQtModuleName;
1069 name = pythonQtModuleName;
1070 }
1070 }
1071 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1071 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1072 _p->_pythonQtModuleName = name;
1072 _p->_pythonQtModuleName = name;
1073
1073
1074 if (redirectStdOut) {
1074 if (redirectStdOut) {
1075 PythonQtObjectPtr sys;
1075 PythonQtObjectPtr sys;
1076 PythonQtObjectPtr out;
1076 PythonQtObjectPtr out;
1077 PythonQtObjectPtr err;
1077 PythonQtObjectPtr err;
1078 sys.setNewRef(PyImport_ImportModule("sys"));
1078 sys.setNewRef(PyImport_ImportModule("sys"));
1079 // create a redirection object for stdout and stderr
1079 // create a redirection object for stdout and stderr
1080 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1080 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1081 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1081 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1082 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1082 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1083 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1083 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1084 // replace the built in file objects with our own objects
1084 // replace the built in file objects with our own objects
1085 PyModule_AddObject(sys, "stdout", out);
1085 PyModule_AddObject(sys, "stdout", out);
1086 PyModule_AddObject(sys, "stderr", err);
1086 PyModule_AddObject(sys, "stderr", err);
1087 }
1087 }
1088 }
1088 }
1089
1089
1090 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1090 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1091 {
1091 {
1092 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1092 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1093 }
1093 }
1094
1094
1095
1095
1096 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1096 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1097 {
1097 {
1098 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1098 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1099 if (!info) {
1099 if (!info) {
1100 info = new PythonQtClassInfo();
1100 info = new PythonQtClassInfo();
1101 info->setupCPPObject(typeName);
1101 info->setupCPPObject(typeName);
1102 _knownClassInfos.insert(typeName, info);
1102 _knownClassInfos.insert(typeName, info);
1103 }
1103 }
1104 return info;
1104 return info;
1105 }
1105 }
1106
1106
1107 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1107 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1108 {
1108 {
1109 _p->addPolymorphicHandler(typeName, cb);
1109 _p->addPolymorphicHandler(typeName, cb);
1110 }
1110 }
1111
1111
1112 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1112 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1113 {
1113 {
1114 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1114 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1115 info->addPolymorphicHandler(cb);
1115 info->addPolymorphicHandler(cb);
1116 }
1116 }
1117
1117
1118 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1118 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1119 {
1119 {
1120 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1120 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1121 }
1121 }
1122
1122
1123 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1123 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1124 {
1124 {
1125 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1125 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1126 if (info) {
1126 if (info) {
1127 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1127 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1128 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1128 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1129 return true;
1129 return true;
1130 } else {
1130 } else {
1131 return false;
1131 return false;
1132 }
1132 }
1133 }
1133 }
1134
1134
1135 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1135 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1136 {
1136 {
1137 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1137 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1138 if (!info->pythonQtClassWrapper()) {
1138 if (!info->pythonQtClassWrapper()) {
1139 info->setTypeSlots(typeSlots);
1139 info->setTypeSlots(typeSlots);
1140 info->setupCPPObject(typeName);
1140 info->setupCPPObject(typeName);
1141 createPythonQtClassWrapper(info, package, module);
1141 createPythonQtClassWrapper(info, package, module);
1142 }
1142 }
1143 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1143 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1144 addParentClass(typeName, parentTypeName, 0);
1144 addParentClass(typeName, parentTypeName, 0);
1145 }
1145 }
1146 if (wrapperCreator) {
1146 if (wrapperCreator) {
1147 info->setDecoratorProvider(wrapperCreator);
1147 info->setDecoratorProvider(wrapperCreator);
1148 }
1148 }
1149 if (shell) {
1149 if (shell) {
1150 info->setShellSetInstanceWrapperCB(shell);
1150 info->setShellSetInstanceWrapperCB(shell);
1151 }
1151 }
1152 }
1152 }
1153
1153
1154 PyObject* PythonQtPrivate::packageByName(const char* name)
1154 PyObject* PythonQtPrivate::packageByName(const char* name)
1155 {
1155 {
1156 if (name==NULL || name[0]==0) {
1156 if (name==NULL || name[0]==0) {
1157 name = "private";
1157 name = "private";
1158 }
1158 }
1159 PyObject* v = _packages.value(name);
1159 PyObject* v = _packages.value(name);
1160 if (!v) {
1160 if (!v) {
1161 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1161 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1162 _packages.insert(name, v);
1162 _packages.insert(name, v);
1163 // AddObject steals the reference, so increment it!
1163 // AddObject steals the reference, so increment it!
1164 Py_INCREF(v);
1164 Py_INCREF(v);
1165 PyModule_AddObject(_pythonQtModule, name, v);
1165 PyModule_AddObject(_pythonQtModule, name, v);
1166 }
1166 }
1167 return v;
1167 return v;
1168 }
1168 }
1169
1169
1170 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1170 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1171 {
1171 {
1172 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1172 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1173 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1173 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1174 PythonQt::self()->handleError();
1174 PythonQt::self()->handleError();
1175 }
1175 }
1176
1176
1177 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1177 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1178 {
1178 {
1179 if (_p->_initFlags & ExternalHelp) {
1179 if (_p->_initFlags & ExternalHelp) {
1180 emit pythonHelpRequest(QByteArray(info->className()));
1180 emit pythonHelpRequest(QByteArray(info->className()));
1181 return Py_BuildValue("");
1181 return Py_BuildValue("");
1182 } else {
1182 } else {
1183 return PyString_FromString(info->help().toLatin1().data());
1183 return PyString_FromString(info->help().toLatin1().data());
1184 }
1184 }
1185 }
1185 }
1186
1186
1187 void PythonQtPrivate::removeWrapperPointer(void* obj)
1187 void PythonQtPrivate::removeWrapperPointer(void* obj)
1188 {
1188 {
1189 _wrappedObjects.remove(obj);
1189 _wrappedObjects.remove(obj);
1190 }
1190 }
1191
1191
1192 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1192 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1193 {
1193 {
1194 _wrappedObjects.insert(obj, wrapper);
1194 _wrappedObjects.insert(obj, wrapper);
1195 }
1195 }
1196
1196
1197 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1197 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1198 {
1198 {
1199 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1199 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1200 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1200 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1201 // this is a wrapper whose QObject was already removed due to destruction
1201 // this is a wrapper whose QObject was already removed due to destruction
1202 // so the obj pointer has to be a new QObject with the same address...
1202 // so the obj pointer has to be a new QObject with the same address...
1203 // we remove the old one and set the copy to NULL
1203 // we remove the old one and set the copy to NULL
1204 wrap->_objPointerCopy = NULL;
1204 wrap->_objPointerCopy = NULL;
1205 removeWrapperPointer(obj);
1205 removeWrapperPointer(obj);
1206 wrap = NULL;
1206 wrap = NULL;
1207 }
1207 }
1208 return wrap;
1208 return wrap;
1209 }
1209 }
1210
1210
1211 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1211 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1212 {
1212 {
1213 PythonQtObjectPtr result;
1213 PythonQtObjectPtr result;
1214 if (pycode) {
1214 if (pycode) {
1215 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1215 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1216 } else {
1216 } else {
1217 PythonQt::self()->handleError();
1217 PythonQt::self()->handleError();
1218 }
1218 }
1219 return result;
1219 return result;
1220 }
1220 }
@@ -1,579 +1,579
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "PythonQtInstanceWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtObjectPtr.h"
49 #include "PythonQtObjectPtr.h"
50 #include <QObject>
50 #include <QObject>
51 #include <QVariant>
51 #include <QVariant>
52 #include <QList>
52 #include <QList>
53 #include <QHash>
53 #include <QHash>
54 #include <QByteArray>
54 #include <QByteArray>
55 #include <QStringList>
55 #include <QStringList>
56 #include <QtDebug>
56 #include <QtDebug>
57 #include <iostream>
57 #include <iostream>
58
58
59
59
60 class PythonQtClassInfo;
60 class PythonQtClassInfo;
61 class PythonQtPrivate;
61 class PythonQtPrivate;
62 class PythonQtMethodInfo;
62 class PythonQtMethodInfo;
63 class PythonQtSignalReceiver;
63 class PythonQtSignalReceiver;
64 class PythonQtImportFileInterface;
64 class PythonQtImportFileInterface;
65 class PythonQtCppWrapperFactory;
65 class PythonQtCppWrapperFactory;
66 class PythonQtQFileImporter;
66 class PythonQtQFileImporter;
67
67
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71
71
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73
73
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
75
75
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
79 }
79 }
80
80
81 //! callback to create a QObject lazily
81 //! callback to create a QObject lazily
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
83
83
84 //! helper template to create a derived QObject class
84 //! helper template to create a derived QObject class
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
86
86
87 //! the main interface to the Python Qt binding, realized as a singleton
87 //! the main interface to the Python Qt binding, realized as a singleton
88 class PYTHONQT_EXPORT PythonQt : public QObject {
88 class PYTHONQT_EXPORT PythonQt : public QObject {
89
89
90 Q_OBJECT
90 Q_OBJECT
91
91
92 public:
92 public:
93 enum InitFlags {
93 enum InitFlags {
94 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
94 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
95 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
95 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
96 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
96 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
97 };
97 };
98
98
99 //! flags that tell PythonQt which operators to expect on the registered type
99 //! flags that tell PythonQt which operators to expect on the registered type
100 enum TypeSlots {
100 enum TypeSlots {
101 Type_Add = 1,
101 Type_Add = 1,
102 Type_Subtract = 1 << 1,
102 Type_Subtract = 1 << 1,
103 Type_Multiply = 1 << 2,
103 Type_Multiply = 1 << 2,
104 Type_Divide = 1 << 3,
104 Type_Divide = 1 << 3,
105 Type_Mod = 1 << 4,
105 Type_Mod = 1 << 4,
106 Type_And = 1 << 5,
106 Type_And = 1 << 5,
107 Type_Or = 1 << 6,
107 Type_Or = 1 << 6,
108 Type_Xor = 1 << 7,
108 Type_Xor = 1 << 7,
109 Type_LShift = 1 << 8,
109 Type_LShift = 1 << 8,
110 Type_RShift = 1 << 9,
110 Type_RShift = 1 << 9,
111
111
112 Type_InplaceAdd = 1 << 10,
112 Type_InplaceAdd = 1 << 10,
113 Type_InplaceSubtract = 1 << 11,
113 Type_InplaceSubtract = 1 << 11,
114 Type_InplaceMultiply = 1 << 12,
114 Type_InplaceMultiply = 1 << 12,
115 Type_InplaceDivide = 1 << 13,
115 Type_InplaceDivide = 1 << 13,
116 Type_InplaceMod = 1 << 14,
116 Type_InplaceMod = 1 << 14,
117 Type_InplaceAnd = 1 << 15,
117 Type_InplaceAnd = 1 << 15,
118 Type_InplaceOr = 1 << 16,
118 Type_InplaceOr = 1 << 16,
119 Type_InplaceXor = 1 << 17,
119 Type_InplaceXor = 1 << 17,
120 Type_InplaceLShift = 1 << 18,
120 Type_InplaceLShift = 1 << 18,
121 Type_InplaceRShift = 1 << 19,
121 Type_InplaceRShift = 1 << 19,
122
122
123 // Not yet needed/nicely mappable/generated...
123 // Not yet needed/nicely mappable/generated...
124 //Type_Positive = 1 << 29,
124 //Type_Positive = 1 << 29,
125 //Type_Negative = 1 << 29,
125 //Type_Negative = 1 << 29,
126 //Type_Abs = 1 << 29,
126 //Type_Abs = 1 << 29,
127 //Type_Hash = 1 << 29,
127 //Type_Hash = 1 << 29,
128
128
129 Type_Invert = 1 << 29,
129 Type_Invert = 1 << 29,
130 Type_RichCompare = 1 << 30,
130 Type_RichCompare = 1 << 30,
131 Type_NonZero = 1 << 31,
131 Type_NonZero = 1 << 31,
132
132
133 };
133 };
134
134
135 //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given
135 //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given
136 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
136 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
137 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
137 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
138 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
138 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
139
139
140 //! cleanup
140 //! cleanup
141 static void cleanup();
141 static void cleanup();
142
142
143 //! get the singleton instance
143 //! get the singleton instance
144 static PythonQt* self() { return _self; }
144 static PythonQt* self() { return _self; }
145
145
146 //-----------------------------------------------------------------------------
146 //-----------------------------------------------------------------------------
147 // Public API:
147 // Public API:
148
148
149 //! defines the object types for introspection
149 //! defines the object types for introspection
150 enum ObjectType {
150 enum ObjectType {
151 Class,
151 Class,
152 Function,
152 Function,
153 Variable,
153 Variable,
154 Module,
154 Module,
155 Anything,
155 Anything,
156 CallOverloads
156 CallOverloads
157 };
157 };
158
158
159 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
159 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
160 void overwriteSysPath(const QStringList& paths);
160 void overwriteSysPath(const QStringList& paths);
161
161
162 //! prepend a path to sys.path to allow importing from it
162 //! prepend a path to sys.path to allow importing from it
163 void addSysPath(const QString& path);
163 void addSysPath(const QString& path);
164
164
165 //! sets the __path__ list of a module to the given list (important for local imports)
165 //! sets the __path__ list of a module to the given list (important for local imports)
166 void setModuleImportPath(PyObject* module, const QStringList& paths);
166 void setModuleImportPath(PyObject* module, const QStringList& paths);
167
167
168 //! get the __main__ module of python
168 //! get the __main__ module of python
169 PythonQtObjectPtr getMainModule();
169 PythonQtObjectPtr getMainModule();
170
170
171 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
171 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
172 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
172 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
173 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
173 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
174 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
174 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
175
175
176 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
176 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
177 //! (ownership of wrapper is passed to PythonQt)
177 //! (ownership of wrapper is passed to PythonQt)
178 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
178 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
179
179
180 This will add a wrapper object that is used to make calls to the given classname \c typeName.
180 This will add a wrapper object that is used to make calls to the given classname \c typeName.
181 All slots that take a pointer to typeName as the first argument will be callable from Python on
181 All slots that take a pointer to typeName as the first argument will be callable from Python on
182 a variant object that contains such a type.
182 a variant object that contains such a type.
183 */
183 */
184 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
184 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
185
185
186 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
186 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
187 //! and it will register the classes when it first sees a pointer to such a derived class
187 //! and it will register the classes when it first sees a pointer to such a derived class
188 void registerQObjectClassNames(const QStringList& names);
188 void registerQObjectClassNames(const QStringList& names);
189
189
190 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
190 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
191 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
191 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
192 //! type is really derived from parentType.
192 //! type is really derived from parentType.
193 //! Returns false if the typeName was not yet registered.
193 //! Returns false if the typeName was not yet registered.
194 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
194 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
195
195
196 //! add a handler for polymorphic downcasting
196 //! add a handler for polymorphic downcasting
197 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
197 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
198
198
199 //! parses the given file and returns the python code object, this can then be used to call evalCode()
199 //! parses the given file and returns the python code object, this can then be used to call evalCode()
200 PythonQtObjectPtr parseFile(const QString& filename);
200 PythonQtObjectPtr parseFile(const QString& filename);
201
201
202 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
202 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
203 //! If pycode is NULL, a python error is printed.
203 //! If pycode is NULL, a python error is printed.
204 QVariant evalCode(PyObject* object, PyObject* pycode);
204 QVariant evalCode(PyObject* object, PyObject* pycode);
205
205
206 //! evaluates the given script code and returns the result value
206 //! evaluates the given script code and returns the result value
207 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
207 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
208
208
209 //! evaluates the given script code from file
209 //! evaluates the given script code from file
210 void evalFile(PyObject* object, const QString& filename);
210 void evalFile(PyObject* object, const QString& filename);
211
211
212 //! creates the new module \c name and evaluates the given file in the context of that module
212 //! creates the new module \c name and evaluates the given file in the context of that module
213 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
213 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
214 //! to a module later on.
214 //! to a module later on.
215 //! The user needs to make sure that the \c name is unique in the python module dictionary.
215 //! The user needs to make sure that the \c name is unique in the python module dictionary.
216 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
216 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
217
217
218 //! creates the new module \c name and evaluates the given script in the context of that module.
218 //! creates the new module \c name and evaluates the given script in the context of that module.
219 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
219 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
220 //! to a module later on.
220 //! to a module later on.
221 //! The user needs to make sure that the \c name is unique in the python module dictionary.
221 //! The user needs to make sure that the \c name is unique in the python module dictionary.
222 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
222 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
223
223
224 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
224 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
225 //! script code
225 //! script code
226 PythonQtObjectPtr createUniqueModule();
226 PythonQtObjectPtr createUniqueModule();
227
227
228 //@{ Signal handlers
228 //@{ Signal handlers
229
229
230 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
230 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
231 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
231 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
232
232
233 //! remove a signal handler from the given \c signal of \c obj
233 //! remove a signal handler from the given \c signal of \c obj
234 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
234 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
235
235
236 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
236 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
237 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
237 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
238
238
239 //! remove a signal handler from the given \c signal of \c obj
239 //! remove a signal handler from the given \c signal of \c obj
240 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
240 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
241
241
242 //@}
242 //@}
243
243
244 //@{ Variable access
244 //@{ Variable access
245
245
246 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
246 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
247 void addObject(PyObject* object, const QString& name, QObject* qObject);
247 void addObject(PyObject* object, const QString& name, QObject* qObject);
248
248
249 //! add the given variable to the object
249 //! add the given variable to the object
250 void addVariable(PyObject* object, const QString& name, const QVariant& v);
250 void addVariable(PyObject* object, const QString& name, const QVariant& v);
251
251
252 //! remove the given variable
252 //! remove the given variable
253 void removeVariable(PyObject* module, const QString& name);
253 void removeVariable(PyObject* module, const QString& name);
254
254
255 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
255 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
256 QVariant getVariable(PyObject* object, const QString& name);
256 QVariant getVariable(PyObject* object, const QString& name);
257
257
258 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
258 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
259 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
259 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
260
260
261 //! returns the found callable object or NULL
261 //! returns the found callable object or NULL
262 //! @return new reference
262 //! @return new reference
263 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
263 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
264
264
265 //@}
265 //@}
266
266
267 //@{ Calling of python callables
267 //@{ Calling of python callables
268
268
269 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
269 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
270 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
270 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
271
271
272 //! call the given python object, returns the result converted to a QVariant
272 //! call the given python object, returns the result converted to a QVariant
273 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
273 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
274
274
275 //! call the given python object, returns the result as new PyObject
275 //! call the given python object, returns the result as new PyObject
276 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
276 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
277
277
278 //@}
278 //@}
279
279
280 //@{ Decorations, constructors, wrappers...
280 //@{ Decorations, constructors, wrappers...
281
281
282
282
283 //! add an object whose slots will be used as decorator slots for
283 //! add an object whose slots will be used as decorator slots for
284 //! other QObjects or CPP classes. The slots need to follow the
284 //! other QObjects or CPP classes. The slots need to follow the
285 //! convention that the first argument is a pointer to the wrapped object.
285 //! convention that the first argument is a pointer to the wrapped object.
286 //! (ownership is passed to PythonQt)
286 //! (ownership is passed to PythonQt)
287 /*!
287 /*!
288 Example:
288 Example:
289
289
290 A slot with the signature
290 A slot with the signature
291
291
292 \code
292 \code
293 bool doSomething(QWidget* w, int a)
293 bool doSomething(QWidget* w, int a)
294 \endcode
294 \endcode
295
295
296 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
296 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
297 that will be called with the concrete instance as first argument.
297 that will be called with the concrete instance as first argument.
298 So in Python you can now e.g. call
298 So in Python you can now e.g. call
299
299
300 \code
300 \code
301 someWidget.doSomething(12)
301 someWidget.doSomething(12)
302 \endcode
302 \endcode
303
303
304 without QWidget really having this method. This allows to easily make normal methods
304 without QWidget really having this method. This allows to easily make normal methods
305 of Qt classes callable by forwarding them with such decorator slots
305 of Qt classes callable by forwarding them with such decorator slots
306 or to make CPP classes (which are not derived from QObject) callable from Python.
306 or to make CPP classes (which are not derived from QObject) callable from Python.
307 */
307 */
308 void addInstanceDecorators(QObject* o);
308 void addInstanceDecorators(QObject* o);
309
309
310 //! add an object whose slots will be used as decorator slots for
310 //! add an object whose slots will be used as decorator slots for
311 //! class objects (ownership is passed to PythonQt)
311 //! class objects (ownership is passed to PythonQt)
312 /*!
312 /*!
313 The slots need to follow the following convention:
313 The slots need to follow the following convention:
314 - SomeClass* new_SomeClass(...)
314 - SomeClass* new_SomeClass(...)
315 - QVariant new_SomeClass(...)
315 - QVariant new_SomeClass(...)
316 - void delete_SomeClass(SomeClass*)
316 - void delete_SomeClass(SomeClass*)
317 - ... static_SomeClass_someName(...)
317 - ... static_SomeClass_someName(...)
318
318
319 This will add:
319 This will add:
320 - a constructor
320 - a constructor
321 - a constructor which generates a QVariant
321 - a constructor which generates a QVariant
322 - a destructor (only useful for CPP objects)
322 - a destructor (only useful for CPP objects)
323 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
323 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
324
324
325 */
325 */
326 void addClassDecorators(QObject* o);
326 void addClassDecorators(QObject* o);
327
327
328 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
328 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
329 void addDecorators(QObject* o);
329 void addDecorators(QObject* o);
330
330
331 //! add the given factory to PythonQt (ownership stays with caller)
331 //! add the given factory to PythonQt (ownership stays with caller)
332 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
332 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
333
333
334 //@}
334 //@}
335
335
336 //@{ Custom importer (to replace internal import implementation of python)
336 //@{ Custom importer (to replace internal import implementation of python)
337
337
338 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
338 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
339 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
339 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
340 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
340 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
341 //! This is not reversible, so even setting setImporter(NULL) afterwards will
341 //! This is not reversible, so even setting setImporter(NULL) afterwards will
342 //! keep the custom PythonQt importer with a QFile default import interface.
342 //! keep the custom PythonQt importer with a QFile default import interface.
343 //! Subsequent python import calls will make use of the passed importInterface
343 //! Subsequent python import calls will make use of the passed importInterface
344 //! which forwards all import calls to the given \c importInterface.
344 //! which forwards all import calls to the given \c importInterface.
345 //! Passing NULL will install a default QFile importer.
345 //! Passing NULL will install a default QFile importer.
346 //! (\c importInterface ownership stays with caller)
346 //! (\c importInterface ownership stays with caller)
347 void setImporter(PythonQtImportFileInterface* importInterface);
347 void setImporter(PythonQtImportFileInterface* importInterface);
348
348
349 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
349 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
350 //! (without calling setImporter or installDefaultImporter at least once, the default python import
350 //! (without calling setImporter or installDefaultImporter at least once, the default python import
351 //! mechanism is in place)
351 //! mechanism is in place)
352 //! the default importer allows to import files from anywhere QFile can read from,
352 //! the default importer allows to import files from anywhere QFile can read from,
353 //! including the Qt resource system using ":". Keep in mind that you need to extend
353 //! including the Qt resource system using ":". Keep in mind that you need to extend
354 //! "sys.path" with ":" to be able to import from the Qt resources.
354 //! "sys.path" with ":" to be able to import from the Qt resources.
355 void installDefaultImporter() { setImporter(NULL); }
355 void installDefaultImporter() { setImporter(NULL); }
356
356
357 //! set paths that the importer should ignore
357 //! set paths that the importer should ignore
358 void setImporterIgnorePaths(const QStringList& paths);
358 void setImporterIgnorePaths(const QStringList& paths);
359
359
360 //! get paths that the importer should ignore
360 //! get paths that the importer should ignore
361 const QStringList& getImporterIgnorePaths();
361 const QStringList& getImporterIgnorePaths();
362
362
363 //@}
363 //@}
364
364
365 //! get access to internal data (should not be used on the public API, but is used by some C functions)
365 //! get access to internal data (should not be used on the public API, but is used by some C functions)
366 static PythonQtPrivate* priv() { return _self->_p; }
366 static PythonQtPrivate* priv() { return _self->_p; }
367
367
368 //! get access to the file importer (if set)
368 //! get access to the file importer (if set)
369 static PythonQtImportFileInterface* importInterface();
369 static PythonQtImportFileInterface* importInterface();
370
370
371 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
371 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
372 //! The error is currently just output to the python stderr, future version might implement better trace printing
372 //! The error is currently just output to the python stderr, future version might implement better trace printing
373 bool handleError();
373 bool handleError();
374
374
375 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
375 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
376 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
376 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
377 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
377 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
378 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
378 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
379
379
380 //! call the callback if it is set
380 //! call the callback if it is set
381 static void qObjectNoLongerWrappedCB(QObject* o);
381 static void qObjectNoLongerWrappedCB(QObject* o);
382
382
383 signals:
383 signals:
384 //! emitted when python outputs something to stdout (and redirection is turned on)
384 //! emitted when python outputs something to stdout (and redirection is turned on)
385 void pythonStdOut(const QString& str);
385 void pythonStdOut(const QString& str);
386 //! emitted when python outputs something to stderr (and redirection is turned on)
386 //! emitted when python outputs something to stderr (and redirection is turned on)
387 void pythonStdErr(const QString& str);
387 void pythonStdErr(const QString& str);
388
388
389 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
389 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
390 void pythonHelpRequest(const QByteArray& cppClassName);
390 void pythonHelpRequest(const QByteArray& cppClassName);
391
391
392
392
393 public:
393 public:
394 //! called by internal help methods
394 //! called by internal help methods
395 PyObject* helpCalled(PythonQtClassInfo* info);
395 PyObject* helpCalled(PythonQtClassInfo* info);
396
396
397 //! returns the found object or NULL
397 //! returns the found object or NULL
398 //! @return new reference
398 //! @return new reference
399 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
399 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
400
400
401 private:
401 private:
402 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
402 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
403
403
404 //! callback for stdout redirection, emits pythonStdOut signal
404 //! callback for stdout redirection, emits pythonStdOut signal
405 static void stdOutRedirectCB(const QString& str);
405 static void stdOutRedirectCB(const QString& str);
406 //! callback for stderr redirection, emits pythonStdErr signal
406 //! callback for stderr redirection, emits pythonStdErr signal
407 static void stdErrRedirectCB(const QString& str);
407 static void stdErrRedirectCB(const QString& str);
408
408
409 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
409 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
410 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
410 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
411
411
412 PythonQt(int flags, const QByteArray& pythonQtModuleName);
412 PythonQt(int flags, const QByteArray& pythonQtModuleName);
413 ~PythonQt();
413 ~PythonQt();
414
414
415 static PythonQt* _self;
415 static PythonQt* _self;
416 static int _uniqueModuleCount;
416 static int _uniqueModuleCount;
417
417
418 PythonQtPrivate* _p;
418 PythonQtPrivate* _p;
419
419
420 };
420 };
421
421
422 //! internal PythonQt details
422 //! internal PythonQt details
423 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
423 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
424
424
425 Q_OBJECT
425 Q_OBJECT
426
426
427 public:
427 public:
428 PythonQtPrivate();
428 PythonQtPrivate();
429 ~PythonQtPrivate();
429 ~PythonQtPrivate();
430
430
431 enum DecoratorTypes {
431 enum DecoratorTypes {
432 StaticDecorator = 1,
432 StaticDecorator = 1,
433 ConstructorDecorator = 2,
433 ConstructorDecorator = 2,
434 DestructorDecorator = 4,
434 DestructorDecorator = 4,
435 InstanceDecorator = 8,
435 InstanceDecorator = 8,
436 AllDecorators = 0xffff
436 AllDecorators = 0xffff
437 };
437 };
438
438
439 //! get the suffixes that are used for shared libraries
439 //! get the suffixes that are used for shared libraries
440 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
440 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
441
441
442 //! returns if the id is the id for PythonQtObjectPtr
442 //! returns if the id is the id for PythonQtObjectPtr
443 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
443 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
444
444
445 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
445 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
446 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
446 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
447 //! remove the wrapper ptr again
447 //! remove the wrapper ptr again
448 void removeWrapperPointer(void* obj);
448 void removeWrapperPointer(void* obj);
449
449
450 //! add parent class relation
450 //! add parent class relation
451 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
451 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
452
452
453 //! add a handler for polymorphic downcasting
453 //! add a handler for polymorphic downcasting
454 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
454 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
455
455
456 //! lookup existing classinfo and return new if not yet present
456 //! lookup existing classinfo and return new if not yet present
457 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
457 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
458
458
459 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
459 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
460 void removeSignalEmitter(QObject* obj);
460 void removeSignalEmitter(QObject* obj);
461
461
462 //! wrap the given QObject into a Python object (or return existing wrapper!)
462 //! wrap the given QObject into a Python object (or return existing wrapper!)
463 PyObject* wrapQObject(QObject* obj);
463 PyObject* wrapQObject(QObject* obj);
464
464
465 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
465 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
466 PyObject* wrapPtr(void* ptr, const QByteArray& name);
466 PyObject* wrapPtr(void* ptr, const QByteArray& name);
467
467
468 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
468 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
469 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
469 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
470 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
470 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
471 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
471 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
472
472
473 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
473 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
474 //! (ownership of wrapper is passed to PythonQt)
474 //! (ownership of wrapper is passed to PythonQt)
475 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
475 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
476
476
477 This will add a wrapper object that is used to make calls to the given classname \c typeName.
477 This will add a wrapper object that is used to make calls to the given classname \c typeName.
478 All slots that take a pointer to typeName as the first argument will be callable from Python on
478 All slots that take a pointer to typeName as the first argument will be callable from Python on
479 a variant object that contains such a type.
479 a variant object that contains such a type.
480 */
480 */
481 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
481 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
482
482
483 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
483 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
484 //! and it will register the classes when it first sees a pointer to such a derived class
484 //! and it will register the classes when it first sees a pointer to such a derived class
485 void registerQObjectClassNames(const QStringList& names);
485 void registerQObjectClassNames(const QStringList& names);
486
486
487 //! add a decorator object
487 //! add a decorator object
488 void addDecorators(QObject* o, int decoTypes);
488 void addDecorators(QObject* o, int decoTypes);
489
489
490 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
490 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
491 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
491 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
492
492
493 //! create a new instance of the given enum type with given value (returns a new reference)
493 //! create a new instance of the given enum type with given value (returns a new reference)
494 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
494 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
495
495
496 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
496 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
497 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
497 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
498
498
499 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
499 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
500 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
500 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
501
501
502 //! get the class info for a meta object (if available)
502 //! get the class info for a meta object (if available)
503 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
503 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
504
504
505 //! get the class info for a meta object (if available)
505 //! get the class info for a meta object (if available)
506 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
506 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
507
507
508 //! creates the new module from the given pycode
508 //! creates the new module from the given pycode
509 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
509 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
510
510
511 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
511 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
512 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
512 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
513
513
514 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
514 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
515 static PyObject* dummyTuple();
515 static PyObject* dummyTuple();
516
516
517 //! called by virtual overloads when a python return value can not be converted to the required Qt type
517 //! called by virtual overloads when a python return value can not be converted to the required Qt type
518 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
518 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
519
519
520 //! get access to the PythonQt module
520 //! get access to the PythonQt module
521 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
521 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
522
522
523 private:
523 private:
524 //! Setup the shared library suffixes by getting them from the "imp" module.
524 //! Setup the shared library suffixes by getting them from the "imp" module.
525 void setupSharedLibrarySuffixes();
525 void setupSharedLibrarySuffixes();
526
526
527 //! create a new pythonqt class wrapper and place it in the pythonqt module
527 //! create a new pythonqt class wrapper and place it in the pythonqt module
528 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
528 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
529
529
530 //! get/create new package module (the returned object is a borrowed reference)
530 //! get/create new package module (the returned object is a borrowed reference)
531 PyObject* packageByName(const char* name);
531 PyObject* packageByName(const char* name);
532
532
533 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
533 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
534 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
534 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
535
535
536 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
536 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
537 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
537 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
538
538
539 //! stores the meta info of known Qt classes
539 //! stores the meta info of known Qt classes
540 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
540 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
541
541
542 //! names of qobject derived classes that can be casted to qobject savely
542 //! names of qobject derived classes that can be casted to qobject savely
543 QHash<QByteArray, bool> _knownQObjectClassNames;
543 QHash<QByteArray, bool> _knownQObjectClassNames;
544
544
545 //! stores signal receivers for QObjects
545 //! stores signal receivers for QObjects
546 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
546 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
547
547
548 //! the PythonQt python module
548 //! the PythonQt python module
549 PythonQtObjectPtr _pythonQtModule;
549 PythonQtObjectPtr _pythonQtModule;
550
550
551 //! the name of the PythonQt python module
551 //! the name of the PythonQt python module
552 QByteArray _pythonQtModuleName;
552 QByteArray _pythonQtModuleName;
553
553
554 //! the importer interface (if set)
554 //! the importer interface (if set)
555 PythonQtImportFileInterface* _importInterface;
555 PythonQtImportFileInterface* _importInterface;
556
556
557 //! the default importer
557 //! the default importer
558 PythonQtQFileImporter* _defaultImporter;
558 PythonQtQFileImporter* _defaultImporter;
559
559
560 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
560 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
561 PythonQtQObjectWrappedCB* _wrappedCB;
561 PythonQtQObjectWrappedCB* _wrappedCB;
562
562
563 QStringList _importIgnorePaths;
563 QStringList _importIgnorePaths;
564 QStringList _sharedLibrarySuffixes;
564 QStringList _sharedLibrarySuffixes;
565
565
566 //! the cpp object wrapper factories
566 //! the cpp object wrapper factories
567 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
567 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
568
568
569 QHash<QByteArray, PyObject*> _packages;
569 QHash<QByteArray, PyObject*> _packages;
570
570
571 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
571 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
572
572
573 int _initFlags;
573 int _initFlags;
574 int _PythonQtObjectPtr_metaId;
574 int _PythonQtObjectPtr_metaId;
575
575
576 friend class PythonQt;
576 friend class PythonQt;
577 };
577 };
578
578
579 #endif
579 #endif
@@ -1,849 +1,849
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _typeSlots = 0;
60 _typeSlots = 0;
61 _isQObject = false;
61 _isQObject = false;
62 _enumsCreated = false;
62 _enumsCreated = false;
63 }
63 }
64
64
65 PythonQtClassInfo::~PythonQtClassInfo()
65 PythonQtClassInfo::~PythonQtClassInfo()
66 {
66 {
67 clearCachedMembers();
67 clearCachedMembers();
68
68
69 if (_constructors) {
69 if (_constructors) {
70 _constructors->deleteOverloadsAndThis();
70 _constructors->deleteOverloadsAndThis();
71 }
71 }
72 if (_destructor) {
72 if (_destructor) {
73 _destructor->deleteOverloadsAndThis();
73 _destructor->deleteOverloadsAndThis();
74 }
74 }
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
76 info->deleteOverloadsAndThis();
76 info->deleteOverloadsAndThis();
77 }
77 }
78 }
78 }
79
79
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
81 {
81 {
82 // _wrappedClassName is already set earlier in the class setup
82 // _wrappedClassName is already set earlier in the class setup
83 _isQObject = true;
83 _isQObject = true;
84 _meta = meta;
84 _meta = meta;
85 }
85 }
86
86
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
88 {
88 {
89 _isQObject = false;
89 _isQObject = false;
90 _wrappedClassName = classname;
90 _wrappedClassName = classname;
91 _metaTypeId = QMetaType::type(classname);
91 _metaTypeId = QMetaType::type(classname);
92 }
92 }
93
93
94 void PythonQtClassInfo::clearCachedMembers()
94 void PythonQtClassInfo::clearCachedMembers()
95 {
95 {
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
97 while (i.hasNext()) {
97 while (i.hasNext()) {
98 PythonQtMemberInfo member = i.next().value();
98 PythonQtMemberInfo member = i.next().value();
99 if (member._type== PythonQtMemberInfo::Slot) {
99 if (member._type== PythonQtMemberInfo::Slot) {
100 PythonQtSlotInfo* info = member._slot;
100 PythonQtSlotInfo* info = member._slot;
101 while (info) {
101 while (info) {
102 PythonQtSlotInfo* next = info->nextInfo();
102 PythonQtSlotInfo* next = info->nextInfo();
103 delete info;
103 delete info;
104 info = next;
104 info = next;
105 }
105 }
106 }
106 }
107 }
107 }
108 }
108 }
109
109
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
111 {
111 {
112 const char* sigEnd = sigStart;
112 const char* sigEnd = sigStart;
113 char c;
113 char c;
114 do {
114 do {
115 c = *sigEnd++;
115 c = *sigEnd++;
116 } while (c!=someChar && c!=0);
116 } while (c!=someChar && c!=0);
117 return sigEnd-sigStart-1;
117 return sigEnd-sigStart-1;
118 }
118 }
119
119
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
121 {
121 {
122 if (!_meta) return false;
122 if (!_meta) return false;
123
123
124 bool found = false;
124 bool found = false;
125 bool nameMapped = false;
125 bool nameMapped = false;
126 const char* attributeName = memberName;
126 const char* attributeName = memberName;
127 // look for properties
127 // look for properties
128 int i = _meta->indexOfProperty(attributeName);
128 int i = _meta->indexOfProperty(attributeName);
129 if (i==-1) {
129 if (i==-1) {
130 // try to map name to objectName
130 // try to map name to objectName
131 if (qstrcmp(attributeName, "name")==0) {
131 if (qstrcmp(attributeName, "name")==0) {
132 attributeName = "objectName";
132 attributeName = "objectName";
133 nameMapped = true;
133 nameMapped = true;
134 i = _meta->indexOfProperty(attributeName);
134 i = _meta->indexOfProperty(attributeName);
135 }
135 }
136 }
136 }
137 if (i!=-1) {
137 if (i!=-1) {
138 PythonQtMemberInfo newInfo(_meta->property(i));
138 PythonQtMemberInfo newInfo(_meta->property(i));
139 _cachedMembers.insert(attributeName, newInfo);
139 _cachedMembers.insert(attributeName, newInfo);
140 if (nameMapped) {
140 if (nameMapped) {
141 _cachedMembers.insert(memberName, newInfo);
141 _cachedMembers.insert(memberName, newInfo);
142 }
142 }
143 #ifdef PYTHONQT_DEBUG
143 #ifdef PYTHONQT_DEBUG
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
145 #endif
145 #endif
146 found = true;
146 found = true;
147 }
147 }
148 return found;
148 return found;
149 }
149 }
150
150
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
152 {
152 {
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
154 foreach(const ParentClassInfo& info, _parentClasses) {
154 foreach(const ParentClassInfo& info, _parentClasses) {
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
156 }
156 }
157 return inputInfo;
157 return inputInfo;
158 }
158 }
159
159
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
161 QObject* decoratorProvider = decorator();
161 QObject* decoratorProvider = decorator();
162 int memberNameLen = strlen(memberName);
162 int memberNameLen = strlen(memberName);
163 if (decoratorProvider) {
163 if (decoratorProvider) {
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
165 const QMetaObject* meta = decoratorProvider->metaObject();
165 const QMetaObject* meta = decoratorProvider->metaObject();
166 int numMethods = meta->methodCount();
166 int numMethods = meta->methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
168 for (int i = startFrom; i < numMethods; i++) {
168 for (int i = startFrom; i < numMethods; i++) {
169 QMetaMethod m = meta->method(i);
169 QMetaMethod m = meta->method(i);
170 if ((m.methodType() == QMetaMethod::Method ||
170 if ((m.methodType() == QMetaMethod::Method ||
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
172
172
173 const char* sigStart = m.signature();
173 const char* sigStart = m.signature();
174 bool isClassDeco = false;
174 bool isClassDeco = false;
175 if (qstrncmp(sigStart, "static_", 7)==0) {
175 if (qstrncmp(sigStart, "static_", 7)==0) {
176 // skip the static_classname_ part of the string
176 // skip the static_classname_ part of the string
177 sigStart += 7 + 1 + strlen(className());
177 sigStart += 7 + 1 + strlen(className());
178 isClassDeco = true;
178 isClassDeco = true;
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
180 isClassDeco = true;
180 isClassDeco = true;
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
182 isClassDeco = true;
182 isClassDeco = true;
183 }
183 }
184 // find the first '('
184 // find the first '('
185 int offset = findCharOffset(sigStart, '(');
185 int offset = findCharOffset(sigStart, '(');
186
186
187 // XXX no checking is currently done if the slots have correct first argument or not...
187 // XXX no checking is currently done if the slots have correct first argument or not...
188
188
189 // check if same length and same name
189 // check if same length and same name
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
191 found = true;
191 found = true;
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
193 info->setUpcastingOffset(upcastingOffset);
193 info->setUpcastingOffset(upcastingOffset);
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
195 if (tail) {
195 if (tail) {
196 tail->setNextInfo(info);
196 tail->setNextInfo(info);
197 } else {
197 } else {
198 PythonQtMemberInfo newInfo(info);
198 PythonQtMemberInfo newInfo(info);
199 memberCache.insert(memberName, newInfo);
199 memberCache.insert(memberName, newInfo);
200 }
200 }
201 tail = info;
201 tail = info;
202 }
202 }
203 }
203 }
204 }
204 }
205 }
205 }
206
206
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
208
208
209 return tail;
209 return tail;
210 }
210 }
211
211
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
213 {
213 {
214 bool found = false;
214 bool found = false;
215 int memberNameLen = strlen(memberName);
215 int memberNameLen = strlen(memberName);
216 PythonQtSlotInfo* tail = NULL;
216 PythonQtSlotInfo* tail = NULL;
217 if (_meta) {
217 if (_meta) {
218 int numMethods = _meta->methodCount();
218 int numMethods = _meta->methodCount();
219 for (int i = 0; i < numMethods; i++) {
219 for (int i = 0; i < numMethods; i++) {
220 QMetaMethod m = _meta->method(i);
220 QMetaMethod m = _meta->method(i);
221 if (((m.methodType() == QMetaMethod::Method ||
221 if (((m.methodType() == QMetaMethod::Method ||
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
223 || m.methodType()==QMetaMethod::Signal) {
223 || m.methodType()==QMetaMethod::Signal) {
224
224
225 const char* sigStart = m.signature();
225 const char* sigStart = m.signature();
226 // find the first '('
226 // find the first '('
227 int offset = findCharOffset(sigStart, '(');
227 int offset = findCharOffset(sigStart, '(');
228
228
229 // check if same length and same name
229 // check if same length and same name
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
231 found = true;
231 found = true;
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
233 if (tail) {
233 if (tail) {
234 tail->setNextInfo(info);
234 tail->setNextInfo(info);
235 } else {
235 } else {
236 PythonQtMemberInfo newInfo(info);
236 PythonQtMemberInfo newInfo(info);
237 _cachedMembers.insert(memberName, newInfo);
237 _cachedMembers.insert(memberName, newInfo);
238 }
238 }
239 tail = info;
239 tail = info;
240 }
240 }
241 }
241 }
242 }
242 }
243 }
243 }
244
244
245 // look for dynamic decorators in this class and in derived classes
245 // look for dynamic decorators in this class and in derived classes
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
247
247
248 return found;
248 return found;
249 }
249 }
250
250
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
252 {
252 {
253 bool found = false;
253 bool found = false;
254 // look for enum values
254 // look for enum values
255 int enumCount = meta->enumeratorCount();
255 int enumCount = meta->enumeratorCount();
256 for (int i=0;i<enumCount; i++) {
256 for (int i=0;i<enumCount; i++) {
257 QMetaEnum e = meta->enumerator(i);
257 QMetaEnum e = meta->enumerator(i);
258 // we do not want flags, they will cause our values to appear two times
258 // we do not want flags, they will cause our values to appear two times
259 if (e.isFlag()) continue;
259 if (e.isFlag()) continue;
260
260
261 for (int j=0; j < e.keyCount(); j++) {
261 for (int j=0; j < e.keyCount(); j++) {
262 if (qstrcmp(e.key(j), memberName)==0) {
262 if (qstrcmp(e.key(j), memberName)==0) {
263 PyObject* enumType = findEnumWrapper(e.name());
263 PyObject* enumType = findEnumWrapper(e.name());
264 if (enumType) {
264 if (enumType) {
265 PythonQtObjectPtr enumValuePtr;
265 PythonQtObjectPtr enumValuePtr;
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
267 PythonQtMemberInfo newInfo(enumValuePtr);
267 PythonQtMemberInfo newInfo(enumValuePtr);
268 _cachedMembers.insert(memberName, newInfo);
268 _cachedMembers.insert(memberName, newInfo);
269 #ifdef PYTHONQT_DEBUG
269 #ifdef PYTHONQT_DEBUG
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
271 #endif
271 #endif
272 found = true;
272 found = true;
273 break;
273 break;
274 } else {
274 } else {
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
276 }
276 }
277 }
277 }
278 }
278 }
279 }
279 }
280 return found;
280 return found;
281 }
281 }
282
282
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
284 {
284 {
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
286 if (info._type != PythonQtMemberInfo::Invalid) {
286 if (info._type != PythonQtMemberInfo::Invalid) {
287 return info;
287 return info;
288 } else {
288 } else {
289 bool found = false;
289 bool found = false;
290
290
291 found = lookForPropertyAndCache(memberName);
291 found = lookForPropertyAndCache(memberName);
292 if (!found) {
292 if (!found) {
293 found = lookForMethodAndCache(memberName);
293 found = lookForMethodAndCache(memberName);
294 }
294 }
295 if (!found) {
295 if (!found) {
296 if (_meta) {
296 if (_meta) {
297 // check enums in our meta object directly
297 // check enums in our meta object directly
298 found = lookForEnumAndCache(_meta, memberName);
298 found = lookForEnumAndCache(_meta, memberName);
299 }
299 }
300 if (!found) {
300 if (!found) {
301 // check enums in the class hierachy of CPP classes
301 // check enums in the class hierachy of CPP classes
302 // look for dynamic decorators in this class and in derived classes
302 // look for dynamic decorators in this class and in derived classes
303 QList<QObject*> decoObjects;
303 QList<QObject*> decoObjects;
304 recursiveCollectDecoratorObjects(decoObjects);
304 recursiveCollectDecoratorObjects(decoObjects);
305 foreach(QObject* deco, decoObjects) {
305 foreach(QObject* deco, decoObjects) {
306 // call on ourself for caching, but with different metaObject():
306 // call on ourself for caching, but with different metaObject():
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
308 if (found) {
308 if (found) {
309 break;
309 break;
310 }
310 }
311 }
311 }
312 }
312 }
313 }
313 }
314 if (!found) {
314 if (!found) {
315 // maybe it is an enum wrapper?
315 // maybe it is an enum wrapper?
316 PyObject* p = findEnumWrapper(memberName);
316 PyObject* p = findEnumWrapper(memberName);
317 if (p) {
317 if (p) {
318 info._type = PythonQtMemberInfo::EnumWrapper;
318 info._type = PythonQtMemberInfo::EnumWrapper;
319 info._enumWrapper = p;
319 info._enumWrapper = p;
320 _cachedMembers.insert(memberName, info);
320 _cachedMembers.insert(memberName, info);
321 found = true;
321 found = true;
322 }
322 }
323 }
323 }
324 if (!found) {
324 if (!found) {
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
327 QByteArray mbrName(memberName);
327 QByteArray mbrName(memberName);
328 if ((mbrName.length()>2) &&
328 if ((mbrName.length()>2) &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
330 (mbrName.at(mbrName.length()-2) != '_')) {
330 (mbrName.at(mbrName.length()-2) != '_')) {
331 mbrName = mbrName.mid(0,mbrName.length()-1);
331 mbrName = mbrName.mid(0,mbrName.length()-1);
332 found = lookForMethodAndCache(mbrName.constData());
332 found = lookForMethodAndCache(mbrName.constData());
333 if (found) {
333 if (found) {
334 return _cachedMembers.value(mbrName);
334 return _cachedMembers.value(mbrName);
335 }
335 }
336 }
336 }
337 }
337 }
338 if (!found) {
338 if (!found) {
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
340 info._type = PythonQtMemberInfo::NotFound;
340 info._type = PythonQtMemberInfo::NotFound;
341 _cachedMembers.insert(memberName, info);
341 _cachedMembers.insert(memberName, info);
342 }
342 }
343 }
343 }
344
344
345 return _cachedMembers.value(memberName);
345 return _cachedMembers.value(memberName);
346 }
346 }
347
347
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
349 QObject* deco = decorator();
349 QObject* deco = decorator();
350 if (deco) {
350 if (deco) {
351 decoratorObjects.append(deco);
351 decoratorObjects.append(deco);
352 }
352 }
353 foreach(const ParentClassInfo& info, _parentClasses) {
353 foreach(const ParentClassInfo& info, _parentClasses) {
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
355 }
355 }
356 }
356 }
357
357
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
359 classInfoObjects.append(this);
359 classInfoObjects.append(this);
360 foreach(const ParentClassInfo& info, _parentClasses) {
360 foreach(const ParentClassInfo& info, _parentClasses) {
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
362 }
362 }
363 }
363 }
364
364
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
366 {
366 {
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
368 while (it.hasNext()) {
368 while (it.hasNext()) {
369
369
370 PythonQtSlotInfo* infoOrig = it.next();
370 PythonQtSlotInfo* infoOrig = it.next();
371
371
372 const char* sigStart = infoOrig->metaMethod()->signature();
372 const char* sigStart = infoOrig->metaMethod()->signature();
373 if (qstrncmp("static_", sigStart, 7)==0) {
373 if (qstrncmp("static_", sigStart, 7)==0) {
374 sigStart += 7;
374 sigStart += 7;
375 sigStart += findCharOffset(sigStart, '_')+1;
375 sigStart += findCharOffset(sigStart, '_')+1;
376 }
376 }
377 int offset = findCharOffset(sigStart, '(');
377 int offset = findCharOffset(sigStart, '(');
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
379 //make a copy, otherwise we will have trouble on overloads!
379 //make a copy, otherwise we will have trouble on overloads!
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
381 info->setUpcastingOffset(upcastingOffset);
381 info->setUpcastingOffset(upcastingOffset);
382 found = true;
382 found = true;
383 if (tail) {
383 if (tail) {
384 tail->setNextInfo(info);
384 tail->setNextInfo(info);
385 } else {
385 } else {
386 PythonQtMemberInfo newInfo(info);
386 PythonQtMemberInfo newInfo(info);
387 memberCache.insert(memberName, newInfo);
387 memberCache.insert(memberName, newInfo);
388 }
388 }
389 tail = info;
389 tail = info;
390 }
390 }
391 }
391 }
392 return tail;
392 return tail;
393 }
393 }
394
394
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
396 QObject* decoratorProvider = decorator();
396 QObject* decoratorProvider = decorator();
397 if (decoratorProvider) {
397 if (decoratorProvider) {
398 const QMetaObject* meta = decoratorProvider->metaObject();
398 const QMetaObject* meta = decoratorProvider->metaObject();
399 int numMethods = meta->methodCount();
399 int numMethods = meta->methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
401 for (int i = startFrom; i < numMethods; i++) {
401 for (int i = startFrom; i < numMethods; i++) {
402 QMetaMethod m = meta->method(i);
402 QMetaMethod m = meta->method(i);
403 if ((m.methodType() == QMetaMethod::Method ||
403 if ((m.methodType() == QMetaMethod::Method ||
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
405
405
406 const char* sigStart = m.signature();
406 const char* sigStart = m.signature();
407 bool isClassDeco = false;
407 bool isClassDeco = false;
408 if (qstrncmp(sigStart, "static_", 7)==0) {
408 if (qstrncmp(sigStart, "static_", 7)==0) {
409 // skip the static_classname_ part of the string
409 // skip the static_classname_ part of the string
410 sigStart += 7 + 1 + strlen(className());
410 sigStart += 7 + 1 + strlen(className());
411 isClassDeco = true;
411 isClassDeco = true;
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
413 continue;
413 continue;
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
415 continue;
415 continue;
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
417 // hide everything that starts with py_
417 // hide everything that starts with py_
418 continue;
418 continue;
419 }
419 }
420 // find the first '('
420 // find the first '('
421 int offset = findCharOffset(sigStart, '(');
421 int offset = findCharOffset(sigStart, '(');
422
422
423 // XXX no checking is currently done if the slots have correct first argument or not...
423 // XXX no checking is currently done if the slots have correct first argument or not...
424 if (!metaOnly || isClassDeco) {
424 if (!metaOnly || isClassDeco) {
425 list << QString::fromLatin1(sigStart, offset);
425 list << QString::fromLatin1(sigStart, offset);
426 }
426 }
427 }
427 }
428 }
428 }
429 }
429 }
430
430
431 // look for global decorator slots
431 // look for global decorator slots
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
433 while (it.hasNext()) {
433 while (it.hasNext()) {
434 PythonQtSlotInfo* slot = it.next();
434 PythonQtSlotInfo* slot = it.next();
435 if (metaOnly) {
435 if (metaOnly) {
436 if (slot->isClassDecorator()) {
436 if (slot->isClassDecorator()) {
437 QByteArray first = slot->slotName();
437 QByteArray first = slot->slotName();
438 if (first.startsWith("static_")) {
438 if (first.startsWith("static_")) {
439 int idx = first.indexOf('_');
439 int idx = first.indexOf('_');
440 idx = first.indexOf('_', idx+1);
440 idx = first.indexOf('_', idx+1);
441 first = first.mid(idx+1);
441 first = first.mid(idx+1);
442 }
442 }
443 list << first;
443 list << first;
444 }
444 }
445 } else {
445 } else {
446 list << slot->slotName();
446 list << slot->slotName();
447 }
447 }
448 }
448 }
449 }
449 }
450
450
451 QStringList PythonQtClassInfo::propertyList()
451 QStringList PythonQtClassInfo::propertyList()
452 {
452 {
453 QStringList l;
453 QStringList l;
454 if (_isQObject && _meta) {
454 if (_isQObject && _meta) {
455 int i;
455 int i;
456 int numProperties = _meta->propertyCount();
456 int numProperties = _meta->propertyCount();
457 for (i = 0; i < numProperties; i++) {
457 for (i = 0; i < numProperties; i++) {
458 QMetaProperty p = _meta->property(i);
458 QMetaProperty p = _meta->property(i);
459 l << QString(p.name());
459 l << QString(p.name());
460 }
460 }
461 }
461 }
462 return l;
462 return l;
463 }
463 }
464
464
465 QStringList PythonQtClassInfo::memberList(bool metaOnly)
465 QStringList PythonQtClassInfo::memberList(bool metaOnly)
466 {
466 {
467 decorator();
467 decorator();
468
468
469 QStringList l;
469 QStringList l;
470 QString h;
470 QString h;
471 if (_isQObject && _meta && !metaOnly) {
471 if (_isQObject && _meta && !metaOnly) {
472 l = propertyList();
472 l = propertyList();
473 }
473 }
474
474
475 // normal slots of QObject (or wrapper QObject)
475 // normal slots of QObject (or wrapper QObject)
476 if (!metaOnly && _meta) {
476 if (!metaOnly && _meta) {
477 int numMethods = _meta->methodCount();
477 int numMethods = _meta->methodCount();
478 bool skipQObj = !_isQObject;
478 bool skipQObj = !_isQObject;
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
480 QMetaMethod m = _meta->method(i);
480 QMetaMethod m = _meta->method(i);
481 if (((m.methodType() == QMetaMethod::Method ||
481 if (((m.methodType() == QMetaMethod::Method ||
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
483 || m.methodType()==QMetaMethod::Signal) {
483 || m.methodType()==QMetaMethod::Signal) {
484 QByteArray signa(m.signature());
484 QByteArray signa(m.signature());
485 signa = signa.left(signa.indexOf('('));
485 signa = signa.left(signa.indexOf('('));
486 l << signa;
486 l << signa;
487 }
487 }
488 }
488 }
489 }
489 }
490
490
491 {
491 {
492 // look for dynamic decorators in this class and in derived classes
492 // look for dynamic decorators in this class and in derived classes
493 QList<PythonQtClassInfo*> infos;
493 QList<PythonQtClassInfo*> infos;
494 recursiveCollectClassInfos(infos);
494 recursiveCollectClassInfos(infos);
495 foreach(PythonQtClassInfo* info, infos) {
495 foreach(PythonQtClassInfo* info, infos) {
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
497 }
497 }
498 }
498 }
499
499
500 // List enumerator keys...
500 // List enumerator keys...
501 QList<const QMetaObject*> enumMetaObjects;
501 QList<const QMetaObject*> enumMetaObjects;
502 if (_meta) {
502 if (_meta) {
503 enumMetaObjects << _meta;
503 enumMetaObjects << _meta;
504 }
504 }
505 // check enums in the class hierachy of CPP classes
505 // check enums in the class hierachy of CPP classes
506 QList<QObject*> decoObjects;
506 QList<QObject*> decoObjects;
507 recursiveCollectDecoratorObjects(decoObjects);
507 recursiveCollectDecoratorObjects(decoObjects);
508 foreach(QObject* deco, decoObjects) {
508 foreach(QObject* deco, decoObjects) {
509 enumMetaObjects << deco->metaObject();
509 enumMetaObjects << deco->metaObject();
510 }
510 }
511
511
512 foreach(const QMetaObject* meta, enumMetaObjects) {
512 foreach(const QMetaObject* meta, enumMetaObjects) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
514 QMetaEnum e = meta->enumerator(i);
514 QMetaEnum e = meta->enumerator(i);
515 l << e.name();
515 l << e.name();
516 // we do not want flags, they will cause our values to appear two times
516 // we do not want flags, they will cause our values to appear two times
517 if (e.isFlag()) continue;
517 if (e.isFlag()) continue;
518
518
519 for (int j=0; j < e.keyCount(); j++) {
519 for (int j=0; j < e.keyCount(); j++) {
520 l << QString(e.key(j));
520 l << QString(e.key(j));
521 }
521 }
522 }
522 }
523 }
523 }
524
524
525 return QSet<QString>::fromList(l).toList();
525 return QSet<QString>::fromList(l).toList();
526 }
526 }
527
527
528 const char* PythonQtClassInfo::className()
528 const char* PythonQtClassInfo::className()
529 {
529 {
530 return _wrappedClassName.constData();
530 return _wrappedClassName.constData();
531 }
531 }
532
532
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
534 {
534 {
535 if (ptr==NULL) {
535 if (ptr==NULL) {
536 return NULL;
536 return NULL;
537 }
537 }
538 if (_wrappedClassName == classname) {
538 if (_wrappedClassName == classname) {
539 return ptr;
539 return ptr;
540 }
540 }
541 foreach(const ParentClassInfo& info, _parentClasses) {
541 foreach(const ParentClassInfo& info, _parentClasses) {
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
543 if (result) {
543 if (result) {
544 return result;
544 return result;
545 }
545 }
546 }
546 }
547 return NULL;
547 return NULL;
548 }
548 }
549
549
550 bool PythonQtClassInfo::inherits(const char* name)
550 bool PythonQtClassInfo::inherits(const char* name)
551 {
551 {
552 if (_wrappedClassName == name) {
552 if (_wrappedClassName == name) {
553 return true;
553 return true;
554 }
554 }
555 foreach(const ParentClassInfo& info, _parentClasses) {
555 foreach(const ParentClassInfo& info, _parentClasses) {
556 if (info._parent->inherits(name)) {
556 if (info._parent->inherits(name)) {
557 return true;
557 return true;
558 }
558 }
559 }
559 }
560 return false;
560 return false;
561 }
561 }
562
562
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
564 {
564 {
565 if (classInfo == this) {
565 if (classInfo == this) {
566 return true;
566 return true;
567 }
567 }
568 foreach(const ParentClassInfo& info, _parentClasses) {
568 foreach(const ParentClassInfo& info, _parentClasses) {
569 if (info._parent->inherits(classInfo)) {
569 if (info._parent->inherits(classInfo)) {
570 return true;
570 return true;
571 }
571 }
572 }
572 }
573 return false;
573 return false;
574 }
574 }
575
575
576 QString PythonQtClassInfo::help()
576 QString PythonQtClassInfo::help()
577 {
577 {
578 decorator();
578 decorator();
579 QString h;
579 QString h;
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
581
581
582 if (_isQObject) {
582 if (_isQObject) {
583 h += "Properties:\n";
583 h += "Properties:\n";
584
584
585 int i;
585 int i;
586 int numProperties = _meta->propertyCount();
586 int numProperties = _meta->propertyCount();
587 for (i = 0; i < numProperties; i++) {
587 for (i = 0; i < numProperties; i++) {
588 QMetaProperty p = _meta->property(i);
588 QMetaProperty p = _meta->property(i);
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
590 }
590 }
591 }
591 }
592
592
593 if (constructors()) {
593 if (constructors()) {
594 h += "Constructors:\n";
594 h += "Constructors:\n";
595 PythonQtSlotInfo* constr = constructors();
595 PythonQtSlotInfo* constr = constructors();
596 while (constr) {
596 while (constr) {
597 h += constr->fullSignature() + "\n";
597 h += constr->fullSignature() + "\n";
598 constr = constr->nextInfo();
598 constr = constr->nextInfo();
599 }
599 }
600 }
600 }
601
601
602 h += "Slots:\n";
602 h += "Slots:\n";
603 h += "QString help()\n";
603 h += "QString help()\n";
604 h += "QString className()\n";
604 h += "QString className()\n";
605
605
606 if (_meta) {
606 if (_meta) {
607 int numMethods = _meta->methodCount();
607 int numMethods = _meta->methodCount();
608 for (int i = 0; i < numMethods; i++) {
608 for (int i = 0; i < numMethods; i++) {
609 QMetaMethod m = _meta->method(i);
609 QMetaMethod m = _meta->method(i);
610 if ((m.methodType() == QMetaMethod::Method ||
610 if ((m.methodType() == QMetaMethod::Method ||
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
612 PythonQtSlotInfo slot(this, m, i);
612 PythonQtSlotInfo slot(this, m, i);
613 h += slot.fullSignature()+ "\n";
613 h += slot.fullSignature()+ "\n";
614 }
614 }
615 }
615 }
616 }
616 }
617
617
618 // TODO xxx : decorators and enums from decorator() are missing...
618 // TODO xxx : decorators and enums from decorator() are missing...
619 // maybe we can reuse memberlist()?
619 // maybe we can reuse memberlist()?
620
620
621 if (_meta && _meta->enumeratorCount()) {
621 if (_meta && _meta->enumeratorCount()) {
622 h += "Enums:\n";
622 h += "Enums:\n";
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
624 QMetaEnum e = _meta->enumerator(i);
624 QMetaEnum e = _meta->enumerator(i);
625 h += QString(e.name()) + " {";
625 h += QString(e.name()) + " {";
626 for (int j=0; j < e.keyCount(); j++) {
626 for (int j=0; j < e.keyCount(); j++) {
627 if (j) { h+= ", "; }
627 if (j) { h+= ", "; }
628 h += e.key(j);
628 h += e.key(j);
629 }
629 }
630 h += " }\n";
630 h += " }\n";
631 }
631 }
632 }
632 }
633
633
634 if (_isQObject && _meta) {
634 if (_isQObject && _meta) {
635 int numMethods = _meta->methodCount();
635 int numMethods = _meta->methodCount();
636 if (numMethods>0) {
636 if (numMethods>0) {
637 h += "Signals:\n";
637 h += "Signals:\n";
638 for (int i = 0; i < numMethods; i++) {
638 for (int i = 0; i < numMethods; i++) {
639 QMetaMethod m = _meta->method(i);
639 QMetaMethod m = _meta->method(i);
640 if (m.methodType() == QMetaMethod::Signal) {
640 if (m.methodType() == QMetaMethod::Signal) {
641 h += QString(m.signature()) + "\n";
641 h += QString(m.signature()) + "\n";
642 }
642 }
643 }
643 }
644 }
644 }
645 }
645 }
646 return h;
646 return h;
647 }
647 }
648
648
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
650 {
650 {
651 if (!_constructors) {
651 if (!_constructors) {
652 // force creation of lazy decorator, which will register the decorators
652 // force creation of lazy decorator, which will register the decorators
653 decorator();
653 decorator();
654 }
654 }
655 return _constructors;
655 return _constructors;
656 }
656 }
657
657
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
659 {
659 {
660 if (!_destructor) {
660 if (!_destructor) {
661 // force creation of lazy decorator, which will register the decorators
661 // force creation of lazy decorator, which will register the decorators
662 decorator();
662 decorator();
663 }
663 }
664 return _destructor;
664 return _destructor;
665 }
665 }
666
666
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
668 {
668 {
669 PythonQtSlotInfo* prev = constructors();
669 PythonQtSlotInfo* prev = constructors();
670 if (prev) {
670 if (prev) {
671 info->setNextInfo(prev->nextInfo());
671 info->setNextInfo(prev->nextInfo());
672 prev->setNextInfo(info);
672 prev->setNextInfo(info);
673 } else {
673 } else {
674 _constructors = info;
674 _constructors = info;
675 }
675 }
676 }
676 }
677
677
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
679 {
679 {
680 _decoratorSlots.append(info);
680 _decoratorSlots.append(info);
681 }
681 }
682
682
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
684 {
684 {
685 if (_destructor) {
685 if (_destructor) {
686 _destructor->deleteOverloadsAndThis();
686 _destructor->deleteOverloadsAndThis();
687 }
687 }
688 _destructor = info;
688 _destructor = info;
689 }
689 }
690
690
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
692 {
692 {
693 _meta = meta;
693 _meta = meta;
694 clearCachedMembers();
694 clearCachedMembers();
695 }
695 }
696
696
697 QObject* PythonQtClassInfo::decorator()
697 QObject* PythonQtClassInfo::decorator()
698 {
698 {
699 if (!_decoratorProvider && _decoratorProviderCB) {
699 if (!_decoratorProvider && _decoratorProviderCB) {
700 _decoratorProvider = (*_decoratorProviderCB)();
700 _decoratorProvider = (*_decoratorProviderCB)();
701 if (_decoratorProvider) {
701 if (_decoratorProvider) {
702 _decoratorProvider->setParent(PythonQt::priv());
702 _decoratorProvider->setParent(PythonQt::priv());
703 // setup enums early, since they might be needed by the constructor decorators:
703 // setup enums early, since they might be needed by the constructor decorators:
704 if (!_enumsCreated) {
704 if (!_enumsCreated) {
705 createEnumWrappers();
705 createEnumWrappers();
706 }
706 }
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
708 }
708 }
709 }
709 }
710 // check if enums need to be created and create them if they are not yet created
710 // check if enums need to be created and create them if they are not yet created
711 if (!_enumsCreated) {
711 if (!_enumsCreated) {
712 createEnumWrappers();
712 createEnumWrappers();
713 }
713 }
714 return _decoratorProvider;
714 return _decoratorProvider;
715 }
715 }
716
716
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
718 {
718 {
719 PythonQtMemberInfo info = member("py_hasOwner");
719 PythonQtMemberInfo info = member("py_hasOwner");
720 if (info._type == PythonQtMemberInfo::Slot) {
720 if (info._type == PythonQtMemberInfo::Slot) {
721 void* obj = object;
721 void* obj = object;
722 bool result = false;
722 bool result = false;
723 void* args[2];
723 void* args[2];
724 args[0] = &result;
724 args[0] = &result;
725 args[1] = &obj;
725 args[1] = &obj;
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
727 return !result;
727 return !result;
728 } else {
728 } else {
729 return false;
729 return false;
730 }
730 }
731 }
731 }
732
732
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
734 {
734 {
735 if (!_polymorphicHandlers.isEmpty()) {
735 if (!_polymorphicHandlers.isEmpty()) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
737 void* resultPtr = (*cb)(ptr, resultClassName);
737 void* resultPtr = (*cb)(ptr, resultClassName);
738 if (resultPtr) {
738 if (resultPtr) {
739 return resultPtr;
739 return resultPtr;
740 }
740 }
741 }
741 }
742 }
742 }
743 foreach(const ParentClassInfo& info, _parentClasses) {
743 foreach(const ParentClassInfo& info, _parentClasses) {
744 if (!info._parent->isQObject()) {
744 if (!info._parent->isQObject()) {
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
746 if (resultPtr) {
746 if (resultPtr) {
747 return resultPtr;
747 return resultPtr;
748 }
748 }
749 }
749 }
750 }
750 }
751 return NULL;
751 return NULL;
752 }
752 }
753
753
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
755 {
755 {
756 char* className;
756 char* className;
757 // this would do downcasting recursively...
757 // this would do downcasting recursively...
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
759
759
760 // we only do downcasting on the base object, not on the whole inheritance tree...
760 // we only do downcasting on the base object, not on the whole inheritance tree...
761 void* resultPtr = NULL;
761 void* resultPtr = NULL;
762 if (!_polymorphicHandlers.isEmpty()) {
762 if (!_polymorphicHandlers.isEmpty()) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
764 resultPtr = (*cb)(ptr, &className);
764 resultPtr = (*cb)(ptr, &className);
765 if (resultPtr) {
765 if (resultPtr) {
766 break;
766 break;
767 }
767 }
768 }
768 }
769 }
769 }
770 if (resultPtr) {
770 if (resultPtr) {
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
772 } else {
772 } else {
773 *resultClassInfo = this;
773 *resultClassInfo = this;
774 resultPtr = ptr;
774 resultPtr = ptr;
775 }
775 }
776 return resultPtr;
776 return resultPtr;
777 }
777 }
778
778
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
780 {
780 {
781 if (isLocalEnum) {
781 if (isLocalEnum) {
782 *isLocalEnum = true;
782 *isLocalEnum = true;
783 }
783 }
784 int scopePos = name.lastIndexOf("::");
784 int scopePos = name.lastIndexOf("::");
785 if (scopePos != -1) {
785 if (scopePos != -1) {
786 if (isLocalEnum) {
786 if (isLocalEnum) {
787 *isLocalEnum = false;
787 *isLocalEnum = false;
788 }
788 }
789 // split into scope and enum name
789 // split into scope and enum name
790 QByteArray enumScope = name.mid(0,scopePos);
790 QByteArray enumScope = name.mid(0,scopePos);
791 QByteArray enumName = name.mid(scopePos+2);
791 QByteArray enumName = name.mid(scopePos+2);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
793 if (info) {
793 if (info) {
794 return info->findEnumWrapper(enumName);
794 return info->findEnumWrapper(enumName);
795 } else{
795 } else{
796 return NULL;
796 return NULL;
797 }
797 }
798 }
798 }
799 if (localScope) {
799 if (localScope) {
800 return localScope->findEnumWrapper(name);
800 return localScope->findEnumWrapper(name);
801 } else {
801 } else {
802 return NULL;
802 return NULL;
803 }
803 }
804 }
804 }
805
805
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
807 {
807 {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
809 QMetaEnum e = meta->enumerator(i);
809 QMetaEnum e = meta->enumerator(i);
810 PythonQtObjectPtr p;
810 PythonQtObjectPtr p;
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
812 _enumWrappers.append(p);
812 _enumWrappers.append(p);
813 }
813 }
814 }
814 }
815
815
816 void PythonQtClassInfo::createEnumWrappers()
816 void PythonQtClassInfo::createEnumWrappers()
817 {
817 {
818 if (!_enumsCreated) {
818 if (!_enumsCreated) {
819 _enumsCreated = true;
819 _enumsCreated = true;
820 if (_meta) {
820 if (_meta) {
821 createEnumWrappers(_meta);
821 createEnumWrappers(_meta);
822 }
822 }
823 if (decorator()) {
823 if (decorator()) {
824 createEnumWrappers(decorator()->metaObject());
824 createEnumWrappers(decorator()->metaObject());
825 }
825 }
826 foreach(const ParentClassInfo& info, _parentClasses) {
826 foreach(const ParentClassInfo& info, _parentClasses) {
827 info._parent->createEnumWrappers();
827 info._parent->createEnumWrappers();
828 }
828 }
829 }
829 }
830 }
830 }
831
831
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
833 // force enum creation
833 // force enum creation
834 if (!_enumsCreated) {
834 if (!_enumsCreated) {
835 createEnumWrappers();
835 createEnumWrappers();
836 }
836 }
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
839 if (qstrcmp(className, name)==0) {
839 if (qstrcmp(className, name)==0) {
840 return p.object();
840 return p.object();
841 }
841 }
842 }
842 }
843 foreach(const ParentClassInfo& info, _parentClasses) {
843 foreach(const ParentClassInfo& info, _parentClasses) {
844 PyObject* p = info._parent->findEnumWrapper(name);
844 PyObject* p = info._parent->findEnumWrapper(name);
845 if (p) return p;
845 if (p) return p;
846 }
846 }
847 return NULL;
847 return NULL;
848 }
848 }
849
849
@@ -1,262 +1,262
1 #ifndef _PYTHONQTCLASSINFO_H
1 #ifndef _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 #include <QMetaObject>
36 #include <QMetaObject>
37 #include <QMetaMethod>
37 #include <QMetaMethod>
38 #include <QHash>
38 #include <QHash>
39 #include <QByteArray>
39 #include <QByteArray>
40 #include <QList>
40 #include <QList>
41 #include "PythonQt.h"
41 #include "PythonQt.h"
42
42
43 class PythonQtSlotInfo;
43 class PythonQtSlotInfo;
44
44
45 struct PythonQtMemberInfo {
45 struct PythonQtMemberInfo {
46 enum Type {
46 enum Type {
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
48 };
48 };
49
49
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51
51
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
53 _type = Slot;
53 _type = Slot;
54 _slot = info;
54 _slot = info;
55 _enumValue = NULL;
55 _enumValue = NULL;
56 }
56 }
57
57
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
59 _type = EnumValue;
59 _type = EnumValue;
60 _slot = NULL;
60 _slot = NULL;
61 _enumValue = enumValue;
61 _enumValue = enumValue;
62 _enumWrapper = NULL;
62 _enumWrapper = NULL;
63 }
63 }
64
64
65 PythonQtMemberInfo(const QMetaProperty& prop) {
65 PythonQtMemberInfo(const QMetaProperty& prop) {
66 _type = Property;
66 _type = Property;
67 _slot = NULL;
67 _slot = NULL;
68 _enumValue = NULL;
68 _enumValue = NULL;
69 _property = prop;
69 _property = prop;
70 _enumWrapper = NULL;
70 _enumWrapper = NULL;
71 }
71 }
72
72
73 Type _type;
73 Type _type;
74
74
75 // TODO: this could be a union...
75 // TODO: this could be a union...
76 PythonQtSlotInfo* _slot;
76 PythonQtSlotInfo* _slot;
77 PyObject* _enumWrapper;
77 PyObject* _enumWrapper;
78 PythonQtObjectPtr _enumValue;
78 PythonQtObjectPtr _enumValue;
79 QMetaProperty _property;
79 QMetaProperty _property;
80 };
80 };
81
81
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
83 /*! for fast lookup of slots when calling the object from Python
83 /*! for fast lookup of slots when calling the object from Python
84 */
84 */
85 class PythonQtClassInfo {
85 class PythonQtClassInfo {
86
86
87 public:
87 public:
88 PythonQtClassInfo();
88 PythonQtClassInfo();
89 ~PythonQtClassInfo();
89 ~PythonQtClassInfo();
90
90
91 //! store information about parent classes
91 //! store information about parent classes
92 struct ParentClassInfo {
92 struct ParentClassInfo {
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 {};
94 {};
95
95
96 PythonQtClassInfo* _parent;
96 PythonQtClassInfo* _parent;
97 int _upcastingOffset;
97 int _upcastingOffset;
98 };
98 };
99
99
100
100
101 //! setup as a QObject, taking the meta object as meta information about the QObject
101 //! setup as a QObject, taking the meta object as meta information about the QObject
102 void setupQObject(const QMetaObject* meta);
102 void setupQObject(const QMetaObject* meta);
103
103
104 //! setup as a CPP (non-QObject), taking the classname
104 //! setup as a CPP (non-QObject), taking the classname
105 void setupCPPObject(const QByteArray& classname);
105 void setupCPPObject(const QByteArray& classname);
106
106
107 //! set the type capabilities
107 //! set the type capabilities
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
109 //! get the type capabilities
109 //! get the type capabilities
110 int typeSlots() const { return _typeSlots; }
110 int typeSlots() const { return _typeSlots; }
111
111
112 //! get the Python method definition for a given slot name (without return type and signature)
112 //! get the Python method definition for a given slot name (without return type and signature)
113 PythonQtMemberInfo member(const char* member);
113 PythonQtMemberInfo member(const char* member);
114
114
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
116 PythonQtSlotInfo* constructors();
116 PythonQtSlotInfo* constructors();
117
117
118 //! get access to the destructor slot
118 //! get access to the destructor slot
119 PythonQtSlotInfo* destructor();
119 PythonQtSlotInfo* destructor();
120
120
121 //! add a constructor, ownership is passed to classinfo
121 //! add a constructor, ownership is passed to classinfo
122 void addConstructor(PythonQtSlotInfo* info);
122 void addConstructor(PythonQtSlotInfo* info);
123
123
124 //! set a destructor, ownership is passed to classinfo
124 //! set a destructor, ownership is passed to classinfo
125 void setDestructor(PythonQtSlotInfo* info);
125 void setDestructor(PythonQtSlotInfo* info);
126
126
127 //! add a decorator slot, ownership is passed to classinfo
127 //! add a decorator slot, ownership is passed to classinfo
128 void addDecoratorSlot(PythonQtSlotInfo* info);
128 void addDecoratorSlot(PythonQtSlotInfo* info);
129
129
130 //! get the classname (either of the QObject or of the wrapped CPP object)
130 //! get the classname (either of the QObject or of the wrapped CPP object)
131 const char* className();
131 const char* className();
132
132
133 //! returns if the QObject
133 //! returns if the QObject
134 bool isQObject() { return _isQObject; }
134 bool isQObject() { return _isQObject; }
135
135
136 //! returns if the class is a CPP wrapper
136 //! returns if the class is a CPP wrapper
137 bool isCPPWrapper() { return !_isQObject; }
137 bool isCPPWrapper() { return !_isQObject; }
138
138
139 //! get the meta object
139 //! get the meta object
140 const QMetaObject* metaObject() { return _meta; }
140 const QMetaObject* metaObject() { return _meta; }
141
141
142 //! set the meta object, this will reset the caching
142 //! set the meta object, this will reset the caching
143 void setMetaObject(const QMetaObject* meta);
143 void setMetaObject(const QMetaObject* meta);
144
144
145 //! returns if this class inherits from the given classname
145 //! returns if this class inherits from the given classname
146 bool inherits(const char* classname);
146 bool inherits(const char* classname);
147
147
148 //! returns if this class inherits from the given classinfo
148 //! returns if this class inherits from the given classinfo
149 bool inherits(PythonQtClassInfo* info);
149 bool inherits(PythonQtClassInfo* info);
150
150
151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
152 //! which might be different to \c ptr due to C++ multiple inheritance
152 //! which might be different to \c ptr due to C++ multiple inheritance
153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
154 void* castTo(void* ptr, const char* classname);
154 void* castTo(void* ptr, const char* classname);
155
155
156 //! get help string for the metaobject
156 //! get help string for the metaobject
157 QString help();
157 QString help();
158
158
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
160 QStringList propertyList();
160 QStringList propertyList();
161
161
162 //! get list of all members
162 //! get list of all members
163 QStringList memberList(bool metaOnly = false);
163 QStringList memberList(bool metaOnly = false);
164
164
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
166 int metaTypeId() { return _metaTypeId; }
166 int metaTypeId() { return _metaTypeId; }
167
167
168 //! set an additional decorator provider that offers additional decorator slots for this class
168 //! set an additional decorator provider that offers additional decorator slots for this class
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
170
170
171 //! get the decorator qobject instance
171 //! get the decorator qobject instance
172 QObject* decorator();
172 QObject* decorator();
173
173
174 //! add the parent class info of a CPP object
174 //! add the parent class info of a CPP object
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
176
176
177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
178 bool hasOwnerMethodButNoOwner(void* object);
178 bool hasOwnerMethodButNoOwner(void* object);
179
179
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
182
182
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
185
185
186 //! set the shell set instance wrapper cb
186 //! set the shell set instance wrapper cb
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
188 _shellSetInstanceWrapperCB = cb;
188 _shellSetInstanceWrapperCB = cb;
189 }
189 }
190
190
191 //! get the shell set instance wrapper cb
191 //! get the shell set instance wrapper cb
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
193 return _shellSetInstanceWrapperCB;
193 return _shellSetInstanceWrapperCB;
194 }
194 }
195
195
196 //! add a handler for polymorphic downcasting
196 //! add a handler for polymorphic downcasting
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
198
198
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
201
201
202 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
202 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
204
204
205 private:
205 private:
206 void createEnumWrappers();
206 void createEnumWrappers();
207 void createEnumWrappers(const QMetaObject* meta);
207 void createEnumWrappers(const QMetaObject* meta);
208 PyObject* findEnumWrapper(const char* name);
208 PyObject* findEnumWrapper(const char* name);
209
209
210 //! clear all cached members
210 //! clear all cached members
211 void clearCachedMembers();
211 void clearCachedMembers();
212
212
213 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
213 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
214
214
215 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
215 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
216 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
216 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
217 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
217 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
218
218
219 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
219 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
220 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
220 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
221
221
222 bool lookForPropertyAndCache(const char* memberName);
222 bool lookForPropertyAndCache(const char* memberName);
223 bool lookForMethodAndCache(const char* memberName);
223 bool lookForMethodAndCache(const char* memberName);
224 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
224 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
225
225
226 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
226 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
227 int findCharOffset(const char* sigStart, char someChar);
227 int findCharOffset(const char* sigStart, char someChar);
228
228
229 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
229 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
230
230
231 PythonQtSlotInfo* _constructors;
231 PythonQtSlotInfo* _constructors;
232 PythonQtSlotInfo* _destructor;
232 PythonQtSlotInfo* _destructor;
233 QList<PythonQtSlotInfo*> _decoratorSlots;
233 QList<PythonQtSlotInfo*> _decoratorSlots;
234
234
235 QList<PythonQtObjectPtr> _enumWrappers;
235 QList<PythonQtObjectPtr> _enumWrappers;
236
236
237 const QMetaObject* _meta;
237 const QMetaObject* _meta;
238
238
239 QByteArray _wrappedClassName;
239 QByteArray _wrappedClassName;
240 QList<ParentClassInfo> _parentClasses;
240 QList<ParentClassInfo> _parentClasses;
241
241
242 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
242 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
243
243
244 QObject* _decoratorProvider;
244 QObject* _decoratorProvider;
245 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
245 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
246
246
247 PyObject* _pythonQtClassWrapper;
247 PyObject* _pythonQtClassWrapper;
248
248
249 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
249 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
250
250
251 int _metaTypeId;
251 int _metaTypeId;
252 int _typeSlots;
252 int _typeSlots;
253
253
254 bool _isQObject;
254 bool _isQObject;
255 bool _enumsCreated;
255 bool _enumsCreated;
256
256
257 };
257 };
258
258
259 //---------------------------------------------------------------
259 //---------------------------------------------------------------
260
260
261
261
262 #endif
262 #endif
@@ -1,454 +1,454
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtClassWrapper.cpp
35 // \file PythonQtClassWrapper.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassWrapper.h"
42 #include "PythonQtClassWrapper.h"
43 #include <QObject>
43 #include <QObject>
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtSlot.h"
46 #include "PythonQtSlot.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtInstanceWrapper.h"
49 #include "PythonQtInstanceWrapper.h"
50
50
51 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
51 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
52 {
52 {
53 PyObject* result = NULL;
53 PyObject* result = NULL;
54 static QByteArray memberName = "__invert__";
54 static QByteArray memberName = "__invert__";
55 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
55 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
56 if (opSlot._type == PythonQtMemberInfo::Slot) {
56 if (opSlot._type == PythonQtMemberInfo::Slot) {
57 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
57 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
58 }
58 }
59 return result;
59 return result;
60 }
60 }
61
61
62 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
62 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
63 {
63 {
64 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
64 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
65 if (result) {
65 if (result) {
66 static QByteArray memberName = "__nonzero__";
66 static QByteArray memberName = "__nonzero__";
67 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
67 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
68 if (opSlot._type == PythonQtMemberInfo::Slot) {
68 if (opSlot._type == PythonQtMemberInfo::Slot) {
69 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
69 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
70 if (resultObj == Py_False) {
70 if (resultObj == Py_False) {
71 result = 0;
71 result = 0;
72 }
72 }
73 Py_XDECREF(resultObj);
73 Py_XDECREF(resultObj);
74 }
74 }
75 }
75 }
76 return result;
76 return result;
77 }
77 }
78
78
79
79
80 static PyObject* PythonQtInstanceWrapper_binaryfunc(PythonQtInstanceWrapper* wrapper, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
80 static PyObject* PythonQtInstanceWrapper_binaryfunc(PythonQtInstanceWrapper* wrapper, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
81 {
81 {
82 PyObject* result = NULL;
82 PyObject* result = NULL;
83 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
83 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
84 if (opSlot._type == PythonQtMemberInfo::Slot) {
84 if (opSlot._type == PythonQtMemberInfo::Slot) {
85 // TODO get rid of tuple
85 // TODO get rid of tuple
86 PyObject* args = PyTuple_New(1);
86 PyObject* args = PyTuple_New(1);
87 Py_INCREF(other);
87 Py_INCREF(other);
88 PyTuple_SET_ITEM(args, 0, other);
88 PyTuple_SET_ITEM(args, 0, other);
89 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
89 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
90 Py_DECREF(args);
90 Py_DECREF(args);
91 if (!result && !fallbackOpName.isEmpty()) {
91 if (!result && !fallbackOpName.isEmpty()) {
92 // try fallback if we did not get a result
92 // try fallback if we did not get a result
93 result = PythonQtInstanceWrapper_binaryfunc(wrapper, other, fallbackOpName);
93 result = PythonQtInstanceWrapper_binaryfunc(wrapper, other, fallbackOpName);
94 }
94 }
95 }
95 }
96 return result;
96 return result;
97 }
97 }
98
98
99 #define BINARY_OP(NAME) \
99 #define BINARY_OP(NAME) \
100 static PyObject* PythonQtInstanceWrapper_ ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \
100 static PyObject* PythonQtInstanceWrapper_ ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \
101 { \
101 { \
102 static const QByteArray opName("__" #NAME "__"); \
102 static const QByteArray opName("__" #NAME "__"); \
103 return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName); \
103 return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName); \
104 }
104 }
105
105
106 #define BINARY_OP_INPLACE(NAME) \
106 #define BINARY_OP_INPLACE(NAME) \
107 static PyObject* PythonQtInstanceWrapper_i ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \
107 static PyObject* PythonQtInstanceWrapper_i ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \
108 { \
108 { \
109 static const QByteArray opName("__i" #NAME "__"); \
109 static const QByteArray opName("__i" #NAME "__"); \
110 static const QByteArray fallbackName("__" #NAME "__"); \
110 static const QByteArray fallbackName("__" #NAME "__"); \
111 return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName, fallbackName); \
111 return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName, fallbackName); \
112 }
112 }
113
113
114 BINARY_OP(add)
114 BINARY_OP(add)
115 BINARY_OP(sub)
115 BINARY_OP(sub)
116 BINARY_OP(mul)
116 BINARY_OP(mul)
117 BINARY_OP(div)
117 BINARY_OP(div)
118 BINARY_OP(and)
118 BINARY_OP(and)
119 BINARY_OP(or)
119 BINARY_OP(or)
120 BINARY_OP(xor)
120 BINARY_OP(xor)
121 BINARY_OP(mod)
121 BINARY_OP(mod)
122 BINARY_OP(lshift)
122 BINARY_OP(lshift)
123 BINARY_OP(rshift)
123 BINARY_OP(rshift)
124
124
125 BINARY_OP_INPLACE(add)
125 BINARY_OP_INPLACE(add)
126 BINARY_OP_INPLACE(sub)
126 BINARY_OP_INPLACE(sub)
127 BINARY_OP_INPLACE(mul)
127 BINARY_OP_INPLACE(mul)
128 BINARY_OP_INPLACE(div)
128 BINARY_OP_INPLACE(div)
129 BINARY_OP_INPLACE(and)
129 BINARY_OP_INPLACE(and)
130 BINARY_OP_INPLACE(or)
130 BINARY_OP_INPLACE(or)
131 BINARY_OP_INPLACE(xor)
131 BINARY_OP_INPLACE(xor)
132 BINARY_OP_INPLACE(mod)
132 BINARY_OP_INPLACE(mod)
133 BINARY_OP_INPLACE(lshift)
133 BINARY_OP_INPLACE(lshift)
134 BINARY_OP_INPLACE(rshift)
134 BINARY_OP_INPLACE(rshift)
135
135
136 static void initializeSlots(PythonQtClassWrapper* wrap)
136 static void initializeSlots(PythonQtClassWrapper* wrap)
137 {
137 {
138 int typeSlots = wrap->classInfo()->typeSlots();
138 int typeSlots = wrap->classInfo()->typeSlots();
139 if (typeSlots) {
139 if (typeSlots) {
140 if (typeSlots & PythonQt::Type_Add) {
140 if (typeSlots & PythonQt::Type_Add) {
141 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
141 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
142 }
142 }
143 if (typeSlots & PythonQt::Type_Subtract) {
143 if (typeSlots & PythonQt::Type_Subtract) {
144 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
144 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
145 }
145 }
146 if (typeSlots & PythonQt::Type_Multiply) {
146 if (typeSlots & PythonQt::Type_Multiply) {
147 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
147 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
148 }
148 }
149 if (typeSlots & PythonQt::Type_Divide) {
149 if (typeSlots & PythonQt::Type_Divide) {
150 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
150 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
151 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
151 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
152 }
152 }
153 if (typeSlots & PythonQt::Type_And) {
153 if (typeSlots & PythonQt::Type_And) {
154 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
154 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
155 }
155 }
156 if (typeSlots & PythonQt::Type_Or) {
156 if (typeSlots & PythonQt::Type_Or) {
157 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
157 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
158 }
158 }
159 if (typeSlots & PythonQt::Type_Xor) {
159 if (typeSlots & PythonQt::Type_Xor) {
160 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
160 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
161 }
161 }
162 if (typeSlots & PythonQt::Type_Mod) {
162 if (typeSlots & PythonQt::Type_Mod) {
163 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
163 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
164 }
164 }
165 if (typeSlots & PythonQt::Type_LShift) {
165 if (typeSlots & PythonQt::Type_LShift) {
166 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
166 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
167 }
167 }
168 if (typeSlots & PythonQt::Type_RShift) {
168 if (typeSlots & PythonQt::Type_RShift) {
169 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
169 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
170 }
170 }
171
171
172 if (typeSlots & PythonQt::Type_InplaceAdd) {
172 if (typeSlots & PythonQt::Type_InplaceAdd) {
173 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
173 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
174 }
174 }
175 if (typeSlots & PythonQt::Type_InplaceSubtract) {
175 if (typeSlots & PythonQt::Type_InplaceSubtract) {
176 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
176 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
177 }
177 }
178 if (typeSlots & PythonQt::Type_InplaceMultiply) {
178 if (typeSlots & PythonQt::Type_InplaceMultiply) {
179 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
179 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
180 }
180 }
181 if (typeSlots & PythonQt::Type_InplaceDivide) {
181 if (typeSlots & PythonQt::Type_InplaceDivide) {
182 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
182 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
183 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
183 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
184 }
184 }
185 if (typeSlots & PythonQt::Type_InplaceAnd) {
185 if (typeSlots & PythonQt::Type_InplaceAnd) {
186 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
186 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
187 }
187 }
188 if (typeSlots & PythonQt::Type_InplaceOr) {
188 if (typeSlots & PythonQt::Type_InplaceOr) {
189 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
189 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
190 }
190 }
191 if (typeSlots & PythonQt::Type_InplaceXor) {
191 if (typeSlots & PythonQt::Type_InplaceXor) {
192 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
192 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
193 }
193 }
194 if (typeSlots & PythonQt::Type_InplaceMod) {
194 if (typeSlots & PythonQt::Type_InplaceMod) {
195 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
195 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
196 }
196 }
197 if (typeSlots & PythonQt::Type_InplaceLShift) {
197 if (typeSlots & PythonQt::Type_InplaceLShift) {
198 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
198 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
199 }
199 }
200 if (typeSlots & PythonQt::Type_InplaceRShift) {
200 if (typeSlots & PythonQt::Type_InplaceRShift) {
201 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
201 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
202 }
202 }
203 if (typeSlots & PythonQt::Type_Invert) {
203 if (typeSlots & PythonQt::Type_Invert) {
204 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
204 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
205 }
205 }
206 if (typeSlots & PythonQt::Type_NonZero) {
206 if (typeSlots & PythonQt::Type_NonZero) {
207 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
207 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
208 }
208 }
209 }
209 }
210 }
210 }
211
211
212 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
212 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
213 {
213 {
214 // call the default type alloc
214 // call the default type alloc
215 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
215 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
216
216
217 // take current class type, if we are called via newPythonQtClassWrapper()
217 // take current class type, if we are called via newPythonQtClassWrapper()
218 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
218 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
219 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
219 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
220 if (wrap->_classInfo) {
220 if (wrap->_classInfo) {
221 initializeSlots(wrap);
221 initializeSlots(wrap);
222 }
222 }
223
223
224 return obj;
224 return obj;
225 }
225 }
226
226
227
227
228 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
228 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
229 {
229 {
230 // call the default type init
230 // call the default type init
231 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
231 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
232 return -1;
232 return -1;
233 }
233 }
234
234
235 // if we have no CPP class information, try our base class
235 // if we have no CPP class information, try our base class
236 if (!self->classInfo()) {
236 if (!self->classInfo()) {
237 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
237 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
238
238
239 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
239 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
240 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
240 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
241 return -1;
241 return -1;
242 }
242 }
243
243
244 // take the class info from the superType
244 // take the class info from the superType
245 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
245 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
246 }
246 }
247
247
248 return 0;
248 return 0;
249 }
249 }
250
250
251 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
251 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
252 {
252 {
253 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
253 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
254 }
254 }
255
255
256 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
256 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
257 {
257 {
258 return PythonQt::self()->helpCalled(type->classInfo());
258 return PythonQt::self()->helpCalled(type->classInfo());
259 }
259 }
260
260
261 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
261 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
262 {
262 {
263 Py_ssize_t argc = PyTuple_Size(args);
263 Py_ssize_t argc = PyTuple_Size(args);
264 if (argc>0) {
264 if (argc>0) {
265 // we need to call __init__ of the instance
265 // we need to call __init__ of the instance
266 PyObject* self = PyTuple_GET_ITEM(args, 0);
266 PyObject* self = PyTuple_GET_ITEM(args, 0);
267 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
267 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
268 PyObject* newargs = PyTuple_New(argc-1);
268 PyObject* newargs = PyTuple_New(argc-1);
269 for (int i = 0;i<argc-1; i++) {
269 for (int i = 0;i<argc-1; i++) {
270 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
270 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
271 }
271 }
272 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
272 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
273 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
273 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
274 Py_DECREF(newargs);
274 Py_DECREF(newargs);
275 if (result==0) {
275 if (result==0) {
276 Py_INCREF(Py_None);
276 Py_INCREF(Py_None);
277 return Py_None;
277 return Py_None;
278 } else {
278 } else {
279 // init failed!
279 // init failed!
280 }
280 }
281 } else {
281 } else {
282 // self not of correct type!
282 // self not of correct type!
283 }
283 }
284 } else {
284 } else {
285 // wrong number of args
285 // wrong number of args
286 }
286 }
287 return NULL;
287 return NULL;
288 }
288 }
289
289
290 static PyMethodDef PythonQtClassWrapper_methods[] = {
290 static PyMethodDef PythonQtClassWrapper_methods[] = {
291 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
291 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
292 "Return the classname of the object"
292 "Return the classname of the object"
293 },
293 },
294 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
294 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
295 "Return the classname of the object"
295 "Return the classname of the object"
296 },
296 },
297 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
297 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
298 "Shows the help of available methods for this class"
298 "Shows the help of available methods for this class"
299 },
299 },
300 {NULL, NULL, 0 , NULL} /* Sentinel */
300 {NULL, NULL, 0 , NULL} /* Sentinel */
301 };
301 };
302
302
303
303
304 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
304 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
305 {
305 {
306 const char *attributeName;
306 const char *attributeName;
307 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
307 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
308
308
309 if ((attributeName = PyString_AsString(name)) == NULL) {
309 if ((attributeName = PyString_AsString(name)) == NULL) {
310 return NULL;
310 return NULL;
311 }
311 }
312 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
312 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
313 return NULL;
313 return NULL;
314 }
314 }
315
315
316 if (qstrcmp(attributeName, "__dict__")==0) {
316 if (qstrcmp(attributeName, "__dict__")==0) {
317 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
317 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
318 if (!wrapper->classInfo()) {
318 if (!wrapper->classInfo()) {
319 Py_INCREF(dict);
319 Py_INCREF(dict);
320 return dict;
320 return dict;
321 }
321 }
322 dict = PyDict_Copy(dict);
322 dict = PyDict_Copy(dict);
323
323
324 QStringList l = wrapper->classInfo()->memberList(false);
324 QStringList l = wrapper->classInfo()->memberList(false);
325 foreach (QString name, l) {
325 foreach (QString name, l) {
326 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
326 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
327 if (o) {
327 if (o) {
328 PyDict_SetItemString(dict, name.toLatin1().data(), o);
328 PyDict_SetItemString(dict, name.toLatin1().data(), o);
329 Py_DECREF(o);
329 Py_DECREF(o);
330 } else {
330 } else {
331 // it must have been a property or child, which we do not know as a class object...
331 // it must have been a property or child, which we do not know as a class object...
332 }
332 }
333 }
333 }
334 if (wrapper->classInfo()->constructors()) {
334 if (wrapper->classInfo()->constructors()) {
335 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[0], obj);
335 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[0], obj);
336 PyDict_SetItemString(dict, "__init__", func);
336 PyDict_SetItemString(dict, "__init__", func);
337 Py_DECREF(func);
337 Py_DECREF(func);
338 }
338 }
339 for (int i = 1;i<3;i++) {
339 for (int i = 1;i<3;i++) {
340 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
340 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
341 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
341 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
342 Py_DECREF(func);
342 Py_DECREF(func);
343 }
343 }
344 return dict;
344 return dict;
345 }
345 }
346
346
347 if (wrapper->classInfo()) {
347 if (wrapper->classInfo()) {
348 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
348 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
349 if (member._type == PythonQtMemberInfo::EnumValue) {
349 if (member._type == PythonQtMemberInfo::EnumValue) {
350 PyObject* enumValue = member._enumValue;
350 PyObject* enumValue = member._enumValue;
351 Py_INCREF(enumValue);
351 Py_INCREF(enumValue);
352 return enumValue;
352 return enumValue;
353 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
353 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
354 PyObject* enumWrapper = member._enumWrapper;
354 PyObject* enumWrapper = member._enumWrapper;
355 Py_INCREF(enumWrapper);
355 Py_INCREF(enumWrapper);
356 return enumWrapper;
356 return enumWrapper;
357 } else if (member._type == PythonQtMemberInfo::Slot) {
357 } else if (member._type == PythonQtMemberInfo::Slot) {
358 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
358 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
359 return PythonQtSlotFunction_New(member._slot, obj, NULL);
359 return PythonQtSlotFunction_New(member._slot, obj, NULL);
360 }
360 }
361 }
361 }
362
362
363 // look for the interal methods (className(), help())
363 // look for the interal methods (className(), help())
364 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
364 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
365 if (internalMethod) {
365 if (internalMethod) {
366 return internalMethod;
366 return internalMethod;
367 }
367 }
368 PyErr_Clear();
368 PyErr_Clear();
369
369
370 // look in super
370 // look in super
371 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
371 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
372 if (superAttr) {
372 if (superAttr) {
373 return superAttr;
373 return superAttr;
374 }
374 }
375
375
376 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
376 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
377 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
377 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
378 return NULL;
378 return NULL;
379 }
379 }
380
380
381 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
381 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
382 {
382 {
383 return PyType_Type.tp_setattro(obj,name,value);
383 return PyType_Type.tp_setattro(obj,name,value);
384 }
384 }
385
385
386 /*
386 /*
387 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
387 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
388 {
388 {
389 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
389 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
390 if (wrapper->classInfo()->isCPPWrapper()) {
390 if (wrapper->classInfo()->isCPPWrapper()) {
391 const QMetaObject* meta = wrapper->classInfo()->metaObject();
391 const QMetaObject* meta = wrapper->classInfo()->metaObject();
392 if (!meta) {
392 if (!meta) {
393 QObject* decorator = wrapper->classInfo()->decorator();
393 QObject* decorator = wrapper->classInfo()->decorator();
394 if (decorator) {
394 if (decorator) {
395 meta = decorator->metaObject();
395 meta = decorator->metaObject();
396 }
396 }
397 }
397 }
398 if (meta) {
398 if (meta) {
399 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
399 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
400 } else {
400 } else {
401 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
401 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
402 }
402 }
403 } else {
403 } else {
404 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
404 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
405 }
405 }
406 }
406 }
407
407
408 */
408 */
409
409
410 PyTypeObject PythonQtClassWrapper_Type = {
410 PyTypeObject PythonQtClassWrapper_Type = {
411 PyObject_HEAD_INIT(NULL)
411 PyObject_HEAD_INIT(NULL)
412 0, /*ob_size*/
412 0, /*ob_size*/
413 "PythonQt.PythonQtClassWrapper", /*tp_name*/
413 "PythonQt.PythonQtClassWrapper", /*tp_name*/
414 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
414 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
415 0, /*tp_itemsize*/
415 0, /*tp_itemsize*/
416 0, /*tp_dealloc*/
416 0, /*tp_dealloc*/
417 0, /*tp_print*/
417 0, /*tp_print*/
418 0, /*tp_getattr*/
418 0, /*tp_getattr*/
419 0, /*tp_setattr*/
419 0, /*tp_setattr*/
420 0, /*tp_compare*/
420 0, /*tp_compare*/
421 0, //PythonQtClassWrapper_repr, /*tp_repr*/
421 0, //PythonQtClassWrapper_repr, /*tp_repr*/
422 0, /*tp_as_number*/
422 0, /*tp_as_number*/
423 0, /*tp_as_sequence*/
423 0, /*tp_as_sequence*/
424 0, /*tp_as_mapping*/
424 0, /*tp_as_mapping*/
425 0, /*tp_hash */
425 0, /*tp_hash */
426 0, /*tp_call*/
426 0, /*tp_call*/
427 0, /*tp_str*/
427 0, /*tp_str*/
428 PythonQtClassWrapper_getattro, /*tp_getattro*/
428 PythonQtClassWrapper_getattro, /*tp_getattro*/
429 PythonQtClassWrapper_setattro, /*tp_setattro*/
429 PythonQtClassWrapper_setattro, /*tp_setattro*/
430 0, /*tp_as_buffer*/
430 0, /*tp_as_buffer*/
431 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
431 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
432 0, /* tp_doc */
432 0, /* tp_doc */
433 0, /* tp_traverse */
433 0, /* tp_traverse */
434 0, /* tp_clear */
434 0, /* tp_clear */
435 0, /* tp_richcompare */
435 0, /* tp_richcompare */
436 0, /* tp_weaklistoffset */
436 0, /* tp_weaklistoffset */
437 0, /* tp_iter */
437 0, /* tp_iter */
438 0, /* tp_iternext */
438 0, /* tp_iternext */
439 0, /* tp_methods */
439 0, /* tp_methods */
440 0, /* tp_members */
440 0, /* tp_members */
441 0, /* tp_getset */
441 0, /* tp_getset */
442 0, /* tp_base */
442 0, /* tp_base */
443 0, /* tp_dict */
443 0, /* tp_dict */
444 0, /* tp_descr_get */
444 0, /* tp_descr_get */
445 0, /* tp_descr_set */
445 0, /* tp_descr_set */
446 0, /* tp_dictoffset */
446 0, /* tp_dictoffset */
447 (initproc)PythonQtClassWrapper_init, /* tp_init */
447 (initproc)PythonQtClassWrapper_init, /* tp_init */
448 PythonQtClassWrapper_alloc, /* tp_alloc */
448 PythonQtClassWrapper_alloc, /* tp_alloc */
449 0, /* tp_new */
449 0, /* tp_new */
450 0, /* tp_free */
450 0, /* tp_free */
451 };
451 };
452
452
453 //-------------------------------------------------------
453 //-------------------------------------------------------
454
454
@@ -1,77 +1,77
1 #ifndef _PYTHONQTCLASSWRAPPER_H
1 #ifndef _PYTHONQTCLASSWRAPPER_H
2 #define _PYTHONQTCLASSWRAPPER_H
2 #define _PYTHONQTCLASSWRAPPER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtClassWrapper.h
38 // \file PythonQtClassWrapper.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include <Python.h>
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48
48
49 #include "structmember.h"
49 #include "structmember.h"
50 #include "methodobject.h"
50 #include "methodobject.h"
51 #include "compile.h"
51 #include "compile.h"
52 #include "eval.h"
52 #include "eval.h"
53 #include <QString>
53 #include <QString>
54
54
55 class PythonQtClassInfo;
55 class PythonQtClassInfo;
56
56
57 //! the type of the PythonQt class wrapper objects
57 //! the type of the PythonQt class wrapper objects
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtClassWrapper_Type;
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtClassWrapper_Type;
59
59
60 //---------------------------------------------------------------
60 //---------------------------------------------------------------
61 //! a Python wrapper object for PythonQt wrapped classes
61 //! a Python wrapper object for PythonQt wrapped classes
62 //! which inherits from the Python type object to allow
62 //! which inherits from the Python type object to allow
63 //! deriving of wrapped CPP classes from Python.
63 //! deriving of wrapped CPP classes from Python.
64 typedef struct {
64 typedef struct {
65 PyHeapTypeObject _base;
65 PyHeapTypeObject _base;
66
66
67 //! the additional class information that PythonQt stores for the CPP class
67 //! the additional class information that PythonQt stores for the CPP class
68 PythonQtClassInfo* _classInfo;
68 PythonQtClassInfo* _classInfo;
69
69
70 //! get the class info
70 //! get the class info
71 PythonQtClassInfo* classInfo() { return _classInfo; }
71 PythonQtClassInfo* classInfo() { return _classInfo; }
72
72
73 } PythonQtClassWrapper;
73 } PythonQtClassWrapper;
74
74
75 //---------------------------------------------------------------
75 //---------------------------------------------------------------
76
76
77 #endif
77 #endif
@@ -1,1228 +1,1228
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtConversion.cpp
35 // \file PythonQtConversion.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 // is it an enum value?
63 // is it an enum value?
64 if (info.enumWrapper) {
64 if (info.enumWrapper) {
65 if (!info.isPointer) {
65 if (!info.isPointer) {
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 } else {
67 } else {
68 // we do not support pointers to enums (who needs them?)
68 // we do not support pointers to enums (who needs them?)
69 Py_INCREF(Py_None);
69 Py_INCREF(Py_None);
70 return Py_None;
70 return Py_None;
71 }
71 }
72 }
72 }
73
73
74 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
75 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
76 return Py_None;
76 return Py_None;
77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
78 // a char ptr will probably be a null terminated string, so we support that:
78 // a char ptr will probably be a null terminated string, so we support that:
79 return PyString_FromString(*((char**)data));
79 return PyString_FromString(*((char**)data));
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
81 info.name.startsWith("QList<")) {
81 info.name.startsWith("QList<")) {
82 // it is a QList template:
82 // it is a QList template:
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
84 if (innerType.endsWith("*")) {
84 if (innerType.endsWith("*")) {
85 innerType.truncate(innerType.length()-1);
85 innerType.truncate(innerType.length()-1);
86 QList<void*>* listPtr;
86 QList<void*>* listPtr;
87 if (info.isPointer) {
87 if (info.isPointer) {
88 listPtr = *((QList<void*>**)data);
88 listPtr = *((QList<void*>**)data);
89 } else {
89 } else {
90 listPtr = (QList<void*>*)data;
90 listPtr = (QList<void*>*)data;
91 }
91 }
92 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
92 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
93 }
93 }
94 }
94 }
95
95
96 if (info.typeId >= QMetaType::User) {
96 if (info.typeId >= QMetaType::User) {
97 // if a converter is registered, we use is:
97 // if a converter is registered, we use is:
98 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
98 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
99 if (converter) {
99 if (converter) {
100 return (*converter)(data, info.typeId);
100 return (*converter)(data, info.typeId);
101 }
101 }
102 }
102 }
103
103
104 // special handling did not match, so we convert the usual way (either pointer or value version):
104 // special handling did not match, so we convert the usual way (either pointer or value version):
105 if (info.isPointer) {
105 if (info.isPointer) {
106 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
106 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
107 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
107 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
108 } else {
108 } else {
109 // handle values that are not yet handled and not pointers
109 // handle values that are not yet handled and not pointers
110 return ConvertQtValueToPythonInternal(info.typeId, data);
110 return ConvertQtValueToPythonInternal(info.typeId, data);
111 }
111 }
112 }
112 }
113
113
114 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
114 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
115 switch (type) {
115 switch (type) {
116 case QMetaType::Void:
116 case QMetaType::Void:
117 Py_INCREF(Py_None);
117 Py_INCREF(Py_None);
118 return Py_None;
118 return Py_None;
119 case QMetaType::Char:
119 case QMetaType::Char:
120 return PyInt_FromLong(*((char*)data));
120 return PyInt_FromLong(*((char*)data));
121 case QMetaType::UChar:
121 case QMetaType::UChar:
122 return PyInt_FromLong(*((unsigned char*)data));
122 return PyInt_FromLong(*((unsigned char*)data));
123 case QMetaType::Short:
123 case QMetaType::Short:
124 return PyInt_FromLong(*((short*)data));
124 return PyInt_FromLong(*((short*)data));
125 case QMetaType::UShort:
125 case QMetaType::UShort:
126 return PyInt_FromLong(*((unsigned short*)data));
126 return PyInt_FromLong(*((unsigned short*)data));
127 case QMetaType::Long:
127 case QMetaType::Long:
128 return PyInt_FromLong(*((long*)data));
128 return PyInt_FromLong(*((long*)data));
129 case QMetaType::ULong:
129 case QMetaType::ULong:
130 // does not fit into simple int of python
130 // does not fit into simple int of python
131 return PyLong_FromUnsignedLong(*((unsigned long*)data));
131 return PyLong_FromUnsignedLong(*((unsigned long*)data));
132 case QMetaType::Bool:
132 case QMetaType::Bool:
133 return PythonQtConv::GetPyBool(*((bool*)data));
133 return PythonQtConv::GetPyBool(*((bool*)data));
134 case QMetaType::Int:
134 case QMetaType::Int:
135 return PyInt_FromLong(*((int*)data));
135 return PyInt_FromLong(*((int*)data));
136 case QMetaType::UInt:
136 case QMetaType::UInt:
137 // does not fit into simple int of python
137 // does not fit into simple int of python
138 return PyLong_FromUnsignedLong(*((unsigned int*)data));
138 return PyLong_FromUnsignedLong(*((unsigned int*)data));
139 case QMetaType::QChar:
139 case QMetaType::QChar:
140 return PyInt_FromLong(*((short*)data));
140 return PyInt_FromLong(*((short*)data));
141 case QMetaType::Float:
141 case QMetaType::Float:
142 return PyFloat_FromDouble(*((float*)data));
142 return PyFloat_FromDouble(*((float*)data));
143 case QMetaType::Double:
143 case QMetaType::Double:
144 return PyFloat_FromDouble(*((double*)data));
144 return PyFloat_FromDouble(*((double*)data));
145 case QMetaType::LongLong:
145 case QMetaType::LongLong:
146 return PyLong_FromLongLong(*((qint64*)data));
146 return PyLong_FromLongLong(*((qint64*)data));
147 case QMetaType::ULongLong:
147 case QMetaType::ULongLong:
148 return PyLong_FromUnsignedLongLong(*((quint64*)data));
148 return PyLong_FromUnsignedLongLong(*((quint64*)data));
149 // implicit conversion from QByteArray to str has been removed:
149 // implicit conversion from QByteArray to str has been removed:
150 //case QMetaType::QByteArray: {
150 //case QMetaType::QByteArray: {
151 // QByteArray* v = (QByteArray*) data;
151 // QByteArray* v = (QByteArray*) data;
152 // return PyString_FromStringAndSize(*v, v->size());
152 // return PyString_FromStringAndSize(*v, v->size());
153 // }
153 // }
154 case QMetaType::QVariantMap:
154 case QMetaType::QVariantMap:
155 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
155 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
156 case QMetaType::QVariantList:
156 case QMetaType::QVariantList:
157 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
157 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
158 case QMetaType::QString:
158 case QMetaType::QString:
159 return PythonQtConv::QStringToPyObject(*((QString*)data));
159 return PythonQtConv::QStringToPyObject(*((QString*)data));
160 case QMetaType::QStringList:
160 case QMetaType::QStringList:
161 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
161 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
162
162
163 case PythonQtMethodInfo::Variant:
163 case PythonQtMethodInfo::Variant:
164 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
164 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
165 case QMetaType::QObjectStar:
165 case QMetaType::QObjectStar:
166 case QMetaType::QWidgetStar:
166 case QMetaType::QWidgetStar:
167 return PythonQt::priv()->wrapQObject(*((QObject**)data));
167 return PythonQt::priv()->wrapQObject(*((QObject**)data));
168
168
169 default:
169 default:
170 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
170 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
171 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
171 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
172 PyObject* o = ((PythonQtObjectPtr*)data)->object();
172 PyObject* o = ((PythonQtObjectPtr*)data)->object();
173 Py_INCREF(o);
173 Py_INCREF(o);
174 return o;
174 return o;
175 } else {
175 } else {
176 if (type > 0) {
176 if (type > 0) {
177 // if the type is known, we can construct it via QMetaType::construct
177 // if the type is known, we can construct it via QMetaType::construct
178 void* newCPPObject = QMetaType::construct(type, data);
178 void* newCPPObject = QMetaType::construct(type, data);
179 // XXX this could be optimized by using metatypeid directly
179 // XXX this could be optimized by using metatypeid directly
180 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
180 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
181 wrap->_ownedByPythonQt = true;
181 wrap->_ownedByPythonQt = true;
182 wrap->_useQMetaTypeDestroy = true;
182 wrap->_useQMetaTypeDestroy = true;
183 return (PyObject*)wrap;
183 return (PyObject*)wrap;
184 }
184 }
185 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
185 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
186 }
186 }
187 }
187 }
188 Py_INCREF(Py_None);
188 Py_INCREF(Py_None);
189 return Py_None;
189 return Py_None;
190 }
190 }
191
191
192 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
192 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
193 void* ptr = NULL;
193 void* ptr = NULL;
194 if (info.isPointer) {
194 if (info.isPointer) {
195 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
195 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
196 } else if (info.enumWrapper) {
196 } else if (info.enumWrapper) {
197 // create enum return value
197 // create enum return value
198 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
198 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
199 } else {
199 } else {
200 switch (info.typeId) {
200 switch (info.typeId) {
201 case QMetaType::Char:
201 case QMetaType::Char:
202 case QMetaType::UChar:
202 case QMetaType::UChar:
203 case QMetaType::Short:
203 case QMetaType::Short:
204 case QMetaType::UShort:
204 case QMetaType::UShort:
205 case QMetaType::Long:
205 case QMetaType::Long:
206 case QMetaType::ULong:
206 case QMetaType::ULong:
207 case QMetaType::Bool:
207 case QMetaType::Bool:
208 case QMetaType::Int:
208 case QMetaType::Int:
209 case QMetaType::UInt:
209 case QMetaType::UInt:
210 case QMetaType::QChar:
210 case QMetaType::QChar:
211 case QMetaType::Float:
211 case QMetaType::Float:
212 case QMetaType::Double:
212 case QMetaType::Double:
213 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
213 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
214 break;
214 break;
215 case PythonQtMethodInfo::Variant:
215 case PythonQtMethodInfo::Variant:
216 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
216 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
217 // return the ptr to the variant
217 // return the ptr to the variant
218 break;
218 break;
219 default:
219 default:
220 if (info.typeId == PythonQtMethodInfo::Unknown) {
220 if (info.typeId == PythonQtMethodInfo::Unknown) {
221 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
221 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
222 if (info.name.startsWith("QList<")) {
222 if (info.name.startsWith("QList<")) {
223 QByteArray innerType = info.name.mid(6,info.name.length()-7);
223 QByteArray innerType = info.name.mid(6,info.name.length()-7);
224 if (innerType.endsWith("*")) {
224 if (innerType.endsWith("*")) {
225 static int id = QMetaType::type("QList<void*>");
225 static int id = QMetaType::type("QList<void*>");
226 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
226 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
227 // return the constData pointer that will be filled with the result value later on
227 // return the constData pointer that will be filled with the result value later on
228 ptr = (void*)((QVariant*)ptr)->constData();
228 ptr = (void*)((QVariant*)ptr)->constData();
229 }
229 }
230 }
230 }
231 }
231 }
232
232
233 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
233 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
234 // everything else is stored in a QVariant, if we know the meta type...
234 // everything else is stored in a QVariant, if we know the meta type...
235 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
235 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
236 // return the constData pointer that will be filled with the result value later on
236 // return the constData pointer that will be filled with the result value later on
237 ptr = (void*)((QVariant*)ptr)->constData();
237 ptr = (void*)((QVariant*)ptr)->constData();
238 }
238 }
239 }
239 }
240 }
240 }
241 return ptr;
241 return ptr;
242 }
242 }
243
243
244 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
244 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
245 {
245 {
246 void* object;
246 void* object;
247 if (wrapper->classInfo()->isCPPWrapper()) {
247 if (wrapper->classInfo()->isCPPWrapper()) {
248 object = wrapper->_wrappedPtr;
248 object = wrapper->_wrappedPtr;
249 } else {
249 } else {
250 QObject* tmp = wrapper->_obj;
250 QObject* tmp = wrapper->_obj;
251 object = tmp;
251 object = tmp;
252 }
252 }
253 if (object) {
253 if (object) {
254 // if we can be upcasted to the given name, we pass the casted pointer in:
254 // if we can be upcasted to the given name, we pass the casted pointer in:
255 object = wrapper->classInfo()->castTo(object, className);
255 object = wrapper->classInfo()->castTo(object, className);
256 ok = object!=NULL;
256 ok = object!=NULL;
257 } else {
257 } else {
258 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
258 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
259 ok = wrapper->classInfo()->inherits(className);
259 ok = wrapper->classInfo()->inherits(className);
260 }
260 }
261 return object;
261 return object;
262 }
262 }
263
263
264 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
264 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
265 {
265 {
266 void* ptr = alreadyAllocatedCPPObject;
266 void* ptr = alreadyAllocatedCPPObject;
267
267
268 static int penId = QMetaType::type("QPen");
268 static int penId = QMetaType::type("QPen");
269 static int brushId = QMetaType::type("QBrush");
269 static int brushId = QMetaType::type("QBrush");
270 static int cursorId = QMetaType::type("QCursor");
270 static int cursorId = QMetaType::type("QCursor");
271 static int colorId = QMetaType::type("QColor");
271 static int colorId = QMetaType::type("QColor");
272 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
272 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
273 if (typeId == cursorId) {
273 if (typeId == cursorId) {
274 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
274 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
275 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
275 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
276 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
276 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
277 if (!ptr) {
277 if (!ptr) {
278 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
278 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
279 ptr = (void*)((QVariant*)ptr)->constData();
279 ptr = (void*)((QVariant*)ptr)->constData();
280 }
280 }
281 *((QCursor*)ptr) = QCursor(val);
281 *((QCursor*)ptr) = QCursor(val);
282 return ptr;
282 return ptr;
283 }
283 }
284 } else if (typeId == penId) {
284 } else if (typeId == penId) {
285 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
285 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
286 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
286 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
287 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
287 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
288 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
288 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
289 if (!ptr) {
289 if (!ptr) {
290 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
290 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
291 ptr = (void*)((QVariant*)ptr)->constData();
291 ptr = (void*)((QVariant*)ptr)->constData();
292 }
292 }
293 *((QPen*)ptr) = QPen(QColor(val));
293 *((QPen*)ptr) = QPen(QColor(val));
294 return ptr;
294 return ptr;
295 } else if ((PyObject*)obj->ob_type == qtColorClass) {
295 } else if ((PyObject*)obj->ob_type == qtColorClass) {
296 if (!ptr) {
296 if (!ptr) {
297 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
297 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
298 ptr = (void*)((QVariant*)ptr)->constData();
298 ptr = (void*)((QVariant*)ptr)->constData();
299 }
299 }
300 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
300 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
301 return ptr;
301 return ptr;
302 }
302 }
303 } else if (typeId == brushId) {
303 } else if (typeId == brushId) {
304 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
304 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
305 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
305 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
306 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
306 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
307 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
307 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
308 if (!ptr) {
308 if (!ptr) {
309 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
309 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
310 ptr = (void*)((QVariant*)ptr)->constData();
310 ptr = (void*)((QVariant*)ptr)->constData();
311 }
311 }
312 *((QBrush*)ptr) = QBrush(QColor(val));
312 *((QBrush*)ptr) = QBrush(QColor(val));
313 return ptr;
313 return ptr;
314 } else if ((PyObject*)obj->ob_type == qtColorClass) {
314 } else if ((PyObject*)obj->ob_type == qtColorClass) {
315 if (!ptr) {
315 if (!ptr) {
316 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
316 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
317 ptr = (void*)((QVariant*)ptr)->constData();
317 ptr = (void*)((QVariant*)ptr)->constData();
318 }
318 }
319 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
319 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
320 return ptr;
320 return ptr;
321 }
321 }
322 } else if (typeId == colorId) {
322 } else if (typeId == colorId) {
323 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
323 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
324 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
324 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
325 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
325 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
326 if (!ptr) {
326 if (!ptr) {
327 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
327 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
328 ptr = (void*)((QVariant*)ptr)->constData();
328 ptr = (void*)((QVariant*)ptr)->constData();
329 }
329 }
330 *((QColor*)ptr) = QColor(val);
330 *((QColor*)ptr) = QColor(val);
331 return ptr;
331 return ptr;
332 }
332 }
333 }
333 }
334 return NULL;
334 return NULL;
335 }
335 }
336
336
337 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
337 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
338 {
338 {
339 bool ok = false;
339 bool ok = false;
340 void* ptr = NULL;
340 void* ptr = NULL;
341
341
342 // autoconversion of QPen/QBrush/QCursor/QColor from different type
342 // autoconversion of QPen/QBrush/QCursor/QColor from different type
343 if (!info.isPointer && !strict) {
343 if (!info.isPointer && !strict) {
344 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
344 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
345 if (ptr) {
345 if (ptr) {
346 return ptr;
346 return ptr;
347 }
347 }
348 }
348 }
349
349
350 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
350 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
351 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
351 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
352 // (the Variant case is handled below in a switch)
352 // (the Variant case is handled below in a switch)
353
353
354 // a C++ wrapper (can be passed as pointer or reference)
354 // a C++ wrapper (can be passed as pointer or reference)
355 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
355 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
356 void* object = castWrapperTo(wrap, info.name, ok);
356 void* object = castWrapperTo(wrap, info.name, ok);
357 if (ok) {
357 if (ok) {
358 if (info.isPointer) {
358 if (info.isPointer) {
359 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
359 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
360 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
360 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
361 } else {
361 } else {
362 // store the wrapped pointer directly, since we are a reference
362 // store the wrapped pointer directly, since we are a reference
363 ptr = object;
363 ptr = object;
364 }
364 }
365 } else {
365 } else {
366 // not matching
366 // not matching
367 }
367 }
368 } else if (info.isPointer) {
368 } else if (info.isPointer) {
369 // a pointer
369 // a pointer
370 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
370 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
371 {
371 {
372 QString str = PyObjGetString(obj, strict, ok);
372 QString str = PyObjGetString(obj, strict, ok);
373 if (ok) {
373 if (ok) {
374 void* ptr2 = NULL;
374 void* ptr2 = NULL;
375 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
375 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
376 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
376 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
377 }
377 }
378 } else if (info.name == "PyObject") {
378 } else if (info.name == "PyObject") {
379 // handle low level PyObject directly
379 // handle low level PyObject directly
380 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
380 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
381 } else if (obj == Py_None) {
381 } else if (obj == Py_None) {
382 // None is treated as a NULL ptr
382 // None is treated as a NULL ptr
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
384 } else {
384 } else {
385 // if we are not strict, we try if we are passed a 0 integer
385 // if we are not strict, we try if we are passed a 0 integer
386 if (!strict) {
386 if (!strict) {
387 bool ok;
387 bool ok;
388 int value = PyObjGetInt(obj, true, ok);
388 int value = PyObjGetInt(obj, true, ok);
389 if (ok && value==0) {
389 if (ok && value==0) {
390 // TODOXXX is this wise? or should it be expected from the programmer to use None?
390 // TODOXXX is this wise? or should it be expected from the programmer to use None?
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
392 }
392 }
393 }
393 }
394 }
394 }
395 } else {
395 } else {
396 // not a pointer
396 // not a pointer
397 switch (info.typeId) {
397 switch (info.typeId) {
398 case QMetaType::Char:
398 case QMetaType::Char:
399 {
399 {
400 int val = PyObjGetInt(obj, strict, ok);
400 int val = PyObjGetInt(obj, strict, ok);
401 if (ok) {
401 if (ok) {
402 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
402 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
403 }
403 }
404 }
404 }
405 break;
405 break;
406 case QMetaType::UChar:
406 case QMetaType::UChar:
407 {
407 {
408 int val = PyObjGetInt(obj, strict, ok);
408 int val = PyObjGetInt(obj, strict, ok);
409 if (ok) {
409 if (ok) {
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
411 }
411 }
412 }
412 }
413 break;
413 break;
414 case QMetaType::Short:
414 case QMetaType::Short:
415 {
415 {
416 int val = PyObjGetInt(obj, strict, ok);
416 int val = PyObjGetInt(obj, strict, ok);
417 if (ok) {
417 if (ok) {
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
419 }
419 }
420 }
420 }
421 break;
421 break;
422 case QMetaType::UShort:
422 case QMetaType::UShort:
423 {
423 {
424 int val = PyObjGetInt(obj, strict, ok);
424 int val = PyObjGetInt(obj, strict, ok);
425 if (ok) {
425 if (ok) {
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
427 }
427 }
428 }
428 }
429 break;
429 break;
430 case QMetaType::Long:
430 case QMetaType::Long:
431 {
431 {
432 long val = (long)PyObjGetLongLong(obj, strict, ok);
432 long val = (long)PyObjGetLongLong(obj, strict, ok);
433 if (ok) {
433 if (ok) {
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
435 }
435 }
436 }
436 }
437 break;
437 break;
438 case QMetaType::ULong:
438 case QMetaType::ULong:
439 {
439 {
440 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
440 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
441 if (ok) {
441 if (ok) {
442 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
442 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
443 }
443 }
444 }
444 }
445 break;
445 break;
446 case QMetaType::Bool:
446 case QMetaType::Bool:
447 {
447 {
448 bool val = PyObjGetBool(obj, strict, ok);
448 bool val = PyObjGetBool(obj, strict, ok);
449 if (ok) {
449 if (ok) {
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
451 }
451 }
452 }
452 }
453 break;
453 break;
454 case QMetaType::Int:
454 case QMetaType::Int:
455 {
455 {
456 int val = PyObjGetInt(obj, strict, ok);
456 int val = PyObjGetInt(obj, strict, ok);
457 if (ok) {
457 if (ok) {
458 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
458 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
459 }
459 }
460 }
460 }
461 break;
461 break;
462 case QMetaType::UInt:
462 case QMetaType::UInt:
463 {
463 {
464 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
464 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
465 if (ok) {
465 if (ok) {
466 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
466 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
467 }
467 }
468 }
468 }
469 break;
469 break;
470 case QMetaType::QChar:
470 case QMetaType::QChar:
471 {
471 {
472 int val = PyObjGetInt(obj, strict, ok);
472 int val = PyObjGetInt(obj, strict, ok);
473 if (ok) {
473 if (ok) {
474 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
474 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
475 }
475 }
476 }
476 }
477 break;
477 break;
478 case QMetaType::Float:
478 case QMetaType::Float:
479 {
479 {
480 float val = (float)PyObjGetDouble(obj, strict, ok);
480 float val = (float)PyObjGetDouble(obj, strict, ok);
481 if (ok) {
481 if (ok) {
482 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
482 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
483 }
483 }
484 }
484 }
485 break;
485 break;
486 case QMetaType::Double:
486 case QMetaType::Double:
487 {
487 {
488 double val = (double)PyObjGetDouble(obj, strict, ok);
488 double val = (double)PyObjGetDouble(obj, strict, ok);
489 if (ok) {
489 if (ok) {
490 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
490 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
491 }
491 }
492 }
492 }
493 break;
493 break;
494 case QMetaType::LongLong:
494 case QMetaType::LongLong:
495 {
495 {
496 qint64 val = PyObjGetLongLong(obj, strict, ok);
496 qint64 val = PyObjGetLongLong(obj, strict, ok);
497 if (ok) {
497 if (ok) {
498 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
498 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
499 }
499 }
500 }
500 }
501 break;
501 break;
502 case QMetaType::ULongLong:
502 case QMetaType::ULongLong:
503 {
503 {
504 quint64 val = PyObjGetULongLong(obj, strict, ok);
504 quint64 val = PyObjGetULongLong(obj, strict, ok);
505 if (ok) {
505 if (ok) {
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
507 }
507 }
508 }
508 }
509 break;
509 break;
510 case QMetaType::QByteArray:
510 case QMetaType::QByteArray:
511 {
511 {
512 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
512 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
513 if (ok) {
513 if (ok) {
514 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
514 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
515 ptr = (void*)((QVariant*)ptr)->constData();
515 ptr = (void*)((QVariant*)ptr)->constData();
516 }
516 }
517 }
517 }
518 break;
518 break;
519 case QMetaType::QString:
519 case QMetaType::QString:
520 {
520 {
521 QString str = PyObjGetString(obj, strict, ok);
521 QString str = PyObjGetString(obj, strict, ok);
522 if (ok) {
522 if (ok) {
523 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
523 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
524 ptr = (void*)((QVariant*)ptr)->constData();
524 ptr = (void*)((QVariant*)ptr)->constData();
525 }
525 }
526 }
526 }
527 break;
527 break;
528 case QMetaType::QStringList:
528 case QMetaType::QStringList:
529 {
529 {
530 QStringList l = PyObjToStringList(obj, strict, ok);
530 QStringList l = PyObjToStringList(obj, strict, ok);
531 if (ok) {
531 if (ok) {
532 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
532 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
533 ptr = (void*)((QVariant*)ptr)->constData();
533 ptr = (void*)((QVariant*)ptr)->constData();
534 }
534 }
535 }
535 }
536 break;
536 break;
537
537
538 case PythonQtMethodInfo::Variant:
538 case PythonQtMethodInfo::Variant:
539 {
539 {
540 QVariant v = PyObjToQVariant(obj);
540 QVariant v = PyObjToQVariant(obj);
541 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
541 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
542 // so we do not check v.isValid() here
542 // so we do not check v.isValid() here
543 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
543 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
544 }
544 }
545 break;
545 break;
546 default:
546 default:
547 {
547 {
548 // check for enum case
548 // check for enum case
549 if (info.enumWrapper) {
549 if (info.enumWrapper) {
550 unsigned int val;
550 unsigned int val;
551 ok = false;
551 ok = false;
552 if ((PyObject*)obj->ob_type == info.enumWrapper) {
552 if ((PyObject*)obj->ob_type == info.enumWrapper) {
553 // we have a exact enum type match:
553 // we have a exact enum type match:
554 val = PyInt_AS_LONG(obj);
554 val = PyInt_AS_LONG(obj);
555 ok = true;
555 ok = true;
556 } else if (!strict) {
556 } else if (!strict) {
557 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
557 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
558 // we want an integer overload to be taken first!
558 // we want an integer overload to be taken first!
559 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
559 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
560 }
560 }
561 if (ok) {
561 if (ok) {
562 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
562 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
563 return ptr;
563 return ptr;
564 } else {
564 } else {
565 return NULL;
565 return NULL;
566 }
566 }
567 }
567 }
568
568
569 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
569 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
570 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
570 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
571 if (info.name.startsWith("QList<")) {
571 if (info.name.startsWith("QList<")) {
572 QByteArray innerType = info.name.mid(6,info.name.length()-7);
572 QByteArray innerType = info.name.mid(6,info.name.length()-7);
573 if (innerType.endsWith("*")) {
573 if (innerType.endsWith("*")) {
574 innerType.truncate(innerType.length()-1);
574 innerType.truncate(innerType.length()-1);
575 static int id = QMetaType::type("QList<void*>");
575 static int id = QMetaType::type("QList<void*>");
576 if (!alreadyAllocatedCPPObject) {
576 if (!alreadyAllocatedCPPObject) {
577 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
577 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
578 ptr = (void*)((QVariant*)ptr)->constData();
578 ptr = (void*)((QVariant*)ptr)->constData();
579 } else {
579 } else {
580 ptr = alreadyAllocatedCPPObject;
580 ptr = alreadyAllocatedCPPObject;
581 }
581 }
582 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
582 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
583 if (ok) {
583 if (ok) {
584 return ptr;
584 return ptr;
585 } else {
585 } else {
586 return NULL;
586 return NULL;
587 }
587 }
588 }
588 }
589 }
589 }
590 }
590 }
591
591
592 // We only do this for registered type > QMetaType::User for performance reasons.
592 // We only do this for registered type > QMetaType::User for performance reasons.
593 if (info.typeId >= QMetaType::User) {
593 if (info.typeId >= QMetaType::User) {
594 // Maybe we have a special converter that is registered for that type:
594 // Maybe we have a special converter that is registered for that type:
595 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
595 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
596 if (converter) {
596 if (converter) {
597 if (!alreadyAllocatedCPPObject) {
597 if (!alreadyAllocatedCPPObject) {
598 // create a new empty variant of concrete type:
598 // create a new empty variant of concrete type:
599 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
599 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
600 ptr = (void*)((QVariant*)ptr)->constData();
600 ptr = (void*)((QVariant*)ptr)->constData();
601 } else {
601 } else {
602 ptr = alreadyAllocatedCPPObject;
602 ptr = alreadyAllocatedCPPObject;
603 }
603 }
604 // now call the converter, passing the internal object of the variant
604 // now call the converter, passing the internal object of the variant
605 ok = (*converter)(obj, ptr, info.typeId, strict);
605 ok = (*converter)(obj, ptr, info.typeId, strict);
606 if (ok) {
606 if (ok) {
607 return ptr;
607 return ptr;
608 } else {
608 } else {
609 return NULL;
609 return NULL;
610 }
610 }
611 }
611 }
612 }
612 }
613 // if no type id is available, conversion to a QVariant makes no sense/is not possible
613 // if no type id is available, conversion to a QVariant makes no sense/is not possible
614 if (info.typeId != PythonQtMethodInfo::Unknown) {
614 if (info.typeId != PythonQtMethodInfo::Unknown) {
615 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
615 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
616 QVariant v = PyObjToQVariant(obj, info.typeId);
616 QVariant v = PyObjToQVariant(obj, info.typeId);
617 if (v.isValid()) {
617 if (v.isValid()) {
618 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
618 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
619 ptr = (void*)((QVariant*)ptr)->constData();
619 ptr = (void*)((QVariant*)ptr)->constData();
620 }
620 }
621 }
621 }
622 }
622 }
623 }
623 }
624 }
624 }
625 return ptr;
625 return ptr;
626 }
626 }
627
627
628
628
629 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
629 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
630 QStringList v;
630 QStringList v;
631 ok = false;
631 ok = false;
632 // if we are strict, we do not want to convert a string to a stringlist
632 // if we are strict, we do not want to convert a string to a stringlist
633 // (strings in python are detected to be sequences)
633 // (strings in python are detected to be sequences)
634 if (strict &&
634 if (strict &&
635 (val->ob_type == &PyString_Type ||
635 (val->ob_type == &PyString_Type ||
636 PyUnicode_Check(val))) {
636 PyUnicode_Check(val))) {
637 ok = false;
637 ok = false;
638 return v;
638 return v;
639 }
639 }
640 if (PySequence_Check(val)) {
640 if (PySequence_Check(val)) {
641 int count = PySequence_Size(val);
641 int count = PySequence_Size(val);
642 for (int i = 0;i<count;i++) {
642 for (int i = 0;i<count;i++) {
643 PyObject* value = PySequence_GetItem(val,i);
643 PyObject* value = PySequence_GetItem(val,i);
644 v.append(PyObjGetString(value,false,ok));
644 v.append(PyObjGetString(value,false,ok));
645 }
645 }
646 ok = true;
646 ok = true;
647 }
647 }
648 return v;
648 return v;
649 }
649 }
650
650
651 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
651 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
652 {
652 {
653 QString r;
653 QString r;
654 PyObject* str = PyObject_Repr(val);
654 PyObject* str = PyObject_Repr(val);
655 if (str) {
655 if (str) {
656 r = QString(PyString_AS_STRING(str));
656 r = QString(PyString_AS_STRING(str));
657 Py_DECREF(str);
657 Py_DECREF(str);
658 }
658 }
659 return r;
659 return r;
660 }
660 }
661
661
662 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
662 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
663 QString r;
663 QString r;
664 ok = true;
664 ok = true;
665 if (val->ob_type == &PyString_Type) {
665 if (val->ob_type == &PyString_Type) {
666 r = QString(PyString_AS_STRING(val));
666 r = QString(PyString_AS_STRING(val));
667 } else if (PyUnicode_Check(val)) {
667 } else if (PyUnicode_Check(val)) {
668 #ifdef WIN32
668 #ifdef WIN32
669 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
669 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
670 #else
670 #else
671 PyObject *ptmp = PyUnicode_AsUTF8String(val);
671 PyObject *ptmp = PyUnicode_AsUTF8String(val);
672 if(ptmp) {
672 if(ptmp) {
673 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
673 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
674 Py_DECREF(ptmp);
674 Py_DECREF(ptmp);
675 }
675 }
676 #endif
676 #endif
677 } else if (!strict) {
677 } else if (!strict) {
678 // EXTRA: could also use _Unicode, but why should we?
678 // EXTRA: could also use _Unicode, but why should we?
679 PyObject* str = PyObject_Str(val);
679 PyObject* str = PyObject_Str(val);
680 if (str) {
680 if (str) {
681 r = QString(PyString_AS_STRING(str));
681 r = QString(PyString_AS_STRING(str));
682 Py_DECREF(str);
682 Py_DECREF(str);
683 } else {
683 } else {
684 ok = false;
684 ok = false;
685 }
685 }
686 } else {
686 } else {
687 ok = false;
687 ok = false;
688 }
688 }
689 return r;
689 return r;
690 }
690 }
691
691
692 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
692 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
693 // TODO: support buffer objects in general
693 // TODO: support buffer objects in general
694 QByteArray r;
694 QByteArray r;
695 ok = true;
695 ok = true;
696 if (val->ob_type == &PyString_Type) {
696 if (val->ob_type == &PyString_Type) {
697 long size = PyString_GET_SIZE(val);
697 long size = PyString_GET_SIZE(val);
698 r = QByteArray(PyString_AS_STRING(val), size);
698 r = QByteArray(PyString_AS_STRING(val), size);
699 } else {
699 } else {
700 ok = false;
700 ok = false;
701 }
701 }
702 return r;
702 return r;
703 }
703 }
704
704
705 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
705 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
706 bool d = false;
706 bool d = false;
707 ok = false;
707 ok = false;
708 if (val == Py_False) {
708 if (val == Py_False) {
709 d = false;
709 d = false;
710 ok = true;
710 ok = true;
711 } else if (val == Py_True) {
711 } else if (val == Py_True) {
712 d = true;
712 d = true;
713 ok = true;
713 ok = true;
714 } else if (!strict) {
714 } else if (!strict) {
715 d = PyObjGetInt(val, false, ok)!=0;
715 d = PyObjGetInt(val, false, ok)!=0;
716 ok = true;
716 ok = true;
717 }
717 }
718 return d;
718 return d;
719 }
719 }
720
720
721 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
721 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
722 int d = 0;
722 int d = 0;
723 ok = true;
723 ok = true;
724 if (val->ob_type == &PyInt_Type) {
724 if (val->ob_type == &PyInt_Type) {
725 d = PyInt_AS_LONG(val);
725 d = PyInt_AS_LONG(val);
726 } else if (!strict) {
726 } else if (!strict) {
727 if (PyObject_TypeCheck(val, &PyInt_Type)) {
727 if (PyObject_TypeCheck(val, &PyInt_Type)) {
728 // support for derived int classes, e.g. for our enums
728 // support for derived int classes, e.g. for our enums
729 d = PyInt_AS_LONG(val);
729 d = PyInt_AS_LONG(val);
730 } else if (val->ob_type == &PyFloat_Type) {
730 } else if (val->ob_type == &PyFloat_Type) {
731 d = floor(PyFloat_AS_DOUBLE(val));
731 d = floor(PyFloat_AS_DOUBLE(val));
732 } else if (val->ob_type == &PyLong_Type) {
732 } else if (val->ob_type == &PyLong_Type) {
733 // handle error on overflow!
733 // handle error on overflow!
734 d = PyLong_AsLong(val);
734 d = PyLong_AsLong(val);
735 } else if (val == Py_False) {
735 } else if (val == Py_False) {
736 d = 0;
736 d = 0;
737 } else if (val == Py_True) {
737 } else if (val == Py_True) {
738 d = 1;
738 d = 1;
739 } else {
739 } else {
740 ok = false;
740 ok = false;
741 }
741 }
742 } else {
742 } else {
743 ok = false;
743 ok = false;
744 }
744 }
745 return d;
745 return d;
746 }
746 }
747
747
748 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
748 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
749 qint64 d = 0;
749 qint64 d = 0;
750 ok = true;
750 ok = true;
751 if (val->ob_type == &PyInt_Type) {
751 if (val->ob_type == &PyInt_Type) {
752 d = PyInt_AS_LONG(val);
752 d = PyInt_AS_LONG(val);
753 } else if (val->ob_type == &PyLong_Type) {
753 } else if (val->ob_type == &PyLong_Type) {
754 d = PyLong_AsLongLong(val);
754 d = PyLong_AsLongLong(val);
755 } else if (!strict) {
755 } else if (!strict) {
756 if (PyObject_TypeCheck(val, &PyInt_Type)) {
756 if (PyObject_TypeCheck(val, &PyInt_Type)) {
757 // support for derived int classes, e.g. for our enums
757 // support for derived int classes, e.g. for our enums
758 d = PyInt_AS_LONG(val);
758 d = PyInt_AS_LONG(val);
759 } else if (val->ob_type == &PyFloat_Type) {
759 } else if (val->ob_type == &PyFloat_Type) {
760 d = floor(PyFloat_AS_DOUBLE(val));
760 d = floor(PyFloat_AS_DOUBLE(val));
761 } else if (val == Py_False) {
761 } else if (val == Py_False) {
762 d = 0;
762 d = 0;
763 } else if (val == Py_True) {
763 } else if (val == Py_True) {
764 d = 1;
764 d = 1;
765 } else {
765 } else {
766 ok = false;
766 ok = false;
767 }
767 }
768 } else {
768 } else {
769 ok = false;
769 ok = false;
770 }
770 }
771 return d;
771 return d;
772 }
772 }
773
773
774 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
774 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
775 quint64 d = 0;
775 quint64 d = 0;
776 ok = true;
776 ok = true;
777 if (PyObject_TypeCheck(val, &PyInt_Type)) {
777 if (PyObject_TypeCheck(val, &PyInt_Type)) {
778 d = PyInt_AS_LONG(val);
778 d = PyInt_AS_LONG(val);
779 } else if (val->ob_type == &PyLong_Type) {
779 } else if (val->ob_type == &PyLong_Type) {
780 d = PyLong_AsLongLong(val);
780 d = PyLong_AsLongLong(val);
781 } else if (!strict) {
781 } else if (!strict) {
782 if (PyObject_TypeCheck(val, &PyInt_Type)) {
782 if (PyObject_TypeCheck(val, &PyInt_Type)) {
783 // support for derived int classes, e.g. for our enums
783 // support for derived int classes, e.g. for our enums
784 d = PyInt_AS_LONG(val);
784 d = PyInt_AS_LONG(val);
785 } else if (val->ob_type == &PyFloat_Type) {
785 } else if (val->ob_type == &PyFloat_Type) {
786 d = floor(PyFloat_AS_DOUBLE(val));
786 d = floor(PyFloat_AS_DOUBLE(val));
787 } else if (val == Py_False) {
787 } else if (val == Py_False) {
788 d = 0;
788 d = 0;
789 } else if (val == Py_True) {
789 } else if (val == Py_True) {
790 d = 1;
790 d = 1;
791 } else {
791 } else {
792 ok = false;
792 ok = false;
793 }
793 }
794 } else {
794 } else {
795 ok = false;
795 ok = false;
796 }
796 }
797 return d;
797 return d;
798 }
798 }
799
799
800 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
800 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
801 double d = 0;
801 double d = 0;
802 ok = true;
802 ok = true;
803 if (val->ob_type == &PyFloat_Type) {
803 if (val->ob_type == &PyFloat_Type) {
804 d = PyFloat_AS_DOUBLE(val);
804 d = PyFloat_AS_DOUBLE(val);
805 } else if (!strict) {
805 } else if (!strict) {
806 if (PyObject_TypeCheck(val, &PyInt_Type)) {
806 if (PyObject_TypeCheck(val, &PyInt_Type)) {
807 d = PyInt_AS_LONG(val);
807 d = PyInt_AS_LONG(val);
808 } else if (val->ob_type == &PyLong_Type) {
808 } else if (val->ob_type == &PyLong_Type) {
809 d = PyLong_AsLong(val);
809 d = PyLong_AsLong(val);
810 } else if (val == Py_False) {
810 } else if (val == Py_False) {
811 d = 0;
811 d = 0;
812 } else if (val == Py_True) {
812 } else if (val == Py_True) {
813 d = 1;
813 d = 1;
814 } else {
814 } else {
815 ok = false;
815 ok = false;
816 }
816 }
817 } else {
817 } else {
818 ok = false;
818 ok = false;
819 }
819 }
820 return d;
820 return d;
821 }
821 }
822
822
823 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
823 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
824 {
824 {
825 QVariant v;
825 QVariant v;
826 bool ok = true;
826 bool ok = true;
827
827
828 if (type==-1) {
828 if (type==-1) {
829 // no special type requested
829 // no special type requested
830 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
830 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
831 type = QVariant::String;
831 type = QVariant::String;
832 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
832 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
833 type = QVariant::Int;
833 type = QVariant::Int;
834 } else if (val->ob_type==&PyLong_Type) {
834 } else if (val->ob_type==&PyLong_Type) {
835 type = QVariant::LongLong;
835 type = QVariant::LongLong;
836 } else if (val->ob_type==&PyFloat_Type) {
836 } else if (val->ob_type==&PyFloat_Type) {
837 type = QVariant::Double;
837 type = QVariant::Double;
838 } else if (val == Py_False || val == Py_True) {
838 } else if (val == Py_False || val == Py_True) {
839 type = QVariant::Bool;
839 type = QVariant::Bool;
840 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
840 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
841 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
841 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
842 // c++ wrapper, check if the class names of the c++ objects match
842 // c++ wrapper, check if the class names of the c++ objects match
843 if (wrap->classInfo()->isCPPWrapper()) {
843 if (wrap->classInfo()->isCPPWrapper()) {
844 if (wrap->classInfo()->metaTypeId()>0) {
844 if (wrap->classInfo()->metaTypeId()>0) {
845 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
845 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
846 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
846 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
847 } else {
847 } else {
848 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
848 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
849 // the pointer here...
849 // the pointer here...
850 // is this worth anything? we loose the knowledge of the cpp object type
850 // is this worth anything? we loose the knowledge of the cpp object type
851 v = qVariantFromValue(wrap->_wrappedPtr);
851 v = qVariantFromValue(wrap->_wrappedPtr);
852 }
852 }
853 } else {
853 } else {
854 // this gives us a QObject pointer
854 // this gives us a QObject pointer
855 QObject* myObject = wrap->_obj;
855 QObject* myObject = wrap->_obj;
856 v = qVariantFromValue(myObject);
856 v = qVariantFromValue(myObject);
857 }
857 }
858 return v;
858 return v;
859 } else if (val->ob_type==&PyDict_Type) {
859 } else if (val->ob_type==&PyDict_Type) {
860 type = QVariant::Map;
860 type = QVariant::Map;
861 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
861 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
862 type = QVariant::List;
862 type = QVariant::List;
863 } else if (val == Py_None) {
863 } else if (val == Py_None) {
864 // none is invalid
864 // none is invalid
865 type = QVariant::Invalid;
865 type = QVariant::Invalid;
866 } else {
866 } else {
867 // this used to be:
867 // this used to be:
868 // type = QVariant::String;
868 // type = QVariant::String;
869 // but now we want to transport the Python Objects directly:
869 // but now we want to transport the Python Objects directly:
870 PythonQtObjectPtr o(val);
870 PythonQtObjectPtr o(val);
871 v = qVariantFromValue(o);
871 v = qVariantFromValue(o);
872 return v;
872 return v;
873 }
873 }
874 }
874 }
875 // special type request:
875 // special type request:
876 switch (type) {
876 switch (type) {
877 case QVariant::Invalid:
877 case QVariant::Invalid:
878 return v;
878 return v;
879 break;
879 break;
880 case QVariant::Int:
880 case QVariant::Int:
881 {
881 {
882 int d = PyObjGetInt(val, false, ok);
882 int d = PyObjGetInt(val, false, ok);
883 if (ok) return QVariant(d);
883 if (ok) return QVariant(d);
884 }
884 }
885 break;
885 break;
886 case QVariant::UInt:
886 case QVariant::UInt:
887 {
887 {
888 int d = PyObjGetInt(val, false,ok);
888 int d = PyObjGetInt(val, false,ok);
889 if (ok) v = QVariant((unsigned int)d);
889 if (ok) v = QVariant((unsigned int)d);
890 }
890 }
891 break;
891 break;
892 case QVariant::Bool:
892 case QVariant::Bool:
893 {
893 {
894 int d = PyObjGetBool(val,false,ok);
894 int d = PyObjGetBool(val,false,ok);
895 if (ok) v = QVariant((bool)(d!=0));
895 if (ok) v = QVariant((bool)(d!=0));
896 }
896 }
897 break;
897 break;
898 case QVariant::Double:
898 case QVariant::Double:
899 {
899 {
900 double d = PyObjGetDouble(val,false,ok);
900 double d = PyObjGetDouble(val,false,ok);
901 if (ok) v = QVariant(d);
901 if (ok) v = QVariant(d);
902 break;
902 break;
903 }
903 }
904 case QMetaType::Float:
904 case QMetaType::Float:
905 {
905 {
906 float d = (float) PyObjGetDouble(val,false,ok);
906 float d = (float) PyObjGetDouble(val,false,ok);
907 if (ok) v = qVariantFromValue(d);
907 if (ok) v = qVariantFromValue(d);
908 break;
908 break;
909 }
909 }
910 case QMetaType::Long:
910 case QMetaType::Long:
911 {
911 {
912 long d = (long) PyObjGetLongLong(val,false,ok);
912 long d = (long) PyObjGetLongLong(val,false,ok);
913 if (ok) v = qVariantFromValue(d);
913 if (ok) v = qVariantFromValue(d);
914 break;
914 break;
915 }
915 }
916 case QMetaType::ULong:
916 case QMetaType::ULong:
917 {
917 {
918 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
918 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
919 if (ok) v = qVariantFromValue(d);
919 if (ok) v = qVariantFromValue(d);
920 break;
920 break;
921 }
921 }
922 case QMetaType::LongLong:
922 case QMetaType::LongLong:
923 {
923 {
924 qint64 d = PyObjGetLongLong(val, false, ok);
924 qint64 d = PyObjGetLongLong(val, false, ok);
925 if (ok) v = qVariantFromValue(d);
925 if (ok) v = qVariantFromValue(d);
926 }
926 }
927 break;
927 break;
928 case QMetaType::ULongLong:
928 case QMetaType::ULongLong:
929 {
929 {
930 quint64 d = PyObjGetULongLong(val, false, ok);
930 quint64 d = PyObjGetULongLong(val, false, ok);
931 if (ok) v = qVariantFromValue(d);
931 if (ok) v = qVariantFromValue(d);
932 }
932 }
933 break;
933 break;
934 case QMetaType::Short:
934 case QMetaType::Short:
935 {
935 {
936 short d = (short) PyObjGetInt(val,false,ok);
936 short d = (short) PyObjGetInt(val,false,ok);
937 if (ok) v = qVariantFromValue(d);
937 if (ok) v = qVariantFromValue(d);
938 break;
938 break;
939 }
939 }
940 case QMetaType::UShort:
940 case QMetaType::UShort:
941 {
941 {
942 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
942 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
943 if (ok) v = qVariantFromValue(d);
943 if (ok) v = qVariantFromValue(d);
944 break;
944 break;
945 }
945 }
946 case QMetaType::Char:
946 case QMetaType::Char:
947 {
947 {
948 char d = (char) PyObjGetInt(val,false,ok);
948 char d = (char) PyObjGetInt(val,false,ok);
949 if (ok) v = qVariantFromValue(d);
949 if (ok) v = qVariantFromValue(d);
950 break;
950 break;
951 }
951 }
952 case QMetaType::UChar:
952 case QMetaType::UChar:
953 {
953 {
954 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
954 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
955 if (ok) v = qVariantFromValue(d);
955 if (ok) v = qVariantFromValue(d);
956 break;
956 break;
957 }
957 }
958
958
959 case QVariant::ByteArray:
959 case QVariant::ByteArray:
960 case QVariant::String:
960 case QVariant::String:
961 {
961 {
962 bool ok;
962 bool ok;
963 v = QVariant(PyObjGetString(val, false, ok));
963 v = QVariant(PyObjGetString(val, false, ok));
964 }
964 }
965 break;
965 break;
966
966
967 // these are important for MeVisLab
967 // these are important for MeVisLab
968 case QVariant::Map:
968 case QVariant::Map:
969 {
969 {
970 if (PyMapping_Check(val)) {
970 if (PyMapping_Check(val)) {
971 QMap<QString,QVariant> map;
971 QMap<QString,QVariant> map;
972 PyObject* items = PyMapping_Items(val);
972 PyObject* items = PyMapping_Items(val);
973 if (items) {
973 if (items) {
974 int count = PyList_Size(items);
974 int count = PyList_Size(items);
975 PyObject* value;
975 PyObject* value;
976 PyObject* key;
976 PyObject* key;
977 PyObject* tuple;
977 PyObject* tuple;
978 for (int i = 0;i<count;i++) {
978 for (int i = 0;i<count;i++) {
979 tuple = PyList_GetItem(items,i);
979 tuple = PyList_GetItem(items,i);
980 key = PyTuple_GetItem(tuple, 0);
980 key = PyTuple_GetItem(tuple, 0);
981 value = PyTuple_GetItem(tuple, 1);
981 value = PyTuple_GetItem(tuple, 1);
982 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
982 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
983 }
983 }
984 Py_DECREF(items);
984 Py_DECREF(items);
985 v = map;
985 v = map;
986 }
986 }
987 }
987 }
988 }
988 }
989 break;
989 break;
990 case QVariant::List:
990 case QVariant::List:
991 if (PySequence_Check(val)) {
991 if (PySequence_Check(val)) {
992 QVariantList list;
992 QVariantList list;
993 int count = PySequence_Size(val);
993 int count = PySequence_Size(val);
994 PyObject* value;
994 PyObject* value;
995 for (int i = 0;i<count;i++) {
995 for (int i = 0;i<count;i++) {
996 value = PySequence_GetItem(val,i);
996 value = PySequence_GetItem(val,i);
997 list.append(PyObjToQVariant(value, -1));
997 list.append(PyObjToQVariant(value, -1));
998 }
998 }
999 v = list;
999 v = list;
1000 }
1000 }
1001 break;
1001 break;
1002 case QVariant::StringList:
1002 case QVariant::StringList:
1003 {
1003 {
1004 bool ok;
1004 bool ok;
1005 QStringList l = PyObjToStringList(val, false, ok);
1005 QStringList l = PyObjToStringList(val, false, ok);
1006 if (ok) {
1006 if (ok) {
1007 v = l;
1007 v = l;
1008 }
1008 }
1009 }
1009 }
1010 break;
1010 break;
1011
1011
1012 default:
1012 default:
1013 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1013 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1014 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1014 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1015 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1015 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1016 // construct a new variant from the C++ object if it has the same meta type
1016 // construct a new variant from the C++ object if it has the same meta type
1017 v = QVariant(type, wrap->_wrappedPtr);
1017 v = QVariant(type, wrap->_wrappedPtr);
1018 } else {
1018 } else {
1019 v = QVariant();
1019 v = QVariant();
1020 }
1020 }
1021 } else {
1021 } else {
1022 v = QVariant();
1022 v = QVariant();
1023 }
1023 }
1024 }
1024 }
1025 return v;
1025 return v;
1026 }
1026 }
1027
1027
1028 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1028 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1029 {
1029 {
1030 if (str.isNull()) {
1030 if (str.isNull()) {
1031 return PyString_FromString("");
1031 return PyString_FromString("");
1032 } else {
1032 } else {
1033 #ifdef WIN32
1033 #ifdef WIN32
1034 // return PyString_FromString(str.toLatin1().data());
1034 // return PyString_FromString(str.toLatin1().data());
1035 return PyUnicode_FromUnicode(str.utf16(), str.length());
1035 return PyUnicode_FromUnicode(str.utf16(), str.length());
1036 #else
1036 #else
1037 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1037 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1038 #endif
1038 #endif
1039 }
1039 }
1040 }
1040 }
1041
1041
1042 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1042 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1043 {
1043 {
1044 PyObject* result = PyTuple_New(list.count());
1044 PyObject* result = PyTuple_New(list.count());
1045 int i = 0;
1045 int i = 0;
1046 QString str;
1046 QString str;
1047 foreach (str, list) {
1047 foreach (str, list) {
1048 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1048 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1049 i++;
1049 i++;
1050 }
1050 }
1051 // why is the error state bad after this?
1051 // why is the error state bad after this?
1052 PyErr_Clear();
1052 PyErr_Clear();
1053 return result;
1053 return result;
1054 }
1054 }
1055
1055
1056 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1056 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1057 {
1057 {
1058 PyObject* result = PyList_New(list.count());
1058 PyObject* result = PyList_New(list.count());
1059 int i = 0;
1059 int i = 0;
1060 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1060 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1061 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1061 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1062 i++;
1062 i++;
1063 }
1063 }
1064 return result;
1064 return result;
1065 }
1065 }
1066
1066
1067 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1067 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1068 {
1068 {
1069 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1069 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1070 }
1070 }
1071
1071
1072 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1072 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1073 PyObject* result = PyDict_New();
1073 PyObject* result = PyDict_New();
1074 QVariantMap::const_iterator t = m.constBegin();
1074 QVariantMap::const_iterator t = m.constBegin();
1075 PyObject* key;
1075 PyObject* key;
1076 PyObject* val;
1076 PyObject* val;
1077 for (;t!=m.end();t++) {
1077 for (;t!=m.end();t++) {
1078 key = QStringToPyObject(t.key());
1078 key = QStringToPyObject(t.key());
1079 val = QVariantToPyObject(t.value());
1079 val = QVariantToPyObject(t.value());
1080 PyDict_SetItem(result, key, val);
1080 PyDict_SetItem(result, key, val);
1081 Py_DECREF(key);
1081 Py_DECREF(key);
1082 Py_DECREF(val);
1082 Py_DECREF(val);
1083 }
1083 }
1084 return result;
1084 return result;
1085 }
1085 }
1086
1086
1087 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1087 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1088 PyObject* result = PyTuple_New(l.count());
1088 PyObject* result = PyTuple_New(l.count());
1089 int i = 0;
1089 int i = 0;
1090 QVariant v;
1090 QVariant v;
1091 foreach (v, l) {
1091 foreach (v, l) {
1092 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1092 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1093 i++;
1093 i++;
1094 }
1094 }
1095 // why is the error state bad after this?
1095 // why is the error state bad after this?
1096 PyErr_Clear();
1096 PyErr_Clear();
1097 return result;
1097 return result;
1098 }
1098 }
1099
1099
1100 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1100 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1101 {
1101 {
1102 PyObject* result = PyTuple_New(list->count());
1102 PyObject* result = PyTuple_New(list->count());
1103 int i = 0;
1103 int i = 0;
1104 foreach (void* value, *list) {
1104 foreach (void* value, *list) {
1105 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1105 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1106 i++;
1106 i++;
1107 }
1107 }
1108 return result;
1108 return result;
1109 }
1109 }
1110
1110
1111 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1111 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1112 {
1112 {
1113 bool result = false;
1113 bool result = false;
1114 if (PySequence_Check(obj)) {
1114 if (PySequence_Check(obj)) {
1115 result = true;
1115 result = true;
1116 int count = PySequence_Size(obj);
1116 int count = PySequence_Size(obj);
1117 PyObject* value;
1117 PyObject* value;
1118 for (int i = 0;i<count;i++) {
1118 for (int i = 0;i<count;i++) {
1119 value = PySequence_GetItem(obj,i);
1119 value = PySequence_GetItem(obj,i);
1120 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1120 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1121 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1121 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1122 bool ok;
1122 bool ok;
1123 void* object = castWrapperTo(wrap, type, ok);
1123 void* object = castWrapperTo(wrap, type, ok);
1124 if (ok) {
1124 if (ok) {
1125 list->append(object);
1125 list->append(object);
1126 } else {
1126 } else {
1127 result = false;
1127 result = false;
1128 break;
1128 break;
1129 }
1129 }
1130 }
1130 }
1131 }
1131 }
1132 }
1132 }
1133 return result;
1133 return result;
1134 }
1134 }
1135
1135
1136 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1136 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1137 {
1137 {
1138 int idx = typeName.indexOf("<");
1138 int idx = typeName.indexOf("<");
1139 if (idx>0) {
1139 if (idx>0) {
1140 int idx2 = typeName.indexOf(">");
1140 int idx2 = typeName.indexOf(">");
1141 if (idx2>0) {
1141 if (idx2>0) {
1142 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1142 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1143 return QMetaType::type(innerType.constData());
1143 return QMetaType::type(innerType.constData());
1144 }
1144 }
1145 }
1145 }
1146 return QMetaType::Void;
1146 return QMetaType::Void;
1147 }
1147 }
1148
1148
1149
1149
1150 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1150 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1151 QString r;
1151 QString r;
1152 switch (type) {
1152 switch (type) {
1153 case QVariant::Size: {
1153 case QVariant::Size: {
1154 const QSize* s = static_cast<const QSize*>(data);
1154 const QSize* s = static_cast<const QSize*>(data);
1155 r = QString::number(s->width()) + ", " + QString::number(s->height());
1155 r = QString::number(s->width()) + ", " + QString::number(s->height());
1156 }
1156 }
1157 break;
1157 break;
1158 case QVariant::SizeF: {
1158 case QVariant::SizeF: {
1159 const QSizeF* s = static_cast<const QSizeF*>(data);
1159 const QSizeF* s = static_cast<const QSizeF*>(data);
1160 r = QString::number(s->width()) + ", " + QString::number(s->height());
1160 r = QString::number(s->width()) + ", " + QString::number(s->height());
1161 }
1161 }
1162 break;
1162 break;
1163 case QVariant::Point: {
1163 case QVariant::Point: {
1164 const QPoint* s = static_cast<const QPoint*>(data);
1164 const QPoint* s = static_cast<const QPoint*>(data);
1165 r = QString::number(s->x()) + ", " + QString::number(s->y());
1165 r = QString::number(s->x()) + ", " + QString::number(s->y());
1166 }
1166 }
1167 break;
1167 break;
1168 case QVariant::PointF: {
1168 case QVariant::PointF: {
1169 const QPointF* s = static_cast<const QPointF*>(data);
1169 const QPointF* s = static_cast<const QPointF*>(data);
1170 r = QString::number(s->x()) + ", " + QString::number(s->y());
1170 r = QString::number(s->x()) + ", " + QString::number(s->y());
1171 }
1171 }
1172 break;
1172 break;
1173 case QVariant::Rect: {
1173 case QVariant::Rect: {
1174 const QRect* s = static_cast<const QRect*>(data);
1174 const QRect* s = static_cast<const QRect*>(data);
1175 r = QString::number(s->x()) + ", " + QString::number(s->y());
1175 r = QString::number(s->x()) + ", " + QString::number(s->y());
1176 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1176 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1177 }
1177 }
1178 break;
1178 break;
1179 case QVariant::RectF: {
1179 case QVariant::RectF: {
1180 const QRectF* s = static_cast<const QRectF*>(data);
1180 const QRectF* s = static_cast<const QRectF*>(data);
1181 r = QString::number(s->x()) + ", " + QString::number(s->y());
1181 r = QString::number(s->x()) + ", " + QString::number(s->y());
1182 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1182 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1183 }
1183 }
1184 break;
1184 break;
1185 case QVariant::Date: {
1185 case QVariant::Date: {
1186 const QDate* s = static_cast<const QDate*>(data);
1186 const QDate* s = static_cast<const QDate*>(data);
1187 r = s->toString(Qt::ISODate);
1187 r = s->toString(Qt::ISODate);
1188 }
1188 }
1189 break;
1189 break;
1190 case QVariant::DateTime: {
1190 case QVariant::DateTime: {
1191 const QDateTime* s = static_cast<const QDateTime*>(data);
1191 const QDateTime* s = static_cast<const QDateTime*>(data);
1192 r = s->toString(Qt::ISODate);
1192 r = s->toString(Qt::ISODate);
1193 }
1193 }
1194 break;
1194 break;
1195 case QVariant::Time: {
1195 case QVariant::Time: {
1196 const QTime* s = static_cast<const QTime*>(data);
1196 const QTime* s = static_cast<const QTime*>(data);
1197 r = s->toString(Qt::ISODate);
1197 r = s->toString(Qt::ISODate);
1198 }
1198 }
1199 break;
1199 break;
1200 case QVariant::Pixmap:
1200 case QVariant::Pixmap:
1201 {
1201 {
1202 const QPixmap* s = static_cast<const QPixmap*>(data);
1202 const QPixmap* s = static_cast<const QPixmap*>(data);
1203 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1203 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1204 }
1204 }
1205 break;
1205 break;
1206 case QVariant::Image:
1206 case QVariant::Image:
1207 {
1207 {
1208 const QImage* s = static_cast<const QImage*>(data);
1208 const QImage* s = static_cast<const QImage*>(data);
1209 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1209 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1210 }
1210 }
1211 break;
1211 break;
1212 case QVariant::Url:
1212 case QVariant::Url:
1213 {
1213 {
1214 const QUrl* s = static_cast<const QUrl*>(data);
1214 const QUrl* s = static_cast<const QUrl*>(data);
1215 r = s->toString();
1215 r = s->toString();
1216 }
1216 }
1217 break;
1217 break;
1218 //TODO: add more printing for other variant types
1218 //TODO: add more printing for other variant types
1219 default:
1219 default:
1220 // this creates a copy, but that should not be expensive for typical simple variants
1220 // this creates a copy, but that should not be expensive for typical simple variants
1221 // (but we do not want to do this for our won user types!
1221 // (but we do not want to do this for our won user types!
1222 if (type>0 && type < (int)QVariant::UserType) {
1222 if (type>0 && type < (int)QVariant::UserType) {
1223 QVariant v(type, data);
1223 QVariant v(type, data);
1224 r = v.toString();
1224 r = v.toString();
1225 }
1225 }
1226 }
1226 }
1227 return r;
1227 return r;
1228 }
1228 }
@@ -1,210 +1,210
1 #ifndef _PYTHONQTCONVERSION_H
1 #ifndef _PYTHONQTCONVERSION_H
2 #define _PYTHONQTCONVERSION_H
2 #define _PYTHONQTCONVERSION_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtConversion.h
38 // \file PythonQtConversion.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtMethodInfo.h"
48 #include "PythonQtMethodInfo.h"
49
49
50 #include <QWidget>
50 #include <QWidget>
51 #include <QList>
51 #include <QList>
52 #include <vector>
52 #include <vector>
53
53
54 typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
54 typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
55 typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
55 typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
56
56
57 #define PythonQtRegisterListTemplateConverter(type, innertype) \
57 #define PythonQtRegisterListTemplateConverter(type, innertype) \
58 { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \
58 { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \
59 PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \
59 PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \
60 PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \
60 PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \
61 }
61 }
62
62
63 #define PythonQtRegisterToolClassesTemplateConverter(innertype) \
63 #define PythonQtRegisterToolClassesTemplateConverter(innertype) \
64 PythonQtRegisterListTemplateConverter(QList, innertype); \
64 PythonQtRegisterListTemplateConverter(QList, innertype); \
65 PythonQtRegisterListTemplateConverter(QVector, innertype); \
65 PythonQtRegisterListTemplateConverter(QVector, innertype); \
66 PythonQtRegisterListTemplateConverter(std::vector, innertype);
66 PythonQtRegisterListTemplateConverter(std::vector, innertype);
67 // TODO: add QHash etc. here!
67 // TODO: add QHash etc. here!
68
68
69 //! a static class that offers methods for type conversion
69 //! a static class that offers methods for type conversion
70 class PYTHONQT_EXPORT PythonQtConv {
70 class PYTHONQT_EXPORT PythonQtConv {
71
71
72 public:
72 public:
73
73
74 //! get a ref counted True or False Python object
74 //! get a ref counted True or False Python object
75 static PyObject* GetPyBool(bool val);
75 static PyObject* GetPyBool(bool val);
76
76
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
79
79
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore)
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore)
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL);
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL);
82
82
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
85
85
86 //! converts QString to Python string (unicode!)
86 //! converts QString to Python string (unicode!)
87 static PyObject* QStringToPyObject(const QString& str);
87 static PyObject* QStringToPyObject(const QString& str);
88
88
89 //! converts QStringList to Python tuple
89 //! converts QStringList to Python tuple
90 static PyObject* QStringListToPyObject(const QStringList& list);
90 static PyObject* QStringListToPyObject(const QStringList& list);
91
91
92 //! converts QStringList to Python list
92 //! converts QStringList to Python list
93 static PyObject* QStringListToPyList(const QStringList& list);
93 static PyObject* QStringListToPyList(const QStringList& list);
94
94
95 //! get string representation of py object
95 //! get string representation of py object
96 static QString PyObjGetRepresentation(PyObject* val);
96 static QString PyObjGetRepresentation(PyObject* val);
97
97
98 //! get string value from py object
98 //! get string value from py object
99 static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; }
99 static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; }
100 //! get string value from py object
100 //! get string value from py object
101 static QString PyObjGetString(PyObject* val, bool strict, bool &ok);
101 static QString PyObjGetString(PyObject* val, bool strict, bool &ok);
102 //! get bytes from py object
102 //! get bytes from py object
103 static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok);
103 static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok);
104 //! get int from py object
104 //! get int from py object
105 static int PyObjGetInt(PyObject* val, bool strict, bool &ok);
105 static int PyObjGetInt(PyObject* val, bool strict, bool &ok);
106 //! get int64 from py object
106 //! get int64 from py object
107 static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok);
107 static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok);
108 //! get int64 from py object
108 //! get int64 from py object
109 static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok);
109 static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok);
110 //! get double from py object
110 //! get double from py object
111 static double PyObjGetDouble(PyObject* val, bool strict, bool &ok);
111 static double PyObjGetDouble(PyObject* val, bool strict, bool &ok);
112 //! get bool from py object
112 //! get bool from py object
113 static bool PyObjGetBool(PyObject* val, bool strict, bool &ok);
113 static bool PyObjGetBool(PyObject* val, bool strict, bool &ok);
114
114
115 //! create a string list from python sequence
115 //! create a string list from python sequence
116 static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok);
116 static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok);
117
117
118 //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise
118 //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise
119 //! it will guess from the python type
119 //! it will guess from the python type
120 static QVariant PyObjToQVariant(PyObject* val, int type = -1);
120 static QVariant PyObjToQVariant(PyObject* val, int type = -1);
121
121
122 //! convert QVariant from PyObject
122 //! convert QVariant from PyObject
123 static PyObject* QVariantToPyObject(const QVariant& v);
123 static PyObject* QVariantToPyObject(const QVariant& v);
124
124
125 static PyObject* QVariantMapToPyObject(const QVariantMap& m);
125 static PyObject* QVariantMapToPyObject(const QVariantMap& m);
126 static PyObject* QVariantListToPyObject(const QVariantList& l);
126 static PyObject* QVariantListToPyObject(const QVariantList& l);
127
127
128 //! get human readable string from CPP object (when the metatype is known)
128 //! get human readable string from CPP object (when the metatype is known)
129 static QString CPPObjectToString(int type, const void* data);
129 static QString CPPObjectToString(int type, const void* data);
130
130
131 //! register a converter callback from python to cpp for given metatype
131 //! register a converter callback from python to cpp for given metatype
132 static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); }
132 static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); }
133
133
134 //! register a converter callback from cpp to python for given metatype
134 //! register a converter callback from cpp to python for given metatype
135 static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
135 static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
136
136
137 //! returns the inner type id of a simple template of the form SomeObject<InnerType>
137 //! returns the inner type id of a simple template of the form SomeObject<InnerType>
138 static int getInnerTemplateMetaType(const QByteArray& typeName);
138 static int getInnerTemplateMetaType(const QByteArray& typeName);
139
139
140 //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
140 //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
141 static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
141 static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
142
142
143 public:
143 public:
144
144
145 static PythonQtValueStorage<qint64, 128> global_valueStorage;
145 static PythonQtValueStorage<qint64, 128> global_valueStorage;
146 static PythonQtValueStorage<void*, 128> global_ptrStorage;
146 static PythonQtValueStorage<void*, 128> global_ptrStorage;
147 static PythonQtValueStorage<QVariant, 32> global_variantStorage;
147 static PythonQtValueStorage<QVariant, 32> global_variantStorage;
148
148
149 protected:
149 protected:
150 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
150 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
151 static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
151 static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
152
152
153 //! handle automatic conversion of some special types (QColor, QBrush, ...)
153 //! handle automatic conversion of some special types (QColor, QBrush, ...)
154 static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);
154 static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);
155
155
156 //! converts the list of pointers of given type to Python
156 //! converts the list of pointers of given type to Python
157 static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type);
157 static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type);
158 //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success
158 //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success
159 static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict);
159 static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict);
160
160
161 //! cast wrapper to given className if possible
161 //! cast wrapper to given className if possible
162 static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok);
162 static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok);
163 };
163 };
164
164
165 template<class ListType, class T>
165 template<class ListType, class T>
166 PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
166 PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
167 {
167 {
168 ListType* list = (ListType*)inList;
168 ListType* list = (ListType*)inList;
169 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
169 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
170 if (innerType == QVariant::Invalid) {
170 if (innerType == QVariant::Invalid) {
171 std::cerr << "PythonQtConvertListOfValueTypeToPythonList: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
171 std::cerr << "PythonQtConvertListOfValueTypeToPythonList: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
172 }
172 }
173 PyObject* result = PyTuple_New(list->size());
173 PyObject* result = PyTuple_New(list->size());
174 int i = 0;
174 int i = 0;
175 foreach (const T& value, *list) {
175 foreach (const T& value, *list) {
176 PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value));
176 PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value));
177 i++;
177 i++;
178 }
178 }
179 return result;
179 return result;
180 }
180 }
181
181
182 template<class ListType, class T>
182 template<class ListType, class T>
183 bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
183 bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
184 {
184 {
185 ListType* list = (ListType*)outList;
185 ListType* list = (ListType*)outList;
186 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
186 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
187 if (innerType == QVariant::Invalid) {
187 if (innerType == QVariant::Invalid) {
188 std::cerr << "PythonQtConvertPythonListToListOfValueType: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
188 std::cerr << "PythonQtConvertPythonListToListOfValueType: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
189 }
189 }
190 bool result = false;
190 bool result = false;
191 if (PySequence_Check(obj)) {
191 if (PySequence_Check(obj)) {
192 result = true;
192 result = true;
193 int count = PySequence_Size(obj);
193 int count = PySequence_Size(obj);
194 PyObject* value;
194 PyObject* value;
195 for (int i = 0;i<count;i++) {
195 for (int i = 0;i<count;i++) {
196 value = PySequence_GetItem(obj,i);
196 value = PySequence_GetItem(obj,i);
197 // this is quite some overhead, but it avoids having another large switch...
197 // this is quite some overhead, but it avoids having another large switch...
198 QVariant v = PythonQtConv::PyObjToQVariant(value, innerType);
198 QVariant v = PythonQtConv::PyObjToQVariant(value, innerType);
199 if (v.isValid()) {
199 if (v.isValid()) {
200 list->push_back(qVariantValue<T>(v));
200 list->push_back(qVariantValue<T>(v));
201 } else {
201 } else {
202 result = false;
202 result = false;
203 break;
203 break;
204 }
204 }
205 }
205 }
206 }
206 }
207 return result;
207 return result;
208 }
208 }
209
209
210 #endif
210 #endif
@@ -1,61 +1,61
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtCppWrapperFactory.h
38 // \file PythonQtCppWrapperFactory.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-06
41 // \date 2006-06
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
47 the create() method.
47 the create() method.
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
49 */
49 */
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
51 {
51 {
52 public:
52 public:
53 PythonQtCppWrapperFactory() {};
53 PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
55
55
56 //! create a wrapper for the given object
56 //! create a wrapper for the given object
57 virtual QObject* create(const QByteArray& name, void *ptr) = 0;
57 virtual QObject* create(const QByteArray& name, void *ptr) = 0;
58
58
59 };
59 };
60
60
61 #endif No newline at end of file
61 #endif
@@ -1,509 +1,509
1 #ifndef _PYTHONQTDOC_H
1 #ifndef _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtDoc.h
38 // \file PythonQtDoc.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-10
41 // \date 2006-10
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 /*!
45 /*!
46 \if USE_GLOBAL_DOXYGEN_DOC
46 \if USE_GLOBAL_DOXYGEN_DOC
47 \page PythonQtPage PythonQt Overview
47 \page PythonQtPage PythonQt Overview
48 \else
48 \else
49 \mainpage PythonQt Overview
49 \mainpage PythonQt Overview
50 \endif
50 \endif
51
51
52 \section Introduction
52 \section Introduction
53
53
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for the Qt framework (http://qt.nokia.com).
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for the Qt framework (http://qt.nokia.com).
55 It offers an easy way to embed the Python scripting language into
55 It offers an easy way to embed the Python scripting language into
56 your C++ Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
56 your C++ Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
57
57
58 The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
58 The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
59 application completely in Python. If you want to write your whole application in Python,
59 application completely in Python. If you want to write your whole application in Python,
60 you should use <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> or <a href="http://www.pyside.org">PySide</a> instead.
60 you should use <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> or <a href="http://www.pyside.org">PySide</a> instead.
61
61
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
63 and to script parts of your application via Python, PythonQt is the way to go!
63 and to script parts of your application via Python, PythonQt is the way to go!
64
64
65 PythonQt is a stable library that was developed to make the
65 PythonQt is a stable library that was developed to make the
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
67 scriptable from Python.
67 scriptable from Python.
68
68
69 \section Download
69 \section Download
70
70
71 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
71 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
72 or download a tarball.
72 or download a tarball.
73
73
74 \section Licensing
74 \section Licensing
75
75
76 PythonQt is distributed under the LGPL license, so it pairs well with the LGPL of the Qt 4.5 release and allows
76 PythonQt is distributed under the LGPL license, so it pairs well with the LGPL of the Qt 4.5 release and allows
77 to be used in commercial applications when following the LGPL 2.1 obligations.
77 to be used in commercial applications when following the LGPL 2.1 obligations.
78
78
79 \section LicensingWrapper Licensing of Wrapper Generator
79 \section LicensingWrapper Licensing of Wrapper Generator
80
80
81 The build system of PythonQt makes use of a modified version of the LGPL'ed QtScript generator,
81 The build system of PythonQt makes use of a modified version of the LGPL'ed QtScript generator,
82 located in the "generator" directory.
82 located in the "generator" directory.
83
83
84 See http://qt.gitorious.org/qt-labs/qtscriptgenerator for details on the original project.
84 See http://qt.gitorious.org/qt-labs/qtscriptgenerator for details on the original project.
85 Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
85 Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
86 Qt typesystem files!
86 Qt typesystem files!
87
87
88 The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are free to be used without any licensing restrictions.
88 The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are free to be used without any licensing restrictions.
89
89
90 The generated wrappers are pre-generated and checked-in for Qt 4.6.1, so you only need to build and run the
90 The generated wrappers are pre-generated and checked-in for Qt 4.6.1, so you only need to build and run the
91 generator when you want to build additional wrappers or you want to upgrade/downgrade to another Qt version.
91 generator when you want to build additional wrappers or you want to upgrade/downgrade to another Qt version.
92 You may use the generator to generate C++ bindings for your own C++ classes (e.g., to make them inheritable in Python),
92 You may use the generator to generate C++ bindings for your own C++ classes (e.g., to make them inheritable in Python),
93 , but this is currently not documented and involves creating your own typesystem files (although the Qt Jambi examples might help you).
93 , but this is currently not documented and involves creating your own typesystem files (although the Qt Jambi examples might help you).
94
94
95 \section Features
95 \section Features
96
96
97 The following are the built-in features of the PythonQt library:
97 The following are the built-in features of the PythonQt library:
98
98
99 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
99 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
100 - Connecting Qt Signals to Python functions (both from within Python and from C++)
100 - Connecting Qt Signals to Python functions (both from within Python and from C++)
101 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
101 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
102 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
102 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
103 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
103 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
104 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
104 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
105 - StdOut/Err redirection to Qt signals instead of cout
105 - StdOut/Err redirection to Qt signals instead of cout
106 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
106 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
107 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
107 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
108 - Support for wrapping of user QVariant types which are registerd via QMetaType
108 - Support for wrapping of user QVariant types which are registerd via QMetaType
109 - Support for Qt namespace (with all enumerators)
109 - Support for Qt namespace (with all enumerators)
110 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
110 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
111 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
111 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
112 - Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
112 - Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
113 - Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
113 - Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
114 - Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
114 - Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
115 - Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
115 - Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
116
116
117 \section FeaturesQtAll Features (with PythonQt_QtAll linked in)
117 \section FeaturesQtAll Features (with PythonQt_QtAll linked in)
118
118
119 Thanks to the new wrapper generator, PythonQt now offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
119 Thanks to the new wrapper generator, PythonQt now offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
120 This offers the following features:
120 This offers the following features:
121
121
122 - Complete Qt API wrapped and accessible
122 - Complete Qt API wrapped and accessible
123 - The following modules are available as submodules of the PythonQt module:
123 - The following modules are available as submodules of the PythonQt module:
124 - QtCore
124 - QtCore
125 - QtGui
125 - QtGui
126 - QtNetwork
126 - QtNetwork
127 - QtOpenGL
127 - QtOpenGL
128 - QtSql
128 - QtSql
129 - QtSvg
129 - QtSvg
130 - QtUiTools
130 - QtUiTools
131 - QtWebKit
131 - QtWebKit
132 - QtXml
132 - QtXml
133 - QtXmlPatterns
133 - QtXmlPatterns
134 - (phonon, QtHelp, assistant, designer are currently not supported, this would require some additional effort on the code generator)
134 - (phonon, QtHelp, assistant, designer are currently not supported, this would require some additional effort on the code generator)
135 - For convenience, all classes are also available in the PythonQt.Qt module, for people who do not care in which module a class is located
135 - For convenience, all classes are also available in the PythonQt.Qt module, for people who do not care in which module a class is located
136 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
136 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
137 - Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
137 - Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
138 - Multiple inheritance support (e.g., QGraphicsTextItem is a QObject AND a QGraphicsItem, PythonQt will handle this well)
138 - Multiple inheritance support (e.g., QGraphicsTextItem is a QObject AND a QGraphicsItem, PythonQt will handle this well)
139
139
140 \section Comparision Comparision with PyQt/PySide
140 \section Comparision Comparision with PyQt/PySide
141
141
142 - PythonQt is not as Pythonic as PyQt in many details (e.g. buffer protocol, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
142 - PythonQt is not as Pythonic as PyQt in many details (e.g. buffer protocol, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
143 - PythonQt allows to communicate in both directions, e.g., calling a Python object from C++ AND calling a C++ method from Python, while PyQt only handles the Python->C++ direction
143 - PythonQt allows to communicate in both directions, e.g., calling a Python object from C++ AND calling a C++ method from Python, while PyQt only handles the Python->C++ direction
144 - PythonQt offers properties as Python attributes, while PyQt offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PyQt)
144 - PythonQt offers properties as Python attributes, while PyQt offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PyQt)
145 - PythonQt does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
145 - PythonQt does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
146 - QObject.emit to emit Qt signals from Python is not yet implemented but PythonQt allows to just emit a signal by calling it
146 - QObject.emit to emit Qt signals from Python is not yet implemented but PythonQt allows to just emit a signal by calling it
147 - PythonQt does not (yet) offer to add new signals to Python/C++ objects
147 - PythonQt does not (yet) offer to add new signals to Python/C++ objects
148 - Ownership of objects is a bit different in PythonQt, currently Python classes derived from a C++ class need to be manually referenced in Python to not get deleted too early (this will be fixed)
148 - Ownership of objects is a bit different in PythonQt, currently Python classes derived from a C++ class need to be manually referenced in Python to not get deleted too early (this will be fixed)
149 - QStrings are always converted to unicode Python objects (PyQt returns QString instead), we prefered to return Python strings.
149 - QStrings are always converted to unicode Python objects (PyQt returns QString instead), we prefered to return Python strings.
150 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
150 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
151
151
152 \section Interface
152 \section Interface
153
153
154 The main interface to PythonQt is the PythonQt singleton.
154 The main interface to PythonQt is the PythonQt singleton.
155 PythonQt needs to be initialized via PythonQt::init() once.
155 PythonQt needs to be initialized via PythonQt::init() once.
156 Afterwards you communicate with the singleton via PythonQt::self().
156 Afterwards you communicate with the singleton via PythonQt::self().
157 PythonQt offers a complete Qt binding, which
157 PythonQt offers a complete Qt binding, which
158 needs to be enabled via PythonQt_QtAll::init().
158 needs to be enabled via PythonQt_QtAll::init().
159
159
160
160
161 \section Datatype Datatype Mapping
161 \section Datatype Datatype Mapping
162
162
163 The following table shows the mapping between Python and Qt objects:
163 The following table shows the mapping between Python and Qt objects:
164 <table>
164 <table>
165 <tr><th>Qt/C++</th><th>Python</th></tr>
165 <tr><th>Qt/C++</th><th>Python</th></tr>
166 <tr><td>bool</td><td>bool</td></tr>
166 <tr><td>bool</td><td>bool</td></tr>
167 <tr><td>double</td><td>float</td></tr>
167 <tr><td>double</td><td>float</td></tr>
168 <tr><td>float</td><td>float</td></tr>
168 <tr><td>float</td><td>float</td></tr>
169 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
169 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
170 <tr><td>long</td><td>integer</td></tr>
170 <tr><td>long</td><td>integer</td></tr>
171 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
171 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
172 <tr><td>QString</td><td>unicode string</td></tr>
172 <tr><td>QString</td><td>unicode string</td></tr>
173 <tr><td>QByteArray</td><td>str</td></tr>
173 <tr><td>QByteArray</td><td>str</td></tr>
174 <tr><td>char*</td><td>str</td></tr>
174 <tr><td>char*</td><td>str</td></tr>
175 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
175 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
176 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
176 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
177 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
177 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
178 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
178 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
179 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
179 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
180 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
180 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
181 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
181 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
182 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
182 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
183 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
183 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
184 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
184 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
185 <tr><td>PyObject</td><td>PyObject</td></tr>
185 <tr><td>PyObject</td><td>PyObject</td></tr>
186 </table>
186 </table>
187
187
188 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
188 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
189 a Qt slot.
189 a Qt slot.
190 QVariants are mapped recursively as given above, e.g. a dictionary can
190 QVariants are mapped recursively as given above, e.g. a dictionary can
191 contain lists of dictionaries of doubles.
191 contain lists of dictionaries of doubles.
192 For example a QVariant of type "String" is mapped to a python unicode string.
192 For example a QVariant of type "String" is mapped to a python unicode string.
193 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
193 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
194
194
195 \section QObject QObject Wrapping
195 \section QObject QObject Wrapping
196
196
197 All classes derived from QObject are automatically wrapped with a python wrapper class
197 All classes derived from QObject are automatically wrapped with a python wrapper class
198 when they become visible to the Python interpreter. This can happen via
198 when they become visible to the Python interpreter. This can happen via
199 - the PythonQt::addObject() method
199 - the PythonQt::addObject() method
200 - when a Qt \b slot returns a QObject derived object to python
200 - when a Qt \b slot returns a QObject derived object to python
201 - when a Qt \b signal contains a QObject and is connected to a python function
201 - when a Qt \b signal contains a QObject and is connected to a python function
202
202
203 It is important that you call PythonQt::registerClass() for any QObject derived class
203 It is important that you call PythonQt::registerClass() for any QObject derived class
204 that may become visible to Python, except when you add it via PythonQt::addObject().
204 that may become visible to Python, except when you add it via PythonQt::addObject().
205 This will register the complete parent hierachy of the registered class, so that
205 This will register the complete parent hierachy of the registered class, so that
206 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
206 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
207 parents).
207 parents).
208
208
209 From Python, you can talk to the returned QObjects in a natural way by calling
209 From Python, you can talk to the returned QObjects in a natural way by calling
210 their slots and receiving the return values. You can also read/write all
210 their slots and receiving the return values. You can also read/write all
211 properties of the objects as if they where normal python properties.
211 properties of the objects as if they where normal python properties.
212
212
213 In addition to this, the wrapped objects support
213 In addition to this, the wrapped objects support
214 - className() - returns a string that reprents the classname of the QObject
214 - className() - returns a string that reprents the classname of the QObject
215 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
215 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
216 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
216 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
217 - connect(signal, function) - connect the signal of the given object to a python function
217 - connect(signal, function) - connect the signal of the given object to a python function
218 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
218 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
219 - disconnect(signal, function) - disconnect the signal of the given object from a python function
219 - disconnect(signal, function) - disconnect the signal of the given object from a python function
220 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
220 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
221 - children() - returns the children of the object
221 - children() - returns the children of the object
222 - setParent(QObject) - set the parent
222 - setParent(QObject) - set the parent
223 - QObject* parent() - get the parent
223 - QObject* parent() - get the parent
224
224
225 The below example shows how to connect signals in Python:
225 The below example shows how to connect signals in Python:
226
226
227 \code
227 \code
228 # define a signal handler function
228 # define a signal handler function
229 def someFunction(flag):
229 def someFunction(flag):
230 print flag
230 print flag
231
231
232 # button1 is a QPushButton that has been added to Python via addObject()
232 # button1 is a QPushButton that has been added to Python via addObject()
233 # connect the clicked signal to a python function:
233 # connect the clicked signal to a python function:
234 button1.connect("clicked(bool)", someFunction)
234 button1.connect("clicked(bool)", someFunction)
235
235
236 \endcode
236 \endcode
237
237
238 \section CPP CPP Wrapping
238 \section CPP CPP Wrapping
239
239
240 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
240 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
241 and adding your factory via addWrapperFactory().
241 and adding your factory via addWrapperFactory().
242 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
242 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
243 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
243 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
244 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
244 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
245 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
245 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
246
246
247 \section MetaObject Meta Object/Class access
247 \section MetaObject Meta Object/Class access
248
248
249 For each known C++ class, PythonQt provides a Python class. These classes are visible
249 For each known C++ class, PythonQt provides a Python class. These classes are visible
250 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
250 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
251
251
252 A Meta class supports:
252 A Meta class supports:
253
253
254 - access to all declared enum values
254 - access to all declared enum values
255 - constructors
255 - constructors
256 - static methods
256 - static methods
257 - unbound non-static methods
257 - unbound non-static methods
258 - help() and className()
258 - help() and className()
259
259
260 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
260 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
261
261
262 \code
262 \code
263 from PythonQt import QtCore
263 from PythonQt import QtCore
264
264
265 # namespace access:
265 # namespace access:
266 print QtCore.Qt.AlignLeft
266 print QtCore.Qt.AlignLeft
267
267
268 # constructors
268 # constructors
269 a = QtCore.QSize(12,13)
269 a = QtCore.QSize(12,13)
270 b = QtCore.QFont()
270 b = QtCore.QFont()
271
271
272 # static method
272 # static method
273 QtCore.QDate.currentDate()
273 QtCore.QDate.currentDate()
274
274
275 # enum value
275 # enum value
276 QtCore.QFont.UltraCondensed
276 QtCore.QFont.UltraCondensed
277
277
278 \endcode
278 \endcode
279
279
280 \section Decorators Decorator slots
280 \section Decorators Decorator slots
281
281
282 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
282 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
283
283
284 - constructors
284 - constructors
285 - destructors (for CPP objects)
285 - destructors (for CPP objects)
286 - additional slots
286 - additional slots
287 - static slots (callable on both the Meta object and the instances)
287 - static slots (callable on both the Meta object and the instances)
288
288
289 The idea behind decorators is that we wanted to make it as easy as possible to extend
289 The idea behind decorators is that we wanted to make it as easy as possible to extend
290 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
290 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
291 Python, it looked promising to use this approach for the extension of wrapped objects as well.
291 Python, it looked promising to use this approach for the extension of wrapped objects as well.
292 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
292 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
293 Qt when he wants to create static methods, constructors and additional member functions.
293 Qt when he wants to create static methods, constructors and additional member functions.
294
294
295 The basic idea about decorators is to create a QObject derived class that implements slots
295 The basic idea about decorators is to create a QObject derived class that implements slots
296 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
296 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
297 These slots are then assigned to other classes via the naming convention.
297 These slots are then assigned to other classes via the naming convention.
298
298
299 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
299 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
300 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
300 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
301 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
301 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
302 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
302 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
303
303
304 The below example shows all kinds of decorators in action:
304 The below example shows all kinds of decorators in action:
305
305
306 \code
306 \code
307
307
308 // an example CPP object
308 // an example CPP object
309 class YourCPPObject {
309 class YourCPPObject {
310 public:
310 public:
311 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
311 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
312
312
313 float doSomething(int arg1) { return arg1*a*b; };
313 float doSomething(int arg1) { return arg1*a*b; };
314
314
315 private:
315 private:
316
316
317 int a;
317 int a;
318 float b;
318 float b;
319 };
319 };
320
320
321 // an example decorator
321 // an example decorator
322 class ExampleDecorator : public QObject
322 class ExampleDecorator : public QObject
323 {
323 {
324 Q_OBJECT
324 Q_OBJECT
325
325
326 public slots:
326 public slots:
327 // add a constructor to QSize that takes a QPoint
327 // add a constructor to QSize that takes a QPoint
328 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
328 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
329
329
330 // add a constructor for QPushButton that takes a text and a parent widget
330 // add a constructor for QPushButton that takes a text and a parent widget
331 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
331 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
332
332
333 // add a constructor for a CPP object
333 // add a constructor for a CPP object
334 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
334 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
335
335
336 // add a destructor for a CPP object
336 // add a destructor for a CPP object
337 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
337 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
338
338
339 // add a static method to QWidget
339 // add a static method to QWidget
340 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
340 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
341
341
342 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
342 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
343 void move(QWidget* w, const QPoint& p) { w->move(p); }
343 void move(QWidget* w, const QPoint& p) { w->move(p); }
344
344
345 // add an additional slot to QWidget, overloading the above move method
345 // add an additional slot to QWidget, overloading the above move method
346 void move(QWidget* w, int x, int y) { w->move(x,y); }
346 void move(QWidget* w, int x, int y) { w->move(x,y); }
347
347
348 // add a method to your own CPP object
348 // add a method to your own CPP object
349 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
349 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
350 };
350 };
351
351
352 ...
352 ...
353
353
354 PythonQt::self()->addDecorators(new ExampleDecorator());
354 PythonQt::self()->addDecorators(new ExampleDecorator());
355 PythonQt::self()->registerCPPClass("YourCPPObject");
355 PythonQt::self()->registerCPPClass("YourCPPObject");
356
356
357 \endcode
357 \endcode
358
358
359 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
359 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
360 (all these calls are mapped to the above decorator slots):
360 (all these calls are mapped to the above decorator slots):
361
361
362 \code
362 \code
363 from PythonQt import QtCore, QtGui, YourCPPObject
363 from PythonQt import QtCore, QtGui, YourCPPObject
364
364
365 # call our new constructor of QSize
365 # call our new constructor of QSize
366 size = QtCore.QSize(QPoint(1,2));
366 size = QtCore.QSize(QPoint(1,2));
367
367
368 # call our new QPushButton constructor
368 # call our new QPushButton constructor
369 button = QtGui.QPushButton("sometext");
369 button = QtGui.QPushButton("sometext");
370
370
371 # call the move slot (overload1)
371 # call the move slot (overload1)
372 button.move(QPoint(0,0))
372 button.move(QPoint(0,0))
373
373
374 # call the move slot (overload2)
374 # call the move slot (overload2)
375 button.move(0,0)
375 button.move(0,0)
376
376
377 # call the static method
377 # call the static method
378 grabber = QtGui.QWidget.mouseWrapper();
378 grabber = QtGui.QWidget.mouseWrapper();
379
379
380 # create a CPP object via constructor
380 # create a CPP object via constructor
381 yourCpp = YourCPPObject(1,11.5)
381 yourCpp = YourCPPObject(1,11.5)
382
382
383 # call the wrapped method on CPP object
383 # call the wrapped method on CPP object
384 print yourCpp.doSomething(1);
384 print yourCpp.doSomething(1);
385
385
386 # destructor will be called:
386 # destructor will be called:
387 yourCpp = None
387 yourCpp = None
388
388
389 \endcode
389 \endcode
390
390
391 \section Building
391 \section Building
392
392
393 PythonQt requires Qt 4.6.1 (or higher) and Python 2.5 or 2.6 on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
393 PythonQt requires Qt 4.6.1 (or higher) and Python 2.5 or 2.6 on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
394 To compile PythonQt, you will need a python developer installation which includes Python's header files and
394 To compile PythonQt, you will need a python developer installation which includes Python's header files and
395 the python2x.[lib | dll | so | dynlib].
395 the python2x.[lib | dll | so | dynlib].
396 The build scripts a currently set to use Python 2.5.
396 The build scripts a currently set to use Python 2.5.
397 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
397 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
398
398
399 \subsection Windows
399 \subsection Windows
400
400
401 On Windows, the (non-source) Python Windows installer can be used.
401 On Windows, the (non-source) Python Windows installer can be used.
402 Make sure that you use the same compiler, the current Python distribution is built
402 Make sure that you use the same compiler, the current Python distribution is built
403 with Visual Studio 2003. If you want to use another compiler, you will need to build
403 with Visual Studio 2003. If you want to use another compiler, you will need to build
404 Python yourself, using your compiler.
404 Python yourself, using your compiler.
405
405
406 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
406 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
407 dir of the python installation and \b PYTHON_LIB to point to
407 dir of the python installation and \b PYTHON_LIB to point to
408 the directory where the python lib file is located.
408 the directory where the python lib file is located.
409
409
410 When using the prebuild Python installer, this will be:
410 When using the prebuild Python installer, this will be:
411
411
412 \code
412 \code
413 > set PYTHON_PATH = c:\Python25
413 > set PYTHON_PATH = c:\Python25
414 > set PYTHON_LIB = c:\Python25\libs
414 > set PYTHON_LIB = c:\Python25\libs
415 \endcode
415 \endcode
416
416
417 When using the python sources, this will be something like:
417 When using the python sources, this will be something like:
418
418
419 \code
419 \code
420 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
420 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
421 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
421 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
422 \endcode
422 \endcode
423
423
424 To build all, do the following (after setting the above variables):
424 To build all, do the following (after setting the above variables):
425
425
426 \code
426 \code
427 > cd PythonQtRoot
427 > cd PythonQtRoot
428 > vcvars32
428 > vcvars32
429 > qmake
429 > qmake
430 > nmake
430 > nmake
431 \endcode
431 \endcode
432
432
433 This should build everything. If Python can not be linked or include files can not be found,
433 This should build everything. If Python can not be linked or include files can not be found,
434 you probably need to tweak \b build/python.prf
434 you probably need to tweak \b build/python.prf
435
435
436 The tests and examples are located in PythonQt/lib.
436 The tests and examples are located in PythonQt/lib.
437
437
438 \subsection Linux
438 \subsection Linux
439
439
440 On Linux, you need to install a Python-dev package.
440 On Linux, you need to install a Python-dev package.
441 If Python can not be linked or include files can not be found,
441 If Python can not be linked or include files can not be found,
442 you probably need to tweak \b build/python.prf
442 you probably need to tweak \b build/python.prf
443
443
444 To build PythonQt, just do a:
444 To build PythonQt, just do a:
445
445
446 \code
446 \code
447 > cd PythonQtRoot
447 > cd PythonQtRoot
448 > qmake
448 > qmake
449 > make all
449 > make all
450 \endcode
450 \endcode
451
451
452 The tests and examples are located in PythonQt/lib.
452 The tests and examples are located in PythonQt/lib.
453 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
453 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
454 linker can find the *.so files.
454 linker can find the *.so files.
455
455
456 \subsection MacOsX
456 \subsection MacOsX
457
457
458 On Mac, Python is installed as a Framework, so you should not need to install it.
458 On Mac, Python is installed as a Framework, so you should not need to install it.
459 To build PythonQt, just do a:
459 To build PythonQt, just do a:
460
460
461 \code
461 \code
462 > cd PythonQtRoot
462 > cd PythonQtRoot
463 > qmake
463 > qmake
464 > make all
464 > make all
465 \endcode
465 \endcode
466
466
467 \section Tests
467 \section Tests
468
468
469 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
469 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
470
470
471 \section Examples
471 \section Examples
472
472
473 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
473 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
474 interactive scripting console that shows how to script a simple application.
474 interactive scripting console that shows how to script a simple application.
475
475
476 The following shows how to integrate PythonQt into you Qt application:
476 The following shows how to integrate PythonQt into you Qt application:
477
477
478 \code
478 \code
479 #include "PythonQt.h"
479 #include "PythonQt.h"
480 #include <QApplication>
480 #include <QApplication>
481 ...
481 ...
482
482
483 int main( int argc, char **argv )
483 int main( int argc, char **argv )
484 {
484 {
485
485
486 QApplication qapp(argc, argv);
486 QApplication qapp(argc, argv);
487
487
488 // init PythonQt and Python itself
488 // init PythonQt and Python itself
489 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
489 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
490
490
491
491
492 // get a smart pointer to the __main__ module of the Python interpreter
492 // get a smart pointer to the __main__ module of the Python interpreter
493 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
493 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
494
494
495 // add a QObject as variable of name "example" to the namespace of the __main__ module
495 // add a QObject as variable of name "example" to the namespace of the __main__ module
496 PyExampleObject example;
496 PyExampleObject example;
497 PythonQt::self()->addObject(mainContext, "example", &example);
497 PythonQt::self()->addObject(mainContext, "example", &example);
498
498
499 // do something
499 // do something
500 PythonQt::self()->runScript(mainContext, "print example\n");
500 PythonQt::self()->runScript(mainContext, "print example\n");
501 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
501 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
502 QVariantList args;
502 QVariantList args;
503 args << 42 << 47;
503 args << 42 << 47;
504 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
504 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
505 ...
505 ...
506 \endcode
506 \endcode
507
507
508
508
509 */
509 */
@@ -1,72 +1,72
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtImportFileInterface.h
38 // \file PythonQtImportFileInterface.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <QDateTime>
45 #include <QDateTime>
46 #include <QString>
46 #include <QString>
47 #include <QByteArray>
47 #include <QByteArray>
48
48
49 //! Defines an abstract interface to file access for the Python import statement.
49 //! Defines an abstract interface to file access for the Python import statement.
50 //! see PythonQt::setImporter()
50 //! see PythonQt::setImporter()
51 class PythonQtImportFileInterface {
51 class PythonQtImportFileInterface {
52
52
53 public:
53 public:
54 // get rid of warnings
54 // get rid of warnings
55 virtual ~PythonQtImportFileInterface() {}
55 virtual ~PythonQtImportFileInterface() {}
56
56
57 //! read the given file as byte array, without doing any linefeed translations
57 //! read the given file as byte array, without doing any linefeed translations
58 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
58 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
59
59
60 //! read a source file, expects a readable Python text file with translated line feeds.
60 //! read a source file, expects a readable Python text file with translated line feeds.
61 //! If the file can not be load OR it can not be verified, ok is set to false
61 //! If the file can not be load OR it can not be verified, ok is set to false
62 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
62 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
63
63
64 //! returns if the file exists
64 //! returns if the file exists
65 virtual bool exists(const QString& filename) = 0;
65 virtual bool exists(const QString& filename) = 0;
66
66
67 //! get the last modified data of a file
67 //! get the last modified data of a file
68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
69
69
70 };
70 };
71
71
72 #endif No newline at end of file
72 #endif
@@ -1,793 +1,793
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtImporter.h
35 // \file PythonQtImporter.h
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 // This module was inspired by the zipimport.c module of the original
40 // This module was inspired by the zipimport.c module of the original
41 // Python distribution. Most of the functions are identical or slightly
41 // Python distribution. Most of the functions are identical or slightly
42 // modified to do all the loading of Python files via an external file interface.
42 // modified to do all the loading of Python files via an external file interface.
43 // In contrast to zipimport.c, this module also writes *.pyc files
43 // In contrast to zipimport.c, this module also writes *.pyc files
44 // automatically if it has write access/is not inside of a zip file.
44 // automatically if it has write access/is not inside of a zip file.
45 //----------------------------------------------------------------------------------
45 //----------------------------------------------------------------------------------
46
46
47 #include "PythonQtImporter.h"
47 #include "PythonQtImporter.h"
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQt.h"
49 #include "PythonQt.h"
50 #include "PythonQtConversion.h"
50 #include "PythonQtConversion.h"
51 #include <QFile>
51 #include <QFile>
52 #include <QFileInfo>
52 #include <QFileInfo>
53
53
54 #define IS_SOURCE 0x0
54 #define IS_SOURCE 0x0
55 #define IS_BYTECODE 0x1
55 #define IS_BYTECODE 0x1
56 #define IS_PACKAGE 0x2
56 #define IS_PACKAGE 0x2
57
57
58 struct st_mlab_searchorder {
58 struct st_mlab_searchorder {
59 char suffix[14];
59 char suffix[14];
60 int type;
60 int type;
61 };
61 };
62
62
63 /* mlab_searchorder defines how we search for a module in the Zip
63 /* mlab_searchorder defines how we search for a module in the Zip
64 archive: we first search for a package __init__, then for
64 archive: we first search for a package __init__, then for
65 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
65 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
66 are swapped by initmlabimport() if we run in optimized mode. Also,
66 are swapped by initmlabimport() if we run in optimized mode. Also,
67 '/' is replaced by SEP there. */
67 '/' is replaced by SEP there. */
68 struct st_mlab_searchorder mlab_searchorder[] = {
68 struct st_mlab_searchorder mlab_searchorder[] = {
69 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
71 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
71 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
72 {".pyc", IS_BYTECODE},
72 {".pyc", IS_BYTECODE},
73 {".pyo", IS_BYTECODE},
73 {".pyo", IS_BYTECODE},
74 {".py", IS_SOURCE},
74 {".py", IS_SOURCE},
75 {"", 0}
75 {"", 0}
76 };
76 };
77
77
78 extern PyTypeObject PythonQtImporter_Type;
78 extern PyTypeObject PythonQtImporter_Type;
79 PyObject *PythonQtImportError;
79 PyObject *PythonQtImportError;
80
80
81 QString PythonQtImport::getSubName(const QString& str)
81 QString PythonQtImport::getSubName(const QString& str)
82 {
82 {
83 int idx = str.lastIndexOf('.');
83 int idx = str.lastIndexOf('.');
84 if (idx!=-1) {
84 if (idx!=-1) {
85 return str.mid(idx+1);
85 return str.mid(idx+1);
86 } else {
86 } else {
87 return str;
87 return str;
88 }
88 }
89 }
89 }
90
90
91 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
91 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
92 {
92 {
93 ModuleInfo info;
93 ModuleInfo info;
94 QString subname;
94 QString subname;
95 struct st_mlab_searchorder *zso;
95 struct st_mlab_searchorder *zso;
96
96
97 subname = getSubName(fullname);
97 subname = getSubName(fullname);
98 QString path = *self->_path + "/" + subname;
98 QString path = *self->_path + "/" + subname;
99
99
100 QString test;
100 QString test;
101 for (zso = mlab_searchorder; *zso->suffix; zso++) {
101 for (zso = mlab_searchorder; *zso->suffix; zso++) {
102 test = path + zso->suffix;
102 test = path + zso->suffix;
103 if (PythonQt::importInterface()->exists(test)) {
103 if (PythonQt::importInterface()->exists(test)) {
104 info.fullPath = test;
104 info.fullPath = test;
105 info.moduleName = subname;
105 info.moduleName = subname;
106 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
106 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
107 return info;
107 return info;
108 }
108 }
109 }
109 }
110 // test if it is a shared library
110 // test if it is a shared library
111 foreach(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
111 foreach(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
112 test = path+suffix;
112 test = path+suffix;
113 if (PythonQt::importInterface()->exists(test)) {
113 if (PythonQt::importInterface()->exists(test)) {
114 info.fullPath = test;
114 info.fullPath = test;
115 info.moduleName = subname;
115 info.moduleName = subname;
116 info.type = MI_SHAREDLIBRARY;
116 info.type = MI_SHAREDLIBRARY;
117 }
117 }
118 }
118 }
119 return info;
119 return info;
120 }
120 }
121
121
122
122
123 /* PythonQtImporter.__init__
123 /* PythonQtImporter.__init__
124 Just store the path argument (or reject if it is in the ignorePaths list
124 Just store the path argument (or reject if it is in the ignorePaths list
125 */
125 */
126 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
126 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
127 {
127 {
128 self->_path = NULL;
128 self->_path = NULL;
129
129
130 const char* cpath;
130 const char* cpath;
131 if (!PyArg_ParseTuple(args, "s",
131 if (!PyArg_ParseTuple(args, "s",
132 &cpath))
132 &cpath))
133 return -1;
133 return -1;
134
134
135 QString path(cpath);
135 QString path(cpath);
136 if (PythonQt::importInterface()->exists(path)) {
136 if (PythonQt::importInterface()->exists(path)) {
137 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
137 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
138 foreach(QString ignorePath, ignorePaths) {
138 foreach(QString ignorePath, ignorePaths) {
139 if (path.startsWith(ignorePath)) {
139 if (path.startsWith(ignorePath)) {
140 PyErr_SetString(PythonQtImportError,
140 PyErr_SetString(PythonQtImportError,
141 "path ignored");
141 "path ignored");
142 return -1;
142 return -1;
143 }
143 }
144 }
144 }
145
145
146 self->_path = new QString(path);
146 self->_path = new QString(path);
147 return 0;
147 return 0;
148 } else {
148 } else {
149 PyErr_SetString(PythonQtImportError,
149 PyErr_SetString(PythonQtImportError,
150 "path does not exist error");
150 "path does not exist error");
151 return -1;
151 return -1;
152 }
152 }
153 }
153 }
154
154
155 void
155 void
156 PythonQtImporter_dealloc(PythonQtImporter *self)
156 PythonQtImporter_dealloc(PythonQtImporter *self)
157 {
157 {
158 // free the stored path
158 // free the stored path
159 if (self->_path) delete self->_path;
159 if (self->_path) delete self->_path;
160 // free ourself
160 // free ourself
161 self->ob_type->tp_free((PyObject *)self);
161 self->ob_type->tp_free((PyObject *)self);
162 }
162 }
163
163
164
164
165 /* Check whether we can satisfy the import of the module named by
165 /* Check whether we can satisfy the import of the module named by
166 'fullname'. Return self if we can, None if we can't. */
166 'fullname'. Return self if we can, None if we can't. */
167 PyObject *
167 PyObject *
168 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
168 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
169 {
169 {
170 PythonQtImporter *self = (PythonQtImporter *)obj;
170 PythonQtImporter *self = (PythonQtImporter *)obj;
171 PyObject *path = NULL;
171 PyObject *path = NULL;
172 char *fullname;
172 char *fullname;
173
173
174 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
174 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
175 &fullname, &path))
175 &fullname, &path))
176 return NULL;
176 return NULL;
177
177
178 //qDebug() << "looking for " << fullname << " at " << *self->_path;
178 //qDebug() << "looking for " << fullname << " at " << *self->_path;
179
179
180 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
180 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
181 if (info.type != PythonQtImport::MI_NOT_FOUND) {
181 if (info.type != PythonQtImport::MI_NOT_FOUND) {
182 Py_INCREF(self);
182 Py_INCREF(self);
183 return (PyObject *)self;
183 return (PyObject *)self;
184 } else {
184 } else {
185 Py_INCREF(Py_None);
185 Py_INCREF(Py_None);
186 return Py_None;
186 return Py_None;
187 }
187 }
188 }
188 }
189
189
190 /* Load and return the module named by 'fullname'. */
190 /* Load and return the module named by 'fullname'. */
191 PyObject *
191 PyObject *
192 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
192 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
193 {
193 {
194 PythonQtImporter *self = (PythonQtImporter *)obj;
194 PythonQtImporter *self = (PythonQtImporter *)obj;
195 PyObject *code = NULL, *mod = NULL, *dict = NULL;
195 PyObject *code = NULL, *mod = NULL, *dict = NULL;
196 char *fullname;
196 char *fullname;
197
197
198 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
198 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
199 &fullname))
199 &fullname))
200 return NULL;
200 return NULL;
201
201
202 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
202 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
203 if (info.type == PythonQtImport::MI_NOT_FOUND) {
203 if (info.type == PythonQtImport::MI_NOT_FOUND) {
204 return NULL;
204 return NULL;
205 }
205 }
206
206
207 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
207 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
208 QString fullPath;
208 QString fullPath;
209 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
209 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
210 if (code == NULL) {
210 if (code == NULL) {
211 return NULL;
211 return NULL;
212 }
212 }
213
213
214 mod = PyImport_AddModule(fullname);
214 mod = PyImport_AddModule(fullname);
215 if (mod == NULL) {
215 if (mod == NULL) {
216 Py_DECREF(code);
216 Py_DECREF(code);
217 return NULL;
217 return NULL;
218 }
218 }
219 dict = PyModule_GetDict(mod);
219 dict = PyModule_GetDict(mod);
220
220
221 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
221 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
222 Py_DECREF(code);
222 Py_DECREF(code);
223 Py_DECREF(mod);
223 Py_DECREF(mod);
224 return NULL;
224 return NULL;
225 }
225 }
226
226
227 if (info.type == PythonQtImport::MI_PACKAGE) {
227 if (info.type == PythonQtImport::MI_PACKAGE) {
228 PyObject *pkgpath, *fullpath;
228 PyObject *pkgpath, *fullpath;
229 QString subname = info.moduleName;
229 QString subname = info.moduleName;
230 int err;
230 int err;
231
231
232 fullpath = PyString_FromFormat("%s%c%s",
232 fullpath = PyString_FromFormat("%s%c%s",
233 self->_path->toLatin1().constData(),
233 self->_path->toLatin1().constData(),
234 SEP,
234 SEP,
235 subname.toLatin1().constData());
235 subname.toLatin1().constData());
236 if (fullpath == NULL) {
236 if (fullpath == NULL) {
237 Py_DECREF(code);
237 Py_DECREF(code);
238 Py_DECREF(mod);
238 Py_DECREF(mod);
239 return NULL;
239 return NULL;
240 }
240 }
241
241
242 pkgpath = Py_BuildValue("[O]", fullpath);
242 pkgpath = Py_BuildValue("[O]", fullpath);
243 Py_DECREF(fullpath);
243 Py_DECREF(fullpath);
244 if (pkgpath == NULL) {
244 if (pkgpath == NULL) {
245 Py_DECREF(code);
245 Py_DECREF(code);
246 Py_DECREF(mod);
246 Py_DECREF(mod);
247 return NULL;
247 return NULL;
248 }
248 }
249 err = PyDict_SetItemString(dict, "__path__", pkgpath);
249 err = PyDict_SetItemString(dict, "__path__", pkgpath);
250 Py_DECREF(pkgpath);
250 Py_DECREF(pkgpath);
251 if (err != 0) {
251 if (err != 0) {
252 Py_DECREF(code);
252 Py_DECREF(code);
253 Py_DECREF(mod);
253 Py_DECREF(mod);
254 return NULL;
254 return NULL;
255 }
255 }
256 }
256 }
257 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
257 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
258 Py_DECREF(code);
258 Py_DECREF(code);
259 if (Py_VerboseFlag) {
259 if (Py_VerboseFlag) {
260 PySys_WriteStderr("import %s # loaded from %s\n",
260 PySys_WriteStderr("import %s # loaded from %s\n",
261 fullname, fullPath.toLatin1().constData());
261 fullname, fullPath.toLatin1().constData());
262 }
262 }
263 } else {
263 } else {
264 PythonQtObjectPtr imp;
264 PythonQtObjectPtr imp;
265 imp.setNewRef(PyImport_ImportModule("imp"));
265 imp.setNewRef(PyImport_ImportModule("imp"));
266
266
267 // Create a PyList with the current path as its single element,
267 // Create a PyList with the current path as its single element,
268 // which is required for find_module (it won't accept a tuple...)
268 // which is required for find_module (it won't accept a tuple...)
269 PythonQtObjectPtr pathList;
269 PythonQtObjectPtr pathList;
270 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
270 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
271
271
272 QVariantList args;
272 QVariantList args;
273 // Pass the module name without the package prefix
273 // Pass the module name without the package prefix
274 args.append(info.moduleName);
274 args.append(info.moduleName);
275 // And the path where we know that the shared library is
275 // And the path where we know that the shared library is
276 args.append(QVariant::fromValue(pathList));
276 args.append(QVariant::fromValue(pathList));
277 QVariant result = imp.call("find_module", args);
277 QVariant result = imp.call("find_module", args);
278 if (result.isValid()) {
278 if (result.isValid()) {
279 // This will return a tuple with (file, pathname, description)
279 // This will return a tuple with (file, pathname, description)
280 QVariantList list = result.toList();
280 QVariantList list = result.toList();
281 if (list.count()==3) {
281 if (list.count()==3) {
282 // We prepend the full module name (including package prefix)
282 // We prepend the full module name (including package prefix)
283 list.prepend(fullname);
283 list.prepend(fullname);
284 // And call "load_module" with (fullname, file, pathname, description)
284 // And call "load_module" with (fullname, file, pathname, description)
285 PythonQtObjectPtr module = imp.call("load_module", list);
285 PythonQtObjectPtr module = imp.call("load_module", list);
286 mod = module.object();
286 mod = module.object();
287 if (mod) {
287 if (mod) {
288 Py_INCREF(mod);
288 Py_INCREF(mod);
289 }
289 }
290
290
291 // Finally, we need to close the file again, which find_module opened for us
291 // Finally, we need to close the file again, which find_module opened for us
292 PythonQtObjectPtr file = list.at(1);
292 PythonQtObjectPtr file = list.at(1);
293 file.call("close");
293 file.call("close");
294 }
294 }
295 }
295 }
296 }
296 }
297 return mod;
297 return mod;
298 }
298 }
299
299
300
300
301 PyObject *
301 PyObject *
302 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
302 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
303 {
303 {
304 // EXTRA, NOT YET IMPLEMENTED
304 // EXTRA, NOT YET IMPLEMENTED
305 return NULL;
305 return NULL;
306 }
306 }
307
307
308 PyObject *
308 PyObject *
309 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
309 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
310 {
310 {
311 PythonQtImporter *self = (PythonQtImporter *)obj;
311 PythonQtImporter *self = (PythonQtImporter *)obj;
312 char *fullname;
312 char *fullname;
313
313
314 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
314 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
315 return NULL;
315 return NULL;
316
316
317 QString notused;
317 QString notused;
318 return PythonQtImport::getModuleCode(self, fullname, notused);
318 return PythonQtImport::getModuleCode(self, fullname, notused);
319 }
319 }
320
320
321 PyObject *
321 PyObject *
322 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
322 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
323 {
323 {
324 // EXTRA, NOT YET IMPLEMENTED
324 // EXTRA, NOT YET IMPLEMENTED
325 return NULL;
325 return NULL;
326 }
326 }
327
327
328 PyDoc_STRVAR(doc_find_module,
328 PyDoc_STRVAR(doc_find_module,
329 "find_module(fullname, path=None) -> self or None.\n\
329 "find_module(fullname, path=None) -> self or None.\n\
330 \n\
330 \n\
331 Search for a module specified by 'fullname'. 'fullname' must be the\n\
331 Search for a module specified by 'fullname'. 'fullname' must be the\n\
332 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
332 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
333 instance itself if the module was found, or None if it wasn't.\n\
333 instance itself if the module was found, or None if it wasn't.\n\
334 The optional 'path' argument is ignored -- it's there for compatibility\n\
334 The optional 'path' argument is ignored -- it's there for compatibility\n\
335 with the importer protocol.");
335 with the importer protocol.");
336
336
337 PyDoc_STRVAR(doc_load_module,
337 PyDoc_STRVAR(doc_load_module,
338 "load_module(fullname) -> module.\n\
338 "load_module(fullname) -> module.\n\
339 \n\
339 \n\
340 Load the module specified by 'fullname'. 'fullname' must be the\n\
340 Load the module specified by 'fullname'. 'fullname' must be the\n\
341 fully qualified (dotted) module name. It returns the imported\n\
341 fully qualified (dotted) module name. It returns the imported\n\
342 module, or raises PythonQtImportError if it wasn't found.");
342 module, or raises PythonQtImportError if it wasn't found.");
343
343
344 PyDoc_STRVAR(doc_get_data,
344 PyDoc_STRVAR(doc_get_data,
345 "get_data(pathname) -> string with file data.\n\
345 "get_data(pathname) -> string with file data.\n\
346 \n\
346 \n\
347 Return the data associated with 'pathname'. Raise IOError if\n\
347 Return the data associated with 'pathname'. Raise IOError if\n\
348 the file wasn't found.");
348 the file wasn't found.");
349
349
350 PyDoc_STRVAR(doc_get_code,
350 PyDoc_STRVAR(doc_get_code,
351 "get_code(fullname) -> code object.\n\
351 "get_code(fullname) -> code object.\n\
352 \n\
352 \n\
353 Return the code object for the specified module. Raise PythonQtImportError\n\
353 Return the code object for the specified module. Raise PythonQtImportError\n\
354 is the module couldn't be found.");
354 is the module couldn't be found.");
355
355
356 PyDoc_STRVAR(doc_get_source,
356 PyDoc_STRVAR(doc_get_source,
357 "get_source(fullname) -> source string.\n\
357 "get_source(fullname) -> source string.\n\
358 \n\
358 \n\
359 Return the source code for the specified module. Raise PythonQtImportError\n\
359 Return the source code for the specified module. Raise PythonQtImportError\n\
360 is the module couldn't be found, return None if the archive does\n\
360 is the module couldn't be found, return None if the archive does\n\
361 contain the module, but has no source for it.");
361 contain the module, but has no source for it.");
362
362
363 PyMethodDef PythonQtImporter_methods[] = {
363 PyMethodDef PythonQtImporter_methods[] = {
364 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
364 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
365 doc_find_module},
365 doc_find_module},
366 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
366 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
367 doc_load_module},
367 doc_load_module},
368 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
368 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
369 doc_get_data},
369 doc_get_data},
370 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
370 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
371 doc_get_code},
371 doc_get_code},
372 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
372 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
373 doc_get_source},
373 doc_get_source},
374 {NULL, NULL, 0 , NULL} /* sentinel */
374 {NULL, NULL, 0 , NULL} /* sentinel */
375 };
375 };
376
376
377
377
378 PyDoc_STRVAR(PythonQtImporter_doc,
378 PyDoc_STRVAR(PythonQtImporter_doc,
379 "PythonQtImporter(path) -> PythonQtImporter object\n\
379 "PythonQtImporter(path) -> PythonQtImporter object\n\
380 \n\
380 \n\
381 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
381 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
382 . Every path is accepted.");
382 . Every path is accepted.");
383
383
384 #define DEFERRED_ADDRESS(ADDR) 0
384 #define DEFERRED_ADDRESS(ADDR) 0
385
385
386 PyTypeObject PythonQtImporter_Type = {
386 PyTypeObject PythonQtImporter_Type = {
387 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
387 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
388 0,
388 0,
389 "PythonQtImport.PythonQtImporter",
389 "PythonQtImport.PythonQtImporter",
390 sizeof(PythonQtImporter),
390 sizeof(PythonQtImporter),
391 0, /* tp_itemsize */
391 0, /* tp_itemsize */
392 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
392 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
393 0, /* tp_print */
393 0, /* tp_print */
394 0, /* tp_getattr */
394 0, /* tp_getattr */
395 0, /* tp_setattr */
395 0, /* tp_setattr */
396 0, /* tp_compare */
396 0, /* tp_compare */
397 0, /* tp_repr */
397 0, /* tp_repr */
398 0, /* tp_as_number */
398 0, /* tp_as_number */
399 0, /* tp_as_sequence */
399 0, /* tp_as_sequence */
400 0, /* tp_as_mapping */
400 0, /* tp_as_mapping */
401 0, /* tp_hash */
401 0, /* tp_hash */
402 0, /* tp_call */
402 0, /* tp_call */
403 0, /* tp_str */
403 0, /* tp_str */
404 PyObject_GenericGetAttr, /* tp_getattro */
404 PyObject_GenericGetAttr, /* tp_getattro */
405 0, /* tp_setattro */
405 0, /* tp_setattro */
406 0, /* tp_as_buffer */
406 0, /* tp_as_buffer */
407 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
407 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
408 PythonQtImporter_doc, /* tp_doc */
408 PythonQtImporter_doc, /* tp_doc */
409 0, /* tp_traverse */
409 0, /* tp_traverse */
410 0, /* tp_clear */
410 0, /* tp_clear */
411 0, /* tp_richcompare */
411 0, /* tp_richcompare */
412 0, /* tp_weaklistoffset */
412 0, /* tp_weaklistoffset */
413 0, /* tp_iter */
413 0, /* tp_iter */
414 0, /* tp_iternext */
414 0, /* tp_iternext */
415 PythonQtImporter_methods, /* tp_methods */
415 PythonQtImporter_methods, /* tp_methods */
416 0, /* tp_members */
416 0, /* tp_members */
417 0, /* tp_getset */
417 0, /* tp_getset */
418 0, /* tp_base */
418 0, /* tp_base */
419 0, /* tp_dict */
419 0, /* tp_dict */
420 0, /* tp_descr_get */
420 0, /* tp_descr_get */
421 0, /* tp_descr_set */
421 0, /* tp_descr_set */
422 0, /* tp_dictoffset */
422 0, /* tp_dictoffset */
423 (initproc)PythonQtImporter_init, /* tp_init */
423 (initproc)PythonQtImporter_init, /* tp_init */
424 PyType_GenericAlloc, /* tp_alloc */
424 PyType_GenericAlloc, /* tp_alloc */
425 PyType_GenericNew, /* tp_new */
425 PyType_GenericNew, /* tp_new */
426 PyObject_Del, /* tp_free */
426 PyObject_Del, /* tp_free */
427 };
427 };
428
428
429
429
430 /* Given a buffer, return the long that is represented by the first
430 /* Given a buffer, return the long that is represented by the first
431 4 bytes, encoded as little endian. This partially reimplements
431 4 bytes, encoded as little endian. This partially reimplements
432 marshal.c:r_long() */
432 marshal.c:r_long() */
433 long
433 long
434 PythonQtImport::getLong(unsigned char *buf)
434 PythonQtImport::getLong(unsigned char *buf)
435 {
435 {
436 long x;
436 long x;
437 x = buf[0];
437 x = buf[0];
438 x |= (long)buf[1] << 8;
438 x |= (long)buf[1] << 8;
439 x |= (long)buf[2] << 16;
439 x |= (long)buf[2] << 16;
440 x |= (long)buf[3] << 24;
440 x |= (long)buf[3] << 24;
441 #if SIZEOF_LONG > 4
441 #if SIZEOF_LONG > 4
442 /* Sign extension for 64-bit machines */
442 /* Sign extension for 64-bit machines */
443 x |= -(x & 0x80000000L);
443 x |= -(x & 0x80000000L);
444 #endif
444 #endif
445 return x;
445 return x;
446 }
446 }
447
447
448 FILE *
448 FILE *
449 open_exclusive(const QString& filename)
449 open_exclusive(const QString& filename)
450 {
450 {
451 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
451 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
452 /* Use O_EXCL to avoid a race condition when another process tries to
452 /* Use O_EXCL to avoid a race condition when another process tries to
453 write the same file. When that happens, our open() call fails,
453 write the same file. When that happens, our open() call fails,
454 which is just fine (since it's only a cache).
454 which is just fine (since it's only a cache).
455 XXX If the file exists and is writable but the directory is not
455 XXX If the file exists and is writable but the directory is not
456 writable, the file will never be written. Oh well.
456 writable, the file will never be written. Oh well.
457 */
457 */
458 QFile::remove(filename);
458 QFile::remove(filename);
459
459
460 int fd;
460 int fd;
461 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
461 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
462 #ifdef O_BINARY
462 #ifdef O_BINARY
463 flags |= O_BINARY; /* necessary for Windows */
463 flags |= O_BINARY; /* necessary for Windows */
464 #endif
464 #endif
465 #ifdef WIN32
465 #ifdef WIN32
466 fd = _wopen(filename.ucs2(), flags, 0666);
466 fd = _wopen(filename.ucs2(), flags, 0666);
467 #else
467 #else
468 fd = open(filename.local8Bit(), flags, 0666);
468 fd = open(filename.local8Bit(), flags, 0666);
469 #endif
469 #endif
470 if (fd < 0)
470 if (fd < 0)
471 return NULL;
471 return NULL;
472 return fdopen(fd, "wb");
472 return fdopen(fd, "wb");
473 #else
473 #else
474 /* Best we can do -- on Windows this can't happen anyway */
474 /* Best we can do -- on Windows this can't happen anyway */
475 return fopen(filename.toLocal8Bit().constData(), "wb");
475 return fopen(filename.toLocal8Bit().constData(), "wb");
476 #endif
476 #endif
477 }
477 }
478
478
479
479
480 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
480 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
481 {
481 {
482 FILE *fp;
482 FILE *fp;
483 // we do not want to write Qt resources to disk, do we?
483 // we do not want to write Qt resources to disk, do we?
484 if (filename.startsWith(":")) {
484 if (filename.startsWith(":")) {
485 return;
485 return;
486 }
486 }
487 fp = open_exclusive(filename);
487 fp = open_exclusive(filename);
488 if (fp == NULL) {
488 if (fp == NULL) {
489 if (Py_VerboseFlag)
489 if (Py_VerboseFlag)
490 PySys_WriteStderr(
490 PySys_WriteStderr(
491 "# can't create %s\n", filename.toLatin1().constData());
491 "# can't create %s\n", filename.toLatin1().constData());
492 return;
492 return;
493 }
493 }
494 #if PY_VERSION_HEX < 0x02040000
494 #if PY_VERSION_HEX < 0x02040000
495 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
495 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
496 #else
496 #else
497 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
497 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
498 #endif
498 #endif
499 /* First write a 0 for mtime */
499 /* First write a 0 for mtime */
500 #if PY_VERSION_HEX < 0x02040000
500 #if PY_VERSION_HEX < 0x02040000
501 PyMarshal_WriteLongToFile(0L, fp);
501 PyMarshal_WriteLongToFile(0L, fp);
502 #else
502 #else
503 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
503 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
504 #endif
504 #endif
505 #if PY_VERSION_HEX < 0x02040000
505 #if PY_VERSION_HEX < 0x02040000
506 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
506 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
507 #else
507 #else
508 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
508 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
509 #endif
509 #endif
510 if (ferror(fp)) {
510 if (ferror(fp)) {
511 if (Py_VerboseFlag)
511 if (Py_VerboseFlag)
512 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
512 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
513 /* Don't keep partial file */
513 /* Don't keep partial file */
514 fclose(fp);
514 fclose(fp);
515 QFile::remove(filename);
515 QFile::remove(filename);
516 return;
516 return;
517 }
517 }
518 /* Now write the true mtime */
518 /* Now write the true mtime */
519 fseek(fp, 4L, 0);
519 fseek(fp, 4L, 0);
520 #if PY_VERSION_HEX < 0x02040000
520 #if PY_VERSION_HEX < 0x02040000
521 PyMarshal_WriteLongToFile(mtime, fp);
521 PyMarshal_WriteLongToFile(mtime, fp);
522 #else
522 #else
523 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
523 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
524 #endif
524 #endif
525 fflush(fp);
525 fflush(fp);
526 fclose(fp);
526 fclose(fp);
527 if (Py_VerboseFlag)
527 if (Py_VerboseFlag)
528 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
528 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
529 //#ifdef macintosh
529 //#ifdef macintosh
530 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
530 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
531 //#endif
531 //#endif
532 }
532 }
533
533
534 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
534 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
535 and return the code object. Return None if it the magic word doesn't
535 and return the code object. Return None if it the magic word doesn't
536 match (we do this instead of raising an exception as we fall back
536 match (we do this instead of raising an exception as we fall back
537 to .py if available and we don't want to mask other errors).
537 to .py if available and we don't want to mask other errors).
538 Returns a new reference. */
538 Returns a new reference. */
539 PyObject *
539 PyObject *
540 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
540 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
541 {
541 {
542 PyObject *code;
542 PyObject *code;
543 // ugly cast, but Python API is not const safe
543 // ugly cast, but Python API is not const safe
544 char *buf = (char*) data.constData();
544 char *buf = (char*) data.constData();
545 int size = data.size();
545 int size = data.size();
546
546
547 if (size <= 9) {
547 if (size <= 9) {
548 PySys_WriteStderr("# %s has bad pyc data\n",
548 PySys_WriteStderr("# %s has bad pyc data\n",
549 path.toLatin1().constData());
549 path.toLatin1().constData());
550 Py_INCREF(Py_None);
550 Py_INCREF(Py_None);
551 return Py_None;
551 return Py_None;
552 }
552 }
553
553
554 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
554 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
555 if (Py_VerboseFlag)
555 if (Py_VerboseFlag)
556 PySys_WriteStderr("# %s has bad magic\n",
556 PySys_WriteStderr("# %s has bad magic\n",
557 path.toLatin1().constData());
557 path.toLatin1().constData());
558 Py_INCREF(Py_None);
558 Py_INCREF(Py_None);
559 return Py_None;
559 return Py_None;
560 }
560 }
561
561
562 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
562 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
563 if (Py_VerboseFlag)
563 if (Py_VerboseFlag)
564 PySys_WriteStderr("# %s has bad mtime\n",
564 PySys_WriteStderr("# %s has bad mtime\n",
565 path.toLatin1().constData());
565 path.toLatin1().constData());
566 Py_INCREF(Py_None);
566 Py_INCREF(Py_None);
567 return Py_None;
567 return Py_None;
568 }
568 }
569
569
570 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
570 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
571 if (code == NULL)
571 if (code == NULL)
572 return NULL;
572 return NULL;
573 if (!PyCode_Check(code)) {
573 if (!PyCode_Check(code)) {
574 Py_DECREF(code);
574 Py_DECREF(code);
575 PyErr_Format(PyExc_TypeError,
575 PyErr_Format(PyExc_TypeError,
576 "compiled module %.200s is not a code object",
576 "compiled module %.200s is not a code object",
577 path.toLatin1().constData());
577 path.toLatin1().constData());
578 return NULL;
578 return NULL;
579 }
579 }
580 return code;
580 return code;
581 }
581 }
582
582
583
583
584 /* Given a string buffer containing Python source code, compile it
584 /* Given a string buffer containing Python source code, compile it
585 return and return a code object as a new reference. */
585 return and return a code object as a new reference. */
586 PyObject *
586 PyObject *
587 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
587 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
588 {
588 {
589 PyObject *code;
589 PyObject *code;
590 QByteArray data1 = data;
590 QByteArray data1 = data;
591 // in qt4, data is null terminated
591 // in qt4, data is null terminated
592 // data1.resize(data.size()+1);
592 // data1.resize(data.size()+1);
593 // data1.data()[data.size()-1] = 0;
593 // data1.data()[data.size()-1] = 0;
594 code = Py_CompileString(data.data(), path.toLatin1().constData(),
594 code = Py_CompileString(data.data(), path.toLatin1().constData(),
595 Py_file_input);
595 Py_file_input);
596 return code;
596 return code;
597 }
597 }
598
598
599
599
600 /* Return the code object for the module named by 'fullname' from the
600 /* Return the code object for the module named by 'fullname' from the
601 Zip archive as a new reference. */
601 Zip archive as a new reference. */
602 PyObject *
602 PyObject *
603 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
603 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
604 {
604 {
605 PyObject *code;
605 PyObject *code;
606
606
607 QByteArray qdata;
607 QByteArray qdata;
608 if (!isbytecode) {
608 if (!isbytecode) {
609 // mlabDebugConst("MLABPython", "reading source " << path);
609 // mlabDebugConst("MLABPython", "reading source " << path);
610 bool ok;
610 bool ok;
611 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
611 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
612 if (!ok) {
612 if (!ok) {
613 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
613 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
614 return NULL;
614 return NULL;
615 }
615 }
616 if (qdata == " ") {
616 if (qdata == " ") {
617 qdata.clear();
617 qdata.clear();
618 }
618 }
619 } else {
619 } else {
620 qdata = PythonQt::importInterface()->readFileAsBytes(path);
620 qdata = PythonQt::importInterface()->readFileAsBytes(path);
621 }
621 }
622
622
623 if (isbytecode) {
623 if (isbytecode) {
624 // mlabDebugConst("MLABPython", "reading bytecode " << path);
624 // mlabDebugConst("MLABPython", "reading bytecode " << path);
625 code = unmarshalCode(path, qdata, mtime);
625 code = unmarshalCode(path, qdata, mtime);
626 }
626 }
627 else {
627 else {
628 // mlabDebugConst("MLABPython", "compiling source " << path);
628 // mlabDebugConst("MLABPython", "compiling source " << path);
629 code = compileSource(path, qdata);
629 code = compileSource(path, qdata);
630 if (code) {
630 if (code) {
631 // save a pyc file if possible
631 // save a pyc file if possible
632 QDateTime time;
632 QDateTime time;
633 time = PythonQt::importInterface()->lastModifiedDate(path);
633 time = PythonQt::importInterface()->lastModifiedDate(path);
634 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
634 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
635 }
635 }
636 }
636 }
637 return code;
637 return code;
638 }
638 }
639
639
640 time_t
640 time_t
641 PythonQtImport::getMTimeOfSource(const QString& path)
641 PythonQtImport::getMTimeOfSource(const QString& path)
642 {
642 {
643 time_t mtime = 0;
643 time_t mtime = 0;
644 QString path2 = path;
644 QString path2 = path;
645 path2.truncate(path.length()-1);
645 path2.truncate(path.length()-1);
646
646
647 if (PythonQt::importInterface()->exists(path2)) {
647 if (PythonQt::importInterface()->exists(path2)) {
648 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
648 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
649 }
649 }
650
650
651 return mtime;
651 return mtime;
652 }
652 }
653
653
654 /* Get the code object associated with the module specified by
654 /* Get the code object associated with the module specified by
655 'fullname'. */
655 'fullname'. */
656 PyObject *
656 PyObject *
657 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
657 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
658 {
658 {
659 QString subname;
659 QString subname;
660 struct st_mlab_searchorder *zso;
660 struct st_mlab_searchorder *zso;
661
661
662 subname = getSubName(fullname);
662 subname = getSubName(fullname);
663 QString path = *self->_path + "/" + subname;
663 QString path = *self->_path + "/" + subname;
664
664
665 QString test;
665 QString test;
666 for (zso = mlab_searchorder; *zso->suffix; zso++) {
666 for (zso = mlab_searchorder; *zso->suffix; zso++) {
667 PyObject *code = NULL;
667 PyObject *code = NULL;
668 test = path + zso->suffix;
668 test = path + zso->suffix;
669
669
670 if (Py_VerboseFlag > 1)
670 if (Py_VerboseFlag > 1)
671 PySys_WriteStderr("# trying %s\n",
671 PySys_WriteStderr("# trying %s\n",
672 test.toLatin1().constData());
672 test.toLatin1().constData());
673 if (PythonQt::importInterface()->exists(test)) {
673 if (PythonQt::importInterface()->exists(test)) {
674 time_t mtime = 0;
674 time_t mtime = 0;
675 int ispackage = zso->type & IS_PACKAGE;
675 int ispackage = zso->type & IS_PACKAGE;
676 int isbytecode = zso->type & IS_BYTECODE;
676 int isbytecode = zso->type & IS_BYTECODE;
677
677
678 if (isbytecode) {
678 if (isbytecode) {
679 mtime = getMTimeOfSource(test);
679 mtime = getMTimeOfSource(test);
680 }
680 }
681 code = getCodeFromData(test, isbytecode, ispackage, mtime);
681 code = getCodeFromData(test, isbytecode, ispackage, mtime);
682 if (code == Py_None) {
682 if (code == Py_None) {
683 Py_DECREF(code);
683 Py_DECREF(code);
684 continue;
684 continue;
685 }
685 }
686 if (code != NULL) {
686 if (code != NULL) {
687 modpath = test;
687 modpath = test;
688 }
688 }
689 return code;
689 return code;
690 }
690 }
691 }
691 }
692 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
692 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
693
693
694 return NULL;
694 return NULL;
695 }
695 }
696
696
697 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
697 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
698 {
698 {
699 QString r;
699 QString r;
700 int i = str.lastIndexOf('.');
700 int i = str.lastIndexOf('.');
701 if (i!=-1) {
701 if (i!=-1) {
702 r = str.mid(0,i) + "." + ext;
702 r = str.mid(0,i) + "." + ext;
703 } else {
703 } else {
704 r = str + "." + ext;
704 r = str + "." + ext;
705 }
705 }
706 return r;
706 return r;
707 }
707 }
708
708
709 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
709 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
710 {
710 {
711 PyObject* code;
711 PyObject* code;
712 const static QString pycStr("pyc");
712 const static QString pycStr("pyc");
713 QString pyc = replaceExtension(file, pycStr);
713 QString pyc = replaceExtension(file, pycStr);
714 if (PythonQt::importInterface()->exists(pyc)) {
714 if (PythonQt::importInterface()->exists(pyc)) {
715 time_t mtime = 0;
715 time_t mtime = 0;
716 mtime = getMTimeOfSource(pyc);
716 mtime = getMTimeOfSource(pyc);
717 code = getCodeFromData(pyc, true, false, mtime);
717 code = getCodeFromData(pyc, true, false, mtime);
718 if (code != Py_None && code != NULL) {
718 if (code != Py_None && code != NULL) {
719 return code;
719 return code;
720 }
720 }
721 if (code) {
721 if (code) {
722 Py_DECREF(code);
722 Py_DECREF(code);
723 }
723 }
724 }
724 }
725 code = getCodeFromData(file,false,false,0);
725 code = getCodeFromData(file,false,false,0);
726 return code;
726 return code;
727 }
727 }
728
728
729 /* Module init */
729 /* Module init */
730
730
731 PyDoc_STRVAR(mlabimport_doc,
731 PyDoc_STRVAR(mlabimport_doc,
732 "Imports python files into PythonQt, completely replaces internal python import");
732 "Imports python files into PythonQt, completely replaces internal python import");
733
733
734 void PythonQtImport::init()
734 void PythonQtImport::init()
735 {
735 {
736 static bool first = true;
736 static bool first = true;
737 if (!first) {
737 if (!first) {
738 return;
738 return;
739 }
739 }
740 first = false;
740 first = false;
741
741
742 PyObject *mod;
742 PyObject *mod;
743
743
744 if (PyType_Ready(&PythonQtImporter_Type) < 0)
744 if (PyType_Ready(&PythonQtImporter_Type) < 0)
745 return;
745 return;
746
746
747 /* Correct directory separator */
747 /* Correct directory separator */
748 mlab_searchorder[0].suffix[0] = SEP;
748 mlab_searchorder[0].suffix[0] = SEP;
749 mlab_searchorder[1].suffix[0] = SEP;
749 mlab_searchorder[1].suffix[0] = SEP;
750 mlab_searchorder[2].suffix[0] = SEP;
750 mlab_searchorder[2].suffix[0] = SEP;
751 if (Py_OptimizeFlag) {
751 if (Py_OptimizeFlag) {
752 /* Reverse *.pyc and *.pyo */
752 /* Reverse *.pyc and *.pyo */
753 struct st_mlab_searchorder tmp;
753 struct st_mlab_searchorder tmp;
754 tmp = mlab_searchorder[0];
754 tmp = mlab_searchorder[0];
755 mlab_searchorder[0] = mlab_searchorder[1];
755 mlab_searchorder[0] = mlab_searchorder[1];
756 mlab_searchorder[1] = tmp;
756 mlab_searchorder[1] = tmp;
757 tmp = mlab_searchorder[3];
757 tmp = mlab_searchorder[3];
758 mlab_searchorder[3] = mlab_searchorder[4];
758 mlab_searchorder[3] = mlab_searchorder[4];
759 mlab_searchorder[4] = tmp;
759 mlab_searchorder[4] = tmp;
760 }
760 }
761
761
762 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
762 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
763 NULL, PYTHON_API_VERSION);
763 NULL, PYTHON_API_VERSION);
764
764
765 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
765 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
766 PyExc_ImportError, NULL);
766 PyExc_ImportError, NULL);
767 if (PythonQtImportError == NULL)
767 if (PythonQtImportError == NULL)
768 return;
768 return;
769
769
770 Py_INCREF(PythonQtImportError);
770 Py_INCREF(PythonQtImportError);
771 if (PyModule_AddObject(mod, "PythonQtImportError",
771 if (PyModule_AddObject(mod, "PythonQtImportError",
772 PythonQtImportError) < 0)
772 PythonQtImportError) < 0)
773 return;
773 return;
774
774
775 Py_INCREF(&PythonQtImporter_Type);
775 Py_INCREF(&PythonQtImporter_Type);
776 if (PyModule_AddObject(mod, "PythonQtImporter",
776 if (PyModule_AddObject(mod, "PythonQtImporter",
777 (PyObject *)&PythonQtImporter_Type) < 0)
777 (PyObject *)&PythonQtImporter_Type) < 0)
778 return;
778 return;
779
779
780 // set our importer into the path_hooks to handle all path on sys.path
780 // set our importer into the path_hooks to handle all path on sys.path
781 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
781 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
782 PyObject* path_hooks = PySys_GetObject("path_hooks");
782 PyObject* path_hooks = PySys_GetObject("path_hooks");
783 PyList_Append(path_hooks, classobj);
783 PyList_Append(path_hooks, classobj);
784
784
785 #ifndef WIN32
785 #ifndef WIN32
786 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
786 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
787 PyObject* modules = PyImport_GetModuleDict();
787 PyObject* modules = PyImport_GetModuleDict();
788 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
788 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
789 if (encodingsModule != NULL) {
789 if (encodingsModule != NULL) {
790 PyImport_ReloadModule(encodingsModule);
790 PyImport_ReloadModule(encodingsModule);
791 }
791 }
792 #endif
792 #endif
793 }
793 }
@@ -1,137 +1,137
1 #ifndef _PYTHONQTIMPORTER_
1 #ifndef _PYTHONQTIMPORTER_
2 #define _PYTHONQTIMPORTER_
2 #define _PYTHONQTIMPORTER_
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtImporter.h
38 // \file PythonQtImporter.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: stk $
40 // \author Last changed by $Author: stk $
41 // \date 2004-06
41 // \date 2004-06
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "Python.h"
45 #include "Python.h"
46 #include "structmember.h"
46 #include "structmember.h"
47 #include "osdefs.h"
47 #include "osdefs.h"
48 #include "marshal.h"
48 #include "marshal.h"
49 #include "compile.h"
49 #include "compile.h"
50 #include <time.h>
50 #include <time.h>
51
51
52 #include <qobject.h>
52 #include <qobject.h>
53 #include <qstring.h>
53 #include <qstring.h>
54
54
55
55
56 //! defines a python object that stores a Qt slot info
56 //! defines a python object that stores a Qt slot info
57 typedef struct _PythonQtImporter {
57 typedef struct _PythonQtImporter {
58 PyObject_HEAD
58 PyObject_HEAD
59 QString* _path;
59 QString* _path;
60 } PythonQtImporter;
60 } PythonQtImporter;
61
61
62
62
63 //! implements importing of python files into PythonQt
63 //! implements importing of python files into PythonQt
64 /*! also compiles/marshalls/unmarshalls py/pyc files and handles time stamps correctly
64 /*! also compiles/marshalls/unmarshalls py/pyc files and handles time stamps correctly
65 */
65 */
66 class PythonQtImport
66 class PythonQtImport
67 {
67 {
68 public:
68 public:
69
69
70 enum ModuleType {
70 enum ModuleType {
71 MI_NOT_FOUND,
71 MI_NOT_FOUND,
72 MI_MODULE,
72 MI_MODULE,
73 MI_PACKAGE,
73 MI_PACKAGE,
74 MI_SHAREDLIBRARY
74 MI_SHAREDLIBRARY
75 };
75 };
76
76
77 struct ModuleInfo {
77 struct ModuleInfo {
78 ModuleInfo() {
78 ModuleInfo() {
79 type = MI_NOT_FOUND;
79 type = MI_NOT_FOUND;
80 }
80 }
81 QString fullPath; //!< the full path to the found file
81 QString fullPath; //!< the full path to the found file
82 QString moduleName; //!< the module name without the package prefix
82 QString moduleName; //!< the module name without the package prefix
83 ModuleType type;
83 ModuleType type;
84 };
84 };
85
85
86 //! initialize
86 //! initialize
87 static void init();
87 static void init();
88
88
89 //! writes the python code to disk, marshalling and writing the time stamp
89 //! writes the python code to disk, marshalling and writing the time stamp
90 static void writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime);
90 static void writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime);
91
91
92 /*! Given the contents of a .py[co] file in a buffer, unmarshal the data
92 /*! Given the contents of a .py[co] file in a buffer, unmarshal the data
93 and return the code object. Return None if it the magic word doesn't
93 and return the code object. Return None if it the magic word doesn't
94 match (we do this instead of raising an exception as we fall back
94 match (we do this instead of raising an exception as we fall back
95 to .py if available and we don't want to mask other errors).
95 to .py if available and we don't want to mask other errors).
96 Returns a new reference. */
96 Returns a new reference. */
97 static PyObject *unmarshalCode(const QString& path, const QByteArray& data, time_t mtime);
97 static PyObject *unmarshalCode(const QString& path, const QByteArray& data, time_t mtime);
98
98
99 //! Given a string buffer containing Python source code, compile it
99 //! Given a string buffer containing Python source code, compile it
100 //! return and return a code object as a new reference.
100 //! return and return a code object as a new reference.
101 static PyObject *compileSource(const QString& path, const QByteArray& data);
101 static PyObject *compileSource(const QString& path, const QByteArray& data);
102
102
103 //! Return the code object for the module named by 'fullname' from the
103 //! Return the code object for the module named by 'fullname' from the
104 //! Zip archive as a new reference.
104 //! Zip archive as a new reference.
105 static PyObject *getCodeFromData(const QString& path, int isbytecode = 0, int ispackage = 0,
105 static PyObject *getCodeFromData(const QString& path, int isbytecode = 0, int ispackage = 0,
106 time_t mtime = 0);
106 time_t mtime = 0);
107
107
108 //! Get the code object associated with the module specified by
108 //! Get the code object associated with the module specified by
109 //! 'fullname'.
109 //! 'fullname'.
110 static PyObject * getModuleCode(PythonQtImporter *self,
110 static PyObject * getModuleCode(PythonQtImporter *self,
111 const char* fullname, QString& modpath);
111 const char* fullname, QString& modpath);
112
112
113
113
114 //! gets the compiled code for the given *.py file if there is a valid pyc file, otherwise compiles the file and writes the pyc
114 //! gets the compiled code for the given *.py file if there is a valid pyc file, otherwise compiles the file and writes the pyc
115 static PyObject* getCodeFromPyc(const QString& file);
115 static PyObject* getCodeFromPyc(const QString& file);
116
116
117 //! Return if module exists and is a package or a module
117 //! Return if module exists and is a package or a module
118 static ModuleInfo getModuleInfo(PythonQtImporter* self, const QString& fullname);
118 static ModuleInfo getModuleInfo(PythonQtImporter* self, const QString& fullname);
119
119
120 //! get the last name of a dot chain (first.second.last)
120 //! get the last name of a dot chain (first.second.last)
121 static QString getSubName(const QString& str);
121 static QString getSubName(const QString& str);
122
122
123 //! Given a buffer, return the long that is represented by the first
123 //! Given a buffer, return the long that is represented by the first
124 //! 4 bytes, encoded as little endian. This partially reimplements
124 //! 4 bytes, encoded as little endian. This partially reimplements
125 //! marshal.c:r_long()
125 //! marshal.c:r_long()
126 static long getLong(unsigned char *buf);
126 static long getLong(unsigned char *buf);
127
127
128 //! get time stamp of file
128 //! get time stamp of file
129 static time_t getMTimeOfSource(const QString& path);
129 static time_t getMTimeOfSource(const QString& path);
130
130
131 //! replace extension of file
131 //! replace extension of file
132 static QString replaceExtension(const QString& str, const QString& ext);
132 static QString replaceExtension(const QString& str, const QString& ext);
133
133
134 };
134 };
135
135
136 #endif
136 #endif
137
137
@@ -1,726 +1,726
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtInstanceWrapper.cpp
35 // \file PythonQtInstanceWrapper.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtInstanceWrapper.h"
42 #include "PythonQtInstanceWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include "PythonQtSlot.h"
45 #include "PythonQtSlot.h"
46 #include "PythonQtClassInfo.h"
46 #include "PythonQtClassInfo.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtClassWrapper.h"
48 #include "PythonQtClassWrapper.h"
49
49
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 {
51 {
52 // take the class info from our type object
52 // take the class info from our type object
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 }
54 }
55
55
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57
57
58 // is this a C++ wrapper?
58 // is this a C++ wrapper?
59 if (self->_wrappedPtr) {
59 if (self->_wrappedPtr) {
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61
61
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 // we own our qobject, so we delete it now:
63 // we own our qobject, so we delete it now:
64 delete self->_obj;
64 delete self->_obj;
65 self->_obj = NULL;
65 self->_obj = NULL;
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 int type = self->classInfo()->metaTypeId();
67 int type = self->classInfo()->metaTypeId();
68 if (self->_useQMetaTypeDestroy && type>=0) {
68 if (self->_useQMetaTypeDestroy && type>=0) {
69 // use QMetaType to destroy the object
69 // use QMetaType to destroy the object
70 QMetaType::destroy(type, self->_wrappedPtr);
70 QMetaType::destroy(type, self->_wrappedPtr);
71 } else {
71 } else {
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 if (slot) {
73 if (slot) {
74 void* args[2];
74 void* args[2];
75 args[0] = NULL;
75 args[0] = NULL;
76 args[1] = &self->_wrappedPtr;
76 args[1] = &self->_wrappedPtr;
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 self->_wrappedPtr = NULL;
78 self->_wrappedPtr = NULL;
79 } else {
79 } else {
80 if (type>=0) {
80 if (type>=0) {
81 // use QMetaType to destroy the object
81 // use QMetaType to destroy the object
82 QMetaType::destroy(type, self->_wrappedPtr);
82 QMetaType::destroy(type, self->_wrappedPtr);
83 } else {
83 } else {
84 // TODO: warn about not being able to destroy the object?
84 // TODO: warn about not being able to destroy the object?
85 }
85 }
86 }
86 }
87 }
87 }
88 }
88 }
89 } else {
89 } else {
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 if (self->_objPointerCopy) {
91 if (self->_objPointerCopy) {
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 }
93 }
94 if (self->_obj) {
94 if (self->_obj) {
95 if (force || self->_ownedByPythonQt) {
95 if (force || self->_ownedByPythonQt) {
96 if (force || !self->_obj->parent()) {
96 if (force || !self->_obj->parent()) {
97 delete self->_obj;
97 delete self->_obj;
98 }
98 }
99 } else {
99 } else {
100 if (self->_obj->parent()==NULL) {
100 if (self->_obj->parent()==NULL) {
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 }
103 }
104 }
104 }
105 }
105 }
106 }
106 }
107 self->_obj = NULL;
107 self->_obj = NULL;
108 }
108 }
109
109
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 {
111 {
112 PythonQtInstanceWrapper_deleteObject(self);
112 PythonQtInstanceWrapper_deleteObject(self);
113 self->_obj.~QPointer<QObject>();
113 self->_obj.~QPointer<QObject>();
114 self->ob_type->tp_free((PyObject*)self);
114 self->ob_type->tp_free((PyObject*)self);
115 }
115 }
116
116
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 {
118 {
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 PythonQtInstanceWrapper *self;
120 PythonQtInstanceWrapper *self;
121 static PyObject* emptyTuple = NULL;
121 static PyObject* emptyTuple = NULL;
122 if (emptyTuple==NULL) {
122 if (emptyTuple==NULL) {
123 emptyTuple = PyTuple_New(0);
123 emptyTuple = PyTuple_New(0);
124 }
124 }
125
125
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127
127
128 if (self != NULL) {
128 if (self != NULL) {
129 new (&self->_obj) QPointer<QObject>();
129 new (&self->_obj) QPointer<QObject>();
130 self->_wrappedPtr = NULL;
130 self->_wrappedPtr = NULL;
131 self->_ownedByPythonQt = false;
131 self->_ownedByPythonQt = false;
132 self->_useQMetaTypeDestroy = false;
132 self->_useQMetaTypeDestroy = false;
133 self->_isShellInstance = false;
133 self->_isShellInstance = false;
134 }
134 }
135 return (PyObject *)self;
135 return (PyObject *)self;
136 }
136 }
137
137
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 {
139 {
140 if (args == PythonQtPrivate::dummyTuple()) {
140 if (args == PythonQtPrivate::dummyTuple()) {
141 // we are called from the internal PythonQt API, so our data will be filled later on...
141 // we are called from the internal PythonQt API, so our data will be filled later on...
142 return 0;
142 return 0;
143 }
143 }
144
144
145 // we are called from python, try to construct our object
145 // we are called from python, try to construct our object
146 if (self->classInfo()->constructors()) {
146 if (self->classInfo()->constructors()) {
147 void* directCPPPointer = NULL;
147 void* directCPPPointer = NULL;
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 if (PyErr_Occurred()) {
149 if (PyErr_Occurred()) {
150 return -1;
150 return -1;
151 }
151 }
152 if (directCPPPointer) {
152 if (directCPPPointer) {
153 // change ownershipflag to be owned by PythonQt
153 // change ownershipflag to be owned by PythonQt
154 self->_ownedByPythonQt = true;
154 self->_ownedByPythonQt = true;
155 self->_useQMetaTypeDestroy = false;
155 self->_useQMetaTypeDestroy = false;
156 if (self->classInfo()->isCPPWrapper()) {
156 if (self->classInfo()->isCPPWrapper()) {
157 self->_wrappedPtr = directCPPPointer;
157 self->_wrappedPtr = directCPPPointer;
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 } else {
159 } else {
160 self->setQObject((QObject*)directCPPPointer);
160 self->setQObject((QObject*)directCPPPointer);
161 }
161 }
162 // register with PythonQt
162 // register with PythonQt
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164
164
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 if (cb) {
166 if (cb) {
167 // if we are a derived python class, we set the wrapper
167 // if we are a derived python class, we set the wrapper
168 // to activate the shell class, otherwise we just ignore that it is a shell...
168 // to activate the shell class, otherwise we just ignore that it is a shell...
169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 // which is the case for all non-python derived types
170 // which is the case for all non-python derived types
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 // set the wrapper and remember that we have a shell instance!
172 // set the wrapper and remember that we have a shell instance!
173 (*cb)(directCPPPointer, self);
173 (*cb)(directCPPPointer, self);
174 self->_isShellInstance = true;
174 self->_isShellInstance = true;
175 }
175 }
176 }
176 }
177 }
177 }
178 } else {
178 } else {
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 return -1;
181 return -1;
182 }
182 }
183 return 0;
183 return 0;
184 }
184 }
185
185
186 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
186 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
187 {
187 {
188 bool validPtrs = false;
188 bool validPtrs = false;
189 bool areSamePtrs = false;
189 bool areSamePtrs = false;
190 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
190 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
192 validPtrs = true;
192 validPtrs = true;
193 PythonQtInstanceWrapper* w1 = wrapper;
193 PythonQtInstanceWrapper* w1 = wrapper;
194 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
194 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
195 // check pointers directly
195 // check pointers directly
196 if (w1->_wrappedPtr != NULL) {
196 if (w1->_wrappedPtr != NULL) {
197 if (w1->_wrappedPtr == w2->_wrappedPtr) {
197 if (w1->_wrappedPtr == w2->_wrappedPtr) {
198 areSamePtrs = true;
198 areSamePtrs = true;
199 }
199 }
200 } else if (w1->_obj == w2->_obj) {
200 } else if (w1->_obj == w2->_obj) {
201 areSamePtrs = true;
201 areSamePtrs = true;
202 }
202 }
203 } else if (other == Py_None) {
203 } else if (other == Py_None) {
204 validPtrs = true;
204 validPtrs = true;
205 if (wrapper->_obj || wrapper->_wrappedPtr) {
205 if (wrapper->_obj || wrapper->_wrappedPtr) {
206 areSamePtrs = false;
206 areSamePtrs = false;
207 } else {
207 } else {
208 areSamePtrs = true;
208 areSamePtrs = true;
209 }
209 }
210 }
210 }
211 }
211 }
212
212
213 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
213 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
214 // shortcut if richcompare is not supported:
214 // shortcut if richcompare is not supported:
215 if (validPtrs && code == Py_EQ) {
215 if (validPtrs && code == Py_EQ) {
216 return PythonQtConv::GetPyBool(areSamePtrs);
216 return PythonQtConv::GetPyBool(areSamePtrs);
217 } else if (validPtrs && code == Py_NE) {
217 } else if (validPtrs && code == Py_NE) {
218 return PythonQtConv::GetPyBool(!areSamePtrs);
218 return PythonQtConv::GetPyBool(!areSamePtrs);
219 }
219 }
220 Py_INCREF(Py_NotImplemented);
220 Py_INCREF(Py_NotImplemented);
221 return Py_NotImplemented;
221 return Py_NotImplemented;
222 }
222 }
223
223
224 QByteArray memberName;
224 QByteArray memberName;
225 switch (code) {
225 switch (code) {
226 case Py_LT:
226 case Py_LT:
227 {
227 {
228 static QByteArray name = "__lt__";
228 static QByteArray name = "__lt__";
229 memberName = name;
229 memberName = name;
230 }
230 }
231 break;
231 break;
232
232
233 case Py_LE:
233 case Py_LE:
234 {
234 {
235 static QByteArray name = "__le__";
235 static QByteArray name = "__le__";
236 memberName = name;
236 memberName = name;
237 }
237 }
238 break;
238 break;
239
239
240 case Py_EQ:
240 case Py_EQ:
241 {
241 {
242 static QByteArray name = "__eq__";
242 static QByteArray name = "__eq__";
243 memberName = name;
243 memberName = name;
244 }
244 }
245 break;
245 break;
246
246
247 case Py_NE:
247 case Py_NE:
248 {
248 {
249 static QByteArray name = "__ne__";
249 static QByteArray name = "__ne__";
250 memberName = name;
250 memberName = name;
251 }
251 }
252 break;
252 break;
253
253
254 case Py_GT:
254 case Py_GT:
255 {
255 {
256 static QByteArray name = "__gt__";
256 static QByteArray name = "__gt__";
257 memberName = name;
257 memberName = name;
258 }
258 }
259 break;
259 break;
260
260
261 case Py_GE:
261 case Py_GE:
262 {
262 {
263 static QByteArray name = "__ge__";
263 static QByteArray name = "__ge__";
264 memberName = name;
264 memberName = name;
265 }
265 }
266 break;
266 break;
267 }
267 }
268
268
269 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
269 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
270 if (opSlot._type == PythonQtMemberInfo::Slot) {
270 if (opSlot._type == PythonQtMemberInfo::Slot) {
271 // TODO get rid of tuple
271 // TODO get rid of tuple
272 PyObject* args = PyTuple_New(1);
272 PyObject* args = PyTuple_New(1);
273 Py_INCREF(other);
273 Py_INCREF(other);
274 PyTuple_SET_ITEM(args, 0, other);
274 PyTuple_SET_ITEM(args, 0, other);
275 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
275 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
276 Py_DECREF(args);
276 Py_DECREF(args);
277 return result;
277 return result;
278 } else {
278 } else {
279 // not implemented, let python try something else!
279 // not implemented, let python try something else!
280 Py_INCREF(Py_NotImplemented);
280 Py_INCREF(Py_NotImplemented);
281 return Py_NotImplemented;
281 return Py_NotImplemented;
282 }
282 }
283 }
283 }
284
284
285
285
286 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
286 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
287 {
287 {
288 return PyString_FromString(obj->ob_type->tp_name);
288 return PyString_FromString(obj->ob_type->tp_name);
289 }
289 }
290
290
291 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
291 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
292 {
292 {
293 return PythonQt::self()->helpCalled(obj->classInfo());
293 return PythonQt::self()->helpCalled(obj->classInfo());
294 }
294 }
295
295
296 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
296 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
297 {
297 {
298 PythonQtInstanceWrapper_deleteObject(self, true);
298 PythonQtInstanceWrapper_deleteObject(self, true);
299 Py_INCREF(Py_None);
299 Py_INCREF(Py_None);
300 return Py_None;
300 return Py_None;
301 }
301 }
302
302
303
303
304 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
304 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
305 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
305 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
306 "Return the classname of the object"
306 "Return the classname of the object"
307 },
307 },
308 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
308 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
309 "Shows the help of available methods for this class"
309 "Shows the help of available methods for this class"
310 },
310 },
311 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
311 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
312 "Deletes the C++ object (at your own risk, my friend!)"
312 "Deletes the C++ object (at your own risk, my friend!)"
313 },
313 },
314 {NULL, NULL, 0, NULL} /* Sentinel */
314 {NULL, NULL, 0, NULL} /* Sentinel */
315 };
315 };
316
316
317
317
318 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
318 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
319 {
319 {
320 const char *attributeName;
320 const char *attributeName;
321 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
321 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
322
322
323 if ((attributeName = PyString_AsString(name)) == NULL) {
323 if ((attributeName = PyString_AsString(name)) == NULL) {
324 return NULL;
324 return NULL;
325 }
325 }
326
326
327 if (qstrcmp(attributeName, "__dict__")==0) {
327 if (qstrcmp(attributeName, "__dict__")==0) {
328 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
328 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
329 dict = PyDict_Copy(dict);
329 dict = PyDict_Copy(dict);
330
330
331 if (wrapper->_obj) {
331 if (wrapper->_obj) {
332 // only the properties are missing, the rest is already available from
332 // only the properties are missing, the rest is already available from
333 // PythonQtClassWrapper...
333 // PythonQtClassWrapper...
334 QStringList l = wrapper->classInfo()->propertyList();
334 QStringList l = wrapper->classInfo()->propertyList();
335 foreach (QString name, l) {
335 foreach (QString name, l) {
336 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
336 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
337 if (o) {
337 if (o) {
338 PyDict_SetItemString(dict, name.toLatin1().data(), o);
338 PyDict_SetItemString(dict, name.toLatin1().data(), o);
339 Py_DECREF(o);
339 Py_DECREF(o);
340 } else {
340 } else {
341 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
341 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
342 }
342 }
343 }
343 }
344
344
345 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
345 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
346 foreach (QByteArray name, dynamicProps) {
346 foreach (QByteArray name, dynamicProps) {
347 PyObject* o = PyObject_GetAttrString(obj, name.data());
347 PyObject* o = PyObject_GetAttrString(obj, name.data());
348 if (o) {
348 if (o) {
349 PyDict_SetItemString(dict, name.data(), o);
349 PyDict_SetItemString(dict, name.data(), o);
350 Py_DECREF(o);
350 Py_DECREF(o);
351 } else {
351 } else {
352 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
352 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
353 }
353 }
354 }
354 }
355 }
355 }
356 // Note: we do not put children into the dict, is would look confusing?!
356 // Note: we do not put children into the dict, is would look confusing?!
357 return dict;
357 return dict;
358 }
358 }
359
359
360 // first look in super, to return derived methods from base object first
360 // first look in super, to return derived methods from base object first
361 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
361 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
362 if (superAttr) {
362 if (superAttr) {
363 return superAttr;
363 return superAttr;
364 }
364 }
365 PyErr_Clear();
365 PyErr_Clear();
366
366
367 // mlabDebugConst("Python","get " << attributeName);
367 // mlabDebugConst("Python","get " << attributeName);
368
368
369 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
369 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
370 switch (member._type) {
370 switch (member._type) {
371 case PythonQtMemberInfo::Property:
371 case PythonQtMemberInfo::Property:
372 if (wrapper->_obj) {
372 if (wrapper->_obj) {
373 if (member._property.userType() != QVariant::Invalid) {
373 if (member._property.userType() != QVariant::Invalid) {
374 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
374 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
375 } else {
375 } else {
376 Py_INCREF(Py_None);
376 Py_INCREF(Py_None);
377 return Py_None;
377 return Py_None;
378 }
378 }
379 } else {
379 } else {
380 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
380 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
381 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
381 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
382 return NULL;
382 return NULL;
383 }
383 }
384 break;
384 break;
385 case PythonQtMemberInfo::Slot:
385 case PythonQtMemberInfo::Slot:
386 return PythonQtSlotFunction_New(member._slot, obj, NULL);
386 return PythonQtSlotFunction_New(member._slot, obj, NULL);
387 break;
387 break;
388 case PythonQtMemberInfo::EnumValue:
388 case PythonQtMemberInfo::EnumValue:
389 {
389 {
390 PyObject* enumValue = member._enumValue;
390 PyObject* enumValue = member._enumValue;
391 Py_INCREF(enumValue);
391 Py_INCREF(enumValue);
392 return enumValue;
392 return enumValue;
393 }
393 }
394 break;
394 break;
395 case PythonQtMemberInfo::EnumWrapper:
395 case PythonQtMemberInfo::EnumWrapper:
396 {
396 {
397 PyObject* enumWrapper = member._enumWrapper;
397 PyObject* enumWrapper = member._enumWrapper;
398 Py_INCREF(enumWrapper);
398 Py_INCREF(enumWrapper);
399 return enumWrapper;
399 return enumWrapper;
400 }
400 }
401 break;
401 break;
402 case PythonQtMemberInfo::NotFound:
402 case PythonQtMemberInfo::NotFound:
403 {
403 {
404 static const QByteArray getterString("py_get_");
404 static const QByteArray getterString("py_get_");
405 // check for a getter slot
405 // check for a getter slot
406 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
406 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
407 if (member._type == PythonQtMemberInfo::Slot) {
407 if (member._type == PythonQtMemberInfo::Slot) {
408 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
408 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
409 }
409 }
410
410
411 // handle dynamic properties
411 // handle dynamic properties
412 if (wrapper->_obj) {
412 if (wrapper->_obj) {
413 QVariant v = wrapper->_obj->property(attributeName);
413 QVariant v = wrapper->_obj->property(attributeName);
414 if (v.isValid()) {
414 if (v.isValid()) {
415 return PythonQtConv::QVariantToPyObject(v);
415 return PythonQtConv::QVariantToPyObject(v);
416 }
416 }
417 }
417 }
418 }
418 }
419 break;
419 break;
420 default:
420 default:
421 // is an invalid type, go on
421 // is an invalid type, go on
422 break;
422 break;
423 }
423 }
424
424
425 // look for the internal methods (className(), help())
425 // look for the internal methods (className(), help())
426 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
426 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
427 if (internalMethod) {
427 if (internalMethod) {
428 return internalMethod;
428 return internalMethod;
429 }
429 }
430 PyErr_Clear();
430 PyErr_Clear();
431
431
432 if (wrapper->_obj) {
432 if (wrapper->_obj) {
433 // look for a child
433 // look for a child
434 QObjectList children = wrapper->_obj->children();
434 QObjectList children = wrapper->_obj->children();
435 for (int i = 0; i < children.count(); i++) {
435 for (int i = 0; i < children.count(); i++) {
436 QObject *child = children.at(i);
436 QObject *child = children.at(i);
437 if (child->objectName() == attributeName) {
437 if (child->objectName() == attributeName) {
438 return PythonQt::priv()->wrapQObject(child);
438 return PythonQt::priv()->wrapQObject(child);
439 }
439 }
440 }
440 }
441 }
441 }
442
442
443 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
443 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
444 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
444 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
445 return NULL;
445 return NULL;
446 }
446 }
447
447
448 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
448 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
449 {
449 {
450 QString error;
450 QString error;
451 const char *attributeName;
451 const char *attributeName;
452 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
452 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
453
453
454 if ((attributeName = PyString_AsString(name)) == NULL)
454 if ((attributeName = PyString_AsString(name)) == NULL)
455 return -1;
455 return -1;
456
456
457 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
457 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
458 if (member._type == PythonQtMemberInfo::Property) {
458 if (member._type == PythonQtMemberInfo::Property) {
459
459
460 if (!wrapper->_obj) {
460 if (!wrapper->_obj) {
461 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
461 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
462 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
462 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
463 return -1;
463 return -1;
464 }
464 }
465
465
466 QMetaProperty prop = member._property;
466 QMetaProperty prop = member._property;
467 if (prop.isWritable()) {
467 if (prop.isWritable()) {
468 QVariant v;
468 QVariant v;
469 if (prop.isEnumType()) {
469 if (prop.isEnumType()) {
470 // this will give us either a string or an int, everything else will probably be an error
470 // this will give us either a string or an int, everything else will probably be an error
471 v = PythonQtConv::PyObjToQVariant(value);
471 v = PythonQtConv::PyObjToQVariant(value);
472 } else {
472 } else {
473 int t = prop.userType();
473 int t = prop.userType();
474 v = PythonQtConv::PyObjToQVariant(value, t);
474 v = PythonQtConv::PyObjToQVariant(value, t);
475 }
475 }
476 bool success = false;
476 bool success = false;
477 if (v.isValid()) {
477 if (v.isValid()) {
478 success = prop.write(wrapper->_obj, v);
478 success = prop.write(wrapper->_obj, v);
479 }
479 }
480 if (success) {
480 if (success) {
481 return 0;
481 return 0;
482 } else {
482 } else {
483 error = QString("Property '") + attributeName + "' of type '" +
483 error = QString("Property '") + attributeName + "' of type '" +
484 prop.typeName() + "' does not accept an object of type "
484 prop.typeName() + "' does not accept an object of type "
485 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
485 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
486 }
486 }
487 } else {
487 } else {
488 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
488 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
489 }
489 }
490 } else if (member._type == PythonQtMemberInfo::Slot) {
490 } else if (member._type == PythonQtMemberInfo::Slot) {
491 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
491 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
492 } else if (member._type == PythonQtMemberInfo::EnumValue) {
492 } else if (member._type == PythonQtMemberInfo::EnumValue) {
493 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
493 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
494 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
494 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
495 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
495 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
496 } else if (member._type == PythonQtMemberInfo::NotFound) {
496 } else if (member._type == PythonQtMemberInfo::NotFound) {
497 // check for a setter slot
497 // check for a setter slot
498 static const QByteArray setterString("py_set_");
498 static const QByteArray setterString("py_set_");
499 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
499 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
500 if (setter._type == PythonQtMemberInfo::Slot) {
500 if (setter._type == PythonQtMemberInfo::Slot) {
501 // call the setter and ignore the result value
501 // call the setter and ignore the result value
502 void* result;
502 void* result;
503 PyObject* args = PyTuple_New(1);
503 PyObject* args = PyTuple_New(1);
504 Py_INCREF(value);
504 Py_INCREF(value);
505 PyTuple_SET_ITEM(args, 0, value);
505 PyTuple_SET_ITEM(args, 0, value);
506 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
506 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
507 Py_DECREF(args);
507 Py_DECREF(args);
508 return 0;
508 return 0;
509 }
509 }
510
510
511 // handle dynamic properties
511 // handle dynamic properties
512 if (wrapper->_obj) {
512 if (wrapper->_obj) {
513 QVariant prop = wrapper->_obj->property(attributeName);
513 QVariant prop = wrapper->_obj->property(attributeName);
514 if (prop.isValid()) {
514 if (prop.isValid()) {
515 QVariant v = PythonQtConv::PyObjToQVariant(value);
515 QVariant v = PythonQtConv::PyObjToQVariant(value);
516 if (v.isValid()) {
516 if (v.isValid()) {
517 wrapper->_obj->setProperty(attributeName, v);
517 wrapper->_obj->setProperty(attributeName, v);
518 return 0;
518 return 0;
519 } else {
519 } else {
520 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
520 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
521 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
521 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
522 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
522 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
523 return -1;
523 return -1;
524 }
524 }
525 }
525 }
526 }
526 }
527
527
528 // if we are a derived python class, we allow setting attributes.
528 // if we are a derived python class, we allow setting attributes.
529 // if we are a direct CPP wrapper, we do NOT allow it, since
529 // if we are a direct CPP wrapper, we do NOT allow it, since
530 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
530 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
531 // and when it is recreated from a CPP pointer the attributes are gone...
531 // and when it is recreated from a CPP pointer the attributes are gone...
532 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
532 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
533 return PyBaseObject_Type.tp_setattro(obj,name,value);
533 return PyBaseObject_Type.tp_setattro(obj,name,value);
534 } else {
534 } else {
535 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
535 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
536 }
536 }
537 }
537 }
538
538
539 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
539 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
540 return -1;
540 return -1;
541 }
541 }
542
542
543 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
543 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
544 QString result;
544 QString result;
545 if (wrapper->_wrappedPtr) {
545 if (wrapper->_wrappedPtr) {
546 // first try some manually string conversions for some variants
546 // first try some manually string conversions for some variants
547 int metaid = wrapper->classInfo()->metaTypeId();
547 int metaid = wrapper->classInfo()->metaTypeId();
548 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
548 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
549 if (!result.isEmpty()) {
549 if (!result.isEmpty()) {
550 return result;
550 return result;
551 }
551 }
552 }
552 }
553 // next, try to call py_toString
553 // next, try to call py_toString
554 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
554 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
555 if (info._type == PythonQtMemberInfo::Slot) {
555 if (info._type == PythonQtMemberInfo::Slot) {
556 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
556 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
557 if (resultObj) {
557 if (resultObj) {
558 // TODO this is one conversion too much, would be nicer to call the slot directly...
558 // TODO this is one conversion too much, would be nicer to call the slot directly...
559 result = PythonQtConv::PyObjGetString(resultObj);
559 result = PythonQtConv::PyObjGetString(resultObj);
560 Py_DECREF(resultObj);
560 Py_DECREF(resultObj);
561 }
561 }
562 }
562 }
563 return result;
563 return result;
564 }
564 }
565
565
566 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
566 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
567 {
567 {
568 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
568 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
569
569
570 // QByteArray should be directly returned as a str
570 // QByteArray should be directly returned as a str
571 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
571 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
572 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
572 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
573 if (b->data()) {
573 if (b->data()) {
574 return PyString_FromStringAndSize(b->data(), b->size());
574 return PyString_FromStringAndSize(b->data(), b->size());
575 } else {
575 } else {
576 return PyString_FromString("");
576 return PyString_FromString("");
577 }
577 }
578 }
578 }
579
579
580 const char* typeName = obj->ob_type->tp_name;
580 const char* typeName = obj->ob_type->tp_name;
581 QObject *qobj = wrapper->_obj;
581 QObject *qobj = wrapper->_obj;
582 QString str = getStringFromObject(wrapper);
582 QString str = getStringFromObject(wrapper);
583 if (!str.isEmpty()) {
583 if (!str.isEmpty()) {
584 return PyString_FromFormat("%s", str.toLatin1().constData());
584 return PyString_FromFormat("%s", str.toLatin1().constData());
585 }
585 }
586 if (wrapper->_wrappedPtr) {
586 if (wrapper->_wrappedPtr) {
587 if (wrapper->_obj) {
587 if (wrapper->_obj) {
588 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
588 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
589 } else {
589 } else {
590 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
590 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
591 }
591 }
592 } else {
592 } else {
593 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
593 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
594 }
594 }
595 }
595 }
596
596
597 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
597 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
598 {
598 {
599 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
599 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
600 const char* typeName = obj->ob_type->tp_name;
600 const char* typeName = obj->ob_type->tp_name;
601
601
602 QObject *qobj = wrapper->_obj;
602 QObject *qobj = wrapper->_obj;
603 QString str = getStringFromObject(wrapper);
603 QString str = getStringFromObject(wrapper);
604 if (!str.isEmpty()) {
604 if (!str.isEmpty()) {
605 if (str.startsWith(typeName)) {
605 if (str.startsWith(typeName)) {
606 return PyString_FromFormat("%s", str.toLatin1().constData());
606 return PyString_FromFormat("%s", str.toLatin1().constData());
607 } else {
607 } else {
608 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
608 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
609 }
609 }
610 }
610 }
611 if (wrapper->_wrappedPtr) {
611 if (wrapper->_wrappedPtr) {
612 if (wrapper->_obj) {
612 if (wrapper->_obj) {
613 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
613 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
614 } else {
614 } else {
615 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
615 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
616 }
616 }
617 } else {
617 } else {
618 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
618 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
619 }
619 }
620 }
620 }
621
621
622 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
622 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
623 {
623 {
624 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
624 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
625 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
625 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
626 }
626 }
627
627
628
628
629 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
629 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
630 {
630 {
631 if (obj->_wrappedPtr != NULL) {
631 if (obj->_wrappedPtr != NULL) {
632 return reinterpret_cast<long>(obj->_wrappedPtr);
632 return reinterpret_cast<long>(obj->_wrappedPtr);
633 } else {
633 } else {
634 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
634 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
635 return reinterpret_cast<long>(qobj);
635 return reinterpret_cast<long>(qobj);
636 }
636 }
637 }
637 }
638
638
639
639
640
640
641 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
641 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
642 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
642 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
643 0, /* nb_add */
643 0, /* nb_add */
644 0, /* nb_subtract */
644 0, /* nb_subtract */
645 0, /* nb_multiply */
645 0, /* nb_multiply */
646 0, /* nb_divide */
646 0, /* nb_divide */
647 0, /* nb_remainder */
647 0, /* nb_remainder */
648 0, /* nb_divmod */
648 0, /* nb_divmod */
649 0, /* nb_power */
649 0, /* nb_power */
650 0, /* nb_negative */
650 0, /* nb_negative */
651 0, /* nb_positive */
651 0, /* nb_positive */
652 0, /* nb_absolute */
652 0, /* nb_absolute */
653 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
653 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
654 0, /* nb_invert */
654 0, /* nb_invert */
655 0, /* nb_lshift */
655 0, /* nb_lshift */
656 0, /* nb_rshift */
656 0, /* nb_rshift */
657 0, /* nb_and */
657 0, /* nb_and */
658 0, /* nb_xor */
658 0, /* nb_xor */
659 0, /* nb_or */
659 0, /* nb_or */
660 0, /* nb_coerce */
660 0, /* nb_coerce */
661 0, /* nb_int */
661 0, /* nb_int */
662 0, /* nb_long */
662 0, /* nb_long */
663 0, /* nb_float */
663 0, /* nb_float */
664 0, /* nb_oct */
664 0, /* nb_oct */
665 0, /* nb_hex */
665 0, /* nb_hex */
666 0, /* nb_inplace_add */
666 0, /* nb_inplace_add */
667 0, /* nb_inplace_subtract */
667 0, /* nb_inplace_subtract */
668 0, /* nb_inplace_multiply */
668 0, /* nb_inplace_multiply */
669 0, /* nb_inplace_divide */
669 0, /* nb_inplace_divide */
670 0, /* nb_inplace_remainder */
670 0, /* nb_inplace_remainder */
671 0, /* nb_inplace_power */
671 0, /* nb_inplace_power */
672 0, /* nb_inplace_lshift */
672 0, /* nb_inplace_lshift */
673 0, /* nb_inplace_rshift */
673 0, /* nb_inplace_rshift */
674 0, /* nb_inplace_and */
674 0, /* nb_inplace_and */
675 0, /* nb_inplace_xor */
675 0, /* nb_inplace_xor */
676 0, /* nb_inplace_or */
676 0, /* nb_inplace_or */
677 0, /* nb_floor_divide */
677 0, /* nb_floor_divide */
678 0, /* nb_true_divide */
678 0, /* nb_true_divide */
679 0, /* nb_inplace_floor_divide */
679 0, /* nb_inplace_floor_divide */
680 0, /* nb_inplace_true_divide */
680 0, /* nb_inplace_true_divide */
681 };
681 };
682
682
683 PyTypeObject PythonQtInstanceWrapper_Type = {
683 PyTypeObject PythonQtInstanceWrapper_Type = {
684 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
684 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
685 0, /*ob_size*/
685 0, /*ob_size*/
686 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
686 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
687 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
687 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
688 0, /*tp_itemsize*/
688 0, /*tp_itemsize*/
689 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
689 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
690 0, /*tp_print*/
690 0, /*tp_print*/
691 0, /*tp_getattr*/
691 0, /*tp_getattr*/
692 0, /*tp_setattr*/
692 0, /*tp_setattr*/
693 0, /*tp_compare*/
693 0, /*tp_compare*/
694 PythonQtInstanceWrapper_repr, /*tp_repr*/
694 PythonQtInstanceWrapper_repr, /*tp_repr*/
695 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
695 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
696 0, /*tp_as_sequence*/
696 0, /*tp_as_sequence*/
697 0, /*tp_as_mapping*/
697 0, /*tp_as_mapping*/
698 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
698 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
699 0, /*tp_call*/
699 0, /*tp_call*/
700 PythonQtInstanceWrapper_str, /*tp_str*/
700 PythonQtInstanceWrapper_str, /*tp_str*/
701 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
701 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
702 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
702 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
703 0, /*tp_as_buffer*/
703 0, /*tp_as_buffer*/
704 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
704 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
705 "PythonQtInstanceWrapper object", /* tp_doc */
705 "PythonQtInstanceWrapper object", /* tp_doc */
706 0, /* tp_traverse */
706 0, /* tp_traverse */
707 0, /* tp_clear */
707 0, /* tp_clear */
708 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
708 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
709 0, /* tp_weaklistoffset */
709 0, /* tp_weaklistoffset */
710 0, /* tp_iter */
710 0, /* tp_iter */
711 0, /* tp_iternext */
711 0, /* tp_iternext */
712 0, /* tp_methods */
712 0, /* tp_methods */
713 0, /* tp_members */
713 0, /* tp_members */
714 0, /* tp_getset */
714 0, /* tp_getset */
715 0, /* tp_base */
715 0, /* tp_base */
716 0, /* tp_dict */
716 0, /* tp_dict */
717 0, /* tp_descr_get */
717 0, /* tp_descr_get */
718 0, /* tp_descr_set */
718 0, /* tp_descr_set */
719 0, /* tp_dictoffset */
719 0, /* tp_dictoffset */
720 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
720 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
721 0, /* tp_alloc */
721 0, /* tp_alloc */
722 PythonQtInstanceWrapper_new, /* tp_new */
722 PythonQtInstanceWrapper_new, /* tp_new */
723 };
723 };
724
724
725 //-------------------------------------------------------
725 //-------------------------------------------------------
726
726
@@ -1,98 +1,98
1 #ifndef _PYTHONQTINSTANCEWRAPPER_H
1 #ifndef _PYTHONQTINSTANCEWRAPPER_H
2 #define _PYTHONQTINSTANCEWRAPPER_H
2 #define _PYTHONQTINSTANCEWRAPPER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtInstanceWrapper.h
38 // \file PythonQtInstanceWrapper.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include <Python.h>
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48 #include <QPointer>
48 #include <QPointer>
49
49
50 #include "structmember.h"
50 #include "structmember.h"
51 #include "methodobject.h"
51 #include "methodobject.h"
52 #include "compile.h"
52 #include "compile.h"
53 #include "eval.h"
53 #include "eval.h"
54
54
55 class PythonQtClassInfo;
55 class PythonQtClassInfo;
56 class QObject;
56 class QObject;
57
57
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
59
59
60 //---------------------------------------------------------------
60 //---------------------------------------------------------------
61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
62 typedef struct PythonQtInstanceWrapperStruct {
62 typedef struct PythonQtInstanceWrapperStruct {
63 PyObject_HEAD
63 PyObject_HEAD
64
64
65 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
65 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
66 PythonQtClassInfo* classInfo();
66 PythonQtClassInfo* classInfo();
67
67
68 //! set the QObject pointer
68 //! set the QObject pointer
69 void setQObject(QObject* object) {
69 void setQObject(QObject* object) {
70 _obj = object;
70 _obj = object;
71 _objPointerCopy = object;
71 _objPointerCopy = object;
72 }
72 }
73
73
74 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
74 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
75 QPointer<QObject> _obj;
75 QPointer<QObject> _obj;
76 //! a copy of the _obj pointer, which is required because the wrapper needs to
76 //! a copy of the _obj pointer, which is required because the wrapper needs to
77 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
77 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
78 void* _objPointerCopy;
78 void* _objPointerCopy;
79
79
80 //! optional C++ object Ptr that is wrapped by the above _obj
80 //! optional C++ object Ptr that is wrapped by the above _obj
81 void* _wrappedPtr;
81 void* _wrappedPtr;
82
82
83 // TODO xxx: put booleans into int that holds flags
83 // TODO xxx: put booleans into int that holds flags
84
84
85 //! flag that stores if the object is owned by pythonQt
85 //! flag that stores if the object is owned by pythonQt
86 bool _ownedByPythonQt;
86 bool _ownedByPythonQt;
87
87
88 //! stores that the owned object should be destroyed using QMetaType::destroy()
88 //! stores that the owned object should be destroyed using QMetaType::destroy()
89 bool _useQMetaTypeDestroy;
89 bool _useQMetaTypeDestroy;
90
90
91 //! stores if the object is a shell instance
91 //! stores if the object is a shell instance
92 bool _isShellInstance;
92 bool _isShellInstance;
93
93
94 } PythonQtInstanceWrapper;
94 } PythonQtInstanceWrapper;
95
95
96 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
96 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
97
97
98 #endif No newline at end of file
98 #endif
@@ -1,351 +1,351
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtMethodInfo.cpp
35 // \file PythonQtMethodInfo.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtMethodInfo.h"
42 #include "PythonQtMethodInfo.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include <iostream>
44 #include <iostream>
45
45
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
48
48
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
50 {
50 {
51 #ifdef PYTHONQT_DEBUG
51 #ifdef PYTHONQT_DEBUG
52 QByteArray sig(meta.signature());
52 QByteArray sig(meta.signature());
53 sig = sig.mid(sig.indexOf('('));
53 sig = sig.mid(sig.indexOf('('));
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
55 std::cout << "caching " << fullSig.data() << std::endl;
55 std::cout << "caching " << fullSig.data() << std::endl;
56 #endif
56 #endif
57
57
58 ParameterInfo type;
58 ParameterInfo type;
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
60 _parameters.append(type);
60 _parameters.append(type);
61 QList<QByteArray> names = meta.parameterTypes();
61 QList<QByteArray> names = meta.parameterTypes();
62 foreach (const QByteArray& name, names) {
62 foreach (const QByteArray& name, names) {
63 fillParameterInfo(type, name, classInfo);
63 fillParameterInfo(type, name, classInfo);
64 _parameters.append(type);
64 _parameters.append(type);
65 }
65 }
66 }
66 }
67
67
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
69 {
69 {
70 ParameterInfo type;
70 ParameterInfo type;
71 fillParameterInfo(type, typeName, NULL);
71 fillParameterInfo(type, typeName, NULL);
72 _parameters.append(type);
72 _parameters.append(type);
73 foreach (const QByteArray& name, args) {
73 foreach (const QByteArray& name, args) {
74 fillParameterInfo(type, name, NULL);
74 fillParameterInfo(type, name, NULL);
75 _parameters.append(type);
75 _parameters.append(type);
76 }
76 }
77 }
77 }
78
78
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
80 {
80 {
81 QByteArray sig(signal.signature());
81 QByteArray sig(signal.signature());
82 sig = sig.mid(sig.indexOf('('));
82 sig = sig.mid(sig.indexOf('('));
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
85 if (!result) {
85 if (!result) {
86 result = new PythonQtMethodInfo(signal, classInfo);
86 result = new PythonQtMethodInfo(signal, classInfo);
87 _cachedSignatures.insert(fullSig, result);
87 _cachedSignatures.insert(fullSig, result);
88 }
88 }
89 return result;
89 return result;
90 }
90 }
91
91
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
93 {
93 {
94 QByteArray typeName = args[0];
94 QByteArray typeName = args[0];
95 QList<QByteArray> arguments;
95 QList<QByteArray> arguments;
96 QByteArray fullSig = typeName;
96 QByteArray fullSig = typeName;
97 fullSig += "(";
97 fullSig += "(";
98 for (int i =1;i<numArgs; i++) {
98 for (int i =1;i<numArgs; i++) {
99 if (i>1) {
99 if (i>1) {
100 fullSig += ",";
100 fullSig += ",";
101 }
101 }
102 arguments << QByteArray(args[i]);
102 arguments << QByteArray(args[i]);
103 }
103 }
104 fullSig += ")";
104 fullSig += ")";
105 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
105 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
106 if (!result) {
106 if (!result) {
107 result = new PythonQtMethodInfo(typeName, arguments);
107 result = new PythonQtMethodInfo(typeName, arguments);
108 _cachedSignatures.insert(fullSig, result);
108 _cachedSignatures.insert(fullSig, result);
109 }
109 }
110 return result;
110 return result;
111 }
111 }
112
112
113 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
113 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
114 {
114 {
115 QByteArray name = orgName;
115 QByteArray name = orgName;
116
116
117 type.enumWrapper = NULL;
117 type.enumWrapper = NULL;
118
118
119 int len = name.length();
119 int len = name.length();
120 if (len>0) {
120 if (len>0) {
121 if (strncmp(name.constData(), "const ", 6)==0) {
121 if (strncmp(name.constData(), "const ", 6)==0) {
122 name = name.mid(6);
122 name = name.mid(6);
123 len -= 6;
123 len -= 6;
124 type.isConst = true;
124 type.isConst = true;
125 } else {
125 } else {
126 type.isConst = false;
126 type.isConst = false;
127 }
127 }
128 bool hadPointer = false;
128 bool hadPointer = false;
129 bool hadReference = false;
129 bool hadReference = false;
130 // remove * and & from the end of the string, handle & and * the same way
130 // remove * and & from the end of the string, handle & and * the same way
131 while (name.at(len-1) == '*') {
131 while (name.at(len-1) == '*') {
132 len--;
132 len--;
133 hadPointer = true;
133 hadPointer = true;
134 }
134 }
135 while (name.at(len-1) == '&') {
135 while (name.at(len-1) == '&') {
136 len--;
136 len--;
137 hadReference = true;
137 hadReference = true;
138 }
138 }
139 if (len!=name.length()) {
139 if (len!=name.length()) {
140 name = name.left(len);
140 name = name.left(len);
141 }
141 }
142 type.isPointer = hadPointer;
142 type.isPointer = hadPointer;
143
143
144 QByteArray alias = _parameterNameAliases.value(name);
144 QByteArray alias = _parameterNameAliases.value(name);
145 if (!alias.isEmpty()) {
145 if (!alias.isEmpty()) {
146 name = alias;
146 name = alias;
147 }
147 }
148
148
149 type.typeId = nameToType(name);
149 type.typeId = nameToType(name);
150 if (!type.isPointer && type.typeId == Unknown) {
150 if (!type.isPointer && type.typeId == Unknown) {
151 type.typeId = QMetaType::type(name.constData());
151 type.typeId = QMetaType::type(name.constData());
152 if (type.typeId == QMetaType::Void) {
152 if (type.typeId == QMetaType::Void) {
153 type.typeId = Unknown;
153 type.typeId = Unknown;
154 }
154 }
155 }
155 }
156 type.name = name;
156 type.name = name;
157
157
158 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
158 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
159 bool isLocalEnum;
159 bool isLocalEnum;
160 // TODOXXX: make use of this flag!
160 // TODOXXX: make use of this flag!
161 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
161 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
162 }
162 }
163 } else {
163 } else {
164 type.typeId = QMetaType::Void;
164 type.typeId = QMetaType::Void;
165 type.isPointer = false;
165 type.isPointer = false;
166 type.isConst = false;
166 type.isConst = false;
167 }
167 }
168 }
168 }
169
169
170 int PythonQtMethodInfo::nameToType(const char* name)
170 int PythonQtMethodInfo::nameToType(const char* name)
171 {
171 {
172 if (_parameterTypeDict.isEmpty()) {
172 if (_parameterTypeDict.isEmpty()) {
173 // we could also use QMetaType::nameToType, but that does a string compare search
173 // we could also use QMetaType::nameToType, but that does a string compare search
174 // and does not support QVariant
174 // and does not support QVariant
175
175
176 // QMetaType names
176 // QMetaType names
177 _parameterTypeDict.insert("long", QMetaType::Long);
177 _parameterTypeDict.insert("long", QMetaType::Long);
178 _parameterTypeDict.insert("int", QMetaType::Int);
178 _parameterTypeDict.insert("int", QMetaType::Int);
179 _parameterTypeDict.insert("short", QMetaType::Short);
179 _parameterTypeDict.insert("short", QMetaType::Short);
180 _parameterTypeDict.insert("char", QMetaType::Char);
180 _parameterTypeDict.insert("char", QMetaType::Char);
181 _parameterTypeDict.insert("ulong", QMetaType::ULong);
181 _parameterTypeDict.insert("ulong", QMetaType::ULong);
182 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
182 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
183 _parameterTypeDict.insert("uint", QMetaType::UInt);
183 _parameterTypeDict.insert("uint", QMetaType::UInt);
184 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
184 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
185 _parameterTypeDict.insert("ushort", QMetaType::UShort);
185 _parameterTypeDict.insert("ushort", QMetaType::UShort);
186 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
186 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
187 _parameterTypeDict.insert("uchar", QMetaType::UChar);
187 _parameterTypeDict.insert("uchar", QMetaType::UChar);
188 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
188 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
189 _parameterTypeDict.insert("bool", QMetaType::Bool);
189 _parameterTypeDict.insert("bool", QMetaType::Bool);
190 _parameterTypeDict.insert("float", QMetaType::Float);
190 _parameterTypeDict.insert("float", QMetaType::Float);
191 _parameterTypeDict.insert("double", QMetaType::Double);
191 _parameterTypeDict.insert("double", QMetaType::Double);
192 _parameterTypeDict.insert("qreal", QMetaType::Double);
192 _parameterTypeDict.insert("qreal", QMetaType::Double);
193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
195 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
195 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
196 _parameterTypeDict.insert("QString", QMetaType::QString);
196 _parameterTypeDict.insert("QString", QMetaType::QString);
197 _parameterTypeDict.insert("", QMetaType::Void);
197 _parameterTypeDict.insert("", QMetaType::Void);
198 _parameterTypeDict.insert("void", QMetaType::Void);
198 _parameterTypeDict.insert("void", QMetaType::Void);
199 // QVariant names
199 // QVariant names
200 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
200 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
201 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
201 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
202 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
202 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
203 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
203 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
204 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
204 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
205 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
205 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
206 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
206 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
207 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
207 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
208 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
208 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
209 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
209 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
210 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
210 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
211 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
211 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
212 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
212 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
213 _parameterTypeDict.insert("QDate", QMetaType::QDate);
213 _parameterTypeDict.insert("QDate", QMetaType::QDate);
214 _parameterTypeDict.insert("QTime", QMetaType::QTime);
214 _parameterTypeDict.insert("QTime", QMetaType::QTime);
215 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
215 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
216 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
216 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
217 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
217 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
218 _parameterTypeDict.insert("QRect", QMetaType::QRect);
218 _parameterTypeDict.insert("QRect", QMetaType::QRect);
219 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
219 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
220 _parameterTypeDict.insert("QSize", QMetaType::QSize);
220 _parameterTypeDict.insert("QSize", QMetaType::QSize);
221 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
221 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
222 _parameterTypeDict.insert("QLine", QMetaType::QLine);
222 _parameterTypeDict.insert("QLine", QMetaType::QLine);
223 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
223 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
224 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
224 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
225 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
225 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
226 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
226 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
227 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
227 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
228 _parameterTypeDict.insert("QFont", QMetaType::QFont);
228 _parameterTypeDict.insert("QFont", QMetaType::QFont);
229 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
229 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
230 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
230 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
231 _parameterTypeDict.insert("QColor", QMetaType::QColor);
231 _parameterTypeDict.insert("QColor", QMetaType::QColor);
232 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
232 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
233 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
233 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
234 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
234 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
235 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
235 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
236 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
236 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
237 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
237 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
238 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
238 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
239 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
239 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
240 _parameterTypeDict.insert("QPen", QMetaType::QPen);
240 _parameterTypeDict.insert("QPen", QMetaType::QPen);
241 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
241 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
242 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
242 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
243 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
243 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
244 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
244 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
245 // own special types... (none so far, could be e.g. ObjectList
245 // own special types... (none so far, could be e.g. ObjectList
246 }
246 }
247 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
247 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
248 if (it!=_parameterTypeDict.end()) {
248 if (it!=_parameterTypeDict.end()) {
249 return it.value();
249 return it.value();
250 } else {
250 } else {
251 return PythonQtMethodInfo::Unknown;
251 return PythonQtMethodInfo::Unknown;
252 }
252 }
253 }
253 }
254
254
255 void PythonQtMethodInfo::cleanupCachedMethodInfos()
255 void PythonQtMethodInfo::cleanupCachedMethodInfos()
256 {
256 {
257 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
257 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
258 while (i.hasNext()) {
258 while (i.hasNext()) {
259 delete i.next().value();
259 delete i.next().value();
260 }
260 }
261 }
261 }
262
262
263 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
263 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
264 {
264 {
265 _parameterNameAliases.insert(alias, name);
265 _parameterNameAliases.insert(alias, name);
266 }
266 }
267
267
268 //-------------------------------------------------------------------------------------------------
268 //-------------------------------------------------------------------------------------------------
269
269
270 void PythonQtSlotInfo::deleteOverloadsAndThis()
270 void PythonQtSlotInfo::deleteOverloadsAndThis()
271 {
271 {
272 PythonQtSlotInfo* cur = this;
272 PythonQtSlotInfo* cur = this;
273 while(cur->nextInfo()) {
273 while(cur->nextInfo()) {
274 PythonQtSlotInfo* next = cur->nextInfo();
274 PythonQtSlotInfo* next = cur->nextInfo();
275 delete cur;
275 delete cur;
276 cur = next;
276 cur = next;
277 }
277 }
278 }
278 }
279
279
280
280
281 QString PythonQtSlotInfo::fullSignature()
281 QString PythonQtSlotInfo::fullSignature()
282 {
282 {
283 bool skipFirstArg = isInstanceDecorator();
283 bool skipFirstArg = isInstanceDecorator();
284 QString result = _meta.typeName();
284 QString result = _meta.typeName();
285 QByteArray sig = slotName();
285 QByteArray sig = slotName();
286 QList<QByteArray> names = _meta.parameterNames();
286 QList<QByteArray> names = _meta.parameterNames();
287
287
288 bool isStatic = false;
288 bool isStatic = false;
289 bool isConstructor = false;
289 bool isConstructor = false;
290 bool isDestructor = false;
290 bool isDestructor = false;
291
291
292 if (_type == ClassDecorator) {
292 if (_type == ClassDecorator) {
293 if (sig.startsWith("new_")) {
293 if (sig.startsWith("new_")) {
294 sig = sig.mid(strlen("new_"));
294 sig = sig.mid(strlen("new_"));
295 isConstructor = true;
295 isConstructor = true;
296 } else if (sig.startsWith("delete_")) {
296 } else if (sig.startsWith("delete_")) {
297 sig = sig.mid(strlen("delete_"));
297 sig = sig.mid(strlen("delete_"));
298 isDestructor = true;
298 isDestructor = true;
299 } else if(sig.startsWith("static_")) {
299 } else if(sig.startsWith("static_")) {
300 isStatic = true;
300 isStatic = true;
301 sig = sig.mid(strlen("static_"));
301 sig = sig.mid(strlen("static_"));
302 int idx = sig.indexOf("_");
302 int idx = sig.indexOf("_");
303 if (idx>=0) {
303 if (idx>=0) {
304 sig = sig.mid(idx+1);
304 sig = sig.mid(idx+1);
305 }
305 }
306 }
306 }
307 }
307 }
308
308
309 result += QByteArray(" ") + sig;
309 result += QByteArray(" ") + sig;
310 result += "(";
310 result += "(";
311
311
312 int lastEntry = _parameters.count()-1;
312 int lastEntry = _parameters.count()-1;
313 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
313 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
314 if (_parameters.at(i).isConst) {
314 if (_parameters.at(i).isConst) {
315 result += "const ";
315 result += "const ";
316 }
316 }
317 result += _parameters.at(i).name;
317 result += _parameters.at(i).name;
318 if (_parameters.at(i).isPointer) {
318 if (_parameters.at(i).isPointer) {
319 result += "*";
319 result += "*";
320 }
320 }
321 if (!names.at(i-1).isEmpty()) {
321 if (!names.at(i-1).isEmpty()) {
322 result += " ";
322 result += " ";
323 result += names.at(i-1);
323 result += names.at(i-1);
324 }
324 }
325 if (i!=lastEntry) {
325 if (i!=lastEntry) {
326 result += ", ";
326 result += ", ";
327 }
327 }
328 }
328 }
329 result += ")";
329 result += ")";
330
330
331 if (isStatic) {
331 if (isStatic) {
332 result = QString("static ") + result;
332 result = QString("static ") + result;
333 }
333 }
334 if (isConstructor) {
334 if (isConstructor) {
335 // result = QString("constructor ") + result;
335 // result = QString("constructor ") + result;
336 }
336 }
337 if (isDestructor) {
337 if (isDestructor) {
338 result = QString("~") + result;
338 result = QString("~") + result;
339 }
339 }
340 return result;
340 return result;
341 }
341 }
342
342
343
343
344 QByteArray PythonQtSlotInfo::slotName()
344 QByteArray PythonQtSlotInfo::slotName()
345 {
345 {
346 QByteArray sig(_meta.signature());
346 QByteArray sig(_meta.signature());
347 int idx = sig.indexOf('(');
347 int idx = sig.indexOf('(');
348 sig = sig.left(idx);
348 sig = sig.left(idx);
349 return sig;
349 return sig;
350 }
350 }
351
351
@@ -1,190 +1,190
1 #ifndef _PYTHONQTMETHODINFO_H
1 #ifndef _PYTHONQTMETHODINFO_H
2 #define _PYTHONQTMETHODINFO_H
2 #define _PYTHONQTMETHODINFO_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtMethodInfo.h
38 // \file PythonQtMethodInfo.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46
46
47 #include <QByteArray>
47 #include <QByteArray>
48 #include <QHash>
48 #include <QHash>
49 #include <QList>
49 #include <QList>
50 #include <QMetaMethod>
50 #include <QMetaMethod>
51
51
52 class PythonQtClassInfo;
52 class PythonQtClassInfo;
53 struct _object;
53 struct _object;
54 typedef struct _object PyObject;
54 typedef struct _object PyObject;
55
55
56 //! stores information about a specific signal/slot/method
56 //! stores information about a specific signal/slot/method
57 class PYTHONQT_EXPORT PythonQtMethodInfo
57 class PYTHONQT_EXPORT PythonQtMethodInfo
58 {
58 {
59 public:
59 public:
60 enum ParameterType {
60 enum ParameterType {
61 Unknown = -1,
61 Unknown = -1,
62 Variant = -2
62 Variant = -2
63 };
63 };
64
64
65 //! stores the QVariant id (if available) and the name of the type
65 //! stores the QVariant id (if available) and the name of the type
66 struct ParameterInfo {
66 struct ParameterInfo {
67 QByteArray name;
67 QByteArray name;
68 PyObject* enumWrapper; // if it is an enum, a pointer to the enum wrapper
68 PyObject* enumWrapper; // if it is an enum, a pointer to the enum wrapper
69 int typeId; // a mixture from QMetaType and ParameterType
69 int typeId; // a mixture from QMetaType and ParameterType
70 bool isPointer;
70 bool isPointer;
71 bool isConst;
71 bool isConst;
72 };
72 };
73
73
74 PythonQtMethodInfo() {};
74 PythonQtMethodInfo() {};
75 ~PythonQtMethodInfo() {};
75 ~PythonQtMethodInfo() {};
76 PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo);
76 PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo);
77 PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args);
77 PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args);
78 PythonQtMethodInfo(const PythonQtMethodInfo& other) {
78 PythonQtMethodInfo(const PythonQtMethodInfo& other) {
79 _parameters = other._parameters;
79 _parameters = other._parameters;
80 }
80 }
81
81
82 //! returns the method info of the signature, uses a cache internally to speed up
82 //! returns the method info of the signature, uses a cache internally to speed up
83 //! multiple requests for the same method, classInfo is passed to allow local enum resolution (if NULL is passed, no local enums are recognized)
83 //! multiple requests for the same method, classInfo is passed to allow local enum resolution (if NULL is passed, no local enums are recognized)
84 static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method, PythonQtClassInfo* classInfo);
84 static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method, PythonQtClassInfo* classInfo);
85
85
86 //! get the cached method info using the passed in list of return value and arguments, return value needs to be passed as first arg
86 //! get the cached method info using the passed in list of return value and arguments, return value needs to be passed as first arg
87 static const PythonQtMethodInfo* getCachedMethodInfoFromArgumentList(int numArgs, const char** args);
87 static const PythonQtMethodInfo* getCachedMethodInfoFromArgumentList(int numArgs, const char** args);
88
88
89 //! cleanup the cache
89 //! cleanup the cache
90 static void cleanupCachedMethodInfos();
90 static void cleanupCachedMethodInfos();
91
91
92 //! returns the number of parameters including the return value
92 //! returns the number of parameters including the return value
93 int parameterCount() const { return _parameters.size(); };
93 int parameterCount() const { return _parameters.size(); };
94
94
95 //! returns the id for the given type (using an internal dictionary)
95 //! returns the id for the given type (using an internal dictionary)
96 static int nameToType(const char* name);
96 static int nameToType(const char* name);
97
97
98 //! get the parameter infos
98 //! get the parameter infos
99 const QList<ParameterInfo>& parameters() const { return _parameters; }
99 const QList<ParameterInfo>& parameters() const { return _parameters; }
100
100
101 //! add an alias for a typename, e.g. QObjectList and QList<QObject*>.
101 //! add an alias for a typename, e.g. QObjectList and QList<QObject*>.
102 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
102 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
103
103
104 protected:
104 protected:
105 static void fillParameterInfo(ParameterInfo& type, const QByteArray& name, PythonQtClassInfo* classInfo);
105 static void fillParameterInfo(ParameterInfo& type, const QByteArray& name, PythonQtClassInfo* classInfo);
106
106
107 static QHash<QByteArray, int> _parameterTypeDict;
107 static QHash<QByteArray, int> _parameterTypeDict;
108 static QHash<QByteArray, QByteArray> _parameterNameAliases;
108 static QHash<QByteArray, QByteArray> _parameterNameAliases;
109
109
110 //! stores the cached signatures of methods to speedup mapping from Qt to Python types
110 //! stores the cached signatures of methods to speedup mapping from Qt to Python types
111 static QHash<QByteArray, PythonQtMethodInfo*> _cachedSignatures;
111 static QHash<QByteArray, PythonQtMethodInfo*> _cachedSignatures;
112
112
113 QList<ParameterInfo> _parameters;
113 QList<ParameterInfo> _parameters;
114 };
114 };
115
115
116 //! stores information about a slot, including a next pointer to overloaded slots
116 //! stores information about a slot, including a next pointer to overloaded slots
117 class PythonQtSlotInfo : public PythonQtMethodInfo
117 class PythonQtSlotInfo : public PythonQtMethodInfo
118 {
118 {
119 public:
119 public:
120 enum Type {
120 enum Type {
121 MemberSlot, InstanceDecorator, ClassDecorator
121 MemberSlot, InstanceDecorator, ClassDecorator
122 };
122 };
123
123
124 PythonQtSlotInfo(const PythonQtSlotInfo& info):PythonQtMethodInfo() {
124 PythonQtSlotInfo(const PythonQtSlotInfo& info):PythonQtMethodInfo() {
125 _meta = info._meta;
125 _meta = info._meta;
126 _parameters = info._parameters;
126 _parameters = info._parameters;
127 _slotIndex = info._slotIndex;
127 _slotIndex = info._slotIndex;
128 _next = NULL;
128 _next = NULL;
129 _decorator = info._decorator;
129 _decorator = info._decorator;
130 _type = info._type;
130 _type = info._type;
131 _upcastingOffset = 0;
131 _upcastingOffset = 0;
132 }
132 }
133
133
134 PythonQtSlotInfo(PythonQtClassInfo* classInfo, const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo()
134 PythonQtSlotInfo(PythonQtClassInfo* classInfo, const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo()
135 {
135 {
136 const PythonQtMethodInfo* info = getCachedMethodInfo(meta, classInfo);
136 const PythonQtMethodInfo* info = getCachedMethodInfo(meta, classInfo);
137 _meta = meta;
137 _meta = meta;
138 _parameters = info->parameters();
138 _parameters = info->parameters();
139 _slotIndex = slotIndex;
139 _slotIndex = slotIndex;
140 _next = NULL;
140 _next = NULL;
141 _decorator = decorator;
141 _decorator = decorator;
142 _type = type;
142 _type = type;
143 _upcastingOffset = 0;
143 _upcastingOffset = 0;
144 }
144 }
145
145
146
146
147 public:
147 public:
148
148
149 void deleteOverloadsAndThis();
149 void deleteOverloadsAndThis();
150
150
151 const QMetaMethod* metaMethod() const { return &_meta; }
151 const QMetaMethod* metaMethod() const { return &_meta; }
152
152
153 void setUpcastingOffset(int upcastingOffset) { _upcastingOffset = upcastingOffset; }
153 void setUpcastingOffset(int upcastingOffset) { _upcastingOffset = upcastingOffset; }
154
154
155 int upcastingOffset() const { return _upcastingOffset; }
155 int upcastingOffset() const { return _upcastingOffset; }
156
156
157 //! get the index of the slot (needed for qt_metacall)
157 //! get the index of the slot (needed for qt_metacall)
158 int slotIndex() const { return _slotIndex; }
158 int slotIndex() const { return _slotIndex; }
159
159
160 //! get next overloaded slot (which has the same name)
160 //! get next overloaded slot (which has the same name)
161 PythonQtSlotInfo* nextInfo() const { return _next; }
161 PythonQtSlotInfo* nextInfo() const { return _next; }
162
162
163 //! set the next overloaded slot
163 //! set the next overloaded slot
164 void setNextInfo(PythonQtSlotInfo* next) { _next = next; }
164 void setNextInfo(PythonQtSlotInfo* next) { _next = next; }
165
165
166 //! returns if the slot is a decorator slot
166 //! returns if the slot is a decorator slot
167 bool isInstanceDecorator() { return _decorator!=NULL && _type == InstanceDecorator; }
167 bool isInstanceDecorator() { return _decorator!=NULL && _type == InstanceDecorator; }
168
168
169 //! returns if the slot is a constructor slot
169 //! returns if the slot is a constructor slot
170 bool isClassDecorator() { return _decorator!=NULL && _type == ClassDecorator; }
170 bool isClassDecorator() { return _decorator!=NULL && _type == ClassDecorator; }
171
171
172 QObject* decorator() { return _decorator; }
172 QObject* decorator() { return _decorator; }
173
173
174 //! get the full signature including return type
174 //! get the full signature including return type
175 QString fullSignature();
175 QString fullSignature();
176
176
177 //! get the short slot name
177 //! get the short slot name
178 QByteArray slotName();
178 QByteArray slotName();
179
179
180 private:
180 private:
181 int _slotIndex;
181 int _slotIndex;
182 PythonQtSlotInfo* _next;
182 PythonQtSlotInfo* _next;
183 QObject* _decorator;
183 QObject* _decorator;
184 Type _type;
184 Type _type;
185 QMetaMethod _meta;
185 QMetaMethod _meta;
186 int _upcastingOffset;
186 int _upcastingOffset;
187 };
187 };
188
188
189
189
190 #endif
190 #endif
@@ -1,43 +1,43
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtMisc.cpp
35 // \file PythonQtMisc.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtMisc.h"
42 #include "PythonQtMisc.h"
43
43
@@ -1,142 +1,142
1 #ifndef _PYTHONQTMISC_H
1 #ifndef _PYTHONQTMISC_H
2 #define _PYTHONQTMISC_H
2 #define _PYTHONQTMISC_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtMisc.h
38 // \file PythonQtMisc.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45
45
46 #include <QList>
46 #include <QList>
47
47
48 #define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
48 #define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
49 { type* item = (type*)store.nextValuePtr(); \
49 { type* item = (type*)store.nextValuePtr(); \
50 *item = value; \
50 *item = value; \
51 ptr = (void*)item; \
51 ptr = (void*)item; \
52 }
52 }
53
53
54 #define PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, type, value, ptr) \
54 #define PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, type, value, ptr) \
55 { \
55 { \
56 type* item = (type*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store.nextValuePtr()); \
56 type* item = (type*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store.nextValuePtr()); \
57 *item = value; \
57 *item = value; \
58 ptr = (void*)item; \
58 ptr = (void*)item; \
59 }
59 }
60
60
61 //! stores a position in the PythonQtValueStorage
61 //! stores a position in the PythonQtValueStorage
62 class PythonQtValueStoragePosition {
62 class PythonQtValueStoragePosition {
63
63
64 public:
64 public:
65 PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; }
65 PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; }
66
66
67 int chunkIdx;
67 int chunkIdx;
68 int chunkOffset;
68 int chunkOffset;
69
69
70 };
70 };
71
71
72 //! a helper class that stores basic C++ value types in chunks
72 //! a helper class that stores basic C++ value types in chunks
73 template <typename T, int chunkEntries> class PythonQtValueStorage
73 template <typename T, int chunkEntries> class PythonQtValueStorage
74 {
74 {
75 public:
75 public:
76 PythonQtValueStorage() {
76 PythonQtValueStorage() {
77 _chunkIdx = 0;
77 _chunkIdx = 0;
78 _chunkOffset = 0;
78 _chunkOffset = 0;
79 _currentChunk = new T[chunkEntries];
79 _currentChunk = new T[chunkEntries];
80 _chunks.append(_currentChunk);
80 _chunks.append(_currentChunk);
81 };
81 };
82
82
83 //! clear all memory
83 //! clear all memory
84 void clear() {
84 void clear() {
85 T* chunk;
85 T* chunk;
86 foreach(chunk, _chunks) {
86 foreach(chunk, _chunks) {
87 delete[]chunk;
87 delete[]chunk;
88 }
88 }
89 _chunks.clear();
89 _chunks.clear();
90 }
90 }
91
91
92 //! reset the storage to 0 (without freeing memory, thus caching old entries for reuse)
92 //! reset the storage to 0 (without freeing memory, thus caching old entries for reuse)
93 void reset() {
93 void reset() {
94 _chunkIdx = 0;
94 _chunkIdx = 0;
95 _chunkOffset = 0;
95 _chunkOffset = 0;
96 _currentChunk = _chunks.at(0);
96 _currentChunk = _chunks.at(0);
97 }
97 }
98
98
99 //! get the current position to be restored with setPos
99 //! get the current position to be restored with setPos
100 void getPos(PythonQtValueStoragePosition & pos) {
100 void getPos(PythonQtValueStoragePosition & pos) {
101 pos.chunkIdx = _chunkIdx;
101 pos.chunkIdx = _chunkIdx;
102 pos.chunkOffset = _chunkOffset;
102 pos.chunkOffset = _chunkOffset;
103 }
103 }
104
104
105 //! set the current position (without freeing memory, thus caching old entries for reuse)
105 //! set the current position (without freeing memory, thus caching old entries for reuse)
106 void setPos(const PythonQtValueStoragePosition& pos) {
106 void setPos(const PythonQtValueStoragePosition& pos) {
107 _chunkOffset = pos.chunkOffset;
107 _chunkOffset = pos.chunkOffset;
108 if (_chunkIdx != pos.chunkIdx) {
108 if (_chunkIdx != pos.chunkIdx) {
109 _chunkIdx = pos.chunkIdx;
109 _chunkIdx = pos.chunkIdx;
110 _currentChunk = _chunks.at(_chunkIdx);
110 _currentChunk = _chunks.at(_chunkIdx);
111 }
111 }
112 }
112 }
113
113
114 //! add one default constructed value and return the pointer to it
114 //! add one default constructed value and return the pointer to it
115 T* nextValuePtr() {
115 T* nextValuePtr() {
116 if (_chunkOffset>=chunkEntries) {
116 if (_chunkOffset>=chunkEntries) {
117 _chunkIdx++;
117 _chunkIdx++;
118 if (_chunkIdx >= _chunks.size()) {
118 if (_chunkIdx >= _chunks.size()) {
119 T* newChunk = new T[chunkEntries];
119 T* newChunk = new T[chunkEntries];
120 _chunks.append(newChunk);
120 _chunks.append(newChunk);
121 _currentChunk = newChunk;
121 _currentChunk = newChunk;
122 } else {
122 } else {
123 _currentChunk = _chunks.at(_chunkIdx);
123 _currentChunk = _chunks.at(_chunkIdx);
124 }
124 }
125 _chunkOffset = 0;
125 _chunkOffset = 0;
126 }
126 }
127 T* newEntry = _currentChunk + _chunkOffset;
127 T* newEntry = _currentChunk + _chunkOffset;
128 _chunkOffset++;
128 _chunkOffset++;
129 return newEntry;
129 return newEntry;
130 };
130 };
131
131
132 private:
132 private:
133 QList<T*> _chunks;
133 QList<T*> _chunks;
134
134
135 int _chunkIdx;
135 int _chunkIdx;
136 int _chunkOffset;
136 int _chunkOffset;
137 T* _currentChunk;
137 T* _currentChunk;
138
138
139 };
139 };
140
140
141
141
142 #endif
142 #endif
@@ -1,101 +1,101
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtObjectPtr.cpp
35 // \file PythonQtObjectPtr.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include <PythonQt.h>
42 #include <PythonQt.h>
43
43
44 QVariant PythonQtObjectPtr::evalScript(const QString& script, int start)
44 QVariant PythonQtObjectPtr::evalScript(const QString& script, int start)
45 {
45 {
46 return PythonQt::self()->evalScript(_object, script, start);
46 return PythonQt::self()->evalScript(_object, script, start);
47 }
47 }
48
48
49 void PythonQtObjectPtr::evalFile(const QString& file)
49 void PythonQtObjectPtr::evalFile(const QString& file)
50 {
50 {
51 PythonQt::self()->evalFile(_object, file);
51 PythonQt::self()->evalFile(_object, file);
52 }
52 }
53
53
54 QVariant PythonQtObjectPtr::evalCode(PyObject* pycode)
54 QVariant PythonQtObjectPtr::evalCode(PyObject* pycode)
55 {
55 {
56 return PythonQt::self()->evalCode(_object, pycode);
56 return PythonQt::self()->evalCode(_object, pycode);
57 }
57 }
58
58
59 void PythonQtObjectPtr::addObject(const QString& name, QObject* object)
59 void PythonQtObjectPtr::addObject(const QString& name, QObject* object)
60 {
60 {
61 PythonQt::self()->addObject(_object, name, object);
61 PythonQt::self()->addObject(_object, name, object);
62 }
62 }
63
63
64 void PythonQtObjectPtr::addVariable(const QString& name, const QVariant& v)
64 void PythonQtObjectPtr::addVariable(const QString& name, const QVariant& v)
65 {
65 {
66 PythonQt::self()->addVariable(_object, name, v);
66 PythonQt::self()->addVariable(_object, name, v);
67 }
67 }
68
68
69 void PythonQtObjectPtr::removeVariable(const QString& name)
69 void PythonQtObjectPtr::removeVariable(const QString& name)
70 {
70 {
71 PythonQt::self()->removeVariable(_object, name);
71 PythonQt::self()->removeVariable(_object, name);
72 }
72 }
73
73
74 QVariant PythonQtObjectPtr::getVariable(const QString& name)
74 QVariant PythonQtObjectPtr::getVariable(const QString& name)
75 {
75 {
76 return PythonQt::self()->getVariable(_object, name);
76 return PythonQt::self()->getVariable(_object, name);
77 }
77 }
78
78
79
79
80 QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args)
80 QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args)
81 {
81 {
82 return PythonQt::self()->call(_object, callable, args);
82 return PythonQt::self()->call(_object, callable, args);
83 }
83 }
84
84
85 QVariant PythonQtObjectPtr::call(const QVariantList& args)
85 QVariant PythonQtObjectPtr::call(const QVariantList& args)
86 {
86 {
87 return PythonQt::self()->call(_object, args);
87 return PythonQt::self()->call(_object, args);
88 }
88 }
89
89
90 bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
90 bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
91 {
91 {
92 if (!variant.isNull()) {
92 if (!variant.isNull()) {
93 setObject(qVariantValue<PythonQtObjectPtr>(variant));
93 setObject(qVariantValue<PythonQtObjectPtr>(variant));
94 return true;
94 return true;
95 }
95 }
96 else {
96 else {
97 setObject(0);
97 setObject(0);
98 return false;
98 return false;
99 }
99 }
100
100
101 }
101 }
@@ -1,174 +1,174
1 #ifndef _PYTHONQTOBJECTPTR_H
1 #ifndef _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtObjectPtr.h
38 // \file PythonQtObjectPtr.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include <Python.h>
46 #include "PythonQtSystem.h"
46 #include "PythonQtSystem.h"
47 #include <QVariant>
47 #include <QVariant>
48 #include <QVariantList>
48 #include <QVariantList>
49
49
50 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
50 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
51 class PYTHONQT_EXPORT PythonQtObjectPtr
51 class PYTHONQT_EXPORT PythonQtObjectPtr
52 {
52 {
53 public:
53 public:
54 PythonQtObjectPtr():_object(NULL) {}
54 PythonQtObjectPtr():_object(NULL) {}
55
55
56 PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) {
56 PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) {
57 setObject(p.object());
57 setObject(p.object());
58 }
58 }
59
59
60 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
60 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
61 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
61 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
62 fromVariant(variant);
62 fromVariant(variant);
63 }
63 }
64
64
65 PythonQtObjectPtr(PyObject* o) {
65 PythonQtObjectPtr(PyObject* o) {
66 _object = o;
66 _object = o;
67 if (o) Py_INCREF(_object);
67 if (o) Py_INCREF(_object);
68 }
68 }
69
69
70 ~PythonQtObjectPtr() { if (_object) Py_DECREF(_object); }
70 ~PythonQtObjectPtr() { if (_object) Py_DECREF(_object); }
71
71
72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
73 bool fromVariant(const QVariant& variant);
73 bool fromVariant(const QVariant& variant);
74
74
75 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
75 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
76 setObject(p.object());
76 setObject(p.object());
77 return *this;
77 return *this;
78 }
78 }
79
79
80 PythonQtObjectPtr &operator=(PyObject* o) {
80 PythonQtObjectPtr &operator=(PyObject* o) {
81 setObject(o);
81 setObject(o);
82 return *this;
82 return *this;
83 }
83 }
84
84
85
85
86 PythonQtObjectPtr &operator=(const QVariant& variant) {
86 PythonQtObjectPtr &operator=(const QVariant& variant) {
87 fromVariant(variant);
87 fromVariant(variant);
88 return *this;
88 return *this;
89 }
89 }
90
90
91
91
92 bool operator==( const PythonQtObjectPtr &p ) const {
92 bool operator==( const PythonQtObjectPtr &p ) const {
93 return object() == p.object();
93 return object() == p.object();
94 }
94 }
95
95
96 bool operator!= ( const PythonQtObjectPtr& p ) const {
96 bool operator!= ( const PythonQtObjectPtr& p ) const {
97 return !( *this == p );
97 return !( *this == p );
98 }
98 }
99
99
100 bool operator==( PyObject* p ) const {
100 bool operator==( PyObject* p ) const {
101 return object() == p;
101 return object() == p;
102 }
102 }
103
103
104 bool operator!= ( PyObject* p ) const {
104 bool operator!= ( PyObject* p ) const {
105 return object() != p;
105 return object() != p;
106 }
106 }
107
107
108 bool isNull() const { return !object(); }
108 bool isNull() const { return !object(); }
109
109
110 PyObject* operator->() const { return object(); }
110 PyObject* operator->() const { return object(); }
111
111
112 PyObject& operator*() const { return *( object() ); }
112 PyObject& operator*() const { return *( object() ); }
113
113
114 operator PyObject*() const { return object(); }
114 operator PyObject*() const { return object(); }
115
115
116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
117 void setNewRef(PyObject* o) {
117 void setNewRef(PyObject* o) {
118 if (o != _object) {
118 if (o != _object) {
119 if (_object) Py_DECREF(_object);
119 if (_object) Py_DECREF(_object);
120 _object = o;
120 _object = o;
121 }
121 }
122 }
122 }
123
123
124 PyObject* object() const {
124 PyObject* object() const {
125 return _object;
125 return _object;
126 }
126 }
127
127
128 //! evaluates the given script code in the context of this object and returns the result value
128 //! evaluates the given script code in the context of this object and returns the result value
129 QVariant evalScript(const QString& script, int start = Py_file_input);
129 QVariant evalScript(const QString& script, int start = Py_file_input);
130
130
131 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
131 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
132 //! If pycode is NULL, a python error is printed.
132 //! If pycode is NULL, a python error is printed.
133 QVariant evalCode(PyObject* pycode);
133 QVariant evalCode(PyObject* pycode);
134
134
135 //! evaluates the given code in the context
135 //! evaluates the given code in the context
136 void evalFile(const QString& filename);
136 void evalFile(const QString& filename);
137
137
138 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
138 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
139 void addObject(const QString& name, QObject* object);
139 void addObject(const QString& name, QObject* object);
140
140
141 //! add the given variable to the module
141 //! add the given variable to the module
142 void addVariable(const QString& name, const QVariant& v);
142 void addVariable(const QString& name, const QVariant& v);
143
143
144 //! remove the given variable
144 //! remove the given variable
145 void removeVariable(const QString& name);
145 void removeVariable(const QString& name);
146
146
147 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
147 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
148 QVariant getVariable(const QString& name);
148 QVariant getVariable(const QString& name);
149
149
150 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
150 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
151 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
151 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
152
152
153 //! call the contained python object directly, returns the result converted to a QVariant
153 //! call the contained python object directly, returns the result converted to a QVariant
154 QVariant call(const QVariantList& args = QVariantList());
154 QVariant call(const QVariantList& args = QVariantList());
155
155
156 protected:
156 protected:
157
157
158 void setObject(PyObject* o) {
158 void setObject(PyObject* o) {
159 if (o != _object) {
159 if (o != _object) {
160 if (_object) Py_DECREF(_object);
160 if (_object) Py_DECREF(_object);
161 _object = o;
161 _object = o;
162 if (_object) Py_INCREF(_object);
162 if (_object) Py_INCREF(_object);
163 }
163 }
164 }
164 }
165
165
166 private:
166 private:
167 PyObject* _object;
167 PyObject* _object;
168 };
168 };
169
169
170
170
171 // register it to the meta type system
171 // register it to the meta type system
172 Q_DECLARE_METATYPE(PythonQtObjectPtr)
172 Q_DECLARE_METATYPE(PythonQtObjectPtr)
173
173
174 #endif No newline at end of file
174 #endif
@@ -1,80 +1,80
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtQFileImporter.h
35 // \file PythonQtQFileImporter.h
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2009-03
38 // \date 2009-03
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include <QFile>
42 #include <QFile>
43 #include <QFileInfo>
43 #include <QFileInfo>
44
44
45 #include "PythonQtQFileImporter.h"
45 #include "PythonQtQFileImporter.h"
46
46
47 PythonQtQFileImporter::PythonQtQFileImporter() {
47 PythonQtQFileImporter::PythonQtQFileImporter() {
48 }
48 }
49
49
50 PythonQtQFileImporter::~PythonQtQFileImporter() {
50 PythonQtQFileImporter::~PythonQtQFileImporter() {
51 }
51 }
52
52
53 QByteArray PythonQtQFileImporter::readFileAsBytes (const QString &filename) {
53 QByteArray PythonQtQFileImporter::readFileAsBytes (const QString &filename) {
54 QFile f(filename);
54 QFile f(filename);
55 if (f.open(QIODevice::ReadOnly)) {
55 if (f.open(QIODevice::ReadOnly)) {
56 return f.readAll();
56 return f.readAll();
57 } else {
57 } else {
58 return QByteArray();
58 return QByteArray();
59 }
59 }
60 }
60 }
61
61
62 QByteArray PythonQtQFileImporter::readSourceFile (const QString &filename, bool &ok) {
62 QByteArray PythonQtQFileImporter::readSourceFile (const QString &filename, bool &ok) {
63 QFile f(filename);
63 QFile f(filename);
64 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
64 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
65 ok = true;
65 ok = true;
66 return f.readAll();
66 return f.readAll();
67 } else {
67 } else {
68 ok = false;
68 ok = false;
69 return QByteArray();
69 return QByteArray();
70 }
70 }
71 }
71 }
72
72
73 bool PythonQtQFileImporter::exists (const QString &filename) {
73 bool PythonQtQFileImporter::exists (const QString &filename) {
74 return QFile::exists(filename);
74 return QFile::exists(filename);
75 }
75 }
76
76
77 QDateTime PythonQtQFileImporter::lastModifiedDate (const QString &filename) {
77 QDateTime PythonQtQFileImporter::lastModifiedDate (const QString &filename) {
78 QFileInfo fi(filename);
78 QFileInfo fi(filename);
79 return fi.lastModified();
79 return fi.lastModified();
80 }
80 }
@@ -1,63 +1,63
1 #ifndef _PYTHONQTQFILEIMPORTER_H
1 #ifndef _PYTHONQTQFILEIMPORTER_H
2 #define _PYTHONQTQFILEIMPORTER_H
2 #define _PYTHONQTQFILEIMPORTER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtQFileImporter.h
38 // \file PythonQtQFileImporter.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2009-03
41 // \date 2009-03
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <PythonQtImportFileInterface.h>
45 #include <PythonQtImportFileInterface.h>
46
46
47 //! default importer implementation using QFile to load python code
47 //! default importer implementation using QFile to load python code
48 class PythonQtQFileImporter : public PythonQtImportFileInterface {
48 class PythonQtQFileImporter : public PythonQtImportFileInterface {
49 public:
49 public:
50 PythonQtQFileImporter();
50 PythonQtQFileImporter();
51 ~PythonQtQFileImporter();
51 ~PythonQtQFileImporter();
52
52
53 QByteArray readFileAsBytes (const QString &filename);
53 QByteArray readFileAsBytes (const QString &filename);
54
54
55 QByteArray readSourceFile (const QString &filename, bool &ok);
55 QByteArray readSourceFile (const QString &filename, bool &ok);
56
56
57 bool exists (const QString &filename);
57 bool exists (const QString &filename);
58
58
59 QDateTime lastModifiedDate (const QString &filename);
59 QDateTime lastModifiedDate (const QString &filename);
60
60
61 };
61 };
62
62
63 #endif
63 #endif
@@ -1,226 +1,226
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSignalReceiver.cpp
35 // \file PythonQtSignalReceiver.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtSignalReceiver.h"
42 #include "PythonQtSignalReceiver.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include "PythonQtMethodInfo.h"
44 #include "PythonQtMethodInfo.h"
45 #include "PythonQtConversion.h"
45 #include "PythonQtConversion.h"
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaMethod>
47 #include <QMetaMethod>
48 #include "funcobject.h"
48 #include "funcobject.h"
49
49
50 void PythonQtSignalTarget::call(void **arguments) const {
50 void PythonQtSignalTarget::call(void **arguments) const {
51 PyObject* result = call(_callable, methodInfo(), arguments);
51 PyObject* result = call(_callable, methodInfo(), arguments);
52 if (result) {
52 if (result) {
53 Py_DECREF(result);
53 Py_DECREF(result);
54 }
54 }
55 }
55 }
56
56
57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
58 {
58 {
59 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
59 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
60 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
60 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
61
61
62 int numPythonArgs = -1;
62 int numPythonArgs = -1;
63 if (PyFunction_Check(callable)) {
63 if (PyFunction_Check(callable)) {
64 PyObject* o = callable;
64 PyObject* o = callable;
65 PyFunctionObject* func = (PyFunctionObject*)o;
65 PyFunctionObject* func = (PyFunctionObject*)o;
66 PyCodeObject* code = (PyCodeObject*)func->func_code;
66 PyCodeObject* code = (PyCodeObject*)func->func_code;
67 if (!(code->co_flags & 0x04)) {
67 if (!(code->co_flags & 0x04)) {
68 numPythonArgs = code->co_argcount;
68 numPythonArgs = code->co_argcount;
69 } else {
69 } else {
70 // variable numbers of arguments allowed
70 // variable numbers of arguments allowed
71 }
71 }
72 } else if (PyMethod_Check(callable)) {
72 } else if (PyMethod_Check(callable)) {
73 PyObject* o = callable;
73 PyObject* o = callable;
74 PyMethodObject* method = (PyMethodObject*)o;
74 PyMethodObject* method = (PyMethodObject*)o;
75 if (PyFunction_Check(method->im_func)) {
75 if (PyFunction_Check(method->im_func)) {
76 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
76 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
77 PyCodeObject* code = (PyCodeObject*)func->func_code;
77 PyCodeObject* code = (PyCodeObject*)func->func_code;
78 if (!(code->co_flags & 0x04)) {
78 if (!(code->co_flags & 0x04)) {
79 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
79 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
80 } else {
80 } else {
81 // variable numbers of arguments allowed
81 // variable numbers of arguments allowed
82 }
82 }
83 }
83 }
84 }
84 }
85
85
86 const PythonQtMethodInfo* m = methodInfos;
86 const PythonQtMethodInfo* m = methodInfos;
87 // parameterCount includes return value:
87 // parameterCount includes return value:
88 int count = m->parameterCount();
88 int count = m->parameterCount();
89 if (numPythonArgs!=-1) {
89 if (numPythonArgs!=-1) {
90 if (count>numPythonArgs+1) {
90 if (count>numPythonArgs+1) {
91 // take less arguments
91 // take less arguments
92 count = numPythonArgs+1;
92 count = numPythonArgs+1;
93 }
93 }
94 }
94 }
95
95
96 PyObject* pargs = NULL;
96 PyObject* pargs = NULL;
97 if (count>1) {
97 if (count>1) {
98 pargs = PyTuple_New(count-1);
98 pargs = PyTuple_New(count-1);
99 }
99 }
100 bool err = false;
100 bool err = false;
101 // transform Qt values to Python
101 // transform Qt values to Python
102 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
102 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
103 for (int i = 1; i < count; i++) {
103 for (int i = 1; i < count; i++) {
104 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
104 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
105 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
105 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
106 if (arg) {
106 if (arg) {
107 // steals reference, no unref
107 // steals reference, no unref
108 PyTuple_SetItem(pargs, i-1,arg);
108 PyTuple_SetItem(pargs, i-1,arg);
109 } else {
109 } else {
110 err = true;
110 err = true;
111 break;
111 break;
112 }
112 }
113 }
113 }
114
114
115 PyObject* result = NULL;
115 PyObject* result = NULL;
116 if (!err) {
116 if (!err) {
117 PyErr_Clear();
117 PyErr_Clear();
118 result = PyObject_CallObject(callable, pargs);
118 result = PyObject_CallObject(callable, pargs);
119 if (result) {
119 if (result) {
120 // ok
120 // ok
121 } else {
121 } else {
122 PythonQt::self()->handleError();
122 PythonQt::self()->handleError();
123 }
123 }
124 }
124 }
125 if (pargs) {
125 if (pargs) {
126 // free the arguments again
126 // free the arguments again
127 Py_DECREF(pargs);
127 Py_DECREF(pargs);
128 }
128 }
129
129
130 return result;
130 return result;
131 }
131 }
132
132
133 //------------------------------------------------------------------------------
133 //------------------------------------------------------------------------------
134
134
135 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
135 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
136 {
136 {
137 _obj = obj;
137 _obj = obj;
138
138
139 // fetch the class info for object, since we will need to for correct enum resolution in
139 // fetch the class info for object, since we will need to for correct enum resolution in
140 // signals
140 // signals
141 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
141 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
142 if (!_objClassInfo || !_objClassInfo->isQObject()) {
142 if (!_objClassInfo || !_objClassInfo->isQObject()) {
143 PythonQt::self()->registerClass(obj->metaObject());
143 PythonQt::self()->registerClass(obj->metaObject());
144 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
144 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
145 }
145 }
146 // force decorator/enum creation
146 // force decorator/enum creation
147 _objClassInfo->decorator();
147 _objClassInfo->decorator();
148
148
149 _slotCount = staticMetaObject.methodOffset();
149 _slotCount = staticMetaObject.methodOffset();
150 }
150 }
151
151
152 PythonQtSignalReceiver::~PythonQtSignalReceiver()
152 PythonQtSignalReceiver::~PythonQtSignalReceiver()
153 {
153 {
154 PythonQt::priv()->removeSignalEmitter(_obj);
154 PythonQt::priv()->removeSignalEmitter(_obj);
155 }
155 }
156
156
157
157
158 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
158 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
159 {
159 {
160 bool flag = false;
160 bool flag = false;
161 int sigId = getSignalIndex(signal);
161 int sigId = getSignalIndex(signal);
162 if (sigId>=0) {
162 if (sigId>=0) {
163 // create PythonQtMethodInfo from signal
163 // create PythonQtMethodInfo from signal
164 QMetaMethod meta = _obj->metaObject()->method(sigId);
164 QMetaMethod meta = _obj->metaObject()->method(sigId);
165 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
165 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
166 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
166 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
167 _targets.append(t);
167 _targets.append(t);
168 // now connect to ourselves with the new slot id
168 // now connect to ourselves with the new slot id
169 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
169 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
170
170
171 _slotCount++;
171 _slotCount++;
172 flag = true;
172 flag = true;
173 }
173 }
174 return flag;
174 return flag;
175 }
175 }
176
176
177 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
177 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
178 {
178 {
179 bool found = false;
179 bool found = false;
180 int sigId = getSignalIndex(signal);
180 int sigId = getSignalIndex(signal);
181 if (sigId>=0) {
181 if (sigId>=0) {
182 QMutableListIterator<PythonQtSignalTarget> i(_targets);
182 QMutableListIterator<PythonQtSignalTarget> i(_targets);
183 while (i.hasNext()) {
183 while (i.hasNext()) {
184 if (i.next().isSame(sigId, callable)) {
184 if (i.next().isSame(sigId, callable)) {
185 i.remove();
185 i.remove();
186 found = true;
186 found = true;
187 break;
187 break;
188 }
188 }
189 }
189 }
190 }
190 }
191 return found;
191 return found;
192 }
192 }
193
193
194 void PythonQtSignalReceiver::removeSignalHandlers()
194 void PythonQtSignalReceiver::removeSignalHandlers()
195 {
195 {
196 _targets.clear();
196 _targets.clear();
197 }
197 }
198
198
199 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
199 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
200 {
200 {
201 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
201 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
202 if (sigId<0) {
202 if (sigId<0) {
203 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
203 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
204 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
204 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
205 }
205 }
206 return sigId;
206 return sigId;
207 }
207 }
208
208
209 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
209 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
210 {
210 {
211 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
211 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
212 if (c != QMetaObject::InvokeMetaMethod) {
212 if (c != QMetaObject::InvokeMetaMethod) {
213 QObject::qt_metacall(c, id, arguments);
213 QObject::qt_metacall(c, id, arguments);
214 }
214 }
215
215
216 bool found = false;
216 bool found = false;
217 foreach(const PythonQtSignalTarget& t, _targets) {
217 foreach(const PythonQtSignalTarget& t, _targets) {
218 if (t.slotId() == id) {
218 if (t.slotId() == id) {
219 found = true;
219 found = true;
220 t.call(arguments);
220 t.call(arguments);
221 break;
221 break;
222 }
222 }
223 }
223 }
224 return 0;
224 return 0;
225 }
225 }
226
226
@@ -1,141 +1,141
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtSignalReceiver.h
38 // \file PythonQtSignalReceiver.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include <Python.h>
46 #include "PythonQtSystem.h"
46 #include "PythonQtSystem.h"
47 #include "PythonQtObjectPtr.h"
47 #include "PythonQtObjectPtr.h"
48
48
49 class PythonQtMethodInfo;
49 class PythonQtMethodInfo;
50 class PythonQtClassInfo;
50 class PythonQtClassInfo;
51
51
52 //! stores information about a signal target
52 //! stores information about a signal target
53 /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented
53 /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented
54 */
54 */
55 class PYTHONQT_EXPORT PythonQtSignalTarget {
55 class PYTHONQT_EXPORT PythonQtSignalTarget {
56 public:
56 public:
57 PythonQtSignalTarget() {
57 PythonQtSignalTarget() {
58 _signalId = -1;
58 _signalId = -1;
59 _methodInfo = NULL;
59 _methodInfo = NULL;
60 _slotId = -1;
60 _slotId = -1;
61 }
61 }
62
62
63 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
63 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
64 {
64 {
65 _signalId = signalId;
65 _signalId = signalId;
66 _slotId = slotId;
66 _slotId = slotId;
67 _methodInfo = methodInfo;
67 _methodInfo = methodInfo;
68 _callable = callable;
68 _callable = callable;
69 };
69 };
70
70
71 ~PythonQtSignalTarget() {
71 ~PythonQtSignalTarget() {
72 };
72 };
73
73
74 //! get the id of the original signal
74 //! get the id of the original signal
75 int signalId() const { return _signalId; }
75 int signalId() const { return _signalId; }
76
76
77 //! get the id that was assigned to this simulated slot
77 //! get the id that was assigned to this simulated slot
78 int slotId() const { return _slotId; }
78 int slotId() const { return _slotId; }
79
79
80 //! get the signals parameter info
80 //! get the signals parameter info
81 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
81 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
82
82
83 //! call the python callable with the given arguments (as defined in methodInfo)
83 //! call the python callable with the given arguments (as defined in methodInfo)
84 void call(void **arguments) const;
84 void call(void **arguments) const;
85
85
86 //! check if it is the same signal target
86 //! check if it is the same signal target
87 bool isSame(int signalId, PyObject* callable) const { return callable==_callable && signalId==_signalId; }
87 bool isSame(int signalId, PyObject* callable) const { return callable==_callable && signalId==_signalId; }
88
88
89 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
89 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
90 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
90 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
91
91
92 private:
92 private:
93 int _signalId;
93 int _signalId;
94 int _slotId;
94 int _slotId;
95 const PythonQtMethodInfo* _methodInfo;
95 const PythonQtMethodInfo* _methodInfo;
96 PythonQtObjectPtr _callable;
96 PythonQtObjectPtr _callable;
97 };
97 };
98
98
99 //! base class for signal receivers
99 //! base class for signal receivers
100 /*!
100 /*!
101 */
101 */
102 class PythonQtSignalReceiverBase : public QObject {
102 class PythonQtSignalReceiverBase : public QObject {
103 Q_OBJECT
103 Q_OBJECT
104 public:
104 public:
105 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
105 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
106 };
106 };
107
107
108 //! receives all signals for one QObject
108 //! receives all signals for one QObject
109 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
109 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
110 */
110 */
111 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
111 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
112
112
113 public:
113 public:
114 PythonQtSignalReceiver(QObject* obj);
114 PythonQtSignalReceiver(QObject* obj);
115 ~PythonQtSignalReceiver();
115 ~PythonQtSignalReceiver();
116
116
117 //! add a signal handler
117 //! add a signal handler
118 bool addSignalHandler(const char* signal, PyObject* callable);
118 bool addSignalHandler(const char* signal, PyObject* callable);
119
119
120 //! remove a signal handler
120 //! remove a signal handler
121 bool removeSignalHandler(const char* signal, PyObject* callable);
121 bool removeSignalHandler(const char* signal, PyObject* callable);
122
122
123 //! remove all signal handlers
123 //! remove all signal handlers
124 void removeSignalHandlers();
124 void removeSignalHandlers();
125
125
126 //! we implement this method to simulate a number of slots that match the ids in _targets
126 //! we implement this method to simulate a number of slots that match the ids in _targets
127 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
127 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
128
128
129 private:
129 private:
130 //! get the index of the signal
130 //! get the index of the signal
131 int getSignalIndex(const char* signal);
131 int getSignalIndex(const char* signal);
132
132
133 QObject* _obj;
133 QObject* _obj;
134 PythonQtClassInfo* _objClassInfo;
134 PythonQtClassInfo* _objClassInfo;
135 int _slotCount;
135 int _slotCount;
136 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
136 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
137 QList<PythonQtSignalTarget> _targets;
137 QList<PythonQtSignalTarget> _targets;
138 };
138 };
139
139
140
140
141 #endif
141 #endif
@@ -1,511 +1,511
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSlot.cpp
35 // \file PythonQtSlot.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtSlot.h"
43 #include "PythonQtSlot.h"
44 #include "PythonQtInstanceWrapper.h"
44 #include "PythonQtInstanceWrapper.h"
45 #include "PythonQtClassInfo.h"
45 #include "PythonQtClassInfo.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include <iostream>
48 #include <iostream>
49
49
50 #define PYTHONQT_MAX_ARGS 32
50 #define PYTHONQT_MAX_ARGS 32
51
51
52
52
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
54 {
54 {
55 static unsigned int recursiveEntry = 0;
55 static unsigned int recursiveEntry = 0;
56
56
57 if (directReturnValuePointer) {
57 if (directReturnValuePointer) {
58 *directReturnValuePointer = NULL;
58 *directReturnValuePointer = NULL;
59 }
59 }
60 // store the current storage position, so that we can get back to this state after a slot is called
60 // store the current storage position, so that we can get back to this state after a slot is called
61 // (do this locally, so that we have all positions on the stack
61 // (do this locally, so that we have all positions on the stack
62 PythonQtValueStoragePosition globalValueStoragePos;
62 PythonQtValueStoragePosition globalValueStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
68
68
69 recursiveEntry++;
69 recursiveEntry++;
70
70
71 // the arguments that are passed to qt_metacall
71 // the arguments that are passed to qt_metacall
72 void* argList[PYTHONQT_MAX_ARGS];
72 void* argList[PYTHONQT_MAX_ARGS];
73 PyObject* result = NULL;
73 PyObject* result = NULL;
74 int argc = info->parameterCount();
74 int argc = info->parameterCount();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
76
76
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
78 // set return argument to NULL
78 // set return argument to NULL
79 argList[0] = NULL;
79 argList[0] = NULL;
80
80
81 bool ok = true;
81 bool ok = true;
82 bool skipFirst = false;
82 bool skipFirst = false;
83 if (info->isInstanceDecorator()) {
83 if (info->isInstanceDecorator()) {
84 skipFirst = true;
84 skipFirst = true;
85
85
86 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
86 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
87 void* arg1 = firstArgument;
87 void* arg1 = firstArgument;
88 if (!arg1) {
88 if (!arg1) {
89 arg1 = objectToCall;
89 arg1 = objectToCall;
90 }
90 }
91 if (arg1) {
91 if (arg1) {
92 // upcast to correct parent class
92 // upcast to correct parent class
93 arg1 = ((char*)arg1)+info->upcastingOffset();
93 arg1 = ((char*)arg1)+info->upcastingOffset();
94 }
94 }
95
95
96 argList[1] = &arg1;
96 argList[1] = &arg1;
97 if (ok) {
97 if (ok) {
98 for (int i = 2; i<argc && ok; i++) {
98 for (int i = 2; i<argc && ok; i++) {
99 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
99 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
100 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
100 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
101 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
101 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
102 if (argList[i]==NULL) {
102 if (argList[i]==NULL) {
103 ok = false;
103 ok = false;
104 break;
104 break;
105 }
105 }
106 }
106 }
107 }
107 }
108 } else {
108 } else {
109 for (int i = 1; i<argc && ok; i++) {
109 for (int i = 1; i<argc && ok; i++) {
110 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
110 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
111 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
111 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
112 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
112 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
113 if (argList[i]==NULL) {
113 if (argList[i]==NULL) {
114 ok = false;
114 ok = false;
115 break;
115 break;
116 }
116 }
117 }
117 }
118 }
118 }
119
119
120 if (ok) {
120 if (ok) {
121 // parameters are ok, now create the qt return value which is assigned to by metacall
121 // parameters are ok, now create the qt return value which is assigned to by metacall
122 if (returnValueParam.typeId != QMetaType::Void) {
122 if (returnValueParam.typeId != QMetaType::Void) {
123 // create empty default value for the return value
123 // create empty default value for the return value
124 if (!directReturnValuePointer) {
124 if (!directReturnValuePointer) {
125 // create empty default value for the return value
125 // create empty default value for the return value
126 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
126 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
127 if (argList[0]==NULL) {
127 if (argList[0]==NULL) {
128 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
128 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
129 // pass its internal pointer
129 // pass its internal pointer
130 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
130 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
131 if (info && info->pythonQtClassWrapper()) {
131 if (info && info->pythonQtClassWrapper()) {
132 PyObject* emptyTuple = PyTuple_New(0);
132 PyObject* emptyTuple = PyTuple_New(0);
133 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
133 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
134 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
134 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
135 if (result) {
135 if (result) {
136 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
136 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
137 }
137 }
138 Py_DECREF(emptyTuple);
138 Py_DECREF(emptyTuple);
139 }
139 }
140 }
140 }
141 } else {
141 } else {
142 // we can use our pointer directly!
142 // we can use our pointer directly!
143 argList[0] = directReturnValuePointer;
143 argList[0] = directReturnValuePointer;
144 }
144 }
145 }
145 }
146
146
147 // invoke the slot via metacall
147 // invoke the slot via metacall
148 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
148 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
149
149
150 // handle the return value (which in most cases still needs to be converted to a Python object)
150 // handle the return value (which in most cases still needs to be converted to a Python object)
151 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
151 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
152 if (directReturnValuePointer) {
152 if (directReturnValuePointer) {
153 result = NULL;
153 result = NULL;
154 } else {
154 } else {
155 // the resulting object maybe present already, because we created it above at 1)...
155 // the resulting object maybe present already, because we created it above at 1)...
156 if (!result) {
156 if (!result) {
157 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
157 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
158 }
158 }
159 }
159 }
160 } else {
160 } else {
161 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
161 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
162 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
162 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
163 result = NULL;
163 result = NULL;
164 }
164 }
165 }
165 }
166 recursiveEntry--;
166 recursiveEntry--;
167
167
168 // reset the parameter storage position to the stored pos to "pop" the parameter stack
168 // reset the parameter storage position to the stored pos to "pop" the parameter stack
169 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
169 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
170 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
170 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
171 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
171 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
172
172
173 *pythonReturnValue = result;
173 *pythonReturnValue = result;
174 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
174 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
175 return result || (directReturnValuePointer && *directReturnValuePointer);
175 return result || (directReturnValuePointer && *directReturnValuePointer);
176 }
176 }
177
177
178 //-----------------------------------------------------------------------------------
178 //-----------------------------------------------------------------------------------
179
179
180 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
180 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
181
181
182 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
182 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
183 {
183 {
184 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
184 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
185 PythonQtSlotInfo* info = f->m_ml;
185 PythonQtSlotInfo* info = f->m_ml;
186 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
186 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
187 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
187 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
188 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
188 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
189 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
189 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
190 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
190 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
191 return NULL;
191 return NULL;
192 } else {
192 } else {
193 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
193 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
194 }
194 }
195 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
195 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
196 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
196 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
197 if (info->isClassDecorator()) {
197 if (info->isClassDecorator()) {
198 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
198 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
199 } else {
199 } else {
200 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
200 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
201 Py_ssize_t argc = PyTuple_Size(args);
201 Py_ssize_t argc = PyTuple_Size(args);
202 if (argc>0) {
202 if (argc>0) {
203 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
203 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
204 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
204 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
205 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
205 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
206 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
206 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
207 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
207 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
208 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
208 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
209 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
209 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
210 return NULL;
210 return NULL;
211 }
211 }
212 // strip the first argument...
212 // strip the first argument...
213 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
213 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
214 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
214 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
215 Py_DECREF(newargs);
215 Py_DECREF(newargs);
216 return result;
216 return result;
217 } else {
217 } else {
218 // first arg is not of correct type!
218 // first arg is not of correct type!
219 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
219 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
220 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
220 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
221 return NULL;
221 return NULL;
222 }
222 }
223 } else {
223 } else {
224 // wrong number of args
224 // wrong number of args
225 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
225 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
226 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
226 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
227 return NULL;
227 return NULL;
228 }
228 }
229 }
229 }
230 }
230 }
231 return NULL;
231 return NULL;
232 }
232 }
233
233
234 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
234 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
235 {
235 {
236 int argc = args?PyTuple_Size(args):0;
236 int argc = args?PyTuple_Size(args):0;
237
237
238 #ifdef PYTHONQT_DEBUG
238 #ifdef PYTHONQT_DEBUG
239 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
239 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
240 #endif
240 #endif
241
241
242 PyObject* r = NULL;
242 PyObject* r = NULL;
243 bool ok = false;
243 bool ok = false;
244 if (directReturnValuePointer) {
244 if (directReturnValuePointer) {
245 *directReturnValuePointer = NULL;
245 *directReturnValuePointer = NULL;
246 }
246 }
247 if (info->nextInfo()) {
247 if (info->nextInfo()) {
248 // overloaded slot call, try on all slots with strict conversion first
248 // overloaded slot call, try on all slots with strict conversion first
249 bool strict = true;
249 bool strict = true;
250 PythonQtSlotInfo* i = info;
250 PythonQtSlotInfo* i = info;
251 while (i) {
251 while (i) {
252 bool skipFirst = i->isInstanceDecorator();
252 bool skipFirst = i->isInstanceDecorator();
253 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
253 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
254 PyErr_Clear();
254 PyErr_Clear();
255 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
255 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
256 if (PyErr_Occurred() || ok) break;
256 if (PyErr_Occurred() || ok) break;
257 }
257 }
258 i = i->nextInfo();
258 i = i->nextInfo();
259 if (!i) {
259 if (!i) {
260 if (strict) {
260 if (strict) {
261 // one more run without being strict
261 // one more run without being strict
262 strict = false;
262 strict = false;
263 i = info;
263 i = info;
264 }
264 }
265 }
265 }
266 }
266 }
267 if (!ok && !PyErr_Occurred()) {
267 if (!ok && !PyErr_Occurred()) {
268 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
268 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
269 PythonQtSlotInfo* i = info;
269 PythonQtSlotInfo* i = info;
270 while (i) {
270 while (i) {
271 e += QString(i->fullSignature()) + "\n";
271 e += QString(i->fullSignature()) + "\n";
272 i = i->nextInfo();
272 i = i->nextInfo();
273 }
273 }
274 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
274 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
275 }
275 }
276 } else {
276 } else {
277 // simple (non-overloaded) slot call
277 // simple (non-overloaded) slot call
278 bool skipFirst = info->isInstanceDecorator();
278 bool skipFirst = info->isInstanceDecorator();
279 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
279 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
280 PyErr_Clear();
280 PyErr_Clear();
281 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
281 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
282 if (!ok && !PyErr_Occurred()) {
282 if (!ok && !PyErr_Occurred()) {
283 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
283 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
284 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
284 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
285 }
285 }
286 } else {
286 } else {
287 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
287 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
288 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
288 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
289 }
289 }
290 }
290 }
291
291
292 return r;
292 return r;
293 }
293 }
294
294
295 PyObject *
295 PyObject *
296 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
296 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
297 {
297 {
298 PythonQtSlotFunctionObject *op;
298 PythonQtSlotFunctionObject *op;
299 op = pythonqtslot_free_list;
299 op = pythonqtslot_free_list;
300 if (op != NULL) {
300 if (op != NULL) {
301 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
301 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
302 PyObject_INIT(op, &PythonQtSlotFunction_Type);
302 PyObject_INIT(op, &PythonQtSlotFunction_Type);
303 }
303 }
304 else {
304 else {
305 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
305 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
306 if (op == NULL)
306 if (op == NULL)
307 return NULL;
307 return NULL;
308 }
308 }
309 op->m_ml = ml;
309 op->m_ml = ml;
310 Py_XINCREF(self);
310 Py_XINCREF(self);
311 op->m_self = self;
311 op->m_self = self;
312 Py_XINCREF(module);
312 Py_XINCREF(module);
313 op->m_module = module;
313 op->m_module = module;
314 PyObject_GC_Track(op);
314 PyObject_GC_Track(op);
315 return (PyObject *)op;
315 return (PyObject *)op;
316 }
316 }
317
317
318 PythonQtSlotInfo*
318 PythonQtSlotInfo*
319 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
319 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
320 {
320 {
321 if (!PythonQtSlotFunction_Check(op)) {
321 if (!PythonQtSlotFunction_Check(op)) {
322 PyErr_BadInternalCall();
322 PyErr_BadInternalCall();
323 return NULL;
323 return NULL;
324 }
324 }
325 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
325 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
326 }
326 }
327
327
328 PyObject *
328 PyObject *
329 PythonQtSlotFunction_GetSelf(PyObject *op)
329 PythonQtSlotFunction_GetSelf(PyObject *op)
330 {
330 {
331 if (!PythonQtSlotFunction_Check(op)) {
331 if (!PythonQtSlotFunction_Check(op)) {
332 PyErr_BadInternalCall();
332 PyErr_BadInternalCall();
333 return NULL;
333 return NULL;
334 }
334 }
335 return ((PythonQtSlotFunctionObject *)op) -> m_self;
335 return ((PythonQtSlotFunctionObject *)op) -> m_self;
336 }
336 }
337
337
338 /* Methods (the standard built-in methods, that is) */
338 /* Methods (the standard built-in methods, that is) */
339
339
340 static void
340 static void
341 meth_dealloc(PythonQtSlotFunctionObject *m)
341 meth_dealloc(PythonQtSlotFunctionObject *m)
342 {
342 {
343 PyObject_GC_UnTrack(m);
343 PyObject_GC_UnTrack(m);
344 Py_XDECREF(m->m_self);
344 Py_XDECREF(m->m_self);
345 Py_XDECREF(m->m_module);
345 Py_XDECREF(m->m_module);
346 m->m_self = (PyObject *)pythonqtslot_free_list;
346 m->m_self = (PyObject *)pythonqtslot_free_list;
347 pythonqtslot_free_list = m;
347 pythonqtslot_free_list = m;
348 }
348 }
349
349
350 static PyObject *
350 static PyObject *
351 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
351 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
352 {
352 {
353 Py_INCREF(Py_None);
353 Py_INCREF(Py_None);
354 return Py_None;
354 return Py_None;
355 }
355 }
356
356
357 static PyObject *
357 static PyObject *
358 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
358 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
359 {
359 {
360 return PyString_FromString(m->m_ml->metaMethod()->signature());
360 return PyString_FromString(m->m_ml->metaMethod()->signature());
361 }
361 }
362
362
363 static int
363 static int
364 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
364 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
365 {
365 {
366 int err;
366 int err;
367 if (m->m_self != NULL) {
367 if (m->m_self != NULL) {
368 err = visit(m->m_self, arg);
368 err = visit(m->m_self, arg);
369 if (err)
369 if (err)
370 return err;
370 return err;
371 }
371 }
372 if (m->m_module != NULL) {
372 if (m->m_module != NULL) {
373 err = visit(m->m_module, arg);
373 err = visit(m->m_module, arg);
374 if (err)
374 if (err)
375 return err;
375 return err;
376 }
376 }
377 return 0;
377 return 0;
378 }
378 }
379
379
380 static PyObject *
380 static PyObject *
381 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
381 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
382 {
382 {
383 PyObject *self;
383 PyObject *self;
384 if (PyEval_GetRestricted()) {
384 if (PyEval_GetRestricted()) {
385 PyErr_SetString(PyExc_RuntimeError,
385 PyErr_SetString(PyExc_RuntimeError,
386 "method.__self__ not accessible in restricted mode");
386 "method.__self__ not accessible in restricted mode");
387 return NULL;
387 return NULL;
388 }
388 }
389 self = m->m_self;
389 self = m->m_self;
390 if (self == NULL)
390 if (self == NULL)
391 self = Py_None;
391 self = Py_None;
392 Py_INCREF(self);
392 Py_INCREF(self);
393 return self;
393 return self;
394 }
394 }
395
395
396 static PyGetSetDef meth_getsets [] = {
396 static PyGetSetDef meth_getsets [] = {
397 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
397 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
398 {"__name__", (getter)meth_get__name__, NULL, NULL},
398 {"__name__", (getter)meth_get__name__, NULL, NULL},
399 {"__self__", (getter)meth_get__self__, NULL, NULL},
399 {"__self__", (getter)meth_get__self__, NULL, NULL},
400 {NULL, NULL, NULL,NULL},
400 {NULL, NULL, NULL,NULL},
401 };
401 };
402
402
403 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
403 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
404 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
404 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
405 #endif
405 #endif
406
406
407 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
407 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
408
408
409 static PyMemberDef meth_members[] = {
409 static PyMemberDef meth_members[] = {
410 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
410 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
411 {NULL}
411 {NULL}
412 };
412 };
413
413
414 static PyObject *
414 static PyObject *
415 meth_repr(PythonQtSlotFunctionObject *f)
415 meth_repr(PythonQtSlotFunctionObject *f)
416 {
416 {
417 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
417 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
418 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
418 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
419 return PyString_FromFormat("<unbound qt slot %s of %s type>",
419 return PyString_FromFormat("<unbound qt slot %s of %s type>",
420 f->m_ml->slotName().data(),
420 f->m_ml->slotName().data(),
421 self->classInfo()->className());
421 self->classInfo()->className());
422 } else {
422 } else {
423 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
423 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
424 f->m_ml->slotName().data(),
424 f->m_ml->slotName().data(),
425 f->m_self->ob_type->tp_name,
425 f->m_self->ob_type->tp_name,
426 f->m_self);
426 f->m_self);
427 }
427 }
428 }
428 }
429
429
430 static int
430 static int
431 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
431 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
432 {
432 {
433 if (a->m_self != b->m_self)
433 if (a->m_self != b->m_self)
434 return (a->m_self < b->m_self) ? -1 : 1;
434 return (a->m_self < b->m_self) ? -1 : 1;
435 if (a->m_ml == b->m_ml)
435 if (a->m_ml == b->m_ml)
436 return 0;
436 return 0;
437 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
437 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
438 return -1;
438 return -1;
439 else
439 else
440 return 1;
440 return 1;
441 }
441 }
442
442
443 static long
443 static long
444 meth_hash(PythonQtSlotFunctionObject *a)
444 meth_hash(PythonQtSlotFunctionObject *a)
445 {
445 {
446 long x,y;
446 long x,y;
447 if (a->m_self == NULL)
447 if (a->m_self == NULL)
448 x = 0;
448 x = 0;
449 else {
449 else {
450 x = PyObject_Hash(a->m_self);
450 x = PyObject_Hash(a->m_self);
451 if (x == -1)
451 if (x == -1)
452 return -1;
452 return -1;
453 }
453 }
454 y = _Py_HashPointer((void*)(a->m_ml));
454 y = _Py_HashPointer((void*)(a->m_ml));
455 if (y == -1)
455 if (y == -1)
456 return -1;
456 return -1;
457 x ^= y;
457 x ^= y;
458 if (x == -1)
458 if (x == -1)
459 x = -2;
459 x = -2;
460 return x;
460 return x;
461 }
461 }
462
462
463
463
464 PyTypeObject PythonQtSlotFunction_Type = {
464 PyTypeObject PythonQtSlotFunction_Type = {
465 PyObject_HEAD_INIT(&PyType_Type)
465 PyObject_HEAD_INIT(&PyType_Type)
466 0,
466 0,
467 "builtin_qt_slot",
467 "builtin_qt_slot",
468 sizeof(PythonQtSlotFunctionObject),
468 sizeof(PythonQtSlotFunctionObject),
469 0,
469 0,
470 (destructor)meth_dealloc, /* tp_dealloc */
470 (destructor)meth_dealloc, /* tp_dealloc */
471 0, /* tp_print */
471 0, /* tp_print */
472 0, /* tp_getattr */
472 0, /* tp_getattr */
473 0, /* tp_setattr */
473 0, /* tp_setattr */
474 (cmpfunc)meth_compare, /* tp_compare */
474 (cmpfunc)meth_compare, /* tp_compare */
475 (reprfunc)meth_repr, /* tp_repr */
475 (reprfunc)meth_repr, /* tp_repr */
476 0, /* tp_as_number */
476 0, /* tp_as_number */
477 0, /* tp_as_sequence */
477 0, /* tp_as_sequence */
478 0, /* tp_as_mapping */
478 0, /* tp_as_mapping */
479 (hashfunc)meth_hash, /* tp_hash */
479 (hashfunc)meth_hash, /* tp_hash */
480 PythonQtSlotFunction_Call, /* tp_call */
480 PythonQtSlotFunction_Call, /* tp_call */
481 0, /* tp_str */
481 0, /* tp_str */
482 PyObject_GenericGetAttr, /* tp_getattro */
482 PyObject_GenericGetAttr, /* tp_getattro */
483 0, /* tp_setattro */
483 0, /* tp_setattro */
484 0, /* tp_as_buffer */
484 0, /* tp_as_buffer */
485 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
485 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
486 0, /* tp_doc */
486 0, /* tp_doc */
487 (traverseproc)meth_traverse, /* tp_traverse */
487 (traverseproc)meth_traverse, /* tp_traverse */
488 0, /* tp_clear */
488 0, /* tp_clear */
489 0, /* tp_richcompare */
489 0, /* tp_richcompare */
490 0, /* tp_weaklistoffset */
490 0, /* tp_weaklistoffset */
491 0, /* tp_iter */
491 0, /* tp_iter */
492 0, /* tp_iternext */
492 0, /* tp_iternext */
493 0, /* tp_methods */
493 0, /* tp_methods */
494 meth_members, /* tp_members */
494 meth_members, /* tp_members */
495 meth_getsets, /* tp_getset */
495 meth_getsets, /* tp_getset */
496 0, /* tp_base */
496 0, /* tp_base */
497 0, /* tp_dict */
497 0, /* tp_dict */
498 };
498 };
499
499
500 /* Clear out the free list */
500 /* Clear out the free list */
501
501
502 void
502 void
503 PythonQtSlotFunction_Fini(void)
503 PythonQtSlotFunction_Fini(void)
504 {
504 {
505 while (pythonqtslot_free_list) {
505 while (pythonqtslot_free_list) {
506 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
506 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
507 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
507 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
508 PyObject_GC_Del(v);
508 PyObject_GC_Del(v);
509 }
509 }
510 }
510 }
511
511
@@ -1,80 +1,80
1 #ifndef _PYTHONQTSLOT_H
1 #ifndef _PYTHONQTSLOT_H
2 #define _PYTHONQTSLOT_H
2 #define _PYTHONQTSLOT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtSlot.h
38 // \file PythonQtSlot.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "Python.h"
45 #include "Python.h"
46 #include "PythonQtSystem.h"
46 #include "PythonQtSystem.h"
47 #include "structmember.h"
47 #include "structmember.h"
48
48
49 class PythonQtSlotInfo;
49 class PythonQtSlotInfo;
50
50
51 extern PYTHONQT_EXPORT PyTypeObject PythonQtSlotFunction_Type;
51 extern PYTHONQT_EXPORT PyTypeObject PythonQtSlotFunction_Type;
52
52
53 #define PythonQtSlotFunction_Check(op) ((op)->ob_type == &PythonQtSlotFunction_Type)
53 #define PythonQtSlotFunction_Check(op) ((op)->ob_type == &PythonQtSlotFunction_Type)
54
54
55 PythonQtSlotInfo* PythonQtSlotFunction_GetSlotInfo(PyObject *);
55 PythonQtSlotInfo* PythonQtSlotFunction_GetSlotInfo(PyObject *);
56 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
56 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
57
57
58 /* Macros for direct access to these values. Type checks are *not*
58 /* Macros for direct access to these values. Type checks are *not*
59 done, so use with care. */
59 done, so use with care. */
60 #define PythonQtSlotFunction_GET_SELF(func) \
60 #define PythonQtSlotFunction_GET_SELF(func) \
61 (((PythonQtSlotFunctionObject *)func) -> m_self)
61 (((PythonQtSlotFunctionObject *)func) -> m_self)
62
62
63 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
63 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
64
64
65 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
65 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
66
66
67
67
68 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
68 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
69 PyObject *);
69 PyObject *);
70
70
71 //! defines a python object that stores a Qt slot info
71 //! defines a python object that stores a Qt slot info
72 typedef struct {
72 typedef struct {
73 PyObject_HEAD
73 PyObject_HEAD
74 PythonQtSlotInfo *m_ml; /* Description of the C function to call */
74 PythonQtSlotInfo *m_ml; /* Description of the C function to call */
75 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
75 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
76 PyObject *m_module; /* The __module__ attribute, can be anything */
76 PyObject *m_module; /* The __module__ attribute, can be anything */
77 } PythonQtSlotFunctionObject;
77 } PythonQtSlotFunctionObject;
78
78
79
79
80 #endif
80 #endif
@@ -1,314 +1,314
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtStdDecorators.cpp
35 // \file PythonQtStdDecorators.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtStdDecorators.h"
42 #include "PythonQtStdDecorators.h"
43 #include "PythonQt.h"
43 #include "PythonQt.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include <QCoreApplication>
45 #include <QCoreApplication>
46
46
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
48 {
48 {
49 QByteArray signalTmp;
49 QByteArray signalTmp;
50 char first = signal.at(0);
50 char first = signal.at(0);
51 if (first>='0' && first<='9') {
51 if (first>='0' && first<='9') {
52 signalTmp = signal;
52 signalTmp = signal;
53 } else {
53 } else {
54 signalTmp = "2" + signal;
54 signalTmp = "2" + signal;
55 }
55 }
56
56
57 if (sender) {
57 if (sender) {
58 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
58 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
59 } else {
59 } else {
60 return false;
60 return false;
61 }
61 }
62 }
62 }
63
63
64 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
64 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
65 {
65 {
66 bool r = false;
66 bool r = false;
67 if (sender && receiver) {
67 if (sender && receiver) {
68 QByteArray signalTmp;
68 QByteArray signalTmp;
69 char first = signal.at(0);
69 char first = signal.at(0);
70 if (first>='0' && first<='9') {
70 if (first>='0' && first<='9') {
71 signalTmp = signal;
71 signalTmp = signal;
72 } else {
72 } else {
73 signalTmp = "2" + signal;
73 signalTmp = "2" + signal;
74 }
74 }
75
75
76 QByteArray slotTmp;
76 QByteArray slotTmp;
77 first = slot.at(0);
77 first = slot.at(0);
78 if (first>='0' && first<='9') {
78 if (first>='0' && first<='9') {
79 slotTmp = slot;
79 slotTmp = slot;
80 } else {
80 } else {
81 slotTmp = "1" + slot;
81 slotTmp = "1" + slot;
82 }
82 }
83 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
83 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
84 }
84 }
85 return r;
85 return r;
86 }
86 }
87
87
88 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
88 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
89 {
89 {
90 QByteArray signalTmp;
90 QByteArray signalTmp;
91 char first = signal.at(0);
91 char first = signal.at(0);
92 if (first>='0' && first<='9') {
92 if (first>='0' && first<='9') {
93 signalTmp = signal;
93 signalTmp = signal;
94 } else {
94 } else {
95 signalTmp = "2" + signal;
95 signalTmp = "2" + signal;
96 }
96 }
97 if (sender) {
97 if (sender) {
98 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
98 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
99 } else {
99 } else {
100 return false;
100 return false;
101 }
101 }
102 }
102 }
103
103
104 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
104 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
105 {
105 {
106 bool r = false;
106 bool r = false;
107 if (sender && receiver) {
107 if (sender && receiver) {
108 QByteArray signalTmp;
108 QByteArray signalTmp;
109 char first = signal.at(0);
109 char first = signal.at(0);
110 if (first>='0' && first<='9') {
110 if (first>='0' && first<='9') {
111 signalTmp = signal;
111 signalTmp = signal;
112 } else {
112 } else {
113 signalTmp = "2" + signal;
113 signalTmp = "2" + signal;
114 }
114 }
115
115
116 QByteArray slotTmp;
116 QByteArray slotTmp;
117 first = slot.at(0);
117 first = slot.at(0);
118 if (first>='0' && first<='9') {
118 if (first>='0' && first<='9') {
119 slotTmp = slot;
119 slotTmp = slot;
120 } else {
120 } else {
121 slotTmp = "1" + slot;
121 slotTmp = "1" + slot;
122 }
122 }
123
123
124 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
124 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
125 }
125 }
126 return r;
126 return r;
127 }
127 }
128
128
129 #undef emit
129 #undef emit
130 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
130 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
131 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
131 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
132 {
132 {
133 // TODO xxx
133 // TODO xxx
134 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
134 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
135 }
135 }
136 #define emit
136 #define emit
137
137
138 QObject* PythonQtStdDecorators::parent(QObject* o) {
138 QObject* PythonQtStdDecorators::parent(QObject* o) {
139 return o->parent();
139 return o->parent();
140 }
140 }
141
141
142 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
142 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
143 {
143 {
144 o->setParent(parent);
144 o->setParent(parent);
145 }
145 }
146
146
147 const QObjectList* PythonQtStdDecorators::children(QObject* o)
147 const QObjectList* PythonQtStdDecorators::children(QObject* o)
148 {
148 {
149 return &o->children();
149 return &o->children();
150 }
150 }
151
151
152 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
152 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
153 {
153 {
154 return o->setProperty(name, value);
154 return o->setProperty(name, value);
155 }
155 }
156
156
157 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
157 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
158 {
158 {
159 return o->property(name);
159 return o->property(name);
160 }
160 }
161
161
162 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
162 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
163 {
163 {
164 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
164 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
165 }
165 }
166
166
167 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
167 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
168 {
168 {
169 const QMetaObject* meta = NULL;
169 const QMetaObject* meta = NULL;
170 const char* typeName = NULL;
170 const char* typeName = NULL;
171
171
172 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
172 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
173 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
173 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
174 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
174 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
175 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
175 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
176 } else if (PyString_Check(type)) {
176 } else if (PyString_Check(type)) {
177 typeName = PyString_AsString(type);
177 typeName = PyString_AsString(type);
178 }
178 }
179
179
180 if (!typeName && !meta)
180 if (!typeName && !meta)
181 return NULL;
181 return NULL;
182
182
183 return findChild(parent, typeName, meta, name);
183 return findChild(parent, typeName, meta, name);
184 }
184 }
185
185
186 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
186 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
187 {
187 {
188 const QMetaObject* meta = NULL;
188 const QMetaObject* meta = NULL;
189 const char* typeName = NULL;
189 const char* typeName = NULL;
190
190
191 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
191 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
192 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
192 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
193 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
193 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
194 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
194 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
195 } else if (PyString_Check(type)) {
195 } else if (PyString_Check(type)) {
196 typeName = PyString_AsString(type);
196 typeName = PyString_AsString(type);
197 }
197 }
198
198
199 QList<QObject*> list;
199 QList<QObject*> list;
200
200
201 if (!typeName && !meta)
201 if (!typeName && !meta)
202 return list;
202 return list;
203
203
204 findChildren(parent, typeName, meta, name, list);
204 findChildren(parent, typeName, meta, name, list);
205
205
206 return list;
206 return list;
207 }
207 }
208
208
209 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
209 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
210 {
210 {
211 const QMetaObject* meta = NULL;
211 const QMetaObject* meta = NULL;
212 const char* typeName = NULL;
212 const char* typeName = NULL;
213
213
214 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
214 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
215 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
215 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
216 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
216 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
217 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
217 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
218 } else if (PyString_Check(type)) {
218 } else if (PyString_Check(type)) {
219 typeName = PyString_AsString(type);
219 typeName = PyString_AsString(type);
220 }
220 }
221
221
222 QList<QObject*> list;
222 QList<QObject*> list;
223
223
224 if (!typeName && !meta)
224 if (!typeName && !meta)
225 return list;
225 return list;
226
226
227 findChildren(parent, typeName, meta, regExp, list);
227 findChildren(parent, typeName, meta, regExp, list);
228
228
229 return list;
229 return list;
230 }
230 }
231
231
232 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
232 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
233 {
233 {
234 const QObjectList &children = parent->children();
234 const QObjectList &children = parent->children();
235
235
236 int i;
236 int i;
237 for (i = 0; i < children.size(); ++i) {
237 for (i = 0; i < children.size(); ++i) {
238 QObject* obj = children.at(i);
238 QObject* obj = children.at(i);
239
239
240 if (!obj)
240 if (!obj)
241 return NULL;
241 return NULL;
242
242
243 // Skip if the name doesn't match.
243 // Skip if the name doesn't match.
244 if (!name.isNull() && obj->objectName() != name)
244 if (!name.isNull() && obj->objectName() != name)
245 continue;
245 continue;
246
246
247 if ((typeName && obj->inherits(typeName)) ||
247 if ((typeName && obj->inherits(typeName)) ||
248 (meta && meta->cast(obj)))
248 (meta && meta->cast(obj)))
249 return obj;
249 return obj;
250 }
250 }
251
251
252 for (i = 0; i < children.size(); ++i) {
252 for (i = 0; i < children.size(); ++i) {
253 QObject* obj = findChild(children.at(i), typeName, meta, name);
253 QObject* obj = findChild(children.at(i), typeName, meta, name);
254
254
255 if (obj != NULL)
255 if (obj != NULL)
256 return obj;
256 return obj;
257 }
257 }
258
258
259 return NULL;
259 return NULL;
260 }
260 }
261
261
262 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
262 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
263 {
263 {
264 const QObjectList& children = parent->children();
264 const QObjectList& children = parent->children();
265 int i;
265 int i;
266
266
267 for (i = 0; i < children.size(); ++i) {
267 for (i = 0; i < children.size(); ++i) {
268 QObject* obj = children.at(i);
268 QObject* obj = children.at(i);
269
269
270 if (!obj)
270 if (!obj)
271 return -1;
271 return -1;
272
272
273 // Skip if the name doesn't match.
273 // Skip if the name doesn't match.
274 if (!name.isNull() && obj->objectName() != name)
274 if (!name.isNull() && obj->objectName() != name)
275 continue;
275 continue;
276
276
277 if ((typeName && obj->inherits(typeName)) ||
277 if ((typeName && obj->inherits(typeName)) ||
278 (meta && meta->cast(obj))) {
278 (meta && meta->cast(obj))) {
279 list += obj;
279 list += obj;
280 }
280 }
281
281
282 if (findChildren(obj, typeName, meta, name, list) < 0)
282 if (findChildren(obj, typeName, meta, name, list) < 0)
283 return -1;
283 return -1;
284 }
284 }
285
285
286 return 0;
286 return 0;
287 }
287 }
288
288
289 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
289 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
290 {
290 {
291 const QObjectList& children = parent->children();
291 const QObjectList& children = parent->children();
292 int i;
292 int i;
293
293
294 for (i = 0; i < children.size(); ++i) {
294 for (i = 0; i < children.size(); ++i) {
295 QObject* obj = children.at(i);
295 QObject* obj = children.at(i);
296
296
297 if (!obj)
297 if (!obj)
298 return -1;
298 return -1;
299
299
300 // Skip if the name doesn't match.
300 // Skip if the name doesn't match.
301 if (regExp.indexIn(obj->objectName()) == -1)
301 if (regExp.indexIn(obj->objectName()) == -1)
302 continue;
302 continue;
303
303
304 if ((typeName && obj->inherits(typeName)) ||
304 if ((typeName && obj->inherits(typeName)) ||
305 (meta && meta->cast(obj))) {
305 (meta && meta->cast(obj))) {
306 list += obj;
306 list += obj;
307 }
307 }
308
308
309 if (findChildren(obj, typeName, meta, regExp, list) < 0)
309 if (findChildren(obj, typeName, meta, regExp, list) < 0)
310 return -1;
310 return -1;
311 }
311 }
312
312
313 return 0;
313 return 0;
314 }
314 }
@@ -1,112 +1,112
1 #ifndef _PYTHONQTSTDDECORATORS_H
1 #ifndef _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtStdDecorators.h
38 // \file PythonQtStdDecorators.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2007-04
41 // \date 2007-04
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include <Python.h>
46 #include <Python.h>
47 #include <QObject>
47 #include <QObject>
48 #include <QVariantList>
48 #include <QVariantList>
49 #include <QTextDocument>
49 #include <QTextDocument>
50 #include <QColor>
50 #include <QColor>
51 #include <QDateTime>
51 #include <QDateTime>
52 #include <QDate>
52 #include <QDate>
53 #include <QTime>
53 #include <QTime>
54
54
55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
56 {
56 {
57 Q_OBJECT
57 Q_OBJECT
58
58
59 public slots:
59 public slots:
60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
64
64
65 #undef emit
65 #undef emit
66 void emit(QObject* sender, const QByteArray& signal, PyObject* arg1 = NULL,PyObject* arg2 = NULL,
66 void emit(QObject* sender, const QByteArray& signal, PyObject* arg1 = NULL,PyObject* arg2 = NULL,
67 PyObject* arg3 = NULL,PyObject* arg4 = NULL,PyObject* arg5 = NULL,PyObject* arg6 = NULL,PyObject* arg7 = NULL);
67 PyObject* arg3 = NULL,PyObject* arg4 = NULL,PyObject* arg5 = NULL,PyObject* arg6 = NULL,PyObject* arg7 = NULL);
68 #define emit
68 #define emit
69
69
70 QObject* parent(QObject* o);
70 QObject* parent(QObject* o);
71 void setParent(QObject* o, QObject* parent);
71 void setParent(QObject* o, QObject* parent);
72
72
73 const QObjectList* children(QObject* o);
73 const QObjectList* children(QObject* o);
74 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
74 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
75 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
75 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
76 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
76 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
77
77
78 bool setProperty(QObject* o, const char* name, const QVariant& value);
78 bool setProperty(QObject* o, const char* name, const QVariant& value);
79 QVariant property(QObject* o, const char* name);
79 QVariant property(QObject* o, const char* name);
80
80
81 double static_Qt_qAbs(double a) { return qAbs(a); }
81 double static_Qt_qAbs(double a) { return qAbs(a); }
82 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
82 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
83 void static_Qt_qDebug(const QByteArray& msg) { qDebug(msg.constData()); }
83 void static_Qt_qDebug(const QByteArray& msg) { qDebug(msg.constData()); }
84 // TODO: multi arg qDebug...
84 // TODO: multi arg qDebug...
85 void static_Qt_qWarning(const QByteArray& msg) { qWarning(msg.constData()); }
85 void static_Qt_qWarning(const QByteArray& msg) { qWarning(msg.constData()); }
86 // TODO: multi arg qWarning...
86 // TODO: multi arg qWarning...
87 void static_Qt_qCritical(const QByteArray& msg) { qCritical(msg.constData()); }
87 void static_Qt_qCritical(const QByteArray& msg) { qCritical(msg.constData()); }
88 // TODO: multi arg qCritical...
88 // TODO: multi arg qCritical...
89 void static_Qt_qFatal(const QByteArray& msg) { qFatal(msg.constData()); }
89 void static_Qt_qFatal(const QByteArray& msg) { qFatal(msg.constData()); }
90 // TODO: multi arg qFatal...
90 // TODO: multi arg qFatal...
91 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
91 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
92 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
92 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
93 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
93 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
94 int static_Qt_qRound(double a) { return qRound(a); }
94 int static_Qt_qRound(double a) { return qRound(a); }
95 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
95 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
96 const char* static_Qt_qVersion() { return qVersion(); }
96 const char* static_Qt_qVersion() { return qVersion(); }
97 int static_Qt_qrand() { return qrand(); }
97 int static_Qt_qrand() { return qrand(); }
98 void static_Qt_qsrand(uint a) { qsrand(a); }
98 void static_Qt_qsrand(uint a) { qsrand(a); }
99
99
100 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
100 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
101
101
102 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
102 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
103 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
103 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
104
104
105 private:
105 private:
106 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
106 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
107 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
107 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
108 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
108 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
109 };
109 };
110
110
111
111
112 #endif
112 #endif
@@ -1,136 +1,136
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtStdOut.cpp
35 // \file PythonQtStdOut.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtStdOut.h"
42 #include "PythonQtStdOut.h"
43
43
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
45 {
45 {
46 PythonQtStdOutRedirect *self;
46 PythonQtStdOutRedirect *self;
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
48
48
49 self->softspace = 0;
49 self->softspace = 0;
50 self->_cb = NULL;
50 self->_cb = NULL;
51
51
52 return (PyObject *)self;
52 return (PyObject *)self;
53 }
53 }
54
54
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
56 {
56 {
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
58 if (s->_cb) {
58 if (s->_cb) {
59 char *string;
59 char *string;
60 if (!PyArg_ParseTuple(args, "s", &string))
60 if (!PyArg_ParseTuple(args, "s", &string))
61 return NULL;
61 return NULL;
62
62
63 if (s->softspace > 0) {
63 if (s->softspace > 0) {
64 (*s->_cb)(QString(""));
64 (*s->_cb)(QString(""));
65 s->softspace = 0;
65 s->softspace = 0;
66 }
66 }
67
67
68 (*s->_cb)(QString(string));
68 (*s->_cb)(QString(string));
69 }
69 }
70 return Py_BuildValue("");
70 return Py_BuildValue("");
71 }
71 }
72
72
73 static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /*args*/)
73 static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /*args*/)
74 {
74 {
75 return Py_BuildValue("");
75 return Py_BuildValue("");
76 }
76 }
77
77
78
78
79
79
80 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
80 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
81 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
81 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
82 "redirect the writing to a callback"},
82 "redirect the writing to a callback"},
83 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
83 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
84 "flush the output, currently not implemented but needed for logging framework"
84 "flush the output, currently not implemented but needed for logging framework"
85 },
85 },
86 {NULL, NULL, 0 , NULL} /* sentinel */
86 {NULL, NULL, 0 , NULL} /* sentinel */
87 };
87 };
88
88
89 static PyMemberDef PythonQtStdOutRedirect_members[] = {
89 static PyMemberDef PythonQtStdOutRedirect_members[] = {
90 {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
90 {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
91 "soft space flag"
91 "soft space flag"
92 },
92 },
93 {NULL} /* Sentinel */
93 {NULL} /* Sentinel */
94 };
94 };
95
95
96 PyTypeObject PythonQtStdOutRedirectType = {
96 PyTypeObject PythonQtStdOutRedirectType = {
97 PyObject_HEAD_INIT(NULL)
97 PyObject_HEAD_INIT(NULL)
98 0, /*ob_size*/
98 0, /*ob_size*/
99 "PythonQtStdOutRedirect", /*tp_name*/
99 "PythonQtStdOutRedirect", /*tp_name*/
100 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
100 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
101 0, /*tp_itemsize*/
101 0, /*tp_itemsize*/
102 0, /*tp_dealloc*/
102 0, /*tp_dealloc*/
103 0, /*tp_print*/
103 0, /*tp_print*/
104 0, /*tp_getattr*/
104 0, /*tp_getattr*/
105 0, /*tp_setattr*/
105 0, /*tp_setattr*/
106 0, /*tp_compare*/
106 0, /*tp_compare*/
107 0, /*tp_repr*/
107 0, /*tp_repr*/
108 0, /*tp_as_number*/
108 0, /*tp_as_number*/
109 0, /*tp_as_sequence*/
109 0, /*tp_as_sequence*/
110 0, /*tp_as_mapping*/
110 0, /*tp_as_mapping*/
111 0, /*tp_hash */
111 0, /*tp_hash */
112 0, /*tp_call*/
112 0, /*tp_call*/
113 0, /*tp_str*/
113 0, /*tp_str*/
114 0, /*tp_getattro*/
114 0, /*tp_getattro*/
115 0, /*tp_setattro*/
115 0, /*tp_setattro*/
116 0, /*tp_as_buffer*/
116 0, /*tp_as_buffer*/
117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
118 "PythonQtStdOutRedirect", /* tp_doc */
118 "PythonQtStdOutRedirect", /* tp_doc */
119 0, /* tp_traverse */
119 0, /* tp_traverse */
120 0, /* tp_clear */
120 0, /* tp_clear */
121 0, /* tp_richcompare */
121 0, /* tp_richcompare */
122 0, /* tp_weaklistoffset */
122 0, /* tp_weaklistoffset */
123 0, /* tp_iter */
123 0, /* tp_iter */
124 0, /* tp_iternext */
124 0, /* tp_iternext */
125 PythonQtStdOutRedirect_methods, /* tp_methods */
125 PythonQtStdOutRedirect_methods, /* tp_methods */
126 PythonQtStdOutRedirect_members, /* tp_members */
126 PythonQtStdOutRedirect_members, /* tp_members */
127 0, /* tp_getset */
127 0, /* tp_getset */
128 0, /* tp_base */
128 0, /* tp_base */
129 0, /* tp_dict */
129 0, /* tp_dict */
130 0, /* tp_descr_get */
130 0, /* tp_descr_get */
131 0, /* tp_descr_set */
131 0, /* tp_descr_set */
132 0, /* tp_dictoffset */
132 0, /* tp_dictoffset */
133 0, /* tp_init */
133 0, /* tp_init */
134 0, /* tp_alloc */
134 0, /* tp_alloc */
135 PythonQtStdOutRedirect_new, /* tp_new */
135 PythonQtStdOutRedirect_new, /* tp_new */
136 };
136 };
@@ -1,63 +1,63
1 #ifndef _PYTHONQTSTDOUT_H
1 #ifndef _PYTHONQTSTDOUT_H
2 #define _PYTHONQTSTDOUT_H
2 #define _PYTHONQTSTDOUT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtStdOut.h
38 // \file PythonQtStdOut.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45
45
46 #include <Python.h>
46 #include <Python.h>
47 #include "structmember.h"
47 #include "structmember.h"
48 #include <QString>
48 #include <QString>
49
49
50 //! declares the type of the stdout redirection class
50 //! declares the type of the stdout redirection class
51 extern PyTypeObject PythonQtStdOutRedirectType;
51 extern PyTypeObject PythonQtStdOutRedirectType;
52
52
53 //! declares the callback that is called from the write() function
53 //! declares the callback that is called from the write() function
54 typedef void PythonQtOutputChangedCB(const QString& str);
54 typedef void PythonQtOutputChangedCB(const QString& str);
55
55
56 //! declares the stdout redirection class
56 //! declares the stdout redirection class
57 typedef struct {
57 typedef struct {
58 PyObject_HEAD
58 PyObject_HEAD
59 PythonQtOutputChangedCB* _cb;
59 PythonQtOutputChangedCB* _cb;
60 int softspace;
60 int softspace;
61 } PythonQtStdOutRedirect;
61 } PythonQtStdOutRedirect;
62
62
63 #endif
63 #endif
@@ -1,56 +1,56
1 #ifndef _PYTHONQTSYSTEM_
1 #ifndef _PYTHONQTSYSTEM_
2 #define _PYTHONQTSYSTEM_
2 #define _PYTHONQTSYSTEM_
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtSystem.h
38 // \file PythonQtSystem.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #ifdef WIN32
45 #ifdef WIN32
46 #ifdef PYTHONQT_EXPORTS
46 #ifdef PYTHONQT_EXPORTS
47 #define PYTHONQT_EXPORT __declspec(dllexport)
47 #define PYTHONQT_EXPORT __declspec(dllexport)
48 #else
48 #else
49 #define PYTHONQT_EXPORT __declspec(dllimport)
49 #define PYTHONQT_EXPORT __declspec(dllimport)
50 #endif
50 #endif
51 #else
51 #else
52 #define PYTHONQT_EXPORT
52 #define PYTHONQT_EXPORT
53 #endif
53 #endif
54
54
55 #endif
55 #endif
56
56
@@ -1,78 +1,78
1 #ifndef _PYTHONQTVARIANTS_
1 #ifndef _PYTHONQTVARIANTS_
2 #define _PYTHONQTVARIANTS_
2 #define _PYTHONQTVARIANTS_
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtVariants.h
38 // \file PythonQtVariants.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: stk $
40 // \author Last changed by $Author: stk $
41 // \date 2006-08
41 // \date 2006-08
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <QBitArray>
45 #include <QBitArray>
46 #include <QDate>
46 #include <QDate>
47 #include <QTime>
47 #include <QTime>
48 #include <QDateTime>
48 #include <QDateTime>
49 #include <QUrl>
49 #include <QUrl>
50 #include <QLocale>
50 #include <QLocale>
51 #include <QRect>
51 #include <QRect>
52 #include <QRectF>
52 #include <QRectF>
53 #include <QLine>
53 #include <QLine>
54 #include <QLineF>
54 #include <QLineF>
55 #include <QPoint>
55 #include <QPoint>
56 #include <QPointF>
56 #include <QPointF>
57 #include <QRegExp>
57 #include <QRegExp>
58
58
59 #include <QFont>
59 #include <QFont>
60 #include <QBitmap>
60 #include <QBitmap>
61 #include <QBrush>
61 #include <QBrush>
62 #include <QColor>
62 #include <QColor>
63 #include <QPalette>
63 #include <QPalette>
64 #include <QIcon>
64 #include <QIcon>
65 #include <QImage>
65 #include <QImage>
66 #include <QPolygon>
66 #include <QPolygon>
67 #include <QRegion>
67 #include <QRegion>
68 #include <QBitmap>
68 #include <QBitmap>
69 #include <QCursor>
69 #include <QCursor>
70 #include <QSizePolicy>
70 #include <QSizePolicy>
71 #include <QKeySequence>
71 #include <QKeySequence>
72 #include <QPen>
72 #include <QPen>
73 #include <QTextLength>
73 #include <QTextLength>
74 #include <QTextFormat>
74 #include <QTextFormat>
75 #include <QMatrix>
75 #include <QMatrix>
76
76
77 #endif
77 #endif
78
78
@@ -1,575 +1,575
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtScriptingConsole.cpp
35 // \file PythonQtScriptingConsole.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-10
38 // \date 2006-10
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtScriptingConsole.h"
42 #include "PythonQtScriptingConsole.h"
43
43
44 #include <QMenu>
44 #include <QMenu>
45 #include <QMouseEvent>
45 #include <QMouseEvent>
46 #include <QKeyEvent>
46 #include <QKeyEvent>
47 #include <QApplication>
47 #include <QApplication>
48 #include <QTextDocumentFragment>
48 #include <QTextDocumentFragment>
49 #include <QTextBlock>
49 #include <QTextBlock>
50 #include <QTextCursor>
50 #include <QTextCursor>
51 #include <QDebug>
51 #include <QDebug>
52 #include <QCompleter>
52 #include <QCompleter>
53 #include <QStringListModel>
53 #include <QStringListModel>
54 #include <QScrollBar>
54 #include <QScrollBar>
55
55
56 //-----------------------------------------------------------------------------
56 //-----------------------------------------------------------------------------
57
57
58 PythonQtScriptingConsole::PythonQtScriptingConsole(QWidget* parent, const PythonQtObjectPtr& context, Qt::WindowFlags windowFlags)
58 PythonQtScriptingConsole::PythonQtScriptingConsole(QWidget* parent, const PythonQtObjectPtr& context, Qt::WindowFlags windowFlags)
59 : QTextEdit(parent) {
59 : QTextEdit(parent) {
60
60
61 setWindowFlags(windowFlags);
61 setWindowFlags(windowFlags);
62
62
63 _defaultTextCharacterFormat = currentCharFormat();
63 _defaultTextCharacterFormat = currentCharFormat();
64 _context = context;
64 _context = context;
65 _historyPosition = 0;
65 _historyPosition = 0;
66 _hadError = false;
66 _hadError = false;
67
67
68 _completer = new QCompleter(this);
68 _completer = new QCompleter(this);
69 _completer->setWidget(this);
69 _completer->setWidget(this);
70 QObject::connect(_completer, SIGNAL(activated(const QString&)),
70 QObject::connect(_completer, SIGNAL(activated(const QString&)),
71 this, SLOT(insertCompletion(const QString&)));
71 this, SLOT(insertCompletion(const QString&)));
72
72
73 clear();
73 clear();
74
74
75 connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)), this, SLOT(stdOut(const QString&)));
75 connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)), this, SLOT(stdOut(const QString&)));
76 connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)), this, SLOT(stdErr(const QString&)));
76 connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)), this, SLOT(stdErr(const QString&)));
77 }
77 }
78
78
79 //-----------------------------------------------------------------------------
79 //-----------------------------------------------------------------------------
80
80
81 void PythonQtScriptingConsole::stdOut(const QString& s)
81 void PythonQtScriptingConsole::stdOut(const QString& s)
82 {
82 {
83 _stdOut += s;
83 _stdOut += s;
84 int idx;
84 int idx;
85 while ((idx = _stdOut.indexOf('\n'))!=-1) {
85 while ((idx = _stdOut.indexOf('\n'))!=-1) {
86 consoleMessage(_stdOut.left(idx));
86 consoleMessage(_stdOut.left(idx));
87 std::cout << _stdOut.left(idx).toLatin1().data() << std::endl;
87 std::cout << _stdOut.left(idx).toLatin1().data() << std::endl;
88 _stdOut = _stdOut.mid(idx+1);
88 _stdOut = _stdOut.mid(idx+1);
89 }
89 }
90 }
90 }
91
91
92 void PythonQtScriptingConsole::stdErr(const QString& s)
92 void PythonQtScriptingConsole::stdErr(const QString& s)
93 {
93 {
94 _hadError = true;
94 _hadError = true;
95 _stdErr += s;
95 _stdErr += s;
96 int idx;
96 int idx;
97 while ((idx = _stdErr.indexOf('\n'))!=-1) {
97 while ((idx = _stdErr.indexOf('\n'))!=-1) {
98 consoleMessage(_stdErr.left(idx));
98 consoleMessage(_stdErr.left(idx));
99 std::cerr << _stdErr.left(idx).toLatin1().data() << std::endl;
99 std::cerr << _stdErr.left(idx).toLatin1().data() << std::endl;
100 _stdErr = _stdErr.mid(idx+1);
100 _stdErr = _stdErr.mid(idx+1);
101 }
101 }
102 }
102 }
103
103
104 void PythonQtScriptingConsole::flushStdOut()
104 void PythonQtScriptingConsole::flushStdOut()
105 {
105 {
106 if (!_stdOut.isEmpty()) {
106 if (!_stdOut.isEmpty()) {
107 stdOut("\n");
107 stdOut("\n");
108 }
108 }
109 if (!_stdErr.isEmpty()) {
109 if (!_stdErr.isEmpty()) {
110 stdErr("\n");
110 stdErr("\n");
111 }
111 }
112 }
112 }
113
113
114 //-----------------------------------------------------------------------------
114 //-----------------------------------------------------------------------------
115
115
116 PythonQtScriptingConsole::~PythonQtScriptingConsole() {
116 PythonQtScriptingConsole::~PythonQtScriptingConsole() {
117 }
117 }
118
118
119
119
120
120
121 //-----------------------------------------------------------------------------
121 //-----------------------------------------------------------------------------
122
122
123 void PythonQtScriptingConsole::clear() {
123 void PythonQtScriptingConsole::clear() {
124
124
125 QTextEdit::clear();
125 QTextEdit::clear();
126 appendCommandPrompt();
126 appendCommandPrompt();
127 }
127 }
128
128
129 //-----------------------------------------------------------------------------
129 //-----------------------------------------------------------------------------
130
130
131 void PythonQtScriptingConsole::executeLine(bool storeOnly)
131 void PythonQtScriptingConsole::executeLine(bool storeOnly)
132 {
132 {
133 QTextCursor textCursor = this->textCursor();
133 QTextCursor textCursor = this->textCursor();
134 textCursor.movePosition(QTextCursor::End);
134 textCursor.movePosition(QTextCursor::End);
135
135
136 // Select the text from the command prompt until the end of the block
136 // Select the text from the command prompt until the end of the block
137 // and get the selected text.
137 // and get the selected text.
138 textCursor.setPosition(commandPromptPosition());
138 textCursor.setPosition(commandPromptPosition());
139 textCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
139 textCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
140 QString code = textCursor.selectedText();
140 QString code = textCursor.selectedText();
141
141
142 // i don't know where this trailing space is coming from, blast it!
142 // i don't know where this trailing space is coming from, blast it!
143 if (code.endsWith(" ")) {
143 if (code.endsWith(" ")) {
144 code.truncate(code.length()-1);
144 code.truncate(code.length()-1);
145 }
145 }
146
146
147 if (!code.isEmpty()) {
147 if (!code.isEmpty()) {
148 // Update the history
148 // Update the history
149 _history << code;
149 _history << code;
150 _historyPosition = _history.count();
150 _historyPosition = _history.count();
151 _currentMultiLineCode += code + "\n";
151 _currentMultiLineCode += code + "\n";
152
152
153 if (!storeOnly) {
153 if (!storeOnly) {
154 executeCode(_currentMultiLineCode);
154 executeCode(_currentMultiLineCode);
155 _currentMultiLineCode = "";
155 _currentMultiLineCode = "";
156 }
156 }
157 }
157 }
158 // Insert a new command prompt
158 // Insert a new command prompt
159 appendCommandPrompt(storeOnly);
159 appendCommandPrompt(storeOnly);
160
160
161 }
161 }
162
162
163 void PythonQtScriptingConsole::executeCode(const QString& code)
163 void PythonQtScriptingConsole::executeCode(const QString& code)
164 {
164 {
165 // put visible cursor to the end of the line
165 // put visible cursor to the end of the line
166 QTextCursor cursor = QTextEdit::textCursor();
166 QTextCursor cursor = QTextEdit::textCursor();
167 cursor.movePosition(QTextCursor::End);
167 cursor.movePosition(QTextCursor::End);
168 setTextCursor(cursor);
168 setTextCursor(cursor);
169
169
170 int cursorPosition = this->textCursor().position();
170 int cursorPosition = this->textCursor().position();
171
171
172 // evaluate the code
172 // evaluate the code
173 _stdOut = "";
173 _stdOut = "";
174 _stdErr = "";
174 _stdErr = "";
175 PythonQtObjectPtr p;
175 PythonQtObjectPtr p;
176 PyObject* dict = NULL;
176 PyObject* dict = NULL;
177 if (PyModule_Check(_context)) {
177 if (PyModule_Check(_context)) {
178 dict = PyModule_GetDict(_context);
178 dict = PyModule_GetDict(_context);
179 } else if (PyDict_Check(_context)) {
179 } else if (PyDict_Check(_context)) {
180 dict = _context;
180 dict = _context;
181 }
181 }
182 if (dict) {
182 if (dict) {
183 p.setNewRef(PyRun_String(code.toLatin1().data(), Py_single_input, dict, dict));
183 p.setNewRef(PyRun_String(code.toLatin1().data(), Py_single_input, dict, dict));
184 }
184 }
185
185
186 if (!p) {
186 if (!p) {
187 PythonQt::self()->handleError();
187 PythonQt::self()->handleError();
188 }
188 }
189
189
190 flushStdOut();
190 flushStdOut();
191
191
192 bool messageInserted = (this->textCursor().position() != cursorPosition);
192 bool messageInserted = (this->textCursor().position() != cursorPosition);
193
193
194 // If a message was inserted, then put another empty line before the command prompt
194 // If a message was inserted, then put another empty line before the command prompt
195 // to improve readability.
195 // to improve readability.
196 if (messageInserted) {
196 if (messageInserted) {
197 append(QString());
197 append(QString());
198 }
198 }
199 }
199 }
200
200
201
201
202 //-----------------------------------------------------------------------------
202 //-----------------------------------------------------------------------------
203
203
204 void PythonQtScriptingConsole::appendCommandPrompt(bool storeOnly) {
204 void PythonQtScriptingConsole::appendCommandPrompt(bool storeOnly) {
205 if (storeOnly) {
205 if (storeOnly) {
206 _commandPrompt = "...> ";
206 _commandPrompt = "...> ";
207 } else {
207 } else {
208 _commandPrompt = "py> ";
208 _commandPrompt = "py> ";
209 }
209 }
210 append(_commandPrompt);
210 append(_commandPrompt);
211
211
212 QTextCursor cursor = textCursor();
212 QTextCursor cursor = textCursor();
213 cursor.movePosition(QTextCursor::End);
213 cursor.movePosition(QTextCursor::End);
214 setTextCursor(cursor);
214 setTextCursor(cursor);
215 }
215 }
216
216
217
217
218
218
219 //-----------------------------------------------------------------------------
219 //-----------------------------------------------------------------------------
220
220
221 void PythonQtScriptingConsole::setCurrentFont(const QColor& color, bool bold) {
221 void PythonQtScriptingConsole::setCurrentFont(const QColor& color, bool bold) {
222
222
223 QTextCharFormat charFormat(_defaultTextCharacterFormat);
223 QTextCharFormat charFormat(_defaultTextCharacterFormat);
224
224
225 QFont font(charFormat.font());
225 QFont font(charFormat.font());
226 font.setBold(bold);
226 font.setBold(bold);
227 charFormat.setFont(font);
227 charFormat.setFont(font);
228
228
229 QBrush brush(charFormat.foreground());
229 QBrush brush(charFormat.foreground());
230 brush.setColor(color);
230 brush.setColor(color);
231 charFormat.setForeground(brush);
231 charFormat.setForeground(brush);
232
232
233 setCurrentCharFormat(charFormat);
233 setCurrentCharFormat(charFormat);
234 }
234 }
235
235
236
236
237
237
238 //-----------------------------------------------------------------------------
238 //-----------------------------------------------------------------------------
239
239
240 int PythonQtScriptingConsole::commandPromptPosition() {
240 int PythonQtScriptingConsole::commandPromptPosition() {
241
241
242 QTextCursor textCursor(this->textCursor());
242 QTextCursor textCursor(this->textCursor());
243 textCursor.movePosition(QTextCursor::End);
243 textCursor.movePosition(QTextCursor::End);
244
244
245 return textCursor.block().position() + _commandPrompt.length();
245 return textCursor.block().position() + _commandPrompt.length();
246 }
246 }
247
247
248
248
249
249
250 //-----------------------------------------------------------------------------
250 //-----------------------------------------------------------------------------
251
251
252 void PythonQtScriptingConsole::insertCompletion(const QString& completion)
252 void PythonQtScriptingConsole::insertCompletion(const QString& completion)
253 {
253 {
254 QTextCursor tc = textCursor();
254 QTextCursor tc = textCursor();
255 tc.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
255 tc.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
256 if (tc.selectedText()==".") {
256 if (tc.selectedText()==".") {
257 tc.insertText(QString(".") + completion);
257 tc.insertText(QString(".") + completion);
258 } else {
258 } else {
259 tc = textCursor();
259 tc = textCursor();
260 tc.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
260 tc.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
261 tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
261 tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
262 tc.insertText(completion);
262 tc.insertText(completion);
263 setTextCursor(tc);
263 setTextCursor(tc);
264 }
264 }
265 }
265 }
266
266
267 //-----------------------------------------------------------------------------
267 //-----------------------------------------------------------------------------
268 void PythonQtScriptingConsole::handleTabCompletion()
268 void PythonQtScriptingConsole::handleTabCompletion()
269 {
269 {
270 QTextCursor textCursor = this->textCursor();
270 QTextCursor textCursor = this->textCursor();
271 int pos = textCursor.position();
271 int pos = textCursor.position();
272 textCursor.setPosition(commandPromptPosition());
272 textCursor.setPosition(commandPromptPosition());
273 textCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
273 textCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
274 int startPos = textCursor.selectionStart();
274 int startPos = textCursor.selectionStart();
275
275
276 int offset = pos-startPos;
276 int offset = pos-startPos;
277 QString text = textCursor.selectedText();
277 QString text = textCursor.selectedText();
278
278
279 QString textToComplete;
279 QString textToComplete;
280 int cur = offset;
280 int cur = offset;
281 while (cur--) {
281 while (cur--) {
282 QChar c = text.at(cur);
282 QChar c = text.at(cur);
283 if (c.isLetterOrNumber() || c == '.' || c == '_') {
283 if (c.isLetterOrNumber() || c == '.' || c == '_') {
284 textToComplete.prepend(c);
284 textToComplete.prepend(c);
285 } else {
285 } else {
286 break;
286 break;
287 }
287 }
288 }
288 }
289
289
290
290
291 QString lookup;
291 QString lookup;
292 QString compareText = textToComplete;
292 QString compareText = textToComplete;
293 int dot = compareText.lastIndexOf('.');
293 int dot = compareText.lastIndexOf('.');
294 if (dot!=-1) {
294 if (dot!=-1) {
295 lookup = compareText.mid(0, dot);
295 lookup = compareText.mid(0, dot);
296 compareText = compareText.mid(dot+1, offset);
296 compareText = compareText.mid(dot+1, offset);
297 }
297 }
298 if (!lookup.isEmpty() || !compareText.isEmpty()) {
298 if (!lookup.isEmpty() || !compareText.isEmpty()) {
299 compareText = compareText.toLower();
299 compareText = compareText.toLower();
300 QStringList found;
300 QStringList found;
301 QStringList l = PythonQt::self()->introspection(_context, lookup, PythonQt::Anything);
301 QStringList l = PythonQt::self()->introspection(_context, lookup, PythonQt::Anything);
302 foreach (QString n, l) {
302 foreach (QString n, l) {
303 if (n.toLower().startsWith(compareText)) {
303 if (n.toLower().startsWith(compareText)) {
304 found << n;
304 found << n;
305 }
305 }
306 }
306 }
307
307
308 if (!found.isEmpty()) {
308 if (!found.isEmpty()) {
309 _completer->setCompletionPrefix(compareText);
309 _completer->setCompletionPrefix(compareText);
310 _completer->setCompletionMode(QCompleter::PopupCompletion);
310 _completer->setCompletionMode(QCompleter::PopupCompletion);
311 _completer->setModel(new QStringListModel(found, _completer));
311 _completer->setModel(new QStringListModel(found, _completer));
312 _completer->setCaseSensitivity(Qt::CaseInsensitive);
312 _completer->setCaseSensitivity(Qt::CaseInsensitive);
313 QTextCursor c = this->textCursor();
313 QTextCursor c = this->textCursor();
314 c.movePosition(QTextCursor::StartOfWord);
314 c.movePosition(QTextCursor::StartOfWord);
315 QRect cr = cursorRect(c);
315 QRect cr = cursorRect(c);
316 cr.setWidth(_completer->popup()->sizeHintForColumn(0)
316 cr.setWidth(_completer->popup()->sizeHintForColumn(0)
317 + _completer->popup()->verticalScrollBar()->sizeHint().width());
317 + _completer->popup()->verticalScrollBar()->sizeHint().width());
318 cr.translate(0,8);
318 cr.translate(0,8);
319 _completer->complete(cr);
319 _completer->complete(cr);
320 } else {
320 } else {
321 _completer->popup()->hide();
321 _completer->popup()->hide();
322 }
322 }
323 } else {
323 } else {
324 _completer->popup()->hide();
324 _completer->popup()->hide();
325 }
325 }
326 }
326 }
327
327
328 void PythonQtScriptingConsole::keyPressEvent(QKeyEvent* event) {
328 void PythonQtScriptingConsole::keyPressEvent(QKeyEvent* event) {
329
329
330 if (_completer && _completer->popup()->isVisible()) {
330 if (_completer && _completer->popup()->isVisible()) {
331 // The following keys are forwarded by the completer to the widget
331 // The following keys are forwarded by the completer to the widget
332 switch (event->key()) {
332 switch (event->key()) {
333 case Qt::Key_Return:
333 case Qt::Key_Return:
334 if (!_completer->popup()->currentIndex().isValid()) {
334 if (!_completer->popup()->currentIndex().isValid()) {
335 insertCompletion(_completer->currentCompletion());
335 insertCompletion(_completer->currentCompletion());
336 _completer->popup()->hide();
336 _completer->popup()->hide();
337 event->accept();
337 event->accept();
338 }
338 }
339 event->ignore();
339 event->ignore();
340 return;
340 return;
341 break;
341 break;
342 case Qt::Key_Enter:
342 case Qt::Key_Enter:
343 case Qt::Key_Escape:
343 case Qt::Key_Escape:
344 case Qt::Key_Tab:
344 case Qt::Key_Tab:
345 case Qt::Key_Backtab:
345 case Qt::Key_Backtab:
346
346
347 event->ignore();
347 event->ignore();
348 return; // let the completer do default behavior
348 return; // let the completer do default behavior
349 default:
349 default:
350 break;
350 break;
351 }
351 }
352 }
352 }
353 bool eventHandled = false;
353 bool eventHandled = false;
354 QTextCursor textCursor = this->textCursor();
354 QTextCursor textCursor = this->textCursor();
355
355
356 int key = event->key();
356 int key = event->key();
357 switch (key) {
357 switch (key) {
358
358
359 case Qt::Key_Left:
359 case Qt::Key_Left:
360
360
361 // Moving the cursor left is limited to the position
361 // Moving the cursor left is limited to the position
362 // of the command prompt.
362 // of the command prompt.
363
363
364 if (textCursor.position() <= commandPromptPosition()) {
364 if (textCursor.position() <= commandPromptPosition()) {
365
365
366 QApplication::beep();
366 QApplication::beep();
367 eventHandled = true;
367 eventHandled = true;
368 }
368 }
369 break;
369 break;
370
370
371 case Qt::Key_Up:
371 case Qt::Key_Up:
372
372
373 // Display the previous command in the history
373 // Display the previous command in the history
374 if (_historyPosition>0) {
374 if (_historyPosition>0) {
375 _historyPosition--;
375 _historyPosition--;
376 changeHistory();
376 changeHistory();
377 }
377 }
378
378
379 eventHandled = true;
379 eventHandled = true;
380 break;
380 break;
381
381
382 case Qt::Key_Down:
382 case Qt::Key_Down:
383
383
384 // Display the next command in the history
384 // Display the next command in the history
385 if (_historyPosition+1<_history.count()) {
385 if (_historyPosition+1<_history.count()) {
386 _historyPosition++;
386 _historyPosition++;
387 changeHistory();
387 changeHistory();
388 }
388 }
389
389
390 eventHandled = true;
390 eventHandled = true;
391 break;
391 break;
392
392
393 case Qt::Key_Return:
393 case Qt::Key_Return:
394
394
395 executeLine(event->modifiers() & Qt::ShiftModifier);
395 executeLine(event->modifiers() & Qt::ShiftModifier);
396 eventHandled = true;
396 eventHandled = true;
397 break;
397 break;
398
398
399 case Qt::Key_Backspace:
399 case Qt::Key_Backspace:
400
400
401 if (textCursor.hasSelection()) {
401 if (textCursor.hasSelection()) {
402
402
403 cut();
403 cut();
404 eventHandled = true;
404 eventHandled = true;
405
405
406 } else {
406 } else {
407
407
408 // Intercept backspace key event to check if
408 // Intercept backspace key event to check if
409 // deleting a character is allowed. It is not
409 // deleting a character is allowed. It is not
410 // allowed, if the user wants to delete the
410 // allowed, if the user wants to delete the
411 // command prompt.
411 // command prompt.
412
412
413 if (textCursor.position() <= commandPromptPosition()) {
413 if (textCursor.position() <= commandPromptPosition()) {
414
414
415 QApplication::beep();
415 QApplication::beep();
416 eventHandled = true;
416 eventHandled = true;
417 }
417 }
418 }
418 }
419 break;
419 break;
420
420
421 case Qt::Key_Delete:
421 case Qt::Key_Delete:
422
422
423 cut();
423 cut();
424 eventHandled = true;
424 eventHandled = true;
425 break;
425 break;
426
426
427 default:
427 default:
428
428
429 if (key >= Qt::Key_Space && key <= Qt::Key_division) {
429 if (key >= Qt::Key_Space && key <= Qt::Key_division) {
430
430
431 if (textCursor.hasSelection() && !verifySelectionBeforeDeletion()) {
431 if (textCursor.hasSelection() && !verifySelectionBeforeDeletion()) {
432
432
433 // The selection must not be deleted.
433 // The selection must not be deleted.
434 eventHandled = true;
434 eventHandled = true;
435
435
436 } else {
436 } else {
437
437
438 // The key is an input character, check if the cursor is
438 // The key is an input character, check if the cursor is
439 // behind the last command prompt, else inserting the
439 // behind the last command prompt, else inserting the
440 // character is not allowed.
440 // character is not allowed.
441
441
442 int commandPromptPosition = this->commandPromptPosition();
442 int commandPromptPosition = this->commandPromptPosition();
443 if (textCursor.position() < commandPromptPosition) {
443 if (textCursor.position() < commandPromptPosition) {
444
444
445 textCursor.setPosition(commandPromptPosition);
445 textCursor.setPosition(commandPromptPosition);
446 setTextCursor(textCursor);
446 setTextCursor(textCursor);
447 }
447 }
448 }
448 }
449 }
449 }
450 }
450 }
451
451
452 if (eventHandled) {
452 if (eventHandled) {
453
453
454 _completer->popup()->hide();
454 _completer->popup()->hide();
455 event->accept();
455 event->accept();
456
456
457 } else {
457 } else {
458
458
459 QTextEdit::keyPressEvent(event);
459 QTextEdit::keyPressEvent(event);
460 QString text = event->text();
460 QString text = event->text();
461 if (!text.isEmpty()) {
461 if (!text.isEmpty()) {
462 handleTabCompletion();
462 handleTabCompletion();
463 } else {
463 } else {
464 _completer->popup()->hide();
464 _completer->popup()->hide();
465 }
465 }
466 eventHandled = true;
466 eventHandled = true;
467 }
467 }
468 }
468 }
469
469
470
470
471
471
472 //-----------------------------------------------------------------------------
472 //-----------------------------------------------------------------------------
473
473
474 void PythonQtScriptingConsole::cut() {
474 void PythonQtScriptingConsole::cut() {
475
475
476 bool deletionAllowed = verifySelectionBeforeDeletion();
476 bool deletionAllowed = verifySelectionBeforeDeletion();
477 if (deletionAllowed) {
477 if (deletionAllowed) {
478 QTextEdit::cut();
478 QTextEdit::cut();
479 }
479 }
480 }
480 }
481
481
482
482
483
483
484 //-----------------------------------------------------------------------------
484 //-----------------------------------------------------------------------------
485
485
486 bool PythonQtScriptingConsole::verifySelectionBeforeDeletion() {
486 bool PythonQtScriptingConsole::verifySelectionBeforeDeletion() {
487
487
488 bool deletionAllowed = true;
488 bool deletionAllowed = true;
489
489
490
490
491 QTextCursor textCursor = this->textCursor();
491 QTextCursor textCursor = this->textCursor();
492
492
493 int commandPromptPosition = this->commandPromptPosition();
493 int commandPromptPosition = this->commandPromptPosition();
494 int selectionStart = textCursor.selectionStart();
494 int selectionStart = textCursor.selectionStart();
495 int selectionEnd = textCursor.selectionEnd();
495 int selectionEnd = textCursor.selectionEnd();
496
496
497 if (textCursor.hasSelection()) {
497 if (textCursor.hasSelection()) {
498
498
499 // Selected text may only be deleted after the last command prompt.
499 // Selected text may only be deleted after the last command prompt.
500 // If the selection is partly after the command prompt set the selection
500 // If the selection is partly after the command prompt set the selection
501 // to the part and deletion is allowed. If the selection occurs before the
501 // to the part and deletion is allowed. If the selection occurs before the
502 // last command prompt, then deletion is not allowed.
502 // last command prompt, then deletion is not allowed.
503
503
504 if (selectionStart < commandPromptPosition ||
504 if (selectionStart < commandPromptPosition ||
505 selectionEnd < commandPromptPosition) {
505 selectionEnd < commandPromptPosition) {
506
506
507 // Assure selectionEnd is bigger than selection start
507 // Assure selectionEnd is bigger than selection start
508 if (selectionStart > selectionEnd) {
508 if (selectionStart > selectionEnd) {
509 int tmp = selectionEnd;
509 int tmp = selectionEnd;
510 selectionEnd = selectionStart;
510 selectionEnd = selectionStart;
511 selectionStart = tmp;
511 selectionStart = tmp;
512 }
512 }
513
513
514 if (selectionEnd < commandPromptPosition) {
514 if (selectionEnd < commandPromptPosition) {
515
515
516 // Selection is completely before command prompt,
516 // Selection is completely before command prompt,
517 // so deletion is not allowed.
517 // so deletion is not allowed.
518 QApplication::beep();
518 QApplication::beep();
519 deletionAllowed = false;
519 deletionAllowed = false;
520
520
521 } else {
521 } else {
522
522
523 // The selectionEnd is after the command prompt, so set
523 // The selectionEnd is after the command prompt, so set
524 // the selection start to the commandPromptPosition.
524 // the selection start to the commandPromptPosition.
525 selectionStart = commandPromptPosition;
525 selectionStart = commandPromptPosition;
526 textCursor.setPosition(selectionStart);
526 textCursor.setPosition(selectionStart);
527 textCursor.setPosition(selectionStart, QTextCursor::KeepAnchor);
527 textCursor.setPosition(selectionStart, QTextCursor::KeepAnchor);
528 setTextCursor(textCursor);
528 setTextCursor(textCursor);
529 }
529 }
530 }
530 }
531
531
532 } else { // if (hasSelectedText())
532 } else { // if (hasSelectedText())
533
533
534 // When there is no selected text, deletion is not allowed before the
534 // When there is no selected text, deletion is not allowed before the
535 // command prompt.
535 // command prompt.
536 if (textCursor.position() < commandPromptPosition) {
536 if (textCursor.position() < commandPromptPosition) {
537
537
538 QApplication::beep();
538 QApplication::beep();
539 deletionAllowed = false;
539 deletionAllowed = false;
540 }
540 }
541 }
541 }
542
542
543 return deletionAllowed;
543 return deletionAllowed;
544 }
544 }
545
545
546
546
547
547
548 //-----------------------------------------------------------------------------
548 //-----------------------------------------------------------------------------
549
549
550 void PythonQtScriptingConsole::changeHistory() {
550 void PythonQtScriptingConsole::changeHistory() {
551
551
552 // Select the text after the last command prompt ...
552 // Select the text after the last command prompt ...
553 QTextCursor textCursor = this->textCursor();
553 QTextCursor textCursor = this->textCursor();
554 textCursor.movePosition(QTextCursor::End);
554 textCursor.movePosition(QTextCursor::End);
555 textCursor.setPosition(commandPromptPosition(), QTextCursor::KeepAnchor);
555 textCursor.setPosition(commandPromptPosition(), QTextCursor::KeepAnchor);
556
556
557 // ... and replace it with the history text.
557 // ... and replace it with the history text.
558 textCursor.insertText(_history.value(_historyPosition));
558 textCursor.insertText(_history.value(_historyPosition));
559
559
560 textCursor.movePosition(QTextCursor::End);
560 textCursor.movePosition(QTextCursor::End);
561 setTextCursor(textCursor);
561 setTextCursor(textCursor);
562 }
562 }
563
563
564
564
565
565
566 //-----------------------------------------------------------------------------
566 //-----------------------------------------------------------------------------
567
567
568 void PythonQtScriptingConsole::consoleMessage(const QString & message) {
568 void PythonQtScriptingConsole::consoleMessage(const QString & message) {
569
569
570 append(QString());
570 append(QString());
571 insertPlainText(message);
571 insertPlainText(message);
572
572
573 // Reset all font modifications done by the html string
573 // Reset all font modifications done by the html string
574 setCurrentCharFormat(_defaultTextCharacterFormat);
574 setCurrentCharFormat(_defaultTextCharacterFormat);
575 }
575 }
@@ -1,149 +1,149
1 #ifndef _PythonQtScriptingConsole_H
1 #ifndef _PythonQtScriptingConsole_H
2 #define _PythonQtScriptingConsole_H
2 #define _PythonQtScriptingConsole_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtScriptingConsole.h
38 // \file PythonQtScriptingConsole.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-10
41 // \date 2006-10
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include <QVariant>
46 #include <QVariant>
47 #include <QTextEdit>
47 #include <QTextEdit>
48
48
49 class QCompleter;
49 class QCompleter;
50
50
51 //-------------------------------------------------------------------------------
51 //-------------------------------------------------------------------------------
52 //! A simple console for python scripting
52 //! A simple console for python scripting
53 class PYTHONQT_EXPORT PythonQtScriptingConsole : public QTextEdit
53 class PYTHONQT_EXPORT PythonQtScriptingConsole : public QTextEdit
54 {
54 {
55 Q_OBJECT
55 Q_OBJECT
56
56
57 public:
57 public:
58 PythonQtScriptingConsole(QWidget* parent, const PythonQtObjectPtr& context, Qt::WindowFlags i = 0);
58 PythonQtScriptingConsole(QWidget* parent, const PythonQtObjectPtr& context, Qt::WindowFlags i = 0);
59
59
60 ~PythonQtScriptingConsole();
60 ~PythonQtScriptingConsole();
61
61
62 public slots:
62 public slots:
63 //! execute current line
63 //! execute current line
64 void executeLine(bool storeOnly);
64 void executeLine(bool storeOnly);
65
65
66 //! derived key press event
66 //! derived key press event
67 void keyPressEvent (QKeyEvent * e);
67 void keyPressEvent (QKeyEvent * e);
68
68
69 //! output from console
69 //! output from console
70 void consoleMessage(const QString & message);
70 void consoleMessage(const QString & message);
71
71
72 //! get history
72 //! get history
73 QStringList history() { return _history; }
73 QStringList history() { return _history; }
74
74
75 //! set history
75 //! set history
76 void setHistory(const QStringList& h) { _history = h; _historyPosition = 0; }
76 void setHistory(const QStringList& h) { _history = h; _historyPosition = 0; }
77
77
78 //! clear the console
78 //! clear the console
79 void clear();
79 void clear();
80
80
81 //! overridden to control which characters a user may delete
81 //! overridden to control which characters a user may delete
82 virtual void cut();
82 virtual void cut();
83
83
84 //! output redirection
84 //! output redirection
85 void stdOut(const QString& s);
85 void stdOut(const QString& s);
86 //! output redirection
86 //! output redirection
87 void stdErr(const QString& s);
87 void stdErr(const QString& s);
88
88
89 void insertCompletion(const QString&);
89 void insertCompletion(const QString&);
90
90
91 //! Appends a newline and command prompt at the end of the document.
91 //! Appends a newline and command prompt at the end of the document.
92 void appendCommandPrompt(bool storeOnly = false);
92 void appendCommandPrompt(bool storeOnly = false);
93
93
94 public:
94 public:
95 //! returns true if python cerr had an error
95 //! returns true if python cerr had an error
96 bool hadError() { return _hadError; }
96 bool hadError() { return _hadError; }
97
97
98 //! returns true if python cerr had an error
98 //! returns true if python cerr had an error
99 void clearError() {
99 void clearError() {
100 _hadError = false;
100 _hadError = false;
101 }
101 }
102
102
103 protected:
103 protected:
104 //! handle the pressing of tab
104 //! handle the pressing of tab
105 void handleTabCompletion();
105 void handleTabCompletion();
106
106
107 //! Returns the position of the command prompt
107 //! Returns the position of the command prompt
108 int commandPromptPosition();
108 int commandPromptPosition();
109
109
110 //! Returns if deletion is allowed at the current cursor
110 //! Returns if deletion is allowed at the current cursor
111 //! (with and without selected text)
111 //! (with and without selected text)
112 bool verifySelectionBeforeDeletion();
112 bool verifySelectionBeforeDeletion();
113
113
114 //! Sets the current font
114 //! Sets the current font
115 void setCurrentFont(const QColor& color = QColor(0,0,0), bool bold = false);
115 void setCurrentFont(const QColor& color = QColor(0,0,0), bool bold = false);
116
116
117 //! change the history according to _historyPos
117 //! change the history according to _historyPos
118 void changeHistory();
118 void changeHistory();
119
119
120 //! flush output that was not yet printed
120 //! flush output that was not yet printed
121 void flushStdOut();
121 void flushStdOut();
122
122
123
123
124 private:
124 private:
125 void executeCode(const QString& code);
125 void executeCode(const QString& code);
126
126
127 PythonQtObjectPtr _context;
127 PythonQtObjectPtr _context;
128
128
129 QStringList _history;
129 QStringList _history;
130 int _historyPosition;
130 int _historyPosition;
131
131
132 QString _clickedAnchor;
132 QString _clickedAnchor;
133 QString _storageKey;
133 QString _storageKey;
134 QString _commandPrompt;
134 QString _commandPrompt;
135
135
136 QString _currentMultiLineCode;
136 QString _currentMultiLineCode;
137
137
138 QString _stdOut;
138 QString _stdOut;
139 QString _stdErr;
139 QString _stdErr;
140
140
141 QTextCharFormat _defaultTextCharacterFormat;
141 QTextCharFormat _defaultTextCharacterFormat;
142 QCompleter* _completer;
142 QCompleter* _completer;
143
143
144 bool _hadError;
144 bool _hadError;
145 };
145 };
146
146
147
147
148
148
149 #endif No newline at end of file
149 #endif
@@ -1,68 +1,68
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtTests.cpp
35 // \file PythonQtTests.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtTests.h"
43 #include "PythonQtTests.h"
44
44
45 int main( int argc, char **argv )
45 int main( int argc, char **argv )
46 {
46 {
47 QApplication qapp(argc, argv);
47 QApplication qapp(argc, argv);
48
48
49 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
49 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
50
50
51 int failCount = 0;
51 int failCount = 0;
52 PythonQtTestApi api;
52 PythonQtTestApi api;
53 failCount += QTest::qExec(&api, argc, argv);
53 failCount += QTest::qExec(&api, argc, argv);
54 PythonQtTestSignalHandler signalHandler;
54 PythonQtTestSignalHandler signalHandler;
55 failCount += QTest::qExec(&signalHandler, argc, argv);
55 failCount += QTest::qExec(&signalHandler, argc, argv);
56 PythonQtTestSlotCalling slotCalling;
56 PythonQtTestSlotCalling slotCalling;
57 failCount += QTest::qExec(&slotCalling, argc, argv);
57 failCount += QTest::qExec(&slotCalling, argc, argv);
58
58
59 PythonQt::cleanup();
59 PythonQt::cleanup();
60
60
61 if (failCount>0) {
61 if (failCount>0) {
62 std::cerr << "Tests failed: " << failCount << std::endl;
62 std::cerr << "Tests failed: " << failCount << std::endl;
63 } else {
63 } else {
64 std::cout << "All tests passed successfully." << std::endl;
64 std::cout << "All tests passed successfully." << std::endl;
65 }
65 }
66 return failCount;
66 return failCount;
67 }
67 }
68
68
@@ -1,585 +1,585
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtTests.cpp
35 // \file PythonQtTests.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtTests.h"
42 #include "PythonQtTests.h"
43
43
44 void PythonQtTestSlotCalling::initTestCase()
44 void PythonQtTestSlotCalling::initTestCase()
45 {
45 {
46 _helper = new PythonQtTestSlotCallingHelper(this);
46 _helper = new PythonQtTestSlotCallingHelper(this);
47 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
47 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
48 main.evalScript("import PythonQt");
48 main.evalScript("import PythonQt");
49 PythonQt::self()->addObject(main, "obj", _helper);
49 PythonQt::self()->addObject(main, "obj", _helper);
50 }
50 }
51
51
52 void PythonQtTestSlotCalling::init() {
52 void PythonQtTestSlotCalling::init() {
53
53
54 }
54 }
55
55
56
56
57 void* polymorphic_ClassB_Handler(const void* ptr, char** className) {
57 void* polymorphic_ClassB_Handler(const void* ptr, char** className) {
58 ClassB* o = (ClassB*)ptr;
58 ClassB* o = (ClassB*)ptr;
59 if (o->type()==2) {
59 if (o->type()==2) {
60 *className = "ClassB";
60 *className = "ClassB";
61 return (ClassB*)o;
61 return (ClassB*)o;
62 }
62 }
63 if (o->type()==3) {
63 if (o->type()==3) {
64 *className = "ClassC";
64 *className = "ClassC";
65 return (ClassC*)o;
65 return (ClassC*)o;
66 }
66 }
67 if (o->type()==4) {
67 if (o->type()==4) {
68 *className = "ClassD";
68 *className = "ClassD";
69 return (ClassD*)o;
69 return (ClassD*)o;
70 }
70 }
71 return NULL;
71 return NULL;
72 }
72 }
73
73
74 void PythonQtTestSlotCalling::testInheritance() {
74 void PythonQtTestSlotCalling::testInheritance() {
75 PythonQt::self()->registerCPPClass("ClassA",NULL,NULL, PythonQtCreateObject<ClassAWrapper>);
75 PythonQt::self()->registerCPPClass("ClassA",NULL,NULL, PythonQtCreateObject<ClassAWrapper>);
76 PythonQt::self()->registerCPPClass("ClassB",NULL,NULL, PythonQtCreateObject<ClassBWrapper>);
76 PythonQt::self()->registerCPPClass("ClassB",NULL,NULL, PythonQtCreateObject<ClassBWrapper>);
77 PythonQt::self()->registerCPPClass("ClassC",NULL,NULL, PythonQtCreateObject<ClassCWrapper>);
77 PythonQt::self()->registerCPPClass("ClassC",NULL,NULL, PythonQtCreateObject<ClassCWrapper>);
78 PythonQt::self()->addParentClass("ClassC", "ClassA", PythonQtUpcastingOffset<ClassC,ClassA>());
78 PythonQt::self()->addParentClass("ClassC", "ClassA", PythonQtUpcastingOffset<ClassC,ClassA>());
79 PythonQt::self()->addParentClass("ClassC", "ClassB", PythonQtUpcastingOffset<ClassC,ClassB>());
79 PythonQt::self()->addParentClass("ClassC", "ClassB", PythonQtUpcastingOffset<ClassC,ClassB>());
80 PythonQt::self()->registerClass(&ClassD::staticMetaObject, NULL, PythonQtCreateObject<ClassDWrapper>);
80 PythonQt::self()->registerClass(&ClassD::staticMetaObject, NULL, PythonQtCreateObject<ClassDWrapper>);
81 PythonQt::self()->addParentClass("ClassD", "ClassA", PythonQtUpcastingOffset<ClassD,ClassA>());
81 PythonQt::self()->addParentClass("ClassD", "ClassA", PythonQtUpcastingOffset<ClassD,ClassA>());
82 PythonQt::self()->addParentClass("ClassD", "ClassB", PythonQtUpcastingOffset<ClassD,ClassB>());
82 PythonQt::self()->addParentClass("ClassD", "ClassB", PythonQtUpcastingOffset<ClassD,ClassB>());
83
83
84 PythonQtObjectPtr classA = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassA");
84 PythonQtObjectPtr classA = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassA");
85 PythonQtObjectPtr classB = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassB");
85 PythonQtObjectPtr classB = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassB");
86 PythonQtObjectPtr classC = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassC");
86 PythonQtObjectPtr classC = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassC");
87 PythonQtObjectPtr classD = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassD");
87 PythonQtObjectPtr classD = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassD");
88 QVERIFY(classA);
88 QVERIFY(classA);
89 QVERIFY(classB);
89 QVERIFY(classB);
90 QVERIFY(classC);
90 QVERIFY(classC);
91 QVERIFY(classD);
91 QVERIFY(classD);
92
92
93 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
93 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
94 QEXPECT_FAIL("", "ClassB can not be converted to ClassA", Continue);
94 QEXPECT_FAIL("", "ClassB can not be converted to ClassA", Continue);
95 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
95 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
96 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
96 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
97 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
97 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
98
98
99 QEXPECT_FAIL("", "ClassA can not be converted to ClassB", Continue);
99 QEXPECT_FAIL("", "ClassA can not be converted to ClassB", Continue);
100 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
100 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
101 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
101 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
102 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
102 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
103 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
103 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
104
104
105 QEXPECT_FAIL("", "ClassA can not be converted to ClassC", Continue);
105 QEXPECT_FAIL("", "ClassA can not be converted to ClassC", Continue);
106 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
106 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
107 QEXPECT_FAIL("", "ClassB can not be converted to ClassC", Continue);
107 QEXPECT_FAIL("", "ClassB can not be converted to ClassC", Continue);
108 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
108 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
109 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
109 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
110 QEXPECT_FAIL("", "ClassD can not be converted to ClassC", Continue);
110 QEXPECT_FAIL("", "ClassD can not be converted to ClassC", Continue);
111 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
111 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
112
112
113 QVERIFY(_helper->runScript("if type(obj.createClassA())==PythonQt.private.ClassA: obj.setPassed();\n"));
113 QVERIFY(_helper->runScript("if type(obj.createClassA())==PythonQt.private.ClassA: obj.setPassed();\n"));
114 QVERIFY(_helper->runScript("if type(obj.createClassB())==PythonQt.private.ClassB: obj.setPassed();\n"));
114 QVERIFY(_helper->runScript("if type(obj.createClassB())==PythonQt.private.ClassB: obj.setPassed();\n"));
115 QVERIFY(_helper->runScript("if type(obj.createClassCAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
115 QVERIFY(_helper->runScript("if type(obj.createClassCAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
116 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
116 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
117 QVERIFY(_helper->runScript("if type(obj.createClassD())==PythonQt.private.ClassD: obj.setPassed();\n"));
117 QVERIFY(_helper->runScript("if type(obj.createClassD())==PythonQt.private.ClassD: obj.setPassed();\n"));
118 QVERIFY(_helper->runScript("if type(obj.createClassDAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
118 QVERIFY(_helper->runScript("if type(obj.createClassDAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
119 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
119 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
120
120
121 PythonQt::self()->addPolymorphicHandler("ClassB", polymorphic_ClassB_Handler);
121 PythonQt::self()->addPolymorphicHandler("ClassB", polymorphic_ClassB_Handler);
122
122
123 QVERIFY(_helper->runScript("if type(obj.getClassBPtr(obj.createClassB()))==PythonQt.private.ClassB: obj.setPassed();\n"));
123 QVERIFY(_helper->runScript("if type(obj.getClassBPtr(obj.createClassB()))==PythonQt.private.ClassB: obj.setPassed();\n"));
124 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassC: obj.setPassed();\n"));
124 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassC: obj.setPassed();\n"));
125 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassD: obj.setPassed();\n"));
125 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassD: obj.setPassed();\n"));
126
126
127 }
127 }
128
128
129 void PythonQtTestSlotCalling::testAutoConversion() {
129 void PythonQtTestSlotCalling::testAutoConversion() {
130 QVERIFY(_helper->runScript("if obj.setAutoConvertColor(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
130 QVERIFY(_helper->runScript("if obj.setAutoConvertColor(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
131 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
131 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
132 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
132 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
133 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
133 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
134 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
134 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
135 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor)).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
135 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor)).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
136 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
136 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
137 }
137 }
138
138
139 void PythonQtTestSlotCalling::testNoArgSlotCall()
139 void PythonQtTestSlotCalling::testNoArgSlotCall()
140 {
140 {
141 QVERIFY(_helper->runScript("obj.testNoArg(); obj.setPassed();\n"));
141 QVERIFY(_helper->runScript("obj.testNoArg(); obj.setPassed();\n"));
142 }
142 }
143
143
144 void PythonQtTestSlotCalling::testOverloadedCall()
144 void PythonQtTestSlotCalling::testOverloadedCall()
145 {
145 {
146 QVERIFY(_helper->runScript("obj.overload(False); obj.setPassed();\n", 0));
146 QVERIFY(_helper->runScript("obj.overload(False); obj.setPassed();\n", 0));
147 QVERIFY(_helper->runScript("obj.overload(True); obj.setPassed();\n", 0));
147 QVERIFY(_helper->runScript("obj.overload(True); obj.setPassed();\n", 0));
148 QVERIFY(_helper->runScript("obj.overload(12.5); obj.setPassed();\n", 1));
148 QVERIFY(_helper->runScript("obj.overload(12.5); obj.setPassed();\n", 1));
149 QVERIFY(_helper->runScript("obj.overload(12); obj.setPassed();\n", 2));
149 QVERIFY(_helper->runScript("obj.overload(12); obj.setPassed();\n", 2));
150 QVERIFY(_helper->runScript("obj.overload('test'); obj.setPassed();\n", 3));
150 QVERIFY(_helper->runScript("obj.overload('test'); obj.setPassed();\n", 3));
151 QVERIFY(_helper->runScript("obj.overload(u'test'); obj.setPassed();\n", 3));
151 QVERIFY(_helper->runScript("obj.overload(u'test'); obj.setPassed();\n", 3));
152 QVERIFY(_helper->runScript("obj.overload(('test','test2')); obj.setPassed();\n", 4));
152 QVERIFY(_helper->runScript("obj.overload(('test','test2')); obj.setPassed();\n", 4));
153 QVERIFY(_helper->runScript("obj.overload(obj); obj.setPassed();\n", 5));
153 QVERIFY(_helper->runScript("obj.overload(obj); obj.setPassed();\n", 5));
154 QVERIFY(_helper->runScript("obj.overload(12,13); obj.setPassed();\n", 6));
154 QVERIFY(_helper->runScript("obj.overload(12,13); obj.setPassed();\n", 6));
155 }
155 }
156
156
157 void PythonQtTestSlotCalling::testPyObjectSlotCall()
157 void PythonQtTestSlotCalling::testPyObjectSlotCall()
158 {
158 {
159 QVERIFY(_helper->runScript("if obj.getPyObject(PythonQt)==PythonQt: obj.setPassed();\n"));
159 QVERIFY(_helper->runScript("if obj.getPyObject(PythonQt)==PythonQt: obj.setPassed();\n"));
160 QVERIFY(_helper->runScript("if obj.getPyObject('Hello')=='Hello': obj.setPassed();\n"));
160 QVERIFY(_helper->runScript("if obj.getPyObject('Hello')=='Hello': obj.setPassed();\n"));
161 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant(PythonQt)==PythonQt: obj.setPassed();\n"));
161 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant(PythonQt)==PythonQt: obj.setPassed();\n"));
162 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant2(PythonQt)==PythonQt: obj.setPassed();\n"));
162 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant2(PythonQt)==PythonQt: obj.setPassed();\n"));
163 // QVERIFY(_helper->runScript("if obj.getPyObjectFromPtr(PythonQt)==PythonQt: obj.setPassed();\n"));
163 // QVERIFY(_helper->runScript("if obj.getPyObjectFromPtr(PythonQt)==PythonQt: obj.setPassed();\n"));
164 }
164 }
165
165
166 void PythonQtTestSlotCalling::testCPPSlotCalls()
166 void PythonQtTestSlotCalling::testCPPSlotCalls()
167 {
167 {
168 // test QColor compare operation
168 // test QColor compare operation
169 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();obj.testNoArg()\n"));
169 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();obj.testNoArg()\n"));
170 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)!=PythonQt.QtGui.QColor(3,2,1): obj.setPassed();obj.testNoArg()\n"));
170 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)!=PythonQt.QtGui.QColor(3,2,1): obj.setPassed();obj.testNoArg()\n"));
171
171
172 // test passing/returning QColors
172 // test passing/returning QColors
173 QVERIFY(_helper->runScript("if obj.getQColor1(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
173 QVERIFY(_helper->runScript("if obj.getQColor1(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
174 QVERIFY(_helper->runScript("if obj.getQColor2(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
174 QVERIFY(_helper->runScript("if obj.getQColor2(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
175 QVERIFY(_helper->runScript("if obj.getQColor3(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
175 QVERIFY(_helper->runScript("if obj.getQColor3(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
176 QVERIFY(_helper->runScript("if obj.getQColor4(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
176 QVERIFY(_helper->runScript("if obj.getQColor4(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
177 QVERIFY(_helper->runScript("if obj.getQColor5()==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
177 QVERIFY(_helper->runScript("if obj.getQColor5()==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
178 }
178 }
179
179
180 void PythonQtTestSlotCalling::testPODSlotCalls()
180 void PythonQtTestSlotCalling::testPODSlotCalls()
181 {
181 {
182 QVERIFY(_helper->runScript("if obj.getBool(False)==False: obj.setPassed();\n"));
182 QVERIFY(_helper->runScript("if obj.getBool(False)==False: obj.setPassed();\n"));
183 QVERIFY(_helper->runScript("if obj.getBool(True)==True: obj.setPassed();\n"));
183 QVERIFY(_helper->runScript("if obj.getBool(True)==True: obj.setPassed();\n"));
184 QVERIFY(_helper->runScript("if obj.getInt(-42)==-42: obj.setPassed();\n"));
184 QVERIFY(_helper->runScript("if obj.getInt(-42)==-42: obj.setPassed();\n"));
185 QVERIFY(_helper->runScript("if obj.getUInt(42)==42: obj.setPassed();\n"));
185 QVERIFY(_helper->runScript("if obj.getUInt(42)==42: obj.setPassed();\n"));
186 QVERIFY(_helper->runScript("if obj.getShort(-43)==-43: obj.setPassed();\n"));
186 QVERIFY(_helper->runScript("if obj.getShort(-43)==-43: obj.setPassed();\n"));
187 QVERIFY(_helper->runScript("if obj.getUShort(43)==43: obj.setPassed();\n"));
187 QVERIFY(_helper->runScript("if obj.getUShort(43)==43: obj.setPassed();\n"));
188 QVERIFY(_helper->runScript("if obj.getChar(-12)==-12: obj.setPassed();\n"));
188 QVERIFY(_helper->runScript("if obj.getChar(-12)==-12: obj.setPassed();\n"));
189 QVERIFY(_helper->runScript("if obj.getUChar(12)==12: obj.setPassed();\n"));
189 QVERIFY(_helper->runScript("if obj.getUChar(12)==12: obj.setPassed();\n"));
190 QVERIFY(_helper->runScript("if obj.getLong(-256*256*256)==-256*256*256: obj.setPassed();\n"));
190 QVERIFY(_helper->runScript("if obj.getLong(-256*256*256)==-256*256*256: obj.setPassed();\n"));
191 QVERIFY(_helper->runScript("if obj.getULong(256*256*256)==256*256*256: obj.setPassed();\n"));
191 QVERIFY(_helper->runScript("if obj.getULong(256*256*256)==256*256*256: obj.setPassed();\n"));
192 QVERIFY(_helper->runScript("if obj.getLongLong(-42)==-42: obj.setPassed();\n"));
192 QVERIFY(_helper->runScript("if obj.getLongLong(-42)==-42: obj.setPassed();\n"));
193 QVERIFY(_helper->runScript("if obj.getULongLong(42)==42: obj.setPassed();\n"));
193 QVERIFY(_helper->runScript("if obj.getULongLong(42)==42: obj.setPassed();\n"));
194 QVERIFY(_helper->runScript("if obj.getQChar(4096)==4096: obj.setPassed();\n"));
194 QVERIFY(_helper->runScript("if obj.getQChar(4096)==4096: obj.setPassed();\n"));
195 QVERIFY(_helper->runScript("if obj.getDouble(47.12)==47.12: obj.setPassed();\n"));
195 QVERIFY(_helper->runScript("if obj.getDouble(47.12)==47.12: obj.setPassed();\n"));
196 QVERIFY(_helper->runScript("if abs(obj.getFloat(47.11)-47.11)<0.01: obj.setPassed();\n"));
196 QVERIFY(_helper->runScript("if abs(obj.getFloat(47.11)-47.11)<0.01: obj.setPassed();\n"));
197 QVERIFY(_helper->runScript("if obj.getQString('testStr')=='testStr': obj.setPassed();\n"));
197 QVERIFY(_helper->runScript("if obj.getQString('testStr')=='testStr': obj.setPassed();\n"));
198 QVERIFY(_helper->runScript("if obj.getQString('')=='': obj.setPassed();\n"));
198 QVERIFY(_helper->runScript("if obj.getQString('')=='': obj.setPassed();\n"));
199 QVERIFY(_helper->runScript("if obj.getQStringList(('test','test2'))==('test','test2'): obj.setPassed();\n"));
199 QVERIFY(_helper->runScript("if obj.getQStringList(('test','test2'))==('test','test2'): obj.setPassed();\n"));
200 }
200 }
201
201
202 void PythonQtTestSlotCalling::testQVariantSlotCalls()
202 void PythonQtTestSlotCalling::testQVariantSlotCalls()
203 {
203 {
204 QVERIFY(_helper->runScript("if obj.getQVariant(-42)==-42: obj.setPassed();\n"));
204 QVERIFY(_helper->runScript("if obj.getQVariant(-42)==-42: obj.setPassed();\n"));
205 QVERIFY(_helper->runScript("if obj.getQVariant('testStr')=='testStr': obj.setPassed();\n"));
205 QVERIFY(_helper->runScript("if obj.getQVariant('testStr')=='testStr': obj.setPassed();\n"));
206 QVERIFY(_helper->runScript("if obj.getQVariant(('test','test2'))==('test','test2'): obj.setPassed();\n"));
206 QVERIFY(_helper->runScript("if obj.getQVariant(('test','test2'))==('test','test2'): obj.setPassed();\n"));
207 QVERIFY(_helper->runScript("if obj.getQVariant(('test',12, 47.11))==('test',12, 47.11): obj.setPassed();\n"));
207 QVERIFY(_helper->runScript("if obj.getQVariant(('test',12, 47.11))==('test',12, 47.11): obj.setPassed();\n"));
208 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
208 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
209 QEXPECT_FAIL("", "Testing to pass a map and compare with a different map", Continue);
209 QEXPECT_FAIL("", "Testing to pass a map and compare with a different map", Continue);
210 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla2','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
210 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla2','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
211 QVERIFY(_helper->runScript("if obj.getQVariant(obj)==obj: obj.setPassed();\n"));
211 QVERIFY(_helper->runScript("if obj.getQVariant(obj)==obj: obj.setPassed();\n"));
212 }
212 }
213
213
214 void PythonQtTestSlotCalling::testObjectSlotCalls()
214 void PythonQtTestSlotCalling::testObjectSlotCalls()
215 {
215 {
216 QVERIFY(_helper->runScript("if obj.getQObject(obj)==obj: obj.setPassed();\n"));
216 QVERIFY(_helper->runScript("if obj.getQObject(obj)==obj: obj.setPassed();\n"));
217 QVERIFY(_helper->runScript("if obj.getTestObject(obj)==obj: obj.setPassed();\n"));
217 QVERIFY(_helper->runScript("if obj.getTestObject(obj)==obj: obj.setPassed();\n"));
218 QVERIFY(_helper->runScript("if obj.getNewObject().className()=='PythonQtTestSlotCallingHelper': obj.setPassed();\n"));
218 QVERIFY(_helper->runScript("if obj.getNewObject().className()=='PythonQtTestSlotCallingHelper': obj.setPassed();\n"));
219 QEXPECT_FAIL("", "Testing to pass a QObject when another object was expected", Continue);
219 QEXPECT_FAIL("", "Testing to pass a QObject when another object was expected", Continue);
220 QVERIFY(_helper->runScript("if obj.getQWidget(obj)==obj: obj.setPassed();\n"));
220 QVERIFY(_helper->runScript("if obj.getQWidget(obj)==obj: obj.setPassed();\n"));
221 }
221 }
222
222
223 void PythonQtTestSlotCalling::testCppFactory()
223 void PythonQtTestSlotCalling::testCppFactory()
224 {
224 {
225 PythonQtTestCppFactory* f = new PythonQtTestCppFactory;
225 PythonQtTestCppFactory* f = new PythonQtTestCppFactory;
226 PythonQt::self()->addInstanceDecorators(new PQCppObjectDecorator);
226 PythonQt::self()->addInstanceDecorators(new PQCppObjectDecorator);
227 // do not register, since we want to know if that works as well
227 // do not register, since we want to know if that works as well
228 //qRegisterMetaType<PQCppObjectNoWrap>("PQCppObjectNoWrap");
228 //qRegisterMetaType<PQCppObjectNoWrap>("PQCppObjectNoWrap");
229 PythonQt::self()->addDecorators(new PQCppObjectNoWrapDecorator);
229 PythonQt::self()->addDecorators(new PQCppObjectNoWrapDecorator);
230
230
231 PythonQt::self()->addWrapperFactory(f);
231 PythonQt::self()->addWrapperFactory(f);
232 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getHeight()==12: obj.setPassed();\n"));
232 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getHeight()==12: obj.setPassed();\n"));
233 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getH()==12: obj.setPassed();\n"));
233 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getH()==12: obj.setPassed();\n"));
234 QVERIFY(_helper->runScript("pq1 = obj.createPQCppObject(12);\n"
234 QVERIFY(_helper->runScript("pq1 = obj.createPQCppObject(12);\n"
235 "pq2 = obj.createPQCppObject(13);\n"
235 "pq2 = obj.createPQCppObject(13);\n"
236 "pq3 = obj.getPQCppObject(pq1);\n"
236 "pq3 = obj.getPQCppObject(pq1);\n"
237 "pq4 = obj.getPQCppObject(pq2);\n"
237 "pq4 = obj.getPQCppObject(pq2);\n"
238 "if pq3.getHeight()==12 and pq4.getHeight()==13: obj.setPassed();\n"
238 "if pq3.getHeight()==12 and pq4.getHeight()==13: obj.setPassed();\n"
239 ));
239 ));
240
240
241 QVERIFY(_helper->runScript("if obj.createPQCppObjectNoWrap(12).getH()==12: obj.setPassed();\n"));
241 QVERIFY(_helper->runScript("if obj.createPQCppObjectNoWrap(12).getH()==12: obj.setPassed();\n"));
242
242
243 QVERIFY(_helper->runScript("if obj.getPQCppObjectNoWrapAsValue().getH()==47: obj.setPassed();\n"));
243 QVERIFY(_helper->runScript("if obj.getPQCppObjectNoWrapAsValue().getH()==47: obj.setPassed();\n"));
244
244
245 qRegisterMetaType<PQUnknownButRegisteredValueObject>("PQUnknownButRegisteredValueObject");
245 qRegisterMetaType<PQUnknownButRegisteredValueObject>("PQUnknownButRegisteredValueObject");
246 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsPtr();print a;\nif a!=None: obj.setPassed();\n"));
246 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsPtr();print a;\nif a!=None: obj.setPassed();\n"));
247 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsValue();print a;\nif a!=None: obj.setPassed();\n"));
247 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsValue();print a;\nif a!=None: obj.setPassed();\n"));
248 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsPtr();print a;\nif a!=None: obj.setPassed();\n"));
248 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsPtr();print a;\nif a!=None: obj.setPassed();\n"));
249 QEXPECT_FAIL("", "Testing by value return without the object being registered as QMetaType or having registered a default constructor decorator", Continue);
249 QEXPECT_FAIL("", "Testing by value return without the object being registered as QMetaType or having registered a default constructor decorator", Continue);
250 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsValue();print a;\nif a!=None: obj.setPassed();\n"));
250 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsValue();print a;\nif a!=None: obj.setPassed();\n"));
251
251
252 // expect to get strict call to double overload
252 // expect to get strict call to double overload
253 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22.2)\nif a.getH()==2: obj.setPassed();\n"));
253 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22.2)\nif a.getH()==2: obj.setPassed();\n"));
254 // expect to get un-strict call to double overload
254 // expect to get un-strict call to double overload
255 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22)\nif a.getH()==2: obj.setPassed();\n"));
255 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22)\nif a.getH()==2: obj.setPassed();\n"));
256 // expect to get strict call to copy constructor overload
256 // expect to get strict call to copy constructor overload
257 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(PQCppObjectNoWrap())\nprint a.getH()\nif a.getH()==1: obj.setPassed();\n"));
257 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(PQCppObjectNoWrap())\nprint a.getH()\nif a.getH()==1: obj.setPassed();\n"));
258
258
259 // test decorated enums
259 // test decorated enums
260 // already registered by signals test
260 // already registered by signals test
261 //PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
261 //PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
262
262
263 // local enum (decorated)
263 // local enum (decorated)
264 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nprint a.testEnumFlag1\nif a.testEnumFlag1(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
264 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nprint a.testEnumFlag1\nif a.testEnumFlag1(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
265 // enum with namespace (decorated)
265 // enum with namespace (decorated)
266 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag2(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
266 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag2(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
267 // with int overload to check overloading
267 // with int overload to check overloading
268 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag3(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
268 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag3(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
269
269
270 }
270 }
271
271
272 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag1(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
272 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag1(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
273 return flag;
273 return flag;
274 }
274 }
275
275
276 PQCppObject2::TestEnumFlag PQCppObject2Decorator::testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag) {
276 PQCppObject2::TestEnumFlag PQCppObject2Decorator::testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag) {
277 return flag;
277 return flag;
278 }
278 }
279
279
280 // with int overload
280 // with int overload
281 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, int flag) {
281 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, int flag) {
282 return (TestEnumFlag)-1;
282 return (TestEnumFlag)-1;
283 }
283 }
284 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
284 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
285 return flag;
285 return flag;
286 }
286 }
287
287
288 void PythonQtTestSlotCalling::testMultiArgsSlotCall()
288 void PythonQtTestSlotCalling::testMultiArgsSlotCall()
289 {
289 {
290 QVERIFY(_helper->runScript("if obj.getMultiArgs(12,47.11,'test')==(12,47.11,'test'): obj.setPassed();\n"));
290 QVERIFY(_helper->runScript("if obj.getMultiArgs(12,47.11,'test')==(12,47.11,'test'): obj.setPassed();\n"));
291 }
291 }
292
292
293 bool PythonQtTestSlotCallingHelper::runScript(const char* script, int expectedOverload)
293 bool PythonQtTestSlotCallingHelper::runScript(const char* script, int expectedOverload)
294 {
294 {
295 _called = false;
295 _called = false;
296 _passed = false;
296 _passed = false;
297 _calledOverload = -1;
297 _calledOverload = -1;
298 PyRun_SimpleString(script);
298 PyRun_SimpleString(script);
299 return _called && _passed && _calledOverload==expectedOverload;
299 return _called && _passed && _calledOverload==expectedOverload;
300 }
300 }
301
301
302
302
303 void PythonQtTestSignalHandler::initTestCase()
303 void PythonQtTestSignalHandler::initTestCase()
304 {
304 {
305 _helper = new PythonQtTestSignalHandlerHelper(this);
305 _helper = new PythonQtTestSignalHandlerHelper(this);
306 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
306 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
307 PythonQt::self()->addObject(main, "obj", _helper);
307 PythonQt::self()->addObject(main, "obj", _helper);
308 }
308 }
309
309
310 void PythonQtTestSignalHandler::testSignalHandler()
310 void PythonQtTestSignalHandler::testSignalHandler()
311 {
311 {
312 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
312 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
313 PyRun_SimpleString("def testIntSignal(a):\n if a==12: obj.setPassed();\n");
313 PyRun_SimpleString("def testIntSignal(a):\n if a==12: obj.setPassed();\n");
314 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
314 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
315 QVERIFY(_helper->emitIntSignal(12));
315 QVERIFY(_helper->emitIntSignal(12));
316
316
317 PyRun_SimpleString("def testFloatSignal(a):\n if a==12: obj.setPassed();\n");
317 PyRun_SimpleString("def testFloatSignal(a):\n if a==12: obj.setPassed();\n");
318 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
318 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
319 QVERIFY(_helper->emitFloatSignal(12));
319 QVERIFY(_helper->emitFloatSignal(12));
320
320
321 // test decorated enums
321 // test decorated enums
322 PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
322 PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
323
323
324 PyRun_SimpleString("def testEnumSignal(a):\n if a==1: obj.setPassed();\n");
324 PyRun_SimpleString("def testEnumSignal(a):\n if a==1: obj.setPassed();\n");
325 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
325 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
326 QVERIFY(_helper->emitEnumSignal(PQCppObject2::TestEnumValue2));
326 QVERIFY(_helper->emitEnumSignal(PQCppObject2::TestEnumValue2));
327
327
328 PyRun_SimpleString("def testVariantSignal(a):\n if a==obj.expectedVariant(): obj.setPassed();\n");
328 PyRun_SimpleString("def testVariantSignal(a):\n if a==obj.expectedVariant(): obj.setPassed();\n");
329 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
329 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
330 _helper->setExpectedVariant(QString("Test"));
330 _helper->setExpectedVariant(QString("Test"));
331 QVERIFY(_helper->emitVariantSignal(QString("Test")));
331 QVERIFY(_helper->emitVariantSignal(QString("Test")));
332 _helper->setExpectedVariant(12);
332 _helper->setExpectedVariant(12);
333 QVERIFY(_helper->emitVariantSignal(12));
333 QVERIFY(_helper->emitVariantSignal(12));
334 _helper->setExpectedVariant(QStringList() << "test1" << "test2");
334 _helper->setExpectedVariant(QStringList() << "test1" << "test2");
335 QVERIFY(_helper->emitVariantSignal(QStringList() << "test1" << "test2"));
335 QVERIFY(_helper->emitVariantSignal(QStringList() << "test1" << "test2"));
336 _helper->setExpectedVariant(qVariantFromValue((QObject*)_helper));
336 _helper->setExpectedVariant(qVariantFromValue((QObject*)_helper));
337 QVERIFY(_helper->emitVariantSignal(qVariantFromValue((QObject*)_helper)));
337 QVERIFY(_helper->emitVariantSignal(qVariantFromValue((QObject*)_helper)));
338
338
339 PyRun_SimpleString("def testComplexSignal(a,b,l,o):\n if a==12 and b==13 and l==('test1','test2') and o == obj: obj.setPassed();\n");
339 PyRun_SimpleString("def testComplexSignal(a,b,l,o):\n if a==12 and b==13 and l==('test1','test2') and o == obj: obj.setPassed();\n");
340 // intentionally not normalized signal:
340 // intentionally not normalized signal:
341 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
341 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
342 QVERIFY(_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
342 QVERIFY(_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
343
343
344 // try removing the handler
344 // try removing the handler
345 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
345 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
346 // and emit the signal, which should fail because the handler was removed
346 // and emit the signal, which should fail because the handler was removed
347 QVERIFY(!_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
347 QVERIFY(!_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
348
348
349 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
349 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
350 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
350 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
351 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
351 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
352 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
352 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
353
353
354 }
354 }
355
355
356 void PythonQtTestSignalHandler::testRecursiveSignalHandler()
356 void PythonQtTestSignalHandler::testRecursiveSignalHandler()
357 {
357 {
358 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
358 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
359 PyRun_SimpleString("def testSignal1(a):\n obj.emitSignal2(a);\n");
359 PyRun_SimpleString("def testSignal1(a):\n obj.emitSignal2(a);\n");
360 PyRun_SimpleString("def testSignal2(a):\n obj.emitSignal3(float(a));\n");
360 PyRun_SimpleString("def testSignal2(a):\n obj.emitSignal3(float(a));\n");
361 PyRun_SimpleString("def testSignal3(a):\n if a==12: obj.setPassed();\n");
361 PyRun_SimpleString("def testSignal3(a):\n if a==12: obj.setPassed();\n");
362 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal1(int)), main, "testSignal1"));
362 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal1(int)), main, "testSignal1"));
363 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal2(const QString&)), main, "testSignal2"));
363 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal2(const QString&)), main, "testSignal2"));
364 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal3(float)), main, "testSignal3"));
364 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal3(float)), main, "testSignal3"));
365 QVERIFY(_helper->emitSignal1(12));
365 QVERIFY(_helper->emitSignal1(12));
366 }
366 }
367
367
368
368
369 void PythonQtTestApi::initTestCase()
369 void PythonQtTestApi::initTestCase()
370 {
370 {
371 _helper = new PythonQtTestApiHelper();
371 _helper = new PythonQtTestApiHelper();
372 _main = PythonQt::self()->getMainModule();
372 _main = PythonQt::self()->getMainModule();
373 _main.evalScript("import PythonQt");
373 _main.evalScript("import PythonQt");
374 _main.addObject("obj", _helper);
374 _main.addObject("obj", _helper);
375 }
375 }
376
376
377 void PythonQtTestApi::testProperties()
377 void PythonQtTestApi::testProperties()
378 {
378 {
379 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
379 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
380 // check for name alias (for backward comp to Qt3)
380 // check for name alias (for backward comp to Qt3)
381 main.evalScript("obj.name = 'hello'");
381 main.evalScript("obj.name = 'hello'");
382 QVERIFY(QString("hello") == main.getVariable("obj.name").toString());
382 QVERIFY(QString("hello") == main.getVariable("obj.name").toString());
383
383
384 main.evalScript("obj.objectName = 'hello2'");
384 main.evalScript("obj.objectName = 'hello2'");
385 QVERIFY(QString("hello2") == main.getVariable("obj.objectName").toString());
385 QVERIFY(QString("hello2") == main.getVariable("obj.objectName").toString());
386
386
387 }
387 }
388
388
389 void PythonQtTestApi::testDynamicProperties()
389 void PythonQtTestApi::testDynamicProperties()
390 {
390 {
391 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
391 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
392
392
393 // this fails and should fail, but how could that be tested?
393 // this fails and should fail, but how could that be tested?
394 // main.evalScript("obj.testProp = 1");
394 // main.evalScript("obj.testProp = 1");
395
395
396 // create a new dynamic property
396 // create a new dynamic property
397 main.evalScript("obj.setProperty('testProp','testValue')");
397 main.evalScript("obj.setProperty('testProp','testValue')");
398
398
399 // read the property
399 // read the property
400 QVERIFY(QString("testValue") == main.getVariable("obj.testProp").toString());
400 QVERIFY(QString("testValue") == main.getVariable("obj.testProp").toString());
401 // modify and read again
401 // modify and read again
402 main.evalScript("obj.testProp = 12");
402 main.evalScript("obj.testProp = 12");
403 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
403 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
404
404
405 // check if dynamic property is in dict
405 // check if dynamic property is in dict
406 QVERIFY(12 == main.evalScript("obj.__dict__['testProp']", Py_eval_input).toInt());
406 QVERIFY(12 == main.evalScript("obj.__dict__['testProp']", Py_eval_input).toInt());
407
407
408 // check if dynamic property is in introspection
408 // check if dynamic property is in introspection
409 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
409 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
410 QVERIFY(l.contains("testProp"));
410 QVERIFY(l.contains("testProp"));
411
411
412 // check with None, previous value expected
412 // check with None, previous value expected
413 main.evalScript("obj.testProp = None");
413 main.evalScript("obj.testProp = None");
414 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
414 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
415
415
416 // remove the dynamic property
416 // remove the dynamic property
417 main.evalScript("obj.setProperty('testProp', None)");
417 main.evalScript("obj.setProperty('testProp', None)");
418
418
419 // check if dynamic property is really gone
419 // check if dynamic property is really gone
420 QStringList l2 = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
420 QStringList l2 = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
421 QVERIFY(!l2.contains("testProp"));
421 QVERIFY(!l2.contains("testProp"));
422
422
423 }
423 }
424
424
425
425
426 bool PythonQtTestApiHelper::call(const QString& function, const QVariantList& args, const QVariant& expectedResult) {
426 bool PythonQtTestApiHelper::call(const QString& function, const QVariantList& args, const QVariant& expectedResult) {
427 _passed = false;
427 _passed = false;
428 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), function, args);
428 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), function, args);
429 return _passed && expectedResult==r;
429 return _passed && expectedResult==r;
430 }
430 }
431
431
432 void PythonQtTestApi::testCall()
432 void PythonQtTestApi::testCall()
433 {
433 {
434 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
434 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
435
435
436 QVERIFY(qVariantValue<QObject*>(PythonQt::self()->getVariable(main, "obj"))==_helper);
436 QVERIFY(qVariantValue<QObject*>(PythonQt::self()->getVariable(main, "obj"))==_helper);
437
437
438 PyRun_SimpleString("def testCallNoArgs():\n obj.setPassed();\n");
438 PyRun_SimpleString("def testCallNoArgs():\n obj.setPassed();\n");
439 QVERIFY(_helper->call("testCallNoArgs", QVariantList(), QVariant()));
439 QVERIFY(_helper->call("testCallNoArgs", QVariantList(), QVariant()));
440
440
441 PyRun_SimpleString("def testCall1(a):\n if a=='test': obj.setPassed();\n return 'test2';\n");
441 PyRun_SimpleString("def testCall1(a):\n if a=='test': obj.setPassed();\n return 'test2';\n");
442 QVERIFY(_helper->call("testCall1", QVariantList() << QVariant("test"), QVariant(QString("test2"))));
442 QVERIFY(_helper->call("testCall1", QVariantList() << QVariant("test"), QVariant(QString("test2"))));
443
443
444 PyRun_SimpleString("def testCall2(a, b):\n if a=='test' and b==obj: obj.setPassed();\n return obj;\n");
444 PyRun_SimpleString("def testCall2(a, b):\n if a=='test' and b==obj: obj.setPassed();\n return obj;\n");
445 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), "testCall2", QVariantList() << QVariant("test") << qVariantFromValue((QObject*)_helper));
445 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), "testCall2", QVariantList() << QVariant("test") << qVariantFromValue((QObject*)_helper));
446 QObject* p = qVariantValue<QObject*>(r);
446 QObject* p = qVariantValue<QObject*>(r);
447 QVERIFY(p==_helper);
447 QVERIFY(p==_helper);
448 }
448 }
449
449
450 void PythonQtTestApi::testVariables()
450 void PythonQtTestApi::testVariables()
451 {
451 {
452 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
452 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
453 QVariant v = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
453 QVariant v = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
454 QObject* p = qVariantValue<QObject*>(v);
454 QObject* p = qVariantValue<QObject*>(v);
455 QVERIFY(p==_helper);
455 QVERIFY(p==_helper);
456 // test for unset variable
456 // test for unset variable
457 QVariant v2 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject2");
457 QVariant v2 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject2");
458 QVERIFY(v2==QVariant());
458 QVERIFY(v2==QVariant());
459
459
460 PythonQt::self()->addVariable(PythonQt::self()->getMainModule(), "someValue", QStringList() << "test1" << "test2");
460 PythonQt::self()->addVariable(PythonQt::self()->getMainModule(), "someValue", QStringList() << "test1" << "test2");
461 QVariant v3 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someValue");
461 QVariant v3 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someValue");
462 QVERIFY(v3 == QVariant(QStringList() << "test1" << "test2"));
462 QVERIFY(v3 == QVariant(QStringList() << "test1" << "test2"));
463
463
464 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), QString::null, PythonQt::Variable);
464 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), QString::null, PythonQt::Variable);
465 QSet<QString> s;
465 QSet<QString> s;
466 // check that at least these three variables are set
466 // check that at least these three variables are set
467 s << "obj" << "someObject" << "someValue";
467 s << "obj" << "someObject" << "someValue";
468 foreach (QString value, s) {
468 foreach (QString value, s) {
469 QVERIFY(l.indexOf(value)!=-1);
469 QVERIFY(l.indexOf(value)!=-1);
470 }
470 }
471
471
472 // insert a second time!
472 // insert a second time!
473 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
473 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
474 // and remove
474 // and remove
475 PythonQt::self()->removeVariable(PythonQt::self()->getMainModule(), "someObject");
475 PythonQt::self()->removeVariable(PythonQt::self()->getMainModule(), "someObject");
476 // we expect to find no variable
476 // we expect to find no variable
477 QVariant v4 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
477 QVariant v4 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
478 QVERIFY(v4==QVariant());
478 QVERIFY(v4==QVariant());
479 }
479 }
480
480
481 void PythonQtTestApi::testImporter()
481 void PythonQtTestApi::testImporter()
482 {
482 {
483 PythonQt::self()->setImporter(_helper);
483 PythonQt::self()->setImporter(_helper);
484 PythonQt::self()->overwriteSysPath(QStringList() << "c:\\test");
484 PythonQt::self()->overwriteSysPath(QStringList() << "c:\\test");
485 PyRun_SimpleString("import bla\n");
485 PyRun_SimpleString("import bla\n");
486 }
486 }
487
487
488 void PythonQtTestApi::testQtNamespace()
488 void PythonQtTestApi::testQtNamespace()
489 {
489 {
490 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.red").toInt()==Qt::red);
490 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.red").toInt()==Qt::red);
491 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.FlatCap").toInt()==Qt::FlatCap);
491 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.FlatCap").toInt()==Qt::FlatCap);
492 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.escape")));
492 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.escape")));
493 // check for an enum type wrapper
493 // check for an enum type wrapper
494 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.AlignmentFlag")));
494 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.AlignmentFlag")));
495 // check for a flags type wrapper
495 // check for a flags type wrapper
496 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.Alignment")));
496 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.Alignment")));
497 }
497 }
498
498
499 void PythonQtTestApi::testConnects()
499 void PythonQtTestApi::testConnects()
500 {
500 {
501 // QVERIFY(qVariantValue<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
501 // QVERIFY(qVariantValue<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
502 //TODO: add signal/slot connect both with QObject.connect and connect
502 //TODO: add signal/slot connect both with QObject.connect and connect
503 }
503 }
504
504
505 void PythonQtTestApi::testQColorDecorators()
505 void PythonQtTestApi::testQColorDecorators()
506 {
506 {
507 PythonQtObjectPtr colorClass = _main.getVariable("PythonQt.QtGui.QColor");
507 PythonQtObjectPtr colorClass = _main.getVariable("PythonQt.QtGui.QColor");
508 QVERIFY(colorClass);
508 QVERIFY(colorClass);
509 // verify that the class is in the correct module
509 // verify that the class is in the correct module
510 QVERIFY(colorClass.getVariable("__module__") == "PythonQt.QtGui");
510 QVERIFY(colorClass.getVariable("__module__") == "PythonQt.QtGui");
511 // test on Qt module as well:
511 // test on Qt module as well:
512 colorClass = _main.getVariable("PythonQt.Qt.QColor");
512 colorClass = _main.getVariable("PythonQt.Qt.QColor");
513 QVERIFY(colorClass);
513 QVERIFY(colorClass);
514 // constructors
514 // constructors
515 QVERIFY(qVariantValue<QColor>(colorClass.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
515 QVERIFY(qVariantValue<QColor>(colorClass.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
516 QVERIFY(qVariantValue<QColor>(colorClass.call()) == QColor());
516 QVERIFY(qVariantValue<QColor>(colorClass.call()) == QColor());
517 QEXPECT_FAIL("", "Testing non-existing constructor", Continue);
517 QEXPECT_FAIL("", "Testing non-existing constructor", Continue);
518 QVERIFY(colorClass.call(QVariantList() << 1 << 2) != QVariant());
518 QVERIFY(colorClass.call(QVariantList() << 1 << 2) != QVariant());
519
519
520 // check that enum overload is taken over int
520 // check that enum overload is taken over int
521 QVERIFY(qVariantValue<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
521 QVERIFY(qVariantValue<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
522 // check that int overload is taken over enum
522 // check that int overload is taken over enum
523 QVERIFY(qVariantValue<QColor>(_main.evalScript("PythonQt.Qt.QColor(0x112233)" ,Py_eval_input)) == QColor(0x112233));
523 QVERIFY(qVariantValue<QColor>(_main.evalScript("PythonQt.Qt.QColor(0x112233)" ,Py_eval_input)) == QColor(0x112233));
524
524
525 // check for decorated Cmyk enum value
525 // check for decorated Cmyk enum value
526 QVERIFY(colorClass.getVariable("Cmyk").toInt() == QColor::Cmyk);
526 QVERIFY(colorClass.getVariable("Cmyk").toInt() == QColor::Cmyk);
527 PythonQtObjectPtr staticMethod = colorClass.getVariable("fromRgb");
527 PythonQtObjectPtr staticMethod = colorClass.getVariable("fromRgb");
528 QVERIFY(staticMethod);
528 QVERIFY(staticMethod);
529 // direct call of static method via class
529 // direct call of static method via class
530 QVERIFY(qVariantValue<QColor>(colorClass.call("fromRgb", QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
530 QVERIFY(qVariantValue<QColor>(colorClass.call("fromRgb", QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
531 // direct call of static method
531 // direct call of static method
532 QVERIFY(qVariantValue<QColor>(staticMethod.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
532 QVERIFY(qVariantValue<QColor>(staticMethod.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
533 PythonQtObjectPtr publicMethod = colorClass.getVariable("red");
533 PythonQtObjectPtr publicMethod = colorClass.getVariable("red");
534 QVERIFY(publicMethod);
534 QVERIFY(publicMethod);
535 // call with passing self in:
535 // call with passing self in:
536 QVERIFY(colorClass.call("red", QVariantList() << QColor(255,0,0)).toInt() == 255);
536 QVERIFY(colorClass.call("red", QVariantList() << QColor(255,0,0)).toInt() == 255);
537 }
537 }
538
538
539 QByteArray PythonQtTestApiHelper::readFileAsBytes(const QString& filename)
539 QByteArray PythonQtTestApiHelper::readFileAsBytes(const QString& filename)
540 {
540 {
541 QByteArray b;
541 QByteArray b;
542 return b;
542 return b;
543 }
543 }
544
544
545 QByteArray PythonQtTestApiHelper::readSourceFile(const QString& filename, bool& ok)
545 QByteArray PythonQtTestApiHelper::readSourceFile(const QString& filename, bool& ok)
546 {
546 {
547 QByteArray b;
547 QByteArray b;
548 ok = true;
548 ok = true;
549 return b;
549 return b;
550 }
550 }
551
551
552 bool PythonQtTestApiHelper::exists(const QString& filename)
552 bool PythonQtTestApiHelper::exists(const QString& filename)
553 {
553 {
554 return true;
554 return true;
555 }
555 }
556
556
557 QDateTime PythonQtTestApiHelper::lastModifiedDate(const QString& filename) {
557 QDateTime PythonQtTestApiHelper::lastModifiedDate(const QString& filename) {
558 return QDateTime::currentDateTime();
558 return QDateTime::currentDateTime();
559 }
559 }
560
560
561
561
562 void PythonQtTestApi::testRedirect()
562 void PythonQtTestApi::testRedirect()
563 {
563 {
564 connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)), _helper, SLOT(stdOut(const QString&)));
564 connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)), _helper, SLOT(stdOut(const QString&)));
565 connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)), _helper, SLOT(stdErr(const QString&)));
565 connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)), _helper, SLOT(stdErr(const QString&)));
566 PyRun_SimpleString("print 'test'\n");
566 PyRun_SimpleString("print 'test'\n");
567 }
567 }
568
568
569 void PythonQtTestApiHelper::stdOut(const QString& s)
569 void PythonQtTestApiHelper::stdOut(const QString& s)
570 {
570 {
571 qDebug() << s;
571 qDebug() << s;
572 }
572 }
573
573
574 void PythonQtTestApiHelper::stdErr(const QString& s)
574 void PythonQtTestApiHelper::stdErr(const QString& s)
575 {
575 {
576 qDebug() << s;
576 qDebug() << s;
577 }
577 }
578
578
579 QObject* PythonQtTestCppFactory::create(const QByteArray& name, void *ptr)
579 QObject* PythonQtTestCppFactory::create(const QByteArray& name, void *ptr)
580 {
580 {
581 if (name == "PQCppObject") {
581 if (name == "PQCppObject") {
582 return new PQCppObjectWrapper(ptr);
582 return new PQCppObjectWrapper(ptr);
583 }
583 }
584 return NULL;
584 return NULL;
585 }
585 }
@@ -1,515 +1,515
1 #ifndef _PYTHONQTTESTS_H
1 #ifndef _PYTHONQTTESTS_H
2 #define _PYTHONQTTESTS_H
2 #define _PYTHONQTTESTS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtTests.h
38 // \file PythonQtTests.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include <QtTest/QtTest>
46 #include <QtTest/QtTest>
47 #include <QVariant>
47 #include <QVariant>
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50
50
51 #include <QPen>
51 #include <QPen>
52 #include <QColor>
52 #include <QColor>
53 #include <QBrush>
53 #include <QBrush>
54 #include <QCursor>
54 #include <QCursor>
55
55
56 class PythonQtTestSlotCallingHelper;
56 class PythonQtTestSlotCallingHelper;
57 class PythonQtTestApiHelper;
57 class PythonQtTestApiHelper;
58 class QWidget;
58 class QWidget;
59
59
60 //! test the PythonQt api
60 //! test the PythonQt api
61 class PythonQtTestApi : public QObject
61 class PythonQtTestApi : public QObject
62 {
62 {
63 Q_OBJECT
63 Q_OBJECT
64
64
65 private slots:
65 private slots:
66 void initTestCase();
66 void initTestCase();
67 void testCall();
67 void testCall();
68 void testVariables();
68 void testVariables();
69 void testRedirect();
69 void testRedirect();
70 void testImporter();
70 void testImporter();
71 void testQColorDecorators();
71 void testQColorDecorators();
72 void testQtNamespace();
72 void testQtNamespace();
73 void testConnects();
73 void testConnects();
74
74
75 void testProperties();
75 void testProperties();
76 void testDynamicProperties();
76 void testDynamicProperties();
77
77
78 private:
78 private:
79 PythonQtTestApiHelper* _helper;
79 PythonQtTestApiHelper* _helper;
80 PythonQtObjectPtr _main;
80 PythonQtObjectPtr _main;
81
81
82 };
82 };
83
83
84 class ClassA {
84 class ClassA {
85 public:
85 public:
86 ClassA() { x = 1; }
86 ClassA() { x = 1; }
87 int x;
87 int x;
88 };
88 };
89
89
90 class ClassB {
90 class ClassB {
91 public:
91 public:
92 ClassB() { y = 2; }
92 ClassB() { y = 2; }
93 int y;
93 int y;
94
94
95 virtual int type() { return 2; }
95 virtual int type() { return 2; }
96 };
96 };
97
97
98 class ClassC : public ClassA, public ClassB {
98 class ClassC : public ClassA, public ClassB {
99 public:
99 public:
100 ClassC() { z = 3; }
100 ClassC() { z = 3; }
101 int z;
101 int z;
102
102
103 virtual int type() { return 3; }
103 virtual int type() { return 3; }
104 };
104 };
105
105
106 class ClassD : public QObject, public ClassA, public ClassB {
106 class ClassD : public QObject, public ClassA, public ClassB {
107 Q_OBJECT
107 Q_OBJECT
108 public:
108 public:
109 ClassD() { d = 4; }
109 ClassD() { d = 4; }
110 public slots:
110 public slots:
111 int getD() { return d; }
111 int getD() { return d; }
112 private:
112 private:
113 int d;
113 int d;
114
114
115 virtual int type() { return 4; }
115 virtual int type() { return 4; }
116 };
116 };
117
117
118 class ClassAWrapper : public QObject {
118 class ClassAWrapper : public QObject {
119 Q_OBJECT
119 Q_OBJECT
120 public slots:
120 public slots:
121 ClassA* new_ClassA() { return new ClassA; }
121 ClassA* new_ClassA() { return new ClassA; }
122 int getX(ClassA* o) { return o->x; }
122 int getX(ClassA* o) { return o->x; }
123 };
123 };
124
124
125 class ClassBWrapper : public QObject {
125 class ClassBWrapper : public QObject {
126 Q_OBJECT
126 Q_OBJECT
127 public slots:
127 public slots:
128 ClassB* new_ClassB() { return new ClassB; }
128 ClassB* new_ClassB() { return new ClassB; }
129 int getY(ClassB* o) { return o->y; }
129 int getY(ClassB* o) { return o->y; }
130 };
130 };
131
131
132 class ClassCWrapper : public QObject {
132 class ClassCWrapper : public QObject {
133 Q_OBJECT
133 Q_OBJECT
134 public slots:
134 public slots:
135 ClassC* new_ClassC() { return new ClassC; }
135 ClassC* new_ClassC() { return new ClassC; }
136 int getZ(ClassC* o) { return o->z; }
136 int getZ(ClassC* o) { return o->z; }
137 };
137 };
138
138
139 class ClassDWrapper : public QObject {
139 class ClassDWrapper : public QObject {
140 Q_OBJECT
140 Q_OBJECT
141 public slots:
141 public slots:
142 ClassD* new_ClassD() { return new ClassD; }
142 ClassD* new_ClassD() { return new ClassD; }
143 };
143 };
144
144
145
145
146 //! test the PythonQt api (helper)
146 //! test the PythonQt api (helper)
147 class PythonQtTestApiHelper : public QObject , public PythonQtImportFileInterface
147 class PythonQtTestApiHelper : public QObject , public PythonQtImportFileInterface
148 {
148 {
149 Q_OBJECT
149 Q_OBJECT
150 public:
150 public:
151 PythonQtTestApiHelper() {
151 PythonQtTestApiHelper() {
152 };
152 };
153
153
154 bool call(const QString& function, const QVariantList& args, const QVariant& expectedResult);
154 bool call(const QString& function, const QVariantList& args, const QVariant& expectedResult);
155
155
156 virtual QByteArray readFileAsBytes(const QString& filename);
156 virtual QByteArray readFileAsBytes(const QString& filename);
157
157
158 virtual QByteArray readSourceFile(const QString& filename, bool& ok);
158 virtual QByteArray readSourceFile(const QString& filename, bool& ok);
159
159
160 virtual bool exists(const QString& filename);
160 virtual bool exists(const QString& filename);
161
161
162 virtual QDateTime lastModifiedDate(const QString& filename);
162 virtual QDateTime lastModifiedDate(const QString& filename);
163
163
164 public slots:
164 public slots:
165
165
166 //! call to set that the test has passed (from Python!)
166 //! call to set that the test has passed (from Python!)
167 void setPassed() { _passed = true; }
167 void setPassed() { _passed = true; }
168
168
169 void stdOut(const QString&);
169 void stdOut(const QString&);
170 void stdErr(const QString&);
170 void stdErr(const QString&);
171
171
172 private:
172 private:
173 bool _passed;
173 bool _passed;
174 };
174 };
175
175
176
176
177 // test implementation of the wrapper factory
177 // test implementation of the wrapper factory
178 class PythonQtTestCppFactory : public PythonQtCppWrapperFactory
178 class PythonQtTestCppFactory : public PythonQtCppWrapperFactory
179 {
179 {
180 public:
180 public:
181 virtual QObject* create(const QByteArray& name, void *ptr);
181 virtual QObject* create(const QByteArray& name, void *ptr);
182 };
182 };
183
183
184 //! an cpp object to be wrapped
184 //! an cpp object to be wrapped
185 class PQCppObject {
185 class PQCppObject {
186
186
187 public:
187 public:
188 PQCppObject(int h) { _height = h; }
188 PQCppObject(int h) { _height = h; }
189
189
190 int getHeight() { return _height; }
190 int getHeight() { return _height; }
191 void setHeight(int h) { _height = h; }
191 void setHeight(int h) { _height = h; }
192
192
193 private:
193 private:
194 int _height;
194 int _height;
195 };
195 };
196
196
197 //! an qobject that wraps the existing cpp object
197 //! an qobject that wraps the existing cpp object
198 class PQCppObjectWrapper : public QObject {
198 class PQCppObjectWrapper : public QObject {
199 Q_OBJECT
199 Q_OBJECT
200 public:
200 public:
201 PQCppObjectWrapper(void* ptr) {
201 PQCppObjectWrapper(void* ptr) {
202 _ptr = (PQCppObject*)ptr;
202 _ptr = (PQCppObject*)ptr;
203 }
203 }
204
204
205 public slots:
205 public slots:
206 int getHeight() { return _ptr->getHeight(); }
206 int getHeight() { return _ptr->getHeight(); }
207 void setHeight(int h) { _ptr->setHeight(h); }
207 void setHeight(int h) { _ptr->setHeight(h); }
208
208
209 private:
209 private:
210 PQCppObject* _ptr;
210 PQCppObject* _ptr;
211 };
211 };
212
212
213 class PQCppObjectDecorator : public QObject {
213 class PQCppObjectDecorator : public QObject {
214 Q_OBJECT
214 Q_OBJECT
215 public slots:
215 public slots:
216 int getH(PQCppObject* obj) { return obj->getHeight(); }
216 int getH(PQCppObject* obj) { return obj->getHeight(); }
217
217
218 };
218 };
219
219
220 //! an cpp object to be wrapped by decorators only
220 //! an cpp object to be wrapped by decorators only
221 class PQCppObjectNoWrap {
221 class PQCppObjectNoWrap {
222
222
223 public:
223 public:
224 PQCppObjectNoWrap() { _height = 0; }
224 PQCppObjectNoWrap() { _height = 0; }
225 PQCppObjectNoWrap(int h) { _height = h; }
225 PQCppObjectNoWrap(int h) { _height = h; }
226
226
227 int getHeight() { return _height; }
227 int getHeight() { return _height; }
228 void setHeight(int h) { _height = h; }
228 void setHeight(int h) { _height = h; }
229
229
230 private:
230 private:
231 int _height;
231 int _height;
232 };
232 };
233
233
234 class PQCppObjectNoWrapDecorator : public QObject {
234 class PQCppObjectNoWrapDecorator : public QObject {
235 Q_OBJECT
235 Q_OBJECT
236
236
237 public slots:
237 public slots:
238 PQCppObjectNoWrap* new_PQCppObjectNoWrap() {
238 PQCppObjectNoWrap* new_PQCppObjectNoWrap() {
239 return new PQCppObjectNoWrap(0);
239 return new PQCppObjectNoWrap(0);
240 }
240 }
241 PQCppObjectNoWrap* new_PQCppObjectNoWrap(const PQCppObjectNoWrap& other) {
241 PQCppObjectNoWrap* new_PQCppObjectNoWrap(const PQCppObjectNoWrap& other) {
242 return new PQCppObjectNoWrap(1);
242 return new PQCppObjectNoWrap(1);
243 }
243 }
244 PQCppObjectNoWrap* new_PQCppObjectNoWrap(double value) {
244 PQCppObjectNoWrap* new_PQCppObjectNoWrap(double value) {
245 return new PQCppObjectNoWrap(2);
245 return new PQCppObjectNoWrap(2);
246 }
246 }
247
247
248 int getH(PQCppObjectNoWrap* obj) { return obj->getHeight(); }
248 int getH(PQCppObjectNoWrap* obj) { return obj->getHeight(); }
249
249
250 };
250 };
251
251
252
252
253 //! an cpp object that is to be wrapped by decorators only
253 //! an cpp object that is to be wrapped by decorators only
254 class PQCppObject2 {
254 class PQCppObject2 {
255
255
256 public:
256 public:
257 enum TestEnumFlag {
257 enum TestEnumFlag {
258 TestEnumValue1 = 0,
258 TestEnumValue1 = 0,
259 TestEnumValue2 = 1
259 TestEnumValue2 = 1
260 };
260 };
261
261
262 PQCppObject2() {}
262 PQCppObject2() {}
263
263
264 };
264 };
265
265
266 class PQCppObject2Decorator : public QObject {
266 class PQCppObject2Decorator : public QObject {
267 Q_OBJECT
267 Q_OBJECT
268
268
269 public:
269 public:
270 Q_ENUMS(TestEnumFlag)
270 Q_ENUMS(TestEnumFlag)
271 Q_FLAGS(TestEnum)
271 Q_FLAGS(TestEnum)
272
272
273 enum TestEnumFlag {
273 enum TestEnumFlag {
274 TestEnumValue1 = 0,
274 TestEnumValue1 = 0,
275 TestEnumValue2 = 1
275 TestEnumValue2 = 1
276 };
276 };
277
277
278 Q_DECLARE_FLAGS(TestEnum, TestEnumFlag)
278 Q_DECLARE_FLAGS(TestEnum, TestEnumFlag)
279
279
280 public slots:
280 public slots:
281 PQCppObject2* new_PQCppObject2() {
281 PQCppObject2* new_PQCppObject2() {
282 return new PQCppObject2();
282 return new PQCppObject2();
283 }
283 }
284
284
285 TestEnumFlag testEnumFlag1(PQCppObject2* obj, TestEnumFlag flag);
285 TestEnumFlag testEnumFlag1(PQCppObject2* obj, TestEnumFlag flag);
286
286
287 PQCppObject2::TestEnumFlag testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag);
287 PQCppObject2::TestEnumFlag testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag);
288
288
289 // with int overload
289 // with int overload
290 TestEnumFlag testEnumFlag3(PQCppObject2* obj, int flag);
290 TestEnumFlag testEnumFlag3(PQCppObject2* obj, int flag);
291 TestEnumFlag testEnumFlag3(PQCppObject2* obj, TestEnumFlag flag);
291 TestEnumFlag testEnumFlag3(PQCppObject2* obj, TestEnumFlag flag);
292
292
293 };
293 };
294
294
295 class PQUnknownValueObject
295 class PQUnknownValueObject
296 {
296 {
297 public:
297 public:
298 PQUnknownValueObject() {};
298 PQUnknownValueObject() {};
299 };
299 };
300
300
301 class PQUnknownButRegisteredValueObject
301 class PQUnknownButRegisteredValueObject
302 {
302 {
303 public:
303 public:
304 PQUnknownButRegisteredValueObject() {};
304 PQUnknownButRegisteredValueObject() {};
305 };
305 };
306
306
307 //! test the calling of slots
307 //! test the calling of slots
308 class PythonQtTestSlotCalling : public QObject
308 class PythonQtTestSlotCalling : public QObject
309 {
309 {
310 Q_OBJECT
310 Q_OBJECT
311
311
312 private slots:
312 private slots:
313 void initTestCase();
313 void initTestCase();
314 void init();
314 void init();
315
315
316 void testNoArgSlotCall();
316 void testNoArgSlotCall();
317 void testPODSlotCalls();
317 void testPODSlotCalls();
318 void testCPPSlotCalls();
318 void testCPPSlotCalls();
319 void testQVariantSlotCalls();
319 void testQVariantSlotCalls();
320 void testObjectSlotCalls();
320 void testObjectSlotCalls();
321 void testMultiArgsSlotCall();
321 void testMultiArgsSlotCall();
322 void testPyObjectSlotCall();
322 void testPyObjectSlotCall();
323 void testOverloadedCall();
323 void testOverloadedCall();
324 void testCppFactory();
324 void testCppFactory();
325 void testInheritance();
325 void testInheritance();
326 void testAutoConversion();
326 void testAutoConversion();
327
327
328 private:
328 private:
329 PythonQtTestSlotCallingHelper* _helper;
329 PythonQtTestSlotCallingHelper* _helper;
330
330
331 };
331 };
332
332
333 //! helper class for slot calling test
333 //! helper class for slot calling test
334 class PythonQtTestSlotCallingHelper : public QObject
334 class PythonQtTestSlotCallingHelper : public QObject
335 {
335 {
336 Q_OBJECT
336 Q_OBJECT
337 public:
337 public:
338 PythonQtTestSlotCallingHelper(PythonQtTestSlotCalling* test) {
338 PythonQtTestSlotCallingHelper(PythonQtTestSlotCalling* test) {
339 _test = test;
339 _test = test;
340 };
340 };
341
341
342 bool runScript(const char* script, int expectedOverload = -1);
342 bool runScript(const char* script, int expectedOverload = -1);
343
343
344 public slots:
344 public slots:
345
345
346 //! call to set that the test has passed (from Python!)
346 //! call to set that the test has passed (from Python!)
347 void setPassed() { _passed = true; }
347 void setPassed() { _passed = true; }
348
348
349 //! no arguments, no return value:
349 //! no arguments, no return value:
350 void testNoArg() { _called = true; }
350 void testNoArg() { _called = true; }
351
351
352 //! overload test!
352 //! overload test!
353 void overload(bool a) { _calledOverload = 0; _called = true; }
353 void overload(bool a) { _calledOverload = 0; _called = true; }
354 void overload(float a) { _calledOverload = 1; _called = true;}
354 void overload(float a) { _calledOverload = 1; _called = true;}
355 void overload(int a) { _calledOverload = 2; _called = true;}
355 void overload(int a) { _calledOverload = 2; _called = true;}
356 void overload(const QString& str) { _calledOverload = 3; _called = true;}
356 void overload(const QString& str) { _calledOverload = 3; _called = true;}
357 void overload(const QStringList& str) { _calledOverload = 4; _called = true;}
357 void overload(const QStringList& str) { _calledOverload = 4; _called = true;}
358 void overload(QObject* str) { _calledOverload = 5; _called = true;}
358 void overload(QObject* str) { _calledOverload = 5; _called = true;}
359 void overload(float a, int b) { _calledOverload = 6; _called = true;}
359 void overload(float a, int b) { _calledOverload = 6; _called = true;}
360
360
361 //! POD values:
361 //! POD values:
362 int getInt(int a) { _called = true; return a; }
362 int getInt(int a) { _called = true; return a; }
363 unsigned int getUInt(unsigned int a) { _called = true; return a; }
363 unsigned int getUInt(unsigned int a) { _called = true; return a; }
364 bool getBool(bool a) { _called = true; return a; }
364 bool getBool(bool a) { _called = true; return a; }
365 char getChar(char a) { _called = true; return a; }
365 char getChar(char a) { _called = true; return a; }
366 unsigned char getUChar(unsigned char a) { _called = true; return a; }
366 unsigned char getUChar(unsigned char a) { _called = true; return a; }
367 long getLong(long a) { _called = true; return a; }
367 long getLong(long a) { _called = true; return a; }
368 unsigned long getULong(unsigned long a) { _called = true; return a; }
368 unsigned long getULong(unsigned long a) { _called = true; return a; }
369 short getShort(short a) { _called = true; return a; }
369 short getShort(short a) { _called = true; return a; }
370 unsigned short getUShort(unsigned short a) { _called = true; return a; }
370 unsigned short getUShort(unsigned short a) { _called = true; return a; }
371 QChar getQChar(QChar a) { _called = true; return a; }
371 QChar getQChar(QChar a) { _called = true; return a; }
372 qint64 getLongLong(qint64 a) { _called = true; return a; }
372 qint64 getLongLong(qint64 a) { _called = true; return a; }
373 quint64 getULongLong(quint64 a) { _called = true; return a; }
373 quint64 getULongLong(quint64 a) { _called = true; return a; }
374 double getDouble(double d) { _called = true; return d; }
374 double getDouble(double d) { _called = true; return d; }
375 float getFloat(float d) { _called = true; return d; }
375 float getFloat(float d) { _called = true; return d; }
376
376
377 //! important qt types:
377 //! important qt types:
378 QString getQString(const QString& s) { _called = true; return s; }
378 QString getQString(const QString& s) { _called = true; return s; }
379 QStringList getQStringList(const QStringList& l) { _called = true; return l; }
379 QStringList getQStringList(const QStringList& l) { _called = true; return l; }
380 QVariant getQVariant(const QVariant& var) { _called = true; return var; }
380 QVariant getQVariant(const QVariant& var) { _called = true; return var; }
381
381
382 // QColor as representative for C++ value classes
382 // QColor as representative for C++ value classes
383 QColor getQColor1(const QColor& var) { _called = true; return var; }
383 QColor getQColor1(const QColor& var) { _called = true; return var; }
384 QColor getQColor2(QColor& var) { _called = true; return var; }
384 QColor getQColor2(QColor& var) { _called = true; return var; }
385 QColor getQColor3(QColor* col) { _called = true; return *col; }
385 QColor getQColor3(QColor* col) { _called = true; return *col; }
386 QColor getQColor4(const QVariant& color) { _called = true; return qVariantValue<QColor>(color); }
386 QColor getQColor4(const QVariant& color) { _called = true; return qVariantValue<QColor>(color); }
387 QColor* getQColor5() { _called = true; static QColor c(1,2,3); return &c; }
387 QColor* getQColor5() { _called = true; static QColor c(1,2,3); return &c; }
388
388
389 PyObject* getPyObject(PyObject* obj) { _called = true; return obj; }
389 PyObject* getPyObject(PyObject* obj) { _called = true; return obj; }
390 PyObject* getPyObjectFromVariant(const QVariant& val) { _called = true; return PythonQtObjectPtr(val); };
390 PyObject* getPyObjectFromVariant(const QVariant& val) { _called = true; return PythonQtObjectPtr(val); };
391 QVariant getPyObjectFromVariant2(const QVariant& val) { _called = true; return val; };
391 QVariant getPyObjectFromVariant2(const QVariant& val) { _called = true; return val; };
392 // this does not yet work but is not required to work:
392 // this does not yet work but is not required to work:
393 //PyObject* getPyObjectFromPtr(const PythonQtObjectPtr& val) { _called = true; return val; };
393 //PyObject* getPyObjectFromPtr(const PythonQtObjectPtr& val) { _called = true; return val; };
394
394
395 //! testing pointer passing
395 //! testing pointer passing
396 PythonQtTestSlotCallingHelper* getTestObject(PythonQtTestSlotCallingHelper* obj) { _called = true; return obj; }
396 PythonQtTestSlotCallingHelper* getTestObject(PythonQtTestSlotCallingHelper* obj) { _called = true; return obj; }
397 //! testing inheritance checking
397 //! testing inheritance checking
398 QObject* getQObject(QObject* obj) { _called = true; return obj; }
398 QObject* getQObject(QObject* obj) { _called = true; return obj; }
399 QWidget* getQWidget(QWidget* obj) { _called = true; return obj; }
399 QWidget* getQWidget(QWidget* obj) { _called = true; return obj; }
400 //! testing if an object that was not wrapped is wrapped earlier is wrapped correctly
400 //! testing if an object that was not wrapped is wrapped earlier is wrapped correctly
401 QObject* getNewObject() { _called = true; return new PythonQtTestSlotCallingHelper(NULL); }
401 QObject* getNewObject() { _called = true; return new PythonQtTestSlotCallingHelper(NULL); }
402
402
403 QVariantList getMultiArgs(int a, double b, const QString& str) { _called = true; return (QVariantList() << a << b << str); }
403 QVariantList getMultiArgs(int a, double b, const QString& str) { _called = true; return (QVariantList() << a << b << str); }
404
404
405 //! cpp wrapper factory test
405 //! cpp wrapper factory test
406 PQCppObject* createPQCppObject(int h) { _called = true; return new PQCppObject(h); }
406 PQCppObject* createPQCppObject(int h) { _called = true; return new PQCppObject(h); }
407
407
408 //! cpp wrapper factory test
408 //! cpp wrapper factory test
409 PQCppObject* getPQCppObject(PQCppObject* p) { _called = true; return p; }
409 PQCppObject* getPQCppObject(PQCppObject* p) { _called = true; return p; }
410
410
411 //! cpp wrapper factory test
411 //! cpp wrapper factory test
412 PQCppObjectNoWrap* createPQCppObjectNoWrap(int h) { _called = true; return new PQCppObjectNoWrap(h); }
412 PQCppObjectNoWrap* createPQCppObjectNoWrap(int h) { _called = true; return new PQCppObjectNoWrap(h); }
413
413
414 //! cpp wrapper factory test
414 //! cpp wrapper factory test
415 PQCppObjectNoWrap* getPQCppObjectNoWrap(PQCppObjectNoWrap* p) { _called = true; return p; }
415 PQCppObjectNoWrap* getPQCppObjectNoWrap(PQCppObjectNoWrap* p) { _called = true; return p; }
416
416
417 //! get a return by value PQCppObjectNoWrap
417 //! get a return by value PQCppObjectNoWrap
418 PQCppObjectNoWrap getPQCppObjectNoWrapAsValue() { _called = true; return PQCppObjectNoWrap(47); }
418 PQCppObjectNoWrap getPQCppObjectNoWrapAsValue() { _called = true; return PQCppObjectNoWrap(47); }
419
419
420 PQUnknownButRegisteredValueObject getUnknownButRegisteredValueObjectAsValue() { _called = true; return PQUnknownButRegisteredValueObject(); }
420 PQUnknownButRegisteredValueObject getUnknownButRegisteredValueObjectAsValue() { _called = true; return PQUnknownButRegisteredValueObject(); }
421 PQUnknownValueObject getUnknownValueObjectAsValue() { _called = true; return PQUnknownValueObject(); }
421 PQUnknownValueObject getUnknownValueObjectAsValue() { _called = true; return PQUnknownValueObject(); }
422
422
423 PQUnknownButRegisteredValueObject* getUnknownButRegisteredValueObjectAsPtr() { _called = true; return new PQUnknownButRegisteredValueObject(); }
423 PQUnknownButRegisteredValueObject* getUnknownButRegisteredValueObjectAsPtr() { _called = true; return new PQUnknownButRegisteredValueObject(); }
424 PQUnknownValueObject* getUnknownValueObjectAsPtr() { _called = true; return new PQUnknownValueObject(); }
424 PQUnknownValueObject* getUnknownValueObjectAsPtr() { _called = true; return new PQUnknownValueObject(); }
425
425
426 ClassA* getClassAPtr(ClassA* o) { _called = true; return o; }
426 ClassA* getClassAPtr(ClassA* o) { _called = true; return o; }
427 ClassB* getClassBPtr(ClassB* o) { _called = true; return o; }
427 ClassB* getClassBPtr(ClassB* o) { _called = true; return o; }
428 ClassC* getClassCPtr(ClassC* o) { _called = true; return o; }
428 ClassC* getClassCPtr(ClassC* o) { _called = true; return o; }
429 ClassD* getClassDPtr(ClassD* o) { _called = true; return o; }
429 ClassD* getClassDPtr(ClassD* o) { _called = true; return o; }
430
430
431 ClassA* createClassA() { _called = true; return new ClassA; }
431 ClassA* createClassA() { _called = true; return new ClassA; }
432 ClassB* createClassB() { _called = true; return new ClassB; }
432 ClassB* createClassB() { _called = true; return new ClassB; }
433 ClassC* createClassC() { _called = true; return new ClassC; }
433 ClassC* createClassC() { _called = true; return new ClassC; }
434 ClassD* createClassD() { _called = true; return new ClassD; }
434 ClassD* createClassD() { _called = true; return new ClassD; }
435 ClassA* createClassCAsA() { _called = true; return new ClassC; }
435 ClassA* createClassCAsA() { _called = true; return new ClassC; }
436 ClassB* createClassCAsB() { _called = true; return new ClassC; }
436 ClassB* createClassCAsB() { _called = true; return new ClassC; }
437 ClassA* createClassDAsA() { _called = true; return new ClassD; }
437 ClassA* createClassDAsA() { _called = true; return new ClassD; }
438 ClassB* createClassDAsB() { _called = true; return new ClassD; }
438 ClassB* createClassDAsB() { _called = true; return new ClassD; }
439
439
440 QColor setAutoConvertColor(const QColor& color) { _called = true; return color; };
440 QColor setAutoConvertColor(const QColor& color) { _called = true; return color; };
441 QBrush setAutoConvertBrush(const QBrush& brush) { _called = true; return brush; };
441 QBrush setAutoConvertBrush(const QBrush& brush) { _called = true; return brush; };
442 QPen setAutoConvertPen(const QPen& pen) { _called = true; return pen; };
442 QPen setAutoConvertPen(const QPen& pen) { _called = true; return pen; };
443 QCursor setAutoConvertCursor(const QCursor& cursor) { _called = true; return cursor; };
443 QCursor setAutoConvertCursor(const QCursor& cursor) { _called = true; return cursor; };
444
444
445 private:
445 private:
446 bool _passed;
446 bool _passed;
447 bool _called;
447 bool _called;
448 int _calledOverload;
448 int _calledOverload;
449 PythonQtTestSlotCalling* _test;
449 PythonQtTestSlotCalling* _test;
450 };
450 };
451
451
452 class PythonQtTestSignalHandlerHelper;
452 class PythonQtTestSignalHandlerHelper;
453
453
454 //! test the connection of signals to python
454 //! test the connection of signals to python
455 class PythonQtTestSignalHandler : public QObject
455 class PythonQtTestSignalHandler : public QObject
456 {
456 {
457 Q_OBJECT
457 Q_OBJECT
458
458
459 private slots:
459 private slots:
460 void initTestCase();
460 void initTestCase();
461
461
462 void testSignalHandler();
462 void testSignalHandler();
463 void testRecursiveSignalHandler();
463 void testRecursiveSignalHandler();
464
464
465 private:
465 private:
466 PythonQtTestSignalHandlerHelper* _helper;
466 PythonQtTestSignalHandlerHelper* _helper;
467
467
468 };
468 };
469
469
470 //! helper class for signal testing
470 //! helper class for signal testing
471 class PythonQtTestSignalHandlerHelper : public QObject
471 class PythonQtTestSignalHandlerHelper : public QObject
472 {
472 {
473 Q_OBJECT
473 Q_OBJECT
474
474
475 public:
475 public:
476 PythonQtTestSignalHandlerHelper(PythonQtTestSignalHandler* test) {
476 PythonQtTestSignalHandlerHelper(PythonQtTestSignalHandler* test) {
477 _test = test;
477 _test = test;
478 };
478 };
479
479
480 public slots:
480 public slots:
481 void setPassed() { _passed = true; }
481 void setPassed() { _passed = true; }
482
482
483 bool emitIntSignal(int a) { _passed = false; emit intSignal(a); return _passed; };
483 bool emitIntSignal(int a) { _passed = false; emit intSignal(a); return _passed; };
484 bool emitFloatSignal(float a) { _passed = false; emit floatSignal(a); return _passed; };
484 bool emitFloatSignal(float a) { _passed = false; emit floatSignal(a); return _passed; };
485 bool emitEnumSignal(PQCppObject2::TestEnumFlag flag) { _passed = false; emit enumSignal(flag); return _passed; };
485 bool emitEnumSignal(PQCppObject2::TestEnumFlag flag) { _passed = false; emit enumSignal(flag); return _passed; };
486
486
487 bool emitVariantSignal(const QVariant& v) { _passed = false; emit variantSignal(v); return _passed; };
487 bool emitVariantSignal(const QVariant& v) { _passed = false; emit variantSignal(v); return _passed; };
488 QVariant expectedVariant() { return _v; }
488 QVariant expectedVariant() { return _v; }
489 void setExpectedVariant(const QVariant& v) { _v = v; }
489 void setExpectedVariant(const QVariant& v) { _v = v; }
490
490
491 bool emitComplexSignal(int a, float b, const QStringList& l, QObject* obj) { _passed = false; emit complexSignal(a,b,l,obj); return _passed; };
491 bool emitComplexSignal(int a, float b, const QStringList& l, QObject* obj) { _passed = false; emit complexSignal(a,b,l,obj); return _passed; };
492
492
493 bool emitSignal1(int a) { _passed = false; emit signal1(a); return _passed; };
493 bool emitSignal1(int a) { _passed = false; emit signal1(a); return _passed; };
494 bool emitSignal2(const QString& s) { _passed = false; emit signal2(s); return _passed; };
494 bool emitSignal2(const QString& s) { _passed = false; emit signal2(s); return _passed; };
495 bool emitSignal3(float a) { _passed = false; emit signal3(a); return _passed; };
495 bool emitSignal3(float a) { _passed = false; emit signal3(a); return _passed; };
496
496
497 signals:
497 signals:
498 void intSignal(int);
498 void intSignal(int);
499 void floatSignal(float);
499 void floatSignal(float);
500 void variantSignal(const QVariant& v);
500 void variantSignal(const QVariant& v);
501 void complexSignal(int a, float b, const QStringList& l, QObject* obj);
501 void complexSignal(int a, float b, const QStringList& l, QObject* obj);
502 void enumSignal(PQCppObject2::TestEnumFlag flag);
502 void enumSignal(PQCppObject2::TestEnumFlag flag);
503
503
504 void signal1(int);
504 void signal1(int);
505 void signal2(const QString&);
505 void signal2(const QString&);
506 void signal3(float);
506 void signal3(float);
507
507
508 private:
508 private:
509 bool _passed;
509 bool _passed;
510 QVariant _v;
510 QVariant _v;
511
511
512 PythonQtTestSignalHandler* _test;
512 PythonQtTestSignalHandler* _test;
513 };
513 };
514
514
515 #endif
515 #endif
General Comments 0
You need to be logged in to leave comments. Login now