Create a base class for commands that just pass raw output
[anjuta-git-plugin.git] / plugins / git / git-ui-utils.c
bloba5197e53b207c7b4097211f4c00d94b0c09854a0
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 "git-ui-utils.h"
27 /* Private structure for pulse progress */
28 typedef struct
30 AnjutaStatus *status;
31 gchar *text;
32 } PulseProgressData;
34 GitUIData*
35 git_ui_data_new (Git* plugin, GladeXML* gxml)
37 GitUIData* data = g_new0 (GitUIData, 1);
38 data->plugin = plugin;
39 data->gxml = gxml;
41 return data;
44 void
45 git_ui_data_free (GitUIData* data)
47 g_object_unref (data->gxml);
48 g_free (data);
51 static void
52 on_message_view_destroy (Git* plugin, gpointer destroyed_view)
54 plugin->message_view = NULL;
57 void
58 create_message_view (Git* plugin)
60 IAnjutaMessageManager* message_manager;
63 message_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
64 IAnjutaMessageManager, NULL);
65 plugin->message_view = ianjuta_message_manager_get_view_by_name (message_manager,
66 _("Git"),
67 NULL);
68 if (!plugin->message_view)
70 plugin->message_view = ianjuta_message_manager_add_view (message_manager,
71 _("Git"),
72 ICON_FILE,
73 NULL);
74 g_object_weak_ref (G_OBJECT (plugin->message_view),
75 (GWeakNotify) on_message_view_destroy, plugin);
78 ianjuta_message_view_clear(plugin->message_view, NULL);
79 ianjuta_message_manager_set_current_view (message_manager, plugin->message_view,
80 NULL);
83 gboolean
84 check_input (GtkWidget *parent, GtkWidget *widget, const gchar *input,
85 const gchar *error_message)
87 gboolean ret;
88 GtkWidget *dialog;
90 ret = FALSE;
92 if (input)
94 if (strlen (input) > 0)
95 ret = TRUE;
98 if (!ret)
100 dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
101 GTK_DIALOG_DESTROY_WITH_PARENT,
102 GTK_MESSAGE_WARNING,
103 GTK_BUTTONS_OK,
104 error_message);
106 gtk_dialog_run (GTK_DIALOG (dialog));
107 gtk_widget_destroy (dialog);
109 gtk_window_set_focus (GTK_WINDOW (parent), widget);
113 return ret;
116 gchar *
117 get_log_from_textview (GtkWidget* textview)
119 gchar* log;
120 GtkTextBuffer* textbuf;
121 GtkTextIter iterbegin, iterend;
123 textbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
124 gtk_text_buffer_get_start_iter(textbuf, &iterbegin);
125 gtk_text_buffer_get_end_iter(textbuf, &iterend) ;
126 log = gtk_text_buffer_get_text(textbuf, &iterbegin, &iterend, FALSE);
127 return log;
130 static gboolean
131 status_pulse_timer (PulseProgressData *data)
133 anjuta_status_progress_pulse (data->status, data->text);
134 return TRUE;
137 static gboolean
138 pulse_timer (GtkProgressBar *progress_bar)
140 gtk_progress_bar_pulse (progress_bar);
141 return TRUE;
144 static void
145 on_pulse_timer_destroyed (PulseProgressData *data)
147 anjuta_status_progress_reset (data->status);
149 g_free (data->text);
150 g_free (data);
153 guint
154 status_bar_progress_pulse (Git *plugin, gchar *text)
156 PulseProgressData *data;
158 data = g_new0 (PulseProgressData, 1);
159 data->status = anjuta_shell_get_status (ANJUTA_PLUGIN (plugin)->shell,
160 NULL);
161 data->text = g_strdup (text);
163 return g_timeout_add_full (G_PRIORITY_DEFAULT, 100,
164 (GSourceFunc) status_pulse_timer, data,
165 (GDestroyNotify) on_pulse_timer_destroyed);
168 void
169 clear_status_bar_progress_pulse (guint timer_id)
171 g_source_remove (timer_id);
174 void
175 report_errors (AnjutaCommand *command, guint return_code)
177 gchar *message;
179 /* In some cases, git might report errors yet still indicate success.
180 * When this happens, use a warning dialog instead of an error, so the user
181 * knows that something actually happened. */
182 message = anjuta_command_get_error_message (command);
184 if (message)
186 if (return_code != 0)
187 anjuta_util_dialog_error (NULL, message);
188 else
189 anjuta_util_dialog_warning (NULL, message);
191 g_free (message);
195 static void
196 stop_pulse_timer (gpointer timer_id, GtkProgressBar *progress_bar)
198 g_source_remove (GPOINTER_TO_UINT (timer_id));
201 void
202 pulse_progress_bar (GtkProgressBar *progress_bar)
204 guint timer_id;
206 timer_id = g_timeout_add (100, (GSourceFunc) pulse_timer,
207 progress_bar);
208 g_object_set_data (G_OBJECT (progress_bar), "pulse-timer-id",
209 GUINT_TO_POINTER (timer_id));
211 g_object_weak_ref (G_OBJECT (progress_bar),
212 (GWeakNotify) stop_pulse_timer,
213 GUINT_TO_POINTER (timer_id));
216 gchar *
217 get_filename_from_full_path (gchar *path)
219 gchar *last_slash;
221 last_slash = strrchr (path, '/');
223 /* There might be a trailing slash in the string */
224 if ((last_slash - path) < strlen (path))
225 return g_strdup (last_slash + 1);
226 else
227 return g_strdup ("");
230 const gchar *
231 get_relative_path (const gchar *path, const gchar *working_directory)
233 /* Path could already be a relative path */
234 if (strstr (path, working_directory))
235 return path + strlen (working_directory) + 1;
236 else
237 return path;
240 void
241 on_command_finished (AnjutaCommand *command, guint return_code,
242 gpointer user_data)
244 report_errors (command, return_code);
246 g_object_unref (command);
249 void
250 on_status_command_data_arrived (AnjutaCommand *command,
251 AnjutaVcsStatusTreeView *tree_view)
253 GQueue *status_queue;
254 GitStatus *status;
255 gchar *path;
257 status_queue = git_status_command_get_status_queue (GIT_STATUS_COMMAND (command));
259 while (g_queue_peek_head (status_queue))
261 status = g_queue_pop_head (status_queue);
262 path = git_status_get_path (status);
264 anjuta_vcs_status_tree_view_add (tree_view, path,
265 git_status_get_vcs_status (status),
266 FALSE);
268 g_object_unref (status);
269 g_free (path);
273 void
274 on_command_info_arrived (AnjutaCommand *command, Git *plugin)
276 GQueue *info;
277 gchar *message;
279 info = git_command_get_info_queue (GIT_COMMAND (command));
281 while (g_queue_peek_head (info))
283 message = g_queue_pop_head (info);
284 ianjuta_message_view_append (plugin->message_view,
285 IANJUTA_MESSAGE_VIEW_TYPE_INFO,
286 message, "", NULL);
287 g_free (message);
291 void
292 on_list_branch_command_data_arrived (AnjutaCommand *command,
293 GitBranchComboData *data)
295 GQueue *output_queue;
296 GitBranch *branch;
298 output_queue = git_branch_list_command_get_output (GIT_BRANCH_LIST_COMMAND (command));
300 while (g_queue_peek_head (output_queue))
302 branch = g_queue_pop_head (output_queue);
303 git_branch_combo_model_append (data->model, branch);
304 g_object_unref (branch);
308 void
309 on_list_branch_command_finished (AnjutaCommand *command, guint return_code,
310 GitBranchComboData *data)
312 gtk_combo_box_set_active (data->combo_box, 0);
314 report_errors (command, return_code);
315 g_object_unref (command);
318 void
319 select_all_status_items (GtkButton *select_all_button,
320 AnjutaVcsStatusTreeView *tree_view)
322 anjuta_vcs_status_tree_view_select_all (tree_view);
325 void
326 clear_all_status_selections (GtkButton *clear_button,
327 AnjutaVcsStatusTreeView *tree_view)
329 anjuta_vcs_status_tree_view_unselect_all (tree_view);
332 void
333 init_whole_project (Git *plugin, GtkWidget* project, gboolean active)
335 gboolean project_loaded;
337 project_loaded = (plugin->project_root_directory != NULL);
339 gtk_widget_set_sensitive(project, project_loaded);
341 if (project_loaded)
342 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (project), active);
345 void
346 on_whole_project_toggled (GtkToggleButton* project, Git *plugin)
348 GtkWidget *path_entry;
350 path_entry = g_object_get_data (G_OBJECT (project), "file-entry");
352 gtk_widget_set_sensitive (path_entry,
353 !gtk_toggle_button_get_active (project));
356 void
357 send_raw_command_output_to_editor (AnjutaCommand *command,
358 IAnjutaEditor *editor)
360 GQueue *output;
361 gchar *line;
363 output = git_raw_output_command_get_output (GIT_RAW_OUTPUT_COMMAND (command));
365 while (g_queue_peek_head (output))
367 line = g_queue_pop_head (output);
368 ianjuta_editor_append (editor, line, strlen (line), NULL);
369 g_free (line);
373 void
374 on_diff_command_finished (AnjutaCommand *command, guint return_code,
375 Git *plugin)
377 AnjutaStatus *status;
379 status = anjuta_shell_get_status (ANJUTA_PLUGIN (plugin)->shell,
380 NULL);
382 anjuta_status (status, _("Git: Diff complete."), 5);
384 report_errors (command, return_code);
386 g_object_unref (command);
389 void
390 stop_status_bar_progress_pulse (AnjutaCommand *command, guint return_code,
391 gpointer timer_id)
393 clear_status_bar_progress_pulse (GPOINTER_TO_UINT (timer_id));
396 void
397 hide_pulse_progress_bar (AnjutaCommand *command, guint return_code,
398 GtkProgressBar *progress_bar)
400 guint timer_id;
402 /* If the progress bar has already been destroyed, the timer should be
403 * stopped by stop_pulse_timer */
404 if (GTK_IS_PROGRESS_BAR (progress_bar))
406 timer_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (progress_bar),
407 "pulse-timer-id"));
409 g_source_remove (GPOINTER_TO_UINT (timer_id));
410 gtk_widget_hide (GTK_WIDGET (progress_bar));
414 /* This function is normally intended to disconnect stock data-arrived signal
415 * handlers in this file. It is assumed that object is the user data for the
416 * callback. If you use any of the stock callbacks defined here, make sure
417 * to weak ref its target with this callback. Make sure to cancel this ref
418 * by connecting cancel_data_arrived_signal_disconnect to the command-finished
419 * signal so we don't try to disconnect signals on a destroyed command. */
420 void
421 disconnect_data_arrived_signals (AnjutaCommand *command, GObject *object)
423 guint data_arrived_signal;
425 if (ANJUTA_IS_COMMAND (command))
427 data_arrived_signal = g_signal_lookup ("data-arrived",
428 ANJUTA_TYPE_COMMAND);
430 g_signal_handlers_disconnect_matched (command,
431 G_SIGNAL_MATCH_DATA,
432 data_arrived_signal,
434 NULL,
435 NULL,
436 object);
441 void
442 cancel_data_arrived_signal_disconnect (AnjutaCommand *command,
443 guint return_code,
444 GObject *signal_target)
446 g_object_weak_unref (signal_target,
447 (GWeakNotify) disconnect_data_arrived_signals,
448 command);