[PyQt] Possible bug in QAbstractItemModel.setItemData

danny shevitz at lanl.gov
Thu Oct 21 22:22:38 BST 2010


Howdy,

I might have found a bug in QAbstractItemModel.setItemData. The situation
is that I am using internal drag and drop but with Qt.UserRole's defined. Having
pored over the source code, the logic flow is:

on the drag:
QAbstractItemView::startDrag
QAbstractItemModel::encodeData
QAbstractItemModel::itemData (creates a QMap of roles to values)

on the drop:
QAbstractItemModel::dropMimeData
QAbstractItemModel::decodeData
QAbstractItemModel::setItemData
QAbstractItemModel::setData

in particular setItemData should loop over all values in it's QMap and call
setData on them in turn.

In my code, the problem is that setItemData is only looping over the standard
data roles and not my
custom roles. 

I don't have a complete working example to post, but here is sample code to show
what is going on:

def itemData(self,  index):
  result = super(Elm3TreeModel,  self).itemData(index)
  # add in my user roles to the dictionary
  for role in self.userRoles:
    result[role]=self.data(index,  role)
  print "in itemData, result=",  result
  return result

def setItemData(self,  index,  roles):
  print "in setItemData, roles = ",  roles
  ############################
  # Probable BUG in setItemData
  # The following lines should not be necessary, but fix the problem
  ############################
# for role in self.userRoles:
#   self.setData(index,  roles[role],  role)
  return super(Elm3TreeModel,  self).setItemData(index,  roles)

def setData(self, index, value, role=Qt.EditRole):
  print "in setData role='%s', value='%s' " % (role,  value) 
  ...

The screen output is: 

in itemData, result= {0: u'b', 1: <PyQt4.QtGui.QPixmap object at 0x0148C768>, 2:
u'b', 32: 'OrGate', 33: '', 34: ''}

in setItemData, roles =  {0: u'b', 1: <PyQt4.QtGui.QPixmap object at
0x0148C650>, 2: u'b', 32: u'OrGate', 33: u'', 34: u''}

in setData role='0', value='b' 
in setData role='1', value='<PyQt4.QtGui.QPixmap object at 0x0148C7A0>' 

So notice that in itemData, the correct dictionary including my user defined
is returned (defining user roles 32, 33, 34)

In setItemData, the correct dictionary is passed in, including the user roles.

In setData, however, we are not looping over all the roles, in fact we are
stopping after user role 1 (not getting user role 2, which is also defined by
the framework).

The relevant C++ source for setItemData is:

bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int,
QVariant> &roles)
{
    bool b = true;
    for (QMap<int, QVariant>::ConstIterator it = roles.begin(); it !=
roles.end(); ++it)
    b = b && setData(index, it.value(), it.key());
}
So setItemData should just be looping over all the items in the roles QMap, but
it isn't.

Does anyone have any idea what I am doing wrong, or is this a bug?

thanks,
Danny




More information about the PyQt mailing list