diff --git a/gooey/gui/controller.py b/gooey/gui/controller.py index 74cc128..d1d6358 100644 --- a/gooey/gui/controller.py +++ b/gooey/gui/controller.py @@ -1,20 +1,5 @@ -import os -import re -import wx -import sys - -import subprocess - -from multiprocessing.dummy import Pool - -from gooey.gui.lang import i18n -from gooey.gui import events from gooey.gui.model import MyModel from gooey.gui.presenter import Presenter -from gooey.gui.pubsub import pub -from gooey.gui.util.taskkill import taskkill -from gooey.gui.viewmodel import ViewModel -from gooey.gui.windows import views from gooey.gui.windows.base_window import BaseWindow @@ -30,147 +15,6 @@ class Controller(object): self.presentation = Presenter(self.view, MyModel(self.build_spec)) self.presentation.initialize_view() - # 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) - # pub.subscribe(self.on_edit, events.WINDOW_EDIT) - # - # def on_edit(self): - # pub.send_message(events.WINDOW_CHANGE, view_name=views.CONFIG_SCREEN) - # - # def on_close(self): - # if self.ask_stop(): - # self.view.Destroy() - # sys.exit() - # - # def on_restart(self): - # self.on_start() - # - # def manual_restart(self): - # self.on_start() - # - # def on_cancel(self): - # msg = i18n._('sure_you_want_to_exit') - # result = self.view.show_dialog(msg, i18n._('close_program'), wx.YES_NO) - # if result == YES: - # self.view.Destroy() - # sys.exit() - # - # def on_start(self): - # print self.presentation.view.required_section.get_values() - # print self.presentation.view.optional_section.get_values() - # # if not self.skipping_config() and not self.required_section_complete(): - # # return self.view.show_dialog(i18n._('error_title'), i18n._('error_required_fields'), wx.ICON_ERROR) - # # - # # cmd_line_args = self.view.GetOptions() - # # command = '{} --ignore-gooey {}'.format(self.build_spec['target'], cmd_line_args) - # # pub.send_message(events.WINDOW_CHANGE, view_name=views.RUNNING_SCREEN) - # # self.run_client_code(command) - # - # def on_stop(self): - # self.ask_stop() - # - # def ask_stop(self): - # if not self.running(): - # return True - # if self.build_spec['disable_stop_button']: - # return False - # msg = i18n._('sure_you_want_to_stop') - # result = self.view.show_dialog(msg, i18n._('stop_task'), wx.YES_NO) - # 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): - # 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)) - # - # def read_stdout(self, process, callback): - # while True: - # line = process.stdout.readline() - # if not line: - # break - # wx.CallAfter(self.view.PublishConsoleMsg, line) - # progress = self.progress_from_line(line) - # if progress is not None: - # wx.CallAfter(self.view.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: - # return self._eval_progress(match, progress_expr) - # else: - # return self._search_progress(match) - # - # def _search_progress(self, match): - # try: - # return int(float(match.group(1))) - # except: - # return None - # - # def _eval_progress(self, match, eval_expr): - # def safe_float(x): - # try: - # return float(x) - # except ValueError: - # return x - # _locals = {k: safe_float(v) for k, v in match.groupdict().items()} - # if "x" not in _locals: - # _locals["x"] = [safe_float(x) for x in match.groups()] - # try: - # return int(float(eval(eval_expr, {}, _locals))) - # except: - # return None - # - # def process_result(self, process): - # _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() - # - # # def skipping_config(self): - # # return self.build_spec['manual_start'] - # # - # # def required_section_complete(self): - # # required_section = self.view.GetRequiredArgs() - # # if len(required_section) == 0: - # # return True # no requirements! - # # return not any(req == '' for req in required_section) - # - # def success_dialog(self): - # self.view.show_dialog(i18n._("execution_finished"), i18n._('success_message'), wx.ICON_INFORMATION) - # - # def error_dialog(self): - # self.view.show_dialog(i18n._('error_title'), i18n._('uh_oh'), wx.ICON_ERROR) def run(self): self.view.Show(True) diff --git a/gooey/gui/presenter.py b/gooey/gui/presenter.py index 9a4308f..9cb01ca 100644 --- a/gooey/gui/presenter.py +++ b/gooey/gui/presenter.py @@ -1,23 +1,15 @@ -import re -from collections import namedtuple - -import subprocess - import sys -from gooey.gui import component_builder from gooey.gui.processor import ProcessController -from gooey.gui.lang.i18n import _ from gooey.gui.model import States from gooey.gui.pubsub import pub from gooey.gui import events -from gooey.gui.windows import views -from multiprocessing.dummy import Pool class Presenter(object): def __init__(self, view, model): self.view = view self.model = model + self.client_runner = ProcessController( self.model.progress_regex, self.model.progress_expr @@ -30,8 +22,6 @@ class Presenter(object): pub.subscribe(self.on_edit, events.WINDOW_EDIT) pub.subscribe(self.on_close, events.WINDOW_CLOSE) - - # console statuses from the other thread pub.subscribe(self.on_new_message, 'console_update') pub.subscribe(self.on_progress_change, 'progress_update') @@ -55,12 +45,29 @@ class Presenter(object): self.syncronize_from_model() - def on_edit(self): - self.model.update_state(States.CONFIGURING) + def update_model(self): + self.update_list(self.model.required_args, self.view.required_section.get_values()) + self.update_list(self.model.optional_args, self.view.optional_section.get_values()) self.syncronize_from_model() - def on_restart(self): - self.on_start() + def syncronize_from_model(self): + # update heading titles + self.view.heading_title = self.model.heading_title + self.view.heading_subtitle = self.model.heading_subtitle + if not self.model.stop_button_disabled: + self.view.enable_stop_button() + + # refresh the widgets + for index, widget in enumerate(self.view.required_section): + widget.set_value(self.model.required_args[index]._value) + for index, widget in enumerate(self.view.optional_section): + widget.set_value(self.model.optional_args[index]._value) + + # swap the views + getattr(self, self.model.current_state)() + + def should_disable_stop_button(self): + return self.model.stop_button_disabled def on_start(self): self.update_model() @@ -71,6 +78,25 @@ class Presenter(object): self.model.update_state(States.RUNNNING) self.syncronize_from_model() + def on_stop(self): + self.ask_stop() + + def on_edit(self): + self.model.update_state(States.CONFIGURING) + self.syncronize_from_model() + + def on_restart(self): + self.on_start() + + def on_cancel(self): + if self.view.confirm_exit_dialog(): + self.view.Destroy() + sys.exit() + + def on_close(self): + self.view.Destroy() + sys.exit() + def on_new_message(self, msg): # observes changes coming from the subprocess self.view.update_console_async(msg) @@ -86,24 +112,6 @@ class Presenter(object): self.model.update_state(States.ERROR) self.syncronize_from_model() - def update_model(self): - self.update_list(self.model.required_args, self.view.required_section.get_values()) - self.update_list(self.model.optional_args, self.view.optional_section.get_values()) - self.syncronize_from_model() - - def on_cancel(self): - if self.view.confirm_exit_dialog(): - self.view.Destroy() - sys.exit() - - def on_stop(self): - self.ask_stop() - - def on_close(self): - if self.ask_stop(): - self.view.Destroy() - sys.exit() - def ask_stop(self): if self.view.confirm_stop_dialog(): self.stop() @@ -113,32 +121,14 @@ class Presenter(object): def stop(self): self.client_runner.stop() - def update_list(self, collection, new_values): - for index, val in enumerate(new_values): - collection[index].value = val - @staticmethod def partition(collection, condition): return filter(condition, collection), filter(lambda x: not condition(x), collection) - def syncronize_from_model(self): - # update heading titles - self.view.heading_title = self.model.heading_title - self.view.heading_subtitle = self.model.heading_subtitle - if not self.model.stop_button_disabled: - self.view.enable_stop_button() - - # refresh the widgets - for index, widget in enumerate(self.view.required_section): - widget.set_value(self.model.required_args[index]._value) - for index, widget in enumerate(self.view.optional_section): - widget.set_value(self.model.optional_args[index]._value) - - # swap the views - getattr(self, self.model.current_state)() - - def should_disable_stop_button(self): - return self.model.stop_button_disabled + def update_list(self, collection, new_values): + # convenience method for syncronizing the model -> widget list collections + for index, val in enumerate(new_values): + collection[index].value = val def configuring(self): self.view.hide_all_buttons()