>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] 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

