Create a global namespace wrapper for each package if required · MeVisLab/pythonqt@e9197ec · GitHub
Skip to content

Commit e9197ec

Browse files
usiemsmrbean-bremen
authored andcommitted
Create a global namespace wrapper for each package if required
This currently just contains global enums. The content of these wrappers will be added to the current package, and to the "Qt" package. Also look in global namespace wrappers for scope-less enum types
1 parent 182df8d commit e9197ec

11 files changed

Lines changed: 140 additions & 32 deletions

generator/abstractmetabuilder.cpp

Lines changed: 28 additions & 21 deletions

generator/abstractmetabuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ class AbstractMetaBuilder
149149
private:
150150
void sortLists();
151151

152+
AbstractMetaClass* getGlobalNamespace(const TypeEntry* typeEntry);
153+
152154
QString m_file_name;
153155

154156
AbstractMetaClassList m_meta_classes;

generator/abstractmetalang.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ class AbstractMetaClass : public AbstractMetaAttributes
676676
m_has_clone_operator(false),
677677
m_is_type_alias(false),
678678
m_has_actual_declaration(false),
679+
m_is_global_namespace(false),
679680
m_qDebug_stream_function(0)
680681
{
681682
}
@@ -801,6 +802,9 @@ class AbstractMetaClass : public AbstractMetaAttributes
801802
void setHasActualDeclaration(bool on) { m_has_actual_declaration = on; }
802803
bool hasActualDeclaration() const { return m_has_actual_declaration; }
803804

805+
void setIsGlobalNamespace(bool on) { m_is_global_namespace = on; }
806+
bool isGlobalNamespace() const { return m_is_global_namespace; }
807+
804808
QString getDefaultNonZeroFunction() const;
805809

806810
void addPropertySpec(QPropertySpec *spec) { m_property_specs << spec; }
@@ -862,7 +866,8 @@ class AbstractMetaClass : public AbstractMetaAttributes
862866
uint m_has_clone_operator :1;
863867
uint m_is_type_alias : 1;
864868
uint m_has_actual_declaration : 1;
865-
uint m_reserved : 17;
869+
uint m_is_global_namespace : 1;
870+
uint m_reserved : 16;
866871
QString m_destructor_exception;
867872

868873
const AbstractMetaClass *m_enclosing_class{};

generator/setupgenerator.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ void SetupGenerator::generate()
337337
}
338338
if (cls->isQObject()) {
339339
s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << qtPackageName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;
340+
} else if (cls->isGlobalNamespace()) {
341+
s << "PythonQt::priv()->registerGlobalNamespace(\"" << cls->qualifiedCppName() << "\", \"" << qtPackageName << "\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">, PythonQtWrapper_" << cls->name() << "::staticMetaObject, module); " << endl;
340342
} else {
341343
QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():"";
342344
s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << qtPackageName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;

generator/shellgenerator.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@
5050
bool ShellGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
5151
{
5252
uint cg = meta_class->typeEntry()->codeGeneration();
53-
// ignore the "Global" namespace, which contains the QtMsgType enum
54-
if (meta_class->name().startsWith("Global")) return false;
5553
return ((cg & TypeEntry::GenerateCode) != 0);
5654
}
5755

generator/shellheadergenerator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,8 @@ void ShellHeaderGenerator::write(QTextStream& s, const AbstractMetaClass* meta_c
312312
bool isEnumClass = enum1->typeEntry()->isEnumClass();
313313
s << "enum " << (isEnumClass ? "class " : "") << enum1->name() << "{" << endl;
314314
bool first = true;
315-
QString scope = enum1->wasProtected() ? promoterClassName(meta_class) : meta_class->qualifiedCppName();
315+
QString scope = meta_class->isGlobalNamespace() ? QString() :
316+
(enum1->wasProtected() ? promoterClassName(meta_class) : meta_class->qualifiedCppName());
316317
if (isEnumClass) {
317318
scope += "::" + enum1->name();
318319
}

generator/typesystem.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,8 +1835,9 @@ FlagsTypeEntry *TypeDatabase::findFlagsType(const QString &name) const
18351835
return fte ? fte : (FlagsTypeEntry *) m_flags_entries.value(name);
18361836
}
18371837

1838-
QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) {
1839-
return QLatin1String("Global");
1838+
QString TypeDatabase::globalNamespaceClassName(const TypeEntry * entry)
1839+
{
1840+
return "Qt" + entry->javaPackage().split('.').back();
18401841
}
18411842

18421843

src/PythonQt.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,73 @@ void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentT
20602060
}
20612061
}
20622062

2063+
namespace {
2064+
2065+
void addObjectToPackage(PyObject* obj, const char* name, const char* packageName, PyObject* package)
2066+
{
2067+
if (PyModule_AddObject(package, name, obj) < 0) {
2068+
Py_DECREF(obj);
2069+
std::cerr << "failed to add " << name << " to " << packageName << "\n";
2070+
}
2071+
}
2072+
2073+
};
2074+
2075+
void PythonQtPrivate::registerGlobalNamespace(const char* typeName, const char* packageName, PythonQtQObjectCreatorFunctionCB* wrapperCreator, const QMetaObject& metaObject, PyObject* module)
2076+
{
2077+
registerCPPClass(typeName, "", packageName, wrapperCreator, nullptr, module, 0);
2078+
2079+
PyObject* package = module ? module : PythonQt::priv()->packageByName(packageName);
2080+
PythonQtClassInfo* classInfo = PythonQt::priv()->getClassInfo(typeName);
2081+
PyObject* globalNamespace = classInfo->pythonQtClassWrapper();
2082+
2083+
// Collect the names of global methods
2084+
QSet<QByteArray> methodNames;
2085+
for (int i = metaObject.methodOffset(); i < metaObject.methodCount(); i++) {
2086+
methodNames.insert(metaObject.method(i).name());
2087+
}
2088+
QByteArray staticPrefix = "static_" + QByteArray(typeName) + "_"; // every static method starts with this string
2089+
for (auto name: methodNames) {
2090+
if (name.startsWith(staticPrefix)) { // non-static methods wouldn't work (and should not exists)
2091+
name = name.mid(staticPrefix.length());
2092+
PyObject* obj = PyObject_GetAttrString(globalNamespace, name.constData());
2093+
if (obj) {
2094+
addObjectToPackage(obj, name, packageName, package);
2095+
}
2096+
else {
2097+
std::cerr << "method not found " << name.constData() << " in " << typeName << std::endl;
2098+
}
2099+
}
2100+
}
2101+
2102+
// Global enums
2103+
for (int i = metaObject.enumeratorOffset(); i < metaObject.enumeratorCount(); i++) {
2104+
QMetaEnum metaEnum = metaObject.enumerator(i);
2105+
PyObject* obj = PyObject_GetAttrString(globalNamespace, metaEnum.name());
2106+
if (obj) {
2107+
addObjectToPackage(obj, metaEnum.name(), packageName, package);
2108+
}
2109+
else {
2110+
std::cerr << "enum type not found " << metaEnum.name() << " in " << typeName << std::endl;
2111+
}
2112+
#if QT_VERSION > 0x050800
2113+
bool isScoped = metaEnum.isScoped();
2114+
#else
2115+
bool isScoped = false;
2116+
#endif
2117+
if (!isScoped) {
2118+
for (int j = 0; j < metaEnum.keyCount(); j++) {
2119+
QByteArray key = PythonQtClassInfo::escapeReservedNames(metaEnum.key(j));
2120+
int value = metaEnum.value(j);
2121+
PyObject* obj = PyInt_FromLong(value);
2122+
addObjectToPackage(obj, key, packageName, package);
2123+
}
2124+
}
2125+
}
2126+
2127+
PythonQtClassInfo::addGlobalNamespaceWrapper(classInfo);
2128+
}
2129+
20632130
PyObject* PythonQtPrivate::packageByName(const char* name)
20642131
{
20652132
if (name==nullptr || name[0]==0) {

src/PythonQt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,9 @@ class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
742742
*/
743743
void registerCPPClass(const char* typeName, const char* parentTypeName = nullptr, const char* package = nullptr, PythonQtQObjectCreatorFunctionCB* wrapperCreator = nullptr, PythonQtShellSetInstanceWrapperCB* shell = nullptr, PyObject* module = nullptr, int typeSlots = 0);
744744

745+
//! Same as above, but all enums of the created wrapper will also be added to the given package and to the "Qt" package
746+
void registerGlobalNamespace(const char* typeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, const QMetaObject& metaObject, PyObject* module = nullptr);
747+
745748
//! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
746749
//! and it will register the classes when it first sees a pointer to such a derived class
747750
void registerQObjectClassNames(const QStringList& names);

src/PythonQtClassInfo.cpp

Lines changed: 20 additions & 3 deletions

0 commit comments

Comments
 (0)