]> Pileus Git - ~andy/gtk/blob - examples/bloatpad.c
Bloatpad: Don't leak a menu model
[~andy/gtk] / examples / bloatpad.c
1 #include <stdlib.h>
2 #include <gtk/gtk.h>
3
4 static GtkClipboard *
5 get_clipboard (GtkWidget *widget)
6 {
7   return gtk_widget_get_clipboard (widget, gdk_atom_intern_static_string ("CLIPBOARD"));
8 }
9
10 static void
11 window_copy (GSimpleAction *action,
12              GVariant      *parameter,
13              gpointer       user_data)
14 {
15   GtkWindow *window = GTK_WINDOW (user_data);
16   GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
17
18   gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (text),
19                                   get_clipboard ((GtkWidget*) text));
20 }
21
22 static void
23 window_paste (GSimpleAction *action,
24               GVariant      *parameter,
25               gpointer       user_data)
26 {
27   GtkWindow *window = GTK_WINDOW (user_data);
28   GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
29   
30   gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text),
31                                    get_clipboard ((GtkWidget*) text),
32                                    NULL,
33                                    TRUE);
34
35 }
36
37 static GActionEntry win_entries[] = {
38   { "copy", window_copy, NULL, NULL, NULL },
39   { "paste", window_paste, NULL, NULL, NULL },
40 };
41
42 static void
43 new_window (GApplication *app,
44             GFile        *file)
45 {
46   GtkWidget *window, *grid, *scrolled, *view;
47
48   window = gtk_application_window_new (GTK_APPLICATION (app));
49   gtk_window_set_default_size ((GtkWindow*)window, 640, 480);
50   g_action_map_add_action_entries (G_ACTION_MAP (window), win_entries, G_N_ELEMENTS (win_entries), window);
51   gtk_window_set_title (GTK_WINDOW (window), "Bloatpad");
52
53   grid = gtk_grid_new ();
54   gtk_container_add (GTK_CONTAINER (window), grid);
55
56   scrolled = gtk_scrolled_window_new (NULL, NULL);
57   gtk_widget_set_hexpand (scrolled, TRUE);
58   gtk_widget_set_vexpand (scrolled, TRUE);
59   view = gtk_text_view_new ();
60
61   g_object_set_data ((GObject*)window, "bloatpad-text", view);
62
63   gtk_container_add (GTK_CONTAINER (scrolled), view);
64
65   gtk_grid_attach (GTK_GRID (grid), scrolled, 0, 0, 1, 1);
66
67   if (file != NULL)
68     {
69       gchar *contents;
70       gsize length;
71
72       if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
73         {
74           GtkTextBuffer *buffer;
75
76           buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
77           gtk_text_buffer_set_text (buffer, contents, length);
78           g_free (contents);
79         }
80     }
81
82   gtk_widget_show_all (GTK_WIDGET (window));
83 }
84
85 static void
86 bloat_pad_activate (GApplication *application)
87 {
88   new_window (application, NULL);
89 }
90
91 static void
92 bloat_pad_open (GApplication  *application,
93                 GFile        **files,
94                 gint           n_files,
95                 const gchar   *hint)
96 {
97   gint i;
98
99   for (i = 0; i < n_files; i++)
100     new_window (application, files[i]);
101 }
102
103 typedef GtkApplication BloatPad;
104 typedef GtkApplicationClass BloatPadClass;
105
106 G_DEFINE_TYPE (BloatPad, bloat_pad, GTK_TYPE_APPLICATION)
107
108 static void
109 bloat_pad_finalize (GObject *object)
110 {
111   G_OBJECT_CLASS (bloat_pad_parent_class)->finalize (object);
112 }
113
114 static void
115 show_about (GSimpleAction *action,
116             GVariant      *parameter,
117             gpointer       user_data)
118 {
119   GtkWindow *window = user_data;
120
121   gtk_show_about_dialog (window,
122                          "program-name", "Bloatpad",
123                          "title", "About Bloatpad",
124                          "comments", "Not much to say, really.",
125                          NULL);
126 }
127
128
129 static void
130 quit_app (GSimpleAction *action,
131           GVariant      *parameter,
132           gpointer       user_data)
133 {
134   GList *list, *next;
135   GtkWindow *win;
136
137   g_print ("Going down...\n");
138
139   list = gtk_application_get_windows (GTK_APPLICATION (g_application_get_default ()));
140   while (list)
141     {
142       win = list->data;
143       next = list->next;
144
145       gtk_widget_destroy (GTK_WIDGET (win));
146
147       list = next;
148     }
149 }
150
151 static GActionEntry app_entries[] = {
152   { "about", show_about, NULL, NULL, NULL },
153   { "quit", quit_app, NULL, NULL, NULL },
154 };
155
156 static GActionGroup *
157 create_app_actions (void)
158 {
159   GSimpleActionGroup *actions = g_simple_action_group_new ();
160   g_simple_action_group_add_entries (actions,
161                                      app_entries, G_N_ELEMENTS (app_entries),
162                                      NULL);
163
164   return G_ACTION_GROUP (actions);
165 }
166
167 static GMenuModel *
168 create_app_menu (void)
169 {
170   GMenu *menu = g_menu_new ();
171   g_menu_append (menu, "_About Bloatpad", "app.about");
172   g_menu_append (menu, "_Quit", "app.quit");
173
174   return G_MENU_MODEL (menu);
175 }
176
177 static GMenuModel *
178 create_window_menu (void)
179 {
180   GMenu *menu;
181   GMenu *edit_menu;
182
183   edit_menu = g_menu_new ();
184   g_menu_append (edit_menu, "_Copy", "win.copy");
185   g_menu_append (edit_menu, "_Paste", "win.paste");
186
187   g_menu_append (edit_menu, "_Fullscreen", "win.fullscreen");
188
189   menu = g_menu_new ();
190   g_menu_append_submenu (menu, "_Edit", (GMenuModel*)edit_menu);
191   g_object_unref (edit_menu);
192
193   return G_MENU_MODEL (menu);
194 }
195
196 static void
197 bloat_pad_init (BloatPad *app)
198 {
199   GActionGroup *actions;
200   GMenuModel *app_menu;
201   GMenuModel *window_menu;
202
203   actions = create_app_actions ();
204   g_application_set_action_group (G_APPLICATION (app), actions);
205   g_object_unref (actions);
206
207   app_menu = create_app_menu ();
208   g_application_set_app_menu (G_APPLICATION (app), app_menu);
209   g_object_unref (app_menu);
210
211   window_menu = create_window_menu ();
212   g_application_set_menubar (G_APPLICATION (app), window_menu);
213   g_object_unref (window_menu);
214 }
215
216 static void
217 bloat_pad_class_init (BloatPadClass *class)
218 {
219   G_OBJECT_CLASS (class)->finalize = bloat_pad_finalize;
220
221   G_APPLICATION_CLASS (class)->activate = bloat_pad_activate;
222   G_APPLICATION_CLASS (class)->open = bloat_pad_open;
223 }
224
225 BloatPad *
226 bloat_pad_new (void)
227 {
228   g_type_init ();
229
230   return g_object_new (bloat_pad_get_type (),
231                        "application-id", "org.gtk.Test.bloatpad",
232                        "flags", G_APPLICATION_HANDLES_OPEN,
233                        NULL);
234 }
235
236 int
237 main (int argc, char **argv)
238 {
239   BloatPad *bloat_pad;
240   int status;
241
242   bloat_pad = bloat_pad_new ();
243   status = g_application_run (G_APPLICATION (bloat_pad), argc, argv);
244   g_object_unref (bloat_pad);
245
246   return status;
247 }