File 0001-Implemented_the_PyQt5_signal_emitters.patch of Package python-sip.2072
# HG changeset patch
# User Phil Thompson <phil@riverbankcomputing.com>
# Date 1392749782 0
# Node ID 4fc63f9adb4402f38d012b0c18c85b74dc0f7f2d
# Parent b96a5e69adb6f2243f8079b5381b4a6a28f86468
Implemented the PyQt5 signal emitters.
diff -r b96a5e69adb6 -r 4fc63f9adb44 sipgen/gencode.c
--- a/sipgen/gencode.c Tue Feb 18 13:54:02 2014 +0000
+++ b/sipgen/gencode.c Tue Feb 18 18:56:22 2014 +0000
@@ -124,8 +124,10 @@
static void generateNamedBaseType(ifaceFileDef *, argDef *, const char *, int,
FILE *);
static void generateTupleBuilder(moduleDef *, signatureDef *, FILE *);
-static void generateEmitters(moduleDef *mod, classDef *cd, FILE *fp);
-static void generateEmitter(moduleDef *, classDef *, visibleList *, FILE *);
+static void generatePyQt3Emitters(moduleDef *mod, classDef *cd, FILE *fp);
+static void generatePyQt3Emitter(moduleDef *, classDef *, visibleList *,
+ FILE *);
+static void generatePyQt5Emitters(moduleDef *mod, classDef *cd, FILE *fp);
static void generateVirtualHandler(moduleDef *mod, virtHandlerDef *vhd,
FILE *fp);
static void generateDefaultInstanceReturn(argDef *res, const char *indent,
@@ -256,7 +258,7 @@
static const char *resultOwner(overDef *od);
static void prCachedName(FILE *fp, nameDef *nd, const char *prefix);
static void generateSignalTableEntry(sipSpec *pt, classDef *cd, overDef *sig,
- memberDef *md, int membernr, FILE *fp);
+ memberDef *md, int membernr, int optional_args, FILE *fp);
static void generateTypesTable(sipSpec *pt, moduleDef *mod, FILE *fp);
static int py2OnlySlot(slotType st);
static int py2_5LaterSlot(slotType st);
@@ -279,6 +281,7 @@
static void generatePreprocLine(int linenr, const char *fname, FILE *fp);
static virtErrorHandler *getVirtErrorHandler(sipSpec *pt, overDef *od,
classDef *cd, moduleDef *mod);
+static int hasOptionalArgs(overDef *od);
/*
@@ -6668,14 +6671,14 @@
/* Generate the emitters if needed. */
if (pluginPyQt3(pt))
- generateEmitters(mod, cd, fp);
-}
-
-
-/*
- * Generate the emitter functions.
- */
-static void generateEmitters(moduleDef *mod, classDef *cd, FILE *fp)
+ generatePyQt3Emitters(mod, cd, fp);
+}
+
+
+/*
+ * Generate the PyQt3 emitter functions.
+ */
+static void generatePyQt3Emitters(moduleDef *mod, classDef *cd, FILE *fp)
{
int noIntro;
visibleList *vl;
@@ -6687,7 +6690,7 @@
for (od = vl->cd->overs; od != NULL; od = od->next)
if (od->common == vl->m && isSignal(od))
{
- generateEmitter(mod, cd, vl, fp);
+ generatePyQt3Emitter(mod, cd, vl, fp);
break;
}
}
@@ -7346,9 +7349,9 @@
/*
- * Generate the emitter function for a signal.
- */
-static void generateEmitter(moduleDef *mod, classDef *cd, visibleList *vl,
+ * Generate the PyQt3 emitter function for a signal.
+ */
+static void generatePyQt3Emitter(moduleDef *mod, classDef *cd, visibleList *vl,
FILE *fp)
{
const char *pname = vl->m->pyname->text;
@@ -9632,7 +9635,7 @@
nr_methods = generateClassMethodTable(pt, cd, fp);
nr_enums = generateEnumMemberTable(pt, mod, cd, NULL, fp);
- /* Generate the PyQt4 signals table. */
+ /* Generate the PyQt4/5 signals table. */
is_signals = FALSE;
if ((pluginPyQt4(pt) || pluginPyQt5(pt)) && isQObjectSubClass(cd))
@@ -9647,9 +9650,6 @@
for (od = cd->overs; od != NULL; od = od->next)
{
- int a, nr_args;
- signatureDef *cppsig;
-
if (od->common != md || !isSignal(od))
continue;
@@ -9671,6 +9671,9 @@
{
is_signals = TRUE;
+ if (pluginPyQt5(pt))
+ generatePyQt5Emitters(mod, cd, fp);
+
prcode(fp,
"\n"
"\n"
@@ -9680,26 +9683,37 @@
}
/*
- * Default arguments are handled as multiple signals. We make
- * sure the largest is first and the smallest last which is
- * what Qt does.
+ * For PyQt4 optional arguments are handled as multiple
+ * signals. We make sure the largest is first and the smallest
+ * last which is what Qt does. For PyQt5 we only include the
+ * version with all arguments and provide an emitter function
+ * which handles the optional arguments.
*/
- cppsig = od->cppsig;
- nr_args = cppsig->nrArgs;
-
- generateSignalTableEntry(pt, cd, od, md, membernr, fp);
+ generateSignalTableEntry(pt, cd, od, md, membernr,
+ hasOptionalArgs(od), fp);
+
membernr = -1;
- for (a = nr_args - 1; a >= 0; --a)
+ if (pluginPyQt4(pt))
{
- if (cppsig->args[a].defval == NULL)
- break;
-
- cppsig->nrArgs = a;
- generateSignalTableEntry(pt, cd, od, md, -1, fp);
+ int a, nr_args;
+ signatureDef *cppsig;
+
+ cppsig = od->cppsig;
+ nr_args = cppsig->nrArgs;
+
+ for (a = nr_args - 1; a >= 0; --a)
+ {
+ if (cppsig->args[a].defval == NULL)
+ break;
+
+ cppsig->nrArgs = a;
+ generateSignalTableEntry(pt, cd, od, md, -1, FALSE,
+ fp);
+ }
+
+ cppsig->nrArgs = nr_args;
}
-
- cppsig->nrArgs = nr_args;
}
}
@@ -10354,12 +10368,110 @@
/*
- * Generate an entry in the PyQt4 signal table.
+ * See if an overload has optional arguments.
+ */
+static int hasOptionalArgs(overDef *od)
+{
+ return (od->cppsig->nrArgs > 0 && od->cppsig->args[od->cppsig->nrArgs - 1].defval != NULL);
+}
+
+
+/*
+ * Generate the PyQt5 emitters for a class.
+ */
+static void generatePyQt5Emitters(moduleDef *mod, classDef *cd, FILE *fp)
+{
+ memberDef *md;
+
+ for (md = cd->members; md != NULL; md = md->next)
+ {
+ int in_emitter = FALSE;
+ overDef *od;
+
+ for (od = cd->overs; od != NULL; od = od->next)
+ {
+ if (od->common != md || !isSignal(od) || !hasOptionalArgs(od))
+ continue;
+
+ if (!in_emitter)
+ {
+ in_emitter = TRUE;
+
+ prcode(fp,
+"\n"
+"\n"
+ );
+
+ if (!generating_c)
+ prcode(fp,
+"extern \"C\" {static int emit_%L_%s(void *, PyObject *);}\n"
+"\n"
+ , cd->iff, od->cppname);
+
+ prcode(fp,
+"static int emit_%L_%s(void *sipCppV, PyObject *sipArgs)\n"
+"{\n"
+" PyObject *sipParseErr = NULL;\n"
+" %C *sipCpp = reinterpret_cast<%C *>(sipCppV);\n"
+ , cd->iff, od->cppname
+ , classFQCName(cd), classFQCName(cd));
+ }
+
+ /*
+ * Generate the code that parses the args and emits the appropriate
+ * overloaded signal.
+ */
+ prcode(fp,
+"\n"
+" {\n"
+ );
+
+ generateArgParser(mod, &od->pysig, cd, NULL, NULL, NULL, FALSE, fp);
+
+ prcode(fp,
+" {\n"
+" Py_BEGIN_ALLOW_THREADS\n"
+" sipCpp->%s("
+ , od->cppname);
+
+ generateCallArgs(mod, od->cppsig, &od->pysig, fp);
+
+ prcode(fp, ");\n"
+" Py_END_ALLOW_THREADS\n"
+"\n"
+ );
+
+ deleteTemps(mod, &od->pysig, fp);
+
+ prcode(fp,
+"\n"
+" return 0;\n"
+" }\n"
+" }\n"
+ );
+ }
+
+ if (in_emitter)
+ {
+ prcode(fp,
+"\n"
+" sipNoMethod(sipParseErr, %N, %N, NULL);\n"
+"\n"
+" return -1;\n"
+"}\n"
+ , cd->pyname, md->pyname);
+ }
+ }
+}
+
+
+/*
+ * Generate an entry in the PyQt4 or PyQt5 signal table.
*/
static void generateSignalTableEntry(sipSpec *pt, classDef *cd, overDef *sig,
- memberDef *md, int membernr, FILE *fp)
-{
- int a;
+ memberDef *md, int membernr, int optional_args, FILE *fp)
+{
+ int a, pyqt5 = pluginPyQt5(pt);
prcode(fp,
" {\"%s(", sig->cppname);
@@ -10411,8 +10523,11 @@
else
prcode(fp, "0");
- if (pluginPyQt5(pt))
- prcode(fp, ", 0");
+ if (pyqt5)
+ if (optional_args)
+ prcode(fp, ", emit_%L_%s", cd->iff, sig->cppname);
+ else
+ prcode(fp, ", 0");
prcode(fp,"},\n"
);
diff -r b96a5e69adb6 -r 4fc63f9adb44 siplib/sip.h.in.in
--- a/siplib/sip.h.in Tue Feb 18 13:54:02 2014 +0000
+++ b/siplib/sip.h.in Tue Feb 18 18:56:22 2014 +0000
@@ -1757,13 +1757,10 @@
/*
* The description of a Qt signal for PyQt5.
*/
-typedef PyObject *(*pyqt5EmitFunc)(sipSimpleWrapper *, PyObject *);
+typedef int (*pyqt5EmitFunc)(void *, PyObject *);
typedef struct _pyqt5QtSignal {
- /*
- * The normalised C++ name and signature of the signal that would be
- * returned by SIGNAL().
- */
+ /* The normalised C++ name and signature of the signal. */
const char *signature;
/* The optional docstring. */