Update Spanish translation
[gnumeric.git] / src / workbook-view.c
blob57e6ed5fe24fc3f98e667f63137155651dc67ee8
1 /*
2 * workbook-view.c: View functions for the workbook
4 * Copyright (C) 2000-2006 Jody Goldberg (jody@gnome.org)
5 * Copyright (C) 2012 Morten Welinder (terra@gnome.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
22 #include <gnumeric-config.h>
23 #include <gnumeric.h>
24 #include <workbook-view.h>
26 #include <workbook-control-priv.h>
27 #include <workbook-priv.h>
28 #include <application.h>
29 #include <sheet.h>
30 #include <sheet-view.h>
31 #include <sheet-merge.h>
32 #include <sheet-style.h>
33 #include <func.h>
34 #include <expr.h>
35 #include <expr-name.h>
36 #include <value.h>
37 #include <ranges.h>
38 #include <selection.h>
39 #include <mstyle.h>
40 #include <validation.h>
41 #include <validation-combo.h>
42 #include <gnm-sheet-slicer.h>
43 #include <gnm-sheet-slicer-combo.h>
44 #include <position.h>
45 #include <cell.h>
46 #include <gutils.h>
47 #include <command-context.h>
48 #include <auto-format.h>
49 #include <sheet-object.h>
50 #include <gnumeric-conf.h>
52 #include <goffice/goffice.h>
53 #include <gsf/gsf-meta-names.h>
54 #include <gsf/gsf-impl-utils.h>
55 #include <gsf/gsf-output-stdio.h>
56 #include <gsf/gsf-input.h>
57 #include <gnm-i18n.h>
58 #include <glib/gstdio.h>
59 #include <string.h>
60 #include <unistd.h>
61 #include <stdlib.h>
62 #include <mathfunc.h>
64 #ifdef G_OS_WIN32
65 #include <windows.h>
66 #endif
68 /**
69 * WorkbookView:
70 * @wb_controls: (element-type WorkbookControl):
71 **/
72 enum {
73 PROP_0,
74 PROP_AUTO_EXPR_FUNC,
75 PROP_AUTO_EXPR_DESCR,
76 PROP_AUTO_EXPR_MAX_PRECISION,
77 PROP_AUTO_EXPR_VALUE,
78 PROP_AUTO_EXPR_EVAL_POS,
79 PROP_SHOW_HORIZONTAL_SCROLLBAR,
80 PROP_SHOW_VERTICAL_SCROLLBAR,
81 PROP_SHOW_NOTEBOOK_TABS,
82 PROP_SHOW_FUNCTION_CELL_MARKERS,
83 PROP_SHOW_EXTENSION_MARKERS,
84 PROP_DO_AUTO_COMPLETION,
85 PROP_PROTECTED,
86 PROP_PREFERRED_WIDTH,
87 PROP_PREFERRED_HEIGHT,
88 PROP_WORKBOOK
91 /* WorkbookView signals */
92 enum {
93 LAST_SIGNAL
96 /**
97 * wb_view_get_workbook:
98 * @wbv: #WorkbookView
100 * Returns: (transfer none): the #Workbook associated with @wbv
102 Workbook *
103 wb_view_get_workbook (WorkbookView const *wbv)
105 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
106 return wbv->wb;
110 * wb_view_get_doc:
111 * @wbv: #WorkbookView
113 * Returns: (transfer none): the #Workbook associated with @wbv cast to a #GODoc
115 GODoc *
116 wb_view_get_doc (WorkbookView const *wbv)
118 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
119 return GO_DOC (wbv->wb);
123 * wb_view_get_index_in_wb:
124 * @wbv: #WorkbookView
126 * Returns 0 based index of wbv within workbook, or -1 if there is no workbook.
129 wb_view_get_index_in_wb (WorkbookView const *wbv)
131 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), -1);
132 if (NULL != wbv->wb) {
133 unsigned i = wbv->wb->wb_views->len;
134 while (i-- > 0)
135 if (g_ptr_array_index (wbv->wb->wb_views, i) == wbv)
136 return i;
138 return -1;
142 * wb_view_cur_sheet:
143 * @wbv: #WorkbookView
145 * Returns: (transfer none): the current sheet.
147 Sheet *
148 wb_view_cur_sheet (WorkbookView const *wbv)
150 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
151 return wbv->current_sheet;
155 * wb_view_cur_sheet_view:
156 * @wbv: #WorkbookView
158 * Returns: (transfer none): the current sheet view.
160 SheetView *
161 wb_view_cur_sheet_view (WorkbookView const *wbv)
163 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
164 return wbv->current_sheet_view;
167 void
168 wb_view_sheet_focus (WorkbookView *wbv, Sheet *sheet)
170 if (wbv->current_sheet != sheet) {
171 /* Make sure the sheet has been attached */
172 g_return_if_fail (sheet == NULL || sheet->index_in_wb >= 0);
174 #if 0
175 g_print ("Focus %s\n", sheet ? sheet->name_quoted : "-");
176 #endif
178 wbv->current_sheet = sheet;
179 wbv->current_sheet_view = sheet_get_view (sheet, wbv);
181 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control,
182 wb_control_sheet_focus (control, sheet););
184 wb_view_selection_desc (wbv, TRUE, NULL);
185 wb_view_edit_line_set (wbv, NULL);
186 wb_view_style_feedback (wbv);
187 wb_view_menus_update (wbv);
188 wb_view_auto_expr_recalc (wbv);
192 void
193 wb_view_sheet_add (WorkbookView *wbv, Sheet *new_sheet)
195 SheetView *new_view;
197 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
199 new_view = gnm_sheet_view_new (new_sheet, wbv);
201 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control,
202 wb_control_sheet_add (control, new_view););
204 g_object_unref (new_view);
206 if (wbv->current_sheet == NULL)
207 wb_view_sheet_focus (wbv, new_sheet);
210 gboolean
211 wb_view_is_protected (WorkbookView *wbv, gboolean check_sheet)
213 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), FALSE);
215 return wbv->is_protected || (check_sheet &&
216 wbv->current_sheet != NULL && wbv->current_sheet->is_protected);
219 void
220 wb_view_set_attribute (WorkbookView *wbv, char const *name, char const *value)
222 gboolean res;
223 GObject *obj;
224 const char *tname;
226 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
227 g_return_if_fail (name != NULL);
228 g_return_if_fail (value != NULL);
230 obj = G_OBJECT (wbv);
231 res = !g_ascii_strcasecmp (value, "TRUE");
233 if (strncmp (name, "WorkbookView::", 14) == 0)
234 tname = name + 14;
235 else if (strncmp (name, "Workbook::", 10) == 0)
236 /* Some old files have this. */
237 tname = name + 10;
238 else
239 tname = "nope";
241 if (!strcmp (tname , "show_horizontal_scrollbar"))
242 g_object_set (obj, "show_horizontal_scrollbar", res, NULL);
243 else if (!strcmp (tname , "show_vertical_scrollbar"))
244 g_object_set (obj, "show_vertical_scrollbar", res, NULL);
245 else if (!strcmp (tname , "show_notebook_tabs"))
246 g_object_set (obj, "show_notebook_tabs", res, NULL);
247 else if (!strcmp (tname , "show_function_cell_markers"))
248 g_object_set (obj, "show_function_cell_markers", res, NULL);
249 else if (!strcmp (tname , "show_extension_markers"))
250 g_object_set (obj, "show_extension_markers", res, NULL);
251 else if (!strcmp (tname , "do_auto_completion"))
252 g_object_set (obj, "do_auto_completion", res, NULL);
253 else if (!strcmp (tname , "is_protected"))
254 g_object_set (obj, "protected", res, NULL);
255 else
256 g_warning ("WorkbookView unknown arg '%s'", name);
259 void
260 wb_view_preferred_size (WorkbookView *wbv, int w, int h)
262 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
264 if (w <= 0)
265 w = 768; /* use default */
266 if (h <= 0)
267 h = 768; /* use default */
269 g_object_set (G_OBJECT (wbv),
270 "preferred-width", w,
271 "preferred-height", h,
272 NULL);
275 void
276 wb_view_style_feedback (WorkbookView *wbv)
278 SheetView *sv;
279 GnmStyle const *style;
280 GnmSheetSlicer const *dslicer;
281 GODataSlicerField *dsfield;
282 GnmValidation const *val;
283 GOFormat const *fmt_style, *fmt_cell;
284 GnmCell *cell;
285 gboolean update_controls = TRUE;
287 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
289 sv = wbv->current_sheet_view;
290 if (sv == NULL)
291 return;
293 style = sheet_style_get (sv->sheet,
294 sv->edit_pos.col, sv->edit_pos.row);
295 fmt_style = gnm_style_get_format (style);
296 if (go_format_is_general (fmt_style) &&
297 (cell = sheet_cell_get (sv->sheet, sv->edit_pos.col, sv->edit_pos.row)) &&
298 cell->value && VALUE_FMT (cell->value))
299 fmt_cell = VALUE_FMT (cell->value);
300 else
301 fmt_cell = fmt_style;
303 if (go_format_eq (fmt_cell, fmt_style)) {
304 if (style == wbv->current_style)
305 update_controls = FALSE;
306 gnm_style_ref (style);
307 } else {
308 GnmStyle *tmp = gnm_style_dup (style);
309 gnm_style_set_format (tmp, fmt_cell);
310 style = tmp;
313 if (wbv->current_style != NULL)
314 gnm_style_unref (wbv->current_style);
315 wbv->current_style = style;
317 if (wbv->in_cell_combo != NULL) {
318 sheet_object_clear_sheet (wbv->in_cell_combo);
319 g_object_unref (wbv->in_cell_combo);
320 wbv->in_cell_combo = NULL;
323 if (gnm_style_is_element_set (style, MSTYLE_VALIDATION) &&
324 NULL != (val = gnm_style_get_validation (style)) &&
325 val->type == GNM_VALIDATION_TYPE_IN_LIST &&
326 val->use_dropdown)
327 wbv->in_cell_combo = gnm_validation_combo_new (val, sv);
328 else if (NULL != (dslicer = gnm_sheet_slicers_at_pos (sv->sheet, &sv->edit_pos)) &&
329 NULL != (dsfield = gnm_sheet_slicer_field_header_at_pos (dslicer, &sv->edit_pos)))
330 wbv->in_cell_combo = g_object_new (gnm_sheet_slicer_combo_get_type (),
331 "sheet-view", sv,
332 "field", dsfield,
333 NULL);
335 if (NULL != wbv->in_cell_combo)
337 const double a_offsets [4] = { 0., 0., 1., 1. };
338 SheetObjectAnchor anchor;
339 GnmRange corner;
340 GnmRange const *r;
341 if (NULL == (r = gnm_sheet_merge_contains_pos (sv->sheet, &sv->edit_pos)))
342 r = range_init_cellpos (&corner, &sv->edit_pos);
343 sheet_object_anchor_init (&anchor, r, a_offsets, GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
344 sheet_object_set_anchor (wbv->in_cell_combo, &anchor);
345 sheet_object_set_sheet (wbv->in_cell_combo, sv->sheet);
348 if (update_controls) {
349 WORKBOOK_VIEW_FOREACH_CONTROL(wbv, control,
350 wb_control_style_feedback (control, NULL););
354 void
355 wb_view_menus_update (WorkbookView *wbv)
357 Sheet *sheet;
359 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
361 sheet = wbv->current_sheet;
362 if (sheet != NULL) {
363 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, wbc, {
364 wb_control_menu_state_update (wbc, MS_ALL);
365 wb_control_update_action_sensitivity (wbc);
371 * wb_view_selection_desc:
372 * @wbv: The view
373 * @use_pos:
374 * @wbc: (allow-none): A #WorkbookControl
376 * Load the edit line with the value of the cell in sheet's edit_pos.
378 * Calculate what to display on the edit line then display it either in the
379 * control @wbc, or if that is %NULL, in all controls.
381 void
382 wb_view_selection_desc (WorkbookView *wbv, gboolean use_pos,
383 WorkbookControl *wbc)
385 SheetView *sv;
387 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
389 sv = wbv->current_sheet_view;
390 if (sv != NULL) {
391 char buffer [10 + 2 * 4 * sizeof (int)];
392 char const *sel_descr = buffer;
393 GnmRange const *r, *m;
395 g_return_if_fail (GNM_IS_SHEET_VIEW (sv));
396 g_return_if_fail (sv->selections);
398 r = selection_first_range (sv, NULL, NULL);
400 if (use_pos || range_is_singleton (r) ||
401 (NULL != (m = gnm_sheet_merge_is_corner (sv->sheet, &r->start)) &&
402 range_equal (r, m))) {
403 sel_descr = sheet_names_check (sv->sheet, r);
404 if (sel_descr == NULL) {
405 GnmParsePos pp;
406 parse_pos_init_editpos (&pp, sv);
407 sel_descr = parsepos_as_string (&pp);
409 } else {
410 int rows = r->end.row - r->start.row + 1;
411 int cols = r->end.col - r->start.col + 1;
413 if (rows == gnm_sheet_get_max_rows (sv->sheet))
414 /* Translators: "%dC" is a very short format to indicate the number of full columns */
415 snprintf (buffer, sizeof (buffer), _("%dC"), cols);
416 else if (cols == gnm_sheet_get_max_cols (sv->sheet))
417 /* Translators: "%dR" is a very short format to indicate the number of full rows */
418 snprintf (buffer, sizeof (buffer), _("%dR"), rows);
419 else
420 /* Translators: "%dR x %dC" is a very short format to indicate the number of rows and columns */
421 snprintf (buffer, sizeof (buffer), _("%dR x %dC"),
422 rows, cols);
425 if (wbc == NULL) {
426 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, wbc,
427 wb_control_selection_descr_set (wbc, sel_descr););
428 } else
429 wb_control_selection_descr_set (wbc, sel_descr);
434 * wb_view_edit_line_set:
435 * @wbv: The view
436 * @wbc: (allow-none): A #WorkbookControl
438 * Load the edit line with the value of the cell in @sheet's edit_pos.
440 * Calculate what to display on the edit line then display it either in the
441 * control @wbc, or if that is %NULL, in all controls.
443 void
444 wb_view_edit_line_set (WorkbookView *wbv, WorkbookControl *wbc)
446 SheetView *sv;
448 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
450 sv = wbv->current_sheet_view;
451 if (sv != NULL) {
452 char *text;
453 Sheet *sheet = sv->sheet;
454 GnmCell const *cell = sheet_cell_get (sheet,
455 sv->edit_pos.col, sv->edit_pos.row);
457 if (NULL != cell) {
458 text = gnm_cell_get_text_for_editing (cell, NULL, NULL);
460 if (gnm_cell_has_expr (cell)) {
461 GnmExprTop const *texpr = cell->base.texpr;
462 GnmCell const *corner = NULL;
463 int x = 0, y = 0;
466 * If this is part of an array we add '{' '}'
467 * and size information to the display. That
468 * is not actually part of the parsable
469 * expression, but it is a useful extension to
470 * the simple '{' '}' that MS excel(tm) uses.
472 if (gnm_expr_top_is_array_corner (texpr))
473 corner = cell;
474 else if (gnm_expr_top_is_array_elem (texpr, &x, &y)) {
475 corner = sheet_cell_get
476 (sheet,
477 cell->pos.col - x,
478 cell->pos.row - y);
481 if (corner) {
482 int cols, rows;
483 char *tmp;
485 gnm_expr_top_get_array_size (corner->base.texpr, &cols, &rows);
487 tmp = g_strdup_printf
488 ("{%s}(%d%c%d)[%d][%d]",
489 text,
490 cols, go_locale_get_arg_sep (), rows,
491 x, y);
492 g_free (text);
493 text = tmp;
496 } else
497 text = g_strdup ("");
499 if (wbc == NULL) {
500 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control,
501 wb_control_edit_line_set (control, text););
502 } else
503 wb_control_edit_line_set (wbc, text);
505 g_free (text);
509 static void
510 accumulate_regions (SheetView *sv, GnmRange const *r, gpointer closure)
512 GnmExprList **selection = closure;
513 GnmCellRef a, b;
515 a.sheet = b.sheet = sv_sheet (sv);
516 a.col_relative = a.row_relative = b.col_relative = b.row_relative = FALSE;
517 a.col = r->start.col;
518 a.row = r->start.row;
519 b.col = r->end.col;
520 b.row = r->end.row;
522 *selection = gnm_expr_list_prepend (*selection,
523 gnm_expr_new_constant (value_new_cellrange_unsafe (&a, &b)));
526 void
527 wb_view_auto_expr_recalc (WorkbookView *wbv)
529 GnmExprList *selection = NULL;
530 GnmValue *v;
531 SheetView *sv;
532 GnmExprTop const *texpr;
533 GnmEvalPos ep;
535 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
537 sv = wb_view_cur_sheet_view (wbv);
538 if (wbv->current_sheet == NULL ||
539 sv == NULL)
540 return;
542 if (wbv->auto_expr.dep.sheet != NULL &&
543 wbv->auto_expr.dep.texpr != NULL) {
544 texpr = wbv->auto_expr.dep.texpr;
545 gnm_expr_top_ref (texpr);
546 } else if (wbv->auto_expr.func != NULL) {
547 sv_selection_apply (sv, &accumulate_regions, FALSE, &selection);
548 texpr = gnm_expr_top_new
549 (gnm_expr_new_funcall (wbv->auto_expr.func, selection));
550 } else {
551 texpr = gnm_expr_top_new_constant (value_new_string (""));
554 eval_pos_init_sheet (&ep, wbv->current_sheet);
556 v = gnm_expr_top_eval (texpr, &ep, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
557 if (v) {
558 if (wbv->auto_expr.use_max_precision)
559 value_set_fmt (v, NULL);
560 else if (!VALUE_FMT (v)) {
561 GOFormat const *fmt = gnm_auto_style_format_suggest (texpr, &ep);
562 value_set_fmt (v, fmt);
563 go_format_unref (fmt);
566 g_object_set (wbv, "auto-expr-value", v, NULL);
567 value_release (v);
568 gnm_expr_top_unref (texpr);
571 /* perform whatever initialization of a control that is necessary when it
572 * finally gets assigned to a view with a workbook */
573 static void
574 wb_view_init_control (G_GNUC_UNUSED WorkbookControl *wbc)
578 void
579 wb_view_attach_control (WorkbookView *wbv, WorkbookControl *wbc)
581 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
582 g_return_if_fail (GNM_IS_WBC (wbc));
583 g_return_if_fail (wb_control_view (wbc) == NULL);
585 if (wbv->wb_controls == NULL)
586 wbv->wb_controls = g_ptr_array_new ();
587 g_ptr_array_add (wbv->wb_controls, wbc);
588 g_object_set (G_OBJECT (wbc), "view", wbv, NULL);
590 if (wbv->wb != NULL)
591 wb_view_init_control (wbc);
594 void
595 wb_view_detach_control (WorkbookControl *wbc)
597 g_return_if_fail (GNM_IS_WBC (wbc));
598 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wb_control_view (wbc)));
600 g_ptr_array_remove (wbc->wb_view->wb_controls, wbc);
601 if (wbc->wb_view->wb_controls->len == 0) {
602 g_ptr_array_free (wbc->wb_view->wb_controls, TRUE);
603 wbc->wb_view->wb_controls = NULL;
605 g_object_set (G_OBJECT (wbc), "view", NULL, NULL);
608 static GObjectClass *parent_class;
610 static void
611 wb_view_auto_expr_func (WorkbookView *wbv, GnmFunc *func)
613 if (wbv->auto_expr.func == func)
614 return;
616 if (wbv->auto_expr.func)
617 gnm_func_dec_usage (wbv->auto_expr.func);
619 if (func)
620 gnm_func_inc_usage (func);
621 wbv->auto_expr.func = func;
623 wb_view_auto_expr_recalc (wbv);
626 static void
627 wb_view_auto_expr_descr (WorkbookView *wbv, const char *descr)
629 char *s;
631 if (go_str_compare (descr, wbv->auto_expr.descr) == 0)
632 return;
634 s = g_strdup (descr);
635 g_free (wbv->auto_expr.descr);
636 wbv->auto_expr.descr = s;
638 wb_view_auto_expr_recalc (wbv);
641 static void
642 wb_view_auto_expr_precision (WorkbookView *wbv, gboolean use_max_precision)
644 use_max_precision = !!use_max_precision;
646 if (wbv->auto_expr.use_max_precision == use_max_precision)
647 return;
649 wbv->auto_expr.use_max_precision = use_max_precision;
651 wb_view_auto_expr_recalc (wbv);
654 static void
655 wb_view_auto_expr_value (WorkbookView *wbv, const GnmValue *value)
657 value_release (wbv->auto_expr.value);
658 wbv->auto_expr.value = value_dup (value);
661 static void
662 cb_clear_auto_expr_sheet (WorkbookView *wbv)
664 g_object_set (G_OBJECT (wbv),
665 "auto-expr-eval-pos", NULL,
666 NULL);
669 static void
670 wb_view_auto_expr_eval_pos (WorkbookView *wbv, GnmEvalPos const *ep)
672 Sheet *sheet = ep ? ep->sheet : NULL;
674 if (wbv->auto_expr.sheet_detached_sig) {
675 g_signal_handler_disconnect (wbv->auto_expr.dep.sheet,
676 wbv->auto_expr.sheet_detached_sig);
677 wbv->auto_expr.sheet_detached_sig = 0;
680 dependent_set_expr (&wbv->auto_expr.dep, NULL);
681 dependent_managed_set_sheet (&wbv->auto_expr.dep, sheet);
683 if (sheet) {
684 GnmRange r;
685 GnmValue *v;
686 GnmExprTop const *texpr;
688 wbv->auto_expr.sheet_detached_sig = g_signal_connect_swapped (
689 G_OBJECT (sheet),
690 "detached-from-workbook",
691 G_CALLBACK (cb_clear_auto_expr_sheet), wbv);
693 range_init_cellpos (&r, &ep->eval);
694 v = value_new_cellrange_r (sheet, &r);
695 texpr = gnm_expr_top_new_constant (v);
696 dependent_managed_set_expr (&wbv->auto_expr.dep, texpr);
697 gnm_expr_top_unref (texpr);
700 wb_view_auto_expr_recalc (wbv);
703 static void
704 wb_view_set_property (GObject *object, guint property_id,
705 const GValue *value, GParamSpec *pspec)
707 WorkbookView *wbv = (WorkbookView *)object;
709 switch (property_id) {
710 case PROP_AUTO_EXPR_FUNC:
711 wb_view_auto_expr_func (wbv, g_value_get_boxed (value));
712 break;
713 case PROP_AUTO_EXPR_DESCR:
714 wb_view_auto_expr_descr (wbv, g_value_get_string (value));
715 break;
716 case PROP_AUTO_EXPR_MAX_PRECISION:
717 wb_view_auto_expr_precision (wbv, g_value_get_boolean (value));
718 break;
719 case PROP_AUTO_EXPR_VALUE:
720 wb_view_auto_expr_value (wbv, g_value_get_boxed (value));
721 break;
722 case PROP_AUTO_EXPR_EVAL_POS:
723 wb_view_auto_expr_eval_pos (wbv, g_value_get_boxed (value));
724 break;
725 case PROP_SHOW_HORIZONTAL_SCROLLBAR:
726 wbv->show_horizontal_scrollbar = !!g_value_get_boolean (value);
727 break;
728 case PROP_SHOW_VERTICAL_SCROLLBAR:
729 wbv->show_vertical_scrollbar = !!g_value_get_boolean (value);
730 break;
731 case PROP_SHOW_NOTEBOOK_TABS:
732 wbv->show_notebook_tabs = !!g_value_get_boolean (value);
733 break;
734 case PROP_SHOW_FUNCTION_CELL_MARKERS:
735 wbv->show_function_cell_markers = !!g_value_get_boolean (value);
736 if (wbv->current_sheet)
737 sheet_redraw_all (wbv->current_sheet, FALSE);
738 break;
739 case PROP_SHOW_EXTENSION_MARKERS:
740 wbv->show_extension_markers = !!g_value_get_boolean (value);
741 if (wbv->current_sheet)
742 sheet_redraw_all (wbv->current_sheet, FALSE);
743 break;
744 case PROP_DO_AUTO_COMPLETION:
745 wbv->do_auto_completion = !!g_value_get_boolean (value);
746 break;
747 case PROP_PROTECTED:
748 wbv->is_protected = !!g_value_get_boolean (value);
749 break;
750 case PROP_PREFERRED_WIDTH:
751 wbv->preferred_width = g_value_get_int (value);
752 break;
753 case PROP_PREFERRED_HEIGHT:
754 wbv->preferred_height = g_value_get_int (value);
755 break;
756 case PROP_WORKBOOK:
757 wbv->wb = g_value_dup_object (value);
758 break;
759 default:
760 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
761 break;
765 static void
766 wb_view_get_property (GObject *object, guint property_id,
767 GValue *value, GParamSpec *pspec)
769 WorkbookView *wbv = (WorkbookView *)object;
771 switch (property_id) {
772 case PROP_AUTO_EXPR_FUNC:
773 g_value_set_boxed (value, wbv->auto_expr.func);
774 break;
775 case PROP_AUTO_EXPR_DESCR:
776 g_value_set_string (value, wbv->auto_expr.descr);
777 break;
778 case PROP_AUTO_EXPR_MAX_PRECISION:
779 g_value_set_boolean (value, wbv->auto_expr.use_max_precision);
780 break;
781 case PROP_AUTO_EXPR_VALUE:
782 g_value_set_boxed (value, wbv->auto_expr.value);
783 break;
784 case PROP_SHOW_HORIZONTAL_SCROLLBAR:
785 g_value_set_boolean (value, wbv->show_horizontal_scrollbar);
786 break;
787 case PROP_SHOW_VERTICAL_SCROLLBAR:
788 g_value_set_boolean (value, wbv->show_vertical_scrollbar);
789 break;
790 case PROP_SHOW_NOTEBOOK_TABS:
791 g_value_set_boolean (value, wbv->show_notebook_tabs);
792 break;
793 case PROP_SHOW_FUNCTION_CELL_MARKERS:
794 g_value_set_boolean (value, wbv->show_function_cell_markers);
795 break;
796 case PROP_SHOW_EXTENSION_MARKERS:
797 g_value_set_boolean (value, wbv->show_extension_markers);
798 break;
799 case PROP_DO_AUTO_COMPLETION:
800 g_value_set_boolean (value, wbv->do_auto_completion);
801 break;
802 case PROP_PROTECTED:
803 g_value_set_boolean (value, wbv->is_protected);
804 break;
805 case PROP_PREFERRED_WIDTH:
806 g_value_set_int (value, wbv->preferred_width);
807 break;
808 case PROP_PREFERRED_HEIGHT:
809 g_value_set_int (value, wbv->preferred_height);
810 break;
811 case PROP_WORKBOOK:
812 g_value_set_object (value, wbv->wb);
813 break;
814 default:
815 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
816 break;
820 void
821 wb_view_detach_from_workbook (WorkbookView *wbv)
823 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
825 if (wbv->wb) {
826 workbook_detach_view (wbv);
827 wbv->wb = NULL;
828 wbv->current_sheet = NULL;
832 static GObject *
833 wb_view_constructor (GType type,
834 guint n_construct_properties,
835 GObjectConstructParam *construct_params)
837 GObject *obj;
838 WorkbookView *wbv;
839 int i;
841 obj = parent_class->constructor
842 (type, n_construct_properties, construct_params);
843 wbv = GNM_WORKBOOK_VIEW (obj);
845 if (wbv->wb == NULL)
846 wbv->wb = workbook_new ();
848 workbook_attach_view (wbv);
850 for (i = 0 ; i < workbook_sheet_count (wbv->wb); i++)
851 wb_view_sheet_add (wbv, workbook_sheet_by_index (wbv->wb, i));
853 if (wbv->auto_expr.func == NULL) {
854 wb_view_auto_expr_func (wbv, gnm_func_lookup ("sum", NULL));
855 wb_view_auto_expr_descr (wbv, _("Sum"));
858 return obj;
861 static void
862 wb_view_dispose (GObject *object)
864 WorkbookView *wbv = GNM_WORKBOOK_VIEW (object);
866 if (wbv->wb_controls != NULL) {
867 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control, {
868 wb_control_sheet_remove_all (control);
869 wb_view_detach_control (control);
870 g_object_unref (control);
872 if (wbv->wb_controls != NULL)
873 g_warning ("Unexpected left-over controls");
876 /* The order of these are important. Make sure not to leak the value. */
877 wb_view_auto_expr_descr (wbv, NULL);
878 wb_view_auto_expr_eval_pos (wbv, NULL);
879 wb_view_auto_expr_func (wbv, NULL);
880 wb_view_auto_expr_value (wbv, NULL);
882 wb_view_detach_from_workbook (wbv);
884 if (wbv->current_style != NULL) {
885 gnm_style_unref (wbv->current_style);
886 wbv->current_style = NULL;
888 if (wbv->in_cell_combo != NULL) {
889 sheet_object_clear_sheet (wbv->in_cell_combo);
890 g_object_unref (wbv->in_cell_combo);
891 wbv->in_cell_combo = NULL;
894 parent_class->dispose (object);
898 static void
899 workbook_view_class_init (GObjectClass *gobject_class)
901 parent_class = g_type_class_peek_parent (gobject_class);
903 gobject_class->constructor = wb_view_constructor;
904 gobject_class->set_property = wb_view_set_property;
905 gobject_class->get_property = wb_view_get_property;
906 gobject_class->dispose = wb_view_dispose;
908 g_object_class_install_property
909 (gobject_class,
910 PROP_AUTO_EXPR_FUNC,
911 g_param_spec_object ("auto-expr-func",
912 P_("Auto-expression function"),
913 P_("The automatically computed sheet function."),
914 GNM_FUNC_TYPE,
915 GSF_PARAM_STATIC |
916 G_PARAM_READWRITE));
917 g_object_class_install_property
918 (gobject_class,
919 PROP_AUTO_EXPR_DESCR,
920 g_param_spec_string ("auto-expr-descr",
921 P_("Auto-expression description"),
922 P_("Description of the automatically computed sheet function."),
923 NULL,
924 GSF_PARAM_STATIC |
925 G_PARAM_READWRITE));
926 g_object_class_install_property
927 (gobject_class,
928 PROP_AUTO_EXPR_MAX_PRECISION,
929 g_param_spec_boolean ("auto-expr-max-precision",
930 P_("Auto-expression maximum precision"),
931 P_("Use maximum available precision for auto-expressions"),
932 FALSE,
933 GSF_PARAM_STATIC |
934 G_PARAM_READWRITE));
935 g_object_class_install_property
936 (gobject_class,
937 PROP_AUTO_EXPR_VALUE,
938 g_param_spec_boxed ("auto-expr-value",
939 P_("Auto-expression value"),
940 P_("The current value of the auto-expression."),
941 gnm_value_get_type (),
942 GSF_PARAM_STATIC |
943 G_PARAM_READWRITE));
944 g_object_class_install_property
945 (gobject_class,
946 PROP_AUTO_EXPR_EVAL_POS,
947 g_param_spec_boxed ("auto-expr-eval-pos",
948 P_("Auto-expression position"),
949 P_("The cell position to track."),
950 gnm_eval_pos_get_type (),
951 GSF_PARAM_STATIC |
952 G_PARAM_WRITABLE));
953 g_object_class_install_property
954 (gobject_class,
955 PROP_SHOW_HORIZONTAL_SCROLLBAR,
956 g_param_spec_boolean ("show-horizontal-scrollbar",
957 P_("Show horizontal scrollbar"),
958 P_("Show the horizontal scrollbar"),
959 TRUE,
960 GSF_PARAM_STATIC |
961 G_PARAM_READWRITE));
962 g_object_class_install_property
963 (gobject_class,
964 PROP_SHOW_VERTICAL_SCROLLBAR,
965 g_param_spec_boolean ("show-vertical-scrollbar",
966 P_("Show vertical scrollbar"),
967 P_("Show the vertical scrollbar"),
968 TRUE,
969 GSF_PARAM_STATIC |
970 G_PARAM_READWRITE));
971 g_object_class_install_property
972 (gobject_class,
973 PROP_SHOW_NOTEBOOK_TABS,
974 g_param_spec_boolean ("show-notebook-tabs",
975 P_("Show notebook tabs"),
976 P_("Show the notebook tabs for sheets"),
977 TRUE,
978 GSF_PARAM_STATIC |
979 G_PARAM_READWRITE));
980 g_object_class_install_property
981 (gobject_class,
982 PROP_SHOW_FUNCTION_CELL_MARKERS,
983 g_param_spec_boolean ("show-function-cell-markers",
984 P_("Show formula cell markers"),
985 P_("Mark each cell containing a formula"),
986 FALSE,
987 GSF_PARAM_STATIC |
988 G_PARAM_READWRITE));
989 g_object_class_install_property
990 (gobject_class,
991 PROP_SHOW_EXTENSION_MARKERS,
992 g_param_spec_boolean ("show-extension-markers",
993 P_("Show extension markers"),
994 P_("Mark each cell that fails to show the complete content"),
995 FALSE,
996 GSF_PARAM_STATIC |
997 G_PARAM_READWRITE));
998 g_object_class_install_property
999 (gobject_class,
1000 PROP_DO_AUTO_COMPLETION,
1001 g_param_spec_boolean ("do-auto-completion",
1002 P_("Do auto completion"),
1003 P_("Auto-complete text"),
1004 FALSE,
1005 GSF_PARAM_STATIC |
1006 G_PARAM_READWRITE));
1007 g_object_class_install_property
1008 (gobject_class,
1009 PROP_PROTECTED,
1010 g_param_spec_boolean ("protected",
1011 P_("Protected"),
1012 P_("Is view protected?"),
1013 FALSE,
1014 GSF_PARAM_STATIC |
1015 G_PARAM_READWRITE));
1016 g_object_class_install_property
1017 (gobject_class,
1018 PROP_PREFERRED_WIDTH,
1019 g_param_spec_int ("preferred-width",
1020 P_("Preferred width"),
1021 P_("Preferred width"),
1022 1, G_MAXINT, 1024,
1023 GSF_PARAM_STATIC |
1024 G_PARAM_READWRITE));
1025 g_object_class_install_property
1026 (gobject_class,
1027 PROP_PREFERRED_HEIGHT,
1028 g_param_spec_int ("preferred-height",
1029 P_("Preferred height"),
1030 P_("Preferred height"),
1031 1, G_MAXINT, 768,
1032 GSF_PARAM_STATIC |
1033 G_PARAM_READWRITE));
1034 g_object_class_install_property
1035 (gobject_class,
1036 PROP_WORKBOOK,
1037 g_param_spec_object ("workbook",
1038 P_("Workbook"),
1039 P_("Workbook"),
1040 GNM_WORKBOOK_TYPE,
1041 GSF_PARAM_STATIC |
1042 G_PARAM_CONSTRUCT_ONLY |
1043 G_PARAM_READWRITE));
1045 parent_class = g_type_class_peek_parent (gobject_class);
1048 static void
1049 workbook_view_init (WorkbookView *wbv)
1051 wbv->show_horizontal_scrollbar = TRUE;
1052 wbv->show_vertical_scrollbar = TRUE;
1053 wbv->show_notebook_tabs = TRUE;
1054 wbv->show_function_cell_markers =
1055 gnm_conf_get_core_gui_cells_function_markers ();
1056 wbv->show_extension_markers =
1057 gnm_conf_get_core_gui_cells_extension_markers ();
1058 wbv->do_auto_completion =
1059 gnm_conf_get_core_gui_editing_autocomplete ();
1060 wbv->is_protected = FALSE;
1062 dependent_managed_init (&wbv->auto_expr.dep, NULL);
1065 GSF_CLASS (WorkbookView, workbook_view,
1066 workbook_view_class_init, workbook_view_init, GO_TYPE_VIEW)
1069 * workbook_view_new:
1070 * @wb: (allow-none) (transfer full): #Workbook
1072 * Returns: A new #WorkbookView for @wb (or a fresh one if that is %NULL).
1074 WorkbookView *
1075 workbook_view_new (Workbook *wb)
1077 WorkbookView *wbv =
1078 g_object_new (GNM_WORKBOOK_VIEW_TYPE, "workbook", wb, NULL);
1079 if (wb) g_object_unref (wb);
1081 return wbv;
1085 * workbook_view_save_to_output:
1086 * @wbv: #WorkbookView
1087 * @fs: #GOFileSaver
1088 * @output: #GsfOutput
1089 * @io_context: #GOIOContext
1091 * NOTE : Temporary api until we get the new output framework.
1093 void
1094 workbook_view_save_to_output (WorkbookView *wbv, GOFileSaver const *fs,
1095 GsfOutput *output, GOIOContext *io_context)
1097 GError const *err;
1098 char const *msg;
1099 GODoc *godoc = wb_view_get_doc (wbv);
1101 if (go_doc_is_dirty (godoc))
1102 /* FIXME: we should be using the true modification time */
1103 gnm_insert_meta_date (godoc, GSF_META_NAME_DATE_MODIFIED);
1104 go_file_saver_save (fs, io_context, GO_VIEW (wbv), output);
1106 /* The plugin convention is unclear */
1107 if (!gsf_output_is_closed (output))
1108 gsf_output_close (output);
1110 if (NULL == (err = gsf_output_error (output)))
1111 return;
1112 if (NULL == (msg = err->message))
1113 msg = _("An unexplained error happened while saving.");
1114 g_printerr (" ==> %s\n", msg);
1115 if (!go_io_error_occurred (io_context))
1116 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context), msg);
1120 * workbook_view_save_to_uri:
1121 * @wbv: #WorkbookView
1122 * @fs: #GOFileSaver
1123 * @uri: destination URI
1124 * @io_context: #GOIOContext
1127 void
1128 workbook_view_save_to_uri (WorkbookView *wbv, GOFileSaver const *fs,
1129 char const *uri, GOIOContext *io_context)
1131 char *msg = NULL;
1132 GError *err = NULL;
1133 GsfOutput *output = go_file_create (uri, &err);
1135 if (output == NULL) {
1136 if (NULL != err) {
1137 msg = g_strdup_printf (_("Can't open '%s' for writing: %s"),
1138 uri, err->message);
1139 g_error_free (err);
1140 } else
1141 msg = g_strdup_printf (_("Can't open '%s' for writing"), uri);
1143 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context), msg);
1144 g_free (msg);
1145 } else {
1146 workbook_view_save_to_output (wbv, fs, output, io_context);
1147 g_object_unref (output);
1151 static GDateTime *
1152 get_uri_modtime (GsfInput *input, const char *uri)
1154 GDateTime *modtime = NULL;
1156 if (input) {
1157 modtime = gsf_input_get_modtime (input);
1158 if (modtime)
1159 g_date_time_ref (modtime);
1162 if (!modtime && uri)
1163 modtime = go_file_get_modtime (uri);
1165 if (gnm_debug_flag ("modtime")) {
1166 char *s = modtime
1167 ? g_date_time_format (modtime, "%F %T")
1168 : g_strdup ("?");
1169 g_printerr ("Modtime of %s is %s\n", uri, s);
1170 g_free (s);
1173 return modtime;
1177 * workbook_view_save_as:
1178 * @wbv: Workbook View
1179 * @fs: GOFileSaver object
1180 * @uri: URI to save as.
1181 * @cc: The #GOCmdContext that invoked the operation
1183 * Saves @wbv and workbook it's attached to into @uri file using
1184 * @fs file saver. If the format sufficiently advanced make it the saver
1185 * and update the uri.
1187 * Return value: %TRUE if file was successfully saved and %FALSE otherwise.
1189 gboolean
1190 workbook_view_save_as (WorkbookView *wbv, GOFileSaver *fs, char const *uri,
1191 GOCmdContext *cc)
1193 GOIOContext *io_context;
1194 Workbook *wb;
1195 gboolean has_error, has_warning;
1197 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), FALSE);
1198 g_return_val_if_fail (GO_IS_FILE_SAVER (fs), FALSE);
1199 g_return_val_if_fail (uri != NULL, FALSE);
1200 g_return_val_if_fail (GO_IS_CMD_CONTEXT (cc), FALSE);
1202 wb = wb_view_get_workbook (wbv);
1203 g_object_ref (wb);
1204 io_context = go_io_context_new (cc);
1206 go_cmd_context_set_sensitive (cc, FALSE);
1207 workbook_view_save_to_uri (wbv, fs, uri, io_context);
1208 go_cmd_context_set_sensitive (cc, TRUE);
1210 has_error = go_io_error_occurred (io_context);
1211 has_warning = go_io_warning_occurred (io_context);
1212 if (!has_error) {
1213 GOFileFormatLevel fl = go_file_saver_get_format_level (fs);
1214 if (workbook_set_saveinfo (wb, fl, fs)) {
1215 if (go_doc_set_uri (GO_DOC (wb), uri)) {
1216 GDateTime *modtime;
1218 go_doc_set_dirty (GO_DOC (wb), FALSE);
1219 /* See 634792. */
1220 go_doc_set_pristine (GO_DOC (wb), FALSE);
1222 modtime = get_uri_modtime (NULL, uri);
1223 go_doc_set_modtime (GO_DOC (wb), modtime);
1224 if (gnm_debug_flag ("modtime"))
1225 g_printerr ("Modtime set\n");
1226 g_date_time_unref (modtime);
1228 } else
1229 workbook_set_last_export_uri (wb, uri);
1231 if (has_error || has_warning)
1232 go_io_error_display (io_context);
1233 g_object_unref (io_context);
1234 g_object_unref (wb);
1236 return !has_error;
1240 * workbook_view_save:
1241 * @wbv: The view to save.
1242 * @cc: The #GOCmdContext that invoked the operation
1244 * Saves @wbv and workbook it's attached to into file assigned to the
1245 * workbook using workbook's file saver. If the workbook has no file
1246 * saver assigned to it, default file saver is used instead.
1248 * Return value: %TRUE if file was successfully saved and %FALSE otherwise.
1250 gboolean
1251 workbook_view_save (WorkbookView *wbv, GOCmdContext *context)
1253 GOIOContext *io_context;
1254 Workbook *wb;
1255 GOFileSaver *fs;
1256 gboolean has_error, has_warning;
1257 char const *uri;
1259 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), FALSE);
1260 g_return_val_if_fail (GO_IS_CMD_CONTEXT (context), FALSE);
1262 wb = wb_view_get_workbook (wbv);
1263 g_object_ref (wb);
1264 uri = go_doc_get_uri (GO_DOC (wb));
1266 fs = workbook_get_file_saver (wb);
1267 if (fs == NULL)
1268 fs = go_file_saver_get_default ();
1270 io_context = go_io_context_new (context);
1271 if (fs == NULL)
1272 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context),
1273 _("Default file saver is not available."));
1274 else {
1275 char const *uri = go_doc_get_uri (GO_DOC (wb));
1276 workbook_view_save_to_uri (wbv, fs, uri, io_context);
1279 has_error = go_io_error_occurred (io_context);
1280 has_warning = go_io_warning_occurred (io_context);
1281 if (!has_error) {
1282 GDateTime *modtime = get_uri_modtime (NULL, uri);
1283 go_doc_set_modtime (GO_DOC (wb), modtime);
1284 if (gnm_debug_flag ("modtime"))
1285 g_printerr ("Modtime set\n");
1286 g_date_time_unref (modtime);
1287 go_doc_set_dirty (GO_DOC (wb), FALSE);
1289 if (has_error || has_warning)
1290 go_io_error_display (io_context);
1292 g_object_unref (io_context);
1293 g_object_unref (wb);
1295 return !has_error;
1299 * workbook_view_new_from_input:
1300 * @input: #GsfInput to read data from.
1301 * @uri: (allow-none): URI
1302 * @file_opener: (allow-none): #GOFileOpener
1303 * @io_context: (allow-none): Context to display errors.
1304 * @encoding: (allow-none): Encoding for @file_opener that understand it
1306 * Reads @uri file using given file opener @file_opener, or probes for a valid
1307 * possibility if @file_opener is %NULL. Reports problems to @io_context.
1309 * Return value: (transfer full) (nullable): the newly allocated WorkbookView
1310 * or %NULL on error.
1312 WorkbookView *
1313 workbook_view_new_from_input (GsfInput *input,
1314 const char *uri,
1315 GOFileOpener const *file_opener,
1316 GOIOContext *io_context,
1317 char const *encoding)
1319 WorkbookView *new_wbv = NULL;
1321 g_return_val_if_fail (GSF_IS_INPUT(input), NULL);
1322 g_return_val_if_fail (file_opener == NULL ||
1323 GO_IS_FILE_OPENER (file_opener), NULL);
1325 /* NOTE : we could support gzipped anything here if we wanted to
1326 * by adding a wrapper, but there is no framework for remembering that
1327 * the file was gzipped so let's not just yet.
1330 /* Search for an applicable opener */
1331 if (file_opener == NULL) {
1332 GOFileProbeLevel pl;
1333 GList *l;
1334 int input_refs = G_OBJECT (input)->ref_count;
1336 for (pl = GO_FILE_PROBE_FILE_NAME; pl < GO_FILE_PROBE_LAST && file_opener == NULL; pl++) {
1337 for (l = go_get_file_openers (); l != NULL; l = l->next) {
1338 GOFileOpener const *tmp_fo = GO_FILE_OPENER (l->data);
1339 int new_input_refs;
1340 /* A name match needs to be a content match too */
1341 if (go_file_opener_probe (tmp_fo, input, pl) &&
1342 (pl == GO_FILE_PROBE_CONTENT ||
1343 !go_file_opener_can_probe (tmp_fo, GO_FILE_PROBE_CONTENT) ||
1344 go_file_opener_probe (tmp_fo, input, GO_FILE_PROBE_CONTENT)))
1345 file_opener = tmp_fo;
1347 new_input_refs = G_OBJECT (input)->ref_count;
1348 if (new_input_refs != input_refs) {
1349 g_warning ("Format %s's probe changed input ref_count from %d to %d.",
1350 go_file_opener_get_id (tmp_fo),
1351 input_refs,
1352 new_input_refs);
1353 input_refs = new_input_refs;
1356 if (file_opener)
1357 break;
1362 if (file_opener != NULL) {
1363 Workbook *new_wb;
1364 gboolean old;
1365 GDateTime *modtime;
1367 new_wbv = workbook_view_new (NULL);
1368 new_wb = wb_view_get_workbook (new_wbv);
1369 if (uri)
1370 go_doc_set_uri (GO_DOC (new_wb), uri);
1372 // Grab the modtime before we actually do the reading
1373 modtime = get_uri_modtime (input, uri);
1374 go_doc_set_modtime (GO_DOC (new_wb), modtime);
1375 if (modtime)
1376 g_date_time_unref (modtime);
1378 /* disable recursive dirtying while loading */
1379 old = workbook_enable_recursive_dirty (new_wb, FALSE);
1380 go_file_opener_open (file_opener, encoding, io_context,
1381 GO_VIEW (new_wbv), input);
1382 workbook_enable_recursive_dirty (new_wb, old);
1384 if (go_io_error_occurred (io_context)) {
1385 g_object_unref (new_wb);
1386 new_wbv = NULL;
1387 } else if (workbook_sheet_count (new_wb) == 0) {
1388 /* we didn't get a sheet nor an error, */
1389 /* the user must have canceled */
1390 g_object_unref (new_wb);
1391 new_wbv = NULL;
1392 } else {
1393 workbook_share_expressions (new_wb, TRUE);
1394 workbook_optimize_style (new_wb);
1395 workbook_queue_volatile_recalc (new_wb);
1396 workbook_recalc (new_wb);
1397 workbook_update_graphs (new_wb);
1398 go_doc_set_dirty (GO_DOC (new_wb), FALSE);
1399 if (uri && workbook_get_file_exporter (new_wb))
1400 workbook_set_last_export_uri
1401 (new_wb, uri);
1403 } else {
1404 if (io_context)
1405 go_cmd_context_error_import
1406 (GO_CMD_CONTEXT (io_context),
1407 _("Unsupported file format."));
1410 return new_wbv;
1414 * workbook_view_new_from_uri:
1415 * @uri: URI for file
1416 * @file_opener: (allow-none): #GOFileOpener
1417 * @io_context: Context to display errors.
1418 * @encoding: (allow-none): Encoding for @file_opener that understands it
1420 * Reads @uri file using given file opener @file_opener, or probes for a valid
1421 * possibility if @file_opener is %NULL. Reports problems to @io_context.
1423 * Return value: (transfer full) (nullable): the newly allocated WorkbookView
1424 * or %NULL on error.
1426 WorkbookView *
1427 workbook_view_new_from_uri (char const *uri,
1428 GOFileOpener const *file_opener,
1429 GOIOContext *io_context,
1430 char const *encoding)
1432 char *msg = NULL;
1433 GError *err = NULL;
1434 GsfInput *input;
1436 g_return_val_if_fail (uri != NULL, NULL);
1438 input = go_file_open (uri, &err);
1439 if (input != NULL) {
1440 WorkbookView *res;
1442 res = workbook_view_new_from_input (input, uri,
1443 file_opener, io_context,
1444 encoding);
1445 g_object_unref (input);
1446 return res;
1449 if (err != NULL) {
1450 if (err->message != NULL)
1451 msg = g_strdup (err->message);
1452 g_error_free (err);
1455 if (msg == NULL)
1456 msg = g_strdup_printf (_("An unexplained error happened while opening %s"),
1457 uri);
1459 if (io_context)
1460 go_cmd_context_error_import (GO_CMD_CONTEXT (io_context), msg);
1461 g_free (msg);
1463 return NULL;