Expand Up
@@ -34,60 +34,60 @@
"""
Data structure:
mRepositories = dict of dicts: {repoName : {"url" QString ,
mRepositories = dict of dicts: {repoName : {"url" unicode ,
"enabled" bool,
"valid" bool,
"QPHttp" QPHttp,
"Relay" Relay, # Relay object for transmitting signals from QPHttp with adding the repoName information
"xmlData" QBuffer,
"state" int, (0 - disabled, 1-loading, 2-loaded ok, 3-error (to be retried), 4-rejected)
"error" QString }}
"error" unicode }}
mPlugins = dict of dicts {id : {
"id" QString # module name
"name" QString , #
"description" QString , #
"category" QString , # will be removed?
"tags" QString , # comma separated, spaces allowed
"changelog" QString , # may be multiline
"author_name" QString , #
"author_email" QString , #
"homepage" QString , # url to a tracker site
"tracker" QString , # url to a tracker site
"code_repository" QString , # url to a repository with code
"version_installed" QString , #
"library" QString , # full path to the installed library/Python module
"icon" QString , # path to the first:(INSTALLED | AVAILABLE) icon
"id" unicode # module name
"name" unicode , #
"description" unicode , #
"category" unicode , # will be removed?
"tags" unicode , # comma separated, spaces allowed
"changelog" unicode , # may be multiline
"author_name" unicode , #
"author_email" unicode , #
"homepage" unicode , # url to a tracker site
"tracker" unicode , # url to a tracker site
"code_repository" unicode , # url to a repository with code
"version_installed" unicode , #
"library" unicode , # full path to the installed library/Python module
"icon" unicode , # path to the first:(INSTALLED | AVAILABLE) icon
"pythonic" const bool=True
"readonly" boolean, # True if core plugin
"installed" boolean, # True if installed
"available" boolean, # True if available in repositories
"status" QString , # ( not installed | new ) | ( installed | upgradeable | orphan | newer )
"error" QString , # NULL | broken | incompatible | dependent
"error_details" QString , # more details
"status" unicode , # ( not installed | new ) | ( installed | upgradeable | orphan | newer )
"error" unicode , # NULL | broken | incompatible | dependent
"error_details" unicode , # more details
"experimental" boolean, # choosen version: experimental or stable?
"version_available" QString , # choosen version: version
"zip_repository" QString , # choosen version: the remote repository id
"download_url" QString , # choosen version: url for downloading
"filename" QString , # choosen version: the zip file to be downloaded
"downloads" QString , # choosen version: number of dowloads
"average_vote" QString , # choosen version: average vote
"rating_votes" QString , # choosen version: number of votes
"stable:version_available" QString , # stable version found in repositories
"stable:download_source" QString ,
"stable:download_url" QString ,
"stable:filename" QString ,
"stable:downloads" QString ,
"stable:average_vote" QString ,
"stable:rating_votes" QString ,
"experimental:version_available" QString , # experimental version found in repositories
"experimental:download_source" QString ,
"experimental:download_url" QString ,
"experimental:filename" QString ,
"experimental:downloads" QString ,
"experimental:average_vote" QString ,
"experimental:rating_votes" QString
"version_available" unicode , # choosen version: version
"zip_repository" unicode , # choosen version: the remote repository id
"download_url" unicode , # choosen version: url for downloading
"filename" unicode , # choosen version: the zip file to be downloaded
"downloads" unicode , # choosen version: number of dowloads
"average_vote" unicode , # choosen version: average vote
"rating_votes" unicode , # choosen version: number of votes
"stable:version_available" unicode , # stable version found in repositories
"stable:download_source" unicode ,
"stable:download_url" unicode ,
"stable:filename" unicode ,
"stable:downloads" unicode ,
"stable:average_vote" unicode ,
"stable:rating_votes" unicode ,
"experimental:version_available" unicode , # experimental version found in repositories
"experimental:download_source" unicode ,
"experimental:download_url" unicode ,
"experimental:filename" unicode ,
"experimental:downloads" unicode ,
"experimental:average_vote" unicode ,
"experimental:rating_votes" unicode
}}
"""
Expand Down
Expand Up
@@ -126,7 +126,7 @@
# --- common functions ------------------------------------------------------------------- #
def removeDir (path ):
result = QString ()
result = ""
if not QFile (path ).exists ():
result = QCoreApplication .translate ("QgsPluginInstaller" ,"Nothing to remove! Plugin directory doesn't exist:" )+ "\n " + path
elif QFile (path ).remove (): # if it is only link, just remove it without resolving.
Expand Down
Expand Up
@@ -164,21 +164,21 @@ def __init__(self,*args):
QHttp .__init__ (self ,* args )
settings = QSettings ()
settings .beginGroup ("proxy" )
if settings .value ("/proxyEnabled" ). toBool ( ):
if settings .value ("/proxyEnabled" , False , type = bool ):
self .proxy = QNetworkProxy ()
proxyType = settings .value ( "/proxyType" , QVariant ( 0 )). toString ( )
if len (args )> 0 and settings .value ("/proxyExcludedUrls" ). toString ( ).contains (args [0 ]):
proxyType = settings .value ( "/proxyType" , "0" , type = unicode )
if len (args )> 0 and settings .value ("/proxyExcludedUrls" , "" , type = unicode ).contains (args [0 ]):
proxyType = "NoProxy"
if proxyType in ["1" ,"Socks5Proxy" ]: self .proxy .setType (QNetworkProxy .Socks5Proxy )
elif proxyType in ["2" ,"NoProxy" ]: self .proxy .setType (QNetworkProxy .NoProxy )
elif proxyType in ["3" ,"HttpProxy" ]: self .proxy .setType (QNetworkProxy .HttpProxy )
elif proxyType in ["4" ,"HttpCachingProxy" ] and QT_VERSION >= 0X040400 : self .proxy .setType (QNetworkProxy .HttpCachingProxy )
elif proxyType in ["5" ,"FtpCachingProxy" ] and QT_VERSION >= 0X040400 : self .proxy .setType (QNetworkProxy .FtpCachingProxy )
else : self .proxy .setType (QNetworkProxy .DefaultProxy )
self .proxy .setHostName (settings .value ("/proxyHost" ). toString ( ))
self .proxy .setPort (settings .value ("/proxyPort" ). toUInt ()[ 0 ] )
self .proxy .setUser (settings .value ("/proxyUser" ). toString ( ))
self .proxy .setPassword (settings .value ("/proxyPassword" ). toString ( ))
self .proxy .setHostName (settings .value ("/proxyHost" , "" , type = unicode ))
self .proxy .setPort (settings .value ("/proxyPort" , 0 , type = int ) )
self .proxy .setUser (settings .value ("/proxyUser" , "" , type = unicode ))
self .proxy .setPassword (settings .value ("/proxyPassword" , "" , type = unicode ))
self .setProxy (self .proxy )
settings .endGroup ()
return None
Expand All
@@ -192,12 +192,14 @@ def __init__(self,*args):
class Relay (QObject ):
""" Relay object for transmitting signals from QPHttp with adding the repoName information """
# ----------------------------------------- #
anythingChanged = pyqtSignal ( unicode , int , int )
def __init__ (self , key ):
QObject .__init__ (self )
self .key = key
def stateChanged (self , state ):
self .emit (SIGNAL ( "anythingChanged(QString, int, int)" ), self .key , state , 0 )
self .anythingChanged . emit ( self .key , state , 0 )
# ----------------------------------------- #
def dataReadProgress (self , done , total ):
Expand All
@@ -206,7 +208,8 @@ def dataReadProgress(self, done, total):
progress = int (float (done )/ float (total )* 100 )
else :
progress = 0
self .emit (SIGNAL ("anythingChanged(QString, int, int)" ), self .key , state , progress )
self .anythingChanged .emit ( self .key , state , progress )
# --- /class Relay ---------------------------------------------------------------------- #
Expand All
@@ -217,6 +220,11 @@ def dataReadProgress(self, done, total):
class Repositories (QObject ):
""" A dict-like class for handling repositories data """
# ----------------------------------------- #
anythingChanged = pyqtSignal ( unicode , int , int )
repositoryFetched = pyqtSignal ( unicode )
checkingDone = pyqtSignal ()
def __init__ (self ):
QObject .__init__ (self )
self .mRepositories = {}
Expand Down
Expand Up
@@ -274,23 +282,22 @@ def rename(self, oldName, newName):
def checkingOnStart (self ):
""" return true if checking for news and updates is enabled """
settings = QSettings ()
return settings .value (settingsGroup + "/checkOnStart" , QVariant ( False )). toBool ( )
return settings .value (settingsGroup + "/checkOnStart" , False , type = bool )
# ----------------------------------------- #
def setCheckingOnStart (self , state ):
""" set state of checking for news and updates """
settings = QSettings ()
settings .setValue (settingsGroup + "/checkOnStart" , QVariant ( state ) )
settings .setValue (settingsGroup + "/checkOnStart" , state )
# ----------------------------------------- #
def checkingOnStartInterval (self ):
""" return checking for news and updates interval """
settings = QSettings ()
(i , ok ) = settings .value (settingsGroup + "/checkOnStartInterval" ).toInt ()
if i < 0 or not ok :
i = 1
i = settings .value (settingsGroup + "/checkOnStartInterval" , 1 , type = int )
if i < 0 : i = 1
# allowed values: 0,1,3,7,14,30 days
interval = 0
for j in [1 ,3 ,7 ,14 ,30 ]:
Expand All
@@ -303,14 +310,14 @@ def checkingOnStartInterval(self):
def setCheckingOnStartInterval (self , interval ):
""" set checking for news and updates interval """
settings = QSettings ()
settings .setValue (settingsGroup + "/checkOnStartInterval" , QVariant ( interval ) )
settings .setValue (settingsGroup + "/checkOnStartInterval" , interval )
# ----------------------------------------- #
def saveCheckingOnStartLastDate (self ):
""" set today's date as the day of last checking """
settings = QSettings ()
settings .setValue (settingsGroup + "/checkOnStartLastDate" , QVariant ( QDate .currentDate () ))
settings .setValue (settingsGroup + "/checkOnStartLastDate" , QDate .currentDate ())
# ----------------------------------------- #
Expand All
@@ -335,25 +342,25 @@ def load(self):
# first, update repositories in QSettings if needed
officialRepoPresent = False
for key in settings .childGroups ():
url = settings .value (key + "/url" , QVariant ()). toString ( )
url = settings .value (key + "/url" , "" , type = unicode )
if url == officialRepo [1 ]:
officialRepoPresent = True
if url == officialRepo [2 ]:
settings .setValue (key + "/url" , QVariant ( officialRepo [1 ]) ) # correct a depreciated url
settings .setValue (key + "/url" , officialRepo [1 ]) # correct a depreciated url
officialRepoPresent = True
if not officialRepoPresent :
settings .setValue (officialRepo [0 ]+ "/url" , QVariant ( officialRepo [1 ]) )
settings .setValue (officialRepo [0 ]+ "/url" , officialRepo [1 ])
for key in settings .childGroups ():
self .mRepositories [key ] = {}
self .mRepositories [key ]["url" ] = settings .value (key + "/url" , QVariant ()). toString ( )
self .mRepositories [key ]["enabled" ] = settings .value (key + "/enabled" , QVariant ( True )). toBool ( )
self .mRepositories [key ]["valid" ] = settings .value (key + "/valid" , QVariant ( True )). toBool ( )
self .mRepositories [key ]["url" ] = settings .value (key + "/url" , "" , type = unicode )
self .mRepositories [key ]["enabled" ] = settings .value (key + "/enabled" , True , type = bool )
self .mRepositories [key ]["valid" ] = settings .value (key + "/valid" , True , type = bool )
self .mRepositories [key ]["QPHttp" ] = QPHttp ()
self .mRepositories [key ]["Relay" ] = Relay (key )
self .mRepositories [key ]["xmlData" ] = QBuffer ()
self .mRepositories [key ]["state" ] = 0
self .mRepositories [key ]["error" ] = QString ()
self .mRepositories [key ]["error" ] = ""
settings .endGroup ()
Expand All
@@ -362,17 +369,18 @@ def requestFetching(self,key):
""" start fetching the repository given by key """
self .mRepositories [key ]["state" ] = 1
url = QUrl (self .mRepositories [key ]["url" ])
path = QString (url .toPercentEncoding (url .path (), "!$&'()*+,;=:@/" ))
path = url .toPercentEncoding (url .path (), "!$&'()*+,;=:@/" )
path = unicode (path )
v = str (QGis .QGIS_VERSION_INT )
path += "?qgis=%d.%d" % ( int (v [0 ]), int (v [1 :3 ]) )
port = url .port ()
if port < 0 :
port = 80
self .mRepositories [key ]["QPHttp" ] = QPHttp (url .host (), port )
self .connect ( self . mRepositories [key ]["QPHttp" ], SIGNAL ( " requestFinished (int, bool)" ), self .xmlDownloaded )
self .connect ( self . mRepositories [key ]["QPHttp" ], SIGNAL ( " stateChanged ( int )" ), self .mRepositories [key ]["Relay" ].stateChanged )
self .connect ( self . mRepositories [key ]["QPHttp" ], SIGNAL ( " dataReadProgress ( int , int )" ), self .mRepositories [key ]["Relay" ].dataReadProgress )
self .connect (self .mRepositories [key ]["Relay" ], SIGNAL ("anythingChanged(QString , int, int)" ), self , SIGNAL ("anythingChanged (QString , int, int)" ))
self .mRepositories [key ]["QPHttp" ]. requestFinished . connect ( self .xmlDownloaded )
self .mRepositories [key ]["QPHttp" ]. stateChanged . connect ( self .mRepositories [key ]["Relay" ].stateChanged )
self .mRepositories [key ]["QPHttp" ]. dataReadProgress . connect ( self .mRepositories [key ]["Relay" ].dataReadProgress )
self .connect (self .mRepositories [key ]["Relay" ], SIGNAL ("anythingChanged(unicode , int, int)" ), self , SIGNAL ("anythingChanged (unicode , int, int)" ))
i = self .mRepositories [key ]["QPHttp" ].get (path , self .mRepositories [key ]["xmlData" ])
self .httpId [i ] = key
Expand Down
Expand Up
@@ -409,35 +417,34 @@ def xmlDownloaded(self,nr,state):
pluginNodes = reposXML .elementsByTagName ("pyqgis_plugin" )
if pluginNodes .size ():
for i in range (pluginNodes .size ()):
fileName = pluginNodes .item (i ).firstChildElement ("file_name" ).text ().simplified ()
fileName = pluginNodes .item (i ).firstChildElement ("file_name" ).text ().strip ()
if not fileName :
fileName = QFileInfo (pluginNodes .item (i ).firstChildElement ("download_url" ).text ().trimmed ().split ("?" )[0 ]).fileName ()
name = fileName .section ("." , 0 , 0 )
name = unicode (name )
fileName = QFileInfo (pluginNodes .item (i ).firstChildElement ("download_url" ).text ().strip ().split ("?" )[0 ]).fileName ()
name = fileName .partition ("." )[0 ]
experimental = False
if pluginNodes .item (i ).firstChildElement ("experimental" ).text ().simplified ().toUpper () in ["TRUE" ,"YES" ]:
if pluginNodes .item (i ).firstChildElement ("experimental" ).text ().strip ().upper () in ["TRUE" ,"YES" ]:
experimental = True
icon = pluginNodes .item (i ).firstChildElement ("icon" ).text ().simplified ()
if icon and not icon .startsWith ("http" ):
icon = pluginNodes .item (i ).firstChildElement ("icon" ).text ().strip ()
if icon and not icon .startswith ("http" ):
icon = "http://%s/%s" % ( QUrl (self .mRepositories [reposName ]["url" ]).host () , icon )
plugin = {
"id" : name ,
"name" : pluginNodes .item (i ).toElement ().attribute ("name" ),
"version_available" : pluginNodes .item (i ).toElement ().attribute ("version" ),
"description" : pluginNodes .item (i ).firstChildElement ("description" ).text ().simplified (),
"author_name" : pluginNodes .item (i ).firstChildElement ("author_name" ).text ().simplified (),
"homepage" : pluginNodes .item (i ).firstChildElement ("homepage" ).text ().simplified (),
"download_url" : pluginNodes .item (i ).firstChildElement ("download_url" ).text ().simplified (),
"category" : pluginNodes .item (i ).firstChildElement ("category" ).text ().simplified (),
"tags" : pluginNodes .item (i ).firstChildElement ("tags" ).text ().simplified (),
"changelog" : pluginNodes .item (i ).firstChildElement ("changelog" ).text ().simplified (),
"author_email" : pluginNodes .item (i ).firstChildElement ("author_email" ).text ().simplified (),
"tracker" : pluginNodes .item (i ).firstChildElement ("tracker" ).text ().simplified (),
"code_repository" : pluginNodes .item (i ).firstChildElement ("repository" ).text ().simplified (),
"downloads" : pluginNodes .item (i ).firstChildElement ("downloads" ).text ().simplified (),
"average_vote" : pluginNodes .item (i ).firstChildElement ("average_vote" ).text ().simplified (),
"rating_votes" : pluginNodes .item (i ).firstChildElement ("rating_votes" ).text ().simplified (),
"description" : pluginNodes .item (i ).firstChildElement ("description" ).text ().strip (),
"author_name" : pluginNodes .item (i ).firstChildElement ("author_name" ).text ().strip (),
"homepage" : pluginNodes .item (i ).firstChildElement ("homepage" ).text ().strip (),
"download_url" : pluginNodes .item (i ).firstChildElement ("download_url" ).text ().strip (),
"category" : pluginNodes .item (i ).firstChildElement ("category" ).text ().strip (),
"tags" : pluginNodes .item (i ).firstChildElement ("tags" ).text ().strip (),
"changelog" : pluginNodes .item (i ).firstChildElement ("changelog" ).text ().strip (),
"author_email" : pluginNodes .item (i ).firstChildElement ("author_email" ).text ().strip (),
"tracker" : pluginNodes .item (i ).firstChildElement ("tracker" ).text ().strip (),
"code_repository" : pluginNodes .item (i ).firstChildElement ("repository" ).text ().strip (),
"downloads" : pluginNodes .item (i ).firstChildElement ("downloads" ).text ().strip (),
"average_vote" : pluginNodes .item (i ).firstChildElement ("average_vote" ).text ().strip (),
"rating_votes" : pluginNodes .item (i ).firstChildElement ("rating_votes" ).text ().strip (),
"icon" : icon ,
"experimental" : experimental ,
"filename" : fileName ,
Expand All
@@ -451,23 +458,23 @@ def xmlDownloaded(self,nr,state):
"library" : "" ,
"readonly" : False
}
qgisMinimumVersion = pluginNodes .item (i ).firstChildElement ("qgis_minimum_version" ).text ().simplified ()
qgisMinimumVersion = pluginNodes .item (i ).firstChildElement ("qgis_minimum_version" ).text ().strip ()
if not qgisMinimumVersion : qgisMinimumVersion = "2"
qgisMaximumVersion = pluginNodes .item (i ).firstChildElement ("qgis_maximum_version" ).text ().simplified ()
qgisMaximumVersion = pluginNodes .item (i ).firstChildElement ("qgis_maximum_version" ).text ().strip ()
if not qgisMaximumVersion : qgisMaximumVersion = qgisMinimumVersion [0 ] + ".99"
#if compatible, add the plugin to the list
if not pluginNodes .item (i ).firstChildElement ("disabled" ).text ().simplified ().toUpper () in ["TRUE" ,"YES" ]:
if not pluginNodes .item (i ).firstChildElement ("disabled" ).text ().strip ().upper () in ["TRUE" ,"YES" ]:
if compareVersions (QGis .QGIS_VERSION , qgisMinimumVersion ) < 2 and compareVersions (qgisMaximumVersion , QGis .QGIS_VERSION ) < 2 :
#add the plugin to the cache
plugins .addFromRepository (plugin )
# set state=2, even if the repo is empty
self .mRepositories [reposName ]["state" ] = 2
self .emit (SIGNAL ( "repositoryFetched(QString)" ), reposName )
self .repositoryFetched . emit ( reposName )
# is the checking done?
if not self .fetchingInProgress ():
self .emit (SIGNAL ( "checkingDone()" ) )
self .checkingDone . emit ()
# --- /class Repositories ---------------------------------------------------------------- #
Expand Down
Expand Up
@@ -543,7 +550,7 @@ def pluginMetadata(fct):
result = qgis .utils .pluginMetadata (key , fct )
if result == "__error__" :
result = ""
return QString ( result )
return result
path = QDir .cleanPath ( QgsApplication .qgisSettingsDirPath () ) + "/python/plugins/" + key
if not QDir (path ).exists ():
Expand All
@@ -557,9 +564,9 @@ def pluginMetadata(fct):
version = normalizeVersion ( pluginMetadata ("version" ) )
if version :
qgisMinimumVersion = pluginMetadata ("qgisMinimumVersion" ).simplified ()
qgisMinimumVersion = pluginMetadata ("qgisMinimumVersion" ).strip ()
if not qgisMinimumVersion : qgisMinimumVersion = "0"
qgisMaximumVersion = pluginMetadata ("qgisMaximumVersion" ).simplified ()
qgisMaximumVersion = pluginMetadata ("qgisMaximumVersion" ).strip ()
if not qgisMaximumVersion : qgisMaximumVersion = qgisMinimumVersion [0 ] + ".999"
#if compatible, add the plugin to the list
if compareVersions (QGis .QGIS_VERSION , qgisMinimumVersion ) == 2 or compareVersions (qgisMaximumVersion , QGis .QGIS_VERSION ) == 2 :
Expand Down
Expand Up
@@ -608,7 +615,7 @@ def pluginMetadata(fct):
"version_installed" : version ,
"library" : path ,
"pythonic" : True ,
"experimental" : pluginMetadata ("experimental" ).simplified ().toUpper () in ["TRUE" ,"YES" ],
"experimental" : pluginMetadata ("experimental" ).strip ().upper () in ["TRUE" ,"YES" ],
"version_available" : "" ,
"zip_repository" : "" ,
"download_url" : path , # warning: local path as url!
Expand Down
Expand Up
@@ -669,7 +676,7 @@ def rebuild(self):
for i in self .localCache .keys ():
self .mPlugins [i ] = self .localCache [i ].copy ()
settings = QSettings ()
allowExperimental = settings .value (settingsGroup + "/allowExperimental" , QVariant ( False )). toBool ( )
allowExperimental = settings .value (settingsGroup + "/allowExperimental" , False , type = bool )
for i in self .repoCache .values ():
for plugin in i :
key = plugin ["id" ]
Expand Down
Expand Up
@@ -724,22 +731,22 @@ def rebuild(self):
def markNews (self ):
""" mark all new plugins as new """
settings = QSettings ()
seenPlugins = settings .value (seenPluginGroup , QVariant ( QStringList ( self .mPlugins .keys ()))). toStringList ( )
seenPlugins = settings .value (seenPluginGroup , self .mPlugins .keys (), type = unicode )
if len (seenPlugins ) > 0 :
for i in self .mPlugins .keys ():
if seenPlugins .count (QString ( i ) ) == 0 and self .mPlugins [i ]["status" ] == "not installed" :
if seenPlugins .count (i ) == 0 and self .mPlugins [i ]["status" ] == "not installed" :
self .mPlugins [i ]["status" ] = "new"
# ----------------------------------------- #
def updateSeenPluginsList (self ):
""" update the list of all seen plugins """
settings = QSettings ()
seenPlugins = settings .value (seenPluginGroup , QVariant ( QStringList ( self .mPlugins .keys ()))). toStringList ( )
seenPlugins = settings .value (seenPluginGroup , self .mPlugins .keys (), type = unicode )
for i in self .mPlugins .keys ():
if seenPlugins .count (QString ( i ) ) == 0 :
if seenPlugins .count (i ) == 0 :
seenPlugins += [i ]
settings .setValue (seenPluginGroup , QVariant ( QStringList ( seenPlugins )) )
settings .setValue (seenPluginGroup , seenPlugins )
# ----------------------------------------- #
Expand Down