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
22 #include <gnumeric-config.h>
24 #include <workbook-view.h>
26 #include <workbook-control-priv.h>
27 #include <workbook-priv.h>
28 #include <application.h>
30 #include <sheet-view.h>
31 #include <sheet-merge.h>
32 #include <sheet-style.h>
35 #include <expr-name.h>
38 #include <selection.h>
40 #include <validation.h>
41 #include <validation-combo.h>
42 #include <gnm-sheet-slicer.h>
43 #include <gnm-sheet-slicer-combo.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>
58 #include <glib/gstdio.h>
70 * @wb_controls: (element-type WorkbookControl):
76 PROP_AUTO_EXPR_MAX_PRECISION
,
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
,
87 PROP_PREFERRED_HEIGHT
,
91 /* WorkbookView signals */
97 * wb_view_get_workbook:
100 * Returns: (transfer none): the #Workbook associated with @wbv
103 wb_view_get_workbook (WorkbookView
const *wbv
)
105 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
), NULL
);
111 * @wbv: #WorkbookView
113 * Returns: (transfer none): the #Workbook associated with @wbv cast to a #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
;
135 if (g_ptr_array_index (wbv
->wb
->wb_views
, i
) == wbv
)
143 * @wbv: #WorkbookView
145 * Returns: (transfer none): the current 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.
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
;
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);
175 g_print ("Focus %s\n", sheet
? sheet
->name_quoted
: "-");
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
);
193 wb_view_sheet_add (WorkbookView
*wbv
, Sheet
*new_sheet
)
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
);
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
);
220 wb_view_set_attribute (WorkbookView
*wbv
, char const *name
, char const *value
)
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)
235 else if (strncmp (name
, "Workbook::", 10) == 0)
236 /* Some old files have this. */
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
);
256 g_warning ("WorkbookView unknown arg '%s'", name
);
260 wb_view_preferred_size (WorkbookView
*wbv
, int w
, int h
)
262 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
265 w
= 768; /* use default */
267 h
= 768; /* use default */
269 g_object_set (G_OBJECT (wbv
),
270 "preferred-width", w
,
271 "preferred-height", h
,
276 wb_view_style_feedback (WorkbookView
*wbv
)
279 GnmStyle
const *style
;
280 GnmSheetSlicer
const *dslicer
;
281 GODataSlicerField
*dsfield
;
282 GnmValidation
const *val
;
283 GOFormat
const *fmt_style
, *fmt_cell
;
285 gboolean update_controls
= TRUE
;
287 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
289 sv
= wbv
->current_sheet_view
;
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
);
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
);
308 GnmStyle
*tmp
= gnm_style_dup (style
);
309 gnm_style_set_format (tmp
, fmt_cell
);
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
&&
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 (),
335 if (NULL
!= wbv
->in_cell_combo
)
337 const double a_offsets
[4] = { 0., 0., 1., 1. };
338 SheetObjectAnchor anchor
;
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
););
355 wb_view_menus_update (WorkbookView
*wbv
)
359 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
361 sheet
= wbv
->current_sheet
;
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:
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.
382 wb_view_selection_desc (WorkbookView
*wbv
, gboolean use_pos
,
383 WorkbookControl
*wbc
)
387 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
389 sv
= wbv
->current_sheet_view
;
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
) {
406 parse_pos_init_editpos (&pp
, sv
);
407 sel_descr
= parsepos_as_string (&pp
);
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
);
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"),
426 WORKBOOK_VIEW_FOREACH_CONTROL (wbv
, wbc
,
427 wb_control_selection_descr_set (wbc
, sel_descr
););
429 wb_control_selection_descr_set (wbc
, sel_descr
);
434 * wb_view_edit_line_set:
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.
444 wb_view_edit_line_set (WorkbookView
*wbv
, WorkbookControl
*wbc
)
448 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
450 sv
= wbv
->current_sheet_view
;
453 Sheet
*sheet
= sv
->sheet
;
454 GnmCell
const *cell
= sheet_cell_get (sheet
,
455 sv
->edit_pos
.col
, sv
->edit_pos
.row
);
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
;
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
))
474 else if (gnm_expr_top_is_array_elem (texpr
, &x
, &y
)) {
475 corner
= sheet_cell_get
485 gnm_expr_top_get_array_size (corner
->base
.texpr
, &cols
, &rows
);
487 tmp
= g_strdup_printf
488 ("{%s}(%d%c%d)[%d][%d]",
490 cols
, go_locale_get_arg_sep (), rows
,
497 text
= g_strdup ("");
500 WORKBOOK_VIEW_FOREACH_CONTROL (wbv
, control
,
501 wb_control_edit_line_set (control
, text
););
503 wb_control_edit_line_set (wbc
, text
);
510 accumulate_regions (SheetView
*sv
, GnmRange
const *r
, gpointer closure
)
512 GnmExprList
**selection
= closure
;
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
;
522 *selection
= gnm_expr_list_prepend (*selection
,
523 gnm_expr_new_constant (value_new_cellrange_unsafe (&a
, &b
)));
527 wb_view_auto_expr_recalc (WorkbookView
*wbv
)
529 GnmExprList
*selection
= NULL
;
532 GnmExprTop
const *texpr
;
535 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
537 sv
= wb_view_cur_sheet_view (wbv
);
538 if (wbv
->current_sheet
== NULL
||
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
));
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
);
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
);
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 */
574 wb_view_init_control (G_GNUC_UNUSED WorkbookControl
*wbc
)
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
);
591 wb_view_init_control (wbc
);
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
;
611 wb_view_auto_expr_func (WorkbookView
*wbv
, GnmFunc
*func
)
613 if (wbv
->auto_expr
.func
== func
)
616 if (wbv
->auto_expr
.func
)
617 gnm_func_dec_usage (wbv
->auto_expr
.func
);
620 gnm_func_inc_usage (func
);
621 wbv
->auto_expr
.func
= func
;
623 wb_view_auto_expr_recalc (wbv
);
627 wb_view_auto_expr_descr (WorkbookView
*wbv
, const char *descr
)
631 if (go_str_compare (descr
, wbv
->auto_expr
.descr
) == 0)
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
);
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
)
649 wbv
->auto_expr
.use_max_precision
= use_max_precision
;
651 wb_view_auto_expr_recalc (wbv
);
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
);
662 cb_clear_auto_expr_sheet (WorkbookView
*wbv
)
664 g_object_set (G_OBJECT (wbv
),
665 "auto-expr-eval-pos", NULL
,
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
);
686 GnmExprTop
const *texpr
;
688 wbv
->auto_expr
.sheet_detached_sig
= g_signal_connect_swapped (
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
);
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
));
713 case PROP_AUTO_EXPR_DESCR
:
714 wb_view_auto_expr_descr (wbv
, g_value_get_string (value
));
716 case PROP_AUTO_EXPR_MAX_PRECISION
:
717 wb_view_auto_expr_precision (wbv
, g_value_get_boolean (value
));
719 case PROP_AUTO_EXPR_VALUE
:
720 wb_view_auto_expr_value (wbv
, g_value_get_boxed (value
));
722 case PROP_AUTO_EXPR_EVAL_POS
:
723 wb_view_auto_expr_eval_pos (wbv
, g_value_get_boxed (value
));
725 case PROP_SHOW_HORIZONTAL_SCROLLBAR
:
726 wbv
->show_horizontal_scrollbar
= !!g_value_get_boolean (value
);
728 case PROP_SHOW_VERTICAL_SCROLLBAR
:
729 wbv
->show_vertical_scrollbar
= !!g_value_get_boolean (value
);
731 case PROP_SHOW_NOTEBOOK_TABS
:
732 wbv
->show_notebook_tabs
= !!g_value_get_boolean (value
);
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
);
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
);
744 case PROP_DO_AUTO_COMPLETION
:
745 wbv
->do_auto_completion
= !!g_value_get_boolean (value
);
748 wbv
->is_protected
= !!g_value_get_boolean (value
);
750 case PROP_PREFERRED_WIDTH
:
751 wbv
->preferred_width
= g_value_get_int (value
);
753 case PROP_PREFERRED_HEIGHT
:
754 wbv
->preferred_height
= g_value_get_int (value
);
757 wbv
->wb
= g_value_dup_object (value
);
760 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
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
);
775 case PROP_AUTO_EXPR_DESCR
:
776 g_value_set_string (value
, wbv
->auto_expr
.descr
);
778 case PROP_AUTO_EXPR_MAX_PRECISION
:
779 g_value_set_boolean (value
, wbv
->auto_expr
.use_max_precision
);
781 case PROP_AUTO_EXPR_VALUE
:
782 g_value_set_boxed (value
, wbv
->auto_expr
.value
);
784 case PROP_SHOW_HORIZONTAL_SCROLLBAR
:
785 g_value_set_boolean (value
, wbv
->show_horizontal_scrollbar
);
787 case PROP_SHOW_VERTICAL_SCROLLBAR
:
788 g_value_set_boolean (value
, wbv
->show_vertical_scrollbar
);
790 case PROP_SHOW_NOTEBOOK_TABS
:
791 g_value_set_boolean (value
, wbv
->show_notebook_tabs
);
793 case PROP_SHOW_FUNCTION_CELL_MARKERS
:
794 g_value_set_boolean (value
, wbv
->show_function_cell_markers
);
796 case PROP_SHOW_EXTENSION_MARKERS
:
797 g_value_set_boolean (value
, wbv
->show_extension_markers
);
799 case PROP_DO_AUTO_COMPLETION
:
800 g_value_set_boolean (value
, wbv
->do_auto_completion
);
803 g_value_set_boolean (value
, wbv
->is_protected
);
805 case PROP_PREFERRED_WIDTH
:
806 g_value_set_int (value
, wbv
->preferred_width
);
808 case PROP_PREFERRED_HEIGHT
:
809 g_value_set_int (value
, wbv
->preferred_height
);
812 g_value_set_object (value
, wbv
->wb
);
815 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
821 wb_view_detach_from_workbook (WorkbookView
*wbv
)
823 g_return_if_fail (GNM_IS_WORKBOOK_VIEW (wbv
));
826 workbook_detach_view (wbv
);
828 wbv
->current_sheet
= NULL
;
833 wb_view_constructor (GType type
,
834 guint n_construct_properties
,
835 GObjectConstructParam
*construct_params
)
841 obj
= parent_class
->constructor
842 (type
, n_construct_properties
, construct_params
);
843 wbv
= GNM_WORKBOOK_VIEW (obj
);
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"));
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
);
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
911 g_param_spec_object ("auto-expr-func",
912 P_("Auto-expression function"),
913 P_("The automatically computed sheet function."),
917 g_object_class_install_property
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."),
926 g_object_class_install_property
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"),
935 g_object_class_install_property
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 (),
944 g_object_class_install_property
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 (),
953 g_object_class_install_property
955 PROP_SHOW_HORIZONTAL_SCROLLBAR
,
956 g_param_spec_boolean ("show-horizontal-scrollbar",
957 P_("Show horizontal scrollbar"),
958 P_("Show the horizontal scrollbar"),
962 g_object_class_install_property
964 PROP_SHOW_VERTICAL_SCROLLBAR
,
965 g_param_spec_boolean ("show-vertical-scrollbar",
966 P_("Show vertical scrollbar"),
967 P_("Show the vertical scrollbar"),
971 g_object_class_install_property
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"),
980 g_object_class_install_property
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"),
989 g_object_class_install_property
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"),
998 g_object_class_install_property
1000 PROP_DO_AUTO_COMPLETION
,
1001 g_param_spec_boolean ("do-auto-completion",
1002 P_("Do auto completion"),
1003 P_("Auto-complete text"),
1006 G_PARAM_READWRITE
));
1007 g_object_class_install_property
1010 g_param_spec_boolean ("protected",
1012 P_("Is view protected?"),
1015 G_PARAM_READWRITE
));
1016 g_object_class_install_property
1018 PROP_PREFERRED_WIDTH
,
1019 g_param_spec_int ("preferred-width",
1020 P_("Preferred width"),
1021 P_("Preferred width"),
1024 G_PARAM_READWRITE
));
1025 g_object_class_install_property
1027 PROP_PREFERRED_HEIGHT
,
1028 g_param_spec_int ("preferred-height",
1029 P_("Preferred height"),
1030 P_("Preferred height"),
1033 G_PARAM_READWRITE
));
1034 g_object_class_install_property
1037 g_param_spec_object ("workbook",
1042 G_PARAM_CONSTRUCT_ONLY
|
1043 G_PARAM_READWRITE
));
1045 parent_class
= g_type_class_peek_parent (gobject_class
);
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).
1075 workbook_view_new (Workbook
*wb
)
1078 g_object_new (GNM_WORKBOOK_VIEW_TYPE
, "workbook", wb
, NULL
);
1079 if (wb
) g_object_unref (wb
);
1085 * workbook_view_save_to_output:
1086 * @wbv: #WorkbookView
1088 * @output: #GsfOutput
1089 * @io_context: #GOIOContext
1091 * NOTE : Temporary api until we get the new output framework.
1094 workbook_view_save_to_output (WorkbookView
*wbv
, GOFileSaver
const *fs
,
1095 GsfOutput
*output
, GOIOContext
*io_context
)
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
)))
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
1123 * @uri: destination URI
1124 * @io_context: #GOIOContext
1128 workbook_view_save_to_uri (WorkbookView
*wbv
, GOFileSaver
const *fs
,
1129 char const *uri
, GOIOContext
*io_context
)
1133 GsfOutput
*output
= go_file_create (uri
, &err
);
1135 if (output
== NULL
) {
1137 msg
= g_strdup_printf (_("Can't open '%s' for writing: %s"),
1141 msg
= g_strdup_printf (_("Can't open '%s' for writing"), uri
);
1143 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context
), msg
);
1146 workbook_view_save_to_output (wbv
, fs
, output
, io_context
);
1147 g_object_unref (output
);
1152 get_uri_modtime (GsfInput
*input
, const char *uri
)
1154 GDateTime
*modtime
= NULL
;
1157 modtime
= gsf_input_get_modtime (input
);
1159 g_date_time_ref (modtime
);
1162 if (!modtime
&& uri
)
1163 modtime
= go_file_get_modtime (uri
);
1165 if (gnm_debug_flag ("modtime")) {
1167 ? g_date_time_format (modtime
, "%F %T")
1169 g_printerr ("Modtime of %s is %s\n", uri
, s
);
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.
1190 workbook_view_save_as (WorkbookView
*wbv
, GOFileSaver
*fs
, char const *uri
,
1193 GOIOContext
*io_context
;
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
);
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
);
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
)) {
1218 go_doc_set_dirty (GO_DOC (wb
), FALSE
);
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
);
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
);
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.
1251 workbook_view_save (WorkbookView
*wbv
, GOCmdContext
*context
)
1253 GOIOContext
*io_context
;
1256 gboolean has_error
, has_warning
;
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
);
1264 uri
= go_doc_get_uri (GO_DOC (wb
));
1266 fs
= workbook_get_file_saver (wb
);
1268 fs
= go_file_saver_get_default ();
1270 io_context
= go_io_context_new (context
);
1272 go_cmd_context_error_export (GO_CMD_CONTEXT (io_context
),
1273 _("Default file saver is not available."));
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
);
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
);
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.
1313 workbook_view_new_from_input (GsfInput
*input
,
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
;
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
);
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
),
1353 input_refs
= new_input_refs
;
1362 if (file_opener
!= NULL
) {
1367 new_wbv
= workbook_view_new (NULL
);
1368 new_wb
= wb_view_get_workbook (new_wbv
);
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
);
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
);
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
);
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
1405 go_cmd_context_error_import
1406 (GO_CMD_CONTEXT (io_context
),
1407 _("Unsupported file format."));
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.
1427 workbook_view_new_from_uri (char const *uri
,
1428 GOFileOpener
const *file_opener
,
1429 GOIOContext
*io_context
,
1430 char const *encoding
)
1436 g_return_val_if_fail (uri
!= NULL
, NULL
);
1438 input
= go_file_open (uri
, &err
);
1439 if (input
!= NULL
) {
1442 res
= workbook_view_new_from_input (input
, uri
,
1443 file_opener
, io_context
,
1445 g_object_unref (input
);
1450 if (err
->message
!= NULL
)
1451 msg
= g_strdup (err
->message
);
1456 msg
= g_strdup_printf (_("An unexplained error happened while opening %s"),
1460 go_cmd_context_error_import (GO_CMD_CONTEXT (io_context
), msg
);