Updated Spanish translation
[anjuta-git-plugin.git] / plugins / tools / editor.c
blobba1d44dd22c9e9f3c0f12f09e2931c00b31e677d
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 editor.c
4 Copyright (C) 2003 Biswapesh Chattopadhyay
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Tool editor dialog
23 * This is used to set all tool informations.
25 *---------------------------------------------------------------------------*/
27 #include <config.h>
29 #include "editor.h"
31 #include "dialog.h"
32 #include "tool.h"
33 #include "variable.h"
35 #include <libanjuta/anjuta-utils.h>
36 #include <libanjuta/interfaces/ianjuta-document-manager.h>
37 #include <libanjuta/interfaces/ianjuta-editor.h>
38 #include <libanjuta/interfaces/ianjuta-file-loader.h>
40 #include <libgnomeui/libgnomeui.h>
41 #include <libgnomevfs/gnome-vfs-utils.h>
43 #include <gtk/gtk.h>
45 #include <string.h>
47 /*---------------------------------------------------------------------------*/
49 /* Variable dialog */
51 typedef enum {
52 ATP_VARIABLE_DEFAULT = 0,
53 ATP_VARIABLE_REPLACE = 1 << 1
54 } ATPVariableType;
56 typedef struct _ATPVariableDialog
58 GtkDialog* dialog;
59 GtkTreeView* view;
60 ATPToolEditor* editor;
61 GtkEditable* entry;
62 ATPVariableType type;
63 } ATPVariableDialog;
65 enum {
66 ATP_VARIABLE_NAME_COLUMN,
67 ATP_VARIABLE_MEAN_COLUMN,
68 ATP_VARIABLE_VALUE_COLUMN,
69 ATP_N_VARIABLE_COLUMNS,
72 /* Structure containing the required properties of the tool editor GUI */
73 struct _ATPToolEditor
75 GtkWidget *dialog;
76 GtkEditable *name_en;
77 GtkEditable *command_en;
78 GtkEditable *param_en;
79 ATPVariableDialog param_var;
80 GtkEditable *dir_en;
81 ATPVariableDialog dir_var;
82 GtkToggleButton *enabled_tb;
83 GtkToggleButton *terminal_tb;
84 GtkToggleButton *autosave_tb;
85 GtkToggleButton *script_tb;
86 GtkComboBox *output_com;
87 GtkComboBox *error_com;
88 GtkComboBox *input_com;
89 GtkEditable *input_en;
90 GtkButton *input_var_bt;
91 ATPVariableDialog input_file_var;
92 ATPVariableDialog input_string_var;
93 GtkToggleButton *shortcut_bt;
94 GnomeIconEntry *icon_en;
95 gchar* shortcut;
96 ATPUserTool *tool;
97 ATPToolDialog* parent;
98 ATPToolEditorList* owner;
99 ATPToolEditor* next;
102 /*---------------------------------------------------------------------------*/
104 /* Widget and signal name found in glade file
105 *---------------------------------------------------------------------------*/
107 #define TOOL_EDITOR "editor_dialog"
108 #define TOOL_NAME "name_entry"
109 #define TOOL_COMMAND "command_entry"
110 #define TOOL_PARAM "parameter_entry"
111 #define TOOL_WORKING_DIR "directory_entry"
112 #define TOOL_ENABLED "enable_checkbox"
113 #define TOOL_AUTOSAVE "save_checkbox"
114 #define TOOL_TERMINAL "terminal_checkbox"
115 #define TOOL_SCRIPT "script_checkbox"
116 #define TOOL_OUTPUT "output_combo"
117 #define TOOL_ERROR "error_combo"
118 #define TOOL_INPUT "input_combo"
119 #define TOOL_INPUT_VALUE "input_entry"
120 #define TOOL_INPUT_VARIABLE "input_button"
121 #define TOOL_SHORTCUT "shortcut_bt"
122 #define TOOL_ICON "icon_entry"
124 #define EDITOR_RESPONSE_SIGNAL "on_editor_dialog_response"
125 #define EDITOR_PARAM_VARIABLE_SIGNAL "on_variable_parameter"
126 #define EDITOR_DIR_VARIABLE_SIGNAL "on_variable_directory"
127 #define EDITOR_INPUT_VARIABLE_SIGNAL "on_variable_input"
128 #define EDITOR_INPUT_CHANGED_SIGNAL "on_input_changed"
129 #define EDITOR_TOGGLE_TERMINAL_SIGNAL "on_toggle_terminal"
130 #define EDITOR_TOGGLE_SHORCUT_SIGNAL "on_toggle_shorcut"
131 #define EDITOR_TOGGLE_SCRIPT_SIGNAL "on_toggle_script"
133 #define TOOL_VARIABLE "variable_dialog"
134 #define VARIABLE_TREEVIEW "variable_treeview"
135 #define VARIABLE_RESPONSE_SIGNAL "on_variable_dialog_response"
136 #define VARIABLE_ACTIVATE_SIGNAL "on_variable_activate_row"
138 /* Add helper function
139 *---------------------------------------------------------------------------*/
141 static gboolean
142 make_directory (gchar* path)
144 gchar c;
145 gchar* ptr;
147 for (ptr = path; *ptr;)
149 /* Get next directory */
150 for (c = '\0'; *ptr; ++ptr)
152 if (*ptr == G_DIR_SEPARATOR)
154 /* Strip leading directory separator */
157 ++ptr;
158 } while (*ptr == G_DIR_SEPARATOR);
159 c = *ptr;
160 *ptr = '\0';
161 break;
165 /* Create it */
166 if (mkdir (path, 0755) < 0)
168 /* Error creating directory */
169 *ptr = c;
170 if (errno != EEXIST)
172 /* An already existing directory is not an error */
173 return FALSE;
176 else
178 /* New directory created */
179 *ptr = c;
183 return TRUE;
186 static void
187 set_combo_box_enum_model (GtkComboBox* combo_box, const ATPEnumType* list)
189 GtkTreeModel *model;
191 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
193 for (; list->id != -1;++list)
195 GtkTreeIter iter;
197 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
198 gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, _(list->name), 1, list->id, -1);
200 gtk_combo_box_set_model (combo_box, model);
203 static gint
204 get_combo_box_value (GtkComboBox* combo_box)
206 GtkTreeIter iter;
207 GtkTreeModel *model;
208 gint value = -1;
210 if (gtk_combo_box_get_active_iter (combo_box, &iter))
212 model = gtk_combo_box_get_model (combo_box);
213 gtk_tree_model_get (model, &iter, 1, &value, -1);
216 return value;
219 static gboolean
220 set_combo_box_value (GtkComboBox* combo_box, gint value)
222 GtkTreeIter iter;
223 GtkTreeModel *model;
224 gint current;
226 if (value != -1)
228 model = gtk_combo_box_get_model (combo_box);
229 if (gtk_tree_model_get_iter_first (model, &iter))
233 gtk_tree_model_get (model, &iter, 1, &current, -1);
234 if (value == current)
236 gtk_combo_box_set_active_iter (combo_box, &iter);
238 return TRUE;
241 while (gtk_tree_model_iter_next (model, &iter));
245 gtk_combo_box_set_active (combo_box, 0);
247 return FALSE;
250 /* Tool variable dialog
251 * Display a list of variables useable as command line parameters or working
252 * directory with their values. Clicking on a variable add it in the current
253 * entry widget.
254 *---------------------------------------------------------------------------*/
256 static ATPVariableDialog*
257 atp_variable_dialog_construct (ATPVariableDialog* this, ATPToolEditor* editor, ATPVariableType type)
259 this->dialog = NULL;
260 this->editor = editor;
261 this->type = type;
263 return this;
266 static void
267 atp_variable_dialog_destroy (ATPVariableDialog* this)
269 if (this->dialog)
271 gtk_widget_destroy (GTK_WIDGET (this->dialog));
272 this->dialog = NULL;
276 static void
277 atp_variable_dialog_set_entry (ATPVariableDialog *this, GtkEditable* entry)
279 this->entry = entry;
282 static void
283 atp_variable_dialog_populate (ATPVariableDialog* this, ATPFlags flag)
285 GtkTreeModel *model;
286 ATPVariable* variable;
287 guint i;
289 variable = atp_tool_dialog_get_variable (this->editor->parent);
290 model = gtk_tree_view_get_model (this->view);
291 gtk_list_store_clear (GTK_LIST_STORE(model));
293 for (i = atp_variable_get_count(variable); i > 0;)
295 GtkTreeIter iter;
296 gchar* value;
297 const gchar* value_col;
299 --i;
300 if ((flag == ATP_DEFAULT_VARIABLE) || (flag & atp_variable_get_flag (variable, i)))
302 if (atp_variable_get_flag (variable, i) & ATP_INTERACTIVE_VARIABLE)
304 value = NULL;
305 value_col = _("ask at runtime");
307 else
309 value = atp_variable_get_value_from_id (variable, i);
310 value_col = (value == NULL) ? _("undefined") : value;
312 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
313 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
314 ATP_VARIABLE_NAME_COLUMN,
315 atp_variable_get_name(variable, i),
316 ATP_VARIABLE_MEAN_COLUMN,
317 _(atp_variable_get_help(variable, i)),
318 ATP_VARIABLE_VALUE_COLUMN,
319 value_col,
320 -1);
321 if (value) g_free (value);
326 static void
327 atp_variable_dialog_add_variable(ATPVariableDialog *this, const gchar* text)
329 gint pos;
331 g_return_if_fail (this->entry);
333 if (text != NULL)
335 gchar* next;
337 if (this->type == ATP_VARIABLE_REPLACE)
339 gtk_editable_delete_text (this->entry, 0, -1);
342 pos = gtk_editable_get_position(this->entry);
343 /* Add space before if useful */
344 if (pos != 0)
346 next = gtk_editable_get_chars (this->entry, pos - 1, pos);
348 if (!g_ascii_isspace (*next))
350 gtk_editable_insert_text (this->entry, " ", 1, &pos);
352 g_free (next);
354 gtk_editable_insert_text (this->entry, "$(", 2, &pos);
355 gtk_editable_insert_text (this->entry, text, strlen(text), &pos);
356 gtk_editable_insert_text (this->entry, ")", 1, &pos);
357 /* Add space after if useful */
358 next = gtk_editable_get_chars (this->entry, pos, pos + 1);
359 if (next != NULL)
361 if ((*next != '\0') && (!g_ascii_isspace (*next)))
363 gtk_editable_insert_text (this->entry, " ",1, &pos);
365 g_free (next);
370 static gchar*
371 get_current_name (GtkTreeView *view)
373 GtkTreeModel *model;
374 GtkTreeSelection *sel;
375 GtkTreeIter iter;
376 gchar* name;
378 model = gtk_tree_view_get_model (view);
379 sel = gtk_tree_view_get_selection (view);
380 if (gtk_tree_selection_get_selected (sel, &model, &iter))
382 gtk_tree_model_get (model, &iter, ATP_VARIABLE_NAME_COLUMN, &name, -1);
384 return name;
387 return NULL;
390 static void
391 on_variable_activate (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
393 ATPVariableDialog *this = (ATPVariableDialog*)user_data;
394 GtkTreeIter iter;
395 GtkTreeModel *model;
396 gchar* name;
398 /* Get Selected variable name */
399 model = gtk_tree_view_get_model (treeview);
400 gtk_tree_model_get_iter (model, &iter, path);
401 gtk_tree_model_get (model, &iter, ATP_VARIABLE_NAME_COLUMN, &name, -1);
403 atp_variable_dialog_add_variable (this, name);
405 gtk_widget_hide (GTK_WIDGET (this->dialog));
408 static void
409 on_variable_response (GtkDialog *dialog, gint response, gpointer user_data)
411 ATPVariableDialog *this = (ATPVariableDialog *)user_data;
412 gchar* name;
414 switch (response)
416 case GTK_RESPONSE_OK:
417 name = get_current_name (this->view);
418 atp_variable_dialog_add_variable (this, name);
419 break;
420 default:
421 break;
424 gtk_widget_hide (GTK_WIDGET (this->dialog));
427 static gboolean
428 atp_variable_dialog_show (ATPVariableDialog* this, ATPFlags flag)
430 GladeXML *xml;
431 GtkTreeModel *model;
432 GtkCellRenderer *renderer;
433 GtkTreeViewColumn *column;
435 if (this->dialog != NULL)
437 /* Display dialog box */
438 if (this->dialog) gtk_window_present (GTK_WINDOW (this->dialog));
439 return TRUE;
442 if (NULL == (xml = glade_xml_new(GLADE_FILE, TOOL_VARIABLE, NULL)))
444 anjuta_util_dialog_error (GTK_WINDOW (this->editor->dialog), _("Unable to build user interface for tool variable"));
445 return FALSE;
447 this->dialog = GTK_DIALOG (glade_xml_get_widget(xml, TOOL_VARIABLE));
448 gtk_widget_show (GTK_WIDGET (this->dialog));
449 gtk_window_set_transient_for (GTK_WINDOW (this->dialog), GTK_WINDOW (this->editor->dialog));
451 /* Create variable list */
452 this->view = GTK_TREE_VIEW (glade_xml_get_widget(xml, VARIABLE_TREEVIEW));
453 model = GTK_TREE_MODEL (gtk_list_store_new (ATP_N_VARIABLE_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING));
454 gtk_tree_view_set_model (this->view, model);
456 renderer = gtk_cell_renderer_text_new ();
457 column = gtk_tree_view_column_new_with_attributes (_("Variable"), renderer, "text", ATP_VARIABLE_NAME_COLUMN, NULL);
458 gtk_tree_view_append_column (this->view, column);
459 renderer = gtk_cell_renderer_text_new ();
460 column = gtk_tree_view_column_new_with_attributes (_("Meaning"), renderer, "text", ATP_VARIABLE_MEAN_COLUMN, NULL);
461 gtk_tree_view_append_column (this->view, column);
462 renderer = gtk_cell_renderer_text_new ();
463 column = gtk_tree_view_column_new_with_attributes (_("Value"), renderer, "text", ATP_VARIABLE_VALUE_COLUMN, NULL);
464 gtk_tree_view_append_column (this->view, column);
465 g_object_unref (model);
466 atp_variable_dialog_populate (this, flag);
468 /* Connect all signals */
469 glade_xml_signal_connect_data (xml, VARIABLE_RESPONSE_SIGNAL, GTK_SIGNAL_FUNC (on_variable_response), this);
470 glade_xml_signal_connect_data (xml, VARIABLE_ACTIVATE_SIGNAL, GTK_SIGNAL_FUNC (on_variable_activate), this);
471 g_signal_connect (G_OBJECT (this->dialog), "delete_event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
473 g_object_unref (xml);
475 return TRUE;
478 /* Tool editor dialog
479 *---------------------------------------------------------------------------*/
481 static void
482 atp_clear_tool_editor(ATPToolEditor* this)
484 g_return_if_fail (this != NULL);
486 gtk_editable_delete_text(this->name_en, 0, -1);
487 gtk_editable_delete_text(this->command_en, 0, -1);
488 gtk_editable_delete_text(this->param_en, 0, -1);
489 gtk_editable_delete_text(this->dir_en, 0, -1);
492 static void
493 atp_update_sensitivity(ATPToolEditor *this)
495 gboolean en;
497 /* Deactivate output and input setting if a terminal is used */
498 en = gtk_toggle_button_get_active (this->terminal_tb);
499 gtk_widget_set_sensitive(GTK_WIDGET (this->output_com), !en);
500 gtk_widget_set_sensitive(GTK_WIDGET (this->error_com), !en);
501 gtk_widget_set_sensitive(GTK_WIDGET (this->input_com), !en);
503 /* input value is available for a few input type only */
504 if (!en)
506 switch (get_combo_box_value (this->input_com))
508 case ATP_TIN_FILE:
509 case ATP_TIN_STRING:
510 en = TRUE;
511 break;
512 default:
513 en = FALSE;
514 break;
516 gtk_widget_set_sensitive(GTK_WIDGET (this->input_en), en);
517 gtk_widget_set_sensitive(GTK_WIDGET (this->input_var_bt), en);
519 else
521 gtk_widget_set_sensitive(GTK_WIDGET (this->input_en), FALSE);
522 gtk_widget_set_sensitive(GTK_WIDGET (this->input_var_bt), FALSE);
526 static void
527 atp_editor_update_shortcut (ATPToolEditor* this)
529 if (this->shortcut != NULL)
531 gtk_button_set_label (GTK_BUTTON (this->shortcut_bt), this->shortcut);
533 else
535 gtk_button_set_label (GTK_BUTTON (this->shortcut_bt), _("Disabled"));
539 static void
540 atp_populate_tool_editor(ATPToolEditor* this)
542 gint pos;
543 const gchar* value;
544 guint accel_key;
545 GdkModifierType accel_mods;
547 g_return_if_fail (this != NULL);
549 /* Nothing to fill */
550 if (this->tool == NULL) return;
552 value = atp_user_tool_get_name (this->tool);
553 if (value)
555 gtk_editable_insert_text(this->name_en, value
556 , strlen(value), &pos);
558 value = atp_user_tool_get_command (this->tool);
559 if (value)
561 gtk_editable_insert_text(this->command_en, value
562 , strlen(value), &pos);
564 value = atp_user_tool_get_param (this->tool);
565 if (value)
567 gtk_editable_insert_text(this->param_en, value
568 , strlen(value), &pos);
570 value = atp_user_tool_get_working_dir (this->tool);
571 if (value)
573 gtk_editable_insert_text(this->dir_en, value
574 , strlen(value), &pos);
576 gtk_toggle_button_set_active (this->enabled_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_ENABLE));
577 gtk_toggle_button_set_active (this->autosave_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_AUTOSAVE));
578 gtk_toggle_button_set_active (this->terminal_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_TERMINAL));
580 set_combo_box_value (this->output_com, atp_user_tool_get_output (this->tool));
581 set_combo_box_value (this->error_com, atp_user_tool_get_error (this->tool));
582 set_combo_box_value (this->input_com, atp_user_tool_get_input (this->tool));
583 switch (atp_user_tool_get_input (this->tool))
585 case ATP_TIN_FILE:
586 case ATP_TIN_STRING:
587 value = atp_user_tool_get_input_string (this->tool);
588 if (value)
590 gtk_editable_insert_text(this->input_en, value, strlen(value), &pos);
592 break;
593 default:
594 break;
596 atp_update_sensitivity (this);
598 if (this->shortcut != NULL) g_free (this->shortcut);
599 if (atp_user_tool_get_accelerator (this->tool, &accel_key, &accel_mods))
601 this->shortcut = gtk_accelerator_name (accel_key, accel_mods);
603 else
605 this->shortcut = NULL;
607 atp_editor_update_shortcut (this);
609 gnome_icon_entry_set_filename (this->icon_en, atp_user_tool_get_icon (this->tool));
612 static void
613 on_editor_terminal_toggle (GtkToggleButton *tb, gpointer user_data)
615 ATPToolEditor *this = (ATPToolEditor *)user_data;
617 atp_update_sensitivity (this);
620 static void
621 on_editor_script_toggle (GtkToggleButton *tb, gpointer user_data)
623 ATPToolEditor *this = (ATPToolEditor *)user_data;
624 gchar* command;
626 if (gtk_toggle_button_get_active(tb))
628 /* Get current command */
629 command = gtk_editable_get_chars(this->command_en, 0, -1);
631 if ((command == NULL) || (*command == '\0'))
633 gchar* name;
634 gint pos;
636 if (command) g_free (command);
637 /* Generate a new script file name */
638 command = gtk_editable_get_chars(this->name_en, 0, -1);
639 if ((command == NULL) || (*command == '\0'))
641 command = g_strdup("script");
643 name = atp_remove_mnemonic (command);
644 g_free (command);
645 command = g_build_filename (g_get_home_dir(),
646 LOCAL_ANJUTA_SCRIPT_DIRECTORY,
647 name, NULL);
648 g_free (name);
650 /* Find a new file name */
651 name = command;
652 pos = 0;
653 while (g_file_test (command, G_FILE_TEST_EXISTS))
655 if (command != name) g_free (command);
656 command = g_strdup_printf("%s%d", name, pos);
657 pos++;
659 if (command != name) g_free (name);
661 /* Fill command line */
662 gtk_editable_delete_text(this->command_en, 0, -1);
663 gtk_editable_insert_text(this->command_en, command,
664 strlen(command), &pos);
666 if (command) g_free (command);
670 static void
671 on_editor_input_changed (GtkComboBox *combo, gpointer user_data)
673 ATPToolEditor *this = (ATPToolEditor *)user_data;
675 atp_update_sensitivity (this);
678 static void
679 on_editor_response (GtkDialog *dialog, gint response, gpointer user_data)
681 ATPToolEditor* this = (ATPToolEditor*)user_data;
682 gchar* name;
683 gchar* data;
684 ATPInputType in_type;
685 gchar* value;
686 guint accel_key;
687 GdkModifierType accel_mods;
688 GtkAccelGroup* group;
689 AnjutaUI* ui;
691 if (response == GTK_RESPONSE_OK)
693 /* Check for all mandatory fields */
694 name = gtk_editable_get_chars(this->name_en, 0, -1);
695 if (!name || '\0' == name[0])
697 if (name) g_free (name);
698 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("You must provide a tool name!"));
699 return;
701 data = gtk_editable_get_chars(this->command_en, 0, -1);
702 if (!data || '\0' == data[0])
704 if (name) g_free (name);
705 if (data) g_free (data);
706 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("You must provide a tool command!"));
707 return;
710 if (!atp_user_tool_set_name (this->tool, name))
712 if (name) g_free (name);
713 if (data) g_free (data);
714 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("A tool with the same name already exists!"));
715 return;
717 g_free (name);
719 if (this->shortcut == NULL)
721 accel_key = 0;
722 accel_mods = 0;
724 else
726 gtk_accelerator_parse (this->shortcut, &accel_key, &accel_mods);
727 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN(this->parent->plugin)->shell, NULL);
728 group = anjuta_ui_get_accel_group(ui);
729 if (gtk_accel_group_query (group, accel_key, accel_mods, NULL) != NULL)
731 if (!anjuta_util_dialog_boolean_question (GTK_WINDOW (this->dialog), _("The shortcut is already used by another component in Anjuta. Do you want to keep it anyway?")))
733 return;
738 /* Set new tool data */
739 atp_user_tool_set_command (this->tool, data);
740 g_free (data);
742 data = gtk_editable_get_chars(this->param_en, 0, -1);
743 atp_user_tool_set_param (this->tool, data);
744 g_free (data);
746 data = gtk_editable_get_chars(this->dir_en, 0, -1);
747 atp_user_tool_set_working_dir (this->tool, data);
748 g_free (data);
750 atp_user_tool_set_flag (this->tool, ATP_TOOL_ENABLE | (gtk_toggle_button_get_active(this->enabled_tb) ? ATP_SET : ATP_CLEAR));
752 atp_user_tool_set_flag (this->tool, ATP_TOOL_AUTOSAVE | (gtk_toggle_button_get_active(this->autosave_tb) ? ATP_SET : ATP_CLEAR));
754 atp_user_tool_set_flag (this->tool, ATP_TOOL_TERMINAL | (gtk_toggle_button_get_active(this->terminal_tb) ? ATP_SET : ATP_CLEAR));
757 atp_user_tool_set_output (this->tool, get_combo_box_value (this->output_com));
758 atp_user_tool_set_error (this->tool, get_combo_box_value (this->error_com));
759 in_type = get_combo_box_value (this->input_com);
760 switch (in_type)
762 case ATP_TIN_FILE:
763 case ATP_TIN_STRING:
764 data = gtk_editable_get_chars(this->input_en, 0, -1);
765 atp_user_tool_set_input (this->tool, in_type, data);
766 g_free (data);
767 break;
768 default:
769 atp_user_tool_set_input (this->tool, in_type, NULL);
770 break;
773 atp_user_tool_set_accelerator (this->tool, accel_key, accel_mods);
775 value = gnome_icon_entry_get_filename (this->icon_en);
776 atp_user_tool_set_icon (this->tool, value);
777 g_free (value);
779 /* Open script in editor if requested */
780 if (gtk_toggle_button_get_active (this->script_tb))
782 IAnjutaDocumentManager *docman;
783 IAnjutaDocument *doc;
784 gchar *uri;
786 /* Check that default script directory exist */
787 data = g_build_filename (g_get_home_dir(), LOCAL_ANJUTA_SCRIPT_DIRECTORY, NULL);
788 make_directory (data);
789 g_free (data);
791 data = gtk_editable_get_chars(this->command_en, 0, -1);
793 if (!g_file_test (data, G_FILE_TEST_EXISTS))
795 FILE* sh;
797 /* Create default script */
798 sh = fopen (data, "wt");
799 if (sh != NULL)
801 gint previous;
803 fprintf(sh, "#!\n#\tScript template generated by Anjuta.\n#\tYou can pass argument using command line parameters\n#\n\n");
804 fclose (sh);
806 /* Make this file executable */
807 previous = umask (0666);
808 chmod (data, 0777 & ~previous);
809 umask (previous);
813 /* Load the script in an editor window */
814 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (this->parent->plugin)->shell, IAnjutaDocumentManager, NULL);
815 if (docman == NULL)
817 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("Unable to edit script"));
818 return;
821 uri = gnome_vfs_get_uri_from_local_path(data);
822 g_free (data);
823 doc =
824 ianjuta_document_manager_find_document_with_uri
825 (docman, uri, NULL);
826 if (doc == NULL)
828 IAnjutaFileLoader* loader;
830 /* Not found, load file */
831 loader = IANJUTA_FILE_LOADER (anjuta_shell_get_interface (ANJUTA_PLUGIN (this->parent->plugin)->shell, IAnjutaFileLoader, NULL));
832 ianjuta_file_loader_load (loader, uri, FALSE, NULL);
834 else
836 /* Set as current */
837 ianjuta_document_manager_set_current_document (docman, doc, NULL);
839 g_free (uri);
843 atp_tool_dialog_refresh (this->parent, atp_user_tool_get_name (this->tool));
845 atp_tool_editor_free (this);
848 static void
849 on_editor_param_variable_show (GtkButton *button, gpointer user_data)
851 ATPToolEditor* this = (ATPToolEditor*)user_data;
853 atp_variable_dialog_show (&this->param_var, ATP_DEFAULT_VARIABLE);
856 static void
857 on_editor_dir_variable_show (GtkButton *button, gpointer user_data)
859 ATPToolEditor* this = (ATPToolEditor*)user_data;
861 atp_variable_dialog_show (&this->dir_var, ATP_DIRECTORY_VARIABLE);
864 static void
865 on_editor_input_variable_show (GtkButton *button, gpointer user_data)
867 ATPToolEditor* this = (ATPToolEditor*)user_data;
869 switch (get_combo_box_value (this->input_com))
871 case ATP_TIN_FILE:
872 atp_variable_dialog_show (&this->input_file_var, ATP_FILE_VARIABLE);
873 break;
874 case ATP_TIN_STRING:
875 atp_variable_dialog_show (&this->input_string_var, ATP_DEFAULT_VARIABLE);
876 break;
880 static gboolean
881 on_editor_get_keys(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
883 ATPToolEditor *this = (ATPToolEditor*)user_data;
884 GdkDisplay *display;
885 guint accel_key = 0;
886 GdkModifierType accel_mods = 0;
887 GdkModifierType consumed_mods = 0;
888 gboolean delete = FALSE;
889 gboolean edited = FALSE;
891 switch (event->keyval)
893 case GDK_Shift_L:
894 case GDK_Shift_R:
895 case GDK_Control_L:
896 case GDK_Control_R:
897 case GDK_Alt_L:
898 case GDK_Alt_R:
899 return TRUE;
900 case GDK_Escape:
901 break;
902 case GDK_Delete:
903 case GDK_KP_Delete:
904 case GDK_BackSpace:
905 delete = TRUE;
906 break;
907 default:
908 display = gtk_widget_get_display (widget);
909 gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display),
910 event->hardware_keycode,
911 event->state,
912 event->group,
913 NULL, NULL, NULL, &consumed_mods);
915 accel_key = gdk_keyval_to_lower (event->keyval);
916 accel_mods = (event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_mods);
918 /* If lowercasing affects the keysym, then we need to include SHIFT
919 * in the modifiers, We re-upper case when we match against the
920 * keyval, but display and save in caseless form.
922 if (accel_key != event->keyval)
923 accel_mods |= GDK_SHIFT_MASK;
925 edited = gtk_accelerator_valid (accel_key, accel_mods);
926 break;
929 if (delete || edited)
931 /* Remove previous shortcut */
932 if (this->shortcut != NULL) g_free (this->shortcut);
934 /* Set new one */
935 this->shortcut = delete ? NULL : gtk_accelerator_name (accel_key, accel_mods);
938 gtk_toggle_button_set_active (this->shortcut_bt, FALSE);
940 return TRUE;
943 static void
944 on_editor_shortcut_toggle (GtkToggleButton *tb, gpointer user_data)
946 ATPToolEditor *this = (ATPToolEditor *)user_data;
948 if (gtk_toggle_button_get_active (tb))
950 gtk_grab_add(GTK_WIDGET(tb));
952 g_signal_connect (G_OBJECT (tb), "key_press_event", G_CALLBACK (on_editor_get_keys), this);
953 gtk_button_set_label (GTK_BUTTON (tb), _("New accelerator..."));
955 else
957 g_signal_handlers_disconnect_by_func (G_OBJECT (this->shortcut_bt), G_CALLBACK (on_editor_get_keys), this);
958 gtk_grab_remove (GTK_WIDGET(this->shortcut_bt));
960 atp_editor_update_shortcut (this);
964 gboolean
965 atp_tool_editor_show (ATPToolEditor* this)
967 GladeXML *xml;
969 if (this->dialog != NULL)
971 /* dialog is already displayed */
972 gtk_window_present (GTK_WINDOW (this->dialog));
973 return TRUE;
976 if (NULL == (xml = glade_xml_new(GLADE_FILE, TOOL_EDITOR, NULL)))
978 anjuta_util_dialog_error (atp_tool_dialog_get_window (this->parent), _("Unable to build user interface for tool editor"));
979 g_free(this);
981 return FALSE;
983 this->dialog = glade_xml_get_widget(xml, TOOL_EDITOR);
984 gtk_widget_show (this->dialog);
985 gtk_window_set_transient_for (GTK_WINDOW (this->dialog), atp_plugin_get_app_window (this->parent->plugin));
987 this->name_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_NAME));
988 this->command_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_COMMAND));
989 this->param_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_PARAM));
990 atp_variable_dialog_set_entry (&this->param_var, this->param_en);
991 this->dir_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_WORKING_DIR));
992 atp_variable_dialog_set_entry (&this->dir_var, this->dir_en);
993 this->enabled_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, TOOL_ENABLED));
994 this->terminal_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_TERMINAL));
995 this->autosave_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_AUTOSAVE));
996 this->script_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_SCRIPT));
997 this->output_com = GTK_COMBO_BOX (glade_xml_get_widget(xml, TOOL_OUTPUT));
998 this->error_com = GTK_COMBO_BOX (glade_xml_get_widget(xml, TOOL_ERROR));
999 this->input_com = GTK_COMBO_BOX (glade_xml_get_widget(xml, TOOL_INPUT));
1000 this->input_en = GTK_EDITABLE (glade_xml_get_widget(xml, TOOL_INPUT_VALUE));
1001 this->input_var_bt = GTK_BUTTON (glade_xml_get_widget(xml, TOOL_INPUT_VARIABLE));
1002 this->shortcut_bt = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_SHORTCUT));
1003 atp_variable_dialog_set_entry (&this->input_file_var, this->input_en);
1004 atp_variable_dialog_set_entry (&this->input_string_var, this->input_en);
1005 this->icon_en = GNOME_ICON_ENTRY (glade_xml_get_widget(xml, TOOL_ICON));
1007 /* Add combox box value */
1008 set_combo_box_enum_model (this->error_com, atp_get_error_type_list());
1009 set_combo_box_enum_model (this->output_com, atp_get_output_type_list());
1010 set_combo_box_enum_model (this->input_com, atp_get_input_type_list());
1012 atp_clear_tool_editor (this);
1013 atp_populate_tool_editor (this);
1014 atp_update_sensitivity (this);
1016 /* Connect all signals */
1017 glade_xml_signal_connect_data (xml, EDITOR_RESPONSE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_response), this);
1018 glade_xml_signal_connect_data (xml, EDITOR_PARAM_VARIABLE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_param_variable_show), this);
1019 glade_xml_signal_connect_data (xml, EDITOR_DIR_VARIABLE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_dir_variable_show), this);
1020 glade_xml_signal_connect_data (xml, EDITOR_TOGGLE_SHORCUT_SIGNAL, GTK_SIGNAL_FUNC (on_editor_shortcut_toggle), this);
1021 glade_xml_signal_connect_data (xml, EDITOR_TOGGLE_TERMINAL_SIGNAL, GTK_SIGNAL_FUNC (on_editor_terminal_toggle), this);
1022 glade_xml_signal_connect_data (xml, EDITOR_TOGGLE_SCRIPT_SIGNAL, GTK_SIGNAL_FUNC (on_editor_script_toggle), this);
1023 glade_xml_signal_connect_data (xml, EDITOR_INPUT_VARIABLE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_input_variable_show), this);
1024 glade_xml_signal_connect_data (xml, EDITOR_INPUT_CHANGED_SIGNAL, GTK_SIGNAL_FUNC (on_editor_input_changed), this);
1026 g_object_unref (xml);
1028 return TRUE;
1031 ATPToolEditor*
1032 atp_tool_editor_new (ATPUserTool *tool, ATPToolEditorList *list, struct _ATPToolDialog *dialog)
1034 ATPToolEditor *this;
1036 /* Search a already existing tool editor with same name */
1037 for (this = list->first; this != NULL; this = this->next)
1039 /* Name use the same string, so a string comparaison is not necessary */
1040 if (atp_user_tool_get_name (this->tool) == atp_user_tool_get_name (tool))
1042 return this;
1046 /* Not found, create a new object */
1047 this = g_new0(ATPToolEditor, 1);
1048 this->parent = dialog;
1049 this->owner = list;
1050 this->tool = tool;
1051 atp_variable_dialog_construct (&this->param_var, this, ATP_VARIABLE_DEFAULT);
1052 atp_variable_dialog_construct (&this->dir_var, this, ATP_VARIABLE_REPLACE);
1053 atp_variable_dialog_construct (&this->input_file_var, this, ATP_VARIABLE_REPLACE);
1054 atp_variable_dialog_construct (&this->input_string_var, this, ATP_VARIABLE_REPLACE);
1056 /* Add it in the list */
1057 if (list != NULL)
1059 this->next = list->first;
1060 list->first = this;
1063 return this;
1066 gboolean
1067 atp_tool_editor_free (ATPToolEditor *this)
1069 ATPToolEditor **prev;
1071 atp_variable_dialog_destroy (&this->input_string_var);
1072 atp_variable_dialog_destroy (&this->input_file_var);
1073 atp_variable_dialog_destroy (&this->dir_var);
1074 atp_variable_dialog_destroy (&this->param_var);
1076 if (this->shortcut != NULL) g_free (this->shortcut);
1078 if (this->owner == NULL)
1080 /* tool editor is not in a list */
1081 gtk_widget_destroy (GTK_WIDGET (this->dialog));
1082 g_free (this);
1084 return TRUE;
1087 /* Search tool editor in list */
1088 for (prev = &this->owner->first; *prev != NULL; prev = &((*prev)->next))
1090 if (*prev == this)
1092 /* remove tool editor from list */
1093 *prev = this->next;
1094 /* delete tool editor object */
1095 gtk_widget_destroy (GTK_WIDGET (this->dialog));
1096 g_free (this);
1098 return TRUE;
1102 /* tool editor not found in list */
1103 return FALSE;
1106 /* Tool editor list
1107 * This list all the current active tool editors, it is mainly useful for
1108 * avoiding to have two dialogs editing the same tool. It could be possible
1109 * because the tool editing dialog is not modal.
1110 *---------------------------------------------------------------------------*/
1112 ATPToolEditorList*
1113 atp_tool_editor_list_construct (ATPToolEditorList* this)
1115 this->first = NULL;
1117 return this;
1120 void
1121 atp_tool_editor_list_destroy (ATPToolEditorList* this)
1123 ATPToolEditor *ted;
1125 for ( ; (ted = this->first) != NULL;)
1127 atp_tool_editor_free (ted);