<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title></title>
</head>
<body>
Geoff Gerrietts schrieb:<br>
<blockquote type="cite"
 cite="mid20030514202225.GA31726@isis.gerrietts.net">
  <pre wrap="">I've been working on a little app that uses a listview on the left to
select an item, while an edit panel on the right lets me modify its
attributes. I think it's a fairly common interface idiom, seen quite a
bit in configuration screens and the like.

My difficulty started when I wanted to add a confirm dialog. I wanted
it so that if you selected a new item while changes were still
pending, you'd get a dialog saying "Discard changes?" Again, a fairly
common UI idiom.

My idea was, when I caught a selectionChanged() signal, I would raise
the dialog. If I got "ok", I would update the edit panel and discard
the changes. If I got anything else, I would reset the selection to
the previous value. To facilitate this, I set it up so that if the
same item was selected twice, I would return immediately.

Conceptually, this seems sound. I catch the signal, discover it's
going to discard changes, warn the user. When the user says "whoops" I
reset the selection, and when my slot catches the new event, it
returns immediately because that's what's already selected. Printing
out the "selectionTree.selectedItem()" before the return should result
in:  new, old.

Instead, I get the warning dialog twice. The printout shows new, old,
new, old.

I have no idea where this second event is coming from, but I know
(based on strategic commenting) it's related to the call to
setSelected() in the handler. What am I doing wrong?

Sample code that illustrates the case is below -- it's not the actual
app, but it reproduces the erroneous behavior. I can send the actual
app to anyone interested in seeing the whole thing, but it's still
very much a work in progress.

Thanks,
--G.

  </pre>
</blockquote>
I guess it must have something to do with immediate signal delivery when
setSelected() is called inside the slot routine.<br>
Blocking the signals in the slot routine does not help. If the setSelected()
is called outside the slot routine, it works.<br>
A QTimer started with a timeout value of 0 helps do delay the setSelected()
call until the slot routine has finished.<br>
<br>
See the changed sample code below.<br>
<br>
Ulli<br>
<br>
<tt>-------------------------------------</tt><br>
<tt>&nbsp;from qt import *<br>
<br>
&nbsp;data = { <br>
&nbsp; &nbsp;&nbsp; 'fruit': ['apple', 'banana', 'cherry'], <br>
&nbsp;&nbsp; &nbsp; 'animal': ['ant', 'bear', 'cat']<br>
&nbsp;}<br>
<br>
&nbsp;class NoteEditor(QDialog):<br>
&nbsp;&nbsp; &nbsp; selectedItem = None<br>
<br>
&nbsp; &nbsp;&nbsp; def __init__(self,parent = None,name = None,modal = 0,fl = 0):<br>
&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; QDialog.__init__(self,parent,name,modal,fl)<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; if name == None:<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.setName("ListMadness!")<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; self.resize(146,480)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; self.setCaption(self.trUtf8("Note Editor"))<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seltree = self.selectionTree = QListView(self,"selectionTree")<br>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seltree.addColumn(self.trUtf8("Topics"))<br>
&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; seltree.header().setClickEnabled(0,seltree.header().count() - 1)<br>
&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; seltree.setGeometry(QRect(4,10,130,460))<br>
<br>
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for category, topics in data.items():<br>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cat_item = QListViewItem(seltree, category)<br>
&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for topic in topics:<br>
&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top_item = QListViewItem(cat_item, topic)<br>
&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if self.selectedItem is None:<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seltree.setSelected(top_item, 1)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.selectedItem = top_item<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; cat_item.setOpen(1)<br>
<br>
<b>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;self.idleTimer = QTimer(self)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;self.connect(self.idleTimer, SIGNAL("timeout()"), self.undoSelectionChange)<br>
</b><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.connect(self.selectionTree,SIGNAL("selectionChanged(QListViewItem*)"),self.refreshActiveTopic)<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp; def refreshActiveTopic(self):<br>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentListItem = self.selectionTree.selectedItem()<br>
&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; print "currentListItem", currentListItem<br>
&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; print "self.selectedItem", self.selectedItem<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; if currentListItem == self.selectedItem:<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<br>
&nbsp;<br>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = QMessageBox.warning(self,<br>
&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Are you sure?",<br>
&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Are you sure you really want to change topics?",<br>
&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QMessageBox.Ok, QMessageBox.Cancel)<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; if res != 1:<br>
<b>&gt;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.idleTimer.start(0, True)<br>
</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; else:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; self.selectedItem = currentListItem<br>
<br>
<b>&gt;&nbsp; &nbsp; def undoSelectionChange(self):<br>
&gt;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; self.selectionTree.blockSignals(True)<br>
&gt;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; self.selectionTree.setSelected(self.selectedItem,1)<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; self.selectionTree.blockSignals(False)<br>
</b><br>
&nbsp;if __name__ == "__main__":<br>
&nbsp;&nbsp; &nbsp; import sys<br>
&nbsp; &nbsp;&nbsp; app = QApplication(sys.argv)<br>
&nbsp;&nbsp; &nbsp; app.connect(app, SIGNAL('lastWindowClosed()'), app, SLOT('quit()'))<br>
&nbsp;&nbsp;&nbsp; &nbsp;w = NoteEditor()<br>
&nbsp;&nbsp;&nbsp; &nbsp;w.show()<br>
&nbsp;&nbsp;&nbsp; &nbsp;app.exec_loop()<br>
-------------------------------------<br>
</tt><br>
</body>
</html>