python - floating QDockWidget does not close when parentWidget closes -
i have 2 open mainwindows: mainwindowwithbutton , mainwindowwithdock. later contains qdockwidget.
is behaviour: when users makes dockwidget floatable , closes mainwindowwithdock, dockwidget doesn't close.
should behaviour: when users makes dockwidget floatable , closes mainwindowwithdock, dockwidget closes well.
notes:
- reason "is behaviour": floating dockwidget seems independent it's parent
- i cannot listen onclose / reject (as give false information in particular case.
- the mainwindow not emit clear signals it's behaviour
- it important, dockwidget closes before mainwindow closed. otherwise focus goes unexpected
example code :
from pyqt4 import qtcore, qtgui pyqt4 import qtcore, qtgui pyqt4.qtgui import qapplication, qdialog, qmainwindow import sys try: _fromutf8 = qtcore.qstring.fromutf8 except attributeerror: def _fromutf8(s): return s try: _encoding = qtgui.qapplication.unicodeutf8 def _translate(context, text, disambig): return qtgui.qapplication.translate(context, text, disambig, _encoding) except attributeerror: def _translate(context, text, disambig): return qtgui.qapplication.translate(context, text, disambig) class ui_mainwindowwithbutton(object): def setupui(self, mainwindowwithbutton): mainwindowwithbutton.setobjectname(_fromutf8("mainwindowwithbutton")) mainwindowwithbutton.resize(567, 384) self.centralwidget = qtgui.qwidget(mainwindowwithbutton) self.centralwidget.setobjectname(_fromutf8("centralwidget")) mainwindowwithbutton.setcentralwidget(self.centralwidget) def retranslateui(self, mainwindowwithbutton): mainwindowwithbutton.setwindowtitle(_translate("mainwindowwithbutton", "mainwindow", none)) class ui_mainwindowwithdock(object): def setupui(self, mainwindowwithdock): mainwindowwithdock.setobjectname(_fromutf8("mainwindowwithdock")) mainwindowwithdock.resize(509, 316) self.centralwidget = qtgui.qwidget(mainwindowwithdock) self.centralwidget.setobjectname(_fromutf8("centralwidget")) mainwindowwithdock.setcentralwidget(self.centralwidget) # # # # # # # # # # # # # # # # # # # # # # # # # setup dock # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # self.thedock = qtgui.qdockwidget(mainwindowwithdock) self.thedock.setobjectname(_fromutf8("thedock")) self.dockwidgetcontents = qtgui.qwidget(self.thedock) self.dockwidgetcontents.setobjectname(_fromutf8("dockwidgetcontents")) self.thedock.setwidget(self.dockwidgetcontents) mainwindowwithdock.adddockwidget(qtcore.qt.dockwidgetarea(2), self.thedock) self.retranslateui(mainwindowwithdock) qtcore.qmetaobject.connectslotsbyname(mainwindowwithdock) def retranslateui(self, mainwindowwithdock): mainwindowwithdock.setwindowtitle(_translate("mainwindowwithdock", "mainwindow", none)) class mainwindowwithbuttondlg(qmainwindow): pass class mainwindowwithdockdlg(qmainwindow): pass def main(): app = qapplication(sys.argv) windowwithdockui = ui_mainwindowwithdock() windowwithdock = mainwindowwithdockdlg() windowwithdockui.setupui(windowwithdock) windowwithdock.show() app.exec() # dock widget should closed ui = ui_mainwindowwithbutton() window = mainwindowwithbuttondlg() ui.setupui(window) window.show() app.exec() if __name__ == '__main__': main()
reject method of original source. here have qdialog qmainwindow it's central widget - therefore becomes qmainwindow in sense(from anki addcards.py (scroll bottom):
def reject(self): if not self.canclose(): # way of calling problem: might leave method without doing return remhook('reset', self.onreset) remhook('currentmodelchanged', self.onmodelchange) clearaudioqueue() self.removetempnote(self.editor.note) self.editor.setnote(none) self.modelchooser.cleanup() self.deckchooser.cleanup() self.mw.maybereset() savegeom(self, "add") aqt.dialogs.close("addcards") qdialog.reject(self)
you can use event-filter monitor events of given window. before window closes, always post close-event. doesn't matter whether window has modified normal closing process or not. if , when closes, accept property of corresponding close-event guaranteed true
. so, if watch event, can check see if accepted, , act accordingly.
the main problem solve how find right window watch. @ time dock-widget created, may not accessible. 1 approach wait until parent of dock-widget first shown, top-level window , install event-filter on that. doing things way means dock-widget never needs know window dependant upon.
below working demo of approach based on example (with of irrelevant stuff removed):
import sys pyqt4 import qtcore, qtgui pyqt4.qtgui import qapplication, qdialog, qmainwindow class eventwatcher(qtcore.qobject): def __init__(self, parent): qtcore.qobject.__init__(self, parent) parent.installeventfilter(self) def eventfilter(self, source, event): if source self.parent(): if event.type() == qtcore.qevent.show: target = source.parent() while target.parent() not none: target = target.parent() print('found target window: %r' % target) source.removeeventfilter(self) target.installeventfilter(self) elif event.type() == qtcore.qevent.close: source.closeevent(event) print('test filter accepted: %s' % event.isaccepted()) if event.isaccepted(): self.parent().close() return true return qtcore.qobject.eventfilter(self, source, event) class ui_mainwindowwithdock(object): def setupui(self, mainwindowwithdock): self.thedock = qtgui.qdockwidget(mainwindowwithdock) mainwindowwithdock.adddockwidget(qtcore.qt.dockwidgetarea(2), self.thedock) # add event watcher eventwatcher(self.thedock) class mainwindowwithdockdlg(qmainwindow): pass # mock-up class testing class mockdialog(qdialog): def __init__(self): qdialog.__init__(self) windowwithdock = mainwindowwithdockdlg() windowwithdockui = ui_mainwindowwithdock() windowwithdockui.setupui(windowwithdock) layout = qtgui.qvboxlayout(self) layout.addwidget(windowwithdock) self.canclose = false def reject(self): if not self.canclose: self.canclose = true return qdialog.reject(self) def closeevent(self, event): qdialog.closeevent(self, event) print('test close accepted: %s' % event.isaccepted()) def main(): app = qapplication(sys.argv) dialog = mockdialog() dialog.show() app.exec_() # dock widget should closed window = qmainwindow() window.show() app.exec_() if __name__ == '__main__': main()
Comments
Post a Comment