def __init__(self, cfg, updater, ttreeview, ttree_paths, info_bar, theme): super(TreeUpdater, self).__init__() self.quit = False self.autoexpand = True self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar self.last_update_time = None self.ancestors = {} self.descendants = [] self.autoexpand_states = [ 'queued', 'submitting', 'submitted', 'running', 'failed' ] self._last_autoexpand_me = [] self.ttree_paths = ttree_paths # Dict of paths vs all descendant node states self.should_group_families = ("text" not in self.cfg.ungrouped_views) self.ttreeview = ttreeview # Hierarchy of models: view <- sorted <- filtered <- base model self.ttreestore = ttreeview.get_model().get_model().get_model() dotm = DotMaker(theme) self.dots = {} for state in task_state.legal: self.dots[state] = dotm.get_icon(state) self.dots['empty'] = dotm.get_icon()
def _set_key_liststore(self): dotm = DotMaker(self._theme, self._dot_size) self._key_liststore.clear() for state in task_state.legal: dot = dotm.get_icon(state) self._key_liststore.append([state, dot]) self._key_liststore.append(['(unknown)', dotm.get_icon('unknown')])
def _set_key_liststore(self): dotm = DotMaker(self._theme, self._dot_size) self._key_liststore.clear() for state in task_state.legal: dot = dotm.get_icon(state) self._key_liststore.append([ state, dot]) self._key_liststore.append(['(unknown)', dotm.get_icon('unknown')])
def __init__(self, cfg, updater, ttreeview, ttree_paths, info_bar, theme): super(TreeUpdater, self).__init__() self.quit = False self.autoexpand = True self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar self.last_update_time = None self.ancestors = {} self.descendants = [] self.autoexpand_states = ["queued", "submitting", "submitted", "running", "failed"] self._last_autoexpand_me = [] self.ttree_paths = ttree_paths # Dict of paths vs all descendant node states self.should_group_families = "text" not in self.cfg.ungrouped_views self.ttreeview = ttreeview # Hierarchy of models: view <- sorted <- filtered <- base model self.ttreestore = ttreeview.get_model().get_model().get_model() dotm = DotMaker(theme) self.dots = {} for state in task_state.legal: self.dots[state] = dotm.get_icon(state) self.dots["empty"] = dotm.get_icon()
def __init__(self, cfg, updater, treeview, info_bar, theme): super(DotUpdater, self).__init__() self.quit = False self.action_required = False self.autoexpand = True self.should_hide_headings = False self.should_group_families = ("dot" not in cfg.ungrouped_views) self.should_transpose_view = False self.is_transposed = False self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar imagedir = self.cfg.imagedir self.last_update_time = None self.state_summary = {} self.fam_state_summary = {} self.ancestors_pruned = {} self.descendants = [] self.filter = "" self.led_headings = [] self.led_treeview = treeview self.led_liststore = treeview.get_model() self._prev_tooltip_task_id = None if hasattr(self.led_treeview, "set_has_tooltip"): self.led_treeview.set_has_tooltip(True) try: self.led_treeview.connect('query-tooltip', self.on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.task_list = [] # generate task state icons dotm = DotMaker(theme) self.dots = {} for state in task_state.legal: self.dots[state] = dotm.get_icon(state) self.dots['empty'] = dotm.get_icon() self.led_digits_one = [] self.led_digits_two = [] self.led_digits_blank = gtk.gdk.pixbuf_new_from_file( imagedir + "/digits/one/digit-blank.xpm") for i in range(10): self.led_digits_one.append( gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/one/digit-" + str(i) + ".xpm")) self.led_digits_two.append( gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/two/digit-" + str(i) + ".xpm"))
def __init__(self, cfg, updater, treeview, info_bar, theme): super(DotUpdater, self).__init__() self.quit = False self.action_required = False self.autoexpand = True self.should_hide_headings = False self.should_group_families = "dot" not in cfg.ungrouped_views self.should_transpose_view = False self.is_transposed = False self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar imagedir = self.cfg.imagedir self.last_update_time = None self.state_summary = {} self.fam_state_summary = {} self.ancestors_pruned = {} self.descendants = [] self.filter = "" self.led_headings = [] self.led_treeview = treeview self.led_liststore = treeview.get_model() self._prev_tooltip_task_id = None if hasattr(self.led_treeview, "set_has_tooltip"): self.led_treeview.set_has_tooltip(True) try: self.led_treeview.connect("query-tooltip", self.on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.task_list = [] # generate task state icons dotm = DotMaker(theme) self.dots = {} for state in task_state.legal: self.dots[state] = dotm.get_icon(state) self.dots["empty"] = dotm.get_icon() self.led_digits_one = [] self.led_digits_two = [] self.led_digits_blank = gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/one/digit-blank.xpm") for i in range(10): self.led_digits_one.append(gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/one/digit-" + str(i) + ".xpm")) self.led_digits_two.append(gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/two/digit-" + str(i) + ".xpm"))
def __init__(self, cfg, updater, treeview, info_bar, theme ): super(DotUpdater, self).__init__() self.quit = False self.cleared = True self.action_required = False self.autoexpand = True self.should_hide_headings = False self.should_group_families = ("dot" not in cfg.ungrouped_views) self.should_transpose_view = False self.is_transposed = False self.defn_order_on = True self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar imagedir = self.cfg.imagedir self.last_update_time = None self.state_summary = {} self.fam_state_summary = {} self.ancestors_pruned = {} self.descendants = [] self.filter = "" self.ctimes = [] self.led_headings = [] self.led_treeview = treeview self.led_liststore = treeview.get_model() self._prev_tooltip_task_id = None if hasattr(self.led_treeview, "set_has_tooltip"): self.led_treeview.set_has_tooltip(True) try: self.led_treeview.connect('query-tooltip', self.on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.task_list = [] # generate task state icons dotm = DotMaker( theme ) self.dots = {} for state in task_state.legal: self.dots[ state ] = dotm.get_icon( state ) self.dots['empty'] = dotm.get_icon()
def __init__(self, cfg, updater, treeview, info_bar, theme, dot_size): super(DotUpdater, self).__init__() self.quit = False self.cleared = True self.action_required = False self.autoexpand = True self.should_hide_headings = False self.should_group_families = ("dot" not in cfg.ungrouped_views) self.should_transpose_view = False self.is_transposed = False self.defn_order_on = True self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar imagedir = self.cfg.imagedir self.last_update_time = None self.state_summary = {} self.fam_state_summary = {} self.ancestors_pruned = {} self.descendants = [] self.filter = "" self.point_strings = [] self.led_headings = [] self.led_treeview = treeview self.led_liststore = treeview.get_model() self._prev_tooltip_task_id = None if hasattr(self.led_treeview, "set_has_tooltip"): self.led_treeview.set_has_tooltip(True) try: self.led_treeview.connect('query-tooltip', self.on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.task_list = [] # generate task state icons dotm = DotMaker(theme, size=dot_size) self.dots = dotm.get_dots()
def __init__(self, cfg, treeview, info_bar, theme ): super(lupdater, self).__init__() self.quit = False self.autoexpand = True self.should_hide_headings = False self.should_group_families = False self.cfg = cfg self.theme = theme self.info_bar = info_bar imagedir = self.cfg.imagedir self.state_summary = {} self.global_summary = {} self.stop_summary = None self.families = [] self.god = None self.mode = "waiting..." self.dt = "waiting..." self.status = None self.poll_schd = PollSchd() self.filter = "" self.led_treeview = treeview self.led_liststore = treeview.get_model() self._prev_tooltip_task_id = None self.reconnect() # generate task state icons dotm = DotMaker( theme ) self.dots = {} for state in task_state.legal: self.dots[ state ] = dotm.get_icon( state ) self.dots['empty'] = dotm.get_icon() self.led_digits_one = [] self.led_digits_two = [] self.led_digits_blank = gtk.gdk.pixbuf_new_from_file( imagedir + "/digits/one/digit-blank.xpm" ) for i in range(10): self.led_digits_one.append( gtk.gdk.pixbuf_new_from_file( imagedir + "/digits/one/digit-" + str(i) + ".xpm" )) self.led_digits_two.append( gtk.gdk.pixbuf_new_from_file( imagedir + "/digits/two/digit-" + str(i) + ".xpm" ))
def __init__(self, cfg, updater, ttreeview, ttree_paths, info_bar, theme ): super(TreeUpdater, self).__init__() self.action_required = False self.quit = False self.cleared = True self.autoexpand = True self.count = 0 self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar self.last_update_time = None self.ancestors = {} self.descendants = [] self.autoexpand_states = [ 'queued', 'ready', 'submitted', 'running', 'failed' ] self._last_autoexpand_me = [] self.ttree_paths = ttree_paths # Dict of paths vs all descendant node states self.should_group_families = ("text" not in self.cfg.ungrouped_views) self.ttreeview = ttreeview # Hierarchy of models: view <- sorted <- filtered <- base model self.ttreestore = ttreeview.get_model().get_model().get_model() self._prev_tooltip_task_id = None if hasattr(self.ttreeview, "set_has_tooltip"): self.ttreeview.set_has_tooltip(True) try: self.ttreeview.connect('query-tooltip', self.on_query_tooltip) except TypeError: # Lower PyGTK version. pass dotm = DotMaker( theme ) self.dots = {} for state in task_state.legal: self.dots[ state ] = dotm.get_icon( state ) self.dots['empty'] = dotm.get_icon()
def __init__(self, cfg, updater, ttreeview, ttree_paths, info_bar, theme, dot_size): super(TreeUpdater, self).__init__() self.action_required = False self.quit = False self.cleared = True self.autoexpand = True self.count = 0 self.cfg = cfg self.updater = updater self.info_bar = info_bar self.last_update_time = None self.ancestors = {} self.descendants = [] self.autoexpand_states = [ 'queued', 'ready', 'submitted', 'running', 'failed' ] self._last_autoexpand_me = [] self.ttree_paths = ttree_paths # Dict of paths vs all descendant node states self.should_group_families = ("text" not in self.cfg.ungrouped_views) self.ttreeview = ttreeview # Hierarchy of models: view <- sorted <- filtered <- base model self.ttreestore = ttreeview.get_model().get_model().get_model() self._prev_tooltip_task_id = None if hasattr(self.ttreeview, "set_has_tooltip"): self.ttreeview.set_has_tooltip(True) try: self.ttreeview.connect('query-tooltip', self.on_query_tooltip) except TypeError: # Lower PyGTK version. pass # Cache the latest ETC calculation for active ids. self._id_tetc_cache = {} # Generate task state icons. dotm = DotMaker(theme, size=dot_size) self.dots = dotm.get_dots()
def __init__(self, hosts, dot_hbox, gcylc_image, is_compact, owner=None, poll_interval=None): self.quit = True self.dot_hbox = dot_hbox self.gcylc_image = gcylc_image self.is_compact = is_compact self._set_gcylc_image_tooltip() self.gcylc_image.set_sensitive(False) self.theme_name = gcfg.get(['use theme']) self.theme = gcfg.get(['themes', self.theme_name]) self.dots = DotMaker(self.theme) self.statuses = {} self.stop_summaries = {} self._set_exception_hook() super(SummaryPanelAppletUpdater, self).__init__(hosts, owner=owner, poll_interval=poll_interval)
def __init__(self, cfg, ttreeview, ttree_paths, info_bar, theme ): super(tupdater, self).__init__() self.quit = False self.autoexpand = True self.cfg = cfg self.theme = theme self.info_bar = info_bar self.state_summary = {} self.global_summary = {} self.fam_state_summary = {} self.stop_summary = None self.families = [] self.god = None self.mode = "waiting..." self.dt = "waiting..." self.status = None self.poll_schd = PollSchd() self.autoexpand_states = [ 'submitted', 'running', 'failed', 'held' ] self._last_autoexpand_me = [] self.ttree_paths = ttree_paths # Dict of paths vs all descendant node states self.should_group_families = False self.ttreeview = ttreeview # Hierarchy of models: view <- sorted <- filtered <- base model self.ttreestore = ttreeview.get_model().get_model().get_model() dotm = DotMaker( theme ) self.dots = {} for state in task_state.legal: self.dots[ state ] = dotm.get_icon( state ) self.dots['empty'] = dotm.get_icon() self.reconnect()
def __init__(self, hosts, dot_hbox, gcylc_image, is_compact, owner=None, poll_interval=None): self.quit = True self.dot_hbox = dot_hbox self.gcylc_image = gcylc_image self.is_compact = is_compact self._set_gcylc_image_tooltip() self.gcylc_image.set_sensitive(False) self.theme_name = gcfg.get( ['use theme'] ) self.theme = gcfg.get( ['themes', self.theme_name] ) self.dots = DotMaker(self.theme) self.statuses = {} self.stop_summaries = {} self._set_exception_hook() super(SummaryPanelAppletUpdater, self).__init__( hosts, owner=owner, poll_interval=poll_interval)
def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = gcfg.get( ['themes',self.theme_name] ) self.dots = DotMaker(self.theme)
def __init__(self, hosts=None, owner=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gsummary") setup_icons() if not hosts: try: hosts = sitecfg.get( ["suite host scanning","hosts"] ) except KeyError: hosts = ["localhost"] self.hosts = hosts if owner is None: owner = user self.owner = owner self.window = gtk.Window() self.window.set_title("cylc gsummary") self.window.set_icon(get_icon()) self.vbox = gtk.VBox() self.vbox.show() self.theme_name = gcfg.get( ['use theme'] ) self.theme = gcfg.get( ['themes', self.theme_name] ) self.dots = DotMaker(self.theme) suite_treemodel = gtk.TreeStore(*([str, str, bool, str, int] + [str] * 20)) self._prev_tooltip_location_id = None self.suite_treeview = gtk.TreeView(suite_treemodel) # Construct the host column. host_name_column = gtk.TreeViewColumn("Host") cell_text_host = gtk.CellRendererText() host_name_column.pack_start(cell_text_host, expand=False) host_name_column.set_cell_data_func( cell_text_host, self._set_cell_text_host) host_name_column.set_sort_column_id(0) host_name_column.set_visible(False) # Construct the suite name column. suite_name_column = gtk.TreeViewColumn("Suite") cell_text_name = gtk.CellRendererText() suite_name_column.pack_start(cell_text_name, expand=False) suite_name_column.set_cell_data_func( cell_text_name, self._set_cell_text_name) suite_name_column.set_sort_column_id(1) # Construct the suite title column. suite_title_column = gtk.TreeViewColumn("Title") cell_text_title = gtk.CellRendererText() suite_title_column.pack_start(cell_text_title, expand=False) suite_title_column.set_cell_data_func( cell_text_title, self._set_cell_text_title) suite_title_column.set_sort_column_id(3) suite_title_column.set_visible(False) # Construct the update time column. time_column = gtk.TreeViewColumn("Updated") cell_text_time = gtk.CellRendererText() time_column.pack_start(cell_text_time, expand=False) time_column.set_cell_data_func( cell_text_time, self._set_cell_text_time) time_column.set_sort_column_id(4) time_column.set_visible(False) # Construct the status column. status_column = gtk.TreeViewColumn("Status") status_column.set_sort_column_id(5) for i in range(5, 25): cell_pixbuf_state = gtk.CellRendererPixbuf() status_column.pack_start(cell_pixbuf_state, expand=False) status_column.set_cell_data_func( cell_pixbuf_state, self._set_cell_pixbuf_state, i) self.suite_treeview.append_column(host_name_column) self.suite_treeview.append_column(suite_name_column) self.suite_treeview.append_column(suite_title_column) self.suite_treeview.append_column(time_column) self.suite_treeview.append_column(status_column) self.suite_treeview.show() if hasattr(self.suite_treeview, "set_has_tooltip"): self.suite_treeview.set_has_tooltip(True) try: self.suite_treeview.connect('query-tooltip', self._on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.suite_treeview.connect("button-press-event", self._on_button_press_event) scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled_window.add(self.suite_treeview) scrolled_window.show() self.vbox.pack_start(scrolled_window, expand=True, fill=True) self.updater = SummaryAppUpdater(self.hosts, suite_treemodel, owner=self.owner, poll_interval=poll_interval) self.updater.start() self.window.add(self.vbox) self.window.connect("destroy", self._on_destroy_event) self.window.set_default_size(200, 100) self.suite_treeview.grab_focus() self.window.show()
class SummaryApp(object): """Summarize running suite statuses for a given set of hosts.""" def __init__(self, hosts=None, owner=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gsummary") setup_icons() if not hosts: try: hosts = sitecfg.get( ["suite host scanning","hosts"] ) except KeyError: hosts = ["localhost"] self.hosts = hosts if owner is None: owner = user self.owner = owner self.window = gtk.Window() self.window.set_title("cylc gsummary") self.window.set_icon(get_icon()) self.vbox = gtk.VBox() self.vbox.show() self.theme_name = gcfg.get( ['use theme'] ) self.theme = gcfg.get( ['themes', self.theme_name] ) self.dots = DotMaker(self.theme) suite_treemodel = gtk.TreeStore(*([str, str, bool, str, int] + [str] * 20)) self._prev_tooltip_location_id = None self.suite_treeview = gtk.TreeView(suite_treemodel) # Construct the host column. host_name_column = gtk.TreeViewColumn("Host") cell_text_host = gtk.CellRendererText() host_name_column.pack_start(cell_text_host, expand=False) host_name_column.set_cell_data_func( cell_text_host, self._set_cell_text_host) host_name_column.set_sort_column_id(0) host_name_column.set_visible(False) # Construct the suite name column. suite_name_column = gtk.TreeViewColumn("Suite") cell_text_name = gtk.CellRendererText() suite_name_column.pack_start(cell_text_name, expand=False) suite_name_column.set_cell_data_func( cell_text_name, self._set_cell_text_name) suite_name_column.set_sort_column_id(1) # Construct the suite title column. suite_title_column = gtk.TreeViewColumn("Title") cell_text_title = gtk.CellRendererText() suite_title_column.pack_start(cell_text_title, expand=False) suite_title_column.set_cell_data_func( cell_text_title, self._set_cell_text_title) suite_title_column.set_sort_column_id(3) suite_title_column.set_visible(False) # Construct the update time column. time_column = gtk.TreeViewColumn("Updated") cell_text_time = gtk.CellRendererText() time_column.pack_start(cell_text_time, expand=False) time_column.set_cell_data_func( cell_text_time, self._set_cell_text_time) time_column.set_sort_column_id(4) time_column.set_visible(False) # Construct the status column. status_column = gtk.TreeViewColumn("Status") status_column.set_sort_column_id(5) for i in range(5, 25): cell_pixbuf_state = gtk.CellRendererPixbuf() status_column.pack_start(cell_pixbuf_state, expand=False) status_column.set_cell_data_func( cell_pixbuf_state, self._set_cell_pixbuf_state, i) self.suite_treeview.append_column(host_name_column) self.suite_treeview.append_column(suite_name_column) self.suite_treeview.append_column(suite_title_column) self.suite_treeview.append_column(time_column) self.suite_treeview.append_column(status_column) self.suite_treeview.show() if hasattr(self.suite_treeview, "set_has_tooltip"): self.suite_treeview.set_has_tooltip(True) try: self.suite_treeview.connect('query-tooltip', self._on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.suite_treeview.connect("button-press-event", self._on_button_press_event) scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled_window.add(self.suite_treeview) scrolled_window.show() self.vbox.pack_start(scrolled_window, expand=True, fill=True) self.updater = SummaryAppUpdater(self.hosts, suite_treemodel, owner=self.owner, poll_interval=poll_interval) self.updater.start() self.window.add(self.vbox) self.window.connect("destroy", self._on_destroy_event) self.window.set_default_size(200, 100) self.suite_treeview.grab_focus() self.window.show() def _on_button_press_event(self, treeview, event): # DISPLAY MENU ONLY ON RIGHT CLICK ONLY if (event.type != gtk.gdk._2BUTTON_PRESS and event.button != 3): return False treemodel = treeview.get_model() x = int(event.x) y = int(event.y) time = event.time pth = treeview.get_path_at_pos(x, y) suite_host_tuples = [] if pth is not None: # Add a gcylc launcher item. path, col, cellx, celly = pth iter_ = treemodel.get_iter(path) host, suite = treemodel.get(iter_, 0, 1) suite_host_tuples.append((suite, host)) if event.type == gtk.gdk._2BUTTON_PRESS: if suite_host_tuples: launch_gcylc(host, suite, owner=self.owner) return False has_stopped_suites = bool(self.updater.stop_summaries) view_item = gtk.ImageMenuItem("View Column...") img = gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU) view_item.set_image(img) view_item.show() view_menu = gtk.Menu() view_item.set_submenu(view_menu) for column_index, column in enumerate(treeview.get_columns()): name = column.get_title() is_visible = column.get_visible() column_item = gtk.CheckMenuItem(name.replace("_", "__")) column_item._connect_args = (column_index, is_visible) column_item.set_active(is_visible) column_item.connect("toggled", self._on_toggle_column_visible) column_item.show() view_menu.append(column_item) menu = get_summary_menu(suite_host_tuples, self.theme_name, self._set_theme, has_stopped_suites, self.updater.clear_stopped_suites, self.hosts, self.updater.set_hosts, self.updater.update_now, self.updater.start, program_name="cylc gsummary", extra_items=[view_item], owner=self.owner) menu.popup( None, None, None, event.button, event.time ) return False def _on_destroy_event(self, widget): self.updater.quit = True gtk.main_quit() return False def _on_query_tooltip(self, widget, x, y, kbd_ctx, tooltip): """Handle a tooltip creation request.""" tip_context = self.suite_treeview.get_tooltip_context(x, y, kbd_ctx) if tip_context is None: self._prev_tooltip_location_id = None return False x, y = self.suite_treeview.convert_widget_to_bin_window_coords(x, y) path, column, cell_x, cell_y = self.suite_treeview.get_path_at_pos( x, y) model = self.suite_treeview.get_model() iter_ = model.get_iter(path) host = model.get_value(iter_, 0) suite = model.get_value(iter_, 1) update_time = model.get_value(iter_, 4) location_id = (host, suite, update_time, column.get_title()) if location_id != self._prev_tooltip_location_id: self._prev_tooltip_location_id = location_id tooltip.set_text(None) return False if column.get_title() in ["Host", "Suite"]: tooltip.set_text(suite + " - " + host) return True if column.get_title() == "Updated": time_object = datetime.datetime.fromtimestamp(update_time) text = "Info retrieved at " + time_object.isoformat() tooltip.set_text(text) return True if column.get_title() != "Status": tooltip.set_text(None) return False state_texts = [] for i in range(5, 25): state_text = model.get_value(iter_, i) if state_text is None: break status, number = state_text.rsplit(" ", 1) state_texts.append(number + " " + status) text = "Tasks: " + ", ".join(state_texts) tooltip.set_text(text) return True def _on_toggle_column_visible(self, menu_item): column_index, is_visible = menu_item._connect_args column = self.suite_treeview.get_columns()[column_index] column.set_visible(not is_visible) return False def _set_cell_pixbuf_state(self, column, cell, model, iter_, index): state_info = model.get_value(iter_, index) if state_info is None: cell.set_property("pixbuf", None) cell.set_property("visible", False) return is_stopped = model.get_value(iter_, 2) state, num_tasks = state_info.rsplit(" ", 1) icon = self.dots.get_icon(state, is_stopped=is_stopped) cell.set_property("pixbuf", icon) cell.set_property("visible", True) def _set_cell_text_host(self, column, cell, model, iter_): host = model.get_value(iter_, 0) is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", host) def _set_cell_text_name(self, column, cell, model, iter_): name = model.get_value(iter_, 1) is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", name) def _set_cell_text_title(self, column, cell, model, iter_): title = model.get_value(iter_, 3) is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", title) def _set_cell_text_time(self, column, cell, model, iter_): update_time = model.get_value(iter_, 4) time_object = datetime.datetime.fromtimestamp(update_time) time_string = time_object.strftime("%H:%M:%S") is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", time_string) def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = gcfg.get( ['themes',self.theme_name] ) self.dots = DotMaker(self.theme) def _set_tooltip(self, widget, text): tooltip = gtk.Tooltips() tooltip.enable() tooltip.set_tip(widget, text)
def _set_key_liststore( self ): dotm = DotMaker( self._theme ) self._key_liststore.clear() for state in task_state.legal: dot = dotm.get_icon( state ) self._key_liststore.append( [ state, dot ] )
def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = gcfg.get(['themes', self.theme_name]) self.dots = DotMaker(self.theme)
class SummaryPanelAppletUpdater(BaseSummaryTimeoutUpdater): """Update the summary panel applet - subclass of gsummary equivalent.""" IDLE_STOPPED_TIME = 3600 # 1 hour. MAX_INDIVIDUAL_SUITES = 5 def __init__(self, hosts, dot_hbox, gcylc_image, is_compact, owner=None, poll_interval=None): self.quit = True self.dot_hbox = dot_hbox self.gcylc_image = gcylc_image self.is_compact = is_compact self._set_gcylc_image_tooltip() self.gcylc_image.set_sensitive(False) self.theme_name = gcfg.get(['use theme']) self.theme = gcfg.get(['themes', self.theme_name]) self.dots = DotMaker(self.theme) self.statuses = {} self.stop_summaries = {} self._set_exception_hook() super(SummaryPanelAppletUpdater, self).__init__(hosts, owner=owner, poll_interval=poll_interval) def clear_stopped_suites(self): """Clear stopped suite information that may have built up.""" self.stop_summaries.clear() gobject.idle_add(self.update) def start(self): self.gcylc_image.set_sensitive(True) super(SummaryPanelAppletUpdater, self).start() self._set_gcylc_image_tooltip() def stop(self): self.gcylc_image.set_sensitive(False) super(SummaryPanelAppletUpdater, self).stop() self._set_gcylc_image_tooltip() def launch_context_menu(self, event, suite_host_tuples=None, extra_items=None): has_stopped_suites = bool(self.stop_summaries) if suite_host_tuples is None: suite_host_tuples = [] if extra_items is None: extra_items = [] gsummary_item = gtk.ImageMenuItem("Launch cylc gsummary") img = gtk.image_new_from_stock("gcylc", gtk.ICON_SIZE_MENU) gsummary_item.set_image(img) gsummary_item.show() gsummary_item.connect("button-press-event", self._on_button_press_event_gsummary) extra_items.append(gsummary_item) menu = get_summary_menu(suite_host_tuples, self.theme_name, self._set_theme, has_stopped_suites, self.clear_stopped_suites, self.hosts, self.set_hosts, self.update_now, self.start, program_name="cylc gpanel", extra_items=extra_items, owner=self.owner, is_stopped=self.quit) menu.popup(None, None, None, event.button, event.time) return False def update(self, update_time=None): """Update the Applet.""" suite_host_tuples = [] statuses = copy.deepcopy(self.statuses) stop_summaries = copy.deepcopy(self.stop_summaries) for host in self.hosts: suites = (statuses.get(host, {}).keys() + stop_summaries.get(host, {}).keys()) for suite in suites: suite_host_tuples.append((suite, host)) suite_host_tuples.sort() for child in self.dot_hbox.get_children(): self.dot_hbox.remove(child) number_mode = (not self.is_compact and len(suite_host_tuples) > self.MAX_INDIVIDUAL_SUITES) suite_statuses = {} compact_suite_statuses = [] for suite, host in suite_host_tuples: if suite in statuses.get(host, {}): status_map = statuses[host][suite] is_stopped = False else: info = stop_summaries[host][suite] status_map, suite_time = info is_stopped = True status = extract_group_state(status_map.keys(), is_stopped=is_stopped) if number_mode: suite_statuses.setdefault(is_stopped, {}) suite_statuses[is_stopped].setdefault(status, []) suite_statuses[is_stopped][status].append( (suite, host, status_map.items())) elif self.is_compact: compact_suite_statuses.append( (suite, host, status, status_map.items(), is_stopped)) else: self._add_image_box([(suite, host, status, status_map.items(), is_stopped)]) if number_mode: for is_stopped in sorted(suite_statuses.keys()): statuses = suite_statuses[is_stopped].items() statuses.sort(lambda x, y: cmp(len(y[1]), len(x[1]))) for status, suite_host_states_tuples in statuses: label = gtk.Label(str(len(suite_host_states_tuples)) + ":") label.show() self.dot_hbox.pack_start(label, expand=False, fill=False) suite_info_tuples = [] for suite, host, task_states in suite_host_states_tuples: suite_info_tuples.append( (suite, host, status, task_states, is_stopped)) self._add_image_box(suite_info_tuples) if self.is_compact: if not compact_suite_statuses: # No suites running or stopped. self.gcylc_image.show() return False self.gcylc_image.hide() self._add_image_box(compact_suite_statuses) return False def _add_image_box(self, suite_host_info_tuples): image_eb = gtk.EventBox() image_eb.show() is_all_stopped = False running_status_list = [] status_list = [] suite_host_tuples = [] for info_tuple in suite_host_info_tuples: suite, host, status, task_states, is_stopped = info_tuple suite_host_tuples.append((suite, host)) if not is_stopped: running_status_list.append(status) status_list.append(status) if running_status_list: status = extract_group_state(running_status_list, is_stopped=False) image = self.dots.get_image(status, is_stopped=False) else: status = extract_group_state(status_list, is_stopped=True) image = self.dots.get_image(status, is_stopped=True) image.show() image_eb.add(image) image_eb._connect_args = suite_host_tuples image_eb.connect("button-press-event", self._on_button_press_event) text_format = "%s - %s - %s" long_text_format = text_format + "\n Tasks: %s\n" text = "" tip_vbox = gtk.VBox() # Only used in PyGTK 2.12+ tip_vbox.show() for info_tuple in suite_host_info_tuples: suite, host, status, task_states, is_stopped = info_tuple task_states.sort(lambda x, y: cmp(len(y[1]), len(x[1]))) tip_hbox = gtk.HBox() tip_hbox.show() state_info = [] for state_name, tasks in task_states: state_info.append(str(len(tasks)) + " " + state_name) image = self.dots.get_image(state_name, is_stopped=is_stopped) image.show() tip_hbox.pack_start(image, expand=False, fill=False) states_text = ", ".join(state_info) if status is None: suite_summary = "?" else: suite_summary = status if is_stopped: suite_summary = "stopped with " + suite_summary tip_label = gtk.Label(text_format % (suite, suite_summary, host)) tip_label.show() tip_hbox.pack_start(tip_label, expand=False, fill=False, padding=5) tip_vbox.pack_start(tip_hbox, expand=False, fill=False) text += long_text_format % (suite, suite_summary, host, states_text) text = text.rstrip() if hasattr(gtk, "Tooltip"): image_eb.set_has_tooltip(True) image_eb.connect("query-tooltip", self._on_img_tooltip_query, tip_vbox) else: self._set_tooltip(image_eb, text) self.dot_hbox.pack_start(image_eb, expand=False, fill=False, padding=1) def _on_button_press_event(self, widget, event): if event.button == 1: self.launch_context_menu(event, suite_host_tuples=widget._connect_args) return False def _on_button_press_event_gsummary(self, widget, event): launch_gsummary(hosts=self.hosts, owner=self.owner) def _on_img_tooltip_query(self, widget, x, y, kbd, tooltip, tip_widget): tooltip.set_custom(tip_widget) return True def _set_exception_hook(self): # Handle an uncaught exception. old_hook = sys.excepthook sys.excepthook = ( lambda *a: self._handle_exception(*a, old_hook=old_hook)) def _handle_exception(self, e_type, e_value, e_traceback, old_hook=None): self.gcylc_image.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) exc_lines = traceback.format_exception(e_type, e_value, e_traceback) exc_text = "".join(exc_lines) info = "cylc gpanel has a problem.\n\n%s" % exc_text self._set_tooltip(self.gcylc_image, info.rstrip()) if old_hook is not None: old_hook(exception_class, exception, trace) def _set_gcylc_image_tooltip(self): if self.quit: self._set_tooltip(self.gcylc_image, "Cylc Applet - Off") else: self._set_tooltip(self.gcylc_image, "Cylc Applet - Active") def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = gcfg.get(['themes', self.theme_name]) self.dots = DotMaker(self.theme) def _set_tooltip(self, widget, text): tooltip = gtk.Tooltips() tooltip.enable() tooltip.set_tip(widget, text)
def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = self.usercfg['themes'][self.theme_name] self.dots = DotMaker(self.theme)
def __init__(self, hosts=None, owner=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gsummary") setup_icons() if not hosts: try: hosts = GLOBAL_CFG.get( ["suite host scanning","hosts"] ) except KeyError: hosts = ["localhost"] self.hosts = hosts if owner is None: owner = user self.owner = owner self.window = gtk.Window() self.window.set_title("cylc gsummary") self.window.set_icon(get_icon()) self.vbox = gtk.VBox() self.vbox.show() self.theme_name = gcfg.get( ['use theme'] ) self.theme = gcfg.get( ['themes', self.theme_name] ) self.dots = DotMaker(self.theme) suite_treemodel = gtk.TreeStore(*([str, str, bool, str, int] + [str] * 20)) self._prev_tooltip_location_id = None self.suite_treeview = gtk.TreeView(suite_treemodel) # Construct the host column. host_name_column = gtk.TreeViewColumn("Host") cell_text_host = gtk.CellRendererText() host_name_column.pack_start(cell_text_host, expand=False) host_name_column.set_cell_data_func( cell_text_host, self._set_cell_text_host) host_name_column.set_sort_column_id(0) host_name_column.set_visible(False) # Construct the suite name column. suite_name_column = gtk.TreeViewColumn("Suite") cell_text_name = gtk.CellRendererText() suite_name_column.pack_start(cell_text_name, expand=False) suite_name_column.set_cell_data_func( cell_text_name, self._set_cell_text_name) suite_name_column.set_sort_column_id(1) # Construct the suite title column. suite_title_column = gtk.TreeViewColumn("Title") cell_text_title = gtk.CellRendererText() suite_title_column.pack_start(cell_text_title, expand=False) suite_title_column.set_cell_data_func( cell_text_title, self._set_cell_text_title) suite_title_column.set_sort_column_id(3) suite_title_column.set_visible(False) # Construct the update time column. time_column = gtk.TreeViewColumn("Updated") cell_text_time = gtk.CellRendererText() time_column.pack_start(cell_text_time, expand=False) time_column.set_cell_data_func( cell_text_time, self._set_cell_text_time) time_column.set_sort_column_id(4) time_column.set_visible(False) # Construct the status column. status_column = gtk.TreeViewColumn("Status") status_column.set_sort_column_id(5) for i in range(5, 25): cell_pixbuf_state = gtk.CellRendererPixbuf() status_column.pack_start(cell_pixbuf_state, expand=False) status_column.set_cell_data_func( cell_pixbuf_state, self._set_cell_pixbuf_state, i) self.suite_treeview.append_column(host_name_column) self.suite_treeview.append_column(suite_name_column) self.suite_treeview.append_column(suite_title_column) self.suite_treeview.append_column(time_column) self.suite_treeview.append_column(status_column) self.suite_treeview.show() if hasattr(self.suite_treeview, "set_has_tooltip"): self.suite_treeview.set_has_tooltip(True) try: self.suite_treeview.connect('query-tooltip', self._on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.suite_treeview.connect("button-press-event", self._on_button_press_event) scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled_window.add(self.suite_treeview) scrolled_window.show() self.vbox.pack_start(scrolled_window, expand=True, fill=True) self.updater = SummaryAppUpdater(self.hosts, suite_treemodel, owner=self.owner, poll_interval=poll_interval) self.updater.start() self.window.add(self.vbox) self.window.connect("destroy", self._on_destroy_event) self.window.set_default_size(200, 100) self.suite_treeview.grab_focus() self.window.show()
class SummaryApp(object): """Summarize running suite statuses for a given set of hosts.""" def __init__(self, hosts=None, owner=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gsummary") setup_icons() if not hosts: try: hosts = GLOBAL_CFG.get( ["suite host scanning","hosts"] ) except KeyError: hosts = ["localhost"] self.hosts = hosts if owner is None: owner = user self.owner = owner self.window = gtk.Window() self.window.set_title("cylc gsummary") self.window.set_icon(get_icon()) self.vbox = gtk.VBox() self.vbox.show() self.theme_name = gcfg.get( ['use theme'] ) self.theme = gcfg.get( ['themes', self.theme_name] ) self.dots = DotMaker(self.theme) suite_treemodel = gtk.TreeStore(*([str, str, bool, str, int] + [str] * 20)) self._prev_tooltip_location_id = None self.suite_treeview = gtk.TreeView(suite_treemodel) # Construct the host column. host_name_column = gtk.TreeViewColumn("Host") cell_text_host = gtk.CellRendererText() host_name_column.pack_start(cell_text_host, expand=False) host_name_column.set_cell_data_func( cell_text_host, self._set_cell_text_host) host_name_column.set_sort_column_id(0) host_name_column.set_visible(False) # Construct the suite name column. suite_name_column = gtk.TreeViewColumn("Suite") cell_text_name = gtk.CellRendererText() suite_name_column.pack_start(cell_text_name, expand=False) suite_name_column.set_cell_data_func( cell_text_name, self._set_cell_text_name) suite_name_column.set_sort_column_id(1) # Construct the suite title column. suite_title_column = gtk.TreeViewColumn("Title") cell_text_title = gtk.CellRendererText() suite_title_column.pack_start(cell_text_title, expand=False) suite_title_column.set_cell_data_func( cell_text_title, self._set_cell_text_title) suite_title_column.set_sort_column_id(3) suite_title_column.set_visible(False) # Construct the update time column. time_column = gtk.TreeViewColumn("Updated") cell_text_time = gtk.CellRendererText() time_column.pack_start(cell_text_time, expand=False) time_column.set_cell_data_func( cell_text_time, self._set_cell_text_time) time_column.set_sort_column_id(4) time_column.set_visible(False) # Construct the status column. status_column = gtk.TreeViewColumn("Status") status_column.set_sort_column_id(5) for i in range(5, 25): cell_pixbuf_state = gtk.CellRendererPixbuf() status_column.pack_start(cell_pixbuf_state, expand=False) status_column.set_cell_data_func( cell_pixbuf_state, self._set_cell_pixbuf_state, i) self.suite_treeview.append_column(host_name_column) self.suite_treeview.append_column(suite_name_column) self.suite_treeview.append_column(suite_title_column) self.suite_treeview.append_column(time_column) self.suite_treeview.append_column(status_column) self.suite_treeview.show() if hasattr(self.suite_treeview, "set_has_tooltip"): self.suite_treeview.set_has_tooltip(True) try: self.suite_treeview.connect('query-tooltip', self._on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.suite_treeview.connect("button-press-event", self._on_button_press_event) scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled_window.add(self.suite_treeview) scrolled_window.show() self.vbox.pack_start(scrolled_window, expand=True, fill=True) self.updater = SummaryAppUpdater(self.hosts, suite_treemodel, owner=self.owner, poll_interval=poll_interval) self.updater.start() self.window.add(self.vbox) self.window.connect("destroy", self._on_destroy_event) self.window.set_default_size(200, 100) self.suite_treeview.grab_focus() self.window.show() def _on_button_press_event(self, treeview, event): # DISPLAY MENU ONLY ON RIGHT CLICK ONLY if (event.type != gtk.gdk._2BUTTON_PRESS and event.button != 3): return False treemodel = treeview.get_model() x = int(event.x) y = int(event.y) time = event.time pth = treeview.get_path_at_pos(x, y) suite_host_tuples = [] if pth is not None: # Add a gcylc launcher item. path, col, cellx, celly = pth iter_ = treemodel.get_iter(path) host, suite = treemodel.get(iter_, 0, 1) suite_host_tuples.append((suite, host)) if event.type == gtk.gdk._2BUTTON_PRESS: if suite_host_tuples: launch_gcylc(host, suite, owner=self.owner) return False has_stopped_suites = bool(self.updater.stop_summaries) view_item = gtk.ImageMenuItem("View Column...") img = gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU) view_item.set_image(img) view_item.show() view_menu = gtk.Menu() view_item.set_submenu(view_menu) for column_index, column in enumerate(treeview.get_columns()): name = column.get_title() is_visible = column.get_visible() column_item = gtk.CheckMenuItem(name.replace("_", "__")) column_item._connect_args = (column_index, is_visible) column_item.set_active(is_visible) column_item.connect("toggled", self._on_toggle_column_visible) column_item.show() view_menu.append(column_item) menu = get_summary_menu(suite_host_tuples, self.theme_name, self._set_theme, has_stopped_suites, self.updater.clear_stopped_suites, self.hosts, self.updater.set_hosts, self.updater.update_now, self.updater.start, program_name="cylc gsummary", extra_items=[view_item], owner=self.owner) menu.popup( None, None, None, event.button, event.time ) return False def _on_destroy_event(self, widget): self.updater.quit = True gtk.main_quit() return False def _on_query_tooltip(self, widget, x, y, kbd_ctx, tooltip): """Handle a tooltip creation request.""" tip_context = self.suite_treeview.get_tooltip_context(x, y, kbd_ctx) if tip_context is None: self._prev_tooltip_location_id = None return False x, y = self.suite_treeview.convert_widget_to_bin_window_coords(x, y) path, column, cell_x, cell_y = self.suite_treeview.get_path_at_pos( x, y) model = self.suite_treeview.get_model() iter_ = model.get_iter(path) host = model.get_value(iter_, 0) suite = model.get_value(iter_, 1) update_time = model.get_value(iter_, 4) location_id = (host, suite, update_time, column.get_title()) if location_id != self._prev_tooltip_location_id: self._prev_tooltip_location_id = location_id tooltip.set_text(None) return False if column.get_title() in ["Host", "Suite"]: tooltip.set_text(suite + " - " + host) return True if column.get_title() == "Updated": time_point = get_timepoint_from_seconds_since_unix_epoch( update_time) tooltip.set_text("Info retrieved at " + str(time_point)) return True if column.get_title() != "Status": tooltip.set_text(None) return False state_texts = [] for i in range(5, 25): state_text = model.get_value(iter_, i) if state_text is None: break status, number = state_text.rsplit(" ", 1) state_texts.append(number + " " + status) text = "Tasks: " + ", ".join(state_texts) tooltip.set_text(text) return True def _on_toggle_column_visible(self, menu_item): column_index, is_visible = menu_item._connect_args column = self.suite_treeview.get_columns()[column_index] column.set_visible(not is_visible) return False def _set_cell_pixbuf_state(self, column, cell, model, iter_, index): state_info = model.get_value(iter_, index) if state_info is None: cell.set_property("pixbuf", None) cell.set_property("visible", False) return is_stopped = model.get_value(iter_, 2) state, num_tasks = state_info.rsplit(" ", 1) icon = self.dots.get_icon(state, is_stopped=is_stopped) cell.set_property("pixbuf", icon) cell.set_property("visible", True) def _set_cell_text_host(self, column, cell, model, iter_): host = model.get_value(iter_, 0) is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", host) def _set_cell_text_name(self, column, cell, model, iter_): name = model.get_value(iter_, 1) is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", name) def _set_cell_text_title(self, column, cell, model, iter_): title = model.get_value(iter_, 3) is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", title) def _set_cell_text_time(self, column, cell, model, iter_): update_time = model.get_value(iter_, 4) time_point = get_timepoint_from_seconds_since_unix_epoch(update_time) time_point.set_time_zone_to_local() time_string = str(time_point).split("T")[1] is_stopped = model.get_value(iter_, 2) cell.set_property("sensitive", not is_stopped) cell.set_property("text", time_string) def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = gcfg.get( ['themes',self.theme_name] ) self.dots = DotMaker(self.theme) def _set_tooltip(self, widget, text): tooltip = gtk.Tooltips() tooltip.enable() tooltip.set_tip(widget, text)
def treeview_widgets(self): # Treeview of current suite state, with filtering and sorting. # sorting is handled somewhat manually because the simple method # of interposing a TreeModelSort at the top: # treestore = gtk.TreeStore(str, ...) # tms = gtk.TreeModelSort( treestore ) #\ # tmf = tms.filter_new() #-- or other way round? # tv = gtk.TreeView() # tv.set_model(tms) # failed to produce correct results (the data displayed was not # consistently what should have been displayed given the # filtering in use) although the exact same code worked for a # liststore. self.sort_col_num = 0 self.ttreestore = gtk.TreeStore(str, str, str, str, str, str, str, str, str, str, gtk.gdk.Pixbuf) self.tmodelfilter = self.ttreestore.filter_new() self.tmodelfilter.set_visible_func(self.visible_cb) self.tmodelsort = gtk.TreeModelSort(self.tmodelfilter) self.ttreeview = gtk.TreeView() self.ttreeview.set_rules_hint(True) self.ttreeview.set_model(self.tmodelsort) ts = self.ttreeview.get_selection() ts.set_mode(gtk.SELECTION_SINGLE) self.ttreeview.connect('button_press_event', self.on_treeview_button_pressed) headings = [ None, 'task', 'state', 'host', 'Job ID', 'T-submit', 'T-start', 'T-finish', 'dT-mean', 'latest message' ] for n in range(1, len(headings)): # Skip first column (cycle point) tvc = gtk.TreeViewColumn(headings[n]) if n == 1: crp = gtk.CellRendererPixbuf() tvc.pack_start(crp, False) tvc.set_attributes(crp, pixbuf=10) cr = gtk.CellRendererText() tvc.pack_start(cr, True) if n == 7: tvc.set_attributes(cr, markup=n) else: tvc.set_attributes(cr, text=n) tvc.set_resizable(True) tvc.set_clickable(True) self.ttreeview.append_column(tvc) tvc.set_sort_column_id(n - 1) self.tmodelsort.set_sort_func(n - 1, self.sort_column, n - 1) sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.add(self.ttreeview) self.tfilterbox = gtk.VBox() subbox1 = gtk.HBox(homogeneous=True) subbox2 = gtk.HBox(homogeneous=True) self.tfilterbox.pack_start(subbox1) self.tfilterbox.pack_start(subbox2) self.tfilter_states = [] dotm = DotMaker(self.theme, size='small') cnt = 0 for st in task_state.legal: box = gtk.HBox() icon = dotm.get_image(st) cb = gtk.CheckButton(task_state.labels[st]) tooltip = gtk.Tooltips() tooltip.enable() tooltip.set_tip(cb, "Filter by task state = %s" % st) box.pack_start(icon, expand=False) box.pack_start(cb, expand=False) cnt += 1 if cnt > (len(task_state.legal) + 1) // 2: subbox2.pack_start(box, expand=False, fill=True) else: subbox1.pack_start(box, expand=False, fill=True) if st in self.tfilter_states: cb.set_active(False) else: cb.set_active(True) cb.connect('toggled', self.check_tfilter_buttons) self.filter_entry = EntryTempText() self.filter_entry.set_width_chars(7) self.filter_entry.connect("activate", self.check_filter_entry) self.filter_entry.set_temp_text("filter") tooltip = gtk.Tooltips() tooltip.enable() tooltip.set_tip( self.filter_entry, "Filter by task name.\n" "Enter a sub-string or regex and hit Enter\n" "(to reset, clear the entry and hit Enter)") subbox2.pack_start(self.filter_entry) cnt += 1 if cnt % 2 != 0: # subbox2 needs another entry to line things up. subbox2.pack_start(gtk.HBox(), expand=False, fill=True) filter_hbox = gtk.HBox() filter_hbox.pack_start(self.tfilterbox, True, True, 10) vbox = gtk.VBox() vbox.pack_start(sw, True) vbox.pack_end(filter_hbox, False) return vbox
class SummaryPanelAppletUpdater(BaseSummaryTimeoutUpdater): """Update the summary panel applet - subclass of gsummary equivalent.""" IDLE_STOPPED_TIME = 3600 # 1 hour. MAX_INDIVIDUAL_SUITES = 5 def __init__(self, hosts, dot_hbox, gcylc_image, is_compact, owner=None, poll_interval=None): self.quit = True self.dot_hbox = dot_hbox self.gcylc_image = gcylc_image self.is_compact = is_compact self._set_gcylc_image_tooltip() self.gcylc_image.set_sensitive(False) self.theme_name = gcfg.get( ['use theme'] ) self.theme = gcfg.get( ['themes', self.theme_name] ) self.dots = DotMaker(self.theme) self.statuses = {} self.stop_summaries = {} self._set_exception_hook() super(SummaryPanelAppletUpdater, self).__init__( hosts, owner=owner, poll_interval=poll_interval) def clear_stopped_suites(self): """Clear stopped suite information that may have built up.""" self.stop_summaries.clear() gobject.idle_add(self.update) def start(self): self.gcylc_image.set_sensitive(True) super(SummaryPanelAppletUpdater, self).start() self._set_gcylc_image_tooltip() def stop(self): self.gcylc_image.set_sensitive(False) super(SummaryPanelAppletUpdater, self).stop() self._set_gcylc_image_tooltip() def launch_context_menu(self, event, suite_host_tuples=None, extra_items=None): has_stopped_suites = bool(self.stop_summaries) if suite_host_tuples is None: suite_host_tuples = [] if extra_items is None: extra_items = [] gsummary_item = gtk.ImageMenuItem("Launch cylc gsummary") img = gtk.image_new_from_stock("gcylc", gtk.ICON_SIZE_MENU) gsummary_item.set_image(img) gsummary_item.show() gsummary_item.connect("button-press-event", self._on_button_press_event_gsummary) extra_items.append(gsummary_item) menu = get_summary_menu(suite_host_tuples, self.theme_name, self._set_theme, has_stopped_suites, self.clear_stopped_suites, self.hosts, self.set_hosts, self.update_now, self.start, program_name="cylc gpanel", extra_items=extra_items, owner=self.owner, is_stopped=self.quit) menu.popup( None, None, None, event.button, event.time ) return False def update(self, update_time=None): """Update the Applet.""" suite_host_tuples = [] statuses = copy.deepcopy(self.statuses) stop_summaries = copy.deepcopy(self.stop_summaries) for host in self.hosts: suites = (statuses.get(host, {}).keys() + stop_summaries.get(host, {}).keys()) for suite in suites: suite_host_tuples.append((suite, host)) suite_host_tuples.sort() for child in self.dot_hbox.get_children(): self.dot_hbox.remove(child) number_mode = (not self.is_compact and len(suite_host_tuples) > self.MAX_INDIVIDUAL_SUITES) suite_statuses = {} compact_suite_statuses = [] for suite, host in suite_host_tuples: if suite in statuses.get(host, {}): status_map = statuses[host][suite] is_stopped = False else: info = stop_summaries[host][suite] status_map, suite_time = info is_stopped = True status = extract_group_state(status_map.keys(), is_stopped=is_stopped) if number_mode: suite_statuses.setdefault(is_stopped, {}) suite_statuses[is_stopped].setdefault(status, []) suite_statuses[is_stopped][status].append( (suite, host, status_map.items())) elif self.is_compact: compact_suite_statuses.append((suite, host, status, status_map.items(), is_stopped)) else: self._add_image_box([(suite, host, status, status_map.items(), is_stopped)]) if number_mode: for is_stopped in sorted(suite_statuses.keys()): statuses = suite_statuses[is_stopped].items() statuses.sort(lambda x, y: cmp(len(y[1]), len(x[1]))) for status, suite_host_states_tuples in statuses: label = gtk.Label( str(len(suite_host_states_tuples)) + ":") label.show() self.dot_hbox.pack_start(label, expand=False, fill=False) suite_info_tuples = [] for suite, host, task_states in suite_host_states_tuples: suite_info_tuples.append((suite, host, status, task_states, is_stopped)) self._add_image_box(suite_info_tuples) if self.is_compact: if not compact_suite_statuses: # No suites running or stopped. self.gcylc_image.show() return False self.gcylc_image.hide() self._add_image_box(compact_suite_statuses) return False def _add_image_box(self, suite_host_info_tuples): image_eb = gtk.EventBox() image_eb.show() is_all_stopped = False running_status_list = [] status_list = [] suite_host_tuples = [] for info_tuple in suite_host_info_tuples: suite, host, status, task_states, is_stopped = info_tuple suite_host_tuples.append((suite, host)) if not is_stopped: running_status_list.append(status) status_list.append(status) if running_status_list: status = extract_group_state(running_status_list, is_stopped=False) image = self.dots.get_image(status, is_stopped=False) else: status = extract_group_state(status_list, is_stopped=True) image = self.dots.get_image(status, is_stopped=True) image.show() image_eb.add(image) image_eb._connect_args = suite_host_tuples image_eb.connect("button-press-event", self._on_button_press_event) text_format = "%s - %s - %s" long_text_format = text_format + "\n Tasks: %s\n" text = "" tip_vbox = gtk.VBox() # Only used in PyGTK 2.12+ tip_vbox.show() for info_tuple in suite_host_info_tuples: suite, host, status, task_states, is_stopped = info_tuple task_states.sort(lambda x, y: cmp(len(y[1]), len(x[1]))) tip_hbox = gtk.HBox() tip_hbox.show() state_info = [] for state_name, tasks in task_states: state_info.append(str(len(tasks)) + " " + state_name) image = self.dots.get_image(state_name, is_stopped=is_stopped) image.show() tip_hbox.pack_start(image, expand=False, fill=False) states_text = ", ".join(state_info) if status is None: suite_summary = "?" else: suite_summary = status if is_stopped: suite_summary = "stopped with " + suite_summary tip_label = gtk.Label(text_format % (suite, suite_summary, host)) tip_label.show() tip_hbox.pack_start(tip_label, expand=False, fill=False, padding=5) tip_vbox.pack_start(tip_hbox, expand=False, fill=False) text += long_text_format % (suite, suite_summary, host, states_text) text = text.rstrip() if hasattr(gtk, "Tooltip"): image_eb.set_has_tooltip(True) image_eb.connect("query-tooltip", self._on_img_tooltip_query, tip_vbox) else: self._set_tooltip(image_eb, text) self.dot_hbox.pack_start(image_eb, expand=False, fill=False, padding=1) def _on_button_press_event(self, widget, event): if event.button == 1: self.launch_context_menu(event, suite_host_tuples=widget._connect_args) return False def _on_button_press_event_gsummary(self, widget, event): launch_gsummary(hosts=self.hosts, owner=self.owner) def _on_img_tooltip_query(self, widget, x, y, kbd, tooltip, tip_widget): tooltip.set_custom(tip_widget) return True def _set_exception_hook(self): # Handle an uncaught exception. old_hook = sys.excepthook sys.excepthook = (lambda *a: self._handle_exception(*a, old_hook=old_hook)) def _handle_exception(self, e_type, e_value, e_traceback, old_hook=None): self.gcylc_image.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) exc_lines = traceback.format_exception(e_type, e_value, e_traceback) exc_text = "".join(exc_lines) info = "cylc gpanel has a problem.\n\n%s" % exc_text self._set_tooltip(self.gcylc_image, info.rstrip()) if old_hook is not None: old_hook(exception_class, exception, trace) def _set_gcylc_image_tooltip(self): if self.quit: self._set_tooltip(self.gcylc_image, "Cylc Applet - Off") else: self._set_tooltip(self.gcylc_image, "Cylc Applet - Active") def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = gcfg.get( ['themes', self.theme_name] ) self.dots = DotMaker(self.theme) def _set_tooltip(self, widget, text): tooltip = gtk.Tooltips() tooltip.enable() tooltip.set_tip(widget, text)