QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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"
24 #include "qgseditorwidgetwrapper.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 
110 void 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 
129 void 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 
144 void 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() );
242  updateDataDefinedButtons();
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 
293 void 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 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
qgsexpressioncontextutils.h
QgsEditorConfigWidget
This class should be subclassed for every configurable editor widget type.
Definition: qgseditorconfigwidget.h:38
QgsExternalStorageFileWidget::createFileWidgetScope
static QgsExpressionContextScope * createFileWidgetScope()
Creates and Returns an expression context scope specific to QgsExternalStorageFileWidget It defines t...
Definition: qgsexternalstoragefilewidget.cpp:144
qgseditorwidgetwrapper.h
QgsWidgetWrapper::DocumentViewerContent
@ DocumentViewerContent
Document type for external resource.
Definition: qgswidgetwrapper.h:79
QgsExternalResourceConfigDlg::config
QVariantMap config() override
Create a configuration from the current GUI state.
Definition: qgsexternalresourceconfigdlg.cpp:162
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsExpressionContextUtils::formScope
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...
Definition: qgsexpressioncontextutils.cpp:270
QgsFileWidget::GetFile
@ GetFile
Select a single file.
Definition: qgsfilewidget.h:68
QgsPropertyCollection::loadVariant
bool loadVariant(const QVariant &configuration, const QgsPropertiesDefinition &definitions) override
Loads this property collection from a QVariantMap, wrapped in a QVariant.
Definition: qgspropertycollection.cpp:341
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsWidgetWrapper::RootPath
@ RootPath
Root path for external resource.
Definition: qgswidgetwrapper.h:78
QgsEditorConfigWidget::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgseditorconfigwidget.cpp:38
qgsexternalresourceconfigdlg.h
QgsWidgetWrapper::context
const QgsAttributeEditorContext & context() const
Returns information about the context in which this widget is shown.
Definition: qgswidgetwrapper.cpp:87
QgsExternalResourceWidget::NoContent
@ NoContent
Definition: qgsexternalresourcewidget.h:75
QgsExternalResourceWidget::DocumentViewerContent
DocumentViewerContent
Definition: qgsexternalresourcewidget.h:73
QgsEditorWidgetWrapper::fieldIdx
int fieldIdx() const
Access the field index.
Definition: qgseditorwidgetwrapper.cpp:34
QgsFileWidget::RelativeProject
@ RelativeProject
Definition: qgsfilewidget.h:81
qgsapplication.h
qgsexternalstorageregistry.h
QgsFileWidget::GetDirectory
@ GetDirectory
Select a directory.
Definition: qgsfilewidget.h:69
QgsWidgetWrapper::StorageUrl
@ StorageUrl
Storage URL for external resource.
Definition: qgswidgetwrapper.h:80
QgsExpressionContextUtils::parentFormScope
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...
Definition: qgsexpressioncontextutils.cpp:281
qgsexternalstorage.h
qgsexternalresourcewidget.h
QgsFileWidget::Absolute
@ Absolute
Definition: qgsfilewidget.h:80
QgsEditorConfigWidget::initializeDataDefinedButton
void initializeDataDefinedButton(QgsPropertyOverrideButton *button, QgsWidgetWrapper::Property key)
Registers a property override button, setting up its initial value, connections and description.
Definition: qgseditorconfigwidget.cpp:43
QgsFileWidget::RelativeDefaultPath
@ RelativeDefaultPath
Definition: qgsfilewidget.h:82
QgsProject::fileName
QString fileName
Definition: qgsproject.h:107
qgsexternalstoragefilewidget.h
QgsExternalResourceWidgetWrapper::value
QVariant value() const override
Will be used to access the widget's value.
Definition: qgsexternalresourcewidgetwrapper.cpp:36
QgsExpressionContextScope
Single scope for storing variables and functions for use within a QgsExpressionContext....
Definition: qgsexpressioncontext.h:113
qgsvectorlayer.h
QgsWidgetWrapper::propertyDefinitions
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the editor widget property definitions.
Definition: qgswidgetwrapper.cpp:22
QgsExternalStorage
Abstract interface for external storage - to be implemented by various backends and registered in Qgs...
Definition: qgsexternalstorage.h:36
QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg
QgsExternalResourceConfigDlg(QgsVectorLayer *vl, int fieldIdx, QWidget *parent=nullptr)
Constructor for QgsExternalResourceConfigDlg.
Definition: qgsexternalresourceconfigdlg.cpp:35
QgsWidgetWrapper::config
QVariantMap config() const
Returns the whole config.
Definition: qgswidgetwrapper.cpp:82
QgsExternalResourceWidget::Image
@ Image
Definition: qgsexternalresourcewidget.h:76
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsExternalResourceWidget::Web
@ Web
Definition: qgsexternalresourcewidget.h:77
QgsWidgetWrapper::mPropertyCollection
QgsPropertyCollection mPropertyCollection
Data defined property collection.
Definition: qgswidgetwrapper.h:246
QgsApplication::externalStorageRegistry
static QgsExternalStorageRegistry * externalStorageRegistry()
Returns registry of available external storage implementations.
Definition: qgsapplication.cpp:2505
qgssettings.h
QgsExternalResourceConfigDlg::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgsexternalresourceconfigdlg.cpp:280
QgsEditorConfigWidget::changed
void changed()
Emitted when the configuration of the widget is changed.
QgsExternalResourceConfigDlg::setConfig
void setConfig(const QVariantMap &config) override
Update the configuration widget to represent the given configuration.
Definition: qgsexternalresourceconfigdlg.cpp:209
QgsPropertyCollection::toVariant
QVariant toVariant(const QgsPropertiesDefinition &definitions) const override
Saves this property collection to a QVariantMap, wrapped in a QVariant.
Definition: qgspropertycollection.cpp:320
QgsExternalResourceWidgetWrapper
Wraps a file name widget. Will offer a file browser to choose files.
Definition: qgsexternalresourcewidgetwrapper.h:41
qgsproject.h
qgspropertyoverridebutton.h
qgsexpressionbuilderdialog.h