def get_icon( self, state=None, is_stopped=False ): """Generate a gtk.gdk.Pixbuf for a state. if is_stopped, generate a stopped form of the Pixbuf. """ size = gcfg.get(['dot icon size']) if is_stopped: xpm = deepcopy(stopped[size]) else: xpm = deepcopy(live[size]) if not state or state not in self.theme: # empty icon ('None' is xpm transparent) cols = ['None', 'None' ] else: style = self.theme[state]['style'] color = self.theme[state]['color'] if style == 'filled': cols = [ color, color ] else: # unfilled with thick border cols = [ 'None', color ] xpm[1] = xpm[1].replace( '<FILL>', cols[0] ) xpm[2] = xpm[2].replace( '<BRDR>', cols[1] ) # NOTE: to get a pixbuf from an xpm file, use: # gtk.gdk.pixbuf_new_from_file('/path/to/file.xpm') return gtk.gdk.pixbuf_new_from_xpm_data( data=xpm )
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.hosts_suites_info = {} self.stopped_hosts_suites_info = {} self._set_exception_hook() super(ScanPanelAppletUpdater, self).__init__( hosts, owner=owner, poll_interval=poll_interval)
def _set_theme(self, new_theme_name): """Set GUI theme.""" self.theme_name = new_theme_name self.theme = gcfg.get(['themes', self.theme_name]) self._set_dots() self.updater.update() self.update_theme_legend()
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) self.interval_full = gsfg.get(['suite listing update interval']) self.interval_part = gsfg.get(['suite status update interval']) 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 __init__(self, hosts, dot_hbox, gcylc_image, is_compact, poll_interval=None): self.hosts = hosts self.dot_hbox = dot_hbox self.gcylc_image = gcylc_image self.is_compact = is_compact if poll_interval is None: poll_interval = self.POLL_INTERVAL self.poll_interval = poll_interval self._should_force_update = False self._last_running_time = None self.quit = True self.last_update_time = None 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.suite_info_map = {} self._set_exception_hook() self.owner_pattern = re.compile(r'\A%s\Z' % USER)
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 = gcfg.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 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 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[self.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 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( "button-press-event", lambda b, e: launch_hosts_dialog( self.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( "button-press-event", lambda b, e: launch_about_dialog("cylc gscan", self.hosts) ) help_menu.append(info_item) self.menu_bar.show_all()
def __init__(self, hosts=None, owner=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gscan") setup_icons() if not hosts: hosts = GLOBAL_CFG.get(["suite host scanning", "hosts"]) self.hosts = hosts if owner is None: owner = USER self.owner = owner self.window = gtk.Window() self.window.set_title("cylc gscan") 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, str) 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("host" in gsfg.get(["columns"])) host_name_column.set_resizable(True) # 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) suite_name_column.set_visible("suite" in gsfg.get(["columns"])) suite_name_column.set_resizable(True) # 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("title" in gsfg.get(["columns"])) suite_title_column.set_resizable(True) # 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("updated" in gsfg.get(["columns"])) time_column.set_resizable(True) 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) # Construct the status column. status_column = gtk.TreeViewColumn("Status") status_column.set_sort_column_id(5) status_column.set_visible("status" in gsfg.get(["columns"])) status_column.set_resizable(True) status_column_info = 6 cycle_column_info = 5 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, cycle_column_info) self.suite_treeview.append_column(status_column) 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, (status_column_info, i)) 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 = ScanAppUpdater( self.hosts, suite_treemodel, self.suite_treeview, 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(300, 150) self.suite_treeview.grab_focus() self.window.show()
def __init__(self, hosts=None, owner=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gscan") setup_icons() if not hosts: hosts = GLOBAL_CFG.get(["suite host scanning", "hosts"]) self.hosts = hosts if owner is None: owner = user self.owner = owner self.window = gtk.Window() self.window.set_title("cylc gscan") 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, str) 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) host_name_column.set_resizable(True) # 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) suite_name_column.set_resizable(True) # 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) suite_title_column.set_resizable(True) # 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) time_column.set_resizable(True) 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) # Construct the status column. status_column = gtk.TreeViewColumn("Status") status_column.set_sort_column_id(5) status_column.set_resizable(True) status_column_info = 6 cycle_column_info = 5 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, cycle_column_info) self.suite_treeview.append_column(status_column) distinct_states = len(task_state.legal) for i in range(distinct_states): 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, (status_column_info, i)) 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 = ScanAppUpdater(self.hosts, suite_treemodel, self.suite_treeview, 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(300, 150) self.suite_treeview.grab_focus() self.window.show()
def get_scan_menu(suite_host_tuples, 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 scan GUIs. suite_host_tuples should be a list of (suite, host) 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 suite, host in suite_host_tuples: gcylc_item = gtk.ImageMenuItem("Launch gcylc: %s - %s" % (suite, host)) img = gtk.image_new_from_stock("gcylc", gtk.ICON_SIZE_MENU) gcylc_item.set_image(img) gcylc_item._connect_args = (suite, host) gcylc_item.connect( "button-press-event", lambda b, e: launch_gcylc( b._connect_args[1], b._connect_args[0], owner=owner)) gcylc_item.show() menu.append(gcylc_item) if suite_host_tuples: 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 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 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: launch_theme_legend(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 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 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 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 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 _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_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, 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 = gcfg.get(['use theme']) self.theme = gcfg.get(['themes', self.theme_name]) suite_treemodel = gtk.TreeStore( str, # group str, # host str, # owner str, # suite 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 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_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) patterns = {"name": None, "owner": None} for label, items in [("owner", patterns_owner), ("name", patterns_name)]: if items: patterns[label] = r"\A(?:" + r")|(?:".join(items) + r")\Z" try: patterns[label] = re.compile(patterns[label]) except re.error: raise ValueError("Invalid %s pattern: %s" % (label, items)) self.updater = ScanAppUpdater(self.window, hosts, suite_treemodel, self.treeview, comms_timeout=comms_timeout, interval=interval, group_column_id=self.GROUP_COLUMN, name_pattern=patterns["name"], owner_pattern=patterns["owner"]) self.updater.start() self.dot_size = gcfg.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 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[self.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 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, hosts=None, owner=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gscan") setup_icons() if not hosts: hosts = GLOBAL_CFG.get(["suite host scanning", "hosts"]) self.hosts = hosts if owner is None: owner = USER self.owner = owner self.window = gtk.Window() self.window.set_title("cylc gscan") self.window.set_icon(get_icon()) self.vbox = gtk.VBox() self.vbox.show() self.warnings = {} 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, str, str) 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("host" in gsfg.get(["columns"])) host_name_column.set_resizable(True) # 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) suite_name_column.set_visible("suite" in gsfg.get(["columns"])) suite_name_column.set_resizable(True) # 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("title" in gsfg.get( ["columns"])) suite_title_column.set_resizable(True) # 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("updated" in gsfg.get(["columns"])) time_column.set_resizable(True) 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) # Construct the status column. status_column = gtk.TreeViewColumn("Status") status_column.set_sort_column_id(5) status_column.set_visible("status" in gsfg.get(["columns"])) 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.suite_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.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 = ScanAppUpdater( self.hosts, suite_treemodel, self.suite_treeview, 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(300, 150) self.suite_treeview.grab_focus() self.window.show() self.warning_icon_shown = []
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 __init__( self, hosts=None, patterns_name=None, patterns_owner=None, comms_timeout=None, poll_interval=None): gobject.threads_init() set_exception_hook_dialog("cylc gscan") setup_icons() if not hosts: hosts = GLOBAL_CFG.get(["suite host scanning", "hosts"]) self.hosts = hosts self.window = gtk.Window() title = "cylc gscan" for opt, items, skip in [ ("-n", patterns_name, None), ("-o", patterns_owner, USER)]: if items: for pattern in items: if pattern != skip: 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 = gcfg.get(['use theme']) self.theme = gcfg.get(['themes', self.theme_name]) suite_treemodel = gtk.TreeStore( str, # group str, # host str, # owner str, # suite 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 vis_cols = gsfg.get(["columns"]) # Doesn't make any sense without suite name column if gsfg.COL_SUITE not in vis_cols: vis_cols.append(gsfg.COL_SUITE.lower()) # In multiple host environment, add host column by default if hosts: vis_cols.append(gsfg.COL_HOST.lower()) # In multiple owner environment, add owner column by default if patterns_owner != [USER]: vis_cols.append(gsfg.COL_OWNER.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_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) patterns = {"name": None, "owner": None} for label, items in [ ("owner", patterns_owner), ("name", patterns_name)]: if items: patterns[label] = r"\A(?:" + r")|(?:".join(items) + r")\Z" try: patterns[label] = re.compile(patterns[label]) except re.error: raise ValueError("Invalid %s pattern: %s" % (label, items)) self.updater = ScanAppUpdater( self.window, self.hosts, suite_treemodel, self.treeview, comms_timeout=comms_timeout, poll_interval=poll_interval, group_column_id=self.GROUP_COLUMN, name_pattern=patterns["name"], owner_pattern=patterns["owner"]) self.updater.start() self.dot_size = gcfg.get(['dot icon size']) self._set_dots() 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.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() 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 get_summary_menu(suite_host_tuples, 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 summary GUIs. suite_host_tuples should be a list of (suite, host) 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 suite, host in suite_host_tuples: gcylc_item = gtk.ImageMenuItem("Launch gcylc: %s - %s" % (suite, host)) img = gtk.image_new_from_stock("gcylc", gtk.ICON_SIZE_MENU) gcylc_item.set_image(img) gcylc_item._connect_args = (suite, host) gcylc_item.connect("button-press-event", lambda b, e: launch_gcylc( b._connect_args[1], b._connect_args[0], owner=owner)) gcylc_item.show() menu.append(gcylc_item) if suite_host_tuples: 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 theme chooser items (same as cylc.gui.SuiteControl). 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 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: launch_theme_legend( 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, 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 = gcfg.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')