1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
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
23 #include <gnumeric-config.h>
25 #include "workbook-view.h"
27 #include "workbook-control-priv.h"
28 #include "workbook-priv.h"
29 #include "application.h"
31 #include "sheet-view.h"
32 #include "sheet-merge.h"
33 #include "sheet-style.h"
36 #include "expr-name.h"
39 #include "selection.h"
41 #include "validation.h"
42 #include "validation-combo.h"
43 #include "gnm-sheet-slicer.h"
44 #include "gnm-sheet-slicer-combo.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>
59 #include <glib/gstdio.h>
71 * @wb_controls: (element-type WorkbookControl):
77 PROP_AUTO_EXPR_MAX_PRECISION
,
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
,
88 PROP_PREFERRED_HEIGHT
,
92 /* WorkbookView signals */
98 * wb_view_get_workbook:
101 * Returns: (transfer none): the #Workbook associated with @wbv
104 wb_view_get_workbook (WorkbookView
const *wbv
)
106 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
), NULL
);
112 * @wbv: #WorkbookView
114 * Returns: (transfer none): the #Workbook associated with @wbv cast to a #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
;
136 if (g_ptr_array_index (wbv
->wb
->wb_views
, i
) == wbv
)
144 * @wbv: #WorkbookView
146 * Returns: (transfer none): the current 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.
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
;
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);
176 g_print ("Focus %s\n", sheet
? sheet
->name_quoted
: "-");
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
);
194 wb_view_sheet_add (WorkbookView
*wbv
, Sheet
*new_sheet
)
198 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
200 new_view
= 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
);
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
);
221 wb_view_set_attribute (WorkbookView
*wbv
, char const *name
, char const *value
)
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)
236 else if (strncmp (name
, "Workbook::", 10) == 0)
237 /* Some old files have this. */
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
);
257 g_warning ("WorkbookView unknown arg '%s'", name
);
261 wb_view_preferred_size (WorkbookView
*wbv
, int w
, int h
)
263 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
266 w
= 768; /* use default */
268 h
= 768; /* use default */
270 g_object_set (G_OBJECT (wbv
),
271 "preferred-width", w
,
272 "preferred-height", h
,
277 wb_view_style_feedback (WorkbookView
*wbv
)
280 GnmStyle
const *style
;
281 GnmSheetSlicer
const *dslicer
;
282 GODataSlicerField
*dsfield
;
283 GnmValidation
const *val
;
284 GOFormat
const *fmt_style
, *fmt_cell
;
286 gboolean update_controls
= TRUE
;
288 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
290 sv
= wbv
->current_sheet_view
;
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
);
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
);
309 GnmStyle
*tmp
= gnm_style_dup (style
);
310 gnm_style_set_format (tmp
, fmt_cell
);
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
&&
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 (),
336 if (NULL
!= wbv
->in_cell_combo
)
338 const double a_offsets
[4] = { 0., 0., 1., 1. };
339 SheetObjectAnchor anchor
;
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
););
356 wb_view_menus_update (WorkbookView
*wbv
)
360 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
362 sheet
= wbv
->current_sheet
;
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:
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.
383 wb_view_selection_desc (WorkbookView
*wbv
, gboolean use_pos
,
384 WorkbookControl
*wbc
)
388 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
390 sv
= wbv
->current_sheet_view
;
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_SV (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
) {
407 parse_pos_init_editpos (&pp
, sv
);
408 sel_descr
= parsepos_as_string (&pp
);
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
);
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"),
427 WORKBOOK_VIEW_FOREACH_CONTROL (wbv
, wbc
,
428 wb_control_selection_descr_set (wbc
, sel_descr
););
430 wb_control_selection_descr_set (wbc
, sel_descr
);
435 * wb_view_edit_line_set:
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.
445 wb_view_edit_line_set (WorkbookView
*wbv
, WorkbookControl
*wbc
)
449 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
451 sv
= wbv
->current_sheet_view
;
454 Sheet
*sheet
= sv
->sheet
;
455 GnmCell
const *cell
= sheet_cell_get (sheet
,
456 sv
->edit_pos
.col
, sv
->edit_pos
.row
);
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
;
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
))
475 else if (gnm_expr_top_is_array_elem (texpr
, &x
, &y
)) {
476 corner
= sheet_cell_get
486 gnm_expr_top_get_array_size (corner
->base
.texpr
, &cols
, &rows
);
488 tmp
= g_strdup_printf
489 ("{%s}(%d%c%d)[%d][%d]",
491 cols
, go_locale_get_arg_sep (), rows
,
498 text
= g_strdup ("");
501 WORKBOOK_VIEW_FOREACH_CONTROL (wbv
, control
,
502 wb_control_edit_line_set (control
, text
););
504 wb_control_edit_line_set (wbc
, text
);
511 accumulate_regions (SheetView
*sv
, GnmRange
const *r
, gpointer closure
)
513 GnmExprList
**selection
= closure
;
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
;
523 *selection
= gnm_expr_list_prepend (*selection
,
524 gnm_expr_new_constant (value_new_cellrange_unsafe (&a
, &b
)));
528 wb_view_auto_expr_recalc (WorkbookView
*wbv
)
530 GnmExprList
*selection
= NULL
;
533 GnmExprTop
const *texpr
;
536 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
538 sv
= wb_view_cur_sheet_view (wbv
);
539 if (wbv
->current_sheet
== NULL
||
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
));
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
);
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
);
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 */
575 wb_view_init_control (G_GNUC_UNUSED WorkbookControl
*wbc
)
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
);
592 wb_view_init_control (wbc
);
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
;
612 wb_view_auto_expr_func (WorkbookView
*wbv
, GnmFunc
*func
)
614 if (wbv
->auto_expr
.func
== func
)
617 if (wbv
->auto_expr
.func
)
618 gnm_func_unref (wbv
->auto_expr
.func
);
622 wbv
->auto_expr
.func
= func
;
624 wb_view_auto_expr_recalc (wbv
);
628 wb_view_auto_expr_descr (WorkbookView
*wbv
, const char *descr
)
632 if (go_str_compare (descr
, wbv
->auto_expr
.descr
) == 0)
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
);
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
)
650 wbv
->auto_expr
.use_max_precision
= use_max_precision
;
652 wb_view_auto_expr_recalc (wbv
);
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
);
663 cb_clear_auto_expr_sheet (WorkbookView
*wbv
)
665 g_object_set (G_OBJECT (wbv
),
666 "auto-expr-eval-pos", NULL
,
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
);
687 GnmExprTop
const *texpr
;
689 wbv
->auto_expr
.sheet_detached_sig
= g_signal_connect_swapped (
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
);
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
));
714 case PROP_AUTO_EXPR_DESCR
:
715 wb_view_auto_expr_descr (wbv
, g_value_get_string (value
));
717 case PROP_AUTO_EXPR_MAX_PRECISION
:
718 wb_view_auto_expr_precision (wbv
, g_value_get_boolean (value
));
720 case PROP_AUTO_EXPR_VALUE
:
721 wb_view_auto_expr_value (wbv
, g_value_get_boxed (value
));
723 case PROP_AUTO_EXPR_EVAL_POS
:
724 wb_view_auto_expr_eval_pos (wbv
, g_value_get_boxed (value
));
726 case PROP_SHOW_HORIZONTAL_SCROLLBAR
:
727 wbv
->show_horizontal_scrollbar
= !!g_value_get_boolean (value
);
729 case PROP_SHOW_VERTICAL_SCROLLBAR
:
730 wbv
->show_vertical_scrollbar
= !!g_value_get_boolean (value
);
732 case PROP_SHOW_NOTEBOOK_TABS
:
733 wbv
->show_notebook_tabs
= !!g_value_get_boolean (value
);
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
);
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
);
745 case PROP_DO_AUTO_COMPLETION
:
746 wbv
->do_auto_completion
= !!g_value_get_boolean (value
);
749 wbv
->is_protected
= !!g_value_get_boolean (value
);
751 case PROP_PREFERRED_WIDTH
:
752 wbv
->preferred_width
= g_value_get_int (value
);
754 case PROP_PREFERRED_HEIGHT
:
755 wbv
->preferred_height
= g_value_get_int (value
);
758 wbv
->wb
= g_value_dup_object (value
);
761 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
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
);
776 case PROP_AUTO_EXPR_DESCR
:
777 g_value_set_string (value
, wbv
->auto_expr
.descr
);
779 case PROP_AUTO_EXPR_MAX_PRECISION
:
780 g_value_set_boolean (value
, wbv
->auto_expr
.use_max_precision
);
782 case PROP_AUTO_EXPR_VALUE
:
783 g_value_set_boxed (value
, wbv
->auto_expr
.value
);
785 case PROP_SHOW_HORIZONTAL_SCROLLBAR
:
786 g_value_set_boolean (value
, wbv
->show_horizontal_scrollbar
);
788 case PROP_SHOW_VERTICAL_SCROLLBAR
:
789 g_value_set_boolean (value
, wbv
->show_vertical_scrollbar
);
791 case PROP_SHOW_NOTEBOOK_TABS
:
792 g_value_set_boolean (value
, wbv
->show_notebook_tabs
);
794 case PROP_SHOW_FUNCTION_CELL_MARKERS
:
795 g_value_set_boolean (value
, wbv
->show_function_cell_markers
);
797 case PROP_SHOW_EXTENSION_MARKERS
:
798 g_value_set_boolean (value
, wbv
->show_extension_markers
);
800 case PROP_DO_AUTO_COMPLETION
:
801 g_value_set_boolean (value
, wbv
->do_auto_completion
);
804 g_value_set_boolean (value
, wbv
->is_protected
);
806 case PROP_PREFERRED_WIDTH
:
807 g_value_set_int (value
, wbv
->preferred_width
);
809 case PROP_PREFERRED_HEIGHT
:
810 g_value_set_int (value
, wbv
->preferred_height
);
813 g_value_set_object (value
, wbv
->wb
);
816 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
822 wb_view_detach_from_workbook (WorkbookView
*wbv
)
824 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
827 workbook_detach_view (wbv
);
829 wbv
->current_sheet
= NULL
;
834 wb_view_constructor (GType type
,
835 guint n_construct_properties
,
836 GObjectConstructParam
*construct_params
)
842 obj
= parent_class
->constructor
843 (type
, n_construct_properties
, construct_params
);
844 wbv
= GNM_WORKBOOK_VIEW (obj
);
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"));
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
);
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
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 (),
919 g_object_class_install_property
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."),
928 g_object_class_install_property
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"),
937 g_object_class_install_property
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 (),
946 g_object_class_install_property
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 (),
955 g_object_class_install_property
957 PROP_SHOW_HORIZONTAL_SCROLLBAR
,
958 g_param_spec_boolean ("show-horizontal-scrollbar",
959 P_("Show horizontal scrollbar"),
960 P_("Show the horizontal scrollbar"),
964 g_object_class_install_property
966 PROP_SHOW_VERTICAL_SCROLLBAR
,
967 g_param_spec_boolean ("show-vertical-scrollbar",
968 P_("Show vertical scrollbar"),
969 P_("Show the vertical scrollbar"),
973 g_object_class_install_property
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"),
982 g_object_class_install_property
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"),
991 g_object_class_install_property
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"),
1000 g_object_class_install_property
1002 PROP_DO_AUTO_COMPLETION
,
1003 g_param_spec_boolean ("do-auto-completion",
1004 P_("Do auto completion"),
1005 P_("Auto-complete text"),
1008 G_PARAM_READWRITE
));
1009 g_object_class_install_property
1012 g_param_spec_boolean ("protected",
1014 P_("Is view protected?"),
1017 G_PARAM_READWRITE
));
1018 g_object_class_install_property
1020 PROP_PREFERRED_WIDTH
,
1021 g_param_spec_int ("preferred-width",
1022 P_("Preferred width"),
1023 P_("Preferred width"),
1026 G_PARAM_READWRITE
));
1027 g_object_class_install_property
1029 PROP_PREFERRED_HEIGHT
,
1030 g_param_spec_int ("preferred-height",
1031 P_("Preferred height"),
1032 P_("Preferred height"),
1035 G_PARAM_READWRITE
));
1036 g_object_class_install_property
1039 g_param_spec_object ("workbook",
1044 G_PARAM_CONSTRUCT_ONLY
|
1045 G_PARAM_READWRITE
));
1047 parent_class
= g_type_class_peek_parent (gobject_class
);
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).
1077 workbook_view_new (Workbook
*wb
)
1080 g_object_new (GNM_WORKBOOK_VIEW_TYPE
, "workbook", wb
, NULL
);
1081 if (wb
) g_object_unref (wb
);
1087 * workbook_view_save_to_output:
1088 * @wbv: #WorkbookView
1090 * @output: #GsfOutput
1091 * @io_context: #GOIOContext
1093 * NOTE : Temporary api until we get the new output framework.
1096 workbook_view_save_to_output (WorkbookView
*wbv
, GOFileSaver
const *fs
,
1097 GsfOutput
*output
, GOIOContext
*io_context
)
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
)))
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
1125 * @uri: destination URI
1126 * @io_context: #GOIOContext
1130 workbook_view_save_to_uri (WorkbookView
*wbv
, GOFileSaver
const *fs
,
1131 char const *uri
, GOIOContext
*io_context
)
1135 GsfOutput
*output
= go_file_create (uri
, &err
);
1137 if (output
== NULL
) {
1139 msg
= g_strdup_printf (_("Can't open '%s' for writing: %s"),
1143 msg
= g_strdup_printf (_("Can't open '%s' for writing"), uri
);
1145 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context
), msg
);
1148 workbook_view_save_to_output (wbv
, fs
, output
, io_context
);
1149 g_object_unref (output
);
1154 get_uri_modtime (GsfInput
*input
, const char *uri
)
1156 GDateTime
*modtime
= NULL
;
1159 modtime
= gsf_input_get_modtime (input
);
1161 g_date_time_ref (modtime
);
1164 if (!modtime
&& uri
)
1165 modtime
= go_file_get_modtime (uri
);
1167 if (gnm_debug_flag ("modtime")) {
1169 ? g_date_time_format (modtime
, "%F %T")
1171 g_printerr ("Modtime of %s is %s\n", uri
, s
);
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.
1192 workbook_view_save_as (WorkbookView
*wbv
, GOFileSaver
*fs
, char const *uri
,
1195 GOIOContext
*io_context
;
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
);
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
);
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
)) {
1220 go_doc_set_dirty (GO_DOC (wb
), FALSE
);
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
);
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
);
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.
1253 workbook_view_save (WorkbookView
*wbv
, GOCmdContext
*context
)
1255 GOIOContext
*io_context
;
1258 gboolean has_error
, has_warning
;
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
);
1266 uri
= go_doc_get_uri (GO_DOC (wb
));
1268 fs
= workbook_get_file_saver (wb
);
1270 fs
= go_file_saver_get_default ();
1272 io_context
= go_io_context_new (context
);
1274 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context
),
1275 _("Default file saver is not available."));
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
);
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
);
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.
1315 workbook_view_new_from_input (GsfInput
*input
,
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
;
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
);
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
),
1355 input_refs
= new_input_refs
;
1364 if (file_opener
!= NULL
) {
1369 new_wbv
= workbook_view_new (NULL
);
1370 new_wb
= wb_view_get_workbook (new_wbv
);
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
);
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
);
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
);
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
1407 go_cmd_context_error_import
1408 (GO_CMD_CONTEXT (io_context
),
1409 _("Unsupported file format."));
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.
1429 workbook_view_new_from_uri (char const *uri
,
1430 GOFileOpener
const *file_opener
,
1431 GOIOContext
*io_context
,
1432 char const *encoding
)
1438 g_return_val_if_fail (uri
!= NULL
, NULL
);
1440 input
= go_file_open (uri
, &err
);
1441 if (input
!= NULL
) {
1444 res
= workbook_view_new_from_input (input
, uri
,
1445 file_opener
, io_context
,
1447 g_object_unref (input
);
1452 if (err
->message
!= NULL
)
1453 msg
= g_strdup (err
->message
);
1458 msg
= g_strdup_printf (_("An unexplained error happened while opening %s"),
1462 go_cmd_context_error_import (GO_CMD_CONTEXT (io_context
), msg
);