QGIS API Documentation 3.29.0-Master (da8bb1db43)
qgsexternalresourcewidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsexternalresourcewidget.cpp
3
4 ---------------------
5 begin : 16.12.2015
6 copyright : (C) 2015 by Denis Rouzaud
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
18#include "qgspixmaplabel.h"
19#include "qgsproject.h"
20#include "qgsapplication.h"
21#include "qgsmediawidget.h"
23#include "qgstaskmanager.h"
24#include "qgsexternalstorage.h"
25#include "qgsmessagebar.h"
27
28#include <QDir>
29#include <QGridLayout>
30#include <QVariant>
31#include <QSettings>
32#include <QImageReader>
33#include <QToolButton>
34#include <QMimeType>
35#include <QMimeDatabase>
36#include <QMovie>
37#ifdef WITH_QTWEBKIT
38#include <QWebView>
39#endif
40
42 : QWidget( parent )
43{
44 setBackgroundRole( QPalette::Window );
45 setAutoFillBackground( true );
46
47 QGridLayout *layout = new QGridLayout();
48 layout->setContentsMargins( 0, 0, 0, 0 );
49
50 mFileWidget = new QgsExternalStorageFileWidget( this );
51 layout->addWidget( mFileWidget, 0, 0 );
52 mFileWidget->setVisible( mFileWidgetVisible );
53
54 mPixmapLabel = new QgsPixmapLabel( this );
55 layout->addWidget( mPixmapLabel, 1, 0 );
56
57#ifdef WITH_QTWEBKIT
58 mWebView = new QWebView( this );
59 mWebView->setAcceptDrops( false );
60 layout->addWidget( mWebView, 2, 0 );
61#endif
62
63 mMediaWidget = new QgsMediaWidget( this );
64 layout->addWidget( mMediaWidget, 3, 0 );
65
66 mLoadingLabel = new QLabel( this );
67 layout->addWidget( mLoadingLabel, 4, 0 );
68 mLoadingMovie = new QMovie( QgsApplication::iconPath( QStringLiteral( "/mIconLoading.gif" ) ), QByteArray(), this );
69 mLoadingMovie->setScaledSize( QSize( 32, 32 ) );
70 mLoadingLabel->setMovie( mLoadingMovie );
71
72 mErrorLabel = new QLabel( this );
73 layout->addWidget( mErrorLabel, 5, 0 );
74 mErrorLabel->setPixmap( QPixmap( QgsApplication::iconPath( QStringLiteral( "/mIconWarning.svg" ) ) ) );
75
76 updateDocumentViewer();
77
78 setLayout( layout );
79
80 connect( mFileWidget, &QgsFileWidget::fileChanged, this, &QgsExternalResourceWidget::loadDocument );
82}
83
84QVariant QgsExternalResourceWidget::documentPath( QVariant::Type type ) const
85{
86 const QString path = mFileWidget->filePath();
87 if ( path.isEmpty() || path == QgsApplication::nullRepresentation() )
88 {
89 return QVariant( type );
90 }
91 else
92 {
93 return path;
94 }
95}
96
98{
99 mFileWidget->setFilePath( path.toString() );
100}
101
103{
104 return mFileWidget;
105}
106
108{
109 return mFileWidgetVisible;
110}
111
113{
114 mFileWidgetVisible = visible;
115 mFileWidget->setVisible( visible );
116}
117
119{
120 return mDocumentViewerContent;
121}
122
124{
125 mDocumentViewerContent = content;
126 if ( mDocumentViewerContent != Image )
127 updateDocumentViewer();
128 loadDocument( mFileWidget->filePath() );
129}
130
132{
133 return mDocumentViewerHeight;
134}
135
137{
138 mDocumentViewerHeight = height;
139 updateDocumentViewer();
140}
141
143{
144 return mDocumentViewerWidth;
145}
146
148{
149 mDocumentViewerWidth = width;
150 updateDocumentViewer();
151}
152
154{
155 mFileWidget->setReadOnly( readOnly );
156}
157
158void QgsExternalResourceWidget::updateDocumentViewer()
159{
160 mErrorLabel->setVisible( false );
161 mLoadingLabel->setVisible( false );
162 mLoadingMovie->stop();
163
164 switch ( mDocumentViewerContent )
165 {
166 case Web:
167 {
168#ifdef WITH_QTWEBKIT
169 mWebView->setVisible( true );
170#endif
171 mMediaWidget->setVisible( false );
172 mPixmapLabel->setVisible( false );
173 break;
174 }
175
176 case Image:
177 {
178#ifdef WITH_QTWEBKIT
179 mWebView->setVisible( false );
180#endif
181 mMediaWidget->setVisible( false );
182 mPixmapLabel->setVisible( true );
183
184#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
185 const QPixmap pm = mPixmapLabel->pixmap() ? *mPixmapLabel->pixmap() : QPixmap();
186#else
187 const QPixmap pm = mPixmapLabel->pixmap();
188#endif
189
190 if ( !pm || pm.isNull() )
191 {
192 mPixmapLabel->setMinimumSize( QSize( 0, 0 ) );
193 }
194 else
195 {
196 QSize size( mDocumentViewerWidth, mDocumentViewerHeight );
197 if ( size.width() == 0 && size.height() > 0 )
198 {
199 size.setWidth( size.height() * pm.size().width() / pm.size().height() );
200 }
201 else if ( size.width() > 0 && size.height() == 0 )
202 {
203 size.setHeight( size.width() * pm.size().height() / pm.size().width() );
204 }
205
206 if ( size.width() != 0 || size.height() != 0 )
207 {
208 mPixmapLabel->setMinimumSize( size );
209 mPixmapLabel->setMaximumSize( size );
210 }
211 }
212 break;
213 }
214
215 case Audio:
216 case Video:
217 {
218#ifdef WITH_QTWEBKIT
219 mWebView->setVisible( false );
220#endif
221 mMediaWidget->setVisible( true );
222 mPixmapLabel->setVisible( false );
223
224 mMediaWidget->setMode( mDocumentViewerContent == Video ? QgsMediaWidget::Video : QgsMediaWidget::Audio );
225 mMediaWidget->setVideoHeight( mDocumentViewerHeight );
226 break;
227 }
228
229 case NoContent:
230 {
231#ifdef WITH_QTWEBKIT
232 mWebView->setVisible( false );
233#endif
234 mMediaWidget->setVisible( false );
235 mPixmapLabel->setVisible( false );
236 break;
237 }
238 }
239}
240
241QString QgsExternalResourceWidget::resolvePath( const QString &path )
242{
243 switch ( mRelativeStorage )
244 {
246 return path;
247 break;
249 return QFileInfo( QgsProject::instance()->absoluteFilePath() ).dir().filePath( path );
250 break;
252 return QDir( mDefaultRoot ).filePath( path );
253 break;
254 }
255 return QString(); // avoid warnings
256}
257
259{
260 return mDefaultRoot;
261}
262
263void QgsExternalResourceWidget::setDefaultRoot( const QString &defaultRoot )
264{
265 mFileWidget->setDefaultRoot( defaultRoot );
266 mDefaultRoot = defaultRoot;
267}
268
270{
271 return mRelativeStorage;
272}
273
275{
276 mFileWidget->setRelativeStorage( relativeStorage );
277 mRelativeStorage = relativeStorage;
278}
279
280void QgsExternalResourceWidget::setStorageType( const QString &storageType )
281{
282 mFileWidget->setStorageType( storageType );
283}
284
286{
287 return mFileWidget->storageType();
288}
289
291{
292 mFileWidget->setStorageAuthConfigId( authCfg );
293}
294
296{
297 return mFileWidget->storageAuthConfigId();
298}
299
301{
302 mFileWidget->setMessageBar( messageBar );
303}
304
306{
307 return mFileWidget->messageBar();
308}
309
310void QgsExternalResourceWidget::updateDocumentContent( const QString &filePath )
311{
312 switch ( mDocumentViewerContent )
313 {
314 case Web:
315 {
316#ifdef WITH_QTWEBKIT
317 mWebView->load( QUrl::fromEncoded( filePath.toUtf8() ) );
318 mWebView->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled, true );
319#endif
320 break;
321 }
322
323 case Image:
324 {
325 QImageReader ir( filePath );
326 // ensure image orientation and transforms are correctly handled
327 ir.setAutoTransform( true );
328 const QPixmap pm = QPixmap::fromImage( ir.read() );
329 if ( !pm.isNull() )
330 {
331 mPixmapLabel->setPixmap( pm );
332 }
333 else
334 {
335 mPixmapLabel->clear();
336 }
337 break;
338 }
339
340 case Audio:
341 case Video:
342 {
343 mMediaWidget->setMediaPath( filePath );
344 break;
345 }
346
347 case NoContent:
348 {
349 break;
350 }
351 }
352
353 updateDocumentViewer();
354}
355
356void QgsExternalResourceWidget::clearContent()
357{
358#ifdef WITH_QTWEBKIT
359 if ( mDocumentViewerContent == Web )
360 {
361 mWebView->load( QUrl( QStringLiteral( "about:blank" ) ) );
362 }
363#endif
364 if ( mDocumentViewerContent == Image )
365 {
366 mPixmapLabel->clear();
367 }
368
369 updateDocumentViewer();
370}
371
372void QgsExternalResourceWidget::loadDocument( const QString &path )
373{
374 if ( path.isEmpty() || path == QgsApplication::nullRepresentation() )
375 {
376 if ( mFileWidget->externalStorage() && mContent )
377 {
378 mContent->cancel();
379 mContent.clear();
380 }
381
382 clearContent();
383 }
384 else if ( mDocumentViewerContent != NoContent )
385 {
386 const QString resolvedPath = resolvePath( path );
387
388 if ( mFileWidget->externalStorage() )
389 {
390 if ( mContent )
391 {
392 mContent->cancel();
393 }
394
395 mContent = mFileWidget->externalStorage()->fetch( resolvedPath, storageAuthConfigId() );
396
397#ifdef WITH_QTWEBKIT
398 mWebView->setVisible( false );
399#endif
400 mMediaWidget->setVisible( false );
401 mPixmapLabel->setVisible( false );
402 mErrorLabel->setVisible( false );
403 mLoadingLabel->setVisible( true );
404 mLoadingMovie->start();
405 connect( mContent, &QgsExternalStorageFetchedContent::fetched, this, &QgsExternalResourceWidget::onFetchFinished );
406 connect( mContent, &QgsExternalStorageFetchedContent::errorOccurred, this, &QgsExternalResourceWidget::onFetchFinished );
407 connect( mContent, &QgsExternalStorageFetchedContent::canceled, this, &QgsExternalResourceWidget::onFetchFinished );
408
409 mContent->fetch();
410 }
411 else
412 {
413 updateDocumentContent( resolvedPath );
414 }
415 }
416}
417
418void QgsExternalResourceWidget::onFetchFinished()
419{
420 QgsExternalStorageFetchedContent *content = qobject_cast<QgsExternalStorageFetchedContent *>( sender() );
421
422 if ( content == mContent && mContent->status() == Qgis::ContentStatus::Failed )
423 {
424#ifdef WITH_QTWEBKIT
425 mWebView->setVisible( false );
426#endif
427 mPixmapLabel->setVisible( false );
428 mLoadingLabel->setVisible( false );
429 mLoadingMovie->stop();
430 mErrorLabel->setVisible( true );
431
432 if ( messageBar() )
433 {
434 messageBar()->pushWarning( tr( "Fetching External Resource" ),
435 tr( "Error while fetching external resource '%1' : %2" ).arg(
436 mFileWidget->filePath(), mContent->errorString() ) );
437 }
438 }
439 else if ( content == mContent && mContent->status() == Qgis::ContentStatus::Finished )
440 {
441 const QString filePath = mDocumentViewerContent == Web
442 ? QUrl::fromLocalFile( mContent->filePath() ).toString()
443 : mContent->filePath();
444
445 updateDocumentContent( filePath );
446 }
447
448 content->deleteLater();
449}
@ Finished
Content fetching/storing is finished and successful.
@ Failed
Content fetching/storing has failed.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
void setDocumentPath(const QVariant &documentPath)
void setMessageBar(QgsMessageBar *messageBar)
Set messageBar to report messages.
void setStorageAuthConfigId(const QString &authCfg)
Sets the authentication configuration ID to be used for the current external storage (if defined)
QVariant documentPath(QVariant::Type type=QVariant::String) const
documentPath returns the path of the current document in the widget
QgsMessageBar * messageBar() const
Returns message bar used to report messages.
QgsExternalStorageFileWidget * fileWidget()
Returns file widget to allow its configuration.
QgsExternalResourceWidget(QWidget *parent=nullptr)
QgsExternalResourceWidget creates a widget with a file widget and a document viewer Both part of the ...
void setStorageType(const QString &storageType)
Set storageType storage type unique identifier as defined in QgsExternalStorageRegistry or null QStri...
void setRelativeStorage(QgsFileWidget::RelativeStorage relativeStorage)
Configures if paths are handled absolute or relative and if relative, which should be the base path.
void setDocumentViewerHeight(int height)
setDocumentViewerWidth set the height of the document viewer.
QString storageType() const
Returns storage type unique identifier as defined in QgsExternalStorageRegistry.
void setDocumentViewerContent(QgsExternalResourceWidget::DocumentViewerContent content)
setDocumentViewerContent defines the type of content to be shown. Widget will be adapted accordingly
DocumentViewerContent documentViewerContent
QString storageAuthConfigId() const
Returns the authentication configuration ID used for the current external storage (if defined)
void setDefaultRoot(const QString &defaultRoot)
Configures the base path which should be used if the relativeStorage property is set to QgsFileWidget...
QgsFileWidget::RelativeStorage relativeStorage
void setDocumentViewerWidth(int width)
setDocumentViewerWidth set the width of the document viewer.
void setFileWidgetVisible(bool visible)
Sets the visibility of the file widget in the layout.
void setReadOnly(bool readOnly)
defines if the widget is readonly
void valueChanged(const QString &)
emitteed as soon as the current document changes
void canceled()
The signal is emitted when content fetching/storing has been canceled.
void errorOccurred(const QString &errorString)
The signal is emitted when an error occurred.
Class for QgsExternalStorage fetched content.
void fetched()
The signal is emitted when the resource has successfully been fetched.
The QgsExternalStorageFileWidget class creates a widget for selecting a file or a folder and stores i...
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 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.
QgsExternalStorageFetchedContent * fetch(const QString &url, const QString &authCfg=QString(), Qgis::ActionStart fetchingMode=Qgis::ActionStart::Deferred) const
Fetches file from url for this project external storage.
QString filePath()
Returns the current file path(s).
void setRelativeStorage(QgsFileWidget::RelativeStorage relativeStorage)
Sets whether the relative path is with respect to the project path or the default path.
void fileChanged(const QString &path)
Emitted whenever the current file or directory path is changed.
RelativeStorage
The RelativeStorage enum determines if path is absolute, relative to the current project path or rela...
Definition: qgsfilewidget.h:79
void setDefaultRoot(const QString &defaultRoot)
Returns the default root path used as the first shown location when picking a file and used if the Re...
void setFilePath(const QString &path)
Sets the current file path.
The QgsMediaWidget class creates a widget for playing back audio and video media files.
@ Video
Video-centric user interface.
@ Audio
Audio-centric user interface.
void setMode(Mode mode)
Sets the media widget mode.
void setVideoHeight(int height)
Sets the video frame height.
void setMediaPath(const QString &path)
Sets the media path.
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
void pushWarning(const QString &title, const QString &message)
Pushes a warning message that must be manually dismissed by the user.
The QgsPixmapLabel class shows a pixmap and adjusts its size to the space given to the widget by the ...
void clear()
Clears any label contents.
void setPixmap(const QPixmap &)
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477