From a34fdef1eddb7e65d63e7c644acac94c1ca3adbe Mon Sep 17 00:00:00 2001 From: Masayuki Igawa Date: Fri, 30 Sep 2016 16:14:43 -0700 Subject: [PATCH] Make size column configurable graph This commit makes the size column configurable to graphs by configuration file. And this commit adds color styles by thresholds which are configurable. Change-Id: Ifdc6961efbb178cc314c0fbd4d948a1ba19dcdd6 --- examples/openstack-gertty.yaml | 9 ++++ gertty/config.py | 15 +++++++ gertty/palette.py | 16 +++++++ gertty/view/change_list.py | 76 ++++++++++++++++++++++++++++++++-- 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/examples/openstack-gertty.yaml b/examples/openstack-gertty.yaml index 55af548..e666fbb 100644 --- a/examples/openstack-gertty.yaml +++ b/examples/openstack-gertty.yaml @@ -143,3 +143,12 @@ reviewkeys: - key: 'meta 4' approvals: [] message: "recheck" + +# 'size-column' is a set of customize parameters for the 'Size' column +# on your dashboard. +# 'type' must be 'graph' or 'number'. Default is 'graph'. +# 'thresholds' is for bar graphs width (when graph) or color styles +# (when number). +size-column: + type: 'graph' + thresholds: [1, 10, 100, 1000] diff --git a/gertty/config.py b/gertty/config.py index 371d44b..7593334 100644 --- a/gertty/config.py +++ b/gertty/config.py @@ -111,6 +111,11 @@ class ConfigSchema(object): keymaps = [keymap] + thresholds = [int, int, int, int, int, int, int, int] + size_column = {v.Required('type'): v.Any('graph', 'splitGraph', 'number', + 'disabled', None), + v.Optional('thresholds'): thresholds} + def getSchema(self, data): schema = v.Schema({v.Required('servers'): self.servers, 'palettes': self.palettes, @@ -129,6 +134,7 @@ class ConfigSchema(object): 'breadcrumbs': bool, 'change-list-options': self.change_list_options, 'expire-age': str, + 'size-column': self.size_column, }) return schema @@ -250,6 +256,15 @@ class Config(object): self.expire_age = self.config.get('expire-age', '2 months') + self.size_column = self.config.get('size-column', {}) + self.size_column['type'] = self.size_column.get('type', 'graph') + if self.size_column['type'] == 'graph': + self.size_column['thresholds'] = self.size_column.get('thresholds', + [1, 10, 100, 1000]) + else: + self.size_column['thresholds'] = self.size_column.get('thresholds', + [1, 10, 100, 200, 400, 600, 800, 1000]) + def getServer(self, name=None): for server in self.config['servers']: if name is None or name == server['name']: diff --git a/gertty/palette.py b/gertty/palette.py index 4d5e81b..ea72a16 100644 --- a/gertty/palette.py +++ b/gertty/palette.py @@ -98,6 +98,22 @@ DEFAULT_PALETTE={ 'added-removed-graph': ['dark green', 'dark red'], 'focused-added-graph': ['default,standout', 'dark green'], 'focused-removed-graph': ['default,standout', 'dark red'], + 'line-count-threshold-1': ['light green', ''], + 'focused-line-count-threshold-1': ['light green,standout', ''], + 'line-count-threshold-2': ['light cyan', ''], + 'focused-line-count-threshold-2': ['light cyan,standout', ''], + 'line-count-threshold-3': ['light blue', ''], + 'focused-line-count-threshold-3': ['light blue,standout', ''], + 'line-count-threshold-4': ['yellow', ''], + 'focused-line-count-threshold-4': ['yellow,standout', ''], + 'line-count-threshold-5': ['dark magenta', ''], + 'focused-line-count-threshold-5': ['dark magenta,standout', ''], + 'line-count-threshold-6': ['light magenta', ''], + 'focused-line-count-threshold-6': ['light magenta,standout', ''], + 'line-count-threshold-7': ['dark red', ''], + 'focused-line-count-threshold-7': ['dark red,standout', ''], + 'line-count-threshold-8': ['light red', ''], + 'focused-line-count-threshold-8': ['light red,standout', ''], } # A delta from the default palette diff --git a/gertty/view/change_list.py b/gertty/view/change_list.py index d502513..e0dfd5d 100644 --- a/gertty/view/change_list.py +++ b/gertty/view/change_list.py @@ -104,6 +104,15 @@ class ChangeRow(urwid.Button, ChangeListColumns): 'added-graph': 'focused-added-graph', 'removed-graph': 'focused-removed-graph', + + 'line-count-threshold-1': 'focused-line-count-threshold-1', + 'line-count-threshold-2': 'focused-line-count-threshold-2', + 'line-count-threshold-3': 'focused-line-count-threshold-3', + 'line-count-threshold-4': 'focused-line-count-threshold-4', + 'line-count-threshold-5': 'focused-line-count-threshold-5', + 'line-count-threshold-6': 'focused-line-count-threshold-6', + 'line-count-threshold-7': 'focused-line-count-threshold-7', + 'line-count-threshold-8': 'focused-line-count-threshold-8', } def selectable(self): @@ -148,7 +157,7 @@ class ChangeRow(urwid.Button, ChangeListColumns): return True return False - def _makeSize(self, added, removed): + def _makeSizeGraph(self, added, removed): # Removed is a red graph on top, added is a green graph on bottom. # # The graph is 4 cells wide. If both the red and green graphs @@ -165,7 +174,9 @@ class ChangeRow(urwid.Button, ChangeListColumns): ret = [] # The graph is logarithmic -- one cell for each order of # magnitude. - for threshold in [1, 10, 100, 1000]: + conf_thresholds = self.app.config.size_column['thresholds'] + # for threshold in [1, 10, 100, 1000]: + for threshold in conf_thresholds: color = [] if (added > threshold and removed > threshold): ret.append(('added-removed-graph', lower_box)) @@ -177,6 +188,36 @@ class ChangeRow(urwid.Button, ChangeListColumns): ret.append(' ') return ret + def _makeSizeSplitGraph(self, added, removed): + # Removed is a red graph on right, added is a green graph on left. + # conf_thresholds[7]: Full block, + # conf_thresholds[6]: Left seven eighths block, + # ...., conf_thresholds[0]: Left one eighth block. + # You can see the character table at the wikipedia[1] or somewhere. + # [1] https://en.wikipedia.org/wiki/Block_Elements#Character_table + conf_thresholds = self.app.config.size_column['thresholds'] + thresholds = [(conf_thresholds[7], u'\u2588'), + (conf_thresholds[6], u'\u2589'), + (conf_thresholds[5], u'\u258a'), + (conf_thresholds[4], u'\u258b'), + (conf_thresholds[3], u'\u258c'), + (conf_thresholds[2], u'\u258d'), + (conf_thresholds[1], u'\u258e'), + (conf_thresholds[0], u'\u258f')] + ret = [] + # The graph is logarithmic -- one cell for each order of + # magnitude. + for diff in [[added, 'added-graph'], [removed, 'removed-graph']]: + for threshold in thresholds: + if (diff[0] == 0): + ret.append(' ') + break + if (diff[0] >= threshold[0]): + ret.append((diff[1], threshold[1])) + break + ret.append(' ') + return ret + def update(self, change, categories): if change.reviewed or change.hidden: style = 'reviewed-change' @@ -217,7 +258,32 @@ class ChangeRow(urwid.Button, ChangeListColumns): continue total_added += rfile.inserted or 0 total_removed += rfile.deleted or 0 - self.size.set_text(self._makeSize(total_added, total_removed)) + if self.app.config.size_column['type'] == 'number': + total_added_removed = total_added + total_removed + thresholds = self.app.config.size_column['thresholds'] + size_style = 'line-count-threshold-1' + if (total_added_removed >= thresholds[7]): + size_style = 'line-count-threshold-8' + elif (total_added_removed >= thresholds[6]): + size_style = 'line-count-threshold-7' + elif (total_added_removed >= thresholds[5]): + size_style = 'line-count-threshold-6' + elif (total_added_removed >= thresholds[4]): + size_style = 'line-count-threshold-5' + elif (total_added_removed >= thresholds[3]): + size_style = 'line-count-threshold-4' + elif (total_added_removed >= thresholds[2]): + size_style = 'line-count-threshold-3' + elif (total_added_removed >= thresholds[1]): + size_style = 'line-count-threshold-2' + elif (total_added_removed >= thresholds[0]): + size_style = 'line-count-threshold-1' + self.size.set_text((size_style, str(total_added_removed))) + elif self.app.config.size_column['type'] == 'splitGraph': + self.size.set_text(self._makeSizeSplitGraph(total_added, + total_removed)) + else: + self.size.set_text(self._makeSizeGraph(total_added, total_removed)) self.category_columns = [] for category in categories: @@ -267,6 +333,7 @@ class ChangeListHeader(urwid.WidgetWrap, ChangeListColumns): @mouse_scroll_decorator.ScrollByWheel class ChangeListView(urwid.WidgetWrap, mywid.Searchable): required_columns = set(['Number', 'Subject', 'Updated']) + # FIXME(masayukig): Disable 'Size' column when configured optional_columns = set(['Topic', 'Branch', 'Size']) def getCommands(self): @@ -344,6 +411,9 @@ class ChangeListView(urwid.WidgetWrap, mywid.Searchable): # not. self.enabled_columns.discard('Owner') self.disabled_columns.add('Owner') + if app.config.size_column['type'] == 'disabled': + self.enabled_columns.discard('Size') + self.disabled_columns.add('Size') self.sort_by = sort_by or app.config.change_list_options['sort-by'] if reverse is not None: self.reverse = reverse