<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Oct 1, 2014 at 5:06 PM, Gary Sherman <span dir="ltr"><<a href="mailto:gsherman@geoapt.com" target="_blank">gsherman@geoapt.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span>On 10/1/14 12:55 PM, Mark Coletti wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
I'm writing a qgis python plugin and have encountered a curious<br>
problem.  I've successfully tested the plugin's dialog standalone via<br>
ipython.  However, I get the following error when I try to execute the<br>
same code from within qgis: "PyQt4.QtCore.QVariant represents a mapped<br>
type and cannot be instantiated".<br>
<br>
</blockquote>
<br></span>
Your answer is here: <a href="http://hub.qgis.org/wiki/quantum-gis/Python_plugin_API_changes_from_18_to_20" target="_blank">http://hub.qgis.org/wiki/<u></u>quantum-gis/Python_plugin_API_<u></u>changes_from_18_to_20</a><br>
<br>
QVariant is no longer present in QGIS since we use the sip 2.0 api.<br>
Use regular strings rather than a QVariant.</blockquote><div><br></div><div>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.  </div><div><br></div><div>First, the link you provided was helpful except with regards to situations where a <i>*null, or empty, QVariant*</i> 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.  :(</div><div><br></div><div>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:</div><div><br></div><div><div><font face="courier new, monospace">from PyQt4 import QtGui, QtCore, Qt</font></div><div><font face="courier new, monospace">from PyQt4.QtCore import Qt, QDateTime</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">from Event import Event</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">class Events(QtCore.QAbstractTableModel) :</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">    # column headers</font><font face="courier new, monospace">    </font></div><div><font face="courier new, monospace">    headers = ['Created', 'Name', 'Description']</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">    def __init__(self, parent = None):</font></div><div><font face="courier new, monospace">        super(Events, self).__init__(parent)</font></div><div><font face="courier new, monospace">        self.events = []</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">    def rowCount(self, parent=QtCore.QModelIndex()) :</font></div><div><font face="courier new, monospace">        return len(self.events)</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">    def columnCount(self, parent=QtCore.QModelIndex()) :</font></div><div><font face="courier new, monospace">        return len(self.headers)</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">    def data(self, index, role) :</font></div><div><font face="courier new, monospace">        if not index.isValid() :</font></div><div><font face="courier new, monospace">            return None #With sip v 1.0 used to be QVariant()</font></div><div><font face="courier new, monospace">        elif role != Qt.DisplayRole :</font></div><div><font face="courier new, monospace">            return None</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">        if index.column() == 1 :</font></div><div><font face="courier new, monospace">            return self.events[index.row()].name</font></div><div><font face="courier new, monospace">        elif index.column() == 2 :</font></div><div><font face="courier new, monospace">            return self.events[index.row()].description</font></div><div><font face="courier new, monospace">        elif index.column() == 0 :</font></div><div><font face="courier new, monospace">            return QDateTime.fromMSecsSinceEpoch(self.events[index.row()].created)</font></div><div><font face="courier new, monospace">        return None</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">    def headerData(self, section, orientation, role):</font></div><div><font face="courier new, monospace">        if role == Qt.DisplayRole :</font></div><div><font face="courier new, monospace">            if orientation == Qt.Horizontal :</font></div><div><font face="courier new, monospace">                return self.headers[section]</font></div><div><font face="courier new, monospace">            elif orientation == Qt.Vertical :</font></div><div><font face="courier new, monospace">                return str(self.events[section].categoryID)</font></div><div><font face="courier new, monospace">        return None</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">    def addEvent(self, categoryID, name, description = '', created = 0) :</font></div><div><font face="courier new, monospace">        self.events.append( Event( name, description, categoryID, created ) )</font></div></div><div><br></div><div><br></div><div>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:</div><div><br></div><div><div><font face="courier new, monospace">import sip</font></div><div><font face="courier new, monospace">try:</font></div><div><font face="courier new, monospace">    sip.setapi('QDate', 2)</font></div><div><font face="courier new, monospace">    sip.setapi('QDateTime', 2)</font></div><div><font face="courier new, monospace">    sip.setapi('QString', 2)</font></div><div><font face="courier new, monospace">    sip.setapi('QtextStream', 2)</font></div><div><font face="courier new, monospace">    sip.setapi('Qtime', 2)</font></div><div><font face="courier new, monospace">    sip.setapi('QUrl', 2)</font></div><div><font face="courier new, monospace">    sip.setapi('QVariant', 2)</font></div><div><font face="courier new, monospace">except ValueError, e:</font></div><div><font face="courier new, monospace">    raise RuntimeError('Could not set API version (%s): did you import PyQt4 directly?' % e)</font></div></div><div><br></div><div><br></div><div>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 <a href="http://cyrille.rossant.net/making-pyqt4-pyside-and-ipython-work-together/">http://cyrille.rossant.net/making-pyqt4-pyside-and-ipython-work-together/</a>)</div><div><br></div><div>Hopefully someone out there at sometime will find this useful!</div><div><br></div><div>Cheers,</div><div><br></div><div>Mark</div></div>
</div></div>