Example #1
0
 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()
Example #2
0
    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)
Example #3
0
 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
Example #4
0
 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)
Example #5
0
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
Example #6
0
    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 = []
Example #7
0
    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()
Example #8
0
    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')