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"
27 #define BROWSE_BUTTON_LOG_DIALOG "browse_button_log_dialog"
40 GtkListStore
*log_store
;
41 GHashTable
*selected_diff_revisions
;
56 on_diff_selected_column_toggled (GtkCellRendererToggle
*renderer
,
62 GtkWidget
*log_diff_selected_button
;
65 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (data
->log_store
),
67 gtk_tree_model_get (GTK_TREE_MODEL (data
->log_store
), &iter
,
68 COL_DIFF_SELECTED
, &selected
,
69 COL_REVISION
, &revision
,
72 log_diff_selected_button
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
,
73 "log_diff_selected_button"));
79 /* Only allow two log items to be selected at once. */
80 if (g_hash_table_size (data
->selected_diff_revisions
) < 2)
82 g_hash_table_insert (data
->selected_diff_revisions
,
83 GINT_TO_POINTER (revision
), NULL
);
85 gtk_list_store_set (data
->log_store
, &iter
,
86 COL_DIFF_SELECTED
, TRUE
,
92 g_hash_table_remove (data
->selected_diff_revisions
,
93 GINT_TO_POINTER (revision
));
95 gtk_list_store_set (data
->log_store
, &iter
,
96 COL_DIFF_SELECTED
, FALSE
,
100 /* For diff selected to work, exactly 2 revisions must be selected. */
101 gtk_widget_set_sensitive (log_diff_selected_button
,
102 g_hash_table_size (data
->selected_diff_revisions
) == 2);
107 create_columns (LogData
*data
)
109 GtkWidget
*log_changes_view
;
110 GtkTreeViewColumn
*column
;
111 GtkCellRenderer
*renderer
;
113 log_changes_view
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
, "log_changes_view"));
115 /* Selected for diff */
116 column
= gtk_tree_view_column_new ();
117 renderer
= gtk_cell_renderer_toggle_new ();
118 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
119 gtk_tree_view_column_set_title (column
, _("Diff"));
120 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
121 gtk_tree_view_column_add_attribute (column
, renderer
, "active",
124 g_signal_connect (G_OBJECT (renderer
), "toggled",
125 G_CALLBACK (on_diff_selected_column_toggled
),
129 column
= gtk_tree_view_column_new ();
130 renderer
= gtk_cell_renderer_text_new ();
131 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
132 gtk_tree_view_column_set_title (column
, _("Author"));
133 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
134 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
138 column
= gtk_tree_view_column_new ();
139 renderer
= gtk_cell_renderer_text_new ();
140 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
141 gtk_tree_view_column_set_title (column
, _("Date"));
142 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
143 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
148 column
= gtk_tree_view_column_new ();
149 renderer
= gtk_cell_renderer_text_new ();
150 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
151 gtk_tree_view_column_set_title (column
, _("Revision"));
152 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
153 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
157 column
= gtk_tree_view_column_new ();
158 renderer
= gtk_cell_renderer_text_new ();
159 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
160 gtk_tree_view_column_set_title (column
, _("Short Log"));
161 gtk_tree_view_append_column (GTK_TREE_VIEW (log_changes_view
), column
);
162 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
168 on_log_command_finished (AnjutaCommand
*command
, guint return_code
,
171 GtkWidget
*log_changes_view
;
173 SvnLogEntry
*log_entry
;
181 g_object_ref (data
->log_store
);
182 log_changes_view
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
, "log_changes_view"));
183 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view
), NULL
);
184 g_hash_table_remove_all (data
->selected_diff_revisions
);
186 log_queue
= svn_log_command_get_entry_queue (SVN_LOG_COMMAND (command
));
188 while (g_queue_peek_tail (log_queue
))
190 log_entry
= g_queue_pop_tail (log_queue
);
192 author
= svn_log_entry_get_author (log_entry
);
193 date
= svn_log_entry_get_date (log_entry
);
194 revision
= svn_log_entry_get_revision (log_entry
);
195 short_log
= svn_log_entry_get_short_log (log_entry
);
196 full_log
= svn_log_entry_get_full_log (log_entry
);
198 gtk_list_store_prepend (data
->log_store
, &iter
);
199 gtk_list_store_set (data
->log_store
, &iter
,
200 COL_DIFF_SELECTED
, FALSE
,
203 COL_REVISION
, revision
,
204 COL_SHORT_LOG
, short_log
,
205 COL_FULL_LOG
, full_log
,
212 svn_log_entry_destroy (log_entry
);
215 report_errors (command
, return_code
);
217 svn_log_command_destroy (SVN_LOG_COMMAND (command
));
219 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view
),
220 GTK_TREE_MODEL (data
->log_store
));
221 g_object_unref (data
->log_store
);
225 subversion_show_log (LogData
*data
)
227 GtkWidget
*log_changes_view
;
228 GtkWidget
*log_file_entry
;
229 GtkWidget
*log_diff_previous_button
;
230 GtkWidget
*log_diff_selected_button
;
231 GtkWidget
*log_view_selected_button
;
233 SvnLogCommand
*log_command
;
234 guint pulse_timer_id
;
236 log_changes_view
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
, "log_changes_view"));
237 log_file_entry
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
, "log_file_entry"));
238 log_diff_previous_button
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
,
239 "log_diff_previous_button"));
240 log_diff_selected_button
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
,
241 "log_diff_selected_button"));
242 log_view_selected_button
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
,
243 "log_view_selected_button"));
244 path
= gtk_entry_get_text (GTK_ENTRY (log_file_entry
));
249 data
->path
= g_strdup (path
);
251 if (strlen (path
) > 0)
254 log_command
= svn_log_command_new ((gchar
*) path
);
256 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
257 _("Subversion: Retrieving"
260 g_signal_connect (G_OBJECT (log_command
), "command-finished",
261 G_CALLBACK (stop_status_bar_progress_pulse
),
262 GUINT_TO_POINTER (pulse_timer_id
));
264 g_signal_connect (G_OBJECT (log_command
), "command-finished",
265 G_CALLBACK (on_log_command_finished
),
268 anjuta_command_start (ANJUTA_COMMAND (log_command
));
271 gtk_widget_set_sensitive (log_diff_previous_button
, FALSE
);
272 gtk_widget_set_sensitive (log_diff_selected_button
, FALSE
);
273 gtk_widget_set_sensitive (log_view_selected_button
, FALSE
);
275 gtk_list_store_clear (data
->log_store
);
279 on_log_view_button_clicked (GtkButton
*button
, LogData
*data
)
281 subversion_show_log (data
);
285 on_cat_command_data_arrived (AnjutaCommand
*command
, IAnjutaEditor
*editor
)
290 output
= svn_cat_command_get_output (SVN_CAT_COMMAND (command
));
292 while (g_queue_peek_head (output
))
294 line
= g_queue_pop_head (output
);
295 ianjuta_editor_append (editor
, line
, strlen (line
), NULL
);
301 on_cat_command_finished (AnjutaCommand
*command
, guint return_code
,
304 AnjutaStatus
*status
;
306 status
= anjuta_shell_get_status (ANJUTA_PLUGIN (plugin
)->shell
,
309 anjuta_status (status
, _("Subversion: File retrieved."), 5);
311 report_errors (command
, return_code
);
313 svn_cat_command_destroy (SVN_CAT_COMMAND (command
));
317 on_log_view_selected_button_clicked (GtkButton
*button
, LogData
*data
)
319 GtkWidget
*log_changes_view
;
320 GtkTreeModel
*log_store
;
321 GtkTreeSelection
*selection
;
322 GtkTreeIter selected_iter
;
324 SvnCatCommand
*cat_command
;;
327 IAnjutaDocumentManager
*docman
;
328 IAnjutaEditor
*editor
;
329 guint pulse_timer_id
;
331 log_changes_view
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
, "log_changes_view"));
332 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view
));
333 gtk_tree_selection_get_selected (selection
, &log_store
, &selected_iter
);
335 gtk_tree_model_get (log_store
, &selected_iter
,
336 COL_REVISION
, &revision
,
339 cat_command
= svn_cat_command_new (data
->path
, revision
);
341 filename
= get_filename_from_full_path (data
->path
);
342 docman
= anjuta_shell_get_interface (ANJUTA_PLUGIN (data
->plugin
)->shell
,
343 IAnjutaDocumentManager
, NULL
);
344 editor_name
= g_strdup_printf ("[Revision %ld] %s", revision
, filename
);
345 editor
= ianjuta_document_manager_add_buffer(docman
, editor_name
, "",
348 g_free (editor_name
);
350 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
351 _("Subversion: Retrieving "
354 g_signal_connect (G_OBJECT (cat_command
), "command-finished",
355 G_CALLBACK (stop_status_bar_progress_pulse
),
356 GUINT_TO_POINTER (pulse_timer_id
));
358 g_signal_connect (G_OBJECT (cat_command
), "data-arrived",
359 G_CALLBACK (on_cat_command_data_arrived
),
362 g_signal_connect (G_OBJECT (cat_command
), "command-finished",
363 G_CALLBACK (on_cat_command_finished
),
366 g_object_weak_ref (G_OBJECT (editor
),
367 (GWeakNotify
) disconnect_data_arrived_signals
,
370 anjuta_command_start (ANJUTA_COMMAND (cat_command
));
374 get_selected_revisions (gpointer revision
, gpointer value
,
375 SelectedDiffData
*data
)
377 data
->revisions
[data
->pos
] = GPOINTER_TO_INT (revision
);
382 on_log_diff_selected_button_clicked (GtkButton
*button
, LogData
*data
)
384 SelectedDiffData
*selected_diff_data
;
385 SvnDiffCommand
*diff_command
;
388 IAnjutaDocumentManager
*docman
;
391 IAnjutaEditor
*editor
;
392 guint pulse_timer_id
;
394 if (g_hash_table_size (data
->selected_diff_revisions
) == 2)
396 selected_diff_data
= g_new0 (SelectedDiffData
, 1);
398 g_hash_table_foreach (data
->selected_diff_revisions
,
399 (GHFunc
) get_selected_revisions
,
402 revision1
= MIN (selected_diff_data
->revisions
[0],
403 selected_diff_data
->revisions
[1]);
404 revision2
= MAX (selected_diff_data
->revisions
[0],
405 selected_diff_data
->revisions
[1]);
407 diff_command
= svn_diff_command_new (data
->path
,
410 data
->plugin
->project_root_dir
,
413 docman
= anjuta_shell_get_interface (ANJUTA_PLUGIN (data
->plugin
)->shell
,
414 IAnjutaDocumentManager
, NULL
);
415 filename
= get_filename_from_full_path (data
->path
);
416 editor_name
= g_strdup_printf ("[Revisions %ld/%ld] %s.diff",
417 revision1
, revision2
, filename
);
419 editor
= ianjuta_document_manager_add_buffer(docman
, editor_name
, "",
423 g_free (editor_name
);
425 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
426 _("Subversion: Retrieving "
429 g_signal_connect (G_OBJECT (diff_command
), "command-finished",
430 G_CALLBACK (stop_status_bar_progress_pulse
),
431 GUINT_TO_POINTER (pulse_timer_id
));
433 g_signal_connect (G_OBJECT (diff_command
), "data-arrived",
434 G_CALLBACK (send_diff_command_output_to_editor
),
437 g_signal_connect (G_OBJECT (diff_command
), "command-finished",
438 G_CALLBACK (on_diff_command_finished
),
441 g_object_weak_ref (G_OBJECT (editor
),
442 (GWeakNotify
) disconnect_data_arrived_signals
,
445 anjuta_command_start (ANJUTA_COMMAND (diff_command
));
447 g_free (selected_diff_data
);
453 on_log_diff_previous_button_clicked (GtkButton
*button
, LogData
*data
)
455 GtkWidget
*log_changes_view
;
456 GtkTreeModel
*log_store
;
457 GtkTreeSelection
*selection
;
458 GtkTreeIter selected_iter
;
460 SvnDiffCommand
*diff_command
;
461 IAnjutaDocumentManager
*docman
;
464 IAnjutaEditor
*editor
;
465 guint pulse_timer_id
;
467 log_changes_view
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
, "log_changes_view"));
468 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view
));
469 gtk_tree_selection_get_selected (selection
, &log_store
, &selected_iter
);
471 gtk_tree_model_get (log_store
, &selected_iter
,
472 COL_REVISION
, &revision
,
475 diff_command
= svn_diff_command_new (data
->path
,
476 SVN_DIFF_REVISION_PREVIOUS
,
478 data
->plugin
->project_root_dir
,
481 docman
= anjuta_shell_get_interface (ANJUTA_PLUGIN (data
->plugin
)->shell
,
482 IAnjutaDocumentManager
, NULL
);
483 filename
= get_filename_from_full_path (data
->path
);
484 editor_name
= g_strdup_printf ("[Revisions %ld/%ld] %s.diff",
485 revision
- 1, revision
, filename
);
486 editor
= ianjuta_document_manager_add_buffer(docman
, editor_name
, "",
490 g_free (editor_name
);
492 pulse_timer_id
= status_bar_progress_pulse (data
->plugin
,
493 _("Subversion: Retrieving "
496 g_signal_connect (G_OBJECT (diff_command
), "command-finished",
497 G_CALLBACK (stop_status_bar_progress_pulse
),
498 GUINT_TO_POINTER (pulse_timer_id
));
500 g_signal_connect (G_OBJECT (diff_command
), "data-arrived",
501 G_CALLBACK (send_diff_command_output_to_editor
),
504 g_signal_connect (G_OBJECT (diff_command
), "command-finished",
505 G_CALLBACK (on_diff_command_finished
),
508 g_object_weak_ref (G_OBJECT (editor
),
509 (GWeakNotify
) disconnect_data_arrived_signals
,
512 anjuta_command_start (ANJUTA_COMMAND (diff_command
));
516 on_subversion_log_vbox_destroy (GtkWidget
*subversion_log
, LogData
*data
)
518 g_hash_table_destroy (data
->selected_diff_revisions
);
524 on_log_changes_view_row_selected (GtkTreeSelection
*selection
,
527 gboolean path_currently_selected
,
531 GtkWidget
*log_message_text
;
532 GtkWidget
*log_diff_previous_button
;
533 GtkWidget
*log_view_selected_button
;
534 GtkTextBuffer
*buffer
;
537 gtk_tree_model_get_iter (model
, &iter
, path
);
538 log_message_text
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
, "log_message_text"));
539 log_diff_previous_button
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
,
540 "log_diff_previous_button"));
541 log_view_selected_button
= GTK_WIDGET (gtk_builder_get_object (data
->bxml
,
542 "log_view_selected_button"));
543 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (log_message_text
));
544 gtk_tree_model_get (model
, &iter
,
545 COL_FULL_LOG
, &log_message
,
548 gtk_text_buffer_set_text (buffer
, log_message
, strlen (log_message
));
549 gtk_widget_set_sensitive (log_diff_previous_button
,
553 gtk_widget_set_sensitive (log_view_selected_button
,
554 !g_file_test (data
->path
,
555 G_FILE_TEST_IS_DIR
));
562 subversion_log_window_create (Subversion
*plugin
)
565 GtkWidget
*subversion_log
;
566 GtkWidget
*subversion_log_vbox
;
567 GtkWidget
*log_changes_view
;
568 GtkWidget
*log_whole_project_check
;
569 GtkWidget
*log_file_entry
;
570 GtkWidget
*log_view_button
;
571 GtkWidget
*log_diff_previous_button
;
572 GtkWidget
*log_diff_selected_button
;
573 GtkWidget
*log_view_selected_button
;
575 GtkListStore
*log_list_store
;
576 GtkTreeSelection
*selection
;
578 data
= g_new0 (LogData
, 1);
579 data
->bxml
= plugin
->log_bxml
;
580 data
->selected_diff_revisions
= g_hash_table_new (g_direct_hash
,
582 data
->plugin
= plugin
;
585 subversion_log
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
, "subversion_log"));
586 subversion_log_vbox
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
, "subversion_log_vbox"));
587 log_changes_view
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
, "log_changes_view"));
588 log_whole_project_check
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
,
589 "log_whole_project_check"));
590 log_file_entry
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
, "log_file_entry"));
591 log_view_button
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
, "log_view_button"));
592 log_diff_previous_button
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
,
593 "log_diff_previous_button"));
594 log_diff_selected_button
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
,
595 "log_diff_selected_button"));
596 log_view_selected_button
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
,
597 "log_view_selected_button"));
598 button
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
, BROWSE_BUTTON_LOG_DIALOG
));
599 g_signal_connect(G_OBJECT(button
), "clicked",
600 G_CALLBACK(on_subversion_browse_button_clicked
), log_file_entry
);
602 g_signal_connect (G_OBJECT (log_view_button
), "clicked",
603 G_CALLBACK (on_log_view_button_clicked
),
606 g_signal_connect (G_OBJECT (log_diff_previous_button
), "clicked",
607 G_CALLBACK (on_log_diff_previous_button_clicked
),
610 g_signal_connect (G_OBJECT (log_diff_selected_button
), "clicked",
611 G_CALLBACK (on_log_diff_selected_button_clicked
),
614 g_signal_connect (G_OBJECT (log_view_selected_button
), "clicked",
615 G_CALLBACK (on_log_view_selected_button_clicked
),
619 g_object_set_data (G_OBJECT (log_whole_project_check
), "fileentry",
621 g_object_set_data (G_OBJECT (subversion_log_vbox
), "log-data", data
);
622 g_signal_connect (G_OBJECT (log_whole_project_check
), "toggled",
623 G_CALLBACK (on_whole_project_toggled
), plugin
);
624 init_whole_project (plugin
, log_whole_project_check
, FALSE
);
626 log_list_store
= gtk_list_store_new (NUM_COLS
,
633 create_columns (data
);
634 gtk_tree_view_set_model (GTK_TREE_VIEW (log_changes_view
),
635 GTK_TREE_MODEL (log_list_store
));
637 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (log_changes_view
));
638 gtk_tree_selection_set_select_function (selection
,
639 (GtkTreeSelectionFunc
) on_log_changes_view_row_selected
,
642 data
->log_store
= log_list_store
;
643 g_object_unref (log_list_store
);
645 g_signal_connect (G_OBJECT (subversion_log_vbox
), "destroy",
646 G_CALLBACK (on_subversion_log_vbox_destroy
),
649 g_object_ref (subversion_log_vbox
);
650 gtk_container_remove (GTK_CONTAINER (subversion_log
), subversion_log_vbox
);
651 gtk_widget_destroy (subversion_log
);
653 return subversion_log_vbox
;
657 on_menu_subversion_log (GtkAction
*action
, Subversion
*plugin
)
659 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin
)->shell
,
660 plugin
->log_viewer
, NULL
);
664 on_fm_subversion_log (GtkAction
*action
, Subversion
*plugin
)
666 GtkWidget
*log_file_entry
;
667 GtkWidget
*log_whole_project_check
;
669 log_file_entry
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
, "log_file_entry"));
670 log_whole_project_check
= GTK_WIDGET (gtk_builder_get_object (plugin
->log_bxml
,
671 "log_whole_project_check"));
673 gtk_entry_set_text (GTK_ENTRY (log_file_entry
),
674 plugin
->fm_current_filename
);
675 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_whole_project_check
),
678 anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin
)->shell
,
679 plugin
->log_viewer
, NULL
);
681 subversion_show_log (g_object_get_data (G_OBJECT (plugin
->log_viewer
),
686 subversion_log_set_whole_project_sensitive (GtkBuilder
*log_bxml
,
689 GtkWidget
*log_whole_project_check
;
691 log_whole_project_check
= GTK_WIDGET (gtk_builder_get_object (log_bxml
,
692 "log_whole_project_check"));
694 gtk_widget_set_sensitive (log_whole_project_check
, sensitive
);
698 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (log_whole_project_check
),