Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CloseEvent to DockItem #303

Merged
merged 5 commits into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion enaml/qt/qt_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
#------------------------------------------------------------------------------
from atom.api import Typed, atomref

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

from .QtCore import Qt
from .QtWidgets import QDialog
Expand Down
30 changes: 27 additions & 3 deletions enaml/qt/qt_dock_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import Int, Typed
from atom.api import Int, Typed, atomref

from enaml.styling import StyleCache
from enaml.widgets.close_event import CloseEvent
from enaml.widgets.dock_item import ProxyDockItem

from .QtCore import Qt, QSize, Signal
Expand All @@ -28,10 +29,33 @@ class QCustomDockItem(QDockItem):
#: before the close event handler returns.
closed = Signal()

def __init__(self, proxy, parent=None):
""" Initialize a QCustomDockItem.

Parameters
----------
proxy : QtDockItem
The proxy object which owns this dock item. Only an atomref
will be maintained to this object.

parent : QWidget, optional
The parent of the window.
"""
super(QCustomDockItem, self).__init__(parent)
self._proxy_ref = atomref(proxy)

def closeEvent(self, event):
""" Handle the close event for the dock item.

"""
if self._proxy_ref:
proxy = self._proxy_ref()
d = proxy.declaration
d_event = CloseEvent()
d.closing(d_event)
if not d_event.is_accepted():
event.ignore()
return

super(QCustomDockItem, self).closeEvent(event)
if event.isAccepted():
self.closed.emit()
Expand All @@ -58,7 +82,7 @@ def create_widget(self):
""" Create the underlying QDockItem widget.

"""
self.widget = QCustomDockItem(self.parent_widget())
self.widget = QCustomDockItem(self, self.parent_widget())

def init_widget(self):
""" Initialize the state of the underlying widget.
Expand Down
2 changes: 1 addition & 1 deletion enaml/qt/qt_main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

from atom.api import Typed, atomref

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

from .QtCore import Qt
from .QtWidgets import QMainWindow
Expand Down
3 changes: 2 additions & 1 deletion enaml/qt/qt_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from atom.api import Typed, atomref

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

from .QtCore import Qt, QPoint, QRect, QSize
from .QtGui import QIcon
Expand Down
42 changes: 42 additions & 0 deletions enaml/widgets/close_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#------------------------------------------------------------------------------
# Copyright (c) 2013-2017, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import Atom, Bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs a copyright header.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is always a bit unclear to me but can the copyright mention 2013 when the file was created only in 2018 ?



class CloseEvent(Atom):
""" An payload object carried by a widget 'closing' event.

User code can manipulate this object to veto a close event.

"""
#: The internal accepted state.
_accepted = Bool(True)

def is_accepted(self):
""" Get whether or not the event is accepted.

Returns
-------
result : bool
True if the event is accepted, False otherwise. The
default is True.

"""
return self._accepted

def accept(self):
""" Accept the close event and allow the widget to be closed.

"""
self._accepted = True

def ignore(self):
""" Reject the close event and prevent the widget from closing.

"""
self._accepted = False
8 changes: 8 additions & 0 deletions enaml/widgets/dock_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from enaml.icon import Icon
from enaml.layout.geometry import Size

from .close_event import CloseEvent
from .container import Container
from .widget import Widget, ProxyWidget

Expand Down Expand Up @@ -81,6 +82,13 @@ class DockItem(Widget):
#: An event emitted when the title bar is right clicked.
title_bar_right_clicked = d_(Event(), writable=False)

#: An event fired when the user request the dock item to be closed.
#: This will happen when the user clicks on the "X" button in the
#: title bar button, or when the 'close' method is called. The
#: payload will be a CloseEvent object which will allow code to
#: veto the close event and prevent the item from closing.
closing = d_(Event(CloseEvent), writable=False)

#: An event emitted when the dock item is closed. The item will be
#: destroyed after this event has completed.
closed = d_(Event(), writable=False)
Expand Down
35 changes: 1 addition & 34 deletions enaml/widgets/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from enaml.icon import Icon
from enaml.layout.geometry import Pos, Rect, Size

from .close_event import CloseEvent
from .container import Container
from .widget import Widget, ProxyWidget

Expand Down Expand Up @@ -89,40 +90,6 @@ def close(self):
raise NotImplementedError


class CloseEvent(Atom):
""" An payload object carried by a window 'closing' event.

User code can manipulate this object to veto a close event.

"""
#: The internal accepted state.
_accepted = Bool(True)

def is_accepted(self):
""" Get whether or not the event is accepted.

Returns
-------
result : bool
True if the event is accepted, False otherwise. The
default is True.

"""
return self._accepted

def accept(self):
""" Accept the close event and allow the window to be closed.

"""
self._accepted = True

def ignore(self):
""" Reject the close event and prevent the window from closing.

"""
self._accepted = False


class Window(Widget):
""" A top-level Window component.

Expand Down
13 changes: 13 additions & 0 deletions examples/widgets/dock_area.enaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ from enaml.layout.api import (
HSplitLayout, VSplitLayout, TabLayout, InsertItem, hbox, vbox, spacer
)
from enaml.stdlib.dock_area_styles import available_styles
from enaml.stdlib.message_box import question
from enaml.widgets.api import (
Window, Container, DockArea, DockItem, PushButton, Field, Html, Slider,
ObjectCombo, CheckBox, MultilineField
Expand All @@ -31,6 +32,16 @@ def cap_case(name):
return ' '.join(s.capitalize() for s in name.split('-'))


def confirm_close(window, event):
button = question(
window, 'Dock item closing', 'Are you sure you want to close this dock item?'
)
if button and button.action == 'accept':
event.accept()
else:
event.ignore()


class LineCollector(Atom):
""" A simple class used to generate event logging text.

Expand Down Expand Up @@ -87,6 +98,8 @@ enamldef MyDockArea(DockArea):
Field: pass
Field: pass
Field: pass
closing ::
confirm_close(self, change['value'])
DockItem:
name = 'item_2'
title = 'Item 2'
Expand Down