Package muntjac :: Package data :: Package util :: Module indexed_container
[hide private]
[frames] | no frames]

Source Code for Module muntjac.data.util.indexed_container

  1  # Copyright (C) 2012 Vaadin Ltd.  
  2  # Copyright (C) 2012 Richard Lincoln 
  3  #  
  4  # Licensed under the Apache License, Version 2.0 (the "License");  
  5  # you may not use this file except in compliance with the License.  
  6  # You may obtain a copy of the License at  
  7  #  
  8  #     http://www.apache.org/licenses/LICENSE-2.0  
  9  #  
 10  # Unless required by applicable law or agreed to in writing, software  
 11  # distributed under the License is distributed on an "AS IS" BASIS,  
 12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
 13  # See the License for the specific language governing permissions and  
 14  # limitations under the License. 
 15   
 16  """An implementation of the IIndexed interface with all important features.""" 
 17   
 18  from muntjac.data import property as prop 
 19   
 20  from muntjac.data.item import IItem 
 21   
 22  from muntjac.data.util.abstract_in_memory_container import \ 
 23      AbstractInMemoryContainer 
 24   
 25  from muntjac.data.util.filter.simple_string_filter import \ 
 26      SimpleStringFilter 
 27   
 28  from muntjac.data.util.filter.unsupported_filter_exception import \ 
 29      UnsupportedFilterException 
 30   
 31  from muntjac.data.util.abstract_container import \ 
 32      BaseItemSetChangeEvent, AbstractContainer 
 33   
 34  from muntjac.data import container 
 35  from muntjac.util import EventObject 
 36  from muntjac.util import fullname 
 37   
 38  # item type is really IndexedContainerItem, but using IItem 
 39  # not to show it in public API 
40 -class IndexedContainer(AbstractInMemoryContainer, 41 container.IPropertySetChangeNotifier, 42 prop.IValueChangeNotifier, container.ISortable, 43 container.IFilterable, container.ISimpleFilterable):
44 """An implementation of the L{IContainer.Indexed} interface with all 45 important features. 46 47 Features: 48 - L{IIndexed} 49 - L{IOrdered} 50 - L{ISortable} 51 - L{IFilterable} 52 - L{ICloneable} (deprecated, might be removed in the future) 53 - Sends all needed events on content changes. 54 55 @see: L{IContainer} 56 @author: Vaadin Ltd. 57 @author: Richard Lincoln 58 @version: 1.1.2 59 """ 60
61 - def __init__(self, itemIds=None):
62 63 #: Linked list of ordered IProperty IDs. 64 self._propertyIds = list() 65 66 #: IProperty ID to type mapping. 67 self._types = dict() 68 69 #: Hash of Items, where each IItem is implemented as a mapping from 70 # IProperty ID to IProperty value. 71 self._items = dict() 72 73 #: Set of properties that are read-only. 74 self._readOnlyProperties = set() 75 76 #: List of all IProperty value change event listeners listening all 77 # the properties. 78 self._propertyValueChangeListeners = list() 79 80 self._propertyValueChangeCallbacks = dict() 81 82 #: Data structure containing all listeners interested in changes to 83 # single Properties. The data structure is a hashtable mapping 84 # IProperty IDs to a hashtable that maps IItem IDs to a linked list 85 # of listeners listening IProperty identified by given IProperty ID 86 # and IItem ID. 87 self._singlePropertyValueChangeListeners = dict() 88 89 self._defaultPropertyValues = dict() 90 91 self._nextGeneratedItemId = 1 92 93 super(IndexedContainer, self).__init__() 94 95 if itemIds is not None: 96 for itemId in itemIds: 97 self.internalAddItemAtEnd(itemId, 98 IndexedContainerItem(itemId, self), False) 99 100 self.filterAll()
101 102 # IContainer methods 103
104 - def getUnfilteredItem(self, itemId):
105 if itemId is not None and itemId in self._items: 106 return IndexedContainerItem(itemId, self) 107 108 return None
109 110
111 - def getContainerPropertyIds(self):
112 return list(self._propertyIds)
113 114
115 - def getType(self, propertyId):
116 """Gets the type of a IProperty stored in the list. 117 118 @param propertyId: 119 the ID of the IProperty. 120 @return: Type of the requested IProperty 121 """ 122 return self._types.get(propertyId)
123 124
125 - def getContainerProperty(self, itemId, propertyId):
126 if not self.containsId(itemId): 127 return None 128 129 return IndexedContainerProperty(itemId, propertyId, self)
130 131
132 - def addContainerProperty(self, propertyId, typ, defaultValue):
133 # Fails, if nulls are given 134 if propertyId is None or typ is None: 135 return False 136 137 # Fails if the IProperty is already present 138 if propertyId in self._propertyIds: 139 return False 140 141 # Adds the IProperty to IProperty list and types 142 self._propertyIds.append(propertyId) 143 self._types[propertyId] = typ 144 145 # If default value is given, set it 146 if defaultValue is not None: 147 # for existing rows 148 for item in self.getAllItemIds(): 149 prop = self.getItem(item).getItemProperty(propertyId) 150 prop.setValue(defaultValue) 151 152 # store for next rows 153 if self._defaultPropertyValues is None: 154 self._defaultPropertyValues = dict() 155 156 self._defaultPropertyValues[propertyId] = defaultValue 157 158 # Sends a change event 159 self.fireContainerPropertySetChange() 160 161 return True
162 163
164 - def removeAllItems(self):
165 origSize = len(self) 166 167 self.internalRemoveAllItems() 168 169 self._items.clear() 170 171 # fire event only if the visible view changed, regardless of whether 172 # filtered out items were removed or not 173 if origSize != 0: 174 # Sends a change event 175 self.fireItemSetChange() 176 177 return True
178 179
180 - def addItem(self, itemId=None):
181 if itemId is None: 182 idd = self.generateId() 183 # Adds the IItem into container 184 self.addItem(idd) 185 return idd 186 else: 187 item = self.internalAddItemAtEnd(itemId, 188 IndexedContainerItem(itemId, self), False) 189 190 if not self.isFiltered(): 191 # always the last item 192 self.fireItemAdded(self.size() - 1, itemId, item) 193 elif self.passesFilters(itemId) and not self.containsId(itemId): 194 self.getFilteredItemIds().append(itemId) 195 # always the last item 196 self.fireItemAdded(self.size() - 1, itemId, item) 197 198 return item
199 200
201 - def addDefaultValues(self, t):
202 """Helper method to add default values for items if available 203 204 @param t: data table of added item 205 """ 206 if self._defaultPropertyValues is not None: 207 for key in self._defaultPropertyValues.keys(): 208 t[key] = self._defaultPropertyValues.get(key)
209 210
211 - def removeItem(self, itemId):
212 if itemId is None or itemId not in self._items: 213 return False 214 else: 215 del self._items[itemId] 216 217 origSize = self.size() 218 position = self.indexOfId(itemId) 219 if self.internalRemoveItem(itemId): 220 # fire event only if the visible view changed, regardless of 221 # whether filtered out items were removed or not 222 if self.size() != origSize: 223 self.fireItemRemoved(position, itemId) 224 225 return True 226 else: 227 return False
228 229
230 - def removeContainerProperty(self, propertyId):
231 232 # Fails if the IProperty is not present 233 if propertyId not in self._propertyIds: 234 return False 235 236 # Removes the IProperty to IProperty list and types 237 self._propertyIds.remove(propertyId) 238 if propertyId in self._types: 239 del self._types[propertyId] 240 if self._defaultPropertyValues is not None: 241 if propertyId in self._defaultPropertyValues: 242 del self._defaultPropertyValues[propertyId] 243 244 # If remove the IProperty from all Items 245 for item in self.getAllItemIds(): 246 self._items.get(item).remove(propertyId) 247 248 # Sends a change event 249 self.fireContainerPropertySetChange() 250 251 return True
252 253
254 - def addItemAfter(self, previousItemId, newItemId=None):
255 if newItemId is None: 256 idd = self.generateId() 257 if self.addItemAfter(previousItemId, idd) is not None: 258 return idd 259 else: 260 return None 261 else: 262 return self.internalAddItemAfter(previousItemId, newItemId, 263 IndexedContainerItem(newItemId, self), True)
264 265
266 - def addItemAt(self, index, newItemId=None):
267 if newItemId is None: 268 idd = self.generateId() 269 # Adds the IItem into container 270 self.addItemAt(index, idd) 271 return idd 272 else: 273 return self.internalAddItemAt(index, newItemId, 274 IndexedContainerItem(newItemId, self), True)
275 276
277 - def generateId(self):
278 """Generates an unique identifier for use as an item id. Guarantees 279 that the generated id is not currently used as an id. 280 """ 281 while True: # FIXME: do statement 282 idd = int(self._nextGeneratedItemId) 283 self._nextGeneratedItemId += 1 284 if idd not in self._items: 285 break 286 return idd
287 288
289 - def registerNewItem(self, index, newItemId, item):
290 t = dict() 291 self._items[newItemId] = t 292 self.addDefaultValues(t)
293 294
295 - def addListener(self, listener, iface=None):
296 if (isinstance(listener, container.IPropertySetChangeListener) and 297 (iface is None or 298 issubclass(iface, container.IPropertySetChangeListener))): 299 #super(IndexedContainer, self).addListener(listener, iface) 300 pass 301 302 if (isinstance(listener, prop.IValueChangeListener) and 303 (iface is None or 304 issubclass(iface, prop.IValueChangeListener))): 305 306 self._propertyValueChangeListeners.append(listener) 307 308 super(IndexedContainer, self).addListener(listener, iface)
309 310
311 - def addCallback(self, callback, eventType=None, *args):
312 if eventType is None: 313 eventType = callback._eventType 314 315 if issubclass(eventType, container.IPropertySetChangeEvent): 316 super(IndexedContainer, self).addCallback(callback, 317 eventType, *args) 318 319 elif issubclass(eventType, prop.ValueChangeEvent): 320 self._propertyValueChangeCallbacks[callback] = args 321 322 else: 323 super(IndexedContainer, self).addCallback(callback, 324 eventType, *args)
325 326
327 - def removeListener(self, listener, iface=None):
328 if (isinstance(listener, container.IPropertySetChangeListener) and 329 (iface is None or 330 issubclass(iface, container.IPropertySetChangeListener))): 331 #super(IndexedContainer, self).removeListener(listener, iface) 332 pass 333 334 if (isinstance(listener, prop.IValueChangeListener) and 335 (iface is None or 336 issubclass(iface, prop.IValueChangeListener))): 337 if listener in self._propertyValueChangeListeners: 338 self._propertyValueChangeListeners.remove(listener) 339 340 super(IndexedContainer, self).removeListener(listener, iface)
341 342
343 - def removeCallback(self, callback, eventType=None):
344 if eventType is None: 345 eventType = callback._eventType 346 347 if issubclass(eventType, container.IPropertySetChangeEvent): 348 super(IndexedContainer, self).removecallback(callback, eventType) 349 350 elif issubclass(eventType, prop.ValueChangeEvent): 351 if callback in self._propertyValueChangeCallbacks: 352 del self._propertyValueChangeCallbacks[callback] 353 354 else: 355 super(IndexedContainer, self).removeCallback(callback, eventType)
356 357
358 - def firePropertyValueChange(self, source):
359 """Sends a IProperty value change event to all interested listeners. 360 361 @param source: 362 the IndexedContainerProperty object. 363 """ 364 # Sends event to listeners listening all value changes 365 event = PropertyValueChangeEvent(source) 366 for listener in self._propertyValueChangeListeners: 367 listener.valueChange(event) 368 369 for callback, args in self._propertyValueChangeCallbacks.iteritems(): 370 callback(event, *args) 371 372 # Sends event to single property value change listeners 373 propertySetToListenerListMap = \ 374 self._singlePropertyValueChangeListeners.get(source._propertyId) 375 376 if propertySetToListenerListMap is not None: 377 listenerList = propertySetToListenerListMap.get(source._itemId) 378 if listenerList is not None: 379 event = PropertyValueChangeEvent(source) 380 for l in listenerList: 381 l.valueChange(event)
382 383
384 - def getListeners(self, eventType):
385 if issubclass(eventType, prop.ValueChangeEvent): 386 return list(self._propertyValueChangeListeners) 387 388 return super(IndexedContainer, self).getListeners(eventType)
389 390
391 - def getCallbacks(self, eventType):
392 if issubclass(eventType, prop.ValueChangeEvent): 393 return dict(self._propertyValueChangeCallbacks) 394 395 return super(IndexedContainer, self).getCallbacks(eventType)
396 397
398 - def fireItemAdded(self, position, itemId, item):
402 403
404 - def fireItemSetChange(self, event=None):
405 if event is None: 406 event = ItemSetChangeEvent(self, -1) 407 super(IndexedContainer, self).fireItemSetChange(event) 408 else: 409 super(IndexedContainer, self).fireItemSetChange(event)
410 411
412 - def addSinglePropertyChangeListener(self, propertyId, itemId, listener):
413 """Adds new single IProperty change listener. 414 415 @param propertyId: 416 the ID of the IProperty to add. 417 @param itemId: 418 the ID of the IItem . 419 @param listener: 420 the listener to be added. 421 """ 422 if listener is not None: 423 if self._singlePropertyValueChangeListeners is None: 424 self._singlePropertyValueChangeListeners = dict() 425 426 propertySetToListenerListMap = \ 427 self._singlePropertyValueChangeListeners.get(propertyId) 428 429 if propertySetToListenerListMap is None: 430 propertySetToListenerListMap = dict() 431 self._singlePropertyValueChangeListeners[propertyId] = \ 432 propertySetToListenerListMap 433 434 listenerList = propertySetToListenerListMap.get(itemId) 435 436 if listenerList is None: 437 listenerList = list() 438 propertySetToListenerListMap[itemId] = listenerList 439 440 listenerList.append(listener)
441 442
443 - def removeSinglePropertyChangeListener(self, propertyId, itemId, listener):
444 """Removes a previously registered single IProperty change listener. 445 446 @param propertyId: 447 the ID of the IProperty to remove. 448 @param itemId: 449 the ID of the IItem. 450 @param listener: 451 the listener to be removed. 452 """ 453 if (listener is not None 454 and self._singlePropertyValueChangeListeners is not None): 455 456 propertySetToListenerListMap = \ 457 self._singlePropertyValueChangeListeners.get(propertyId) 458 459 if propertySetToListenerListMap is not None: 460 listenerList = propertySetToListenerListMap.get(itemId) 461 462 if listenerList is not None and listener in listenerList: 463 listenerList.remove(listener) 464 465 if len(listenerList) == 0: 466 if itemId in propertySetToListenerListMap: 467 del propertySetToListenerListMap[itemId] 468 469 if len(propertySetToListenerListMap) == 0: 470 if propertyId in self._singlePropertyValueChangeListeners: 471 del self._singlePropertyValueChangeListeners[propertyId] 472 473 if len(self._singlePropertyValueChangeListeners) == 0: 474 self._singlePropertyValueChangeListeners = None
475 476
477 - def sort(self, propertyId, ascending):
478 self.sortContainer(propertyId, ascending)
479 480
482 return self.getSortablePropertyIds()
483 484
485 - def getItemSorter(self):
486 return super(IndexedContainer, self).getItemSorter()
487 488
489 - def setItemSorter(self, itemSorter):
490 super(IndexedContainer, self).setItemSorter(itemSorter)
491 492
493 - def clone(self):
494 """Supports cloning of the IndexedContainer cleanly. 495 496 @raise CloneNotSupportedException: 497 if an object cannot be cloned. . 498 499 @deprecated: cloning support might be removed from IndexedContainer 500 in the future 501 """ 502 # Creates the clone 503 nc = IndexedContainer() 504 505 # Clone the shallow properties 506 if self.getAllItemIds() is not None: 507 nc.setAllItemIds(self.getAllItemIds().clone()) # FIXME: clone 508 else: 509 nc.setAllItemIds(None) 510 511 if self.getItemSetChangeListeners() is not None: 512 nc.setItemSetChangeListeners(list(self.getItemSetChangeListeners())) 513 else: 514 nc.setItemSetChangeListeners(None) 515 516 if self._propertyIds is not None: 517 nc._propertyIds = self._propertyIds.clone() 518 else: 519 nc._propertyIds = None 520 521 if self.getPropertySetChangeListeners() is not None: 522 nc.setPropertySetChangeListeners( 523 list(self.getPropertySetChangeListeners())) 524 else: 525 nc.setPropertySetChangeListeners(None) 526 527 if self._propertyValueChangeListeners is not None: 528 nc.propertyValueChangeListeners = self._propertyValueChangeListeners.clone() 529 else: 530 nc.propertyValueChangeListeners = None 531 532 if self._readOnlyProperties is not None: 533 nc.readOnlyProperties = self._readOnlyProperties.clone() 534 else: 535 nc.readOnlyProperties = None 536 537 if self._singlePropertyValueChangeListeners is not None: 538 nc.singlePropertyValueChangeListeners = self._singlePropertyValueChangeListeners.clone() 539 else: 540 nc.singlePropertyValueChangeListeners = None 541 542 if self._types is not None: 543 nc.types = self._types.clone() 544 else: 545 nc.types = None 546 547 nc.setFilters(self.getFilters().clone()) 548 549 if self.getFilteredItemIds() is None: 550 nc.setFilteredItemIds(None) 551 else: 552 nc.setFilteredItemIds( self.getFilteredItemIds().clone() ) 553 554 # Clone property-values 555 if self._items is None: 556 nc.items = None 557 else: 558 nc.items = dict() 559 for idd in self._items.keys(): 560 it = self._items.get(idd) 561 nc.items[idd] = it.clone() 562 return nc
563 564
565 - def addContainerFilter(self, *args):
566 nargs = len(args) 567 if nargs == 1: 568 fltr, = args 569 self.addFilter(fltr) 570 elif nargs == 4: 571 propertyId, filterString, ignoreCase, onlyMatchPrefix = args 572 # the filter instance created here is always valid for 573 # in-memory containers 574 try: 575 self.addFilter(SimpleStringFilter(propertyId, filterString, 576 ignoreCase, onlyMatchPrefix)) 577 except UnsupportedFilterException: 578 pass 579 else: 580 raise ValueError, 'invalid number of elements'
581 582
584 self.removeAllFilters()
585 586
587 - def removeContainerFilters(self, propertyId):
588 self.removeFilters(propertyId)
589 590
591 - def removeContainerFilter(self, fltr):
592 self.removeFilter(fltr)
593 594
595 -class IndexedContainerItem(IItem):
596
597 - def __init__(self, itemId, container): # FIXME: inner class
598 """Constructs a new ListItem instance and connects it to a host 599 container. 600 601 @param itemId: the IItem ID of the new IItem. 602 """ 603 if itemId is None: 604 raise ValueError 605 606 # IItem ID in the host container for this IItem. 607 self._itemId = itemId 608 609 self._container = container
610 611
612 - def getItemProperty(self, idd):
613 return IndexedContainerProperty(self._itemId, idd, self._container)
614 615
616 - def getItemPropertyIds(self):
617 return list(self._container._propertyIds)
618 619
620 - def __str__(self):
621 """Gets the string representation of the contents of the IItem. The 622 format of the string is a space separated catenation of the string 623 representations of the Properties contained by the IItem. 624 625 @return: string representation of the IItem contents 626 """ 627 retValue = '' 628 629 for i, propertyId in enumerate(self._container._propertyIds): 630 retValue += str(self.getItemProperty(propertyId)) 631 if i < len(self._container._propertyIds) - 1: 632 retValue += ' ' 633 634 return retValue
635 636
637 - def __hash__(self):
638 """Calculates a integer hash-code for the IItem that's unique inside 639 the list. Two Items inside the same list have always different 640 hash-codes, though Items in different lists may have identical 641 hash-codes. 642 643 @return: A locally unique hash-code as integer 644 """ 645 return hash(self._itemId)
646 647
648 - def __eq__(self, obj):
649 """Tests if the given object is the same as the this object. Two Items 650 got from a list container with the same ID are equal. 651 652 @param obj: 653 an object to compare with this object 654 @return: C{True} if the given object is the same as this 655 object, C{False} if not 656 """ 657 if obj is None or obj.__class__ != IndexedContainerItem: 658 return False 659 660 li = obj 661 662 return self.getHost() == li.getHost() and self._itemId == li._itemId
663 664
665 - def getHost(self):
666 return self._container
667 668
669 - def addItemProperty(self, idd, prop):
670 """IndexedContainerItem does not support adding new properties. Add 671 properties at container level. See 672 L{IndexedContainer.addContainerProperty} 673 674 @see: L{IItem.addProperty} 675 """ 676 raise NotImplementedError, ('Indexed container item ' 677 + 'does not support adding new properties')
678 679
680 - def removeItemProperty(self, idd):
681 """Indexed container does not support removing properties. Remove 682 properties at container level. See 683 L{IndexedContainer.removeContainerProperty} 684 685 @see: IItem.removeProperty 686 """ 687 raise NotImplementedError, \ 688 'Indexed container item does not support property removal'
689 690
691 -class IndexedContainerProperty(prop.IProperty, prop.IValueChangeNotifier):
692 """A class implementing the L{IProperty} interface to be contained in 693 the L{IndexedContainerItem} contained in the L{IndexedContainer}. 694 695 @author: Vaadin Ltd. 696 @author: Richard Lincoln 697 @version: 1.1.2 698 """ 699
700 - def __init__(self, itemId, propertyId, container):
701 """Constructs a new L{IndexedContainerProperty} object. 702 703 @param itemId: 704 the ID of the IItem to connect the new IProperty to. 705 @param propertyId: 706 the IProperty ID of the new IProperty. 707 @param container: 708 the list that contains the IItem to contain the new 709 IProperty. 710 """ 711 if (itemId is None) or (propertyId is None): 712 # Null ids are not accepted 713 raise ValueError, 'IContainer item or property ids can not be null' 714 715 # ID of the IItem, where this property resides. 716 self._propertyId = propertyId 717 718 # Id of the IProperty. 719 self._itemId = itemId 720 721 self._container = container
722 723
724 - def getType(self):
725 return self._container._types.get(self._propertyId)
726 727
728 - def getValue(self):
729 return self._container._items.get(self._itemId).get(self._propertyId)
730 731
732 - def isReadOnly(self):
733 return self in self._container._readOnlyProperties
734 735
736 - def setReadOnly(self, newStatus):
737 if newStatus: 738 self._container._readOnlyProperties.add(self) 739 else: 740 self._container._readOnlyProperties.remove(self)
741 742
743 - def setValue(self, newValue):
744 # Gets the IProperty set 745 propertySet = self._container._items.get(self._itemId) 746 747 # Support null values on all types 748 if newValue is None: 749 if self._propertyId in propertySet: 750 del propertySet[self._propertyId] 751 elif issubclass(newValue.__class__, self.getType()): 752 propertySet[self._propertyId] = newValue 753 else: 754 try: 755 # Gets the string constructor 756 #constr = self.getType().getConstructor([str]) 757 constr = self.getType().__init__ # FIXME: getConstructor 758 # Creates new object from the string 759 propertySet[self._propertyId] = constr(*[str(newValue)]) 760 except Exception: 761 raise prop.ConversionException, ('Conversion for value \'' 762 + newValue + '\' of class ' + fullname(newValue) 763 + ' to ' + self.getType().__name__ + ' failed') 764 765 # update the container filtering if this property is being filtered 766 if self._container.isPropertyFiltered(self._propertyId): 767 self._container.filterAll() 768 769 self._container.firePropertyValueChange(self)
770 771
772 - def __str__(self):
773 """Returns the value of the IProperty in human readable textual format. 774 The return value should be assignable to the C{setValue} method if the 775 IProperty is not in read-only mode. 776 777 @return: String representation of the value stored in the IProperty 778 """ 779 value = self.getValue() 780 781 if value is None: 782 return '' 783 784 return str(value)
785 786
787 - def __hash__(self):
788 """Calculates a integer hash-code for the IProperty that's unique inside 789 the IItem containing the IProperty. Two different Properties inside the 790 same IItem contained in the same list always have different 791 hash-codes, though Properties in different Items may have identical 792 hash-codes. 793 794 @return: A locally unique hash-code as integer 795 """ 796 return hash(self._itemId) ^ hash(self._propertyId)
797 798
799 - def __eq__(self, obj):
800 """Tests if the given object is the same as the this object. Two 801 Properties got from an IItem with the same ID are equal. 802 803 @param obj: 804 an object to compare with this object 805 @return: C{True} if the given object is the same as this 806 object, C{False} if not 807 """ 808 if obj is None or obj.__class__ != IndexedContainerProperty: 809 return False 810 811 lp = obj 812 813 return (lp.getHost() == self.getHost() 814 and lp._propertyId == self._propertyId 815 and lp._itemId == self._itemId)
816 817
818 - def addListener(self, listener, iface=None):
819 if (isinstance(listener, prop.IValueChangeListener) and 820 (iface is None or iface == prop.IValueChangeListener)): 821 self._container.addSinglePropertyChangeListener(self._propertyId, 822 self._itemId, listener)
823 824
825 - def addCallback(self, callback, eventType=None, *args):
826 if eventType is None: 827 eventType = callback._eventType 828 829 if eventType == prop.ValueChangeEvent: 830 self._container.addSinglePropertyChangeListener(self._propertyId, 831 self._itemId, (callback, args)) 832 else: 833 super(IndexedContainerProperty, self).addCallback(callback, 834 eventType, *args)
835 836
837 - def removeListener(self, listener, iface=None):
838 if (isinstance(listener, prop.IValueChangeListener) and 839 (iface is None or iface == prop.IValueChangeListener)): 840 self._container.removeSinglePropertyChangeListener(self._propertyId, 841 self._itemId, listener)
842 843
844 - def removeCallback(self, callback, eventType=None):
845 if eventType is None: 846 eventType = callback._eventType 847 848 if eventType == prop.ValueChangeEvent: 849 self._container.removeSinglePropertyChangeListener(self._propertyId, 850 self._itemId, callback) 851 852 else: 853 super(IndexedContainer, self).removeCallback(callback, eventType)
854 855
856 - def getHost(self):
857 return self._container
858 859
860 -class ItemSetChangeEvent(BaseItemSetChangeEvent):
861 """An C{Event} object specifying the list whose IItem set has changed. 862 863 @author: Vaadin Ltd. 864 @author: Richard Lincoln 865 @version: 1.1.2 866 """ 867
868 - def __init__(self, source, addedItemIndex):
869 super(ItemSetChangeEvent, self).__init__(source) 870 self._addedItemIndex = addedItemIndex
871 872
873 - def getAddedItemIndex(self):
874 """Iff one item is added, gives its index. 875 876 @return: -1 if either multiple items are changed or some other change 877 than add is done. 878 """ 879 return self._addedItemIndex
880 881
882 -class PropertyValueChangeEvent(EventObject, prop.ValueChangeEvent):
883 """An C{Event} object specifying the IProperty in a list whose 884 value has changed. 885 886 @author: Vaadin Ltd. 887 @author: Richard Lincoln 888 @version: 1.1.2 889 """ 890
891 - def __init__(self, source):
892 super(PropertyValueChangeEvent, self).__init__(source)
893 894
895 - def getProperty(self):
896 return self.getSource()
897