11# -*- coding: utf-8 -*-
22"""
33Copyright (C) 2007-2008 Matthew Perry
4- Copyright (C) 2008 Borys Jurgiel
4+ Copyright (C) 2008-2009 Borys Jurgiel
55
66/***************************************************************************
77 * *
2020from qgis .core import *
2121from unzip import unzip
2222from version_compare import compareVersions , normalizeVersion
23-
23+ import sys
2424
2525"""
2626Data structure:
@@ -84,7 +84,7 @@ def setIface(qgisIface):
8484 ("Martin Dobias' Sandbox" , "http://mapserver.sk/~wonder/qgis/plugins-sandbox.xml" , "" ),
8585 ("Aaron Racicot's Repository" , "http://qgisplugins.z-pulley.com" , "" ),
8686 ("Barry Rowlingson's Repository" , "http://www.maths.lancs.ac.uk/~rowlings/Qgis/Plugins/plugins.xml" , "" ),
87- ("GIS-Lab Repository" , "http://gis-lab.info/programs/qgis/qgis-repo.xml" , "" )]
87+ ("GIS-Lab Repository" , "http://gis-lab.info/programs/qgis/qgis-repo.xml" , "" )]
8888
8989
9090
@@ -245,11 +245,17 @@ def allUnavailable(self):
245245
246246
247247 # ----------------------------------------- #
248- def setRepositoryData (self ,reposName , key , value ):
248+ def setRepositoryData (self , reposName , key , value ):
249249 """ write data to the mRepositories dict """
250250 self .mRepositories [reposName ][key ] = value
251251
252252
253+ # ----------------------------------------- #
254+ def remove (self , reposName ):
255+ """ remove given item from the mRepositories dict """
256+ del self .mRepositories [reposName ]
257+
258+
253259 # ----------------------------------------- #
254260 def rename (self , oldName , newName ):
255261 """ rename repository key """
@@ -284,7 +290,7 @@ def checkingOnStartInterval(self):
284290 interval = 0
285291 for j in [1 ,3 ,7 ,14 ,30 ]:
286292 if i >= j :
287- interval = j
293+ interval = j
288294 return interval
289295
290296
@@ -414,8 +420,7 @@ def xmlDownloaded(self,nr,state):
414420 experimental = False
415421 if pluginNodes .item (i ).firstChildElement ("experimental" ).text ().simplified ().toUpper () in ["TRUE" ,"YES" ]:
416422 experimental = True
417- plugin = {}
418- plugin [name ] = {
423+ plugin = {
419424 "name" : pluginNodes .item (i ).toElement ().attribute ("name" ),
420425 "version_avail" : pluginNodes .item (i ).toElement ().attribute ("version" ),
421426 "desc_repo" : pluginNodes .item (i ).firstChildElement ("description" ).text ().simplified (),
@@ -440,8 +445,8 @@ def xmlDownloaded(self,nr,state):
440445 #if compatible, add the plugin to the list
441446 if compareVersions (QGIS_VER , qgisMinimumVersion ) < 2 and compareVersions (qgisMaximumVersion , QGIS_VER ) < 2 :
442447 if QGIS_VER [0 ]== qgisMinimumVersion [0 ] or name == "plugin_installer" or (qgisMinimumVersion != "0" and qgisMaximumVersion != "2" ):
443- plugins . addPlugin ( plugin )
444- plugins .workarounds ( )
448+ #add the plugin to the cache
449+ plugins .addFromRepository ( plugin )
445450 self .mRepositories [reposName ]["state" ] = 2
446451 else :
447452 #print "Repository parsing error"
@@ -452,7 +457,7 @@ def xmlDownloaded(self,nr,state):
452457
453458 # is the checking done?
454459 if not self .fetchingInProgress ():
455- plugins .getAllInstalled ()
460+ plugins .rebuild ()
456461 self .saveCheckingOnStartLastDate ()
457462 self .emit (SIGNAL ("checkingDone()" ))
458463# --- /class Repositories ---------------------------------------------------------------- #
@@ -467,7 +472,10 @@ class Plugins(QObject):
467472 # ----------------------------------------- #
468473 def __init__ (self ):
469474 QObject .__init__ (self )
470- self .mPlugins = {}
475+ self .mPlugins = {} # the dict of plugins (dicts)
476+ self .repoCache = {} # the dict of lists of plugins (dicts)
477+ self .localCache = {} # the dict of plugins (dicts)
478+ self .obsoletePlugins = [] # the list of outdated 'user' plugins masking newer 'system' ones
471479
472480
473481 # ----------------------------------------- #
@@ -486,37 +494,39 @@ def keyByUrl(self, name):
486494
487495
488496 # ----------------------------------------- #
489- def setPluginData (self , pluginName , key , value ):
490- """ write data to the mPlugins dict """
491- self .mPlugins [pluginName ][key ] = value
497+ def addInstalled (self , plugin ):
498+ """ add given plugin to the localCache """
499+ key = plugin ["localdir" ]
500+ self .localCache [key ] = plugin
492501
493502
494503 # ----------------------------------------- #
495- def clear (self ):
496- """ clear the plugins dict"""
497- self .mPlugins = {}
504+ def addFromRepository (self , plugin ):
505+ """ add given plugin to the repoCache """
506+ repo = plugin ["repository" ]
507+ try :
508+ self .repoCache [repo ] += [plugin ]
509+ except :
510+ self .repoCache [repo ] = [plugin ]
498511
499512
500513 # ----------------------------------------- #
501- def addPlugin (self , plugins ):
502- """ add a plugin (first from given) to the mPlugins dict """
503- key = plugins .keys ()[0 ]
504- plugin = plugins [key ]
505- plugin ["version_avail" ] = normalizeVersion (plugin ["version_avail" ])
506- plugin ["version_inst" ] = normalizeVersion (plugin ["version_inst" ])
507- if not self .mPlugins .has_key (key ) or compareVersions (self .mPlugins [key ]["version_avail" ],plugin ["version_avail" ]) == 2 :
508- self .mPlugins [key ] = plugin # add the plugin if not present yet or if is newer than existing one
514+ def removeInstalledPlugin (self , key ):
515+ """ remove given plugin from the localCache """
516+ if self .localCache .has_key (key ):
517+ del self .localCache [key ]
509518
510519
511520 # ----------------------------------------- #
512- def remove (self , key ):
513- """ remove given plugin from the mPlugins dict """
514- del self .mPlugins [key ]
521+ def removeRepository (self , repo ):
522+ """ remove whole repository from the repoCache """
523+ if self .repoCache .has_key (repo ):
524+ del self .repoCache [repo ]
515525
516526
517527 # ----------------------------------------- #
518- def updatePlugin (self , key , readOnly ):
519- """ The mPlugins should contain available plugins first. Now, add installed one (add when not present, update if present) """
528+ def getInstalledPlugin (self , key , readOnly ):
529+ """ get the metadata of an installed plugin """
520530 if readOnly :
521531 path = QgsApplication .pkgDataPath ()
522532 else :
@@ -532,7 +542,8 @@ def updatePlugin(self, key, readOnly):
532542 error = ""
533543 errorDetails = ""
534544 try :
535- exec ("import " + key )
545+ exec ("import %s" % key )
546+ exec ("reload (%s)" % key )
536547 try :
537548 exec ("nam = %s.name()" % key )
538549 except :
@@ -589,73 +600,107 @@ def updatePlugin(self, key, readOnly):
589600 "url" : path ,
590601 "experimental" : False ,
591602 "filename" : "" ,
592- "status" : "" ,
603+ "status" : "orphan " ,
593604 "error" : error ,
594605 "error_details" : errorDetails ,
595606 "repository" : "" ,
596607 "localdir" : key ,
597608 "read-only" : readOnly }
598-
599- if not self .mPlugins .has_key (key ):
600- self .mPlugins [key ] = plugin # just add a new plugin
601- else :
602- self .mPlugins [key ]["localdir" ] = plugin ["localdir" ]
603- self .mPlugins [key ]["read-only" ] = plugin ["read-only" ]
604- self .mPlugins [key ]["error" ] = plugin ["error" ]
605- self .mPlugins [key ]["error_details" ] = plugin ["error_details" ]
606- if plugin ["name" ] and plugin ["name" ] != key :
607- self .mPlugins [key ]["name" ] = plugin ["name" ] # local name has higher priority
608- self .mPlugins [key ]["version_inst" ] = plugin ["version_inst" ]
609- self .mPlugins [key ]["desc_local" ] = plugin ["desc_local" ]
610- # set status
611- #
612- # installed available status
613- # ---------------------------------------
614- # none any "not installed" (will be later checked if is "new")
615- # any none "orphan"
616- # same same "installed"
617- # less greater "upgradeable"
618- # greater less "newer"
619- if not self .mPlugins [key ]["version_avail" ]:
620- self .mPlugins [key ]["status" ] = "orphan"
621- elif self .mPlugins [key ]["error" ] in ["broken" ,"dependent" ]:
622- self .mPlugins [key ]["status" ] = "installed"
623- elif not self .mPlugins [key ]["version_inst" ]:
624- self .mPlugins [key ]["status" ] = "not installed"
625- elif compareVersions (self .mPlugins [key ]["version_avail" ],self .mPlugins [key ]["version_inst" ]) == 0 :
626- self .mPlugins [key ]["status" ] = "installed"
627- elif compareVersions (self .mPlugins [key ]["version_avail" ],self .mPlugins [key ]["version_inst" ]) == 1 :
628- self .mPlugins [key ]["status" ] = "upgradeable"
629- else :
630- self .mPlugins [key ]["status" ] = "newer"
609+ return plugin
631610
632611
633612 # ----------------------------------------- #
634613 def getAllInstalled (self ):
635- """ update the mPlugins dict with alredy installed plugins """
614+ """ Build the localCache """
615+ self .localCache = {}
636616 # first, try to add the read-only plugins...
617+ pluginsPath = unicode (QDir .convertSeparators (QDir .cleanPath (QgsApplication .pkgDataPath () + "/python/plugins" )))
618+ # temporarily add the system path as the first element to force loading the read-only plugins, even if masked by user ones.
619+ sys .path = [pluginsPath ] + sys .path
637620 try :
638- pluginDir = QDir .cleanPath (unicode (QgsApplication .pkgDataPath ()) + "/python/plugins" )
639- pluginDir = QDir (pluginDir )
621+ pluginDir = QDir (pluginsPath )
640622 pluginDir .setFilter (QDir .AllDirs )
641623 for key in pluginDir .entryList ():
642624 key = unicode (key )
643625 if not key in ["." ,".." ]:
644- self .updatePlugin (key , True )
626+ self .localCache [ key ] = self . getInstalledPlugin (key , True )
645627 except :
646628 # return QCoreApplication.translate("QgsPluginInstaller","Couldn't open the system plugin directory")
647629 pass # it's not necessary to stop due to this error
630+ # remove the temporarily added path
631+ sys .path .remove (pluginsPath )
648632 # ...then try to add locally installed ones
649633 try :
650- pluginDir = QDir .cleanPath (unicode ( QgsApplication .qgisSettingsDirPath ()) + "/python/plugins" )
634+ pluginDir = QDir .convertSeparators ( QDir . cleanPath (QgsApplication .qgisSettingsDirPath () + "/python/plugins" ) )
651635 pluginDir = QDir (pluginDir )
652636 pluginDir .setFilter (QDir .AllDirs )
653637 except :
654638 return QCoreApplication .translate ("QgsPluginInstaller" ,"Couldn't open the local plugin directory" )
655639 for key in pluginDir .entryList ():
656640 key = unicode (key )
657641 if not key in ["." ,".." ]:
658- self .updatePlugin (key , False )
642+ plugin = self .getInstalledPlugin (key , False )
643+ if key in self .localCache .keys () and compareVersions (self .localCache [key ]["version_inst" ],plugin ["version_inst" ]) == 1 :
644+ # An obsolete plugin in the "user" location is masking a newer one in the "system" location!
645+ self .obsoletePlugins += [key ]
646+ self .localCache [key ] = plugin
647+
648+
649+ # ----------------------------------------- #
650+ def rebuild (self ):
651+ """ build or rebuild the mPlugins from the caches """
652+ self .mPlugins = {}
653+ for i in self .localCache .keys ():
654+ self .mPlugins [i ] = self .localCache [i ].copy ()
655+ settings = QSettings ()
656+ (allowed , ok ) = settings .value (settingsGroup + "/allowedPluginType" , QVariant (2 )).toInt ()
657+ for i in self .repoCache .values ():
658+ for plugin in i :
659+ key = plugin ["localdir" ]
660+ # check if the plugin is allowed and if there isn't any better one added already.
661+ if (allowed != 1 or plugin ["repository" ] == officialRepo [0 ]) and (allowed == 3 or not plugin ["experimental" ]) \
662+ and not (self .mPlugins .has_key (key ) and self .mPlugins [key ]["version_avail" ] and compareVersions (self .mPlugins [key ]["version_avail" ], plugin ["version_avail" ]) < 2 ):
663+ # The mPlugins doct contains now locally installed plugins.
664+ # Now, add the available one if not present yet or update it if present already.
665+ if not self .mPlugins .has_key (key ):
666+ self .mPlugins [key ] = plugin # just add a new plugin
667+ else :
668+ self .mPlugins [key ]["version_avail" ] = plugin ["version_avail" ]
669+ self .mPlugins [key ]["desc_repo" ] = plugin ["desc_repo" ]
670+ self .mPlugins [key ]["filename" ] = plugin ["filename" ]
671+ self .mPlugins [key ]["repository" ] = plugin ["repository" ]
672+ self .mPlugins [key ]["experimental" ] = plugin ["experimental" ]
673+ # use remote name if local one is not available
674+ if self .mPlugins [key ]["name" ] == key and plugin ["name" ]:
675+ self .mPlugins [key ]["name" ] = plugin ["name" ]
676+ # those metadata has higher priority for their remote instances:
677+ if plugin ["author" ]:
678+ self .mPlugins [key ]["author" ] = plugin ["author" ]
679+ if plugin ["homepage" ]:
680+ self .mPlugins [key ]["homepage" ] = plugin ["homepage" ]
681+ if plugin ["url" ]:
682+ self .mPlugins [key ]["url" ] = plugin ["url" ]
683+ # set status
684+ #
685+ # installed available status
686+ # ---------------------------------------
687+ # none any "not installed" (will be later checked if is "new")
688+ # any none "orphan"
689+ # same same "installed"
690+ # less greater "upgradeable"
691+ # greater less "newer"
692+ if not self .mPlugins [key ]["version_avail" ]:
693+ self .mPlugins [key ]["status" ] = "orphan"
694+ elif self .mPlugins [key ]["error" ] in ["broken" ,"dependent" ]:
695+ self .mPlugins [key ]["status" ] = "installed"
696+ elif not self .mPlugins [key ]["version_inst" ]:
697+ self .mPlugins [key ]["status" ] = "not installed"
698+ elif compareVersions (self .mPlugins [key ]["version_avail" ],self .mPlugins [key ]["version_inst" ]) == 0 :
699+ self .mPlugins [key ]["status" ] = "installed"
700+ elif compareVersions (self .mPlugins [key ]["version_avail" ],self .mPlugins [key ]["version_inst" ]) == 1 :
701+ self .mPlugins [key ]["status" ] = "upgradeable"
702+ else :
703+ self .mPlugins [key ]["status" ] = "newer"
659704
660705
661706 # ----------------------------------------- #
@@ -689,12 +734,6 @@ def isThereAnythingNew(self):
689734 return False
690735
691736
692- # ----------------------------------------- #
693- def workarounds (self ):
694- """ workarounds for particular plugins with wrong metadata """
695- if self .mPlugins .has_key ("select" ) and self .mPlugins ["select" ]["version_avail" ] == "0.1" :
696- self .mPlugins ["select" ]["version_avail" ] = "0.2"
697-
698737# --- /class Plugins --------------------------------------------------------------------- #
699738
700739
0 commit comments