poll-questions.c: cosmetix
[k8lowj.git] / src / poll-questions.c
blob5b63c5853cfafa459b36b9ad65ccbec83f2ed335
1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2004 Evan Martin <martine@danga.com>
3 */
4 #include "gtk-all.h"
5 #include "util-gtk.h"
7 #include "poll.h"
10 typedef struct {
11 GtkWidget *dlg;
12 GtkWidget *typemenu;
13 GtkWidget *question;
14 JamReorderable answers;
15 } PollMultiDlg;
18 typedef struct {
19 GtkWidget *dlg;
20 GtkWidget *question;
21 GtkWidget *size, *width;
22 } PollTextDlg;
25 typedef struct {
26 GtkWidget *dlg;
27 GtkWidget *question;
28 GtkWidget *from, *to, *by;
29 } PollScaleDlg;
32 static char *pollmultidlg_option (GtkWindow *parent, const char *current) {
33 GtkWidget *dlg, *vbox, *label, *view;
34 GtkTextBuffer *buffer;
35 char *newtext = NULL;
37 dlg = gtk_dialog_new_with_buttons(_("Multi Poll Option"), parent, GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
38 jam_win_set_size(GTK_WINDOW(dlg), 300, -1);
40 vbox = gtk_vbox_new(FALSE, 6);
42 label = gtk_label_new_with_mnemonic(_("O_ption:"));
43 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
44 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
46 view = gtk_text_view_new();
47 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
48 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
49 if (current) gtk_text_buffer_insert_at_cursor(buffer, current, -1);
50 gtk_label_set_mnemonic_widget(GTK_LABEL(label), view);
51 gtk_box_pack_start(GTK_BOX(vbox), scroll_wrap(view), TRUE, TRUE, 0);
53 jam_dialog_set_contents(GTK_DIALOG(dlg), vbox);
55 if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_OK) {
56 GtkTextIter start, end;
57 gtk_text_buffer_get_bounds(buffer, &start, &end);
58 newtext = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
60 gtk_widget_destroy(dlg);
61 return newtext;
65 static void add_option_cb (PollMultiDlg *pmdlg) {
66 char *newtext;
67 GtkTreeIter iter;
69 newtext = pollmultidlg_option(GTK_WINDOW(pmdlg->dlg), NULL);
70 if (!newtext) return;
71 gtk_list_store_append(pmdlg->answers.store, &iter);
72 gtk_list_store_set(pmdlg->answers.store, &iter, 0, newtext, -1);
73 g_free(newtext);
77 static void edit_option_cb (PollMultiDlg *pmdlg) {
78 GtkTreeSelection *sel;
79 GtkTreeModel *model;
80 GtkTreeIter iter;
81 char *text, *newtext;
83 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(pmdlg->answers.view));
85 if (!gtk_tree_selection_get_selected(sel, &model, &iter)) return;
86 gtk_tree_model_get(model, &iter, 0, &text, -1);
87 newtext = pollmultidlg_option(GTK_WINDOW(pmdlg->dlg), text);
88 if (newtext) gtk_list_store_set(pmdlg->answers.store, &iter, 0, newtext, -1);
89 g_free(text);
90 g_free(newtext);
94 static void remove_option_cb (PollMultiDlg *pmdlg) {
95 GtkTreeSelection *sel;
96 GtkTreeIter iter;
98 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(pmdlg->answers.view));
99 if (!gtk_tree_selection_get_selected(sel, NULL, &iter)) return;
100 gtk_list_store_remove(pmdlg->answers.store, &iter);
104 static void pollmulti_make_list (PollMultiDlg *pmdlg) {
105 GtkCellRenderer *renderer;
106 GtkTreeViewColumn *column;
108 pmdlg->answers.store = gtk_list_store_new(1, G_TYPE_STRING);
110 jam_reorderable_make(&pmdlg->answers);
111 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(pmdlg->answers.view), FALSE);
112 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(pmdlg->answers.view), TRUE);
113 g_object_unref(pmdlg->answers.store);
115 renderer = gtk_cell_renderer_text_new();
116 column = gtk_tree_view_column_new();
117 gtk_tree_view_column_pack_start(column, renderer, TRUE);
118 gtk_tree_view_column_add_attribute(column, renderer, "text", 0);
119 gtk_tree_view_append_column(GTK_TREE_VIEW(pmdlg->answers.view), column);
121 g_signal_connect_swapped(G_OBJECT(pmdlg->answers.add), "clicked", G_CALLBACK(add_option_cb), pmdlg);
122 g_signal_connect_swapped(G_OBJECT(pmdlg->answers.edit), "clicked", G_CALLBACK(edit_option_cb), pmdlg);
123 g_signal_connect_swapped(G_OBJECT(pmdlg->answers.remove), "clicked", G_CALLBACK(remove_option_cb), pmdlg);
127 static void pollmultidlg_init (PollMultiDlg *pmdlg, GtkWindow *parent) {
128 GtkWidget *mainbox, *vbox, *paned;
129 GtkWidget *menu, *label;
131 pmdlg->dlg = gtk_dialog_new_with_buttons(_("Multi Poll Question"),
132 parent, GTK_DIALOG_MODAL,
133 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
134 jam_win_set_size(GTK_WINDOW(pmdlg->dlg), 500, -1);
136 mainbox = gtk_vbox_new(FALSE, 12);
138 menu = gtk_menu_new();
139 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_menu_item_new_with_mnemonic(_("Choose best answer (_radio buttons)")));
140 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_menu_item_new_with_mnemonic(_("Choose best answer (_drop-down menu)")));
141 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_menu_item_new_with_mnemonic(_("Select _all that apply (checkboxes)")));
143 pmdlg->typemenu = gtk_option_menu_new();
144 gtk_option_menu_set_menu(GTK_OPTION_MENU(pmdlg->typemenu), menu);
145 gtk_box_pack_start(GTK_BOX(mainbox), labelled_box_new_expand(_("Choice _Type:"), pmdlg->typemenu, TRUE), FALSE, FALSE, 0);
147 paned = gtk_hpaned_new();
148 gtk_box_pack_start(GTK_BOX(mainbox), paned, TRUE, TRUE, 0);
150 vbox = gtk_vbox_new(FALSE, 6);
151 label = gtk_label_new_with_mnemonic(_("_Question:"));
152 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
153 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
155 pmdlg->question = gtk_text_view_new();
156 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(pmdlg->question), GTK_WRAP_WORD);
157 gtk_label_set_mnemonic_widget(GTK_LABEL(label), pmdlg->question);
158 gtk_box_pack_start(GTK_BOX(vbox), scroll_wrap(pmdlg->question), TRUE, TRUE, 0);
160 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, FALSE);
162 vbox = gtk_vbox_new(FALSE, 6);
163 pollmulti_make_list(pmdlg);
164 label = gtk_label_new_with_mnemonic(_("O_ptions:"));
165 gtk_label_set_mnemonic_widget(GTK_LABEL(label), pmdlg->answers.view);
166 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
167 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
168 gtk_box_pack_start(GTK_BOX(vbox), pmdlg->answers.box, TRUE, TRUE, 0);
170 gtk_paned_pack2(GTK_PANED(paned), vbox, TRUE, FALSE);
172 jam_dialog_set_contents(GTK_DIALOG(pmdlg->dlg), mainbox);
176 PollQuestion *pollmultidlg_run (GtkWindow *parent, PollQuestionMulti *qm) {
177 PollQuestion *q = NULL;
178 GtkTextBuffer *buffer;
179 STACK(PollMultiDlg, pmdlg);
181 pollmultidlg_init(pmdlg, parent);
183 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pmdlg->question));
184 if (qm) {
185 GSList *l;
186 GtkTreeIter iter;
187 q = (PollQuestion *) qm;
188 gtk_option_menu_set_history(GTK_OPTION_MENU(pmdlg->typemenu), q->type);
189 gtk_text_buffer_insert_at_cursor(buffer, q->question, -1);
190 for (l = qm->answers; l; l = l->next) {
191 gtk_list_store_append(pmdlg->answers.store, &iter);
192 gtk_list_store_set(pmdlg->answers.store, &iter, 0, l->data, -1);
196 if (gtk_dialog_run(GTK_DIALOG(pmdlg->dlg)) == GTK_RESPONSE_OK) {
197 GtkTextIter start, end;
198 GtkTreeModel *model = GTK_TREE_MODEL(pmdlg->answers.store);
199 GtkTreeIter iter;
201 if (qm == NULL) qm = g_new0(PollQuestionMulti, 1);
202 q = (PollQuestion *)qm;
203 q->type = gtk_option_menu_get_history(GTK_OPTION_MENU(pmdlg->typemenu));
205 gtk_text_buffer_get_bounds(buffer, &start, &end);
206 g_free(q->question);
207 q->question = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
209 g_slist_foreach(qm->answers, (GFunc) g_free, NULL);
210 g_slist_free(qm->answers);
211 qm->answers = NULL;
212 if (gtk_tree_model_get_iter_first(model, &iter)) {
213 /* this is probably O(n^2) or something like that.
214 * but there hopefully won't be that many answers. */
215 do {
216 char *text;
217 gtk_tree_model_get(model, &iter, 0, &text, -1);
218 qm->answers = g_slist_append(qm->answers, text);
219 } while (gtk_tree_model_iter_next(model, &iter));
222 gtk_widget_destroy(GTK_WIDGET(pmdlg->dlg));
223 return q;
227 static void polltextdlg_init (PollTextDlg *ptdlg, GtkWindow *parent) {
228 GtkWidget *mainbox, *vbox;
229 GtkWidget *label, *view;
231 ptdlg->dlg = gtk_dialog_new_with_buttons(_("Text Poll Question"),
232 parent, GTK_DIALOG_MODAL,
233 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
235 mainbox = gtk_vbox_new(FALSE, 12);
237 vbox = gtk_vbox_new(FALSE, 6);
239 label = gtk_label_new_with_mnemonic(_("_Question:"));
240 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
241 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
243 ptdlg->question = view = gtk_text_view_new();
244 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
245 gtk_label_set_mnemonic_widget(GTK_LABEL(label), view);
246 gtk_box_pack_start(GTK_BOX(vbox), scroll_wrap(view), TRUE, TRUE, 0);
248 gtk_box_pack_start(GTK_BOX(mainbox), vbox, TRUE, TRUE, 0);
250 vbox = gtk_vbox_new(FALSE, 6);
252 ptdlg->size = gtk_entry_new();
253 gtk_entry_set_width_chars(GTK_ENTRY(ptdlg->size), 4);
254 ptdlg->width = gtk_entry_new();
255 gtk_entry_set_width_chars(GTK_ENTRY(ptdlg->width), 4);
257 gtk_box_pack_start(GTK_BOX(vbox), labelled_box_new(_("_Text field size (optional): "), ptdlg->size), FALSE, FALSE, 0);
258 gtk_box_pack_start(GTK_BOX(vbox), labelled_box_new(_("_Maximum text length (optional): "), ptdlg->width), FALSE, FALSE, 0);
260 gtk_box_pack_start(GTK_BOX(mainbox), vbox, FALSE, FALSE, 0);
262 jam_dialog_set_contents(GTK_DIALOG(ptdlg->dlg), mainbox);
266 PollQuestion *polltextdlg_run (GtkWindow *parent, PollQuestionText *pqt) {
267 STACK(PollTextDlg, ptdlg);
268 PollQuestion *q = NULL;
269 GtkTextBuffer *buffer;
271 polltextdlg_init(ptdlg, parent);
273 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ptdlg->question));
274 if (pqt) {
275 char *text;
276 q = (PollQuestion *) pqt;
277 gtk_text_buffer_insert_at_cursor(buffer, q->question, -1);
278 if (pqt->size) {
279 text = g_strdup_printf("%d", pqt->size);
280 gtk_entry_set_text(GTK_ENTRY(ptdlg->size), text);
281 g_free(text);
283 if (pqt->width) {
284 text = g_strdup_printf("%d", pqt->width);
285 gtk_entry_set_text(GTK_ENTRY(ptdlg->width), text);
286 g_free(text);
290 if (gtk_dialog_run(GTK_DIALOG(ptdlg->dlg)) == GTK_RESPONSE_OK) {
291 GtkTextIter start, end;
292 const char *text;
294 if (!pqt) pqt = g_new0(PollQuestionText, 1);
295 q = (PollQuestion *) pqt;
296 q->type = PQ_TEXT;
298 gtk_text_buffer_get_bounds(buffer, &start, &end);
299 g_free(q->question);
300 q->question = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
302 text = gtk_entry_get_text(GTK_ENTRY(ptdlg->size));
303 if (text && text[0])
304 pqt->size = atoi(text);
306 text = gtk_entry_get_text(GTK_ENTRY(ptdlg->width));
307 if (text && text[0]) pqt->width = atoi(text);
309 gtk_widget_destroy(GTK_WIDGET(ptdlg->dlg));
310 return q;
314 static void pollscaledlg_init (PollScaleDlg *psdlg, GtkWindow *parent) {
315 GtkWidget *mainbox, *vbox;
316 GtkWidget *label;
317 GtkSizeGroup *sizegroup;
319 GtkAdjustment *adj1 = (GtkAdjustment *)gtk_adjustment_new(1.0, -32000.0, 32000.0, 1.0, 5.0, 5.0);
320 GtkAdjustment *adj2 = (GtkAdjustment *)gtk_adjustment_new(10.0, -32000.0, 32000.0, 1.0, 5.0, 5.0);
321 GtkAdjustment *adj3 = (GtkAdjustment *)gtk_adjustment_new(1.0, -32000.0, 32000.0, 1.0, 5.0, 5.0);
323 psdlg->dlg = gtk_dialog_new_with_buttons(_("Scale Poll Question"),
324 parent, GTK_DIALOG_MODAL,
325 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
326 jam_win_set_size(GTK_WINDOW(psdlg->dlg), 400, -1);
328 mainbox = gtk_hbox_new(FALSE, 12);
330 vbox = gtk_vbox_new(FALSE, 6);
331 label = gtk_label_new_with_mnemonic(_("_Question:"));
332 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
333 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
335 psdlg->question = gtk_text_view_new();
336 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(psdlg->question), GTK_WRAP_WORD);
337 gtk_label_set_mnemonic_widget(GTK_LABEL(label), psdlg->question);
338 gtk_box_pack_start(GTK_BOX(vbox), scroll_wrap(psdlg->question), TRUE, TRUE, 0);
340 gtk_box_pack_start(GTK_BOX(mainbox), vbox, TRUE, TRUE, 0);
342 vbox = gtk_vbox_new(FALSE, 6);
343 sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
345 psdlg->from = gtk_spin_button_new(adj1, 1.0, 0);
346 gtk_box_pack_start(GTK_BOX(vbox), labelled_box_new_sg(_("_From:"), psdlg->from, sizegroup), FALSE, FALSE, 0);
347 psdlg->to = gtk_spin_button_new(adj2, 1.0, 0);
348 gtk_box_pack_start(GTK_BOX(vbox), labelled_box_new_sg(_("_To:"), psdlg->to, sizegroup), FALSE, FALSE, 0);
349 psdlg->by = gtk_spin_button_new(adj3, 1.0, 0);
350 gtk_box_pack_start(GTK_BOX(vbox), labelled_box_new_sg(_("_By:"), psdlg->by, sizegroup), FALSE, FALSE, 0);
352 gtk_box_pack_start(GTK_BOX(mainbox), vbox, FALSE, FALSE, 0);
354 jam_dialog_set_contents(GTK_DIALOG(psdlg->dlg), mainbox);
358 PollQuestion *pollscaledlg_run (GtkWindow *parent, PollQuestionScale *pqs) {
359 STACK(PollScaleDlg, psdlg);
360 PollQuestion *q = NULL;
361 GtkTextBuffer *buffer;
363 pollscaledlg_init(psdlg, parent);
364 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(psdlg->question));
365 if (pqs) {
366 q = (PollQuestion *)pqs;
367 gtk_text_buffer_insert_at_cursor(buffer, q->question, -1);
368 gtk_spin_button_set_value(GTK_SPIN_BUTTON(psdlg->from), (gdouble) pqs->from);
369 gtk_spin_button_set_value(GTK_SPIN_BUTTON(psdlg->to), (gdouble) pqs->to);
370 gtk_spin_button_set_value(GTK_SPIN_BUTTON(psdlg->by), (gdouble) pqs->by);
373 if (gtk_dialog_run(GTK_DIALOG(psdlg->dlg)) == GTK_RESPONSE_OK) {
374 GtkTextIter start, end;
376 if (!pqs) pqs = g_new0(PollQuestionScale, 1);
377 q = (PollQuestion *)pqs;
378 q->type = PQ_SCALE;
380 gtk_text_buffer_get_bounds(buffer, &start, &end);
381 g_free(q->question);
382 q->question = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
384 pqs->from = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(psdlg->from));
385 pqs->to = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(psdlg->to));
386 pqs->by = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(psdlg->by));
388 gtk_widget_destroy(GTK_WIDGET(psdlg->dlg));
389 return q;
393 void poll_question_free (PollQuestion *pq) {
394 switch (pq->type) {
395 case PQ_RADIO:
396 case PQ_COMBO:
397 case PQ_CHECK:
398 g_slist_foreach(((PollQuestionMulti *)pq)->answers, (GFunc)g_free, NULL);
399 g_slist_free(((PollQuestionMulti *)pq)->answers);
400 break;
401 case PQ_TEXT:
402 case PQ_SCALE:
403 break;
405 g_free(pq);