Re: [Automatic Bug Reporting Tool - ABRT] #541: allow only one instance of abrt-gui
by fedora-badges
#541: allow only one instance of abrt-gui
-----------------------+------------------------------------
Reporter: jmoskovc | Owner: crash-catcher@…
Type: defect | Status: closed
Priority: major | Milestone: Usability improvements
Component: gui | Version:
Resolution: fixed | Keywords: Nov2012
Blocked By: | Blocking:
-----------------------+------------------------------------
Comment (by jmoskovc):
commit 69a74e99465582b836e0e8e823b29a5eff8254fb
Author: Jiri Moskovcak <jmoskovc(a)redhat.com>
Date: Mon Nov 26 15:56:30 2012 +0100
allow only one instance of gui trac#541
--
Ticket URL: <https://fedorahosted.org/abrt/ticket/541#comment:3>
Automatic Bug Reporting Tool - ABRT <http://fedorahoted.org/abrt/>
Automatic bug reporting tool
11 years, 5 months
[PATCH] allow only one instance of gui trac#541
by Jiri Moskovcak
---
src/gui-gtk/main.c | 85 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 56 insertions(+), 29 deletions(-)
diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c
index 4ec14d6..1b846df 100644
--- a/src/gui-gtk/main.c
+++ b/src/gui-gtk/main.c
@@ -1192,6 +1192,55 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin
return TRUE; /* "please don't remove this event" */
}
+static void activate(GtkApplication *app)
+{
+
+ GList *windows = NULL;
+
+ windows = gtk_application_get_windows(app);
+
+ if (windows)
+ {
+ gtk_window_present(GTK_WINDOW(windows->data));
+ return;
+ }
+
+ GtkWidget *main_window = create_main_window();
+ load_abrt_conf();
+ load_user_settings("abrt-gui");
+
+ init_notify();
+
+ scan_dirs_and_add_to_dirlist();
+
+ gtk_window_set_application(GTK_WINDOW(main_window), app);
+
+ gtk_widget_show_all(main_window);
+
+ sanitize_cursor(NULL);
+
+ /* Set up signal pipe */
+ xpipe(s_signal_pipe);
+ close_on_exec_on(s_signal_pipe[0]);
+ close_on_exec_on(s_signal_pipe[1]);
+ ndelay_on(s_signal_pipe[0]);
+ ndelay_on(s_signal_pipe[1]);
+ signal(SIGCHLD, handle_signal);
+ g_io_add_watch(g_io_channel_unix_new(s_signal_pipe[0]),
+ G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ handle_signal_pipe,
+ NULL);
+
+ g_custom_logger = &show_warning_dialog;
+
+ /* Enter main loop */
+ gtk_main();
+
+ save_user_settings();
+ free_abrt_conf_data();
+ return;
+}
+
int main(int argc, char **argv)
{
/* I18n */
@@ -1230,13 +1279,8 @@ int main(int argc, char **argv)
migrate_to_xdg_dirs();
- load_user_settings("abrt-gui");
-
export_abrt_envvars(g_opts & OPT_p);
- GtkWidget *main_window = create_main_window();
-
- load_abrt_conf();
const char *default_dirs[] = {
NULL,
NULL,
@@ -1249,32 +1293,15 @@ int main(int argc, char **argv)
}
s_dirs = argv;
- init_notify();
+ GtkApplication *app = NULL;
+ gint status;
- scan_dirs_and_add_to_dirlist();
+ app = gtk_application_new("org.freedesktop.AbrtGui", 0);
+ g_signal_connect(app, "activate", G_CALLBACK (activate), NULL);
- gtk_widget_show_all(main_window);
+ status = g_application_run(G_APPLICATION(app), argc, argv);
- sanitize_cursor(NULL);
+ g_object_unref(app);
- /* Set up signal pipe */
- xpipe(s_signal_pipe);
- close_on_exec_on(s_signal_pipe[0]);
- close_on_exec_on(s_signal_pipe[1]);
- ndelay_on(s_signal_pipe[0]);
- ndelay_on(s_signal_pipe[1]);
- signal(SIGCHLD, handle_signal);
- g_io_add_watch(g_io_channel_unix_new(s_signal_pipe[0]),
- G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- handle_signal_pipe,
- NULL);
-
- g_custom_logger = &show_warning_dialog;
-
- /* Enter main loop */
- gtk_main();
-
- save_user_settings();
- free_abrt_conf_data();
- return 0;
+ return status;
}
--
1.8.0
11 years, 5 months
[LIBREPORT PATCH 1/4] use get_ and set_ functions to access event_config_t
by Jiri Moskovcak
---
libreport.spec.in | 1 +
src/cli/cli-report.c | 8 ++--
src/gtk-helpers/event_config_dialog.c | 6 +--
src/gui-wizard-gtk/wizard.c | 18 ++++----
src/include/Makefile.am | 1 +
src/include/config_item_info.h | 45 +++++++++++++++++++
src/include/event_config.h | 20 +++++++--
src/lib/Makefile.am | 3 +-
src/lib/config_item_info.c | 85 +++++++++++++++++++++++++++++++++++
src/lib/event_config.c | 56 +++++++++++++++++++++--
src/lib/event_xml_parser.c | 19 ++++----
src/report-newt/report-newt.c | 8 ++--
12 files changed, 233 insertions(+), 37 deletions(-)
create mode 100644 src/include/config_item_info.h
create mode 100644 src/lib/config_item_info.c
diff --git a/libreport.spec.in b/libreport.spec.in
index 8eefb3d..cda8f23 100644
--- a/libreport.spec.in
+++ b/libreport.spec.in
@@ -290,6 +290,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%{_includedir}/libreport/report.h
%{_includedir}/libreport/run_event.h
%{_includedir}/libreport/file_obj.h
+%{_includedir}/libreport/config_item_info.h
# Private api headers:
%{_includedir}/libreport/internal_abrt_dbus.h
%{_includedir}/libreport/internal_libreport.h
diff --git a/src/cli/cli-report.c b/src/cli/cli-report.c
index f256e25..d6697e9 100644
--- a/src/cli/cli-report.c
+++ b/src/cli/cli-report.c
@@ -617,7 +617,7 @@ char *select_event_option(GList *list_options)
if (config)
{
++pos;
- printf(" %i) %s\n", pos, config->screen_name);
+ printf(" %i) %s\n", pos, ec_get_screen_name(config));
}
}
@@ -717,7 +717,7 @@ int collect(const char *dump_dir_name, int batch)
if (!config)
VERB1 log("No configuration file found for collector '%s'", collector_name);
- printf(" %d) %s\n", i, (config && config->screen_name) ? config->screen_name : collector_name);
+ printf(" %d) %s\n", i, (config && ec_get_screen_name(config)) ? ec_get_screen_name(config) : collector_name);
}
read_from_stdin(_("Select collector(s): "), wanted_collectors, sizeof(wanted_collectors));
@@ -901,7 +901,7 @@ int report(const char *dump_dir_name, int flags)
char *reporter_name = (char *) li->data;
event_config_t *config = get_event_config(reporter_name);
- printf(" %d) %s\n", i, (config && config->screen_name) ? config->screen_name : reporter_name);
+ printf(" %d) %s\n", i, (config && ec_get_screen_name(config)) ? ec_get_screen_name(config) : reporter_name);
}
read_from_stdin(_("Select reporter(s): "), wanted_reporters, sizeof(wanted_reporters));
@@ -1007,7 +1007,7 @@ int run_events_chain(const char *dump_dir_name, GList *chain)
{
char *msg = xasprintf(_("Event '%s' requires permission to send possibly sensitive data."
" Do you want to continue?"),
- config->screen_name ? config->screen_name : event);
+ ec_get_screen_name(config) ? ec_get_screen_name(config) : event);
const bool response = ask_yesno(msg);
free(msg);
if (!response)
diff --git a/src/gtk-helpers/event_config_dialog.c b/src/gtk-helpers/event_config_dialog.c
index a067511..f135c9a 100644
--- a/src/gtk-helpers/event_config_dialog.c
+++ b/src/gtk-helpers/event_config_dialog.c
@@ -236,8 +236,8 @@ static void add_event_to_liststore(gpointer key, gpointer value, gpointer user_d
event_config_t *ec = (event_config_t *)value;
char *event_label;
- if (ec->screen_name != NULL && ec->description != NULL)
- event_label = xasprintf("<b>%s</b>\n%s", ec->screen_name, ec->description);
+ if (ec_get_screen_name(ec) != NULL && ec_get_description(ec) != NULL)
+ event_label = xasprintf("<b>%s</b>\n%s", ec_get_screen_name(ec), ec_get_description(ec));
else
//if event has no xml description
event_label = xasprintf("<b>%s</b>\nNo description available", key);
@@ -296,7 +296,7 @@ int show_event_config_dialog(const char *event_name, GtkWindow *parent)
GtkWindow *parent_window = parent ? parent : g_event_list_window;
GtkWidget *dialog = gtk_dialog_new_with_buttons(
- /*title:*/ event->screen_name ? event->screen_name : event_name,
+ /*title:*/ ec_get_screen_name(event) ? ec_get_screen_name(event) : event_name,
parent_window,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_CANCEL,
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index f351988..9f1be9f 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -273,12 +273,12 @@ static void show_event_opt_error_dialog(const char *event_name)
"reporting will probably fail if you continue "
"with the current configuration.\n\n"
"Read more about the configuration at: https://fedorahosted.org/abrt/wiki/AbrtConfiguration"),
- ec->screen_name);
+ ec_get_screen_name(ec));
char *markup_message = xasprintf(_("Wrong settings detected for <b>%s</b>, "
"reporting will probably fail if you continue "
"with the current configuration.\n\n"
"<a href=\"https://fedorahosted.org/abrt/wiki/AbrtConfiguration\">Read more about the configuration</a>"),
- ec->screen_name);
+ ec_get_screen_name(ec));
GtkWidget *wrong_settings = g_top_most_window = gtk_message_dialog_new(GTK_WINDOW(g_wnd_assistant),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
@@ -292,7 +292,7 @@ static void show_event_opt_error_dialog(const char *event_name)
free(markup_message);
GtkWidget *act_area = gtk_dialog_get_content_area(GTK_DIALOG(wrong_settings));
- char * conf_btn_lbl = xasprintf(_("Con_figure %s"), ec->screen_name);
+ char * conf_btn_lbl = xasprintf(_("Con_figure %s"), ec_get_screen_name(ec));
GtkWidget *configure_event_btn = gtk_button_new_with_mnemonic(conf_btn_lbl);
g_signal_connect(configure_event_btn, "clicked", G_CALLBACK(on_configure_event_cb), (gpointer)event_name);
free(conf_btn_lbl);
@@ -1016,9 +1016,9 @@ static event_gui_data_t *add_event_buttons(GtkBox *box,
if (cfg)
{
/* .xml has (presumably) prettier description, use it: */
- if (cfg->screen_name)
- event_screen_name = cfg->screen_name;
- event_description = cfg->description;
+ if (ec_get_screen_name(cfg))
+ event_screen_name = ec_get_screen_name(cfg);
+ event_description = ec_get_description(cfg);
char *missing = missing_items_in_comma_list(cfg->ec_requires_items);
if (missing)
@@ -1078,8 +1078,8 @@ static event_gui_data_t *add_event_buttons(GtkBox *box,
if (func)
g_signal_connect(G_OBJECT(button), "toggled", func, xstrdup(event_name));
- if (cfg && cfg->long_descr)
- gtk_widget_set_tooltip_text(button, cfg->long_descr);
+ if (cfg && ec_get_long_desc(cfg))
+ gtk_widget_set_tooltip_text(button, ec_get_long_desc(cfg));
event_gui_data_t *event_gui_data = new_event_gui_data_t();
event_gui_data->event_name = xstrdup(event_name);
@@ -2431,7 +2431,7 @@ static bool get_sensitive_data_permission(const char *event_name)
char *msg = xasprintf(_("Event '%s' requires permission to send possibly sensitive data."
"\nDo you want to continue?"),
- event_cfg->screen_name ? event_cfg->screen_name : event_name);
+ ec_get_screen_name(event_cfg) ? ec_get_screen_name(event_cfg) : event_name);
const bool response = ask_yes_no_save_result(msg, "ask_send_sensitive_data");
free(msg);
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 948662e..a9af359 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -8,6 +8,7 @@ libreport_include_HEADERS = \
run_event.h \
libreport_curl.h \
\
+ config_item_info.h \
file_obj.h \
internal_libreport.h \
internal_abrt_dbus.h
diff --git a/src/include/config_item_info.h b/src/include/config_item_info.h
new file mode 100644
index 0000000..dee6bc2
--- /dev/null
+++ b/src/include/config_item_info.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2011 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef LIBREPORT_CONFIG_ITEM_H
+#define LIBREPORT_CONFIG_ITEM_H
+
+typedef struct
+{
+ char *name; //the event name (from it's filename)
+ char *screen_name; //ui friendly name of the event: "Bugzilla" "RedHat Support Upload"
+ char *description; // "Report to..."/"Save to file". Should be one sentence, not long
+ char *long_desc; // Long(er) explanation, if needed
+
+} config_item_info_t;
+
+config_item_info_t *new_config_info();
+void free_config_info(config_item_info_t *info);
+
+void ci_set_screen_name(config_item_info_t *ci, const char *screen_name);
+void ci_set_name(config_item_info_t *ci, const char *name);
+void ci_set_description(config_item_info_t *ci, const char *description);
+void ci_set_long_desc(config_item_info_t *ci, const char *long_description);
+
+extern const char *ci_get_screen_name(config_item_info_t *ci);
+extern const char *ci_get_name(config_item_info_t *ci);
+extern const char *ci_get_description(config_item_info_t *ci);
+extern const char *ci_get_long_desc(config_item_info_t *ci);
+
+#endif
diff --git a/src/include/event_config.h b/src/include/event_config.h
index 438c723..60e5b94 100644
--- a/src/include/event_config.h
+++ b/src/include/event_config.h
@@ -22,6 +22,7 @@
#include <stdbool.h>
#include <glib.h>
#include "problem_data.h"
+#include "config_item_info.h"
#ifdef __cplusplus
extern "C" {
@@ -68,10 +69,7 @@ void free_event_option(event_option_t *p);
//structure to hold the option data
typedef struct
{
- char *name; //the event name (from it's filename)
- char *screen_name; //ui friendly name of the event: "Bugzilla" "RedHat Support Upload"
- char *description; // "Report to..."/"Save to file". Should be one sentence, not long
- char *long_descr; // Long(er) explanation, if needed
+ config_item_info_t *info;
char *ec_creates_items;
char *ec_requires_items;
@@ -87,6 +85,19 @@ typedef struct
} event_config_t;
event_config_t *new_event_config(void);
+config_item_info_t *ec_get_config_info(event_config_t * ec);
+const char *ec_get_screen_name(event_config_t *ec);
+void ec_set_screen_name(event_config_t *ec, const char *screen_name);
+void ec_set_name(event_config_t *ec, const char *name);
+
+const char *ec_get_description(event_config_t *ec);
+void ec_set_description(event_config_t *ec, const char *description);
+
+const char *ec_get_name(event_config_t *ec);
+const char *ec_get_long_desc(event_config_t *ec);
+void ec_set_long_desc(event_config_t *ec, const char *long_desc);
+bool ec_is_configurable(event_config_t* ec);
+
void free_event_config(event_config_t *p);
@@ -99,6 +110,7 @@ void free_event_config_data(void);
event_config_t *get_event_config(const char *event_name);
event_option_t *get_event_option_from_list(const char *option_name, GList *event_options);
+
extern GHashTable *g_event_config_list; // for iterating through entire list of all loaded configs
GList *export_event_config(const char *event_name);
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 2865624..0a7a819 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -49,7 +49,8 @@ libreport_la_SOURCES = \
client.c \
utf8.c \
file_list.c \
- file_obj.c
+ file_obj.c \
+ config_item_info.c
libreport_la_CPPFLAGS = \
-I$(srcdir)/../include \
-DLOCALSTATEDIR='"$(localstatedir)"' \
diff --git a/src/lib/config_item_info.c b/src/lib/config_item_info.c
new file mode 100644
index 0000000..1635e72
--- /dev/null
+++ b/src/lib/config_item_info.c
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2011 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "internal_libreport.h"
+//#include "config_item_info.h"
+
+
+config_item_info_t *new_config_info()
+{
+ config_item_info_t *info = (config_item_info_t *)xzalloc(sizeof(config_item_info_t));
+ return info;
+}
+
+void free_config_info(config_item_info_t *info)
+{
+ if (info == NULL)
+ return;
+
+ free(info->name);
+ free(info->screen_name);
+ free(info->description);
+ free(info->long_desc);
+
+ free(info);
+}
+
+void ci_set_screen_name(config_item_info_t *ci, const char *screen_name)
+{
+ free(ci->screen_name);
+ ci->screen_name = xstrdup(screen_name);
+}
+
+void ci_set_name(config_item_info_t *ci, const char *name)
+{
+ free(ci->name);
+ ci->name = xstrdup(name);
+}
+
+void ci_set_description(config_item_info_t *ci, const char *description)
+{
+ free(ci->description);
+ ci->description = xstrdup(description);
+}
+
+void ci_set_long_desc(config_item_info_t *ci, const char *long_description)
+{
+ free(ci->long_desc);
+ ci->long_desc = xstrdup(long_description);
+}
+
+inline const char *ci_get_screen_name(config_item_info_t *ci)
+{
+ return ci->screen_name;
+}
+
+inline const char *ci_get_name(config_item_info_t *ci)
+{
+ return ci->name;
+}
+
+inline const char *ci_get_description(config_item_info_t *ci)
+{
+ return ci->description;
+}
+
+inline const char *ci_get_long_desc(config_item_info_t *ci)
+{
+ return ci->long_desc;
+}
diff --git a/src/lib/event_config.c b/src/lib/event_config.c
index 2019e53..3c094bd 100644
--- a/src/lib/event_config.c
+++ b/src/lib/event_config.c
@@ -16,6 +16,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+
#include "internal_libreport.h"
GHashTable *g_event_config_list;
@@ -29,9 +30,60 @@ event_option_t *new_event_option(void)
event_config_t *new_event_config(void)
{
event_config_t *e = xzalloc(sizeof(event_config_t));
+ e->info = new_config_info();
return e;
}
+config_item_info_t *ec_get_config_info(event_config_t * ec)
+{
+ return ec->info;
+}
+
+void ec_set_name(event_config_t *ec, const char *name)
+{
+ ci_set_name(ec->info, name);
+}
+
+void ec_set_screen_name(event_config_t *ec, const char *screen_name)
+{
+ ci_set_screen_name(ec->info, screen_name);
+}
+
+const char *ec_get_screen_name(event_config_t *ec)
+{
+ return ci_get_screen_name(ec->info);
+}
+
+const char *ec_get_description(event_config_t *ec)
+{
+ return ci_get_description(ec->info);
+}
+
+void ec_set_description(event_config_t *ec, const char *description)
+{
+ ci_set_description(ec->info, description);
+}
+
+const char *ec_get_name(event_config_t *ec)
+{
+ return ci_get_name(ec->info);
+}
+
+const char *ec_get_long_desc(event_config_t *ec)
+{
+ return ci_get_long_desc(ec->info);
+}
+
+void ec_set_long_desc(event_config_t *ec, const char *long_descr)
+{
+ ci_set_long_desc(ec->info, long_descr);
+}
+
+bool ec_is_configurable(event_config_t* ec)
+{
+ return g_list_length(ec->options) > 0;
+}
+
void free_event_option(event_option_t *p)
{
if (!p)
@@ -50,9 +102,7 @@ void free_event_config(event_config_t *p)
if (!p)
return;
- free(p->screen_name);
- free(p->description);
- free(p->long_descr);
+ free_config_info(p->info);
free(p->ec_creates_items);
free(p->ec_requires_items);
free(p->ec_exclude_items_by_default);
diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c
index 157b717..585e2e5 100644
--- a/src/lib/event_xml_parser.c
+++ b/src/lib/event_xml_parser.c
@@ -336,11 +336,11 @@ 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'
- || !ui->screen_name /* && parse_data->attribute_lang is "" - always true */
+ || !ec_get_screen_name(ui) /* && parse_data->attribute_lang is "" - always true */
) {
VERB2 log("event name:'%s'", text_copy);
- free(ui->screen_name);
- ui->screen_name = text_copy;
+ ec_set_screen_name(ui, text_copy);
+ free(text_copy);
text_copy = NULL;
}
}
@@ -355,10 +355,10 @@ static void text(GMarkupParseContext *context,
* OR the description is still not set and we found the default value
*/
if (parse_data->attribute_lang[0] != '\0'
- || !ui->description /* && parse_data->attribute_lang is "" - always true */
+ || !ec_get_description(ui) /* && parse_data->attribute_lang is "" - always true */
) {
- free(ui->description);
- ui->description = text_copy;
+ ec_set_description(ui, text_copy);
+ free(text_copy);
text_copy = NULL;
}
}
@@ -373,10 +373,10 @@ static void text(GMarkupParseContext *context,
* OR the description is still not set and we found the default value
*/
if (parse_data->attribute_lang[0] != '\0'
- || !ui->long_descr /* && parse_data->attribute_lang is "" - always true */
+ || !ec_get_long_desc(ui) /* && parse_data->attribute_lang is "" - always true */
) {
- free(ui->long_descr);
- ui->long_descr = text_copy;
+ ec_set_long_desc(ui, text_copy);
+ free(text_copy);
text_copy = NULL;
}
}
@@ -463,6 +463,7 @@ static void error(GMarkupParseContext *context,
void load_event_description_from_file(event_config_t *event_config, const char* filename)
{
+ VERB1 log("loading event: '%s'", filename);
struct my_parse_data parse_data = { event_config, NULL, NULL, NULL };
parse_data.cur_locale = setlocale(LC_ALL, NULL);
diff --git a/src/report-newt/report-newt.c b/src/report-newt/report-newt.c
index 8532e82..44d30bd 100644
--- a/src/report-newt/report-newt.c
+++ b/src/report-newt/report-newt.c
@@ -60,8 +60,8 @@ static int select_reporters(GArray *reporters)
{
struct reporter *r = &g_array_index(reporters, struct reporter, i);
- checkboxes[i] = newtCheckbox(20, i + 1, r->config && r->config->screen_name ?
- r->config->screen_name : r->name, 0, NULL, NULL);
+ checkboxes[i] = newtCheckbox(20, i + 1, r->config && ec_get_screen_name(r->config) ?
+ ec_get_screen_name(r->config) : r->name, 0, NULL, NULL);
newtGridSetField(cgrid, 0, i, NEWT_GRID_COMPONENT, checkboxes[i], 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
}
@@ -104,8 +104,8 @@ static int configure_reporter(struct reporter *r, bool skip_if_valid)
while ((error_table = validate_event(r->name)) ||
(!skip_if_valid && first && r->config))
{
- text = newtTextboxReflowed(0, 0, r->config->screen_name ?
- r->config->screen_name : r->name, 35, 5, 5, 0);
+ text = newtTextboxReflowed(0, 0, ec_get_screen_name(r->config) ?
+ xstrdup(ec_get_screen_name(r->config)) : r->name, 35, 5, 5, 0);
num_opts = g_list_length(r->config->options);
options = xmalloc(sizeof (newtComponent) * num_opts);
--
1.8.0
11 years, 5 months
[LIBREPORT PATCH] introduced workflows trac#822
by Jiri Moskovcak
---
configure.ac | 3 +
libreport.spec.in | 16 ++
po/POTFILES.in | 27 +--
src/Makefile.am | 2 +-
src/cli/cli-report.c | 8 +-
src/gtk-helpers/Makefile.am | 5 +-
src/gtk-helpers/config_dialog.c | 216 ++++++++++++++++++++++++
src/gtk-helpers/event_config_dialog.c | 279 +++++++++++++++----------------
src/gtk-helpers/internal_libreport_gtk.h | 20 ++-
src/gtk-helpers/secrets.c | 4 +-
src/gtk-helpers/workflow_config_dialog.c | 119 +++++++++++++
src/gui-wizard-gtk/Makefile.am | 1 +
src/gui-wizard-gtk/main.c | 10 +-
src/gui-wizard-gtk/wizard.c | 111 +++++++++---
src/gui-wizard-gtk/wizard.glade | 20 ++-
src/gui-wizard-gtk/wizard.h | 2 +-
src/include/Makefile.am | 2 +
src/include/config_item_info.h | 45 +++++
src/include/event_config.h | 19 ++-
src/include/file_obj.h | 2 +
src/include/internal_libreport.h | 3 +
src/include/workflow.h | 51 ++++++
src/lib/Makefile.am | 6 +-
src/lib/config_item_info.c | 85 ++++++++++
src/lib/event_config.c | 51 +++++-
src/lib/event_xml_parser.c | 19 ++-
src/lib/workflow.c | 146 ++++++++++++++++
src/lib/workflow_xml_parser.c | 173 +++++++++++++++++++
src/report-newt/report-newt.c | 8 +-
src/workflows/Makefile.am | 10 ++
src/workflows/report_Fedora.xml.in | 13 ++
src/workflows/report_fedora.conf | 3 +
32 files changed, 1269 insertions(+), 210 deletions(-)
create mode 100644 src/gtk-helpers/config_dialog.c
create mode 100644 src/gtk-helpers/workflow_config_dialog.c
create mode 100644 src/include/config_item_info.h
create mode 100644 src/include/workflow.h
create mode 100644 src/lib/config_item_info.c
create mode 100644 src/lib/workflow.c
create mode 100644 src/lib/workflow_xml_parser.c
create mode 100644 src/workflows/Makefile.am
create mode 100644 src/workflows/report_Fedora.xml.in
create mode 100644 src/workflows/report_fedora.conf
diff --git a/configure.ac b/configure.ac
index 07b3cf8..1607880 100644
--- a/configure.ac
+++ b/configure.ac
@@ -176,6 +176,7 @@ PLUGINS_CONF_DIR='${sysconfdir}/${PACKAGE_NAME}/plugins'
REPORT_PLUGINS_CONF_DIR='${sysconfdir}/libreport/plugins'
EVENTS_DIR='${sysconfdir}/${PACKAGE_NAME}/events'
EVENTS_CONF_DIR='${sysconfdir}/${PACKAGE_NAME}/events.d'
+WORKFLOWS_DIR='${sysconfdir}/${PACKAGE_NAME}/workflows'
PLUGINS_LIB_DIR='${libdir}/${PACKAGE_NAME}'
LIBEXEC_DIR='${libexecdir}'
@@ -195,6 +196,7 @@ AC_SUBST(EVENTS_DIR)
AC_SUBST(PLUGINS_LIB_DIR)
AC_SUBST(DEBUG_DUMPS_DIR)
AC_SUBST(LIBEXEC_DIR)
+AC_SUBST(WORKFLOWS_DIR)
# Initialize the test suite.
AC_CONFIG_TESTDIR(tests)
@@ -222,6 +224,7 @@ AC_CONFIG_FILES([
src/client-python/Makefile
po/Makefile.in
doc/Makefile
+ src/workflows/Makefile
])
# src/plugins/Makefile
diff --git a/libreport.spec.in b/libreport.spec.in
index 8eefb3d..018b39d 100644
--- a/libreport.spec.in
+++ b/libreport.spec.in
@@ -217,6 +217,15 @@ Obsoletes: report-config-scp < 0:0.23-1
%description plugin-reportuploader
Plugin to report bugs into anonymous FTP site associated with ticketing system.
+%package fedora
+Summary: Default configuration for reporting bugs via Fedora infrastructure
+Group: Applications/File
+
+%description fedora
+Default configuration for reporting bugs via Fedora infrastructure
+used to easy configure the reporting process for Fedora sytems. Just
+install this package and you're done.
+
%prep
%setup -q
@@ -290,6 +299,8 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%{_includedir}/libreport/report.h
%{_includedir}/libreport/run_event.h
%{_includedir}/libreport/file_obj.h
+%{_includedir}/libreport/config_item_info.h
+%{_includedir}/libreport/workflow.h
# Private api headers:
%{_includedir}/libreport/internal_abrt_dbus.h
%{_includedir}/libreport/internal_libreport.h
@@ -393,6 +404,11 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%{_sysconfdir}/libreport/events/report_Uploader.xml
%config(noreplace) %{_sysconfdir}/libreport/events.d/uploader_event.conf
+%files fedora
+%defattr(-,root,root,-)
+%{_sysconfdir}/libreport/workflows/report_Fedora.xml
+%{_sysconfdir}/libreport/workflows/report_fedora.conf
+
%changelog
* Wed Nov 14 2012 Jakub Filak <jfilak(a)redhat.com> 2.0.19-1
- bugzilla_format[_libreport].conf: emit truncated backtrace into its own paragraph
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 668c526..90d4285 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,31 +3,27 @@
# Please keep this file sorted alphabetically.
src/cli/cli.c
src/cli/cli-report.c
-src/client-python/__init__.py
src/client-python/debuginfo.py
+src/client-python/__init__.py
+src/gtk-helpers/config_dialog.c
src/gtk-helpers/event_config_dialog.c
src/gtk-helpers/secrets.c
+src/gtk-helpers/workflow_config_dialog.c
src/gui-wizard-gtk/main.c
src/gui-wizard-gtk/wizard.c
src/gui-wizard-gtk/wizard.glade
src/include/internal_libreport.h
src/lib/abrt_sock.c
+src/lib/client.c
src/lib/create_dump_dir.c
+src/lib/curl.c
src/lib/event_config.c
src/lib/parse_options.c
-src/lib/curl.c
-src/lib/client.c
-src/lib/run_event.c
src/lib/problem_data.c
+src/lib/run_event.c
src/plugins/abrt_rh_support.c
-src/plugins/report.c
src/plugins/report_Bugzilla.xml.in
-src/plugins/report_Kerneloops.xml.in
-src/plugins/report_Logger.xml.in
-src/plugins/report_Mailx.xml.in
-src/plugins/report_RHTSupport.xml.in
-src/plugins/report_Uploader.xml.in
-src/plugins/report_uReport.xml.in
+src/plugins/report.c
src/plugins/reporter-bugzilla.c
src/plugins/reporter-kerneloops.c
src/plugins/reporter-mailx.c
@@ -35,6 +31,13 @@ src/plugins/reporter-print.c
src/plugins/reporter-rhtsupport.c
src/plugins/reporter-rhtsupport-parse.c
src/plugins/reporter-upload.c
+src/plugins/report_Kerneloops.xml.in
+src/plugins/report_Logger.xml.in
+src/plugins/report_Mailx.xml.in
+src/plugins/report_RHTSupport.xml.in
+src/plugins/report_Uploader.xml.in
+src/plugins/report_uReport.xml.in
src/plugins/rhbz.c
-src/report-newt/report-newt.c
src/plugins/ureport.c
+src/report-newt/report-newt.c
+src/workflows/report_Fedora.xml.in
diff --git a/src/Makefile.am b/src/Makefile.am
index 68bd1c0..c15928c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,4 +8,4 @@ if BUILD_NEWT
sub_dirs += report-newt
endif
-SUBDIRS = include lib plugins report-python cli client-python $(sub_dirs)
+SUBDIRS = include lib plugins report-python cli client-python workflows $(sub_dirs)
diff --git a/src/cli/cli-report.c b/src/cli/cli-report.c
index f256e25..d6697e9 100644
--- a/src/cli/cli-report.c
+++ b/src/cli/cli-report.c
@@ -617,7 +617,7 @@ char *select_event_option(GList *list_options)
if (config)
{
++pos;
- printf(" %i) %s\n", pos, config->screen_name);
+ printf(" %i) %s\n", pos, ec_get_screen_name(config));
}
}
@@ -717,7 +717,7 @@ int collect(const char *dump_dir_name, int batch)
if (!config)
VERB1 log("No configuration file found for collector '%s'", collector_name);
- printf(" %d) %s\n", i, (config && config->screen_name) ? config->screen_name : collector_name);
+ printf(" %d) %s\n", i, (config && ec_get_screen_name(config)) ? ec_get_screen_name(config) : collector_name);
}
read_from_stdin(_("Select collector(s): "), wanted_collectors, sizeof(wanted_collectors));
@@ -901,7 +901,7 @@ int report(const char *dump_dir_name, int flags)
char *reporter_name = (char *) li->data;
event_config_t *config = get_event_config(reporter_name);
- printf(" %d) %s\n", i, (config && config->screen_name) ? config->screen_name : reporter_name);
+ printf(" %d) %s\n", i, (config && ec_get_screen_name(config)) ? ec_get_screen_name(config) : reporter_name);
}
read_from_stdin(_("Select reporter(s): "), wanted_reporters, sizeof(wanted_reporters));
@@ -1007,7 +1007,7 @@ int run_events_chain(const char *dump_dir_name, GList *chain)
{
char *msg = xasprintf(_("Event '%s' requires permission to send possibly sensitive data."
" Do you want to continue?"),
- config->screen_name ? config->screen_name : event);
+ ec_get_screen_name(config) ? ec_get_screen_name(config) : event);
const bool response = ask_yesno(msg);
free(msg);
if (!response)
diff --git a/src/gtk-helpers/Makefile.am b/src/gtk-helpers/Makefile.am
index a821b5d..0d3f9d8 100644
--- a/src/gtk-helpers/Makefile.am
+++ b/src/gtk-helpers/Makefile.am
@@ -12,7 +12,9 @@ libreport_gtk_la_SOURCES = \
event_config_dialog.c \
secrets.c \
hyperlinks.c \
- autowrapped_label.c
+ autowrapped_label.c \
+ workflow_config_dialog.c \
+ config_dialog.c
libreport_gtk_la_CPPFLAGS = \
-I$(srcdir)/../include \
@@ -20,6 +22,7 @@ libreport_gtk_la_CPPFLAGS = \
$(GTK_CFLAGS) \
$(GLIB_CFLAGS) \
$(GIO_CFLAGS) \
+ -DWORKFLOWS_DIR=\"$(WORKFLOWS_DIR)\" \
-D_GNU_SOURCE
libreport_gtk_la_LDFLAGS = \
-version-info 0:1:0
diff --git a/src/gtk-helpers/config_dialog.c b/src/gtk-helpers/config_dialog.c
new file mode 100644
index 0000000..8d09d53
--- /dev/null
+++ b/src/gtk-helpers/config_dialog.c
@@ -0,0 +1,216 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <gtk/gtk.h>
+#include "internal_libreport_gtk.h"
+
+enum
+{
+ COLUMN_UINAME,
+ COLUMN_NAME,
+ CONFIG_DIALOG,
+ NUM_COLUMNS
+};
+
+enum
+{
+ TYPE_STR,
+ TYPE_POINTER
+};
+
+GtkListStore *new_conf_liststore()
+{
+ /* Create data store for the list and attach it
+ * COLUMN_EVENT_UINAME -> name+description
+ * COLUMN_EVENT_NAME -> event name so we can retrieve it from the row
+ */
+ return gtk_list_store_new(NUM_COLUMNS,
+ G_TYPE_STRING, /* Event name + description */
+ G_TYPE_STRING, /* event name */
+ G_TYPE_POINTER
+ );
+}
+
+static const void *get_column_value_from_row(GtkTreeView *treeview, int column, int type)
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
+ const void *retval = NULL;
+ if (selection)
+ {
+ GtkTreeIter iter;
+ GtkTreeModel *store = gtk_tree_view_get_model(treeview);
+ if (gtk_tree_selection_get_selected(selection, &store, &iter) == TRUE)
+ {
+ GValue value = { 0 };
+ gtk_tree_model_get_value(store, &iter, column, &value);
+ switch(type){
+ case TYPE_STR:
+ retval = g_value_get_string(&value);
+ break;
+ case TYPE_POINTER:
+ retval = g_value_get_pointer(&value);
+ }
+ }
+ }
+ return retval;
+}
+
+static void on_row_changed_cb(GtkTreeView *treeview, gpointer user_data)
+{
+ VERB1 log("activated row: '%s'", (const char*)get_column_value_from_row(treeview, COLUMN_NAME, TYPE_STR));
+
+ const void *dialog = get_column_value_from_row(treeview, CONFIG_DIALOG, TYPE_POINTER);
+ gtk_widget_set_sensitive(GTK_WIDGET(user_data), dialog != NULL);
+
+ /*
+ void (*handler)(void) = (void (*)(void))get_column_value_from_row(treeview, ON_ROWCHANGE_CB, TYPE_POINTER);
+
+ if (handler == NULL)
+ return;
+
+ handler();
+ */
+
+ /*
+ const char *event_name = get_event_name_from_row(treeview);
+
+ if (event_name)
+ {
+ event_config_t *ec = get_event_config(event_name);
+ gtk_widget_set_sensitive(GTK_WIDGET(user_data), ec->options != NULL);
+ }
+ */
+}
+
+static void on_configure_button_cb(GtkWidget *button, gpointer user_data)
+{
+ GtkTreeView *tv = (GtkTreeView *)user_data;
+ const void * dialog = get_column_value_from_row(tv, CONFIG_DIALOG, TYPE_POINTER);
+
+ if (dialog != NULL)
+ {
+ int result = gtk_dialog_run(GTK_DIALOG(dialog));
+ if (result == GTK_RESPONSE_APPLY)
+ {
+ //TODO: saving!!!
+ g_print("apply\n");
+ }
+ //else if (result == GTK_RESPONSE_CANCEL)
+ // log("log");
+ gtk_widget_hide(GTK_WIDGET(dialog));
+ }
+}
+
+static void on_close_list_cb(GtkWidget *button, gpointer user_data)
+{
+ GtkWidget *window = (GtkWidget *)user_data;
+ gtk_widget_destroy(window);
+}
+
+void add_item_to_config_liststore(gpointer dialog, gpointer inf, gpointer user_data)
+{
+ GtkListStore *list_store = (GtkListStore *)user_data;
+ config_item_info_t *info = (config_item_info_t *)inf;
+
+ VERB1 log("adding '%s' to workflow list\n", info->screen_name);
+ char *label;
+ if (ci_get_screen_name(info) != NULL && ci_get_description(info) != NULL)
+ label = xasprintf("<b>%s</b>\n%s",ci_get_screen_name(info), ci_get_description(info));
+ else
+ //if event has no xml description
+ label = xasprintf("<b>%s</b>\nNo description available", ci_get_name(info));
+
+ GtkTreeIter iter;
+ gtk_list_store_append(list_store, &iter);
+ gtk_list_store_set(list_store, &iter,
+ COLUMN_UINAME, label,
+ COLUMN_NAME, ci_get_name(info),
+ CONFIG_DIALOG, dialog,
+ -1);
+ free(label);
+}
+
+GtkWidget *create_config_list_dialog(const char *column_label,
+ GHashTable *items,
+ GtkWindow *dialog,
+ GHFunc item_to_config_info,
+ GCallback on_config_cb,
+ GCallback on_row_change)
+{
+ GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ /* workflow list treeview */
+ GtkWidget *tv = gtk_tree_view_new();
+ /* column with workflow name and description */
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* add column to tree view */
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(column_label,
+ renderer,
+ "markup",
+ COLUMN_UINAME,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ g_object_set(G_OBJECT(renderer), "wrap-mode", PANGO_WRAP_WORD, NULL);
+ g_object_set(G_OBJECT(renderer), "wrap-width", 440, NULL);
+ gtk_tree_view_column_set_sort_column_id(column, COLUMN_NAME);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column);
+ /* "Please draw rows in alternating colors": */
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tv), TRUE);
+ // TODO: gtk_tree_view_set_headers_visible(FALSE)? We have only one column anyway...
+
+ /* Create data store for the list and attach it
+ * COLUMN_UINAME -> name+description
+ * COLUMN_NAME -> workflow name so we can retrieve it from the row
+ */
+ GtkListStore *list_store = new_conf_liststore();
+ gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(list_store));
+
+ g_hash_table_foreach(items,
+ item_to_config_info,
+ list_store);
+//TODO: can unref workflows_list_store? treeview holds one ref.
+
+ /* Double click/Enter handler */
+ //g_signal_connect(workflows_tv, "row-activated", G_CALLBACK(on_workflow_row_activated_cb), NULL);
+
+ gtk_container_add(GTK_CONTAINER(scroll), tv);
+
+ GtkWidget *configure_btn = gtk_button_new_with_mnemonic(_("C_onfigure"));
+ gtk_widget_set_sensitive(configure_btn, false);
+ g_signal_connect(configure_btn, "clicked", G_CALLBACK(on_configure_button_cb), tv);
+ g_signal_connect(tv, "cursor-changed", G_CALLBACK(on_row_changed_cb), configure_btn);
+
+ GtkWidget *close_btn = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
+ g_signal_connect(close_btn, "clicked", G_CALLBACK(on_close_list_cb), dialog);
+
+ GtkWidget *btnbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
+ gtk_box_pack_end(GTK_BOX(btnbox), close_btn, false, false, 0);
+ gtk_box_pack_end(GTK_BOX(btnbox), configure_btn, false, false, 0);
+
+ gtk_box_pack_start(GTK_BOX(main_vbox), scroll, true, true, 10);
+ gtk_box_pack_start(GTK_BOX(main_vbox), btnbox, false, false, 0);
+
+ return main_vbox;
+}
diff --git a/src/gtk-helpers/event_config_dialog.c b/src/gtk-helpers/event_config_dialog.c
index a067511..a2e1085 100644
--- a/src/gtk-helpers/event_config_dialog.c
+++ b/src/gtk-helpers/event_config_dialog.c
@@ -177,80 +177,6 @@ static void add_option_to_table(gpointer data, gpointer user_data)
free(option_label);
}
-static void on_close_event_list_cb(GtkWidget *button, gpointer user_data)
-{
- GtkWidget *window = (GtkWidget *)user_data;
- gtk_widget_destroy(window);
-}
-
-static char *get_event_name_from_row(GtkTreeView *treeview)
-{
- GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
- char *event_name = NULL;
- if (selection)
- {
- GtkTreeIter iter;
- GtkTreeModel *store = gtk_tree_view_get_model(treeview);
- if (gtk_tree_selection_get_selected(selection, &store, &iter) == TRUE)
- {
- GValue value = { 0 };
- gtk_tree_model_get_value(store, &iter, COLUMN_EVENT_NAME, &value);
- event_name = (char *)g_value_get_string(&value);
- }
- }
- return event_name;
-}
-
-static void on_configure_event_cb(GtkWidget *button, gpointer user_data)
-{
- GtkTreeView *events_tv = (GtkTreeView *)user_data;
- char *event_name = get_event_name_from_row(events_tv);
- if (event_name != NULL)
- show_event_config_dialog(event_name, NULL);
- //else
- // error_msg(_("Please select a plugin from the list to edit its options."));
-}
-
-static void on_event_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
-{
- char *event_name = get_event_name_from_row(treeview);
- event_config_t *ec = get_event_config(event_name);
- if (ec->options != NULL) //We need to have some options to show
- show_event_config_dialog(event_name, NULL);
-}
-
-static void on_event_row_changed_cb(GtkTreeView *treeview, gpointer user_data)
-{
- const char *event_name = get_event_name_from_row(treeview);
-
- if (event_name)
- {
- event_config_t *ec = get_event_config(event_name);
- gtk_widget_set_sensitive(GTK_WIDGET(user_data), ec->options != NULL);
- }
-}
-
-static void add_event_to_liststore(gpointer key, gpointer value, gpointer user_data)
-{
- GtkListStore *events_list_store = (GtkListStore *)user_data;
- event_config_t *ec = (event_config_t *)value;
-
- char *event_label;
- if (ec->screen_name != NULL && ec->description != NULL)
- event_label = xasprintf("<b>%s</b>\n%s", ec->screen_name, ec->description);
- else
- //if event has no xml description
- event_label = xasprintf("<b>%s</b>\nNo description available", key);
-
- GtkTreeIter iter;
- gtk_list_store_append(events_list_store, &iter);
- gtk_list_store_set(events_list_store, &iter,
- COLUMN_EVENT_UINAME, event_label,
- COLUMN_EVENT_NAME, key,
- -1);
- free(event_label);
-}
-
static void save_value_from_widget(gpointer data, gpointer user_data)
{
option_widget_t *ow = (option_widget_t *)data;
@@ -283,43 +209,12 @@ static void dehydrate_config_dialog()
g_list_foreach(option_widget_list, &save_value_from_widget, NULL);
}
-int show_event_config_dialog(const char *event_name, GtkWindow *parent)
+GtkWidget *create_event_config_dialog_content(event_config_t *event, GtkWidget *content)
{
- if (option_widget_list != NULL)
- {
- g_list_free(option_widget_list);
- option_widget_list = NULL;
- }
-
- event_config_t *event = get_event_config(event_name);
-
- GtkWindow *parent_window = parent ? parent : g_event_list_window;
-
- GtkWidget *dialog = gtk_dialog_new_with_buttons(
- /*title:*/ event->screen_name ? event->screen_name : event_name,
- parent_window,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK,
- GTK_RESPONSE_APPLY,
- NULL);
-
- /* Allow resize?
- * W/o resize, e.g. upload configuration hint looks awfully
- * line wrapped.
- * With resize, there are some somewhat not nice effects:
- * for one, opening an expander will enlarge window,
- * but won't contract it back when expander is closed.
- */
- gtk_window_set_resizable(GTK_WINDOW(dialog), true);
- gtk_window_set_default_size(GTK_WINDOW(dialog), 450, -1);
+ if (content == NULL)
+ content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- if (parent_window != NULL)
- {
- gtk_window_set_icon_name(GTK_WINDOW(dialog),
- gtk_window_get_icon_name(parent_window));
- }
+ //event_config_t *event = get_event_config(event_name);
GtkWidget *option_table = gtk_grid_new();
gtk_grid_set_row_homogeneous(GTK_GRID(option_table), FALSE);
@@ -359,7 +254,6 @@ int show_event_config_dialog(const char *event_name, GtkWindow *parent)
g_signal_connect(pass_store_cb, "toggled", G_CALLBACK(on_show_pass_store_cb), NULL);
}
- GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
gtk_box_pack_start(GTK_BOX(content), option_table, false, false, 20);
/* add the adv_option_table to the dialog only if there is some adv option */
@@ -379,6 +273,103 @@ int show_event_config_dialog(const char *event_name, GtkWindow *parent)
gtk_box_pack_start(GTK_BOX(content), keyring_warn_lbl, false, false, 0);
}
+ gtk_widget_show_all(content); //make it all visible
+
+ return content;
+}
+
+GtkWidget *create_config_dialog(const char *event_name, GtkWindow *parent)
+{
+ if (option_widget_list != NULL)
+ {
+ g_list_free(option_widget_list);
+ option_widget_list = NULL;
+ }
+
+ event_config_t *event = get_event_config(event_name);
+
+ GtkWindow *parent_window = parent ? parent : g_event_list_window;
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons(
+ /*title:*/ec_get_screen_name(event) ? ec_get_screen_name(event) : event_name,
+ parent_window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_APPLY,
+ NULL);
+
+ /* Allow resize?
+ * W/o resize, e.g. upload configuration hint looks awfully
+ * line wrapped.
+ * With resize, there are some somewhat not nice effects:
+ * for one, opening an expander will enlarge window,
+ * but won't contract it back when expander is closed.
+ */
+ gtk_window_set_resizable(GTK_WINDOW(dialog), true);
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 450, -1);
+
+ if (parent_window != NULL)
+ {
+ gtk_window_set_icon_name(GTK_WINDOW(dialog),
+ gtk_window_get_icon_name(parent_window));
+ }
+
+ GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ content = create_event_config_dialog_content(event, content);
+
+ return dialog;
+}
+
+static void add_event_to_liststore(gpointer key, gpointer value, gpointer user_data)
+{
+ config_item_info_t *info = ec_get_config_info((event_config_t *)value);
+ GtkWidget *dialog = create_config_dialog(key, NULL);
+ add_item_to_config_liststore(dialog, info, user_data);
+}
+
+int show_event_config_dialog(const char *event_name, GtkWindow *parent)
+{
+ if (option_widget_list != NULL)
+ {
+ g_list_free(option_widget_list);
+ option_widget_list = NULL;
+ }
+
+ event_config_t *event = get_event_config(event_name);
+
+ GtkWindow *parent_window = parent ? parent : g_event_list_window;
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons(
+ /*title:*/ec_get_screen_name(event) ? ec_get_screen_name(event) : event_name,
+ parent_window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_APPLY,
+ NULL);
+
+ /* Allow resize?
+ * W/o resize, e.g. upload configuration hint looks awfully
+ * line wrapped.
+ * With resize, there are some somewhat not nice effects:
+ * for one, opening an expander will enlarge window,
+ * but won't contract it back when expander is closed.
+ */
+ gtk_window_set_resizable(GTK_WINDOW(dialog), true);
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 450, -1);
+
+ if (parent_window != NULL)
+ {
+ gtk_window_set_icon_name(GTK_WINDOW(dialog),
+ gtk_window_get_icon_name(parent_window));
+ }
+
+ GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ content = create_event_config_dialog_content(event, content);
+
gtk_widget_show_all(content);
int result = gtk_dialog_run(GTK_DIALOG(dialog));
@@ -396,31 +387,9 @@ int show_event_config_dialog(const char *event_name, GtkWindow *parent)
return result;
}
-void show_events_list_dialog(GtkWindow *parent)
+#if 0
+GtkWidget *create_event_list_config_dialog()
{
- /*remove this line if we want to reload the config
- *everytime we show the config dialog
- */
- if (g_event_config_list == NULL)
- {
- load_event_config_data();
- load_event_config_data_from_user_storage(g_event_config_list);
- }
-
- GtkWidget *event_list_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- g_event_list_window = (GtkWindow*)event_list_window;
- gtk_window_set_title(g_event_list_window, _("Event Configuration"));
- gtk_window_set_default_size(g_event_list_window, 450, 400);
- gtk_window_set_position(g_event_list_window, parent ? GTK_WIN_POS_CENTER_ON_PARENT : GTK_WIN_POS_CENTER);
- if (parent != NULL)
- {
- gtk_window_set_transient_for(g_event_list_window, parent);
- // modal = parent window can't steal focus
- gtk_window_set_modal(g_event_list_window, true);
- gtk_window_set_icon_name(g_event_list_window,
- gtk_window_get_icon_name(parent));
- }
-
GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
GtkWidget *events_scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(events_scroll),
@@ -448,18 +417,13 @@ void show_events_list_dialog(GtkWindow *parent)
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(events_tv), TRUE);
// TODO: gtk_tree_view_set_headers_visible(FALSE)? We have only one column anyway...
- /* Create data store for the list and attach it
- * COLUMN_EVENT_UINAME -> name+description
- * COLUMN_EVENT_NAME -> event name so we can retrieve it from the row
- */
- GtkListStore *events_list_store = gtk_list_store_new(NUM_COLUMNS,
- G_TYPE_STRING, /* Event name + description */
- G_TYPE_STRING /* event name */
+
);
+ events_list_store = new_conf_liststore();
gtk_tree_view_set_model(GTK_TREE_VIEW(events_tv), GTK_TREE_MODEL(events_list_store));
g_hash_table_foreach(g_event_config_list,
- &add_event_to_liststore,
+ &add_event_to_liststore_wrap,
events_list_store);
//TODO: can unref events_list_store? treeview holds one ref.
@@ -483,6 +447,37 @@ void show_events_list_dialog(GtkWindow *parent)
gtk_box_pack_start(GTK_BOX(main_vbox), events_scroll, true, true, 10);
gtk_box_pack_start(GTK_BOX(main_vbox), btnbox, false, false, 0);
+ return main_vbox;
+}
+#endif
+
+void show_events_list_dialog(GtkWindow *parent)
+{
+ /*remove this line if we want to reload the config
+ *everytime we show the config dialog
+ */
+ if (g_event_config_list == NULL)
+ {
+ load_event_config_data();
+ load_event_config_data_from_user_storage(g_event_config_list);
+ }
+
+ GtkWidget *event_list_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ g_event_list_window = (GtkWindow*)event_list_window;
+ gtk_window_set_title(g_event_list_window, _("Event Configuration"));
+ gtk_window_set_default_size(g_event_list_window, 450, 400);
+ gtk_window_set_position(g_event_list_window, parent ? GTK_WIN_POS_CENTER_ON_PARENT : GTK_WIN_POS_CENTER);
+ if (parent != NULL)
+ {
+ gtk_window_set_transient_for(g_event_list_window, parent);
+ // modal = parent window can't steal focus
+ gtk_window_set_modal(g_event_list_window, true);
+ gtk_window_set_icon_name(g_event_list_window,
+ gtk_window_get_icon_name(parent));
+ }
+
+ GtkWidget *main_vbox = create_config_list_dialog(_("Event"), g_event_config_list, GTK_WINDOW(event_list_window), &add_event_to_liststore, NULL, NULL);
+
gtk_container_add(GTK_CONTAINER(event_list_window), main_vbox);
gtk_widget_show_all(event_list_window);
diff --git a/src/gtk-helpers/internal_libreport_gtk.h b/src/gtk-helpers/internal_libreport_gtk.h
index 5cb965c..ff3d653 100644
--- a/src/gtk-helpers/internal_libreport_gtk.h
+++ b/src/gtk-helpers/internal_libreport_gtk.h
@@ -37,7 +37,7 @@ void show_events_list_dialog(GtkWindow *parent);
bool is_event_config_user_storage_available();
#define load_single_event_config_data_from_user_storage libreport_load_single_event_config_data_from_user_storage
-void load_single_event_config_data_from_user_storage(const char *event_name, event_config_t *config);
+void load_single_event_config_data_from_user_storage(event_config_t *config);
#define load_event_config_data_from_user_storage libreport_load_event_config_data_from_user_storage
void load_event_config_data_from_user_storage(GHashTable *event_config_list);
@@ -50,6 +50,24 @@ void save_event_config_data_to_user_storage(const char *event_name,
#define show_event_config_dialog libreport_show_event_config_dialog
int show_event_config_dialog(const char *event_name, GtkWindow *parent);
+#define create_event_config_dialog_content libreport_create_event_config_dialog_content
+GtkWidget *create_event_config_dialog_content(event_config_t *event, GtkWidget *content);
+
+#define show_workflow_list_dialog libreport_show_workflow_list_dialog
+void show_workflow_list_dialog(GtkWindow *parent);
+
+#define add_item_to_config_liststore libreport_add_item_to_config_liststore
+void add_item_to_config_liststore(gpointer key, gpointer value, gpointer user_data);
+
+#define create_config_list_dialog libreport_create_config_list_dialog
+GtkWidget *create_config_list_dialog(const char *column_label,
+ GHashTable *items,
+ GtkWindow *dialog,
+ GHFunc item_to_config_info,
+ GCallback on_config_cb,
+ GCallback on_row_change);
+GtkListStore *new_conf_liststore();
+
char * tag_url(const char* line, const char* prefix);
#define url_token libreport_url_token
diff --git a/src/gtk-helpers/secrets.c b/src/gtk-helpers/secrets.c
index 468c508..9de2284 100644
--- a/src/gtk-helpers/secrets.c
+++ b/src/gtk-helpers/secrets.c
@@ -1378,7 +1378,7 @@ bool is_event_config_user_storage_available()
* @param name Event name
* @param config Event config
*/
-void load_single_event_config_data_from_user_storage(const char *event_name, event_config_t *config)
+void load_single_event_config_data_from_user_storage(event_config_t *config)
{
GHashTable *tmp = g_hash_table_new_full(
/*hash_func*/ g_str_hash,
@@ -1386,7 +1386,7 @@ void load_single_event_config_data_from_user_storage(const char *event_name, eve
/*key_destroy_func:*/ g_free,
/*value_destroy_func:*/ NULL);
- g_hash_table_insert(tmp, xstrdup(event_name), config);
+ g_hash_table_insert(tmp, xstrdup(ec_get_name(config)), config);
load_event_config_data_from_user_storage(tmp);
diff --git a/src/gtk-helpers/workflow_config_dialog.c b/src/gtk-helpers/workflow_config_dialog.c
new file mode 100644
index 0000000..acdc81d
--- /dev/null
+++ b/src/gtk-helpers/workflow_config_dialog.c
@@ -0,0 +1,119 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <gtk/gtk.h>
+#include "internal_libreport_gtk.h"
+
+enum
+{
+ COLUMN_WORKFLOW_UINAME,
+ COLUMN_WORKFLOW_NAME,
+ NUM_COLUMNS
+};
+
+static GtkWindow *g_parent_window;
+
+GtkWidget *create_workflow_config_dialog(const char *workflow_name, GtkWindow *parent)
+{
+ workflow_t *workflow = get_workflow(workflow_name);
+ GList *events = workflow->events;
+
+ GtkWindow *parent_window = parent ? parent : g_parent_window;
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons(
+ /*title:*/ wf_get_screen_name(workflow) ? wf_get_screen_name(workflow) : workflow_name,
+ parent_window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_APPLY,
+ NULL);
+
+ gtk_window_set_resizable(GTK_WINDOW(dialog), true);
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 450, -1);
+
+ if (parent_window != NULL)
+ {
+ gtk_window_set_icon_name(GTK_WINDOW(dialog),
+ gtk_window_get_icon_name(parent_window));
+ }
+
+ GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+ //GtkWidget *event_conf_widg = NULL;
+ while(events)
+ {
+ event_config_t *ec = (event_config_t *)events->data;
+ create_event_config_dialog_content(ec, content);
+ //gtk_box_pack_start(GTK_BOX(content), event_conf_widg, true, true, 0);
+ events = g_list_next(events);
+ }
+
+ return dialog;
+}
+
+static void add_workflow_to_liststore(gpointer key, gpointer value, gpointer user_data)
+{
+ config_item_info_t *info = workflow_get_config_info((workflow_t *)value);
+ GtkWidget *dialog = create_workflow_config_dialog(key, g_parent_window);
+ add_item_to_config_liststore(dialog, info, user_data);
+}
+
+static void load_single_event_config_foreach(event_config_t *ec, gpointer user_data)
+{
+ load_single_event_config_data_from_user_storage(ec);
+}
+
+static void load_events_foreach_workflow(const char *name, workflow_t *workflow, gpointer user_data)
+{
+ g_list_foreach(wf_get_event_list(workflow), (GFunc)load_single_event_config_foreach, NULL);
+}
+
+void show_workflow_list_dialog(GtkWindow *parent)
+{
+ g_parent_window = parent;
+ //g_verbose = 3;
+ if (g_workflow_list == NULL)
+ {
+ VERB1 log("workflow list is empty - reloading");
+ load_workflow_config_data(WORKFLOWS_DIR);
+ }
+
+ g_hash_table_foreach(g_workflow_list, (GHFunc)load_events_foreach_workflow, NULL);
+
+ GtkWindow *workflow_list_window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
+ gtk_window_set_title(workflow_list_window, _("Workflow Configuration"));
+ gtk_window_set_default_size(workflow_list_window, 450, 400);
+ gtk_window_set_position(workflow_list_window, parent ? GTK_WIN_POS_CENTER_ON_PARENT : GTK_WIN_POS_CENTER);
+ if (parent != NULL)
+ {
+ gtk_window_set_transient_for(workflow_list_window, parent);
+ // modal = parent window can't steal focus
+ gtk_window_set_modal(workflow_list_window, true);
+ gtk_window_set_icon_name(workflow_list_window,
+ gtk_window_get_icon_name(parent));
+ }
+
+ GtkWidget *main_vbox = create_config_list_dialog(_("Workflow"), g_workflow_list, workflow_list_window, add_workflow_to_liststore, NULL, NULL);
+
+ gtk_container_add(GTK_CONTAINER(workflow_list_window), main_vbox);
+
+ gtk_widget_show_all(GTK_WIDGET(workflow_list_window));
+
+}
diff --git a/src/gui-wizard-gtk/Makefile.am b/src/gui-wizard-gtk/Makefile.am
index ecd1887..46c1d65 100644
--- a/src/gui-wizard-gtk/Makefile.am
+++ b/src/gui-wizard-gtk/Makefile.am
@@ -19,6 +19,7 @@ report_gtk_CFLAGS = \
-DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
-DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
-DICON_DIR=\"${datadir}/abrt/icons/hicolor/48x48/status\" \
+ -DWORKFLOWS_DIR=\"$(WORKFLOWS_DIR)\" \
$(GLIB_CFLAGS) \
$(GTK_CFLAGS) \
-D_GNU_SOURCE
diff --git a/src/gui-wizard-gtk/main.c b/src/gui-wizard-gtk/main.c
index fab88f1..1bb9af1 100644
--- a/src/gui-wizard-gtk/main.c
+++ b/src/gui-wizard-gtk/main.c
@@ -74,6 +74,8 @@ void problem_data_reload_from_dump_dir(void)
int main(int argc, char **argv)
{
+ bool expert_mode = false;
+
const char *prgname = "abrt";
abrt_init(argv);
@@ -110,6 +112,7 @@ int main(int argc, char **argv)
OPT_p = 1 << 2,
OPT_d = 1 << 3,
OPT_e = 1 << 4,
+ OPT_x = 1 << 5,
};
/* Keep enum above and order of options below in sync! */
struct options program_options[] = {
@@ -119,6 +122,7 @@ int main(int argc, char **argv)
/* for use from 3rd party apps to show just a reporter selector */
OPT_BOOL( 'd', "delete", NULL, _("Remove DIR after reporting")),
OPT_LIST( 'e', "event", &g_auto_event_list, "EVENT", _("Run only this event")),
+ OPT_BOOL( 'x', "expert", &expert_mode, _("Run wizard in expert mode - shows advanced options")),
OPT_END()
};
unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
@@ -130,6 +134,8 @@ int main(int argc, char **argv)
for (GList *elem = g_auto_event_list; elem; elem = g_list_next(elem))
elem->data = xstrdup((const char *)elem->data);
+ g_auto_event_list = NULL;
+
export_abrt_envvars(opts & OPT_p);
g_dump_dir_name = xstrdup(argv[0]);
@@ -140,9 +146,11 @@ int main(int argc, char **argv)
load_event_config_data_from_user_storage(g_event_config_list);
load_user_settings("report-gtk");
+ load_workflow_config_data(WORKFLOWS_DIR);
+
problem_data_reload_from_dump_dir();
- create_assistant();
+ create_assistant(expert_mode);
g_custom_logger = &show_error_as_msgbox;
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index f351988..04dc961 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -64,6 +64,7 @@ static GtkWidget *g_btn_close;
static GtkWidget *g_btn_next;
static GtkBox *g_box_events;
+static GtkBox *g_box_workflows;
/* List of event_gui_data's */
static GList *g_list_events;
static GtkLabel *g_lbl_event_log;
@@ -104,6 +105,9 @@ static GtkImage *g_img_process_ok;
static GtkWidget *g_top_most_window;
+static void add_workflow_buttons(GtkBox *box, GHashTable *workflows, GCallback func);
+static void set_auto_event_chain(GtkButton *button, gpointer user_data);
+
typedef struct
{
int page; //which tab in notepad
@@ -162,8 +166,8 @@ enum {
* instead of strcmp.
*/
static const gchar PAGE_SUMMARY[] = "page_0";
-static const gchar PAGE_EVENT_SELECTOR[] = "page_2";
-static const gchar PAGE_EDIT_COMMENT[] = "page_1";
+static const gchar PAGE_EVENT_SELECTOR[] = "page_1";
+static const gchar PAGE_EDIT_COMMENT[] = "page_2";
static const gchar PAGE_EDIT_ELEMENTS[] = "page_3";
static const gchar PAGE_REVIEW_DATA[] = "page_4";
static const gchar PAGE_EVENT_PROGRESS[] = "page_5";
@@ -273,12 +277,12 @@ static void show_event_opt_error_dialog(const char *event_name)
"reporting will probably fail if you continue "
"with the current configuration.\n\n"
"Read more about the configuration at: https://fedorahosted.org/abrt/wiki/AbrtConfiguration"),
- ec->screen_name);
+ ec_get_screen_name(ec));
char *markup_message = xasprintf(_("Wrong settings detected for <b>%s</b>, "
"reporting will probably fail if you continue "
"with the current configuration.\n\n"
"<a href=\"https://fedorahosted.org/abrt/wiki/AbrtConfiguration\">Read more about the configuration</a>"),
- ec->screen_name);
+ ec_get_screen_name(ec));
GtkWidget *wrong_settings = g_top_most_window = gtk_message_dialog_new(GTK_WINDOW(g_wnd_assistant),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
@@ -292,7 +296,7 @@ static void show_event_opt_error_dialog(const char *event_name)
free(markup_message);
GtkWidget *act_area = gtk_dialog_get_content_area(GTK_DIALOG(wrong_settings));
- char * conf_btn_lbl = xasprintf(_("Con_figure %s"), ec->screen_name);
+ char * conf_btn_lbl = xasprintf(_("Con_figure %s"), ec_get_screen_name(ec));
GtkWidget *configure_event_btn = gtk_button_new_with_mnemonic(conf_btn_lbl);
g_signal_connect(configure_event_btn, "clicked", G_CALLBACK(on_configure_event_cb), (gpointer)event_name);
free(conf_btn_lbl);
@@ -972,6 +976,7 @@ static char *missing_items_in_comma_list(const char *input_item_list)
}
return result;
}
+
static event_gui_data_t *add_event_buttons(GtkBox *box,
GList **p_event_list,
char *event_name,
@@ -1016,9 +1021,9 @@ static event_gui_data_t *add_event_buttons(GtkBox *box,
if (cfg)
{
/* .xml has (presumably) prettier description, use it: */
- if (cfg->screen_name)
- event_screen_name = cfg->screen_name;
- event_description = cfg->description;
+ if (ec_get_screen_name(cfg))
+ event_screen_name = ec_get_screen_name(cfg);
+ event_description = ec_get_description(cfg);
char *missing = missing_items_in_comma_list(cfg->ec_requires_items);
if (missing)
@@ -1078,8 +1083,8 @@ static event_gui_data_t *add_event_buttons(GtkBox *box,
if (func)
g_signal_connect(G_OBJECT(button), "toggled", func, xstrdup(event_name));
- if (cfg && cfg->long_descr)
- gtk_widget_set_tooltip_text(button, cfg->long_descr);
+ if (cfg && ec_get_long_desc(cfg))
+ gtk_widget_set_tooltip_text(button, ec_get_long_desc(cfg));
event_gui_data_t *event_gui_data = new_event_gui_data_t();
event_gui_data->event_name = xstrdup(event_name);
@@ -1099,7 +1104,9 @@ static event_gui_data_t *add_event_buttons(GtkBox *box,
event_name = event_name_end + 1;
gtk_box_pack_start(box, button, /*expand*/ false, /*fill*/ false, /*padding*/ 0);
+ gtk_widget_show_all(GTK_WIDGET(button));
}
+ gtk_widget_show_all(GTK_WIDGET(box));
return active_button;
}
@@ -1316,13 +1323,24 @@ void update_gui_state_from_problem_data(int flags)
load_text_to_text_view(g_tv_comment, FILENAME_COMMENT);
- /* Update event radio buttons */
- event_gui_data_t *active_button = add_event_buttons(
- g_box_events,
- &g_list_events,
- g_events,
- G_CALLBACK(event_rb_was_toggled)
- );
+ add_workflow_buttons(g_box_workflows, g_workflow_list,
+ G_CALLBACK(set_auto_event_chain));
+
+ /* Update event radio buttons
+ * show them only in expert mode
+ */
+ event_gui_data_t *active_button = NULL;
+ if (g_expert_mode == true)
+ {
+ //this widget doesn't react to show_all, so we need to "force" it
+ gtk_widget_show(GTK_WIDGET(g_box_events));
+ active_button = add_event_buttons(
+ g_box_events,
+ &g_list_events,
+ g_events,
+ G_CALLBACK(event_rb_was_toggled)
+ );
+ }
if (flags & UPDATE_SELECTED_EVENT && g_expert_mode)
{
@@ -1335,7 +1353,6 @@ void update_gui_state_from_problem_data(int flags)
}
VERB2 log("g_event_selected='%s'", g_event_selected);
}
-
/* We can't just do gtk_widget_show_all once in main:
* We created new widgets (buttons). Need to make them visible.
*/
@@ -2400,6 +2417,50 @@ static void on_page_prepare(GtkNotebook *assistant, GtkWidget *page, gpointer us
}
}
+//static void event_rb_was_toggled(GtkButton *button, gpointer user_data)
+static void set_auto_event_chain(GtkButton *button, gpointer user_data)
+{
+ //event is selected, so make sure the expert mode is disabled
+ g_expert_mode = false;
+
+ workflow_t *w = (workflow_t *)user_data;
+ config_item_info_t *info = workflow_get_config_info(w);
+ VERB1 log("selected workflow '%s'", info->screen_name);
+
+ GList *wf_event_list = wf_get_event_list(w);
+ while(wf_event_list)
+ {
+ g_auto_event_list = g_list_append(g_auto_event_list, xstrdup(ec_get_name(wf_event_list->data)));
+ load_single_event_config_data_from_user_storage((event_config_t *)wf_event_list->data);
+
+ wf_event_list = g_list_next(wf_event_list);
+ }
+
+ gint current_page_no = gtk_notebook_get_current_page(g_assistant);
+ gint next_page_no = select_next_page_no(current_page_no, NULL);
+
+ /* if pageno is not change 'switch-page' signal is not emitted */
+ if (current_page_no == next_page_no)
+ on_page_prepare(g_assistant, gtk_notebook_get_nth_page(g_assistant, next_page_no), NULL);
+ else
+ gtk_notebook_set_current_page(g_assistant, next_page_no);
+}
+
+static void add_workflow_buttons(GtkBox *box, GHashTable *workflows, GCallback func)
+{
+ GList *keys = g_hash_table_get_keys(g_workflow_list);
+ while(keys)
+ {
+ workflow_t *workflow = g_hash_table_lookup(g_workflow_list, keys->data);
+ config_item_info_t *info = workflow_get_config_info(workflow);
+ GtkWidget *button = gtk_button_new_with_label(info->screen_name);
+ g_signal_connect(button, "clicked", func, workflow);
+ gtk_box_pack_start(box, button, true, false, 0);
+ keys = g_list_next(keys);
+ }
+
+}
+
static char *setup_next_processed_event(GList **events_list)
{
free(g_event_selected);
@@ -2431,7 +2492,7 @@ static bool get_sensitive_data_permission(const char *event_name)
char *msg = xasprintf(_("Event '%s' requires permission to send possibly sensitive data."
"\nDo you want to continue?"),
- event_cfg->screen_name ? event_cfg->screen_name : event_name);
+ ec_get_screen_name(event_cfg) ? ec_get_screen_name(event_cfg) : event_name);
const bool response = ask_yes_no_save_result(msg, "ask_send_sensitive_data");
free(msg);
@@ -2449,6 +2510,11 @@ static gint select_next_page_no(gint current_page_no, gpointer data)
if (pages[PAGENO_EVENT_SELECTOR].page_widget == page)
{
+ if (!g_expert_mode && (g_auto_event_list == NULL))
+ {
+ return current_page_no; //stay here and let user select the workflow
+ }
+
if (!g_expert_mode)
{
/* (note: this frees and sets to NULL g_event_selected) */
@@ -2881,6 +2947,7 @@ static void add_pages(void)
/* Set pointers to objects we might need to work with */
g_lbl_cd_reason = GTK_LABEL( gtk_builder_get_object(g_builder, "lbl_cd_reason"));
g_box_events = GTK_BOX( gtk_builder_get_object(g_builder, "vb_events"));
+ g_box_workflows = GTK_BOX( gtk_builder_get_object(g_builder, "vb_workflows"));
g_lbl_event_log = GTK_LABEL( gtk_builder_get_object(g_builder, "lbl_event_log"));
g_tv_event_log = GTK_TEXT_VIEW( gtk_builder_get_object(g_builder, "tv_event_log"));
g_tv_comment = GTK_TEXT_VIEW( gtk_builder_get_object(g_builder, "tv_comment"));
@@ -2989,7 +3056,7 @@ static void init_page(page_obj_t *page, const char *name, const char *title)
static void init_pages(void)
{
init_page(&pages[0], PAGE_SUMMARY , _("Problem description") );
- init_page(&pages[1], PAGE_EVENT_SELECTOR , _("Select operation") );
+ init_page(&pages[1], PAGE_EVENT_SELECTOR , _("Select how to report this problem"));
init_page(&pages[2], PAGE_EDIT_COMMENT,_("Provide additional information"));
init_page(&pages[3], PAGE_EDIT_ELEMENTS , _("Review the data") );
init_page(&pages[4], PAGE_REVIEW_DATA , _("Confirm data to report"));
@@ -3005,11 +3072,11 @@ static void assistant_quit_cb(void *obj, void *data)
gtk_main_quit();
}
-void create_assistant(void)
+void create_assistant(bool expert_mode)
{
g_loaded_texts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
- g_expert_mode = !g_auto_event_list;
+ g_expert_mode = expert_mode;
g_monospace_font = pango_font_description_from_string("monospace");
g_builder = gtk_builder_new();
diff --git a/src/gui-wizard-gtk/wizard.glade b/src/gui-wizard-gtk/wizard.glade
index 53e215e..15a5697 100644
--- a/src/gui-wizard-gtk/wizard.glade
+++ b/src/gui-wizard-gtk/wizard.glade
@@ -83,7 +83,7 @@
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
- <object class="GtkVBox" id="page_1">
+ <object class="GtkVBox" id="page_2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">10</property>
@@ -177,15 +177,31 @@
<object class="GtkWindow" id="window2">
<property name="can_focus">False</property>
<child>
- <object class="GtkVBox" id="page_2">
+ <object class="GtkVBox" id="page_1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">10</property>
<property name="spacing">3</property>
<child>
+ <object class="GtkBox" id="vb_workflows">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkVBox" id="vb_events">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
<child>
<placeholder/>
</child>
diff --git a/src/gui-wizard-gtk/wizard.h b/src/gui-wizard-gtk/wizard.h
index d2caaa6..a6d8b5d 100644
--- a/src/gui-wizard-gtk/wizard.h
+++ b/src/gui-wizard-gtk/wizard.h
@@ -21,7 +21,7 @@
#include "internal_libreport_gtk.h"
-void create_assistant(void);
+void create_assistant(bool expert_mode);
enum
{
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 948662e..a4dc133 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -7,7 +7,9 @@ libreport_include_HEADERS = \
report.h \
run_event.h \
libreport_curl.h \
+ workflow.h \
\
+ config_item_info.h \
file_obj.h \
internal_libreport.h \
internal_abrt_dbus.h
diff --git a/src/include/config_item_info.h b/src/include/config_item_info.h
new file mode 100644
index 0000000..ac49bd5
--- /dev/null
+++ b/src/include/config_item_info.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2011 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef LIBREPORT_CONFIG_ITEM_H
+#define LIBREPORT_CONFIG_ITEM_H
+
+typedef struct
+{
+ char *name; //the event name (from it's filename)
+ char *screen_name; //ui friendly name of the event: "Bugzilla" "RedHat Support Upload"
+ char *description; // "Report to..."/"Save to file". Should be one sentence, not long
+ char *long_desc; // Long(er) explanation, if needed
+
+} config_item_info_t;
+
+config_item_info_t *new_config_info();
+void free_config_info(config_item_info_t *info);
+
+void ci_set_screen_name(config_item_info_t *ci, const char *screen_name);
+void ci_set_name(config_item_info_t *ci, const char *name);
+void ci_set_description(config_item_info_t *ci, const char *description);
+void ci_set_long_desc(config_item_info_t *ci, const char *long_description);
+
+const char *ci_get_screen_name(config_item_info_t *ci);
+const char *ci_get_name(config_item_info_t *ci);
+const char *ci_get_description(config_item_info_t *ci);
+const char *ci_get_long_desc(config_item_info_t *ci);
+
+#endif
diff --git a/src/include/event_config.h b/src/include/event_config.h
index 438c723..60fa5c6 100644
--- a/src/include/event_config.h
+++ b/src/include/event_config.h
@@ -22,6 +22,7 @@
#include <stdbool.h>
#include <glib.h>
#include "problem_data.h"
+#include "config_item_info.h"
#ifdef __cplusplus
extern "C" {
@@ -68,10 +69,7 @@ void free_event_option(event_option_t *p);
//structure to hold the option data
typedef struct
{
- char *name; //the event name (from it's filename)
- char *screen_name; //ui friendly name of the event: "Bugzilla" "RedHat Support Upload"
- char *description; // "Report to..."/"Save to file". Should be one sentence, not long
- char *long_descr; // Long(er) explanation, if needed
+ config_item_info_t *info;
char *ec_creates_items;
char *ec_requires_items;
@@ -87,6 +85,18 @@ typedef struct
} event_config_t;
event_config_t *new_event_config(void);
+config_item_info_t *ec_get_config_info(event_config_t * ec);
+const char *ec_get_screen_name(event_config_t *ec);
+void ec_set_screen_name(event_config_t *ec, const char *screen_name);
+void ec_set_name(event_config_t *ec, const char *name);
+
+const char *ec_get_description(event_config_t *ec);
+void ec_set_description(event_config_t *ec, const char *description);
+
+const char *ec_get_name(event_config_t *ec);
+const char *ec_get_long_desc(event_config_t *ec);
+void ec_set_long_desc(event_config_t *ec, const char *long_desc);
+
void free_event_config(event_config_t *p);
@@ -99,6 +109,7 @@ void free_event_config_data(void);
event_config_t *get_event_config(const char *event_name);
event_option_t *get_event_option_from_list(const char *option_name, GList *event_options);
+
extern GHashTable *g_event_config_list; // for iterating through entire list of all loaded configs
GList *export_event_config(const char *event_name);
diff --git a/src/include/file_obj.h b/src/include/file_obj.h
index 9cb293f..08823af 100644
--- a/src/include/file_obj.h
+++ b/src/include/file_obj.h
@@ -24,6 +24,8 @@ typedef struct file_obj
* e.g:
* if fullpath is: /foo/bar/report_Bugzilla.xml
* then filename is: report_Bugzilla
+ * in case of symlink the filename is created from the symlink name
+ * and the fullpath is the symlink target
*/
char *filename;
char *fullpath; //the full path with extension
diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h
index d22bcbe..4f85b2a 100644
--- a/src/include/internal_libreport.h
+++ b/src/include/internal_libreport.h
@@ -93,6 +93,7 @@ int vdprintf(int d, const char *format, va_list ap);
#include "problem_data.h"
#include "report.h"
#include "run_event.h"
+#include "workflow.h"
#include "file_obj.h"
#ifdef __cplusplus
@@ -642,6 +643,8 @@ void free_file_list(GList *filelist);
file_obj_t *new_file_obj(const char* fullpath, const char* filename);
#define free_file_obj libreport_free_file_obj
void free_file_obj(file_obj_t *f);
+#define load_workflow_config_data libreport_load_workflow_config_data
+void load_workflow_config_data(const char* path);
/* Connect to abrtd over unix domain socket, issue DELETE command */
int delete_dump_dir_possibly_using_abrtd(const char *dump_dir_name);
diff --git a/src/include/workflow.h b/src/include/workflow.h
new file mode 100644
index 0000000..dc2768c
--- /dev/null
+++ b/src/include/workflow.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2011 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef LIBREPORT_WORKFLOW_H
+#define LIBREPORT_WORKFLOW_H
+
+#include <glib.h>
+#include "event_config.h"
+#include "config_item_info.h"
+
+typedef struct
+{
+ config_item_info_t *info;
+
+ GList *events; //list of event_option_t
+} workflow_t;
+
+extern GHashTable *g_workflow_list;
+
+workflow_t *new_workflow(void);
+workflow_t *get_workflow(const char *name);
+void free_workflow(workflow_t *w);
+
+void load_workflow_description_from_file(workflow_t *w, const char *filename);
+config_item_info_t *workflow_get_config_info(workflow_t *w);
+const char *wf_get_name(workflow_t *w);
+GList *wf_get_event_list(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);
+
+void wf_set_name(workflow_t *w, const char* name);
+void wf_set_description(workflow_t *w, const char* description);
+void wf_set_long_desc(workflow_t *w, const char* long_desc);
+
+#endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 2865624..dad9f89 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -49,7 +49,10 @@ libreport_la_SOURCES = \
client.c \
utf8.c \
file_list.c \
- file_obj.c
+ file_obj.c \
+ workflow.c \
+ workflow_xml_parser.c \
+ config_item_info.c
libreport_la_CPPFLAGS = \
-I$(srcdir)/../include \
-DLOCALSTATEDIR='"$(localstatedir)"' \
@@ -59,6 +62,7 @@ libreport_la_CPPFLAGS = \
-DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
-DCONF_DIR=\"$(CONF_DIR)\" \
-DEVENTS_DIR=\"$(EVENTS_DIR)\" \
+ -DWORKFLOWS_DIR=\"$(WORKFLOWS_DIR)\" \
-DBIN_DIR=\"$(bindir)\" \
$(GLIB_CFLAGS) \
-D_GNU_SOURCE
diff --git a/src/lib/config_item_info.c b/src/lib/config_item_info.c
new file mode 100644
index 0000000..c8e2d78
--- /dev/null
+++ b/src/lib/config_item_info.c
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2011 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "internal_libreport.h"
+//#include "config_item_info.h"
+
+
+config_item_info_t *new_config_info()
+{
+ config_item_info_t *info = (config_item_info_t *)xzalloc(sizeof(config_item_info_t));
+ return info;
+}
+
+void free_config_info(config_item_info_t *info)
+{
+ if (info == NULL)
+ return;
+
+ free(info->name);
+ free(info->screen_name);
+ free(info->description);
+ free(info->long_desc);
+
+ free(info);
+}
+
+void ci_set_screen_name(config_item_info_t *ci, const char *screen_name)
+{
+ free(ci->screen_name);
+ ci->screen_name = xstrdup(screen_name);
+}
+
+void ci_set_name(config_item_info_t *ci, const char *name)
+{
+ free(ci->name);
+ ci->name = xstrdup(name);
+}
+
+void ci_set_description(config_item_info_t *ci, const char *description)
+{
+ free(ci->description);
+ ci->description = xstrdup(description);
+}
+
+void ci_set_long_desc(config_item_info_t *ci, const char *long_description)
+{
+ free(ci->long_desc);
+ ci->long_desc = xstrdup(long_description);
+}
+
+const char *ci_get_screen_name(config_item_info_t *ci)
+{
+ return ci->screen_name;
+}
+
+const char *ci_get_name(config_item_info_t *ci)
+{
+ return ci->name;
+}
+
+const char *ci_get_description(config_item_info_t *ci)
+{
+ return ci->description;
+}
+
+const char *ci_get_long_desc(config_item_info_t *ci)
+{
+ return ci->long_desc;
+}
diff --git a/src/lib/event_config.c b/src/lib/event_config.c
index 2019e53..402a09f 100644
--- a/src/lib/event_config.c
+++ b/src/lib/event_config.c
@@ -16,6 +16,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+
#include "internal_libreport.h"
GHashTable *g_event_config_list;
@@ -29,9 +30,55 @@ event_option_t *new_event_option(void)
event_config_t *new_event_config(void)
{
event_config_t *e = xzalloc(sizeof(event_config_t));
+ e->info = new_config_info();
return e;
}
+config_item_info_t *ec_get_config_info(event_config_t * ec)
+{
+ return ec->info;
+}
+
+void ec_set_name(event_config_t *ec, const char *name)
+{
+ ci_set_name(ec->info, name);
+}
+
+void ec_set_screen_name(event_config_t *ec, const char *screen_name)
+{
+ ci_set_screen_name(ec->info, screen_name);
+}
+
+const char *ec_get_screen_name(event_config_t *ec)
+{
+ return ci_get_screen_name(ec->info);
+}
+
+const char *ec_get_description(event_config_t *ec)
+{
+ return ci_get_description(ec->info);
+}
+
+void ec_set_description(event_config_t *ec, const char *description)
+{
+ ci_set_description(ec->info, description);
+}
+
+const char *ec_get_name(event_config_t *ec)
+{
+ return ci_get_name(ec->info);
+}
+
+const char *ec_get_long_desc(event_config_t *ec)
+{
+ return ci_get_long_desc(ec->info);
+}
+
+void ec_set_long_desc(event_config_t *ec, const char *long_descr)
+{
+ ci_set_long_desc(ec->info, long_descr);
+}
+
void free_event_option(event_option_t *p)
{
if (!p)
@@ -50,9 +97,7 @@ void free_event_config(event_config_t *p)
if (!p)
return;
- free(p->screen_name);
- free(p->description);
- free(p->long_descr);
+ free_config_info(p->info);
free(p->ec_creates_items);
free(p->ec_requires_items);
free(p->ec_exclude_items_by_default);
diff --git a/src/lib/event_xml_parser.c b/src/lib/event_xml_parser.c
index 157b717..585e2e5 100644
--- a/src/lib/event_xml_parser.c
+++ b/src/lib/event_xml_parser.c
@@ -336,11 +336,11 @@ 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'
- || !ui->screen_name /* && parse_data->attribute_lang is "" - always true */
+ || !ec_get_screen_name(ui) /* && parse_data->attribute_lang is "" - always true */
) {
VERB2 log("event name:'%s'", text_copy);
- free(ui->screen_name);
- ui->screen_name = text_copy;
+ ec_set_screen_name(ui, text_copy);
+ free(text_copy);
text_copy = NULL;
}
}
@@ -355,10 +355,10 @@ static void text(GMarkupParseContext *context,
* OR the description is still not set and we found the default value
*/
if (parse_data->attribute_lang[0] != '\0'
- || !ui->description /* && parse_data->attribute_lang is "" - always true */
+ || !ec_get_description(ui) /* && parse_data->attribute_lang is "" - always true */
) {
- free(ui->description);
- ui->description = text_copy;
+ ec_set_description(ui, text_copy);
+ free(text_copy);
text_copy = NULL;
}
}
@@ -373,10 +373,10 @@ static void text(GMarkupParseContext *context,
* OR the description is still not set and we found the default value
*/
if (parse_data->attribute_lang[0] != '\0'
- || !ui->long_descr /* && parse_data->attribute_lang is "" - always true */
+ || !ec_get_long_desc(ui) /* && parse_data->attribute_lang is "" - always true */
) {
- free(ui->long_descr);
- ui->long_descr = text_copy;
+ ec_set_long_desc(ui, text_copy);
+ free(text_copy);
text_copy = NULL;
}
}
@@ -463,6 +463,7 @@ static void error(GMarkupParseContext *context,
void load_event_description_from_file(event_config_t *event_config, const char* filename)
{
+ VERB1 log("loading event: '%s'", filename);
struct my_parse_data parse_data = { event_config, NULL, NULL, NULL };
parse_data.cur_locale = setlocale(LC_ALL, NULL);
diff --git a/src/lib/workflow.c b/src/lib/workflow.c
new file mode 100644
index 0000000..9b17a73
--- /dev/null
+++ b/src/lib/workflow.c
@@ -0,0 +1,146 @@
+/*
+ Copyright (C) 2011 ABRT team
+ Copyright (C) 2010 RedHat Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "event_config.h"
+#include "workflow.h"
+#include "internal_libreport.h"
+
+GHashTable *g_workflow_list;
+
+workflow_t *new_workflow(void)
+{
+ workflow_t *w = xzalloc(sizeof(event_config_t));
+ w->info = new_config_info();
+ return w;
+}
+
+void free_workflow(workflow_t *w)
+{
+ if (!w)
+ return;
+
+ free_config_info(w->info);
+ g_list_free_full(w->events, (GDestroyNotify)free_event_config);
+ free(w);
+ w = NULL;
+}
+
+static void free_workflow_cb(const char *name, workflow_t *w, gpointer user_data)
+{
+ free_workflow(w);
+}
+
+void free_workflow_list(GHashTable *wl)
+{
+ g_hash_table_foreach(wl, (GHFunc)free_workflow_cb, NULL);
+ g_hash_table_destroy(wl);
+ wl = NULL;
+}
+
+workflow_t *get_workflow(const char *name)
+{
+ if (!g_workflow_list)
+ return NULL;
+ /* @@ FIXME: SYMLINKS@!!!
+ if (g_event_config_symlinks)
+ {
+ char *link = g_hash_table_lookup(g_event_config_symlinks, name);
+ if (link)
+ name = link;
+ }
+ */
+ return g_hash_table_lookup(g_workflow_list, name);
+}
+
+void load_workflow_config_data(const char* path)
+{
+ if (g_workflow_list == NULL)
+ {
+ g_workflow_list = g_hash_table_new_full(
+ g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) free_workflow
+ );
+ }
+
+ GList *workflow_files = get_file_list(path, "xml");
+ while(workflow_files)
+ {
+ file_obj_t *file = (file_obj_t *)workflow_files->data;
+
+ workflow_t *workflow = get_workflow(file->filename);
+ bool nw_workflow = (!workflow);
+ if (nw_workflow)
+ workflow = new_workflow();
+
+ load_workflow_description_from_file(workflow, file->fullpath);
+
+ if (nw_workflow)
+ g_hash_table_replace(g_workflow_list, xstrdup(file->filename), workflow);
+
+ workflow_files = g_list_next(workflow_files);
+ }
+ free_file_list(workflow_files);
+}
+
+config_item_info_t *workflow_get_config_info(workflow_t *w)
+{
+ return w->info;
+}
+
+GList *wf_get_event_list(workflow_t *w)
+{
+ return w->events;
+}
+
+const char *wf_get_name(workflow_t *w)
+{
+ return ci_get_name(workflow_get_config_info(w));
+}
+
+const char *wf_get_screen_name(workflow_t *w)
+{
+ return ci_get_screen_name(workflow_get_config_info(w));
+}
+
+const char *wf_get_description(workflow_t *w)
+{
+ return ci_get_description(workflow_get_config_info(w));
+}
+
+const char *wf_get_long_desc(workflow_t *w)
+{
+ return ci_get_long_desc(workflow_get_config_info(w));
+}
+
+void wf_set_name(workflow_t *w, const char* name)
+{
+ ci_set_name(workflow_get_config_info(w), name);
+}
+
+void wf_set_description(workflow_t *w, const char* description)
+{
+ ci_set_description(workflow_get_config_info(w), description);
+}
+
+void wf_set_long_desc(workflow_t *w, const char* long_desc)
+{
+ ci_set_long_desc(workflow_get_config_info(w), long_desc);
+}
diff --git a/src/lib/workflow_xml_parser.c b/src/lib/workflow_xml_parser.c
new file mode 100644
index 0000000..abea00b
--- /dev/null
+++ b/src/lib/workflow_xml_parser.c
@@ -0,0 +1,173 @@
+/*
+ Copyright (C) 2011 ABRT Team
+ Copyright (C) 2011 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "workflow.h"
+#include "internal_libreport.h"
+
+//workflow elements
+#define WORKFLOW_ELEMENT "workflow"
+#define EVENTS_ELEMENT "events"
+#define EVENT_ELEMENT "event"
+#define DESCRIPTION_ELEMENT "description"
+#define NAME_ELEMENT "name"
+
+struct my_parse_data
+{
+ workflow_t *workflow;
+ const char *cur_locale;
+ char *attribute_lang;
+ bool in_event_list;
+};
+
+static void start_element(GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ //log("start: %s", element_name);
+
+ struct my_parse_data *parse_data = user_data;
+ if (strcmp(element_name, EVENTS_ELEMENT) == 0)
+ {
+ parse_data->in_event_list = true;
+ }
+}
+
+// Called for close tags </foo>
+static void end_element(GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ struct my_parse_data *parse_data = user_data;
+
+ free(parse_data->attribute_lang);
+ parse_data->attribute_lang = NULL;
+
+ if (strcmp(element_name, EVENT_ELEMENT) == 0)
+ {
+ if (parse_data->in_event_list == true)
+ {
+ //pass
+ }
+ }
+
+ if (strcmp(element_name, EVENTS_ELEMENT) == 0)
+ {
+ parse_data->in_event_list = false;
+ }
+}
+
+// Called for character data
+// text is not nul-terminated
+static void text(GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ struct my_parse_data *parse_data = user_data;
+ workflow_t *workflow = parse_data->workflow;
+
+ const gchar *inner_element = g_markup_parse_context_get_element(context);
+
+ if(parse_data->in_event_list && strcmp(inner_element, EVENT_ELEMENT) == 0)
+ {
+ event_config_t *ec = new_event_config();
+ char *subevent_filename = xasprintf(EVENTS_DIR"/%s.xml", text);
+
+ load_event_description_from_file(ec, subevent_filename);
+ //HACK: need to make ec = NULL if the loading fails
+ if (ec_get_screen_name(ec))
+ {
+ workflow->events = g_list_append(workflow->events, ec);
+ VERB2 log("added to ev list: '%s'", ec_get_screen_name(ec));
+ }
+ ec_set_name(ec, text);
+ free(subevent_filename);
+ }
+
+ if(strcmp(inner_element, NAME_ELEMENT) == 0)
+ {
+ workflow->info->screen_name = xstrdup(text);
+ }
+
+ if(strcmp(inner_element, DESCRIPTION_ELEMENT) == 0)
+ {
+ workflow->info->description = xstrdup(text);
+ }
+}
+
+ // Called for strings that should be re-saved verbatim in this same
+ // position, but are not otherwise interpretable. At the moment
+ // this includes comments and processing instructions.
+ // text is not nul-terminated
+static void passthrough(GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ VERB3 log("passthrough");
+}
+
+// Called on error, including one set by other
+// methods in the vtable. The GError should not be freed.
+static void error(GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ error_msg("error in XML parsing");
+}
+
+void load_workflow_description_from_file(workflow_t *workflow, const char* filename)
+{
+ VERB1 log("loading workflow: '%s'", filename);
+ struct my_parse_data parse_data = { workflow, NULL, NULL, 0};
+ parse_data.cur_locale = setlocale(LC_ALL, NULL);
+
+ GMarkupParser parser;
+ memset(&parser, 0, sizeof(parser)); /* just in case */
+ parser.start_element = &start_element;
+ parser.end_element = &end_element;
+ parser.text = &text;
+ parser.passthrough = &passthrough;
+ parser.error = &error;
+
+ GMarkupParseContext *context = g_markup_parse_context_new(
+ &parser, G_MARKUP_TREAT_CDATA_AS_TEXT,
+ &parse_data, /*GDestroyNotify:*/ NULL);
+
+ FILE* fin = fopen(filename, "r");
+ if (fin != NULL)
+ {
+ size_t read_bytes;
+ char buff[1024];
+ while ((read_bytes = fread(buff, 1, 1024, fin)) != 0)
+ {
+ g_markup_parse_context_parse(context, buff, read_bytes, NULL);
+ }
+ fclose(fin);
+ }
+
+ g_markup_parse_context_free(context);
+
+ free(parse_data.attribute_lang); /* just in case */
+}
diff --git a/src/report-newt/report-newt.c b/src/report-newt/report-newt.c
index 8532e82..44d30bd 100644
--- a/src/report-newt/report-newt.c
+++ b/src/report-newt/report-newt.c
@@ -60,8 +60,8 @@ static int select_reporters(GArray *reporters)
{
struct reporter *r = &g_array_index(reporters, struct reporter, i);
- checkboxes[i] = newtCheckbox(20, i + 1, r->config && r->config->screen_name ?
- r->config->screen_name : r->name, 0, NULL, NULL);
+ checkboxes[i] = newtCheckbox(20, i + 1, r->config && ec_get_screen_name(r->config) ?
+ ec_get_screen_name(r->config) : r->name, 0, NULL, NULL);
newtGridSetField(cgrid, 0, i, NEWT_GRID_COMPONENT, checkboxes[i], 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
}
@@ -104,8 +104,8 @@ static int configure_reporter(struct reporter *r, bool skip_if_valid)
while ((error_table = validate_event(r->name)) ||
(!skip_if_valid && first && r->config))
{
- text = newtTextboxReflowed(0, 0, r->config->screen_name ?
- r->config->screen_name : r->name, 35, 5, 5, 0);
+ text = newtTextboxReflowed(0, 0, ec_get_screen_name(r->config) ?
+ xstrdup(ec_get_screen_name(r->config)) : r->name, 35, 5, 5, 0);
num_opts = g_list_length(r->config->options);
options = xmalloc(sizeof (newtComponent) * num_opts);
diff --git a/src/workflows/Makefile.am b/src/workflows/Makefile.am
new file mode 100644
index 0000000..28dc024
--- /dev/null
+++ b/src/workflows/Makefile.am
@@ -0,0 +1,10 @@
+workflowsdir = $(WORKFLOWS_DIR)
+
+dist_workflows_DATA = \
+ report_Fedora.xml \
+ report_fedora.conf
+
+@INTLTOOL_XML_RULE@
+
+EXTRA_DIST = \
+ report_Fedora.xml.in
diff --git a/src/workflows/report_Fedora.xml.in b/src/workflows/report_Fedora.xml.in
new file mode 100644
index 0000000..f9df177
--- /dev/null
+++ b/src/workflows/report_Fedora.xml.in
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<workflow>
+ <_name>Report to Fedora</_name>
+ <_description>Process the report using the Fedora infrastructure</_description>
+
+ <events>
+ <event>report_uReport</event>
+ <event>collect_*</event>
+ <event>analyze_CCpp</event>
+ <event>report_Bugzilla</event>
+ <event>post_report</event>
+ </events>
+</workflow>
diff --git a/src/workflows/report_fedora.conf b/src/workflows/report_fedora.conf
new file mode 100644
index 0000000..9dd86ce
--- /dev/null
+++ b/src/workflows/report_fedora.conf
@@ -0,0 +1,3 @@
+EVENT=report_Fedora analyzer=CCpp
+# this is just a meta event which consists of other events
+# the list is defined in the xml file
--
1.8.0
11 years, 5 months
[Automatic Bug Reporting Tool - ABRT] #838: don't delete the xorg reports in postcreate, just mark it as not_reportable
by fedora-badges
#838: don't delete the xorg reports in postcreate, just mark it as not_reportable
-----------------------+------------------
Reporter: jmoskovc | Owner: vda
Type: defect | Status: new
Priority: major | Milestone:
Component: libreport | Version:
Keywords: Nov2012 | Blocked By:
Blocking: |
-----------------------+------------------
- the decision if the xorg crash is not_reportable should be in the C code
not in the event configuration for the following reasons:
1. it's not translatable
2. it's not configurable
- there should be a config file with "BlacklistedModules=nvidia,fglrx,
..." which is checked either against the /proc/modules or against the
output of lsmod
3. having the code in the conf files makes the updates to fail (rpm
detects teh local changes in conf files and refuses to update it)
--
Ticket URL: <https://fedorahosted.org/abrt/ticket/838>
Automatic Bug Reporting Tool - ABRT <http://fedorahoted.org/abrt/>
Automatic bug reporting tool
11 years, 5 months