2 * dialog-comparet-order.c: Dialog to compare two sheets.
4 * (C) Copyright 2018 Morten Welinder (terra@gnome.org)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20 #include <gnumeric-config.h>
21 #include <glib/gi18n-lib.h>
23 #include <sheet-diff.h>
24 #include <dialogs/dialogs.h>
25 #include <dialogs/help.h>
29 #include <workbook-view.h>
31 #include <workbook-priv.h>
35 #include <sheet-style.h>
36 #include <application.h>
37 #include <selection.h>
38 #include <sheet-view.h>
39 #include <widgets/gnm-sheet-sel.h>
40 #include <widgets/gnm-workbook-sel.h>
42 #define SHEET_COMPARE_KEY "sheet-compare-dialog"
65 DIR_QUIET
// Like CHANGED, but for always-changed context
76 GtkWidget
*cancel_btn
;
77 GtkWidget
*compare_btn
;
79 GtkWidget
*sheet_sel_A
;
80 GtkWidget
*sheet_sel_B
;
83 GtkWidget
*results_window
;
85 GtkTreeView
*results_view
;
86 GtkTreeStore
*results
;
88 gboolean has_cell_section
;
89 GtkTreeIter cell_section_iter
;
91 gboolean has_style_section
;
92 GtkTreeIter style_section_iter
;
94 gboolean has_colrow_section
;
95 GtkTreeIter colrow_section_iter
;
103 cb_sheet_compare_destroy (SheetCompare
*state
)
105 Workbook
*wb
= wb_control_get_workbook (GNM_WBC (state
->wbcg
));
107 g_object_unref (state
->gui
);
108 g_object_set_data (G_OBJECT (wb
), SHEET_COMPARE_KEY
, NULL
);
115 cb_cancel_clicked (G_GNUC_UNUSED GtkWidget
*ignore
,
118 gtk_widget_destroy (GTK_WIDGET (state
->dialog
));
122 create_wb_selector (SheetCompare
*state
, GtkWidget
*sheet_sel
)
124 GtkWidget
*res
= gnm_workbook_sel_new ();
125 gnm_sheet_sel_link (GNM_SHEET_SEL (sheet_sel
),
126 GNM_WORKBOOK_SEL (res
));
131 select_default_sheets (SheetCompare
*state
)
133 Workbook
*wb
= wb_control_get_workbook (GNM_WBC (state
->wbcg
));
134 GList
*wb_list
= gnm_app_workbook_list ();
136 if (g_list_length (wb_list
) > 1) {
137 // Multiple workbooks
139 gnm_workbook_sel_set_workbook
140 (GNM_WORKBOOK_SEL (state
->wb_sel_A
), wb
);
141 gnm_workbook_sel_set_workbook
142 (GNM_WORKBOOK_SEL (state
->wb_sel_B
),
143 wb
== wb_list
->data
? wb_list
->next
->data
: wb_list
->data
);
144 } else if (workbook_sheet_count (wb
) > 1) {
145 // One workbook, multiple sheets
146 gnm_sheet_sel_set_sheet (GNM_SHEET_SEL (state
->sheet_sel_B
),
147 workbook_sheet_by_index (wb
, 1));
149 // One workbook, one sheet
153 /* ------------------------------------------------------------------------- */
156 setup_section (SheetCompare
*state
, gboolean
*phas
, GtkTreeIter
*iter
,
160 gtk_tree_store_insert (state
->results
, iter
, NULL
, -1);
161 gtk_tree_store_set (state
->results
, iter
,
162 ITEM_SECTION
, section
,
163 ITEM_DIRECTION
, DIR_NA
,
170 extract_range (GnmRangeRef
const *rr
, GnmRange
*r
, Sheet
**psheet
)
172 *psheet
= rr
->a
.sheet
;
173 r
->start
.col
= rr
->a
.col
;
174 r
->start
.row
= rr
->a
.row
;
175 r
->end
.col
= rr
->b
.col
;
176 r
->end
.row
= rr
->b
.row
;
180 loc_from_range (GnmRangeRef
*loc
, Sheet
*sheet
, GnmRange
const *r
)
182 gnm_cellref_init (&loc
->a
, sheet
,
183 r
->start
.col
, r
->start
.row
,
185 gnm_cellref_init (&loc
->b
, sheet
,
186 r
->end
.col
, r
->end
.row
,
191 get_mstyle_name (int e
)
194 case MSTYLE_COLOR_BACK
: return _("Background color");
195 case MSTYLE_COLOR_PATTERN
: return _("Pattern color");
197 case MSTYLE_BORDER_TOP
: return _("Top border");
198 case MSTYLE_BORDER_BOTTOM
: return _("Bottom border");
199 case MSTYLE_BORDER_LEFT
: return _("Left border");
200 case MSTYLE_BORDER_RIGHT
: return _("Right border");
201 case MSTYLE_BORDER_REV_DIAGONAL
: return _("Reverse diagonal border");
202 case MSTYLE_BORDER_DIAGONAL
: return _("Diagonal border");
203 case MSTYLE_PATTERN
: return _("Pattern");
205 case MSTYLE_FONT_COLOR
: return _("Font color");
206 case MSTYLE_FONT_NAME
: return _("Font");
207 case MSTYLE_FONT_BOLD
: return _("Bold");
208 case MSTYLE_FONT_ITALIC
: return _("Italic");
209 case MSTYLE_FONT_UNDERLINE
: return _("Underline");
210 case MSTYLE_FONT_STRIKETHROUGH
: return _("Strikethrough");
211 case MSTYLE_FONT_SCRIPT
: return _("Script");
212 case MSTYLE_FONT_SIZE
: return _("Size");
214 case MSTYLE_FORMAT
: return _("Format");
216 case MSTYLE_ALIGN_V
: return _("Vertical alignment");
217 case MSTYLE_ALIGN_H
: return _("Horizontal alignment");
218 case MSTYLE_INDENT
: return _("Indentation");
219 case MSTYLE_ROTATION
: return _("Rotation");
220 case MSTYLE_TEXT_DIR
: return _("Direction");
221 case MSTYLE_WRAP_TEXT
: return _("Wrap");
222 case MSTYLE_SHRINK_TO_FIT
: return _("Shrink-to-fit");
224 case MSTYLE_CONTENTS_LOCKED
: return _("Locked");
225 case MSTYLE_CONTENTS_HIDDEN
: return _("Hidden");
227 case MSTYLE_VALIDATION
: return _("Validation");
228 case MSTYLE_HLINK
: return _("Hyperlink");
229 case MSTYLE_INPUT_MSG
: return _("Input message");
230 case MSTYLE_CONDITIONS
: return _("Conditional format");
237 section_renderer_func (GtkTreeViewColumn
*tree_column
,
238 GtkCellRenderer
*cell
,
244 const char *text
= "?";
247 gtk_tree_model_get (model
, iter
,
248 ITEM_SECTION
, §ion
,
249 ITEM_DIRECTION
, &dir
,
255 case SEC_CELLS
: text
= _("Cells"); break;
256 case SEC_STYLE
: text
= _("Formatting"); break;
257 case SEC_COLROW
: text
= _("Columns/Rows"); break;
263 text
= (e
== -1) ? _("Various") : get_mstyle_name (e
);
272 case DIR_ADDED
: text
= _("Added"); break;
273 case DIR_REMOVED
: text
= _("Removed"); break;
274 case DIR_CHANGED
: text
= _("Changed"); break;
277 g_object_set (cell
, "text", text
, NULL
);
281 location_renderer_func (GtkTreeViewColumn
*tree_column
,
282 GtkCellRenderer
*cell
,
287 GnmRangeRef
*loc_old
= NULL
;
288 GnmRangeRef
*loc_new
= NULL
;
291 gtk_tree_model_get (model
, iter
,
292 ITEM_OLD_LOC
, &loc_new
,
293 ITEM_NEW_LOC
, &loc_old
,
296 loc
= loc_old
? loc_old
: loc_new
;
303 extract_range (loc
, &r
, &sheet
);
305 if (range_is_full (&r
, sheet
, TRUE
) &&
306 r
.start
.row
== r
.end
.row
)
307 text
= str
= g_strdup_printf
308 (_("Row %s"), row_name (r
.start
.row
));
309 else if (range_is_full (&r
, sheet
, FALSE
) &&
310 r
.start
.col
== r
.end
.col
)
311 text
= str
= g_strdup_printf
312 (_("Column %s"), col_name (r
.start
.col
));
314 text
= range_as_string (&r
);
316 g_object_set (cell
, "text", text
, NULL
);
319 g_object_set (cell
, "text", "", NULL
);
326 do_color (GnmColor
const *gcolor
)
328 GOColor color
= gcolor
->go_color
;
331 const char *coltxt
= NULL
;
335 GO_COLOR_TO_RGBA (color
, &r
, &g
, &b
, &a
);
337 snprintf (buf
, sizeof (buf
), "#%02X%02X%02X", r
, g
, b
);
339 snprintf (buf
, sizeof (buf
), "#%02X%02X%02X%02X", r
, g
, b
, a
);
341 for (n
= 0; go_color_palette_query (n
, &nc
); n
++) {
342 if (nc
.color
== color
) {
348 return g_strdup_printf
349 ("%s%s (<span bgcolor=\"%s\"> </span>)",
350 gcolor
->is_auto
? "Auto " : "",
351 coltxt
? coltxt
: buf
,
358 return g_strdup (b
? _("Yes") : _("No"));
364 return g_strdup_printf ("%d", i
);
370 return g_strdup_printf ("%g", d
);
374 do_halign (GnmHAlign h
)
377 case GNM_HALIGN_GENERAL
: return g_strdup (_("General"));
378 case GNM_HALIGN_LEFT
: return g_strdup (_("Left"));
379 case GNM_HALIGN_RIGHT
: return g_strdup (_("Right"));
380 case GNM_HALIGN_CENTER
: return g_strdup (_("Center"));
381 case GNM_HALIGN_FILL
: return g_strdup (_("Fill"));
382 case GNM_HALIGN_JUSTIFY
: return g_strdup (_("Justify"));
383 case GNM_HALIGN_CENTER_ACROSS_SELECTION
: return g_strdup (_("Center across selection"));
384 case GNM_HALIGN_DISTRIBUTED
: return g_strdup (_("Distributed"));
385 default: return g_strdup ("?");
390 do_valign (GnmVAlign v
)
393 case GNM_VALIGN_TOP
: return g_strdup (_("Top"));
394 case GNM_VALIGN_BOTTOM
: return g_strdup (_("Bottom"));
395 case GNM_VALIGN_CENTER
: return g_strdup (_("Center"));
396 case GNM_VALIGN_JUSTIFY
: return g_strdup (_("Justify"));
397 case GNM_VALIGN_DISTRIBUTED
: return g_strdup (_("Distributed"));
398 default: return g_strdup ("?");
402 static const char *underlines
[] = {
403 N_("None"), N_("Single"), N_("Double"),
404 N_("Single low"), N_("Double low"), NULL
407 static const char *textdirs
[] = {
408 N_("Right-to-left"), N_("Auto"), N_("Left-to-right"), NULL
412 do_enum (int i
, const char *const choices
[])
414 if (i
< 0 || i
>= (int)g_strv_length ((gchar
**)choices
))
415 return g_strdup ("?");
416 return g_strdup (_(choices
[i
]));
421 oldnew_renderer_func (GtkTreeViewColumn
*tree_column
,
422 GtkCellRenderer
*cell
,
427 gboolean qnew
= GPOINTER_TO_UINT (user_data
);
428 GnmRangeRef
*loc
= NULL
;
432 gboolean qmarkup
= FALSE
;
434 gtk_tree_model_get (model
, iter
,
435 ITEM_SECTION
, §ion
,
436 ITEM_DIRECTION
, &dir
,
437 (qnew
? ITEM_NEW_LOC
: ITEM_OLD_LOC
), &loc
,
439 ITEM_QCOLS
, &is_cols
,
441 if (dir
== DIR_NA
|| !loc
|| !loc
->a
.sheet
)
444 if (section
== SEC_CELLS
) {
445 GnmCell
const *cell
=
446 sheet_cell_get (loc
->a
.sheet
, loc
->a
.col
, loc
->a
.row
);
449 text
= gnm_cell_get_entered_text (cell
);
450 } else if (section
== SEC_STYLE
) {
451 GnmStyle
const *style
;
455 style
= sheet_style_get (loc
->a
.sheet
, loc
->a
.col
, loc
->a
.row
);
458 case MSTYLE_COLOR_BACK
:
459 text
= do_color (gnm_style_get_back_color (style
));
462 case MSTYLE_COLOR_PATTERN
:
463 text
= do_color (gnm_style_get_pattern_color (style
));
466 case MSTYLE_FONT_COLOR
:
467 text
= do_color (gnm_style_get_font_color (style
));
471 // TODO: Add api to get pattern name from goffice
472 text
= do_int (gnm_style_get_pattern (style
));
475 case MSTYLE_FONT_NAME
:
476 text
= g_strdup (gnm_style_get_font_name (style
));
478 case MSTYLE_FONT_BOLD
:
479 text
= do_bool (gnm_style_get_font_bold (style
));
481 case MSTYLE_FONT_ITALIC
:
482 text
= do_bool (gnm_style_get_font_italic (style
));
484 case MSTYLE_FONT_UNDERLINE
:
485 text
= do_enum (gnm_style_get_font_uline (style
),
488 case MSTYLE_FONT_STRIKETHROUGH
:
489 text
= do_bool (gnm_style_get_font_strike (style
));
491 case MSTYLE_FONT_SCRIPT
:
492 text
= do_int (gnm_style_get_font_script (style
));
494 case MSTYLE_FONT_SIZE
:
495 text
= do_double (gnm_style_get_font_size (style
));
497 case MSTYLE_ROTATION
:
498 text
= do_int (gnm_style_get_rotation (style
));
501 text
= do_int (gnm_style_get_indent (style
));
505 text
= g_strdup (go_format_as_XL (gnm_style_get_format (style
)));
508 case MSTYLE_TEXT_DIR
:
509 text
= do_enum (1 + gnm_style_get_text_dir (style
),
513 text
= do_halign (gnm_style_get_align_h (style
));
516 text
= do_valign (gnm_style_get_align_v (style
));
518 case MSTYLE_CONTENTS_LOCKED
:
519 text
= do_bool (gnm_style_get_contents_locked (style
));
521 case MSTYLE_CONTENTS_HIDDEN
:
522 text
= do_bool (gnm_style_get_contents_hidden (style
));
526 text
= g_strdup (_("Unavailable"));
528 } else if (section
== SEC_COLROW
) {
529 ColRowInfo
const *cr
=
530 sheet_colrow_get_info (loc
->a
.sheet
, e
, is_cols
);
531 text
= g_strdup_printf (ngettext ("%d pixel", "%d pixels", cr
->size_pixels
), cr
->size_pixels
);
536 (qmarkup
? "markup" : "text"),
537 (text
? text
: ""), NULL
);
544 text
= g_strdup ("?");
549 dsc_sheet_start (gpointer user
, Sheet
const *os
, Sheet
const *ns
)
551 SheetCompare
*state
= user
;
552 state
->old_sheet
= (Sheet
*)os
;
553 state
->new_sheet
= (Sheet
*)ns
;
557 dsc_sheet_end (gpointer user
)
559 SheetCompare
*state
= user
;
560 state
->old_sheet
= NULL
;
561 state
->new_sheet
= NULL
;
565 dsc_cell_changed (gpointer user
, GnmCell
const *oc
, GnmCell
const *nc
)
567 SheetCompare
*state
= user
;
571 setup_section (state
,
572 &state
->has_cell_section
,
573 &state
->cell_section_iter
,
576 dir
= (oc
? (nc
? DIR_CHANGED
: DIR_REMOVED
) : DIR_ADDED
);
578 gtk_tree_store_insert (state
->results
, &iter
,
579 &state
->cell_section_iter
,
581 gtk_tree_store_set (state
->results
, &iter
,
582 ITEM_SECTION
, SEC_CELLS
,
588 gnm_cellref_init (&loc
.a
, oc
->base
.sheet
,
589 oc
->pos
.col
, oc
->pos
.row
,
592 gtk_tree_store_set (state
->results
, &iter
,
599 gnm_cellref_init (&loc
.a
, nc
->base
.sheet
,
600 nc
->pos
.col
, nc
->pos
.row
,
603 gtk_tree_store_set (state
->results
, &iter
,
610 dsc_style_changed (gpointer user
, GnmRange
const *r
,
611 GnmStyle
const *os
, GnmStyle
const *ns
)
613 SheetCompare
*state
= user
;
614 GtkTreeIter iter
, piter
;
615 GnmRangeRef loc_old
, loc_new
;
616 unsigned int conflicts
;
619 conflicts
= gnm_style_find_differences (os
, ns
, TRUE
);
621 setup_section (state
,
622 &state
->has_style_section
,
623 &state
->style_section_iter
,
626 loc_from_range (&loc_old
, state
->old_sheet
, r
);
627 loc_from_range (&loc_new
, state
->new_sheet
, r
);
629 piter
= state
->style_section_iter
;
630 estart
= ((conflicts
& (conflicts
- 1)) == 0 ? 0 : -1);
631 for (e
= estart
; e
< MSTYLE_ELEMENT_MAX
; e
++) {
632 gboolean qhead
= (e
== -1);
633 if (!qhead
&& (conflicts
& (1u << e
)) == 0)
636 gtk_tree_store_insert (state
->results
, &iter
, &piter
, -1);
637 if (qhead
) piter
= iter
;
639 gtk_tree_store_set (state
->results
, &iter
,
640 ITEM_SECTION
, SEC_STYLE
,
641 ITEM_DIRECTION
, DIR_QUIET
,
642 ITEM_OLD_LOC
, &loc_old
,
643 ITEM_NEW_LOC
, &loc_new
,
650 dsc_colrow_changed (gpointer user
, ColRowInfo
const *oc
, ColRowInfo
const *nc
,
651 gboolean is_cols
, int i
)
653 SheetCompare
*state
= user
;
655 GnmRangeRef loc_old
, loc_new
;
658 (is_cols
? range_init_cols
: range_init_rows
)
659 (&rold
, state
->old_sheet
, i
, i
);
660 loc_from_range (&loc_old
, state
->old_sheet
, &rold
);
662 (is_cols
? range_init_cols
: range_init_rows
)
663 (&rnew
, state
->new_sheet
, i
, i
);
664 loc_from_range (&loc_new
, state
->new_sheet
, &rnew
);
666 setup_section (state
,
667 &state
->has_colrow_section
,
668 &state
->colrow_section_iter
,
671 gtk_tree_store_insert (state
->results
,
672 &iter
, &state
->colrow_section_iter
, -1);
674 gtk_tree_store_set (state
->results
, &iter
,
675 ITEM_SECTION
, SEC_COLROW
,
676 ITEM_DIRECTION
, DIR_QUIET
,
677 ITEM_OLD_LOC
, &loc_old
,
678 ITEM_NEW_LOC
, &loc_new
,
684 static const GnmDiffActions dsc_actions
= {
685 .sheet_start
= dsc_sheet_start
,
686 .sheet_end
= dsc_sheet_end
,
687 .cell_changed
= dsc_cell_changed
,
688 .style_changed
= dsc_style_changed
,
689 .colrow_changed
= dsc_colrow_changed
,
693 cb_compare_clicked (G_GNUC_UNUSED GtkWidget
*ignore
,
696 GtkTreeView
*tv
= state
->results_view
;
697 GtkTreeStore
*ts
= gtk_tree_store_new
699 G_TYPE_INT
, // Enum, really
700 G_TYPE_INT
, // Enum, really
701 gnm_rangeref_get_type (),
702 gnm_rangeref_get_type (),
705 Sheet
*sheet_A
, *sheet_B
;
707 if (gtk_tree_view_get_n_columns (tv
) == 0) {
708 GtkTreeViewColumn
*tvc
;
711 tvc
= gtk_tree_view_column_new ();
712 cr
= gtk_cell_renderer_text_new ();
713 gtk_tree_view_column_set_title (tvc
, _("Description"));
714 gtk_tree_view_column_set_cell_data_func
715 (tvc
, cr
, section_renderer_func
, NULL
, NULL
);
716 gtk_tree_view_column_pack_start (tvc
, cr
, TRUE
);
717 gtk_tree_view_append_column (tv
, tvc
);
719 tvc
= gtk_tree_view_column_new ();
720 cr
= gtk_cell_renderer_text_new ();
721 gtk_tree_view_column_set_title (tvc
, _("Location"));
722 gtk_tree_view_column_set_cell_data_func
723 (tvc
, cr
, location_renderer_func
, NULL
, NULL
);
724 gtk_tree_view_column_pack_start (tvc
, cr
, TRUE
);
725 gtk_tree_view_append_column (tv
, tvc
);
727 tvc
= gtk_tree_view_column_new ();
728 cr
= gtk_cell_renderer_text_new ();
729 g_object_set (G_OBJECT (cr
), "max-width-chars", 30, NULL
);
730 gtk_tree_view_column_set_title (tvc
, _("Old"));
731 gtk_tree_view_column_set_cell_data_func
732 (tvc
, cr
, oldnew_renderer_func
,
733 GUINT_TO_POINTER (FALSE
), NULL
);
734 gtk_tree_view_column_pack_start (tvc
, cr
, TRUE
);
735 gtk_tree_view_append_column (tv
, tvc
);
737 tvc
= gtk_tree_view_column_new ();
738 cr
= gtk_cell_renderer_text_new ();
739 g_object_set (G_OBJECT (cr
), "max-width-chars", 30, NULL
);
740 gtk_tree_view_column_set_title (tvc
, _("New"));
741 gtk_tree_view_column_set_cell_data_func
742 (tvc
, cr
, oldnew_renderer_func
,
743 GUINT_TO_POINTER (TRUE
), NULL
);
744 gtk_tree_view_column_pack_start (tvc
, cr
, TRUE
);
745 gtk_tree_view_append_column (tv
, tvc
);
748 state
->has_cell_section
= FALSE
;
749 state
->has_style_section
= FALSE
;
750 state
->has_colrow_section
= FALSE
;
752 sheet_A
= gnm_sheet_sel_get_sheet (GNM_SHEET_SEL (state
->sheet_sel_A
));
753 sheet_B
= gnm_sheet_sel_get_sheet (GNM_SHEET_SEL (state
->sheet_sel_B
));
755 if (sheet_A
&& sheet_B
) {
757 gnm_diff_sheets (&dsc_actions
, state
, sheet_A
, sheet_B
);
758 state
->results
= NULL
;
761 gtk_tree_view_set_model (tv
, GTK_TREE_MODEL (ts
));
764 gtk_notebook_set_current_page (GTK_NOTEBOOK (state
->notebook
), 1);
768 find_and_focus (GnmRangeRef
const *loc
, SheetView
*avoid
)
776 extract_range (loc
, &r
, &loc_sheet
);
777 wb
= loc_sheet
->workbook
;
779 WORKBOOK_FOREACH_VIEW(wb
, view
, {
781 int col
= r
.start
.col
;
782 int row
= r
.start
.row
;
784 sv
= wb_view_cur_sheet_view (view
);
788 if (wb_view_cur_sheet (view
) != loc_sheet
)
791 gnm_sheet_view_set_edit_pos (sv
, &r
.start
);
792 sv_selection_set (sv
, &r
.start
, col
, row
, col
, row
);
793 gnm_sheet_view_make_cell_visible (sv
, col
, row
, FALSE
);
794 gnm_sheet_view_update (sv
);
801 cb_cursor_changed (GtkTreeView
*tree_view
, SheetCompare
*state
)
805 GnmRangeRef
*loc_old
= NULL
;
806 GnmRangeRef
*loc_new
= NULL
;
807 GtkTreeModel
*model
= gtk_tree_view_get_model (tree_view
);
811 gtk_tree_view_get_cursor (tree_view
, &path
, NULL
);
815 ok
= gtk_tree_model_get_iter (model
, &iter
, path
);
816 gtk_tree_path_free (path
);
820 gtk_tree_model_get (model
, &iter
,
821 ITEM_OLD_LOC
, &loc_new
,
822 ITEM_NEW_LOC
, &loc_old
,
825 sv
= find_and_focus (loc_old
, NULL
);
826 (void)find_and_focus (loc_new
, sv
);
832 /* ------------------------------------------------------------------------- */
835 dialog_sheet_compare (WBCGtk
*wbcg
)
843 g_return_if_fail (wbcg
!= NULL
);
845 wb
= wb_control_get_workbook (GNM_WBC (wbcg
));
847 gui
= gnm_gtk_builder_load ("res:ui/sheet-compare.ui", NULL
, GO_CMD_CONTEXT (wbcg
));
851 /* Only pop up one copy per workbook */
852 if (gnm_dialog_raise_if_exists (wbcg
, SHEET_COMPARE_KEY
))
855 layout
= gtk_widget_create_pango_layout (GTK_WIDGET (wbcg_toplevel (wbcg
)), "Mg19");
856 pango_layout_get_pixel_size (layout
, &width
, &height
);
857 g_object_unref (layout
);
859 g_object_set_data (G_OBJECT (wb
), SHEET_COMPARE_KEY
, (gpointer
) gui
);
860 state
= g_new0 (SheetCompare
, 1);
863 state
->dialog
= go_gtk_builder_get_widget (gui
, "sheet-compare-dialog");
864 state
->notebook
= go_gtk_builder_get_widget (gui
, "notebook");
865 state
->cancel_btn
= go_gtk_builder_get_widget (gui
, "cancel_button");
866 state
->compare_btn
= go_gtk_builder_get_widget (gui
, "compare_button");
867 state
->results_window
= go_gtk_builder_get_widget (gui
, "results_window");
868 state
->results_view
= GTK_TREE_VIEW (go_gtk_builder_get_widget (gui
, "results_treeview"));
870 gtk_widget_set_size_request (state
->results_window
,
874 state
->sheet_sel_A
= gnm_sheet_sel_new ();
875 state
->wb_sel_A
= create_wb_selector (state
, state
->sheet_sel_A
);
876 go_gtk_widget_replace (go_gtk_builder_get_widget (gui
, "sheet_selector_A"),
878 go_gtk_widget_replace (go_gtk_builder_get_widget (gui
, "wb_selector_A"),
881 state
->sheet_sel_B
= gnm_sheet_sel_new ();
882 state
->wb_sel_B
= create_wb_selector (state
, state
->sheet_sel_B
);
883 go_gtk_widget_replace (go_gtk_builder_get_widget (gui
, "sheet_selector_B"),
885 go_gtk_widget_replace (go_gtk_builder_get_widget (gui
, "wb_selector_B"),
888 select_default_sheets (state
);
890 #define CONNECT(o,s,c) g_signal_connect(G_OBJECT(o),s,G_CALLBACK(c),state)
891 CONNECT (state
->cancel_btn
, "clicked", cb_cancel_clicked
);
892 CONNECT (state
->compare_btn
, "clicked", cb_compare_clicked
);
893 CONNECT (state
->results_view
, "cursor-changed", cb_cursor_changed
);
896 /* a candidate for merging into attach guru */
897 wbc_gtk_attach_guru (state
->wbcg
, GTK_WIDGET (state
->dialog
));
898 g_object_set_data_full (G_OBJECT (state
->dialog
),
900 (GDestroyNotify
) cb_sheet_compare_destroy
);
902 gnm_restore_window_geometry (GTK_WINDOW (state
->dialog
),
905 go_gtk_nonmodal_dialog (wbcg_toplevel (state
->wbcg
),
906 GTK_WINDOW (state
->dialog
));
907 gtk_widget_show_all (GTK_WIDGET (state
->dialog
));