1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) James Liggett 2007 <jrliggett@cox.net>
6 * anjuta is free software.
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)
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"
38 GtkListStore
*list_store
;
39 GtkCellRenderer
*graph_renderer
;
45 author_cell_function (GtkTreeViewColumn
*column
, GtkCellRenderer
*renderer
,
46 GtkTreeModel
*model
, GtkTreeIter
*iter
,
49 GitRevision
*revision
;
52 gtk_tree_model_get (model
, iter
, COL_REVISION
, &revision
, -1);
53 author
= git_revision_get_author (revision
);
55 g_object_unref (revision
);
57 g_object_set (renderer
, "text", author
, NULL
);
63 date_cell_function (GtkTreeViewColumn
*column
, GtkCellRenderer
*renderer
,
64 GtkTreeModel
*model
, GtkTreeIter
*iter
, gpointer user_data
)
66 GitRevision
*revision
;
69 gtk_tree_model_get (model
, iter
, COL_REVISION
, &revision
, -1);
70 date
= git_revision_get_formatted_date (revision
);
72 g_object_unref (revision
);
74 g_object_set (renderer
, "text", date
, NULL
);
80 short_log_cell_function (GtkTreeViewColumn
*column
, GtkCellRenderer
*renderer
,
81 GtkTreeModel
*model
, GtkTreeIter
*iter
,
84 GitRevision
*revision
;
87 gtk_tree_model_get (model
, iter
, COL_REVISION
, &revision
, -1);
88 short_log
= git_revision_get_short_log (revision
);
90 g_object_unref (revision
);
92 g_object_set (renderer
, "text", short_log
, NULL
);
98 ref_icon_cell_function (GtkTreeViewColumn
*column
, GtkCellRenderer
*renderer
,
99 GtkTreeModel
*model
, GtkTreeIter
*iter
,
102 GitRevision
*revision
;
105 gtk_tree_model_get (model
, iter
, COL_REVISION
, &revision
, -1);
106 sha
= git_revision_get_sha (revision
);
108 g_object_unref (revision
);
110 if (g_hash_table_lookup_extended (data
->refs
, sha
, NULL
, NULL
))
111 g_object_set (renderer
, "stock-id", GTK_STOCK_INFO
, NULL
);
113 g_object_set (renderer
, "stock-id", "", NULL
);
119 create_columns (LogData
*data
)
121 GtkWidget
*log_changes_view
;
123 GtkTreeViewColumn
*column
;
124 GtkCellRenderer
*renderer
;
126 log_changes_view
= glade_xml_get_widget (data
->gxml
, "log_changes_view");
127 font_size
= PANGO_PIXELS (pango_font_description_get_size (GTK_WIDGET (log_changes_view
)->style
->font_desc
));
130 column
= gtk_tree_view_column_new ();
131 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
132 renderer
= gtk_cell_renderer_pixbuf_new ();
133 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
134 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
135 (GtkTreeCellDataFunc
) ref_icon_cell_function
,
141 column
= gtk_tree_view_column_new ();
142 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
143 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_FIXED
);
144 gtk_tree_view_column_set_min_width (column
, font_size
* 10);
145 gtk_tree_view_column_set_resizable (column
, TRUE
);
146 gtk_tree_view_column_pack_start (column
, data
->graph_renderer
, TRUE
);
147 gtk_tree_view_column_add_attribute (column
, data
->graph_renderer
,
148 "revision", COL_REVISION
);
149 gtk_tree_view_column_set_title (column
, "Graph");
152 column
= gtk_tree_view_column_new ();
153 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
154 renderer
= gtk_cell_renderer_text_new ();
155 g_object_set (renderer
, "ellipsize", PANGO_ELLIPSIZE_END
, NULL
);
156 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_FIXED
);
157 gtk_tree_view_column_set_min_width (column
, font_size
* 10);
158 gtk_tree_view_column_set_resizable (column
, TRUE
);
159 gtk_tree_view_column_set_expand (column
, TRUE
);
160 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
161 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
162 (GtkTreeCellDataFunc
) short_log_cell_function
,
164 gtk_tree_view_column_set_title (column
, "Short log");
167 column
= gtk_tree_view_column_new ();
168 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
169 renderer
= gtk_cell_renderer_text_new ();
170 gtk_tree_view_column_set_resizable (column
, TRUE
);
171 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
172 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
173 (GtkTreeCellDataFunc
) author_cell_function
,
175 gtk_tree_view_column_set_title (column
, "Author");
178 column
= gtk_tree_view_column_new ();
179 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
180 renderer
= gtk_cell_renderer_text_new ();
181 gtk_tree_view_column_set_resizable (column
, TRUE
);
182 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
183 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
184 (GtkTreeCellDataFunc
) date_cell_function
,
186 gtk_tree_view_column_set_title (column
, "Date");
188 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view
),
189 GTK_TREE_MODEL (data
->list_store
));
190 g_object_unref (data
->list_store
);
195 on_log_command_finished (AnjutaCommand
*command
, guint return_code
,
198 GtkWidget
*log_changes_view
;
201 GitRevision
*revision
;
203 log_changes_view
= glade_xml_get_widget (data
->gxml
, "log_changes_view");
205 g_object_ref (data
->list_store
);
206 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view
), NULL
);
208 queue
= git_log_command_get_output_queue (GIT_LOG_COMMAND (command
));
210 while (g_queue_peek_head (queue
))
212 revision
= g_queue_pop_head (queue
);
214 gtk_list_store_append (data
->list_store
, &iter
);
215 gtk_list_store_set (data
->list_store
, &iter
, COL_REVISION
, revision
, -1);
216 g_object_unref (revision
);
219 giggle_graph_renderer_validate_model (GIGGLE_GRAPH_RENDERER (data
->graph_renderer
),
220 GTK_TREE_MODEL (data
->list_store
),
222 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view
),
223 GTK_TREE_MODEL (data
->list_store
));
224 g_object_unref (data
->list_store
);
226 g_object_unref (command
);
230 on_ref_command_finished (AnjutaCommand
*command
, guint return_code
,
233 GitLogCommand
*log_command
;
236 data
->refs
= git_ref_command_get_refs (GIT_REF_COMMAND (command
));
237 log_command
= git_log_command_new (data
->plugin
->project_root_directory
);
239 gtk_list_store_clear (data
->list_store
);
241 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
245 g_signal_connect (G_OBJECT (log_command
), "command-finished",
246 G_CALLBACK (stop_status_bar_progress_pulse
),
247 GUINT_TO_POINTER (pulse_timer_id
));
249 g_signal_connect (G_OBJECT (log_command
), "command-finished",
250 G_CALLBACK (on_log_command_finished
),
253 anjuta_command_start (ANJUTA_COMMAND (log_command
));
255 g_object_unref (command
);
259 on_view_log_button_clicked (GtkButton
*button
, LogData
*data
)
261 GitRefCommand
*ref_command
;
264 g_hash_table_unref (data
->refs
);
266 ref_command
= git_ref_command_new (data
->plugin
->project_root_directory
);
268 g_signal_connect (G_OBJECT (ref_command
), "command-finished",
269 G_CALLBACK (on_ref_command_finished
),
272 anjuta_command_start (ANJUTA_COMMAND (ref_command
));
276 on_log_vbox_destroy (GtkObject
*log_vbox
, LogData
*data
)
279 g_object_unref (data
->gxml
);
282 g_hash_table_unref (data
->refs
);
288 on_log_message_command_finished (AnjutaCommand
*command
, guint return_code
,
291 GtkWidget
*log_text_view
;
292 GtkTextBuffer
*buffer
;
295 log_text_view
= glade_xml_get_widget (data
->gxml
, "log_text_view");
296 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_text_view
));
297 log_message
= git_log_message_command_get_message (GIT_LOG_MESSAGE_COMMAND (command
));
299 gtk_text_buffer_set_text (buffer
, log_message
, strlen (log_message
));
301 g_free (log_message
);
302 g_object_unref (command
);
306 on_log_changes_view_row_selected (GtkTreeSelection
*selection
,
309 gboolean path_currently_selected
,
313 GitRevision
*revision
;
315 GitLogMessageCommand
*log_message_command
;
317 if (!path_currently_selected
)
319 gtk_tree_model_get_iter (model
, &iter
, path
);
320 gtk_tree_model_get (model
, &iter
, COL_REVISION
, &revision
, -1);
321 sha
= git_revision_get_sha (revision
);
323 log_message_command
= git_log_message_command_new (data
->plugin
->project_root_directory
,
327 g_object_unref (revision
);
329 g_signal_connect (G_OBJECT (log_message_command
), "command-finished",
330 G_CALLBACK (on_log_message_command_finished
),
333 anjuta_command_start (ANJUTA_COMMAND (log_message_command
));
340 on_log_changes_view_query_tooltip (GtkWidget
*log_changes_view
, gint x
, gint y
,
341 gboolean keyboard_mode
, GtkTooltip
*tooltip
,
345 GtkTreeViewColumn
*ref_column
;
348 GtkTreeViewColumn
*current_column
;
352 GitRevision
*revision
;
356 GString
*tooltip_string
;
362 ref_column
= gtk_tree_view_get_column (GTK_TREE_VIEW (log_changes_view
), 0);
364 gtk_tree_view_convert_widget_to_bin_window_coords (GTK_TREE_VIEW (log_changes_view
),
365 x
, y
, &bin_x
, &bin_y
);
366 gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (log_changes_view
), bin_x
,
367 bin_y
, &path
, ¤t_column
, NULL
, NULL
);
369 /* We need to be in the ref icon column */
370 if (current_column
== ref_column
)
372 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (log_changes_view
));
373 gtk_tree_model_get_iter (model
, &iter
, path
);
375 gtk_tree_model_get (model
, &iter
, COL_REVISION
, &revision
, -1);
376 sha
= git_revision_get_sha (revision
);
378 g_object_unref (revision
);
380 ref_list
= g_hash_table_lookup (data
->refs
, sha
);
385 current_ref
= ref_list
;
386 tooltip_string
= g_string_new ("");
390 ref_name
= git_ref_get_name (GIT_REF (current_ref
->data
));
391 ref_type
= git_ref_get_ref_type (GIT_REF (current_ref
->data
));
393 if (tooltip_string
->len
> 0)
394 g_string_append (tooltip_string
, "\n");
398 case GIT_REF_TYPE_BRANCH
:
399 g_string_append_printf (tooltip_string
,
400 _("<b>Branch:</b> %s"),
403 case GIT_REF_TYPE_TAG
:
404 g_string_append_printf (tooltip_string
,
408 case GIT_REF_TYPE_REMOTE
:
409 g_string_append_printf (tooltip_string
,
410 _("<b>Remote:</b> %s"),
418 current_ref
= g_list_next (current_ref
);
421 gtk_tooltip_set_markup (tooltip
, tooltip_string
->str
);
422 g_string_free (tooltip_string
, TRUE
);
428 gtk_tree_path_free (path
);
435 on_log_changes_view_button_press_event (GtkWidget
*log_changes_view
,
436 GdkEventButton
*event
,
439 GtkTreeSelection
*selection
;
441 if (event
->type
== GDK_BUTTON_PRESS
)
443 if (event
->button
== 3)
445 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view
));
447 if (gtk_tree_selection_count_selected_rows (selection
) > 0)
449 gtk_menu_popup (GTK_MENU(plugin
->log_popup_menu
), NULL
, NULL
,
450 NULL
, NULL
, event
->button
, event
->time
);
458 git_log_window_create (Git
*plugin
)
461 GtkWidget
*log_window
;
463 GtkWidget
*log_changes_view
;
464 GtkWidget
*view_log_button
;
465 GtkWidget
*whole_project_check
;
466 GtkWidget
*path_entry
;
467 GtkTreeSelection
*selection
;
469 data
= g_new0 (LogData
, 1);
470 data
->gxml
= glade_xml_new (GLADE_FILE
, "log_window", NULL
);
472 data
->plugin
= plugin
;
474 data
->graph_renderer
= giggle_graph_renderer_new ();
476 log_window
= glade_xml_get_widget (data
->gxml
, "log_window");
477 log_vbox
= glade_xml_get_widget (data
->gxml
, "log_vbox");
478 log_changes_view
= glade_xml_get_widget (data
->gxml
, "log_changes_view");
479 whole_project_check
= glade_xml_get_widget (data
->gxml
,
480 "whole_project_check");
481 path_entry
= glade_xml_get_widget (data
->gxml
, "path_entry");
482 view_log_button
= glade_xml_get_widget (data
->gxml
,
485 g_object_set_data (G_OBJECT (log_vbox
), "log-data", data
);
487 g_signal_connect (G_OBJECT (log_changes_view
), "query-tooltip",
488 G_CALLBACK (on_log_changes_view_query_tooltip
),
490 g_signal_connect (G_OBJECT (log_changes_view
), "button-press-event",
491 G_CALLBACK (on_log_changes_view_button_press_event
),
495 g_signal_connect (G_OBJECT (view_log_button
), "clicked",
496 G_CALLBACK (on_view_log_button_clicked
),
499 g_object_set_data (G_OBJECT (whole_project_check
), "file-entry",
501 g_signal_connect (G_OBJECT (whole_project_check
), "toggled",
502 G_CALLBACK (on_whole_project_toggled
), plugin
);
504 data
->list_store
= gtk_list_store_new (NUM_COLS
,
506 create_columns (data
);
508 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view
));
509 gtk_tree_selection_set_select_function (selection
,
510 (GtkTreeSelectionFunc
) on_log_changes_view_row_selected
,
513 g_signal_connect (G_OBJECT (log_vbox
), "destroy",
514 G_CALLBACK (on_log_vbox_destroy
),
517 g_object_ref (log_vbox
);
518 gtk_container_remove (GTK_CONTAINER (log_window
), log_vbox
);
519 gtk_widget_destroy (log_window
);
525 on_menu_git_log (GtkAction
*action
, Git
*plugin
)
527 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin
)->shell
,
528 plugin
->log_viewer
, NULL
);
531 /* TODO: Enable when FM support is implemented */
534 on_fm_subversion_log (GtkAction
*action
, Git
*plugin
)
536 GtkWidget
*path_text_entry
;
538 path_text_entry
= glade_xml_get_widget (plugin
->log_gxml
,
541 gtk_entry_set_text (GTK_ENTRY path_entry
),
542 plugin
->fm_current_filename
);
544 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin
)->shell
,
545 plugin
->log_viewer
, NULL
);
550 git_log_window_clear (Git
*plugin
)
553 GtkWidget
*log_text_view
;
554 GtkTextBuffer
*buffer
;
556 data
= g_object_get_data (G_OBJECT (plugin
->log_viewer
), "log-data");
557 log_text_view
= glade_xml_get_widget (data
->gxml
, "log_text_view");
558 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_text_view
));
560 gtk_list_store_clear (data
->list_store
);
561 gtk_text_buffer_set_text (buffer
, "", 0);
565 git_log_get_selected_revision (Git
*plugin
)
568 GtkWidget
*log_changes_view
;
569 GitRevision
*revision
;
570 GtkTreeSelection
*selection
;
574 data
= g_object_get_data (G_OBJECT (plugin
->log_viewer
), "log-data");
575 log_changes_view
= glade_xml_get_widget (data
->gxml
, "log_changes_view");
578 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view
));
579 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (log_changes_view
));
581 gtk_tree_selection_get_selected (selection
, NULL
, &iter
);
582 gtk_tree_model_get (model
, &iter
, COL_REVISION
, &revision
, -1);