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 "subversion-log-dialog.h"
38 GtkListStore
*log_store
;
39 GHashTable
*selected_diff_revisions
;
54 on_diff_selected_column_toggled (GtkCellRendererToggle
*renderer
,
60 GtkWidget
*log_diff_selected_button
;
63 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (data
->log_store
),
65 gtk_tree_model_get (GTK_TREE_MODEL (data
->log_store
), &iter
,
66 COL_DIFF_SELECTED
, &selected
,
67 COL_REVISION
, &revision
,
70 log_diff_selected_button
= glade_xml_get_widget (data
->gxml
,
71 "log_diff_selected_button");
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
,
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
,
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);
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",
122 g_signal_connect (G_OBJECT (renderer
), "toggled",
123 G_CALLBACK (on_diff_selected_column_toggled
),
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",
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",
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",
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",
166 on_log_command_finished (AnjutaCommand
*command
, guint return_code
,
169 GtkWidget
*log_changes_view
;
171 SvnLogEntry
*log_entry
;
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
,
201 COL_REVISION
, revision
,
202 COL_SHORT_LOG
, short_log
,
203 COL_FULL_LOG
, 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
);
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
;
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
));
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"
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
),
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
);
277 on_cat_command_data_arrived (AnjutaCommand
*command
, IAnjutaEditor
*editor
)
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
);
293 on_cat_command_finished (AnjutaCommand
*command
, guint return_code
,
296 AnjutaStatus
*status
;
298 status
= anjuta_shell_get_status (ANJUTA_PLUGIN (plugin
)->shell
,
301 anjuta_status (status
, _("Subversion: File retrieved."), 5);
303 report_errors (command
, return_code
);
305 svn_cat_command_destroy (SVN_CAT_COMMAND (command
));
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
;
316 SvnCatCommand
*cat_command
;;
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
,
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
, "",
340 g_free (editor_name
);
342 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
343 _("Subversion: Retrieving "
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
),
354 g_signal_connect (G_OBJECT (cat_command
), "command-finished",
355 G_CALLBACK (on_cat_command_finished
),
358 g_object_weak_ref (G_OBJECT (editor
),
359 (GWeakNotify
) disconnect_data_arrived_signals
,
362 anjuta_command_start (ANJUTA_COMMAND (cat_command
));
366 get_selected_revisions (gpointer revision
, gpointer value
,
367 SelectedDiffData
*data
)
369 data
->revisions
[data
->pos
] = GPOINTER_TO_INT (revision
);
374 on_log_diff_selected_button_clicked (GtkButton
*button
, LogData
*data
)
376 SelectedDiffData
*selected_diff_data
;
377 SvnDiffCommand
*diff_command
;
380 IAnjutaDocumentManager
*docman
;
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
,
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
,
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
, "",
414 g_free (editor_name
);
416 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
417 _("Subversion: Retrieving "
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
),
428 g_signal_connect (G_OBJECT (diff_command
), "command-finished",
429 G_CALLBACK (on_diff_command_finished
),
432 g_object_weak_ref (G_OBJECT (editor
),
433 (GWeakNotify
) disconnect_data_arrived_signals
,
436 anjuta_command_start (ANJUTA_COMMAND (diff_command
));
438 g_free (selected_diff_data
);
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
;
451 SvnDiffCommand
*diff_command
;
452 IAnjutaDocumentManager
*docman
;
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
,
466 diff_command
= svn_diff_command_new (data
->path
, SVN_DIFF_REVISION_PREVIOUS
,
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
, "",
478 g_free (editor_name
);
480 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
481 _("Subversion: Retrieving "
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
),
492 g_signal_connect (G_OBJECT (diff_command
), "command-finished",
493 G_CALLBACK (on_diff_command_finished
),
496 g_object_weak_ref (G_OBJECT (editor
),
497 (GWeakNotify
) disconnect_data_arrived_signals
,
500 anjuta_command_start (ANJUTA_COMMAND (diff_command
));
504 on_subversion_log_vbox_destroy (GtkObject
*subversion_log
, LogData
*data
)
506 g_hash_table_destroy (data
->selected_diff_revisions
);
512 on_log_changes_view_row_selected (GtkTreeSelection
*selection
,
515 gboolean path_currently_selected
,
519 GtkWidget
*log_message_text
;
520 GtkWidget
*log_diff_previous_button
;
521 GtkWidget
*log_view_selected_button
;
522 GtkTextBuffer
*buffer
;
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
,
536 gtk_text_buffer_set_text (buffer
, log_message
, strlen (log_message
));
537 gtk_widget_set_sensitive (log_diff_previous_button
,
541 gtk_widget_set_sensitive (log_view_selected_button
,
542 !g_file_test (data
->path
,
543 G_FILE_TEST_IS_DIR
));
550 subversion_log_window_create (Subversion
*plugin
)
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
,
569 data
->plugin
= plugin
;
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
),
590 g_signal_connect (G_OBJECT (log_diff_previous_button
), "clicked",
591 G_CALLBACK (on_log_diff_previous_button_clicked
),
594 g_signal_connect (G_OBJECT (log_diff_selected_button
), "clicked",
595 G_CALLBACK (on_log_diff_selected_button_clicked
),
598 g_signal_connect (G_OBJECT (log_view_selected_button
), "clicked",
599 G_CALLBACK (on_log_view_selected_button_clicked
),
603 g_object_set_data (G_OBJECT (log_whole_project_check
), "fileentry",
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
,
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
,
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
),
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
;
640 on_menu_subversion_log (GtkAction
*action
, Subversion
*plugin
)
642 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin
)->shell
,
643 plugin
->log_viewer
, NULL
);
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
);
661 subversion_log_set_whole_project_sensitive (GladeXML
*log_gxml
,
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
);
673 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_whole_project_check
),