From 3f3655980007d39e0377e76a49fd2937f43f0be7 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak 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), _("Not submitted reports")); + + /* 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), _("Submitted reports")); + + + /* 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