QGIS API Documentation 3.41.0-Master (3440c17df1d)
Loading...
Searching...
No Matches
qgsexternalstoragefilewidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsexternalstoragefilewidget.cpp
3 --------------------------------------
4 Date : August 2021
5 Copyright : (C) 2021 by Julien Cabieces
6 Email : julien dot cabieces at oslandia dot com
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
17#include "moc_qgsexternalstoragefilewidget.cpp"
18
19#include <QLineEdit>
20#include <QToolButton>
21#include <QLabel>
22#include <QGridLayout>
23#include <QUrl>
24#include <QDropEvent>
25#include <QRegularExpression>
26#include <QProgressBar>
27
28#include "qgslogger.h"
29#include "qgsapplication.h"
30#include "qgsexternalstorage.h"
32#include "qgsmessagebar.h"
33#include "qgsexpression.h"
34
35#define FILEPATH_VARIABLE "selected_file_path"
36
38 : QgsFileWidget( parent )
39{
40 mProgressLabel = new QLabel( this );
41 mLayout->addWidget( mProgressLabel );
42 mProgressLabel->hide();
43
44 mProgressBar = new QProgressBar( this );
45 mLayout->addWidget( mProgressBar );
46 mProgressBar->hide();
47
48 mCancelButton = new QToolButton( this );
49 mLayout->addWidget( mCancelButton );
50 mCancelButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mTaskCancel.svg" ) ) );
51 mCancelButton->hide();
52
53 updateAcceptDrops();
54}
55
56void QgsExternalStorageFileWidget::setStorageType( const QString &storageType )
57{
58 if ( storageType.isEmpty() )
59 mExternalStorage = nullptr;
60
61 else
62 {
64 if ( !mExternalStorage )
65 {
66 QgsDebugError( QStringLiteral( "Invalid storage type: %1" ).arg( storageType ) );
67 }
68 else
69 {
71 }
72 }
73
74 updateAcceptDrops();
75}
76
78{
80 updateAcceptDrops();
81}
82
83void QgsExternalStorageFileWidget::updateAcceptDrops()
84{
85 setAcceptDrops( !mReadOnly && mExternalStorage );
86}
87
89{
90 return mExternalStorage ? mExternalStorage->type() : QString();
91}
92
94{
95 return mExternalStorage;
96}
97
99{
100 mAuthCfg = authCfg;
101}
102
104{
105 return mAuthCfg;
106}
107
109{
110 mStorageUrlExpression.reset( new QgsExpression( urlExpression ) );
111}
112
114{
115 return mStorageUrlExpression.get();
116}
117
119{
120 return mStorageUrlExpression ? mStorageUrlExpression->expression() : QString();
121}
122
123
125{
126 mScope = nullptr; // deleted by old context when we override it with the new one
127 mExpressionContext = context;
129}
130
132{
133 if ( !mExternalStorage || mScope )
134 return;
135
136 mScope = createFileWidgetScope();
137 mExpressionContext << mScope;
138}
139
141{
142 QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "FileWidget" ) );
144 QStringLiteral( FILEPATH_VARIABLE ),
145 QString(), true, false, tr( "User selected absolute filepath" ) ) );
146 return scope;
147}
148
150{
151 return mExpressionContext;
152}
153
154
156{
157 mMessageBar = messageBar;
158}
159
161{
162 return mMessageBar;
163}
164
166{
167 mProgressLabel->setVisible( mStoreInProgress );
168 mProgressBar->setVisible( mStoreInProgress );
169 mCancelButton->setVisible( mStoreInProgress );
170
171 const bool linkVisible = mUseLink && !mIsLinkEdited;
172
173 mLineEdit->setVisible( !mStoreInProgress && !linkVisible );
174 mLinkLabel->setVisible( !mStoreInProgress && linkVisible );
175 mLinkEditButton->setVisible( !mStoreInProgress && mUseLink && !mReadOnly );
176
177 mFileWidgetButton->setVisible( mButtonVisible && !mStoreInProgress );
178 mFileWidgetButton->setEnabled( !mReadOnly );
179 mLineEdit->setEnabled( !mReadOnly );
180
181 mLinkEditButton->setIcon( linkVisible && !mReadOnly ?
182 QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) ) :
183 QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveEdits.svg" ) ) );
184}
185
187{
188 Q_ASSERT( fileNames.count() );
189
190 // store files first, update filePath later
191 if ( mExternalStorage )
192 {
193 if ( !mStorageUrlExpression->prepare( &mExpressionContext ) )
194 {
195 if ( messageBar() )
196 {
197 messageBar()->pushWarning( tr( "Storing External resource" ),
198 tr( "Storage URL expression is invalid : %1" ).arg( mStorageUrlExpression->evalErrorString() ) );
199 }
200
201 QgsDebugError( QStringLiteral( "Storage URL expression is invalid : %1" ).arg( mStorageUrlExpression->evalErrorString() ) );
202 return;
203 }
204
205 storeExternalFiles( fileNames );
206 }
207 else
208 {
210 }
211}
212
213void QgsExternalStorageFileWidget::storeExternalFiles( QStringList fileNames, QStringList storedUrls )
214{
215 if ( fileNames.isEmpty() )
216 return;
217
218 const QString filePath = fileNames.takeFirst();
219
220 mProgressLabel->setText( tr( "Storing file %1 ..." ).arg( QFileInfo( filePath ).fileName() ) );
221 mStoreInProgress = true;
222 mProgressBar->setValue( 0 );
223 updateLayout();
224
225 Q_ASSERT( mScope );
226 mScope->setVariable( QStringLiteral( FILEPATH_VARIABLE ), filePath );
227
228 QVariant url = mStorageUrlExpression->evaluate( &mExpressionContext );
229 if ( !url.isValid() )
230 {
231 if ( messageBar() )
232 {
233 messageBar()->pushWarning( tr( "Storing External resource" ),
234 tr( "Storage URL expression is invalid : %1" ).arg( mStorageUrlExpression->evalErrorString() ) );
235 }
236
237 mStoreInProgress = false;
238 updateLayout();
239
240 return;
241 }
242
243 QgsExternalStorageStoredContent *storedContent = mExternalStorage->store( filePath, url.toString(), mAuthCfg );
244
245 connect( storedContent, &QgsExternalStorageStoredContent::progressChanged, mProgressBar, &QProgressBar::setValue );
246 connect( mCancelButton, &QToolButton::clicked, storedContent, &QgsExternalStorageStoredContent::cancel );
247
248 auto onStoreFinished = [ = ]
249 {
250 mStoreInProgress = false;
251 updateLayout();
252 storedContent->deleteLater();
253
254 if ( storedContent->status() == Qgis::ContentStatus::Failed && messageBar() )
255 {
256 messageBar()->pushWarning( tr( "Storing External resource" ),
257 tr( "Storing file '%1' to url '%2' has failed : %3" ).arg( filePath, url.toString(), storedContent->errorString() ) );
258 }
259
260 if ( storedContent->status() != Qgis::ContentStatus::Finished )
261 return;
262
263 QStringList newStoredUrls = storedUrls;
264 newStoredUrls << storedContent->url();
265
266 // every thing has been stored, we update filepath
267 if ( fileNames.isEmpty() )
268 {
269 setFilePaths( newStoredUrls );
270 }
271 else
272 storeExternalFiles( fileNames, newStoredUrls );
273 };
274
275 connect( storedContent, &QgsExternalStorageStoredContent::stored, onStoreFinished );
276 connect( storedContent, &QgsExternalStorageStoredContent::canceled, onStoreFinished );
277 connect( storedContent, &QgsExternalStorageStoredContent::errorOccurred, onStoreFinished );
278
279 storedContent->store();
280}
281
283{
284 const QStringList filePaths = mLineEdit->acceptableFilePaths( event );
285 if ( !filePaths.isEmpty() )
286 {
287 event->acceptProposedAction();
288 }
289 else
290 {
291 event->ignore();
292 }
293}
294
296{
297 storeExternalFiles( mLineEdit->acceptableFilePaths( event ) );
298 event->acceptProposedAction();
299}
@ Finished
Content fetching/storing is finished and successful.
@ Failed
Content fetching/storing has failed.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsExternalStorageRegistry * externalStorageRegistry()
Returns registry of available external storage implementations.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Class for parsing and evaluation of expressions (formerly called "search strings").
void canceled()
The signal is emitted when content fetching/storing has been canceled.
void progressChanged(double progress)
The signal is emitted whenever content fetching/storing estimated progression value progress has chan...
void errorOccurred(const QString &errorString)
The signal is emitted when an error occurred.
Qgis::ContentStatus status() const
Returns content status.
virtual void cancel()
Cancels content fetching/storing.
const QString & errorString() const
Returns error textual description if an error occurred and status() returns Failed.
void updateLayout() override
Update buttons visibility.
void setSelectedFileNames(QStringList fileNames) override
Called whenever user select fileNames from dialog.
void setMessageBar(QgsMessageBar *messageBar)
Set messageBar to report messages.
const QString & storageAuthConfigId() const
Returns the authentication configuration ID used for the current external storage (if defined)
void setStorageType(const QString &storageType)
Set storageType storage type unique identifier as defined in QgsExternalStorageRegistry or null QStri...
void setExpressionContext(const QgsExpressionContext &context)
Set expression context to be used when for storage URL expression evaluation.
QString storageUrlExpressionString() const
Returns the original, unmodified expression string, which once evaluated, provide the URL used to sto...
void setStorageUrlExpression(const QString &urlExpression)
Set urlExpression expression, which once evaluated, provide the URL used to store selected documents.
static QgsExpressionContextScope * createFileWidgetScope()
Creates and Returns an expression context scope specific to QgsExternalStorageFileWidget It defines t...
QgsExternalStorageFileWidget(QWidget *parent=nullptr)
QgsExternalStorageFileWidget creates a widget for selecting a file or a folder.
void setReadOnly(bool readOnly) override
Sets whether the widget should be read only.
QgsExternalStorage * externalStorage() const
Returns external storage used to store selected file names, nullptr if none have been defined.
void setStorageAuthConfigId(const QString &authCfg)
Sets the authentication configuration ID to be used for the current external storage (if defined)
QgsMessageBar * messageBar() const
Returns message bar used to report messages.
void addFileWidgetScope()
Add file widget specific scope to expression context.
void dragEnterEvent(QDragEnterEvent *event) override
const QgsExpressionContext & expressionContext() const
Returns expression context used for storage url expression evaluation.
void dropEvent(QDropEvent *event) override
QgsExternalStorage * externalStorageFromType(const QString &type) const
Returns external storage implementation if the storage type matches one.
Class for QgsExternalStorage stored content.
void stored()
The signal is emitted when the resource has successfully been stored.
virtual QString url() const =0
Returns stored resource URL.
virtual void store()=0
Starts storing.
Abstract interface for external storage - to be implemented by various backends and registered in Qgs...
virtual QString type() const =0
Unique identifier of the external storage type.
QgsExternalStorageStoredContent * store(const QString &filePath, const QString &url, const QString &authCfg=QString(), Qgis::ActionStart storingMode=Qgis::ActionStart::Deferred) const
Stores file filePath to the url for this project external storage.
The QgsFileWidget class creates a widget for selecting a file or a folder.
QString filePath()
Returns the current file path(s).
void setFilePaths(const QStringList &filePaths)
Update filePath according to filePaths list.
QHBoxLayout * mLayout
virtual void setSelectedFileNames(QStringList fileNames)
Called whenever user select fileNames from dialog.
QgsFileDropEdit * mLineEdit
QToolButton * mLinkEditButton
QToolButton * mFileWidgetButton
QLabel * mLinkLabel
virtual void setReadOnly(bool readOnly)
Sets whether the widget should be read only.
A bar for displaying non-blocking messages to the user.
void pushWarning(const QString &title, const QString &message)
Pushes a warning message that must be manually dismissed by the user.
#define FILEPATH_VARIABLE
#define QgsDebugError(str)
Definition qgslogger.h:38
Single variable definition for use within a QgsExpressionContextScope.