Support individual files and folders in log output.
[anjuta-git-plugin.git] / plugins / git / git-log-dialog.c
blob658d15d259a47257a8db6c877db56467d6c05bd8
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta
4 * Copyright (C) James Liggett 2007 <jrliggett@cox.net>
5 *
6 * anjuta is free software.
7 *
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
13 * anjuta is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with anjuta. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
25 #include "git-log-dialog.h"
27 enum
29 COL_REVISION,
31 NUM_COLS
34 typedef struct
36 Git *plugin;
37 GladeXML *gxml;
38 GtkListStore *list_store;
39 GtkCellRenderer *graph_renderer;
40 gchar *path;
41 GHashTable *refs;
42 GHashTable *filters;
43 } LogData;
45 static void
46 author_cell_function (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
47 GtkTreeModel *model, GtkTreeIter *iter,
48 gpointer user_data)
50 GitRevision *revision;
51 gchar *author;
53 gtk_tree_model_get (model, iter, COL_REVISION, &revision, -1);
54 author = git_revision_get_author (revision);
56 g_object_unref (revision);
58 g_object_set (renderer, "text", author, NULL);
60 g_free (author);
63 static void
64 date_cell_function (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
65 GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
67 GitRevision *revision;
68 gchar *date;
70 gtk_tree_model_get (model, iter, COL_REVISION, &revision, -1);
71 date = git_revision_get_formatted_date (revision);
73 g_object_unref (revision);
75 g_object_set (renderer, "text", date, NULL);
77 g_free (date);
80 static void
81 short_log_cell_function (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
82 GtkTreeModel *model, GtkTreeIter *iter,
83 gpointer user_data)
85 GitRevision *revision;
86 gchar *short_log;
88 gtk_tree_model_get (model, iter, COL_REVISION, &revision, -1);
89 short_log = git_revision_get_short_log (revision);
91 g_object_unref (revision);
93 g_object_set (renderer, "text", short_log, NULL);
95 g_free (short_log);
98 static void
99 ref_icon_cell_function (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
100 GtkTreeModel *model, GtkTreeIter *iter,
101 LogData *data)
103 GitRevision *revision;
104 gchar *sha;
106 gtk_tree_model_get (model, iter, COL_REVISION, &revision, -1);
107 sha = git_revision_get_sha (revision);
109 g_object_unref (revision);
111 if (g_hash_table_lookup_extended (data->refs, sha, NULL, NULL))
112 g_object_set (renderer, "stock-id", GTK_STOCK_INFO, NULL);
113 else
114 g_object_set (renderer, "stock-id", "", NULL);
116 g_free (sha);
119 static void
120 create_columns (LogData *data)
122 GtkWidget *log_changes_view;
123 gint font_size;
124 GtkTreeViewColumn *column;
125 GtkCellRenderer *renderer;
127 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
128 font_size = PANGO_PIXELS (pango_font_description_get_size (GTK_WIDGET (log_changes_view)->style->font_desc));
130 /* Ref info */
131 column = gtk_tree_view_column_new ();
132 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
133 renderer = gtk_cell_renderer_pixbuf_new ();
134 gtk_tree_view_column_pack_start (column, renderer, TRUE);
135 gtk_tree_view_column_set_cell_data_func (column, renderer,
136 (GtkTreeCellDataFunc) ref_icon_cell_function,
137 data, NULL);
141 /* Graph */
142 column = gtk_tree_view_column_new ();
143 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
144 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
145 gtk_tree_view_column_set_min_width (column, font_size * 10);
146 gtk_tree_view_column_set_resizable (column, TRUE);
147 gtk_tree_view_column_pack_start (column, data->graph_renderer, TRUE);
148 gtk_tree_view_column_add_attribute (column, data->graph_renderer,
149 "revision", COL_REVISION);
150 gtk_tree_view_column_set_title (column, "Graph");
152 /* Short log */
153 column = gtk_tree_view_column_new ();
154 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
155 renderer = gtk_cell_renderer_text_new ();
156 g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
157 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
158 gtk_tree_view_column_set_min_width (column, font_size * 10);
159 gtk_tree_view_column_set_resizable (column, TRUE);
160 gtk_tree_view_column_set_expand (column, TRUE);
161 gtk_tree_view_column_pack_start (column, renderer, TRUE);
162 gtk_tree_view_column_set_cell_data_func (column, renderer,
163 (GtkTreeCellDataFunc) short_log_cell_function,
164 NULL, NULL);
165 gtk_tree_view_column_set_title (column, "Short log");
167 /* Author */
168 column = gtk_tree_view_column_new ();
169 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
170 renderer = gtk_cell_renderer_text_new ();
171 gtk_tree_view_column_set_resizable (column, TRUE);
172 gtk_tree_view_column_pack_start (column, renderer, TRUE);
173 gtk_tree_view_column_set_cell_data_func (column, renderer,
174 (GtkTreeCellDataFunc) author_cell_function,
175 NULL, NULL);
176 gtk_tree_view_column_set_title (column, "Author");
178 /* Date */
179 column = gtk_tree_view_column_new ();
180 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
181 renderer = gtk_cell_renderer_text_new ();
182 gtk_tree_view_column_set_resizable (column, TRUE);
183 gtk_tree_view_column_pack_start (column, renderer, TRUE);
184 gtk_tree_view_column_set_cell_data_func (column, renderer,
185 (GtkTreeCellDataFunc) date_cell_function,
186 NULL, NULL);
187 gtk_tree_view_column_set_title (column, "Date");
189 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view),
190 GTK_TREE_MODEL (data->list_store));
191 g_object_unref (data->list_store);
195 static void
196 on_log_command_finished (AnjutaCommand *command, guint return_code,
197 LogData *data)
199 GtkWidget *log_changes_view;
200 GQueue *queue;
201 GtkTreeIter iter;
202 GitRevision *revision;
204 if (return_code != 0)
206 git_report_errors (command, return_code);
207 g_object_unref (command);
209 return;
212 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
214 g_object_ref (data->list_store);
215 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view), NULL);
217 queue = git_log_command_get_output_queue (GIT_LOG_COMMAND (command));
219 while (g_queue_peek_head (queue))
221 revision = g_queue_pop_head (queue);
223 gtk_list_store_append (data->list_store, &iter);
224 gtk_list_store_set (data->list_store, &iter, COL_REVISION, revision, -1);
225 g_object_unref (revision);
228 giggle_graph_renderer_validate_model (GIGGLE_GRAPH_RENDERER (data->graph_renderer),
229 GTK_TREE_MODEL (data->list_store),
230 COL_REVISION);
231 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view),
232 GTK_TREE_MODEL (data->list_store));
233 g_object_unref (data->list_store);
235 g_object_unref (command);
238 static void
239 on_ref_command_finished (AnjutaCommand *command, guint return_code,
240 LogData *data)
242 gchar *path;
243 const gchar *relative_path;
244 GtkWidget *log_changes_view;
245 GtkTreeViewColumn *graph_column;
246 gchar *author;
247 gchar *grep;
248 gchar *since_date;
249 gchar *until_date;
250 gchar *since_commit;
251 gchar *until_commit;
252 GitLogCommand *log_command;
253 gint pulse_timer_id;
255 path = g_object_get_data (G_OBJECT (command), "path");
256 relative_path = NULL;
258 if (return_code != 0)
260 git_report_errors (command, return_code);
261 g_object_unref (command);
263 return;
266 if (path)
268 relative_path = git_get_relative_path (path,
269 data->plugin->project_root_directory);
272 /* If the user is using any filters or getting the log of an individual,
273 * file or folder, hide the graph column, because we can't be assured that
274 * the graph will be correct in these cases */
275 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
276 graph_column = gtk_tree_view_get_column (GTK_TREE_VIEW (log_changes_view),
279 if (g_hash_table_size (data->filters) > 0 || path)
280 gtk_tree_view_column_set_visible (graph_column, FALSE);
281 else
282 gtk_tree_view_column_set_visible (graph_column, TRUE);
284 /* Get the filter data */
285 author = g_hash_table_lookup (data->filters, "author");
286 grep = g_hash_table_lookup (data->filters, "grep");
287 since_date = g_hash_table_lookup (data->filters, "since-date");
288 until_date = g_hash_table_lookup (data->filters, "until-date");
289 since_commit = g_hash_table_lookup (data->filters, "since-commit");
290 until_commit = g_hash_table_lookup (data->filters, "until-commit");
292 if (data->refs)
293 g_hash_table_unref (data->refs);
295 data->refs = git_ref_command_get_refs (GIT_REF_COMMAND (command));
296 log_command = git_log_command_new (data->plugin->project_root_directory,
297 relative_path,
298 author, grep, since_date, until_date,
299 since_commit, until_commit);
301 gtk_list_store_clear (data->list_store);
303 pulse_timer_id = git_status_bar_progress_pulse (data->plugin,
304 _("Git: Retrieving"
305 " log..."));
307 g_signal_connect (G_OBJECT (log_command), "command-finished",
308 G_CALLBACK (git_stop_status_bar_progress_pulse),
309 GUINT_TO_POINTER (pulse_timer_id));
311 g_signal_connect (G_OBJECT (log_command), "command-finished",
312 G_CALLBACK (on_log_command_finished),
313 data);
315 anjuta_command_start (ANJUTA_COMMAND (log_command));
317 g_object_unref (command);
320 static void
321 on_log_view_button_clicked (GtkButton *button, LogData *data)
323 gchar *path;
324 GtkWidget *log_window;
325 GtkWidget *log_whole_project_check;
326 GtkWidget *log_path_entry;
327 GitRefCommand *ref_command;
329 path = NULL;
331 log_whole_project_check = glade_xml_get_widget (data->gxml,
332 "log_whole_project_check");
334 if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (log_whole_project_check)))
336 log_window = glade_xml_get_widget (data->gxml, "log_window");
337 log_path_entry = glade_xml_get_widget (data->gxml, "log_path_entry");
338 path = gtk_editable_get_chars (GTK_EDITABLE (log_path_entry), 0, -1);
340 if (!git_check_input (log_window, log_path_entry, path,
341 _("Please enter a path.")))
343 g_free (path);
344 return;
348 ref_command = git_ref_command_new (data->plugin->project_root_directory);
350 g_signal_connect (G_OBJECT (ref_command), "command-finished",
351 G_CALLBACK (on_ref_command_finished),
352 data);
355 /* Attach path to this command so it can be passed to the log command. */
356 g_object_set_data_full (G_OBJECT (ref_command), "path",
357 g_strdup (path), g_free);
359 g_free (path);
361 anjuta_command_start (ANJUTA_COMMAND (ref_command));
364 static void
365 on_log_vbox_destroy (GtkObject *log_vbox, LogData *data)
367 g_free (data->path);
368 g_object_unref (data->gxml);
370 if (data->refs)
371 g_hash_table_unref (data->refs);
373 g_hash_table_destroy (data->filters);
375 g_free (data);
378 static void
379 on_log_message_command_finished (AnjutaCommand *command, guint return_code,
380 LogData *data)
382 GtkWidget *log_text_view;
383 GtkTextBuffer *buffer;
384 gchar *log_message;
386 log_text_view = glade_xml_get_widget (data->gxml, "log_text_view");
387 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_text_view));
388 log_message = git_log_message_command_get_message (GIT_LOG_MESSAGE_COMMAND (command));
390 gtk_text_buffer_set_text (buffer, log_message, strlen (log_message));
392 g_free (log_message);
393 g_object_unref (command);
396 static gboolean
397 on_log_changes_view_row_selected (GtkTreeSelection *selection,
398 GtkTreeModel *model,
399 GtkTreePath *path,
400 gboolean path_currently_selected,
401 LogData *data)
403 GtkTreeIter iter;
404 GitRevision *revision;
405 gchar *sha;
406 GitLogMessageCommand *log_message_command;
408 if (!path_currently_selected)
410 gtk_tree_model_get_iter (model, &iter, path);
411 gtk_tree_model_get (model, &iter, COL_REVISION, &revision, -1);
412 sha = git_revision_get_sha (revision);
414 log_message_command = git_log_message_command_new (data->plugin->project_root_directory,
415 sha);
417 g_free (sha);
418 g_object_unref (revision);
420 g_signal_connect (G_OBJECT (log_message_command), "command-finished",
421 G_CALLBACK (on_log_message_command_finished),
422 data);
424 anjuta_command_start (ANJUTA_COMMAND (log_message_command));
427 return TRUE;
430 static gboolean
431 on_log_changes_view_query_tooltip (GtkWidget *log_changes_view, gint x, gint y,
432 gboolean keyboard_mode, GtkTooltip *tooltip,
433 LogData *data)
435 gboolean ret;
436 GtkTreeViewColumn *ref_column;
437 gint bin_x;
438 gint bin_y;
439 GtkTreeViewColumn *current_column;
440 GtkTreePath *path;
441 GtkTreeModel *model;
442 GtkTreeIter iter;
443 GitRevision *revision;
444 gchar *sha;
445 GList *ref_list;
446 GList *current_ref;
447 GString *tooltip_string;
448 gchar *ref_name;
449 GitRefType ref_type;
451 ret = FALSE;
453 ref_column = gtk_tree_view_get_column (GTK_TREE_VIEW (log_changes_view), 0);
455 gtk_tree_view_convert_widget_to_bin_window_coords (GTK_TREE_VIEW (log_changes_view),
456 x, y, &bin_x, &bin_y);
457 gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (log_changes_view), bin_x,
458 bin_y, &path, &current_column, NULL, NULL);
460 /* We need to be in the ref icon column */
461 if (current_column == ref_column)
463 model = gtk_tree_view_get_model (GTK_TREE_VIEW (log_changes_view));
464 gtk_tree_model_get_iter (model, &iter, path);
466 gtk_tree_model_get (model, &iter, COL_REVISION, &revision, -1);
467 sha = git_revision_get_sha (revision);
469 g_object_unref (revision);
471 ref_list = g_hash_table_lookup (data->refs, sha);
472 g_free (sha);
474 if (ref_list)
476 current_ref = ref_list;
477 tooltip_string = g_string_new ("");
479 while (current_ref)
481 ref_name = git_ref_get_name (GIT_REF (current_ref->data));
482 ref_type = git_ref_get_ref_type (GIT_REF (current_ref->data));
484 if (tooltip_string->len > 0)
485 g_string_append (tooltip_string, "\n");
487 switch (ref_type)
489 case GIT_REF_TYPE_BRANCH:
490 g_string_append_printf (tooltip_string,
491 _("<b>Branch:</b> %s"),
492 ref_name);
493 break;
494 case GIT_REF_TYPE_TAG:
495 g_string_append_printf (tooltip_string,
496 _("<b>Tag:</b> %s"),
497 ref_name);
498 break;
499 case GIT_REF_TYPE_REMOTE:
500 g_string_append_printf (tooltip_string,
501 _("<b>Remote:</b> %s"),
502 ref_name);
503 break;
504 default:
505 break;
508 g_free (ref_name);
509 current_ref = g_list_next (current_ref);
512 gtk_tooltip_set_markup (tooltip, tooltip_string->str);
513 g_string_free (tooltip_string, TRUE);
515 ret = TRUE;
519 gtk_tree_path_free (path);
520 return ret;
525 static gboolean
526 on_log_changes_view_button_press_event (GtkWidget *log_changes_view,
527 GdkEventButton *event,
528 Git *plugin)
530 GtkTreeSelection *selection;
532 if (event->type == GDK_BUTTON_PRESS)
534 if (event->button == 3)
536 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view));
538 if (gtk_tree_selection_count_selected_rows (selection) > 0)
540 gtk_menu_popup (GTK_MENU(plugin->log_popup_menu), NULL, NULL,
541 NULL, NULL, event->button, event->time);
545 return FALSE;
548 static void
549 on_log_filter_entry_changed (GtkEditable *editable, LogData *data)
551 gchar *filter_name;
552 gchar *text;
554 filter_name = g_object_get_data (G_OBJECT (editable), "filter-name");
555 text = gtk_editable_get_chars (editable, 0, -1);
557 if (strlen (text) > 0)
558 g_hash_table_insert (data->filters, filter_name, g_strdup (text));
559 else
560 g_hash_table_remove (data->filters, filter_name);
562 g_free (text);
565 static void
566 on_log_filter_date_changed (GtkCalendar *calendar, LogData *data)
568 gchar *filter_name;
569 guint year;
570 guint month;
571 guint day;
572 gchar *date;
574 filter_name = g_object_get_data (G_OBJECT (calendar), "filter-name");
576 gtk_calendar_get_date (calendar, &year, &month, &day);
577 date = g_strdup_printf ("%i-%02i-%02i", year, (month + 1), day);
578 g_hash_table_insert (data->filters, filter_name, g_strdup (date));
580 g_free (date);
583 static void
584 on_log_filter_date_check_toggled (GtkToggleButton *toggle_button, LogData *data)
586 GtkCalendar *calendar;
587 gchar *filter_name;
589 calendar = g_object_get_data (G_OBJECT (toggle_button), "calendar");
591 if (gtk_toggle_button_get_active (toggle_button))
593 gtk_widget_set_sensitive (GTK_WIDGET (calendar), TRUE);
595 /* Treat the currently selected date as a date to filter on */
596 on_log_filter_date_changed (calendar, data);
598 else
600 filter_name = g_object_get_data (G_OBJECT (calendar), "filter-name");
602 gtk_widget_set_sensitive (GTK_WIDGET (calendar), FALSE);
603 g_hash_table_remove (data->filters, filter_name);
607 static void
608 on_log_filter_clear_button_clicked (GtkButton *button, LogData *data)
610 GtkWidget *log_filter_author_entry;
611 GtkWidget *log_filter_grep_entry;
612 GtkWidget *log_filter_from_check;
613 GtkWidget *log_filter_to_check;
614 GtkWidget *log_filter_from_entry;
615 GtkWidget *log_filter_to_entry;
617 log_filter_author_entry = glade_xml_get_widget (data->gxml,
618 "log_filter_author_entry");
619 log_filter_grep_entry = glade_xml_get_widget (data->gxml,
620 "log_filter_grep_entry");
621 log_filter_from_check = glade_xml_get_widget (data->gxml,
622 "log_filter_from_check");
623 log_filter_to_check = glade_xml_get_widget (data->gxml,
624 "log_filter_to_check");
625 log_filter_from_entry = glade_xml_get_widget (data->gxml,
626 "log_filter_from_entry");
627 log_filter_to_entry = glade_xml_get_widget (data->gxml,
628 "log_filter_to_entry");
630 gtk_entry_set_text (GTK_ENTRY (log_filter_author_entry), "");
631 gtk_entry_set_text (GTK_ENTRY (log_filter_grep_entry), "");
632 gtk_entry_set_text (GTK_ENTRY (log_filter_from_entry), "");
633 gtk_entry_set_text (GTK_ENTRY (log_filter_from_entry), "");
634 gtk_entry_set_text (GTK_ENTRY (log_filter_to_entry), "");
636 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_filter_from_check),
637 FALSE);
638 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_filter_to_check),
639 FALSE);
643 static void
644 setup_filters (LogData *data)
646 GtkWidget *log_filter_author_entry;
647 GtkWidget *log_filter_grep_entry;
648 GtkWidget *log_filter_from_check;
649 GtkWidget *log_filter_to_check;
650 GtkWidget *log_filter_from_calendar;
651 GtkWidget *log_filter_to_calendar;
652 GtkWidget *log_filter_from_entry;
653 GtkWidget *log_filter_to_entry;
654 GtkWidget *log_filter_clear_button;
656 data->filters = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
657 g_free);
659 log_filter_author_entry = glade_xml_get_widget (data->gxml,
660 "log_filter_author_entry");
661 log_filter_grep_entry = glade_xml_get_widget (data->gxml,
662 "log_filter_grep_entry");
663 log_filter_from_check = glade_xml_get_widget (data->gxml,
664 "log_filter_from_check");
665 log_filter_to_check = glade_xml_get_widget (data->gxml,
666 "log_filter_to_check");
667 log_filter_from_calendar = glade_xml_get_widget (data->gxml,
668 "log_filter_from_calendar");
669 log_filter_to_calendar = glade_xml_get_widget (data->gxml,
670 "log_filter_to_calendar");
671 log_filter_from_entry = glade_xml_get_widget (data->gxml,
672 "log_filter_from_entry");
673 log_filter_to_entry = glade_xml_get_widget (data->gxml,
674 "log_filter_to_entry");
675 log_filter_clear_button = glade_xml_get_widget (data->gxml,
676 "log_filter_clear_button");
678 /* Each widget that has some kind of filter must have a "filter name"
679 * associated with it so that we can generically see how many filters
680 * the user asked for, so we can hide the graph column, and to get this
681 * information in a somewhat generic way. */
682 g_object_set_data (G_OBJECT (log_filter_author_entry), "filter-name",
683 "author");
684 g_object_set_data (G_OBJECT (log_filter_grep_entry), "filter-name",
685 "grep");
686 g_object_set_data (G_OBJECT (log_filter_from_calendar), "filter-name",
687 "since-date");
688 g_object_set_data (G_OBJECT (log_filter_to_calendar), "filter-name",
689 "until-date");
690 g_object_set_data (G_OBJECT (log_filter_from_entry), "filter-name",
691 "since-commit");
692 g_object_set_data (G_OBJECT (log_filter_to_entry), "filter-name",
693 "until-commit");
695 g_object_set_data (G_OBJECT (log_filter_from_check), "calendar",
696 log_filter_from_calendar);
697 g_object_set_data (G_OBJECT (log_filter_to_check), "calendar",
698 log_filter_to_calendar);
700 /* Each widget should have one generic handler that inserts its changes
701 * into the filter hash table as needed. */
702 g_signal_connect (G_OBJECT (log_filter_author_entry), "changed",
703 G_CALLBACK (on_log_filter_entry_changed),
704 data);
706 g_signal_connect (G_OBJECT (log_filter_grep_entry), "changed",
707 G_CALLBACK (on_log_filter_entry_changed),
708 data);
710 g_signal_connect (G_OBJECT (log_filter_from_entry), "changed",
711 G_CALLBACK (on_log_filter_entry_changed),
712 data);
714 g_signal_connect (G_OBJECT (log_filter_to_entry), "changed",
715 G_CALLBACK (on_log_filter_entry_changed),
716 data);
718 /* Calendars don't have one catch all signal that handles both month and
719 * day changes, so we have to connect to both signals. */
720 g_signal_connect (G_OBJECT (log_filter_from_calendar), "day-selected",
721 G_CALLBACK (on_log_filter_date_changed),
722 data);
724 g_signal_connect (G_OBJECT (log_filter_from_calendar), "month-changed",
725 G_CALLBACK (on_log_filter_date_changed),
726 data);
728 g_signal_connect (G_OBJECT (log_filter_to_calendar), "day-selected",
729 G_CALLBACK (on_log_filter_date_changed),
730 data);
732 g_signal_connect (G_OBJECT (log_filter_to_calendar), "month-changed",
733 G_CALLBACK (on_log_filter_date_changed),
734 data);
736 g_signal_connect (G_OBJECT (log_filter_from_check), "toggled",
737 G_CALLBACK (on_log_filter_date_check_toggled),
738 data);
740 g_signal_connect (G_OBJECT (log_filter_to_check), "toggled",
741 G_CALLBACK (on_log_filter_date_check_toggled),
742 data);
744 g_signal_connect (G_OBJECT (log_filter_clear_button), "clicked",
745 G_CALLBACK (on_log_filter_clear_button_clicked),
746 data);
749 GtkWidget *
750 git_log_window_create (Git *plugin)
752 LogData *data;
753 GtkWidget *log_window;
754 GtkWidget *log_vbox;
755 GtkWidget *log_changes_view;
756 GtkWidget *log_view_button;
757 GtkWidget *log_whole_project_check;
758 GtkWidget *log_path_entry;
759 GtkTreeSelection *selection;
761 data = g_new0 (LogData, 1);
762 data->gxml = glade_xml_new (GLADE_FILE, "log_window", NULL);
764 data->plugin = plugin;
765 data->path = NULL;
766 data->graph_renderer = giggle_graph_renderer_new ();
768 log_window = glade_xml_get_widget (data->gxml, "log_window");
769 log_vbox = glade_xml_get_widget (data->gxml, "log_vbox");
770 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
771 log_whole_project_check = glade_xml_get_widget (data->gxml,
772 "log_whole_project_check");
773 log_path_entry = glade_xml_get_widget (data->gxml, "log_path_entry");
774 log_view_button = glade_xml_get_widget (data->gxml,
775 "log_view_button");
777 g_object_set_data (G_OBJECT (log_vbox), "log-data", data);
779 setup_filters (data);
781 g_signal_connect (G_OBJECT (log_changes_view), "query-tooltip",
782 G_CALLBACK (on_log_changes_view_query_tooltip),
783 data);
784 g_signal_connect (G_OBJECT (log_changes_view), "button-press-event",
785 G_CALLBACK (on_log_changes_view_button_press_event),
786 plugin);
789 g_signal_connect (G_OBJECT (log_view_button), "clicked",
790 G_CALLBACK (on_log_view_button_clicked),
791 data);
793 g_object_set_data (G_OBJECT (log_whole_project_check), "file-entry",
794 log_path_entry);
795 g_signal_connect (G_OBJECT (log_whole_project_check), "toggled",
796 G_CALLBACK (on_git_whole_project_toggled), plugin);
798 data->list_store = gtk_list_store_new (NUM_COLS,
799 G_TYPE_OBJECT);
800 create_columns (data);
802 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view));
803 gtk_tree_selection_set_select_function (selection,
804 (GtkTreeSelectionFunc) on_log_changes_view_row_selected,
805 data, NULL);
807 g_signal_connect (G_OBJECT (log_vbox), "destroy",
808 G_CALLBACK (on_log_vbox_destroy),
809 data);
811 g_object_ref (log_vbox);
812 gtk_container_remove (GTK_CONTAINER (log_window), log_vbox);
813 gtk_widget_destroy (log_window);
815 return log_vbox;
818 void
819 on_menu_git_log (GtkAction *action, Git *plugin)
821 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin)->shell,
822 plugin->log_viewer, NULL);
825 void
826 on_fm_git_log (GtkAction *action, Git *plugin)
828 LogData *data;
829 GtkWidget *log_path_entry;
830 GtkWidget *log_whole_project_check;
832 data = g_object_get_data (G_OBJECT (plugin->log_viewer), "log-data");
833 log_path_entry = glade_xml_get_widget (data->gxml,
834 "log_path_entry");
835 log_whole_project_check = glade_xml_get_widget (data->gxml,
836 "log_whole_project_check");
838 gtk_entry_set_text (GTK_ENTRY (log_path_entry),
839 plugin->current_fm_filename);
840 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_whole_project_check),
841 FALSE);
843 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin)->shell,
844 plugin->log_viewer, NULL);
847 void
848 git_log_window_clear (Git *plugin)
850 LogData *data;
851 GtkWidget *log_text_view;
852 GtkTextBuffer *buffer;
854 data = g_object_get_data (G_OBJECT (plugin->log_viewer), "log-data");
855 log_text_view = glade_xml_get_widget (data->gxml, "log_text_view");
856 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_text_view));
858 gtk_list_store_clear (data->list_store);
859 gtk_text_buffer_set_text (buffer, "", 0);
862 GitRevision *
863 git_log_get_selected_revision (Git *plugin)
865 LogData *data;
866 GtkWidget *log_changes_view;
867 GitRevision *revision;
868 GtkTreeSelection *selection;
869 GtkTreeModel *model;
870 GtkTreeIter iter;
872 data = g_object_get_data (G_OBJECT (plugin->log_viewer), "log-data");
873 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
874 revision = NULL;
876 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view));
877 model = gtk_tree_view_get_model (GTK_TREE_VIEW (log_changes_view));
879 gtk_tree_selection_get_selected (selection, NULL, &iter);
880 gtk_tree_model_get (model, &iter, COL_REVISION, &revision, -1);
882 return revision;