mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-22 00:06:12 -05:00
[core] Address review: Move loadFunctionsFromProject and cleanFunctionsFromProject to QgsProject::read and ::clear, respectively. Introduce function pythonEmbeddedInProjectAllowed to ask for permissions to load both macros and expression functions, with a parameter enum and rename existing enum for macros. Sort includes. Drop not needed file. Add python/expressions/ to gitignore, to get rid of files produced by the introduced Python test.
This commit is contained in:
parent
053e95e5e6
commit
c5286e4dcc
15
.gitignore
vendored
15
.gitignore
vendored
@ -47,6 +47,21 @@ desktop.ini
|
||||
doc/INSTALL.tex
|
||||
i18n/*.qm
|
||||
ms-windows/*.exe*
|
||||
ms-windows/Installer-Files/postinstall.bat
|
||||
ms-windows/Installer-Files/preremove.bat
|
||||
ms-windows/nsis/
|
||||
ms-windows/osgeo4w/addons/
|
||||
ms-windows/osgeo4w/binary-*
|
||||
ms-windows/osgeo4w/build-*
|
||||
ms-windows/osgeo4w/nsis/
|
||||
ms-windows/osgeo4w/packages-x86/
|
||||
ms-windows/osgeo4w/packages-x86_64/
|
||||
ms-windows/osgeo4w/unpacked/
|
||||
ms-windows/osgeo4w/untgz/
|
||||
ms-windows/packages/
|
||||
ms-windows/progs/
|
||||
ms-windows/untgz/
|
||||
python/expressions/
|
||||
python/plugins/grassprovider/description/algorithms.json
|
||||
python/plugins/grassprovider/tests/testdata/directions.tif.aux.xml
|
||||
python/plugins/processing/tests/testdata/*.aux.xml
|
||||
|
@ -620,34 +620,37 @@ Qgis.VectorLayerTypeFlags = lambda flags=0: Qgis.VectorLayerTypeFlag(flags)
|
||||
Qgis.VectorLayerTypeFlags.baseClass = Qgis
|
||||
VectorLayerTypeFlags = Qgis # dirty hack since SIP seems to introduce the flags in module
|
||||
# monkey patching scoped based enum
|
||||
Qgis.Never = Qgis.PythonMacroMode.Never
|
||||
Qgis.Never.is_monkey_patched = True
|
||||
Qgis.Never.__doc__ = "Macros are never run"
|
||||
Qgis.Ask = Qgis.PythonMacroMode.Ask
|
||||
Qgis.Ask.is_monkey_patched = True
|
||||
Qgis.Ask.__doc__ = "User is prompt before running"
|
||||
Qgis.SessionOnly = Qgis.PythonMacroMode.SessionOnly
|
||||
Qgis.SessionOnly.is_monkey_patched = True
|
||||
Qgis.SessionOnly.__doc__ = "Only during this session"
|
||||
Qgis.Always = Qgis.PythonMacroMode.Always
|
||||
Qgis.Always.is_monkey_patched = True
|
||||
Qgis.Always.__doc__ = "Macros are always run"
|
||||
Qgis.NotForThisSession = Qgis.PythonMacroMode.NotForThisSession
|
||||
Qgis.NotForThisSession.is_monkey_patched = True
|
||||
Qgis.NotForThisSession.__doc__ = "Macros will not be run for this session"
|
||||
Qgis.PythonMacroMode.__doc__ = """Authorisation to run Python Macros
|
||||
Qgis.PythonEmbeddedMode.Never.__doc__ = "Python embedded never run"
|
||||
Qgis.PythonEmbeddedMode.Ask.__doc__ = "User is prompt before running"
|
||||
Qgis.PythonEmbeddedMode.SessionOnly.__doc__ = "Only during this session"
|
||||
Qgis.PythonEmbeddedMode.Always.__doc__ = "Python embedded is always run"
|
||||
Qgis.PythonEmbeddedMode.NotForThisSession.__doc__ = "Python embedded will not be run for this session"
|
||||
Qgis.PythonEmbeddedMode.__doc__ = """Authorisation to run Python Embedded in projects
|
||||
|
||||
.. versionadded:: 3.10
|
||||
.. versionadded:: 3.40
|
||||
|
||||
* ``Never``: Macros are never run
|
||||
* ``Never``: Python embedded never run
|
||||
* ``Ask``: User is prompt before running
|
||||
* ``SessionOnly``: Only during this session
|
||||
* ``Always``: Macros are always run
|
||||
* ``NotForThisSession``: Macros will not be run for this session
|
||||
* ``Always``: Python embedded is always run
|
||||
* ``NotForThisSession``: Python embedded will not be run for this session
|
||||
|
||||
"""
|
||||
# --
|
||||
Qgis.PythonMacroMode.baseClass = Qgis
|
||||
Qgis.PythonEmbeddedMode.baseClass = Qgis
|
||||
# monkey patching scoped based enum
|
||||
Qgis.PythonEmbeddedType.Macro.__doc__ = ""
|
||||
Qgis.PythonEmbeddedType.ExpressionFunction.__doc__ = ""
|
||||
Qgis.PythonEmbeddedType.__doc__ = """Type of Python Embedded in projects
|
||||
|
||||
.. versionadded:: 3.40
|
||||
|
||||
* ``Macro``:
|
||||
* ``ExpressionFunction``:
|
||||
|
||||
"""
|
||||
# --
|
||||
Qgis.PythonEmbeddedType.baseClass = Qgis
|
||||
QgsDataProvider.ReadFlag = Qgis.DataProviderReadFlag
|
||||
# monkey patching scoped based enum
|
||||
QgsDataProvider.FlagTrustDataSource = Qgis.DataProviderReadFlag.TrustDataSource
|
||||
|
@ -519,8 +519,6 @@ Returns the number of functions defined in the parser
|
||||
:return: The number of function defined in the parser.
|
||||
%End
|
||||
|
||||
|
||||
|
||||
static QString quotedColumnRef( QString name );
|
||||
%Docstring
|
||||
Returns a quoted column reference (in double quotes)
|
||||
|
@ -1657,6 +1657,9 @@ Sets the elevation shading renderer used for global map shading
|
||||
.. versionadded:: 3.30
|
||||
%End
|
||||
|
||||
|
||||
|
||||
|
||||
SIP_PYOBJECT __repr__();
|
||||
%MethodCode
|
||||
QString str = QStringLiteral( "<QgsProject: '%1'%2>" ).arg( sipCpp->fileName(),
|
||||
|
@ -224,8 +224,8 @@ The development version
|
||||
typedef QFlags<Qgis::VectorLayerTypeFlag> VectorLayerTypeFlags;
|
||||
|
||||
|
||||
enum class PythonMacroMode /BaseType=IntEnum/
|
||||
{
|
||||
enum class PythonEmbeddedMode /BaseType=IntEnum/
|
||||
{
|
||||
Never,
|
||||
Ask,
|
||||
SessionOnly,
|
||||
@ -233,6 +233,12 @@ The development version
|
||||
NotForThisSession,
|
||||
};
|
||||
|
||||
enum class PythonEmbeddedType /BaseType=IntEnum/
|
||||
{
|
||||
Macro,
|
||||
ExpressionFunction,
|
||||
};
|
||||
|
||||
enum class DataProviderReadFlag /BaseType=IntFlag/
|
||||
{
|
||||
TrustDataSource,
|
||||
|
@ -251,7 +251,6 @@ Returns the screen at the given global ``point`` (pixel).
|
||||
|
||||
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
void optionsChanged();
|
||||
|
@ -612,34 +612,37 @@ Qgis.VectorLayerTypeFlag.baseClass = Qgis
|
||||
Qgis.VectorLayerTypeFlags.baseClass = Qgis
|
||||
VectorLayerTypeFlags = Qgis # dirty hack since SIP seems to introduce the flags in module
|
||||
# monkey patching scoped based enum
|
||||
Qgis.Never = Qgis.PythonMacroMode.Never
|
||||
Qgis.Never.is_monkey_patched = True
|
||||
Qgis.Never.__doc__ = "Macros are never run"
|
||||
Qgis.Ask = Qgis.PythonMacroMode.Ask
|
||||
Qgis.Ask.is_monkey_patched = True
|
||||
Qgis.Ask.__doc__ = "User is prompt before running"
|
||||
Qgis.SessionOnly = Qgis.PythonMacroMode.SessionOnly
|
||||
Qgis.SessionOnly.is_monkey_patched = True
|
||||
Qgis.SessionOnly.__doc__ = "Only during this session"
|
||||
Qgis.Always = Qgis.PythonMacroMode.Always
|
||||
Qgis.Always.is_monkey_patched = True
|
||||
Qgis.Always.__doc__ = "Macros are always run"
|
||||
Qgis.NotForThisSession = Qgis.PythonMacroMode.NotForThisSession
|
||||
Qgis.NotForThisSession.is_monkey_patched = True
|
||||
Qgis.NotForThisSession.__doc__ = "Macros will not be run for this session"
|
||||
Qgis.PythonMacroMode.__doc__ = """Authorisation to run Python Macros
|
||||
Qgis.PythonEmbeddedMode.Never.__doc__ = "Python embedded never run"
|
||||
Qgis.PythonEmbeddedMode.Ask.__doc__ = "User is prompt before running"
|
||||
Qgis.PythonEmbeddedMode.SessionOnly.__doc__ = "Only during this session"
|
||||
Qgis.PythonEmbeddedMode.Always.__doc__ = "Python embedded is always run"
|
||||
Qgis.PythonEmbeddedMode.NotForThisSession.__doc__ = "Python embedded will not be run for this session"
|
||||
Qgis.PythonEmbeddedMode.__doc__ = """Authorisation to run Python Embedded in projects
|
||||
|
||||
.. versionadded:: 3.10
|
||||
.. versionadded:: 3.40
|
||||
|
||||
* ``Never``: Macros are never run
|
||||
* ``Never``: Python embedded never run
|
||||
* ``Ask``: User is prompt before running
|
||||
* ``SessionOnly``: Only during this session
|
||||
* ``Always``: Macros are always run
|
||||
* ``NotForThisSession``: Macros will not be run for this session
|
||||
* ``Always``: Python embedded is always run
|
||||
* ``NotForThisSession``: Python embedded will not be run for this session
|
||||
|
||||
"""
|
||||
# --
|
||||
Qgis.PythonMacroMode.baseClass = Qgis
|
||||
Qgis.PythonEmbeddedMode.baseClass = Qgis
|
||||
# monkey patching scoped based enum
|
||||
Qgis.PythonEmbeddedType.Macro.__doc__ = ""
|
||||
Qgis.PythonEmbeddedType.ExpressionFunction.__doc__ = ""
|
||||
Qgis.PythonEmbeddedType.__doc__ = """Type of Python Embedded in projects
|
||||
|
||||
.. versionadded:: 3.40
|
||||
|
||||
* ``Macro``:
|
||||
* ``ExpressionFunction``:
|
||||
|
||||
"""
|
||||
# --
|
||||
Qgis.PythonEmbeddedType.baseClass = Qgis
|
||||
QgsDataProvider.ReadFlag = Qgis.DataProviderReadFlag
|
||||
# monkey patching scoped based enum
|
||||
QgsDataProvider.FlagTrustDataSource = Qgis.DataProviderReadFlag.TrustDataSource
|
||||
|
@ -519,8 +519,6 @@ Returns the number of functions defined in the parser
|
||||
:return: The number of function defined in the parser.
|
||||
%End
|
||||
|
||||
|
||||
|
||||
static QString quotedColumnRef( QString name );
|
||||
%Docstring
|
||||
Returns a quoted column reference (in double quotes)
|
||||
|
@ -1657,6 +1657,9 @@ Sets the elevation shading renderer used for global map shading
|
||||
.. versionadded:: 3.30
|
||||
%End
|
||||
|
||||
|
||||
|
||||
|
||||
SIP_PYOBJECT __repr__();
|
||||
%MethodCode
|
||||
QString str = QStringLiteral( "<QgsProject: '%1'%2>" ).arg( sipCpp->fileName(),
|
||||
|
@ -224,8 +224,8 @@ The development version
|
||||
typedef QFlags<Qgis::VectorLayerTypeFlag> VectorLayerTypeFlags;
|
||||
|
||||
|
||||
enum class PythonMacroMode
|
||||
{
|
||||
enum class PythonEmbeddedMode
|
||||
{
|
||||
Never,
|
||||
Ask,
|
||||
SessionOnly,
|
||||
@ -233,6 +233,12 @@ The development version
|
||||
NotForThisSession,
|
||||
};
|
||||
|
||||
enum class PythonEmbeddedType
|
||||
{
|
||||
Macro,
|
||||
ExpressionFunction,
|
||||
};
|
||||
|
||||
enum class DataProviderReadFlag
|
||||
{
|
||||
TrustDataSource,
|
||||
|
@ -251,7 +251,6 @@ Returns the screen at the given global ``point`` (pixel).
|
||||
|
||||
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
void optionsChanged();
|
||||
|
@ -230,11 +230,11 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
|
||||
// non-default themes are best rendered using the Fusion style, therefore changing themes must require a restart to
|
||||
lblUITheme->setText( QStringLiteral( "%1 <i>(%2)</i>" ).arg( lblUITheme->text(), tr( "QGIS restart required" ) ) );
|
||||
|
||||
mEnableMacrosComboBox->addItem( tr( "Never" ), QVariant::fromValue( Qgis::PythonMacroMode::Never ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "Ask" ), QVariant::fromValue( Qgis::PythonMacroMode::Ask ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "For This Session Only" ), QVariant::fromValue( Qgis::PythonMacroMode::SessionOnly ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "Not During This Session" ), QVariant::fromValue( Qgis::PythonMacroMode::NotForThisSession ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "Always (Not Recommended)" ), QVariant::fromValue( Qgis::PythonMacroMode::Always ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "Never" ), QVariant::fromValue( Qgis::PythonEmbeddedMode::Never ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "Ask" ), QVariant::fromValue( Qgis::PythonEmbeddedMode::Ask ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "For This Session Only" ), QVariant::fromValue( Qgis::PythonEmbeddedMode::SessionOnly ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "Not During This Session" ), QVariant::fromValue( Qgis::PythonEmbeddedMode::NotForThisSession ) );
|
||||
mEnableMacrosComboBox->addItem( tr( "Always (Not Recommended)" ), QVariant::fromValue( Qgis::PythonEmbeddedMode::Always ) );
|
||||
|
||||
mIdentifyHighlightColorButton->setColorDialogTitle( tr( "Identify Highlight Color" ) );
|
||||
mIdentifyHighlightColorButton->setAllowOpacity( true );
|
||||
@ -823,8 +823,8 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
|
||||
chbAskToSaveProjectChanges->setChecked( mSettings->value( QStringLiteral( "qgis/askToSaveProjectChanges" ), QVariant( true ) ).toBool() );
|
||||
mLayerDeleteConfirmationChkBx->setChecked( mSettings->value( QStringLiteral( "qgis/askToDeleteLayers" ), true ).toBool() );
|
||||
chbWarnOldProjectVersion->setChecked( mSettings->value( QStringLiteral( "/qgis/warnOldProjectVersion" ), QVariant( true ) ).toBool() );
|
||||
Qgis::PythonMacroMode pyMacroMode = mSettings->enumValue( QStringLiteral( "/qgis/enableMacros" ), Qgis::PythonMacroMode::Ask );
|
||||
mEnableMacrosComboBox->setCurrentIndex( mEnableMacrosComboBox->findData( QVariant::fromValue( pyMacroMode ) ) );
|
||||
Qgis::PythonEmbeddedMode pyEmbeddedMode = mSettings->enumValue( QStringLiteral( "/qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::Ask );
|
||||
mEnableMacrosComboBox->setCurrentIndex( mEnableMacrosComboBox->findData( QVariant::fromValue( pyEmbeddedMode ) ) );
|
||||
|
||||
mDefaultPathsComboBox->addItem( tr( "Absolute" ), static_cast< int >( Qgis::FilePathType::Absolute ) );
|
||||
mDefaultPathsComboBox->addItem( tr( "Relative" ), static_cast< int >( Qgis::FilePathType::Relative ) );
|
||||
@ -1655,7 +1655,7 @@ void QgsOptions::saveOptions()
|
||||
mSettings->setValue( QStringLiteral( "/qgis/projectTemplateDir" ), leTemplateFolder->text() );
|
||||
QgisApp::instance()->updateProjectFromTemplates();
|
||||
}
|
||||
mSettings->setEnumValue( QStringLiteral( "/qgis/enableMacros" ), mEnableMacrosComboBox->currentData().value<Qgis::PythonMacroMode>() );
|
||||
mSettings->setEnumValue( QStringLiteral( "/qgis/enablePythonEmbedded" ), mEnableMacrosComboBox->currentData().value<Qgis::PythonEmbeddedMode>() );
|
||||
|
||||
mSettings->setValue( QStringLiteral( "/qgis/defaultProjectPathsRelative" ),
|
||||
static_cast< Qgis::FilePathType >( mDefaultPathsComboBox->currentData().toInt() ) == Qgis::FilePathType::Relative );
|
||||
|
@ -2889,17 +2889,17 @@ void QgisApp::readSettings()
|
||||
readRecentProjects();
|
||||
|
||||
// this is a new session, reset enable macros value when they are set for session
|
||||
Qgis::PythonMacroMode macroMode = settings.enumValue( QStringLiteral( "qgis/enableMacros" ), Qgis::PythonMacroMode::Ask );
|
||||
switch ( macroMode )
|
||||
Qgis::PythonEmbeddedMode pythonEmbeddedMode = settings.enumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::Ask );
|
||||
switch ( pythonEmbeddedMode )
|
||||
{
|
||||
case Qgis::PythonMacroMode::NotForThisSession:
|
||||
case Qgis::PythonMacroMode::SessionOnly:
|
||||
settings.setEnumValue( QStringLiteral( "qgis/enableMacros" ), Qgis::PythonMacroMode::Ask );
|
||||
case Qgis::PythonEmbeddedMode::NotForThisSession:
|
||||
case Qgis::PythonEmbeddedMode::SessionOnly:
|
||||
settings.setEnumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::Ask );
|
||||
break;
|
||||
|
||||
case Qgis::PythonMacroMode::Always:
|
||||
case Qgis::PythonMacroMode::Never:
|
||||
case Qgis::PythonMacroMode::Ask:
|
||||
case Qgis::PythonEmbeddedMode::Always:
|
||||
case Qgis::PythonEmbeddedMode::Never:
|
||||
case Qgis::PythonEmbeddedMode::Ask:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -6575,14 +6575,14 @@ bool QgisApp::addProject( const QString &projectFile )
|
||||
if ( !QgsProject::instance()->readEntry( QStringLiteral( "Macros" ), QStringLiteral( "/pythonCode" ), QString() ).isEmpty() )
|
||||
{
|
||||
auto lambda = []() {QgisApp::instance()->enableProjectMacros();};
|
||||
QgsGui::pythonMacroAllowed( lambda, mInfoBar );
|
||||
QgsGui::pythonEmbeddedInProjectAllowed( lambda, mInfoBar, Qgis::PythonEmbeddedType::Macro );
|
||||
}
|
||||
|
||||
// does the project have expression functions?
|
||||
const QString projectFunctions = QgsProject::instance()->readEntry( QStringLiteral( "ExpressionFunctions" ), QStringLiteral( "/pythonCode" ), QString() );
|
||||
if ( !projectFunctions.isEmpty() )
|
||||
{
|
||||
QgsGui::pythonExpressionFromProjectAllowed( mInfoBar );
|
||||
QgsGui::pythonEmbeddedInProjectAllowed( nullptr, mInfoBar, Qgis::PythonEmbeddedType::ExpressionFunction );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -13865,15 +13865,6 @@ void QgisApp::closeProject()
|
||||
}
|
||||
mPythonMacrosEnabled = false;
|
||||
|
||||
#ifdef WITH_BINDINGS
|
||||
// unload the project expression functions and reload user expressions
|
||||
const QString projectFunctions = QgsProject::instance()->readEntry( QStringLiteral( "ExpressionFunctions" ), QStringLiteral( "/pythonCode" ), QString() );
|
||||
if ( !projectFunctions.isEmpty() )
|
||||
{
|
||||
QgsExpression::cleanFunctionsFromProject();
|
||||
}
|
||||
#endif
|
||||
|
||||
mLegendExpressionFilterButton->setExpressionText( QString() );
|
||||
mLegendExpressionFilterButton->setChecked( false );
|
||||
mFilterLegendByMapContentAction->setChecked( false );
|
||||
|
@ -630,24 +630,6 @@ class CORE_EXPORT QgsExpression
|
||||
*/
|
||||
static int functionCount();
|
||||
|
||||
/**
|
||||
* Loads python expression functions stored in the currrent project
|
||||
* \returns Whether the project functions where loaded or not.
|
||||
*
|
||||
* \note not available in Python bindings
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
static bool loadFunctionsFromProject() SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Unloads python expression functions stored in the current project
|
||||
* and reloads local functions from the user profile.
|
||||
*
|
||||
* \note not available in Python bindings
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
static void cleanFunctionsFromProject() SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Returns a quoted column reference (in double quotes)
|
||||
* \see quotedString()
|
||||
|
@ -64,7 +64,6 @@
|
||||
#include "qgsunittypes.h"
|
||||
#include "qgsspatialindex.h"
|
||||
#include "qgscolorrampimpl.h"
|
||||
#include "qgspythonrunner.h"
|
||||
|
||||
#include <QMimeDatabase>
|
||||
#include <QProcessEnvironment>
|
||||
@ -9502,22 +9501,6 @@ const QStringList &QgsExpression::BuiltinFunctions()
|
||||
return *sBuiltinFunctions();
|
||||
}
|
||||
|
||||
bool QgsExpression::loadFunctionsFromProject()
|
||||
{
|
||||
const QString projectFunctions = QgsProject::instance()->readEntry( QStringLiteral( "ExpressionFunctions" ), QStringLiteral( "/pythonCode" ), QString() );
|
||||
if ( !projectFunctions.isEmpty() )
|
||||
{
|
||||
QgsPythonRunner::run( projectFunctions );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsExpression::cleanFunctionsFromProject()
|
||||
{
|
||||
QgsPythonRunner::run( "qgis.utils.clean_project_expression_functions()" );
|
||||
}
|
||||
|
||||
QgsArrayForeachExpressionFunction::QgsArrayForeachExpressionFunction()
|
||||
: QgsExpressionFunction( QStringLiteral( "array_foreach" ), QgsExpressionFunction::ParameterList() // skip-keyword-check
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "array" ) )
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "qgsrunnableprovidercreator.h"
|
||||
#include "qgssettingsregistrycore.h"
|
||||
#include "qgspluginlayer.h"
|
||||
#include "qgspythonrunner.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QApplication>
|
||||
@ -1167,6 +1168,15 @@ void QgsProject::clear()
|
||||
|
||||
emit aboutToBeCleared();
|
||||
|
||||
if ( !mIsBeingDeleted )
|
||||
{
|
||||
// Unregister expression functions stored in the project.
|
||||
// If we clean on destruction we may end-up with a non-valid
|
||||
// mPythonUtils, so be safe and only clean when not destroying.
|
||||
// This should be called before calling mProperties.clearKeys().
|
||||
cleanFunctionsFromProject();
|
||||
}
|
||||
|
||||
mProjectScope.reset();
|
||||
mFile.setFileName( QString() );
|
||||
mProperties.clearKeys();
|
||||
@ -2284,6 +2294,11 @@ bool QgsProject::readProjectFile( const QString &filename, Qgis::ProjectReadFlag
|
||||
QgsMessageLog::logMessage( tr( "Project Variables Invalid" ), tr( "The project contains invalid variable settings." ) );
|
||||
}
|
||||
|
||||
// Register expression functions stored in the project.
|
||||
// They might be using project variables and might be
|
||||
// in turn being used by other components (e.g., layouts).
|
||||
loadFunctionsFromProject();
|
||||
|
||||
QDomElement element = doc->documentElement().firstChildElement( QStringLiteral( "projectMetadata" ) );
|
||||
|
||||
if ( !element.isNull() )
|
||||
@ -5266,6 +5281,33 @@ void QgsProject::loadProjectFlags( const QDomDocument *doc )
|
||||
setFlags( flags );
|
||||
}
|
||||
|
||||
bool QgsProject::loadFunctionsFromProject( bool force )
|
||||
{
|
||||
if ( QgsPythonRunner::isValid() )
|
||||
{
|
||||
const Qgis::PythonEmbeddedMode pythonEmbeddedMode = QgsSettings().enumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::Ask );
|
||||
|
||||
if ( force || pythonEmbeddedMode == Qgis::PythonEmbeddedMode::SessionOnly || pythonEmbeddedMode == Qgis::PythonEmbeddedMode::Always )
|
||||
{
|
||||
const QString projectFunctions = readEntry( QStringLiteral( "ExpressionFunctions" ), QStringLiteral( "/pythonCode" ), QString() );
|
||||
if ( !projectFunctions.isEmpty() )
|
||||
{
|
||||
QgsPythonRunner::run( projectFunctions );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsProject::cleanFunctionsFromProject()
|
||||
{
|
||||
if ( QgsPythonRunner::isValid() )
|
||||
{
|
||||
QgsPythonRunner::run( "qgis.utils.clean_project_expression_functions()" );
|
||||
}
|
||||
}
|
||||
|
||||
/// @cond PRIVATE
|
||||
GetNamedProjectColor::GetNamedProjectColor( const QgsProject *project )
|
||||
: QgsScopedExpressionFunction( QStringLiteral( "project_color" ), 1, QStringLiteral( "Color" ) )
|
||||
|
@ -1698,6 +1698,26 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
|
||||
*/
|
||||
void setElevationShadingRenderer( const QgsElevationShadingRenderer &elevationShadingRenderer );
|
||||
|
||||
/**
|
||||
* Loads python expression functions stored in the currrent project
|
||||
* \param force Whether to check enablePythonEmbedded setting (default) or not.
|
||||
* \returns Whether the project functions were loaded or not.
|
||||
*
|
||||
* \note not available in Python bindings
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
bool loadFunctionsFromProject( bool force = false ) SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Unloads python expression functions stored in the current project
|
||||
* and reloads local functions from the user profile.
|
||||
*
|
||||
* \note not available in Python bindings
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
void cleanFunctionsFromProject() SIP_SKIP;
|
||||
|
||||
|
||||
#ifdef SIP_RUN
|
||||
SIP_PYOBJECT __repr__();
|
||||
% MethodCode
|
||||
|
@ -333,18 +333,29 @@ class CORE_EXPORT Qgis
|
||||
Q_FLAG( VectorLayerTypeFlags )
|
||||
|
||||
/**
|
||||
* Authorisation to run Python Macros
|
||||
* \since QGIS 3.10
|
||||
* Authorisation to run Python Embedded in projects
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
enum class PythonMacroMode SIP_MONKEYPATCH_SCOPEENUM_UNNEST( Qgis, PythonMacroMode ) : int
|
||||
{
|
||||
Never = 0, //!< Macros are never run
|
||||
enum class PythonEmbeddedMode : int
|
||||
{
|
||||
Never = 0, //!< Python embedded never run
|
||||
Ask = 1, //!< User is prompt before running
|
||||
SessionOnly = 2, //!< Only during this session
|
||||
Always = 3, //!< Macros are always run
|
||||
NotForThisSession, //!< Macros will not be run for this session
|
||||
Always = 3, //!< Python embedded is always run
|
||||
NotForThisSession, //!< Python embedded will not be run for this session
|
||||
};
|
||||
Q_ENUM( PythonMacroMode )
|
||||
Q_ENUM( PythonEmbeddedMode )
|
||||
|
||||
/**
|
||||
* Type of Python Embedded in projects
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
enum class PythonEmbeddedType : int
|
||||
{
|
||||
Macro = 0,
|
||||
ExpressionFunction = 1,
|
||||
};
|
||||
Q_ENUM( PythonEmbeddedType )
|
||||
|
||||
/**
|
||||
* Flags which control data provider construction.
|
||||
|
@ -2356,7 +2356,7 @@ void QgsAttributeForm::initPython()
|
||||
// If we have a function code, run it
|
||||
if ( !initCode.isEmpty() )
|
||||
{
|
||||
if ( QgsGui::pythonMacroAllowed() )
|
||||
if ( QgsGui::pythonEmbeddedInProjectAllowed( nullptr, nullptr, Qgis::PythonEmbeddedType::Macro ) )
|
||||
QgsPythonRunner::run( initCode );
|
||||
else
|
||||
mMessageBar->pushMessage( QString(),
|
||||
|
@ -13,9 +13,10 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsexpressionaddfunctionfiledialog.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include "qgsexpressionaddfunctionfiledialog.h"
|
||||
|
||||
QgsExpressionAddFunctionFileDialog::QgsExpressionAddFunctionFileDialog( bool enableProjectFunctions, QWidget *parent )
|
||||
: QDialog( parent )
|
||||
|
@ -370,71 +370,121 @@ QgsGui::QgsGui()
|
||||
qRegisterMetaType< QgsHistoryEntry >( "QgsHistoryEntry" );
|
||||
}
|
||||
|
||||
bool QgsGui::pythonMacroAllowed( void ( *lambda )(), QgsMessageBar *messageBar )
|
||||
bool QgsGui::pythonEmbeddedInProjectAllowed( void ( *lambda )(), QgsMessageBar *messageBar, Qgis::PythonEmbeddedType embeddedType )
|
||||
{
|
||||
const Qgis::PythonMacroMode macroMode = QgsSettings().enumValue( QStringLiteral( "qgis/enableMacros" ), Qgis::PythonMacroMode::Ask );
|
||||
const Qgis::PythonEmbeddedMode pythonEmbeddedMode = QgsSettings().enumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::Ask );
|
||||
|
||||
switch ( macroMode )
|
||||
switch ( pythonEmbeddedMode )
|
||||
{
|
||||
case Qgis::PythonMacroMode::SessionOnly:
|
||||
case Qgis::PythonMacroMode::Always:
|
||||
if ( lambda )
|
||||
lambda();
|
||||
case Qgis::PythonEmbeddedMode::SessionOnly:
|
||||
case Qgis::PythonEmbeddedMode::Always:
|
||||
if ( embeddedType == Qgis::PythonEmbeddedType::Macro )
|
||||
{
|
||||
if ( lambda )
|
||||
lambda();
|
||||
}
|
||||
// If this is the case, expression functions
|
||||
// are loaded directly by the QGIS project.
|
||||
return true;
|
||||
case Qgis::PythonMacroMode::Never:
|
||||
case Qgis::PythonMacroMode::NotForThisSession:
|
||||
case Qgis::PythonEmbeddedMode::Never:
|
||||
case Qgis::PythonEmbeddedMode::NotForThisSession:
|
||||
if ( messageBar )
|
||||
{
|
||||
messageBar->pushMessage( tr( "Python Macros" ),
|
||||
tr( "Python macros are currently disabled and will not be run" ),
|
||||
Qgis::MessageLevel::Warning );
|
||||
switch ( embeddedType )
|
||||
{
|
||||
case Qgis::PythonEmbeddedType::Macro:
|
||||
messageBar->pushMessage( tr( "Python Macros" ),
|
||||
tr( "Python macros are currently disabled and will not be run" ),
|
||||
Qgis::MessageLevel::Warning );
|
||||
break;
|
||||
case Qgis::PythonEmbeddedType::ExpressionFunction:
|
||||
messageBar->pushMessage( tr( "Python Expressions" ),
|
||||
tr( "Python expressions from project are currently disabled and will not be loaded" ),
|
||||
Qgis::MessageLevel::Warning );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case Qgis::PythonMacroMode::Ask:
|
||||
if ( !lambda )
|
||||
case Qgis::PythonEmbeddedMode::Ask:
|
||||
if ( embeddedType == Qgis::PythonEmbeddedType::Macro )
|
||||
{
|
||||
QMessageBox msgBox( QMessageBox::Information, tr( "Python Macros" ),
|
||||
tr( "Python macros are currently disabled. Do you allow this macro to run?" ) );
|
||||
QAbstractButton *stopSessionButton = msgBox.addButton( tr( "Disable for this Session" ), QMessageBox::DestructiveRole );
|
||||
msgBox.addButton( tr( "No" ), QMessageBox::NoRole );
|
||||
QAbstractButton *yesButton = msgBox.addButton( tr( "Yes" ), QMessageBox::YesRole );
|
||||
msgBox.exec();
|
||||
|
||||
QAbstractButton *clicked = msgBox.clickedButton();
|
||||
if ( clicked == stopSessionButton )
|
||||
if ( !lambda )
|
||||
{
|
||||
QgsSettings().setEnumValue( QStringLiteral( "qgis/enableMacros" ), Qgis::PythonMacroMode::NotForThisSession );
|
||||
QMessageBox msgBox( QMessageBox::Information, tr( "Python Macros" ),
|
||||
tr( "Python macros are currently disabled. Do you allow this macro to run?" ) );
|
||||
QAbstractButton *stopSessionButton = msgBox.addButton( tr( "Disable for this Session" ), QMessageBox::DestructiveRole );
|
||||
msgBox.addButton( tr( "No" ), QMessageBox::NoRole );
|
||||
QAbstractButton *yesButton = msgBox.addButton( tr( "Yes" ), QMessageBox::YesRole );
|
||||
msgBox.exec();
|
||||
|
||||
QAbstractButton *clicked = msgBox.clickedButton();
|
||||
if ( clicked == stopSessionButton )
|
||||
{
|
||||
QgsSettings().setEnumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::NotForThisSession );
|
||||
}
|
||||
return clicked == yesButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
// create the notification widget for macros
|
||||
Q_ASSERT( messageBar );
|
||||
if ( messageBar )
|
||||
{
|
||||
QToolButton *btnEnableMacros = new QToolButton();
|
||||
btnEnableMacros->setText( tr( "Enable Macros" ) );
|
||||
btnEnableMacros->setStyleSheet( QStringLiteral( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ) );
|
||||
btnEnableMacros->setCursor( Qt::PointingHandCursor );
|
||||
btnEnableMacros->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
|
||||
|
||||
QgsMessageBarItem *macroMsg = new QgsMessageBarItem(
|
||||
tr( "Security warning" ),
|
||||
tr( "Python macros cannot currently be run." ),
|
||||
btnEnableMacros,
|
||||
Qgis::MessageLevel::Warning,
|
||||
0,
|
||||
messageBar );
|
||||
|
||||
connect( btnEnableMacros, &QToolButton::clicked, messageBar, [ = ]()
|
||||
{
|
||||
lambda();
|
||||
messageBar->popWidget( macroMsg );
|
||||
} );
|
||||
|
||||
// display the macros notification widget
|
||||
messageBar->pushItem( macroMsg );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return clicked == yesButton;
|
||||
}
|
||||
else
|
||||
else if ( embeddedType == Qgis::PythonEmbeddedType::ExpressionFunction )
|
||||
{
|
||||
// create the notification widget for macros
|
||||
// create the notification widget for expressions from project
|
||||
Q_ASSERT( messageBar );
|
||||
if ( messageBar )
|
||||
{
|
||||
QToolButton *btnEnableMacros = new QToolButton();
|
||||
btnEnableMacros->setText( tr( "Enable Macros" ) );
|
||||
btnEnableMacros->setStyleSheet( QStringLiteral( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ) );
|
||||
btnEnableMacros->setCursor( Qt::PointingHandCursor );
|
||||
btnEnableMacros->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
|
||||
QToolButton *btnEnableExpressionsFromProject = new QToolButton();
|
||||
btnEnableExpressionsFromProject->setText( tr( "Enable python expressions from project" ) );
|
||||
btnEnableExpressionsFromProject->setStyleSheet( QStringLiteral( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ) );
|
||||
btnEnableExpressionsFromProject->setCursor( Qt::PointingHandCursor );
|
||||
btnEnableExpressionsFromProject->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
|
||||
|
||||
QgsMessageBarItem *macroMsg = new QgsMessageBarItem(
|
||||
QgsMessageBarItem *expressionFromProjectMsg = new QgsMessageBarItem(
|
||||
tr( "Security warning" ),
|
||||
tr( "Python macros cannot currently be run." ),
|
||||
btnEnableMacros,
|
||||
tr( "Python expressions from project cannot currently be loaded." ),
|
||||
btnEnableExpressionsFromProject,
|
||||
Qgis::MessageLevel::Warning,
|
||||
0,
|
||||
messageBar );
|
||||
|
||||
connect( btnEnableMacros, &QToolButton::clicked, messageBar, [ = ]()
|
||||
connect( btnEnableExpressionsFromProject, &QToolButton::clicked, messageBar, [ = ]()
|
||||
{
|
||||
lambda();
|
||||
messageBar->popWidget( macroMsg );
|
||||
QgsProject::instance()->loadFunctionsFromProject( true );
|
||||
messageBar->popWidget( expressionFromProjectMsg );
|
||||
} );
|
||||
|
||||
// display the macros notification widget
|
||||
messageBar->pushItem( macroMsg );
|
||||
// display the notification widget
|
||||
messageBar->pushItem( expressionFromProjectMsg );
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -443,59 +493,6 @@ bool QgsGui::pythonMacroAllowed( void ( *lambda )(), QgsMessageBar *messageBar )
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsGui::pythonExpressionFromProjectAllowed( QgsMessageBar *messageBar )
|
||||
{
|
||||
const Qgis::PythonMacroMode pythonMode = QgsSettings().enumValue( QStringLiteral( "qgis/enableMacros" ), Qgis::PythonMacroMode::Ask );
|
||||
|
||||
switch ( pythonMode )
|
||||
{
|
||||
case Qgis::PythonMacroMode::SessionOnly:
|
||||
case Qgis::PythonMacroMode::Always:
|
||||
QgsExpression::loadFunctionsFromProject();
|
||||
return true;
|
||||
case Qgis::PythonMacroMode::Never:
|
||||
case Qgis::PythonMacroMode::NotForThisSession:
|
||||
if ( messageBar )
|
||||
{
|
||||
messageBar->pushMessage( tr( "Python Expressions" ),
|
||||
tr( "Python expressions from project are currently disabled and will not be loaded" ),
|
||||
Qgis::MessageLevel::Warning );
|
||||
}
|
||||
return false;
|
||||
case Qgis::PythonMacroMode::Ask:
|
||||
// create the notification widget for expressions from project
|
||||
Q_ASSERT( messageBar );
|
||||
if ( messageBar )
|
||||
{
|
||||
QToolButton *btnEnableExpressionsFromProject = new QToolButton();
|
||||
btnEnableExpressionsFromProject->setText( tr( "Enable python expressions from project" ) );
|
||||
btnEnableExpressionsFromProject->setStyleSheet( QStringLiteral( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ) );
|
||||
btnEnableExpressionsFromProject->setCursor( Qt::PointingHandCursor );
|
||||
btnEnableExpressionsFromProject->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
|
||||
|
||||
QgsMessageBarItem *expressionFromProjectMsg = new QgsMessageBarItem(
|
||||
tr( "Security warning" ),
|
||||
tr( "Python expressions from project cannot currently be loaded." ),
|
||||
btnEnableExpressionsFromProject,
|
||||
Qgis::MessageLevel::Warning,
|
||||
0,
|
||||
messageBar );
|
||||
|
||||
connect( btnEnableExpressionsFromProject, &QToolButton::clicked, messageBar, [ = ]()
|
||||
{
|
||||
QgsExpression::loadFunctionsFromProject();
|
||||
messageBar->popWidget( expressionFromProjectMsg );
|
||||
} );
|
||||
|
||||
// display the notification widget
|
||||
messageBar->pushItem( expressionFromProjectMsg );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsGui::initCalloutWidgets()
|
||||
{
|
||||
static std::once_flag initialized;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#ifndef QGSGUI_H
|
||||
#define QGSGUI_H
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgis_gui.h"
|
||||
#include "qgis_sip.h"
|
||||
#include <QWidget>
|
||||
@ -291,28 +292,20 @@ class GUI_EXPORT QgsGui : public QObject
|
||||
static QScreen *findScreenAt( QPoint point );
|
||||
|
||||
/**
|
||||
* Returns TRUE if python macros are currently allowed to be run
|
||||
* If the global option is to ask user, a modal dialog will be shown
|
||||
* Returns TRUE if python embedded in a project is currently allowed to be loaded.
|
||||
* If the global option is to ask user, a modal dialog will be shown for macros
|
||||
* or a button to enable Python expressions will be shown in a message bar.
|
||||
* \param lambda a pointer to a lambda method. If specified, the dialog is not modal,
|
||||
* a message is shown with a button to enable macro.
|
||||
* The lambda will be run either if macros are currently allowed or if the user accepts the message.
|
||||
* The \a messageBar must be given in such case.
|
||||
* \param messageBar the message bar must be provided if a lambda method is used.
|
||||
*
|
||||
* \note Not available in Python bindings
|
||||
*/
|
||||
static bool pythonMacroAllowed( void ( *lambda )() = nullptr, QgsMessageBar *messageBar = nullptr ) SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Returns TRUE if python expression functions from project are currently allowed to be loaded.
|
||||
*
|
||||
* If the global option is to ask user, a button to enable them will be shown in a message bar.
|
||||
* \param messageBar Message bar to communicate with the user.
|
||||
* \param embeddedType enum value to identify if macros or expression functions should be checked.
|
||||
*
|
||||
* \note Not available in Python bindings
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
static bool pythonExpressionFromProjectAllowed( QgsMessageBar *messageBar ) SIP_SKIP;
|
||||
static bool pythonEmbeddedInProjectAllowed( void ( *lambda )() = nullptr, QgsMessageBar *messageBar = nullptr, Qgis::PythonEmbeddedType embeddedType = Qgis::PythonEmbeddedType::Macro ) SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Initializes callout widgets.
|
||||
|
@ -1,96 +0,0 @@
|
||||
/********************************************************************************
|
||||
** Form generated from reading UI file 'qgsexpressionaddfunctionfiledialogbase.ui'
|
||||
**
|
||||
** Created by: Qt User Interface Compiler version 5.15.3
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef QGSEXPRESSIONADDFUNCTIONFILEDIALOGBASE_H
|
||||
#define QGSEXPRESSIONADDFUNCTIONFILEDIALOGBASE_H
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QGridLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Ui_QgsAddFunctionFileDialogBase
|
||||
{
|
||||
public:
|
||||
QGridLayout *gridLayout;
|
||||
QLabel *label;
|
||||
QComboBox *cboFileOptions;
|
||||
QLabel *lblNewFileName;
|
||||
QDialogButtonBox *buttonBox;
|
||||
QLineEdit *txtNewFileName;
|
||||
|
||||
void setupUi( QDialog *QgsAddFunctionFileDialogBase )
|
||||
{
|
||||
if ( QgsAddFunctionFileDialogBase->objectName().isEmpty() )
|
||||
QgsAddFunctionFileDialogBase->setObjectName( QString::fromUtf8( "QgsAddFunctionFileDialogBase" ) );
|
||||
QgsAddFunctionFileDialogBase->resize( 277, 132 );
|
||||
gridLayout = new QGridLayout( QgsAddFunctionFileDialogBase );
|
||||
gridLayout->setObjectName( QString::fromUtf8( "gridLayout" ) );
|
||||
label = new QLabel( QgsAddFunctionFileDialogBase );
|
||||
label->setObjectName( QString::fromUtf8( "label" ) );
|
||||
|
||||
gridLayout->addWidget( label, 0, 0, 1, 1 );
|
||||
|
||||
cboFileOptions = new QComboBox( QgsAddFunctionFileDialogBase );
|
||||
cboFileOptions->addItem( QString() );
|
||||
cboFileOptions->addItem( QString() );
|
||||
cboFileOptions->setObjectName( QString::fromUtf8( "cboFileOptions" ) );
|
||||
|
||||
gridLayout->addWidget( cboFileOptions, 0, 1, 1, 1 );
|
||||
|
||||
lblNewFileName = new QLabel( QgsAddFunctionFileDialogBase );
|
||||
lblNewFileName->setObjectName( QString::fromUtf8( "lblNewFileName" ) );
|
||||
|
||||
gridLayout->addWidget( lblNewFileName, 1, 0, 1, 1 );
|
||||
|
||||
buttonBox = new QDialogButtonBox( QgsAddFunctionFileDialogBase );
|
||||
buttonBox->setObjectName( QString::fromUtf8( "buttonBox" ) );
|
||||
buttonBox->setOrientation( Qt::Horizontal );
|
||||
buttonBox->setStandardButtons( QDialogButtonBox::Cancel | QDialogButtonBox::Ok );
|
||||
|
||||
gridLayout->addWidget( buttonBox, 2, 0, 1, 2 );
|
||||
|
||||
txtNewFileName = new QLineEdit( QgsAddFunctionFileDialogBase );
|
||||
txtNewFileName->setObjectName( QString::fromUtf8( "txtNewFileName" ) );
|
||||
|
||||
gridLayout->addWidget( txtNewFileName, 1, 1, 1, 1 );
|
||||
|
||||
|
||||
retranslateUi( QgsAddFunctionFileDialogBase );
|
||||
QObject::connect( buttonBox, SIGNAL( accepted() ), QgsAddFunctionFileDialogBase, SLOT( accept() ) );
|
||||
QObject::connect( buttonBox, SIGNAL( rejected() ), QgsAddFunctionFileDialogBase, SLOT( reject() ) );
|
||||
|
||||
QMetaObject::connectSlotsByName( QgsAddFunctionFileDialogBase );
|
||||
} // setupUi
|
||||
|
||||
void retranslateUi( QDialog *QgsAddFunctionFileDialogBase )
|
||||
{
|
||||
QgsAddFunctionFileDialogBase->setWindowTitle( QCoreApplication::translate( "QgsAddFunctionFileDialogBase", "Add Function File", nullptr ) );
|
||||
label->setText( QCoreApplication::translate( "QgsAddFunctionFileDialogBase", "Create", nullptr ) );
|
||||
cboFileOptions->setItemText( 0, QCoreApplication::translate( "QgsAddFunctionFileDialogBase", "Function file", nullptr ) );
|
||||
cboFileOptions->setItemText( 1, QCoreApplication::translate( "QgsAddFunctionFileDialogBase", "Project functions", nullptr ) );
|
||||
|
||||
lblNewFileName->setText( QCoreApplication::translate( "QgsAddFunctionFileDialogBase", "File name", nullptr ) );
|
||||
} // retranslateUi
|
||||
|
||||
};
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class QgsAddFunctionFileDialogBase: public Ui_QgsAddFunctionFileDialogBase {};
|
||||
} // namespace Ui
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QGSEXPRESSIONADDFUNCTIONFILEDIALOGBASE_H
|
@ -82,9 +82,17 @@ void TestQgsProjectExpressions::projectExpressions()
|
||||
// Load expressions from project
|
||||
// Project registers 2 functions: mychoice (overwriting it) and myprojectfunction
|
||||
const QByteArray projectPath = QByteArray( TEST_DATA_DIR ) + "/projects/test_project_functions.qgz";
|
||||
|
||||
const Qgis::PythonEmbeddedMode pythonEmbeddedMode = QgsSettings().enumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::Ask );
|
||||
QgsSettings().setEnumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::Never );
|
||||
QgsProject::instance()->read( projectPath );
|
||||
QCOMPARE( QgsExpression::functionIndex( QStringLiteral( "myprojectfunction" ) ), -1 );
|
||||
QgsExpression::loadFunctionsFromProject();
|
||||
|
||||
// Set the global setting to accept expression functions
|
||||
QgsSettings().setEnumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), Qgis::PythonEmbeddedMode::SessionOnly );
|
||||
QgsProject::instance()->loadFunctionsFromProject();
|
||||
QgsSettings().setEnumValue( QStringLiteral( "qgis/enablePythonEmbedded" ), pythonEmbeddedMode );
|
||||
|
||||
QVERIFY( QgsExpression::functionIndex( QStringLiteral( "myprojectfunction" ) ) != -1 );
|
||||
QVERIFY( QgsExpression::functionIndex( QStringLiteral( "mychoice" ) ) != -1 ); // Overwritten function
|
||||
const int count_project_loaded = QgsExpression::functionCount();
|
||||
@ -95,7 +103,7 @@ void TestQgsProjectExpressions::projectExpressions()
|
||||
QCOMPARE( exp.evaluate().toInt(), 2 ); // Different result because now it's from project
|
||||
|
||||
// Unload expressions from project, reload user ones
|
||||
QgsExpression::cleanFunctionsFromProject();
|
||||
QgsProject::instance()->cleanFunctionsFromProject();
|
||||
const int count_project_unloaded = QgsExpression::functionCount();
|
||||
QCOMPARE( count_before_project, count_project_unloaded ); // myprojectfunction is gone
|
||||
|
||||
|
@ -133,7 +133,7 @@ class TestQgsEditFormConfig(QgisTestCase):
|
||||
pyUrl = 'http://localhost:' + \
|
||||
str(self.port) + '/qgis_local_server/layer_attribute_form.py'
|
||||
|
||||
QgsSettings().setEnumValue('qgis/enableMacros', Qgis.Always)
|
||||
QgsSettings().setEnumValue('qgis/enablePythonEmbedded', Qgis.Always)
|
||||
|
||||
config.setInitFilePath(pyUrl)
|
||||
config.setInitFunction('formOpen')
|
||||
|
Loading…
x
Reference in New Issue
Block a user