chiark / gitweb /
Switch to GPL v3
[disorder] / disobedience / menu.c
CommitLineData
460b9539 1/*
2 * This file is part of DisOrder.
fb009628 3 * Copyright (C) 2006-2008 Richard Kettlewell
460b9539 4 *
e7eb3a27 5 * This program is free software: you can redistribute it and/or modify
460b9539 6 * it under the terms of the GNU General Public License as published by
e7eb3a27 7 * the Free Software Foundation, either version 3 of the License, or
460b9539 8 * (at your option) any later version.
9 *
e7eb3a27
RK
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
460b9539 15 * You should have received a copy of the GNU General Public License
e7eb3a27 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
460b9539 17 */
2c348789
RK
18/** @file disobedience/menu.c
19 * @brief Main menu
20 */
460b9539 21
22#include "disobedience.h"
23
24static GtkWidget *selectall_widget;
fb009628 25static GtkWidget *selectnone_widget;
460b9539 26static GtkWidget *properties_widget;
27
ac6bf2ba
RK
28/** @brief Main menu widgets */
29GtkItemFactory *mainmenufactory;
30
06bfbba4 31static void about_popup_got_version(void *v,
e2717131 32 const char *err,
06bfbba4 33 const char *value);
460b9539 34
2c348789
RK
35/** @brief Called when the quit option is activated
36 *
37 * Just exits.
38 */
460b9539 39static void quit_program(gpointer attribute((unused)) callback_data,
40 guint attribute((unused)) callback_action,
41 GtkWidget attribute((unused)) *menu_item) {
42 D(("quit_program"));
43 exit(0);
44}
45
d9a92920 46/** @brief Called when an edit menu item is selected
2c348789 47 *
d9a92920
RK
48 * Shared by several menu items; callback_action is expected to be the offset
49 * of the activate member of struct tabtype.
2c348789 50 */
d9a92920
RK
51static void menu_tab_action(gpointer attribute((unused)) callback_data,
52 guint callback_action,
460b9539 53 GtkWidget attribute((unused)) *menu_item) {
54 GtkWidget *tab = gtk_notebook_get_nth_page
55 (GTK_NOTEBOOK(tabs), gtk_notebook_current_page(GTK_NOTEBOOK(tabs)));
56 const struct tabtype *t = g_object_get_data(G_OBJECT(tab), "type");
57
d9a92920
RK
58 void (**activatep)(GtkMenuItem *, gpointer)
59 = (void *)((const char *)t + callback_action);
60 void (*activate)(GtkMenuItem *, gpointer) = *activatep;
61
62 if(activate)
63 activate(NULL, t->extra);
460b9539 64}
65
73f1b9f3
RK
66/** @brief Called when the login option is activated */
67static void login(gpointer attribute((unused)) callback_data,
68 guint attribute((unused)) callback_action,
69 GtkWidget attribute((unused)) *menu_item) {
70 login_box();
71}
72
ffc4dbaf
RK
73/** @brief Called when the login option is activated */
74static void users(gpointer attribute((unused)) callback_data,
75 guint attribute((unused)) callback_action,
76 GtkWidget attribute((unused)) *menu_item) {
77 manage_users();
78}
79
46fb1b05
RK
80#if 0
81/** @brief Called when the settings option is activated */
82static void settings(gpointer attribute((unused)) callback_data,
83 guint attribute((unused)) callback_action,
84 GtkWidget attribute((unused)) *menu_item) {
85 popup_settings();
86}
87#endif
88
229d327f 89/** @brief Called when edit menu is shown
2c348789
RK
90 *
91 * Determines option sensitivity according to the current tab and adjusts the
92 * widgets accordingly. Knows about @ref DISORDER_CONNECTED so the callbacks
93 * need not.
94 */
229d327f
RK
95static void edit_menu_show(GtkWidget attribute((unused)) *widget,
96 gpointer attribute((unused)) user_data) {
961d31f6
RK
97 if(tabs) {
98 GtkWidget *tab = gtk_notebook_get_nth_page
99 (GTK_NOTEBOOK(tabs),
229d327f 100 gtk_notebook_current_page(GTK_NOTEBOOK(tabs)));
961d31f6
RK
101 const struct tabtype *t = g_object_get_data(G_OBJECT(tab), "type");
102
103 assert(t != 0);
104 gtk_widget_set_sensitive(properties_widget,
ee7552f8
RK
105 (t->properties_sensitive
106 && t->properties_sensitive(t->extra)
961d31f6
RK
107 && (disorder_eclient_state(client) & DISORDER_CONNECTED)));
108 gtk_widget_set_sensitive(selectall_widget,
ee7552f8
RK
109 t->selectall_sensitive
110 && t->selectall_sensitive(t->extra));
961d31f6 111 gtk_widget_set_sensitive(selectnone_widget,
ee7552f8
RK
112 t->selectnone_sensitive
113 && t->selectnone_sensitive(t->extra));
961d31f6 114 }
460b9539 115}
2c348789
RK
116
117/** @brief Fetch version in order to display the about... popup */
460b9539 118static void about_popup(gpointer attribute((unused)) callback_data,
119 guint attribute((unused)) callback_action,
120 GtkWidget attribute((unused)) *menu_item) {
121 D(("about_popup"));
122
123 gtk_label_set_text(GTK_LABEL(report_label), "getting server version");
124 disorder_eclient_version(client,
125 about_popup_got_version,
126 0);
127}
128
13affe66
RK
129static void manual_popup(gpointer attribute((unused)) callback_data,
130 guint attribute((unused)) callback_action,
131 GtkWidget attribute((unused)) *menu_item) {
132 D(("manual_popup"));
133
134 popup_help();
135}
136
883a4e96 137/** @brief Called when version arrives, displays about... popup */
460b9539 138static void about_popup_got_version(void attribute((unused)) *v,
abf99697 139 const char attribute((unused)) *err,
460b9539 140 const char *value) {
141 GtkWidget *w;
142 char *server_version_string;
54cca6d6 143 char *short_version_string;
413b30a4 144 GtkWidget *hbox, *vbox, *title;
460b9539 145
06bfbba4
RK
146 if(!value)
147 value = "[error]";
460b9539 148 byte_xasprintf(&server_version_string, "Server version %s", value);
54cca6d6
RK
149 byte_xasprintf(&short_version_string, "Disobedience %s",
150 disorder_short_version_string);
413b30a4 151 w = gtk_dialog_new_with_buttons("About Disobedience",
460b9539 152 GTK_WINDOW(toplevel),
153 (GTK_DIALOG_MODAL
154 |GTK_DIALOG_DESTROY_WITH_PARENT),
155 GTK_STOCK_OK,
156 GTK_RESPONSE_ACCEPT,
157 (char *)NULL);
413b30a4
RK
158 hbox = gtk_hbox_new(FALSE/*homogeneous*/, 1/*padding*/);
159 vbox = gtk_vbox_new(FALSE/*homogeneous*/, 1/*padding*/);
160 gtk_box_pack_start(GTK_BOX(hbox),
161 gtk_image_new_from_pixbuf(find_image("duck.png")),
162 FALSE/*expand*/,
163 FALSE/*fill*/,
164 4/*padding*/);
165 gtk_box_pack_start(GTK_BOX(vbox),
54cca6d6 166 gtk_label_new(short_version_string),
413b30a4
RK
167 FALSE/*expand*/,
168 FALSE/*fill*/,
169 1/*padding*/);
170 gtk_box_pack_start(GTK_BOX(vbox),
171 gtk_label_new(server_version_string),
172 FALSE/*expand*/,
173 FALSE/*fill*/,
174 1/*padding*/);
175 gtk_box_pack_start(GTK_BOX(vbox),
8f9616f1 176 gtk_label_new("\xC2\xA9 2004-2008 Richard Kettlewell"),
413b30a4
RK
177 FALSE/*expand*/,
178 FALSE/*fill*/,
179 1/*padding*/);
180 gtk_box_pack_end(GTK_BOX(hbox),
181 vbox,
182 FALSE/*expand*/,
183 FALSE/*fill*/,
184 0/*padding*/);
185 title = gtk_label_new(0);
186 gtk_label_set_markup(GTK_LABEL(title),
187 "<span font_desc=\"Sans 36\">Disobedience</span>");
188 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(w)->vbox), title,
189 FALSE/*expand*/,
190 FALSE/*fill*/,
191 0/*padding*/);
192 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(w)->vbox), hbox,
193 FALSE/*expand*/,
194 FALSE/*fill*/,
195 0/*padding*/);
76fc02c5 196 set_tool_colors(w);
460b9539 197 gtk_widget_show_all(w);
198 gtk_dialog_run(GTK_DIALOG(w));
199 gtk_widget_destroy(w);
200}
201
c73bd6c1
RK
202/** @brief Set 'Manage Users' menu item sensitivity */
203void users_set_sensitive(int sensitive) {
204 GtkWidget *w = gtk_item_factory_get_widget(mainmenufactory,
205 "<GdisorderMain>/Server/Manage users");
206 gtk_widget_set_sensitive(w, sensitive);
207}
208
6f09d54d
RK
209/** @brief Called when our rights change */
210static void menu_rights_changed(const char attribute((unused)) *event,
211 void attribute((unused)) *eventdata,
212 void attribute((unused)) *callbackdata) {
213 users_set_sensitive(!!(last_rights & RIGHT_ADMIN));
c73bd6c1
RK
214}
215
2c348789 216/** @brief Create the menu bar widget */
460b9539 217GtkWidget *menubar(GtkWidget *w) {
d4ef4132
RK
218 GtkWidget *m;
219
460b9539 220 static const GtkItemFactoryEntry entries[] = {
2d504956 221 {
eb80584d 222 (char *)"/Server", /* path */
2d504956
RK
223 0, /* accelerator */
224 0, /* callback */
225 0, /* callback_action */
226 (char *)"<Branch>", /* item_type */
227 0 /* extra_data */
228 },
229 {
eb80584d 230 (char *)"/Server/Login", /* path */
2d504956
RK
231 (char *)"<CTRL>L", /* accelerator */
232 login, /* callback */
233 0, /* callback_action */
234 0, /* item_type */
235 0 /* extra_data */
236 },
ffc4dbaf 237 {
eb80584d 238 (char *)"/Server/Manage users", /* path */
ffc4dbaf
RK
239 0, /* accelerator */
240 users, /* callback */
241 0, /* callback_action */
242 0, /* item_type */
243 0 /* extra_data */
244 },
46fb1b05
RK
245#if 0
246 {
eb80584d 247 (char *)"/Server/Settings", /* path */
46fb1b05
RK
248 0, /* accelerator */
249 settings, /* callback */
250 0, /* callback_action */
251 0, /* item_type */
252 0 /* extra_data */
253 },
254#endif
2d504956 255 {
eb80584d 256 (char *)"/Server/Quit Disobedience", /* path */
2d504956
RK
257 (char *)"<CTRL>Q", /* accelerator */
258 quit_program, /* callback */
259 0, /* callback_action */
260 (char *)"<StockItem>", /* item_type */
261 GTK_STOCK_QUIT /* extra_data */
262 },
ac6bf2ba 263
2d504956
RK
264 {
265 (char *)"/Edit", /* path */
266 0, /* accelerator */
267 0, /* callback */
268 0, /* callback_action */
269 (char *)"<Branch>", /* item_type */
270 0 /* extra_data */
271 },
272 {
273 (char *)"/Edit/Select all tracks", /* path */
52d45ac3 274 0, /* accelerator */
d9a92920
RK
275 menu_tab_action, /* callback */
276 offsetof(struct tabtype, selectall_activate), /* callback_action */
2d504956
RK
277 0, /* item_type */
278 0 /* extra_data */
279 },
280 {
fb009628 281 (char *)"/Edit/Deselect all tracks", /* path */
52d45ac3 282 0, /* accelerator */
d9a92920
RK
283 menu_tab_action, /* callback */
284 offsetof(struct tabtype, selectnone_activate), /* callback_action */
fb009628
RK
285 0, /* item_type */
286 0 /* extra_data */
287 },
288 {
2d504956
RK
289 (char *)"/Edit/Track properties", /* path */
290 0, /* accelerator */
d9a92920
RK
291 menu_tab_action, /* callback */
292 offsetof(struct tabtype, properties_activate), /* callback_action */
2d504956
RK
293 0, /* item_type */
294 0 /* extra_data */
295 },
296
297 {
298 (char *)"/Control", /* path */
299 0, /* accelerator */
300 0, /* callback */
301 0, /* callback_action */
302 (char *)"<Branch>", /* item_type */
303 0 /* extra_data */
304 },
305 {
306 (char *)"/Control/Scratch", /* path */
307 (char *)"<CTRL>S", /* accelerator */
308 0, /* callback */
309 0, /* callback_action */
310 0, /* item_type */
311 0 /* extra_data */
312 },
313 {
685bdfbd
RK
314 (char *)"/Control/Playing", /* path */
315 (char *)"<CTRL>P", /* accelerator */
316 0, /* callback */
317 0, /* callback_action */
318 (char *)"<CheckItem>", /* item_type */
319 0 /* extra_data */
320 },
321 {
2d504956
RK
322 (char *)"/Control/Random play", /* path */
323 (char *)"<CTRL>R", /* accelerator */
324 0, /* callback */
685bdfbd
RK
325 0, /* callback_action */
326 (char *)"<CheckItem>", /* item_type */
327 0 /* extra_data */
328 },
329 {
330 (char *)"/Control/Network player", /* path */
331 (char *)"<CTRL>N", /* accelerator */
332 0, /* callback */
2d504956
RK
333 0, /* callback_action */
334 (char *)"<CheckItem>", /* item_type */
335 0 /* extra_data */
336 },
337
338 {
339 (char *)"/Help", /* path */
340 0, /* accelerator */
341 0, /* callback */
342 0, /* callback_action */
343 (char *)"<Branch>", /* item_type */
344 0 /* extra_data */
345 },
346 {
13affe66
RK
347 (char *)"/Help/Manual page", /* path */
348 0, /* accelerator */
349 manual_popup, /* callback */
350 0, /* callback_action */
351 0, /* item_type */
352 0 /* extra_data */
353 },
354 {
2d504956
RK
355 (char *)"/Help/About DisOrder", /* path */
356 0, /* accelerator */
357 about_popup, /* callback */
358 0, /* callback_action */
359 (char *)"<StockItem>", /* item_type */
360 GTK_STOCK_ABOUT /* extra_data */
361 },
460b9539 362 };
363
460b9539 364 GtkAccelGroup *accel = gtk_accel_group_new();
365
366 D(("add_menubar"));
367 /* TODO: item factories are deprecated in favour of some XML thing */
ac6bf2ba
RK
368 mainmenufactory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<GdisorderMain>",
369 accel);
370 gtk_item_factory_create_items(mainmenufactory,
460b9539 371 sizeof entries / sizeof *entries,
372 (GtkItemFactoryEntry *)entries,
373 0);
374 gtk_window_add_accel_group(GTK_WINDOW(w), accel);
ac6bf2ba 375 selectall_widget = gtk_item_factory_get_widget(mainmenufactory,
39fe1014 376 "<GdisorderMain>/Edit/Select all tracks");
fb009628
RK
377 selectnone_widget = gtk_item_factory_get_widget(mainmenufactory,
378 "<GdisorderMain>/Edit/Deselect all tracks");
ac6bf2ba 379 properties_widget = gtk_item_factory_get_widget(mainmenufactory,
39fe1014 380 "<GdisorderMain>/Edit/Track properties");
460b9539 381 assert(selectall_widget != 0);
fb009628 382 assert(selectnone_widget != 0);
460b9539 383 assert(properties_widget != 0);
229d327f
RK
384
385
386 GtkWidget *edit_widget = gtk_item_factory_get_widget(mainmenufactory,
387 "<GdisorderMain>/Edit");
229d327f
RK
388 g_signal_connect(edit_widget, "show", G_CALLBACK(edit_menu_show), 0);
389
6f09d54d
RK
390 event_register("rights-changed", menu_rights_changed, 0);
391 users_set_sensitive(0);
d4ef4132
RK
392 m = gtk_item_factory_get_widget(mainmenufactory,
393 "<GdisorderMain>");
394 set_tool_colors(m);
395 return m;
460b9539 396}
397
398/*
399Local Variables:
400c-basic-offset:2
401comment-column:40
402fill-column:79
403indent-tabs-mode:nil
404End:
405*/