1 /***************************************************************************
2 begin : Sun May 16 2010
3 copyright : (C) 2010 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * Please see toplevel file COPYING for license details *
8 ***************************************************************************/
9
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13
14
15 #include "gtk2_gui_dialog_p.h"
16 #include <assert.h>
17
18 #include <gwenhywfar/inherit.h>
19 #include <gwenhywfar/debug.h>
20 #include <gwenhywfar/gui_be.h>
21 #include <gwenhywfar/i18n.h>
22
23 #include <gwenhywfar/text.h>
24 #include <gwenhywfar/mdigest.h>
25 #include <gwenhywfar/debug.h>
26 #include <gwenhywfar/directory.h>
27
28 #include <ctype.h>
29
30
31 #define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
32
33
34 #define GTK2_DIALOG_WIDGET_REAL 0
35 #define GTK2_DIALOG_WIDGET_CONTENT 1
36 #define GTK2_DIALOG_WIDGET_DATA 2
37
38 #define GTK2_DIALOG_STRING_TITLE 0
39 #define GTK2_DIALOG_STRING_VALUE 1
40
41
42 #include "w_combobox.c"
43 #include "w_label.c"
44 #include "w_dialog.c"
45 #include "w_gridlayout.c"
46 #include "w_hlayout.c"
47 #include "w_hline.c"
48 #include "w_hspacer.c"
49 #include "w_vlayout.c"
50 #include "w_vline.c"
51 #include "w_vspacer.c"
52 #include "w_pushbutton.c"
53 #include "w_lineedit.c"
54 #include "w_textedit.c"
55 #include "w_textbrowser.c"
56 #include "w_stack.c"
57 #include "w_tabbook.c"
58 #include "w_groupbox.c"
59 #include "w_progressbar.c"
60 #include "w_listbox.c"
61 #include "w_checkbox.c"
62 #include "w_scrollarea.c"
63 #include "w_radiobutton.c"
64 #include "w_spinbox.c"
65
66
67
GWEN_INHERIT(GWEN_DIALOG,GTK2_GUI_DIALOG)68 GWEN_INHERIT(GWEN_DIALOG, GTK2_GUI_DIALOG)
69
70
71
72
73 void Gtk2Gui_Dialog_Extend(GWEN_DIALOG *dlg)
74 {
75 GTK2_GUI_DIALOG *xdlg;
76
77 GWEN_NEW_OBJECT(GTK2_GUI_DIALOG, xdlg);
78 GWEN_INHERIT_SETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg, xdlg, Gtk2Gui_Dialog_FreeData);
79
80 /* set virtual functions */
81 xdlg->setIntPropertyFn=GWEN_Dialog_SetSetIntPropertyFn(dlg, Gtk2Gui_Dialog_SetIntProperty);
82 xdlg->getIntPropertyFn=GWEN_Dialog_SetGetIntPropertyFn(dlg, Gtk2Gui_Dialog_GetIntProperty);
83 xdlg->setCharPropertyFn=GWEN_Dialog_SetSetCharPropertyFn(dlg, Gtk2Gui_Dialog_SetCharProperty);
84 xdlg->getCharPropertyFn=GWEN_Dialog_SetGetCharPropertyFn(dlg, Gtk2Gui_Dialog_GetCharProperty);
85
86 }
87
88
89
Gtk2Gui_Dialog_Unextend(GWEN_DIALOG * dlg)90 void Gtk2Gui_Dialog_Unextend(GWEN_DIALOG *dlg)
91 {
92 GTK2_GUI_DIALOG *xdlg;
93
94 assert(dlg);
95 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
96 assert(xdlg);
97
98 /* reset virtual functions */
99 GWEN_Dialog_SetSetIntPropertyFn(dlg, xdlg->setIntPropertyFn);
100 GWEN_Dialog_SetGetIntPropertyFn(dlg, xdlg->getIntPropertyFn);
101 GWEN_Dialog_SetSetCharPropertyFn(dlg, xdlg->setCharPropertyFn);
102 GWEN_Dialog_SetGetCharPropertyFn(dlg, xdlg->getCharPropertyFn);
103
104 GWEN_INHERIT_UNLINK(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
105 }
106
107
108
Gtk2Gui_Dialog_FreeData(GWEN_UNUSED void * bp,void * p)109 void GWENHYWFAR_CB Gtk2Gui_Dialog_FreeData(GWEN_UNUSED void *bp, void *p)
110 {
111 GTK2_GUI_DIALOG *xdlg;
112
113 xdlg=(GTK2_GUI_DIALOG *) p;
114
115 if (xdlg->mainWidget)
116 gtk_widget_destroy(xdlg->mainWidget);
117
118 GWEN_FREE_OBJECT(xdlg);
119 }
120
121
122
Gtk2Gui_Dialog_GetMainWidget(const GWEN_DIALOG * dlg)123 GtkWidget *Gtk2Gui_Dialog_GetMainWidget(const GWEN_DIALOG *dlg)
124 {
125 GTK2_GUI_DIALOG *xdlg;
126
127 assert(dlg);
128 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
129 assert(xdlg);
130
131 return xdlg->mainWidget;
132 }
133
134
135
Gtk2Gui_Dialog_SetIntProperty(GWEN_UNUSED GWEN_DIALOG * dlg,GWEN_WIDGET * w,GWEN_DIALOG_PROPERTY prop,int index,int value,int doSignal)136 GWENHYWFAR_CB int Gtk2Gui_Dialog_SetIntProperty(GWEN_UNUSED GWEN_DIALOG *dlg,
137 GWEN_WIDGET *w,
138 GWEN_DIALOG_PROPERTY prop,
139 int index,
140 int value,
141 int doSignal)
142 {
143 return GWEN_Widget_SetIntProperty(w, prop, index, value, doSignal);
144 }
145
146
147
Gtk2Gui_Dialog_GetIntProperty(GWEN_UNUSED GWEN_DIALOG * dlg,GWEN_WIDGET * w,GWEN_DIALOG_PROPERTY prop,int index,int defaultValue)148 GWENHYWFAR_CB int Gtk2Gui_Dialog_GetIntProperty(GWEN_UNUSED GWEN_DIALOG *dlg,
149 GWEN_WIDGET *w,
150 GWEN_DIALOG_PROPERTY prop,
151 int index,
152 int defaultValue)
153 {
154 return GWEN_Widget_GetIntProperty(w, prop, index, defaultValue);
155 }
156
157
158
Gtk2Gui_Dialog_SetCharProperty(GWEN_UNUSED GWEN_DIALOG * dlg,GWEN_WIDGET * w,GWEN_DIALOG_PROPERTY prop,int index,const char * value,int doSignal)159 GWENHYWFAR_CB int Gtk2Gui_Dialog_SetCharProperty(GWEN_UNUSED GWEN_DIALOG *dlg,
160 GWEN_WIDGET *w,
161 GWEN_DIALOG_PROPERTY prop,
162 int index,
163 const char *value,
164 int doSignal)
165 {
166 return GWEN_Widget_SetCharProperty(w, prop, index, value, doSignal);
167 }
168
169
170
Gtk2Gui_Dialog_GetCharProperty(GWEN_UNUSED GWEN_DIALOG * dlg,GWEN_WIDGET * w,GWEN_DIALOG_PROPERTY prop,int index,const char * defaultValue)171 GWENHYWFAR_CB const char *Gtk2Gui_Dialog_GetCharProperty(GWEN_UNUSED GWEN_DIALOG *dlg,
172 GWEN_WIDGET *w,
173 GWEN_DIALOG_PROPERTY prop,
174 int index,
175 const char *defaultValue)
176 {
177 return GWEN_Widget_GetCharProperty(w, prop, index, defaultValue);
178 }
179
180
181
Gtk2Gui_Dialog_Setup(GWEN_DIALOG * dlg,GWEN_UNUSED GtkWidget * parentWindow)182 int Gtk2Gui_Dialog_Setup(GWEN_DIALOG *dlg, GWEN_UNUSED GtkWidget *parentWindow)
183 {
184 GTK2_GUI_DIALOG *xdlg;
185 GWEN_WIDGET_TREE *wtree;
186 GWEN_WIDGET *w;
187 GtkWindow *gw;
188 int rv;
189 GList *tll;
190
191 assert(dlg);
192 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
193 assert(xdlg);
194
195 wtree=GWEN_Dialog_GetWidgets(dlg);
196 if (wtree==NULL) {
197 DBG_ERROR(GWEN_LOGDOMAIN, "No widget tree in dialog");
198 return GWEN_ERROR_NOT_FOUND;
199 }
200 w=GWEN_Widget_Tree_GetFirst(wtree);
201 if (w==NULL) {
202 DBG_ERROR(GWEN_LOGDOMAIN, "No widgets in dialog");
203 return GWEN_ERROR_NOT_FOUND;
204 }
205
206 rv=Gtk2Gui_Dialog_SetupTree(w);
207 if (rv<0) {
208 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
209 return rv;
210 }
211
212 gw=GTK_WINDOW(GWEN_Widget_GetImplData(w, GTK2_DIALOG_WIDGET_REAL));
213 gtk_window_set_type_hint(GTK_WINDOW(gw), GDK_WINDOW_TYPE_HINT_DIALOG);
214 gtk_window_set_position(GTK_WINDOW(gw), GTK_WIN_POS_CENTER_ON_PARENT);
215 /*gtk_window_set_keep_above(GTK_WINDOW(gw), TRUE);*/
216 xdlg->mainWidget=GTK_WIDGET(gw);
217
218 tll=gtk_window_list_toplevels();
219 if (tll) {
220 GList *element;
221 GtkWindow *topLevel=NULL;
222
223 for (element = tll; element; element = g_list_next(element)) {
224 GtkWindow *win = GTK_WINDOW(element->data);
225 if (gtk_window_is_active(win)) {
226 topLevel=win;
227 break;
228 }
229 }
230 g_list_free(tll);
231
232 if (topLevel) {
233 DBG_NOTICE(GWEN_LOGDOMAIN, "Found active window [%s]",
234 gtk_window_get_title(topLevel));
235 gtk_window_set_transient_for(gw, topLevel);
236 }
237 else {
238 DBG_ERROR(GWEN_LOGDOMAIN, "No active window found...");
239 }
240 }
241
242 return 0;
243 }
244
245
246
Gtk2Gui_Dialog_Leave(GWEN_DIALOG * dlg,int result)247 void Gtk2Gui_Dialog_Leave(GWEN_DIALOG *dlg, int result)
248 {
249 GTK2_GUI_DIALOG *xdlg;
250 GWEN_DIALOG *parent;
251
252 /* get toplevel dialog, the one which actually is the GUI dialog */
253 while ((parent=GWEN_Dialog_GetParentDialog(dlg)))
254 dlg=parent;
255
256 assert(dlg);
257 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
258 assert(xdlg);
259
260 xdlg->response=result;
261 if (g_main_loop_is_running(xdlg->loop))
262 g_main_loop_quit(xdlg->loop);
263 }
264
265
266
run_unmap_handler(GWEN_UNUSED GtkWindow * window,gpointer data)267 static void run_unmap_handler(GWEN_UNUSED GtkWindow *window, gpointer data)
268 {
269 GWEN_DIALOG *dlg;
270 GTK2_GUI_DIALOG *xdlg;
271
272 dlg=data;
273 assert(dlg);
274 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
275 assert(xdlg);
276
277 Gtk2Gui_Dialog_Leave(dlg, 0);
278 }
279
280
281
run_delete_handler(GWEN_UNUSED GtkWindow * window,GWEN_UNUSED GdkEventAny * event,gpointer data)282 static gint run_delete_handler(GWEN_UNUSED GtkWindow *window,
283 GWEN_UNUSED GdkEventAny *event,
284 gpointer data)
285 {
286 GWEN_DIALOG *dlg;
287 GTK2_GUI_DIALOG *xdlg;
288
289 dlg=data;
290 assert(dlg);
291 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
292 assert(xdlg);
293
294 Gtk2Gui_Dialog_Leave(dlg, 0);
295 return TRUE; /* Do not destroy */
296 }
297
298
299
run_destroy_handler(GWEN_UNUSED GtkWindow * window,gpointer data)300 static void run_destroy_handler(GWEN_UNUSED GtkWindow *window, gpointer data)
301 {
302 GWEN_DIALOG *dlg;
303 GTK2_GUI_DIALOG *xdlg;
304
305 dlg=data;
306 assert(dlg);
307 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
308 assert(xdlg);
309
310 xdlg->destroyed=1;
311 }
312
313
314
GTK2_Gui_Dialog_Run(GWEN_DIALOG * dlg,int untilEnd)315 int GTK2_Gui_Dialog_Run(GWEN_DIALOG *dlg, int untilEnd)
316 {
317 GTK2_GUI_DIALOG *xdlg;
318 GtkWidget *g;
319
320 assert(dlg);
321 xdlg=GWEN_INHERIT_GETDATA(GWEN_DIALOG, GTK2_GUI_DIALOG, dlg);
322 assert(xdlg);
323
324 g=Gtk2Gui_Dialog_GetMainWidget(dlg);
325 if (g==NULL) {
326 DBG_ERROR(GWEN_LOGDOMAIN, "No main widget");
327 Gtk2Gui_Dialog_Unextend(dlg);
328 return GWEN_ERROR_INVALID;
329 }
330
331 xdlg->unmap_handler =
332 g_signal_connect(g,
333 "unmap",
334 G_CALLBACK(run_unmap_handler),
335 dlg);
336
337 xdlg->delete_handler =
338 g_signal_connect(g,
339 "delete-event",
340 G_CALLBACK(run_delete_handler),
341 dlg);
342
343 xdlg->destroy_handler =
344 g_signal_connect(g,
345 "destroy",
346 G_CALLBACK(run_destroy_handler),
347 dlg);
348
349 xdlg->loop=g_main_loop_new(NULL, FALSE);
350 if (untilEnd)
351 g_main_loop_run(xdlg->loop);
352 else {
353 GMainContext *ctx;
354
355 ctx=g_main_loop_get_context(xdlg->loop);
356 while (g_main_context_pending(ctx))
357 g_main_context_iteration(ctx, FALSE);
358 }
359 g_main_loop_unref(xdlg->loop);
360
361 if (!xdlg->destroyed) {
362 g_signal_handler_disconnect(g, xdlg->unmap_handler);
363 g_signal_handler_disconnect(g, xdlg->delete_handler);
364 g_signal_handler_disconnect(g, xdlg->destroy_handler);
365 }
366
367 return xdlg->response;
368 }
369
370
371
Gtk2Gui_Dialog_SetupTree(GWEN_WIDGET * w)372 int Gtk2Gui_Dialog_SetupTree(GWEN_WIDGET *w)
373 {
374 int rv;
375
376 switch (GWEN_Widget_GetType(w)) {
377 case GWEN_Widget_TypeDialog:
378 rv=Gtk2Gui_WDialog_Setup(w);
379 break;
380 case GWEN_Widget_TypeLabel:
381 rv=Gtk2Gui_WLabel_Setup(w);
382 break;
383 case GWEN_Widget_TypeGridLayout:
384 rv=Gtk2Gui_WGridLayout_Setup(w);
385 break;
386 case GWEN_Widget_TypeVLayout:
387 rv=Gtk2Gui_WVLayout_Setup(w);
388 break;
389 case GWEN_Widget_TypeHLayout:
390 rv=Gtk2Gui_WHLayout_Setup(w);
391 break;
392 case GWEN_Widget_TypePushButton:
393 rv=Gtk2Gui_WPushButton_Setup(w);
394 break;
395 case GWEN_Widget_TypeLineEdit:
396 rv=Gtk2Gui_WLineEdit_Setup(w);
397 break;
398 case GWEN_Widget_TypeHLine:
399 rv=Gtk2Gui_WHLine_Setup(w);
400 break;
401 case GWEN_Widget_TypeVLine:
402 rv=Gtk2Gui_WVLine_Setup(w);
403 break;
404 case GWEN_Widget_TypeVSpacer:
405 rv=Gtk2Gui_WVSpacer_Setup(w);
406 break;
407 case GWEN_Widget_TypeHSpacer:
408 rv=Gtk2Gui_WHSpacer_Setup(w);
409 break;
410 case GWEN_Widget_TypeComboBox:
411 rv=Gtk2Gui_WComboBox_Setup(w);
412 break;
413 case GWEN_Widget_TypeTextEdit:
414 rv=Gtk2Gui_WTextEdit_Setup(w);
415 break;
416 case GWEN_Widget_TypeWidgetStack:
417 rv=Gtk2Gui_WStack_Setup(w);
418 break;
419 case GWEN_Widget_TypeTabBook:
420 rv=Gtk2Gui_WTabBook_Setup(w);
421 break;
422 case GWEN_Widget_TypeTabPage:
423 /* just re-use vbox */
424 GWEN_Widget_AddFlags(w, GWEN_WIDGET_FLAGS_FILLX | GWEN_WIDGET_FLAGS_FILLY);
425 rv=Gtk2Gui_WVLayout_Setup(w);
426 break;
427 case GWEN_Widget_TypeGroupBox:
428 rv=Gtk2Gui_WGroupBox_Setup(w);
429 break;
430 case GWEN_Widget_TypeTextBrowser:
431 rv=Gtk2Gui_WTextBrowser_Setup(w);
432 break;
433 case GWEN_Widget_TypeProgressBar:
434 rv=Gtk2Gui_WProgressBar_Setup(w);
435 break;
436 case GWEN_Widget_TypeSpinBox:
437 rv=Gtk2Gui_WSpinBox_Setup(w);
438 break;
439 case GWEN_Widget_TypeListBox:
440 rv=Gtk2Gui_WListBox_Setup(w);
441 break;
442 case GWEN_Widget_TypeCheckBox:
443 rv=Gtk2Gui_WCheckBox_Setup(w);
444 break;
445 case GWEN_Widget_TypeScrollArea:
446 rv=Gtk2Gui_WScrollArea_Setup(w);
447 break;
448 case GWEN_Widget_TypeRadioButton:
449 rv=Gtk2Gui_WRadioButton_Setup(w);
450 break;
451 default:
452 DBG_ERROR(GWEN_LOGDOMAIN, "Unhandled widget type %d", GWEN_Widget_GetType(w));
453 rv=GWEN_ERROR_INVALID;
454 break;
455 }
456
457 if (rv<0) {
458 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
459 return rv;
460 }
461 else {
462 GWEN_WIDGET *wChild;
463
464 /* handle children */
465 wChild=GWEN_Widget_Tree_GetFirstChild(w);
466 while (wChild) {
467 /* recursion */
468 rv=Gtk2Gui_Dialog_SetupTree(wChild);
469 if (rv<0) {
470 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
471 return rv;
472 }
473 wChild=GWEN_Widget_Tree_GetNext(wChild);
474 }
475 }
476
477 return 0;
478 }
479
480
481
482
Gtk2Gui_GetRawText(const char * text,GWEN_BUFFER * tbuf)483 int Gtk2Gui_GetRawText(const char *text, GWEN_BUFFER *tbuf)
484 {
485 const char *p=0;
486 const char *p2=0;
487
488 if (text==NULL)
489 return 0;
490
491 /* find begin of HTML area */
492 p=text;
493 while ((p=strchr(p, '<'))) {
494 const char *t;
495
496 t=p;
497 t++;
498 if (toupper(*t)=='H') {
499 t++;
500 if (toupper(*t)=='T') {
501 t++;
502 if (toupper(*t)=='M') {
503 t++;
504 if (toupper(*t)=='L') {
505 t++;
506 if (toupper(*t)=='>') {
507 break;
508 }
509 }
510 }
511 }
512 }
513 p++;
514 } /* while */
515
516 /* find end of HTML area */
517 if (p) {
518 p2=p;
519 p2+=6; /* skip "<html>" */
520 while ((p2=strchr(p2, '<'))) {
521 const char *t;
522
523 t=p2;
524 t++;
525 if (toupper(*t)=='/') {
526 t++;
527 if (toupper(*t)=='H') {
528 t++;
529 if (toupper(*t)=='T') {
530 t++;
531 if (toupper(*t)=='M') {
532 t++;
533 if (toupper(*t)=='L') {
534 t++;
535 if (toupper(*t)=='>') {
536 break;
537 }
538 }
539 }
540 }
541 }
542 }
543 p2++;
544 } /* while */
545 }
546
547 if (p && p2) {
548 int startPos;
549 /*int endPos;*/
550
551 p2+=7; /* skip "</html>" */
552
553 startPos=(p-text);
554 /*endPos=(p2-text);*/
555
556 /* append stuff before startPos */
557 if (startPos)
558 GWEN_Buffer_AppendBytes(tbuf, text, startPos);
559 if (*p2)
560 GWEN_Buffer_AppendString(tbuf, p2);
561 return 0;
562 }
563 else {
564 GWEN_Buffer_AppendString(tbuf, text);
565 return 0;
566 }
567 }
568
569
570