| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| /*************************************************************************** | ||
| qgseditorwidgetsetup.h - Holder for the widget configuration. | ||
| -------------------------------------- | ||
| Date : 01-Sep-2016 | ||
| Copyright : (C) 2016 by Patrick Valsecchi | ||
| email : patrick.valsecchi at camptocamp.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSEDITORWIDGETSETUP_H | ||
| #define QGSEDITORWIDGETSETUP_H | ||
|
|
||
| #include "qgseditorwidgetconfig.h" | ||
|
|
||
| /** \ingroup core | ||
| * Holder for the widget type and its configuration for a field. | ||
| * | ||
| * @note added in QGIS 3.0 | ||
| */ | ||
| class CORE_EXPORT QgsEditorWidgetSetup | ||
| { | ||
| public: | ||
| /** | ||
| * Constructor | ||
| */ | ||
| QgsEditorWidgetSetup( const QString& type, const QgsEditorWidgetConfig& config ) : mType( type ), mConfig( config ) {} | ||
| QgsEditorWidgetSetup() {} | ||
|
|
||
| /** | ||
| * @return the widget type to use | ||
| */ | ||
| QString type() const { return mType; } | ||
|
|
||
| /** | ||
| * @return the widget configuration to used | ||
| */ | ||
| QgsEditorWidgetConfig config() const { return mConfig; } | ||
|
|
||
| /** | ||
| * @return true if there is no widget configured. | ||
| */ | ||
| bool isNull() const { return mType.isEmpty(); } | ||
| private: | ||
| QString mType; | ||
| QgsEditorWidgetConfig mConfig; | ||
| }; | ||
|
|
||
| #endif // QGSEDITORWIDGETSETUP_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| /*************************************************************************** | ||
| qgseditorwidgetautoconf.cpp | ||
| --------------------- | ||
| begin : July 2016 | ||
| copyright : (C) 2016 by Patrick Valsecchi | ||
| email : patrick.valsecchi at camptocamp.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #include "qgseditorwidgetautoconf.h" | ||
| #include "qgseditorwidgetregistry.h" | ||
|
|
||
| /** \ingroup gui | ||
| * Widget auto conf plugin that guesses what widget type to use in function of what the widgets support. | ||
| * | ||
| * @note not available in Python bindings | ||
| * @note added in QGIS 3.0 | ||
| */ | ||
| class FromFactoriesPlugin: public QgsEditorWidgetAutoConfPlugin | ||
| { | ||
| public: | ||
| virtual QgsEditorWidgetSetup editorWidgetSetup( const QgsVectorLayer* vl, const QString& fieldName, int& score ) const override | ||
| { | ||
| int bestScore = 0; | ||
| QString bestType; | ||
| const QMap<QString, QgsEditorWidgetFactory*> factories = QgsEditorWidgetRegistry::instance()->factories(); | ||
| for ( QMap<QString, QgsEditorWidgetFactory*>::const_iterator i = factories.begin(); i != factories.end(); ++i ) | ||
| { | ||
| const int index = vl->fieldNameIndex( fieldName ); | ||
| if ( index >= 0 ) | ||
| { | ||
| const int score = i.value()->fieldScore( vl, index ); | ||
| if ( score > bestScore ) | ||
| { | ||
| bestType = i.key(); | ||
| bestScore = score; | ||
| } | ||
| } | ||
| } | ||
| if ( bestScore > 0 ) | ||
| { | ||
| score = 10; | ||
| return QgsEditorWidgetSetup( bestType, QgsEditorWidgetConfig() ); | ||
| } | ||
| return QgsEditorWidgetSetup(); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
| /** \ingroup gui | ||
| * Widget auto conf plugin that reads the widget setup to use from what the data provider says. | ||
| * | ||
| * @note not available in Python bindings | ||
| * @note added in QGIS 3.0 | ||
| */ | ||
| class FromDbTablePlugin: public QgsEditorWidgetAutoConfPlugin | ||
| { | ||
| public: | ||
| virtual QgsEditorWidgetSetup editorWidgetSetup( const QgsVectorLayer* vl, const QString& fieldName, int& score ) const override | ||
| { | ||
| QgsField field = vl->fields().field( fieldName ); | ||
| if ( !field.editorWidgetSetup().isNull() ) | ||
| { | ||
| score = 20; | ||
| return field.editorWidgetSetup(); | ||
| } | ||
| else | ||
| { | ||
| return QgsEditorWidgetSetup(); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| ///@cond PRIVATE | ||
| QgsEditorWidgetAutoConf::QgsEditorWidgetAutoConf() | ||
| { | ||
| registerPlugin( new FromFactoriesPlugin() ); | ||
| registerPlugin( new FromDbTablePlugin() ); | ||
| } | ||
|
|
||
| QgsEditorWidgetSetup QgsEditorWidgetAutoConf::editorWidgetSetup( const QgsVectorLayer* vl, const QString& fieldName ) const | ||
| { | ||
| QgsEditorWidgetSetup result( "TextEdit", QgsEditorWidgetConfig() ); | ||
|
|
||
| if ( vl->fields().indexFromName( fieldName ) >= 0 ) | ||
| { | ||
| int bestScore = 0; | ||
| Q_FOREACH ( QSharedPointer<QgsEditorWidgetAutoConfPlugin> cur, plugins ) | ||
| { | ||
| int score = 0; | ||
| const QgsEditorWidgetSetup curResult = cur->editorWidgetSetup( vl, fieldName, score ); | ||
| if ( score > bestScore ) | ||
| { | ||
| result = curResult; | ||
| bestScore = score; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| void QgsEditorWidgetAutoConf::registerPlugin( QgsEditorWidgetAutoConfPlugin* plugin ) | ||
| { | ||
| plugins.append( QSharedPointer<QgsEditorWidgetAutoConfPlugin>( plugin ) ); | ||
| } | ||
| ///@endcond |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| /*************************************************************************** | ||
| qgseditorwidgetautoconf.h | ||
| --------------------- | ||
| begin : July 2016 | ||
| copyright : (C) 2016 by Patrick Valsecchi | ||
| email : patrick.valsecchi at camptocamp.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #ifndef QGSEDITORWIDGETAUTOCONF_H | ||
| #define QGSEDITORWIDGETAUTOCONF_H | ||
|
|
||
| #include <QList> | ||
| #include <QSharedPointer> | ||
|
|
||
| class QgsVectorLayer; | ||
| class QgsEditorWidgetSetup; | ||
|
|
||
| /** \ingroup gui | ||
| * Base class for plugins allowing to pick automatically a widget type for editing fields. | ||
| * | ||
| * @note added in QGIS 3.0 | ||
| */ | ||
| class GUI_EXPORT QgsEditorWidgetAutoConfPlugin | ||
| { | ||
| public: | ||
| /** | ||
| * Typical scores are: | ||
| * * 0: no matching type found. | ||
| * * 10: a widget has been guessed from the type of field. | ||
| * * 20: a widget has been determined from an external configuration (for example a database table) | ||
| * | ||
| * @param vl The vector layer for which this widget will be created | ||
| * @param fieldName The field name on the specified layer for which this widget will be created | ||
| * @param score Where the score is returned (default to 0) | ||
| * | ||
| * @return and integer value rating how good is the setup provided by this plugin. | ||
| */ | ||
| virtual QgsEditorWidgetSetup editorWidgetSetup( const QgsVectorLayer* vl, const QString& fieldName, int& score ) const = 0; | ||
|
|
||
| }; | ||
|
|
||
|
|
||
| ///@cond PRIVATE | ||
| /** \ingroup gui | ||
| * Class that allows to register plugins to pick automatically a widget type for editing fields. | ||
| * This class has only one instance, owned by the QgsEditorWidgetRegistry singleton | ||
| * | ||
| * The plugins are instances of QgsEditorWidgetAutoConfPlugin. | ||
| * @note added in QGIS 3.0 | ||
| * @note not available in Python bindings | ||
| */ | ||
| class GUI_EXPORT QgsEditorWidgetAutoConf | ||
| { | ||
| public: | ||
| /** | ||
| * Register the default plugins. | ||
| */ | ||
| QgsEditorWidgetAutoConf(); | ||
|
|
||
| /** | ||
| * Iterate over the plugins and return the setup of the plugin returning the highest score. | ||
| * | ||
| * @param vl The vector layer for which this widget will be created | ||
| * @param fieldName The field name on the specified layer for which this widget will be created | ||
| * | ||
| * @return The best widget setup that was found | ||
| */ | ||
| QgsEditorWidgetSetup editorWidgetSetup( const QgsVectorLayer* vl, const QString& fieldName ) const; | ||
|
|
||
| /** | ||
| * Register a new plugin. | ||
| * | ||
| * @param plugin The plugin (ownership is transfered) | ||
| */ | ||
| void registerPlugin( QgsEditorWidgetAutoConfPlugin* plugin ); | ||
|
|
||
| private: | ||
| QList<QSharedPointer<QgsEditorWidgetAutoConfPlugin> > plugins; | ||
| }; | ||
| ///@endcond | ||
|
|
||
| #endif // QGSEDITORWIDGETAUTOCONF_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,3 @@ | ||
| ######################################################## | ||
| # Files | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| /*************************************************************************** | ||
| testqgseditorwidgetregistry.cpp | ||
| --------------------- | ||
| begin : July 2016 | ||
| copyright : (C) 2016 by Patrick Valsecchi | ||
| email : patrick.valsecchi at camptocamp.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| #include <QtTest/QtTest> | ||
|
|
||
| #include "qgseditorwidgetregistry.h" | ||
| #include "qgseditorwidgetautoconf.h" | ||
|
|
||
|
|
||
| class TestQgsEditorWidgetRegistry: public QObject | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| class DummyPlugin: public QgsEditorWidgetAutoConfPlugin | ||
| { | ||
| public: | ||
| QgsEditorWidgetSetup editorWidgetSetup( const QgsVectorLayer* vl, const QString& fieldName, int& score ) const override | ||
| { | ||
| Q_UNUSED( vl ) | ||
| if ( fieldName == "special" ) | ||
| { | ||
| score = 100; | ||
| return QgsEditorWidgetSetup( "Special", QgsEditorWidgetConfig() ); | ||
| } | ||
| score = 0; | ||
| return QgsEditorWidgetSetup(); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
| private slots: | ||
| void initTestCase() | ||
| { | ||
| QgsApplication::init(); | ||
| QgsApplication::initQgis(); | ||
| QgsEditorWidgetRegistry::initEditors(); | ||
| QgsEditorWidgetRegistry::instance()->registerAutoConfPlugin( new DummyPlugin() ); | ||
| } | ||
|
|
||
| void cleanupTestCase() | ||
| { | ||
| QgsApplication::exitQgis(); | ||
| } | ||
|
|
||
| void stringType() | ||
| { | ||
| checkSimple( "string", "TextEdit" ); | ||
| } | ||
|
|
||
| void datetimeType() | ||
| { | ||
| checkSimple( "datetime", "DateTime" ); | ||
| } | ||
|
|
||
| void integerType() | ||
| { | ||
| checkSimple( "integer", "Range" ); | ||
| } | ||
|
|
||
| void doubleType() | ||
| { | ||
| checkSimple( "double", "Range" ); | ||
| } | ||
|
|
||
| void configuredType() | ||
| { | ||
| QgsVectorLayer vl( "LineString?crs=epsg:3111&field=pk:int&field=col1:string", "vl", "memory" ); | ||
| QgsEditFormConfig formConfig = vl.editFormConfig(); | ||
| formConfig.setWidgetType( "col1", "FooEdit" ); | ||
| QgsEditorWidgetConfig config; | ||
| config["a"] = QVariant( 12 ); | ||
| config["b"] = QVariant( "bar" ); | ||
| formConfig.setWidgetConfig( "col1", config ); | ||
| vl.setEditFormConfig( formConfig ); | ||
| const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( &vl, "col1" ); | ||
| QCOMPARE( setup.type(), QString( "FooEdit" ) ); | ||
| QCOMPARE( setup.config(), config ); | ||
| } | ||
|
|
||
| void wrongFieldName() | ||
| { | ||
| const QgsVectorLayer vl( "LineString?crs=epsg:3111&field=pk:int&field=col1:string", "vl", "memory" ); | ||
| const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( &vl, "col2" ); | ||
| // an unknown fields leads to a default setup with a TextEdit | ||
| QCOMPARE( setup.type(), QString( "TextEdit" ) ); | ||
| QCOMPARE( setup.config().count(), 0 ); | ||
| } | ||
|
|
||
| void typeFromPlugin() | ||
| { | ||
| const QgsVectorLayer vl( "LineString?crs=epsg:3111&field=pk:int&field=special:string", "vl", "memory" ); | ||
| const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( &vl, "special" ); | ||
| QCOMPARE( setup.type(), QString( "Special" ) ); | ||
| } | ||
|
|
||
| private: | ||
|
|
||
| static void checkSimple( const QString& dataType, const QString& widgetType ) | ||
| { | ||
| const QgsVectorLayer vl( "LineString?crs=epsg:3111&field=pk:int&field=col1:" + dataType, "vl", "memory" ); | ||
| const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( &vl, "col1" ); | ||
| QCOMPARE( setup.type(), widgetType ); | ||
| QCOMPARE( setup.config().count(), 0 ); | ||
| } | ||
| }; | ||
|
|
||
| QTEST_MAIN( TestQgsEditorWidgetRegistry ) | ||
| #include "testqgseditorwidgetregistry.moc" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is not really any advantage in making these local variables const