Skip to content

Commit bdc2e24

Browse files
committed
File downloader for identify dialog hyperlinks
fixes #14703 Include C++ and Python tests
1 parent db0e7d5 commit bdc2e24

File tree

11 files changed

+815
-0
lines changed

11 files changed

+815
-0
lines changed

python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
%Include qgsfieldvalidator.sip
8282
%Include qgsfiledropedit.sip
8383
%Include qgsfilewidget.sip
84+
%Include qgsfiledownloader.sip
8485
%Include qgsfilterlineedit.sip
8586
%Include qgsfocuswatcher.sip
8687
%Include qgsformannotationitem.sip

python/gui/qgsfiledownloader.sip

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/***************************************************************************
2+
qgsfiledownloader.sip
3+
--------------------------------------
4+
Date : November 2016
5+
Copyright : (C) 2016 by Alessandro Pasotti
6+
Email : elpaso at itopen dot it
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+
16+
/** \ingroup gui
17+
* QgsFileDownloader is a utility class for downloading files.
18+
*
19+
* To use this class, it is necessary to pass the URL and an output file name as
20+
* arguments to the constructor, the download will start immediately.
21+
* The download is asynchronous and depending on the guiNotificationsEnabled
22+
* parameter accepted by the constructor (default = true) the class will
23+
* show a progress dialog and report all errors in a QMessageBox::warning dialog.
24+
* If the guiNotificationsEnabled parameter is set to false, the class can still
25+
* be used through the signals and slots mechanism.
26+
* The object will destroy itself when the request completes, errors or is canceled.
27+
*/
28+
class QgsFileDownloader : public QObject
29+
{
30+
%TypeHeaderCode
31+
#include <qgsfiledownloader.h>
32+
%End
33+
public:
34+
/**
35+
* QgsFileDownloader
36+
* @param url the download url
37+
* @param outputFileName file name where the downloaded content will be stored
38+
* @param guiNotificationsEnabled if false, the downloader will not display any progress bar or error message
39+
*/
40+
QgsFileDownloader(QUrl url, QString outputFileName, bool guiNotificationsEnabled = true);
41+
42+
signals:
43+
/** Emitted when the download has completed successfully */
44+
void downloadCompleted();
45+
/** Emitted always when the downloader exits */
46+
void downloadExited();
47+
/** Emitted when the download was canceled by the user */
48+
void downloadCanceled();
49+
/** Emitted when an error makes the download fail */
50+
void downloadError( QStringList errorMessages );
51+
/** Emitted when data ready to be processed */
52+
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
53+
54+
public slots:
55+
/**
56+
* Called when a download is canceled by the user
57+
* this slot aborts the download and deletes the object
58+
*/
59+
void onDownloadCanceled();
60+
61+
private:
62+
~QgsFileDownloader();
63+
64+
};

src/app/qgsidentifyresultsdialog.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "qgswebview.h"
3939
#include "qgswebframe.h"
4040
#include "qgsstringutils.h"
41+
#include "qgsfiledownloader.h"
4142

4243
#include <QCloseEvent>
4344
#include <QLabel>
@@ -55,6 +56,11 @@
5556
#include <QMessageBox>
5657
#include <QComboBox>
5758
#include <QTextDocument>
59+
#include <QNetworkRequest>
60+
#include <QNetworkReply>
61+
#include <QFileDialog>
62+
#include <QFileInfo>
63+
#include <QRegExp>
5864

5965
//graph
6066
#include <qwt_plot.h>
@@ -68,13 +74,63 @@ QgsIdentifyResultsWebView::QgsIdentifyResultsWebView( QWidget *parent ) : QgsWeb
6874
setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
6975
page()->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
7076
// page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
77+
page()->setForwardUnsupportedContent( true );
7178
page()->setLinkDelegationPolicy( QWebPage::DontDelegateLinks );
7279
settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
7380
settings()->setAttribute( QWebSettings::JavascriptCanOpenWindows, true );
7481
settings()->setAttribute( QWebSettings::PluginsEnabled, true );
7582
#ifdef QGISDEBUG
7683
settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
7784
#endif
85+
connect( page(), SIGNAL( downloadRequested( QNetworkRequest ) ), this, SLOT( downloadRequested( QNetworkRequest ) ) );
86+
connect( page(), SIGNAL( unsupportedContent( QNetworkReply* ) ), this, SLOT( unsupportedContent( QNetworkReply* ) ) );
87+
}
88+
89+
90+
void QgsIdentifyResultsWebView::downloadRequested( const QNetworkRequest &request )
91+
{
92+
qDebug() << "Download Requested: " << request.url();
93+
handleDownload( request.url() );
94+
}
95+
96+
void QgsIdentifyResultsWebView::unsupportedContent( QNetworkReply * reply )
97+
{
98+
qDebug() << "Unsupported Content: " << reply->url();
99+
handleDownload( reply->url() );
100+
}
101+
102+
void QgsIdentifyResultsWebView::handleDownload( QUrl url )
103+
{
104+
qDebug() << "Downloading: " << url;
105+
if ( ! url.isValid() )
106+
{
107+
QMessageBox::warning( this, tr( "Invalid URL" ), tr( "The download URL is not valid: %1" ).arg( url.toString( ) ) );
108+
}
109+
else
110+
{
111+
const QString DOWNLOADER_LAST_DIR_KEY( "Qgis/fileDownloaderLastDir" );
112+
QSettings settings;
113+
// Try to get some information from the URL
114+
QFileInfo info( url.toString( ) );
115+
QString savePath = settings.value( DOWNLOADER_LAST_DIR_KEY ).toString( );
116+
QString fileName = info.fileName().replace( QRegExp( "[^A-z0-9\\-_\\.]" ), "_" );
117+
if ( ! savePath.isEmpty() && ! fileName.isEmpty( ) )
118+
{
119+
savePath = QDir::cleanPath( savePath + QDir::separator() + fileName );
120+
}
121+
QString targetFile = QFileDialog::getSaveFileName( this,
122+
tr( "Save as" ),
123+
savePath,
124+
info.suffix( ).isEmpty() ? QString( ) : "*." + info.suffix( )
125+
);
126+
if ( ! targetFile.isEmpty() )
127+
{
128+
settings.setValue( DOWNLOADER_LAST_DIR_KEY, QFileInfo( targetFile ).dir().absolutePath( ) );
129+
// Start the download
130+
qDebug() << "Start the download: " << url;
131+
new QgsFileDownloader( url, targetFile );
132+
}
133+
}
78134
}
79135

80136
void QgsIdentifyResultsWebView::print()

src/app/qgsidentifyresultsdialog.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131

3232
#include <QWidget>
3333
#include <QList>
34+
#include <QNetworkRequest>
35+
#include <QNetworkReply>
36+
#include <QUrl>
3437

3538
class QCloseEvent;
3639
class QTreeWidgetItem;
@@ -57,9 +60,13 @@ class APP_EXPORT QgsIdentifyResultsWebView : public QgsWebView
5760
QSize sizeHint() const override;
5861
public slots:
5962
void print();
63+
void downloadRequested( const QNetworkRequest &request );
64+
void unsupportedContent( QNetworkReply *reply );
6065
protected:
6166
void contextMenuEvent( QContextMenuEvent* ) override;
6267
QgsWebView *createWindow( QWebPage::WebWindowType type ) override;
68+
private:
69+
void handleDownload( QUrl url );
6370
};
6471

6572
class APP_EXPORT QgsIdentifyResultsFeatureItem: public QTreeWidgetItem

src/gui/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ SET(QGIS_GUI_SRCS
307307
qgsuserinputdockwidget.cpp
308308
qgsvariableeditorwidget.cpp
309309
qgsvertexmarker.cpp
310+
qgsfiledownloader.cpp
310311
)
311312

312313
IF (WITH_QTWEBKIT)
@@ -454,6 +455,7 @@ SET(QGIS_GUI_MOC_HDRS
454455
qgsunitselectionwidget.h
455456
qgsuserinputdockwidget.h
456457
qgsvariableeditorwidget.h
458+
qgsfiledownloader.h
457459

458460
raster/qgsmultibandcolorrendererwidget.h
459461
raster/qgspalettedrendererwidget.h
@@ -648,6 +650,7 @@ SET(QGIS_GUI_HDRS
648650
qgsuserinputdockwidget.h
649651
qgsvectorlayertools.h
650652
qgsvertexmarker.h
653+
qgsfiledownloader.h
651654

652655
attributetable/qgsfeaturemodel.h
653656

0 commit comments

Comments
 (0)