Skip to content

Commit

Permalink
[ExternalStorage] Add widget to configure/edit and visualize external…
Browse files Browse the repository at this point in the history
… storage
  • Loading branch information
troopa81 committed Aug 16, 2021
1 parent bdaf65e commit 5612703
Show file tree
Hide file tree
Showing 19 changed files with 2,597 additions and 115 deletions.
Expand Up @@ -51,7 +51,8 @@ changed status of the widget will be saved.
enum Property
{
RootPath,
DocumentViewerContent
DocumentViewerContent,
StorageUrl
};

static const QgsPropertiesDefinition &propertyDefinitions();
Expand Down
49 changes: 49 additions & 0 deletions python/gui/auto_generated/qgsexternalresourcewidget.sip.in
Expand Up @@ -133,6 +133,55 @@ is set to :py:class:`QgsFileWidget`.RelativeDefaultPath.
%Docstring
Configures the base path which should be used if the relativeStorage property
is set to :py:class:`QgsFileWidget`.RelativeDefaultPath.
%End

void setStorageType( const QString &storageType );
%Docstring
Set ``storageType`` storage type unique identifier as defined in :py:class:`QgsExternalStorageRegistry` or
null QString if there is no storage defined, only file selection.

.. seealso:: :py:func:`storageType`

.. versionadded:: 3.22
%End

QString storageType() const;
%Docstring
Get storage type unique identifier as defined in :py:class:`QgsExternalStorageRegistry`.
Returns null QString if there is no storage defined, only file selection.

.. seealso:: :py:func:`setStorageType`

.. versionadded:: 3.22
%End

void setStorageAuthConfigId( const QString &authCfg );
%Docstring
Sets the authentication configuration ID to be used for the current external storage (if
defined)

.. versionadded:: 3.22
%End

const QString &storageAuthConfigId() const;
%Docstring
Returns the authentication configuration ID used for the current external storage (if defined)

.. versionadded:: 3.22
%End

void setMessageBar( QgsMessageBar *messageBar );
%Docstring
Set ``messageBar`` to report messages

.. versionadded:: 3.22
%End

QgsMessageBar *messageBar() const;
%Docstring
Returns message bar used to report messages

.. versionadded:: 3.22
%End

signals:
Expand Down
120 changes: 120 additions & 0 deletions python/gui/auto_generated/qgsfilewidget.sip.in
Expand Up @@ -9,6 +9,8 @@





class QgsFileWidget : QWidget
{
%Docstring(signature="appended")
Expand Down Expand Up @@ -75,6 +77,104 @@ Sets the current file ``path``.
void setReadOnly( bool readOnly );
%Docstring
Sets whether the widget should be read only.
%End

void setStorageType( const QString &storageType );
%Docstring
Set ``storageType`` storage type unique identifier as defined in :py:class:`QgsExternalStorageRegistry` or
null QString if there is no storage defined.
If no external storage has been defined, QgsFileWidget will only update file path according to
selected files.

.. seealso:: :py:func:`storageType`

.. versionadded:: 3.22
%End

QString storageType() const;
%Docstring
Get storage type unique identifier as defined in :py:class:`QgsExternalStorageRegistry`.
Returns null QString if there is no storage defined, only file selection.

.. seealso:: :py:func:`setStorageType`

.. versionadded:: 3.22
%End

QgsExternalStorage *externalStorage() const;
%Docstring
Returns external storage used to store selected file names, None if none have been defined.
If no external storage has been defined, QgsFileWidget will only update file path according to
selected files.

.. seealso:: :py:func:`setStorageType`

.. versionadded:: 3.22
%End

void setStorageAuthConfigId( const QString &authCfg );
%Docstring
Sets the authentication configuration ID to be used for the current external storage (if
defined)

.. versionadded:: 3.22
%End

const QString &storageAuthConfigId() const;
%Docstring
Returns the authentication configuration ID used for the current external storage (if defined)

.. versionadded:: 3.22
%End

void setStorageUrlExpression( const QString &urlExpression );
%Docstring
Set ``urlExpression`` expression, which once evaluated, provide the URL used to store selected
documents. This is used only if an external storage has been defined

.. seealso:: :py:func:`setStorageType`

.. versionadded:: 3.22
%End

QString storageUrlExpressionString() const;
%Docstring
Returns the original, unmodified expression string, which once evaluated, provide the
URL used to store selected documents. This is used only if an external storage has been defined.
Returns null if no expression has been set.

.. seealso:: :py:func:`setStorageUrlExpression`

.. versionadded:: 3.22
%End

QgsExpression *storageUrlExpression() const;
%Docstring
Returns expression, which once evaluated, provide the URL used to store selected
documents. This is used only if an external storage has been defined.
Returns null if no expression has been set.

.. seealso:: :py:func:`setStorageUrlExpression`

.. versionadded:: 3.22
%End

void setExpressionContext( const QgsExpressionContext &context );
%Docstring
Set expression context to be used when for storage URL expression evaluation

.. seealso:: :py:func:`setStorageUrlExpression`

.. versionadded:: 3.22
%End

const QgsExpressionContext &expressionContext() const;
%Docstring
Returns expression context used for storage url expression evaluation

.. seealso:: :py:func:`storageUrlExpression`

.. versionadded:: 3.22
%End

QString dialogTitle() const;
Expand Down Expand Up @@ -250,6 +350,26 @@ Returns a pointer to the widget's line edit, which can be used to customize
the appearance and behavior of the line edit portion of the widget.

.. versionadded:: 3.0
%End

void setMessageBar( QgsMessageBar *messageBar );
%Docstring
Set ``messageBar`` to report messages

.. versionadded:: 3.22
%End

QgsMessageBar *messageBar() const;
%Docstring
Returns message bar used to report messages

.. versionadded:: 3.22
%End

static QgsExpressionContextScope *createFileWidgetScope();
%Docstring
Creates and Returns an expression context scope specific to QgsFileWidget
It defines the variable containing the user selected file name
%End

signals:
Expand Down
2 changes: 1 addition & 1 deletion src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp
Expand Up @@ -63,7 +63,7 @@ void QgsEditorWidgetRegistry::initEditors( QgsMapCanvas *mapCanvas, QgsMessageBa
registerWidget( QStringLiteral( "Color" ), new QgsColorWidgetFactory( tr( "Color" ) ) );
registerWidget( QStringLiteral( "RelationReference" ), new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
registerWidget( QStringLiteral( "DateTime" ), new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
registerWidget( QStringLiteral( "ExternalResource" ), new QgsExternalResourceWidgetFactory( tr( "Attachment" ) ) );
registerWidget( QStringLiteral( "ExternalResource" ), new QgsExternalResourceWidgetFactory( tr( "Attachment" ), messageBar ) );
registerWidget( QStringLiteral( "KeyValue" ), new QgsKeyValueWidgetFactory( tr( "Key/Value" ) ) );
registerWidget( QStringLiteral( "List" ), new QgsListWidgetFactory( tr( "List" ) ) );
registerWidget( QStringLiteral( "Binary" ), new QgsBinaryWidgetFactory( tr( "Binary (BLOB)" ), messageBar ) );
Expand Down
3 changes: 2 additions & 1 deletion src/gui/editorwidgets/core/qgswidgetwrapper.cpp
Expand Up @@ -28,7 +28,8 @@ const QgsPropertiesDefinition &QgsWidgetWrapper::propertyDefinitions()
properties =
{
{ RootPath, QgsPropertyDefinition( "propertyRootPath", QgsPropertyDefinition::DataTypeString, QObject::tr( "Root path" ), QObject::tr( "string of variable length representing root path to attachment" ) ) },
{ DocumentViewerContent, QgsPropertyDefinition( "documentViewerContent", QgsPropertyDefinition::DataTypeString, QObject::tr( "Document viewer content" ), QObject::tr( "string" ) + "<b>NoContent</b>|<b>Image</b>|<b>Web</b>" ) }
{ DocumentViewerContent, QgsPropertyDefinition( "documentViewerContent", QgsPropertyDefinition::DataTypeString, QObject::tr( "Document viewer content" ), QObject::tr( "string" ) + "<b>NoContent</b>|<b>Image</b>|<b>Web</b>" ) },
{ StorageUrl, QgsPropertyDefinition( "storageUrl", QgsPropertyDefinition::DataTypeString, QObject::tr( "Storage Url" ), QObject::tr( "String of variable length representing the URL used to store document with an external storage" ) ) }
};
}
return properties;
Expand Down
3 changes: 2 additions & 1 deletion src/gui/editorwidgets/core/qgswidgetwrapper.h
Expand Up @@ -76,7 +76,8 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
enum Property
{
RootPath = 0, //!< Root path for external resource
DocumentViewerContent //!< Document type for external resource
DocumentViewerContent, //!< Document type for external resource
StorageUrl //!< Storage URL for external resource
};

/**
Expand Down
55 changes: 55 additions & 0 deletions src/gui/editorwidgets/qgsexternalresourceconfigdlg.cpp
Expand Up @@ -22,8 +22,12 @@
#include "qgsvectorlayer.h"
#include "qgspropertyoverridebutton.h"
#include "qgseditorwidgetwrapper.h"
#include "qgsexternalstorage.h"
#include "qgsexternalstorageregistry.h"
#include "qgsexpressioncontextutils.h"

#include <QFileDialog>
#include <QComboBox>

class QgsExternalResourceWidgetWrapper;

Expand All @@ -32,6 +36,20 @@ QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl,
{
setupUi( this );

mStorageType->addItem( tr( "Select existing file" ), QString() );
for ( QgsExternalStorage *storage : QgsApplication::externalStorageRegistry()->externalStorages() )
{
mStorageType->addItem( tr( "Store with %1" ).arg( storage->type() ), storage->type() );
}

mExternalStorageGroupBox->setVisible( false );

initializeDataDefinedButton( mStorageUrlPropertyOverrideButton, QgsEditorWidgetWrapper::StorageUrl );
mStorageUrlPropertyOverrideButton->registerVisibleWidget( mStorageUrlExpression );
mStorageUrlPropertyOverrideButton->registerExpressionWidget( mStorageUrlExpression );
mStorageUrlPropertyOverrideButton->registerVisibleWidget( mStorageUrl, false );
mStorageUrlPropertyOverrideButton->registerExpressionContextGenerator( this );

// By default, uncheck some options
mUseLink->setChecked( false );
mFullUrl->setChecked( false );
Expand Down Expand Up @@ -69,6 +87,7 @@ QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl,
mRelativeButtonGroup->setId( mRelativeDefault, QgsFileWidget::RelativeDefaultPath );
mRelativeProject->setChecked( true );

connect( mStorageType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsExternalResourceConfigDlg::changeStorageType );
connect( mFileWidgetGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
connect( mFileWidgetButtonGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
connect( mFileWidgetFilterLineEdit, &QLineEdit::textChanged, this, &QgsEditorConfigWidget::changed );
Expand All @@ -82,6 +101,7 @@ QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl,
{ mDocumentViewerContentSettingsWidget->setEnabled( ( QgsExternalResourceWidget::DocumentViewerContent )idx != QgsExternalResourceWidget::NoContent ); } );
connect( mDocumentViewerHeight, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsEditorConfigWidget::changed );
connect( mDocumentViewerWidth, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsEditorConfigWidget::changed );
connect( mStorageUrlExpression, &QLineEdit::textChanged, this, &QgsEditorConfigWidget::changed );

mDocumentViewerContentComboBox->addItem( tr( "No Content" ), QgsExternalResourceWidget::NoContent );
mDocumentViewerContentComboBox->addItem( tr( "Image" ), QgsExternalResourceWidget::Image );
Expand Down Expand Up @@ -135,6 +155,11 @@ QVariantMap QgsExternalResourceConfigDlg::config()
{
QVariantMap cfg;

cfg.insert( QStringLiteral( "StorageType" ), mStorageType->currentData() );
cfg.insert( QStringLiteral( "StorageAuthConfigId" ), mAuthSettingsProtocol->configId() );
if ( !mStorageUrl->text().isEmpty() )
cfg.insert( QStringLiteral( "StorageUrl" ), mStorageUrl->text() );

cfg.insert( QStringLiteral( "FileWidget" ), mFileWidgetGroupBox->isChecked() );
cfg.insert( QStringLiteral( "FileWidgetButton" ), mFileWidgetButtonGroupBox->isChecked() );
cfg.insert( QStringLiteral( "FileWidgetFilter" ), mFileWidgetFilterLineEdit->text() );
Expand Down Expand Up @@ -174,6 +199,16 @@ QVariantMap QgsExternalResourceConfigDlg::config()

void QgsExternalResourceConfigDlg::setConfig( const QVariantMap &config )
{
if ( config.contains( QStringLiteral( "StorageType" ) ) )
{
const int index = mStorageType->findData( config.value( QStringLiteral( "StorageType" ) ) );
if ( index >= 0 )
mStorageType->setCurrentIndex( index );
}

mAuthSettingsProtocol->setConfigId( config.value( QStringLiteral( "StorageAuthConfigId" ) ).toString() );
mStorageUrl->setText( config.value( QStringLiteral( "StorageUrl" ) ).toString() );

if ( config.contains( QStringLiteral( "FileWidget" ) ) )
{
mFileWidgetGroupBox->setChecked( config.value( QStringLiteral( "FileWidget" ) ).toBool() );
Expand Down Expand Up @@ -240,3 +275,23 @@ void QgsExternalResourceConfigDlg::setConfig( const QVariantMap &config )
}
}
}

QgsExpressionContext QgsExternalResourceConfigDlg::createExpressionContext() const
{
QgsExpressionContext context = QgsEditorConfigWidget::createExpressionContext();
context << QgsExpressionContextUtils::formScope( );
context << QgsExpressionContextUtils::parentFormScope( );

QgsExpressionContextScope *fileWidgetScope = QgsFileWidget::createFileWidgetScope();
context << fileWidgetScope;

context.setHighlightedVariables( fileWidgetScope->variableNames() );
return context;
}

void QgsExternalResourceConfigDlg::changeStorageType( int storageType )
{
// first one in combo box is not an external storage
mExternalStorageGroupBox->setVisible( storageType );
emit changed();
}
6 changes: 6 additions & 0 deletions src/gui/editorwidgets/qgsexternalresourceconfigdlg.h
Expand Up @@ -38,6 +38,8 @@ class GUI_EXPORT QgsExternalResourceConfigDlg : public QgsEditorConfigWidget, pr
//! Constructor for QgsExternalResourceConfigDlg
explicit QgsExternalResourceConfigDlg( QgsVectorLayer *vl, int fieldIdx, QWidget *parent = nullptr );

QgsExpressionContext createExpressionContext() const override;

// QgsEditorConfigWidget interface
public:
QVariantMap config() override;
Expand All @@ -49,6 +51,10 @@ class GUI_EXPORT QgsExternalResourceConfigDlg : public QgsEditorConfigWidget, pr

//! Modify RelativeDefault according to mRootPath content
void enableRelativeDefault();

//! change storage type according to index from storage type combo box
void changeStorageType( int index );

};

#endif // QGSEXTERNALRESOURCECONFIGDLG_H
5 changes: 3 additions & 2 deletions src/gui/editorwidgets/qgsexternalresourcewidgetfactory.cpp
Expand Up @@ -19,14 +19,15 @@
#include "qgsexternalresourcewidgetwrapper.h"
#include "qgsexternalresourceconfigdlg.h"

QgsExternalResourceWidgetFactory::QgsExternalResourceWidgetFactory( const QString &name )
QgsExternalResourceWidgetFactory::QgsExternalResourceWidgetFactory( const QString &name, QgsMessageBar *messageBar )
: QgsEditorWidgetFactory( name )
, mMessageBar( messageBar )
{
}

QgsEditorWidgetWrapper *QgsExternalResourceWidgetFactory::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const
{
return new QgsExternalResourceWidgetWrapper( vl, fieldIdx, editor, parent );
return new QgsExternalResourceWidgetWrapper( vl, fieldIdx, editor, mMessageBar, parent );
}

QgsEditorConfigWidget *QgsExternalResourceWidgetFactory::configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const
Expand Down

0 comments on commit 5612703

Please sign in to comment.