Code cleanup
[gnumeric.git] / src / workbook-view.c
blobc88bf6299c9b0f75b82a4c0b904ad8279501a281
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * workbook-view.c: View functions for the workbook
5 * Copyright (C) 2000-2006 Jody Goldberg (jody@gnome.org)
6 * Copyright (C) 2012 Morten Welinder (terra@gnome.org)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21 * USA
23 #include <gnumeric-config.h>
24 #include "gnumeric.h"
25 #include "workbook-view.h"
27 #include "workbook-control-priv.h"
28 #include "workbook-priv.h"
29 #include "application.h"
30 #include "sheet.h"
31 #include "sheet-view.h"
32 #include "sheet-merge.h"
33 #include "sheet-style.h"
34 #include "func.h"
35 #include "expr.h"
36 #include "expr-name.h"
37 #include "value.h"
38 #include "ranges.h"
39 #include "selection.h"
40 #include "mstyle.h"
41 #include "validation.h"
42 #include "validation-combo.h"
43 #include "gnm-sheet-slicer.h"
44 #include "gnm-sheet-slicer-combo.h"
45 #include "position.h"
46 #include "cell.h"
47 #include "gutils.h"
48 #include "command-context.h"
49 #include "auto-format.h"
50 #include "sheet-object.h"
51 #include "gnumeric-conf.h"
53 #include <goffice/goffice.h>
54 #include <gsf/gsf-meta-names.h>
55 #include <gsf/gsf-impl-utils.h>
56 #include <gsf/gsf-output-stdio.h>
57 #include <gsf/gsf-input.h>
58 #include "gnm-i18n.h"
59 #include <glib/gstdio.h>
60 #include <string.h>
61 #include <unistd.h>
62 #include <stdlib.h>
63 #include "mathfunc.h"
65 #ifdef G_OS_WIN32
66 #include <windows.h>
67 #endif
69 /**
70 * WorkbookView:
71 * @wb_controls: (element-type WorkbookControl):
72 **/
73 enum {
74 PROP_0,
75 PROP_AUTO_EXPR_FUNC,
76 PROP_AUTO_EXPR_DESCR,
77 PROP_AUTO_EXPR_MAX_PRECISION,
78 PROP_AUTO_EXPR_VALUE,
79 PROP_AUTO_EXPR_EVAL_POS,
80 PROP_SHOW_HORIZONTAL_SCROLLBAR,
81 PROP_SHOW_VERTICAL_SCROLLBAR,
82 PROP_SHOW_NOTEBOOK_TABS,
83 PROP_SHOW_FUNCTION_CELL_MARKERS,
84 PROP_SHOW_EXTENSION_MARKERS,
85 PROP_DO_AUTO_COMPLETION,
86 PROP_PROTECTED,
87 PROP_PREFERRED_WIDTH,
88 PROP_PREFERRED_HEIGHT,
89 PROP_WORKBOOK
92 /* WorkbookView signals */
93 enum {
94 LAST_SIGNAL
97 /**
98 * wb_view_get_workbook:
99 * @wbv: #WorkbookView
101 * Returns: (transfer none): the #Workbook associated with @wbv
103 Workbook *
104 wb_view_get_workbook (WorkbookView const *wbv)
106 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
107 return wbv->wb;
111 * wb_view_get_doc:
112 * @wbv: #WorkbookView
114 * Returns: (transfer none): the #Workbook associated with @wbv cast to a #GODoc
116 GODoc *
117 wb_view_get_doc (WorkbookView const *wbv)
119 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
120 return GO_DOC (wbv->wb);
124 * wb_view_get_index_in_wb:
125 * @wbv: #WorkbookView
127 * Returns 0 based index of wbv within workbook, or -1 if there is no workbook.
130 wb_view_get_index_in_wb (WorkbookView const *wbv)
132 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), -1);
133 if (NULL != wbv->wb) {
134 unsigned i = wbv->wb->wb_views->len;
135 while (i-- > 0)
136 if (g_ptr_array_index (wbv->wb->wb_views, i) == wbv)
137 return i;
139 return -1;
143 * wb_view_cur_sheet:
144 * @wbv: #WorkbookView
146 * Returns: (transfer none): the current sheet.
148 Sheet *
149 wb_view_cur_sheet (WorkbookView const *wbv)
151 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
152 return wbv->current_sheet;
156 * wb_view_cur_sheet_view:
157 * @wbv: #WorkbookView
159 * Returns: (transfer none): the current sheet view.
161 SheetView *
162 wb_view_cur_sheet_view (WorkbookView const *wbv)
164 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), NULL);
165 return wbv->current_sheet_view;
168 void
169 wb_view_sheet_focus (WorkbookView *wbv, Sheet *sheet)
171 if (wbv->current_sheet != sheet) {
172 /* Make sure the sheet has been attached */
173 g_return_if_fail (sheet == NULL || sheet->index_in_wb >= 0);
175 #if 0
176 g_print ("Focus %s\n", sheet ? sheet->name_quoted : "-");
177 #endif
179 wbv->current_sheet = sheet;
180 wbv->current_sheet_view = sheet_get_view (sheet, wbv);
182 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control,
183 wb_control_sheet_focus (control, sheet););
185 wb_view_selection_desc (wbv, TRUE, NULL);
186 wb_view_edit_line_set (wbv, NULL);
187 wb_view_style_feedback (wbv);
188 wb_view_menus_update (wbv);
189 wb_view_auto_expr_recalc (wbv);
193 void
194 wb_view_sheet_add (WorkbookView *wbv, Sheet *new_sheet)
196 SheetView *new_view;
198 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
200 new_view = gnm_sheet_view_new (new_sheet, wbv);
202 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control,
203 wb_control_sheet_add (control, new_view););
205 g_object_unref (new_view);
207 if (wbv->current_sheet == NULL)
208 wb_view_sheet_focus (wbv, new_sheet);
211 gboolean
212 wb_view_is_protected (WorkbookView *wbv, gboolean check_sheet)
214 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), FALSE);
216 return wbv->is_protected || (check_sheet &&
217 wbv->current_sheet != NULL && wbv->current_sheet->is_protected);
220 void
221 wb_view_set_attribute (WorkbookView *wbv, char const *name, char const *value)
223 gboolean res;
224 GObject *obj;
225 const char *tname;
227 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
228 g_return_if_fail (name != NULL);
229 g_return_if_fail (value != NULL);
231 obj = G_OBJECT (wbv);
232 res = !g_ascii_strcasecmp (value, "TRUE");
234 if (strncmp (name, "WorkbookView::", 14) == 0)
235 tname = name + 14;
236 else if (strncmp (name, "Workbook::", 10) == 0)
237 /* Some old files have this. */
238 tname = name + 10;
239 else
240 tname = "nope";
242 if (!strcmp (tname , "show_horizontal_scrollbar"))
243 g_object_set (obj, "show_horizontal_scrollbar", res, NULL);
244 else if (!strcmp (tname , "show_vertical_scrollbar"))
245 g_object_set (obj, "show_vertical_scrollbar", res, NULL);
246 else if (!strcmp (tname , "show_notebook_tabs"))
247 g_object_set (obj, "show_notebook_tabs", res, NULL);
248 else if (!strcmp (tname , "show_function_cell_markers"))
249 g_object_set (obj, "show_function_cell_markers", res, NULL);
250 else if (!strcmp (tname , "show_extension_markers"))
251 g_object_set (obj, "show_extension_markers", res, NULL);
252 else if (!strcmp (tname , "do_auto_completion"))
253 g_object_set (obj, "do_auto_completion", res, NULL);
254 else if (!strcmp (tname , "is_protected"))
255 g_object_set (obj, "protected", res, NULL);
256 else
257 g_warning ("WorkbookView unknown arg '%s'", name);
260 void
261 wb_view_preferred_size (WorkbookView *wbv, int w, int h)
263 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
265 if (w <= 0)
266 w = 768; /* use default */
267 if (h <= 0)
268 h = 768; /* use default */
270 g_object_set (G_OBJECT (wbv),
271 "preferred-width", w,
272 "preferred-height", h,
273 NULL);
276 void
277 wb_view_style_feedback (WorkbookView *wbv)
279 SheetView *sv;
280 GnmStyle const *style;
281 GnmSheetSlicer const *dslicer;
282 GODataSlicerField *dsfield;
283 GnmValidation const *val;
284 GOFormat const *fmt_style, *fmt_cell;
285 GnmCell *cell;
286 gboolean update_controls = TRUE;
288 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
290 sv = wbv->current_sheet_view;
291 if (sv == NULL)
292 return;
294 style = sheet_style_get (sv->sheet,
295 sv->edit_pos.col, sv->edit_pos.row);
296 fmt_style = gnm_style_get_format (style);
297 if (go_format_is_general (fmt_style) &&
298 (cell = sheet_cell_get (sv->sheet, sv->edit_pos.col, sv->edit_pos.row)) &&
299 cell->value && VALUE_FMT (cell->value))
300 fmt_cell = VALUE_FMT (cell->value);
301 else
302 fmt_cell = fmt_style;
304 if (go_format_eq (fmt_cell, fmt_style)) {
305 if (style == wbv->current_style)
306 update_controls = FALSE;
307 gnm_style_ref (style);
308 } else {
309 GnmStyle *tmp = gnm_style_dup (style);
310 gnm_style_set_format (tmp, fmt_cell);
311 style = tmp;
314 if (wbv->current_style != NULL)
315 gnm_style_unref (wbv->current_style);
316 wbv->current_style = style;
318 if (wbv->in_cell_combo != NULL) {
319 sheet_object_clear_sheet (wbv->in_cell_combo);
320 g_object_unref (wbv->in_cell_combo);
321 wbv->in_cell_combo = NULL;
324 if (gnm_style_is_element_set (style, MSTYLE_VALIDATION) &&
325 NULL != (val = gnm_style_get_validation (style)) &&
326 val->type == GNM_VALIDATION_TYPE_IN_LIST &&
327 val->use_dropdown)
328 wbv->in_cell_combo = gnm_validation_combo_new (val, sv);
329 else if (NULL != (dslicer = gnm_sheet_slicers_at_pos (sv->sheet, &sv->edit_pos)) &&
330 NULL != (dsfield = gnm_sheet_slicer_field_header_at_pos (dslicer, &sv->edit_pos)))
331 wbv->in_cell_combo = g_object_new (gnm_sheet_slicer_combo_get_type (),
332 "sheet-view", sv,
333 "field", dsfield,
334 NULL);
336 if (NULL != wbv->in_cell_combo)
338 const double a_offsets [4] = { 0., 0., 1., 1. };
339 SheetObjectAnchor anchor;
340 GnmRange corner;
341 GnmRange const *r;
342 if (NULL == (r = gnm_sheet_merge_contains_pos (sv->sheet, &sv->edit_pos)))
343 r = range_init_cellpos (&corner, &sv->edit_pos);
344 sheet_object_anchor_init (&anchor, r, a_offsets, GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
345 sheet_object_set_anchor (wbv->in_cell_combo, &anchor);
346 sheet_object_set_sheet (wbv->in_cell_combo, sv->sheet);
349 if (update_controls) {
350 WORKBOOK_VIEW_FOREACH_CONTROL(wbv, control,
351 wb_control_style_feedback (control, NULL););
355 void
356 wb_view_menus_update (WorkbookView *wbv)
358 Sheet *sheet;
360 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
362 sheet = wbv->current_sheet;
363 if (sheet != NULL) {
364 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, wbc, {
365 wb_control_menu_state_update (wbc, MS_ALL);
366 wb_control_update_action_sensitivity (wbc);
372 * wb_view_selection_desc:
373 * @wbv: The view
374 * @use_pos:
375 * @wbc: (allow-none): A #WorkbookControl
377 * Load the edit line with the value of the cell in sheet's edit_pos.
379 * Calculate what to display on the edit line then display it either in the
380 * control @wbc, or if that is %NULL, in all controls.
382 void
383 wb_view_selection_desc (WorkbookView *wbv, gboolean use_pos,
384 WorkbookControl *wbc)
386 SheetView *sv;
388 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
390 sv = wbv->current_sheet_view;
391 if (sv != NULL) {
392 char buffer [10 + 2 * 4 * sizeof (int)];
393 char const *sel_descr = buffer;
394 GnmRange const *r, *m;
396 g_return_if_fail (GNM_IS_SHEET_VIEW (sv));
397 g_return_if_fail (sv->selections);
399 r = selection_first_range (sv, NULL, NULL);
401 if (use_pos || range_is_singleton (r) ||
402 (NULL != (m = gnm_sheet_merge_is_corner (sv->sheet, &r->start)) &&
403 range_equal (r, m))) {
404 sel_descr = sheet_names_check (sv->sheet, r);
405 if (sel_descr == NULL) {
406 GnmParsePos pp;
407 parse_pos_init_editpos (&pp, sv);
408 sel_descr = parsepos_as_string (&pp);
410 } else {
411 int rows = r->end.row - r->start.row + 1;
412 int cols = r->end.col - r->start.col + 1;
414 if (rows == gnm_sheet_get_max_rows (sv->sheet))
415 /* Translators: "%dC" is a very short format to indicate the number of full columns */
416 snprintf (buffer, sizeof (buffer), _("%dC"), cols);
417 else if (cols == gnm_sheet_get_max_cols (sv->sheet))
418 /* Translators: "%dR" is a very short format to indicate the number of full rows */
419 snprintf (buffer, sizeof (buffer), _("%dR"), rows);
420 else
421 /* Translators: "%dR x %dC" is a very short format to indicate the number of rows and columns */
422 snprintf (buffer, sizeof (buffer), _("%dR x %dC"),
423 rows, cols);
426 if (wbc == NULL) {
427 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, wbc,
428 wb_control_selection_descr_set (wbc, sel_descr););
429 } else
430 wb_control_selection_descr_set (wbc, sel_descr);
435 * wb_view_edit_line_set:
436 * @wbv: The view
437 * @wbc: (allow-none): A #WorkbookControl
439 * Load the edit line with the value of the cell in @sheet's edit_pos.
441 * Calculate what to display on the edit line then display it either in the
442 * control @wbc, or if that is %NULL, in all controls.
444 void
445 wb_view_edit_line_set (WorkbookView *wbv, WorkbookControl *wbc)
447 SheetView *sv;
449 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
451 sv = wbv->current_sheet_view;
452 if (sv != NULL) {
453 char *text;
454 Sheet *sheet = sv->sheet;
455 GnmCell const *cell = sheet_cell_get (sheet,
456 sv->edit_pos.col, sv->edit_pos.row);
458 if (NULL != cell) {
459 text = gnm_cell_get_text_for_editing (cell, NULL, NULL);
461 if (gnm_cell_has_expr (cell)) {
462 GnmExprTop const *texpr = cell->base.texpr;
463 GnmCell const *corner = NULL;
464 int x = 0, y = 0;
467 * If this is part of an array we add '{' '}'
468 * and size information to the display. That
469 * is not actually part of the parsable
470 * expression, but it is a useful extension to
471 * the simple '{' '}' that MS excel(tm) uses.
473 if (gnm_expr_top_is_array_corner (texpr))
474 corner = cell;
475 else if (gnm_expr_top_is_array_elem (texpr, &x, &y)) {
476 corner = sheet_cell_get
477 (sheet,
478 cell->pos.col - x,
479 cell->pos.row - y);
482 if (corner) {
483 int cols, rows;
484 char *tmp;
486 gnm_expr_top_get_array_size (corner->base.texpr, &cols, &rows);
488 tmp = g_strdup_printf
489 ("{%s}(%d%c%d)[%d][%d]",
490 text,
491 cols, go_locale_get_arg_sep (), rows,
492 x, y);
493 g_free (text);
494 text = tmp;
497 } else
498 text = g_strdup ("");
500 if (wbc == NULL) {
501 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control,
502 wb_control_edit_line_set (control, text););
503 } else
504 wb_control_edit_line_set (wbc, text);
506 g_free (text);
510 static void
511 accumulate_regions (SheetView *sv, GnmRange const *r, gpointer closure)
513 GnmExprList **selection = closure;
514 GnmCellRef a, b;
516 a.sheet = b.sheet = sv_sheet (sv);
517 a.col_relative = a.row_relative = b.col_relative = b.row_relative = FALSE;
518 a.col = r->start.col;
519 a.row = r->start.row;
520 b.col = r->end.col;
521 b.row = r->end.row;
523 *selection = gnm_expr_list_prepend (*selection,
524 gnm_expr_new_constant (value_new_cellrange_unsafe (&a, &b)));
527 void
528 wb_view_auto_expr_recalc (WorkbookView *wbv)
530 GnmExprList *selection = NULL;
531 GnmValue *v;
532 SheetView *sv;
533 GnmExprTop const *texpr;
534 GnmEvalPos ep;
536 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
538 sv = wb_view_cur_sheet_view (wbv);
539 if (wbv->current_sheet == NULL ||
540 sv == NULL)
541 return;
543 if (wbv->auto_expr.dep.sheet != NULL &&
544 wbv->auto_expr.dep.texpr != NULL) {
545 texpr = wbv->auto_expr.dep.texpr;
546 gnm_expr_top_ref (texpr);
547 } else if (wbv->auto_expr.func != NULL) {
548 sv_selection_apply (sv, &accumulate_regions, FALSE, &selection);
549 texpr = gnm_expr_top_new
550 (gnm_expr_new_funcall (wbv->auto_expr.func, selection));
551 } else {
552 texpr = gnm_expr_top_new_constant (value_new_string (""));
555 eval_pos_init_sheet (&ep, wbv->current_sheet);
557 v = gnm_expr_top_eval (texpr, &ep, GNM_EXPR_EVAL_SCALAR_NON_EMPTY);
558 if (v) {
559 if (wbv->auto_expr.use_max_precision)
560 value_set_fmt (v, NULL);
561 else if (!VALUE_FMT (v)) {
562 GOFormat const *fmt = gnm_auto_style_format_suggest (texpr, &ep);
563 value_set_fmt (v, fmt);
564 go_format_unref (fmt);
567 g_object_set (wbv, "auto-expr-value", v, NULL);
568 value_release (v);
569 gnm_expr_top_unref (texpr);
572 /* perform whatever initialization of a control that is necessary when it
573 * finally gets assigned to a view with a workbook */
574 static void
575 wb_view_init_control (G_GNUC_UNUSED WorkbookControl *wbc)
579 void
580 wb_view_attach_control (WorkbookView *wbv, WorkbookControl *wbc)
582 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
583 g_return_if_fail (GNM_IS_WBC (wbc));
584 g_return_if_fail (wb_control_view (wbc) == NULL);
586 if (wbv->wb_controls == NULL)
587 wbv->wb_controls = g_ptr_array_new ();
588 g_ptr_array_add (wbv->wb_controls, wbc);
589 g_object_set (G_OBJECT (wbc), "view", wbv, NULL);
591 if (wbv->wb != NULL)
592 wb_view_init_control (wbc);
595 void
596 wb_view_detach_control (WorkbookControl *wbc)
598 g_return_if_fail (GNM_IS_WBC (wbc));
599 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wb_control_view (wbc)));
601 g_ptr_array_remove (wbc->wb_view->wb_controls, wbc);
602 if (wbc->wb_view->wb_controls->len == 0) {
603 g_ptr_array_free (wbc->wb_view->wb_controls, TRUE);
604 wbc->wb_view->wb_controls = NULL;
606 g_object_set (G_OBJECT (wbc), "view", NULL, NULL);
609 static GObjectClass *parent_class;
611 static void
612 wb_view_auto_expr_func (WorkbookView *wbv, GnmFunc *func)
614 if (wbv->auto_expr.func == func)
615 return;
617 if (wbv->auto_expr.func)
618 gnm_func_unref (wbv->auto_expr.func);
620 if (func)
621 gnm_func_ref (func);
622 wbv->auto_expr.func = func;
624 wb_view_auto_expr_recalc (wbv);
627 static void
628 wb_view_auto_expr_descr (WorkbookView *wbv, const char *descr)
630 char *s;
632 if (go_str_compare (descr, wbv->auto_expr.descr) == 0)
633 return;
635 s = g_strdup (descr);
636 g_free (wbv->auto_expr.descr);
637 wbv->auto_expr.descr = s;
639 wb_view_auto_expr_recalc (wbv);
642 static void
643 wb_view_auto_expr_precision (WorkbookView *wbv, gboolean use_max_precision)
645 use_max_precision = !!use_max_precision;
647 if (wbv->auto_expr.use_max_precision == use_max_precision)
648 return;
650 wbv->auto_expr.use_max_precision = use_max_precision;
652 wb_view_auto_expr_recalc (wbv);
655 static void
656 wb_view_auto_expr_value (WorkbookView *wbv, const GnmValue *value)
658 value_release (wbv->auto_expr.value);
659 wbv->auto_expr.value = value_dup (value);
662 static void
663 cb_clear_auto_expr_sheet (WorkbookView *wbv)
665 g_object_set (G_OBJECT (wbv),
666 "auto-expr-eval-pos", NULL,
667 NULL);
670 static void
671 wb_view_auto_expr_eval_pos (WorkbookView *wbv, GnmEvalPos const *ep)
673 Sheet *sheet = ep ? ep->sheet : NULL;
675 if (wbv->auto_expr.sheet_detached_sig) {
676 g_signal_handler_disconnect (wbv->auto_expr.dep.sheet,
677 wbv->auto_expr.sheet_detached_sig);
678 wbv->auto_expr.sheet_detached_sig = 0;
681 dependent_set_expr (&wbv->auto_expr.dep, NULL);
682 dependent_managed_set_sheet (&wbv->auto_expr.dep, sheet);
684 if (sheet) {
685 GnmRange r;
686 GnmValue *v;
687 GnmExprTop const *texpr;
689 wbv->auto_expr.sheet_detached_sig = g_signal_connect_swapped (
690 G_OBJECT (sheet),
691 "detached-from-workbook",
692 G_CALLBACK (cb_clear_auto_expr_sheet), wbv);
694 range_init_cellpos (&r, &ep->eval);
695 v = value_new_cellrange_r (sheet, &r);
696 texpr = gnm_expr_top_new_constant (v);
697 dependent_managed_set_expr (&wbv->auto_expr.dep, texpr);
698 gnm_expr_top_unref (texpr);
701 wb_view_auto_expr_recalc (wbv);
704 static void
705 wb_view_set_property (GObject *object, guint property_id,
706 const GValue *value, GParamSpec *pspec)
708 WorkbookView *wbv = (WorkbookView *)object;
710 switch (property_id) {
711 case PROP_AUTO_EXPR_FUNC:
712 wb_view_auto_expr_func (wbv, g_value_get_boxed (value));
713 break;
714 case PROP_AUTO_EXPR_DESCR:
715 wb_view_auto_expr_descr (wbv, g_value_get_string (value));
716 break;
717 case PROP_AUTO_EXPR_MAX_PRECISION:
718 wb_view_auto_expr_precision (wbv, g_value_get_boolean (value));
719 break;
720 case PROP_AUTO_EXPR_VALUE:
721 wb_view_auto_expr_value (wbv, g_value_get_boxed (value));
722 break;
723 case PROP_AUTO_EXPR_EVAL_POS:
724 wb_view_auto_expr_eval_pos (wbv, g_value_get_boxed (value));
725 break;
726 case PROP_SHOW_HORIZONTAL_SCROLLBAR:
727 wbv->show_horizontal_scrollbar = !!g_value_get_boolean (value);
728 break;
729 case PROP_SHOW_VERTICAL_SCROLLBAR:
730 wbv->show_vertical_scrollbar = !!g_value_get_boolean (value);
731 break;
732 case PROP_SHOW_NOTEBOOK_TABS:
733 wbv->show_notebook_tabs = !!g_value_get_boolean (value);
734 break;
735 case PROP_SHOW_FUNCTION_CELL_MARKERS:
736 wbv->show_function_cell_markers = !!g_value_get_boolean (value);
737 if (wbv->current_sheet)
738 sheet_redraw_all (wbv->current_sheet, FALSE);
739 break;
740 case PROP_SHOW_EXTENSION_MARKERS:
741 wbv->show_extension_markers = !!g_value_get_boolean (value);
742 if (wbv->current_sheet)
743 sheet_redraw_all (wbv->current_sheet, FALSE);
744 break;
745 case PROP_DO_AUTO_COMPLETION:
746 wbv->do_auto_completion = !!g_value_get_boolean (value);
747 break;
748 case PROP_PROTECTED:
749 wbv->is_protected = !!g_value_get_boolean (value);
750 break;
751 case PROP_PREFERRED_WIDTH:
752 wbv->preferred_width = g_value_get_int (value);
753 break;
754 case PROP_PREFERRED_HEIGHT:
755 wbv->preferred_height = g_value_get_int (value);
756 break;
757 case PROP_WORKBOOK:
758 wbv->wb = g_value_dup_object (value);
759 break;
760 default:
761 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
762 break;
766 static void
767 wb_view_get_property (GObject *object, guint property_id,
768 GValue *value, GParamSpec *pspec)
770 WorkbookView *wbv = (WorkbookView *)object;
772 switch (property_id) {
773 case PROP_AUTO_EXPR_FUNC:
774 g_value_set_boxed (value, wbv->auto_expr.func);
775 break;
776 case PROP_AUTO_EXPR_DESCR:
777 g_value_set_string (value, wbv->auto_expr.descr);
778 break;
779 case PROP_AUTO_EXPR_MAX_PRECISION:
780 g_value_set_boolean (value, wbv->auto_expr.use_max_precision);
781 break;
782 case PROP_AUTO_EXPR_VALUE:
783 g_value_set_boxed (value, wbv->auto_expr.value);
784 break;
785 case PROP_SHOW_HORIZONTAL_SCROLLBAR:
786 g_value_set_boolean (value, wbv->show_horizontal_scrollbar);
787 break;
788 case PROP_SHOW_VERTICAL_SCROLLBAR:
789 g_value_set_boolean (value, wbv->show_vertical_scrollbar);
790 break;
791 case PROP_SHOW_NOTEBOOK_TABS:
792 g_value_set_boolean (value, wbv->show_notebook_tabs);
793 break;
794 case PROP_SHOW_FUNCTION_CELL_MARKERS:
795 g_value_set_boolean (value, wbv->show_function_cell_markers);
796 break;
797 case PROP_SHOW_EXTENSION_MARKERS:
798 g_value_set_boolean (value, wbv->show_extension_markers);
799 break;
800 case PROP_DO_AUTO_COMPLETION:
801 g_value_set_boolean (value, wbv->do_auto_completion);
802 break;
803 case PROP_PROTECTED:
804 g_value_set_boolean (value, wbv->is_protected);
805 break;
806 case PROP_PREFERRED_WIDTH:
807 g_value_set_int (value, wbv->preferred_width);
808 break;
809 case PROP_PREFERRED_HEIGHT:
810 g_value_set_int (value, wbv->preferred_height);
811 break;
812 case PROP_WORKBOOK:
813 g_value_set_object (value, wbv->wb);
814 break;
815 default:
816 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
817 break;
821 void
822 wb_view_detach_from_workbook (WorkbookView *wbv)
824 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv));
826 if (wbv->wb) {
827 workbook_detach_view (wbv);
828 wbv->wb = NULL;
829 wbv->current_sheet = NULL;
833 static GObject *
834 wb_view_constructor (GType type,
835 guint n_construct_properties,
836 GObjectConstructParam *construct_params)
838 GObject *obj;
839 WorkbookView *wbv;
840 int i;
842 obj = parent_class->constructor
843 (type, n_construct_properties, construct_params);
844 wbv = GNM_WORKBOOK_VIEW (obj);
846 if (wbv->wb == NULL)
847 wbv->wb = workbook_new ();
849 workbook_attach_view (wbv);
851 for (i = 0 ; i < workbook_sheet_count (wbv->wb); i++)
852 wb_view_sheet_add (wbv, workbook_sheet_by_index (wbv->wb, i));
854 if (wbv->auto_expr.func == NULL) {
855 wb_view_auto_expr_func (wbv, gnm_func_lookup ("sum", NULL));
856 wb_view_auto_expr_descr (wbv, _("Sum"));
859 return obj;
862 static void
863 wb_view_dispose (GObject *object)
865 WorkbookView *wbv = GNM_WORKBOOK_VIEW (object);
867 if (wbv->wb_controls != NULL) {
868 WORKBOOK_VIEW_FOREACH_CONTROL (wbv, control, {
869 wb_control_sheet_remove_all (control);
870 wb_view_detach_control (control);
871 g_object_unref (control);
873 if (wbv->wb_controls != NULL)
874 g_warning ("Unexpected left-over controls");
877 /* The order of these are important. Make sure not to leak the value. */
878 wb_view_auto_expr_descr (wbv, NULL);
879 wb_view_auto_expr_eval_pos (wbv, NULL);
880 wb_view_auto_expr_func (wbv, NULL);
881 wb_view_auto_expr_value (wbv, NULL);
883 wb_view_detach_from_workbook (wbv);
885 if (wbv->current_style != NULL) {
886 gnm_style_unref (wbv->current_style);
887 wbv->current_style = NULL;
889 if (wbv->in_cell_combo != NULL) {
890 sheet_object_clear_sheet (wbv->in_cell_combo);
891 g_object_unref (wbv->in_cell_combo);
892 wbv->in_cell_combo = NULL;
895 parent_class->dispose (object);
899 static void
900 workbook_view_class_init (GObjectClass *gobject_class)
902 parent_class = g_type_class_peek_parent (gobject_class);
904 gobject_class->constructor = wb_view_constructor;
905 gobject_class->set_property = wb_view_set_property;
906 gobject_class->get_property = wb_view_get_property;
907 gobject_class->dispose = wb_view_dispose;
909 /* FIXME? Make a boxed type. */
910 g_object_class_install_property
911 (gobject_class,
912 PROP_AUTO_EXPR_FUNC,
913 g_param_spec_boxed ("auto-expr-func",
914 P_("Auto-expression function"),
915 P_("The automatically computed sheet function."),
916 gnm_func_get_type (),
917 GSF_PARAM_STATIC |
918 G_PARAM_READWRITE));
919 g_object_class_install_property
920 (gobject_class,
921 PROP_AUTO_EXPR_DESCR,
922 g_param_spec_string ("auto-expr-descr",
923 P_("Auto-expression description"),
924 P_("Description of the automatically computed sheet function."),
925 NULL,
926 GSF_PARAM_STATIC |
927 G_PARAM_READWRITE));
928 g_object_class_install_property
929 (gobject_class,
930 PROP_AUTO_EXPR_MAX_PRECISION,
931 g_param_spec_boolean ("auto-expr-max-precision",
932 P_("Auto-expression maximum precision"),
933 P_("Use maximum available precision for auto-expressions"),
934 FALSE,
935 GSF_PARAM_STATIC |
936 G_PARAM_READWRITE));
937 g_object_class_install_property
938 (gobject_class,
939 PROP_AUTO_EXPR_VALUE,
940 g_param_spec_boxed ("auto-expr-value",
941 P_("Auto-expression value"),
942 P_("The current value of the auto-expression."),
943 gnm_value_get_type (),
944 GSF_PARAM_STATIC |
945 G_PARAM_READWRITE));
946 g_object_class_install_property
947 (gobject_class,
948 PROP_AUTO_EXPR_EVAL_POS,
949 g_param_spec_boxed ("auto-expr-eval-pos",
950 P_("Auto-expression position"),
951 P_("The cell position to track."),
952 gnm_eval_pos_get_type (),
953 GSF_PARAM_STATIC |
954 G_PARAM_WRITABLE));
955 g_object_class_install_property
956 (gobject_class,
957 PROP_SHOW_HORIZONTAL_SCROLLBAR,
958 g_param_spec_boolean ("show-horizontal-scrollbar",
959 P_("Show horizontal scrollbar"),
960 P_("Show the horizontal scrollbar"),
961 TRUE,
962 GSF_PARAM_STATIC |
963 G_PARAM_READWRITE));
964 g_object_class_install_property
965 (gobject_class,
966 PROP_SHOW_VERTICAL_SCROLLBAR,
967 g_param_spec_boolean ("show-vertical-scrollbar",
968 P_("Show vertical scrollbar"),
969 P_("Show the vertical scrollbar"),
970 TRUE,
971 GSF_PARAM_STATIC |
972 G_PARAM_READWRITE));
973 g_object_class_install_property
974 (gobject_class,
975 PROP_SHOW_NOTEBOOK_TABS,
976 g_param_spec_boolean ("show-notebook-tabs",
977 P_("Show notebook tabs"),
978 P_("Show the notebook tabs for sheets"),
979 TRUE,
980 GSF_PARAM_STATIC |
981 G_PARAM_READWRITE));
982 g_object_class_install_property
983 (gobject_class,
984 PROP_SHOW_FUNCTION_CELL_MARKERS,
985 g_param_spec_boolean ("show-function-cell-markers",
986 P_("Show formula cell markers"),
987 P_("Mark each cell containing a formula"),
988 FALSE,
989 GSF_PARAM_STATIC |
990 G_PARAM_READWRITE));
991 g_object_class_install_property
992 (gobject_class,
993 PROP_SHOW_EXTENSION_MARKERS,
994 g_param_spec_boolean ("show-extension-markers",
995 P_("Show extension markers"),
996 P_("Mark each cell that fails to show the complete content"),
997 FALSE,
998 GSF_PARAM_STATIC |
999 G_PARAM_READWRITE));
1000 g_object_class_install_property
1001 (gobject_class,
1002 PROP_DO_AUTO_COMPLETION,
1003 g_param_spec_boolean ("do-auto-completion",
1004 P_("Do auto completion"),
1005 P_("Auto-complete text"),
1006 FALSE,
1007 GSF_PARAM_STATIC |
1008 G_PARAM_READWRITE));
1009 g_object_class_install_property
1010 (gobject_class,
1011 PROP_PROTECTED,
1012 g_param_spec_boolean ("protected",
1013 P_("Protected"),
1014 P_("Is view protected?"),
1015 FALSE,
1016 GSF_PARAM_STATIC |
1017 G_PARAM_READWRITE));
1018 g_object_class_install_property
1019 (gobject_class,
1020 PROP_PREFERRED_WIDTH,
1021 g_param_spec_int ("preferred-width",
1022 P_("Preferred width"),
1023 P_("Preferred width"),
1024 1, G_MAXINT, 1024,
1025 GSF_PARAM_STATIC |
1026 G_PARAM_READWRITE));
1027 g_object_class_install_property
1028 (gobject_class,
1029 PROP_PREFERRED_HEIGHT,
1030 g_param_spec_int ("preferred-height",
1031 P_("Preferred height"),
1032 P_("Preferred height"),
1033 1, G_MAXINT, 768,
1034 GSF_PARAM_STATIC |
1035 G_PARAM_READWRITE));
1036 g_object_class_install_property
1037 (gobject_class,
1038 PROP_WORKBOOK,
1039 g_param_spec_object ("workbook",
1040 P_("Workbook"),
1041 P_("Workbook"),
1042 GNM_WORKBOOK_TYPE,
1043 GSF_PARAM_STATIC |
1044 G_PARAM_CONSTRUCT_ONLY |
1045 G_PARAM_READWRITE));
1047 parent_class = g_type_class_peek_parent (gobject_class);
1050 static void
1051 workbook_view_init (WorkbookView *wbv)
1053 wbv->show_horizontal_scrollbar = TRUE;
1054 wbv->show_vertical_scrollbar = TRUE;
1055 wbv->show_notebook_tabs = TRUE;
1056 wbv->show_function_cell_markers =
1057 gnm_conf_get_core_gui_cells_function_markers ();
1058 wbv->show_extension_markers =
1059 gnm_conf_get_core_gui_cells_extension_markers ();
1060 wbv->do_auto_completion =
1061 gnm_conf_get_core_gui_editing_autocomplete ();
1062 wbv->is_protected = FALSE;
1064 dependent_managed_init (&wbv->auto_expr.dep, NULL);
1067 GSF_CLASS (WorkbookView, workbook_view,
1068 workbook_view_class_init, workbook_view_init, GO_TYPE_VIEW)
1071 * workbook_view_new:
1072 * @wb: (allow-none) (transfer full): #Workbook
1074 * Returns: A new #WorkbookView for @wb (or a fresh one if that is %NULL).
1076 WorkbookView *
1077 workbook_view_new (Workbook *wb)
1079 WorkbookView *wbv =
1080 g_object_new (GNM_WORKBOOK_VIEW_TYPE, "workbook", wb, NULL);
1081 if (wb) g_object_unref (wb);
1083 return wbv;
1087 * workbook_view_save_to_output:
1088 * @wbv: #WorkbookView
1089 * @fs: #GOFileSaver
1090 * @output: #GsfOutput
1091 * @io_context: #GOIOContext
1093 * NOTE : Temporary api until we get the new output framework.
1095 void
1096 workbook_view_save_to_output (WorkbookView *wbv, GOFileSaver const *fs,
1097 GsfOutput *output, GOIOContext *io_context)
1099 GError const *err;
1100 char const *msg;
1101 GODoc *godoc = wb_view_get_doc (wbv);
1103 if (go_doc_is_dirty (godoc))
1104 /* FIXME: we should be using the true modification time */
1105 gnm_insert_meta_date (godoc, GSF_META_NAME_DATE_MODIFIED);
1106 go_file_saver_save (fs, io_context, GO_VIEW (wbv), output);
1108 /* The plugin convention is unclear */
1109 if (!gsf_output_is_closed (output))
1110 gsf_output_close (output);
1112 if (NULL == (err = gsf_output_error (output)))
1113 return;
1114 if (NULL == (msg = err->message))
1115 msg = _("An unexplained error happened while saving.");
1116 g_printerr (" ==> %s\n", msg);
1117 if (!go_io_error_occurred (io_context))
1118 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context), msg);
1122 * workbook_view_save_to_uri:
1123 * @wbv: #WorkbookView
1124 * @fs: #GOFileSaver
1125 * @uri: destination URI
1126 * @io_context: #GOIOContext
1129 void
1130 workbook_view_save_to_uri (WorkbookView *wbv, GOFileSaver const *fs,
1131 char const *uri, GOIOContext *io_context)
1133 char *msg = NULL;
1134 GError *err = NULL;
1135 GsfOutput *output = go_file_create (uri, &err);
1137 if (output == NULL) {
1138 if (NULL != err) {
1139 msg = g_strdup_printf (_("Can't open '%s' for writing: %s"),
1140 uri, err->message);
1141 g_error_free (err);
1142 } else
1143 msg = g_strdup_printf (_("Can't open '%s' for writing"), uri);
1145 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context), msg);
1146 g_free (msg);
1147 } else {
1148 workbook_view_save_to_output (wbv, fs, output, io_context);
1149 g_object_unref (output);
1153 static GDateTime *
1154 get_uri_modtime (GsfInput *input, const char *uri)
1156 GDateTime *modtime = NULL;
1158 if (input) {
1159 modtime = gsf_input_get_modtime (input);
1160 if (modtime)
1161 g_date_time_ref (modtime);
1164 if (!modtime && uri)
1165 modtime = go_file_get_modtime (uri);
1167 if (gnm_debug_flag ("modtime")) {
1168 char *s = modtime
1169 ? g_date_time_format (modtime, "%F %T")
1170 : g_strdup ("?");
1171 g_printerr ("Modtime of %s is %s\n", uri, s);
1172 g_free (s);
1175 return modtime;
1179 * workbook_view_save_as:
1180 * @wbv: Workbook View
1181 * @fs: GOFileSaver object
1182 * @uri: URI to save as.
1183 * @cc: The #GOCmdContext that invoked the operation
1185 * Saves @wbv and workbook it's attached to into @uri file using
1186 * @fs file saver. If the format sufficiently advanced make it the saver
1187 * and update the uri.
1189 * Return value: %TRUE if file was successfully saved and %FALSE otherwise.
1191 gboolean
1192 workbook_view_save_as (WorkbookView *wbv, GOFileSaver *fs, char const *uri,
1193 GOCmdContext *cc)
1195 GOIOContext *io_context;
1196 Workbook *wb;
1197 gboolean has_error, has_warning;
1199 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), FALSE);
1200 g_return_val_if_fail (GO_IS_FILE_SAVER (fs), FALSE);
1201 g_return_val_if_fail (uri != NULL, FALSE);
1202 g_return_val_if_fail (GO_IS_CMD_CONTEXT (cc), FALSE);
1204 wb = wb_view_get_workbook (wbv);
1205 g_object_ref (wb);
1206 io_context = go_io_context_new (cc);
1208 go_cmd_context_set_sensitive (cc, FALSE);
1209 workbook_view_save_to_uri (wbv, fs, uri, io_context);
1210 go_cmd_context_set_sensitive (cc, TRUE);
1212 has_error = go_io_error_occurred (io_context);
1213 has_warning = go_io_warning_occurred (io_context);
1214 if (!has_error) {
1215 GOFileFormatLevel fl = go_file_saver_get_format_level (fs);
1216 if (workbook_set_saveinfo (wb, fl, fs)) {
1217 if (go_doc_set_uri (GO_DOC (wb), uri)) {
1218 GDateTime *modtime;
1220 go_doc_set_dirty (GO_DOC (wb), FALSE);
1221 /* See 634792. */
1222 go_doc_set_pristine (GO_DOC (wb), FALSE);
1224 modtime = get_uri_modtime (NULL, uri);
1225 go_doc_set_modtime (GO_DOC (wb), modtime);
1226 if (gnm_debug_flag ("modtime"))
1227 g_printerr ("Modtime set\n");
1228 g_date_time_unref (modtime);
1230 } else
1231 workbook_set_last_export_uri (wb, uri);
1233 if (has_error || has_warning)
1234 go_io_error_display (io_context);
1235 g_object_unref (io_context);
1236 g_object_unref (wb);
1238 return !has_error;
1242 * workbook_view_save:
1243 * @wbv: The view to save.
1244 * @cc: The #GOCmdContext that invoked the operation
1246 * Saves @wbv and workbook it's attached to into file assigned to the
1247 * workbook using workbook's file saver. If the workbook has no file
1248 * saver assigned to it, default file saver is used instead.
1250 * Return value: %TRUE if file was successfully saved and %FALSE otherwise.
1252 gboolean
1253 workbook_view_save (WorkbookView *wbv, GOCmdContext *context)
1255 GOIOContext *io_context;
1256 Workbook *wb;
1257 GOFileSaver *fs;
1258 gboolean has_error, has_warning;
1259 char const *uri;
1261 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv), FALSE);
1262 g_return_val_if_fail (GO_IS_CMD_CONTEXT (context), FALSE);
1264 wb = wb_view_get_workbook (wbv);
1265 g_object_ref (wb);
1266 uri = go_doc_get_uri (GO_DOC (wb));
1268 fs = workbook_get_file_saver (wb);
1269 if (fs == NULL)
1270 fs = go_file_saver_get_default ();
1272 io_context = go_io_context_new (context);
1273 if (fs == NULL)
1274 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context),
1275 _("Default file saver is not available."));
1276 else {
1277 char const *uri = go_doc_get_uri (GO_DOC (wb));
1278 workbook_view_save_to_uri (wbv, fs, uri, io_context);
1281 has_error = go_io_error_occurred (io_context);
1282 has_warning = go_io_warning_occurred (io_context);
1283 if (!has_error) {
1284 GDateTime *modtime = get_uri_modtime (NULL, uri);
1285 go_doc_set_modtime (GO_DOC (wb), modtime);
1286 if (gnm_debug_flag ("modtime"))
1287 g_printerr ("Modtime set\n");
1288 g_date_time_unref (modtime);
1289 go_doc_set_dirty (GO_DOC (wb), FALSE);
1291 if (has_error || has_warning)
1292 go_io_error_display (io_context);
1294 g_object_unref (io_context);
1295 g_object_unref (wb);
1297 return !has_error;
1301 * workbook_view_new_from_input:
1302 * @input: #GsfInput to read data from.
1303 * @uri: (allow-none): URI
1304 * @file_opener: (allow-none): #GOFileOpener
1305 * @io_context: (allow-none): Context to display errors.
1306 * @encoding: (allow-none): Encoding for @file_opener that understand it
1308 * Reads @uri file using given file opener @file_opener, or probes for a valid
1309 * possibility if @file_opener is %NULL. Reports problems to @io_context.
1311 * Return value: (transfer full) (nullable): the newly allocated WorkbookView
1312 * or %NULL on error.
1314 WorkbookView *
1315 workbook_view_new_from_input (GsfInput *input,
1316 const char *uri,
1317 GOFileOpener const *file_opener,
1318 GOIOContext *io_context,
1319 char const *encoding)
1321 WorkbookView *new_wbv = NULL;
1323 g_return_val_if_fail (GSF_IS_INPUT(input), NULL);
1324 g_return_val_if_fail (file_opener == NULL ||
1325 GO_IS_FILE_OPENER (file_opener), NULL);
1327 /* NOTE : we could support gzipped anything here if we wanted to
1328 * by adding a wrapper, but there is no framework for remembering that
1329 * the file was gzipped so let's not just yet.
1332 /* Search for an applicable opener */
1333 if (file_opener == NULL) {
1334 GOFileProbeLevel pl;
1335 GList *l;
1336 int input_refs = G_OBJECT (input)->ref_count;
1338 for (pl = GO_FILE_PROBE_FILE_NAME; pl < GO_FILE_PROBE_LAST && file_opener == NULL; pl++) {
1339 for (l = go_get_file_openers (); l != NULL; l = l->next) {
1340 GOFileOpener const *tmp_fo = GO_FILE_OPENER (l->data);
1341 int new_input_refs;
1342 /* A name match needs to be a content match too */
1343 if (go_file_opener_probe (tmp_fo, input, pl) &&
1344 (pl == GO_FILE_PROBE_CONTENT ||
1345 !go_file_opener_can_probe (tmp_fo, GO_FILE_PROBE_CONTENT) ||
1346 go_file_opener_probe (tmp_fo, input, GO_FILE_PROBE_CONTENT)))
1347 file_opener = tmp_fo;
1349 new_input_refs = G_OBJECT (input)->ref_count;
1350 if (new_input_refs != input_refs) {
1351 g_warning ("Format %s's probe changed input ref_count from %d to %d.",
1352 go_file_opener_get_id (tmp_fo),
1353 input_refs,
1354 new_input_refs);
1355 input_refs = new_input_refs;
1358 if (file_opener)
1359 break;
1364 if (file_opener != NULL) {
1365 Workbook *new_wb;
1366 gboolean old;
1367 GDateTime *modtime;
1369 new_wbv = workbook_view_new (NULL);
1370 new_wb = wb_view_get_workbook (new_wbv);
1371 if (uri)
1372 go_doc_set_uri (GO_DOC (new_wb), uri);
1374 // Grab the modtime before we actually do the reading
1375 modtime = get_uri_modtime (input, uri);
1376 go_doc_set_modtime (GO_DOC (new_wb), modtime);
1377 if (modtime)
1378 g_date_time_unref (modtime);
1380 /* disable recursive dirtying while loading */
1381 old = workbook_enable_recursive_dirty (new_wb, FALSE);
1382 go_file_opener_open (file_opener, encoding, io_context,
1383 GO_VIEW (new_wbv), input);
1384 workbook_enable_recursive_dirty (new_wb, old);
1386 if (go_io_error_occurred (io_context)) {
1387 g_object_unref (new_wb);
1388 new_wbv = NULL;
1389 } else if (workbook_sheet_count (new_wb) == 0) {
1390 /* we didn't get a sheet nor an error, */
1391 /* the user must have canceled */
1392 g_object_unref (new_wb);
1393 new_wbv = NULL;
1394 } else {
1395 workbook_share_expressions (new_wb, TRUE);
1396 workbook_optimize_style (new_wb);
1397 workbook_queue_volatile_recalc (new_wb);
1398 workbook_recalc (new_wb);
1399 workbook_update_graphs (new_wb);
1400 go_doc_set_dirty (GO_DOC (new_wb), FALSE);
1401 if (uri && workbook_get_file_exporter (new_wb))
1402 workbook_set_last_export_uri
1403 (new_wb, uri);
1405 } else {
1406 if (io_context)
1407 go_cmd_context_error_import
1408 (GO_CMD_CONTEXT (io_context),
1409 _("Unsupported file format."));
1412 return new_wbv;
1416 * workbook_view_new_from_uri:
1417 * @uri: URI for file
1418 * @file_opener: (allow-none): #GOFileOpener
1419 * @io_context: Context to display errors.
1420 * @encoding: (allow-none): Encoding for @file_opener that understands it
1422 * Reads @uri file using given file opener @file_opener, or probes for a valid
1423 * possibility if @file_opener is %NULL. Reports problems to @io_context.
1425 * Return value: (transfer full) (nullable): the newly allocated WorkbookView
1426 * or %NULL on error.
1428 WorkbookView *
1429 workbook_view_new_from_uri (char const *uri,
1430 GOFileOpener const *file_opener,
1431 GOIOContext *io_context,
1432 char const *encoding)
1434 char *msg = NULL;
1435 GError *err = NULL;
1436 GsfInput *input;
1438 g_return_val_if_fail (uri != NULL, NULL);
1440 input = go_file_open (uri, &err);
1441 if (input != NULL) {
1442 WorkbookView *res;
1444 res = workbook_view_new_from_input (input, uri,
1445 file_opener, io_context,
1446 encoding);
1447 g_object_unref (input);
1448 return res;
1451 if (err != NULL) {
1452 if (err->message != NULL)
1453 msg = g_strdup (err->message);
1454 g_error_free (err);
1457 if (msg == NULL)
1458 msg = g_strdup_printf (_("An unexplained error happened while opening %s"),
1459 uri);
1461 if (io_context)
1462 go_cmd_context_error_import (GO_CMD_CONTEXT (io_context), msg);
1463 g_free (msg);
1465 return NULL;