<div id="__MailbirdStyleContent" style="font-size: 12pt;font-family: Candara;color: #000000">
                                        
                                        
                                            
                                        
                                        
                                        :head slap:<div><br></div><div>Wow.  Thanks again Maurizio!</div><div><br></div><div>On the negative side:  That was kind of a dumb mistake.  Imagine the problem being that simple.  I definitely thought it was something darker and more sinister.</div><div><br></div><div>On the positive side:  My understanding wasn't as far off as I thought!</div><div><br></div><div>Appreciate the help, as always.  Learning all the time ...</div><div><br></div><div>/John</div><div><div class="mb_sig"></div>
                                        
                                        <blockquote class="history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
                        <p style="color: #AAAAAA; margin-top: 10px;">On 5/19/2019 6:28:49 PM, Maurizio Berti <maurizio.berti@gmail.com> wrote:</p><div style="font-family:Arial,Helvetica,sans-serif"><div dir="ltr"><div dir="ltr"><div>Hi John,</div><div dir="ltr">I think that the issue comes from your implementation of the closeEditor slot.<div><br></div><div>Since you're calling super() *after* changing the model structure, the view's default closeEditor() method tries to interact with what it thought it was the "current" index, but you just deleted it: the proxy model isn't able to map the index, since it doesn't exist anymore, then it crashes (although, in some tests I did it justs reports inconsistencies, while in other cases it just ignored as the index is invalid or just froze the main loop).</div><div>After moving the super() at the beginning of the method, you'll see that everything works as expected.</div><div>The only issue with this is that the EndEditHint will be ignored, but I think that you can manage that.</div><div>Also remember to implement the setEditorData() with the current index.data (but you can do that within createEditor() too).</div><div><br></div><div>Maurizio</div><div><br></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Il giorno dom 19 mag 2019 alle ore 18:09 John F Sturtz <<a href="mailto:john@sturtz.org">john@sturtz.org</a>> ha scritto:<br></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex;border-left: 1px solid rgb(204,204,204);padding-left: 1ex;min-width: 500px"><div id="gmail-m_5179131991134333094__MailbirdStyleContent" style="font-size: 12pt;font-family: Candara;color: rgb(0,0,0)">
                                        
                                        
                                            
                                        
                                        
                                        Hi again Maurizio.  Thanks as always for your help.<div><br></div><div>Minimal example is attached.  Here is a brief summary of what it is trying to do:</div><div><br></div><div>This is code to manage a list of categories and subcategories.  It creates a dialog (<span style="font-family:"Courier New"">Dlg</span>, which is loaded from the attached <span style="font-family:"Courier New"">dlg.ui</span> file) that uses a <span style="font-family:"Courier New"">QTreeView</span> to display a list of main categories, each of which can contain zero or more subcategories.  The dialog has buttons to create a new main category, create a new subcategory, and delete either type.</div><div><br></div><div>The actual data for a main category or subcategory is represented by a <span style="font-family:"Courier New"">CategoryNode</span>object.  A tree structure of these nodes is <span style="font-size: 12pt;line-height: 1.5">the data structure that underlies the source model (</span><span style="font-family:"Courier New"">CategoryTreeModel</span>)<span style="font-size: 12pt;line-height: 1.5">.  The source model manipulates the data tree using the methods defined in the <span style="font-family:"Courier New"">CategoryNode</span> class.</span></div><div><span style="font-family:"Courier New""><br></span></div><div>The <span style="font-family:"Courier New"">QTreeView</span> (<span style="font-family:"Courier New"">TreeView</span><span style="font-size: 12pt;line-height: 1.5">) uses a </span><span style="font-family:"Courier New"">QSortFilterProxyModel</span><span style="font-size: 12pt;line-height: 1.5"> proxy model to maintain a sorted view of the data.  </span><span style="font-size: 12pt;line-height: 1.5">Here's how I maintain the sorted view (not sure this is correct, but it's what I gleaned from such documentation as I could find):  The proxy model overrides </span><span style="font-family:"Courier New"">setData()</span><span style="font-size: 12pt;line-height: 1.5">, so when an item in the view is edited (either an existing one is changed, or a new one is added), the proxy's </span><span style="font-family:"Courier New"">setData()</span><span style="font-size: 12pt;line-height: 1.5"> gets called.  It first calls the source model's </span><span style="font-family:"Courier New"">setData()</span><span style="font-size: 12pt;line-height: 1.5"> to update the appropriate node in the underlying</span><span style="font-family:"Courier New"">CategoryNode</span><span style="font-size: 12pt;line-height: 1.5"> tree.  Then it calls </span><span style="font-family:"Courier New"">sort()</span><span style="font-size: 12pt;line-height: 1.5"> and </span><span style="font-family:"Courier New"">invalidate()</span><span style="font-size: 12pt;line-height: 1.5"> on itself to sort the view.</span></div><div><br></div><div>All this seems to work pretty well.  I've ensured that the model is implemented correctly at least to this extent:</div><div><ul><li><span style="font-size: 12pt;line-height: 1.5">I've run the model through the </span><span style="font-family:"Courier New"">pytest</span><span style="font-size: 12pt;line-height: 1.5"> </span><span style="font-family:"Courier New"">qmodeltester</span><span style="font-size: 12pt;line-height: 1.5"> and not gotten any warnings.</span></li><li>I've spent quite a bit of time going about adding, deleting and changing the descriptions of the items in the view using the buttons in the dialog, and they seem to work properly.</li></ul></div><div>The problem comes when I try to do this:  When you add either a main category or subcategory, it creates a new node in the tree with a blank value, then opens a <span style="font-family:"Courier New"">QLineEdit</span> delegate editor to enter the description.  If the user hits <i>Escape</i>, or hits <i>Enter</i> without typing in a value, I want to just delete the newly-added node and throw it away.</div><div><br></div><div>To that end, I override <span style="font-family:"Courier New"">closeEditor()</span> in the <span style="font-family:"Courier New"">TreeView</span>.  I get the view's <span style="font-family:"Courier New"">currentIndex()</span> (which should be an index in the proxy model, I think?).  If the value is empty, I get a reference to the source model, map the current index to the corresponding index in the source model (<span style="font-family:"Courier New"">mapToSource()</span>), and then call the source model's <span style="font-family:"Courier New"">removeRows()</span> method to delete it (lines 277-282).</div><div><br></div><div>This consistently crashes or produces a warning.</div><div><br></div><div>On my machine, the following consistently crashes:</div><div><ul><li>Start the app</li><li>Click on <b>Reimbursible</b> at the bottom of the list</li><li>Click the Sub button to add a new empty subcategory</li><li>Hit <i>Escape</i></li></ul><div>This consistently produces the message <b><span style="color:rgb(192,0,0)">QSortFilterProxyModel: inconsistent changes reported by source model </span></b><span style="font-size: 12pt;line-height: 1.5">(but doesn't crash):</span></div></div><div><ul><li>Start the app</li><li>Click on <b>Healthcare</b></li><li>Click the Sub button to add a new empty subcategory</li><li>Hit Escape</li></ul><div>I thought I was doing all this correctly (don't we usually?), but clearly I must misunderstand some part of it.  If you (or anyone) spots a problem, I'd be grateful to hear it.</div></div><div><br></div><div>Thanks!</div><div><br></div><div>/John</div><div class="gmail-m_5179131991134333094mb_sig"></div>
                                        
                                        <blockquote class="gmail-m_5179131991134333094history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
                        <p style="color:rgb(170,170,170);margin-top:10px">On 5/17/2019 4:37:47 PM, Maurizio Berti <<a href="mailto:maurizio.berti@gmail.com" target="_blank">maurizio.berti@gmail.com</a>> wrote:</p><div style="font-family:Arial,Helvetica,sans-serif"><div dir="ltr">Since you're implementing your own model, implementing removeRows() in the source model should be enough, but you have to ensure that its implementation responds as expected: removeRows has to return a bool, and the parent *must* be checked, expecially if you have a tree structure. Also ensure that all basic model functions (index, parent, rowCount, columnCount and data) are correctly implemented.<div><br></div><div>I'd suggest you to give us a minimal example anyway, you might even find out what is wrong in your case.</div><div><br></div><div>Maurizio</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Il giorno mar 14 mag 2019 alle ore 21:38 John F Sturtz <<a href="mailto:john@sturtz.org" target="_blank">john@sturtz.org</a>> ha scritto:<br></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex;border-left: 1px solid rgb(204,204,204);padding-left: 1ex;min-width: 500px"><div id="gmail-m_5179131991134333094gmail-m_-4221747021917962755__MailbirdStyleContent" style="font-size: 12pt;font-family: Candara;color: rgb(0,0,0)">Hi again.<div class="gmail-m_5179131991134333094gmail-m_-4221747021917962755mb_sig"></div><div><br></div><div>I'm the one who started the <b>QTreeView + sort + delete = crash</b> thread on May 8th.  In response to assistance from Kyle and Florian, I've re-implemented to use a <span style="font-family:"Courier New"">QAbstractItemModel</span> with associated <span style="font-family:"Courier New"">QSortFilterProxyModel</span>.</div><div><br></div><div>On the whole, that seems to be working pretty well, but there's one thing (well, at least one) I haven't been clear on despite poring over what documentation I can find.  I can post the test code again if it will help, but I think this is more of a general question:</div><div><br></div><div>If I have both a source model and also a proxy, and I'm modifying the view in a way that changes the structure (deleting a row, in the current case I'm working on), should I be overriding <span style="font-family:"Courier New"">removeRows()</span> for <i>both</i> the source model and the proxy, and calling <span style="font-family:"Courier New"">beginRemoveRows()/endRemoveRows()</span> in both cases?</div><div><br></div><div>I guess that seems to make sense to me, and my initial testing suggests it's so, as it seems to work (whereas if I <i>don't</i> do that, I either get a crash, or a message something like <span style="font-family:Consolas">QSortFilterProxyModel: inconsistent changes reported by source model</span>).</div><div><br></div><div>Same for inserting rows?  Just checking to see if I'm thinking right here.</div><div><br></div><div>Thanks!</div><div><br></div><div>/John</div></div>_______________________________________________<br>
PyQt mailing list    <a href="mailto:PyQt@riverbankcomputing.com" target="_blank">PyQt@riverbankcomputing.com</a><br>
<a href="https://www.riverbankcomputing.com/mailman/listinfo/pyqt" rel="noreferrer" target="_blank">https://www.riverbankcomputing.com/mailman/listinfo/pyqt</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail-m_5179131991134333094gmail_signature">È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi<br><a href="http://www.jidesk.net" target="_blank">http://www.jidesk.net</a></div>
</div></blockquote></div>_______________________________________________<br>
PyQt mailing list    <a href="mailto:PyQt@riverbankcomputing.com" target="_blank">PyQt@riverbankcomputing.com</a><br>
<a href="https://www.riverbankcomputing.com/mailman/listinfo/pyqt" rel="noreferrer" target="_blank">https://www.riverbankcomputing.com/mailman/listinfo/pyqt</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature">È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi<br><a href="http://www.jidesk.net" target="_blank">http://www.jidesk.net</a></div>
</div></blockquote></div></div>