QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
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
65 mRootPathPropertyOverrideButton->registerVisibleWidget( mRootPathExpression );
66 mRootPathPropertyOverrideButton->registerExpressionWidget( mRootPathExpression );
67 mRootPathPropertyOverrideButton->registerVisibleWidget( mRootPath, false );
68 mRootPathPropertyOverrideButton->registerEnabledWidget( mRootPathButton, false );
69
70 initializeDataDefinedButton( mDocumentViewerContentPropertyOverrideButton, QgsEditorWidgetWrapper::Property::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 )
100 {
101 const QgsExternalResourceWidget::DocumentViewerContent content = static_cast<QgsExternalResourceWidget::DocumentViewerContent>( mDocumentViewerContentComboBox->currentData().toInt() );
102 const bool hasSizeSettings = ( content != QgsExternalResourceWidget::NoContent && content != QgsExternalResourceWidget::Audio );
103 mDocumentViewerContentSettingsWidget->setEnabled( hasSizeSettings );
104 } );
105 connect( mDocumentViewerHeight, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsEditorConfigWidget::changed );
106 connect( mDocumentViewerWidth, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &QgsEditorConfigWidget::changed );
107 connect( mStorageUrlExpression, &QLineEdit::textChanged, this, &QgsEditorConfigWidget::changed );
108
109 mDocumentViewerContentComboBox->addItem( tr( "No Content" ), QgsExternalResourceWidget::NoContent );
110 mDocumentViewerContentComboBox->addItem( tr( "Image" ), QgsExternalResourceWidget::Image );
111 mDocumentViewerContentComboBox->addItem( tr( "Audio" ), QgsExternalResourceWidget::Audio );
112 mDocumentViewerContentComboBox->addItem( tr( "Video" ), QgsExternalResourceWidget::Video );
113 mDocumentViewerContentComboBox->addItem( tr( "Web View" ), QgsExternalResourceWidget::Web );
114}
115
116void QgsExternalResourceConfigDlg::chooseDefaultPath()
117{
118 QString dir;
119 if ( !mRootPath->text().isEmpty() )
120 {
121 dir = mRootPath->text();
122 }
123 else
124 {
125 const QString path = QFileInfo( QgsProject::instance()->absoluteFilePath() ).path();
126 dir = QgsSettings().value( QStringLiteral( "/UI/lastExternalResourceWidgetDefaultPath" ), QDir::toNativeSeparators( QDir::cleanPath( path ) ) ).toString();
127 }
128
129 const QString rootName = QFileDialog::getExistingDirectory( this, tr( "Select a Directory" ), dir, QFileDialog::Options() );
130
131 if ( !rootName.isNull() )
132 mRootPath->setText( rootName );
133}
134
135void QgsExternalResourceConfigDlg::enableCbxItem( QComboBox *comboBox, int index, bool enabled )
136{
137 // https://stackoverflow.com/a/62261745
138 const auto *model = qobject_cast<QStandardItemModel *>( comboBox->model() );
139 assert( model );
140 if ( !model )
141 return;
142
143 auto *item = model->item( index );
144 assert( item );
145 if ( !item )
146 return;
147 item->setEnabled( enabled );
148}
149
150void QgsExternalResourceConfigDlg::enableRelativeDefault()
151{
152 bool relativePathActive = false;
153
154 if ( mRootPathPropertyOverrideButton->isActive() )
155 {
156 if ( !mRootPathExpression->text().isEmpty() )
157 relativePathActive = true;
158 }
159 else
160 {
161 if ( !mRootPath->text().isEmpty() )
162 relativePathActive = true;
163 }
164 // Activate (or not) the RelativeDefault item if default path
165 enableCbxItem( mStoragePathCbx, 2, relativePathActive );
166}
167
169{
170 QVariantMap cfg;
171
172 cfg.insert( QStringLiteral( "StorageType" ), mStorageType->currentData() );
173 cfg.insert( QStringLiteral( "StorageAuthConfigId" ), mAuthSettingsProtocol->configId() );
174 if ( !mStorageUrl->text().isEmpty() )
175 cfg.insert( QStringLiteral( "StorageUrl" ), mStorageUrl->text() );
176
177 cfg.insert( QStringLiteral( "FileWidget" ), mFileWidgetGroupBox->isChecked() );
178 cfg.insert( QStringLiteral( "FileWidgetButton" ), mFileWidgetButtonGroupBox->isChecked() );
179 cfg.insert( QStringLiteral( "FileWidgetFilter" ), mFileWidgetFilterLineEdit->text() );
180
181 if ( mUseLink->isChecked() )
182 {
183 cfg.insert( QStringLiteral( "UseLink" ), mUseLink->isChecked() );
184 if ( mFullUrl->isChecked() )
185 cfg.insert( QStringLiteral( "FullUrl" ), mFullUrl->isChecked() );
186 }
187
188 cfg.insert( QStringLiteral( "PropertyCollection" ), mPropertyCollection.toVariant( QgsWidgetWrapper::propertyDefinitions() ) );
189
190 if ( !mRootPath->text().isEmpty() )
191 cfg.insert( QStringLiteral( "DefaultRoot" ), mRootPath->text() );
192
193 if ( !mStorageType->currentIndex() )
194 {
195 // Save Storage Mode
196 cfg.insert( QStringLiteral( "StorageMode" ), mStorageModeCbx->currentData().toInt() );
197 // Save Relative Paths option
198 cfg.insert( QStringLiteral( "RelativeStorage" ), mStoragePathCbx->currentData().toInt() );
199 }
200 else
201 {
202 // Only file mode and absolute paths are supported for external storage
203 cfg.insert( QStringLiteral( "StorageMode" ), static_cast<int>( QgsFileWidget::GetFile ) );
204 cfg.insert( QStringLiteral( "RelativeStorage" ), static_cast<int>( QgsFileWidget::Absolute ) );
205 }
206
207 cfg.insert( QStringLiteral( "DocumentViewer" ), mDocumentViewerContentComboBox->currentData().toInt() );
208 cfg.insert( QStringLiteral( "DocumentViewerHeight" ), mDocumentViewerHeight->value() );
209 cfg.insert( QStringLiteral( "DocumentViewerWidth" ), mDocumentViewerWidth->value() );
210
211 return cfg;
212}
213
214
216{
217 if ( config.contains( QStringLiteral( "StorageType" ) ) )
218 {
219 const int index = mStorageType->findData( config.value( QStringLiteral( "StorageType" ) ) );
220 if ( index >= 0 )
221 mStorageType->setCurrentIndex( index );
222 }
223
224 mAuthSettingsProtocol->setConfigId( config.value( QStringLiteral( "StorageAuthConfigId" ) ).toString() );
225 mStorageUrl->setText( config.value( QStringLiteral( "StorageUrl" ) ).toString() );
226
227 if ( config.contains( QStringLiteral( "FileWidget" ) ) )
228 {
229 mFileWidgetGroupBox->setChecked( config.value( QStringLiteral( "FileWidget" ) ).toBool() );
230 }
231 if ( config.contains( QStringLiteral( "FileWidget" ) ) )
232 {
233 mFileWidgetButtonGroupBox->setChecked( config.value( QStringLiteral( "FileWidgetButton" ) ).toBool() );
234 }
235 if ( config.contains( QStringLiteral( "FileWidgetFilter" ) ) )
236 {
237 mFileWidgetFilterLineEdit->setText( config.value( QStringLiteral( "FileWidgetFilter" ) ).toString() );
238 }
239
240 if ( config.contains( QStringLiteral( "UseLink" ) ) )
241 {
242 mUseLink->setChecked( config.value( QStringLiteral( "UseLink" ) ).toBool() );
243 if ( config.contains( QStringLiteral( "FullUrl" ) ) )
244 mFullUrl->setChecked( true );
245 }
246
247 mPropertyCollection.loadVariant( config.value( QStringLiteral( "PropertyCollection" ) ), QgsWidgetWrapper::propertyDefinitions() );
249
250 mRootPath->setText( config.value( QStringLiteral( "DefaultRoot" ) ).toString() );
251
252 // relative storage
253 if ( config.contains( QStringLiteral( "RelativeStorage" ) ) )
254 {
255 const int relative = config.value( QStringLiteral( "RelativeStorage" ) ).toInt();
256 mStoragePathCbx->setCurrentIndex( relative );
257 }
258
259 // set storage mode
260 if ( config.contains( QStringLiteral( "StorageMode" ) ) )
261 {
262 const int mode = config.value( QStringLiteral( "StorageMode" ) ).toInt();
263 mStorageModeCbx->setCurrentIndex( mode );
264 }
265
266 // Document viewer
267 if ( config.contains( QStringLiteral( "DocumentViewer" ) ) )
268 {
269 const QgsExternalResourceWidget::DocumentViewerContent content = ( QgsExternalResourceWidget::DocumentViewerContent )config.value( QStringLiteral( "DocumentViewer" ) ).toInt();
270 const int idx = mDocumentViewerContentComboBox->findData( content );
271 if ( idx >= 0 )
272 {
273 mDocumentViewerContentComboBox->setCurrentIndex( idx );
274 }
275 if ( config.contains( QStringLiteral( "DocumentViewerHeight" ) ) )
276 {
277 mDocumentViewerHeight->setValue( config.value( QStringLiteral( "DocumentViewerHeight" ) ).toInt() );
278 }
279 if ( config.contains( QStringLiteral( "DocumentViewerWidth" ) ) )
280 {
281 mDocumentViewerWidth->setValue( config.value( QStringLiteral( "DocumentViewerWidth" ) ).toInt() );
282 }
283 }
284}
285
287{
291
293 context << fileWidgetScope;
294
295 context.setHighlightedVariables( fileWidgetScope->variableNames() );
296 return context;
297}
298
299void QgsExternalResourceConfigDlg::changeStorageType( int storageTypeIndex )
300{
301 // first one in combo box is not an external storage
302 mExternalStorageGroupBox->setVisible( storageTypeIndex > 0 );
303
304 // for now, we store only files in external storage
305 mStorageModeCbx->setVisible( !storageTypeIndex );
306 mStorageModeLbl->setVisible( !storageTypeIndex );
307
308 // Absolute path are mandatory when using external storage
309 mStoragePathCbx->setVisible( !storageTypeIndex );
310 mStoragePathLbl->setVisible( !storageTypeIndex );
311
312 emit changed();
313}
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:481
QString fileName
Definition: qgsproject.h:110
QVariant toVariant(const QgsPropertiesDefinition &definitions) const final
Saves this property collection to a QVariantMap, wrapped in a QVariant.
bool loadVariant(const QVariant &configuration, const QgsPropertiesDefinition &definitions) final
Loads this property collection from a QVariantMap, wrapped in a QVariant.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
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.
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
QVariantMap config() const
Returns the whole config.
@ DocumentViewerContent
Document type for external resource.
@ StorageUrl
Storage URL for external resource.
@ RootPath
Root path for external resource.