def _set_theme(self, new_theme_name): """Set GUI theme.""" self.theme_name = new_theme_name self.theme = GcylcConfig.get_inst().get(['themes', self.theme_name]) self._set_dots() self.updater.update() self.update_theme_legend()
def __init__(self, app): super(Updater, self).__init__() self.quit = False self.app_window = app.window self.cfg = app.cfg self.info_bar = app.info_bar self.full_mode = True self.err_log_lines = [] self.task_list = [] self.state_summary = {} self.full_state_summary = {} self.fam_state_summary = {} self.full_fam_state_summary = {} self.all_families = {} self.global_summary = {} self.ancestors = {} self.ancestors_pruned = {} self.descendants = {} self.stop_summary = None self.mode = "waiting..." self.update_time_str = "waiting..." self.last_update_time = time() self.update_interval = 1.0 self.max_update_interval = GcylcConfig.get_inst().get( ['maximum update interval']) self.status = SUITE_STATUS_NOT_CONNECTED self.is_reloading = False self.connected = False self.no_update_event = threading.Event() self.ns_defn_order = [] self.dict_ns_defn_order = {} self.restricted_display = app.restricted_display self.filter_name_string = '' self.filter_states_excl = [] self.kept_task_ids = set() self.filt_task_ids = set() self.version_mismatch_warned = False self.client = None # Report sign-out on exit. atexit.register(self.signout)
def __init__(self, dot_hbox, gcylc_image, is_compact): self.hosts = [] self.dot_hbox = dot_hbox self.gcylc_image = gcylc_image self.is_compact = is_compact self.prev_full_update = None self.prev_norm_update = None self.quit = True self._set_gcylc_image_tooltip() self.gcylc_image.set_sensitive(False) gsfg = GScanConfig.get_inst() self.interval_full = gsfg.get(['suite listing update interval']) self.interval_part = gsfg.get(['suite status update interval']) gcfg = GcylcConfig.get_inst() self.theme_name = gcfg.get(['use theme']) self.theme = gcfg.get(['themes', self.theme_name]) self.dots = DotMaker(self.theme) self.suite_info_map = {} self._set_exception_hook() self.owner_pattern = None
def _set_theme(self, new_theme_name): self.theme_name = new_theme_name self.theme = GcylcConfig.get_inst().get(['themes', self.theme_name]) self.dots = DotMaker(self.theme)
def get_gpanel_scan_menu(suite_keys, theme_name, set_theme_func, has_stopped_suites, clear_stopped_suites_func, scanned_hosts, change_hosts_func, update_now_func, start_func, program_name, extra_items=None, owner=None, is_stopped=False): """Return a right click menu for the gpanel GUI. TODO this used to be for gscan too; simplify now it's only for gpanel? suite_keys should be a list of (host, owner, suite) tuples (if any). theme_name should be the name of the current theme. set_theme_func should be a function accepting a new theme name. has_stopped_suites should be a boolean denoting currently stopped suites. clear_stopped_suites should be a function with no arguments that removes stopped suites from the current view. scanned_hosts should be a list of currently scanned suite hosts. change_hosts_func should be a function accepting a new list of suite hosts to scan. update_now_func should be a function with no arguments that forces an update now or soon. start_func should be a function with no arguments that re-activates idle GUIs. program_name should be a string describing the parent program. extra_items (keyword) should be a list of extra menu items to add to the right click menu. owner (keyword) should be the owner of the suites, if not the current user. is_stopped (keyword) denotes whether the GUI is in an inactive state. """ menu = gtk.Menu() if is_stopped: switch_on_item = gtk.ImageMenuItem("Activate") img = gtk.image_new_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) switch_on_item.set_image(img) switch_on_item.show() switch_on_item.connect("button-press-event", lambda b, e: start_func()) menu.append(switch_on_item) # Construct gcylc launcher items for each relevant suite. for host, owner, suite in suite_keys: gcylc_item = gtk.ImageMenuItem("Launch gcylc: %s - %s@%s" % (suite.replace('_', '__'), owner, host)) img_gcylc = gtk.image_new_from_stock("gcylc", gtk.ICON_SIZE_MENU) gcylc_item.set_image(img_gcylc) gcylc_item._connect_args = (host, owner, suite) gcylc_item.connect("button-press-event", lambda b, e: launch_gcylc(b._connect_args)) gcylc_item.show() menu.append(gcylc_item) if suite_keys: sep_item = gtk.SeparatorMenuItem() sep_item.show() menu.append(sep_item) if extra_items is not None: for item in extra_items: menu.append(item) sep_item = gtk.SeparatorMenuItem() sep_item.show() menu.append(sep_item) # Construct a cylc stop item to stop a suite if len(suite_keys) > 1: stoptask_item = gtk.ImageMenuItem('Stop all') else: stoptask_item = gtk.ImageMenuItem('Stop') img_stop = gtk.image_new_from_stock(gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_MENU) stoptask_item.set_image(img_stop) stoptask_item._connect_args = suite_keys, 'stop' stoptask_item.connect( "button-press-event", lambda b, e: call_cylc_command(b._connect_args[0], b._connect_args[1])) stoptask_item.show() menu.append(stoptask_item) # Construct a cylc hold item to hold (pause) a suite if len(suite_keys) > 1: holdtask_item = gtk.ImageMenuItem('Hold all') else: holdtask_item = gtk.ImageMenuItem('Hold') img_hold = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_MENU) holdtask_item.set_image(img_hold) holdtask_item._connect_args = suite_keys, 'hold' holdtask_item.connect( "button-press-event", lambda b, e: call_cylc_command(b._connect_args[0], b._connect_args[1])) menu.append(holdtask_item) holdtask_item.show() # Construct a cylc release item to release a paused/stopped suite if len(suite_keys) > 1: unstoptask_item = gtk.ImageMenuItem('Release all') else: unstoptask_item = gtk.ImageMenuItem('Release') img_release = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_MENU) unstoptask_item.set_image(img_release) unstoptask_item._connect_args = suite_keys, 'release' unstoptask_item.connect( "button-press-event", lambda b, e: call_cylc_command(b._connect_args[0], b._connect_args[1])) unstoptask_item.show() menu.append(unstoptask_item) # Add another separator sep_item = gtk.SeparatorMenuItem() sep_item.show() menu.append(sep_item) # Construct theme chooser items (same as cylc.gui.app_main). theme_item = gtk.ImageMenuItem('Theme') img = gtk.image_new_from_stock(gtk.STOCK_SELECT_COLOR, gtk.ICON_SIZE_MENU) theme_item.set_image(img) theme_item.set_sensitive(not is_stopped) thememenu = gtk.Menu() theme_item.set_submenu(thememenu) theme_item.show() theme_items = {} theme = "default" theme_items[theme] = gtk.RadioMenuItem(label=theme) thememenu.append(theme_items[theme]) theme_items[theme].theme_name = theme gcfg = GcylcConfig.get_inst() for theme in gcfg.get(['themes']): if theme == "default": continue theme_items[theme] = gtk.RadioMenuItem(group=theme_items['default'], label=theme) thememenu.append(theme_items[theme]) theme_items[theme].theme_name = theme # set_active then connect, to avoid causing an unnecessary toggle now. theme_items[theme_name].set_active(True) for theme in gcfg.get(['themes']): theme_items[theme].show() theme_items[theme].connect( 'toggled', lambda i: (i.get_active() and set_theme_func(i.theme_name))) menu.append(theme_item) theme_legend_item = gtk.MenuItem("Show task state key") theme_legend_item.show() theme_legend_item.set_sensitive(not is_stopped) theme_legend_item.connect( "button-press-event", lambda b, e: ThemeLegendWindow(None, gcfg.get(['themes', theme_name]))) menu.append(theme_legend_item) sep_item = gtk.SeparatorMenuItem() sep_item.show() menu.append(sep_item) # Construct a trigger update item. update_now_item = gtk.ImageMenuItem("Update Now") img = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU) update_now_item.set_image(img) update_now_item.show() update_now_item.set_sensitive(not is_stopped) update_now_item.connect("button-press-event", lambda b, e: update_now_func()) menu.append(update_now_item) # Construct a clean stopped suites item. clear_item = gtk.ImageMenuItem("Clear Stopped Suites") img = gtk.image_new_from_stock(gtk.STOCK_CLEAR, gtk.ICON_SIZE_MENU) clear_item.set_image(img) clear_item.show() clear_item.set_sensitive(has_stopped_suites) clear_item.connect("button-press-event", lambda b, e: clear_stopped_suites_func()) menu.append(clear_item) # Construct a configure scanned hosts item. hosts_item = gtk.ImageMenuItem("Configure Hosts") img = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU) hosts_item.set_image(img) hosts_item.show() hosts_item.connect( "button-press-event", lambda b, e: launch_hosts_dialog(scanned_hosts, change_hosts_func)) menu.append(hosts_item) sep_item = gtk.SeparatorMenuItem() sep_item.show() menu.append(sep_item) # Construct an about dialog item. info_item = gtk.ImageMenuItem("About") img = gtk.image_new_from_stock(gtk.STOCK_ABOUT, gtk.ICON_SIZE_MENU) info_item.set_image(img) info_item.show() info_item.connect( "button-press-event", lambda b, e: launch_about_dialog(program_name, scanned_hosts)) menu.append(info_item) return menu
def __init__(self, hosts=None, patterns_name=None, patterns_owner=None, comms_timeout=None, interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gscan") setup_icons() self.window = gtk.Window() title = "cylc gscan" for opt, items in [("-n", patterns_name), ("-o", patterns_owner)]: if items: for pattern in items: if pattern is not None: title += " %s %s" % (opt, pattern) self.window.set_title(title) self.window.set_icon(get_icon()) self.vbox = gtk.VBox() self.vbox.show() self.warnings = {} self.theme_name = GcylcConfig.get_inst().get(['use theme']) self.theme = GcylcConfig.get_inst().get(['themes', self.theme_name]) suite_treemodel = gtk.TreeStore( str, # group str, # host str, # owner str, # suite str, # version bool, # is_stopped str, # title int, # update_time str, # states str, # states_text str) # warning_text self._prev_tooltip_location_id = None self.treeview = gtk.TreeView(suite_treemodel) # Visibility of columns gsfg = GScanConfig.get_inst() vis_cols = gsfg.get(["columns"]) hide_main_menu_bar = gsfg.get(["hide main menubar"]) # Doesn't make any sense without suite name column if gsfg.COL_SUITE not in vis_cols: vis_cols.append(gsfg.COL_SUITE.lower()) # Construct the group, host, owner, suite, title, update time column. for col_title, col_id, col_cell_text_setter in [ (gsfg.COL_GROUP, self.GROUP_COLUMN, self._set_cell_text_group), (gsfg.COL_HOST, self.HOST_COLUMN, self._set_cell_text_host), (gsfg.COL_OWNER, self.OWNER_COLUMN, self._set_cell_text_owner), (gsfg.COL_SUITE, self.SUITE_COLUMN, self._set_cell_text_name), (gsfg.COL_VERSION, self.VERSION_COLUMN, self._set_cell_text_version), (gsfg.COL_TITLE, self.TITLE_COLUMN, self._set_cell_text_title), (gsfg.COL_UPDATED, self.UPDATE_TIME_COLUMN, self._set_cell_text_time), ]: column = gtk.TreeViewColumn(col_title) cell_text = gtk.CellRendererText() column.pack_start(cell_text, expand=False) column.set_cell_data_func(cell_text, col_cell_text_setter) column.set_sort_column_id(col_id) column.set_visible(col_title.lower() in vis_cols) column.set_resizable(True) self.treeview.append_column(column) # Construct the status column. status_column = gtk.TreeViewColumn(gsfg.COL_STATUS) status_column.set_sort_column_id(self.STATUS_COLUMN) status_column.set_visible(gsfg.COL_STATUS.lower() in vis_cols) status_column.set_resizable(True) cell_text_cycle = gtk.CellRendererText() status_column.pack_start(cell_text_cycle, expand=False) status_column.set_cell_data_func(cell_text_cycle, self._set_cell_text_cycle, self.CYCLE_COLUMN) self.treeview.append_column(status_column) # Warning icon. warn_icon = gtk.CellRendererPixbuf() image = gtk.Image() pixbuf = image.render_icon(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_LARGE_TOOLBAR) self.warn_icon_colour = pixbuf.scale_simple( # colour warn icon pixbuf self.ICON_SIZE, self.ICON_SIZE, gtk.gdk.INTERP_HYPER) self.warn_icon_grey = pixbuf.scale_simple(self.ICON_SIZE, self.ICON_SIZE, gtk.gdk.INTERP_HYPER) self.warn_icon_colour.saturate_and_pixelate( self.warn_icon_grey, 0, False) # b&w warn icon pixbuf status_column.pack_start(warn_icon, expand=False) status_column.set_cell_data_func(warn_icon, self._set_error_icon_state) self.warn_icon_blank = gtk.gdk.Pixbuf( # Transparent pixbuff. gtk.gdk.COLORSPACE_RGB, True, 8, self.ICON_SIZE, self.ICON_SIZE).fill(0x00000000) # Task status icons. for i in range(len(TASK_STATUSES_ORDERED)): 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.treeview.show() if hasattr(self.treeview, "set_has_tooltip"): self.treeview.set_has_tooltip(True) try: self.treeview.connect('query-tooltip', self._on_query_tooltip) except TypeError: # Lower PyGTK version. pass self.treeview.connect("button-press-event", self._on_button_press_event) cre_owner, cre_name = re_compile_filters(patterns_owner, patterns_name) self.updater = ScanAppUpdater(self.window, hosts, suite_treemodel, self.treeview, comms_timeout, interval, self.GROUP_COLUMN, cre_owner, cre_name) self.updater.start() self.dot_size = GcylcConfig.get_inst().get(['dot icon size']) self.dots = None self._set_dots() self.menu_bar = None self.create_menubar() accelgroup = gtk.AccelGroup() self.window.add_accel_group(accelgroup) key, modifier = gtk.accelerator_parse('<Alt>m') accelgroup.connect_group(key, modifier, gtk.ACCEL_VISIBLE, self._toggle_hide_menu_bar) self.tool_bar = None self.create_tool_bar() self.menu_hbox = gtk.HBox() self.menu_hbox.pack_start(self.menu_bar, expand=True, fill=True) self.menu_hbox.pack_start(self.tool_bar, expand=True, fill=True) self.menu_hbox.show_all() if hide_main_menu_bar: self.menu_hbox.hide_all() scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled_window.add(self.treeview) scrolled_window.show() self.vbox.pack_start(self.menu_hbox, expand=False) self.vbox.pack_start(scrolled_window, expand=True, fill=True) self.window.add(self.vbox) self.window.connect("destroy", self._on_destroy_event) wsize = gsfg.get(['window size']) self.window.set_default_size(*wsize) self.treeview.grab_focus() self.window.show() self.theme_legend_window = None self.warning_icon_shown = []
def create_menubar(self): """Create the main menu.""" self.menu_bar = gtk.MenuBar() file_menu = gtk.Menu() file_menu_root = gtk.MenuItem('_File') file_menu_root.set_submenu(file_menu) exit_item = gtk.ImageMenuItem('E_xit') img = gtk.image_new_from_stock(gtk.STOCK_QUIT, gtk.ICON_SIZE_MENU) exit_item.set_image(img) exit_item.show() exit_item.connect("activate", self._on_destroy_event) file_menu.append(exit_item) view_menu = gtk.Menu() view_menu_root = gtk.MenuItem('_View') view_menu_root.set_submenu(view_menu) col_item = gtk.ImageMenuItem("_Columns...") img = gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU) col_item.set_image(img) col_item.show() col_menu = gtk.Menu() for column_index, column in enumerate(self.treeview.get_columns()): name = column.get_title() is_visible = column.get_visible() column_item = gtk.CheckMenuItem(name.replace("_", "__")) column_item._connect_args = column_index column_item.set_active(is_visible) column_item.connect("toggled", self._on_toggle_column_visible) column_item.show() col_menu.append(column_item) col_item.set_submenu(col_menu) col_item.show_all() view_menu.append(col_item) view_menu.append(gtk.SeparatorMenuItem()) # Construct theme chooser items (same as cylc.gui.app_main). theme_item = gtk.ImageMenuItem('Theme...') img = gtk.image_new_from_stock(gtk.STOCK_SELECT_COLOR, gtk.ICON_SIZE_MENU) theme_item.set_image(img) thememenu = gtk.Menu() theme_item.set_submenu(thememenu) theme_item.show() theme_items = {} theme = "default" theme_items[theme] = gtk.RadioMenuItem(label=theme) thememenu.append(theme_items[theme]) theme_items[theme].theme_name = theme for theme in GcylcConfig.get_inst().get(['themes']): if theme == "default": continue theme_items[theme] = gtk.RadioMenuItem( group=theme_items['default'], label=theme) thememenu.append(theme_items[theme]) theme_items[theme].theme_name = theme # set_active then connect, to avoid causing an unnecessary toggle now. theme_items[self.theme_name].set_active(True) for theme in GcylcConfig.get_inst().get(['themes']): theme_items[theme].show() theme_items[theme].connect( 'toggled', lambda i: (i.get_active() and self._set_theme(i.theme_name))) view_menu.append(theme_item) theme_legend_item = gtk.ImageMenuItem("Show task state key") img = gtk.image_new_from_stock(gtk.STOCK_SELECT_COLOR, gtk.ICON_SIZE_MENU) theme_legend_item.set_image(img) theme_legend_item.show() theme_legend_item.connect("activate", self.popup_theme_legend) view_menu.append(theme_legend_item) view_menu.append(gtk.SeparatorMenuItem()) # Construct a configure scanned hosts item. hosts_item = gtk.ImageMenuItem("Configure Hosts") img = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU) hosts_item.set_image(img) hosts_item.show() hosts_item.connect( "activate", lambda w: launch_hosts_dialog(self.updater.hosts, self. updater.set_hosts)) view_menu.append(hosts_item) sep_item = gtk.SeparatorMenuItem() sep_item.show() help_menu = gtk.Menu() help_menu_root = gtk.MenuItem('_Help') help_menu_root.set_submenu(help_menu) self.menu_bar.append(file_menu_root) self.menu_bar.append(view_menu_root) self.menu_bar.append(help_menu_root) # Construct an about dialog item. info_item = gtk.ImageMenuItem("About") img = gtk.image_new_from_stock(gtk.STOCK_ABOUT, gtk.ICON_SIZE_MENU) info_item.set_image(img) info_item.show() info_item.connect( "activate", lambda w: launch_about_dialog("cylc gscan", self.updater.hosts)) help_menu.append(info_item) self.menu_bar.show_all()
def __init__(self, cfg, updater, theme, info_bar, xdot): super(GraphUpdater, self).__init__() self.quit = False self.cleared = False self.ignore_suicide = True self.focus_start_point_string = None self.focus_stop_point_string = None self.xdot = xdot self.first_update = False self.graph_disconnect = False self.action_required = True self.oldest_point_string = None self.newest_point_string = None self.orientation = "TB" # Top to Bottom ordering of nodes self.best_fit = True # zoom to page size self.normal_fit = False # zoom to 1.0 scale self.crop = False # organise by cycle point. self.subgraphs_on = GcylcConfig.get_inst().get(["sub-graphs on"]) self.descendants = {} self.all_families = [] self.write_dot_frames = False self.prev_graph_id = () self.cfg = cfg self.updater = updater self.theme = theme self.info_bar = info_bar self.state_summary = {} self.fam_state_summary = {} self.global_summary = {} self.last_update_time = None self.god = None self.mode = "waiting..." self.update_time_str = "waiting..." self.prev_graph_id = () # empty graphw object: self.graphw = CGraphPlain(self.cfg.suite) # lists of nodes to newly group or ungroup (not of all currently # grouped and ungrouped nodes - still held server side) self.group = [] self.ungroup = [] self.have_leaves_and_feet = False self.leaves = [] self.feet = [] self.ungroup_recursive = False if "graph" in self.cfg.ungrouped_views: self.ungroup_all = True self.group_all = False else: self.ungroup_all = False self.group_all = True self.graph_frame_count = 0 self.suite_share_dir = glbl_cfg().get_derived_host_item( self.cfg.suite, 'suite share directory')