<!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> from qt import *<br>
<br>
data = { <br>
'fruit': ['apple', 'banana', 'cherry'], <br>
'animal': ['ant', 'bear', 'cat']<br>
}<br>
<br>
class NoteEditor(QDialog):<br>
selectedItem = None<br>
<br>
def __init__(self,parent = None,name = None,modal = 0,fl = 0):<br>
QDialog.__init__(self,parent,name,modal,fl)<br>
<br>
if name == None:<br>
self.setName("ListMadness!")<br>
<br>
self.resize(146,480)<br>
self.setCaption(self.trUtf8("Note Editor"))<br>
<br>
seltree = self.selectionTree = QListView(self,"selectionTree")<br>
seltree.addColumn(self.trUtf8("Topics"))<br>
seltree.header().setClickEnabled(0,seltree.header().count() - 1)<br>
seltree.setGeometry(QRect(4,10,130,460))<br>
<br>
for category, topics in data.items():<br>
cat_item = QListViewItem(seltree, category)<br>
for topic in topics:<br>
top_item = QListViewItem(cat_item, topic)<br>
if self.selectedItem is None:<br>
seltree.setSelected(top_item, 1)<br>
self.selectedItem = top_item<br>
cat_item.setOpen(1)<br>
<br>
<b>> self.idleTimer = QTimer(self)<br>
> self.connect(self.idleTimer, SIGNAL("timeout()"), self.undoSelectionChange)<br>
</b><br>
self.connect(self.selectionTree,SIGNAL("selectionChanged(QListViewItem*)"),self.refreshActiveTopic)<br>
<br>
<br>
def refreshActiveTopic(self):<br>
currentListItem = self.selectionTree.selectedItem()<br>
print "currentListItem", currentListItem<br>
print "self.selectedItem", self.selectedItem<br>
<br>
if currentListItem == self.selectedItem:<br>
return<br>
<br>
res = QMessageBox.warning(self,<br>
"Are you sure?",<br>
"Are you sure you really want to change topics?",<br>
QMessageBox.Ok, QMessageBox.Cancel)<br>
if res != 1:<br>
<b>> self.idleTimer.start(0, True)<br>
</b> else:<br>
self.selectedItem = currentListItem<br>
<br>
<b>> def undoSelectionChange(self):<br>
> self.selectionTree.blockSignals(True)<br>
> self.selectionTree.setSelected(self.selectedItem,1)<br>
> self.selectionTree.blockSignals(False)<br>
</b><br>
if __name__ == "__main__":<br>
import sys<br>
app = QApplication(sys.argv)<br>
app.connect(app, SIGNAL('lastWindowClosed()'), app, SLOT('quit()'))<br>
w = NoteEditor()<br>
w.show()<br>
app.exec_loop()<br>
-------------------------------------<br>
</tt><br>
</body>
</html>