From 3f3655980007d39e0377e76a49fd2937f43f0be7 Mon Sep 17 00:00:00 2001
From: Jiri Moskovcak <jmoskovc@redhat.com>
Date: Thu, 21 Jul 2011 11:02:11 +0200
Subject: [PATCH 2/4] gui: split the main window in 2 panes -
reported/not-reported
---
src/gui-gtk/main.c | 215 ++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 182 insertions(+), 33 deletions(-)
diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c
index 1409191..776e85a 100644
--- a/src/gui-gtk/main.c
+++ b/src/gui-gtk/main.c
@@ -32,7 +32,9 @@ static const char help_uri[] = "http://docs.fedoraproject.org/en-US/"
"Fedora/14/html/Deployment_Guide/ch-abrt.html";
static GtkListStore *s_dumps_list_store;
+static GtkListStore *s_reported_dumps_list_store;
static GtkWidget *s_treeview;
+static GtkWidget *s_reported_treeview;
static GtkWidget *g_main_window;
static GtkWidget *s_report_window;
@@ -40,13 +42,38 @@ enum
{
COLUMN_SOURCE,
COLUMN_REASON,
- COLUMN_DIRNAME,
COLUMN_LATEST_CRASH_STR,
COLUMN_LATEST_CRASH,
COLUMN_DUMP_DIR,
+ COLUMN_REPORTED_TO,
NUM_COLUMNS
};
+//FIXME: maybe we can use strrchr and make this faster...
+static char *get_last_line(const char* msg)
+{
+ const char *curr_end = NULL;
+ const char *start = msg;
+ const char *end = msg;
+
+ while((curr_end = strchr(end, '\n')) != NULL)
+ {
+ end = curr_end;
+ curr_end = strchr(end+1, '\n');
+ if (curr_end == NULL || strchr(end+2, '\n') == NULL)
+ break;
+
+ start = end+1;
+ end = curr_end;
+ }
+
+ //fix the case where reported_to has only 1 line without \n
+ if (end == msg)
+ end = end + strlen(msg);
+
+ return xstrndup(start, end - start);
+}
+
static void add_directory_to_dirlist(const char *dirname)
{
/* Silently ignore *any* errors, not only EACCES.
@@ -67,21 +94,11 @@ static void add_directory_to_dirlist(const char *dirname)
{
time_t t = strtol(time_str, NULL, 10); /* atoi won't work past 2038! */
struct tm *ptm = localtime(&t);
- size_t time_len = strftime(time_buf, sizeof(time_buf)-1, "%Y-%m-%m %H:%M", ptm);
+ size_t time_len = strftime(time_buf, sizeof(time_buf)-1, "%Y-%m-%d %H:%M", ptm);
time_buf[time_len] = '\0';
}
free(time_str);
- /*
- char *msg = dd_load_text_ext(dd, FILENAME_REPORTED_TO, 0
- | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
- | DD_FAIL_QUIETLY_ENOENT
- | DD_FAIL_QUIETLY_EACCES
- );
- const char *reported = (msg ? GTK_STOCK_YES : GTK_STOCK_NO);
- free(msg);
- */
-
char *reason = dd_load_text(dd, FILENAME_REASON);
/* the source of the problem:
@@ -102,18 +119,38 @@ static void add_directory_to_dirlist(const char *dirname)
);
}
+ char *msg = dd_load_text_ext(dd, FILENAME_REPORTED_TO, 0
+ | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ | DD_FAIL_QUIETLY_ENOENT
+ | DD_FAIL_QUIETLY_EACCES
+ );
+
+
+ GtkListStore *list_store;
+
+ char *subm_status = NULL;
+ if (msg)
+ {
+ list_store = s_reported_dumps_list_store;
+ subm_status = get_last_line(msg);
+ }
+ else
+ list_store = s_dumps_list_store;
GtkTreeIter iter;
- gtk_list_store_append(s_dumps_list_store, &iter);
- gtk_list_store_set(s_dumps_list_store, &iter,
+ gtk_list_store_append(list_store, &iter);
+ gtk_list_store_set(list_store, &iter,
COLUMN_SOURCE, source,
COLUMN_REASON, reason,
- COLUMN_DIRNAME, dd->dd_dirname,
//OPTION: time format
COLUMN_LATEST_CRASH_STR, time_buf,
COLUMN_LATEST_CRASH, time,
COLUMN_DUMP_DIR, dirname,
+ COLUMN_REPORTED_TO, msg ? subm_status : NULL,
-1);
+ /* this is safe, subm_status is either null or malloced string from get_last_line */
+ free(subm_status);
+ free(msg);
free(reason);
dd_close(dd);
@@ -123,6 +160,7 @@ static void add_directory_to_dirlist(const char *dirname)
static void rescan_dirs_and_add_to_dirlist(void)
{
gtk_list_store_clear(s_dumps_list_store);
+ gtk_list_store_clear(s_reported_dumps_list_store);
scan_dirs_and_add_to_dirlist();
}
@@ -232,7 +270,7 @@ static void delete_report(GtkTreeView *treeview)
VERB1 log("Deleting '%s'", dump_dir_name);
if (delete_dump_dir_possibly_using_abrtd(dump_dir_name) == 0)
{
- gtk_list_store_remove(s_dumps_list_store, &iter);
+ gtk_list_store_remove(GTK_LIST_STORE(store), &iter);
}
else
{
@@ -262,7 +300,9 @@ static gint on_key_press_event_cb(GtkTreeView *treeview, GdkEventKey *key, gpoin
static void on_btn_delete_cb(GtkButton *button, gpointer unused)
{
+ /* delete from both treeviews */
delete_report(GTK_TREE_VIEW(s_treeview));
+ delete_report(GTK_TREE_VIEW(s_reported_treeview));
}
static void on_menu_help_cb(GtkMenuItem *menuitem, gpointer unused)
@@ -421,6 +461,50 @@ static void add_columns(GtkTreeView *treeview)
gtk_tree_view_append_column(treeview, column);
}
+static void add_columns_reported(GtkTreeView *treeview)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Source"),
+ renderer,
+ "text",
+ COLUMN_SOURCE,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_column_set_sort_column_id(column, COLUMN_SOURCE);
+ gtk_tree_view_append_column(treeview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Problem"),
+ renderer,
+ "text",
+ COLUMN_REASON,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_column_set_sort_column_id(column, COLUMN_REASON);
+ gtk_tree_view_append_column(treeview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Date Submitted"),
+ renderer,
+ "text",
+ COLUMN_LATEST_CRASH_STR,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id(column, COLUMN_LATEST_CRASH);
+ gtk_tree_view_append_column(treeview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Submision Result"),
+ renderer,
+ "text",
+ COLUMN_REPORTED_TO,
+ NULL);
+ //gtk_tree_view_column_set_sort_column_id(column, COLUMN_LATEST_CRASH);
+ gtk_tree_view_append_column(treeview, column);
+}
+
static GtkWidget *create_menu(void)
{
/* main bar */
@@ -476,40 +560,102 @@ static GtkWidget *create_main_window(void)
gtk_window_set_default_icon_name("abrt");
GtkWidget *main_vbox = gtk_vbox_new(false, 0);
+ /* add menu */
+ gtk_box_pack_start(GTK_BOX(main_vbox), create_menu(), false, false, 0);
- /* Scrolled region inside main window */
- GtkWidget *scroll_win = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_win),
+ GtkWidget *not_subm_vbox = gtk_vbox_new(false, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(not_subm_vbox), 10);
+ GtkWidget *subm_vbox = gtk_vbox_new(false, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(subm_vbox), 10);
+
+ /* Scrolled region for not reported problems inside main window*/
+ GtkWidget *new_problems_scroll_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(new_problems_scroll_win),
GTK_SHADOW_ETCHED_IN);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win),
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(new_problems_scroll_win),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
- gtk_box_pack_start(GTK_BOX(main_vbox), create_menu(), false, false, 0);
- gtk_box_pack_start(GTK_BOX(main_vbox), scroll_win, true, true, 0);
- gtk_container_add(GTK_CONTAINER(g_main_window), main_vbox);
+ GtkWidget *not_subm_lbl = gtk_label_new(_("Not submitted reports"));
+ gtk_misc_set_alignment(GTK_MISC(not_subm_lbl), 0, 0);
+ gtk_label_set_markup(GTK_LABEL(not_subm_lbl), _("<b>Not submitted reports</b>"));
+
+ /* add label for not submitted tree view */
+ gtk_box_pack_start(GTK_BOX(not_subm_vbox), not_subm_lbl, false, false, 0);
+ gtk_box_pack_start(GTK_BOX(not_subm_vbox), new_problems_scroll_win, true, true, 0);
+ gtk_box_pack_start(GTK_BOX(main_vbox), not_subm_vbox, true, true, 0);
/* Tree view inside scrolled region */
s_treeview = gtk_tree_view_new();
g_object_set(s_treeview, "rules-hint", 1, NULL); /* use alternating colors */
add_columns(GTK_TREE_VIEW(s_treeview));
- gtk_container_add(GTK_CONTAINER(scroll_win), s_treeview);
+ gtk_container_add(GTK_CONTAINER(new_problems_scroll_win), s_treeview);
/* Create data store for the list and attach it */
- s_dumps_list_store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING, /* source */
+ s_dumps_list_store = gtk_list_store_new(NUM_COLUMNS,
+ G_TYPE_STRING, /* source */
+ G_TYPE_STRING, /* executable */
+ G_TYPE_STRING, /* time */
+ G_TYPE_INT, /* unix time - used for sort */
+ G_TYPE_STRING, /* dump dir path */
+ G_TYPE_STRING); /* reported_to */
+
+
+ //FIXME: configurable!!
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_dumps_list_store),
+ COLUMN_LATEST_CRASH,
+ GTK_SORT_DESCENDING);
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(s_treeview), GTK_TREE_MODEL(s_dumps_list_store));
+
+ /* Double click/Enter handler */
+ g_signal_connect(s_treeview, "row-activated", G_CALLBACK(on_row_activated_cb), NULL);
+ /* Delete handler */
+ g_signal_connect(s_treeview, "key-press-event", G_CALLBACK(on_key_press_event_cb), NULL);
+
+ /* scrolled region for reported problems */
+ GtkWidget *reported_problems_scroll_win = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(reported_problems_scroll_win),
+ GTK_SHADOW_ETCHED_IN);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(reported_problems_scroll_win),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ GtkWidget *subm_lbl = gtk_label_new(_("Submitted reports"));
+ /* align to left */
+ gtk_misc_set_alignment(GTK_MISC(subm_lbl), 0, 0);
+ gtk_label_set_markup(GTK_LABEL(subm_lbl), _("<b>Submitted reports</b>"));
+
+
+ /* add label for submitted tree view */
+ gtk_box_pack_start(GTK_BOX(subm_vbox), subm_lbl, false, false, 0);
+ gtk_box_pack_start(GTK_BOX(subm_vbox), reported_problems_scroll_win, true, true, 0);
+ gtk_box_pack_start(GTK_BOX(main_vbox), subm_vbox, true, true, 0);
+
+ /* Tree view inside scrolled region */
+ s_reported_treeview = gtk_tree_view_new();
+ g_object_set(s_reported_treeview, "rules-hint", 1, NULL); /* use alternating colors */
+ add_columns_reported(GTK_TREE_VIEW(s_reported_treeview));
+ gtk_container_add(GTK_CONTAINER(reported_problems_scroll_win), s_reported_treeview);
+
+ /* Create data store for the list and attach it */
+ s_reported_dumps_list_store = gtk_list_store_new(NUM_COLUMNS,
+ G_TYPE_STRING, /* source */
G_TYPE_STRING, /* executable */
- G_TYPE_STRING, /* hostname */
G_TYPE_STRING, /* time */
G_TYPE_INT, /* unix time - used for sort */
G_TYPE_STRING, /* dump dir path */
- G_TYPE_STRING);/* row background */
+ G_TYPE_STRING); /* reported_to */
+
//FIXME: configurable!!
- gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_dumps_list_store),
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(s_reported_dumps_list_store),
COLUMN_LATEST_CRASH,
GTK_SORT_DESCENDING);
- gtk_tree_view_set_model(GTK_TREE_VIEW(s_treeview), GTK_TREE_MODEL(s_dumps_list_store));
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(s_reported_treeview), GTK_TREE_MODEL(s_reported_dumps_list_store));
+
/* buttons are homogenous so set size only for one button and it will
* work for the rest buttons in same gtk_hbox_new() */
@@ -518,20 +664,23 @@ static GtkWidget *create_main_window(void)
GtkWidget *btn_delete = gtk_button_new_from_stock(GTK_STOCK_DELETE);
- GtkWidget *hbox_report_delete = gtk_hbox_new(true, 4);
+ GtkWidget *hbox_report_delete = gtk_hbox_new(true, 0);
gtk_box_pack_start(GTK_BOX(hbox_report_delete), btn_delete, true, true, 0);
- gtk_box_pack_start(GTK_BOX(hbox_report_delete), btn_report, true, true, 0);
+ gtk_box_pack_start(GTK_BOX(hbox_report_delete), btn_report, true, true, 10);
GtkWidget *halign = gtk_alignment_new(1, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), hbox_report_delete);
gtk_box_pack_start(GTK_BOX(main_vbox), halign, false, false, 10);
+ /* put the main_vbox to main window */
+ gtk_container_add(GTK_CONTAINER(g_main_window), main_vbox);
+
/* Double click/Enter handler */
- g_signal_connect(s_treeview, "row-activated", G_CALLBACK(on_row_activated_cb), NULL);
+ g_signal_connect(s_reported_treeview, "row-activated", G_CALLBACK(on_row_activated_cb), NULL);
g_signal_connect(btn_report, "clicked", G_CALLBACK(on_btn_report_cb), NULL);
/* Delete handler */
- g_signal_connect(s_treeview, "key-press-event", G_CALLBACK(on_key_press_event_cb), NULL);
+ g_signal_connect(s_reported_treeview, "key-press-event", G_CALLBACK(on_key_press_event_cb), NULL);
g_signal_connect(btn_delete, "clicked", G_CALLBACK(on_btn_delete_cb), NULL);
/* Quit when user closes the main window */
g_signal_connect(g_main_window, "destroy", gtk_main_quit, NULL);
--
1.7.6