Browse Source

implement Stop button

pull/120/head
Alexander Gordeyev 9 years ago
parent
commit
369b7898b0
10 changed files with 91 additions and 33 deletions
  1. 40
      gooey/gui/controller.py
  2. 11
      gooey/gui/util/taskkill.py
  3. 2
      gooey/gui/widgets/widget_pack.py
  4. 13
      gooey/gui/windows/base_window.py
  5. 2
      gooey/gui/windows/footer.py
  6. 17
      gooey/languages/eng.py
  7. 30
      gooey/languages/english.json
  8. 4
      gooey/python_bindings/docopt_to_json.py
  9. 4
      gooey/python_bindings/gooey_decorator.py
  10. 1
      gooey/python_bindings/gooey_parser.py

40
gooey/gui/controller.py

@ -5,6 +5,7 @@ Created on Dec 22, 2013
''' '''
import wx import wx
import os
import sys import sys
import subprocess import subprocess
@ -14,12 +15,13 @@ from multiprocessing.dummy import Pool
from gooey.gui import events from gooey.gui import events
from gooey.gui.lang import i18n from gooey.gui.lang import i18n
from gooey.gui.windows import views from gooey.gui.windows import views
from gooey.gui.util.taskkill import taskkill
YES = 5103 YES = 5103
NO = 5104 NO = 5104
class Controller(object): class Controller(object):
''' '''
Main controller for the gui. Main controller for the gui.
@ -34,9 +36,11 @@ class Controller(object):
''' '''
self.core_gui = base_frame self.core_gui = base_frame
self.build_spec = build_spec self.build_spec = build_spec
self._process = None
# wire up all the observers # wire up all the observers
pub.subscribe(self.on_cancel, events.WINDOW_CANCEL) pub.subscribe(self.on_cancel, events.WINDOW_CANCEL)
pub.subscribe(self.on_stop, events.WINDOW_STOP)
pub.subscribe(self.on_start, events.WINDOW_START) pub.subscribe(self.on_start, events.WINDOW_START)
pub.subscribe(self.on_restart, events.WINDOW_RESTART) pub.subscribe(self.on_restart, events.WINDOW_RESTART)
pub.subscribe(self.on_close, events.WINDOW_CLOSE) pub.subscribe(self.on_close, events.WINDOW_CLOSE)
@ -74,8 +78,32 @@ class Controller(object):
pub.send_message(events.WINDOW_CHANGE, view_name=views.RUNNING_SCREEN) pub.send_message(events.WINDOW_CHANGE, view_name=views.RUNNING_SCREEN)
self.run_client_code(command) self.run_client_code(command)
def on_stop(self):
if not self.running():
return True
msg = i18n._('sure_you_want_to_stop')
dlg = wx.MessageDialog(None, msg, i18n._('stop_task'), wx.YES_NO)
result = dlg.ShowModal()
dlg.Destroy()
if result == YES:
self.stop()
return True
return False
def stop(self):
if self.running():
taskkill(self._process.pid)
def running(self):
return self._process and self._process.poll() is None
def run_client_code(self, command): def run_client_code(self, command):
p = subprocess.Popen(command, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
env = os.environ.copy()
env["GOOEY"] = "1"
print "run command:", command
p = subprocess.Popen(command, bufsize=1, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, shell=True, env=env)
self._process = p
pool = Pool(1) pool = Pool(1)
pool.apply_async(self.read_stdout, (p, self.process_result)) pool.apply_async(self.read_stdout, (p, self.process_result))
@ -88,13 +116,13 @@ class Controller(object):
wx.CallAfter(callback, process) wx.CallAfter(callback, process)
def process_result(self, process): def process_result(self, process):
_stdout, _stderr = process.communicate()
_stdout, _ = process.communicate()
if process.returncode == 0: if process.returncode == 0:
pub.send_message(events.WINDOW_CHANGE, view_name=views.SUCCESS_SCREEN) pub.send_message(events.WINDOW_CHANGE, view_name=views.SUCCESS_SCREEN)
self.success_dialog() self.success_dialog()
else: else:
pub.send_message(events.WINDOW_CHANGE, view_name=views.ERROR_SCREEN) pub.send_message(events.WINDOW_CHANGE, view_name=views.ERROR_SCREEN)
self.error_dialog(_stderr)
self.error_dialog()
def skipping_config(self): def skipping_config(self):
return self.build_spec['manual_start'] return self.build_spec['manual_start']
@ -108,8 +136,8 @@ class Controller(object):
def success_dialog(self): def success_dialog(self):
self.show_dialog(i18n._("execution_finished"), i18n._('success_message'), wx.ICON_INFORMATION) self.show_dialog(i18n._("execution_finished"), i18n._('success_message'), wx.ICON_INFORMATION)
def error_dialog(self, error_msg):
self.show_dialog(i18n._('error_title'), i18n._('uh_oh').format(error_msg), wx.ICON_ERROR)
def error_dialog(self):
self.show_dialog(i18n._('error_title'), i18n._('uh_oh'), wx.ICON_ERROR)
def show_dialog(self, title, content, style): def show_dialog(self, title, content, style):
a = wx.MessageDialog(None, content, title, style) a = wx.MessageDialog(None, content, title, style)

11
gooey/gui/util/taskkill.py

@ -0,0 +1,11 @@
import sys
import os
import signal
if sys.platform.startswith("win"):
def taskkill(pid):
os.system('taskkill /F /PID {:d} /T >NUL 2>NUL'.format(pid))
else: # POSIX
def taskkill(pid):
os.kill(pid, signal.SIGTERM)

2
gooey/gui/widgets/widget_pack.py

@ -60,7 +60,7 @@ class BaseChooser(WidgetPack):
widget_sizer = wx.BoxSizer(wx.HORIZONTAL) widget_sizer = wx.BoxSizer(wx.HORIZONTAL)
widget_sizer.Add(self.text_box, 1, wx.EXPAND) widget_sizer.Add(self.text_box, 1, wx.EXPAND)
widget_sizer.AddSpacer(10) widget_sizer.AddSpacer(10)
widget_sizer.Add(self.button, 0)
widget_sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
parent.Bind(wx.EVT_BUTTON, self.onButton, self.button) parent.Bind(wx.EVT_BUTTON, self.onButton, self.button)
return widget_sizer return widget_sizer

13
gooey/gui/windows/base_window.py

@ -40,6 +40,7 @@ class BaseWindow(wx.Frame):
self._init_controller() self._init_controller()
self.registerControllers() self.registerControllers()
self.Bind(wx.EVT_SIZE, self.onResize) self.Bind(wx.EVT_SIZE, self.onResize)
self.Bind(wx.EVT_CLOSE, self.onClose)
self.Bind(wx.EVT_CLOSE, lambda x: pub.send_message(str(events.WINDOW_CLOSE))) self.Bind(wx.EVT_CLOSE, lambda x: pub.send_message(str(events.WINDOW_CLOSE)))
@ -137,6 +138,18 @@ class BaseWindow(wx.Frame):
def onResize(self, evt): def onResize(self, evt):
evt.Skip() evt.Skip()
def onClose(self, evt):
if evt.CanVeto():
if self._controller.on_stop():
self._controller.on_close()
else:
evt.Veto()
return
else:
self._controller.stop()
self._controller.on_close()
evt.Skip()
def PublishConsoleMsg(self, text): def PublishConsoleMsg(self, text):
self.runtime_display.cmd_textbox.AppendText(text) self.runtime_display.cmd_textbox.AppendText(text)

2
gooey/gui/windows/footer.py

@ -64,6 +64,7 @@ class AbstractFooter(wx.Panel):
def running(): def running():
self.hide_all_buttons() self.hide_all_buttons()
self.stop_button.Show()
self.running_animation.Show() self.running_animation.Show()
self.running_animation.Play() self.running_animation.Play()
self.Layout() self.Layout()
@ -99,6 +100,7 @@ class AbstractFooter(wx.Panel):
h_sizer.AddStretchSpacer(1) h_sizer.AddStretchSpacer(1)
h_sizer.Add(self.cancel_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 20) 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) h_sizer.Add(self.start_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 20)
h_sizer.Add(self.stop_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 20)
v_sizer.AddStretchSpacer(1) v_sizer.AddStretchSpacer(1)
v_sizer.Add(h_sizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND) v_sizer.Add(h_sizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)

17
gooey/languages/eng.py

@ -25,17 +25,18 @@ if __name__ == '__main__':
'required_args_msg': 'Required Arguments', 'required_args_msg': 'Required Arguments',
'optional_args_msg': 'Optional Arguments', # popup dialogs 'optional_args_msg': 'Optional Arguments', # popup dialogs
"sure_you_want_to_exit": "Are you sure you want to exit?", "sure_you_want_to_exit": "Are you sure you want to exit?",
'close_program': 'Close Program?',
'close_program': 'Close program?',
'sure_you_want_to_stop': 'Are you sure you want to stop the task? ' +
'\nInterruption can corrupt your data!',
'stop_task': 'Stop task?',
'status': 'Status', 'status': 'Status',
'uh_oh': ''' 'uh_oh': '''
Uh oh! Looks like there was a problem.
Copy the below error to let your developer know what went wrong.
{}
''',
Uh oh! Looks like there was a problem.
Copy the text from status window to let your developer know what went wrong.
''',
'error_title': "Error", 'error_title': "Error",
'execution_finished': 'Execution Finished',
'success_message': 'Program completed Sucessfully!',
'execution_finished': 'Execution finished',
'success_message': 'Program completed sucessfully!',
} }

30
gooey/languages/english.json

@ -1,17 +1,18 @@
{ {
"cancel": "Cancel",
"close": "Close",
"close_program": "Close Program?",
"error_title": "Error",
"execution_finished": "Execution Finished",
"cancel": "Cancel",
"close": "Close",
"close_program": "Close program?",
"stop_task": "Stop task?",
"error_title": "Error",
"execution_finished": "Execution finished",
"finished_msg": "All done! You may now safely close the program.", "finished_msg": "All done! You may now safely close the program.",
"finished_error": "An error has occurred.", "finished_error": "An error has occurred.",
"finished_title": "Finished",
"optional_args_msg": "Optional Arguments",
"required_args_msg": "Required Arguments",
"running_msg": "Please wait while the application performs its tasks. \nThis may take a few moments",
"running_title": "Running",
"settings_title": "Settings",
"finished_title": "Finished",
"optional_args_msg": "Optional Arguments",
"required_args_msg": "Required Arguments",
"running_msg": "Please wait while the application performs its tasks. \nThis may take a few moments",
"running_title": "Running",
"settings_title": "Settings",
"simple_config": "Enter Command Line Arguments", "simple_config": "Enter Command Line Arguments",
"error_required_fields": "Must fill in all fields in the Required section!", "error_required_fields": "Must fill in all fields in the Required section!",
"start": "Start", "start": "Start",
@ -19,8 +20,9 @@
"status": "Status", "status": "Status",
"restart": "Restart", "restart": "Restart",
"edit": "Edit", "edit": "Edit",
"success_message": "Program completed Sucessfully!\nPress the OK button to exit",
"sure_you_want_to_exit": "Are you sure you want to exit?",
"uh_oh": "\nUh oh! Looks like there was a problem. \nCopy the below error to let your developer know what went wrong.\n\n{} \t\t\n\t\t",
"success_message": "Program completed sucessfully!",
"sure_you_want_to_exit": "Are you sure you want to exit?",
"sure_you_want_to_stop": "Are you sure you want to stop the task? \nInterruption can corrupt your data!!",
"uh_oh": "\nUh oh! Looks like there was a problem. \nCopy the text from status window to let your developer know what went wrong.\n",
"browse": "Browse" "browse": "Browse"
} }

4
gooey/python_bindings/docopt_to_json.py

@ -28,7 +28,7 @@ Options:
# types? # types?
import re
from docopt import docopt, Option, Argument from docopt import docopt, Option, Argument
@ -51,7 +51,7 @@ class MyOption(Option):
else: else:
argcount = 1 argcount = 1
if argcount: if argcount:
matched = re.findall('\[default: (.*)\]', description, flags=re.I)
matched = re.findall(r'\[default: (.*)\]', description, flags=re.I)
value = matched[0] if matched else None value = matched[0] if matched else None
return class_(short, long, argcount, value, description=description.strip()) return class_(short, long, argcount, value, description=description.strip())

4
gooey/python_bindings/gooey_decorator.py

@ -6,6 +6,7 @@ Created on Jan 24, 2014
TODO: this TODO: this
''' '''
import sys
import os import os
import json import json
import atexit import atexit
@ -13,7 +14,6 @@ import tempfile
from . import source_parser from . import source_parser
from . import config_generator from . import config_generator
import sys
from gooey.gui import application from gooey.gui import application
@ -58,7 +58,7 @@ def Gooey(f=None,
if dump_build_config: if dump_build_config:
config_path = os.path.join(os.getcwd(), 'gooey_config.json') config_path = os.path.join(os.getcwd(), 'gooey_config.json')
print( 'Writing Build Config to: {}'.format(config_path))
print 'Writing Build Config to: {}'.format(config_path)
with open(config_path, 'w') as f: with open(config_path, 'w') as f:
f.write(json.dumps(build_spec, indent=2)) f.write(json.dumps(build_spec, indent=2))
application.run(build_spec) application.run(build_spec)

1
gooey/python_bindings/gooey_parser.py

@ -1,4 +1,5 @@
from argparse import ArgumentParser, _SubParsersAction from argparse import ArgumentParser, _SubParsersAction
from gooey.gui.lang.i18n import _
class GooeySubParser(_SubParsersAction): class GooeySubParser(_SubParsersAction):

Loading…
Cancel
Save