The code below creates a single QListView with three items. This QListView gets populated via its .model's. Without using the model I could go ahead and do something like this:
view=QtGui.QListWidget()
item=QtGui.QListWidgetItem()
item.setText('Item Name')
icon=QtGui.QIcon('/Volumes/path/to/file.jpg')
item.setIcon(icon)
view.addItem(item)
But with `.model' in use there are no items available (the indexes instead). Please advise.

import os,sys
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
elements={'Animals':{1:'Bison',2:'Panther',3:'Elephant'},'Birds':{1:'Duck',2:'Hawk',3:'Pigeon'},'Fish':{1:'Shark',2:'Salmon',3:'Piranha'}}
class Model(QtCore.QAbstractListModel):
def __init__(self):
QtCore.QAbstractListModel.__init__(self)
self.items=[]
self.modelDict={}
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role):
if not index.isValid() or not (0<=index.row()<len(self.items)): return QtCore.QVariant()
if role==QtCore.Qt.DisplayRole: return self.items[index.row()]
def addItems(self):
for key in self.modelDict:
index=QtCore.QModelIndex()
self.beginInsertRows(index, 0, 0)
self.items.append(key)
self.endInsertRows()
class ListView(QtGui.QListView):
def __init__(self):
super(ListView, self).__init__()
self.model= Model()
self.model.modelDict=elements
self.model.addItems()
self.setModel(self.model)
self.show()
window=ListView()
sys.exit(app.exec_())
The code below is revised fully working version of the one posted earlier. Basically we have to supply model with the data requested. The actual icon "assignment" will be handled by the model itself. We only need to make sure the request for icon happens under correct if Role==x scope. The icons should be requested/returned in if DecorationRole portion of .data() method. There are other roles available: Qt.DisplayRole, Qt.TextAlignmentRole, Qt.TextColorRole, Qt.BackgroundColorRole, Qt.ItemDataRole, Qt.UserRole and etc)

import os,sys
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
elements={'Animals':{1:'Bison',2:'Panther',3:'Elephant'},'Birds':{1:'Duck',2:'Hawk',3:'Pigeon'},'Fish':{1:'Shark',2:'Salmon',3:'Piranha'}}
icon=QtGui.QIcon('C:\\myIcon.png')
class Model(QtCore.QAbstractListModel):
def __init__(self):
QtCore.QAbstractListModel.__init__(self)
self.items=[]
self.modelDict={}
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role):
if not index.isValid() or not (0<=index.row()<len(self.items)): return QtCore.QVariant()
if role==QtCore.Qt.DisplayRole:
return self.items[index.row()]
elif role==QtCore.Qt.DecorationRole:
return icon
def addItems(self):
for key in self.modelDict:
index=QtCore.QModelIndex()
self.beginInsertRows(index, 0, 0)
self.items.append(key)
self.endInsertRows()
class ListView(QtGui.QListView):
def __init__(self):
super(ListView, self).__init__()
self.model= Model()
self.model.modelDict=elements
self.model.addItems()
self.setModel(self.model)
self.show()
window=ListView()
sys.exit(app.exec_())
First off, you'll need Model.data to be able to return a QIcon (or QPixmap, if that's more convenient) when the role passed in is DecorationRole. With this current code, it'll return None, which not only doesn't do what you want, is actually invalid. If it doesn't know how to deal with the passed role, it should return an invalid QVariant (like you do on the first line of the method). PyQt is probably smart enough to handle None properly, though.
Secondly, you already appear to be using the QModelIndex correctly. You can just have the icon be another field attached to the model itself that you access similarly. QListWidgetItem is simply a convenience class, and there's nothing stopping you from encapsulating all of the data associated with a row in a similar class that you stash on the model (like you're already doing with the DisplayRole data) and access via the QModelIndex.row().
Something like this:
def data(self, index, role):
if not index.isValid() or not (0 <= index.row() < len(self.items)):
return QtCore.QVariant()
if role == QtCore.Qt.DisplayRole:
return self.items[index.row()]
if role == QtCore.Qt.DecorationRole:
return self.icons[index.row()]
return QtCore.QVariant()
Although I'd personally recommend having a dict whose values contain both the DisplayRole and DecorationRole data as fields on a class.
I don't know off-hand if a QListView will request the DecorationRole from the model by default. You might need to set the iconSize property on the list view, or similar. These are all the changes you need to make to the model itself, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With