diff --git a/doc/gcylcrc.tex b/doc/gcylcrc.tex index c0f256d5ba6..4b7b94add28 100644 --- a/doc/gcylcrc.tex +++ b/doc/gcylcrc.tex @@ -12,6 +12,31 @@ \section{Gcylc Config File Reference} \subsection{Top Level Items} +\subsubsection{dot icon size} + +Set the size of the task state dot icons displayed in the text and dot +views. + +\begin{myitemize} +\item {\em type:} string +\item {\em legal values:} ``small'' (10px), ``medium'' (14px), ``large'' (20px), + ``extra large (30px)'' +\item {\em default:} ``medium'' +\end{myitemize} + + +\subsubsection{initial side-by-side views} + +Set the suite view panels initial orientation when the GUI starts. +This can be changed later using the ``View'' menu ``Toggle views side-by-side'' + option. + +\begin{myitemize} +\item {\em type:} boolean (False or True) +\item {\em default:} ``False'' +\end{myitemize} + + \subsubsection{initial views} Set the suite view panel(s) displayed initially, when the GUI starts. @@ -24,47 +49,62 @@ \subsubsection{initial views} \item {\em example:} \lstinline@initial views = graph, dot@ \end{myitemize} -\subsubsection{ungrouped views} +\subsubsection{sort by definition order} -List suite views, if any, that should be displayed initially in an -ungrouped state. Namespace family grouping can be changed later -using the tool bar. +If this is not turned off the default sort order for task names and +families in the dot and text views will the order they appear in the +suite definition. Clicking on the task name column in the treeview will +toggle to alphanumeric sort, and a View menu item does the same for the +dot view. If turned off, the default sort order is alphanumeric and +definition order is not available at all. \begin{myitemize} -\item {\em type:} string (a list of zero or more view names) -\item {\em legal values:} ``text'', ``dot'', ``graph'' -\item {\em default:} (none) -\item {\em example:} \lstinline@ungrouped views = text, dot@ +\item {\em type:} boolean +\item {\em default:} True \end{myitemize} -\subsubsection{use theme} -Set the task state color theme, common to all views, to use -initially. The color theme can be changed later using the tool bar. -See \lstinline@gcylc.rc.eg@ and \lstinline@themes.rc@ in -\lstinline@$CYLC_DIR/conf/gcylcrc/@ for how to modify existing color -themes or define your own. Use \lstinline@cylc get-gui-config@ -to list your available themes. +\subsubsection{sort column} + +If ``text'' is in \lstinline@initial views@ then \lstinline@sort column@ sets +the column that will be sorted initially when the GUI launches. Sorting can be +changed later by clicking on the column headers. \begin{myitemize} -\item {\em type:} string (theme name) -\item {\em legal values:} ``default'', ``solid'', ``high-contrast'', - ``color-blind'', and any custom or user-modified themes. -\item {\em default:} ``default'' + \item {\em type:} string + \item {\em legal values:} ``task'', ``state'', ``host'', ``job system'', + ``job ID'', ``T-submit'', ``T-start'', ``T-finish'', ``dT-mean'', + ``latest message'', ``none'' + \item {\em default:} ``none'' + \item {\em example:} \lstinline@sort column = T-start@ \end{myitemize} -\subsubsection{initial side-by-side views} -Set the suite view panels initial orientation when the GUI starts. -This can be changed later using the "View" menu "Toggle views side-by-side" - option. +\subsubsection{sort column ascending} + +For use in combination with \lstinline@sort column@, sets whether the column will +be sorted using ascending or descending order. \begin{myitemize} -\item {\em type:} boolean (False or True) -\item {\em legal values:} ``False'', ``True''. -\item {\em default:} ``False'' + \item {\em type:} boolean + \item {\em default:} ``True'' + \item {\em example:} \lstinline@sort column ascending = False@ +\end{myitemize} + + +\subsubsection{task filter highlight color} + +The color used to highlight active task filters in gcylc. It must be a name +from the X11 rgb.txt file, e.g.\ \lstinline=SteelBlue=; or a +{\em quoted} hexadecimal color code, e.g.\ \lstinline="#ff0000"= for red (quotes +are required to prevent the hex code being interpreted as a comment). + +\begin{myitemize} + \item {\em type:} string + \item {\em default:} \lstinline=PowderBlue= \end{myitemize} + \subsubsection{task states to filter out} Set the initial filtering options when the GUI starts. Later this can be @@ -77,43 +117,76 @@ \subsubsection{task states to filter out} \item {\em default:} runahead \end{myitemize} -\subsubsection{dot icon size} -Set the size of the task state dot icons displayed in the text and dot -views. +\subsubsection{transpose dot} + +Transposes the content in dot view so that it displays from left to right rather +than from top to bottom. Can be changed later using the options submenu +available via the view menu. \begin{myitemize} -\item {\em type:} string -\item {\em legal values:} ``small'' (10px), ``medium'' (14px), ``large'' (20px) -\item {\em default:} ``medium'' + \item {\em type:} boolean + \item {\em default:} ``False'' + \item {\em example:} \lstinline@transpose dot = True@ \end{myitemize} -\subsubsection{sort by definition order} -If this is not turned off the default sort order for task names and -families in the dot and text views will the order they appear in the -suite definition. Clicking on the task name column in the treeview will -toggle to alphanumeric sort, and a View menu item does the same for the -dot view. If turned off, the default sort order is alphanumeric and -definition order is not available at all. +\subsubsection{transpose graph} + +Transposes the content in graph view so that it displays from left to right +rather than from top to bottom. Can be changed later using the options submenu +via the view menu. \begin{myitemize} -\item {\em type:} boolean -\item {\em default:} True + \item {\em type:} boolean + \item {\em default:} ``False'' + \item {\em example:} \lstinline@transpose graph = True@ \end{myitemize} -\subsubsection{task filter highlight color} -The color used to highlight active task filters in gcylc. It must be a name -from the X11 rgb.txt file, e.g.\ \lstinline=SteelBlue=; or a -{\em quoted} hexadecimal color code, e.g.\ \lstinline="#ff0000"= for red (quotes -are required to prevent the hex code being interpreted as a comment). +\subsubsection{ungrouped views} + +List suite views, if any, that should be displayed initially in an +ungrouped state. Namespace family grouping can be changed later +using the tool bar. \begin{myitemize} - \item {\em type:} string - \item {\em default:} \lstinline=PowderBlue= +\item {\em type:} string (a list of zero or more view names) +\item {\em legal values:} ``text'', ``dot'', ``graph'' +\item {\em default:} (none) +\item {\em example:} \lstinline@ungrouped views = text, dot@ +\end{myitemize} + + +\subsubsection{use theme} + +Set the task state color theme, common to all views, to use +initially. The color theme can be changed later using the tool bar. +See \lstinline@gcylc.rc.eg@ and \lstinline@themes.rc@ in +\lstinline@$CYLC_DIR/conf/gcylcrc/@ for how to modify existing color +themes or define your own. Use \lstinline@cylc get-gui-config@ +to list your available themes. + +\begin{myitemize} +\item {\em type:} string (theme name) +\item {\em legal values:} ``default'', ``solid'', ``high-contrast'', + ``color-blind'', and any custom or user-modified themes. +\item {\em default:} ``default'' +\end{myitemize} + + +\subsubsection{window size} + +Sets the size (in pixels) of the cylc GUI at startup. + +\begin{myitemize} + \item {\em type:} integer list (x, y) + \item {\em legal values:} positive integers + \item {\em default:} 800, 500 + \item {\em example:} \lstinline@window size = 1000, 700@ \end{myitemize} + \subsection{[themes]} This section may contain task state color theme definitions. diff --git a/lib/cylc/cfgspec/gcylc.py b/lib/cylc/cfgspec/gcylc.py index a25b0249039..2259e59cfd5 100644 --- a/lib/cylc/cfgspec/gcylc.py +++ b/lib/cylc/cfgspec/gcylc.py @@ -26,6 +26,7 @@ from parsec.validate import validator as vdr from parsec.upgrade import upgrader from parsec.util import printcfg +from cylc.gui.view_tree import ControlTree from cylc.task_state import ( TASK_STATUSES_ALL, TASK_STATUS_RUNAHEAD, TASK_STATUS_HELD, TASK_STATUS_WAITING, TASK_STATUS_EXPIRED, TASK_STATUS_QUEUED, @@ -41,16 +42,20 @@ USER_FILE = os.path.join(os.environ['HOME'], '.cylc', 'gcylc.rc') SPEC = { - 'initial views': vdr(vtype='string_list', default=["text"]), - 'ungrouped views': vdr(vtype='string_list', default=[]), - 'use theme': vdr(vtype='string', default="default"), 'dot icon size': vdr( vtype='string', default="medium", options=["small", "medium", "large", "extra large"]), + 'initial side-by-side views': vdr(vtype='boolean', default=False), + 'initial views': vdr(vtype='string_list', default=["text"]), 'sort by definition order': vdr(vtype='boolean', default=True), + 'sort column': vdr( + vtype='string', + default='none', + options=[heading for heading in ControlTree.headings if heading is not + None] + ['none']), + 'sort column ascending': vdr(vtype='boolean', default=True), 'task filter highlight color': vdr(vtype='string', default='PowderBlue'), - 'initial side-by-side views': vdr(vtype='boolean', default=False), 'task states to filter out': vdr( vtype='string_list', default=[TASK_STATUS_RUNAHEAD]), @@ -73,6 +78,11 @@ TASK_STATUS_RUNAHEAD: vdr(vtype='string_list'), }, }, + 'transpose dot': vdr(vtype='boolean', default=False), + 'transpose graph': vdr(vtype='boolean', default=False), + 'ungrouped views': vdr(vtype='string_list', default=[]), + 'use theme': vdr(vtype='string', default="default"), + 'window size': vdr(vtype='integer_list', default=[800, 500]), } @@ -173,8 +183,24 @@ def transform(self): cfg['themes'] = cfg_themes def check(self): - # check initial view config cfg = self.get(sparse=True) + + # check window size config + if 'window size' in cfg: + fail = False + if len(cfg['window size']) != 2: + print >> sys.stderr, ("WARNING: window size requires two " + "values (x, y). Using default.") + fail = True + elif cfg['window size'][0] < 0 or cfg['window size'][1] < 0: + print >> sys.stderr, ("WARNING: window size values must be " + "positive. Using default.") + fail = True + # TODO: check for daft window sizes? (10, 5), (80000, 5000) ? + if fail: + cfg['window size'] = [800, 500] + + # check initial view config if 'initial views' not in cfg: return views = copy(cfg['initial views']) diff --git a/lib/cylc/gui/app_gcylc.py b/lib/cylc/gui/app_gcylc.py index 976d7347dc1..692223ab073 100644 --- a/lib/cylc/gui/app_gcylc.py +++ b/lib/cylc/gui/app_gcylc.py @@ -562,7 +562,8 @@ def __init__(self, suite, db, owner, host, port, pyro_timeout, self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_icon(get_icon()) - self.window.set_default_size(800, 500) + window_size = gcfg.get(['window size']) + self.window.set_default_size(window_size[0], window_size[1]) self.window.connect("delete_event", self.delete_event) self._prev_status = None @@ -878,6 +879,10 @@ def create_view(self, viewname, view_num=0, pane_position=-1): view_widgets.set_size_request(1, 1) container.pack_start(view_widgets, expand=True, fill=True) + + # Set user default values for this view + self.set_view_defaults(viewname, view_num) + # Handle menu menu = self.views_option_menus[view_num] for item in menu.get_children(): @@ -899,6 +904,23 @@ def create_view(self, viewname, view_num=0, pane_position=-1): self.current_view_toolitems[view_num] = new_toolitems self.window_show_all() + def set_view_defaults(self, viewname, view_num): + """Apply user settings defined in gcylc.rc on a new view. + Run this method before handling menus or toolbars.""" + # Sort text view by column ('sort column') + if gcfg.get(['sort column']) != 'none' and viewname == 'text': + self.current_views[view_num].sort_by_column( + gcfg.get(['sort column']), + ascending=gcfg.get(['sort column ascending']) + ) + # Transpose graph view ('transpose graph') + elif gcfg.get(['transpose graph']) and viewname == 'graph': + self.current_views[view_num].toggle_left_to_right_mode(None) + # Transpose dot view ('transpose dot') + elif gcfg.get(['transpose dot']) and viewname == 'dot': + view = self.current_views[view_num] + view.t.should_transpose_view = True + def remove_view(self, view_num): """Remove a view instance.""" self.current_views[view_num].stop() diff --git a/lib/cylc/gui/view_tree.py b/lib/cylc/gui/view_tree.py index 4b51f4a0c67..9cd3a430564 100644 --- a/lib/cylc/gui/view_tree.py +++ b/lib/cylc/gui/view_tree.py @@ -29,6 +29,11 @@ class ControlTree(object): """Text Treeview suite control interface.""" + headings = [ + None, 'task', 'state', 'host', 'job system', 'job ID', 'T-submit', + 'T-start', 'T-finish', 'dT-mean', 'latest message', + ] + def __init__(self, cfg, updater, theme, dot_size, info_bar, get_right_click_menu, log_colors, insert_task_popup): @@ -105,14 +110,10 @@ def treeview_widgets(self): self.ttreeview.connect( 'button_press_event', self.on_treeview_button_pressed) - headings = [ - None, 'task', 'state', 'host', 'job system', 'job ID', 'T-submit', - 'T-start', 'T-finish', 'dT-mean', 'latest message', - ] - for n in range(1, len(headings)): + for n in range(1, len(ControlTree.headings)): # Skip first column (cycle point) - tvc = gtk.TreeViewColumn(headings[n]) + tvc = gtk.TreeViewColumn(ControlTree.headings[n]) if n == 1: crp = gtk.CellRendererPixbuf() tvc.pack_start(crp, False) @@ -207,6 +208,18 @@ def on_treeview_button_pressed(self, treeview, event): return True + def sort_by_column(self, col_name=None, col_no=None, ascending=True): + """Sort this ControlTree by the column selected by the string + col_name OR by the index col_no.""" + if col_name is not None and col_name in ControlTree.headings: + col_no = ControlTree.headings.index(col_name) + if col_no is not None: + self.sort_col_num = col_no + cols = self.ttreeview.get_columns() + order = gtk.SORT_ASCENDING if ascending else gtk.SORT_DESCENDING + cols[col_no].set_sort_order(order) + self.tmodelsort.set_sort_column_id(col_no - 1, order) + def sort_column(self, model, iter1, iter2, col_num): cols = self.ttreeview.get_columns() point_string1 = model.get_value(iter1, 0)