1414from collections import namedtuple , deque
1515from xml .sax .saxutils import escape
1616from distutils import version
17+ from typing import Optional , List , Union , Tuple
1718
1819import pkg_resources
1920import requests
8384 "local" ]
8485)
8586
87+ #: An installable item/slot
88+ Item = Union [Available , Installed ]
89+
8690
8791def is_updatable (item ):
92+ # type: (Item) -> bool
8893 if isinstance (item , Available ):
8994 return False
9095 elif item .installable is None :
@@ -249,6 +254,7 @@ def __init__(self, parent=None, **kwargs):
249254 self .layout ().addWidget (self .__details )
250255
251256 def set_items (self , items ):
257+ # type: (List[Item]) -> None
252258 self .__items = items
253259 model = self .__model
254260 model .setRowCount (0 )
@@ -313,7 +319,12 @@ def set_items(self, items):
313319 QItemSelectionModel .Select | QItemSelectionModel .Rows
314320 )
315321
322+ def items (self ):
323+ # type: () -> List[Item]
324+ return list (self .__items )
325+
316326 def item_state (self ):
327+ # type: () -> List['Action']
317328 steps = []
318329 for i in range (self .__model .rowCount ()):
319330 modelitem = self .__model .item (i , 0 )
@@ -328,6 +339,37 @@ def item_state(self):
328339
329340 return steps
330341
342+ def set_item_state (self , steps ):
343+ # type: (List['Action']) -> None
344+ model = self .__model
345+ if model .rowCount () == 0 :
346+ return
347+
348+ for row in range (model .rowCount ()):
349+ modelitem = model .item (row , 0 ) # type: QStandardItem
350+ item = modelitem .data (Qt .UserRole ) # type: Item
351+ # Find the action command in the steps list for the item
352+ cmd = - 1
353+ for cmd_ , item_ in steps :
354+ if item == item_ :
355+ cmd = cmd_
356+ break
357+ if isinstance (item , Available ):
358+ modelitem .setCheckState (
359+ Qt .Checked if cmd == Install else Qt .Unchecked
360+ )
361+ elif isinstance (item , Installed ):
362+ if cmd == Upgrade :
363+ modelitem .setCheckState (Qt .Checked )
364+ elif cmd == Uninstall :
365+ modelitem .setCheckState (Qt .Unchecked )
366+ elif is_updatable (item ):
367+ modelitem .setCheckState (Qt .PartiallyChecked )
368+ else :
369+ modelitem .setCheckState (Qt .Checked )
370+ else :
371+ assert False
372+
331373 def __selected_row (self ):
332374 indices = self .__view .selectedIndexes ()
333375 if indices :
@@ -548,7 +590,9 @@ def add_package(self, installable):
548590 return
549591 else :
550592 packages = self ._packages + [installable ]
593+ state = self .addonwidget .item_state ()
551594 self .set_packages (packages )
595+ self .addonwidget .set_item_state (state )
552596
553597 def __progressDialog (self ):
554598 if self .__progress is None :
@@ -677,10 +721,19 @@ def dropEvent(self, event):
677721 packages .append (
678722 Installable (name , vers , summary ,
679723 descr or summary , path , [path ]))
680- future = concurrent .futures .Future ()
681- future .set_result ((AddonManagerDialog ._packages or []) + packages )
682- self ._set_packages (future )
683- self .addonwidget .set_install_projects (names )
724+
725+ if packages :
726+ state = self .addonwidget .item_state ()
727+ self .set_packages ((self ._packages or []) + packages )
728+ items = self .addonwidget .items ()
729+ # mark for installation the added packages
730+ for item in items :
731+ if item .installable in packages :
732+ if isinstance (item , Available ):
733+ state .append ((Install , item ))
734+ elif isinstance (item , Installed ) and is_updatable (item ):
735+ state .append ((Upgrade , item ))
736+ self .addonwidget .set_item_state (state )
684737
685738 def __accepted (self ):
686739 steps = self .addonwidget .item_state ()
@@ -842,6 +895,8 @@ def have_install_permissions():
842895
843896Install , Upgrade , Uninstall = 1 , 2 , 3
844897
898+ Action = Tuple [int , Item ]
899+
845900
846901class CommandFailed (Exception ):
847902 def __init__ (self , cmd , retcode , output ):
0 commit comments