Implement simple revision log UI
[anjuta-git-plugin.git] / plugins / git / git-log-dialog.c
blob50307ab1c2a2f51f7817ce32d77b4a730d08d64a
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 } LogData;
43 static void
44 author_cell_function (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
45 GtkTreeModel *model, GtkTreeIter *iter,
46 gpointer user_data)
48 GitRevision *revision;
49 gchar *author;
51 gtk_tree_model_get (model, iter, COL_REVISION, &revision, -1);
52 author = git_revision_get_author (revision);
54 g_object_unref (revision);
56 g_object_set (renderer, "text", author, NULL);
58 g_free (author);
61 static void
62 date_cell_function (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
63 GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
65 GitRevision *revision;
66 gchar *date;
68 gtk_tree_model_get (model, iter, COL_REVISION, &revision, -1);
69 date = git_revision_get_formatted_date (revision);
71 g_object_unref (revision);
73 g_object_set (renderer, "text", date, NULL);
75 g_free (date);
78 static void
79 short_log_cell_function (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
80 GtkTreeModel *model, GtkTreeIter *iter,
81 gpointer user_data)
83 GitRevision *revision;
84 gchar *short_log;
86 gtk_tree_model_get (model, iter, COL_REVISION, &revision, -1);
87 short_log = git_revision_get_short_log (revision);
89 g_object_unref (revision);
91 g_object_set (renderer, "text", short_log, NULL);
93 g_free (short_log);
96 static void
97 create_columns (LogData *data)
99 GtkWidget *log_changes_view;
100 gint font_size;
101 GtkTreeViewColumn *column;
102 GtkCellRenderer *renderer;
104 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
105 font_size = PANGO_PIXELS (pango_font_description_get_size (GTK_WIDGET (log_changes_view)->style->font_desc));
107 /* Graph */
108 column = gtk_tree_view_column_new ();
109 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
110 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
111 gtk_tree_view_column_set_min_width (column, font_size * 10);
112 gtk_tree_view_column_set_resizable (column, TRUE);
113 gtk_tree_view_column_pack_start (column, data->graph_renderer, TRUE);
114 gtk_tree_view_column_add_attribute (column, data->graph_renderer,
115 "revision", COL_REVISION);
116 gtk_tree_view_column_set_title (column, "Graph");
118 /* Short log */
119 column = gtk_tree_view_column_new ();
120 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
121 renderer = gtk_cell_renderer_text_new ();
122 g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
123 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
124 gtk_tree_view_column_set_min_width (column, font_size * 10);
125 gtk_tree_view_column_set_resizable (column, TRUE);
126 gtk_tree_view_column_set_expand (column, TRUE);
127 gtk_tree_view_column_pack_start (column, renderer, TRUE);
128 gtk_tree_view_column_set_cell_data_func (column, renderer,
129 (GtkTreeCellDataFunc) short_log_cell_function,
130 NULL, NULL);
131 gtk_tree_view_column_set_title (column, "Short log");
133 /* Author */
134 column = gtk_tree_view_column_new ();
135 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
136 renderer = gtk_cell_renderer_text_new ();
137 gtk_tree_view_column_set_resizable (column, TRUE);
138 gtk_tree_view_column_pack_start (column, renderer, TRUE);
139 gtk_tree_view_column_set_cell_data_func (column, renderer,
140 (GtkTreeCellDataFunc) author_cell_function,
141 NULL, NULL);
142 gtk_tree_view_column_set_title (column, "Author");
144 /* Date */
145 column = gtk_tree_view_column_new ();
146 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
147 renderer = gtk_cell_renderer_text_new ();
148 gtk_tree_view_column_set_resizable (column, TRUE);
149 gtk_tree_view_column_pack_start (column, renderer, TRUE);
150 gtk_tree_view_column_set_cell_data_func (column, renderer,
151 (GtkTreeCellDataFunc) date_cell_function,
152 NULL, NULL);
153 gtk_tree_view_column_set_title (column, "Date");
155 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view),
156 GTK_TREE_MODEL (data->list_store));
157 g_object_unref (data->list_store);
161 static void
162 on_log_command_finished (AnjutaCommand *command, guint return_code,
163 LogData *data)
165 GtkWidget *log_changes_view;
166 GQueue *queue;
167 GtkTreeIter iter;
168 GitRevision *revision;
170 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
172 g_object_ref (data->list_store);
173 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view), NULL);
175 queue = git_log_command_get_output_queue (GIT_LOG_COMMAND (command));
177 while (g_queue_peek_head (queue))
179 revision = g_queue_pop_head (queue);
181 gtk_list_store_append (data->list_store, &iter);
182 gtk_list_store_set (data->list_store, &iter, COL_REVISION, revision, -1);
183 g_object_unref (revision);
186 giggle_graph_renderer_validate_model (GIGGLE_GRAPH_RENDERER (data->graph_renderer),
187 GTK_TREE_MODEL (data->list_store),
188 COL_REVISION);
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);
193 g_object_unref (command);
196 static void
197 on_view_log_button_clicked (GtkButton *button, LogData *data)
199 GitLogCommand *log_command;
200 gint pulse_timer_id;
202 log_command = git_log_command_new (data->plugin->project_root_directory);
204 gtk_list_store_clear (data->list_store);
206 pulse_timer_id = status_bar_progress_pulse (data->plugin,
207 _("Git: Retrieving"
208 " log..."));
210 g_signal_connect (G_OBJECT (log_command), "command-finished",
211 G_CALLBACK (stop_status_bar_progress_pulse),
212 GUINT_TO_POINTER (pulse_timer_id));
214 g_signal_connect (G_OBJECT (log_command), "command-finished",
215 G_CALLBACK (on_log_command_finished),
216 data);
218 anjuta_command_start (ANJUTA_COMMAND (log_command));
222 static void
223 on_log_vbox_destroy (GtkObject *log_vbox, LogData *data)
225 g_free (data->path);
226 g_object_unref (data->gxml);
227 g_free (data);
230 static void
231 on_log_message_command_finished (AnjutaCommand *command, guint return_code,
232 LogData *data)
234 GtkWidget *log_text_view;
235 GtkTextBuffer *buffer;
236 gchar *log_message;
238 log_text_view = glade_xml_get_widget (data->gxml, "log_text_view");
239 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_text_view));
240 log_message = git_log_message_command_get_message (GIT_LOG_MESSAGE_COMMAND (command));
242 gtk_text_buffer_set_text (buffer, log_message, strlen (log_message));
244 g_free (log_message);
245 g_object_unref (command);
248 static gboolean
249 on_log_changes_view_row_selected (GtkTreeSelection *selection,
250 GtkTreeModel *model,
251 GtkTreePath *path,
252 gboolean path_currently_selected,
253 LogData *data)
255 GtkTreeIter iter;
256 GitRevision *revision;
257 gchar *sha;
258 GitLogMessageCommand *log_message_command;
260 if (!path_currently_selected)
262 gtk_tree_model_get_iter (model, &iter, path);
263 gtk_tree_model_get (model, &iter, COL_REVISION, &revision, -1);
264 sha = git_revision_get_sha (revision);
266 log_message_command = git_log_message_command_new (data->plugin->project_root_directory,
267 sha);
269 g_free (sha);
270 g_object_unref (revision);
272 g_signal_connect (G_OBJECT (log_message_command), "command-finished",
273 G_CALLBACK (on_log_message_command_finished),
274 data);
276 anjuta_command_start (ANJUTA_COMMAND (log_message_command));
279 return TRUE;
282 GtkWidget *
283 git_log_window_create (Git *plugin)
285 LogData *data;
286 GtkWidget *log_window;
287 GtkWidget *log_vbox;
288 GtkWidget *log_changes_view;
289 GtkWidget *view_log_button;
290 GtkWidget *whole_project_check;
291 GtkWidget *path_entry;
292 GtkTreeSelection *selection;
294 data = g_new0 (LogData, 1);
295 data->gxml = glade_xml_new (GLADE_FILE, "log_window", NULL);
297 data->plugin = plugin;
298 data->path = NULL;
299 data->graph_renderer = giggle_graph_renderer_new ();
301 log_window = glade_xml_get_widget (data->gxml, "log_window");
302 log_vbox = glade_xml_get_widget (data->gxml, "log_vbox");
303 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
304 whole_project_check = glade_xml_get_widget (data->gxml,
305 "whole_project_check");
306 path_entry = glade_xml_get_widget (data->gxml, "path_entry");
307 view_log_button = glade_xml_get_widget (data->gxml,
308 "view_log_button");
310 g_object_set_data (G_OBJECT (log_vbox), "log-data", data);
312 g_signal_connect (G_OBJECT (view_log_button), "clicked",
313 G_CALLBACK (on_view_log_button_clicked),
314 data);
316 g_object_set_data (G_OBJECT (whole_project_check), "file-entry",
317 path_entry);
318 g_signal_connect (G_OBJECT (whole_project_check), "toggled",
319 G_CALLBACK (on_whole_project_toggled), plugin);
321 data->list_store = gtk_list_store_new (NUM_COLS,
322 G_TYPE_OBJECT);
323 create_columns (data);
325 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view));
326 gtk_tree_selection_set_select_function (selection,
327 (GtkTreeSelectionFunc) on_log_changes_view_row_selected,
328 data, NULL);
330 g_signal_connect (G_OBJECT (log_vbox), "destroy",
331 G_CALLBACK (on_log_vbox_destroy),
332 data);
334 g_object_ref (log_vbox);
335 gtk_container_remove (GTK_CONTAINER (log_window), log_vbox);
336 gtk_widget_destroy (log_window);
338 return log_vbox;
341 void
342 on_menu_git_log (GtkAction *action, Git *plugin)
344 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin)->shell,
345 plugin->log_viewer, NULL);
348 /* TODO: Enable when FM support is implemented */
349 #if 0
350 void
351 on_fm_subversion_log (GtkAction *action, Git *plugin)
353 GtkWidget *path_text_entry;
355 path_text_entry = glade_xml_get_widget (plugin->log_gxml,
356 "path_text_entry");
358 gtk_entry_set_text (GTK_ENTRY path_entry),
359 plugin->fm_current_filename);
361 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin)->shell,
362 plugin->log_viewer, NULL);
364 #endif
366 void
367 git_log_window_clear (Git *plugin)
369 LogData *data;
370 GtkWidget *log_text_view;
371 GtkTextBuffer *buffer;
373 data = g_object_get_data (G_OBJECT (plugin->log_viewer), "log-data");
374 log_text_view = glade_xml_get_widget (data->gxml, "log_text_view");
375 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_text_view));
377 gtk_list_store_clear (data->list_store);
378 gtk_text_buffer_set_text (buffer, "", 0);
381 void
382 git_log_set_whole_project_sensitive (Git *plugin, gboolean sensitive)
384 LogData *data;
385 GtkWidget *whole_project_check;
387 data = g_object_get_data (G_OBJECT (plugin->log_viewer), "log-data");
388 whole_project_check = glade_xml_get_widget (data->gxml,
389 "whole_project_check");
391 gtk_widget_set_sensitive (whole_project_check, sensitive);