On Wed, Oct 1, 2014 at 5:06 PM, Gary Sherman <gsher...@geoapt.com> wrote:
> On 10/1/14 12:55 PM, Mark Coletti wrote: > >> I'm writing a qgis python plugin and have encountered a curious >> problem. I've successfully tested the plugin's dialog standalone via >> ipython. However, I get the following error when I try to execute the >> same code from within qgis: "PyQt4.QtCore.QVariant represents a mapped >> type and cannot be instantiated". >> >> > Your answer is here: http://hub.qgis.org/wiki/ > quantum-gis/Python_plugin_API_changes_from_18_to_20 > > QVariant is no longer present in QGIS since we use the sip 2.0 api. > Use regular strings rather than a QVariant. I'm posting a follow up here on the odd chance that someone else has the same problem and greps for it on this mailing list. I'm relatively new to python-based qgis plugins, and found that most of the extant documentation for PyQt was for sip 1.0 api; and, worse yet, there was no mention that there were two versions. So it's very, very easy for a newbie to fall into the same trap I did. First, the link you provided was helpful except with regards to situations where a **null, or empty, QVariant** was returned. I found that returning empty strings and empty lists yielded all manner of strange and counter-intuitive behavior for my table. I.e., both horizontal and vertical headers were missing altogether, and the cells were mysteriously populated with uncheckable check boxes. The solution was simple: return None. I would have done that *first*, but read somewhere that that wouldn't work. :( So, for future reference for those wanting to do this same thing as I was, that is creating a Qt table from a model for use within qgis, here's a stripped down version of my class: from PyQt4 import QtGui, QtCore, Qt from PyQt4.QtCore import Qt, QDateTime from Event import Event class Events(QtCore.QAbstractTableModel) : # column headers headers = ['Created', 'Name', 'Description'] def __init__(self, parent = None): super(Events, self).__init__(parent) self.events = [] def rowCount(self, parent=QtCore.QModelIndex()) : return len(self.events) def columnCount(self, parent=QtCore.QModelIndex()) : return len(self.headers) def data(self, index, role) : if not index.isValid() : return None #With sip v 1.0 used to be QVariant() elif role != Qt.DisplayRole : return None if index.column() == 1 : return self.events[index.row()].name elif index.column() == 2 : return self.events[index.row()].description elif index.column() == 0 : return QDateTime.fromMSecsSinceEpoch(self.events[index.row()].created) return None def headerData(self, section, orientation, role): if role == Qt.DisplayRole : if orientation == Qt.Horizontal : return self.headers[section] elif orientation == Qt.Vertical : return str(self.events[section].categoryID) return None def addEvent(self, categoryID, name, description = '', created = 0) : self.events.append( Event( name, description, categoryID, created ) ) I did find a way to force ipython to use sip 2.0, which was particularly useful for when I wanted to test the dialog standalone. In my "~/.ipython/profile_default/ipython_config.py" I placed the following: import sip try: sip.setapi('QDate', 2) sip.setapi('QDateTime', 2) sip.setapi('QString', 2) sip.setapi('QtextStream', 2) sip.setapi('Qtime', 2) sip.setapi('QUrl', 2) sip.setapi('QVariant', 2) except ValueError, e: raise RuntimeError('Could not set API version (%s): did you import PyQt4 directly?' % e) So, while in ipython I could use the "gui qt" command and The Right Thing would happen: sip 2.0 would be used, so I could then test within the proper sip API context. (H/t to http://cyrille.rossant.net/making-pyqt4-pyside-and-ipython-work-together/) Hopefully someone out there at sometime will find this useful! Cheers, Mark
_______________________________________________ Qgis-developer mailing list Qgis-developer@lists.osgeo.org http://lists.osgeo.org/mailman/listinfo/qgis-developer