45#include <glib/gstdio.h>
49static GtkUIManager *
uim;
91 "<toolbar name='GeanyToolbar'>"
92 "<toolitem action='New'/>"
93 "<toolitem action='Open'/>"
94 "<toolitem action='Save'/>"
95 "<toolitem action='SaveAll'/>"
97 "<toolitem action='Reload'/>"
98 "<toolitem action='Close'/>"
100 "<toolitem action='NavBack'/>"
101 "<toolitem action='NavFor'/>"
103 "<toolitem action='Compile'/>"
104 "<toolitem action='Build'/>"
105 "<toolitem action='Run'/>"
107 "<toolitem action='Color'/>"
109 "<toolitem action='SearchEntry'/>"
110 "<toolitem action='Search'/>"
112 "<toolitem action='GotoEntry'/>"
113 "<toolitem action='Goto'/>"
115 "<toolitem action='Quit'/>"
131 path = g_strconcat(
"/ui/GeanyToolbar/",
name,
NULL);
132 widget = gtk_ui_manager_get_widget(
uim, path);
145 if (G_LIKELY(widget !=
NULL))
146 return gtk_bin_get_child(GTK_BIN(widget));
156 return gtk_action_group_get_action(
group,
name);
168 g_return_if_fail(item !=
NULL);
182 static guint merge_id = 0;
183 GtkWidget *toolbar_new_file_menu =
NULL;
184 GtkWidget *toolbar_recent_files_menu =
NULL;
185 GtkWidget *toolbar_build_menu =
NULL;
193 g_object_ref(l->data);
199 g_object_ref(toolbar_new_file_menu);
202 g_object_ref(toolbar_recent_files_menu);
205 g_object_ref(toolbar_build_menu);
210 gtk_ui_manager_remove_ui(
uim, merge_id);
211 gtk_ui_manager_ensure_update(
uim);
216 merge_id = gtk_ui_manager_add_ui_from_string(
uim, markup, -1, &
error);
225 if (! g_error_matches(
error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
226 geany_debug(
"Loading user toolbar UI definition failed (%s).",
error->message);
237 geany_debug(
"UI creation failed, using internal fallback definition. Error message: %s",
267 g_object_unref(l->data);
271 if (toolbar_new_file_menu !=
NULL)
274 gtk_action_group_get_action(
group,
"New")), toolbar_new_file_menu);
275 g_object_unref(toolbar_new_file_menu);
277 if (toolbar_recent_files_menu !=
NULL)
280 gtk_action_group_get_action(
group,
"Open")), toolbar_recent_files_menu);
281 g_object_unref(toolbar_recent_files_menu);
283 if (toolbar_build_menu !=
NULL)
286 gtk_action_group_get_action(
group,
"Build")), toolbar_build_menu);
287 g_object_unref(toolbar_build_menu);
294 gboolean doc_changed = (doc !=
NULL) ? doc->
changed : FALSE;
324 const gchar *arg_name = g_param_spec_get_name(arg1);
343 GtkAction *action_new;
344 GtkAction *action_open;
345 GtkAction *action_build;
346 GtkAction *action_searchentry;
347 GtkAction *action_gotoentry;
348 GtkSettings *gtk_settings;
350 uim = gtk_ui_manager_new();
351 group = gtk_action_group_new(
"GeanyToolbar");
359 _(
"Create a new file"),
360 _(
"Create a new file from a template"),
363 gtk_action_group_add_action(
group, action_new);
367 _(
"Open an existing file"),
368 _(
"Open a recent file"),
371 gtk_action_group_add_action(
group, action_open);
375 _(
"Build the current file"),
376 _(
"Choose more build actions"),
378 g_signal_connect(action_build,
"button-clicked",
380 gtk_action_group_add_action(
group, action_build);
383 "SearchEntry",
_(
"Search Field"),
_(
"Find the entered text in the current file"), FALSE);
384 g_signal_connect(action_searchentry,
"entry-activate",
386 g_signal_connect(action_searchentry,
"entry-activate-backward",
388 g_signal_connect(action_searchentry,
"entry-changed",
390 gtk_action_group_add_action(
group, action_searchentry);
393 "GotoEntry",
_(
"Goto Field"),
_(
"Jump to the entered line number"), TRUE);
394 g_signal_connect(action_gotoentry,
"entry-activate",
396 gtk_action_group_add_action(
group, action_gotoentry);
398 gtk_ui_manager_insert_action_group(
uim,
group, 0);
401 gtk_style_context_add_class(gtk_widget_get_style_context(toolbar),
"primary-toolbar");
403 gtk_settings = gtk_widget_get_settings(GTK_WIDGET(toolbar));
404 if (gtk_settings !=
NULL)
406 g_signal_connect(gtk_settings,
"notify::gtk-toolbar-style",
416 static GtkWidget *hbox_menubar =
NULL;
417 static GtkWidget *menubar =
NULL;
419 GtkToolItem *first_item;
428 if (first_item !=
NULL && GTK_IS_SEPARATOR_TOOL_ITEM(first_item))
430 gtk_widget_destroy(GTK_WIDGET(first_item));
437 GtkWidget *menubar_toolbar_separator;
441 if (parent != hbox_menubar)
457 menubar_toolbar_separator = GTK_WIDGET(gtk_separator_tool_item_new());
458 gtk_widget_show(menubar_toolbar_separator);
460 GTK_TOOL_ITEM(menubar_toolbar_separator), 0);
487 gtk_box_set_child_packing(GTK_BOX(hbox_menubar), menubar,
503 gint quit_pos = -1,
pos;
506 quit_pos = gtk_toolbar_get_item_index(GTK_TOOLBAR(
main_widgets.
toolbar), GTK_TOOL_ITEM(quit));
509 if (quit_pos == (
pos - 1))
512 if (GTK_IS_SEPARATOR_TOOL_ITEM(gtk_toolbar_get_nth_item(
533 g_object_unref(
group);
542 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
584#define TB_EDITOR_SEPARATOR _("Separator")
585#define TB_EDITOR_SEPARATOR_LABEL _("--- Separator ---")
604 {
"GEANY_TB_EDITOR_ROW", 0, 0 }
617 const gchar **attribute_names,
618 const gchar **attribute_values, gpointer data,
622 GSList **actions = data;
628 for (i = 0; attribute_names[i] !=
NULL; i++)
632 *actions = g_slist_append(*actions, g_strdup(attribute_values[i]));
646 GMarkupParseContext *context;
650 g_markup_parse_context_parse(context, buffer, length,
error);
651 g_markup_parse_context_free(context);
661 gchar *label_clean =
NULL;
664 action = gtk_action_group_get_action(
group,
name);
674 g_object_get(action,
"icon-name", &icon,
NULL);
676 g_object_get(action,
"stock-id", &icon,
NULL);
678 g_object_get(action,
"label", &
label,
NULL);
683 gtk_list_store_set(store, iter,
697 GtkTreePath *path = gtk_tree_model_get_path(gtk_tree_view_get_model(treeview), iter);
698 gtk_tree_view_scroll_to_cell(treeview, path,
NULL, TRUE, 0.5, 0.0);
699 gtk_tree_path_free(path);
715 GtkTreeModel *model_used;
716 GtkTreeSelection *selection_used;
717 GtkTreeIter iter_used, iter_new;
720 selection_used = gtk_tree_view_get_selection(tbw->
tree_used);
721 if (gtk_tree_selection_get_selected(selection_used, &model_used, &iter_used))
724 if (gtk_list_store_remove(tbw->
store_used, &iter_used))
725 gtk_tree_selection_select_iter(selection_used, &iter_used);
741 GtkTreeModel *model_available;
742 GtkTreeSelection *selection_available, *selection_used;
743 GtkTreeIter iter_available, iter_new, iter_selected;
746 selection_available = gtk_tree_view_get_selection(tbw->
tree_available);
747 if (gtk_tree_selection_get_selected(selection_available, &model_available, &iter_available))
749 gtk_tree_model_get(model_available, &iter_available,
754 gtk_tree_selection_select_iter(selection_available, &iter_available);
757 selection_used = gtk_tree_view_get_selection(tbw->
tree_used);
758 if (gtk_tree_selection_get_selected(selection_used,
NULL, &iter_selected))
759 gtk_list_store_insert_before(tbw->
store_used, &iter_new, &iter_selected);
761 gtk_list_store_append(tbw->
store_used, &iter_new);
776 gtk_tree_view_get_drag_dest_row(GTK_TREE_VIEW(widget),
784 GtkSelectionData *data, guint info, guint ltime,
788 GtkTreeSelection *selection;
793 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
794 if (! gtk_tree_selection_get_selected(selection, &model, &iter))
805 gtk_selection_data_set(data, atom, 8, (guchar*)
name, strlen(
name));
814 gint x, gint y, GtkSelectionData *data, guint info,
817 GtkTreeView *tree = GTK_TREE_VIEW(widget);
818 gboolean del = FALSE;
820 if (gtk_selection_data_get_length(data) >= 0 && gtk_selection_data_get_format(data) == 8)
825 text = (gchar*) gtk_selection_data_get_data(data);
834 GtkTreeIter iter, iter_before, *iter_before_ptr;
835 GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
839 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter_before, tbw->
last_drag_path);
841 if (gtk_list_store_iter_is_valid(store, &iter_before))
842 iter_before_ptr = &iter_before;
844 iter_before_ptr =
NULL;
848 gtk_list_store_insert_before(store, &iter, iter_before_ptr);
850 gtk_list_store_insert_after(store, &iter, iter_before_ptr);
853 gtk_list_store_append(store, &iter);
864 gtk_drag_finish(context, TRUE, del, ltime);
869 GtkTreeIter *iter, gpointer data)
876 g_string_append_printf(data,
"\t\t<separator/>\n");
877 else if (G_LIKELY(!
EMPTY(action_name)))
878 g_string_append_printf(data,
"\t\t<toolitem action='%s' />\n", action_name);
888 const gchar *
template =
"<ui>\n<!--\n\
889This is Geany's toolbar UI definition.\nThe DTD can be found at \n\
890http://library.gnome.org/devel/gtk/stable/GtkUIManager.html#GtkUIManager.description.\n\n\
891You can re-order all items and freely add and remove available actions.\n\
892You cannot add new actions which are not listed in the documentation.\n\
893Everything you add or change must be inside the /ui/toolbar/ path.\n\n\
894For changes to take effect, you need to restart Geany. Alternatively you can use the toolbar\n\
896A list of available actions can be found in the documentation included with Geany or\n\
897at https://www.geany.org/manual/current/index.html#customizing-the-toolbar.\n-->\n\
898\t<toolbar name='GeanyToolbar'>\n";
900 GString *str = g_string_new(
template);
904 g_string_append(str,
"\n\t</toolbar>\n</ui>\n");
912 g_string_free(str, TRUE);
932 GtkWidget *
dialog, *vbox, *hbox, *vbox_buttons, *button_add, *button_remove;
933 GtkWidget *swin_available, *swin_used, *tree_available, *tree_used, *
label;
934 GtkCellRenderer *text_renderer, *icon_renderer;
935 GtkTreeViewColumn *column;
941 dialog = gtk_dialog_new_with_buttons(
_(
"Customize Toolbar"),
943 GTK_DIALOG_DESTROY_WITH_PARENT,
944 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
NULL);
946 gtk_box_set_spacing(GTK_BOX(vbox), 6);
947 gtk_widget_set_name(
dialog,
"GeanyDialog");
948 gtk_window_set_default_size(GTK_WINDOW(
dialog), -1, 400);
949 gtk_dialog_set_default_response(GTK_DIALOG(
dialog), GTK_RESPONSE_CLOSE);
952 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
954 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
956 label = gtk_label_new(
957 _(
"Select items to be displayed on the toolbar. Items can be reordered by drag and drop."));
958 gtk_misc_set_alignment(GTK_MISC(
label), 0.0, 0.5);
960 tree_available = gtk_tree_view_new();
961 gtk_tree_view_set_model(GTK_TREE_VIEW(tree_available), GTK_TREE_MODEL(tbw->
store_available));
962 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_available), TRUE);
963 gtk_tree_sortable_set_sort_column_id(
966 icon_renderer = gtk_cell_renderer_pixbuf_new();
967 column = gtk_tree_view_column_new_with_attributes(
969 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_available), column);
971 text_renderer = gtk_cell_renderer_text_new();
972 column = gtk_tree_view_column_new_with_attributes(
974 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_available), column);
976 swin_available = gtk_scrolled_window_new(
NULL,
NULL);
977 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin_available),
978 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
979 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swin_available), GTK_SHADOW_IN);
982 tree_used = gtk_tree_view_new();
983 gtk_tree_view_set_model(GTK_TREE_VIEW(tree_used), GTK_TREE_MODEL(tbw->
store_used));
984 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_used), TRUE);
985 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tree_used), TRUE);
987 icon_renderer = gtk_cell_renderer_pixbuf_new();
988 column = gtk_tree_view_column_new_with_attributes(
990 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_used), column);
992 text_renderer = gtk_cell_renderer_text_new();
993 column = gtk_tree_view_column_new_with_attributes(
995 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_used), column);
997 swin_used = gtk_scrolled_window_new(
NULL,
NULL);
998 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin_used),
999 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1000 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swin_used), GTK_SHADOW_IN);
1004 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(tree_available), GDK_BUTTON1_MASK,
1006 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(tree_available),
1008 g_signal_connect(tree_available,
"drag-data-get",
1010 g_signal_connect(tree_available,
"drag-data-received",
1012 g_signal_connect(tree_available,
"drag-motion",
1015 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(tree_used), GDK_BUTTON1_MASK,
1017 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(tree_used),
1019 g_signal_connect(tree_used,
"drag-data-get",
1021 g_signal_connect(tree_used,
"drag-data-received",
1023 g_signal_connect(tree_used,
"drag-motion",
1032 vbox_buttons = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1034 gtk_box_pack_start(GTK_BOX(vbox_buttons), gtk_label_new(
""), TRUE, TRUE, 0);
1035 gtk_box_pack_start(GTK_BOX(vbox_buttons), button_add, FALSE, FALSE, 0);
1036 gtk_box_pack_start(GTK_BOX(vbox_buttons), button_remove, FALSE, FALSE, 0);
1037 gtk_box_pack_start(GTK_BOX(vbox_buttons), gtk_label_new(
""), TRUE, TRUE, 0);
1039 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
1040 gtk_box_pack_start(GTK_BOX(hbox), swin_available, TRUE, TRUE, 0);
1041 gtk_box_pack_start(GTK_BOX(hbox), vbox_buttons, FALSE, FALSE, 0);
1042 gtk_box_pack_start(GTK_BOX(hbox), swin_used, TRUE, TRUE, 0);
1044 gtk_box_pack_start(GTK_BOX(vbox),
label, FALSE, FALSE, 6);
1045 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
1054 tbw->
tree_used = GTK_TREE_VIEW(tree_used);
1065 GSList *sl, *used_items;
1066 GList *l, *all_items;
1071 markup = gtk_ui_manager_get_ui(
uim);
1076 all_items = gtk_action_group_list_actions(
group);
1088 const gchar *
name = gtk_action_get_name(l->data);
1090 if (g_slist_find_custom(used_items,
name, (GCompareFunc) strcmp) ==
NULL)
1102 gtk_list_store_append(tbw->
store_used, &iter);
1106 path = gtk_tree_path_new_from_string(
"0");
1107 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tbw->
tree_used), path);
1108 gtk_tree_path_free(path);
1111 g_signal_connect(tbw->
store_used,
"row-changed",
1113 g_signal_connect(tbw->
store_used,
"row-deleted",
1117 gtk_dialog_run(GTK_DIALOG(tbw->
dialog));
1119 gtk_widget_destroy(tbw->
dialog);
1121 g_slist_foreach(used_items, (GFunc) g_free,
NULL);
1122 g_slist_free(used_items);
1123 g_list_free(all_items);
void build_toolbutton_build_clicked(GtkAction *action, gpointer unused)
Interface to the Build menu functionality.
void on_replace1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_save_all1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_delete1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_menu_increase_indent1_activate(GtkMenuItem *menuitem, gpointer user_data)
gboolean on_escape_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
void on_paste1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_zoom_in1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_toolbutton_forward_activate(GtkAction *menuitem, gpointer user_data)
void on_toolbutton_back_activate(GtkAction *menuitem, gpointer user_data)
void on_toolbutton_run_clicked(GtkAction *action, gpointer user_data)
void on_show_color_chooser1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_save1_activate(GtkMenuItem *menuitem, gpointer user_data)
gboolean toolbar_popup_menu(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
void on_undo1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_close_all1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_copy1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_open1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_cut1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_toolbutton_goto_clicked(GtkAction *action, gpointer user_data)
void on_new1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_zoom_out1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_preferences1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_redo1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_toolbar_search_entry_activate(GtkAction *action, const gchar *text, gpointer user_data)
void on_menu_decrease_indent1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_save_as1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_toolbutton_compile_clicked(GtkAction *action, gpointer user_data)
void on_toolbutton_search_clicked(GtkAction *action, gpointer user_data)
gboolean on_motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
void on_quit1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_toolbutton_reload_clicked(GtkAction *action, gpointer user_data)
void on_print1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_close1_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_toolbar_search_entry_changed(GtkAction *action, const gchar *text, gpointer user_data)
void on_toolbutton_goto_entry_activate(GtkAction *action, const gchar *text, gpointer user_data)
GeanyDocument * document_get_current(void)
Finds the current document.
Document related actions: new, save, open, etc.
void error(const errorSelection selection, const char *const format,...)
GtkAction * geany_entry_action_new(const gchar *name, const gchar *label, const gchar *tooltip, gboolean numeric)
void geany_debug(gchar const *format,...)
Main program-related commands.
gtk_container_add(GTK_CONTAINER(dialog->vbox), check_button)
gtk_widget_show_all(dialog)
gchar * configdir
User configuration directory, usually ~/.config/geany.
Structure for representing an open tab with all its properties.
gboolean changed
Whether this document has been changed since it was last saved.
GtkWidget * window
Main window.
GtkWidget * toolbar
Main toolbar.
Defines internationalization macros.
void ui_init_toolbar_widgets(void)
void ui_widget_show_hide(GtkWidget *widget, gboolean show)
gint ui_get_gtk_settings_integer(const gchar *property_name, gint default_value)
Reads an integer from the GTK default settings registry (see http://library.gnome....
GtkWidget * ui_dialog_vbox_new(GtkDialog *dialog)
Makes a fixed border for dialogs without increasing the button box border.
void ui_save_buttons_toggle(gboolean enable)
GeanyMainWidgets main_widgets
void ui_document_buttons_update(void)
GtkWidget * ui_button_new_with_image(const gchar *stock_id, const gchar *text)
Creates a GtkButton with custom text and a stock image similar to gtk_button_new_from_stock().
GtkWidget * ui_lookup_widget(GtkWidget *widget, const gchar *widget_name)
Returns a widget from a name in a component, usually created by Glade.
void ui_update_popup_reundo_items(GeanyDocument *doc)
User Interface general utility functions.
#define GEANY_STOCK_CLOSE_ALL
#define GEANY_STOCK_SAVE_ALL
#define GEANY_STOCK_BUILD
gint utils_write_file(const gchar *filename, const gchar *text)
Writes text into a file named filename.
gchar * utils_str_remove_chars(gchar *string, const gchar *chars)
Removes characters from a string, in place.
gboolean utils_str_equal(const gchar *a, const gchar *b)
NULL-safe string comparison.
General utility functions, non-GTK related.
#define foreach_slist(node, list)
Iterates all the nodes in list.
#define foreach_list(node, list)
Iterates all the nodes in list.
#define SETPTR(ptr, result)
Assigns result to ptr, then frees the old value.
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.