Updated Spanish translation
[anjuta.git] / plugins / tools / editor.c
blobf5c90dce778f4abc175f8aca0e2e731a3bf883cd
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>
28 #include <errno.h>
29 #include <sys/stat.h>
30 #include "editor.h"
32 #include "dialog.h"
33 #include "tool.h"
34 #include "variable.h"
36 #include <libanjuta/anjuta-utils.h>
37 #include <libanjuta/interfaces/ianjuta-document-manager.h>
38 #include <libanjuta/interfaces/ianjuta-editor.h>
39 #include <libanjuta/interfaces/ianjuta-file-loader.h>
40 #include <glib.h>
41 #include <gdk/gdk.h>
42 #include <gtk/gtk.h>
43 #include <sys/types.h>
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include <string.h>
48 /*---------------------------------------------------------------------------*/
50 /* Variable dialog */
52 typedef enum {
53 ATP_VARIABLE_DEFAULT = 0,
54 ATP_VARIABLE_REPLACE = 1 << 1
55 } ATPVariableType;
57 typedef struct _ATPVariableDialog
59 GtkDialog* dialog;
60 GtkTreeView* view;
61 ATPToolEditor* editor;
62 GtkEditable* entry;
63 ATPVariableType type;
64 } ATPVariableDialog;
66 enum {
67 ATP_VARIABLE_NAME_COLUMN,
68 ATP_VARIABLE_MEAN_COLUMN,
69 ATP_VARIABLE_VALUE_COLUMN,
70 ATP_N_VARIABLE_COLUMNS,
73 /* Structure containing the required properties of the tool editor GUI */
74 struct _ATPToolEditor
76 GtkWidget *dialog;
77 GtkEditable *name_en;
78 GtkEditable *command_en;
79 GtkEditable *param_en;
80 ATPVariableDialog param_var;
81 GtkEditable *dir_en;
82 ATPVariableDialog dir_var;
83 GtkToggleButton *enabled_tb;
84 GtkToggleButton *terminal_tb;
85 GtkToggleButton *autosave_tb;
86 GtkToggleButton *script_tb;
87 GtkComboBox *output_com;
88 GtkComboBox *error_com;
89 GtkComboBox *input_com;
90 GtkEditable *input_en;
91 GtkButton *input_var_bt;
92 ATPVariableDialog input_file_var;
93 ATPVariableDialog input_string_var;
94 GtkToggleButton *shortcut_bt;
95 GtkButton *icon_en;
96 gchar* shortcut;
97 ATPUserTool *tool;
98 ATPToolDialog* parent;
99 ATPToolEditorList* owner;
100 ATPToolEditor* next;
103 /*---------------------------------------------------------------------------*/
105 /* Widget and signal name found in glade file
106 *---------------------------------------------------------------------------*/
108 #define TOOL_EDITOR "editor_dialog"
109 #define TOOL_NAME "name_entry"
110 #define TOOL_COMMAND "command_entry"
111 #define TOOL_PARAM "parameter_entry"
112 #define TOOL_WORKING_DIR "directory_entry"
113 #define TOOL_ENABLED "enable_checkbox"
114 #define TOOL_AUTOSAVE "save_checkbox"
115 #define TOOL_TERMINAL "terminal_checkbox"
116 #define TOOL_SCRIPT "script_checkbox"
117 #define TOOL_OUTPUT "output_combo"
118 #define TOOL_ERROR "error_combo"
119 #define TOOL_INPUT "input_combo"
120 #define TOOL_INPUT_VALUE "input_entry"
121 #define TOOL_INPUT_VARIABLE "input_button"
122 #define TOOL_SHORTCUT "shortcut_bt"
123 #define TOOL_ICON "icon_entry"
124 #define TOOL_BROWSE_WORKING_DIR "browse_button_directory_entry"
125 #define TOOL_BROWSE_COMMAND "browse_button_command_entry"
126 #define TOOL_VARIABLE "variable_dialog"
127 #define VARIABLE_TREEVIEW "variable_treeview"
129 void atp_on_variable_activate_row (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data);
130 void atp_on_variable_dialog_response (GtkDialog *dialog, gint response, gpointer user_data);
131 void atp_on_editor_icon_entry_clicked (GtkButton *button, gpointer user_data);
132 void atp_on_editor_terminal_toggle (GtkToggleButton *tb, gpointer user_data);
133 void atp_on_editor_script_toggle (GtkToggleButton *tb, gpointer user_data);
134 void atp_on_editor_input_changed (GtkComboBox *combo, gpointer user_data);
135 void atp_on_editor_dialog_response (GtkDialog *dialog, gint response, gpointer user_data);
136 void atp_on_editor_param_variable_show (GtkButton *button, gpointer user_data);
137 void atp_on_editor_dir_variable_show (GtkButton *button, gpointer user_data);
138 void atp_on_editor_input_variable_show (GtkButton *button, gpointer user_data);
139 void atp_on_editor_shortcut_toggle (GtkToggleButton *tb, gpointer user_data);
140 void atp_on_editor_browse_button_clicked (GtkButton *button, GtkEntry *entry);
141 void atp_on_editor_browse_button_dir_clicked (GtkButton *button, GtkEntry *entry);
144 /* Add helper function
145 *---------------------------------------------------------------------------*/
147 static gboolean
148 make_directory (gchar* path)
150 gchar c;
151 gchar* ptr;
153 for (ptr = path; *ptr;)
155 /* Get next directory */
156 for (c = '\0'; *ptr; ++ptr)
158 if (*ptr == G_DIR_SEPARATOR)
160 /* Strip leading directory separator */
163 ++ptr;
164 } while (*ptr == G_DIR_SEPARATOR);
165 c = *ptr;
166 *ptr = '\0';
167 break;
171 /* Create it */
172 if (mkdir (path, 0755) < 0)
174 /* Error creating directory */
175 *ptr = c;
176 if (errno != EEXIST)
178 /* An already existing directory is not an error */
179 return FALSE;
182 else
184 /* New directory created */
185 *ptr = c;
189 return TRUE;
192 static void
193 set_combo_box_enum_model (GtkComboBox* combo_box, const ATPEnumType* list)
195 GtkTreeModel *model;
196 GtkCellRenderer * renderer;
198 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
200 for (; list->id != -1;++list)
202 GtkTreeIter iter;
204 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
205 gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, _(list->name), 1, list->id, -1);
207 gtk_combo_box_set_model (combo_box, model);
208 renderer = gtk_cell_renderer_text_new();
209 gtk_cell_layout_clear (GTK_CELL_LAYOUT(combo_box));
210 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(combo_box), renderer, TRUE);
211 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(combo_box), renderer, "text", 0 );
214 static gint
215 get_combo_box_value (GtkComboBox* combo_box)
217 GtkTreeIter iter;
218 GtkTreeModel *model;
219 gint value = -1;
221 if (gtk_combo_box_get_active_iter (combo_box, &iter))
223 model = gtk_combo_box_get_model (combo_box);
224 gtk_tree_model_get (model, &iter, 1, &value, -1);
227 return value;
230 static gboolean
231 set_combo_box_value (GtkComboBox* combo_box, gint value)
233 GtkTreeIter iter;
234 GtkTreeModel *model;
235 gint current;
237 if (value != -1)
239 model = gtk_combo_box_get_model (combo_box);
240 if (gtk_tree_model_get_iter_first (model, &iter))
244 gtk_tree_model_get (model, &iter, 1, &current, -1);
245 if (value == current)
247 gtk_combo_box_set_active_iter (combo_box, &iter);
249 return TRUE;
252 while (gtk_tree_model_iter_next (model, &iter));
256 gtk_combo_box_set_active (combo_box, 0);
258 return FALSE;
261 /* Tool variable dialog
262 * Display a list of variables useable as command line parameters or working
263 * directory with their values. Clicking on a variable add it in the current
264 * entry widget.
265 *---------------------------------------------------------------------------*/
267 static ATPVariableDialog*
268 atp_variable_dialog_construct (ATPVariableDialog* this, ATPToolEditor* editor, ATPVariableType type)
270 this->dialog = NULL;
271 this->editor = editor;
272 this->type = type;
274 return this;
277 static void
278 atp_variable_dialog_destroy (ATPVariableDialog* this)
280 if (this->dialog)
282 gtk_widget_destroy (GTK_WIDGET (this->dialog));
283 this->dialog = NULL;
287 static void
288 atp_variable_dialog_set_entry (ATPVariableDialog *this, GtkEditable* entry)
290 this->entry = entry;
293 static void
294 atp_variable_dialog_populate (ATPVariableDialog* this, ATPFlags flag)
296 GtkTreeModel *model;
297 ATPVariable* variable;
298 guint i;
300 variable = atp_tool_dialog_get_variable (this->editor->parent);
301 model = gtk_tree_view_get_model (this->view);
302 gtk_list_store_clear (GTK_LIST_STORE(model));
304 for (i = atp_variable_get_count(variable); i > 0;)
306 GtkTreeIter iter;
307 gchar* value;
308 const gchar* value_col;
309 ATPFlags var_flags;
311 --i;
312 var_flags = atp_variable_get_flag (variable, i);
313 if (!(var_flags & ATP_NO_VARIABLE) && ((flag == ATP_DEFAULT_VARIABLE) || (var_flags & flag)))
315 if (var_flags & ATP_INTERACTIVE_VARIABLE)
317 value = NULL;
318 value_col = _("ask at runtime");
320 else
322 value = atp_variable_get_value_from_id (variable, i);
323 value_col = (value == NULL) ? _("undefined") : value;
325 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
326 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
327 ATP_VARIABLE_NAME_COLUMN,
328 atp_variable_get_name(variable, i),
329 ATP_VARIABLE_MEAN_COLUMN,
330 _(atp_variable_get_help(variable, i)),
331 ATP_VARIABLE_VALUE_COLUMN,
332 value_col,
333 -1);
334 if (value) g_free (value);
339 static void
340 atp_variable_dialog_add_variable(ATPVariableDialog *this, const gchar* text)
342 gint pos;
344 g_return_if_fail (this->entry);
346 if (text != NULL)
348 gchar* next;
350 if (this->type == ATP_VARIABLE_REPLACE)
352 gtk_editable_delete_text (this->entry, 0, -1);
355 pos = gtk_editable_get_position(this->entry);
356 /* Add space before if useful */
357 if (pos != 0)
359 next = gtk_editable_get_chars (this->entry, pos - 1, pos);
361 if (!g_ascii_isspace (*next))
363 gtk_editable_insert_text (this->entry, " ", 1, &pos);
365 g_free (next);
367 gtk_editable_insert_text (this->entry, "$(", 2, &pos);
368 gtk_editable_insert_text (this->entry, text, strlen(text), &pos);
369 gtk_editable_insert_text (this->entry, ")", 1, &pos);
370 /* Add space after if useful */
371 next = gtk_editable_get_chars (this->entry, pos, pos + 1);
372 if (next != NULL)
374 if ((*next != '\0') && (!g_ascii_isspace (*next)))
376 gtk_editable_insert_text (this->entry, " ",1, &pos);
378 g_free (next);
383 static gchar*
384 get_current_name (GtkTreeView *view)
386 GtkTreeModel *model;
387 GtkTreeSelection *sel;
388 GtkTreeIter iter;
389 gchar* name;
391 model = gtk_tree_view_get_model (view);
392 sel = gtk_tree_view_get_selection (view);
393 if (gtk_tree_selection_get_selected (sel, &model, &iter))
395 gtk_tree_model_get (model, &iter, ATP_VARIABLE_NAME_COLUMN, &name, -1);
397 return name;
400 return NULL;
403 void
404 atp_on_variable_activate_row (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
406 ATPVariableDialog *this = (ATPVariableDialog*)user_data;
407 GtkTreeIter iter;
408 GtkTreeModel *model;
409 gchar* name;
411 /* Get Selected variable name */
412 model = gtk_tree_view_get_model (treeview);
413 gtk_tree_model_get_iter (model, &iter, path);
414 gtk_tree_model_get (model, &iter, ATP_VARIABLE_NAME_COLUMN, &name, -1);
416 atp_variable_dialog_add_variable (this, name);
418 gtk_widget_hide (GTK_WIDGET (this->dialog));
421 void
422 atp_on_variable_dialog_response (GtkDialog *dialog, gint response, gpointer user_data)
424 ATPVariableDialog *this = (ATPVariableDialog *)user_data;
425 gchar* name;
427 switch (response)
429 case GTK_RESPONSE_OK:
430 name = get_current_name (this->view);
431 atp_variable_dialog_add_variable (this, name);
432 break;
433 default:
434 break;
437 gtk_widget_hide (GTK_WIDGET (this->dialog));
440 static gboolean
441 atp_variable_dialog_show (ATPVariableDialog* this, ATPFlags flag)
443 GtkBuilder *bxml;
444 GtkTreeModel *model;
445 GtkCellRenderer *renderer;
446 GtkTreeViewColumn *column;
448 if (this->dialog != NULL)
450 /* Display dialog box */
451 if (this->dialog) gtk_window_present (GTK_WINDOW (this->dialog));
452 return TRUE;
455 bxml = anjuta_util_builder_new (GLADE_FILE, NULL);
456 if (!bxml) return FALSE;
457 anjuta_util_builder_get_objects (bxml,
458 TOOL_VARIABLE, &this->dialog,
459 VARIABLE_TREEVIEW, &this->view,
460 NULL);
462 gtk_widget_show (GTK_WIDGET (this->dialog));
463 gtk_window_set_transient_for (GTK_WINDOW (this->dialog), GTK_WINDOW (this->editor->dialog));
465 /* Create variable list */
466 model = GTK_TREE_MODEL (gtk_list_store_new (ATP_N_VARIABLE_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING));
467 gtk_tree_view_set_model (this->view, model);
469 renderer = gtk_cell_renderer_text_new ();
470 column = gtk_tree_view_column_new_with_attributes (_("Variable"), renderer, "text", ATP_VARIABLE_NAME_COLUMN, NULL);
471 gtk_tree_view_append_column (this->view, column);
472 renderer = gtk_cell_renderer_text_new ();
473 column = gtk_tree_view_column_new_with_attributes (_("Meaning"), renderer, "text", ATP_VARIABLE_MEAN_COLUMN, NULL);
474 gtk_tree_view_append_column (this->view, column);
475 renderer = gtk_cell_renderer_text_new ();
476 column = gtk_tree_view_column_new_with_attributes (_("Value"), renderer, "text", ATP_VARIABLE_VALUE_COLUMN, NULL);
477 gtk_tree_view_append_column (this->view, column);
478 g_object_unref (model);
479 atp_variable_dialog_populate (this, flag);
481 /* Connect all signals */
482 gtk_builder_connect_signals (bxml, this);
483 g_signal_connect (G_OBJECT (this->dialog), "delete_event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
485 g_object_unref (bxml);
487 return TRUE;
490 /* Tool editor dialog
491 *---------------------------------------------------------------------------*/
493 static void
494 cb_preview_update (GtkFileChooser *fc,
495 GtkImage *preview)
497 char *filename;
498 GdkPixbuf *pixbuf;
500 filename = gtk_file_chooser_get_preview_filename (fc);
501 if (filename) {
502 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
504 gtk_file_chooser_set_preview_widget_active (fc, pixbuf != NULL);
506 if (pixbuf) {
507 gtk_image_set_from_pixbuf (preview, pixbuf);
508 g_object_unref (pixbuf);
511 g_free (filename);
515 void
516 atp_on_editor_icon_entry_clicked (GtkButton *button, gpointer user_data)
518 ATPToolEditor *this = (ATPToolEditor *)user_data;
519 GtkWidget *dialog;
520 GtkFileFilter *filter;
521 GtkWidget *preview;
522 int res;
524 dialog = gtk_file_chooser_dialog_new (_("Select an Image File"),
525 NULL,
526 GTK_FILE_CHOOSER_ACTION_OPEN,
527 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
528 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
529 NULL);
530 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
531 PACKAGE_PIXMAPS_DIR);
532 filter = gtk_file_filter_new ();
533 gtk_file_filter_add_pixbuf_formats (filter);
534 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
536 preview = gtk_image_new ();
537 gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog),
538 preview);
539 g_signal_connect (dialog, "update-preview",
540 G_CALLBACK (cb_preview_update), preview);
542 res = gtk_dialog_run (GTK_DIALOG (dialog));
544 if (res == GTK_RESPONSE_ACCEPT) {
545 gchar *filename;
547 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
548 if (filename != NULL)
550 GtkWidget* image;
551 image = gtk_image_new_from_file (filename);
552 gtk_button_set_image (button, image);
553 gtk_button_set_label (button, NULL);
555 else
557 gtk_button_set_image (button, NULL);
558 gtk_button_set_label (button, _("Choose Icon"));
560 atp_user_tool_set_icon (this->tool, filename);
561 g_free (filename);
564 gtk_widget_destroy (dialog);
567 static void
568 atp_clear_tool_editor(ATPToolEditor* this)
570 g_return_if_fail (this != NULL);
572 gtk_editable_delete_text(this->name_en, 0, -1);
573 gtk_editable_delete_text(this->command_en, 0, -1);
574 gtk_editable_delete_text(this->param_en, 0, -1);
575 gtk_editable_delete_text(this->dir_en, 0, -1);
578 static void
579 atp_update_sensitivity(ATPToolEditor *this)
581 gboolean en;
583 /* Deactivate output and input setting if a terminal is used */
584 en = gtk_toggle_button_get_active (this->terminal_tb);
585 gtk_widget_set_sensitive(GTK_WIDGET (this->output_com), !en);
586 gtk_widget_set_sensitive(GTK_WIDGET (this->error_com), !en);
587 gtk_widget_set_sensitive(GTK_WIDGET (this->input_com), !en);
589 /* input value is available for a few input type only */
590 if (!en)
592 switch (get_combo_box_value (this->input_com))
594 case ATP_TIN_FILE:
595 case ATP_TIN_STRING:
596 en = TRUE;
597 break;
598 default:
599 en = FALSE;
600 break;
602 gtk_widget_set_sensitive(GTK_WIDGET (this->input_en), en);
603 gtk_widget_set_sensitive(GTK_WIDGET (this->input_var_bt), en);
605 else
607 gtk_widget_set_sensitive(GTK_WIDGET (this->input_en), FALSE);
608 gtk_widget_set_sensitive(GTK_WIDGET (this->input_var_bt), FALSE);
612 static void
613 atp_editor_update_shortcut (ATPToolEditor* this)
615 if (this->shortcut != NULL)
617 gtk_button_set_label (GTK_BUTTON (this->shortcut_bt), this->shortcut);
619 else
621 gtk_button_set_label (GTK_BUTTON (this->shortcut_bt), _("Disabled"));
625 static void
626 atp_populate_tool_editor(ATPToolEditor* this)
628 gint pos;
629 const gchar* value;
630 guint accel_key;
631 GdkModifierType accel_mods;
633 g_return_if_fail (this != NULL);
635 /* Nothing to fill */
636 if (this->tool == NULL) return;
638 value = atp_user_tool_get_name (this->tool);
639 if (value)
641 gtk_editable_insert_text(this->name_en, value
642 , strlen(value), &pos);
644 value = atp_user_tool_get_command (this->tool);
645 if (value)
647 gtk_editable_insert_text(this->command_en, value
648 , strlen(value), &pos);
650 value = atp_user_tool_get_param (this->tool);
651 if (value)
653 gtk_editable_insert_text(this->param_en, value
654 , strlen(value), &pos);
656 value = atp_user_tool_get_working_dir (this->tool);
657 if (value)
659 gtk_editable_insert_text(this->dir_en, value
660 , strlen(value), &pos);
662 gtk_toggle_button_set_active (this->enabled_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_ENABLE));
663 gtk_toggle_button_set_active (this->autosave_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_AUTOSAVE));
664 gtk_toggle_button_set_active (this->terminal_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_TERMINAL));
666 set_combo_box_value (this->output_com, atp_user_tool_get_output (this->tool));
667 set_combo_box_value (this->error_com, atp_user_tool_get_error (this->tool));
668 set_combo_box_value (this->input_com, atp_user_tool_get_input (this->tool));
669 switch (atp_user_tool_get_input (this->tool))
671 case ATP_TIN_FILE:
672 case ATP_TIN_STRING:
673 value = atp_user_tool_get_input_string (this->tool);
674 if (value)
676 gtk_editable_insert_text(this->input_en, value, strlen(value), &pos);
678 break;
679 default:
680 break;
682 atp_update_sensitivity (this);
684 if (this->shortcut != NULL) g_free (this->shortcut);
685 if (atp_user_tool_get_accelerator (this->tool, &accel_key, &accel_mods))
687 this->shortcut = gtk_accelerator_name (accel_key, accel_mods);
689 else
691 this->shortcut = NULL;
693 atp_editor_update_shortcut (this);
695 if (atp_user_tool_get_icon (this->tool))
697 GtkWidget* image;
698 image = gtk_image_new_from_file (atp_user_tool_get_icon (this->tool));
699 gtk_button_set_image (this->icon_en, image);
700 gtk_button_set_label (this->icon_en, NULL);
702 else
704 gtk_button_set_image (this->icon_en, NULL);
705 gtk_button_set_label (this->icon_en, _("Choose Icon"));
709 void
710 atp_on_editor_terminal_toggle (GtkToggleButton *tb, gpointer user_data)
712 ATPToolEditor *this = (ATPToolEditor *)user_data;
714 atp_update_sensitivity (this);
717 void
718 atp_on_editor_script_toggle (GtkToggleButton *tb, gpointer user_data)
720 ATPToolEditor *this = (ATPToolEditor *)user_data;
721 gchar* command;
723 if (gtk_toggle_button_get_active(tb))
725 /* Get current command */
726 command = gtk_editable_get_chars(this->command_en, 0, -1);
728 if ((command == NULL) || (*command == '\0'))
730 gchar* name;
731 gint pos;
733 if (command) g_free (command);
734 /* Generate a new script file name */
735 command = gtk_editable_get_chars(this->name_en, 0, -1);
736 if ((command == NULL) || (*command == '\0'))
738 command = g_strdup("script");
740 name = atp_remove_mnemonic (command);
741 g_free (command);
743 command = anjuta_util_get_user_data_file_path ("scripts/", name, NULL);
744 g_free (name);
746 /* Find a new file name */
747 name = command;
748 pos = 0;
749 while (g_file_test (command, G_FILE_TEST_EXISTS))
751 if (command != name) g_free (command);
752 command = g_strdup_printf("%s%d", name, pos);
753 pos++;
755 if (command != name) g_free (name);
757 /* Fill command line */
758 gtk_editable_delete_text(this->command_en, 0, -1);
759 gtk_editable_insert_text(this->command_en, command,
760 strlen(command), &pos);
762 if (command) g_free (command);
766 void
767 atp_on_editor_input_changed (GtkComboBox *combo, gpointer user_data)
769 ATPToolEditor *this = (ATPToolEditor *)user_data;
771 atp_update_sensitivity (this);
774 void
775 atp_on_editor_dialog_response (GtkDialog *dialog, gint response, gpointer user_data)
777 ATPToolEditor* this = (ATPToolEditor*)user_data;
778 gchar* name;
779 gchar* data;
780 ATPInputType in_type;
781 guint accel_key;
782 GdkModifierType accel_mods;
783 GtkAccelGroup* group;
784 AnjutaUI* ui;
786 if (response == GTK_RESPONSE_OK)
788 /* Check for all mandatory fields */
789 name = gtk_editable_get_chars(this->name_en, 0, -1);
790 if (!name || '\0' == name[0])
792 if (name) g_free (name);
793 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("You must provide a tool name!"));
794 return;
796 data = gtk_editable_get_chars(this->command_en, 0, -1);
797 if (!data || '\0' == data[0])
799 if (name) g_free (name);
800 if (data) g_free (data);
801 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("You must provide a tool command!"));
802 return;
805 if (!atp_user_tool_set_name (this->tool, name))
807 if (name) g_free (name);
808 if (data) g_free (data);
809 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("A tool with the same name already exists!"));
810 return;
812 g_free (name);
814 if (this->shortcut == NULL)
816 accel_key = 0;
817 accel_mods = 0;
819 else
821 gtk_accelerator_parse (this->shortcut, &accel_key, &accel_mods);
822 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN(this->parent->plugin)->shell, NULL);
823 group = anjuta_ui_get_accel_group(ui);
824 if (gtk_accel_group_query (group, accel_key, accel_mods, NULL) != NULL)
826 if (!anjuta_util_dialog_boolean_question (GTK_WINDOW (this->dialog), FALSE,
827 _("The shortcut is already used by another component in Anjuta. Do you want to keep it anyway?")))
829 return;
834 /* Set new tool data */
835 atp_user_tool_set_command (this->tool, data);
836 g_free (data);
838 data = gtk_editable_get_chars(this->param_en, 0, -1);
839 atp_user_tool_set_param (this->tool, data);
840 g_free (data);
842 data = gtk_editable_get_chars(this->dir_en, 0, -1);
843 atp_user_tool_set_working_dir (this->tool, data);
844 g_free (data);
846 atp_user_tool_set_flag (this->tool, ATP_TOOL_ENABLE | (gtk_toggle_button_get_active(this->enabled_tb) ? ATP_SET : ATP_CLEAR));
848 atp_user_tool_set_flag (this->tool, ATP_TOOL_AUTOSAVE | (gtk_toggle_button_get_active(this->autosave_tb) ? ATP_SET : ATP_CLEAR));
850 atp_user_tool_set_flag (this->tool, ATP_TOOL_TERMINAL | (gtk_toggle_button_get_active(this->terminal_tb) ? ATP_SET : ATP_CLEAR));
853 atp_user_tool_set_output (this->tool, get_combo_box_value (this->output_com));
854 atp_user_tool_set_error (this->tool, get_combo_box_value (this->error_com));
855 in_type = get_combo_box_value (this->input_com);
856 switch (in_type)
858 case ATP_TIN_FILE:
859 case ATP_TIN_STRING:
860 data = gtk_editable_get_chars(this->input_en, 0, -1);
861 atp_user_tool_set_input (this->tool, in_type, data);
862 g_free (data);
863 break;
864 default:
865 atp_user_tool_set_input (this->tool, in_type, NULL);
866 break;
869 atp_user_tool_set_accelerator (this->tool, accel_key, accel_mods);
871 /* Open script in editor if requested */
872 if (gtk_toggle_button_get_active (this->script_tb))
874 IAnjutaDocumentManager *docman;
875 IAnjutaDocument *doc;
876 GFile* file;
878 /* Check that default script directory exist */
879 data = anjuta_util_get_user_data_file_path ("scripts/", NULL);
881 // TODO: Replace with g_mkdir_with_parents
882 make_directory (data);
883 g_free (data);
885 data = gtk_editable_get_chars(this->command_en, 0, -1);
887 if (!g_file_test (data, G_FILE_TEST_EXISTS))
889 FILE* sh;
891 /* Create default script */
892 sh = fopen (data, "wt");
893 if (sh != NULL)
895 gint previous;
897 fprintf(sh, "#!\n#\tScript template generated by Anjuta.\n#\tYou can pass argument using command line parameters\n#\n\n");
898 fclose (sh);
900 /* Make this file executable */
901 previous = umask (0666);
902 chmod (data, 0777 & ~previous);
903 umask (previous);
907 /* Load the script in an editor window */
908 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (this->parent->plugin)->shell, IAnjutaDocumentManager, NULL);
909 if (docman == NULL)
911 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("Unable to edit script"));
912 return;
915 file = g_file_new_for_path (data);
916 g_free (data);
917 doc =
918 ianjuta_document_manager_find_document_with_file
919 (docman, file, NULL);
920 if (doc == NULL)
922 IAnjutaFileLoader* loader;
924 /* Not found, load file */
925 loader = IANJUTA_FILE_LOADER (anjuta_shell_get_interface (ANJUTA_PLUGIN (this->parent->plugin)->shell, IAnjutaFileLoader, NULL));
926 ianjuta_file_loader_load (loader, file, FALSE, NULL);
928 else
930 /* Set as current */
931 ianjuta_document_manager_set_current_document (docman, doc, NULL);
933 g_object_unref (file);
937 atp_tool_dialog_refresh (this->parent, atp_user_tool_get_name (this->tool));
939 atp_tool_editor_free (this);
942 void
943 atp_on_editor_param_variable_show (GtkButton *button, gpointer user_data)
945 ATPToolEditor* this = (ATPToolEditor*)user_data;
947 atp_variable_dialog_show (&this->param_var, ATP_DEFAULT_VARIABLE);
950 void
951 atp_on_editor_dir_variable_show (GtkButton *button, gpointer user_data)
953 ATPToolEditor* this = (ATPToolEditor*)user_data;
955 atp_variable_dialog_show (&this->dir_var, ATP_DIRECTORY_VARIABLE);
958 void
959 atp_on_editor_input_variable_show (GtkButton *button, gpointer user_data)
961 ATPToolEditor* this = (ATPToolEditor*)user_data;
963 switch (get_combo_box_value (this->input_com))
965 case ATP_TIN_FILE:
966 atp_variable_dialog_show (&this->input_file_var, ATP_FILE_VARIABLE);
967 break;
968 case ATP_TIN_STRING:
969 atp_variable_dialog_show (&this->input_string_var, ATP_DEFAULT_VARIABLE);
970 break;
974 static gboolean
975 on_editor_get_keys(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
977 ATPToolEditor *this = (ATPToolEditor*)user_data;
978 GdkDisplay *display;
979 guint accel_key = 0;
980 GdkModifierType accel_mods = 0;
981 GdkModifierType consumed_mods = 0;
982 gboolean delete = FALSE;
983 gboolean edited = FALSE;
985 switch (event->keyval)
987 case GDK_KEY_Shift_L:
988 case GDK_KEY_Shift_R:
989 case GDK_KEY_Control_L:
990 case GDK_KEY_Control_R:
991 case GDK_KEY_Alt_L:
992 case GDK_KEY_Alt_R:
993 return TRUE;
994 case GDK_KEY_Escape:
995 break;
996 case GDK_KEY_Delete:
997 case GDK_KEY_KP_Delete:
998 case GDK_KEY_BackSpace:
999 delete = TRUE;
1000 break;
1001 default:
1002 display = gtk_widget_get_display (widget);
1003 gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display),
1004 event->hardware_keycode,
1005 event->state,
1006 event->group,
1007 NULL, NULL, NULL, &consumed_mods);
1009 accel_key = gdk_keyval_to_lower (event->keyval);
1010 accel_mods = (event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_mods);
1012 /* If lowercasing affects the keysym, then we need to include SHIFT
1013 * in the modifiers, We re-upper case when we match against the
1014 * keyval, but display and save in caseless form.
1016 if (accel_key != event->keyval)
1017 accel_mods |= GDK_SHIFT_MASK;
1019 edited = gtk_accelerator_valid (accel_key, accel_mods);
1020 break;
1023 if (delete || edited)
1025 /* Remove previous shortcut */
1026 if (this->shortcut != NULL) g_free (this->shortcut);
1028 /* Set new one */
1029 this->shortcut = delete ? NULL : gtk_accelerator_name (accel_key, accel_mods);
1032 gtk_toggle_button_set_active (this->shortcut_bt, FALSE);
1034 return TRUE;
1037 void
1038 atp_on_editor_shortcut_toggle (GtkToggleButton *tb, gpointer user_data)
1040 ATPToolEditor *this = (ATPToolEditor *)user_data;
1042 if (gtk_toggle_button_get_active (tb))
1044 gtk_grab_add(GTK_WIDGET(tb));
1046 g_signal_connect (G_OBJECT (tb), "key_press_event", G_CALLBACK (on_editor_get_keys), this);
1047 gtk_button_set_label (GTK_BUTTON (tb), _("New accelerator…"));
1049 else
1051 g_signal_handlers_disconnect_by_func (G_OBJECT (this->shortcut_bt), G_CALLBACK (on_editor_get_keys), this);
1052 gtk_grab_remove (GTK_WIDGET(this->shortcut_bt));
1054 atp_editor_update_shortcut (this);
1058 void
1059 atp_on_editor_browse_button_clicked (GtkButton *button, GtkEntry *entry)
1061 GtkWidget *dialog;
1062 dialog = gtk_file_chooser_dialog_new ("Open File",
1063 NULL,
1064 GTK_FILE_CHOOSER_ACTION_OPEN,
1065 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1066 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1067 NULL);
1068 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
1070 char *filename;
1071 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1073 gtk_entry_set_text (entry, filename);
1075 g_free (filename);
1077 gtk_widget_destroy(dialog);
1080 void
1081 atp_on_editor_browse_button_dir_clicked (GtkButton *button, GtkEntry *entry)
1083 GtkWidget *dialog;
1084 dialog = gtk_file_chooser_dialog_new ("Open",
1085 NULL,
1086 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1087 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1088 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1089 NULL);
1090 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
1092 char *filename;
1093 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1095 gtk_entry_set_text (entry, filename);
1097 g_free (filename);
1099 gtk_widget_destroy(dialog);
1102 gboolean
1103 atp_tool_editor_show (ATPToolEditor* this)
1105 GtkBuilder *bxml;
1107 if (this->dialog != NULL)
1109 /* dialog is already displayed */
1110 gtk_window_present (GTK_WINDOW (this->dialog));
1111 return TRUE;
1114 bxml = anjuta_util_builder_new (GLADE_FILE, NULL);
1115 if (!bxml) return FALSE;
1117 /* Get all objects */
1118 anjuta_util_builder_get_objects (bxml,
1119 TOOL_EDITOR, &this->dialog,
1120 TOOL_NAME, &this->name_en ,
1121 TOOL_COMMAND, &this->command_en,
1122 TOOL_PARAM, &this->param_en,
1123 TOOL_WORKING_DIR, &this->dir_en,
1124 TOOL_ENABLED, &this->enabled_tb,
1125 TOOL_TERMINAL, &this->terminal_tb,
1126 TOOL_AUTOSAVE, &this->autosave_tb,
1127 TOOL_SCRIPT, &this->script_tb,
1128 TOOL_OUTPUT, &this->output_com,
1129 TOOL_ERROR, &this->error_com,
1130 TOOL_INPUT, &this->input_com,
1131 TOOL_INPUT_VALUE, &this->input_en,
1132 TOOL_INPUT_VARIABLE, &this->input_var_bt,
1133 TOOL_SHORTCUT, &this->shortcut_bt,
1134 TOOL_ICON, &this->icon_en,
1135 NULL);
1137 gtk_widget_show (this->dialog);
1138 gtk_window_set_transient_for (GTK_WINDOW (this->dialog), atp_plugin_get_app_window (this->parent->plugin));
1140 /* Initialize entries */
1141 atp_variable_dialog_set_entry (&this->param_var, this->param_en);
1142 atp_variable_dialog_set_entry (&this->dir_var, this->dir_en);
1143 atp_variable_dialog_set_entry (&this->input_file_var, this->input_en);
1144 atp_variable_dialog_set_entry (&this->input_string_var, this->input_en);
1146 /* Add combox box value */
1147 set_combo_box_enum_model (this->error_com, atp_get_error_type_list());
1148 set_combo_box_enum_model (this->output_com, atp_get_output_type_list());
1149 set_combo_box_enum_model (this->input_com, atp_get_input_type_list());
1151 atp_clear_tool_editor (this);
1152 atp_populate_tool_editor (this);
1153 atp_update_sensitivity (this);
1155 /* Connect all signals */
1156 gtk_builder_connect_signals (bxml, this);
1158 g_object_unref (bxml);
1160 return TRUE;
1163 ATPToolEditor*
1164 atp_tool_editor_new (ATPUserTool *tool, ATPToolEditorList *list, struct _ATPToolDialog *dialog)
1166 ATPToolEditor *this;
1168 /* Search a already existing tool editor with same name */
1169 for (this = list->first; this != NULL; this = this->next)
1171 /* Name use the same string, so a string comparaison is not necessary */
1172 if (atp_user_tool_get_name (this->tool) == atp_user_tool_get_name (tool))
1174 return this;
1178 /* Not found, create a new object */
1179 this = g_new0(ATPToolEditor, 1);
1180 this->parent = dialog;
1181 this->owner = list;
1182 this->tool = tool;
1183 atp_variable_dialog_construct (&this->param_var, this, ATP_VARIABLE_DEFAULT);
1184 atp_variable_dialog_construct (&this->dir_var, this, ATP_VARIABLE_REPLACE);
1185 atp_variable_dialog_construct (&this->input_file_var, this, ATP_VARIABLE_REPLACE);
1186 atp_variable_dialog_construct (&this->input_string_var, this, ATP_VARIABLE_REPLACE);
1188 /* Add it in the list */
1189 if (list != NULL)
1191 this->next = list->first;
1192 list->first = this;
1195 return this;
1198 gboolean
1199 atp_tool_editor_free (ATPToolEditor *this)
1201 ATPToolEditor **prev;
1203 atp_variable_dialog_destroy (&this->input_string_var);
1204 atp_variable_dialog_destroy (&this->input_file_var);
1205 atp_variable_dialog_destroy (&this->dir_var);
1206 atp_variable_dialog_destroy (&this->param_var);
1208 if (this->shortcut != NULL) g_free (this->shortcut);
1210 if (atp_user_tool_get_name (this->tool) == NULL) atp_user_tool_free(this->tool);
1212 if (this->owner == NULL)
1214 /* tool editor is not in a list */
1215 gtk_widget_destroy (GTK_WIDGET (this->dialog));
1216 g_free (this);
1218 return TRUE;
1221 /* Search tool editor in list */
1222 for (prev = &this->owner->first; *prev != NULL; prev = &((*prev)->next))
1224 if (*prev == this)
1226 /* remove tool editor from list */
1227 *prev = this->next;
1228 /* delete tool editor object */
1229 gtk_widget_destroy (GTK_WIDGET (this->dialog));
1230 g_free (this);
1232 return TRUE;
1236 /* tool editor not found in list */
1237 return FALSE;
1240 /* Tool editor list
1241 * This list all the current active tool editors, it is mainly useful for
1242 * avoiding to have two dialogs editing the same tool. It could be possible
1243 * because the tool editing dialog is not modal.
1244 *---------------------------------------------------------------------------*/
1246 ATPToolEditorList*
1247 atp_tool_editor_list_construct (ATPToolEditorList* this)
1249 this->first = NULL;
1251 return this;
1254 void
1255 atp_tool_editor_list_destroy (ATPToolEditorList* this)
1257 ATPToolEditor *ted;
1259 for ( ; (ted = this->first) != NULL;)
1261 atp_tool_editor_free (ted);