GUI: Move .ui files from goffice resources to glib resources
[gnumeric.git] / src / dialogs / dialog-data-slicer.c
blob95c3b0f0ff4479ca96513563d16c6a561075d1cb
1 /**
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
19 * USA
22 #include <gnumeric-config.h>
23 #include <glib/gi18n-lib.h>
24 #include <gnumeric.h>
25 #include "dialogs.h"
26 #include "help.h"
28 #include <gui-util.h>
29 #include <commands.h>
30 #include <workbook-control.h>
31 #include <workbook.h>
32 #include <wbc-gtk.h>
33 #include <sheet.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>
41 typedef struct {
42 GtkWidget *dialog;
43 WBCGtk *wbcg;
44 SheetView *sv;
46 GnmSheetSlicer *slicer;
47 GODataCache *cache;
48 GODataCacheSource *source;
50 GtkWidget *notebook;
51 GnmExprEntry *source_expr;
53 GtkTreeView *treeview;
54 GtkTreeSelection *selection;
55 } DialogDataSlicer;
57 enum {
58 FIELD,
59 FIELD_TYPE,
60 FIELD_NAME,
61 FIELD_HEADER_INDEX,
62 NUM_COLUMNS
64 #define DIALOG_KEY "dialog-data-slicer"
66 static void
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; }
72 state->dialog = NULL;
73 g_free (state);
76 static void
77 cb_dialog_data_slicer_ok (G_GNUC_UNUSED GtkWidget *button,
78 DialogDataSlicer *state)
80 gtk_widget_destroy (state->dialog);
83 static void
84 cb_dialog_data_slicer_cancel (G_GNUC_UNUSED GtkWidget *button,
85 DialogDataSlicer *state)
87 gtk_widget_destroy (state->dialog);
90 static gint
91 cb_sort_by_header_index (GtkTreeModel *model,
92 GtkTreeIter *a,
93 GtkTreeIter *b,
94 gpointer user_data)
96 #if 0
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,
107 -1);
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,
111 -1);
113 if (!info_a)
114 return 1;
116 if (!info_b)
117 return -1;
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))
124 return -1;
125 else if (gtk_recent_info_get_modified (info_a) > gtk_recent_info_get_modified (info_b))
126 return 1;
127 else
128 #endif
129 return 0;
132 static void
133 cb_dialog_data_slicer_create_model (DialogDataSlicer *state)
135 struct {
136 GODataSlicerFieldType type;
137 char const * type_name;
138 GtkTreeIter iter;
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") },
144 /* Must be last */
145 { GDS_FIELD_TYPE_UNSET, N_("Unused") }
148 unsigned int i, j, n;
149 GtkTreeStore *model;
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,
166 FIELD, NULL,
167 FIELD_TYPE, field_type_labels[i].type,
168 FIELD_NAME, _(field_type_labels[i].type_name),
169 FIELD_HEADER_INDEX, -1,
170 -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)
183 : (used ? -1 : 0);
184 if (header_index >= 0) {
185 used = TRUE;
186 gtk_tree_store_append (model, &child_iter, &field_type_labels[j].iter);
187 gtk_tree_store_set (model, &child_iter,
188 FIELD, field,
189 FIELD_TYPE, field_type_labels[j].type,
190 FIELD_NAME, name->str,
191 FIELD_HEADER_INDEX, header_index,
192 -1);
196 gtk_tree_view_set_model (state->treeview, smodel);
199 static void
200 cb_dialog_data_slicer_selection_changed (GtkTreeSelection *selection,
201 DialogDataSlicer *state)
205 static void
206 cb_source_expr_changed (DialogDataSlicer *state)
208 GnmValue *range;
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);
215 void
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;
222 GtkBuilder *gui;
223 GtkWidget *w;
225 g_return_if_fail (wbcg != NULL);
227 if (gnm_dialog_raise_if_exists (wbcg, DIALOG_KEY))
228 return;
230 gui = gnm_gtk_builder_load ("res:ui/data-slicer.ui", NULL, GO_CMD_CONTEXT (wbcg));
231 if (NULL == gui)
232 return;
234 state = g_new0 (DialogDataSlicer, 1);
235 state->wbcg = wbcg;
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);
241 state->cache = NULL;
242 state->source = NULL;
244 if (NULL == state->slicer) {
245 state->slicer = g_object_new (GNM_SHEET_SLICER_TYPE, NULL);
246 } else {
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);