From 27a2c75409c7abae68c4ad3af99d8e90927af803 Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Mon, 28 Apr 2014 13:57:05 +0200 Subject: [LIBREPORT PATCH 03/10] Worklflow: order workflows according to their priority Higher number -> higher priority -> more visible place in UI Introduce 'priority' element in XML workflow definition: - child of 'workflow' element - the type is signed integer - optional value, if not present, 0 is used Related to #259 Signed-off-by: Jakub Filak mmilata: fix DTD in manual page --- doc/report-gtk.txt | 8 +++++++- src/cli/cli-report.c | 32 ++++++++++++++++++-------------- src/gui-wizard-gtk/wizard.c | 10 ++++++---- src/include/workflow.h | 10 ++++++++++ src/lib/workflow.c | 21 +++++++++++++++++++++ src/lib/workflow_xml_parser.c | 20 +++++++++++++++++++- 6 files changed, 81 insertions(+), 20 deletions(-) diff --git a/doc/report-gtk.txt b/doc/report-gtk.txt index e7611de..f39c77c 100644 --- a/doc/report-gtk.txt +++ b/doc/report-gtk.txt @@ -64,11 +64,12 @@ These configuration files are placed in /usr/share/libreport/workflows. Each file has XML formatting with the following DTD: ------------ - + + ------------ @@ -79,6 +80,10 @@ name:: description:: User visible description +priority:: + Priority of the workflow. Higher number means a more visible place in UI. + If not provided, 0 is used. The value is signed integer. + events:: List of executed events @@ -98,6 +103,7 @@ Simple reporting work flow Příklad Example description Příklad popisu + 10 analyze_example collect_example diff --git a/src/cli/cli-report.c b/src/cli/cli-report.c index 68baa8b..9cc7613 100644 --- a/src/cli/cli-report.c +++ b/src/cli/cli-report.c @@ -824,32 +824,36 @@ int run_event_chain(const char *dump_dir_name, GList *chain, int interactive) static workflow_t *select_workflow(GHashTable *workflows) { - GHashTableIter iter; - gpointer key = NULL; - workflow_t *value = NULL; + GList *wf_list = g_hash_table_get_values(workflows); - g_hash_table_iter_init(&iter, workflows); - - if (!g_hash_table_iter_next(&iter, &key, (gpointer *)&value)) + if (wf_list == NULL) { error_msg("No workflow suitable for this problem was found!"); return NULL; } - if (g_hash_table_size(workflows) == 1) + const guint wf_cnt = g_list_length(wf_list); + if (wf_cnt == 1) { - log_notice("autoselected workflow: '%s'", (char *)key); - return value; + workflow_t *wf_selected = (workflow_t *)wf_list->data; + log_notice("autoselected workflow: '%s'", (char *)wf_get_name(wf_selected)); + g_list_free(wf_list); + return wf_selected; } - workflow_t *help_wf_array[g_hash_table_size(workflows)]; + wf_list = g_list_sort(wf_list, (GCompareFunc)wf_priority_compare); + + workflow_t *help_wf_array[wf_cnt]; unsigned count = 0; - do + + for(GList *wf_iter = wf_list; wf_iter; wf_iter = g_list_next(wf_iter)) { - help_wf_array[count] = value; - printf("%d %s\n %s\n\n", ++count, wf_get_screen_name(value), wf_get_description(value)); + workflow_t *wf = (workflow_t *)wf_iter->data; + help_wf_array[count] = wf; + printf("%d %s\n %s\n\n", ++count, wf_get_screen_name(wf), wf_get_description(wf)); } - while (g_hash_table_iter_next(&iter, &key, (gpointer *)&value)); + + g_list_free(wf_list); const unsigned picked = choose_number_from_range(1, count, _("Select a workflow to run: ")); return help_wf_array[picked - 1]; diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c index 82bdf3e..e6f6ee7 100644 --- a/src/gui-wizard-gtk/wizard.c +++ b/src/gui-wizard-gtk/wizard.c @@ -2736,10 +2736,12 @@ static void add_workflow_buttons(GtkBox *box, GHashTable *workflows, GCallback f list_possible_events_glist(g_dump_dir_name, "workflow"), WORKFLOWS_DIR); - GList *keys = g_hash_table_get_keys(workflow_table); - while(keys) + GList *wf_list = g_hash_table_get_values(workflow_table); + wf_list = g_list_sort(wf_list, (GCompareFunc)wf_priority_compare); + + for (GList *wf_iter = wf_list; wf_iter; wf_iter = g_list_next(wf_iter)) { - workflow_t *w = g_hash_table_lookup(workflow_table, keys->data); + workflow_t *w = (workflow_t *)wf_iter->data; char *btn_label = xasprintf("%s\n%s", wf_get_screen_name(w), wf_get_description(w)); GtkWidget *button = gtk_button_new_with_label(btn_label); GList *children = gtk_container_get_children(GTK_CONTAINER(button)); @@ -2756,9 +2758,9 @@ static void add_workflow_buttons(GtkBox *box, GHashTable *workflows, GCallback f free(btn_label); g_signal_connect(button, "clicked", func, w); gtk_box_pack_start(box, button, true, false, 2); - keys = g_list_next(keys); } + g_list_free(wf_list); } static char *setup_next_processed_event(GList **events_list) diff --git a/src/include/workflow.h b/src/include/workflow.h index 66bbdaf..d79708e 100644 --- a/src/include/workflow.h +++ b/src/include/workflow.h @@ -39,11 +39,21 @@ GList *wf_get_event_names(workflow_t *w); const char *wf_get_screen_name(workflow_t *w); const char *wf_get_description(workflow_t *w); const char *wf_get_long_desc(workflow_t *w); +int wf_get_priority(workflow_t *w); void wf_set_screen_name(workflow_t *w, const char* screen_name); void wf_set_description(workflow_t *w, const char* description); void wf_set_long_desc(workflow_t *w, const char* long_desc); void wf_add_event(workflow_t *w, event_config_t *ec); +void wf_set_priority(workflow_t *w, int priority); + +/* + * Returns a negative integer if the first value comes before the second, 0 if + * they are equal, or a positive integer if the first value comes after the + * second. + */ +int wf_priority_compare(const workflow_t *first, const workflow_t *second); + GHashTable *load_workflow_config_data_from_list(GList *wf_names, const char *path); #endif diff --git a/src/lib/workflow.c b/src/lib/workflow.c index 52ad924..c6eedf4 100644 --- a/src/lib/workflow.c +++ b/src/lib/workflow.c @@ -24,6 +24,7 @@ struct workflow { config_item_info_t *info; + int priority; // direct correlation: higher number -> higher priority GList *events; //list of event_option_t }; @@ -193,6 +194,11 @@ const char *wf_get_long_desc(workflow_t *w) return ci_get_long_desc(workflow_get_config_info(w)); } +int wf_get_priority(workflow_t *w) +{ + return w->priority; +} + void wf_set_screen_name(workflow_t *w, const char* screen_name) { ci_set_screen_name(workflow_get_config_info(w), screen_name); @@ -213,3 +219,18 @@ void wf_add_event(workflow_t *w, event_config_t *ec) w->events = g_list_append(w->events, ec); log_info("added to ev list: '%s'", ec_get_screen_name(ec)); } + +void wf_set_priority(workflow_t *w, int priority) +{ + w->priority = priority; +} + +/* + * Returns a negative integer if the first value comes before the second, 0 if + * they are equal, or a positive integer if the first value comes after the + * second. + */ +int wf_priority_compare(const workflow_t *first, const workflow_t *second) +{ + return second->priority - first->priority; +} diff --git a/src/lib/workflow_xml_parser.c b/src/lib/workflow_xml_parser.c index 0efc733..f216c18 100644 --- a/src/lib/workflow_xml_parser.c +++ b/src/lib/workflow_xml_parser.c @@ -26,6 +26,7 @@ #define EVENT_ELEMENT "event" #define DESCRIPTION_ELEMENT "description" #define NAME_ELEMENT "name" +#define PRIORITY_ELEMENT "priority" static void start_element(GMarkupParseContext *context, const gchar *element_name, @@ -134,9 +135,26 @@ static void text(GMarkupParseContext *context, } } } - } + else if(strcmp(inner_element, PRIORITY_ELEMENT) == 0) + { + log_debug("workflow priority:'%s'", text); + + char *end = NULL; + long long val = strtoll(text, &end, 10); + + if (text == end || end[0] != '\0' + || (errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) + || (val > INT_MAX || val < INT_MIN) + || (errno != 0 && val == 0)) + { + error_msg("Workflow's priority is not a number in range <%d,%d>", INT_MIN, INT_MAX); + return; + } + + wf_set_priority(workflow, (int)val); + } } // Called for strings that should be re-saved verbatim in this same -- 1.8.3.1