Skip to content

Commit 42ea216

Browse files
authored
FIX - Move custom expression function help to group box (#8163)
1 parent 9cad526 commit 42ea216

File tree

3 files changed

+149
-110
lines changed

3 files changed

+149
-110
lines changed

python/user.py

-32
Original file line numberDiff line numberDiff line change
@@ -66,38 +66,6 @@ def load_user_expressions(path):
6666
open(initfile, "w").close()
6767

6868
template = """\"\"\"
69-
Define a new function using the @qgsfunction decorator.
70-
71-
The function accept the following parameters
72-
73-
:param [any]: Define any parameters you want to pass to your function before
74-
the following arguments.
75-
:param feature: The current feature
76-
:param parent: The QgsExpression object
77-
:param context: If there is an argument called ``context`` found at the last
78-
position, this variable will contain a ``QgsExpressionContext``
79-
object, that gives access to various additional information like
80-
expression variables. E.g. ``context.variable('layer_id')``
81-
:returns: The result of the expression.
82-
83-
84-
The @qgsfunction decorator accepts the following arguments:
85-
86-
:param args: Defines the number of arguments. With ``args='auto'`` the number of
87-
arguments will automatically be extracted from the signature.
88-
With ``args=-1``, any number of arguments are accepted.
89-
:param group: The name of the group under which this expression function will
90-
be listed.
91-
:param handlesnull: Set this to True if your function has custom handling for NULL values.
92-
If False, the result will always be NULL as soon as any parameter is NULL.
93-
Defaults to False.
94-
:param usesgeometry: Set this to False if your function does not access
95-
feature.geometry(). Defaults to True.
96-
:param referenced_columns: An array of attribute names that are required to run
97-
this function. Defaults to
98-
[QgsFeatureRequest.ALL_ATTRIBUTES].
99-
\"\"\"
100-
10169
from qgis.core import *
10270
from qgis.gui import *
10371

src/gui/qgsexpressionbuilderwidget.cpp

+88-50
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,44 @@ QgsExpressionBuilderWidget::QgsExpressionBuilderWidget( QWidget *parent )
148148
txtExpressionString->setCallTipsVisible( 0 );
149149

150150
setExpectedOutputFormat( QString() );
151+
mFunctionBuilderHelp->setMarginVisible( false );
152+
mFunctionBuilderHelp->setEdgeMode( QsciScintilla::EdgeNone );
153+
mFunctionBuilderHelp->setEdgeColumn( 0 );
154+
mFunctionBuilderHelp->setReadOnly( true );
155+
mFunctionBuilderHelp->setText( tr( R"("""Define a new function using the @qgsfunction decorator.
156+
157+
The function accepts the following parameters
158+
159+
160+
: param [any]: Define any parameters you want to pass to your function before
161+
the following arguments.
162+
: param feature: The current feature
163+
: param parent: The QgsExpression object
164+
: param context: If there is an argument called ``context`` found at the last
165+
position, this variable will contain a ``QgsExpressionContext``
166+
object, that gives access to various additional information like
167+
expression variables. E.g. ``context.variable( 'layer_id' )``
168+
: returns: The result of the expression.
169+
170+
171+
172+
The @qgsfunction decorator accepts the following arguments:
173+
174+
175+
: param args: Defines the number of arguments. With ``args = 'auto'`` the number of
176+
arguments will automatically be extracted from the signature.
177+
With ``args = -1``, any number of arguments are accepted.
178+
: param group: The name of the group under which this expression function will
179+
be listed.
180+
: param handlesnull: Set this to True if your function has custom handling for NULL values.
181+
If False, the result will always be NULL as soon as any parameter is NULL.
182+
Defaults to False.
183+
: param usesgeometry : Set this to False if your function does not access
184+
feature.geometry(). Defaults to True.
185+
: param referenced_columns: An array of attribute names that are required to run
186+
this function. Defaults to
187+
[QgsFeatureRequest.ALL_ATTRIBUTES].
188+
"""")" ) );
151189
}
152190

153191

@@ -826,72 +864,72 @@ void QgsExpressionBuilderWidget::createMarkers( const QgsExpressionNode *inNode
826864
switch ( inNode->nodeType() )
827865
{
828866
case QgsExpressionNode::NodeType::ntFunction:
829-
{
830-
const QgsExpressionNodeFunction *node = static_cast<const QgsExpressionNodeFunction *>( inNode );
831-
txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORCURRENT, FUNCTION_MARKER_ID );
832-
txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORVALUE, node->fnIndex() );
833-
int start = inNode->parserFirstColumn - 1;
834-
int end = inNode->parserLastColumn - 1;
835-
int start_pos = txtExpressionString->positionFromLineIndex( inNode->parserFirstLine - 1, start );
836-
txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORFILLRANGE, start_pos, end - start );
837-
if ( node->args() )
838867
{
839-
const QList< QgsExpressionNode * > nodeList = node->args()->list();
840-
for ( QgsExpressionNode *n : nodeList )
868+
const QgsExpressionNodeFunction *node = static_cast<const QgsExpressionNodeFunction *>( inNode );
869+
txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORCURRENT, FUNCTION_MARKER_ID );
870+
txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORVALUE, node->fnIndex() );
871+
int start = inNode->parserFirstColumn - 1;
872+
int end = inNode->parserLastColumn - 1;
873+
int start_pos = txtExpressionString->positionFromLineIndex( inNode->parserFirstLine - 1, start );
874+
txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORFILLRANGE, start_pos, end - start );
875+
if ( node->args() )
841876
{
842-
createMarkers( n );
877+
const QList< QgsExpressionNode * > nodeList = node->args()->list();
878+
for ( QgsExpressionNode *n : nodeList )
879+
{
880+
createMarkers( n );
881+
}
843882
}
883+
break;
844884
}
845-
break;
846-
}
847885
case QgsExpressionNode::NodeType::ntLiteral:
848-
{
849-
break;
850-
}
886+
{
887+
break;
888+
}
851889
case QgsExpressionNode::NodeType::ntUnaryOperator:
852-
{
853-
const QgsExpressionNodeUnaryOperator *node = static_cast<const QgsExpressionNodeUnaryOperator *>( inNode );
854-
createMarkers( node->operand() );
855-
break;
856-
}
890+
{
891+
const QgsExpressionNodeUnaryOperator *node = static_cast<const QgsExpressionNodeUnaryOperator *>( inNode );
892+
createMarkers( node->operand() );
893+
break;
894+
}
857895
case QgsExpressionNode::NodeType::ntBinaryOperator:
858-
{
859-
const QgsExpressionNodeBinaryOperator *node = static_cast<const QgsExpressionNodeBinaryOperator *>( inNode );
860-
createMarkers( node->opLeft() );
861-
createMarkers( node->opRight() );
862-
break;
863-
}
896+
{
897+
const QgsExpressionNodeBinaryOperator *node = static_cast<const QgsExpressionNodeBinaryOperator *>( inNode );
898+
createMarkers( node->opLeft() );
899+
createMarkers( node->opRight() );
900+
break;
901+
}
864902
case QgsExpressionNode::NodeType::ntColumnRef:
865-
{
866-
break;
867-
}
903+
{
904+
break;
905+
}
868906
case QgsExpressionNode::NodeType::ntInOperator:
869-
{
870-
const QgsExpressionNodeInOperator *node = static_cast<const QgsExpressionNodeInOperator *>( inNode );
871-
if ( node->list() )
872907
{
873-
const QList< QgsExpressionNode * > nodeList = node->list()->list();
874-
for ( QgsExpressionNode *n : nodeList )
908+
const QgsExpressionNodeInOperator *node = static_cast<const QgsExpressionNodeInOperator *>( inNode );
909+
if ( node->list() )
875910
{
876-
createMarkers( n );
911+
const QList< QgsExpressionNode * > nodeList = node->list()->list();
912+
for ( QgsExpressionNode *n : nodeList )
913+
{
914+
createMarkers( n );
915+
}
877916
}
917+
break;
878918
}
879-
break;
880-
}
881919
case QgsExpressionNode::NodeType::ntCondition:
882-
{
883-
const QgsExpressionNodeCondition *node = static_cast<const QgsExpressionNodeCondition *>( inNode );
884-
for ( QgsExpressionNodeCondition::WhenThen *cond : node->conditions() )
885920
{
886-
createMarkers( cond->whenExp() );
887-
createMarkers( cond->thenExp() );
888-
}
889-
if ( node->elseExp() )
890-
{
891-
createMarkers( node->elseExp() );
921+
const QgsExpressionNodeCondition *node = static_cast<const QgsExpressionNodeCondition *>( inNode );
922+
for ( QgsExpressionNodeCondition::WhenThen *cond : node->conditions() )
923+
{
924+
createMarkers( cond->whenExp() );
925+
createMarkers( cond->thenExp() );
926+
}
927+
if ( node->elseExp() )
928+
{
929+
createMarkers( node->elseExp() );
930+
}
931+
break;
892932
}
893-
break;
894-
}
895933
}
896934
}
897935

src/ui/qgsexpressionbuilder.ui

+61-28
Original file line numberDiff line numberDiff line change
@@ -626,30 +626,49 @@
626626
</property>
627627
<widget class="QWidget" name="layoutWidget3">
628628
<layout class="QVBoxLayout" name="verticalLayout_5">
629+
<item>
630+
<widget class="QListWidget" name="cmbFileNames">
631+
<property name="sizePolicy">
632+
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
633+
<horstretch>0</horstretch>
634+
<verstretch>0</verstretch>
635+
</sizepolicy>
636+
</property>
637+
<property name="minimumSize">
638+
<size>
639+
<width>0</width>
640+
<height>0</height>
641+
</size>
642+
</property>
643+
<property name="editTriggers">
644+
<set>QAbstractItemView::NoEditTriggers</set>
645+
</property>
646+
</widget>
647+
</item>
629648
<item>
630649
<layout class="QHBoxLayout" name="horizontalLayout_6">
631650
<property name="topMargin">
632651
<number>0</number>
633652
</property>
634653
<item>
635-
<widget class="QToolButton" name="btnNewFile">
654+
<widget class="QPushButton" name="btnNewFile">
636655
<property name="toolTip">
637656
<string>Create a new function file based on the template file.
638657

639658
Change the name of the script and save to allow QGIS to auto load on startup.</string>
640659
</property>
641660
<property name="text">
642-
<string>New file</string>
661+
<string/>
643662
</property>
644663
<property name="icon">
645664
<iconset resource="../../images/images.qrc">
646-
<normaloff>:/images/themes/default/console/iconTabEditorConsole.svg</normaloff>:/images/themes/default/console/iconTabEditorConsole.svg</iconset>
647-
</property>
648-
<property name="toolButtonStyle">
649-
<enum>Qt::ToolButtonTextBesideIcon</enum>
665+
<normaloff>:/images/themes/default/console/iconNewTabEditorConsole.svg</normaloff>:/images/themes/default/console/iconNewTabEditorConsole.svg</iconset>
650666
</property>
651-
<property name="autoRaise">
652-
<bool>true</bool>
667+
<property name="iconSize">
668+
<size>
669+
<width>24</width>
670+
<height>24</height>
671+
</size>
653672
</property>
654673
</widget>
655674
</item>
@@ -668,29 +687,13 @@ Change the name of the script and save to allow QGIS to auto load on startup.</s
668687
</item>
669688
</layout>
670689
</item>
671-
<item>
672-
<widget class="QListWidget" name="cmbFileNames">
673-
<property name="sizePolicy">
674-
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
675-
<horstretch>0</horstretch>
676-
<verstretch>0</verstretch>
677-
</sizepolicy>
678-
</property>
679-
<property name="minimumSize">
680-
<size>
681-
<width>0</width>
682-
<height>0</height>
683-
</size>
684-
</property>
685-
<property name="editTriggers">
686-
<set>QAbstractItemView::NoEditTriggers</set>
687-
</property>
688-
</widget>
689-
</item>
690690
</layout>
691691
</widget>
692692
<widget class="QWidget" name="layoutWidget">
693693
<layout class="QVBoxLayout" name="verticalLayout_3">
694+
<property name="bottomMargin">
695+
<number>0</number>
696+
</property>
694697
<item>
695698
<layout class="QHBoxLayout" name="horizontalLayout_5">
696699
<property name="sizeConstraint">
@@ -709,7 +712,7 @@ Use this when testing your functions.
709712
Saved scripts are auto loaded on QGIS startup.</string>
710713
</property>
711714
<property name="text">
712-
<string>Load</string>
715+
<string>Save and load functions</string>
713716
</property>
714717
<property name="icon">
715718
<iconset resource="../../images/images.qrc">
@@ -751,6 +754,30 @@ Saved scripts are auto loaded on QGIS startup.</string>
751754
<item>
752755
<widget class="QgsCodeEditorPython" name="txtPython" native="true"/>
753756
</item>
757+
<item>
758+
<widget class="QgsCollapsibleGroupBox" name="groupBox">
759+
<property name="title">
760+
<string>Help</string>
761+
</property>
762+
<layout class="QGridLayout" name="gridLayout_4">
763+
<property name="leftMargin">
764+
<number>0</number>
765+
</property>
766+
<property name="topMargin">
767+
<number>0</number>
768+
</property>
769+
<property name="rightMargin">
770+
<number>0</number>
771+
</property>
772+
<property name="bottomMargin">
773+
<number>0</number>
774+
</property>
775+
<item row="0" column="0">
776+
<widget class="QgsCodeEditorPython" name="mFunctionBuilderHelp" native="true"/>
777+
</item>
778+
</layout>
779+
</widget>
780+
</item>
754781
</layout>
755782
</widget>
756783
</widget>
@@ -779,6 +806,12 @@ Saved scripts are auto loaded on QGIS startup.</string>
779806
<header>qgscodeeditorpython.h</header>
780807
<container>1</container>
781808
</customwidget>
809+
<customwidget>
810+
<class>QgsCollapsibleGroupBox</class>
811+
<extends>QGroupBox</extends>
812+
<header>qgscollapsiblegroupbox.h</header>
813+
<container>1</container>
814+
</customwidget>
782815
</customwidgets>
783816
<resources>
784817
<include location="../../images/images.qrc"/>

0 commit comments

Comments
 (0)