1 /* 2 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com> 3 * Copyright (C) 2011 - 2012 Vivien Malerba <malerba@gnome-db.org> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 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 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 */ 19 20 #include <glib/gi18n-lib.h> 21 #include <string.h> 22 #include "filter-editor.h" 23 #include <libgda-ui/gdaui-combo.h> 24 #include <libgda-ui/gdaui-data-selector.h> 25 26 struct _FilterEditorPrivate { 27 BrowserConnection *bcnc; 28 GtkWidget *base_dn; 29 GtkWidget *filter; 30 GtkWidget *attributes; 31 GtkWidget *scope; 32 33 GdaLdapSearchScope default_scope; 34 }; 35 36 static void filter_editor_class_init (FilterEditorClass *klass); 37 static void filter_editor_init (FilterEditor *feditor, FilterEditorClass *klass); 38 static void filter_editor_dispose (GObject *object); 39 40 static GObjectClass *parent_class = NULL; 41 42 /* signals */ 43 enum { 44 ACTIVATE, 45 LAST_SIGNAL 46 }; 47 48 gint filter_editor_signals [LAST_SIGNAL] = { 0 }; 49 50 /* 51 * FilterEditor class implementation 52 */ 53 54 static void 55 filter_editor_class_init (FilterEditorClass *klass) 56 { 57 GObjectClass *object_class = G_OBJECT_CLASS (klass); 58 59 parent_class = g_type_class_peek_parent (klass); 60 61 filter_editor_signals [ACTIVATE] = 62 g_signal_new ("activate", 63 G_TYPE_FROM_CLASS (object_class), 64 G_SIGNAL_RUN_FIRST, 65 G_STRUCT_OFFSET (FilterEditorClass, activate), 66 NULL, NULL, 67 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); 68 klass->activate = NULL; 69 object_class->dispose = filter_editor_dispose; 70 } 71 72 static void 73 filter_editor_init (FilterEditor *feditor, G_GNUC_UNUSED FilterEditorClass *klass) 74 { 75 feditor->priv = g_new0 (FilterEditorPrivate, 1); 76 feditor->priv->bcnc = NULL; 77 feditor->priv->default_scope = GDA_LDAP_SEARCH_SUBTREE; 78 79 gtk_orientable_set_orientation (GTK_ORIENTABLE (feditor), GTK_ORIENTATION_VERTICAL); 80 } 81 82 static void 83 filter_editor_dispose (GObject *object) 84 { 85 FilterEditor *feditor = (FilterEditor *) object; 86 87 /* free memory */ 88 if (feditor->priv) { 89 if (feditor->priv->bcnc) 90 g_object_unref (feditor->priv->bcnc); 91 g_free (feditor->priv); 92 feditor->priv = NULL; 93 } 94 95 parent_class->dispose (object); 96 } 97 98 GType 99 filter_editor_get_type (void) 100 { 101 static GType type = 0; 102 103 if (G_UNLIKELY (type == 0)) { 104 static const GTypeInfo info = { 105 sizeof (FilterEditorClass), 106 (GBaseInitFunc) NULL, 107 (GBaseFinalizeFunc) NULL, 108 (GClassInitFunc) filter_editor_class_init, 109 NULL, 110 NULL, 111 sizeof (FilterEditor), 112 0, 113 (GInstanceInitFunc) filter_editor_init, 114 0 115 }; 116 117 type = g_type_register_static (GTK_TYPE_BOX, "FilterEditor", &info, 0); 118 } 119 return type; 120 } 121 122 static void 123 activated_cb (G_GNUC_UNUSED GtkEntry *entry, FilterEditor *feditor) 124 { 125 g_signal_emit (feditor, filter_editor_signals [ACTIVATE], 0); 126 } 127 128 /** 129 * filter_editor_new: 130 * 131 * Returns: a new #GtkWidget 132 */ 133 GtkWidget * 134 filter_editor_new (BrowserConnection *bcnc) 135 { 136 FilterEditor *feditor; 137 GtkWidget *grid, *label, *entry; 138 GdaDataModel *model; 139 GList *values; 140 GValue *v1, *v2; 141 gfloat ya; 142 143 g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL); 144 145 feditor = FILTER_EDITOR (g_object_new (FILTER_EDITOR_TYPE, NULL)); 146 feditor->priv->bcnc = g_object_ref ((GObject*) bcnc); 147 148 grid = gtk_grid_new (); 149 gtk_grid_set_column_spacing (GTK_GRID (grid), 5); 150 gtk_box_pack_start (GTK_BOX (feditor), grid, TRUE, TRUE, 0); 151 152 label = gtk_label_new (_("Base DN:")); 153 gtk_misc_get_alignment (GTK_MISC (label), NULL, &ya); 154 gtk_misc_set_alignment (GTK_MISC (label), 0., ya); 155 gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1); 156 label = gtk_label_new (_("Filter expression:")); 157 gtk_misc_get_alignment (GTK_MISC (label), NULL, &ya); 158 gtk_misc_set_alignment (GTK_MISC (label), 0., ya); 159 gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1); 160 label = gtk_label_new (_("Attributes to fetch:")); 161 gtk_misc_get_alignment (GTK_MISC (label), NULL, &ya); 162 gtk_misc_set_alignment (GTK_MISC (label), 0., ya); 163 gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1); 164 label = gtk_label_new (_("Search scope:")); 165 gtk_misc_get_alignment (GTK_MISC (label), NULL, &ya); 166 gtk_misc_set_alignment (GTK_MISC (label), 0., ya); 167 gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1); 168 169 entry = gtk_entry_new (); 170 gtk_grid_attach (GTK_GRID (grid), entry, 1, 0, 1, 1); 171 feditor->priv->base_dn = entry; 172 g_signal_connect (entry, "activate", 173 G_CALLBACK (activated_cb), feditor); 174 175 entry = gtk_entry_new (); 176 gtk_grid_attach (GTK_GRID (grid), entry, 1, 1, 1, 1); 177 feditor->priv->filter = entry; 178 g_signal_connect (entry, "activate", 179 G_CALLBACK (activated_cb), feditor); 180 181 entry = gtk_entry_new (); 182 gtk_grid_attach (GTK_GRID (grid), entry, 1, 2, 1, 1); 183 feditor->priv->attributes = entry; 184 g_signal_connect (entry, "activate", 185 G_CALLBACK (activated_cb), feditor); 186 187 model = gda_data_model_array_new_with_g_types (2, G_TYPE_INT, G_TYPE_STRING); 188 g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), "Base (search the base DN only)"); 189 values = g_list_prepend (NULL, v1); 190 g_value_set_int ((v2 = gda_value_new (G_TYPE_INT)), GDA_LDAP_SEARCH_BASE); 191 values = g_list_prepend (values, v2); 192 g_assert (gda_data_model_append_values (model, values, NULL) >= 0); 193 gda_value_free (v1); 194 gda_value_free (v2); 195 196 g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), "Onelevel (search immediate children of base DN only)"); 197 values = g_list_prepend (NULL, v1); 198 g_value_set_int ((v2 = gda_value_new (G_TYPE_INT)), GDA_LDAP_SEARCH_ONELEVEL); 199 values = g_list_prepend (values, v2); 200 g_assert (gda_data_model_append_values (model, values, NULL) >= 0); 201 gda_value_free (v1); 202 gda_value_free (v2); 203 204 g_value_set_string ((v1 = gda_value_new (G_TYPE_STRING)), "Subtree (search of the base DN and the entire subtree below)"); 205 values = g_list_prepend (NULL, v1); 206 g_value_set_int ((v2 = gda_value_new (G_TYPE_INT)), GDA_LDAP_SEARCH_SUBTREE); 207 values = g_list_prepend (values, v2); 208 g_assert (gda_data_model_append_values (model, values, NULL) >= 0); 209 gda_value_free (v1); 210 gda_value_free (v2); 211 212 gint cols[] = {1}; 213 entry = gdaui_combo_new_with_model (model, 1, cols); 214 g_object_unref (model); 215 gtk_grid_attach (GTK_GRID (grid), entry, 1, 3, 1, 1); 216 feditor->priv->scope = entry; 217 filter_editor_clear (feditor); 218 219 gtk_widget_show_all (grid); 220 return (GtkWidget*) feditor; 221 } 222 223 /** 224 * filter_editor_clear: 225 */ 226 void 227 filter_editor_clear (FilterEditor *fedit) 228 { 229 g_return_if_fail (IS_FILTER_EDITOR (fedit)); 230 filter_editor_set_settings (fedit, NULL, NULL, NULL, fedit->priv->default_scope); 231 } 232 233 /** 234 * filter_editor_set_settings: 235 */ 236 void 237 filter_editor_set_settings (FilterEditor *fedit, 238 const gchar *base_dn, const gchar *filter, 239 const gchar *attributes, GdaLdapSearchScope scope) 240 { 241 g_return_if_fail (IS_FILTER_EDITOR (fedit)); 242 243 gtk_entry_set_text (GTK_ENTRY (fedit->priv->base_dn), base_dn ? base_dn : ""); 244 gtk_entry_set_text (GTK_ENTRY (fedit->priv->filter), filter ? filter : "(cn=*)"); 245 gtk_entry_set_text (GTK_ENTRY (fedit->priv->attributes), attributes ? attributes : "cn"); 246 gdaui_data_selector_select_row (GDAUI_DATA_SELECTOR (fedit->priv->scope), scope - 1); 247 } 248 249 /** 250 * filter_editor_get_settings: 251 */ 252 void 253 filter_editor_get_settings (FilterEditor *fedit, 254 gchar **out_base_dn, gchar **out_filter, 255 gchar **out_attributes, GdaLdapSearchScope *out_scope) 256 { 257 const gchar *tmp; 258 g_return_if_fail (IS_FILTER_EDITOR (fedit)); 259 if (out_base_dn) { 260 tmp = gtk_entry_get_text (GTK_ENTRY (fedit->priv->base_dn)); 261 *out_base_dn = tmp && *tmp ? g_strdup (tmp) : NULL; 262 } 263 if (out_filter) { 264 tmp = gtk_entry_get_text (GTK_ENTRY (fedit->priv->filter)); 265 if (tmp && *tmp) { 266 /* add surrounding parenthesis if not yet there */ 267 if (*tmp != '(') { 268 gint len; 269 len = strlen (tmp); 270 if (tmp [len-1] != ')') 271 *out_filter = g_strdup_printf ("(%s)", tmp); 272 else 273 *out_filter = g_strdup (tmp);/* may result in an error when executed */ 274 } 275 else 276 *out_filter = g_strdup (tmp); 277 278 } 279 else 280 *out_filter = NULL; 281 } 282 if (out_attributes) { 283 tmp = gtk_entry_get_text (GTK_ENTRY (fedit->priv->attributes)); 284 *out_attributes = tmp && *tmp ? g_strdup (tmp) : NULL; 285 } 286 if (out_scope) 287 *out_scope = gtk_combo_box_get_active (GTK_COMBO_BOX (fedit->priv->scope)) + 1; 288 } 289