1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 Imendio AB
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 #include <glib/gi18n.h>
24 #include <glade/glade.h>
25 #include <gtksourceview/gtksourceview.h>
26 #include <gtksourceview/gtksourcelanguagesmanager.h>
29 #include "giggle-window.h"
30 #include "giggle-error.h"
31 #include "giggle-git.h"
32 #include "giggle-git-branches.h"
33 #include "giggle-git-diff.h"
34 #include "giggle-git-revisions.h"
35 #include "giggle-revision.h"
36 #include "giggle-graph-renderer.h"
37 #include "giggle-personal-details-window.h"
39 typedef struct GiggleWindowPriv GiggleWindowPriv
;
41 struct GiggleWindowPriv
{
42 GtkWidget
*content_vbox
;
43 GtkWidget
*menubar_hbox
;
44 GtkWidget
*revision_treeview
;
45 GtkWidget
*log_textview
;
46 GtkWidget
*diff_textview
;
48 GtkCellRenderer
*graph_renderer
;
50 GtkUIManager
*ui_manager
;
52 GtkRecentManager
*recent_manager
;
53 GtkActionGroup
*recent_action_group
;
57 /* Current job in progress. */
58 GiggleJob
*current_job
;
66 static void window_finalize (GObject
*object
);
67 static void window_setup_revision_treeview (GiggleWindow
*window
);
68 static void window_setup_diff_textview (GiggleWindow
*window
,
70 static void window_update_revision_info (GiggleWindow
*window
,
71 GiggleRevision
*current_revision
,
72 GiggleRevision
*previous_revision
);
73 static void window_add_widget_cb (GtkUIManager
*merge
,
75 GiggleWindow
*window
);
76 static void window_revision_selection_changed_cb (GtkTreeSelection
*selection
,
77 GiggleWindow
*window
);
78 static void window_git_diff_result_callback (GiggleGit
*git
,
82 static void window_revision_cell_data_log_func (GtkTreeViewColumn
*tree_column
,
83 GtkCellRenderer
*cell
,
84 GtkTreeModel
*tree_model
,
87 static void window_revision_cell_data_author_func (GtkTreeViewColumn
*tree_column
,
88 GtkCellRenderer
*cell
,
89 GtkTreeModel
*tree_model
,
92 static void window_revision_cell_data_date_func (GtkTreeViewColumn
*tree_column
,
93 GtkCellRenderer
*cell
,
94 GtkTreeModel
*tree_model
,
97 static void window_action_quit_cb (GtkAction
*action
,
98 GiggleWindow
*window
);
99 static void window_action_open_cb (GtkAction
*action
,
100 GiggleWindow
*window
);
101 static void window_action_save_patch_cb (GtkAction
*action
,
102 GiggleWindow
*window
);
103 static void window_action_personal_details_cb (GtkAction
*action
,
104 GiggleWindow
*window
);
105 static void window_action_about_cb (GtkAction
*action
,
106 GiggleWindow
*window
);
107 static void window_directory_changed_cb (GiggleGit
*git
,
109 GiggleWindow
*window
);
110 static void window_git_dir_changed_cb (GiggleGit
*git
,
112 GiggleWindow
*window
);
113 static void window_recent_repositories_update (GiggleWindow
*window
);
115 static const GtkActionEntry action_entries
[] = {
117 N_("_File"), NULL
, NULL
,
121 N_("_Edit"), NULL
, NULL
,
125 N_("_Help"), NULL
, NULL
,
128 { "Open", GTK_STOCK_OPEN
,
129 N_("_Open"), "<control>O", N_("Open a GIT repository"),
130 G_CALLBACK (window_action_open_cb
)
132 { "SavePatch", GTK_STOCK_SAVE
,
133 N_("_Save patch"), "<control>S", N_("Save a patch"),
134 G_CALLBACK (window_action_save_patch_cb
)
136 { "Quit", GTK_STOCK_QUIT
,
137 N_("_Quit"), "<control>Q", N_("Quit the application"),
138 G_CALLBACK (window_action_quit_cb
)
140 { "PersonalDetails", NULL
,
141 N_("Personal _Details"), NULL
, N_("Personal details"),
142 G_CALLBACK (window_action_personal_details_cb
)
144 { "About", GTK_STOCK_ABOUT
,
145 N_("_About"), NULL
, N_("About this application"),
146 G_CALLBACK (window_action_about_cb
)
150 static const gchar
*ui_layout
=
152 " <menubar name='MainMenubar'>"
153 " <menu action='FileMenu'>"
154 " <menuitem action='Open'/>"
155 " <menuitem action='SavePatch'/>"
157 " <placeholder name='RecentRepositories'/>"
159 " <menuitem action='Quit'/>"
161 " <menu action='EditMenu'>"
162 " <menuitem action='PersonalDetails'/>"
164 " <menu action='HelpMenu'>"
165 " <menuitem action='About'/>"
171 G_DEFINE_TYPE (GiggleWindow
, giggle_window
, GTK_TYPE_WINDOW
)
173 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GIGGLE_TYPE_WINDOW, GiggleWindowPriv))
175 #define RECENT_FILES_GROUP "giggle"
176 #define SAVE_PATCH_UI_PATH "/ui/MainMenubar/FileMenu/SavePatch"
177 #define RECENT_REPOS_PLACEHOLDER_PATH "/ui/MainMenubar/FileMenu/RecentRepositories"
180 giggle_window_class_init (GiggleWindowClass
*class)
182 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
184 object_class
->finalize
= window_finalize
;
186 g_type_class_add_private (object_class
, sizeof (GiggleWindowPriv
));
190 window_create_menu (GiggleWindow
*window
)
192 GiggleWindowPriv
*priv
;
193 GtkActionGroup
*action_group
;
195 GError
*error
= NULL
;
197 priv
= GET_PRIV (window
);
198 priv
->ui_manager
= gtk_ui_manager_new ();
199 g_signal_connect (priv
->ui_manager
,
201 G_CALLBACK (window_add_widget_cb
),
204 action_group
= gtk_action_group_new ("MainActions");
205 gtk_action_group_set_translation_domain (action_group
, GETTEXT_PACKAGE
);
206 gtk_action_group_add_actions (action_group
,
208 G_N_ELEMENTS (action_entries
),
210 gtk_ui_manager_insert_action_group (priv
->ui_manager
, action_group
, 0);
212 gtk_window_add_accel_group (GTK_WINDOW (window
),
213 gtk_ui_manager_get_accel_group (priv
->ui_manager
));
215 g_object_unref (action_group
);
217 gtk_ui_manager_add_ui_from_string (priv
->ui_manager
, ui_layout
, -1, &error
);
219 g_error ("Couldn't create UI: %s}\n", error
->message
);
222 gtk_ui_manager_ensure_update (priv
->ui_manager
);
224 action
= gtk_ui_manager_get_action (priv
->ui_manager
, SAVE_PATCH_UI_PATH
);
225 gtk_action_set_sensitive (action
, FALSE
);
227 /* create recent repositories resources */
228 priv
->recent_action_group
= gtk_action_group_new ("RecentRepositories");
229 gtk_ui_manager_insert_action_group (priv
->ui_manager
, priv
->recent_action_group
, 0);
231 priv
->recent_manager
= gtk_recent_manager_get_default ();
232 g_signal_connect_swapped (priv
->recent_manager
, "changed",
233 G_CALLBACK (window_recent_repositories_update
), window
);
235 window_recent_repositories_update (window
);
239 giggle_window_init (GiggleWindow
*window
)
241 GiggleWindowPriv
*priv
;
244 GError
*error
= NULL
;
246 priv
= GET_PRIV (window
);
248 priv
->git
= giggle_git_get ();
249 g_signal_connect (priv
->git
,
251 G_CALLBACK (window_directory_changed_cb
),
253 g_signal_connect (priv
->git
,
255 G_CALLBACK (window_git_dir_changed_cb
),
258 xml
= glade_xml_new (GLADEDIR
"/main-window.glade",
259 "content_vbox", NULL
);
261 g_error ("Couldn't find glade file, did you install?");
264 priv
->content_vbox
= glade_xml_get_widget (xml
, "content_vbox");
265 gtk_container_add (GTK_CONTAINER (window
), priv
->content_vbox
);
267 priv
->menubar_hbox
= glade_xml_get_widget (xml
, "menubar_hbox");
268 priv
->revision_treeview
= glade_xml_get_widget (xml
, "revision_treeview");
269 window_setup_revision_treeview (window
);
271 priv
->log_textview
= glade_xml_get_widget (xml
, "log_textview");
273 window_setup_diff_textview (
275 glade_xml_get_widget (xml
, "diff_scrolledwindow"));
277 g_object_unref (xml
);
279 window_create_menu (window
);
281 dir
= g_get_current_dir ();
283 if (!giggle_git_set_directory (priv
->git
, dir
, &error
)) {
286 dialog
= gtk_message_dialog_new (GTK_WINDOW (window
),
287 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
290 _("The directory '%s' does not look like a "
291 "GIT repository."), dir
);
293 gtk_dialog_run (GTK_DIALOG (dialog
));
295 gtk_widget_destroy (dialog
);
302 window_finalize (GObject
*object
)
304 GiggleWindowPriv
*priv
;
306 priv
= GET_PRIV (object
);
308 g_object_unref (priv
->ui_manager
);
310 if (priv
->current_job
) {
311 giggle_git_cancel_job (priv
->git
, priv
->current_job
);
312 g_object_unref (priv
->current_job
);
315 g_object_unref (priv
->git
);
316 g_object_unref (priv
->recent_manager
);
317 g_object_unref (priv
->recent_action_group
);
319 G_OBJECT_CLASS (giggle_window_parent_class
)->finalize (object
);
323 window_recent_repositories_add (GiggleWindow
*window
,
324 const gchar
*repository
)
326 static gchar
*groups
[] = { RECENT_FILES_GROUP
, NULL
};
327 GiggleWindowPriv
*priv
;
331 g_return_if_fail (repository
!= NULL
);
333 priv
= GET_PRIV (window
);
335 if(g_str_has_suffix(repository
, "/.git")) {
336 /* "file:///path/to/project/.git" */
337 gchar
* dirname
= g_path_get_dirname(repository
);
338 display_name
= g_path_get_basename(dirname
);
341 /* "file:///path/to/project.git" */
342 gchar
const *separator
;
343 separator
= g_strrstr(repository
, G_DIR_SEPARATOR_S
);
344 g_return_if_fail(separator
&& *separator
);
345 display_name
= g_strdup(separator
+1);
347 data
= g_slice_new0 (GtkRecentData
);
348 data
->display_name
= display_name
;
349 data
->groups
= groups
;
350 data
->mime_type
= g_strdup ("x-directory/normal");
351 data
->app_name
= (gchar
*) g_get_application_name ();
352 data
->app_exec
= g_strjoin (g_get_prgname (), " %u", NULL
);
354 gtk_recent_manager_add_full (priv
->recent_manager
,
359 window_recent_repository_activate (GtkAction
*action
,
360 GiggleWindow
*window
)
362 GiggleWindowPriv
*priv
;
363 const gchar
*directory
;
365 priv
= GET_PRIV (window
);
367 directory
= g_object_get_data (G_OBJECT (action
), "recent-action-path");
368 giggle_git_set_directory (priv
->git
, directory
, NULL
);
372 window_recent_repositories_clear (GiggleWindow
*window
)
374 GiggleWindowPriv
*priv
;
377 priv
= GET_PRIV (window
);
378 actions
= l
= gtk_action_group_list_actions (priv
->recent_action_group
);
380 for (l
= actions
; l
!= NULL
; l
= l
->next
) {
381 gtk_action_group_remove_action (priv
->recent_action_group
, l
->data
);
384 g_list_free (actions
);
387 /* this should not be necessary when there's
388 * GtkRecentManager/GtkUIManager integration
391 window_recent_repositories_reload (GiggleWindow
*window
)
393 GiggleWindowPriv
*priv
;
394 GList
*recent_items
, *l
;
397 guint recent_menu_id
;
398 gchar
*action_name
, *label
;
401 priv
= GET_PRIV (window
);
403 recent_items
= l
= gtk_recent_manager_get_items (priv
->recent_manager
);
404 recent_menu_id
= gtk_ui_manager_new_merge_id (priv
->ui_manager
);
406 /* FIXME: the max count is hardcoded */
407 while (l
&& count
< 10) {
410 if (gtk_recent_info_has_group (info
, RECENT_FILES_GROUP
)) {
411 action_name
= g_strdup_printf ("recent-repository-%d", count
);
412 label
= g_strdup (gtk_recent_info_get_uri_display (info
));
414 /* FIXME: add accel? */
416 action
= gtk_action_new (action_name
,
421 g_object_set_data_full (G_OBJECT (action
), "recent-action-path",
422 g_strdup (gtk_recent_info_get_uri_display (info
)),
423 (GDestroyNotify
) g_free
);
425 g_signal_connect (action
,
427 G_CALLBACK (window_recent_repository_activate
),
430 gtk_action_group_add_action (priv
->recent_action_group
, action
);
432 gtk_ui_manager_add_ui (priv
->ui_manager
,
434 RECENT_REPOS_PLACEHOLDER_PATH
,
437 GTK_UI_MANAGER_MENUITEM
,
440 g_object_unref (action
);
441 g_free (action_name
);
449 g_list_foreach (recent_items
, (GFunc
) gtk_recent_info_unref
, NULL
);
450 g_list_free (recent_items
);
454 window_recent_repositories_update (GiggleWindow
*window
)
456 window_recent_repositories_clear (window
);
457 window_recent_repositories_reload (window
);
461 window_git_get_revisions_cb (GiggleGit
*git
,
466 GiggleWindow
*window
;
467 GiggleWindowPriv
*priv
;
472 window
= GIGGLE_WINDOW (user_data
);
473 priv
= GET_PRIV (window
);
474 store
= gtk_list_store_new (REVISION_NUM_COLS
, GIGGLE_TYPE_REVISION
);
475 revisions
= giggle_git_revisions_get_revisions (GIGGLE_GIT_REVISIONS (job
));
478 gtk_list_store_append (store
, &iter
);
479 gtk_list_store_set (store
, &iter
,
480 REVISION_COL_OBJECT
, g_object_ref ((GObject
*) revisions
->data
),
482 revisions
= revisions
->next
;
485 giggle_graph_renderer_validate_model (GIGGLE_GRAPH_RENDERER (priv
->graph_renderer
), GTK_TREE_MODEL (store
), 0);
486 gtk_tree_view_set_model (GTK_TREE_VIEW (priv
->revision_treeview
), GTK_TREE_MODEL (store
));
487 g_object_unref (store
);
488 g_object_unref (job
);
492 window_git_get_branches_cb (GiggleGit
*git
,
497 /* FIXME: do something with branches */
498 g_object_unref (job
);
502 window_setup_revision_treeview (GiggleWindow
*window
)
504 GiggleWindowPriv
*priv
;
505 GtkCellRenderer
*cell
;
506 GtkTreeSelection
*selection
;
509 priv
= GET_PRIV (window
);
511 priv
->graph_renderer
= giggle_graph_renderer_new ();
512 gtk_tree_view_insert_column_with_attributes (
513 GTK_TREE_VIEW (priv
->revision_treeview
),
516 priv
->graph_renderer
,
517 "revision", REVISION_COL_OBJECT
,
520 cell
= gtk_cell_renderer_text_new ();
522 "ellipsize", PANGO_ELLIPSIZE_END
,
524 n_columns
= gtk_tree_view_insert_column_with_data_func (
525 GTK_TREE_VIEW (priv
->revision_treeview
),
529 window_revision_cell_data_log_func
,
532 gtk_tree_view_column_set_expand (
533 gtk_tree_view_get_column (GTK_TREE_VIEW (priv
->revision_treeview
), n_columns
- 1),
536 cell
= gtk_cell_renderer_text_new ();
537 gtk_tree_view_insert_column_with_data_func (
538 GTK_TREE_VIEW (priv
->revision_treeview
),
542 window_revision_cell_data_author_func
,
546 cell
= gtk_cell_renderer_text_new ();
547 gtk_tree_view_insert_column_with_data_func (
548 GTK_TREE_VIEW (priv
->revision_treeview
),
552 window_revision_cell_data_date_func
,
556 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (priv
->revision_treeview
));
557 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_MULTIPLE
);
558 gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv
->revision_treeview
), TRUE
);
560 g_signal_connect (selection
,
562 G_CALLBACK (window_revision_selection_changed_cb
),
567 window_setup_diff_textview (GiggleWindow
*window
,
570 GiggleWindowPriv
*priv
;
571 PangoFontDescription
*font_desc
;
572 GtkTextBuffer
*buffer
;
573 GtkSourceLanguage
*language
;
574 GtkSourceLanguagesManager
*manager
;
576 priv
= GET_PRIV (window
);
578 priv
->diff_textview
= gtk_source_view_new ();
579 gtk_text_view_set_editable (GTK_TEXT_VIEW (priv
->diff_textview
), FALSE
);
581 font_desc
= pango_font_description_from_string ("monospace");
582 gtk_widget_modify_font (priv
->diff_textview
, font_desc
);
583 pango_font_description_free (font_desc
);
585 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv
->diff_textview
));
587 manager
= gtk_source_languages_manager_new ();
588 language
= gtk_source_languages_manager_get_language_from_mime_type (
589 manager
, "text/x-patch");
591 gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer
), language
);
592 gtk_source_buffer_set_highlight (GTK_SOURCE_BUFFER (buffer
), TRUE
);
594 g_object_unref (manager
);
596 gtk_widget_show (priv
->diff_textview
);
598 gtk_container_add (GTK_CONTAINER (scrolled
), priv
->diff_textview
);
601 /* Update revision info. If previous_revision is not NULL, a diff between it and
602 * the current revision will be shown.
605 window_update_revision_info (GiggleWindow
*window
,
606 GiggleRevision
*current_revision
,
607 GiggleRevision
*previous_revision
)
609 GiggleWindowPriv
*priv
;
615 priv
= GET_PRIV (window
);
617 if (current_revision
) {
618 sha
= giggle_revision_get_sha (current_revision
);
619 log
= giggle_revision_get_long_log (current_revision
);
621 log
= giggle_revision_get_short_log (current_revision
);
631 str
= g_strdup_printf ("%s\n%s", sha
, log
);
633 gtk_text_buffer_set_text (
634 gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv
->log_textview
)),
639 /* Clear the diff view until we get new content. */
640 gtk_text_buffer_set_text (
641 gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv
->diff_textview
)),
644 if (priv
->current_job
) {
645 giggle_git_cancel_job (priv
->git
, priv
->current_job
);
646 g_object_unref (priv
->current_job
);
647 priv
->current_job
= NULL
;
650 if (current_revision
&& previous_revision
) {
651 action
= gtk_ui_manager_get_action (priv
->ui_manager
, SAVE_PATCH_UI_PATH
);
652 gtk_action_set_sensitive (action
, FALSE
);
654 priv
->current_job
= giggle_git_diff_new (previous_revision
, current_revision
);
655 giggle_git_run_job (priv
->git
,
657 window_git_diff_result_callback
,
663 window_add_widget_cb (GtkUIManager
*merge
,
665 GiggleWindow
*window
)
667 GiggleWindowPriv
*priv
;
669 priv
= GET_PRIV (window
);
671 gtk_box_pack_start (GTK_BOX (priv
->menubar_hbox
), widget
, TRUE
, TRUE
, 0);
675 window_revision_selection_changed_cb (GtkTreeSelection
*selection
,
676 GiggleWindow
*window
)
678 GiggleWindowPriv
*priv
;
680 GtkTreeIter first_iter
;
681 GtkTreeIter last_iter
;
682 GiggleRevision
*first_revision
;
683 GiggleRevision
*last_revision
;
688 priv
= GET_PRIV (window
);
689 rows
= gtk_tree_selection_get_selected_rows (selection
, &model
);
690 first_revision
= last_revision
= NULL
;
697 /* get the first row iter */
698 gtk_tree_model_get_iter (model
, &first_iter
,
699 (GtkTreePath
*) rows
->data
);
701 if (g_list_length (rows
) > 1) {
702 last_row
= g_list_last (rows
);
703 valid
= gtk_tree_model_get_iter (model
, &last_iter
,
704 (GtkTreePath
*) last_row
->data
);
709 gtk_tree_model_get (model
, &first_iter
,
710 REVISION_COL_OBJECT
, &first_revision
,
713 gtk_tree_model_get (model
, &last_iter
,
714 REVISION_COL_OBJECT
, &last_revision
,
717 /* maybe select a better parent? */
718 GList
* parents
= giggle_revision_get_parents (first_revision
);
719 last_revision
= parents
? g_object_ref(parents
->data
) : NULL
;
722 window_update_revision_info (window
,
726 g_object_unref (first_revision
);
728 g_object_unref (last_revision
);
731 g_list_foreach (rows
, (GFunc
) gtk_tree_path_free
, NULL
);
736 window_git_diff_result_callback (GiggleGit
*git
,
741 GiggleWindow
*window
;
742 GiggleWindowPriv
*priv
;
745 window
= GIGGLE_WINDOW (user_data
);
746 priv
= GET_PRIV (window
);
751 dialog
= gtk_message_dialog_new (GTK_WINDOW (window
),
752 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
755 _("An error ocurred when retrieving a diff:\n"
756 "%s"), error
->message
);
758 gtk_dialog_run (GTK_DIALOG (dialog
));
759 gtk_widget_destroy (dialog
);
761 gtk_text_buffer_set_text (
762 gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv
->diff_textview
)),
763 giggle_git_diff_get_result (GIGGLE_GIT_DIFF (job
)),
766 action
= gtk_ui_manager_get_action (
769 gtk_action_set_sensitive (action
, TRUE
);
772 g_object_unref (priv
->current_job
);
773 priv
->current_job
= NULL
;
777 window_revision_cell_data_log_func (GtkTreeViewColumn
*column
,
778 GtkCellRenderer
*cell
,
783 GiggleWindowPriv
*priv
;
784 GiggleRevision
*revision
;
786 priv
= GET_PRIV (data
);
788 gtk_tree_model_get (model
, iter
,
789 REVISION_COL_OBJECT
, &revision
,
793 "text", giggle_revision_get_short_log (revision
),
796 g_object_unref (revision
);
800 window_revision_cell_data_author_func (GtkTreeViewColumn
*column
,
801 GtkCellRenderer
*cell
,
806 GiggleWindowPriv
*priv
;
807 GiggleRevision
*revision
;
809 priv
= GET_PRIV (data
);
811 gtk_tree_model_get (model
, iter
,
812 REVISION_COL_OBJECT
, &revision
,
816 "text", giggle_revision_get_author (revision
),
819 g_object_unref (revision
);
823 window_revision_cell_data_date_func (GtkTreeViewColumn
*column
,
824 GtkCellRenderer
*cell
,
829 GiggleWindowPriv
*priv
;
830 GiggleRevision
*revision
;
832 priv
= GET_PRIV (data
);
834 gtk_tree_model_get (model
, iter
,
835 REVISION_COL_OBJECT
, &revision
,
839 "text", giggle_revision_get_date (revision
),
842 g_object_unref (revision
);
846 window_action_quit_cb (GtkAction
*action
,
847 GiggleWindow
*window
)
853 window_action_open_cb (GtkAction
*action
,
854 GiggleWindow
*window
)
856 GiggleWindowPriv
*priv
;
857 GtkWidget
*file_chooser
;
858 const gchar
*directory
;
860 priv
= GET_PRIV (window
);
862 file_chooser
= gtk_file_chooser_dialog_new (
863 _("Select GIT repository"),
865 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
,
866 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
867 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
870 gtk_file_chooser_set_current_folder (
871 GTK_FILE_CHOOSER (file_chooser
),
872 giggle_git_get_directory (priv
->git
));
874 if (gtk_dialog_run (GTK_DIALOG (file_chooser
)) == GTK_RESPONSE_OK
) {
875 directory
= gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (file_chooser
));
877 /* FIXME: no error handling */
878 giggle_git_set_directory (priv
->git
, directory
, NULL
);
881 gtk_widget_destroy (file_chooser
);
885 window_action_save_patch_cb (GtkAction
*action
,
886 GiggleWindow
*window
)
888 GiggleWindowPriv
*priv
;
889 GtkWidget
*file_chooser
;
890 GtkTextBuffer
*text_buffer
;
891 GtkTextIter iter_start
, iter_end
;
893 GError
*error
= NULL
;
895 priv
= GET_PRIV (window
);
897 file_chooser
= gtk_file_chooser_dialog_new (
898 _("Save patch file"),
900 GTK_FILE_CHOOSER_ACTION_SAVE
,
901 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
902 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
905 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (file_chooser
), TRUE
);
907 /* FIXME: remember the last selected folder */
909 if (gtk_dialog_run (GTK_DIALOG (file_chooser
)) == GTK_RESPONSE_OK
) {
910 text_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv
->diff_textview
));
911 gtk_text_buffer_get_bounds (text_buffer
, &iter_start
, &iter_end
);
913 text
= gtk_text_buffer_get_text (text_buffer
, &iter_start
, &iter_end
, TRUE
);
914 path
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser
));
916 if (!g_file_set_contents (path
, text
, strlen (text
), &error
)) {
919 dialog
= gtk_message_dialog_new (
921 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
924 _("There was an error saving to file: \n%s"),
927 gtk_dialog_run (GTK_DIALOG (dialog
));
929 gtk_widget_destroy (dialog
);
930 g_error_free (error
);
934 gtk_widget_destroy (file_chooser
);
938 window_action_personal_details_cb (GtkAction
*action
,
939 GiggleWindow
*window
)
941 GtkWidget
*personal_details
;
943 personal_details
= giggle_personal_details_window_new ();
944 gtk_window_set_transient_for (GTK_WINDOW (personal_details
),
945 GTK_WINDOW (window
));
946 gtk_widget_show (personal_details
);
948 g_signal_connect_after (G_OBJECT (personal_details
), "response",
949 G_CALLBACK (gtk_widget_destroy
), NULL
);
954 window_action_about_cb (GtkAction
*action
,
955 GiggleWindow
*window
)
957 gtk_show_about_dialog (GTK_WINDOW (window
),
959 "copyright", "Copyright 2007 Imendio AB",
960 "translator-credits", _("translator-credits"),
965 window_directory_changed_cb (GiggleGit
*git
,
967 GiggleWindow
*window
)
969 GiggleWindowPriv
*priv
;
972 const gchar
*directory
;
974 priv
= GET_PRIV (window
);
976 directory
= giggle_git_get_directory (git
);
977 title
= g_strdup_printf ("%s - Giggle", directory
);
978 gtk_window_set_title (GTK_WINDOW (window
), title
);
981 /* empty the treeview */
982 gtk_tree_view_set_model (GTK_TREE_VIEW (priv
->revision_treeview
), NULL
);
984 job
= giggle_git_revisions_new ();
985 giggle_git_run_job (priv
->git
, job
,
986 window_git_get_revisions_cb
,
989 job
= giggle_git_branches_new ();
990 giggle_git_run_job (priv
->git
, job
,
991 window_git_get_branches_cb
,
996 window_git_dir_changed_cb (GiggleGit
*git
,
998 GiggleWindow
*window
)
1000 /* add repository uri to recents */
1001 gchar
*uri
= g_filename_to_uri (giggle_git_get_git_dir (git
), NULL
, NULL
);
1002 window_recent_repositories_add (window
, uri
);
1007 giggle_window_new (void)
1011 window
= g_object_new (GIGGLE_TYPE_WINDOW
, NULL
);