QGIS API Documentation 3.29.0-Master (19d7edcfed)
qgsexternalresourceconfigdlg.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsexternalresourceconfigdlg.cpp
3 --------------------------------------
4 Date : 2015-11-26
5 Copyright : (C) 2015 Médéric Ribreux
6 Email : mederic.ribreux at medspx dot fr
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
18#include "qgsproject.h"
19#include "qgssettings.h"
21#include "qgsapplication.h"
22#include "qgsvectorlayer.h"
25#include "qgsexternalstorage.h"
29
30#include <QFileDialog>
31#include <QComboBox>
32
34
36 : QgsEditorConfigWidget( vl, fieldIdx, parent )
37{
38 setupUi( this );
39
40 mStorageType->addItem( tr( "Select Existing file" ), QString() );
41 for ( QgsExternalStorage *storage : QgsApplication::externalStorageRegistry()->externalStorages() )
42 {
43 mStorageType->addItem( storage->displayName(), storage->type() );
44 }
45
46 mExternalStorageGroupBox->setVisible( false );
47
48 initializeDataDefinedButton( mStorageUrlPropertyOverrideButton, QgsEditorWidgetWrapper::StorageUrl );
49 mStorageUrlPropertyOverrideButton->registerVisibleWidget( mStorageUrlExpression );
50 mStorageUrlPropertyOverrideButton->registerExpressionWidget( mStorageUrlExpression );
51 mStorageUrlPropertyOverrideButton->registerVisibleWidget( mStorageUrl, false );
52 mStorageUrlPropertyOverrideButton->registerExpressionContextGenerator( this );
53
54 // By default, uncheck some options
55 mUseLink->setChecked( false );
56 mFullUrl->setChecked( false );
57
58 const QString defpath = QgsProject::instance()->fileName().isEmpty() ? QDir::homePath() : QFileInfo( QgsProject::instance()->absoluteFilePath() ).path();
59
60 mRootPath->setPlaceholderText( QgsSettings().value( QStringLiteral( "/UI/lastExternalResourceWidgetDefaultPath" ), QDir::toNativeSeparators( QDir::cleanPath( defpath ) ) ).toString() );
61
62 connect( mRootPathButton, &QToolButton::clicked, this, &QgsExternalResourceConfigDlg::chooseDefaultPath );
63
64 initializeDataDefinedButton( mRootPathPropertyOverrideButton, QgsEditorWidgetWrapper::RootPath );
65 mRootPathPropertyOverrideButton->registerVisibleWidget( mRootPathExpression );
66 mRootPathPropertyOverrideButton->registerExpressionWidget( mRootPathExpression );
67 mRootPathPropertyOverrideButton->registerVisibleWidget( mRootPath, false );
68 mRootPathPropertyOverrideButton->registerEnabledWidget( mRootPathButton, false );
69
70 initializeDataDefinedButton( mDocumentViewerContentPropertyOverrideButton, QgsEditorWidgetWrapper::DocumentViewerContent );
71 mDocumentViewerContentPropertyOverrideButton->registerVisibleWidget( mDocumentViewerContentExpression );
72 mDocumentViewerContentPropertyOverrideButton->registerExpressionWidget( mDocumentViewerContentExpression );
73 mDocumentViewerContentPropertyOverrideButton->registerEnabledWidget( mDocumentViewerContentComboBox, false );
74
75 // Activate Relative Default Path option only if Default Path is set
76 connect( mRootPath, &QLineEdit::textChanged, this, &QgsExternalResourceConfigDlg::enableRelativeDefault );
77 connect( mRootPathExpression, &QLineEdit::textChanged, this, &QgsExternalResourceConfigDlg::enableRelativeDefault );
78
79 // Add storage modes
80 mStorageModeCbx->addItem( tr( "File Paths" ), QgsFileWidget::GetFile );
81 mStorageModeCbx->addItem( tr( "Directory Paths" ), QgsFileWidget::GetDirectory );
82
83 // Add storage path options
84 mStoragePathCbx->addItem( tr( "Absolute Path" ), QgsFileWidget::Absolute );
85 mStoragePathCbx->addItem( tr( "Relative to Project Path" ), QgsFileWidget::RelativeProject );
86 mStoragePathCbx->addItem( tr( "Relative to Default Path" ), QgsFileWidget::RelativeDefaultPath );
87 enableCbxItem( mStoragePathCbx, 2, false );
88
89 connect( mStorageType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsExternalResourceConfigDlg::changeStorageType );
90 connect( mFileWidgetGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
91 connect( mFileWidgetButtonGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
92 connect( mFileWidgetFilterLineEdit, &QLineEdit::textChanged, this, &QgsEditorConfigWidget::changed );
93 connect( mUseLink, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
94 connect( mFullUrl, &QAbstractButton::toggled, this, &QgsEditorConfigWidget::changed );
95 connect( mRootPath, &QLineEdit::textChanged, this, &QgsEditorConfigWidget::changed );
96 connect( mStorageModeCbx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditorConfigWidget::changed );
97 connect( mStoragePathCbx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsEditorConfigWidget::changed );
98 connect( mDocumentViewerGroupBox, &QGroupBox::toggled, this, &QgsEditorConfigWidget::changed );
99 connect( mDocumentViewerContentComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [ = ]( int idx )
100 { mDocumentViewerContentSettingsWidget->setEnabled( ( QgsExternalResourceWidget::DocumentViewerContent )idx != QgsExternalResourceWidget::NoContent ); } );
101 connect( mDocumentViewerHeight, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsEditorConfigWidget::changed );
102 connect( mDocumentViewerWidth, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsEditorConfigWidget::changed );
103 connect( mStorageUrlExpression, &QLineEdit::textChanged, this, &QgsEditorConfigWidget::changed );
104
105 mDocumentViewerContentComboBox->addItem( tr( "No Content" ), QgsExternalResourceWidget::NoContent );
106 mDocumentViewerContentComboBox->addItem( tr( "Image" ), QgsExternalResourceWidget::Image );
107 mDocumentViewerContentComboBox->addItem( tr( "Web View" ), QgsExternalResourceWidget::Web );
108}
109
110void QgsExternalResourceConfigDlg::chooseDefaultPath()
111{
112 QString dir;
113 if ( !mRootPath->text().isEmpty() )
114 {
115 dir = mRootPath->text();
116 }
117 else
118 {
119 const QString path = QFileInfo( QgsProject::instance()->absoluteFilePath() ).path();
120 dir = QgsSettings().value( QStringLiteral( "/UI/lastExternalResourceWidgetDefaultPath" ), QDir::toNativeSeparators( QDir::cleanPath( path ) ) ).toString();
121 }
122
123 const QString rootName = QFileDialog::getExistingDirectory( this, tr( "Select a Directory" ), dir, QFileDialog::Options() );
124
125 if ( !rootName.isNull() )
126 mRootPath->setText( rootName );
127}
128
129void QgsExternalResourceConfigDlg::enableCbxItem( QComboBox *comboBox, int index, bool enabled )
130{
131 // https://stackoverflow.com/a/62261745
132 const auto *model = qobject_cast<QStandardItemModel *>( comboBox->model() );
133 assert( model );
134 if ( !model )
135 return;
136
137 auto *item = model->item( index );
138 assert( item );
139 if ( !item )
140 return;
141 item->setEnabled( enabled );
142}
143
144void QgsExternalResourceConfigDlg::enableRelativeDefault()
145{
146 bool relativePathActive = false;
147
148 if ( mRootPathPropertyOverrideButton->isActive() )
149 {
150 if ( !mRootPathExpression->text().isEmpty() )
151 relativePathActive = true;
152 }
153 else
154 {
155 if ( !mRootPath->text().isEmpty() )
156 relativePathActive = true;
157 }
158 // Activate (or not) the RelativeDefault item if default path
159 enableCbxItem( mStoragePathCbx, 2, relativePathActive );
160}
161
163{
164 QVariantMap cfg;
165
166 cfg.insert( QStringLiteral( "StorageType" ), mStorageType->currentData() );
167 cfg.insert( QStringLiteral( "StorageAuthConfigId" ), mAuthSettingsProtocol->configId() );
168 if ( !mStorageUrl->text().isEmpty() )
169 cfg.insert( QStringLiteral( "StorageUrl" ), mStorageUrl->text() );
170
171 cfg.insert( QStringLiteral( "FileWidget" ), mFileWidgetGroupBox->isChecked() );
172 cfg.insert( QStringLiteral( "FileWidgetButton" ), mFileWidgetButtonGroupBox->isChecked() );
173 cfg.insert( QStringLiteral( "FileWidgetFilter" ), mFileWidgetFilterLineEdit->text() );
174
175 if ( mUseLink->isChecked() )
176 {
177 cfg.insert( QStringLiteral( "UseLink" ), mUseLink->isChecked() );
178 if ( mFullUrl->isChecked() )
179 cfg.insert( QStringLiteral( "FullUrl" ), mFullUrl->isChecked() );
180 }
181
182 cfg.insert( QStringLiteral( "PropertyCollection" ), mPropertyCollection.toVariant( QgsWidgetWrapper::propertyDefinitions() ) );
183
184 if ( !mRootPath->text().isEmpty() )
185 cfg.insert( QStringLiteral( "DefaultRoot" ), mRootPath->text() );
186
187 if ( !mStorageType->currentIndex() )
188 {
189 // Save Storage Mode
190 cfg.insert( QStringLiteral( "StorageMode" ), mStorageModeCbx->currentData().toInt() );
191 // Save Relative Paths option
192 cfg.insert( QStringLiteral( "RelativeStorage" ), mStoragePathCbx->currentData().toInt() );
193 }
194 else
195 {
196 // Only file mode and absolute paths are supported for external storage
197 cfg.insert( QStringLiteral( "StorageMode" ), static_cast<int>( QgsFileWidget::GetFile ) );
198 cfg.insert( QStringLiteral( "RelativeStorage" ), static_cast<int>( QgsFileWidget::Absolute ) );
199 }
200
201 cfg.insert( QStringLiteral( "DocumentViewer" ), mDocumentViewerContentComboBox->currentData().toInt() );
202 cfg.insert( QStringLiteral( "DocumentViewerHeight" ), mDocumentViewerHeight->value() );
203 cfg.insert( QStringLiteral( "DocumentViewerWidth" ), mDocumentViewerWidth->value() );
204
205 return cfg;
206}
207
208
210{
211 if ( config.contains( QStringLiteral( "StorageType" ) ) )
212 {
213 const int index = mStorageType->findData( config.value( QStringLiteral( "StorageType" ) ) );
214 if ( index >= 0 )
215 mStorageType->setCurrentIndex( index );
216 }
217
218 mAuthSettingsProtocol->setConfigId( config.value( QStringLiteral( "StorageAuthConfigId" ) ).toString() );
219 mStorageUrl->setText( config.value( QStringLiteral( "StorageUrl" ) ).toString() );
220
221 if ( config.contains( QStringLiteral( "FileWidget" ) ) )
222 {
223 mFileWidgetGroupBox->setChecked( config.value( QStringLiteral( "FileWidget" ) ).toBool() );
224 }
225 if ( config.contains( QStringLiteral( "FileWidget" ) ) )
226 {
227 mFileWidgetButtonGroupBox->setChecked( config.value( QStringLiteral( "FileWidgetButton" ) ).toBool() );
228 }
229 if ( config.contains( QStringLiteral( "FileWidgetFilter" ) ) )
230 {
231 mFileWidgetFilterLineEdit->setText( config.value( QStringLiteral( "FileWidgetFilter" ) ).toString() );
232 }
233
234 if ( config.contains( QStringLiteral( "UseLink" ) ) )
235 {
236 mUseLink->setChecked( config.value( QStringLiteral( "UseLink" ) ).toBool() );
237 if ( config.contains( QStringLiteral( "FullUrl" ) ) )
238 mFullUrl->setChecked( true );
239 }
240
241 mPropertyCollection.loadVariant( config.value( QStringLiteral( "PropertyCollection" ) ), QgsWidgetWrapper::propertyDefinitions() );
243
244 mRootPath->setText( config.value( QStringLiteral( "DefaultRoot" ) ).toString() );
245
246 // relative storage
247 if ( config.contains( QStringLiteral( "RelativeStorage" ) ) )
248 {
249 const int relative = config.value( QStringLiteral( "RelativeStorage" ) ).toInt();
250 mStoragePathCbx->setCurrentIndex( relative );
251 }
252
253 // set storage mode
254 if ( config.contains( QStringLiteral( "StorageMode" ) ) )
255 {
256 const int mode = config.value( QStringLiteral( "StorageMode" ) ).toInt();
257 mStorageModeCbx->setCurrentIndex( mode );
258 }
259
260 // Document viewer
261 if ( config.contains( QStringLiteral( "DocumentViewer" ) ) )
262 {
263 const QgsExternalResourceWidget::DocumentViewerContent content = ( QgsExternalResourceWidget::DocumentViewerContent )config.value( QStringLiteral( "DocumentViewer" ) ).toInt();
264 const int idx = mDocumentViewerContentComboBox->findData( content );
265 if ( idx >= 0 )
266 {
267 mDocumentViewerContentComboBox->setCurrentIndex( idx );
268 }
269 if ( config.contains( QStringLiteral( "DocumentViewerHeight" ) ) )
270 {
271 mDocumentViewerHeight->setValue( config.value( QStringLiteral( "DocumentViewerHeight" ) ).toInt() );
272 }
273 if ( config.contains( QStringLiteral( "DocumentViewerWidth" ) ) )
274 {
275 mDocumentViewerWidth->setValue( config.value( QStringLiteral( "DocumentViewerWidth" ) ).toInt() );
276 }
277 }
278}
279
281{
285
287 context << fileWidgetScope;
288
289 context.setHighlightedVariables( fileWidgetScope->variableNames() );
290 return context;
291}
292
293void QgsExternalResourceConfigDlg::changeStorageType( int storageTypeIndex )
294{
295 // first one in combo box is not an external storage
296 mExternalStorageGroupBox->setVisible( storageTypeIndex > 0 );
297
298 // for now, we store only files in external storage
299 mStorageModeCbx->setVisible( !storageTypeIndex );
300 mStorageModeLbl->setVisible( !storageTypeIndex );
301
302 // Absolute path are mandatory when using external storage
303 mStoragePathCbx->setVisible( !storageTypeIndex );
304 mStoragePathLbl->setVisible( !storageTypeIndex );
305
306 emit changed();
307}
static QgsExternalStorageRegistry * externalStorageRegistry()
Returns registry of available external storage implementations.
This class should be subclassed for every configurable editor widget type.
void updateDataDefinedButtons()
Updates all property override buttons to reflect the widgets's current properties.
QgsPropertyCollection mPropertyCollection
Temporary property collection for config widgets.
void initializeDataDefinedButton(QgsPropertyOverrideButton *button, QgsWidgetWrapper::Property key)
Registers a property override button, setting up its initial value, connections and description.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void changed()
Emitted when the configuration of the widget is changed.
int fieldIdx() const
Access the field index.
Single scope for storing variables and functions for use within a QgsExpressionContext.
QStringList variableNames() const
Returns a list of variable names contained within the scope.
static QgsExpressionContextScope * parentFormScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current parent attribute form/tab...
static QgsExpressionContextScope * formScope(const QgsFeature &formFeature=QgsFeature(), const QString &formMode=QString())
Creates a new scope which contains functions and variables from the current attribute form/table form...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setConfig(const QVariantMap &config) override
Update the configuration widget to represent the given configuration.
QVariantMap config() override
Create a configuration from the current GUI state.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsExternalResourceConfigDlg(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Constructor for QgsExternalResourceConfigDlg.
QVariant value() const override
Will be used to access the widget's value.
static QgsExpressionContextScope * createFileWidgetScope()
Creates and Returns an expression context scope specific to QgsExternalStorageFileWidget It defines t...
Abstract interface for external storage - to be implemented by various backends and registered in Qgs...
@ GetFile
Select a single file.
Definition: qgsfilewidget.h:68
@ GetDirectory
Select a directory.
Definition: qgsfilewidget.h:69
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
QString fileName
Definition: qgsproject.h:108
bool loadVariant(const QVariant &configuration, const QgsPropertiesDefinition &definitions) override
Loads this property collection from a QVariantMap, wrapped in a QVariant.
QVariant toVariant(const QgsPropertiesDefinition &definitions) const override
Saves this property collection to a QVariantMap, wrapped in a QVariant.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:63
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Represents a vector layer which manages a vector based data sets.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the editor widget property definitions.
@ DocumentViewerContent
Document type for external resource.
@ RootPath
Root path for external resource.
@ StorageUrl
Storage URL for external resource.
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
QVariantMap config() const
Returns the whole config.