Пример #1
0
 def _set_key_liststore(self):
     dotm = DotMaker(self._theme, self._dot_size)
     self._key_liststore.clear()
     for state in task_state.legal:
         dot = dotm.get_icon(state)
         self._key_liststore.append([state, dot])
     self._key_liststore.append(['(unknown)', dotm.get_icon('unknown')])
Пример #2
0
 def _set_key_liststore(self):
     dotm = DotMaker(self._theme, self._dot_size)
     self._key_liststore.clear()
     for state in task_state.legal:
         dot = dotm.get_icon(state)
         self._key_liststore.append([ state, dot])
     self._key_liststore.append(['(unknown)', dotm.get_icon('unknown')])
Пример #3
0
    def __init__(self, cfg, updater, ttreeview, ttree_paths, info_bar, theme):

        super(TreeUpdater, self).__init__()

        self.quit = False
        self.autoexpand = True

        self.cfg = cfg
        self.updater = updater
        self.theme = theme
        self.info_bar = info_bar
        self.last_update_time = None
        self.ancestors = {}
        self.descendants = []

        self.autoexpand_states = [
            'queued', 'submitting', 'submitted', 'running', 'failed'
        ]
        self._last_autoexpand_me = []
        self.ttree_paths = ttree_paths  # Dict of paths vs all descendant node states
        self.should_group_families = ("text" not in self.cfg.ungrouped_views)
        self.ttreeview = ttreeview
        # Hierarchy of models: view <- sorted <- filtered <- base model
        self.ttreestore = ttreeview.get_model().get_model().get_model()

        dotm = DotMaker(theme)
        self.dots = {}
        for state in task_state.legal:
            self.dots[state] = dotm.get_icon(state)
        self.dots['empty'] = dotm.get_icon()
Пример #4
0
    def __init__(self, cfg, updater, ttreeview, ttree_paths, info_bar, theme):

        super(TreeUpdater, self).__init__()

        self.quit = False
        self.autoexpand = True

        self.cfg = cfg
        self.updater = updater
        self.theme = theme
        self.info_bar = info_bar
        self.last_update_time = None
        self.ancestors = {}
        self.descendants = []

        self.autoexpand_states = ["queued", "submitting", "submitted", "running", "failed"]
        self._last_autoexpand_me = []
        self.ttree_paths = ttree_paths  # Dict of paths vs all descendant node states
        self.should_group_families = "text" not in self.cfg.ungrouped_views
        self.ttreeview = ttreeview
        # Hierarchy of models: view <- sorted <- filtered <- base model
        self.ttreestore = ttreeview.get_model().get_model().get_model()

        dotm = DotMaker(theme)
        self.dots = {}
        for state in task_state.legal:
            self.dots[state] = dotm.get_icon(state)
        self.dots["empty"] = dotm.get_icon()
Пример #5
0
    def __init__(self, cfg, updater, treeview, info_bar, theme):

        super(DotUpdater, self).__init__()

        self.quit = False
        self.action_required = False
        self.autoexpand = True
        self.should_hide_headings = False
        self.should_group_families = ("dot" not in cfg.ungrouped_views)
        self.should_transpose_view = False
        self.is_transposed = False

        self.cfg = cfg
        self.updater = updater
        self.theme = theme
        self.info_bar = info_bar
        imagedir = self.cfg.imagedir
        self.last_update_time = None
        self.state_summary = {}
        self.fam_state_summary = {}
        self.ancestors_pruned = {}
        self.descendants = []
        self.filter = ""

        self.led_headings = []
        self.led_treeview = treeview
        self.led_liststore = treeview.get_model()
        self._prev_tooltip_task_id = None
        if hasattr(self.led_treeview, "set_has_tooltip"):
            self.led_treeview.set_has_tooltip(True)
            try:
                self.led_treeview.connect('query-tooltip',
                                          self.on_query_tooltip)
            except TypeError:
                # Lower PyGTK version.
                pass

        self.task_list = []

        # generate task state icons
        dotm = DotMaker(theme)
        self.dots = {}
        for state in task_state.legal:
            self.dots[state] = dotm.get_icon(state)
        self.dots['empty'] = dotm.get_icon()

        self.led_digits_one = []
        self.led_digits_two = []
        self.led_digits_blank = gtk.gdk.pixbuf_new_from_file(
            imagedir + "/digits/one/digit-blank.xpm")
        for i in range(10):
            self.led_digits_one.append(
                gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/one/digit-" +
                                             str(i) + ".xpm"))
            self.led_digits_two.append(
                gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/two/digit-" +
                                             str(i) + ".xpm"))
Пример #6
0
    def __init__(self, cfg, updater, treeview, info_bar, theme):

        super(DotUpdater, self).__init__()

        self.quit = False
        self.action_required = False
        self.autoexpand = True
        self.should_hide_headings = False
        self.should_group_families = "dot" not in cfg.ungrouped_views
        self.should_transpose_view = False
        self.is_transposed = False

        self.cfg = cfg
        self.updater = updater
        self.theme = theme
        self.info_bar = info_bar
        imagedir = self.cfg.imagedir
        self.last_update_time = None
        self.state_summary = {}
        self.fam_state_summary = {}
        self.ancestors_pruned = {}
        self.descendants = []
        self.filter = ""

        self.led_headings = []
        self.led_treeview = treeview
        self.led_liststore = treeview.get_model()
        self._prev_tooltip_task_id = None
        if hasattr(self.led_treeview, "set_has_tooltip"):
            self.led_treeview.set_has_tooltip(True)
            try:
                self.led_treeview.connect("query-tooltip", self.on_query_tooltip)
            except TypeError:
                # Lower PyGTK version.
                pass

        self.task_list = []

        # generate task state icons
        dotm = DotMaker(theme)
        self.dots = {}
        for state in task_state.legal:
            self.dots[state] = dotm.get_icon(state)
        self.dots["empty"] = dotm.get_icon()

        self.led_digits_one = []
        self.led_digits_two = []
        self.led_digits_blank = gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/one/digit-blank.xpm")
        for i in range(10):
            self.led_digits_one.append(gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/one/digit-" + str(i) + ".xpm"))
            self.led_digits_two.append(gtk.gdk.pixbuf_new_from_file(imagedir + "/digits/two/digit-" + str(i) + ".xpm"))
Пример #7
0
    def __init__(self, cfg, updater, treeview, info_bar, theme ):

        super(DotUpdater, self).__init__()

        self.quit = False
        self.cleared = True
        self.action_required = False
        self.autoexpand = True
        self.should_hide_headings = False
        self.should_group_families = ("dot" not in cfg.ungrouped_views)
        self.should_transpose_view = False
        self.is_transposed = False
        self.defn_order_on = True

        self.cfg = cfg
        self.updater = updater
        self.theme = theme
        self.info_bar = info_bar
        imagedir = self.cfg.imagedir
        self.last_update_time = None
        self.state_summary = {}
        self.fam_state_summary = {}
        self.ancestors_pruned = {}
        self.descendants = []
        self.filter = ""
        self.ctimes = []

        self.led_headings = []
        self.led_treeview = treeview
        self.led_liststore = treeview.get_model()
        self._prev_tooltip_task_id = None
        if hasattr(self.led_treeview, "set_has_tooltip"):
            self.led_treeview.set_has_tooltip(True)
            try:
                self.led_treeview.connect('query-tooltip',
                                          self.on_query_tooltip)
            except TypeError:
                # Lower PyGTK version.
                pass

        self.task_list = []

        # generate task state icons
        dotm = DotMaker( theme )
        self.dots = {}
        for state in task_state.legal:
            self.dots[ state ] = dotm.get_icon( state )
        self.dots['empty'] = dotm.get_icon()
Пример #8
0
    def __init__(self, cfg, treeview, info_bar, theme ):

        super(lupdater, self).__init__()

        self.quit = False
        self.autoexpand = True
        self.should_hide_headings = False
        self.should_group_families = False

        self.cfg = cfg
        self.theme = theme
        self.info_bar = info_bar
        imagedir = self.cfg.imagedir

        self.state_summary = {}
        self.global_summary = {}
        self.stop_summary = None
        self.families = []
        self.god = None
        self.mode = "waiting..."
        self.dt = "waiting..."
        self.status = None
        self.poll_schd = PollSchd()
        self.filter = ""

        self.led_treeview = treeview
        self.led_liststore = treeview.get_model()
        self._prev_tooltip_task_id = None

        self.reconnect()

        # generate task state icons
        dotm = DotMaker( theme )
        self.dots = {}
        for state in task_state.legal:
            self.dots[ state ] = dotm.get_icon( state )
        self.dots['empty'] = dotm.get_icon()

        self.led_digits_one = []
        self.led_digits_two = []
        self.led_digits_blank = gtk.gdk.pixbuf_new_from_file( imagedir + "/digits/one/digit-blank.xpm" )
        for i in range(10):
            self.led_digits_one.append( gtk.gdk.pixbuf_new_from_file( imagedir + "/digits/one/digit-" + str(i) + ".xpm" ))
            self.led_digits_two.append( gtk.gdk.pixbuf_new_from_file( imagedir + "/digits/two/digit-" + str(i) + ".xpm" ))
Пример #9
0
    def __init__(self, cfg, updater, ttreeview, ttree_paths, info_bar, theme ):

        super(TreeUpdater, self).__init__()

        self.action_required = False
        self.quit = False
        self.cleared = True
        self.autoexpand = True

        self.count = 0

        self.cfg = cfg
        self.updater = updater
        self.theme = theme
        self.info_bar = info_bar
        self.last_update_time = None
        self.ancestors = {}
        self.descendants = []

        self.autoexpand_states = [ 'queued', 'ready', 'submitted', 'running', 'failed' ]
        self._last_autoexpand_me = []
        self.ttree_paths = ttree_paths  # Dict of paths vs all descendant node states
        self.should_group_families = ("text" not in self.cfg.ungrouped_views)
        self.ttreeview = ttreeview
        # Hierarchy of models: view <- sorted <- filtered <- base model
        self.ttreestore = ttreeview.get_model().get_model().get_model()
        self._prev_tooltip_task_id = None
        if hasattr(self.ttreeview, "set_has_tooltip"):
            self.ttreeview.set_has_tooltip(True)
            try:
                self.ttreeview.connect('query-tooltip',
                                       self.on_query_tooltip)
            except TypeError:
                # Lower PyGTK version.
                pass

        dotm = DotMaker( theme )
        self.dots = {}
        for state in task_state.legal:
            self.dots[ state ] = dotm.get_icon( state )
        self.dots['empty'] = dotm.get_icon()
Пример #10
0
    def __init__(self, cfg, ttreeview, ttree_paths, info_bar, theme ):

        super(tupdater, self).__init__()

        self.quit = False
        self.autoexpand = True

        self.cfg = cfg
        self.theme = theme
        self.info_bar = info_bar

        self.state_summary = {}
        self.global_summary = {}
        self.fam_state_summary = {}
        self.stop_summary = None
        self.families = []
        self.god = None
        self.mode = "waiting..."
        self.dt = "waiting..."
        self.status = None
        self.poll_schd = PollSchd()

        self.autoexpand_states = [ 'submitted', 'running', 'failed', 'held' ]
        self._last_autoexpand_me = []
        self.ttree_paths = ttree_paths  # Dict of paths vs all descendant node states
        self.should_group_families = False
        self.ttreeview = ttreeview
        # Hierarchy of models: view <- sorted <- filtered <- base model
        self.ttreestore = ttreeview.get_model().get_model().get_model()

        dotm = DotMaker( theme )
        self.dots = {}
        for state in task_state.legal:
            self.dots[ state ] = dotm.get_icon( state )
        self.dots['empty'] = dotm.get_icon()

        self.reconnect()
Пример #11
0
class SummaryApp(object):

    """Summarize running suite statuses for a given set of hosts."""

    def __init__(self, hosts=None, owner=None, poll_interval=None):
        gobject.threads_init()
        set_exception_hook_dialog("cylc gsummary")
        setup_icons()
        if not hosts:
            try:
                hosts = sitecfg.get( ["suite host scanning","hosts"] )
            except KeyError:
                hosts = ["localhost"]
        self.hosts = hosts
        if owner is None:
            owner = user
        self.owner = owner
        self.window = gtk.Window()
        self.window.set_title("cylc gsummary")
        self.window.set_icon(get_icon())
        self.vbox = gtk.VBox()
        self.vbox.show()

        self.theme_name = gcfg.get( ['use theme'] )
        self.theme = gcfg.get( ['themes', self.theme_name] )

        self.dots = DotMaker(self.theme)
        suite_treemodel = gtk.TreeStore(*([str, str, bool, str, int] +
            [str] * 20))
        self._prev_tooltip_location_id = None
        self.suite_treeview = gtk.TreeView(suite_treemodel)

        # Construct the host column.
        host_name_column = gtk.TreeViewColumn("Host")
        cell_text_host = gtk.CellRendererText()
        host_name_column.pack_start(cell_text_host, expand=False)
        host_name_column.set_cell_data_func(
                  cell_text_host, self._set_cell_text_host)
        host_name_column.set_sort_column_id(0)
        host_name_column.set_visible(False)

        # Construct the suite name column.
        suite_name_column = gtk.TreeViewColumn("Suite")
        cell_text_name = gtk.CellRendererText()
        suite_name_column.pack_start(cell_text_name, expand=False)
        suite_name_column.set_cell_data_func(
                   cell_text_name, self._set_cell_text_name)
        suite_name_column.set_sort_column_id(1)

        # Construct the suite title column.
        suite_title_column = gtk.TreeViewColumn("Title")
        cell_text_title = gtk.CellRendererText()
        suite_title_column.pack_start(cell_text_title, expand=False)
        suite_title_column.set_cell_data_func(
                   cell_text_title, self._set_cell_text_title)
        suite_title_column.set_sort_column_id(3)
        suite_title_column.set_visible(False)

        # Construct the update time column.
        time_column = gtk.TreeViewColumn("Updated")
        cell_text_time = gtk.CellRendererText()
        time_column.pack_start(cell_text_time, expand=False)
        time_column.set_cell_data_func(
                    cell_text_time, self._set_cell_text_time)
        time_column.set_sort_column_id(4)
        time_column.set_visible(False)

        # Construct the status column.
        status_column = gtk.TreeViewColumn("Status")
        status_column.set_sort_column_id(5)
        for i in range(5, 25):
            cell_pixbuf_state = gtk.CellRendererPixbuf()
            status_column.pack_start(cell_pixbuf_state, expand=False)
            status_column.set_cell_data_func(
                   cell_pixbuf_state, self._set_cell_pixbuf_state, i)

        self.suite_treeview.append_column(host_name_column)
        self.suite_treeview.append_column(suite_name_column)
        self.suite_treeview.append_column(suite_title_column)
        self.suite_treeview.append_column(time_column)
        self.suite_treeview.append_column(status_column)
        self.suite_treeview.show()
        if hasattr(self.suite_treeview, "set_has_tooltip"):
            self.suite_treeview.set_has_tooltip(True)
            try:
                self.suite_treeview.connect('query-tooltip',
                                            self._on_query_tooltip)
            except TypeError:
                # Lower PyGTK version.
                pass
        self.suite_treeview.connect("button-press-event",
                                    self._on_button_press_event)
        scrolled_window = gtk.ScrolledWindow()
        scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
                                   gtk.POLICY_AUTOMATIC)
        scrolled_window.add(self.suite_treeview)
        scrolled_window.show()
        self.vbox.pack_start(scrolled_window, expand=True, fill=True)
        self.updater = SummaryAppUpdater(self.hosts, suite_treemodel,
                                         owner=self.owner,
                                         poll_interval=poll_interval)
        self.updater.start()
        self.window.add(self.vbox)
        self.window.connect("destroy", self._on_destroy_event)
        self.window.set_default_size(200, 100)
        self.suite_treeview.grab_focus()
        self.window.show()

    def _on_button_press_event(self, treeview, event):
        # DISPLAY MENU ONLY ON RIGHT CLICK ONLY

        if (event.type != gtk.gdk._2BUTTON_PRESS and
            event.button != 3):
            return False

        treemodel = treeview.get_model()

        x = int(event.x)
        y = int(event.y)
        time = event.time
        pth = treeview.get_path_at_pos(x, y)

        suite_host_tuples = []

        if pth is not None:
            # Add a gcylc launcher item.
            path, col, cellx, celly = pth

            iter_ = treemodel.get_iter(path)
            host, suite = treemodel.get(iter_, 0, 1)
            suite_host_tuples.append((suite, host))

        if event.type == gtk.gdk._2BUTTON_PRESS:
            if suite_host_tuples:
                launch_gcylc(host, suite, owner=self.owner)
            return False

        has_stopped_suites = bool(self.updater.stop_summaries)

        view_item = gtk.ImageMenuItem("View Column...")
        img = gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU)
        view_item.set_image(img)
        view_item.show()
        view_menu = gtk.Menu()
        view_item.set_submenu(view_menu)
        for column_index, column in enumerate(treeview.get_columns()):
            name = column.get_title()
            is_visible = column.get_visible()
            column_item = gtk.CheckMenuItem(name.replace("_", "__"))
            column_item._connect_args = (column_index, is_visible)
            column_item.set_active(is_visible)
            column_item.connect("toggled", self._on_toggle_column_visible)
            column_item.show()
            view_menu.append(column_item)

        menu = get_summary_menu(suite_host_tuples,
                                self.theme_name,
                                self._set_theme,
                                has_stopped_suites,
                                self.updater.clear_stopped_suites,
                                self.hosts,
                                self.updater.set_hosts,
                                self.updater.update_now,
                                self.updater.start,
                                program_name="cylc gsummary",
                                extra_items=[view_item],
                                owner=self.owner)
        menu.popup( None, None, None, event.button, event.time )
        return False

    def _on_destroy_event(self, widget):
        self.updater.quit = True
        gtk.main_quit()
        return False

    def _on_query_tooltip(self, widget, x, y, kbd_ctx, tooltip):
        """Handle a tooltip creation request."""
        tip_context = self.suite_treeview.get_tooltip_context(x, y, kbd_ctx)
        if tip_context is None:
            self._prev_tooltip_location_id = None
            return False
        x, y = self.suite_treeview.convert_widget_to_bin_window_coords(x, y)
        path, column, cell_x, cell_y = self.suite_treeview.get_path_at_pos(
                                                                    x, y)
        model = self.suite_treeview.get_model()
        iter_ = model.get_iter(path)
        host = model.get_value(iter_, 0)
        suite = model.get_value(iter_, 1)
        update_time = model.get_value(iter_, 4)

        location_id = (host, suite, update_time, column.get_title())
        if location_id != self._prev_tooltip_location_id:
            self._prev_tooltip_location_id = location_id
            tooltip.set_text(None)
            return False
        if column.get_title() in ["Host", "Suite"]:
            tooltip.set_text(suite + " - " + host)
            return True
        if column.get_title() == "Updated":
            time_object = datetime.datetime.fromtimestamp(update_time)
            text = "Info retrieved at " + time_object.isoformat()
            tooltip.set_text(text)
            return True
        if column.get_title() != "Status":
            tooltip.set_text(None)
            return False
        state_texts = []
        for i in range(5, 25):
            state_text = model.get_value(iter_, i)
            if state_text is None:
                break
            status, number = state_text.rsplit(" ", 1)
            state_texts.append(number + " " + status)
        text = "Tasks: " + ", ".join(state_texts)
        tooltip.set_text(text)
        return True

    def _on_toggle_column_visible(self, menu_item):
        column_index, is_visible = menu_item._connect_args
        column = self.suite_treeview.get_columns()[column_index]
        column.set_visible(not is_visible)
        return False

    def _set_cell_pixbuf_state(self, column, cell, model, iter_, index):
        state_info = model.get_value(iter_, index)
        if state_info is None:
            cell.set_property("pixbuf", None)
            cell.set_property("visible", False)
            return
        is_stopped = model.get_value(iter_, 2)
        state, num_tasks = state_info.rsplit(" ", 1)
        icon = self.dots.get_icon(state, is_stopped=is_stopped)
        cell.set_property("pixbuf", icon)
        cell.set_property("visible", True)

    def _set_cell_text_host(self, column, cell, model, iter_):
        host = model.get_value(iter_, 0)
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", host)

    def _set_cell_text_name(self, column, cell, model, iter_):
        name = model.get_value(iter_, 1)
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", name)

    def _set_cell_text_title(self, column, cell, model, iter_):
        title = model.get_value(iter_, 3)
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", title)

    def _set_cell_text_time(self, column, cell, model, iter_):
        update_time = model.get_value(iter_, 4)
        time_object = datetime.datetime.fromtimestamp(update_time)
        time_string = time_object.strftime("%H:%M:%S")
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", time_string)

    def _set_theme(self, new_theme_name):
        self.theme_name = new_theme_name
        self.theme = gcfg.get( ['themes',self.theme_name] )
        self.dots = DotMaker(self.theme)

    def _set_tooltip(self, widget, text):
        tooltip = gtk.Tooltips()
        tooltip.enable()
        tooltip.set_tip(widget, text)
Пример #12
0
 def _set_key_liststore( self ):
     dotm = DotMaker( self._theme )
     self._key_liststore.clear()
     for state in task_state.legal:
         dot = dotm.get_icon( state )
         self._key_liststore.append( [ state, dot ] )
Пример #13
0
class SummaryApp(object):

    """Summarize running suite statuses for a given set of hosts."""

    def __init__(self, hosts=None, owner=None, poll_interval=None):
        gobject.threads_init()
        set_exception_hook_dialog("cylc gsummary")
        setup_icons()
        if not hosts:
            try:
                hosts = GLOBAL_CFG.get( ["suite host scanning","hosts"] )
            except KeyError:
                hosts = ["localhost"]
        self.hosts = hosts
        if owner is None:
            owner = user
        self.owner = owner
        self.window = gtk.Window()
        self.window.set_title("cylc gsummary")
        self.window.set_icon(get_icon())
        self.vbox = gtk.VBox()
        self.vbox.show()

        self.theme_name = gcfg.get( ['use theme'] )
        self.theme = gcfg.get( ['themes', self.theme_name] )

        self.dots = DotMaker(self.theme)
        suite_treemodel = gtk.TreeStore(*([str, str, bool, str, int] +
            [str] * 20))
        self._prev_tooltip_location_id = None
        self.suite_treeview = gtk.TreeView(suite_treemodel)

        # Construct the host column.
        host_name_column = gtk.TreeViewColumn("Host")
        cell_text_host = gtk.CellRendererText()
        host_name_column.pack_start(cell_text_host, expand=False)
        host_name_column.set_cell_data_func(
                  cell_text_host, self._set_cell_text_host)
        host_name_column.set_sort_column_id(0)
        host_name_column.set_visible(False)

        # Construct the suite name column.
        suite_name_column = gtk.TreeViewColumn("Suite")
        cell_text_name = gtk.CellRendererText()
        suite_name_column.pack_start(cell_text_name, expand=False)
        suite_name_column.set_cell_data_func(
                   cell_text_name, self._set_cell_text_name)
        suite_name_column.set_sort_column_id(1)

        # Construct the suite title column.
        suite_title_column = gtk.TreeViewColumn("Title")
        cell_text_title = gtk.CellRendererText()
        suite_title_column.pack_start(cell_text_title, expand=False)
        suite_title_column.set_cell_data_func(
                   cell_text_title, self._set_cell_text_title)
        suite_title_column.set_sort_column_id(3)
        suite_title_column.set_visible(False)

        # Construct the update time column.
        time_column = gtk.TreeViewColumn("Updated")
        cell_text_time = gtk.CellRendererText()
        time_column.pack_start(cell_text_time, expand=False)
        time_column.set_cell_data_func(
                    cell_text_time, self._set_cell_text_time)
        time_column.set_sort_column_id(4)
        time_column.set_visible(False)

        # Construct the status column.
        status_column = gtk.TreeViewColumn("Status")
        status_column.set_sort_column_id(5)
        for i in range(5, 25):
            cell_pixbuf_state = gtk.CellRendererPixbuf()
            status_column.pack_start(cell_pixbuf_state, expand=False)
            status_column.set_cell_data_func(
                   cell_pixbuf_state, self._set_cell_pixbuf_state, i)

        self.suite_treeview.append_column(host_name_column)
        self.suite_treeview.append_column(suite_name_column)
        self.suite_treeview.append_column(suite_title_column)
        self.suite_treeview.append_column(time_column)
        self.suite_treeview.append_column(status_column)
        self.suite_treeview.show()
        if hasattr(self.suite_treeview, "set_has_tooltip"):
            self.suite_treeview.set_has_tooltip(True)
            try:
                self.suite_treeview.connect('query-tooltip',
                                            self._on_query_tooltip)
            except TypeError:
                # Lower PyGTK version.
                pass
        self.suite_treeview.connect("button-press-event",
                                    self._on_button_press_event)
        scrolled_window = gtk.ScrolledWindow()
        scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
                                   gtk.POLICY_AUTOMATIC)
        scrolled_window.add(self.suite_treeview)
        scrolled_window.show()
        self.vbox.pack_start(scrolled_window, expand=True, fill=True)
        self.updater = SummaryAppUpdater(self.hosts, suite_treemodel,
                                         owner=self.owner,
                                         poll_interval=poll_interval)
        self.updater.start()
        self.window.add(self.vbox)
        self.window.connect("destroy", self._on_destroy_event)
        self.window.set_default_size(200, 100)
        self.suite_treeview.grab_focus()
        self.window.show()

    def _on_button_press_event(self, treeview, event):
        # DISPLAY MENU ONLY ON RIGHT CLICK ONLY

        if (event.type != gtk.gdk._2BUTTON_PRESS and
            event.button != 3):
            return False

        treemodel = treeview.get_model()

        x = int(event.x)
        y = int(event.y)
        time = event.time
        pth = treeview.get_path_at_pos(x, y)

        suite_host_tuples = []

        if pth is not None:
            # Add a gcylc launcher item.
            path, col, cellx, celly = pth

            iter_ = treemodel.get_iter(path)
            host, suite = treemodel.get(iter_, 0, 1)
            suite_host_tuples.append((suite, host))

        if event.type == gtk.gdk._2BUTTON_PRESS:
            if suite_host_tuples:
                launch_gcylc(host, suite, owner=self.owner)
            return False

        has_stopped_suites = bool(self.updater.stop_summaries)

        view_item = gtk.ImageMenuItem("View Column...")
        img = gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU)
        view_item.set_image(img)
        view_item.show()
        view_menu = gtk.Menu()
        view_item.set_submenu(view_menu)
        for column_index, column in enumerate(treeview.get_columns()):
            name = column.get_title()
            is_visible = column.get_visible()
            column_item = gtk.CheckMenuItem(name.replace("_", "__"))
            column_item._connect_args = (column_index, is_visible)
            column_item.set_active(is_visible)
            column_item.connect("toggled", self._on_toggle_column_visible)
            column_item.show()
            view_menu.append(column_item)

        menu = get_summary_menu(suite_host_tuples,
                                self.theme_name,
                                self._set_theme,
                                has_stopped_suites,
                                self.updater.clear_stopped_suites,
                                self.hosts,
                                self.updater.set_hosts,
                                self.updater.update_now,
                                self.updater.start,
                                program_name="cylc gsummary",
                                extra_items=[view_item],
                                owner=self.owner)
        menu.popup( None, None, None, event.button, event.time )
        return False

    def _on_destroy_event(self, widget):
        self.updater.quit = True
        gtk.main_quit()
        return False

    def _on_query_tooltip(self, widget, x, y, kbd_ctx, tooltip):
        """Handle a tooltip creation request."""
        tip_context = self.suite_treeview.get_tooltip_context(x, y, kbd_ctx)
        if tip_context is None:
            self._prev_tooltip_location_id = None
            return False
        x, y = self.suite_treeview.convert_widget_to_bin_window_coords(x, y)
        path, column, cell_x, cell_y = self.suite_treeview.get_path_at_pos(
                                                                    x, y)
        model = self.suite_treeview.get_model()
        iter_ = model.get_iter(path)
        host = model.get_value(iter_, 0)
        suite = model.get_value(iter_, 1)
        update_time = model.get_value(iter_, 4)

        location_id = (host, suite, update_time, column.get_title())
        if location_id != self._prev_tooltip_location_id:
            self._prev_tooltip_location_id = location_id
            tooltip.set_text(None)
            return False
        if column.get_title() in ["Host", "Suite"]:
            tooltip.set_text(suite + " - " + host)
            return True
        if column.get_title() == "Updated":
            time_point = get_timepoint_from_seconds_since_unix_epoch(
                update_time)
            tooltip.set_text("Info retrieved at " + str(time_point))
            return True
        if column.get_title() != "Status":
            tooltip.set_text(None)
            return False
        state_texts = []
        for i in range(5, 25):
            state_text = model.get_value(iter_, i)
            if state_text is None:
                break
            status, number = state_text.rsplit(" ", 1)
            state_texts.append(number + " " + status)
        text = "Tasks: " + ", ".join(state_texts)
        tooltip.set_text(text)
        return True

    def _on_toggle_column_visible(self, menu_item):
        column_index, is_visible = menu_item._connect_args
        column = self.suite_treeview.get_columns()[column_index]
        column.set_visible(not is_visible)
        return False

    def _set_cell_pixbuf_state(self, column, cell, model, iter_, index):
        state_info = model.get_value(iter_, index)
        if state_info is None:
            cell.set_property("pixbuf", None)
            cell.set_property("visible", False)
            return
        is_stopped = model.get_value(iter_, 2)
        state, num_tasks = state_info.rsplit(" ", 1)
        icon = self.dots.get_icon(state, is_stopped=is_stopped)
        cell.set_property("pixbuf", icon)
        cell.set_property("visible", True)

    def _set_cell_text_host(self, column, cell, model, iter_):
        host = model.get_value(iter_, 0)
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", host)

    def _set_cell_text_name(self, column, cell, model, iter_):
        name = model.get_value(iter_, 1)
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", name)

    def _set_cell_text_title(self, column, cell, model, iter_):
        title = model.get_value(iter_, 3)
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", title)

    def _set_cell_text_time(self, column, cell, model, iter_):
        update_time = model.get_value(iter_, 4)
        time_point = get_timepoint_from_seconds_since_unix_epoch(update_time)
        time_point.set_time_zone_to_local()
        time_string = str(time_point).split("T")[1]
        is_stopped = model.get_value(iter_, 2)
        cell.set_property("sensitive", not is_stopped)
        cell.set_property("text", time_string)

    def _set_theme(self, new_theme_name):
        self.theme_name = new_theme_name
        self.theme = gcfg.get( ['themes',self.theme_name] )
        self.dots = DotMaker(self.theme)

    def _set_tooltip(self, widget, text):
        tooltip = gtk.Tooltips()
        tooltip.enable()
        tooltip.set_tip(widget, text)