Location | Tool | Test ID | Function | Issue |
---|---|---|---|---|
gal-define-views-dialog.c:327:18 | clang-analyzer | Access to field 'view_count' results in a dereference of a null pointer (loaded from variable 'collection') | ||
gal-define-views-dialog.c:327:18 | clang-analyzer | Access to field 'view_count' results in a dereference of a null pointer (loaded from variable 'collection') |
1 /*
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with the program; if not, see <http://www.gnu.org/licenses/>
15 *
16 *
17 * Authors:
18 * Chris Lahey <clahey@ximian.com>
19 *
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <glib/gi18n.h>
29
30 #include "e-util/e-util.h"
31 #include "e-util/e-util-private.h"
32
33 #include "gal-define-views-dialog.h"
34 #include "gal-define-views-model.h"
35 #include "gal-view-new-dialog.h"
36
37 static void gal_define_views_dialog_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
38 static void gal_define_views_dialog_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
39 static void gal_define_views_dialog_dispose (GObject *object);
40
41 /* The properties we support */
42 enum {
43 PROP_0,
44 PROP_COLLECTION
45 };
46
47 enum {
48 COL_GALVIEW_NAME,
49 COL_GALVIEW_DATA
50 };
51
52 typedef struct {
53 gchar *title;
54
55 GtkTreeView *treeview;
56 GtkTreeModel *model;
57
58 GalDefineViewsDialog *names;
59 } GalDefineViewsDialogChild;
60
61 G_DEFINE_TYPE (GalDefineViewsDialog, gal_define_views_dialog, GTK_TYPE_DIALOG)
62
63 static void
64 gal_define_views_dialog_class_init (GalDefineViewsDialogClass *class)
65 {
66 GObjectClass *object_class;
67
68 object_class = (GObjectClass *) class;
69
70 object_class->set_property = gal_define_views_dialog_set_property;
71 object_class->get_property = gal_define_views_dialog_get_property;
72 object_class->dispose = gal_define_views_dialog_dispose;
73
74 g_object_class_install_property (
75 object_class,
76 PROP_COLLECTION,
77 g_param_spec_object (
78 "collection",
79 "Collection",
80 NULL,
81 GAL_VIEW_COLLECTION_TYPE,
82 G_PARAM_READWRITE));
83 }
84
85 /* Button callbacks */
86
87 static void
88 gdvd_button_new_dialog_callback (GtkWidget *widget,
89 gint id,
90 GalDefineViewsDialog *dialog)
91 {
92 gchar *name;
93 GtkTreeIter iter;
94 GalView *view;
95 GalViewCollectionItem *item;
96 GalViewFactory *factory;
97
98 switch (id) {
99 case GTK_RESPONSE_OK:
100 g_object_get (
101 widget,
102 "name", &name,
103 "factory", &factory,
104 NULL);
105
106 if (name && factory) {
107 g_strchomp (name);
108 if (*name != '\0') {
109 view = gal_view_factory_new_view (factory, name);
110 gal_view_collection_append (dialog->collection, view);
111
112 item = dialog->collection->view_data[dialog->collection->view_count - 1];
113 gtk_list_store_append (GTK_LIST_STORE (dialog->model), &iter);
114 gtk_list_store_set (
115 GTK_LIST_STORE (dialog->model), &iter,
116 COL_GALVIEW_NAME, name,
117 COL_GALVIEW_DATA, item,
118 -1);
119
120 if (view && GAL_VIEW_GET_CLASS (view)->edit)
121 gal_view_edit (view, GTK_WINDOW (dialog));
122 g_object_unref (view);
123 }
124 }
125 g_object_unref (factory);
126 g_free (name);
127 break;
128 }
129 gtk_widget_destroy (widget);
130 }
131
132 static void
133 gdvd_button_new_callback (GtkWidget *widget,
134 GalDefineViewsDialog *dialog)
135 {
136 GtkWidget *view_new_dialog = gal_view_new_dialog_new (dialog->collection);
137 gtk_window_set_transient_for (GTK_WINDOW (view_new_dialog), GTK_WINDOW (dialog));
138 g_signal_connect (
139 view_new_dialog, "response",
140 G_CALLBACK (gdvd_button_new_dialog_callback), dialog);
141 gtk_widget_show (view_new_dialog);
142 }
143
144 static void
145 gdvd_button_modify_callback (GtkWidget *widget,
146 GalDefineViewsDialog *dialog)
147 {
148 GtkTreeIter iter;
149 GalViewCollectionItem *item;
150
151 if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (dialog->treeview),
152 &dialog->model,
153 &iter)) {
154 gtk_tree_model_get (dialog->model, &iter, COL_GALVIEW_DATA, &item, -1);
155
156 g_return_if_fail (item && !item->built_in);
157
158 gal_view_edit (item->view, GTK_WINDOW (dialog));
159 }
160 }
161
162 static void
163 gdvd_button_delete_callback (GtkWidget *widget,
164 GalDefineViewsDialog *dialog)
165 {
166 gint row;
167 GtkTreeIter iter;
168 GtkTreePath *path;
169 GtkTreeSelection *selection;
170 GalViewCollectionItem *item;
171
172 selection = gtk_tree_view_get_selection (dialog->treeview);
173
174 if (gtk_tree_selection_get_selected (selection,
175 &dialog->model,
176 &iter)) {
177 gtk_tree_model_get (dialog->model, &iter, COL_GALVIEW_DATA, &item, -1);
178
179 g_return_if_fail (item && !item->built_in);
180
181 for (row = 0; row < dialog->collection->view_count; row++) {
182 if (item == dialog->collection->view_data[row]) {
183 gal_view_collection_delete_view (dialog->collection, row);
184 path = gtk_tree_model_get_path (dialog->model, &iter);
185 gtk_list_store_remove (GTK_LIST_STORE (dialog->model), &iter);
186
187 if (gtk_tree_path_prev (path)) {
188 gtk_tree_model_get_iter (dialog->model, &iter, path);
189 } else {
190 gtk_tree_model_get_iter_first (dialog->model, &iter);
191 }
192
193 gtk_tree_selection_select_iter (selection, &iter);
194 break;
195 }
196 }
197 }
198 }
199
200 static void
201 gdvd_selection_changed_callback (GtkTreeSelection *selection,
202 GalDefineViewsDialog *dialog)
203 {
204 GtkWidget *button;
205 GtkTreeIter iter;
206 GalViewCollectionItem *item = NULL;
207 GalViewClass *gvclass = NULL;
208
209 if (gtk_tree_selection_get_selected (selection, &dialog->model, &iter)) {
210 gtk_tree_model_get (dialog->model, &iter, COL_GALVIEW_DATA, &item, -1);
211
212 if (item && item->view)
213 gvclass = GAL_VIEW_GET_CLASS (item->view);
214 }
215
216 button = e_builder_get_widget (dialog->builder, "button-delete");
217 gtk_widget_set_sensitive (GTK_WIDGET (button), item && !item->built_in);
218
219 button = e_builder_get_widget (dialog->builder, "button-modify");
220 gtk_widget_set_sensitive (GTK_WIDGET (button), item && !item->built_in && gvclass && gvclass->edit != NULL);
221 }
222
223 static void
224 gdvd_connect_signal (GalDefineViewsDialog *dialog,
225 const gchar *widget_name,
226 const gchar *signal,
227 GCallback handler)
228 {
229 GtkWidget *widget;
230
231 widget = e_builder_get_widget (dialog->builder, widget_name);
232
233 if (widget)
234 g_signal_connect (widget, signal, handler, dialog);
235 }
236
237 static void
238 dialog_response (GalDefineViewsDialog *dialog,
239 gint response_id,
240 gpointer data)
241 {
242 gal_view_collection_save (dialog->collection);
243 }
244
245 static void
246 gal_define_views_dialog_init (GalDefineViewsDialog *dialog)
247 {
248 GtkWidget *content_area;
249 GtkWidget *parent;
250 GtkWidget *widget;
251 GtkTreeSelection *selection;
252
253 dialog->collection = NULL;
254
255 dialog->builder = gtk_builder_new ();
256 e_load_ui_builder_definition (dialog->builder, "gal-define-views.ui");
257
258 widget = e_builder_get_widget (dialog->builder, "table-top");
259 if (!widget) {
260 return;
261 }
262
263 g_object_ref (widget);
264
265 parent = gtk_widget_get_parent (widget);
266 gtk_container_remove (GTK_CONTAINER (parent), widget);
267 gtk_window_set_default_size (GTK_WINDOW (dialog), 360, 270);
268 gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
269 gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
270
271 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
272 gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0);
273
274 g_object_unref (widget);
275
276 gtk_dialog_add_buttons (
277 GTK_DIALOG (dialog),
278 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
279 NULL);
280
281 dialog->treeview = GTK_TREE_VIEW (e_builder_get_widget (dialog->builder, "treeview1"));
282 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (dialog->treeview), FALSE);
283 gtk_tree_view_set_headers_visible (dialog->treeview, TRUE);
284
285 gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
286
287 gdvd_connect_signal (dialog, "button-new", "clicked", G_CALLBACK (gdvd_button_new_callback));
288 gdvd_connect_signal (dialog, "button-modify", "clicked", G_CALLBACK (gdvd_button_modify_callback));
289 gdvd_connect_signal (dialog, "button-delete", "clicked", G_CALLBACK (gdvd_button_delete_callback));
290 g_signal_connect (
291 dialog, "response",
292 G_CALLBACK (dialog_response), NULL);
293
294 selection = gtk_tree_view_get_selection (dialog->treeview);
295 g_signal_connect (
296 selection, "changed",
297 G_CALLBACK (gdvd_selection_changed_callback), dialog);
298 gdvd_selection_changed_callback (selection, dialog);
299
300 gtk_widget_show (GTK_WIDGET (dialog));
301 }
302
303 static void
304 gal_define_views_dialog_dispose (GObject *object)
305 {
306 GalDefineViewsDialog *gal_define_views_dialog = GAL_DEFINE_VIEWS_DIALOG (object);
307
308 if (gal_define_views_dialog->builder)
309 g_object_unref (gal_define_views_dialog->builder);
310 gal_define_views_dialog->builder = NULL;
311
312 /* Chain up to parent's dispose() method. */
313 G_OBJECT_CLASS (gal_define_views_dialog_parent_class)->dispose (object);
314 }
315
316 static void
317 gal_define_views_dialog_set_collection (GalDefineViewsDialog *dialog,
318 GalViewCollection *collection)
319 {
320 gint i;
321 GtkListStore *store;
322 GtkCellRenderer *renderer;
323 dialog->collection = collection;
324
325 store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
326
327 for (i = 0; i < collection->view_count; i++) {
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
328 GalViewCollectionItem *item = collection->view_data[i];
329 GtkTreeIter iter;
330
331 /* hide built in views */
332 /*if (item->built_in == 1)
333 continue;*/
334
335 gchar *title = NULL;
336 title = e_str_without_underscores (item->title);
337
338 gtk_list_store_append (store, &iter);
339 gtk_list_store_set (
340 store, &iter,
341 COL_GALVIEW_NAME, title,
342 COL_GALVIEW_DATA, item,
343 -1);
344
345 g_free (title);
346 }
347
348 gtk_tree_sortable_set_sort_column_id (
349 GTK_TREE_SORTABLE (store),
350 COL_GALVIEW_NAME, GTK_SORT_ASCENDING);
351
352 /* attaching treeview to model */
353 gtk_tree_view_set_model (dialog->treeview, GTK_TREE_MODEL (store));
354 gtk_tree_view_set_search_column (dialog->treeview, COL_GALVIEW_NAME);
355
356 dialog->model = GTK_TREE_MODEL (store);
357
358 renderer = gtk_cell_renderer_text_new ();
359 gtk_tree_view_insert_column_with_attributes (
360 dialog->treeview,
361 COL_GALVIEW_NAME, _("Name"),
362 renderer, "text", COL_GALVIEW_NAME,
363 NULL);
364
365 /* set sort column */
366 gtk_tree_sortable_set_sort_column_id (
367 GTK_TREE_SORTABLE (dialog->model),
368 COL_GALVIEW_NAME, GTK_SORT_ASCENDING);
369
370 if (dialog->builder) {
371 GtkWidget *widget = e_builder_get_widget (dialog->builder, "label-views");
372 if (widget && GTK_IS_LABEL (widget)) {
373 if (collection->title) {
374 gchar *text = g_strdup_printf (
375 _("Define Views for %s"),
376 collection->title);
377 gtk_label_set_text (
378 GTK_LABEL (widget),
379 text);
380 gtk_window_set_title (GTK_WINDOW (dialog), text);
381 g_free (text);
382 } else {
383 gtk_label_set_text (
384 GTK_LABEL (widget),
385 _("Define Views"));
386 gtk_window_set_title (
387 GTK_WINDOW (dialog),
388 _("Define Views"));
389 }
390 }
391 }
392 }
393
394 /**
395 * gal_define_views_dialog_new
396 *
397 * Returns a new dialog for defining views.
398 *
399 * Returns: The GalDefineViewsDialog.
400 */
401 GtkWidget *
402 gal_define_views_dialog_new (GalViewCollection *collection)
403 {
404 GtkWidget *widget = g_object_new (GAL_TYPE_DEFINE_VIEWS_DIALOG, NULL);
405 gal_define_views_dialog_set_collection (GAL_DEFINE_VIEWS_DIALOG (widget), collection);
406 return widget;
407 }
408
409 static void
410 gal_define_views_dialog_set_property (GObject *object,
411 guint property_id,
412 const GValue *value,
413 GParamSpec *pspec)
414 {
415 GalDefineViewsDialog *dialog;
416
417 dialog = GAL_DEFINE_VIEWS_DIALOG (object);
418
419 switch (property_id) {
420 case PROP_COLLECTION:
421 if (g_value_get_object (value))
422 gal_define_views_dialog_set_collection (dialog, GAL_VIEW_COLLECTION (g_value_get_object (value)));
423 else
424 gal_define_views_dialog_set_collection (dialog, NULL);
425 break;
426
427 default:
428 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
429 return;
430 }
431 }
432
433 static void
434 gal_define_views_dialog_get_property (GObject *object,
435 guint property_id,
436 GValue *value,
437 GParamSpec *pspec)
438 {
439 GalDefineViewsDialog *dialog;
440
441 dialog = GAL_DEFINE_VIEWS_DIALOG (object);
442
443 switch (property_id) {
444 case PROP_COLLECTION:
445 g_value_set_object (value, dialog->collection);
446
447 default:
448 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
449 break;
450 }
451 }