Updated Spanish translation
[anjuta.git] / libanjuta / anjuta-ui.c
blob355d5b2583a4840f4289409b1e04c6baf7bc5da6
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-ui.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
5 *
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
21 /**
22 * SECTION:anjuta-ui
23 * @short_description: User Interface manager
24 * @see_also: #GtkAction, #GtkActionEntry, #GtkToggleAction,
25 * #GtkToggleActionEntry, #GtkRadioAction, #GtkRadioActionEntry,
26 * #GtkActionGroup, #GtkUIManager
27 * @stability: Unstable
28 * @include: libanjuta/
30 * #AnjutaUI subclasses #GtkUIManager, so you should really read #GtkUIManager
31 * documentation first to know about Actions, UI merging and UI XML file
32 * format. This documentation will cover only the relevent APIs.
34 * #AnjutaUI has its own methods for adding action groups, which is differnt
35 * from #GtkUIManager methods. All #AnjutaPlugin based classes should use
36 * these methods instead of #GtkUIManager methods. The reason is, in addition
37 * to adding the actions and groups to the UI manager, it also resgisters
38 * them for UI customization and accellerators editing. It also keeps
39 * record of all actions.
41 * An interesting side effect of this is that these
42 * actions could be conveniently accessed or activated with
43 * anjuta_ui_get_action() or anjuta_ui_activate_action_by_path(), without
44 * the need of original action group object. This makes it is possible for
45 * activating actions remotely from other plugins.
47 * anjuta_ui_get_accel_editor() will return a widget containing the
48 * UI customization and accellerators editor. All actions and action groups
49 * are organized into a tree view, which should be added to a visible
50 * container (e.g. a #GtkDialog based object) and displayed to users.
52 * <note>
53 * <para>
54 * Any actions additions/removals using #GtkUIManager are not
55 * registred with #AnjutaUI and hence their accellerators
56 * cannot be edited. Nor will they be listed in UI manager
57 * dialog. Hence, use #AnjutaUI methods whenever possible.
58 * </para>
59 * </note>
62 #ifdef HAVE_CONFIG_H
63 # include <config.h>
64 #endif
66 #include <stdio.h>
67 #include <string.h>
68 #include <glib/gi18n.h>
69 #include <gtk/gtk.h>
71 #include "resources.h"
72 #include "anjuta-ui.h"
73 #include "anjuta-utils.h"
74 #include "anjuta-debug.h"
76 struct _AnjutaUIPrivate {
77 GtkIconFactory *icon_factory;
78 GtkTreeModel *name_model;
79 GtkTreeModel *accel_model;
80 GHashTable *customizable_actions_hash;
81 GHashTable *uncustomizable_actions_hash;
84 enum {
85 COLUMN_PIXBUF,
86 COLUMN_ACTION_LABEL,
87 COLUMN_VISIBLE,
88 COLUMN_SHOW_VISIBLE,
89 COLUMN_SENSITIVE,
90 COLUMN_ACTION,
91 COLUMN_GROUP,
92 N_COLUMNS
95 static gchar*
96 get_action_label (GtkAction *action)
98 gchar *action_label = NULL;
100 g_object_get (G_OBJECT (action), "label", &action_label, NULL);
101 if (action_label && strlen (action_label))
103 gchar *s, *d;
104 s = d = action_label;
105 while (*s)
107 /* FIXME: May break with multibyte chars */
108 if (*s == '_')
109 s++;
110 *d = *s; d++; s++;
112 *d = '\0';
114 else
115 action_label = g_strdup (gtk_action_get_name (action));
116 return action_label;
119 /* Find action in tree */
120 static gboolean
121 find_action (GtkTreeModel *model, GtkTreeIter *iter, GtkAction *action)
123 GtkTreeIter group;
124 gboolean valid;
126 for (valid = gtk_tree_model_get_iter_first (model, &group);
127 valid;
128 valid = gtk_tree_model_iter_next (model, &group))
130 for (valid = gtk_tree_model_iter_children (model, iter, &group);
131 valid;
132 valid = gtk_tree_model_iter_next (model, iter))
134 GtkAction *child_action;
136 gtk_tree_model_get (model, iter, COLUMN_ACTION, &child_action, -1);
137 g_object_unref (child_action);
138 if (action == child_action) return TRUE;
142 return FALSE;
145 /* Find group in tree starting after sibling or from beginning if sibling is
146 * NULL */
147 static gboolean
148 find_group_after (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *sibling, const gchar *group_label)
150 gboolean valid;
152 if (sibling == NULL)
154 valid = gtk_tree_model_get_iter_first (model, iter);
156 else
158 *iter = *sibling;
159 valid = gtk_tree_model_iter_next (model, iter);
161 while (valid)
163 gchar *label;
164 gint comp;
166 gtk_tree_model_get (model, iter, COLUMN_ACTION_LABEL, &label, -1);
167 comp = strcmp (label, group_label);
168 g_free (label);
170 if (comp == 0) return TRUE;
172 valid = gtk_tree_model_iter_next (model, iter);
175 return FALSE;
178 /* Find position for new label */
179 static GtkTreeIter *
180 find_sorted_name (GtkTreeModel *model, GtkTreeIter *iter, const gchar *label)
182 gboolean valid;
186 gchar *iter_label;
187 gint comp;
189 gtk_tree_model_get (model, iter, COLUMN_ACTION_LABEL, &iter_label, -1);
191 comp = g_utf8_collate (label, iter_label);
192 g_free (iter_label);
194 if (comp <= 0) return iter;
196 valid = gtk_tree_model_iter_next (model, iter);
197 } while (valid);
199 return NULL;
202 /* Find position for new accel */
203 static gboolean
204 find_sorted_accel (GtkTreeModel *model, GtkTreeIter *iter, GtkAction *action)
206 GtkTreeIter group;
207 gboolean valid;
208 const gchar *accel_path;
209 GtkAccelKey key;
211 accel_path = gtk_action_get_accel_path (action);
212 if ((accel_path == NULL) ||
213 !gtk_accel_map_lookup_entry (accel_path, &key) ||
214 ((key.accel_key == 0) && (key.accel_mods == 0)))
216 /* No accelerator */
217 return FALSE;
220 for (valid = gtk_tree_model_get_iter_first (model, &group);
221 valid;
222 valid = gtk_tree_model_iter_next (model, &group))
224 for (valid = gtk_tree_model_iter_children (model, iter, &group);
225 valid;
226 valid = gtk_tree_model_iter_next (model, iter))
228 GtkAction *child_action;
229 GtkAccelKey child_key;
231 gtk_tree_model_get (model, iter, COLUMN_ACTION, &child_action, -1);
232 accel_path = gtk_action_get_accel_path (child_action);
233 g_object_unref (child_action);
234 if ((accel_path == NULL) ||
235 !gtk_accel_map_lookup_entry (accel_path, &child_key) ||
236 ((child_key.accel_key == 0) && (child_key.accel_mods == 0)))
238 /* No more accelerator and as accelerators are sorted, there is
239 * no need to go further */
240 return TRUE;
243 if ((child_key.accel_key > key.accel_key) ||
244 ((child_key.accel_key == key.accel_key) && (child_key.accel_mods >= key.accel_mods)))
246 /* Find next accelerator */
247 return TRUE;
252 return FALSE;
255 static void
256 insert_sorted_by_accel (GtkTreeModel *model, GtkTreeIter *iter, const gchar *group_label, GtkAction *action)
258 GtkTreeIter next;
259 GtkTreeIter parent;
261 if (find_sorted_accel (model, &next, action))
263 gchar *label;
265 /* Try to set next action in an already existing parent */
266 gtk_tree_model_iter_parent (model, &parent, &next);
267 gtk_tree_model_get (model, &parent, COLUMN_ACTION_LABEL, &label, -1);
268 if (strcmp (label, group_label) == 0)
270 /* Already the right group, just insert action */
271 gtk_tree_store_insert_before (GTK_TREE_STORE (model), iter, &parent, &next);
273 else
275 /* Try to put in the previous group */
276 GtkTreePath *path;
277 gboolean prev;
279 path = gtk_tree_model_get_path (model, &next);
280 prev = gtk_tree_path_prev (path);
281 gtk_tree_path_free (path);
283 if (!prev)
285 path = gtk_tree_model_get_path (model, &parent);
286 if (gtk_tree_path_prev (path))
288 g_free (label);
289 gtk_tree_model_get_iter (model, &parent, path);
290 gtk_tree_model_get (model, &parent, COLUMN_ACTION_LABEL, &label, -1);
291 if (strcmp (label, group_label) != 0)
293 /* Create new parent */
294 next = parent;
295 gtk_tree_store_insert_after (GTK_TREE_STORE (model), &parent, NULL, &next);
298 else
300 next = parent;
301 gtk_tree_store_insert_before (GTK_TREE_STORE (model), &parent, NULL, &next);
303 gtk_tree_path_free (path);
304 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
305 COLUMN_ACTION_LABEL, group_label,
306 COLUMN_SHOW_VISIBLE, FALSE,
307 -1);
309 /* Add action at the end */
310 gtk_tree_store_append (GTK_TREE_STORE (model), iter, &parent);
312 else
314 /* Split parent and add new parent in the middle */
315 GtkTreeIter split;
316 gboolean valid;
318 gtk_tree_store_insert_after (GTK_TREE_STORE (model), &split, NULL, &parent);
319 gtk_tree_store_set (GTK_TREE_STORE (model), &split,
320 COLUMN_ACTION_LABEL, label,
321 COLUMN_SHOW_VISIBLE, FALSE,
322 -1);
326 GtkTreeIter child;
327 GdkPixbuf *pixbuf;
328 gchar *action_label;
329 gboolean visible;
330 gboolean sensitive;
331 GtkAction *action;
332 gpointer action_group;
334 gtk_tree_model_get (model, &next,
335 COLUMN_PIXBUF, &pixbuf,
336 COLUMN_ACTION_LABEL, &action_label,
337 COLUMN_VISIBLE, &visible,
338 COLUMN_SENSITIVE, &sensitive,
339 COLUMN_ACTION, &action,
340 COLUMN_GROUP, &action_group,
341 -1);
342 gtk_tree_store_append (GTK_TREE_STORE (model), &child, &split);
343 gtk_tree_store_set (GTK_TREE_STORE (model), &child,
344 COLUMN_PIXBUF, pixbuf,
345 COLUMN_ACTION_LABEL, action_label,
346 COLUMN_VISIBLE, visible,
347 COLUMN_SHOW_VISIBLE, TRUE,
348 COLUMN_SENSITIVE, sensitive,
349 COLUMN_ACTION, action,
350 COLUMN_GROUP, action_group,
351 -1);
352 if (pixbuf) g_object_unref (pixbuf);
353 if (action) g_object_unref (action);
354 g_free (action_label);
356 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &next);
357 } while (valid);
359 /* Add new parent */
360 gtk_tree_store_insert_before (GTK_TREE_STORE (model), &parent, NULL, &split);
361 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
362 COLUMN_ACTION_LABEL, group_label,
363 COLUMN_SHOW_VISIBLE, FALSE,
364 -1);
366 gtk_tree_store_append (GTK_TREE_STORE (model), iter, &parent);
369 g_free (label);
371 else
373 if (find_group_after (model, &parent, NULL, group_label))
375 GtkTreeIter child;
376 GtkAction *child_action;
377 const gchar *accel_path;
378 GtkAccelKey key;
380 /* Find last group */
381 while (find_group_after (model, &next, &parent, group_label))
383 parent = next;
386 gtk_tree_model_iter_children (model, &child, &parent);
387 gtk_tree_model_get (model, &child, COLUMN_ACTION, &child_action, -1);
389 accel_path = gtk_action_get_accel_path (child_action);
390 g_object_unref (child_action);
391 if ((accel_path != NULL) &&
392 gtk_accel_map_lookup_entry (accel_path, &key) &&
393 ((key.accel_key != 0) || (key.accel_mods != 0)))
395 /* Create new group */
396 gtk_tree_store_append (GTK_TREE_STORE (model), &parent, NULL);
397 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
398 COLUMN_ACTION_LABEL, group_label,
399 COLUMN_SHOW_VISIBLE, FALSE,
400 -1);
404 else
406 /* Create new group */
407 gtk_tree_store_append (GTK_TREE_STORE (model), &parent, NULL);
408 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
409 COLUMN_ACTION_LABEL, group_label,
410 COLUMN_SHOW_VISIBLE, FALSE,
411 -1);
414 /* Append action */
415 gtk_tree_store_append (GTK_TREE_STORE (model), iter, &parent);
419 static void
420 insert_sorted_by_name (GtkTreeModel *model, GtkTreeIter *iter, const gchar *group_label, GtkAction *action)
422 GtkTreeIter parent;
423 GtkTreeIter child;
424 GtkTreeIter *sibling;
425 gchar *label;
427 if (!find_group_after (model, &parent, NULL, group_label))
429 /* Insert group for label */
430 if (gtk_tree_model_get_iter_first (model, &child))
432 sibling = find_sorted_name (model, &child, group_label);
434 else
436 sibling = NULL;
438 gtk_tree_store_insert_before (GTK_TREE_STORE (model), &parent, NULL, sibling);
439 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
440 COLUMN_ACTION_LABEL, group_label,
441 COLUMN_SHOW_VISIBLE, FALSE,
442 -1);
445 if (gtk_tree_model_iter_children (model, &child, &parent))
447 label = get_action_label (action);
448 sibling = find_sorted_name (model, &child, label);
449 g_free (label);
451 else
453 sibling = NULL;
456 gtk_tree_store_insert_before (GTK_TREE_STORE (model), iter, &parent, sibling);
459 static void
460 fill_action_data (GtkTreeModel *model, GtkTreeIter *iter, GtkAction *action, GtkActionGroup *group)
462 gchar *action_label;
463 gchar *icon;
464 GdkPixbuf *pixbuf = NULL;
465 GtkWidget *dummy = NULL;
467 action_label = get_action_label (action);
468 g_object_get (G_OBJECT (action), "stock-id", &icon, NULL);
469 if (icon != NULL)
471 GtkWidget *dummy = gtk_label_new ("Dummy");
472 g_object_ref_sink(G_OBJECT(dummy));
473 pixbuf = gtk_widget_render_icon_pixbuf (dummy, icon, GTK_ICON_SIZE_MENU);
475 gtk_tree_store_set (GTK_TREE_STORE (model), iter,
476 COLUMN_PIXBUF, pixbuf,
477 COLUMN_ACTION_LABEL, action_label,
478 COLUMN_VISIBLE, gtk_action_get_visible (action),
479 COLUMN_SHOW_VISIBLE, TRUE,
480 COLUMN_SENSITIVE, gtk_action_get_sensitive (action),
481 COLUMN_ACTION, action,
482 COLUMN_GROUP, group,
483 -1);
484 if (pixbuf != NULL) g_object_unref (G_OBJECT (pixbuf));
485 if (dummy != NULL) g_object_unref (dummy);
486 g_free (icon);
487 g_free (action_label);
490 /* Remove all actions in the action group group */
491 static void
492 remove_action_in_group (GtkTreeModel *model, GtkActionGroup *group)
494 GtkTreeIter parent;
495 gboolean valid;
497 valid = gtk_tree_model_get_iter_first (model, &parent);
498 while (valid)
500 /* Check each action, as a parent can contains actions from different
501 * groups */
502 GtkTreeIter child;
504 valid = gtk_tree_model_iter_children (model, &child, &parent);
505 while (valid)
507 gpointer child_group;
509 gtk_tree_model_get (model, &child, COLUMN_GROUP, &child_group, -1);
511 if (child_group == (gpointer)group)
513 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &child);
515 else
517 valid = gtk_tree_model_iter_next (model, &child);
521 /* if parent is now empty remove it */
522 if (!gtk_tree_model_iter_has_child (model, &parent))
524 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &parent);
526 else
528 valid = gtk_tree_model_iter_next (model, &parent);
533 #if 0
534 static void
535 sensitivity_toggled (GtkCellRendererToggle *cell,
536 const gchar *path_str, GtkTreeView *tree_view)
538 GtkTreeModel *model;
539 GtkTreeModel *other_model;
540 GtkTreePath *path;
541 GtkTreeIter iter;
542 GtkAction *action;
543 gboolean sensitive;
545 model = gtk_tree_view_get_model (tree_view);
546 path = gtk_tree_path_new_from_string (path_str);
547 gtk_tree_model_get_iter (model, &iter, path);
548 gtk_tree_path_free (path);
550 gtk_tree_model_get (model, &iter,
551 COLUMN_SENSITIVE, &sensitive,
552 COLUMN_ACTION, &action, -1);
553 g_object_set (G_OBJECT (action), "sensitive", !sensitive, NULL);
554 g_object_unref (action);
556 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
557 COLUMN_SENSITIVE, !sensitive, -1);
559 /* Update other model */
560 other_model = g_object_get_data (G_OBJECT (tree_view), "other_model");
561 if (find_action (other_model, &iter, action))
563 gtk_tree_store_set (GTK_TREE_STORE (other_model), &iter,
564 COLUMN_SENSITIVE, !sensitive, -1);
567 #endif
569 static void
570 visibility_toggled (GtkCellRendererToggle *cell,
571 const gchar *path_str, GtkTreeView *tree_view)
573 GtkTreeModel *model;
574 GtkTreeModel *other_model;
575 GtkTreePath *path;
576 GtkTreeIter iter;
577 GtkAction *action;
578 gboolean visible;
580 model = gtk_tree_view_get_model (tree_view);
581 path = gtk_tree_path_new_from_string (path_str);
582 gtk_tree_model_get_iter (model, &iter, path);
583 gtk_tree_path_free (path);
585 gtk_tree_model_get (model, &iter,
586 COLUMN_VISIBLE, &visible,
587 COLUMN_ACTION, &action, -1);
588 g_object_set (G_OBJECT (action), "visible", !visible, NULL);
589 g_object_unref (action);
590 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
591 COLUMN_VISIBLE, !visible, -1);
593 /* Update other model */
594 other_model = g_object_get_data (G_OBJECT (tree_view), "other_model");
595 if (find_action (other_model, &iter, action))
597 gtk_tree_store_set (GTK_TREE_STORE (other_model), &iter,
598 COLUMN_VISIBLE, !visible, -1);
602 static void
603 accel_edited_callback (GtkCellRendererAccel *cell,
604 const char *path_string,
605 guint keyval,
606 GdkModifierType mask,
607 guint hardware_keycode,
608 GtkTreeView *tree_view)
610 GtkTreeModel *model;
611 GtkTreePath *path;
612 GtkTreeIter iter;
613 GtkAction *action;
614 const gchar *accel_path;
616 model = gtk_tree_view_get_model (tree_view);
617 path = gtk_tree_path_new_from_string (path_string);
618 gtk_tree_model_get_iter (model, &iter, path);
619 gtk_tree_path_free (path);
621 gtk_tree_model_get (model, &iter,
622 COLUMN_ACTION, &action, -1);
624 /* sanity check */
625 if (action == NULL)
626 return;
628 accel_path = gtk_action_get_accel_path (action);
629 g_object_unref (action);
630 if (accel_path) {
631 gtk_accel_map_change_entry (accel_path, keyval, mask, TRUE);
635 static void
636 accel_cleared_callback (GtkCellRendererAccel *cell,
637 const char *path_string,
638 GtkTreeView *tree_view)
640 GtkTreeModel *model;
641 GtkTreePath *path;
642 GtkTreeIter iter;
643 GtkAction *action;
644 const gchar *accel_path;
647 model = gtk_tree_view_get_model (tree_view);
648 path = gtk_tree_path_new_from_string (path_string);
649 gtk_tree_model_get_iter (model, &iter, path);
650 gtk_tree_path_free (path);
652 gtk_tree_model_get (model, &iter,
653 COLUMN_ACTION, &action, -1);
655 /* sanity check */
656 if (action == NULL)
657 return;
659 accel_path = gtk_action_get_accel_path (action);
660 g_object_unref (action);
661 if (accel_path) {
662 gtk_accel_map_change_entry (accel_path, 0, 0, TRUE);
666 /* Fill the model sorted by accelerator with data from default model sorted by
667 * name */
668 static void
669 fill_sort_by_accel_store (GtkTreeStore *store, GtkTreeModel *model)
671 gboolean valid;
672 GtkTreeIter group;
674 for (valid = gtk_tree_model_get_iter_first (model, &group);
675 valid;
676 valid = gtk_tree_model_iter_next (model, &group))
678 GtkTreeIter iter;
679 gchar *group_label;
681 gtk_tree_model_get (model, &group,
682 COLUMN_ACTION_LABEL, &group_label,
683 -1);
685 for (valid = gtk_tree_model_iter_children (model, &iter, &group);
686 valid;
687 valid = gtk_tree_model_iter_next (model, &iter))
689 GtkTreeIter child;
690 GdkPixbuf *pixbuf;
691 gchar *action_label;
692 gboolean visible;
693 gboolean sensitive;
694 GtkAction *action;
695 gpointer action_group;
697 gtk_tree_model_get (model, &iter,
698 COLUMN_PIXBUF, &pixbuf,
699 COLUMN_ACTION_LABEL, &action_label,
700 COLUMN_VISIBLE, &visible,
701 COLUMN_SENSITIVE, &sensitive,
702 COLUMN_ACTION, &action,
703 COLUMN_GROUP, &action_group,
704 -1);
706 if (action != NULL)
708 insert_sorted_by_accel (GTK_TREE_MODEL (store), &child, group_label, action);
710 gtk_tree_store_set (store, &child,
711 COLUMN_PIXBUF, pixbuf,
712 COLUMN_ACTION_LABEL, action_label,
713 COLUMN_VISIBLE, visible,
714 COLUMN_SHOW_VISIBLE, TRUE,
715 COLUMN_SENSITIVE, sensitive,
716 COLUMN_ACTION, action,
717 COLUMN_GROUP, action_group,
718 -1);
722 if (pixbuf != NULL) g_object_unref (pixbuf);
723 g_free (action_label);
724 if (action != NULL) g_object_unref (action);
726 g_free (group_label);
730 /* Switch to the model sorted by name if use_name is true or sorted by
731 * accelerator if use_name is false */
732 static void
733 change_tree_model (GtkTreeView *tree_view, gboolean use_name)
735 gboolean has_name;
737 has_name = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_view), "name_model"));
738 if (has_name != use_name)
740 GtkTreeModel *model;
741 GtkTreeModel *other_model;
742 GtkTreeIter iter;
743 GtkTreePath *path;
744 GList *expanded = NULL;
745 GtkAction *selected_action = NULL;
746 gchar *selected_group = NULL;
747 GtkTreeSelection *selection;
748 GList *item;
750 /* Save selection */
751 model = gtk_tree_view_get_model (tree_view);
752 selection = gtk_tree_view_get_selection (tree_view);
753 if (gtk_tree_selection_get_selected (selection, NULL, &iter))
755 gtk_tree_model_get (model, &iter,
756 COLUMN_ACTION_LABEL, &selected_group,
757 COLUMN_ACTION, &selected_action,
758 -1);
761 /* Save expanded groups */
762 for (path = gtk_tree_path_new_first ();
763 gtk_tree_model_get_iter (model, &iter, path);
764 gtk_tree_path_next (path))
766 if (gtk_tree_view_row_expanded (tree_view, path))
768 gchar *label;
770 gtk_tree_model_get (model, &iter, COLUMN_ACTION_LABEL, &label, -1);
771 expanded = g_list_prepend (expanded, label);
772 g_message ("expanded %s", label);
775 gtk_tree_path_free (path);
777 /* Swap model */
778 other_model = g_object_get_data (G_OBJECT (tree_view), "other_model");
780 if (!gtk_tree_model_get_iter_first (other_model, &iter) && !use_name)
782 /* Accelerator model is empty fill it */
783 fill_sort_by_accel_store (GTK_TREE_STORE (other_model), model);
786 gtk_tree_view_set_model (tree_view, other_model);
787 g_object_set_data (G_OBJECT (tree_view), "other_model", model);
788 g_object_set_data (G_OBJECT (tree_view), "name_model", GINT_TO_POINTER (use_name));
790 /* Expand same group */
791 for (item = g_list_first (expanded); item != NULL; item = g_list_next (item))
793 gchar *label = (gchar *)item->data;
794 gboolean valid;
796 for (valid = find_group_after (other_model, &iter, NULL, label);
797 valid;
798 valid = find_group_after (other_model, &iter, &iter, label))
800 path = gtk_tree_model_get_path (other_model, &iter);
801 gtk_tree_view_expand_row (tree_view, path, FALSE);
802 gtk_tree_path_free (path);
804 g_free (label);
806 g_list_free (expanded);
808 /* Restore selection */
809 if (selected_action != NULL)
811 find_action (other_model, &iter, selected_action);
812 gtk_tree_selection_select_iter (selection, &iter);
813 g_object_unref (selected_action);
815 else if (selected_group != NULL)
817 find_group_after (other_model, &iter, NULL, selected_group);
818 gtk_tree_selection_select_iter (selection, &iter);
820 /* Display selected row */
821 if ((selected_action != NULL) || (selected_group != NULL))
823 GtkTreePath *path;
825 path = gtk_tree_model_get_path (other_model, &iter);
826 gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0);
827 gtk_tree_path_free (path);
829 g_free (selected_group);
833 static void
834 accel_sort_by_accel_callback (GtkTreeViewColumn *column,
835 gpointer data)
837 GtkTreeView *tree_view = (GtkTreeView *)data;
839 change_tree_model (tree_view, FALSE);
842 static void
843 accel_sort_by_name_callback (GtkTreeViewColumn *column,
844 gpointer data)
846 GtkTreeView *tree_view = (GtkTreeView *)data;
848 change_tree_model (tree_view, TRUE);
851 static void
852 accel_set_func (GtkTreeViewColumn *tree_column,
853 GtkCellRenderer *cell,
854 GtkTreeModel *model,
855 GtkTreeIter *iter,
856 gpointer data)
858 GtkAction *action;
859 const gchar *accel_path;
860 GtkAccelKey key;
862 gtk_tree_model_get (model, iter,
863 COLUMN_ACTION, &action, -1);
864 if (action == NULL)
865 g_object_set (G_OBJECT (cell), "visible", FALSE, NULL);
866 else
868 if ((accel_path = gtk_action_get_accel_path (action)))
870 if (gtk_accel_map_lookup_entry (accel_path, &key))
872 g_object_set (G_OBJECT (cell), "visible", TRUE,
873 "accel-key", key.accel_key,
874 "accel-mods", key.accel_mods, NULL);
876 else
877 g_object_set (G_OBJECT (cell), "visible", TRUE,
878 "accel-key", 0,
879 "accel-mods", 0, NULL);
881 g_object_unref (action);
885 G_DEFINE_TYPE(AnjutaUI, anjuta_ui, GTK_TYPE_UI_MANAGER)
887 static void
888 anjuta_ui_dispose (GObject *obj)
890 AnjutaUI *ui = ANJUTA_UI (obj);
892 if (ui->priv->name_model) {
893 /* This will also release the refs on actions.
894 * Clear is necessary because following unref() might not actually
895 * finalize the model. It basically ensures all refs on actions
896 * are released irrespective of whether the model is finalized
897 * or not.
899 gtk_tree_store_clear (GTK_TREE_STORE (ui->priv->name_model));
901 g_object_unref (G_OBJECT (ui->priv->name_model));
902 ui->priv->name_model = NULL;
904 if (ui->priv->accel_model) {
905 gtk_tree_store_clear (GTK_TREE_STORE (ui->priv->accel_model));
906 g_object_unref (G_OBJECT (ui->priv->accel_model));
907 ui->priv->accel_model = NULL;
909 if (ui->priv->customizable_actions_hash)
911 /* This will also release the refs on all action groups */
912 g_hash_table_destroy (ui->priv->customizable_actions_hash);
913 ui->priv->customizable_actions_hash = NULL;
915 if (ui->priv->uncustomizable_actions_hash)
917 /* This will also release the refs on all action groups */
918 g_hash_table_destroy (ui->priv->uncustomizable_actions_hash);
919 ui->priv->uncustomizable_actions_hash = NULL;
921 if (ui->priv->icon_factory) {
922 g_object_unref (G_OBJECT (ui->priv->icon_factory));
923 ui->priv->icon_factory = NULL;
925 G_OBJECT_CLASS (anjuta_ui_parent_class)->dispose (obj);
928 static void
929 anjuta_ui_finalize (GObject *obj)
931 AnjutaUI *ui = ANJUTA_UI (obj);
932 g_free (ui->priv);
933 G_OBJECT_CLASS (anjuta_ui_parent_class)->finalize (obj);
936 static void
937 anjuta_ui_class_init (AnjutaUIClass *class)
939 GObjectClass *object_class = G_OBJECT_CLASS (class);
941 object_class->dispose = anjuta_ui_dispose;
942 object_class->finalize = anjuta_ui_finalize;
945 static void
946 anjuta_ui_init (AnjutaUI *ui)
948 GtkTreeStore *store;
950 /* Initialize member data */
951 ui->priv = g_new0 (AnjutaUIPrivate, 1);
952 ui->priv->customizable_actions_hash =
953 g_hash_table_new_full (g_str_hash,
954 g_str_equal,
955 (GDestroyNotify) g_free,
956 NULL);
957 ui->priv->uncustomizable_actions_hash =
958 g_hash_table_new_full (g_str_hash,
959 g_str_equal,
960 (GDestroyNotify) g_free,
961 NULL);
962 /* Create Icon factory */
963 ui->priv->icon_factory = gtk_icon_factory_new ();
964 gtk_icon_factory_add_default (ui->priv->icon_factory);
966 /* Create Accel editor sorted by name model */
967 store = gtk_tree_store_new (N_COLUMNS,
968 GDK_TYPE_PIXBUF,
969 G_TYPE_STRING,
970 G_TYPE_BOOLEAN,
971 G_TYPE_BOOLEAN,
972 G_TYPE_BOOLEAN,
973 G_TYPE_OBJECT,
974 G_TYPE_POINTER);
976 /* unreferenced in dispose() method. */
977 ui->priv->name_model = GTK_TREE_MODEL (store);
979 /* Create Accel editor sorted by accelerator model */
980 store = gtk_tree_store_new (N_COLUMNS,
981 GDK_TYPE_PIXBUF,
982 G_TYPE_STRING,
983 G_TYPE_BOOLEAN,
984 G_TYPE_BOOLEAN,
985 G_TYPE_BOOLEAN,
986 G_TYPE_OBJECT,
987 G_TYPE_POINTER);
989 /* unreferenced in dispose() method. */
990 ui->priv->accel_model = GTK_TREE_MODEL (store);
994 * anjuta_ui_new:
996 * Creates a new instance of #AnjutaUI.
998 * Return value: A #AnjutaUI object
1000 AnjutaUI *
1001 anjuta_ui_new (void)
1003 return g_object_new (ANJUTA_TYPE_UI, NULL);
1007 * anjuta_ui_add_action_group_entries:
1008 * @ui: A #AnjutaUI object.
1009 * @action_group_name: Untranslated name of the action group.
1010 * @action_group_label: Translated label of the action group.
1011 * @entries: (array length=num_entries): An array of action entries.
1012 * @num_entries: Number of elements in the action entries array.
1013 * @can_customize: If true the actions are customizable by user.
1014 * @translation_domain: The translation domain used to translated the entries.
1015 * It is usually the GETTEXT_PACKAGE macro in a project.
1016 * @user_data: User data to pass to action objects. This is the data that
1017 * will come as user_data in "activate" signal of the actions.
1019 * #GtkAction objects are created from the #GtkActionEntry structures and
1020 * added to the UI Manager. "activate" signal of #GtkAction is connected for
1021 * all the action objects using the callback in the entry structure and the
1022 * @user_data passed here.
1024 * This group of actions are registered with the name @action_group_name
1025 * in #AnjutaUI. A #GtkAction object from this action group can be later
1026 * retrieved by anjuta_ui_get_action() using @action_group_name and action name.
1027 * @action_group_label is used as the display name for the action group in
1028 * UI manager dialog where action shortcuts are configured.
1030 * Return value: (transfer none): A #GtkActionGroup object holding all the
1031 * action objects.
1033 GtkActionGroup*
1034 anjuta_ui_add_action_group_entries (AnjutaUI *ui,
1035 const gchar *action_group_name,
1036 const gchar *action_group_label,
1037 GtkActionEntry *entries,
1038 gint num_entries,
1039 const gchar *translation_domain,
1040 gboolean can_customize,
1041 gpointer user_data)
1043 GtkActionGroup *action_group;
1045 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1046 g_return_val_if_fail (action_group_name != NULL, NULL);
1047 g_return_val_if_fail (action_group_name != NULL, NULL);
1049 action_group = gtk_action_group_new (action_group_name);
1051 gtk_action_group_set_translation_domain (action_group, translation_domain);
1052 gtk_action_group_add_actions (action_group, entries, num_entries,
1053 user_data);
1054 anjuta_ui_add_action_group (ui, action_group_name,
1055 action_group_label, action_group,
1056 can_customize);
1057 return action_group;
1061 * anjuta_ui_add_toggle_action_group_entries:
1062 * @ui: A #AnjutaUI object.
1063 * @action_group_name: Untranslated name of the action group.
1064 * @action_group_label: Translated label of the action group.
1065 * @entries: (array length=num_entries): An array of action entries.
1066 * @num_entries: Number of elements in the action entries array.
1067 * @translation_domain: The translation domain used to translated the entries.
1068 * It is usually the GETTEXT_PACKAGE macro in a project.
1069 * @user_data: User data to pass to action objects. This is the data that
1070 * will come as user_data in "activate" signal of the actions.
1072 * This is similar to anjuta_ui_add_action_group_entries(), except that
1073 * it adds #GtkToggleAction objects after creating them from the @entries.
1075 * Return value: (transfer none): A #GtkActionGroup object holding all the
1076 * action objects.
1078 GtkActionGroup*
1079 anjuta_ui_add_toggle_action_group_entries (AnjutaUI *ui,
1080 const gchar *action_group_name,
1081 const gchar *action_group_label,
1082 GtkToggleActionEntry *entries,
1083 gint num_entries,
1084 const gchar *translation_domain,
1085 gboolean can_customize,
1086 gpointer user_data)
1088 GtkActionGroup *action_group;
1090 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1091 g_return_val_if_fail (action_group_name != NULL, NULL);
1092 g_return_val_if_fail (action_group_name != NULL, NULL);
1094 action_group = gtk_action_group_new (action_group_name);
1095 gtk_action_group_set_translation_domain (action_group, translation_domain);
1096 gtk_action_group_add_toggle_actions (action_group, entries, num_entries,
1097 user_data);
1098 anjuta_ui_add_action_group (ui, action_group_name,
1099 action_group_label, action_group,
1100 can_customize);
1101 return action_group;
1105 * anjuta_ui_add_action_group:
1106 * @ui: A #AnjutaUI object.
1107 * @action_group_name: Untranslated name of the action group.
1108 * @action_group_label: Translated label of the action group.
1109 * @action_group: (transfer full): #GtkActionGroup object to add.
1111 * This is similar to anjuta_ui_add_action_group_entries(), except that
1112 * it adds #GtkActionGroup object @action_group directly. All actions in this
1113 * group are automatically registered in #AnjutaUI and can be retrieved
1114 * normally with anjuta_ui_get_action().
1116 void
1117 anjuta_ui_add_action_group (AnjutaUI *ui,
1118 const gchar *action_group_name,
1119 const gchar *action_group_label,
1120 GtkActionGroup *action_group,
1121 gboolean can_customize)
1123 GList *actions, *l;
1125 g_return_if_fail (ANJUTA_IS_UI (ui));
1126 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1127 g_return_if_fail (action_group_name != NULL);
1128 g_return_if_fail (action_group_name != NULL);
1130 gtk_ui_manager_insert_action_group (GTK_UI_MANAGER (ui), action_group, 0);
1132 if (can_customize)
1134 g_hash_table_insert (ui->priv->customizable_actions_hash,
1135 g_strdup (action_group_name), action_group);
1137 else
1139 g_hash_table_insert (ui->priv->uncustomizable_actions_hash,
1140 g_strdup (action_group_name), action_group);
1143 actions = gtk_action_group_list_actions (action_group);
1144 for (l = actions; l; l = l->next)
1146 guint signal_id;
1147 gint n_handlers;
1148 GtkTreeIter iter;
1149 GtkAction *action = l->data;
1151 if (!action)
1152 continue;
1154 signal_id = g_signal_lookup ("activate", GTK_TYPE_ACTION);
1155 n_handlers = g_signal_has_handler_pending (action, signal_id,
1156 0, TRUE);
1157 if (n_handlers == 0)
1158 continue; /* The action element is not user configuration */
1160 insert_sorted_by_name (ui->priv->name_model, &iter, action_group_label, action);
1161 fill_action_data (ui->priv->name_model, &iter, action, action_group);
1163 if (gtk_tree_model_get_iter_first (ui->priv->accel_model, &iter))
1165 /* accel model is filled only if needed */
1166 insert_sorted_by_accel (ui->priv->accel_model, &iter, action_group_label, action);
1167 fill_action_data (ui->priv->accel_model, &iter, action, action_group);
1170 g_list_free(actions);
1173 static gboolean
1174 on_action_group_remove_hash (gpointer key, gpointer value, gpointer data)
1176 if (data == value)
1177 return TRUE;
1178 else
1179 return FALSE;
1183 * anjuta_ui_remove_action_group:
1184 * @ui: A #AnjutaUI object
1185 * @action_group: #GtkActionGroup object to remove.
1187 * Removes a previous added action group. All actions in this group are
1188 * also unregistered from UI manager.
1190 void
1191 anjuta_ui_remove_action_group (AnjutaUI *ui, GtkActionGroup *action_group)
1193 g_return_if_fail (ANJUTA_IS_UI (ui));
1195 remove_action_in_group (ui->priv->name_model, action_group);
1196 remove_action_in_group (ui->priv->accel_model, action_group);
1198 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (ui), action_group);
1200 g_hash_table_foreach_remove (ui->priv->customizable_actions_hash,
1201 on_action_group_remove_hash, action_group);
1202 g_hash_table_foreach_remove (ui->priv->uncustomizable_actions_hash,
1203 on_action_group_remove_hash, action_group);
1207 * anjuta_ui_get_action:
1208 * @ui: This #AnjutaUI object
1209 * @action_group_name: Group name.
1210 * @action_name: Action name.
1212 * Returns the action object with the name @action_name in @action_group_name.
1213 * Note that it will be only sucessully returned if the group has been added
1214 * using methods in #AnjutaUI.
1216 * Returns: (transfer none): A #GtkAction object
1218 GtkAction*
1219 anjuta_ui_get_action (AnjutaUI *ui, const gchar *action_group_name,
1220 const gchar *action_name)
1222 GtkActionGroup *action_group;
1223 GtkAction *action;
1225 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1227 action_group = g_hash_table_lookup (ui->priv->customizable_actions_hash,
1228 action_group_name);
1229 if (!action_group)
1231 action_group = g_hash_table_lookup (ui->priv->uncustomizable_actions_hash,
1232 action_group_name);
1234 if (GTK_IS_ACTION_GROUP (action_group) == FALSE)
1236 g_warning ("Unable to find action group \"%s\"", action_group_name);
1237 return NULL;
1239 action = gtk_action_group_get_action (action_group, action_name);
1240 if (GTK_IS_ACTION (action))
1241 return action;
1242 g_warning ("Unable to find action \"%s\" in group \"%s\"",
1243 action_name, action_group_name);
1244 return NULL;
1248 * anjuta_ui_activate_action_by_path:
1249 * @ui: This #AnjutaUI object
1250 * @action_path: Path of the action in the form "GroupName/ActionName"
1252 * Activates the action represented by @action_path. The path is in the form
1253 * "ActionGroupName/ActionName". Note that it will only work if the group has
1254 * been added using methods in #AnjutaUI.
1256 void
1257 anjuta_ui_activate_action_by_path (AnjutaUI *ui, const gchar *action_path)
1259 const gchar *action_group_name;
1260 const gchar *action_name;
1261 GtkAction *action;
1262 gchar **strv;
1264 g_return_if_fail (ANJUTA_IS_UI (ui));
1265 g_return_if_fail (action_path != NULL);
1267 strv = g_strsplit (action_path, "/", 2);
1268 action_group_name = strv[0];
1269 action_name = strv[1];
1271 g_return_if_fail (action_group_name != NULL && action_name != NULL);
1273 action = anjuta_ui_get_action (ui, action_group_name, action_name);
1274 if (action)
1275 gtk_action_activate (action);
1276 g_strfreev (strv);
1280 * anjuta_ui_activate_action_by_group:
1281 * @ui: This #AnjutaUI object
1282 * @action_group: Action group.
1283 * @action_name: Action name.
1285 * Activates the action @action_name in the #GtkActionGroup @action_group.
1286 * "ActionGroupName/ActionName". Note that it will only work if the group has
1287 * been added using methods in #AnjutaUI.
1289 void
1290 anjuta_ui_activate_action_by_group (AnjutaUI *ui, GtkActionGroup *action_group,
1291 const gchar *action_name)
1293 GtkAction *action;
1295 g_return_if_fail (ANJUTA_IS_UI (ui));
1296 g_return_if_fail (action_group != NULL && action_name != NULL);
1298 action = gtk_action_group_get_action (action_group, action_name);
1299 if (GTK_IS_ACTION (action))
1300 gtk_action_activate (action);
1304 * anjuta_ui_merge:
1305 * @ui: A #AnjutaUI object.
1306 * @ui_filename: UI file to merge into UI manager.
1308 * Merges XML UI definition in @ui_filename. UI elements defined in the xml
1309 * are merged with existing UI elements in UI manager. The format of the
1310 * file content is the standard XML UI definition tree. For more detail,
1311 * read the documentation for #GtkUIManager.
1313 * Return value: Integer merge ID
1315 gint
1316 anjuta_ui_merge (AnjutaUI *ui, const gchar *ui_filename)
1318 gint id;
1319 GError *err = NULL;
1321 g_return_val_if_fail (ANJUTA_IS_UI (ui), -1);
1322 g_return_val_if_fail (ui_filename != NULL, -1);
1323 id = gtk_ui_manager_add_ui_from_file(GTK_UI_MANAGER (ui),
1324 ui_filename, &err);
1325 #ifdef DEBUG
1327 gchar *basename = g_path_get_basename (ui_filename);
1328 DEBUG_PRINT ("merged [%d] %s", id, basename);
1329 g_free(basename);
1331 #endif
1332 if (err != NULL)
1333 g_warning ("Could not merge [%s]: %s", ui_filename, err->message);
1334 return id;
1338 * anjuta_ui_unmerge:
1339 * @ui: A #AnjutaUI object.
1340 * @id: Merge ID returned by anjuta_ui_merge().
1342 * Unmerges UI with the ID value @id (returned by anjuta_ui_merge() when
1343 * it was merged. For more detail, read the documentation for #GtkUIManager.
1345 void
1346 anjuta_ui_unmerge (AnjutaUI *ui, gint id)
1348 /* DEBUG_PRINT ("Menu unmerging %d", id); */
1349 g_return_if_fail (ANJUTA_IS_UI (ui));
1350 gtk_ui_manager_remove_ui(GTK_UI_MANAGER (ui), id);
1354 * anjuta_ui_get_accel_group:
1355 * @ui: A #AnjutaUI object.
1357 * Returns the #GtkAccelGroup object associated with this UI manager.
1359 * Returns: (transfer none): A #GtkAccelGroup object.
1361 GtkAccelGroup*
1362 anjuta_ui_get_accel_group (AnjutaUI *ui)
1364 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1365 return gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (ui));
1369 * anjuta_ui_get_accel_editor:
1370 * @ui: A #AnjutaUI object.
1372 * Creates an accel editor widget and returns it. It should be added to
1373 * container and displayed to users.
1375 * Returns: (transfer none): a #GtkWidget containing the editor.
1377 GtkWidget *
1378 anjuta_ui_get_accel_editor (AnjutaUI *ui)
1380 GtkWidget *tree_view, *sw;
1381 GtkTreeStore *store;
1382 GtkTreeViewColumn *column;
1383 GtkCellRenderer *renderer;
1385 store = GTK_TREE_STORE (ui->priv->name_model);
1387 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
1388 g_object_set_data (G_OBJECT (tree_view), "other_model", ui->priv->accel_model);
1389 g_object_set_data (G_OBJECT (tree_view), "name_model", GINT_TO_POINTER (TRUE));
1390 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
1392 /* Columns */
1393 column = gtk_tree_view_column_new ();
1394 gtk_tree_view_column_set_title (column, dgettext (GETTEXT_PACKAGE, "Action"));
1396 renderer = gtk_cell_renderer_pixbuf_new ();
1397 gtk_tree_view_column_pack_start (column, renderer, FALSE);
1398 gtk_tree_view_column_add_attribute (column, renderer, "pixbuf",
1399 COLUMN_PIXBUF);
1401 renderer = gtk_cell_renderer_text_new ();
1402 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1403 gtk_tree_view_column_add_attribute (column, renderer, "text",
1404 COLUMN_ACTION_LABEL);
1405 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1406 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree_view), column);
1407 gtk_tree_view_column_set_clickable (column, TRUE);
1408 g_signal_connect (G_OBJECT (column), "clicked",
1409 G_CALLBACK (accel_sort_by_name_callback),
1410 tree_view);
1412 renderer = gtk_cell_renderer_toggle_new ();
1413 g_signal_connect (G_OBJECT (renderer), "toggled",
1414 G_CALLBACK (visibility_toggled), tree_view);
1415 column = gtk_tree_view_column_new_with_attributes (dgettext (GETTEXT_PACKAGE, "Visible"),
1416 renderer,
1417 "active",
1418 COLUMN_VISIBLE,
1419 "visible",
1420 COLUMN_SHOW_VISIBLE,
1421 NULL);
1422 gtk_tree_view_column_set_alignment (column, 0.5f);
1423 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1424 #if 0
1425 renderer = gtk_cell_renderer_toggle_new ();
1426 g_signal_connect (G_OBJECT (renderer), "toggled",
1427 G_CALLBACK (sensitivity_toggled), tree_view);
1428 column = gtk_tree_view_column_new_with_attributes (_("Sensitive"),
1429 renderer,
1430 "active",
1431 COLUMN_SENSITIVE,
1432 NULL);
1433 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1434 #endif
1435 column = gtk_tree_view_column_new ();
1436 gtk_tree_view_column_set_title (column, dgettext (GETTEXT_PACKAGE, "Shortcut"));
1437 renderer = g_object_new (GTK_TYPE_CELL_RENDERER_ACCEL,
1438 "editable", TRUE,
1439 NULL);
1440 g_signal_connect (G_OBJECT (renderer), "accel-edited",
1441 G_CALLBACK (accel_edited_callback),
1442 tree_view);
1443 g_signal_connect (G_OBJECT (renderer), "accel-cleared",
1444 G_CALLBACK (accel_cleared_callback),
1445 tree_view);
1446 g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
1447 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1448 gtk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL, NULL);
1449 gtk_tree_view_column_set_clickable (column, TRUE);
1450 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1451 g_signal_connect (G_OBJECT (column), "clicked",
1452 G_CALLBACK (accel_sort_by_accel_callback),
1453 tree_view);
1455 sw = gtk_scrolled_window_new (NULL, NULL);
1456 gtk_container_set_border_width (GTK_CONTAINER (sw), 6);
1457 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1458 GTK_POLICY_AUTOMATIC,
1459 GTK_POLICY_AUTOMATIC);
1460 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
1461 GTK_SHADOW_IN);
1462 gtk_container_add (GTK_CONTAINER (sw), tree_view);
1463 gtk_widget_show_all (sw);
1464 return sw;
1468 * anjuta_ui_get_icon_factory:
1469 * @ui: A #AnjutaUI object
1471 * This returns the IconFactory object. All icons should be registered using
1472 * this icon factory. Read the documentation for #GtkIconFactory on how to
1473 * use it.
1475 * Return value: (transfer none): The #GtkIconFactory object used by it
1477 GtkIconFactory*
1478 anjuta_ui_get_icon_factory (AnjutaUI *ui)
1480 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1481 return ui->priv->icon_factory;
1485 * anjuta_ui_dump_tree:
1486 * @ui: A #AnjutaUI object.
1488 * Dumps the current UI XML tree in STDOUT. Useful for debugging.
1490 void
1491 anjuta_ui_dump_tree (AnjutaUI *ui)
1493 gchar *ui_str;
1495 g_return_if_fail (ANJUTA_IS_UI(ui));
1497 gtk_ui_manager_ensure_update (GTK_UI_MANAGER (ui));
1498 ui_str = gtk_ui_manager_get_ui (GTK_UI_MANAGER (ui));
1499 /* DEBUG_PRINT ("%s", ui_str); */
1500 g_free (ui_str);
1504 * Accels
1506 static gchar *
1507 anjuta_ui_get_accel_file (void)
1509 return anjuta_util_get_user_config_file_path ("anjuta-accels", NULL);
1512 void
1513 anjuta_ui_load_accels (const gchar *filename)
1515 if (filename)
1517 gtk_accel_map_load (filename);
1519 else
1521 gchar *def_filename = anjuta_ui_get_accel_file ();
1522 if (def_filename != NULL)
1524 gtk_accel_map_load (def_filename);
1525 g_free (def_filename);
1530 void
1531 anjuta_ui_save_accels (const gchar *filename)
1533 if (filename)
1535 gtk_accel_map_save (filename);
1537 else
1539 gchar * def_filename = anjuta_ui_get_accel_file ();
1541 if (def_filename != NULL)
1543 gtk_accel_map_save (def_filename);
1544 g_free (def_filename);
1549 static void anjuta_ui_remove_accel (AnjutaUI *ui,
1550 const gchar *accel_path, guint accel_key,
1551 GdkModifierType accel_mods, gboolean changed)
1553 gtk_accel_group_disconnect_key (anjuta_ui_get_accel_group(ui), accel_key, accel_mods);
1556 void
1557 anjuta_ui_unload_accels (AnjutaUI *ui)
1559 anjuta_ui_save_accels (NULL);
1560 gtk_accel_map_foreach_unfiltered (ui, (GtkAccelMapForeach) anjuta_ui_remove_accel);