[evolution/webkit: 52/124] Add buttons for reordering headers in the Print dialog



commit ea976384b9bafeef4cc2bd98b3bc2d2982d938e5
Author: Dan VrÃtil <dvratil redhat com>
Date:   Thu Nov 24 10:42:19 2011 +0100

    Add buttons for reordering headers in the Print dialog

 mail/e-mail-printer.c |  353 ++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 288 insertions(+), 65 deletions(-)
---
diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c
index 4613b70..3fccca6 100644
--- a/mail/e-mail-printer.c
+++ b/mail/e-mail-printer.c
@@ -31,13 +31,27 @@
 
 static gpointer parent_class = NULL;
 
+enum {
+        BUTTON_SELECT_ALL,
+        BUTTON_SELECT_NONE,
+        BUTTON_TOP,
+        BUTTON_UP,
+        BUTTON_DOWN,
+        BUTTON_BOTTOM,
+        BUTTONS_COUNT
+};
+
 struct _EMailPrinterPrivate {
 	EMFormatHTMLPrint *efhp;
 
 	GtkListStore *headers;
-	GtkTreeModel *sortable_headers;
 	
 	WebKitWebView *webview; /* WebView to print from */
+	gchar *uri;
+        GtkWidget *buttons[BUTTONS_COUNT];
+        GtkWidget *treeview;
+
+        GtkPrintOperation *operation;
 };
 
 G_DEFINE_TYPE (
@@ -60,7 +74,6 @@ enum {
 	COLUMN_HEADER_NAME,
 	COLUMN_HEADER_VALUE,
 	COLUMN_HEADER_STRUCT,
-	COLUMN_HEADER_SORT,
 	LAST_COLUMN
 };
 
@@ -128,16 +141,14 @@ emp_printing_done (GtkPrintOperation *operation,
 	g_signal_emit (emp, signals[SIGNAL_DONE], 0, operation, result);
 }
 
-
 static void
-emp_run_print_operation (EMailPrinter *emp,
-		      	 GtkPrintOperation *operation)
+emp_run_print_operation (EMailPrinter *emp)
 {
 	EMFormat *emf;
 	SoupSession *session;
 	GHashTable *formatters;
 	WebKitWebFrame *frame;
-	gchar *mail_uri, *tmp;
+	gchar *mail_uri;
 
 	emf = EM_FORMAT (emp->priv->efhp);
 	mail_uri = em_format_build_mail_uri (emf->folder, emf->message_uid, NULL, NULL);
@@ -150,24 +161,24 @@ emp_run_print_operation (EMailPrinter *emp,
 	g_hash_table_insert (formatters, g_strdup (mail_uri), emp->priv->efhp);
 
 	/* Print_layout is a special PURI created by EMFormatHTMLPrint */
-	tmp = g_strconcat (mail_uri, "?part_id=print_layout", NULL);
-	if (emp->priv->webview == NULL) {
+        if (emp->priv->uri)
+                g_free (emp->priv->uri);
+        emp->priv->uri = g_strconcat (mail_uri, "?part_id=print_layout", NULL);
+
+        if (emp->priv->webview == NULL) {
 		emp->priv->webview = WEBKIT_WEB_VIEW (webkit_web_view_new ());
 		g_object_ref_sink (emp->priv->webview);
 	}
 
-	webkit_web_view_load_uri (emp->priv->webview, tmp);
-
 	frame = webkit_web_view_get_main_frame (emp->priv->webview);
 
 	if (em_format_html_print_get_action (emp->priv->efhp) == GTK_PRINT_OPERATION_ACTION_EXPORT) {
-		gtk_print_operation_set_export_filename (operation, emp->priv->efhp->export_filename);
-		webkit_web_frame_print_full (frame, operation, GTK_PRINT_OPERATION_ACTION_EXPORT, NULL);
+		gtk_print_operation_set_export_filename (emp->priv->operation, emp->priv->efhp->export_filename);
+		webkit_web_frame_print_full (frame, emp->priv->operation, GTK_PRINT_OPERATION_ACTION_EXPORT, NULL);
 	} else {
-		webkit_web_frame_print_full (frame, operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL);
+		webkit_web_frame_print_full (frame, emp->priv->operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL);
 	}
 
-	g_free (tmp);
 	g_free (mail_uri);
 }
 
@@ -178,15 +189,12 @@ header_active_renderer_toggled_cb (GtkCellRendererToggle *renderer,
 				   EMailPrinter *emp)
 {
 	EMFormat *emf = (EMFormat *)emp->priv->efhp;
-	GtkTreeIter sorted_iter, iter;
+	GtkTreeIter iter;
 	gboolean active;
 	EMFormatHeader *header;
 
-	gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (emp->priv->sortable_headers),
-		&sorted_iter, path);
-	gtk_tree_model_sort_convert_iter_to_child_iter (
-		GTK_TREE_MODEL_SORT (emp->priv->sortable_headers),
-		&iter, &sorted_iter);
+	gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (emp->priv->headers),
+		&iter, path);
 
 	gtk_tree_model_get (GTK_TREE_MODEL (emp->priv->headers), &iter,
 		COLUMN_ACTIVE, &active, -1);
@@ -198,34 +206,202 @@ header_active_renderer_toggled_cb (GtkCellRendererToggle *renderer,
 	/* If the new state is active */
 	if ((!active) == TRUE) {
 		em_format_add_header_struct (emf, header);
-
-		gtk_list_store_set (GTK_LIST_STORE (emp->priv->headers), &iter,
-			COLUMN_HEADER_SORT, g_queue_index (&emf->header_list, header), -1);
 	} else {
 		em_format_remove_header_struct (emf, header);
 	}
 }
 
+static void
+emp_headers_tab_toggle_selection (GtkWidget *button,
+                                  gpointer user_data)
+{
+        EMailPrinter *emp = user_data;
+        EMFormat *emf = (EMFormat *) emp->priv->efhp;
+        GtkTreeIter iter;
+        gboolean select;
+
+        if (button == emp->priv->buttons[BUTTON_SELECT_ALL])
+                select = TRUE;
+        else if (button == emp->priv->buttons[BUTTON_SELECT_NONE])
+                select = FALSE;
+        else
+                return;
+
+        if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (emp->priv->headers), &iter))
+                return;
+
+        do {
+                EMFormatHeader *header;
+
+                gtk_tree_model_get (GTK_TREE_MODEL (emp->priv->headers), &iter,
+                        COLUMN_HEADER_STRUCT, &header, -1);
+                gtk_list_store_set (GTK_LIST_STORE (emp->priv->headers), &iter, 
+                        COLUMN_ACTIVE, select, -1);
+
+                if (select)
+                        em_format_add_header_struct (emf, header);
+                else
+                        em_format_remove_header_struct (emf, header);
+
+        } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (emp->priv->headers), &iter));
+}
+
+static void
+emp_headers_tab_selection_changed (GtkTreeSelection *selection,
+                                   gpointer user_data)
+{
+        EMailPrinter *emp = user_data;
+        gboolean enabled;
+        GList *selected_rows;
+        GtkTreeIter iter;
+        GtkTreeModel *model;
+        GtkTreePath *path;
+
+        if (gtk_tree_selection_count_selected_rows (selection) == 0) {
+                gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_TOP], FALSE);
+                gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_UP], FALSE);
+                gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_DOWN], FALSE);
+                gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_BOTTOM], FALSE);
+
+                return;
+        }
+
+        model = GTK_TREE_MODEL (emp->priv->headers);
+        selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+        path = gtk_tree_path_copy (selected_rows->data);
+        enabled = gtk_tree_path_prev (path);
+        gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_TOP], enabled);
+        gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_UP], enabled);
+
+        gtk_tree_model_get_iter (model, &iter, g_list_last (selected_rows)->data);
+        enabled = gtk_tree_model_iter_next (model, &iter);
+        gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_DOWN], enabled);
+        gtk_widget_set_sensitive (emp->priv->buttons[BUTTON_BOTTOM], enabled);
+
+        g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
+        g_list_free (selected_rows);
+        gtk_tree_path_free (path);
+}
+
+static void
+emp_headers_tab_move (GtkWidget *button,
+                      gpointer user_data)
+{
+        EMailPrinter *emp = user_data;
+        GtkTreeSelection *selection;
+        GList *selected_rows, *references, *l;
+        GtkTreePath *path;
+        GtkTreeModel *model;
+        GtkTreeIter iter;
+        GtkTreeRowReference *selection_middle;
+
+        model = GTK_TREE_MODEL (emp->priv->headers);
+        selection = gtk_tree_view_get_selection  (GTK_TREE_VIEW (emp->priv->treeview));
+        selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+        l = g_list_nth (selected_rows, g_list_length (selected_rows) / 2);
+        selection_middle = gtk_tree_row_reference_new (model, l->data);
+
+        references = NULL;
+
+        if (button == emp->priv->buttons[BUTTON_TOP]) {
+
+                for (l = selected_rows; l; l = l->next) {
+                        references = g_list_prepend (references,
+                                gtk_tree_row_reference_new (model, l->data));
+                }
+
+                for (l = references; l; l = l->next) {
+                        path = gtk_tree_row_reference_get_path (l->data);
+                        gtk_tree_model_get_iter (model, &iter, path);
+                        gtk_list_store_move_after (emp->priv->headers, &iter, NULL);
+                        gtk_tree_path_free (path);
+                }
+
+                g_list_foreach (references, (GFunc) gtk_tree_row_reference_free, NULL);
+                g_list_free (references);
+
+        } else if (button == emp->priv->buttons[BUTTON_UP]) {
+
+                GtkTreeIter iter_last;
+
+                gtk_tree_model_get_iter (model, &iter, selected_rows->data);
+                gtk_tree_model_iter_previous (model, &iter);
+
+                gtk_tree_model_get_iter (model, &iter_last,
+                        g_list_last (selected_rows)->data);
+
+                gtk_list_store_move_after (emp->priv->headers, &iter, &iter_last);
+
+        } else if (button == emp->priv->buttons[BUTTON_DOWN]) {
+
+                GtkTreeIter iter_last;
+
+                gtk_tree_model_get_iter (model, &iter, selected_rows->data);
+
+                gtk_tree_model_get_iter (model, &iter_last,
+                        g_list_last (selected_rows)->data);
+                gtk_tree_model_iter_next (model, &iter_last);
+
+                gtk_list_store_move_before (emp->priv->headers, &iter_last, &iter);
+
+        } else if (button == emp->priv->buttons[BUTTON_BOTTOM]) {
+
+                for (l = selected_rows; l; l = l->next) {
+                        references = g_list_prepend (references,
+                                gtk_tree_row_reference_new (model, l->data));
+                }
+                references = g_list_reverse (references);
+
+                for (l = references; l; l = l->next) {
+                        path = gtk_tree_row_reference_get_path (l->data);
+                        gtk_tree_model_get_iter (model, &iter, path);
+                        gtk_list_store_move_before (emp->priv->headers, &iter, NULL);
+                        gtk_tree_path_free (path);
+                }
+
+                g_list_foreach (references, (GFunc) gtk_tree_row_reference_free, NULL);
+                g_list_free (references);
+
+        };
+
+        path = gtk_tree_row_reference_get_path (selection_middle);
+        gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (emp->priv->treeview),
+                path, COLUMN_ACTIVE, TRUE, 0.5, 0.5);
+        gtk_tree_path_free (path);
+        gtk_tree_row_reference_free (selection_middle);
+
+        g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
+        g_list_free (selected_rows);
+
+        emp_headers_tab_selection_changed (selection, user_data);
+}
+
 static GtkWidget*
 emp_get_headers_tab (GtkPrintOperation *operation,
 		     EMailPrinter *emp)
 {
-	GtkWidget *box, *label, *scw;
+	GtkWidget *vbox, *hbox, *label, *scw, *button;
 	GtkTreeView *view;
+        GtkTreeSelection *selection;
 	GtkTreeViewColumn *column;
 	GtkCellRenderer *renderer;
 
-	box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
-
+        hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
+        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+        gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 5);
+/*
 	label = gtk_label_new (_("Select headers you want to print"));
-	gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 5);
-
-	emp->priv->sortable_headers = gtk_tree_model_sort_new_with_model (
-		GTK_TREE_MODEL (emp->priv->headers));
-	gtk_tree_sortable_set_sort_column_id (
-		GTK_TREE_SORTABLE (emp->priv->sortable_headers), COLUMN_HEADER_SORT,
-		GTK_SORT_ASCENDING);
-	view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (emp->priv->sortable_headers));
+        gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 2, 1);
+*/
+	emp->priv->treeview = gtk_tree_view_new_with_model (
+                GTK_TREE_MODEL (emp->priv->headers));
+        view = GTK_TREE_VIEW (emp->priv->treeview);
+        selection = gtk_tree_view_get_selection (view);
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+        g_signal_connect (selection, "changed",
+                G_CALLBACK (emp_headers_tab_selection_changed), emp);
 
 	renderer = gtk_cell_renderer_toggle_new ();
 	g_signal_connect (renderer, "toggled",
@@ -249,11 +425,52 @@ emp_get_headers_tab (GtkPrintOperation *operation,
 
 	scw = gtk_scrolled_window_new (NULL, NULL);
 	gtk_container_add (GTK_CONTAINER (scw), GTK_WIDGET (view));
-	gtk_box_pack_start (GTK_BOX (box), scw, TRUE, TRUE, 5);
-	gtk_widget_show_all (box);
+        gtk_box_pack_start (GTK_BOX (hbox), scw, TRUE, TRUE, 0);
+
+        button = gtk_button_new_from_stock (GTK_STOCK_SELECT_ALL);
+        emp->priv->buttons[BUTTON_SELECT_ALL] = button;
+        g_signal_connect (button, "clicked",
+                G_CALLBACK (emp_headers_tab_toggle_selection), emp);
+        gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
+
+        button = gtk_button_new_with_label (_("Unselect All"));
+        emp->priv->buttons[BUTTON_SELECT_NONE] = button;
+        g_signal_connect (button, "clicked",
+                G_CALLBACK (emp_headers_tab_toggle_selection), emp);
+        gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
+
+        button = gtk_button_new_from_stock (GTK_STOCK_GOTO_TOP);
+        emp->priv->buttons[BUTTON_TOP] = button;
+        gtk_widget_set_sensitive (button, FALSE);
+        g_signal_connect (button, "clicked",
+                G_CALLBACK (emp_headers_tab_move), emp);
+        gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
+
+        button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
+        emp->priv->buttons[BUTTON_UP] = button;
+        gtk_widget_set_sensitive (button, FALSE);
+        g_signal_connect (button, "clicked",
+                G_CALLBACK (emp_headers_tab_move), emp);
+        gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
+
+        button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
+        emp->priv->buttons[BUTTON_DOWN] = button;
+        gtk_widget_set_sensitive (button, FALSE);
+        g_signal_connect (button, "clicked",
+                G_CALLBACK (emp_headers_tab_move), emp);
+        gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
+
+        button = gtk_button_new_from_stock (GTK_STOCK_GOTO_BOTTOM);
+        emp->priv->buttons[BUTTON_BOTTOM] = button;
+        gtk_widget_set_sensitive (button, FALSE);
+        g_signal_connect (button, "clicked",
+                G_CALLBACK (emp_headers_tab_move), emp);
+        gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 5);
 
 	gtk_print_operation_set_custom_tab_label (operation, _("Headers"));
-	return box;
+        gtk_widget_show_all (hbox);
+
+        return hbox;
 }
 
 static void
@@ -284,7 +501,7 @@ emp_set_formatter (EMailPrinter *emp,
 		GtkTreeIter iter;
 		GList *found_header;
 		EMFormatHeader *emfh;
-		gint index;
+		gint index = G_MAXINT;
 
 		header = &g_array_index (headers, CamelMediumHeader, i);
 		emfh = em_format_header_new (header->name, header->value);
@@ -295,17 +512,16 @@ emp_set_formatter (EMailPrinter *emp,
 		if (found_header) {
 			index = g_queue_link_index (&EM_FORMAT (formatter)->header_list, 
 				found_header);
-		} else {
-			index = G_MAXINT;
 		}
-		gtk_list_store_append (emp->priv->headers, &iter);
+
+		gtk_list_store_insert (emp->priv->headers, &iter, index);
 
 		gtk_list_store_set (emp->priv->headers, &iter,
 			COLUMN_ACTIVE, (found_header != NULL),
 			COLUMN_HEADER_NAME, emfh->name,
 			COLUMN_HEADER_VALUE, emfh->value,
-			COLUMN_HEADER_STRUCT, emfh,
-		      	COLUMN_HEADER_SORT, index, -1);
+			COLUMN_HEADER_STRUCT, emfh, -1);
+
 	}
 
 	camel_medium_free_headers (CAMEL_MEDIUM (emf->message), headers);
@@ -358,21 +574,17 @@ emp_finalize (GObject *object)
 		priv->efhp = NULL;
 	}
 
-	if (priv->sortable_headers) {
-		g_object_unref (priv->sortable_headers);
-		priv->sortable_headers = NULL;
-	}
-
 	if (priv->headers) {
 		GtkTreeIter iter;
 
-		gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->headers), &iter);
-		while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->headers), &iter)) {
-			EMFormatHeader *header = NULL;
-			gtk_tree_model_get (GTK_TREE_MODEL (priv->headers), &iter,
-				COLUMN_HEADER_STRUCT, &header, -1);
-			em_format_header_free (header);
-		}
+		if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->headers), &iter)) {
+                	do {
+		        	EMFormatHeader *header = NULL;
+			        gtk_tree_model_get (GTK_TREE_MODEL (priv->headers), &iter,
+				        COLUMN_HEADER_STRUCT, &header, -1);
+			        em_format_header_free (header);
+		        } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->headers), &iter));
+                }
 		g_object_unref (priv->headers);
 		priv->headers = NULL;
 	}
@@ -382,7 +594,17 @@ emp_finalize (GObject *object)
 		priv->webview = NULL;
 	}
 
-	/* Chain up to parent's finalize() method. */
+	if (priv->uri) {
+                g_free (priv->uri);
+                priv->uri = NULL;
+        }
+
+        if (priv->operation) {
+                g_object_unref (priv->operation);
+                priv->operation = NULL;
+        }
+
+        /* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -451,22 +673,23 @@ void
 e_mail_printer_print (EMailPrinter *emp,
 		      GCancellable *cancellable)
 {
-	GtkPrintOperation *operation;
-
 	g_return_if_fail (E_IS_MAIL_PRINTER (emp));
 
-	operation = gtk_print_operation_new ();
-	gtk_print_operation_set_show_progress (operation, TRUE);
-	g_signal_connect (operation, "create-custom-widget",
+        if (emp->priv->operation)
+                g_object_unref (emp->priv->operation);
+	emp->priv->operation = gtk_print_operation_new ();
+
+	gtk_print_operation_set_show_progress (emp->priv->operation, TRUE);
+	g_signal_connect (emp->priv->operation, "create-custom-widget",
 		G_CALLBACK (emp_get_headers_tab), emp);
-	g_signal_connect (operation, "done",
+	g_signal_connect (emp->priv->operation, "done",
 		G_CALLBACK (emp_printing_done), emp);
 	g_signal_connect_swapped (cancellable, "cancelled",
-		G_CALLBACK (gtk_print_operation_cancel), operation);
-	g_signal_connect (operation, "draw-page",
+		G_CALLBACK (gtk_print_operation_cancel), emp->priv->operation);
+	g_signal_connect (emp->priv->operation, "draw-page",
 		G_CALLBACK (emp_draw_footer), NULL);
 
-	emp_run_print_operation (emp, operation);
+	emp_run_print_operation (emp);
 }
 
 EMFormatHTMLPrint*



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]