QGIS API Documentation  3.25.0-Master (10b47c2603)
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
7  email : [email protected]
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"
22 #include "qgstaskmanager.h"
23 #include "qgsexternalstorage.h"
24 #include "qgsmessagebar.h"
26 
27 #include <QDir>
28 #include <QGridLayout>
29 #include <QVariant>
30 #include <QSettings>
31 #include <QImageReader>
32 #include <QToolButton>
33 #include <QMimeType>
34 #include <QMimeDatabase>
35 #include <QMovie>
36 #ifdef WITH_QTWEBKIT
37 #include <QWebView>
38 #endif
39 
41  : QWidget( parent )
42 {
43  setBackgroundRole( QPalette::Window );
44  setAutoFillBackground( true );
45 
46  QGridLayout *layout = new QGridLayout();
47  layout->setContentsMargins( 0, 0, 0, 0 );
48 
49  mFileWidget = new QgsExternalStorageFileWidget( this );
50  layout->addWidget( mFileWidget, 0, 0 );
51  mFileWidget->setVisible( mFileWidgetVisible );
52 
53  mPixmapLabel = new QgsPixmapLabel( this );
54  layout->addWidget( mPixmapLabel, 1, 0 );
55 
56 #ifdef WITH_QTWEBKIT
57  mWebView = new QWebView( this );
58  mWebView->setAcceptDrops( false );
59  layout->addWidget( mWebView, 2, 0 );
60 #endif
61 
62  mLoadingLabel = new QLabel( this );
63  layout->addWidget( mLoadingLabel, 3, 0 );
64  mLoadingMovie = new QMovie( QgsApplication::iconPath( QStringLiteral( "/mIconLoading.gif" ) ), QByteArray(), this );
65  mLoadingMovie->setScaledSize( QSize( 32, 32 ) );
66  mLoadingLabel->setMovie( mLoadingMovie );
67 
68  mErrorLabel = new QLabel( this );
69  layout->addWidget( mErrorLabel, 4, 0 );
70  mErrorLabel->setPixmap( QPixmap( QgsApplication::iconPath( QStringLiteral( "/mIconWarning.svg" ) ) ) );
71 
72  updateDocumentViewer();
73 
74  setLayout( layout );
75 
76  connect( mFileWidget, &QgsFileWidget::fileChanged, this, &QgsExternalResourceWidget::loadDocument );
78 }
79 
80 QVariant QgsExternalResourceWidget::documentPath( QVariant::Type type ) const
81 {
82  const QString path = mFileWidget->filePath();
83  if ( path.isEmpty() || path == QgsApplication::nullRepresentation() )
84  {
85  return QVariant( type );
86  }
87  else
88  {
89  return path;
90  }
91 }
92 
93 void QgsExternalResourceWidget::setDocumentPath( const QVariant &path )
94 {
95  mFileWidget->setFilePath( path.toString() );
96 }
97 
99 {
100  return mFileWidget;
101 }
102 
104 {
105  return mFileWidgetVisible;
106 }
107 
109 {
110  mFileWidgetVisible = visible;
111  mFileWidget->setVisible( visible );
112 }
113 
115 {
116  return mDocumentViewerContent;
117 }
118 
120 {
121  mDocumentViewerContent = content;
122  if ( mDocumentViewerContent != Image )
123  updateDocumentViewer();
124  loadDocument( mFileWidget->filePath() );
125 }
126 
128 {
129  return mDocumentViewerHeight;
130 }
131 
133 {
134  mDocumentViewerHeight = height;
135  updateDocumentViewer();
136 }
137 
139 {
140  return mDocumentViewerWidth;
141 }
142 
144 {
145  mDocumentViewerWidth = width;
146  updateDocumentViewer();
147 }
148 
150 {
151  mFileWidget->setReadOnly( readOnly );
152 }
153 
154 void QgsExternalResourceWidget::updateDocumentViewer()
155 {
156  mErrorLabel->setVisible( false );
157  mLoadingLabel->setVisible( false );
158  mLoadingMovie->stop();
159 
160 #ifdef WITH_QTWEBKIT
161  mWebView->setVisible( mDocumentViewerContent == Web );
162 #endif
163 
164  mPixmapLabel->setVisible( mDocumentViewerContent == Image );
165 
166  if ( mDocumentViewerContent == Image )
167  {
168 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
169  const QPixmap pm = mPixmapLabel->pixmap() ? *mPixmapLabel->pixmap() : QPixmap();
170 #else
171  const QPixmap pm = mPixmapLabel->pixmap();
172 #endif
173 
174  if ( !pm || pm.isNull() )
175  {
176  mPixmapLabel->setMinimumSize( QSize( 0, 0 ) );
177  }
178  else
179  {
180  QSize size( mDocumentViewerWidth, mDocumentViewerHeight );
181  if ( size.width() == 0 && size.height() > 0 )
182  {
183  size.setWidth( size.height() * pm.size().width() / pm.size().height() );
184  }
185  else if ( size.width() > 0 && size.height() == 0 )
186  {
187  size.setHeight( size.width() * pm.size().height() / pm.size().width() );
188  }
189 
190  if ( size.width() != 0 || size.height() != 0 )
191  {
192  mPixmapLabel->setMinimumSize( size );
193  mPixmapLabel->setMaximumSize( size );
194  }
195  }
196  }
197 }
198 
199 QString QgsExternalResourceWidget::resolvePath( const QString &path )
200 {
201  switch ( mRelativeStorage )
202  {
204  return path;
205  break;
207  return QFileInfo( QgsProject::instance()->absoluteFilePath() ).dir().filePath( path );
208  break;
210  return QDir( mDefaultRoot ).filePath( path );
211  break;
212  }
213  return QString(); // avoid warnings
214 }
215 
217 {
218  return mDefaultRoot;
219 }
220 
221 void QgsExternalResourceWidget::setDefaultRoot( const QString &defaultRoot )
222 {
223  mFileWidget->setDefaultRoot( defaultRoot );
224  mDefaultRoot = defaultRoot;
225 }
226 
228 {
229  return mRelativeStorage;
230 }
231 
233 {
234  mFileWidget->setRelativeStorage( relativeStorage );
235  mRelativeStorage = relativeStorage;
236 }
237 
238 void QgsExternalResourceWidget::setStorageType( const QString &storageType )
239 {
240  mFileWidget->setStorageType( storageType );
241 }
242 
244 {
245  return mFileWidget->storageType();
246 }
247 
249 {
250  mFileWidget->setStorageAuthConfigId( authCfg );
251 }
252 
254 {
255  return mFileWidget->storageAuthConfigId();
256 }
257 
259 {
260  mFileWidget->setMessageBar( messageBar );
261 }
262 
264 {
265  return mFileWidget->messageBar();
266 }
267 
268 void QgsExternalResourceWidget::updateDocumentContent( const QString &filePath )
269 {
270 #ifdef WITH_QTWEBKIT
271  if ( mDocumentViewerContent == Web )
272  {
273  mWebView->load( QUrl::fromEncoded( filePath.toUtf8() ) );
274  mWebView->page()->settings()->setAttribute( QWebSettings::LocalStorageEnabled, true );
275  }
276 #endif
277 
278  if ( mDocumentViewerContent == Image )
279  {
280  // use an image reader to ensure image orientation and transforms are correctly handled
281  QImageReader ir( filePath );
282  ir.setAutoTransform( true );
283  const QPixmap pm = QPixmap::fromImage( ir.read() );
284  if ( !pm.isNull() )
285  mPixmapLabel->setPixmap( pm );
286  else
287  mPixmapLabel->clear();
288  }
289 
290  updateDocumentViewer();
291 }
292 
293 void QgsExternalResourceWidget::clearContent()
294 {
295 #ifdef WITH_QTWEBKIT
296  if ( mDocumentViewerContent == Web )
297  {
298  mWebView->load( QUrl( QStringLiteral( "about:blank" ) ) );
299  }
300 #endif
301  if ( mDocumentViewerContent == Image )
302  {
303  mPixmapLabel->clear();
304  }
305 
306  updateDocumentViewer();
307 }
308 
309 void QgsExternalResourceWidget::loadDocument( const QString &path )
310 {
311  if ( path.isEmpty() || path == QgsApplication::nullRepresentation() )
312  {
313  if ( mFileWidget->externalStorage() && mContent )
314  {
315  mContent->cancel();
316  mContent.clear();
317  }
318 
319  clearContent();
320  }
321  else if ( mDocumentViewerContent != NoContent )
322  {
323  const QString resolvedPath = resolvePath( path );
324 
325  if ( mFileWidget->externalStorage() )
326  {
327  if ( mContent )
328  {
329  mContent->cancel();
330  }
331 
332  mContent = mFileWidget->externalStorage()->fetch( resolvedPath, storageAuthConfigId() );
333 
334 #ifdef WITH_QTWEBKIT
335  mWebView->setVisible( false );
336 #endif
337  mPixmapLabel->setVisible( false );
338  mErrorLabel->setVisible( false );
339  mLoadingLabel->setVisible( true );
340  mLoadingMovie->start();
341  connect( mContent, &QgsExternalStorageFetchedContent::fetched, this, &QgsExternalResourceWidget::onFetchFinished );
342  connect( mContent, &QgsExternalStorageFetchedContent::errorOccurred, this, &QgsExternalResourceWidget::onFetchFinished );
343  connect( mContent, &QgsExternalStorageFetchedContent::canceled, this, &QgsExternalResourceWidget::onFetchFinished );
344 
345  mContent->fetch();
346  }
347  else
348  {
349  updateDocumentContent( resolvedPath );
350  }
351  }
352 }
353 
354 void QgsExternalResourceWidget::onFetchFinished()
355 {
356  QgsExternalStorageFetchedContent *content = qobject_cast<QgsExternalStorageFetchedContent *>( sender() );
357 
358  if ( content == mContent && mContent->status() == Qgis::ContentStatus::Failed )
359  {
360 #ifdef WITH_QTWEBKIT
361  mWebView->setVisible( false );
362 #endif
363  mPixmapLabel->setVisible( false );
364  mLoadingLabel->setVisible( false );
365  mLoadingMovie->stop();
366  mErrorLabel->setVisible( true );
367 
368  if ( messageBar() )
369  {
370  messageBar()->pushWarning( tr( "Fetching External Resource" ),
371  tr( "Error while fetching external resource '%1' : %2" ).arg(
372  mFileWidget->filePath(), mContent->errorString() ) );
373  }
374  }
375  else if ( content == mContent && mContent->status() == Qgis::ContentStatus::Finished )
376  {
377  const QString filePath = mDocumentViewerContent == Web
378  ? QUrl::fromLocalFile( mContent->filePath() ).toString()
379  : mContent->filePath();
380 
381  updateDocumentContent( filePath );
382  }
383 
384  content->deleteLater();
385 }
@ 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.
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:479