Updated Spanish translation
[anjuta-git-plugin.git] / plugins / subversion / subversion-log-dialog.c
blob875fb615bb139c5c7cc65255b7b10e4272dbf2b0
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 "subversion-log-dialog.h"
27 typedef struct
29 glong revisions[2];
30 gint pos;
31 } SelectedDiffData;
33 typedef struct
35 GladeXML *gxml;
36 Subversion *plugin;
37 gchar *path;
38 GtkListStore *log_store;
39 GHashTable *selected_diff_revisions;
40 } LogData;
42 enum
44 COL_DIFF_SELECTED,
45 COL_AUTHOR,
46 COL_DATE,
47 COL_REVISION,
48 COL_SHORT_LOG,
49 COL_FULL_LOG,
50 NUM_COLS
53 static void
54 on_diff_selected_column_toggled (GtkCellRendererToggle *renderer,
55 gchar *tree_path,
56 LogData *data)
58 GtkTreeIter iter;
59 glong revision;
60 GtkWidget *log_diff_selected_button;
61 gboolean selected;
63 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (data->log_store),
64 &iter, tree_path);
65 gtk_tree_model_get (GTK_TREE_MODEL (data->log_store), &iter,
66 COL_DIFF_SELECTED, &selected,
67 COL_REVISION, &revision,
68 -1);
70 log_diff_selected_button = glade_xml_get_widget (data->gxml,
71 "log_diff_selected_button");
73 selected = !selected;
75 if (selected)
77 /* Only allow two log items to be selected at once. */
78 if (g_hash_table_size (data->selected_diff_revisions) < 2)
80 g_hash_table_insert (data->selected_diff_revisions,
81 GINT_TO_POINTER (revision), NULL);
83 gtk_list_store_set (data->log_store, &iter,
84 COL_DIFF_SELECTED, TRUE,
85 -1);
88 else
90 g_hash_table_remove (data->selected_diff_revisions,
91 GINT_TO_POINTER (revision));
93 gtk_list_store_set (data->log_store, &iter,
94 COL_DIFF_SELECTED, FALSE,
95 -1);
98 /* For diff selected to work, exactly 2 revisions must be selected. */
99 gtk_widget_set_sensitive (log_diff_selected_button,
100 g_hash_table_size (data->selected_diff_revisions) == 2);
104 static void
105 create_columns (LogData *data)
107 GtkWidget *log_changes_view;
108 GtkTreeViewColumn *column;
109 GtkCellRenderer *renderer;
111 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
113 /* Selected for diff */
114 column = gtk_tree_view_column_new ();
115 renderer = gtk_cell_renderer_toggle_new ();
116 gtk_tree_view_column_pack_start (column, renderer, TRUE);
117 gtk_tree_view_column_set_title (column, "Diff");
118 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
119 gtk_tree_view_column_add_attribute (column, renderer, "active",
120 COL_DIFF_SELECTED);
122 g_signal_connect (G_OBJECT (renderer), "toggled",
123 G_CALLBACK (on_diff_selected_column_toggled),
124 data);
126 /* Author */
127 column = gtk_tree_view_column_new ();
128 renderer = gtk_cell_renderer_text_new ();
129 gtk_tree_view_column_pack_start (column, renderer, TRUE);
130 gtk_tree_view_column_set_title (column, "Author");
131 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
132 gtk_tree_view_column_add_attribute (column, renderer, "text",
133 COL_AUTHOR);
135 /* Date */
136 column = gtk_tree_view_column_new ();
137 renderer = gtk_cell_renderer_text_new ();
138 gtk_tree_view_column_pack_start (column, renderer, TRUE);
139 gtk_tree_view_column_set_title (column, "Date");
140 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
141 gtk_tree_view_column_add_attribute (column, renderer, "text",
142 COL_DATE);
145 /* Revision */
146 column = gtk_tree_view_column_new ();
147 renderer = gtk_cell_renderer_text_new ();
148 gtk_tree_view_column_pack_start (column, renderer, TRUE);
149 gtk_tree_view_column_set_title (column, "Revision");
150 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
151 gtk_tree_view_column_add_attribute (column, renderer, "text",
152 COL_REVISION);
154 /* Short log */
155 column = gtk_tree_view_column_new ();
156 renderer = gtk_cell_renderer_text_new ();
157 gtk_tree_view_column_pack_start (column, renderer, TRUE);
158 gtk_tree_view_column_set_title (column, "Short Log");
159 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view), column);
160 gtk_tree_view_column_add_attribute (column, renderer, "text",
161 COL_SHORT_LOG);
165 static void
166 on_log_command_finished (AnjutaCommand *command, guint return_code,
167 LogData *data)
169 GtkWidget *log_changes_view;
170 GQueue *log_queue;
171 SvnLogEntry *log_entry;
172 GtkTreeIter iter;
173 gchar *author;
174 gchar *date;
175 glong revision;
176 gchar *short_log;
177 gchar *full_log;
179 g_object_ref (data->log_store);
180 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
181 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view), NULL);
182 g_hash_table_remove_all (data->selected_diff_revisions);
184 log_queue = svn_log_command_get_entry_queue (SVN_LOG_COMMAND (command));
186 while (g_queue_peek_tail (log_queue))
188 log_entry = g_queue_pop_tail (log_queue);
190 author = svn_log_entry_get_author (log_entry);
191 date = svn_log_entry_get_date (log_entry);
192 revision = svn_log_entry_get_revision (log_entry);
193 short_log = svn_log_entry_get_short_log (log_entry);
194 full_log = svn_log_entry_get_full_log (log_entry);
196 gtk_list_store_prepend (data->log_store, &iter);
197 gtk_list_store_set (data->log_store, &iter,
198 COL_DIFF_SELECTED, FALSE,
199 COL_AUTHOR, author,
200 COL_DATE, date,
201 COL_REVISION, revision,
202 COL_SHORT_LOG, short_log,
203 COL_FULL_LOG, full_log,
204 -1);
206 g_free (author);
207 g_free (date);
208 g_free (short_log);
209 g_free (full_log);
210 svn_log_entry_destroy (log_entry);
213 report_errors (command, return_code);
215 svn_log_command_destroy (SVN_LOG_COMMAND (command));
217 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view),
218 GTK_TREE_MODEL (data->log_store));
219 g_object_unref (data->log_store);
222 static void
223 on_log_view_button_clicked (GtkButton *button, LogData *data)
225 GtkWidget *log_changes_view;
226 GtkWidget *log_file_entry;
227 GtkWidget *log_diff_previous_button;
228 GtkWidget *log_diff_selected_button;
229 GtkWidget *log_view_selected_button;
230 const gchar *path;
231 SvnLogCommand *log_command;
232 guint pulse_timer_id;
234 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
235 log_file_entry = glade_xml_get_widget (data->gxml, "log_file_entry");
236 log_diff_previous_button = glade_xml_get_widget (data->gxml,
237 "log_diff_previous_button");
238 log_diff_selected_button = glade_xml_get_widget (data->gxml,
239 "log_diff_selected_button");
240 log_view_selected_button = glade_xml_get_widget (data->gxml,
241 "log_view_selected_button");
242 path = gtk_entry_get_text (GTK_ENTRY (log_file_entry));
244 if (data->path)
245 g_free (data->path);
247 data->path = g_strdup (path);
249 if (strlen (path) > 0)
252 log_command = svn_log_command_new ((gchar *) path);
254 pulse_timer_id = status_bar_progress_pulse (data->plugin,
255 _("Subversion: Retrieving"
256 " log..."));
258 g_signal_connect (G_OBJECT (log_command), "command-finished",
259 G_CALLBACK (stop_status_bar_progress_pulse),
260 GUINT_TO_POINTER (pulse_timer_id));
262 g_signal_connect (G_OBJECT (log_command), "command-finished",
263 G_CALLBACK (on_log_command_finished),
264 data);
266 anjuta_command_start (ANJUTA_COMMAND (log_command));
269 gtk_widget_set_sensitive (log_diff_previous_button, FALSE);
270 gtk_widget_set_sensitive (log_diff_selected_button, FALSE);
271 gtk_widget_set_sensitive (log_view_selected_button, FALSE);
273 gtk_list_store_clear (data->log_store);
276 static void
277 on_cat_command_data_arrived (AnjutaCommand *command, IAnjutaEditor *editor)
279 GQueue *output;
280 gchar *line;
282 output = svn_cat_command_get_output (SVN_CAT_COMMAND (command));
284 while (g_queue_peek_head (output))
286 line = g_queue_pop_head (output);
287 ianjuta_editor_append (editor, line, strlen (line), NULL);
288 g_free (line);
292 static void
293 on_cat_command_finished (AnjutaCommand *command, guint return_code,
294 Subversion *plugin)
296 AnjutaStatus *status;
298 status = anjuta_shell_get_status (ANJUTA_PLUGIN (plugin)->shell,
299 NULL);
301 anjuta_status (status, _("Subversion: File retrieved."), 5);
303 report_errors (command, return_code);
305 svn_cat_command_destroy (SVN_CAT_COMMAND (command));
308 static void
309 on_log_view_selected_button_clicked (GtkButton *button, LogData *data)
311 GtkWidget *log_changes_view;
312 GtkTreeModel *log_store;
313 GtkTreeSelection *selection;
314 GtkTreeIter selected_iter;
315 glong revision;
316 SvnCatCommand *cat_command;;
317 gchar *filename;
318 gchar *editor_name;
319 IAnjutaDocumentManager *docman;
320 IAnjutaEditor *editor;
321 guint pulse_timer_id;
323 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
324 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view));
325 gtk_tree_selection_get_selected (selection, &log_store, &selected_iter);
327 gtk_tree_model_get (log_store, &selected_iter,
328 COL_REVISION, &revision,
329 -1);
331 cat_command = svn_cat_command_new (data->path, revision);
333 filename = get_filename_from_full_path (data->path);
334 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (data->plugin)->shell,
335 IAnjutaDocumentManager, NULL);
336 editor_name = g_strdup_printf ("[Revision %ld] %s", revision, filename);
337 editor = ianjuta_document_manager_add_buffer(docman, editor_name, "",
338 NULL);
339 g_free (filename);
340 g_free (editor_name);
342 pulse_timer_id = status_bar_progress_pulse (data->plugin,
343 _("Subversion: Retrieving "
344 "file..."));
346 g_signal_connect (G_OBJECT (cat_command), "command-finished",
347 G_CALLBACK (stop_status_bar_progress_pulse),
348 GUINT_TO_POINTER (pulse_timer_id));
350 g_signal_connect (G_OBJECT (cat_command), "data-arrived",
351 G_CALLBACK (on_cat_command_data_arrived),
352 editor);
354 g_signal_connect (G_OBJECT (cat_command), "command-finished",
355 G_CALLBACK (on_cat_command_finished),
356 data->plugin);
358 g_object_weak_ref (G_OBJECT (editor),
359 (GWeakNotify) disconnect_data_arrived_signals,
360 cat_command);
362 anjuta_command_start (ANJUTA_COMMAND (cat_command));
365 static void
366 get_selected_revisions (gpointer revision, gpointer value,
367 SelectedDiffData *data)
369 data->revisions[data->pos] = GPOINTER_TO_INT (revision);
370 data->pos++;
373 static void
374 on_log_diff_selected_button_clicked (GtkButton *button, LogData *data)
376 SelectedDiffData *selected_diff_data;
377 SvnDiffCommand *diff_command;
378 glong revision1;
379 glong revision2;
380 IAnjutaDocumentManager *docman;
381 gchar *filename;
382 gchar *editor_name;
383 IAnjutaEditor *editor;
384 guint pulse_timer_id;
386 if (g_hash_table_size (data->selected_diff_revisions) == 2)
388 selected_diff_data = g_new0 (SelectedDiffData, 1);
390 g_hash_table_foreach (data->selected_diff_revisions,
391 (GHFunc) get_selected_revisions,
392 selected_diff_data);
394 revision1 = MIN (selected_diff_data->revisions[0],
395 selected_diff_data->revisions[1]);
396 revision2 = MAX (selected_diff_data->revisions[0],
397 selected_diff_data->revisions[1]);
399 diff_command = svn_diff_command_new (data->path,
400 revision1,
401 revision2,
402 TRUE);
404 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (data->plugin)->shell,
405 IAnjutaDocumentManager, NULL);
406 filename = get_filename_from_full_path (data->path);
407 editor_name = g_strdup_printf ("[Revisions %ld/%ld] %s.diff",
408 revision1, revision2, filename);
410 editor = ianjuta_document_manager_add_buffer(docman, editor_name, "",
411 NULL);
413 g_free (filename);
414 g_free (editor_name);
416 pulse_timer_id = status_bar_progress_pulse (data->plugin,
417 _("Subversion: Retrieving "
418 "diff..."));
420 g_signal_connect (G_OBJECT (diff_command), "command-finished",
421 G_CALLBACK (stop_status_bar_progress_pulse),
422 GUINT_TO_POINTER (pulse_timer_id));
424 g_signal_connect (G_OBJECT (diff_command), "data-arrived",
425 G_CALLBACK (send_diff_command_output_to_editor),
426 editor);
428 g_signal_connect (G_OBJECT (diff_command), "command-finished",
429 G_CALLBACK (on_diff_command_finished),
430 data->plugin);
432 g_object_weak_ref (G_OBJECT (editor),
433 (GWeakNotify) disconnect_data_arrived_signals,
434 diff_command);
436 anjuta_command_start (ANJUTA_COMMAND (diff_command));
438 g_free (selected_diff_data);
443 static void
444 on_log_diff_previous_button_clicked (GtkButton *button, LogData *data)
446 GtkWidget *log_changes_view;
447 GtkTreeModel *log_store;
448 GtkTreeSelection *selection;
449 GtkTreeIter selected_iter;
450 glong revision;
451 SvnDiffCommand *diff_command;
452 IAnjutaDocumentManager *docman;
453 gchar *filename;
454 gchar *editor_name;
455 IAnjutaEditor *editor;
456 guint pulse_timer_id;
458 log_changes_view = glade_xml_get_widget (data->gxml, "log_changes_view");
459 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view));
460 gtk_tree_selection_get_selected (selection, &log_store, &selected_iter);
462 gtk_tree_model_get (log_store, &selected_iter,
463 COL_REVISION, &revision,
464 -1);
466 diff_command = svn_diff_command_new (data->path, SVN_DIFF_REVISION_PREVIOUS,
467 revision, TRUE);
469 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (data->plugin)->shell,
470 IAnjutaDocumentManager, NULL);
471 filename = get_filename_from_full_path (data->path);
472 editor_name = g_strdup_printf ("[Revisions %ld/%ld] %s.diff",
473 revision - 1, revision, filename);
474 editor = ianjuta_document_manager_add_buffer(docman, editor_name, "",
475 NULL);
477 g_free (filename);
478 g_free (editor_name);
480 pulse_timer_id = status_bar_progress_pulse (data->plugin,
481 _("Subversion: Retrieving "
482 "diff..."));
484 g_signal_connect (G_OBJECT (diff_command), "command-finished",
485 G_CALLBACK (stop_status_bar_progress_pulse),
486 GUINT_TO_POINTER (pulse_timer_id));
488 g_signal_connect (G_OBJECT (diff_command), "data-arrived",
489 G_CALLBACK (send_diff_command_output_to_editor),
490 editor);
492 g_signal_connect (G_OBJECT (diff_command), "command-finished",
493 G_CALLBACK (on_diff_command_finished),
494 data->plugin);
496 g_object_weak_ref (G_OBJECT (editor),
497 (GWeakNotify) disconnect_data_arrived_signals,
498 diff_command);
500 anjuta_command_start (ANJUTA_COMMAND (diff_command));
503 static void
504 on_subversion_log_vbox_destroy (GtkObject *subversion_log, LogData *data)
506 g_hash_table_destroy (data->selected_diff_revisions);
507 g_free (data->path);
508 g_free (data);
511 static gboolean
512 on_log_changes_view_row_selected (GtkTreeSelection *selection,
513 GtkTreeModel *model,
514 GtkTreePath *path,
515 gboolean path_currently_selected,
516 LogData *data)
518 GtkTreeIter iter;
519 GtkWidget *log_message_text;
520 GtkWidget *log_diff_previous_button;
521 GtkWidget *log_view_selected_button;
522 GtkTextBuffer *buffer;
523 gchar *log_message;
525 gtk_tree_model_get_iter (model, &iter, path);
526 log_message_text = glade_xml_get_widget (data->gxml, "log_message_text");
527 log_diff_previous_button = glade_xml_get_widget (data->gxml,
528 "log_diff_previous_button");
529 log_view_selected_button = glade_xml_get_widget (data->gxml,
530 "log_view_selected_button");
531 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_message_text));
532 gtk_tree_model_get (model, &iter,
533 COL_FULL_LOG, &log_message,
534 -1);
536 gtk_text_buffer_set_text (buffer, log_message, strlen (log_message));
537 gtk_widget_set_sensitive (log_diff_previous_button,
538 TRUE);
539 if (data->path)
541 gtk_widget_set_sensitive (log_view_selected_button,
542 !g_file_test (data->path,
543 G_FILE_TEST_IS_DIR));
546 return TRUE;
549 GtkWidget *
550 subversion_log_window_create (Subversion *plugin)
552 LogData *data;
553 GtkWidget *subversion_log;
554 GtkWidget *subversion_log_vbox;
555 GtkWidget *log_changes_view;
556 GtkWidget *log_whole_project_check;
557 GtkWidget *log_file_entry;
558 GtkWidget *log_view_button;
559 GtkWidget *log_diff_previous_button;
560 GtkWidget *log_diff_selected_button;
561 GtkWidget *log_view_selected_button;
562 GtkListStore *log_list_store;
563 GtkTreeSelection *selection;
565 data = g_new0 (LogData, 1);
566 data->gxml = plugin->log_gxml;
567 data->selected_diff_revisions = g_hash_table_new (g_direct_hash,
568 g_direct_equal);
569 data->plugin = plugin;
570 data->path = NULL;
572 subversion_log = glade_xml_get_widget (plugin->log_gxml, "subversion_log");
573 subversion_log_vbox = glade_xml_get_widget (plugin->log_gxml, "subversion_log_vbox");
574 log_changes_view = glade_xml_get_widget (plugin->log_gxml, "log_changes_view");
575 log_whole_project_check = glade_xml_get_widget (plugin->log_gxml,
576 "log_whole_project_check");
577 log_file_entry = glade_xml_get_widget (plugin->log_gxml, "log_file_entry");
578 log_view_button = glade_xml_get_widget (plugin->log_gxml, "log_view_button");
579 log_diff_previous_button = glade_xml_get_widget (plugin->log_gxml,
580 "log_diff_previous_button");
581 log_diff_selected_button = glade_xml_get_widget (plugin->log_gxml,
582 "log_diff_selected_button");
583 log_view_selected_button = glade_xml_get_widget (plugin->log_gxml,
584 "log_view_selected_button");
586 g_signal_connect (G_OBJECT (log_view_button), "clicked",
587 G_CALLBACK (on_log_view_button_clicked),
588 data);
590 g_signal_connect (G_OBJECT (log_diff_previous_button), "clicked",
591 G_CALLBACK (on_log_diff_previous_button_clicked),
592 data);
594 g_signal_connect (G_OBJECT (log_diff_selected_button), "clicked",
595 G_CALLBACK (on_log_diff_selected_button_clicked),
596 data);
598 g_signal_connect (G_OBJECT (log_view_selected_button), "clicked",
599 G_CALLBACK (on_log_view_selected_button_clicked),
600 data);
603 g_object_set_data (G_OBJECT (log_whole_project_check), "fileentry",
604 log_file_entry);
605 g_signal_connect (G_OBJECT (log_whole_project_check), "toggled",
606 G_CALLBACK (on_whole_project_toggled), plugin);
607 init_whole_project (plugin, log_whole_project_check, FALSE);
609 log_list_store = gtk_list_store_new (NUM_COLS,
610 G_TYPE_BOOLEAN,
611 G_TYPE_STRING,
612 G_TYPE_STRING,
613 G_TYPE_LONG,
614 G_TYPE_STRING,
615 G_TYPE_STRING);
616 create_columns (data);
617 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view),
618 GTK_TREE_MODEL (log_list_store));
620 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view));
621 gtk_tree_selection_set_select_function (selection,
622 (GtkTreeSelectionFunc) on_log_changes_view_row_selected,
623 data, NULL);
625 data->log_store = log_list_store;
626 g_object_unref (log_list_store);
628 g_signal_connect (G_OBJECT (subversion_log_vbox), "destroy",
629 G_CALLBACK (on_subversion_log_vbox_destroy),
630 data);
632 g_object_ref (subversion_log_vbox);
633 gtk_container_remove (GTK_CONTAINER (subversion_log), subversion_log_vbox);
634 gtk_widget_destroy (subversion_log);
636 return subversion_log_vbox;
639 void
640 on_menu_subversion_log (GtkAction *action, Subversion *plugin)
642 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin)->shell,
643 plugin->log_viewer, NULL);
646 void
647 on_fm_subversion_log (GtkAction *action, Subversion *plugin)
649 GtkWidget *log_file_entry;
651 log_file_entry = glade_xml_get_widget (plugin->log_gxml, "log_file_entry");
653 gtk_entry_set_text (GTK_ENTRY (log_file_entry),
654 plugin->fm_current_filename);
656 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin)->shell,
657 plugin->log_viewer, NULL);
660 void
661 subversion_log_set_whole_project_sensitive (GladeXML *log_gxml,
662 gboolean sensitive)
664 GtkWidget *log_whole_project_check;
666 log_whole_project_check = glade_xml_get_widget (log_gxml,
667 "log_whole_project_check");
669 gtk_widget_set_sensitive (log_whole_project_check, sensitive);
671 if (!sensitive)
673 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_whole_project_check),
674 FALSE);