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 os
import sys
import subprocess
@ -14,12 +15,13 @@ from multiprocessing.dummy import Pool
from gooey.gui import events
from gooey.gui.lang import i18n
from gooey.gui.windows import views
from gooey.gui.util.taskkill import taskkill
YES = 5103
NO = 5104
class Controller(object):
'''
Main controller for the gui.
@ -34,9 +36,11 @@ class Controller(object):
'''
self.core_gui = base_frame
self.build_spec = build_spec
self._process = None
# wire up all the observers
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_restart, events.WINDOW_RESTART)
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)
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):
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.apply_async(self.read_stdout, (p, self.process_result))
@ -88,13 +116,13 @@ class Controller(object):
wx.CallAfter(callback, process)
def process_result(self, process):
_stdout, _stderr = process.communicate()
_stdout, _ = process.communicate()
if process.returncode == 0:
pub.send_message(events.WINDOW_CHANGE, view_name=views.SUCCESS_SCREEN)
self.success_dialog()
else:
pub.send_message(events.WINDOW_CHANGE, view_name=views.ERROR_SCREEN)
self.error_dialog(_stderr)
self.error_dialog()
def skipping_config(self):
return self.build_spec['manual_start']
@ -108,8 +136,8 @@ class Controller(object):
def success_dialog(self):
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):
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.Add(self.text_box, 1, wx.EXPAND)
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)
return widget_sizer

13
gooey/gui/windows/base_window.py

@ -40,6 +40,7 @@ class BaseWindow(wx.Frame):
self._init_controller()
self.registerControllers()
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)))
@ -137,6 +138,18 @@ class BaseWindow(wx.Frame):
def onResize(self, evt):
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):
self.runtime_display.cmd_textbox.AppendText(text)

2
gooey/gui/windows/footer.py

@ -64,6 +64,7 @@ class AbstractFooter(wx.Panel):
def running():
self.hide_all_buttons()
self.stop_button.Show()
self.running_animation.Show()
self.running_animation.Play()
self.Layout()
@ -99,6 +100,7 @@ class AbstractFooter(wx.Panel):
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)
h_sizer.Add(self.stop_button, 0, wx.ALIGN_RIGHT | wx.RIGHT, 20)
v_sizer.AddStretchSpacer(1)
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',
'optional_args_msg': 'Optional Arguments', # popup dialogs
"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',
'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",
'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_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",
"error_required_fields": "Must fill in all fields in the Required section!",
"start": "Start",
@ -19,8 +20,9 @@
"status": "Status",
"restart": "Restart",
"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"
}

4
gooey/python_bindings/docopt_to_json.py

@ -28,7 +28,7 @@ Options:
# types?
import re
from docopt import docopt, Option, Argument
@ -51,7 +51,7 @@ class MyOption(Option):
else:
argcount = 1
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
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
'''
import sys
import os
import json
import atexit
@ -13,7 +14,6 @@ import tempfile
from . import source_parser
from . import config_generator
import sys
from gooey.gui import application
@ -58,7 +58,7 @@ def Gooey(f=None,
if dump_build_config:
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:
f.write(json.dumps(build_spec, indent=2))
application.run(build_spec)

1
gooey/python_bindings/gooey_parser.py

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

Loading…
Cancel
Save