1 /*
2 * Copyright (C) 2010 - 2011 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include <string.h>
22 #include "gdaui-entry-rt.h"
23 #include <libgda-ui/gdaui-rt-editor.h>
24 #include <libgda/gda-data-handler.h>
25 #include <libgda/gda-blob-op.h>
26
27 /*
28 * Main static functions
29 */
30 static void gdaui_entry_rt_class_init (GdauiEntryRtClass * class);
31 static void gdaui_entry_rt_init (GdauiEntryRt * srv);
32 static void gdaui_entry_rt_dispose (GObject * object);
33 static void gdaui_entry_rt_finalize (GObject * object);
34
file_load_cb(GtkWidget * button,BinMenu * menu)35 /* virtual functions */
36 static GtkWidget *create_entry (GdauiEntryWrapper *mgwrap);
37 static void real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value);
38 static GValue *real_get_value (GdauiEntryWrapper *mgwrap);
39 static void connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb);
40 static void set_editable (GdauiEntryWrapper *mgwrap, gboolean editable);
41
42 /* get a pointer to the parents to be able to call their destructor */
43 static GObjectClass *parent_class = NULL;
44
45 /* private structure */
46 struct _GdauiEntryRtPrivate
47 {
48 GtkWidget *view;
49 };
50
51
52 GType
53 gdaui_entry_rt_get_type (void)
54 {
55 static GType type = 0;
56
57 if (G_UNLIKELY (type == 0)) {
58 static const GTypeInfo info = {
59 sizeof (GdauiEntryRtClass),
60 (GBaseInitFunc) NULL,
61 (GBaseFinalizeFunc) NULL,
62 (GClassInitFunc) gdaui_entry_rt_class_init,
63 NULL,
64 NULL,
65 sizeof (GdauiEntryRt),
66 0,
67 (GInstanceInitFunc) gdaui_entry_rt_init,
68 0
69 };
70
71 type = g_type_register_static (GDAUI_TYPE_ENTRY_WRAPPER, "GdauiEntryRt", &info, 0);
72 }
73 return type;
74 }
75
76 static void
77 gdaui_entry_rt_class_init (GdauiEntryRtClass * class)
78 {
79 GObjectClass *object_class = G_OBJECT_CLASS (class);
80
81 parent_class = g_type_class_peek_parent (class);
82
83 object_class->dispose = gdaui_entry_rt_dispose;
84 object_class->finalize = gdaui_entry_rt_finalize;
85
86 GDAUI_ENTRY_WRAPPER_CLASS (class)->create_entry = create_entry;
87 GDAUI_ENTRY_WRAPPER_CLASS (class)->real_set_value = real_set_value;
88 GDAUI_ENTRY_WRAPPER_CLASS (class)->real_get_value = real_get_value;
89 GDAUI_ENTRY_WRAPPER_CLASS (class)->connect_signals = connect_signals;
90 GDAUI_ENTRY_WRAPPER_CLASS (class)->set_editable = set_editable;
91 }
92
93 static void
94 gdaui_entry_rt_init (GdauiEntryRt *gdaui_entry_rt)
95 {
96 gdaui_entry_rt->priv = g_new0 (GdauiEntryRtPrivate, 1);
97 gdaui_entry_rt->priv->view = NULL;
98 gtk_widget_set_vexpand (GTK_WIDGET (gdaui_entry_rt), TRUE);
99 }
100
101 /**
102 * gdaui_entry_rt_new
103 * @dh: the data handler to be used by the new widget
104 * @type: the requested data type (compatible with @dh)
file_save_cb(GtkWidget * button,BinMenu * menu)105 * @options: the options
106 *
107 * Creates a new widget which is mainly a GtkEntry
108 *
109 * Returns: the new widget
110 */
111 GtkWidget *
112 gdaui_entry_rt_new (GdaDataHandler *dh, GType type, G_GNUC_UNUSED const gchar *options)
113 {
114 GObject *obj;
115
116 g_return_val_if_fail (dh && GDA_IS_DATA_HANDLER (dh), NULL);
117 g_return_val_if_fail (gda_data_handler_accepts_g_type (dh, type), NULL);
118
119 obj = g_object_new (GDAUI_TYPE_ENTRY_RT, "handler", dh, NULL);
120 gdaui_data_entry_set_value_type (GDAUI_DATA_ENTRY (obj), type);
121
122 return GTK_WIDGET (obj);
123 }
124
125
126 static void
127 gdaui_entry_rt_dispose (GObject * object)
128 {
129 GdauiEntryRt *gdaui_entry_rt;
130
131 g_return_if_fail (object != NULL);
132 g_return_if_fail (GDAUI_IS_ENTRY_RT (object));
133
134 gdaui_entry_rt = GDAUI_ENTRY_RT (object);
135 if (gdaui_entry_rt->priv) {
136 }
137
138 /* parent class */
139 parent_class->dispose (object);
140 }
141
142 static void
143 gdaui_entry_rt_finalize (GObject * object)
144 {
145 GdauiEntryRt *gdaui_entry_rt;
146
147 g_return_if_fail (object != NULL);
148 g_return_if_fail (GDAUI_IS_ENTRY_RT (object));
149
150 gdaui_entry_rt = GDAUI_ENTRY_RT (object);
151 if (gdaui_entry_rt->priv) {
152 g_free (gdaui_entry_rt->priv);
153 gdaui_entry_rt->priv = NULL;
154 }
155
156 /* parent class */
157 parent_class->finalize (object);
158 }
159
160 static GtkWidget *
161 create_entry (GdauiEntryWrapper *mgwrap)
162 {
163 GdauiEntryRt *mgtxt;
164
165 g_return_val_if_fail (mgwrap && GDAUI_IS_ENTRY_RT (mgwrap), NULL);
166 mgtxt = GDAUI_ENTRY_RT (mgwrap);
167 g_return_val_if_fail (mgtxt->priv, NULL);
168
169 mgtxt->priv->view = gdaui_rt_editor_new ();
170
171 return mgtxt->priv->view;
172 }
173
174 static void
175 real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
176 {
177 GdauiEntryRt *mgtxt;
178
common_bin_create_menu(BinMenu * binmenu,PopupContainerPositionFunc pos_func,GType entry_type,BinCallback loaded_value_cb,gpointer loaded_value_cb_data)179 g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_RT (mgwrap));
180 mgtxt = GDAUI_ENTRY_RT (mgwrap);
181 g_return_if_fail (mgtxt->priv);
182
183 gdaui_rt_editor_set_contents (GDAUI_RT_EDITOR (mgtxt->priv->view), "", -1);
184 if (value) {
185 if (! gda_value_is_null ((GValue *) value)) {
186 GdaDataHandler *dh;
187 gchar *str;
188 gboolean done = FALSE;
189
190 if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB) {
191 const GdaBlob *blob;
192 GdaBinary *bin;
193 blob = gda_value_get_blob (value);
194 bin = (GdaBinary *) blob;
195 if (blob->op &&
196 (bin->binary_length != gda_blob_op_get_length (blob->op)))
197 gda_blob_op_read_all (blob->op, (GdaBlob*) blob);
198 if (g_utf8_validate ((gchar*) bin->data, bin->binary_length, NULL)) {
199 gdaui_rt_editor_set_contents (GDAUI_RT_EDITOR (mgtxt->priv->view),
200 (gchar*) bin->data,
201 bin->binary_length);
202 done = TRUE;
203 }
204 }
205 else if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY) {
206 const GdaBinary *bin;
207 bin = gda_value_get_binary (value);
208 if (g_utf8_validate ((gchar*) bin->data, bin->binary_length, NULL)) {
209 gdaui_rt_editor_set_contents (GDAUI_RT_EDITOR (mgtxt->priv->view),
210 (gchar*) bin->data,
211 bin->binary_length);
212 done = TRUE;
213 }
214 }
215
216 if (!done) {
217 dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
218 str = gda_data_handler_get_str_from_value (dh, value);
219 if (str) {
220 gdaui_rt_editor_set_contents (GDAUI_RT_EDITOR (mgtxt->priv->view),
221 str, -1);
222 g_free (str);
223 }
224 }
225 }
226 }
227 }
228
229 static GValue *
230 real_get_value (GdauiEntryWrapper *mgwrap)
231 {
232 GValue *value;
format_size(gulong size)233 GdauiEntryRt *mgtxt;
234 GdaDataHandler *dh;
235 gchar *str;
236
237 g_return_val_if_fail (mgwrap && GDAUI_IS_ENTRY_RT (mgwrap), NULL);
238 mgtxt = GDAUI_ENTRY_RT (mgwrap);
239 g_return_val_if_fail (mgtxt->priv, NULL);
240
241 dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
242 str = gdaui_rt_editor_get_contents (GDAUI_RT_EDITOR (mgtxt->priv->view));
243 value = gda_data_handler_get_value_from_str (dh, str,
244 gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgwrap)));
245 g_free (str);
246 if (!value) {
247 /* in case the gda_data_handler_get_value_from_sql() returned an error because
248 the contents of the GtkEntry cannot be interpreted as a GValue */
common_bin_adjust_menu(BinMenu * binmenu,gboolean editable,const GValue * value)249 value = gda_value_new_null ();
250 }
251
252 return value;
253 }
254
255 typedef void (*Callback2) (gpointer, gpointer);
256 static gboolean
257 focus_out_cb (GtkWidget *widget, GdkEventFocus *event, GdauiEntryRt *mgtxt)
258 {
259 GCallback activate_cb;
260 activate_cb = g_object_get_data (G_OBJECT (widget), "_activate_cb");
261 g_assert (activate_cb);
262 ((Callback2)activate_cb) (widget, mgtxt);
263
264 return gtk_widget_event (GTK_WIDGET (mgtxt), (GdkEvent*) event);
265 }
266
267 static void
268 connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb)
269 {
270 GdauiEntryRt *mgtxt;
271
272 g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_RT (mgwrap));
273 mgtxt = GDAUI_ENTRY_RT (mgwrap);
274 g_return_if_fail (mgtxt->priv);
275
276 g_object_set_data (G_OBJECT (mgtxt->priv->view), "_activate_cb", activate_cb);
277 g_signal_connect (G_OBJECT (GDAUI_RT_EDITOR (mgtxt->priv->view)), "changed",
278 modify_cb, mgwrap);
279 g_signal_connect (G_OBJECT (mgtxt->priv->view), "focus-out-event",
280 G_CALLBACK (focus_out_cb), mgtxt);
281 /* FIXME: how does the user "activates" the GtkRtView widget ? */
282 }
283
284 static void
285 set_editable (GdauiEntryWrapper *mgwrap, gboolean editable)
286 {
287 GdauiEntryRt *mgtxt;
288
289 g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_RT (mgwrap));
290 mgtxt = GDAUI_ENTRY_RT (mgwrap);
291
292 gdaui_rt_editor_set_editable (GDAUI_RT_EDITOR (mgtxt->priv->view), editable);
293 }
294