Stored expressions initial implementation

This commit is contained in:
Alessandro Pasotti 2019-11-28 18:44:38 +01:00
parent b42a31ec2f
commit e8d76e2a92
4 changed files with 416 additions and 187 deletions

View File

@ -217,14 +217,38 @@ Registers a node item for the expression builder.
void saveToRecent( const QString &collection = "generic" );
%Docstring
Adds the current expression to the given collection.
Adds the current expression to the given ``collection``.
By default it is saved to the collection "generic".
%End
void loadRecent( const QString &collection = "generic" );
%Docstring
Loads the recent expressions from the given collection.
Loads the recent expressions from the given ``collection``.
By default it is loaded from the collection "generic".
%End
void loadStored( const QString &collection = "generic" );
%Docstring
Loads the stored expressions from the given ``collection``.
By default it is loaded from the collection "generic".
.. versionadded:: 3.12
%End
void saveToStored( const QString &label, const QString expression, const QString &helpText, const QString &collection = "generic" );
%Docstring
Stores the ``expression`` in the given ``collection`` with given ``label`` and ``helpText``.
By default it is saved to the collection "generic".
.. versionadded:: 3.12
%End
void removeFromStored( const QString &name, const QString &collection = "generic" );
%Docstring
Removes the expression ``name`` from the stored expressions in the given ``collection``.
By default it is removed from the collection "generic".
.. versionadded:: 3.12
%End
void newFunctionFile( const QString &fileName = "scratch" );
@ -318,6 +342,21 @@ Enabled or disable auto saving. When enabled Python scripts will be auto saved
when text changes.
:param enabled: ``True`` to enable auto saving.
%End
void storeCurrentExpression( );
%Docstring
Adds the current expressions to the stored expressions.
.. versionadded:: 3.12
%End
void removeSelectedExpression( );
%Docstring
Removes the selected expression from the stored expressions,
the selected expression must be a stored expression.
.. versionadded:: 3.12
%End
signals:

View File

@ -59,7 +59,8 @@ QgsExpressionBuilderWidget::QgsExpressionBuilderWidget( QWidget *parent )
connect( txtSearchEdit, &QgsFilterLineEdit::textChanged, this, &QgsExpressionBuilderWidget::txtSearchEdit_textChanged );
connect( lblPreview, &QLabel::linkActivated, this, &QgsExpressionBuilderWidget::lblPreview_linkActivated );
connect( mValuesListView, &QListView::doubleClicked, this, &QgsExpressionBuilderWidget::mValuesListView_doubleClicked );
connect( btnSaveExpression, &QPushButton::pressed, this, &QgsExpressionBuilderWidget::storeCurrentExpression );
connect( btnRemoveExpression, &QPushButton::pressed, this, &QgsExpressionBuilderWidget::removeSelectedExpression );
txtHelpText->setOpenExternalLinks( true );
mValueGroupBox->hide();
@ -591,6 +592,65 @@ void QgsExpressionBuilderWidget::loadRecent( const QString &collection )
}
}
void QgsExpressionBuilderWidget::loadStored( const QString &collection )
{
mRecentKey = collection;
QString groupName = tr( "Stored (%1)" ).arg( collection );
// Cleanup
if ( mExpressionGroups.contains( groupName ) )
{
QgsExpressionItem *node = mExpressionGroups.value( groupName );
node->removeRows( 0, node->rowCount() );
}
const QList<QStandardItem *> groupItems { mModel->findItems( groupName ) };
if ( ! groupItems.isEmpty() )
{
const QModelIndex idx { mModel->indexFromItem( groupItems.first() ) };
if ( idx.isValid() )
{
mModel->removeRow( idx.row(), idx.parent() );
}
}
QgsSettings settings;
QString location = QStringLiteral( "/expressions/stored/%1" ).arg( collection );
settings.beginGroup( location, QgsSettings::Section::Gui );
QString label;
QString helpText;
QString expression;
int i = 0;
for ( const auto &label : settings.childKeys() )
{
settings.beginGroup( groupName );
expression = settings.value( QStringLiteral( "expression" ) ).toString();
helpText = settings.value( QStringLiteral( "helpText" ) ).toString();
this->registerItem( groupName, label, expression, helpText, QgsExpressionItem::ExpressionNode, false, i++ );
settings.endGroup();
}
}
void QgsExpressionBuilderWidget::saveToStored( const QString &label, const QString expression, const QString &helpText, const QString &collection )
{
QgsSettings settings;
QString location = QStringLiteral( "/expressions/stored/%1" ).arg( collection );
settings.beginGroup( location, QgsSettings::Section::Gui );
settings.beginGroup( label );
settings.setValue( QStringLiteral( "expression" ), expression );
settings.setValue( QStringLiteral( "helpText" ), helpText );
this->loadStored( collection );
}
void QgsExpressionBuilderWidget::removeFromStored( const QString &name, const QString &collection )
{
QgsSettings settings;
QString location = QStringLiteral( "/expressions/stored/%1" ).arg( collection );
settings.beginGroup( location, QgsSettings::Section::Gui );
settings.remove( name );
this->loadStored( collection );
}
void QgsExpressionBuilderWidget::loadLayers()
{
if ( !mProject )
@ -1149,6 +1209,27 @@ void QgsExpressionBuilderWidget::autosave()
anim->start( QAbstractAnimation::DeleteWhenStopped );
}
void QgsExpressionBuilderWidget::storeCurrentExpression()
{
const QString expression { this->expressionText() };
saveToStored( expression, expression, expression, mRecentKey );
}
void QgsExpressionBuilderWidget::removeSelectedExpression()
{
QModelIndex idx { expressionTree->currentIndex() };
QgsExpressionItem *item = dynamic_cast<QgsExpressionItem *>( mModel->itemFromIndex( idx ) );
if ( !item )
return;
// Don't handle the double-click if we are on a header node.
if ( item->getItemType() == QgsExpressionItem::Header )
return;
removeFromStored( item->text(), mRecentKey );
}
void QgsExpressionBuilderWidget::indicatorClicked( int line, int index, Qt::KeyboardModifiers state )
{
if ( state & Qt::ControlModifier )

View File

@ -225,17 +225,38 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
bool isExpressionValid();
/**
* Adds the current expression to the given collection.
* Adds the current expression to the given \a collection.
* By default it is saved to the collection "generic".
*/
void saveToRecent( const QString &collection = "generic" );
/**
* Loads the recent expressions from the given collection.
* Loads the recent expressions from the given \a collection.
* By default it is loaded from the collection "generic".
*/
void loadRecent( const QString &collection = "generic" );
/**
* Loads the stored expressions from the given \a collection.
* By default it is loaded from the collection "generic".
* \since QGIS 3.12
*/
void loadStored( const QString &collection = "generic" );
/**
* Stores the \a expression in the given \a collection with given \a label and \a helpText.
* By default it is saved to the collection "generic".
* \since QGIS 3.12
*/
void saveToStored( const QString &label, const QString expression, const QString &helpText, const QString &collection = "generic" );
/**
* Removes the expression \a name from the stored expressions in the given \a collection.
* By default it is removed from the collection "generic".
* \since QGIS 3.12
*/
void removeFromStored( const QString &name, const QString &collection = "generic" );
/**
* Create a new file in the function editor
*/
@ -323,6 +344,19 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
*/
void setAutoSave( bool enabled ) { mAutoSave = enabled; }
/**
* Adds the current expressions to the stored expressions.
* \since QGIS 3.12
*/
void storeCurrentExpression( );
/**
* Removes the selected expression from the stored expressions,
* the selected expression must be a stored expression.
* \since QGIS 3.12
*/
void removeSelectedExpression( );
private slots:
void indicatorClicked( int line, int index, Qt::KeyboardModifiers state );
void showContextMenu( QPoint );

View File

@ -99,178 +99,255 @@
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<layout class="QVBoxLayout" name="verticalLayout_6" stretch="0,1,1">
<item>
<widget class="QFrame" name="mOperatorsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>27</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>7</width>
<height>0</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="btnEqualPushButton">
<property name="toolTip">
<string>Equal operator</string>
<layout class="QHBoxLayout" name="horizontalLayout_10" stretch="0,0,0">
<item>
<widget class="QFrame" name="mOperatorsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>27</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>7</width>
<height>0</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<property name="text">
<string>=</string>
<property name="leftMargin">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnPlusPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="rightMargin">
<number>0</number>
</property>
<property name="toolTip">
<string>Addition operator</string>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="text">
<string>+</string>
<item>
<widget class="QPushButton" name="btnEqualPushButton">
<property name="toolTip">
<string>Equal operator</string>
</property>
<property name="text">
<string>=</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnPlusPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Addition operator</string>
</property>
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnMinusPushButton">
<property name="toolTip">
<string>Subtraction operator</string>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnDividePushButton">
<property name="toolTip">
<string>Division operator</string>
</property>
<property name="text">
<string>/</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnMultiplyPushButton">
<property name="toolTip">
<string>Multiplication operator</string>
</property>
<property name="text">
<string>*</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnExpButton">
<property name="toolTip">
<string>Power operator</string>
</property>
<property name="text">
<string>^</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnConcatButton">
<property name="toolTip">
<string>String Concatenation</string>
</property>
<property name="text">
<string>||</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnOpenBracketPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="toolTip">
<string>Open Bracket </string>
</property>
<property name="text">
<string>(</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnCloseBracketPushButton">
<property name="toolTip">
<string>Close Bracket </string>
</property>
<property name="text">
<string>)</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnNewLinePushButton">
<property name="toolTip">
<string>New Line</string>
</property>
<property name="text">
<string>'\n'</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="spacing">
<number>2</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnMinusPushButton">
<property name="toolTip">
<string>Subtraction operator</string>
<property name="leftMargin">
<number>0</number>
</property>
<property name="text">
<string>-</string>
<property name="rightMargin">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnDividePushButton">
<property name="toolTip">
<string>Division operator</string>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="text">
<string>/</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnMultiplyPushButton">
<property name="toolTip">
<string>Multiplication operator</string>
</property>
<property name="text">
<string>*</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnExpButton">
<property name="toolTip">
<string>Power operator</string>
</property>
<property name="text">
<string>^</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnConcatButton">
<property name="toolTip">
<string>String Concatenation</string>
</property>
<property name="text">
<string>||</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnOpenBracketPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="toolTip">
<string>Open Bracket </string>
</property>
<property name="text">
<string>(</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnCloseBracketPushButton">
<property name="toolTip">
<string>Close Bracket </string>
</property>
<property name="text">
<string>)</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnNewLinePushButton">
<property name="toolTip">
<string>New Line</string>
</property>
<property name="text">
<string>'\n'</string>
</property>
</widget>
</item>
</layout>
</widget>
<item>
<widget class="QToolButton" name="btnSaveExpression">
<property name="toolTip">
<string>Add the selected expression to the stored expressions</string>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnRemoveExpression">
<property name="toolTip">
<string>Removes selected expression from the stored expressions</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QgsCodeEditorExpression" name="txtExpressionString" native="true"/>
@ -456,20 +533,6 @@
</property>
<widget class="QWidget" name="layoutWidget1">
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QgsFilterLineEdit" name="txtSearchEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="mShowHelpButton">
<property name="text">
<string>Show Help</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTreeView" name="expressionTree">
<property name="frameShape">
@ -495,6 +558,20 @@
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="mShowHelpButton">
<property name="text">
<string>Show Help</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QgsFilterLineEdit" name="txtSearchEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mHelpAndValuesWidget" native="true">
@ -677,7 +754,7 @@ Change the name of the script and save to allow QGIS to auto load on startup.</s
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/console/iconNewTabEditorConsole.svg</normaloff>:/images/themes/default/console/iconNewTabEditorConsole.svg</iconset>
</property>
<property name="iconSize">
@ -769,7 +846,7 @@ Saved scripts are auto loaded on QGIS startup.</string>
<string>Save and Load Functions</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionStart.svg</normaloff>:/images/themes/default/mActionStart.svg</iconset>
</property>
</widget>
@ -835,8 +912,6 @@ Saved scripts are auto loaded on QGIS startup.</string>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<resources/>
<connections/>
</ui>