Skip to content

Commit fb8edea

Browse files
committedMay 19, 2017
[sipify] implement template inheritance
1 parent bbcc872 commit fb8edea

File tree

8 files changed

+155
-123
lines changed

8 files changed

+155
-123
lines changed
 

‎python/core/core.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
%Include qgsobjectcustomproperties.sip
114114
%Include qgsofflineediting.sip
115115
%Include qgsogcutils.sip
116+
%Include qgsoptional.sip
116117
%Include qgsoptionalexpression.sip
117118
%Include qgsowsconnection.sip
118119
%Include qgspaintenginehack.sip

‎python/core/qgsoptional.sip

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/core/qgsoptional.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
template<T>
12+
class QgsOptional
13+
{
14+
%Docstring
15+
16+
QgsOptional is a container for other classes and adds an additional enabled/disabled flag.
17+
18+
Often it is used for configuration options which can be enabled or disabled but also have
19+
more internal configuration information that should not be lost when disabling and re-enabling.
20+
21+
.. versionadded:: 3.0
22+
%End
23+
24+
%TypeHeaderCode
25+
#include "qgsoptional.h"
26+
%End
27+
public:
28+
29+
QgsOptional();
30+
%Docstring
31+
A QgsOptional is disabled by default if default constructed.
32+
%End
33+
34+
QgsOptional( const T &data );
35+
%Docstring
36+
A QgsOptional is enabled by default if constructed with payload.
37+
%End
38+
39+
QgsOptional( const T &data, bool enabled );
40+
%Docstring
41+
A QgsOptional constructed with enabled status and data
42+
%End
43+
44+
bool operator== ( const QgsOptional<T> &other ) const;
45+
46+
operator bool() const;
47+
%Docstring
48+
Boolean operator. Will return true if this optional is enabled.
49+
%End
50+
51+
bool enabled() const;
52+
%Docstring
53+
Check if this optional is enabled
54+
55+
.. versionadded:: 3.0
56+
:rtype: bool
57+
%End
58+
59+
void setEnabled( bool enabled );
60+
%Docstring
61+
Set if this optional is enabled
62+
63+
.. versionadded:: 3.0
64+
%End
65+
66+
67+
T data() const;
68+
%Docstring
69+
Access the payload data
70+
71+
.. versionadded:: 3.0
72+
:rtype: T
73+
%End
74+
75+
void setData( const T &data );
76+
%Docstring
77+
Set the payload data
78+
79+
.. versionadded:: 3.0
80+
%End
81+
82+
};
83+
84+
/************************************************************************
85+
* This file has been generated automatically from *
86+
* *
87+
* src/core/qgsoptional.h *
88+
* *
89+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
90+
************************************************************************/

‎python/core/qgsoptionalexpression.sip

Lines changed: 9 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99

1010

1111

12-
class QgsOptionalExpression
12+
13+
14+
15+
16+
typedef QgsOptional<QgsExpression> QgsOptionalQgsExpressionBase;
17+
18+
class QgsOptionalExpression : QgsOptionalQgsExpressionBase
1319
{
1420
%Docstring
1521

@@ -24,6 +30,8 @@ class QgsOptionalExpression
2430

2531
%TypeHeaderCode
2632
#include "qgsoptionalexpression.h"
33+
#include "qgsoptional.h"
34+
typedef QgsOptional<QgsExpression> QgsOptionalQgsExpressionBase;
2735
%End
2836
public:
2937

@@ -45,51 +53,6 @@ class QgsOptionalExpression
4553
%End
4654

4755

48-
49-
int operator== ( const QgsOptionalExpression &other ) const;
50-
%MethodCode
51-
sipRes = *sipCpp == *a0;
52-
%End
53-
54-
55-
int __bool__() const;
56-
%Docstring
57-
:rtype: int
58-
%End
59-
%MethodCode
60-
sipRes = sipCpp->enabled();
61-
%End
62-
63-
bool enabled() const;
64-
%Docstring
65-
Check if this optional is enabled
66-
67-
.. versionadded:: 3.0
68-
:rtype: bool
69-
%End
70-
71-
void setEnabled( bool enabled );
72-
%Docstring
73-
Set if this optional is enabled
74-
75-
.. versionadded:: 3.0
76-
%End
77-
78-
QgsExpression data() const;
79-
%Docstring
80-
Access the payload data
81-
82-
.. versionadded:: 3.0
83-
:rtype: QgsExpression
84-
%End
85-
86-
void setData( const QgsExpression &data );
87-
%Docstring
88-
Set the payload data
89-
90-
.. versionadded:: 3.0
91-
%End
92-
9356
void writeXml( QDomElement &element );
9457
%Docstring
9558
Save the optional expression to the provided QDomElement.

‎scripts/sipify.pl

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,21 +95,21 @@ sub dbg_info
9595
}
9696
}
9797

98-
sub detect_following_body_or_list {
98+
sub detect_and_remove_following_body_or_initializerlist {
9999
# https://regex101.com/r/ZaP3tC/6
100100
do {no warnings 'uninitialized';
101-
if ( $line =~ m/^(\s*)?((?:(?:explicit|static|const|unsigned|virtual)\s+)*)(([\w:]+(<.*?>)?\s+[*&]?)?(~?\w+|(\w+::)?operator.{1,2})\(([\w=()\/ ,&*<>."-]|::)*\)( (?:const|SIP_[A-Z_]*?))*)\s*((\s*[:,]\s+\w+\(.*\))*\s*\{.*\};?|(?!;))(\s*\/\/.*)?$/
101+
if ( $line =~ m/^(\s*)?((?:(?:explicit|static|const|unsigned|virtual)\s+)*)(([\w:]+(<.*?>)?\s+[*&]?)?(~?\w+|(\w+::)?operator.{1,2})\s*\(([\w=()\/ ,&*<>."-]|::)*\)( (?:const|SIP_[A-Z_]*?))*)\s*((\s*[:,]\s+\w+\(.*\))*\s*\{.*\};?|(?!;))(\s*\/\/.*)?$/
102102
|| $line =~ m/SIP_SKIP\s*(?!;)\s*(\/\/.*)?$/
103103
|| $line =~ m/^\s*class.*SIP_SKIP/ ){
104104
dbg_info("remove constructor definition, function bodies, member initializing list");
105105
my $newline = "$1$2$3;";
106-
remove_initializerlist_or_body() unless $line =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
106+
remove_following_body_or_initializerlist() unless $line =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
107107
$line = $newline;
108108
}
109109
};
110110
}
111111

112-
sub remove_initializerlist_or_body {
112+
sub remove_following_body_or_initializerlist {
113113
do {no warnings 'uninitialized';
114114
dbg_info("remove constructor definition, function bodies, member initializing list");
115115
$line = $lines[$line_idx];
@@ -368,7 +368,7 @@ sub detect_comment_block{
368368
$MULTILINE_DEFINITION = 0;
369369
}
370370
# also skip method body if there is one
371-
detect_following_body_or_list();
371+
detect_and_remove_following_body_or_initializerlist();
372372
# line skipped, go to next iteration
373373
next;
374374
}
@@ -432,8 +432,9 @@ sub detect_comment_block{
432432
next;
433433
}
434434
# Skip operators
435-
if ( $line =~ m/operator(=|<<|>>)\s*\(/ ){
435+
if ( $line =~ m/operator(=|<<|>>|->)\s*\(/ ){
436436
dbg_info("skip operator");
437+
detect_and_remove_following_body_or_initializerlist();
437438
next;
438439
}
439440

@@ -475,12 +476,14 @@ sub detect_comment_block{
475476
my $m = $4;
476477
$m =~ s/public //g;
477478
$m =~ s/[,:]?\s*private \w+(::\w+)?//g;
478-
while ($m =~ /[,:]\s+(\w+)<((\w|::)+)>/g){
479+
# detect template based inheritance
480+
while ($m =~ /[,:]\s+((?!QList)\w+)<((\w|::)+)>/g){
479481
dbg_info("template class");
480482
push @template_inheritance_template, $1;
481483
push @template_inheritance_class, $2;
482484
}
483-
$m =~ s/\w+<(\w|::)+>//g; # remove template Inheritance, not handled at the moment (see commented lines below)
485+
$m =~ s/(\b(?!QList)\w+)<((?:\w|::)+)>/$1${2}Base/g; # use the typeded as template inheritance
486+
$m =~ s/(\w+)<((?:\w|::)+)>//g; # remove remaining templates
484487
$m =~ s/([:,])\s*,/$1/g;
485488
$m =~ s/(\s*[:,])?\s*$//;
486489
$line .= $m;
@@ -496,14 +499,17 @@ sub detect_comment_block{
496499
$line .= "%Docstring\n$comment\n%End\n";
497500
}
498501
$line .= "\n%TypeHeaderCode\n#include \"" . basename($headerfile) . "\"";
502+
# for template based inheritance, add a typedef to define the base type
503+
# add it to the class and to the TypeHeaderCode
504+
# also include the template header
499505
# see https://www.riverbankcomputing.com/pipermail/pyqt/2015-May/035893.html
500-
# this doesn't work as expected since it leads to double definitions (typedef vs class)
501-
# while (@template_inheritance_template) {
502-
# my $tpl = pop @template_inheritance_template;
503-
# my $cls = pop @template_inheritance_class;
504-
# $line .= "\n#include \"" . lc $tpl . ".h\"";
505-
# $line .= "\ntypedef $tpl<$cls> $classname;";
506-
# }
506+
while (@template_inheritance_template) {
507+
my $tpl = pop @template_inheritance_template;
508+
my $cls = pop @template_inheritance_class;
509+
$line = "\ntypedef $tpl<$cls> ${tpl}${cls}Base;\n\n$line";
510+
$line .= "\n#include \"" . lc $tpl . ".h\"";
511+
$line .= "\ntypedef $tpl<$cls> ${tpl}${cls}Base;";
512+
}
507513
push @output, dbg("CLS")."$line\n";
508514

509515
# Skip opening curly bracket, we already added that above
@@ -612,13 +618,16 @@ sub detect_comment_block{
612618
$line =~ s/^(\s*?)\b(.*)$/$1virtual $2\n/;
613619
}
614620
}
621+
622+
# keyword fixes
623+
$line =~ s/^(\s*template<)(?:class|typename) (\w+>)(.*)$/$1$2$3/;
615624
$line =~ s/\s*\boverride\b//;
616625
$line =~ s/^(\s*)?(const )?(virtual |static )?inline /$1$2$3/;
617626
$line =~ s/\bnullptr\b/0/g;
618627
$line =~ s/\s*=\s*default\b//g;
619628

620629
# remove constructor definition, function bodies, member initializing list
621-
$SIP_RUN == 1 or detect_following_body_or_list();
630+
$SIP_RUN == 1 or detect_and_remove_following_body_or_initializerlist();
622631

623632
# remove inline declarations
624633
if ( $line =~ m/^(\s*)?(static |const )*(([\w:]+(<.*?>)?\s+(\*|&)?)?(\w+)( (?:const*?))*)\s*(\{.*\});(\s*\/\/.*)?$/ ){
@@ -674,7 +683,7 @@ sub detect_comment_block{
674683
if ( $SIP_RUN == 0 && $line !~ m/(\{.*\}|;)\s*(\/\/.*)?$/ ){
675684
dbg_info("remove following body of multiline def");
676685
my $last_line = $line;
677-
remove_initializerlist_or_body();
686+
remove_following_body_or_initializerlist();
678687
# add missing semi column
679688
my $dummy = pop(@output);
680689
push @output, dbg("MLT")."$last_line;\n";
@@ -697,6 +706,10 @@ sub detect_comment_block{
697706
$is_override = 0;
698707
next;
699708
}
709+
if ( $line =~ m/^\s*template<.*>/ ){
710+
# do not comment now for templates, wait for class definition
711+
next;
712+
}
700713
elsif ( $line =~ m/\/\// ||
701714
$line =~ m/\s*typedef / ||
702715
$line =~ m/\s*struct / ||

‎src/core/qgsoptional.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@
2828
* more internal configuration information that should not be lost when disabling and re-enabling.
2929
*
3030
* \since QGIS 3.0
31-
* \note For Python you need to use implementations for specific template classes
3231
*/
33-
template<class T>
32+
template<typename T>
3433
class CORE_EXPORT QgsOptional
3534
{
3635
public:

‎src/core/qgsoptionalexpression.h

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "qgis_core.h"
2323

24+
2425
/**
2526
* \ingroup core
2627
*
@@ -33,6 +34,8 @@
3334
* \since QGIS 2.18
3435
*/
3536

37+
38+
3639
class CORE_EXPORT QgsOptionalExpression : public QgsOptional<QgsExpression>
3740
{
3841
public:
@@ -55,58 +58,6 @@ class CORE_EXPORT QgsOptionalExpression : public QgsOptional<QgsExpression>
5558
QgsOptionalExpression( const QgsExpression &expression, bool enabled );
5659

5760

58-
// SIP does not handle properly template class Inheritance at the moment
59-
// following is copied from QgsOptional header
60-
#ifdef SIP_RUN
61-
62-
/**
63-
* Compare this QgsOptionalExpression to another one.
64-
*
65-
* This will compare the enabled flag and call the == operator
66-
* of the contained class.
67-
*
68-
* @note Added in QGIS 3.0
69-
*/
70-
int operator== ( const QgsOptionalExpression &other ) const;
71-
% MethodCode
72-
sipRes = *sipCpp == *a0;
73-
% End
74-
75-
76-
int __bool__() const;
77-
% MethodCode
78-
sipRes = sipCpp->enabled();
79-
% End
80-
81-
/**
82-
* Check if this optional is enabled
83-
*
84-
* \since QGIS 3.0
85-
*/
86-
bool enabled() const;
87-
88-
/**
89-
* Set if this optional is enabled
90-
*
91-
* \since QGIS 3.0
92-
*/
93-
void setEnabled( bool enabled );
94-
95-
/**
96-
* Access the payload data
97-
*
98-
* \since QGIS 3.0
99-
*/
100-
QgsExpression data() const;
101-
102-
/**
103-
* Set the payload data
104-
*
105-
* \since QGIS 3.0
106-
*/
107-
void setData( const QgsExpression &data );
108-
#endif
109-
11061
/**
11162
* Save the optional expression to the provided QDomElement.
11263
*

‎tests/scripts/sipifyheader.expected.sip

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ typedef QVector<QVariant> QgsSuperClass;
4444
%End
4545
}
4646

47-
class QgsSipifyHeader
47+
48+
typedef QtClass<QVariant> QtClassQVariantBase;
49+
50+
class QgsSipifyHeader : QtClassQVariantBase
4851
{
4952
%Docstring
5053
Documentation goes here
@@ -58,6 +61,8 @@ class QgsSipifyHeader
5861

5962
%TypeHeaderCode
6063
#include "sipifyheader.h"
64+
#include "qtclass.h"
65+
typedef QtClass<QVariant> QtClassQVariantBase;
6166
%End
6267

6368
%ConvertToSubClassCode
@@ -387,11 +392,16 @@ A constructor
387392
QFlags<QgsSipifyHeader::MyEnum> operator|(QgsSipifyHeader::MyEnum f1, QFlags<QgsSipifyHeader::MyEnum> f2);
388393

389394

390-
class TemplateInheritance1
395+
396+
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
397+
398+
class TemplateInheritance1 : QgsTemplateSomethingBase
391399
{
392400

393401
%TypeHeaderCode
394402
#include "sipifyheader.h"
403+
#include "qgstemplate.h"
404+
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
395405
%End
396406
}
397407
class TemplateInheritance2
@@ -401,11 +411,16 @@ class TemplateInheritance2
401411
#include "sipifyheader.h"
402412
%End
403413
}
404-
class TemplateInheritance3 : SomethingElse
414+
415+
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
416+
417+
class TemplateInheritance3 : QgsTemplateSomethingBase, SomethingElse
405418
{
406419

407420
%TypeHeaderCode
408421
#include "sipifyheader.h"
422+
#include "qgstemplate.h"
423+
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
409424
%End
410425
}
411426
class TemplateInheritance4 : SomethingElse1, SomethingElse2

‎tests/scripts/sipifyheader.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -475,16 +475,16 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( QgsSipifyHeader::Flags )
475475
class CORE_EXPORT TemplateInheritance1 : public QgsTemplate<Something>
476476
{
477477
}
478-
class CORE_EXPORT TemplateInheritance2 : public QgsTemplate<Something>, private SomethingElse
478+
class CORE_EXPORT TemplateInheritance2 : public QList<Something>, private SomethingElse
479479
{
480480
}
481481
class CORE_EXPORT TemplateInheritance3 : public QgsTemplate<Something>, public SomethingElse
482482
{
483483
}
484-
class CORE_EXPORT TemplateInheritance4 : public SomethingElse1, public QgsTemplate<Something>, public SomethingElse2
484+
class CORE_EXPORT TemplateInheritance4 : public SomethingElse1, public QList<Something>, public SomethingElse2
485485
{
486486
}
487-
class CORE_EXPORT TemplateInheritance5 : public SomethingElse, public QgsTemplate<Something>
487+
class CORE_EXPORT TemplateInheritance5 : public SomethingElse, public QList<Something>
488488
{
489489
}
490490

0 commit comments

Comments
 (0)
Please sign in to comment.