1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) James Liggett 2010 <jrliggett@cox.net>
6 * anjuta is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * anjuta is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "git-push-pane.h"
22 struct _GitPushPanePriv
25 GtkWidget
*repository_selector
;
34 G_DEFINE_TYPE (GitPushPane
, git_push_pane
, GIT_TYPE_PANE
);
36 /* Foreach function for both the selected branches and tags list. Will generate
37 * one list of both types of selected items. */
39 get_selected_items (GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
,
45 gtk_tree_model_get (model
, iter
, COL_SELECTED
, &selected
, -1);
49 gtk_tree_model_get (model
, iter
, COL_NAME
, &name
, -1);
50 *list
= g_list_append (*list
, name
);
57 on_ok_button_clicked (GtkButton
*button
, GitPushPane
*self
)
60 GtkTreeModel
*push_branch_model
;
61 GtkTreeModel
*push_tag_model
;
62 GtkToggleButton
*push_all_tags_check
;
63 GtkToggleButton
*push_all_check
;
64 GtkToggleButton
*force_check
;
65 GList
*selected_items
;
66 gboolean push_all_tags
;
69 GitPushCommand
*push_command
;
71 plugin
= ANJUTA_PLUGIN_GIT (anjuta_dock_pane_get_plugin (ANJUTA_DOCK_PANE (self
)));
72 push_branch_model
= GTK_TREE_MODEL (gtk_builder_get_object (self
->priv
->builder
,
73 "push_branch_model"));
74 push_tag_model
= GTK_TREE_MODEL (gtk_builder_get_object (self
->priv
->builder
,
76 push_all_tags_check
= GTK_TOGGLE_BUTTON (gtk_builder_get_object (self
->priv
->builder
,
77 "push_all_tags_check"));
78 push_all_check
= GTK_TOGGLE_BUTTON (gtk_builder_get_object (self
->priv
->builder
,
80 force_check
= GTK_TOGGLE_BUTTON (gtk_builder_get_object (self
->priv
->builder
,
82 selected_items
= NULL
;
83 push_all_tags
= gtk_toggle_button_get_active (push_all_tags_check
);
84 push_all
= gtk_toggle_button_get_active (push_all_check
);
86 /* Check that the user has given a valid repository. In this case we only
87 * care about checking if the selector widget is in URL mode, because even
88 * if a remote isn't selected, it will default to origin, so we should
89 * always get something when the selector is in Remote mode. */
90 repository
= git_repository_selector_get_repository (GIT_REPOSITORY_SELECTOR (self
->priv
->repository_selector
));
92 if (!git_pane_check_input (GTK_WIDGET (ANJUTA_PLUGIN (plugin
)->shell
),
93 self
->priv
->repository_selector
, repository
,
94 _("Please enter a URL.")))
102 /* Get selected branches */
103 gtk_tree_model_foreach (push_branch_model
,
104 (GtkTreeModelForeachFunc
) get_selected_items
,
108 /* Don't bother getting selected tags if Push all tags is checked or if
109 * Push all branches and tags is checked */
110 if (!push_all
&& !push_all_tags
)
112 /* Get selected tags */
113 gtk_tree_model_foreach (push_tag_model
,
114 (GtkTreeModelForeachFunc
) get_selected_items
,
118 push_command
= git_push_command_new (plugin
->project_root_directory
,
119 repository
, selected_items
,
120 push_all
, push_all_tags
,
121 gtk_toggle_button_get_active (force_check
));
124 anjuta_util_glist_strings_free (selected_items
);
126 git_pane_create_message_view (plugin
);
128 g_signal_connect (G_OBJECT (push_command
), "data-arrived",
129 G_CALLBACK (git_pane_on_command_info_arrived
),
132 g_signal_connect (G_OBJECT (push_command
), "command-finished",
133 G_CALLBACK (git_pane_report_errors
),
136 g_signal_connect (G_OBJECT (push_command
), "command-finished",
137 G_CALLBACK (git_plugin_status_changed_emit
),
140 g_signal_connect (G_OBJECT (push_command
), "command-finished",
141 G_CALLBACK (g_object_unref
),
144 anjuta_command_start (ANJUTA_COMMAND (push_command
));
146 git_pane_remove_from_dock (GIT_PANE (self
));
150 on_selected_renderer_toggled (GtkCellRendererToggle
*renderer
, gchar
*path
,
156 gtk_tree_model_get_iter_from_string (model
, &iter
, path
);
158 gtk_tree_model_get (model
, &iter
, COL_SELECTED
, &selected
, -1);
160 selected
= !selected
;
162 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
, COL_SELECTED
, selected
,
167 on_branch_list_command_data_arrived (AnjutaCommand
*command
,
168 GtkListStore
*push_branch_model
)
170 GList
*current_branch
;
175 current_branch
= git_branch_list_command_get_output (GIT_BRANCH_LIST_COMMAND (command
));
177 while (current_branch
)
179 branch
= current_branch
->data
;
180 name
= git_branch_get_name (branch
);
182 gtk_list_store_append (push_branch_model
, &iter
);
183 gtk_list_store_set (push_branch_model
, &iter
,
190 current_branch
= g_list_next (current_branch
);
195 on_tag_list_command_data_arrived (AnjutaCommand
*command
,
196 GtkListStore
*push_tag_model
)
202 output
= git_raw_output_command_get_output (GIT_RAW_OUTPUT_COMMAND (command
));
204 while (g_queue_peek_head (output
))
206 name
= g_queue_pop_head (output
);
208 gtk_list_store_append (push_tag_model
, &iter
);
209 gtk_list_store_set (push_tag_model
, &iter
,
219 on_push_all_check_toggled (GtkToggleButton
*button
, GtkWidget
*widget
)
221 gtk_widget_set_sensitive (widget
,
222 !gtk_toggle_button_get_active (button
));
226 on_remote_selected (AnjutaDockPane
*pane
,
227 GitRepositorySelector
*repository_selector
)
231 remote
= git_remotes_pane_get_selected_remote (GIT_REMOTES_PANE (pane
));
232 git_repository_selector_set_remote (repository_selector
, remote
);
238 git_push_pane_init (GitPushPane
*self
)
240 gchar
*objects
[] = {"push_pane",
244 GError
*error
= NULL
;
245 GtkWidget
*ok_button
;
246 GtkWidget
*cancel_button
;
247 GtkContainer
*repository_alignment
;
248 GtkWidget
*branches_view
;
249 GtkWidget
*tags_view
;
250 GtkTreeModel
*push_branch_model
;
251 GtkTreeModel
*push_tag_model
;
252 GtkCellRenderer
*branches_selected_renderer
;
253 GtkCellRenderer
*tags_selected_renderer
;
254 GtkWidget
*push_all_tags_check
;
255 GtkWidget
*push_all_check
;;
257 self
->priv
= g_new0 (GitPushPanePriv
, 1);
258 self
->priv
->builder
= gtk_builder_new ();
260 if (!gtk_builder_add_objects_from_file (self
->priv
->builder
, BUILDER_FILE
,
264 g_warning ("Couldn't load builder file: %s", error
->message
);
265 g_error_free (error
);
268 ok_button
= GTK_WIDGET (gtk_builder_get_object (self
->priv
->builder
,
270 cancel_button
= GTK_WIDGET (gtk_builder_get_object (self
->priv
->builder
,
272 repository_alignment
= GTK_CONTAINER (gtk_builder_get_object (self
->priv
->builder
,
273 "repository_alignment"));
274 self
->priv
->repository_selector
= git_repository_selector_new ();
275 branches_view
= GTK_WIDGET (gtk_builder_get_object (self
->priv
->builder
,
277 tags_view
= GTK_WIDGET (gtk_builder_get_object (self
->priv
->builder
,
279 push_branch_model
= GTK_TREE_MODEL (gtk_builder_get_object (self
->priv
->builder
,
280 "push_branch_model"));
281 push_tag_model
= GTK_TREE_MODEL (gtk_builder_get_object (self
->priv
->builder
,
283 branches_selected_renderer
= GTK_CELL_RENDERER (gtk_builder_get_object (self
->priv
->builder
,
284 "branches_selected_renderer"));
285 tags_selected_renderer
= GTK_CELL_RENDERER (gtk_builder_get_object (self
->priv
->builder
,
286 "tags_selected_renderer"));
287 push_all_tags_check
= GTK_WIDGET (gtk_builder_get_object (self
->priv
->builder
,
288 "push_all_tags_check"));
289 push_all_check
= GTK_WIDGET (gtk_builder_get_object (self
->priv
->builder
,
292 gtk_container_add (repository_alignment
, self
->priv
->repository_selector
);
294 g_signal_connect (G_OBJECT (ok_button
), "clicked",
295 G_CALLBACK (on_ok_button_clicked
),
298 g_signal_connect_swapped (G_OBJECT (cancel_button
), "clicked",
299 G_CALLBACK (git_pane_remove_from_dock
),
302 g_signal_connect (G_OBJECT (branches_selected_renderer
), "toggled",
303 G_CALLBACK (on_selected_renderer_toggled
),
306 g_signal_connect (G_OBJECT (tags_selected_renderer
), "toggled",
307 G_CALLBACK (on_selected_renderer_toggled
),
310 /* Use the push all tags check callback to handle both the Push all tags
311 * and the Push all branches and tags check boxes. The behavior is the same
312 * for both; they just act on different widgets. */
313 g_signal_connect (G_OBJECT (push_all_tags_check
), "toggled",
314 G_CALLBACK (on_push_all_check_toggled
),
317 g_signal_connect (G_OBJECT (push_all_check
), "toggled",
318 G_CALLBACK (on_push_all_check_toggled
),
321 g_signal_connect (G_OBJECT (push_all_check
), "toggled",
322 G_CALLBACK (on_push_all_check_toggled
),
327 git_push_pane_dispose (GObject
*object
)
332 self
= GIT_PUSH_PANE (object
);
333 plugin
= ANJUTA_PLUGIN_GIT (anjuta_dock_pane_get_plugin (ANJUTA_DOCK_PANE (object
)));
335 g_signal_handlers_disconnect_by_func (plugin
->remotes_pane
,
337 self
->priv
->repository_selector
);
339 G_OBJECT_CLASS (git_push_pane_parent_class
)->dispose (object
);
344 git_push_pane_finalize (GObject
*object
)
348 self
= GIT_PUSH_PANE (object
);
350 g_object_unref (self
->priv
->builder
);
353 G_OBJECT_CLASS (git_push_pane_parent_class
)->finalize (object
);
357 git_push_pane_get_widget (AnjutaDockPane
*pane
)
361 self
= GIT_PUSH_PANE (pane
);
363 return GTK_WIDGET (gtk_builder_get_object (self
->priv
->builder
,
368 git_push_pane_class_init (GitPushPaneClass
*klass
)
370 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
371 AnjutaDockPaneClass
* pane_class
= ANJUTA_DOCK_PANE_CLASS (klass
);
373 object_class
->finalize
= git_push_pane_finalize
;
374 object_class
->dispose
= git_push_pane_dispose
;
375 pane_class
->get_widget
= git_push_pane_get_widget
;
376 pane_class
->refresh
= NULL
;
380 git_push_pane_new (Git
*plugin
)
383 GtkLabel
*selected_remote_label
;
384 GtkListStore
*push_branch_model
;
385 GtkListStore
*push_tag_model
;
386 GitBranchListCommand
*branch_list_command
;
387 GitTagListCommand
*tag_list_command
;
389 self
= g_object_new (GIT_TYPE_PUSH_PANE
, "plugin", plugin
, NULL
);
390 selected_remote_label
= GTK_LABEL (gtk_builder_get_object (self
->priv
->builder
,
391 "selected_remote_label"));
392 push_branch_model
= GTK_LIST_STORE (gtk_builder_get_object (self
->priv
->builder
,
393 "push_branch_model"));
394 push_tag_model
= GTK_LIST_STORE (gtk_builder_get_object (self
->priv
->builder
,
396 branch_list_command
= git_branch_list_command_new (plugin
->project_root_directory
,
397 GIT_BRANCH_TYPE_LOCAL
);
398 tag_list_command
= git_tag_list_command_new (plugin
->project_root_directory
);
400 g_signal_connect (G_OBJECT (plugin
->remotes_pane
), "single-selection-changed",
401 G_CALLBACK (on_remote_selected
),
402 self
->priv
->repository_selector
);
404 g_signal_connect (G_OBJECT (branch_list_command
), "data-arrived",
405 G_CALLBACK (on_branch_list_command_data_arrived
),
408 g_signal_connect (G_OBJECT (tag_list_command
), "data-arrived",
409 G_CALLBACK (on_tag_list_command_data_arrived
),
412 g_signal_connect (G_OBJECT (branch_list_command
), "command-finished",
413 G_CALLBACK (g_object_unref
),
416 g_signal_connect (G_OBJECT (tag_list_command
), "command-finished",
417 G_CALLBACK (g_object_unref
),
420 /* Set the contents of the selected remote label */
421 on_remote_selected (plugin
->remotes_pane
,
422 GIT_REPOSITORY_SELECTOR (self
->priv
->repository_selector
));
424 anjuta_command_start (ANJUTA_COMMAND (branch_list_command
));
425 anjuta_command_start (ANJUTA_COMMAND (tag_list_command
));
427 return ANJUTA_DOCK_PANE (self
);
431 on_push_button_clicked (GtkAction
*action
, Git
*plugin
)
433 AnjutaDockPane
*pane
;
435 pane
= git_push_pane_new (plugin
);
437 anjuta_dock_replace_command_pane (ANJUTA_DOCK (plugin
->dock
), "Push",
438 _("Push"), NULL
, pane
, GDL_DOCK_BOTTOM
,