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