mirror of https://github.com/chriskiehl/Gooey.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.3 KiB
190 lines
6.3 KiB
import sys
|
|
|
|
from gooey.gui.processor import ProcessController
|
|
from gooey.gui.model import States
|
|
from gooey.gui.pubsub import pub
|
|
from gooey.gui import events
|
|
from gooey.gui.windows import layouts
|
|
|
|
import wx
|
|
|
|
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
|
|
)
|
|
|
|
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_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')
|
|
pub.subscribe(self.on_client_done, 'execution_complete')
|
|
|
|
|
|
pub.subscribe(self.on_selection_change, events.LIST_BOX)
|
|
|
|
|
|
def on_selection_change(self, selection):
|
|
self.update_model()
|
|
self.model.active_group = selection
|
|
self.redraw_from_model()
|
|
self.syncronize_from_model()
|
|
|
|
def initialize_view(self):
|
|
self.view.window_title = self.model.program_name
|
|
self.view.window_size = self.model.default_size
|
|
|
|
self.view.required_section.clear()
|
|
self.view.optional_section.clear()
|
|
self.view.required_section.populate(self.model.required_args, self.model.num_required_cols)
|
|
self.view.optional_section.populate(self.model.optional_args, self.model.num_optional_cols)
|
|
|
|
if self.model.use_monospace_font:
|
|
self.view.set_display_font_style('monospace')
|
|
|
|
if self.should_disable_stop_button():
|
|
self.view.disable_stop_button()
|
|
else:
|
|
self.view.enable_stop_button()
|
|
|
|
if self.model.layout_type == layouts.COLUMN:
|
|
self.view.set_list_contents(self.model.argument_groups.keys())
|
|
|
|
if self.model.auto_start:
|
|
self.model.update_state(States.RUNNNING)
|
|
self.on_start()
|
|
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 syncronize_from_model(self):
|
|
#TODO move this out of the presenter
|
|
#TODO Make all view interactions thread safe
|
|
wx.CallAfter(self.syncronize_from_model_async)
|
|
|
|
def syncronize_from_model_async(self):
|
|
# update heading titles
|
|
self.view.heading_title = self.model.heading_title
|
|
self.view.heading_subtitle = self.model.heading_subtitle
|
|
|
|
# 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 redraw_from_model(self):
|
|
self.view.freeze()
|
|
self.view.required_section.clear()
|
|
self.view.optional_section.clear()
|
|
self.view.required_section.populate(self.model.required_args, self.model.num_required_cols)
|
|
self.view.optional_section.populate(self.model.optional_args, self.model.num_optional_cols)
|
|
getattr(self, self.model.current_state)()
|
|
self.view.thaw()
|
|
|
|
def should_disable_stop_button(self):
|
|
return self.model.stop_button_disabled
|
|
|
|
def on_start(self):
|
|
self.update_model()
|
|
if not self.model.is_valid():
|
|
return self.view.show_missing_args_dialog()
|
|
command = self.model.build_command_line_string()
|
|
self.client_runner.run(command)
|
|
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)
|
|
|
|
def on_progress_change(self, progress):
|
|
# observes changes coming from the subprocess
|
|
self.view.update_progress_aync(progress, self.model.disable_progress_bar_animation)
|
|
|
|
def on_client_done(self):
|
|
if self.client_runner.was_success():
|
|
self.model.update_state(States.SUCCESS)
|
|
else:
|
|
self.model.update_state(States.ERROR)
|
|
self.syncronize_from_model()
|
|
|
|
def ask_stop(self):
|
|
if self.view.confirm_stop_dialog():
|
|
self.stop()
|
|
return True
|
|
return False
|
|
|
|
def stop(self):
|
|
self.client_runner.stop()
|
|
|
|
def configuring(self):
|
|
self.view.hide_all_buttons()
|
|
self.view.hide('check_mark', 'running_img', 'error_symbol', 'runtime_display')
|
|
self.view.show('settings_img', 'cancel_button', 'start_button', 'config_panel')
|
|
self.view.Layout()
|
|
|
|
def running(self):
|
|
self.view.hide_all_buttons()
|
|
self.view.hide('check_mark', 'settings_img', 'error_symbol', 'config_panel')
|
|
self.view.show('running_img', 'stop_button', 'progress_bar', 'runtime_display')
|
|
self.view.progress_bar.Pulse()
|
|
self.view.Layout()
|
|
|
|
def success(self):
|
|
self.view.hide_all_buttons()
|
|
self.view.hide('running_img', 'progress_bar', 'config_panel')
|
|
self.view.show('check_mark', 'edit_button', 'restart_button', 'close_button', 'runtime_display')
|
|
self.view.Layout()
|
|
|
|
def error(self):
|
|
self.view.hide_all_buttons()
|
|
self.view.hide('running_img', 'progress_bar', 'config_panel')
|
|
self.view.show('error_symbol', 'edit_button', 'restart_button', 'close_button', 'runtime_display')
|
|
self.view.Layout()
|
|
|
|
@staticmethod
|
|
def partition(collection, condition):
|
|
return filter(condition, collection), filter(lambda x: not condition(x), collection)
|
|
|
|
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
|
|
|
|
|