2013-05-19 17:44:57 +02:00
"""
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2013-06-08 22:10:07 +02:00
qgsplugininstallerinstallingdialog . py
Plugin Installer module
2013-05-19 17:44:57 +02:00
- - - - - - - - - - - - - - - - - - -
2013-06-08 22:10:07 +02:00
Date : June 2013
2013-05-19 17:44:57 +02:00
Copyright : ( C ) 2013 by Borys Jurgiel
Email : info at borysjurgiel dot pl
This module is based on former plugin_installer plugin :
Copyright ( C ) 2007 - 2008 Matthew Perry
Copyright ( C ) 2008 - 2013 Borys Jurgiel
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
"""
2024-06-22 13:37:53 +02:00
from pathlib import Path
from qgis . PyQt import uic
2016-04-22 10:38:48 +02:00
from qgis . PyQt . QtCore import QDir , QUrl , QFile , QCoreApplication
from qgis . PyQt . QtWidgets import QDialog
from qgis . PyQt . QtNetwork import QNetworkRequest , QNetworkReply
2013-05-19 17:44:57 +02:00
2019-01-25 11:00:50 +10:00
from qgis . core import (
QgsNetworkAccessManager ,
QgsApplication ,
QgsNetworkRequestParameters ,
2024-11-29 14:26:30 +01:00
)
2023-11-24 07:44:47 +10:00
from qgis . utils import HOME_PLUGIN_PATH
2013-05-19 17:44:57 +02:00
2016-03-21 05:04:29 +01:00
from . installer_data import removeDir , repositories
from . unzip import unzip
2013-05-19 17:44:57 +02:00
2024-06-22 13:37:53 +02:00
Ui_QgsPluginInstallerInstallingDialogBase , _ = uic . loadUiType (
Path ( __file__ ) . parent / " qgsplugininstallerinstallingbase.ui "
)
2013-05-19 17:44:57 +02:00
class QgsPluginInstallerInstallingDialog (
QDialog , Ui_QgsPluginInstallerInstallingDialogBase
) :
2015-08-22 14:29:41 +02:00
# ----------------------------------------- #
2020-03-04 18:38:42 +01:00
def __init__ ( self , parent , plugin , stable = True ) :
2015-08-22 14:29:41 +02:00
QDialog . __init__ ( self , parent )
self . setupUi ( self )
self . plugin = plugin
self . mResult = " "
self . progressBar . setRange ( 0 , 0 )
self . progressBar . setFormat ( " % p % " )
self . labelName . setText ( plugin [ " name " ] )
self . buttonBox . clicked . connect ( self . abort )
2020-03-04 18:38:42 +01:00
self . url = QUrl (
plugin [ " download_url_stable " ]
if stable
else plugin [ " download_url_experimental " ]
)
2017-12-11 21:02:59 +01:00
self . redirectionCounter = 0
2015-08-22 14:29:41 +02:00
fileName = plugin [ " filename " ]
tmpDir = QDir . tempPath ( )
tmpPath = QDir . cleanPath ( tmpDir + " / " + fileName )
self . file = QFile ( tmpPath )
2017-12-11 21:02:59 +01:00
self . requestDownloading ( )
def requestDownloading ( self ) :
self . request = QNetworkRequest ( self . url )
2024-01-19 12:51:10 +10:00
self . request . setAttribute (
QNetworkRequest . Attribute (
QgsNetworkRequestParameters . RequestAttributes . AttributeInitiatorClass
) ,
" QgsPluginInstallerInstallingDialog " ,
)
2017-12-11 21:02:59 +01:00
authcfg = repositories . all ( ) [ self . plugin [ " zip_repository " ] ] [ " authcfg " ]
2016-09-21 18:24:26 +02:00
if authcfg and isinstance ( authcfg , str ) :
2017-11-07 08:56:20 +01:00
if not QgsApplication . authManager ( ) . updateNetworkRequest (
2016-02-26 11:54:08 +02:00
self . request , authcfg . strip ( )
) :
self . mResult = self . tr (
" Update of network request with authentication "
" credentials FAILED for configuration ' {0} ' "
) . format ( authcfg )
self . request = None
if self . request is not None :
self . reply = QgsNetworkAccessManager . instance ( ) . get ( self . request )
self . reply . downloadProgress . connect ( self . readProgress )
self . reply . finished . connect ( self . requestFinished )
self . stateChanged ( 4 )
2024-01-21 21:04:15 +10:00
def exec ( self ) :
2016-02-26 11:54:08 +02:00
if self . request is None :
2024-01-19 12:51:10 +10:00
return QDialog . DialogCode . Rejected
2016-02-26 11:54:08 +02:00
2024-01-21 21:04:15 +10:00
QDialog . exec ( self )
2015-08-22 14:29:41 +02:00
# ----------------------------------------- #
def result ( self ) :
return self . mResult
# ----------------------------------------- #
def stateChanged ( self , state ) :
2018-02-15 22:30:52 +01:00
messages = [
QCoreApplication . translate (
" QgsPluginInstallerInstallingDialog " , " Installing… "
) ,
QCoreApplication . translate (
" QgsPluginInstallerInstallingDialog " , " Resolving host name… "
) ,
QCoreApplication . translate (
" QgsPluginInstallerInstallingDialog " , " Connecting… "
) ,
QCoreApplication . translate (
" QgsPluginInstallerInstallingDialog " , " Host connected. Sending request… "
) ,
QCoreApplication . translate (
" QgsPluginInstallerInstallingDialog " , " Downloading data… "
) ,
self . tr ( " Idle " ) ,
QCoreApplication . translate (
" QgsPluginInstallerInstallingDialog " , " Closing connection… "
) ,
self . tr ( " Error " ) ,
]
2015-08-22 14:29:41 +02:00
self . labelState . setText ( messages [ state ] )
# ----------------------------------------- #
def readProgress ( self , done , total ) :
if total > 0 :
self . progressBar . setMaximum ( total )
self . progressBar . setValue ( done )
# ----------------------------------------- #
def requestFinished ( self ) :
reply = self . sender ( )
self . buttonBox . setEnabled ( False )
2024-01-19 12:51:10 +10:00
if reply . error ( ) != QNetworkReply . NetworkError . NoError :
2015-08-22 14:29:41 +02:00
self . mResult = reply . errorString ( )
2024-01-19 12:51:10 +10:00
if reply . error ( ) == QNetworkReply . NetworkError . OperationCanceledError :
2017-01-16 22:27:14 +01:00
self . mResult + = " <br/><br/> " + QCoreApplication . translate (
" QgsPluginInstaller " ,
" If you haven ' t canceled the download manually, it might be caused by a timeout. In this case consider increasing the connection timeout value in QGIS options. " ,
)
2015-08-22 14:29:41 +02:00
self . reject ( )
reply . deleteLater ( )
return
2024-01-19 12:51:10 +10:00
elif reply . attribute ( QNetworkRequest . Attribute . HttpStatusCodeAttribute ) in (
301 ,
302 ,
) :
redirectionUrl = reply . attribute (
QNetworkRequest . Attribute . RedirectionTargetAttribute
)
2017-12-11 21:02:59 +01:00
self . redirectionCounter + = 1
if self . redirectionCounter > 4 :
self . mResult = QCoreApplication . translate (
" QgsPluginInstaller " , " Too many redirections "
)
self . reject ( )
reply . deleteLater ( )
return
else :
if redirectionUrl . isRelative ( ) :
redirectionUrl = reply . url ( ) . resolved ( redirectionUrl )
# Fire a new request and exit immediately in order to quietly destroy the old one
self . url = redirectionUrl
self . requestDownloading ( )
reply . deleteLater ( )
return
2024-01-22 09:42:23 +10:00
self . file . open ( QFile . OpenModeFlag . WriteOnly )
2015-08-22 14:29:41 +02:00
self . file . write ( reply . readAll ( ) )
self . file . close ( )
self . stateChanged ( 0 )
reply . deleteLater ( )
2023-11-24 07:44:47 +10:00
pluginDir = HOME_PLUGIN_PATH
2015-08-22 14:29:41 +02:00
tmpPath = self . file . fileName ( )
# make sure that the parent directory exists
if not QDir ( pluginDir ) . exists ( ) :
QDir ( ) . mkpath ( pluginDir )
# if the target directory already exists as a link, remove the link without resolving:
2016-09-21 18:24:26 +02:00
QFile ( pluginDir + str ( QDir . separator ( ) ) + self . plugin [ " id " ] ) . remove ( )
2015-08-22 14:29:41 +02:00
try :
2016-09-21 18:24:26 +02:00
unzip (
str ( tmpPath ) , str ( pluginDir )
) # test extract. If fails, then exception will be raised and no removing occurs
2015-08-22 14:29:41 +02:00
# removing old plugin files if exist
2016-03-21 05:04:29 +01:00
removeDir (
QDir . cleanPath ( pluginDir + " / " + self . plugin [ " id " ] )
) # remove old plugin if exists
2016-09-21 18:24:26 +02:00
unzip ( str ( tmpPath ) , str ( pluginDir ) ) # final extract.
2015-08-22 14:29:41 +02:00
except :
self . mResult = (
self . tr (
" Failed to unzip the plugin package. Probably it ' s broken or missing from the repository. You may also want to make sure that you have write permission to the plugin directory: "
)
+ " \n "
+ pluginDir
2024-11-29 14:26:30 +01:00
)
2015-08-22 14:29:41 +02:00
self . reject ( )
return
try :
# cleaning: removing the temporary zip file
QFile ( tmpPath ) . remove ( )
except :
pass
self . close ( )
# ----------------------------------------- #
def abort ( self ) :
if self . reply . isRunning ( ) :
self . reply . finished . disconnect ( )
self . reply . abort ( )
del self . reply
self . mResult = self . tr ( " Aborted by user " )
self . reject ( )