[sipify] implement template inheritance

This commit is contained in:
Denis Rouzaud 2017-05-18 14:16:42 +02:00
parent bbcc8725fc
commit fb8edea112
8 changed files with 155 additions and 123 deletions

View File

@ -113,6 +113,7 @@
%Include qgsobjectcustomproperties.sip
%Include qgsofflineediting.sip
%Include qgsogcutils.sip
%Include qgsoptional.sip
%Include qgsoptionalexpression.sip
%Include qgsowsconnection.sip
%Include qgspaintenginehack.sip

View File

@ -0,0 +1,90 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsoptional.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
template<T>
class QgsOptional
{
%Docstring
QgsOptional is a container for other classes and adds an additional enabled/disabled flag.
Often it is used for configuration options which can be enabled or disabled but also have
more internal configuration information that should not be lost when disabling and re-enabling.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgsoptional.h"
%End
public:
QgsOptional();
%Docstring
A QgsOptional is disabled by default if default constructed.
%End
QgsOptional( const T &data );
%Docstring
A QgsOptional is enabled by default if constructed with payload.
%End
QgsOptional( const T &data, bool enabled );
%Docstring
A QgsOptional constructed with enabled status and data
%End
bool operator== ( const QgsOptional<T> &other ) const;
operator bool() const;
%Docstring
Boolean operator. Will return true if this optional is enabled.
%End
bool enabled() const;
%Docstring
Check if this optional is enabled
.. versionadded:: 3.0
:rtype: bool
%End
void setEnabled( bool enabled );
%Docstring
Set if this optional is enabled
.. versionadded:: 3.0
%End
T data() const;
%Docstring
Access the payload data
.. versionadded:: 3.0
:rtype: T
%End
void setData( const T &data );
%Docstring
Set the payload data
.. versionadded:: 3.0
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsoptional.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -9,7 +9,13 @@
class QgsOptionalExpression
typedef QgsOptional<QgsExpression> QgsOptionalQgsExpressionBase;
class QgsOptionalExpression : QgsOptionalQgsExpressionBase
{
%Docstring
@ -24,6 +30,8 @@ class QgsOptionalExpression
%TypeHeaderCode
#include "qgsoptionalexpression.h"
#include "qgsoptional.h"
typedef QgsOptional<QgsExpression> QgsOptionalQgsExpressionBase;
%End
public:
@ -45,51 +53,6 @@ class QgsOptionalExpression
%End
int operator== ( const QgsOptionalExpression &other ) const;
%MethodCode
sipRes = *sipCpp == *a0;
%End
int __bool__() const;
%Docstring
:rtype: int
%End
%MethodCode
sipRes = sipCpp->enabled();
%End
bool enabled() const;
%Docstring
Check if this optional is enabled
.. versionadded:: 3.0
:rtype: bool
%End
void setEnabled( bool enabled );
%Docstring
Set if this optional is enabled
.. versionadded:: 3.0
%End
QgsExpression data() const;
%Docstring
Access the payload data
.. versionadded:: 3.0
:rtype: QgsExpression
%End
void setData( const QgsExpression &data );
%Docstring
Set the payload data
.. versionadded:: 3.0
%End
void writeXml( QDomElement &element );
%Docstring
Save the optional expression to the provided QDomElement.

View File

@ -95,21 +95,21 @@ sub dbg_info
}
}
sub detect_following_body_or_list {
sub detect_and_remove_following_body_or_initializerlist {
# https://regex101.com/r/ZaP3tC/6
do {no warnings 'uninitialized';
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*\/\/.*)?$/
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*\/\/.*)?$/
|| $line =~ m/SIP_SKIP\s*(?!;)\s*(\/\/.*)?$/
|| $line =~ m/^\s*class.*SIP_SKIP/ ){
dbg_info("remove constructor definition, function bodies, member initializing list");
my $newline = "$1$2$3;";
remove_initializerlist_or_body() unless $line =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
remove_following_body_or_initializerlist() unless $line =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
$line = $newline;
}
};
}
sub remove_initializerlist_or_body {
sub remove_following_body_or_initializerlist {
do {no warnings 'uninitialized';
dbg_info("remove constructor definition, function bodies, member initializing list");
$line = $lines[$line_idx];
@ -368,7 +368,7 @@ while ($line_idx < $line_count){
$MULTILINE_DEFINITION = 0;
}
# also skip method body if there is one
detect_following_body_or_list();
detect_and_remove_following_body_or_initializerlist();
# line skipped, go to next iteration
next;
}
@ -432,8 +432,9 @@ while ($line_idx < $line_count){
next;
}
# Skip operators
if ( $line =~ m/operator(=|<<|>>)\s*\(/ ){
if ( $line =~ m/operator(=|<<|>>|->)\s*\(/ ){
dbg_info("skip operator");
detect_and_remove_following_body_or_initializerlist();
next;
}
@ -475,12 +476,14 @@ while ($line_idx < $line_count){
my $m = $4;
$m =~ s/public //g;
$m =~ s/[,:]?\s*private \w+(::\w+)?//g;
while ($m =~ /[,:]\s+(\w+)<((\w|::)+)>/g){
# detect template based inheritance
while ($m =~ /[,:]\s+((?!QList)\w+)<((\w|::)+)>/g){
dbg_info("template class");
push @template_inheritance_template, $1;
push @template_inheritance_class, $2;
}
$m =~ s/\w+<(\w|::)+>//g; # remove template Inheritance, not handled at the moment (see commented lines below)
$m =~ s/(\b(?!QList)\w+)<((?:\w|::)+)>/$1${2}Base/g; # use the typeded as template inheritance
$m =~ s/(\w+)<((?:\w|::)+)>//g; # remove remaining templates
$m =~ s/([:,])\s*,/$1/g;
$m =~ s/(\s*[:,])?\s*$//;
$line .= $m;
@ -496,14 +499,17 @@ while ($line_idx < $line_count){
$line .= "%Docstring\n$comment\n%End\n";
}
$line .= "\n%TypeHeaderCode\n#include \"" . basename($headerfile) . "\"";
# for template based inheritance, add a typedef to define the base type
# add it to the class and to the TypeHeaderCode
# also include the template header
# see https://www.riverbankcomputing.com/pipermail/pyqt/2015-May/035893.html
# this doesn't work as expected since it leads to double definitions (typedef vs class)
# while (@template_inheritance_template) {
# my $tpl = pop @template_inheritance_template;
# my $cls = pop @template_inheritance_class;
# $line .= "\n#include \"" . lc $tpl . ".h\"";
# $line .= "\ntypedef $tpl<$cls> $classname;";
# }
while (@template_inheritance_template) {
my $tpl = pop @template_inheritance_template;
my $cls = pop @template_inheritance_class;
$line = "\ntypedef $tpl<$cls> ${tpl}${cls}Base;\n\n$line";
$line .= "\n#include \"" . lc $tpl . ".h\"";
$line .= "\ntypedef $tpl<$cls> ${tpl}${cls}Base;";
}
push @output, dbg("CLS")."$line\n";
# Skip opening curly bracket, we already added that above
@ -612,13 +618,16 @@ while ($line_idx < $line_count){
$line =~ s/^(\s*?)\b(.*)$/$1virtual $2\n/;
}
}
# keyword fixes
$line =~ s/^(\s*template<)(?:class|typename) (\w+>)(.*)$/$1$2$3/;
$line =~ s/\s*\boverride\b//;
$line =~ s/^(\s*)?(const )?(virtual |static )?inline /$1$2$3/;
$line =~ s/\bnullptr\b/0/g;
$line =~ s/\s*=\s*default\b//g;
# remove constructor definition, function bodies, member initializing list
$SIP_RUN == 1 or detect_following_body_or_list();
$SIP_RUN == 1 or detect_and_remove_following_body_or_initializerlist();
# remove inline declarations
if ( $line =~ m/^(\s*)?(static |const )*(([\w:]+(<.*?>)?\s+(\*|&)?)?(\w+)( (?:const*?))*)\s*(\{.*\});(\s*\/\/.*)?$/ ){
@ -674,7 +683,7 @@ while ($line_idx < $line_count){
if ( $SIP_RUN == 0 && $line !~ m/(\{.*\}|;)\s*(\/\/.*)?$/ ){
dbg_info("remove following body of multiline def");
my $last_line = $line;
remove_initializerlist_or_body();
remove_following_body_or_initializerlist();
# add missing semi column
my $dummy = pop(@output);
push @output, dbg("MLT")."$last_line;\n";
@ -697,6 +706,10 @@ while ($line_idx < $line_count){
$is_override = 0;
next;
}
if ( $line =~ m/^\s*template<.*>/ ){
# do not comment now for templates, wait for class definition
next;
}
elsif ( $line =~ m/\/\// ||
$line =~ m/\s*typedef / ||
$line =~ m/\s*struct / ||

View File

@ -28,9 +28,8 @@
* more internal configuration information that should not be lost when disabling and re-enabling.
*
* \since QGIS 3.0
* \note For Python you need to use implementations for specific template classes
*/
template<class T>
template<typename T>
class CORE_EXPORT QgsOptional
{
public:

View File

@ -21,6 +21,7 @@
#include "qgis_core.h"
/**
* \ingroup core
*
@ -33,6 +34,8 @@
* \since QGIS 2.18
*/
class CORE_EXPORT QgsOptionalExpression : public QgsOptional<QgsExpression>
{
public:
@ -55,58 +58,6 @@ class CORE_EXPORT QgsOptionalExpression : public QgsOptional<QgsExpression>
QgsOptionalExpression( const QgsExpression &expression, bool enabled );
// SIP does not handle properly template class Inheritance at the moment
// following is copied from QgsOptional header
#ifdef SIP_RUN
/**
* Compare this QgsOptionalExpression to another one.
*
* This will compare the enabled flag and call the == operator
* of the contained class.
*
* @note Added in QGIS 3.0
*/
int operator== ( const QgsOptionalExpression &other ) const;
% MethodCode
sipRes = *sipCpp == *a0;
% End
int __bool__() const;
% MethodCode
sipRes = sipCpp->enabled();
% End
/**
* Check if this optional is enabled
*
* \since QGIS 3.0
*/
bool enabled() const;
/**
* Set if this optional is enabled
*
* \since QGIS 3.0
*/
void setEnabled( bool enabled );
/**
* Access the payload data
*
* \since QGIS 3.0
*/
QgsExpression data() const;
/**
* Set the payload data
*
* \since QGIS 3.0
*/
void setData( const QgsExpression &data );
#endif
/**
* Save the optional expression to the provided QDomElement.
*

View File

@ -44,7 +44,10 @@ typedef QVector<QVariant> QgsSuperClass;
%End
}
class QgsSipifyHeader
typedef QtClass<QVariant> QtClassQVariantBase;
class QgsSipifyHeader : QtClassQVariantBase
{
%Docstring
Documentation goes here
@ -58,6 +61,8 @@ class QgsSipifyHeader
%TypeHeaderCode
#include "sipifyheader.h"
#include "qtclass.h"
typedef QtClass<QVariant> QtClassQVariantBase;
%End
%ConvertToSubClassCode
@ -387,11 +392,16 @@ A constructor
QFlags<QgsSipifyHeader::MyEnum> operator|(QgsSipifyHeader::MyEnum f1, QFlags<QgsSipifyHeader::MyEnum> f2);
class TemplateInheritance1
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
class TemplateInheritance1 : QgsTemplateSomethingBase
{
%TypeHeaderCode
#include "sipifyheader.h"
#include "qgstemplate.h"
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
%End
}
class TemplateInheritance2
@ -401,11 +411,16 @@ class TemplateInheritance2
#include "sipifyheader.h"
%End
}
class TemplateInheritance3 : SomethingElse
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
class TemplateInheritance3 : QgsTemplateSomethingBase, SomethingElse
{
%TypeHeaderCode
#include "sipifyheader.h"
#include "qgstemplate.h"
typedef QgsTemplate<Something> QgsTemplateSomethingBase;
%End
}
class TemplateInheritance4 : SomethingElse1, SomethingElse2

View File

@ -475,16 +475,16 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( QgsSipifyHeader::Flags )
class CORE_EXPORT TemplateInheritance1 : public QgsTemplate<Something>
{
}
class CORE_EXPORT TemplateInheritance2 : public QgsTemplate<Something>, private SomethingElse
class CORE_EXPORT TemplateInheritance2 : public QList<Something>, private SomethingElse
{
}
class CORE_EXPORT TemplateInheritance3 : public QgsTemplate<Something>, public SomethingElse
{
}
class CORE_EXPORT TemplateInheritance4 : public SomethingElse1, public QgsTemplate<Something>, public SomethingElse2
class CORE_EXPORT TemplateInheritance4 : public SomethingElse1, public QList<Something>, public SomethingElse2
{
}
class CORE_EXPORT TemplateInheritance5 : public SomethingElse, public QgsTemplate<Something>
class CORE_EXPORT TemplateInheritance5 : public SomethingElse, public QList<Something>
{
}