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

Timed messages in StatusBar #522

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
25 changes: 25 additions & 0 deletions pyface/tests/test_application_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,31 @@ def test_statusbar_changed(self):
with self.event_loop():
self.window.close()

def test_statusbar_timed_changed(self):
from time import sleep

# test that status bar gets changed as expected
self.window.status_bar_manager = StatusBarManager(
message="hello world"
)
with self.event_loop():
self.window._create()
with self.event_loop():
self.window.show(True)
with self.event_loop():
duration = 0.3
status_bar = self.window.status_bar_manager
status_bar.message_duration_sec = duration
status_bar.messages = ["goodbye world"]
self.assertEqual(status_bar.message, "goodbye world")
sleep(duration)
self.gui.process_events()
self.assertEqual(status_bar.message, "")
with self.event_loop():
self.window.show(False)
with self.event_loop():
self.window.close()

def test_icon(self):
# test that status bar gets created as expected
self.window.icon = ImageResource("core")
Expand Down
37 changes: 29 additions & 8 deletions pyface/ui/qt4/action/status_bar_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
from pyface.qt import QtGui


from traits.api import Any, Bool, HasTraits, List, Property, Str
from traits.api import Any, Bool, Float, HasTraits, Instance, List, Property, \
Str
from pyface.timer.api import Timer


class StatusBarManager(HasTraits):
Expand All @@ -38,6 +40,11 @@ class StatusBarManager(HasTraits):
# Whether the status bar is visible.
visible = Bool(True)

# Number of seconds to display new messages for [default: indefinitely]
message_duration_sec = Float

_timer = Instance(Timer)

# ------------------------------------------------------------------------
# 'StatusBarManager' interface.
# ------------------------------------------------------------------------
Expand All @@ -49,17 +56,17 @@ def create_status_bar(self, parent):
self.status_bar = QtGui.QStatusBar(parent)
self.status_bar.setSizeGripEnabled(self.size_grip)
self.status_bar.setVisible(self.visible)

if len(self.messages) > 1:
self._show_messages()
else:
self.status_bar.showMessage(self.message)
self._show_messages()

return self.status_bar

def destroy_status_bar(self):
""" Destroys the status bar. """
if self.status_bar is not None:
if self._timer is not None:
self._timer.Stop()
self._timer = None

self.status_bar.deleteLater()
self.status_bar = None

Expand All @@ -68,7 +75,6 @@ def destroy_status_bar(self):
# ------------------------------------------------------------------------

def _get_message(self):

if len(self.messages) > 0:
message = self.messages[0]
else:
Expand Down Expand Up @@ -120,10 +126,25 @@ def _visible_changed(self):
# ------------------------------------------------------------------------

def _show_messages(self):
""" Display the list of messages. """
""" Display the list of messages.

Note: not using the msecs argument of the `status_bar.showNessage`
method to keep this class' message trait in sync with the Qt widget.
"""
def timed_action():
self.messages = []
self._timer.Stop()
self._timer = None

if self.status_bar is None:
return

# FIXME v3: At the moment we just string them together but we may
# decide to put all but the first message into separate widgets. We
# probably also need to extend the API to allow a "message" to be a
# widget - depends on what wx is capable of.
self.status_bar.showMessage(" ".join(self.messages))

# Schedule removing the message if needed:
if self.message_duration_sec > 0 and self._timer is None:
self._timer = Timer(self.message_duration_sec * 1000, timed_action)
43 changes: 27 additions & 16 deletions pyface/ui/wx/action/status_bar_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import wx


from traits.api import Any, HasTraits, List, Property, Str
from traits.api import Any, Float, HasTraits, Instance, List, on_trait_change,\
Property, Str
from pyface.timer.api import Timer


class StatusBarManager(HasTraits):
Expand All @@ -31,29 +33,35 @@ class StatusBarManager(HasTraits):
# The toolkit-specific control that represents the status bar.
status_bar = Any()

# Number of seconds to display new messages for [default: indefinitely]
message_duration_sec = Float

_timer = Instance(Timer)

# ------------------------------------------------------------------------
# 'StatusBarManager' interface.
# ------------------------------------------------------------------------

def create_status_bar(self, parent):
""" Creates a status bar. """

if self.status_bar is None:
self.status_bar = wx.StatusBar(parent)
self.status_bar._pyface_control = self
if len(self.messages) > 1:
self.status_bar.SetFieldsCount(len(self.messages))
for i in range(len(self.messages)):
self.status_bar.SetStatusText(self.messages[i], i)
else:
self.status_bar.SetStatusText(self.message)

self.messages_changed()

return self.status_bar

def remove_status_bar(self, parent):
""" Removes a status bar. """

if self.status_bar is not None:
if self._timer is not None:
self._timer.Stop()
self._timer = None

self.status_bar.Destroy()
self.status_bar._pyface_control = None
self.status_bar = None
Expand Down Expand Up @@ -92,18 +100,21 @@ def _set_message(self, value):
# Trait event handlers.
# ------------------------------------------------------------------------

def _messages_changed(self):
@on_trait_change("messages[]", post_init=True)
def messages_changed(self):
""" Sets the text displayed on the status bar. """

if self.status_bar is not None:
for i in range(len(self.messages)):
self.status_bar.SetStatusText(self.messages[i], i)
def timed_action():
self.messages = []
self._timer.Stop()
self._timer = None

def _messages_items_changed(self):
""" Sets the text displayed on the status bar. """
if self.status_bar is None:
return

if self.status_bar is not None:
for i in range(len(self.messages)):
self.status_bar.SetStatusText(self.messages[i], i)
for i in range(len(self.messages)):
self.status_bar.SetStatusText(self.messages[i], i)

return
# Schedule removing the message if needed:
if self.message_duration_sec > 0 and self._timer is None:
self._timer = Timer(self.message_duration_sec * 1000, timed_action)