Skip to content

Commit

Permalink
add ability to veto a close event
Browse files Browse the repository at this point in the history
  • Loading branch information
sccolbert committed Feb 6, 2014
1 parent 57499f4 commit bbd9aa1
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 71 deletions.
10 changes: 4 additions & 6 deletions enaml/qt/q_window_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from .QtCore import Qt, QSize, Signal
from .QtCore import Qt, QSize
from .QtGui import QWidget, QLayout

from .q_single_widget_layout import QSingleWidgetLayout
Expand Down Expand Up @@ -55,11 +55,6 @@ class QWindowBase(QWidget):
normally be computed by the layout.
"""
#: A signal which can be emitted when the window is closed. The
#: decision as to when and if to emit this signal is left up to
#: the derived classes.
closed = Signal()

def __init__(self, parent=None, flags=Qt.WindowFlags(0)):
""" Initialize a QWindowBase.
Expand All @@ -68,6 +63,9 @@ def __init__(self, parent=None, flags=Qt.WindowFlags(0)):
parent : QWidget, optional
The parent of the window.
flags : Qt.WindowFlags, optional
The window flags to pass to the parent constructor.
"""
super(QWindowBase, self).__init__(parent, flags)
self._expl_min_size = QSize()
Expand Down
44 changes: 32 additions & 12 deletions enaml/qt/qt_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,57 @@
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import Typed
from atom.api import Typed, atomref

from enaml.widgets.dialog import ProxyDialog
from enaml.widgets.window import CloseEvent

from .QtCore import Qt, Signal
from .QtCore import Qt
from .QtGui import QDialog

from .q_deferred_caller import deferredCall
from .q_window_base import QWindowBase
from .qt_window import QtWindow
from .qt_window import QtWindow, finalize_close


class QWindowDialog(QDialog, QWindowBase):
""" A window base subclass which implements dialog behavior.
"""
# This signal must be redefined, or the QtWindow base class will
# not be able to connect to it. This is a quirk of using multiple
# inheritance with PyQt. Note that this signal is never emitted
# it is here only for API compatibility with the base class.
closed = Signal()

def __init__(self, parent=None, flags=Qt.Widget):
def __init__(self, proxy, parent=None, flags=Qt.Widget):
""" Initialize a QWindowDialog.
Parameters
----------
proxy : QtDialog
The proxy object which owns this dialog. Only an atomref
will be maintained to this object.
parent : QWidget, optional
The parent of the dialog.
flags : Qt.WindowFlags, optional
The window flags to pass to the parent constructor.
"""
super(QWindowDialog, self).__init__(parent, flags)
self._proxy_ref = atomref(proxy)

def closeEvent(self, event):
""" Handle the close event for the dialog.
"""
event.accept()
if not self._proxy_ref:
return
proxy = self._proxy_ref()
d = proxy.declaration
d_event = CloseEvent()
d.closing(d_event)
if d_event.is_accepted():
super(QWindowDialog, self).closeEvent(event)
else:
event.ignore()


class QtDialog(QtWindow, ProxyDialog):
Expand All @@ -49,7 +69,7 @@ def create_widget(self):
"""
flags = self.creation_flags()
self.widget = QWindowDialog(self.parent_widget(), flags)
self.widget = QWindowDialog(self, self.parent_widget(), flags)

def init_widget(self):
""" Initialize the underlying widget.
Expand All @@ -73,7 +93,7 @@ def on_finished(self):
d.accepted()
else:
d.rejected()
d._handle_close()
deferredCall(finalize_close, d)

#--------------------------------------------------------------------------
# ProxyDialog API
Expand Down
47 changes: 35 additions & 12 deletions enaml/qt/qt_main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
#------------------------------------------------------------------------------
import sys

from atom.api import Typed
from atom.api import Typed, atomref

from enaml.widgets.main_window import ProxyMainWindow
from enaml.widgets.window import CloseEvent

from .QtCore import Qt, Signal
from .QtCore import Qt
from .QtGui import QMainWindow

from .q_deferred_caller import deferredCall
Expand All @@ -20,25 +21,47 @@
from .qt_menu_bar import QtMenuBar
from .qt_status_bar import QtStatusBar
from .qt_tool_bar import QtToolBar
from .qt_window import QtWindow
from .qt_window import QtWindow, finalize_close


class QCustomMainWindow(QMainWindow):
""" A custom QMainWindow which adds some Enaml specific features.
"""
#: A signal emitted when the window is closed by the user
closed = Signal()
def __init__(self, proxy, parent=None, flags=Qt.Widget):
""" Initialize a QCustomMainWindow.
Parameters
----------
proxy : QtMainWindow
The proxy object which owns this window. Only an atomref
will be maintained to this object.
parent : QWidget, optional
The parent of the window.
flags : Qt.WindowFlags, optional
The window flags to pass to the parent constructor.
"""
super(QCustomMainWindow, self).__init__(parent, Qt.Window | flags)
self._proxy_ref = atomref(proxy)

#--------------------------------------------------------------------------
# Private API
#--------------------------------------------------------------------------
def closeEvent(self, event):
""" A close event handler which emits the 'closed' signal.
""" Handle the close event for the window.
"""
super(QCustomMainWindow, self).closeEvent(event)
self.closed.emit()
event.accept()
if not self._proxy_ref:
return
proxy = self._proxy_ref()
d = proxy.declaration
d_event = CloseEvent()
d.closing(d_event)
if d_event.is_accepted():
deferredCall(finalize_close, d)
else:
event.ignore()

#--------------------------------------------------------------------------
# Public API
Expand Down Expand Up @@ -109,7 +132,7 @@ def create_widget(self):
"""
flags = self.creation_flags()
widget = QCustomMainWindow(self.parent_widget(), flags)
widget = QCustomMainWindow(self, self.parent_widget(), flags)
widget.setDocumentMode(True)
widget.setDockNestingEnabled(True)
self.widget = widget
Expand Down
57 changes: 38 additions & 19 deletions enaml/qt/qt_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
#------------------------------------------------------------------------------
import sys

from atom.api import Typed
from atom.api import Typed, atomref

from enaml.layout.geometry import Pos, Rect, Size
from enaml.widgets.window import ProxyWindow
from enaml.widgets.window import ProxyWindow, CloseEvent

from .QtCore import Qt, QPoint, QRect, QSize
from .QtGui import QApplication, QIcon

from .q_deferred_caller import deferredCall
from .q_resource_helpers import get_cached_qicon
from .q_window_base import QWindowBase
from .qt_container import QtContainer
Expand All @@ -28,33 +29,60 @@
}


def finalize_close(d):
""" Finalize the closing of the declaration object.
This is performed as a deferred call so that the window may fully
close before the declaration is potentially destroyed.
"""
d.visible = False
d.closed()
if d.destroy_on_close:
d.destroy()


class QWindow(QWindowBase):
""" A window base subclass which handles the close event.
The window layout computes the min/max size of the window based
on its central widget, unless the user explicitly changes them.
"""
def __init__(self, parent=None, flags=Qt.Widget):
def __init__(self, proxy, parent=None, flags=Qt.Widget):
""" Initialize a QWindow.
Parameters
----------
proxy : QtWindow
The proxy object which owns this window. Only an atomref
will be maintained to this object.
parent : QWidget, optional
The parent of the window.
flags : Qt.WindowFlags, optional
The window flags to pass to the parent constructor.
"""
super(QWindow, self).__init__(parent, Qt.Window | flags)
self._proxy_ref = atomref(proxy)

def closeEvent(self, event):
""" Handle the QCloseEvent from the window system.
By default, this handler calls the superclass' method to close
the window and then emits the 'closed' signal.
""" Handle the close event for the window.
"""
super(QWindow, self).closeEvent(event)
self.closed.emit()
event.accept()
if not self._proxy_ref:
return
proxy = self._proxy_ref()
d = proxy.declaration
d_event = CloseEvent()
d.closing(d_event)
if d_event.is_accepted():
deferredCall(finalize_close, d)
else:
event.ignore()


class QtWindow(QtWidget, ProxyWindow):
Expand All @@ -81,7 +109,7 @@ def create_widget(self):
"""
flags = self.creation_flags()
self.widget = QWindow(self.parent_widget(), flags)
self.widget = QWindow(self, self.parent_widget(), flags)

def init_widget(self):
""" Initialize the widget.
Expand All @@ -99,7 +127,6 @@ def init_widget(self):
self.set_modality(d.modality)
if d.icon:
self.set_icon(d.icon)
self.widget.closed.connect(self.on_closed)

def init_layout(self):
""" Initialize the widget layout.
Expand All @@ -125,14 +152,6 @@ def central_widget(self):
if d is not None:
return d.proxy.widget

def on_closed(self):
""" The signal handler for the 'closed' signal.
This method will fire the 'closed' event on the declaration.
"""
self.declaration._handle_close()

#--------------------------------------------------------------------------
# Child Events
#--------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit bbd9aa1

Please sign in to comment.