Changeset 9117:c99139cb37a2 in orange


Ignore:
Timestamp:
10/18/11 15:31:43 (3 years ago)
Author:
ales_erjavec <ales.erjavec@…>
Branch:
default
Convert:
b74404fd295999c14d96934412004c97d516515c
Message:

Added the option to store other data roles in the PyListModel.
Support for drag/drop actions.
Some bug fixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/OWItemModels.py

    r8042 r9117  
    22from PyQt4.QtGui import * 
    33 
    4 from functools import wraps 
    5  
     4from functools import wraps, partial 
     5from collections import defaultdict 
     6 
     7class _store(dict): 
     8    pass 
     9 
     10def _argsort(seq, cmp=None, key=None, reverse=False): 
     11    if key is not None: 
     12        items = sorted(zip(range(len(seq)), seq), key=lambda i,v: key(v)) 
     13    elif cmp is not None: 
     14        items = sorted(zip(range(len(seq)), seq), cmp=lambda a,b: cmp(a[1], b[1])) 
     15    else: 
     16        items = sorted(zip(range(len(seq)), seq), key=seq.__getitem__) 
     17    if reverse: 
     18        items = reversed(items) 
     19    return items 
     20 
     21     
    622class PyListModel(QAbstractListModel): 
    723    """ A model for displaying python list like objects in Qt item view classes 
    824    """ 
    9     def __init__(self, iterable=[], parent=None, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled): 
     25    def __init__(self, iterable=[], parent=None, 
     26                 flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled, 
     27                 list_item_role=Qt.DisplayRole, 
     28                 supportedDropActions=Qt.MoveAction): 
    1029        QAbstractListModel.__init__(self, parent) 
    1130        self._list = [] 
    12         self._flags = flags  
     31        self._other_data = [] 
     32        self._flags = flags 
     33        self.list_item_role = list_item_role 
     34         
     35        self._supportedDropActions = supportedDropActions 
    1336        self.extend(iterable) 
    1437         
     
    1841        """ 
    1942        self._list = list 
     43        self._other_data = [_store() for _ in list] 
    2044        self.reset() 
    2145     
     
    3559    def data(self, index, role=Qt.DisplayRole): 
    3660        row = index.row() 
    37         if role == Qt.DisplayRole: 
     61        if role in [self.list_item_role, Qt.EditRole]: 
    3862            return QVariant(self[index.row()]) 
    39         return QVariant() 
     63        else: 
     64            return QVariant(self._other_data[index.row()].get(role, QVariant())) 
     65     
     66    def itemData(self, index): 
     67        map = QAbstractListModel.itemData(self, index) 
     68        for key, value in self._other_data[index.row()].items(): 
     69            map[key] = QVariant(value) 
     70        return map 
    4071     
    4172    def parent(self, index=QModelIndex()): 
     
    4374     
    4475    def setData(self, index, value, role=Qt.EditRole): 
    45         obj = value.toPyObject() 
    46         self[index.row()] = obj 
     76        if role == Qt.EditRole: 
     77            obj = value.toPyObject() 
     78            self[index.row()] = obj 
     79        else: 
     80            self._other_data[index.row()][role] = value 
     81            self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), index, index) 
    4782        return True 
    4883         
    4984    def flags(self, index): 
    50         return Qt.ItemFlags(self._flags) 
     85        if index.isValid(): 
     86            return self._other_data[index.row()].get("flags", self._flags) 
     87        else: 
     88            return self._flags | Qt.ItemIsDropEnabled 
     89         
     90    def insertRows(self, row, count, parent=QModelIndex()): 
     91        """ Insert ``count`` rows at ``row``, the list fill be filled  
     92        with ``None``  
     93        """ 
     94#        print "Insert", row, count 
     95        if not parent.isValid(): 
     96            self.__setslice__(row, row, [None] * count) 
     97            return True 
     98        else: 
     99            return False 
    51100         
    52101    def removeRows(self, row, count, parent=QModelIndex()): 
     102        """ 
     103        """ 
     104#        print "Remove", row, count 
    53105        if not parent.isValid(): 
    54106            self.__delslice__(row, row + count) 
     
    61113        self.beginInsertRows(QModelIndex(), len(self), len(self) + len(list_) - 1) 
    62114        self._list.extend(list_) 
     115        self._other_data.extend([_store() for _ in list_]) 
    63116        self.endInsertRows() 
    64117     
     
    69122        self.beginInsertRows(QModelIndex(), i, i) 
    70123        self._list.insert(i, val) 
     124        self._other_data.insert(i, _store()) 
    71125        self.endInsertRows() 
    72126         
     
    90144         
    91145    def __add__(self, iterable): 
     146        # Does not preserve flags other data. 
    92147        return PyListModel(self._list + iterable, self.parent()) 
    93148     
     
    98153        self.beginRemoveRows(QModelIndex(), i, i) 
    99154        del self._list[i] 
     155        del self._other_data[i] 
    100156        self.endRemoveRows() 
    101157         
     
    104160            self.beginRemoveRows(QModelIndex(), i, j - 1) 
    105161            del self._list[i:j] 
     162            del self._other_data[i:j] 
    106163            self.endRemoveRows() 
    107164         
     
    116173            self.beginInsertRows(QModelIndex(), i, i + len(all) - 1) 
    117174            self._list[i:i] = all 
     175            self._other_data[i:i] = [_store() for _ in all] 
    118176            self.endInsertRows() 
    119 #        self.reset() 
    120 #        self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.index(i), self.index(j)) 
    121177         
    122178    def reverse(self): 
    123179        self._list.reverse() 
     180        self._other_data.reverse() 
    124181        self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.index(0), self.index(len(self) -1)) 
    125182         
    126183    def sort(self, *args, **kwargs): 
    127         self._list.sort(*args, **kwargs) 
     184        indices = _argsort(self._list, *args, **kwargs) 
     185        list = [self._list[i] for i in indices] 
     186        other = [self._other_data[i] for i in indices] 
     187        for i, new_l, new_o in enumerate(zip(list, other)): 
     188            self._list[i] = new_l 
     189            self._other_data[i] = new_o 
     190#        self._list.sort(*args, **kwargs) 
    128191        self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.index(0), self.index(len(self) -1)) 
    129192         
     
    143206        for ind in indexList: 
    144207            self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.index(ind), self.index(ind)) 
     208             
     209    ########### 
     210    # Drag/drop 
     211    ########### 
     212     
     213    def supportedDropActions(self): 
     214        return self._supportedDropActions 
    145215             
    146216 
     
    155225        elif role == Qt.DecorationRole: 
    156226            return QVariant(OWGUI.getAttributeIcons().get(self.__getitem__(i).varType, -1)) 
    157         elif role == Qt.EditRole: 
    158             return QVariant(self.__getitem__(i)) 
    159         return QVariant() 
    160          
    161     def setData(self, index, value, role): 
    162         i = index.row() 
    163         if role == Qt.EditRole:     
    164             self.__setitem__(i,  value.toPyObject())  
     227        else: 
     228            return PyListModel.data(self, index, role) 
     229         
    165230         
    166231class VariableEditor(QWidget): 
Note: See TracChangeset for help on using the changeset viewer.