diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2011-04-15 15:52:09 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2011-04-15 15:52:09 +0200 |
commit | 3ebfe02dd9c81b10f47ca258bb2a0ef080dbbbeb (patch) | |
tree | d936b4e68e219e8783e6ac70821da4a9e5a35cd7 /src | |
parent | aa77bb9ee015eace791d5331b5ce5fe9e5e14634 (diff) | |
download | abrt-3ebfe02dd9c81b10f47ca258bb2a0ef080dbbbeb.tar.gz abrt-3ebfe02dd9c81b10f47ca258bb2a0ef080dbbbeb.tar.xz abrt-3ebfe02dd9c81b10f47ca258bb2a0ef080dbbbeb.zip |
Implement the possibility to add text labels to even config GUI. Closes #199.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/report.c | 17 | ||||
-rw-r--r-- | src/gtk-helpers/abrt-keyring.c | 8 | ||||
-rw-r--r-- | src/gtk-helpers/autowrapped_label.c | 2 | ||||
-rw-r--r-- | src/gtk-helpers/event_config_dialog.c | 62 | ||||
-rw-r--r-- | src/include/report/event_config.h | 12 | ||||
-rw-r--r-- | src/lib/event_config.c | 59 | ||||
-rw-r--r-- | src/lib/event_xml_parser.c | 83 | ||||
-rw-r--r-- | src/plugins/analyze_LocalGDB.xml.in | 4 | ||||
-rw-r--r-- | src/plugins/analyze_RetraceServer.xml.in | 4 | ||||
-rw-r--r-- | src/plugins/report_Bugzilla.xml.in | 1 |
10 files changed, 151 insertions, 101 deletions
diff --git a/src/cli/report.c b/src/cli/report.c index 9374a3f7..f2c23804 100644 --- a/src/cli/report.c +++ b/src/cli/report.c @@ -443,17 +443,17 @@ static void ask_for_missing_settings(const char *event_name) event_option_t *opt = get_event_option_from_list(opt_name, event_config->options); - free(opt->value); - opt->value = NULL; + free(opt->eo_value); + opt->eo_value = NULL; char result[512]; - char *question = xasprintf("%s: ", (opt->label) ? opt->label: opt->name); - switch (opt->type) { + char *question = xasprintf("%s: ", (opt->eo_label) ? opt->eo_label : opt->eo_name); + switch (opt->eo_type) { case OPTION_TYPE_TEXT: case OPTION_TYPE_NUMBER: read_from_stdin(question, result, 512); - opt->value = xstrdup(result); + opt->eo_value = xstrdup(result); break; case OPTION_TYPE_PASSWORD: { @@ -462,7 +462,7 @@ static void ask_for_missing_settings(const char *event_name) if (changed) set_echo(true); - opt->value = xstrdup(result); + opt->eo_value = xstrdup(result); /* Newline was not added by pressing Enter because ECHO was disabled, so add it now. */ puts(""); @@ -470,11 +470,12 @@ static void ask_for_missing_settings(const char *event_name) } case OPTION_TYPE_BOOL: if (ask_yesno(question)) - opt->value = xstrdup("yes"); + opt->eo_value = xstrdup("yes"); else - opt->value = xstrdup("no"); + opt->eo_value = xstrdup("no"); break; + case OPTION_TYPE_HINT_HTML: /* TODO? */ case OPTION_TYPE_INVALID: break; }; diff --git a/src/gtk-helpers/abrt-keyring.c b/src/gtk-helpers/abrt-keyring.c index c4fbffae..7f01d946 100644 --- a/src/gtk-helpers/abrt-keyring.c +++ b/src/gtk-helpers/abrt-keyring.c @@ -56,7 +56,7 @@ void abrt_keyring_save_settings(const char *event_name) for (l = g_list_first(ec->options); l != NULL; l = g_list_next(l)) { event_option_t *op = (event_option_t *)l->data; - gnome_keyring_attribute_list_append_string(attrs, op->name, op->value); + gnome_keyring_attribute_list_append_string(attrs, op->eo_name, op->eo_value); } GnomeKeyringResult result; @@ -110,9 +110,9 @@ static void abrt_keyring_load_settings(const char *event_name, event_config_t *e event_option_t *option = get_event_option_from_list(name, ec->options); if (option) { - free(option->value); - option->value = xstrdup(g_array_index(attrs, GnomeKeyringAttribute, index).value.string); - VERB2 log("added or replaced in event config:'%s=%s'", name, option->value); + free(option->eo_value); + option->eo_value = xstrdup(g_array_index(attrs, GnomeKeyringAttribute, index).value.string); + VERB2 log("added or replaced in event config:'%s=%s'", name, option->eo_value); } } } diff --git a/src/gtk-helpers/autowrapped_label.c b/src/gtk-helpers/autowrapped_label.c index 130aa8a2..4406be26 100644 --- a/src/gtk-helpers/autowrapped_label.c +++ b/src/gtk-helpers/autowrapped_label.c @@ -61,7 +61,7 @@ void make_label_autowrap_on_resize(GtkLabel *label) { // So far, only tested to work on labels which were set up as: //gtk_label_set_justify(label, GTK_JUSTIFY_LEFT); - //gtk_misc_set_alignment(GTK_MISC(label), /*xalign:*/ 0.0, /*yalign:*/ 0.0); + //gtk_misc_set_alignment(GTK_MISC(label), /*x,yalign:*/ 0.0, 0.0); // yalign != 0 definitely breaks things! // also, <property name="ypad">NONZERO</property> would be bad diff --git a/src/gtk-helpers/event_config_dialog.c b/src/gtk-helpers/event_config_dialog.c index c9f24894..6882ac25 100644 --- a/src/gtk-helpers/event_config_dialog.c +++ b/src/gtk-helpers/event_config_dialog.c @@ -82,11 +82,11 @@ static void add_option_to_table(gpointer data, gpointer user_data) unsigned last_row; char *option_label; - if (option->label != NULL) - option_label = xstrdup(option->label); + if (option->eo_label != NULL) + option_label = xstrdup(option->eo_label); else { - option_label = xstrdup(option->name); + option_label = xstrdup(option->eo_name ? option->eo_name : ""); /* Replace '_' with ' ' */ char *p = option_label - 1; while (*++p) @@ -94,7 +94,7 @@ static void add_option_to_table(gpointer data, gpointer user_data) *p = ' '; } - switch (option->type) + switch (option->eo_type) { case OPTION_TYPE_TEXT: case OPTION_TYPE_NUMBER: @@ -107,15 +107,15 @@ static void add_option_to_table(gpointer data, gpointer user_data) /*x,yoptions:*/ GTK_FILL, GTK_FILL, /*x,ypadding:*/ 0, 0); option_input = gtk_entry_new(); - if (option->value != NULL) - gtk_entry_set_text(GTK_ENTRY(option_input), option->value); + if (option->eo_value != NULL) + gtk_entry_set_text(GTK_ENTRY(option_input), option->eo_value); gtk_table_attach(option_table, option_input, /*left,right_attach:*/ 1, 2, /*top,bottom_attach:*/ last_row, last_row+1, /*x,yoptions:*/ GTK_FILL | GTK_EXPAND, GTK_FILL, /*x,ypadding:*/ 0, 0); add_option_widget(option_input, option); - if (option->type == OPTION_TYPE_PASSWORD) + if (option->eo_type == OPTION_TYPE_PASSWORD) { gtk_entry_set_visibility(GTK_ENTRY(option_input), 0); last_row = grow_table_by_1(option_table); @@ -129,6 +129,20 @@ static void add_option_to_table(gpointer data, gpointer user_data) } break; + case OPTION_TYPE_HINT_HTML: + label = gtk_label_new(option_label); + gtk_label_set_use_markup(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), /*x,yalign:*/ 0.0, 0.0); + make_label_autowrap_on_resize(GTK_LABEL(label)); + + last_row = grow_table_by_1(option_table); + gtk_table_attach(option_table, label, + /*left,right_attach:*/ 0, 2, + /*top,bottom_attach:*/ last_row, last_row+1, + /*x,yoptions:*/ GTK_FILL, GTK_FILL, + /*x,ypadding:*/ 0, 0); + break; + case OPTION_TYPE_BOOL: last_row = grow_table_by_1(option_table); option_input = gtk_check_button_new_with_label(option_label); @@ -137,15 +151,32 @@ static void add_option_to_table(gpointer data, gpointer user_data) /*top,bottom_attach:*/ last_row, last_row+1, /*x,yoptions:*/ GTK_FILL, GTK_FILL, /*x,ypadding:*/ 0, 0); - if (option->value != NULL) + if (option->eo_value != NULL) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(option_input), - string_to_bool(option->value)); + string_to_bool(option->eo_value)); add_option_widget(option_input, option); break; default: //option_input = gtk_label_new_justify_left("WTF?"); log("unsupported option type"); + free(option_label); + return; + } + + if (option->eo_note_html) + { + label = gtk_label_new(option->eo_note_html); + gtk_label_set_use_markup(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), /*x,yalign:*/ 0.0, 0.0); + make_label_autowrap_on_resize(GTK_LABEL(label)); + + last_row = grow_table_by_1(option_table); + gtk_table_attach(option_table, label, + /*left,right_attach:*/ 1, 2, + /*top,bottom_attach:*/ last_row, last_row+1, + /*x,yoptions:*/ GTK_FILL, GTK_FILL, + /*x,ypadding:*/ 0, 0); } free(option_label); @@ -225,7 +256,7 @@ static void save_value_from_widget(gpointer data, gpointer user_data) option_widget_t *ow = (option_widget_t *)data; const char *val = NULL; - switch (ow->option->type) + switch (ow->option->eo_type) { case OPTION_TYPE_TEXT: case OPTION_TYPE_NUMBER: @@ -240,9 +271,9 @@ static void save_value_from_widget(gpointer data, gpointer user_data) } if (val) { - free(ow->option->value); - ow->option->value = xstrdup(val); - VERB1 log("saved: %s:%s", ow->option->name, ow->option->value); + free(ow->option->eo_value); + ow->option->eo_value = xstrdup(val); + VERB1 log("saved: %s:%s", ow->option->eo_name, ow->option->eo_value); } } @@ -277,9 +308,10 @@ static void show_event_config_dialog(const char *event_name) gtk_window_get_icon_name(g_event_list_window)); } - int length = g_list_length(event->options); - GtkWidget *option_table = gtk_table_new(length, 2, 0); + GtkWidget *option_table = gtk_table_new(/*rows*/ 0, /*cols*/ 2, /*homogeneous*/ FALSE); + gtk_table_set_row_spacings(GTK_TABLE(option_table), 2); g_list_foreach(event->options, &add_option_to_table, option_table); + GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); gtk_box_pack_start(GTK_BOX(content), option_table, false, false, 20); gtk_widget_show_all(option_table); diff --git a/src/include/report/event_config.h b/src/include/report/event_config.h index 5b3532a1..5c898d9a 100644 --- a/src/include/report/event_config.h +++ b/src/include/report/event_config.h @@ -32,6 +32,7 @@ typedef enum OPTION_TYPE_BOOL, OPTION_TYPE_PASSWORD, OPTION_TYPE_NUMBER, + OPTION_TYPE_HINT_HTML, OPTION_TYPE_INVALID, } option_type_t; @@ -48,11 +49,12 @@ typedef enum */ typedef struct { - char *name; //name of the value which should be used for env variable - char *value; - char *label; - option_type_t type; - int allow_empty; + char *eo_name; //name of the value which should be used for env variable + char *eo_value; + char *eo_label; + char *eo_note_html; + option_type_t eo_type; + int eo_allow_empty; //char *description; //can be used as tooltip in gtk app //char *allowed_value; //int required; diff --git a/src/lib/event_config.c b/src/lib/event_config.c index 2b57696d..66f9beba 100644 --- a/src/lib/event_config.c +++ b/src/lib/event_config.c @@ -35,11 +35,12 @@ void free_event_option(event_option_t *p) { if (!p) return; - free(p->name); - free(p->value); - free(p->label); - //free(p->description); - //free(p->allowed_value); + free(p->eo_name); + free(p->eo_value); + free(p->eo_label); + free(p->eo_note_html); + //free(p->eo_description); + //free(p->eo_allowed_value); free(p); } @@ -63,7 +64,8 @@ void free_event_config(event_config_t *p) static int cmp_event_option_name_with_string(gconstpointer a, gconstpointer b) { - return strcmp(((event_option_t *)a)->name, (char *)b); + const event_option_t *evopt = a; + return !evopt->eo_name || strcmp(evopt->eo_name, (char *)b) != 0; } event_option_t *get_event_option_from_list(const char *name, GList *options) @@ -113,20 +115,20 @@ static void load_config_files(const char *dir_path) { event_option_t *opt; GList *elem = g_list_find_custom(event_config->options, name, - &cmp_event_option_name_with_string); + cmp_event_option_name_with_string); if (elem) { opt = elem->data; // log("conf: replacing '%s' value:'%s'->'%s'", name, opt->value, value); - free(opt->value); + free(opt->eo_value); } else { // log("conf: new value %s='%s'", name, value); opt = new_event_option(); - opt->name = xstrdup(name); + opt->eo_name = xstrdup(name); } - opt->value = xstrdup(value); + opt->eo_value = xstrdup(value); if (!elem) event_config->options = g_list_append(event_config->options, opt); } @@ -261,9 +263,9 @@ GList *export_event_config(const char *event_name) for (lopt = config->options; lopt; lopt = lopt->next) { event_option_t *opt = lopt->data; - if (!opt->value) + if (!opt->eo_value) continue; - char *var_val = xasprintf("%s=%s", opt->name, opt->value); + char *var_val = xasprintf("%s=%s", opt->eo_name, opt->eo_value); VERB3 log("Exporting '%s'", var_val); env_list = g_list_prepend(env_list, var_val); putenv(var_val); @@ -288,18 +290,18 @@ void unexport_event_config(GList *env_list) /* return NULL if successful otherwise appropriate error message */ static char *validate_event_option(event_option_t *opt) { - if (!opt->allow_empty && (!opt->value || !opt->value[0])) + if (!opt->eo_allow_empty && (!opt->eo_value || !opt->eo_value[0])) return xstrdup(_("Missing mandatory value")); /* if value is NULL and allow-empty yes than it doesn't make sence to check it */ - if (!opt->value) + if (!opt->eo_value) return NULL; const gchar *s = NULL; - if (!g_utf8_validate(opt->value, -1, &s)) + if (!g_utf8_validate(opt->eo_value, -1, &s)) return xasprintf(_("Invalid utf8 character '%c'"), *s); - switch (opt->type) { + switch (opt->eo_type) { case OPTION_TYPE_TEXT: case OPTION_TYPE_PASSWORD: break; @@ -307,24 +309,26 @@ static char *validate_event_option(event_option_t *opt) { char *endptr; errno = 0; - long r = strtol(opt->value, &endptr, 10); + long r = strtol(opt->eo_value, &endptr, 10); (void) r; - if (errno != 0 || endptr == opt->value || *endptr != '\0') - return xasprintf(_("Invalid number '%s'"), opt->value); + if (errno != 0 || endptr == opt->eo_value || *endptr != '\0') + return xasprintf(_("Invalid number '%s'"), opt->eo_value); break; } case OPTION_TYPE_BOOL: - if (strcmp(opt->value, "yes") != 0 - && strcmp(opt->value, "no") != 0 - && strcmp(opt->value, "on") != 0 - && strcmp(opt->value, "off") != 0 - && strcmp(opt->value, "1") != 0 - && strcmp(opt->value, "0") != 0) + if (strcmp(opt->eo_value, "yes") != 0 + && strcmp(opt->eo_value, "no") != 0 + && strcmp(opt->eo_value, "on") != 0 + && strcmp(opt->eo_value, "off") != 0 + && strcmp(opt->eo_value, "1") != 0 + && strcmp(opt->eo_value, "0") != 0) { - return xasprintf(_("Invalid boolean value '%s'"), opt->value); + return xasprintf(_("Invalid boolean value '%s'"), opt->eo_value); } break; + case OPTION_TYPE_HINT_HTML: + return NULL; default: return xstrdup(_("Unsupported option type")); }; @@ -338,7 +342,6 @@ GHashTable *validate_event(const char *event_name) if (!config) return NULL; - GHashTable *errors = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); GList *li; @@ -347,7 +350,7 @@ GHashTable *validate_event(const char *event_name) event_option_t *opt = (event_option_t *)li->data; char *err = validate_event_option(opt); if (err) - g_hash_table_insert(errors, xstrdup(opt->name), err); + g_hash_table_insert(errors, xstrdup(opt->eo_name), err); } if (g_hash_table_size(errors)) diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c index 8c899f14..859e8951 100644 --- a/src/lib/event_xml_parser.c +++ b/src/lib/event_xml_parser.c @@ -22,8 +22,9 @@ #define EVENT_ELEMENT "event" #define LABEL_ELEMENT "label" #define DESCRIPTION_ELEMENT "description" -#define LONG_DESCR_ELEMENT "long_description" +#define LONG_DESCR_ELEMENT "long-description" #define ALLOW_EMPTY_ELEMENT "allow-empty" +#define NOTE_HTML_ELEMENT "note-html" #define OPTION_ELEMENT "option" //#define ACTION_ELEMENT "action" #define NAME_ELEMENT "name" @@ -39,11 +40,12 @@ struct my_parse_data static const char *const option_types[] = { - "text", - "bool", - "password", - "number", - NULL + [OPTION_TYPE_TEXT ] = "text", + [OPTION_TYPE_BOOL ] = "bool", + [OPTION_TYPE_PASSWORD ] = "password", + [OPTION_TYPE_NUMBER ] = "number", + [OPTION_TYPE_HINT_HTML] = "hint-html", + [OPTION_TYPE_INVALID ] = NULL }; // Return xml:lang value for <foo xml:lang="value"> if value matches current locale, @@ -86,7 +88,9 @@ static char *get_element_lang(struct my_parse_data *parse_data, const gchar **at static int cmp_event_option_name_with_string(gconstpointer a, gconstpointer b) { - return strcmp(((event_option_t *)a)->name, (char *)b); + const event_option_t *evopt = a; + /* "When it is not a match?" */ + return !evopt->eo_name || strcmp(evopt->eo_name, (char *)b) != 0; } static void consume_cur_option(struct my_parse_data *parse_data) @@ -94,39 +98,38 @@ static void consume_cur_option(struct my_parse_data *parse_data) event_option_t *opt = parse_data->cur_option; if (!opt) return; - parse_data->cur_option = NULL; - if (!opt->name) - { -//TODO: "option w/o name" error msg? - free_event_option(opt); - return; - } - event_config_t *event_config = parse_data->event_config; - GList *elem = g_list_find_custom(event_config->options, opt->name, - &cmp_event_option_name_with_string); + + /* Example of "nameless" option: <option type="hint-html"> + * The remaining code does not like "nameless" options + * (strcmp would segfault, etc), so provide invented name: + */ + if (!opt->eo_name) + opt->eo_name = xasprintf("%u", (unsigned)g_list_length(event_config->options)); + + GList *elem = g_list_find_custom(event_config->options, opt->eo_name, cmp_event_option_name_with_string); if (elem) { /* we already have option with such name */ event_option_t *old_opt = elem->data; - if (old_opt->value) + if (old_opt->eo_value) { /* ...and it already has a value, which * overrides xml-defined default one: */ - free(opt->value); - opt->value = old_opt->value; - old_opt->value = NULL; + free(opt->eo_value); + opt->eo_value = old_opt->eo_value; + old_opt->eo_value = NULL; } - //log("xml: replacing '%s' value:'%s'->'%s'", opt->name, old_opt->value, opt->value); + //log("xml: replacing '%s' value:'%s'->'%s'", opt->eo_name, old_opt->eo_value, opt->eo_value); free_event_option(old_opt); elem->data = opt; } else { - //log("xml: new value %s='%s'", opt->name, opt->value); + //log("xml: new value %s='%s'", opt->eo_name, opt->eo_value); event_config->options = g_list_append(event_config->options, opt); } } @@ -159,8 +162,8 @@ static void start_element(GMarkupParseContext *context, VERB2 log("attr: %s:%s", attribute_names[i], attribute_values[i]); if (strcmp(attribute_names[i], "name") == 0) { - free(opt->name); - opt->name = xstrdup(attribute_values[i]); + free(opt->eo_name); + opt->eo_name = xstrdup(attribute_values[i]); } else if (strcmp(attribute_names[i], "type") == 0) { @@ -168,7 +171,7 @@ static void start_element(GMarkupParseContext *context, for (type = OPTION_TYPE_TEXT; type < OPTION_TYPE_INVALID; ++type) { if (strcmp(option_types[type], attribute_values[i]) == 0) - opt->type = type; + opt->eo_type = type; } } } @@ -229,10 +232,10 @@ static void text(GMarkupParseContext *context, * OR the label is still not set and we found the default value */ if (parse_data->attribute_lang[0] != '\0' - || !opt->label /* && parse_data->attribute_lang is "" - always true */ + || !opt->eo_label /* && parse_data->attribute_lang is "" - always true */ ) { - free(opt->label); - opt->label = text_copy; + free(opt->eo_label); + opt->eo_label = text_copy; } } return; @@ -246,23 +249,31 @@ static void text(GMarkupParseContext *context, if (strcmp(inner_element, DEFAULT_VALUE_ELEMENT) == 0) { VERB2 log("default value:'%s'", text_copy); - free(opt->value); - opt->value = text_copy; + free(opt->eo_value); + opt->eo_value = text_copy; + return; + } + + if (strcmp(inner_element, NOTE_HTML_ELEMENT) == 0) + { + VERB2 log("html note:'%s'", text_copy); + free(opt->eo_note_html); + opt->eo_note_html = text_copy; return; } if (strcmp(inner_element, ALLOW_EMPTY_ELEMENT) == 0) { VERB2 log("allow-empty:'%s'", text_copy); - opt->allow_empty = string_to_bool(text_copy); + opt->eo_allow_empty = string_to_bool(text_copy); return; } /* if (strcmp(inner_element, DESCRIPTION_ELEMENT) == 0) { VERB2 log("tooltip:'%s'", text_copy); - free(opt->description); - opt->description = text_copy; + free(opt->eo_description); + opt->eo_description = text_copy; return; } */ @@ -274,8 +285,8 @@ static void text(GMarkupParseContext *context, if (strcmp(inner_element, ACTION_ELEMENT) == 0) { VERB2 log("action description:'%s'", text_copy); - free(ui->action); - ui->action = text_copy; + free(ui->eo_action); + ui->eo_action = text_copy; return; } */ diff --git a/src/plugins/analyze_LocalGDB.xml.in b/src/plugins/analyze_LocalGDB.xml.in index f85072d0..925f2c41 100644 --- a/src/plugins/analyze_LocalGDB.xml.in +++ b/src/plugins/analyze_LocalGDB.xml.in @@ -2,7 +2,7 @@ <event> <_name>Local GNU Debugger</_name> <_description>Download debuginfo packages and generate backtrace locally using GDB</_description> - <_long_description>Needs to downloads debuginfo packages, which might take significant time, and take up disk space. + <_long-description>Needs to downloads debuginfo packages, which might take significant time, and take up disk space. However, unlike RetraceServer, doesn't send coredump to remote machines. - </_long_description> + </_long-description> </event> diff --git a/src/plugins/analyze_RetraceServer.xml.in b/src/plugins/analyze_RetraceServer.xml.in index 7f7f0362..f91bf763 100644 --- a/src/plugins/analyze_RetraceServer.xml.in +++ b/src/plugins/analyze_RetraceServer.xml.in @@ -2,10 +2,10 @@ <event> <name>Retrace Server</name> <_description>Send core dump to remote retrace server for analysis</_description> - <_long_description>Uploads coredump to a server, which generates backtrace and returns it. + <_long-description>Uploads coredump to a server, which generates backtrace and returns it. Pros: no need for debuginfo downloads. Retrace server's database of debuginfos is more complete. Retrace server may generate better backtraces. Cons: coredump you upload contains all the data from the crashed program, including your private data, if any. - </_long_description> + </_long-description> <options> <option type="text" name="RETRACE_SERVER_URL"> <_label>Retrace server URL</_label> diff --git a/src/plugins/report_Bugzilla.xml.in b/src/plugins/report_Bugzilla.xml.in index 6c87ad95..123235ea 100644 --- a/src/plugins/report_Bugzilla.xml.in +++ b/src/plugins/report_Bugzilla.xml.in @@ -8,6 +8,7 @@ <allow-empty>no</allow-empty> <_description>Address of Bugzilla server</_description> <default-value>https://bugzilla.redhat.com</default-value> + <note-html>You can create bugzilla.redhat.com account <a href="https://bugzilla.redhat.com/createaccount.cgi">here</a></note-html> </option> <option type="text" name="Bugzilla_Login"> <_label>User name</_label> |