2 * dialog-data-slicer.c: Edit DataSlicers
4 * (c) Copyright 2008-2009 Jody Goldberg <jody@gnome.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) version 3.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 #include <gnumeric-config.h>
23 #include <glib/gi18n-lib.h>
30 #include <workbook-control.h>
34 #include <sheet-view.h>
35 #include <workbook-cmd-format.h>
36 #include <gnm-sheet-slicer.h>
37 #include <go-data-slicer.h>
38 #include <go-data-slicer-field.h>
39 #include <go-data-cache.h>
46 GnmSheetSlicer
*slicer
;
48 GODataCacheSource
*source
;
51 GnmExprEntry
*source_expr
;
53 GtkTreeView
*treeview
;
54 GtkTreeSelection
*selection
;
64 #define DIALOG_KEY "dialog-data-slicer"
67 cb_dialog_data_slicer_destroy (DialogDataSlicer
*state
)
69 if (NULL
!= state
->slicer
) { g_object_unref (state
->slicer
); state
->slicer
= NULL
; }
70 if (NULL
!= state
->cache
) { g_object_unref (state
->cache
); state
->cache
= NULL
; }
71 if (NULL
!= state
->source
) { g_object_unref (state
->source
); state
->source
= NULL
; }
77 cb_dialog_data_slicer_ok (G_GNUC_UNUSED GtkWidget
*button
,
78 DialogDataSlicer
*state
)
80 gtk_widget_destroy (state
->dialog
);
84 cb_dialog_data_slicer_cancel (G_GNUC_UNUSED GtkWidget
*button
,
85 DialogDataSlicer
*state
)
87 gtk_widget_destroy (state
->dialog
);
91 cb_sort_by_header_index (GtkTreeModel
*model
,
97 GtkTreeIter child_a
, child_b
;
98 GtkRecentInfo
*info_a
, *info_b
;
99 gboolean is_folder_a
, is_folder_b
;
101 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model
), &child_a
, a
);
102 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model
), &child_b
, b
);
104 gtk_tree_model_get (GTK_TREE_MODEL (impl
->recent_model
), &child_a
,
105 RECENT_MODEL_COL_IS_FOLDER
, &is_folder_a
,
106 RECENT_MODEL_COL_INFO
, &info_a
,
108 gtk_tree_model_get (GTK_TREE_MODEL (impl
->recent_model
), &child_b
,
109 RECENT_MODEL_COL_IS_FOLDER
, &is_folder_b
,
110 RECENT_MODEL_COL_INFO
, &info_b
,
119 /* folders always go first */
120 if (is_folder_a
!= is_folder_b
)
121 return is_folder_a
? 1 : -1;
123 if (gtk_recent_info_get_modified (info_a
) < gtk_recent_info_get_modified (info_b
))
125 else if (gtk_recent_info_get_modified (info_a
) > gtk_recent_info_get_modified (info_b
))
133 cb_dialog_data_slicer_create_model (DialogDataSlicer
*state
)
136 GODataSlicerFieldType type
;
137 char const * type_name
;
139 } field_type_labels
[] = {
140 { GDS_FIELD_TYPE_PAGE
, N_("Filter") },
141 { GDS_FIELD_TYPE_ROW
, N_("Row") },
142 { GDS_FIELD_TYPE_COL
, N_("Column") },
143 { GDS_FIELD_TYPE_DATA
, N_("Data") },
145 { GDS_FIELD_TYPE_UNSET
, N_("Unused") }
148 unsigned int i
, j
, n
;
150 GtkTreeModel
*smodel
;
152 model
= gtk_tree_store_new (NUM_COLUMNS
,
153 G_TYPE_POINTER
, /* field */
154 G_TYPE_INT
, /* field-type */
155 G_TYPE_STRING
, /* field-name */
156 G_TYPE_INT
); /* field-header-index */
157 smodel
= gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (model
));
158 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (smodel
),
159 FIELD_HEADER_INDEX
, cb_sort_by_header_index
, NULL
, NULL
);
160 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (smodel
),
161 FIELD_HEADER_INDEX
, GTK_SORT_ASCENDING
);
163 for (i
= 0 ; i
< G_N_ELEMENTS (field_type_labels
) ; i
++) {
164 gtk_tree_store_append (model
, &field_type_labels
[i
].iter
, NULL
);
165 gtk_tree_store_set (model
, &field_type_labels
[i
].iter
,
167 FIELD_TYPE
, field_type_labels
[i
].type
,
168 FIELD_NAME
, _(field_type_labels
[i
].type_name
),
169 FIELD_HEADER_INDEX
, -1,
172 n
= go_data_slicer_num_fields (GO_DATA_SLICER (state
->slicer
));
173 for (i
= 0 ; i
< n
; i
++) {
174 GtkTreeIter child_iter
;
175 GODataSlicerField
*field
=
176 go_data_slicer_get_field (GO_DATA_SLICER (state
->slicer
), i
);
177 GOString
*name
= go_data_slicer_field_get_name (field
);
178 gboolean used
= FALSE
;
180 for (j
= 0 ; j
< G_N_ELEMENTS (field_type_labels
) ; j
++) {
181 int header_index
= (GDS_FIELD_TYPE_UNSET
!= field_type_labels
[j
].type
)
182 ? go_data_slicer_field_get_field_type_pos (field
, field_type_labels
[j
].type
)
184 if (header_index
>= 0) {
186 gtk_tree_store_append (model
, &child_iter
, &field_type_labels
[j
].iter
);
187 gtk_tree_store_set (model
, &child_iter
,
189 FIELD_TYPE
, field_type_labels
[j
].type
,
190 FIELD_NAME
, name
->str
,
191 FIELD_HEADER_INDEX
, header_index
,
196 gtk_tree_view_set_model (state
->treeview
, smodel
);
200 cb_dialog_data_slicer_selection_changed (GtkTreeSelection
*selection
,
201 DialogDataSlicer
*state
)
206 cb_source_expr_changed (DialogDataSlicer
*state
)
209 range
= gnm_expr_entry_parse_as_value
210 (GNM_EXPR_ENTRY (state
->source_expr
), sv_sheet (state
->sv
));
211 #warning "FIXME: Now what?"
212 value_release (range
);
216 dialog_data_slicer (WBCGtk
*wbcg
, gboolean create
)
218 static GtkTargetEntry row_targets
[] = {
219 { (char *)"GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_APP
, 0 }
221 DialogDataSlicer
*state
;
225 g_return_if_fail (wbcg
!= NULL
);
227 if (gnm_dialog_raise_if_exists (wbcg
, DIALOG_KEY
))
230 gui
= gnm_gtk_builder_load ("data-slicer.ui", NULL
, GO_CMD_CONTEXT (wbcg
));
234 state
= g_new0 (DialogDataSlicer
, 1);
236 state
->sv
= wb_control_cur_sheet_view (GNM_WBC (wbcg
));
238 state
->dialog
= go_gtk_builder_get_widget (gui
, "dialog_data_slicer");
239 state
->notebook
= go_gtk_builder_get_widget (gui
, "notebook");
240 state
->slicer
= create
? NULL
: gnm_sheet_view_editpos_in_slicer (state
->sv
);
242 state
->source
= NULL
;
244 if (NULL
== state
->slicer
) {
245 state
->slicer
= g_object_new (GNM_SHEET_SLICER_TYPE
, NULL
);
247 g_object_ref (state
->slicer
);
248 g_object_get (G_OBJECT (state
->slicer
), "cache", &state
->cache
, NULL
);
249 if (NULL
!= state
->cache
&&
250 NULL
!= (state
->source
= go_data_cache_get_source (state
->cache
)))
251 g_object_ref (state
->source
);
254 state
->source_expr
= gnm_expr_entry_new (state
->wbcg
, TRUE
);
255 gnm_expr_entry_set_flags (state
->source_expr
,
256 GNM_EE_SINGLE_RANGE
, GNM_EE_MASK
);
257 g_signal_connect_swapped (G_OBJECT (state
->source_expr
),
258 "changed", G_CALLBACK (cb_source_expr_changed
), state
);
259 w
= go_gtk_builder_get_widget (gui
, "source_vbox");
260 gtk_box_pack_start (GTK_BOX (w
), GTK_WIDGET (state
->source_expr
), FALSE
, FALSE
, 0);
261 gtk_widget_show (GTK_WIDGET (state
->source_expr
));
263 w
= go_gtk_builder_get_widget (gui
, "ok_button");
264 g_signal_connect (G_OBJECT (w
), "clicked",
265 G_CALLBACK (cb_dialog_data_slicer_ok
), state
);
266 w
= go_gtk_builder_get_widget (gui
, "cancel_button");
267 g_signal_connect (G_OBJECT (w
), "clicked",
268 G_CALLBACK (cb_dialog_data_slicer_cancel
), state
);
270 state
->treeview
= GTK_TREE_VIEW (go_gtk_builder_get_widget (gui
, "field_tree"));
271 gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (state
->treeview
), GDK_BUTTON1_MASK
,
272 row_targets
, G_N_ELEMENTS (row_targets
), GDK_ACTION_MOVE
);
273 gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (state
->treeview
),
274 row_targets
, G_N_ELEMENTS (row_targets
), GDK_ACTION_MOVE
);
275 state
->selection
= gtk_tree_view_get_selection (state
->treeview
);
276 gtk_tree_selection_set_mode (state
->selection
, GTK_SELECTION_SINGLE
);
277 g_signal_connect (state
->selection
, "changed",
278 G_CALLBACK (cb_dialog_data_slicer_selection_changed
), state
);
280 gtk_tree_view_append_column (state
->treeview
,
281 gtk_tree_view_column_new_with_attributes ("",
282 gtk_cell_renderer_text_new (), "text", FIELD_NAME
, NULL
));
283 cb_dialog_data_slicer_create_model (state
);
285 g_signal_connect (state
->treeview
, "realize", G_CALLBACK (gtk_tree_view_expand_all
), NULL
);
287 gtk_notebook_set_current_page (GTK_NOTEBOOK (state
->notebook
), create
? 0 : 1);
289 /* a candidate for merging into attach guru */
290 gnm_init_help_button (go_gtk_builder_get_widget (gui
, "help_button"),
291 GNUMERIC_HELP_LINK_DATA_SLICER
);
292 g_object_set_data_full (G_OBJECT (state
->dialog
),
293 "state", state
, (GDestroyNotify
)cb_dialog_data_slicer_destroy
);
294 wbc_gtk_attach_guru (state
->wbcg
, state
->dialog
);
295 gnm_keyed_dialog (wbcg
, GTK_WINDOW (state
->dialog
), DIALOG_KEY
);
296 gtk_widget_show (state
->dialog
);
297 g_object_unref (gui
);