From b40bc521608bca9ea74eb878e9258649c78ae133 Mon Sep 17 00:00:00 2001 From: Alexander Gordeyev Date: Fri, 23 Oct 2015 18:14:25 +0300 Subject: [PATCH] implement progress bar --- gooey/gui/controller.py | 35 +++++++++++++++++++++++ gooey/gui/windows/base_window.py | 7 +++++ gooey/gui/windows/footer.py | 19 ++++++------ gooey/python_bindings/config_generator.py | 4 ++- gooey/python_bindings/gooey_decorator.py | 4 ++- 5 files changed, 57 insertions(+), 12 deletions(-) diff --git a/gooey/gui/controller.py b/gooey/gui/controller.py index 2262ea3..c9905d3 100644 --- a/gooey/gui/controller.py +++ b/gooey/gui/controller.py @@ -6,6 +6,7 @@ Created on Dec 22, 2013 import wx import os +import re import sys import subprocess @@ -113,8 +114,42 @@ class Controller(object): if not line: break wx.CallAfter(self.core_gui.PublishConsoleMsg, line) + progress = self.progress_from_line(line) + if progress is not None: + wx.CallAfter(self.core_gui.UpdateProgressBar, progress) wx.CallAfter(callback, process) + def progress_from_line(self, text): + progress_regex = self.build_spec['progress_regex'] + if not progress_regex: + return None + match = re.search(progress_regex, text.strip()) + if not match: + return None + progress_expr = self.build_spec['progress_expr'] + if progress_expr: + def safe_float(x): + try: + return float(x) + except ValueError: + return x + eval_locals = {k: safe_float(v) for k, v in match.groupdict().items()} + if "x" not in eval_locals: + eval_locals["x"] = [safe_float(x) for x in match.groups()] + try: + value = eval(progress_expr, {}, eval_locals) + except: + return None + else: + try: + value = match.group(1) + except IndexError: + return None + try: + return int(value) + except ValueError: + return None + def process_result(self, process): _stdout, _ = process.communicate() if process.returncode == 0: diff --git a/gooey/gui/windows/base_window.py b/gooey/gui/windows/base_window.py index 0b7f14e..34872ab 100644 --- a/gooey/gui/windows/base_window.py +++ b/gooey/gui/windows/base_window.py @@ -153,6 +153,13 @@ class BaseWindow(wx.Frame): def PublishConsoleMsg(self, text): self.runtime_display.cmd_textbox.AppendText(text) + def UpdateProgressBar(self, value): + pb = self.foot_panel.progress_bar + if value < 0: + pb.Pulse() + else: + pb.SetValue(min(value, pb.GetRange())) + if __name__ == '__main__': pass diff --git a/gooey/gui/windows/footer.py b/gooey/gui/windows/footer.py index b7f22a3..d32c8d3 100644 --- a/gooey/gui/windows/footer.py +++ b/gooey/gui/windows/footer.py @@ -10,7 +10,7 @@ import wx.animate from gooey.gui.pubsub import pub from gooey.gui.lang import i18n -from gooey.gui import imageutil, image_repository, events +from gooey.gui import imageutil, events class AbstractFooter(wx.Panel): @@ -27,7 +27,7 @@ class AbstractFooter(wx.Panel): # components self.cancel_button = None self.start_button = None - self.running_animation = None + self.progress_bar = None self.close_button = None self.stop_button = None self.restart_button = None @@ -50,7 +50,7 @@ class AbstractFooter(wx.Panel): self.restart_button = self.button(i18n._('restart'), wx.ID_OK, event_id=int(events.WINDOW_RESTART)) self.edit_button = self.button(i18n._('edit'), wx.ID_OK, event_id=int(events.WINDOW_EDIT)) - self.running_animation = wx.animate.GIFAnimationCtrl(self, -1, image_repository.loader) + self.progress_bar = wx.Gauge(self, range=100) self.buttons = [self.cancel_button, self.start_button, self.stop_button, self.close_button, self.restart_button, self.edit_button] @@ -59,20 +59,18 @@ class AbstractFooter(wx.Panel): self.hide_all_buttons() self.cancel_button.Show() self.start_button.Show() - self.running_animation.Stop() self.Layout() def running(): self.hide_all_buttons() self.stop_button.Show() - self.running_animation.Show() - self.running_animation.Play() + self.progress_bar.Show() + self.progress_bar.Pulse() self.Layout() def success(): self.hide_all_buttons() - self.running_animation.Stop() - self.running_animation.Hide() + self.progress_bar.Hide() self.edit_button.Show() self.restart_button.Show() self.close_button.Show() @@ -97,6 +95,9 @@ class AbstractFooter(wx.Panel): v_sizer = wx.BoxSizer(wx.VERTICAL) h_sizer = wx.BoxSizer(wx.HORIZONTAL) + h_sizer.Add(self.progress_bar, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 20) + self.progress_bar.Hide() + h_sizer.AddStretchSpacer(1) h_sizer.Add(self.cancel_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 20) h_sizer.Add(self.start_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 20) @@ -104,8 +105,6 @@ class AbstractFooter(wx.Panel): v_sizer.AddStretchSpacer(1) v_sizer.Add(h_sizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND) - v_sizer.Add(self.running_animation, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.RIGHT, 20) - self.running_animation.Hide() h_sizer.Add(self.edit_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 10) h_sizer.Add(self.restart_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 10) diff --git a/gooey/python_bindings/config_generator.py b/gooey/python_bindings/config_generator.py index fc61514..4a51daa 100644 --- a/gooey/python_bindings/config_generator.py +++ b/gooey/python_bindings/config_generator.py @@ -25,7 +25,9 @@ def create_from_parser(parser, source_path, **kwargs): 'num_optional_cols': kwargs.get('optional_cols', 3), 'manual_start': False, 'layout_type': 'column', - 'monospace_display': kwargs.get('monospace_display', False) + 'monospace_display': kwargs.get('monospace_display', False), + 'progress_regex': kwargs.get('progress_regex'), + 'progress_expr': kwargs.get('progress_expr'), } if show_config: diff --git a/gooey/python_bindings/gooey_decorator.py b/gooey/python_bindings/gooey_decorator.py index 91f4210..73405b5 100644 --- a/gooey/python_bindings/gooey_decorator.py +++ b/gooey/python_bindings/gooey_decorator.py @@ -33,7 +33,9 @@ def Gooey(f=None, optional_cols=2, dump_build_config=False, load_build_config=None, - monospace_display=False): + monospace_display=False, + progress_regex=None, + progress_expr=None): ''' Decorator for client code's main function. Serializes argparse data to JSON for use with the Gooey front end