<div dir="ltr"><div class="gmail_default" style="font-family:tahoma,sans-serif"><br></div><div class="gmail_extra"><br><div class="gmail_quote">On 10 May 2018 at 12:34, Phil Thompson <span dir="ltr"><<a href="mailto:phil@riverbankcomputing.com" target="_blank">phil@riverbankcomputing.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 10 May 2018, at 11:31 am, J Barchan <<a href="mailto:jnbarchan@gmail.com">jnbarchan@gmail.com</a>> wrote:<br>
> <br>
> ​Hi Phil,<br>
> <br>
> Sorry, but I have one more related question about surprise behaviour.  I will try to keep this as brief as possible.<br>
> <br>
> Yesterday I came to understand why overriding, say, QSqlTableModel.data() came to grief on database-NULL, because of the Python loss of distinction on the QVariants representing ​"null" versus "default/invalid".  I would get back the "default" value where I expected the "null" value.<br>
> <br>
> In sorting my code out now in that light, I began to assume that QSqlTableModel.setData(index, None) would effectively suffer from exactly the same problem, in the opposite direction, i.e. it would set it to the "default" value not the "null" one.  And so I would need to deal with too.<br>
> <br>
> However, I find that, whether I do or do not override (in similar fashion) QSqlTableModel.setData(index: QModelIndex, value: QVariant)  ​it does set the value to database-NULL when called via .setData(index, None).<br>
> <br>
> This surprises me, as I expected it to have the same QVariant conversion issue over None as data(index) would.  Would you care to explain why this does not appear to be the symmetrical problematic case?<br>
<br>
</span>Despite what the docs say, None is converted to an invalid QVariant rather than a null QVariant. I don't know what Qt does when given an invalid QVariant.<br>
<span class="HOEnZb"><font color="#888888"><br>
Phil</font></span></blockquote></div><br><div style="font-family:tahoma,sans-serif" class="gmail_default">​Dear Phil,</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><br></div><div style="font-family:tahoma,sans-serif" class="gmail_default">I previously wrote that I had had to give up on overriding <span style="font-family:monospace,monospace">QSqlQueryModel.data()</span> because​ none of the solutions we discussed (concerning return type of native Python type versus <span style="font-family:monospace,monospace">QVariant</span> type) worked acceptably for me.  I have since discovered that, for various reasons, I <i>have to</i> provide a Python override of that method.</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><br></div><div style="font-family:tahoma,sans-serif" class="gmail_default">I have revisited this issue, and have come up with a solution which <i>seems</i> to work in all cases but which we did not propose between the two of us.</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><br></div><div style="font-family:tahoma,sans-serif" class="gmail_default"><i>Reminder of problems</i>:</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><ol><li><i>Without</i> the <span style="font-family:monospace,monospace">sip.enableautoconversion(QVariant, False)</span> call, overridden <span style="font-family:monospace,monospace">QSqlQueryModel.data()</span> definition, at least when called on database <span style="font-family:monospace,monospace">NULL</span> value for role <span style="font-family:monospace,monospace">DisplayRole</span>, would return a "default" value string like <span style="font-family:monospace,monospace">0</span> or <span style="font-family:monospace,monospace">''</span>, which is wrong (I need blank/empty).</li><li><i>With</i> the <span style="font-family:monospace,monospace">sip.enableautoconversion(QVariant, False)</span> call, and returning the <span style="font-family:monospace,monospace">QVariant</span> as-is, solved the above case perfectly <span style="font-family:monospace,monospace">but</span> meant that Python callers of the method would need to be changed to call <span style="font-family:monospace,monospace">QVariant.value()</span> on the return result to behave as before now, which is not at all good for the existing code I have inherited.</li></ol><p>There did not seem to be an alternative which just "worked" for me. <i> I have now come up with the following override code</i>:</p><pre style="background-color:rgb(255,255,255);color:rgb(0,0,0);font-family:"DejaVu Sans Mono";font-size:9pt"><span style="color:rgb(0,0,128);font-weight:bold">def </span>data(<span style="color:rgb(148,85,141)">self</span>, item: QtCore.QModelIndex, role: QtCore.Qt.ItemDataRole = QtCore.Qt.DisplayRole):<br>    was_enabled = sip.enableautoconversion(QtCore.QVariant, <span style="color:rgb(0,0,128);font-weight:bold">False</span>)<br>    v = <span style="color:rgb(0,0,128)">super</span>().data(item, role)<br>    sip.enableautoconversion(QtCore.QVariant, was_enabled<span style="color:rgb(0,0,128);font-weight:bold"></span>)<br>    <span style="color:rgb(0,0,128);font-weight:bold">if not </span>v.isValid() <span style="color:rgb(0,0,128);font-weight:bold">or </span>v.isNull():<br>        <span style="color:rgb(0,0,128);font-weight:bold">return None<br></span><span style="color:rgb(0,0,128);font-weight:bold">    else</span>:<br>        <span style="color:rgb(0,0,128);font-weight:bold">return </span>v.value()</pre>Note how:</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><ul><li>In the invalid or <span style="font-family:monospace,monospace">NULL</span> cases, it explicitly returns Python native <span style="font-family:monospace,monospace">None</span>.  That is <i>instead of</i> <span style="font-family:monospace,monospace">v.value()</span>, which would have returned <span style="font-family:monospace,monospace">0</span> or <span style="font-family:monospace,monospace">''</span>.  <i>This solves Problem #1 above</i>.<br></li><li>In the valid, non-<span style="font-family:monospace,monospace">NULL</span> case, it returns <span style="font-family:monospace,monospace">QVariant.value()</span>, i.e. native Python type, keeping Python callers unchanged.  <i>This solves Problem #2 above</i>.</li></ul><p>Would you kindly comment whether you agree this definition is acceptable?  Do you see any pitfalls, or need to change any code here (e.g. based on role value)?  I can only say that I have tried running with this, and am finding all the cases I can see are working correctly/as desired, but cannot be sure there is a case I have not thought of....</p><p></p><p>I'd <i>really</i> appreciate your feedback on this (hoping you'll agree with me!!), thank you.<br></p></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><span style="font-family:tahoma,sans-serif">Kindest,</span></div><div><span style="font-family:tahoma,sans-serif">Jonathan</span></div></div></div></div></div>
</div></div>