1
1
# -*- coding: utf-8 -*-
2
2
"""
3
3
Copyright (C) 2007-2008 Matthew Perry
4
- Copyright (C) 2008 Borys Jurgiel
4
+ Copyright (C) 2008-2009 Borys Jurgiel
5
5
6
6
/***************************************************************************
7
7
* *
20
20
from qgis .core import *
21
21
from unzip import unzip
22
22
from version_compare import compareVersions , normalizeVersion
23
-
23
+ import sys
24
24
25
25
"""
26
26
Data structure:
@@ -84,7 +84,7 @@ def setIface(qgisIface):
84
84
("Martin Dobias' Sandbox" , "http://mapserver.sk/~wonder/qgis/plugins-sandbox.xml" , "" ),
85
85
("Aaron Racicot's Repository" , "http://qgisplugins.z-pulley.com" , "" ),
86
86
("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" , "" )]
88
88
89
89
90
90
@@ -245,11 +245,17 @@ def allUnavailable(self):
245
245
246
246
247
247
# ----------------------------------------- #
248
- def setRepositoryData (self ,reposName , key , value ):
248
+ def setRepositoryData (self , reposName , key , value ):
249
249
""" write data to the mRepositories dict """
250
250
self .mRepositories [reposName ][key ] = value
251
251
252
252
253
+ # ----------------------------------------- #
254
+ def remove (self , reposName ):
255
+ """ remove given item from the mRepositories dict """
256
+ del self .mRepositories [reposName ]
257
+
258
+
253
259
# ----------------------------------------- #
254
260
def rename (self , oldName , newName ):
255
261
""" rename repository key """
@@ -284,7 +290,7 @@ def checkingOnStartInterval(self):
284
290
interval = 0
285
291
for j in [1 ,3 ,7 ,14 ,30 ]:
286
292
if i >= j :
287
- interval = j
293
+ interval = j
288
294
return interval
289
295
290
296
@@ -414,8 +420,7 @@ def xmlDownloaded(self,nr,state):
414
420
experimental = False
415
421
if pluginNodes .item (i ).firstChildElement ("experimental" ).text ().simplified ().toUpper () in ["TRUE" ,"YES" ]:
416
422
experimental = True
417
- plugin = {}
418
- plugin [name ] = {
423
+ plugin = {
419
424
"name" : pluginNodes .item (i ).toElement ().attribute ("name" ),
420
425
"version_avail" : pluginNodes .item (i ).toElement ().attribute ("version" ),
421
426
"desc_repo" : pluginNodes .item (i ).firstChildElement ("description" ).text ().simplified (),
@@ -440,8 +445,8 @@ def xmlDownloaded(self,nr,state):
440
445
#if compatible, add the plugin to the list
441
446
if compareVersions (QGIS_VER , qgisMinimumVersion ) < 2 and compareVersions (qgisMaximumVersion , QGIS_VER ) < 2 :
442
447
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 )
445
450
self .mRepositories [reposName ]["state" ] = 2
446
451
else :
447
452
#print "Repository parsing error"
@@ -452,7 +457,7 @@ def xmlDownloaded(self,nr,state):
452
457
453
458
# is the checking done?
454
459
if not self .fetchingInProgress ():
455
- plugins .getAllInstalled ()
460
+ plugins .rebuild ()
456
461
self .saveCheckingOnStartLastDate ()
457
462
self .emit (SIGNAL ("checkingDone()" ))
458
463
# --- /class Repositories ---------------------------------------------------------------- #
@@ -467,7 +472,10 @@ class Plugins(QObject):
467
472
# ----------------------------------------- #
468
473
def __init__ (self ):
469
474
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
471
479
472
480
473
481
# ----------------------------------------- #
@@ -486,37 +494,39 @@ def keyByUrl(self, name):
486
494
487
495
488
496
# ----------------------------------------- #
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
492
501
493
502
494
503
# ----------------------------------------- #
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 ]
498
511
499
512
500
513
# ----------------------------------------- #
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 ]
509
518
510
519
511
520
# ----------------------------------------- #
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 ]
515
525
516
526
517
527
# ----------------------------------------- #
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 """
520
530
if readOnly :
521
531
path = QgsApplication .pkgDataPath ()
522
532
else :
@@ -532,7 +542,8 @@ def updatePlugin(self, key, readOnly):
532
542
error = ""
533
543
errorDetails = ""
534
544
try :
535
- exec ("import " + key )
545
+ exec ("import %s" % key )
546
+ exec ("reload (%s)" % key )
536
547
try :
537
548
exec ("nam = %s.name()" % key )
538
549
except :
@@ -589,73 +600,107 @@ def updatePlugin(self, key, readOnly):
589
600
"url" : path ,
590
601
"experimental" : False ,
591
602
"filename" : "" ,
592
- "status" : "" ,
603
+ "status" : "orphan " ,
593
604
"error" : error ,
594
605
"error_details" : errorDetails ,
595
606
"repository" : "" ,
596
607
"localdir" : key ,
597
608
"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
631
610
632
611
633
612
# ----------------------------------------- #
634
613
def getAllInstalled (self ):
635
- """ update the mPlugins dict with alredy installed plugins """
614
+ """ Build the localCache """
615
+ self .localCache = {}
636
616
# 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
637
620
try :
638
- pluginDir = QDir .cleanPath (unicode (QgsApplication .pkgDataPath ()) + "/python/plugins" )
639
- pluginDir = QDir (pluginDir )
621
+ pluginDir = QDir (pluginsPath )
640
622
pluginDir .setFilter (QDir .AllDirs )
641
623
for key in pluginDir .entryList ():
642
624
key = unicode (key )
643
625
if not key in ["." ,".." ]:
644
- self .updatePlugin (key , True )
626
+ self .localCache [ key ] = self . getInstalledPlugin (key , True )
645
627
except :
646
628
# return QCoreApplication.translate("QgsPluginInstaller","Couldn't open the system plugin directory")
647
629
pass # it's not necessary to stop due to this error
630
+ # remove the temporarily added path
631
+ sys .path .remove (pluginsPath )
648
632
# ...then try to add locally installed ones
649
633
try :
650
- pluginDir = QDir .cleanPath (unicode ( QgsApplication .qgisSettingsDirPath ()) + "/python/plugins" )
634
+ pluginDir = QDir .convertSeparators ( QDir . cleanPath (QgsApplication .qgisSettingsDirPath () + "/python/plugins" ) )
651
635
pluginDir = QDir (pluginDir )
652
636
pluginDir .setFilter (QDir .AllDirs )
653
637
except :
654
638
return QCoreApplication .translate ("QgsPluginInstaller" ,"Couldn't open the local plugin directory" )
655
639
for key in pluginDir .entryList ():
656
640
key = unicode (key )
657
641
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"
659
704
660
705
661
706
# ----------------------------------------- #
@@ -689,12 +734,6 @@ def isThereAnythingNew(self):
689
734
return False
690
735
691
736
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
-
698
737
# --- /class Plugins --------------------------------------------------------------------- #
699
738
700
739
0 commit comments