gwenhywfar  4.3.3
w_listbox.c
Go to the documentation of this file.
00001 /***************************************************************************
00002     begin       : Fri Jul 09 2010
00003     copyright   : (C) 2010 by Martin Preuss
00004     email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *          Please see toplevel file COPYING for license details           *
00008  ***************************************************************************/
00009 
00010 
00011 #define W_LISTBOX_MAX_TYPES 256
00012 
00013 
00014 
00015 static GWENHYWFAR_CB
00016 int Gtk2Gui_WListBox_SetIntProperty(GWEN_WIDGET *w,
00017                                     GWEN_DIALOG_PROPERTY prop,
00018                                     int index,
00019                                     int value,
00020                                     int doSignal) {
00021   GtkWidget *g;
00022 
00023   g=GTK_WIDGET(GWEN_Widget_GetImplData(w, GTK2_DIALOG_WIDGET_CONTENT));
00024   assert(g);
00025 
00026   switch(prop) {
00027   case GWEN_DialogProperty_Enabled:
00028     gtk_widget_set_sensitive(GTK_WIDGET(g), (value==0)?FALSE:TRUE);
00029     return 0;
00030   
00031   case GWEN_DialogProperty_Focus:
00032     gtk_widget_grab_focus(GTK_WIDGET(g));
00033     return 0;
00034 
00035   case GWEN_DialogProperty_Value: {
00036     GtkTreePath *path;
00037 
00038     path=gtk_tree_path_new_from_indices(value, -1);
00039     gtk_tree_view_set_cursor(GTK_TREE_VIEW(g), path, NULL, FALSE);
00040     gtk_tree_path_free(path);
00041     return 0;
00042   }
00043 
00044   case GWEN_DialogProperty_SelectionMode: {
00045     GtkTreeSelection *sel;
00046 
00047     sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(g));
00048     if (sel) {
00049       switch(value) {
00050       case GWEN_Dialog_SelectionMode_None:
00051         gtk_tree_selection_set_mode(sel, GTK_SELECTION_NONE);
00052         return 0;
00053       case GWEN_Dialog_SelectionMode_Single:
00054         gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
00055         return 0;
00056       case GWEN_Dialog_SelectionMode_Multi:
00057         gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
00058         return 0;
00059       }
00060       DBG_ERROR(GWEN_LOGDOMAIN, "Unknown SelectionMode %d", value);
00061       return GWEN_ERROR_INVALID;
00062     }
00063     break;
00064   }
00065 
00066   case GWEN_DialogProperty_ColumnWidth: {
00067     GtkTreeViewColumn *col;
00068 
00069     col=gtk_tree_view_get_column(GTK_TREE_VIEW(g), index);
00070     if (col) {
00071       gtk_tree_view_column_set_fixed_width(col, value);
00072       return 0;
00073     }
00074 
00075     /* no width */
00076     return GWEN_ERROR_INVALID;
00077   }
00078 
00079   case GWEN_DialogProperty_SortDirection: {
00080     GtkTreeViewColumn *col;
00081     int i;
00082     int cols;
00083 
00084     /* remove sort indicator from all columns */
00085     cols=GWEN_Widget_GetColumns(w);
00086     for (i=0; i<cols; i++) {
00087       col=gtk_tree_view_get_column(GTK_TREE_VIEW(g), index);
00088       if (col) {
00089         if (gtk_tree_view_column_get_sort_indicator(col)==TRUE)
00090           gtk_tree_view_column_set_sort_indicator(col, FALSE);
00091       }
00092     }
00093 
00094     if (value!=GWEN_DialogSortDirection_None) {
00095       /* set sort indicator on given column */
00096       col=gtk_tree_view_get_column(GTK_TREE_VIEW(g), index);
00097       if (col) {
00098         switch(value) {
00099         case GWEN_DialogSortDirection_Up:
00100           gtk_tree_view_column_set_sort_order(col, GTK_SORT_ASCENDING);
00101           break;
00102         case GWEN_DialogSortDirection_Down:
00103           gtk_tree_view_column_set_sort_order(col, GTK_SORT_DESCENDING);
00104           break;
00105         default:
00106           break;
00107         }
00108       }
00109     }
00110 
00111     return 0;
00112   }
00113 
00114   case GWEN_DialogProperty_ClearValues: {
00115     GtkListStore *sto;
00116 
00117     sto=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(g)));
00118     if (sto)
00119       gtk_list_store_clear(sto);
00120     return 0;
00121   }
00122 
00123   case GWEN_DialogProperty_Sort:
00124     /* NOOP, we use auto-sorting for now (TODO: figure out how to manually sort) */
00125     return 0;
00126 
00127   default:
00128     break;
00129   }
00130 
00131   DBG_WARN(GWEN_LOGDOMAIN,
00132            "Function is not appropriate for this type of widget (%s)",
00133            GWEN_Widget_Type_toString(GWEN_Widget_GetType(w)));
00134   return GWEN_ERROR_INVALID;
00135 }
00136 
00137 
00138 
00139 
00140 static GWENHYWFAR_CB
00141 int Gtk2Gui_WListBox_GetIntProperty(GWEN_WIDGET *w,
00142                                      GWEN_DIALOG_PROPERTY prop,
00143                                      int index,
00144                                      int defaultValue) {
00145   GtkWidget *g;
00146 
00147   g=GTK_WIDGET(GWEN_Widget_GetImplData(w, GTK2_DIALOG_WIDGET_CONTENT));
00148   assert(g);
00149 
00150   switch(prop) {
00151   case GWEN_DialogProperty_Enabled:
00152     return (gtk_widget_get_sensitive(GTK_WIDGET(g))==TRUE)?1:0;
00153 
00154   case GWEN_DialogProperty_Focus:
00155     return (gtk_widget_has_focus(GTK_WIDGET(g))==TRUE)?1:0;
00156     return 0;
00157 
00158   case GWEN_DialogProperty_Value: {
00159     GtkTreePath *path=NULL;
00160 
00161     gtk_tree_view_get_cursor(GTK_TREE_VIEW(g), &path, NULL);
00162     if (path!=NULL) {
00163       gint *idxlist;
00164 
00165       idxlist=gtk_tree_path_get_indices(path);
00166       if (idxlist!=NULL) {
00167         int res;
00168 
00169         res=idxlist[0];
00170         gtk_tree_path_free(path);
00171         return res;
00172       }
00173       gtk_tree_path_free(path);
00174     }
00175 
00176     /* no cursor */
00177     return -1;
00178   }
00179 
00180   case GWEN_DialogProperty_ColumnWidth: {
00181     GtkTreeViewColumn *col;
00182 
00183     col=gtk_tree_view_get_column(GTK_TREE_VIEW(g), index);
00184     if (col)
00185       return gtk_tree_view_column_get_width(col);
00186 
00187     /* no width */
00188     return -1;
00189   }
00190 
00191   case GWEN_DialogProperty_SortDirection: {
00192     GtkTreeViewColumn *col;
00193 
00194     col=gtk_tree_view_get_column(GTK_TREE_VIEW(g), index);
00195     if (col) {
00196       if (gtk_tree_view_column_get_sort_indicator(col)==TRUE) {
00197         switch(gtk_tree_view_column_get_sort_order(col)) {
00198         case GTK_SORT_ASCENDING:
00199           return GWEN_DialogSortDirection_Up;
00200         case GTK_SORT_DESCENDING:
00201           return GWEN_DialogSortDirection_Down;
00202         default:
00203           break;
00204         }
00205       }
00206       /*break; <- this is wrong here, isn't it? */
00207     }
00208 
00209     return GWEN_DialogSortDirection_None;
00210   }
00211 
00212   default:
00213     break;
00214   }
00215 
00216   DBG_WARN(GWEN_LOGDOMAIN,
00217            "Function %d is not appropriate for this type of widget (%s)",
00218            prop,
00219            GWEN_Widget_Type_toString(GWEN_Widget_GetType(w)));
00220   return defaultValue;
00221 }
00222 
00223 
00224 
00225 static GWENHYWFAR_CB
00226 int Gtk2Gui_WListBox_SetCharProperty(GWEN_WIDGET *w,
00227                                      GWEN_DIALOG_PROPERTY prop,
00228                                      int index,
00229                                      const char *value,
00230                                      int doSignal) {
00231   GtkWidget *g;
00232 
00233   g=GTK_WIDGET(GWEN_Widget_GetImplData(w, GTK2_DIALOG_WIDGET_CONTENT));
00234   assert(g);
00235 
00236   switch(prop) {
00237   case GWEN_DialogProperty_Title: {
00238     int cols=0;
00239     if (value && *value) {
00240       int i;
00241       int l;
00242 
00243       l=strlen(value);
00244       cols=1;
00245       for (i=0; i<l; i++) {
00246         if (value[i]=='\t')
00247           cols++;
00248       }
00249     }
00250 
00251     if (cols) {
00252       GType types[W_LISTBOX_MAX_TYPES];
00253       GtkListStore *sto;
00254       int i;
00255       const char *s;
00256       GtkTreeViewColumn *col;
00257       char *vcopy;
00258       char *p;
00259 
00260       if (cols>W_LISTBOX_MAX_TYPES)
00261         cols=W_LISTBOX_MAX_TYPES;
00262       for (i=0; i<cols; i++)
00263         types[i]=G_TYPE_STRING;
00264       sto=gtk_list_store_newv(cols, types);
00265       s=value;
00266 
00267       /* clear current headers in tree view */
00268       while( (col=gtk_tree_view_get_column(GTK_TREE_VIEW(g), 0)) )
00269         gtk_tree_view_remove_column(GTK_TREE_VIEW(g), col);
00270 
00271       /* set new model */
00272       gtk_tree_view_set_model(GTK_TREE_VIEW(g), GTK_TREE_MODEL(sto));
00273 
00274       /* insert new headers */
00275       i=0;
00276       vcopy=strdup(value);
00277       p=vcopy;
00278       while(*p && i<cols) {
00279         char *pT;
00280         GtkCellRenderer *renderer;
00281 
00282         pT=strchr(p, '\t');
00283         if (pT)
00284           *pT=0;
00285 
00286         renderer=gtk_cell_renderer_text_new();
00287         col=gtk_tree_view_column_new();
00288         gtk_tree_view_column_set_title(col, p);
00289         gtk_tree_view_column_pack_start(col, renderer, TRUE);
00290         gtk_tree_view_column_set_sort_column_id(col, i);
00291         gtk_tree_view_column_set_resizable(col, TRUE);
00292         gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
00293         gtk_tree_view_column_set_attributes(col, renderer, "text", i, NULL);
00294 
00295         gtk_tree_view_append_column(GTK_TREE_VIEW(g), col);
00296 
00297         if (pT)
00298           p=pT+1;
00299         else
00300           /* no more tab, all columns done */
00301           break;
00302         i++;
00303       }
00304       free(vcopy);
00305       GWEN_Widget_SetColumns(w, cols);
00306       gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(g), TRUE);
00307     }
00308     else {
00309       DBG_ERROR(GWEN_LOGDOMAIN, "No columns (empty title)");
00310       return GWEN_ERROR_INVALID;
00311     }
00312 
00313     return 0;
00314   }
00315 
00316   case GWEN_DialogProperty_ClearValues: {
00317     GtkListStore *sto;
00318 
00319     sto=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(g)));
00320     if (sto)
00321       gtk_list_store_clear(sto);
00322     return 0;
00323   }
00324 
00325   case GWEN_DialogProperty_AddValue: {
00326     GtkListStore *sto;
00327 
00328     sto=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(g)));
00329     if (sto) {
00330       GtkTreeIter iter;
00331       int cols;
00332       int i;
00333       char *vcopy;
00334       char *p;
00335 
00336       cols=GWEN_Widget_GetColumns(w);
00337 
00338       vcopy=strdup(value);
00339       p=vcopy;
00340       i=0;
00341       gtk_list_store_append(sto, &iter);
00342       while(*p && i<cols) {
00343         char *pT;
00344         GValue val={0};
00345 
00346         g_value_init(&val, G_TYPE_STRING);
00347 
00348         pT=strchr(p, '\t');
00349         if (pT)
00350           *pT=0;
00351         g_value_set_string(&val, p);
00352         gtk_list_store_set_value(sto, &iter, i, &val);
00353         g_value_unset(&val);
00354 
00355         if (pT)
00356           p=pT+1;
00357         else
00358           /* no more tabs, all columns done */
00359           break;
00360         i++;
00361       }
00362       free(vcopy);
00363     }
00364 
00365     return 0;
00366   }
00367 
00368   default:
00369     break;
00370   }
00371 
00372   DBG_WARN(GWEN_LOGDOMAIN,
00373            "Function is not appropriate for this type of widget (%s)",
00374            GWEN_Widget_Type_toString(GWEN_Widget_GetType(w)));
00375   return GWEN_ERROR_INVALID;
00376 }
00377 
00378 
00379 
00380 static GWENHYWFAR_CB
00381 const char* Gtk2Gui_WListBox_GetCharProperty(GWEN_WIDGET *w,
00382                                              GWEN_DIALOG_PROPERTY prop,
00383                                              int index,
00384                                              const char *defaultValue) {
00385   GtkWidget *g;
00386 
00387   g=GTK_WIDGET(GWEN_Widget_GetImplData(w, GTK2_DIALOG_WIDGET_CONTENT));
00388   assert(g);
00389 
00390   switch(prop) {
00391   case GWEN_DialogProperty_Title: {
00392     GList *cols;
00393 
00394     cols=gtk_tree_view_get_columns(GTK_TREE_VIEW(g));
00395     if (cols) {
00396       GList *le;
00397       GWEN_BUFFER *tbuf;
00398       int cnt=0;
00399 
00400       tbuf=GWEN_Buffer_new(0, 256, 0, 1);
00401       le=g_list_first(cols);
00402       while(le) {
00403         const gchar *s;
00404 
00405         if (cnt)
00406           GWEN_Buffer_AppendByte(tbuf, '\t');
00407         s=gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(le->data));
00408         if (s && *s)
00409           GWEN_Buffer_AppendString(tbuf, s);
00410         cnt++;
00411         le=g_list_next(le);
00412       } /* while */
00413       GWEN_Widget_SetText(w, GTK2_DIALOG_STRING_TITLE, GWEN_Buffer_GetStart(tbuf));
00414       GWEN_Buffer_free(tbuf);
00415 
00416       g_list_free(cols);
00417       return GWEN_Widget_GetText(w, GTK2_DIALOG_STRING_TITLE);
00418     }
00419     return defaultValue;
00420   }
00421 
00422   case GWEN_DialogProperty_Value: {
00423     GtkTreePath *path;
00424 
00425     path=gtk_tree_path_new_from_indices(index, -1);
00426     if (path!=NULL) {
00427       GtkListStore *sto;
00428       GtkTreeIter iter;
00429 
00430       sto=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(g)));
00431       if (gtk_tree_model_get_iter(GTK_TREE_MODEL(sto), &iter, path)) {
00432         GList *cols;
00433 
00434         cols=gtk_tree_view_get_columns(GTK_TREE_VIEW(g));
00435         if (cols) {
00436           GList *le;
00437           GWEN_BUFFER *tbuf;
00438           int cnt=0;
00439 
00440           tbuf=GWEN_Buffer_new(0, 256, 0, 1);
00441           le=g_list_first(cols);
00442           while(le) {
00443             gchar *s;
00444 
00445             if (cnt)
00446               GWEN_Buffer_AppendByte(tbuf, '\t');
00447             gtk_tree_model_get(GTK_TREE_MODEL(sto), &iter, cnt, &s, -1, NULL);
00448             if (s) {
00449               GWEN_Buffer_AppendString(tbuf, s);
00450               g_free(s);
00451             }
00452             cnt++;
00453             le=g_list_next(le);
00454           } /* while */
00455           GWEN_Widget_SetText(w, GTK2_DIALOG_STRING_VALUE, GWEN_Buffer_GetStart(tbuf));
00456           GWEN_Buffer_free(tbuf);
00457 
00458           g_list_free(cols);
00459           return GWEN_Widget_GetText(w, GTK2_DIALOG_STRING_VALUE);
00460         }
00461       }
00462 
00463       gtk_tree_path_free(path);
00464     }
00465     return defaultValue;
00466   }
00467 
00468   default:
00469     break;
00470   }
00471 
00472   DBG_WARN(GWEN_LOGDOMAIN,
00473            "Function is not appropriate for this type of widget (%s)",
00474            GWEN_Widget_Type_toString(GWEN_Widget_GetType(w)));
00475   return defaultValue;
00476 }
00477 
00478 
00479 
00480 static void Gtk2Gui_WListBox_CursorChanged_handler(GtkTreeView *g, gpointer data) {
00481   GWEN_WIDGET *w;
00482   int rv;
00483 
00484   w=data;
00485   assert(w);
00486   rv=GWEN_Dialog_EmitSignal(GWEN_Widget_GetDialog(w),
00487                             GWEN_DialogEvent_TypeActivated,
00488                             GWEN_Widget_GetName(w));
00489   if (rv==GWEN_DialogEvent_ResultAccept)
00490     Gtk2Gui_Dialog_Leave(GWEN_Widget_GetTopDialog(w), 1);
00491   else if (rv==GWEN_DialogEvent_ResultReject)
00492     Gtk2Gui_Dialog_Leave(GWEN_Widget_GetTopDialog(w), 0);
00493 }
00494 
00495 
00496 
00497 int Gtk2Gui_WListBox_Setup(GWEN_WIDGET *w) {
00498   GtkWidget *g;
00499   GtkWidget *gScroll;
00500   uint32_t flags;
00501   GWEN_WIDGET *wParent;
00502   gulong changed_handler_id;
00503 
00504   flags=GWEN_Widget_GetFlags(w);
00505   wParent=GWEN_Widget_Tree_GetParent(w);
00506 
00507   gScroll=gtk_scrolled_window_new(NULL, NULL);
00508   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gScroll),
00509                                  GTK_POLICY_AUTOMATIC,
00510                                  GTK_POLICY_AUTOMATIC);
00511   g=gtk_tree_view_new();
00512   gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(g), TRUE);
00513   gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(g), TRUE);
00514   gtk_container_add(GTK_CONTAINER(gScroll), GTK_WIDGET(g));
00515 
00516   GWEN_Widget_SetImplData(w, GTK2_DIALOG_WIDGET_REAL, (void*) gScroll);
00517   GWEN_Widget_SetImplData(w, GTK2_DIALOG_WIDGET_CONTENT, (void*) g);
00518 
00519   GWEN_Widget_SetSetIntPropertyFn(w, Gtk2Gui_WListBox_SetIntProperty);
00520   GWEN_Widget_SetGetIntPropertyFn(w, Gtk2Gui_WListBox_GetIntProperty);
00521   GWEN_Widget_SetSetCharPropertyFn(w, Gtk2Gui_WListBox_SetCharProperty);
00522   GWEN_Widget_SetGetCharPropertyFn(w, Gtk2Gui_WListBox_GetCharProperty);
00523 
00524   changed_handler_id=g_signal_connect(g,
00525                                       "cursor-changed",
00526                                       G_CALLBACK (Gtk2Gui_WListBox_CursorChanged_handler),
00527                                       w);
00528 
00529   if (wParent)
00530     GWEN_Widget_AddChildGuiWidget(wParent, w);
00531 
00532   return 0;
00533 }
00534 
00535