diff: use new selector widgets
[gnumeric.git] / src / dialogs / dialog-sheet-compare.c
blob37ac9d06dc9c88e63410e16c6f334df2e2156985
1 /*
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>
22 #include <gnumeric.h>
23 #include "sheet-diff.h"
24 #include "dialogs.h"
25 #include "help.h"
27 #include <gui-util.h>
28 #include <wbc-gtk.h>
29 #include <workbook-view.h>
30 #include <workbook.h>
31 #include <sheet.h>
32 #include <ranges.h>
33 #include <cell.h>
34 #include <sheet-style.h>
35 #include <application.h>
36 #include <widgets/gnm-sheet-sel.h>
37 #include <widgets/gnm-workbook-sel.h>
39 #define SHEET_COMPARE_KEY "sheet-compare-dialog"
41 enum {
42 ITEM_SECTION,
43 ITEM_DIRECTION,
44 ITEM_OLD_LOC,
45 ITEM_NEW_LOC,
46 ITEM_MSTYLE_ELEM,
47 NUM_COLUMNS
50 enum {
51 SEC_CELLS,
52 SEC_STYLE
55 enum {
56 DIR_NA,
57 DIR_ADDED,
58 DIR_REMOVED,
59 DIR_CHANGED,
60 DIR_QUIET // Like CHANGED, but for always-changed context
64 typedef struct {
65 WBCGtk *wbcg;
67 GtkBuilder *gui;
68 GtkWidget *dialog;
69 GtkWidget *notebook;
71 GtkWidget *cancel_btn;
72 GtkWidget *compare_btn;
74 GtkWidget *sheet_sel_A;
75 GtkWidget *sheet_sel_B;
76 GtkWidget *wb_sel_A;
77 GtkWidget *wb_sel_B;
78 GtkWidget *results_window;
80 GtkTreeView *results_view;
81 GtkTreeStore *results;
83 gboolean has_cell_section;
84 GtkTreeIter cell_section_iter;
86 gboolean has_style_section;
87 GtkTreeIter style_section_iter;
89 Sheet *old_sheet;
90 Sheet *new_sheet;
91 } SheetCompare;
94 static void
95 cb_sheet_compare_destroy (SheetCompare *state)
97 Workbook *wb = wb_control_get_workbook (GNM_WBC (state->wbcg));
99 g_object_unref (state->gui);
100 g_object_set_data (G_OBJECT (wb), SHEET_COMPARE_KEY, NULL);
101 state->gui = NULL;
103 g_free (state);
106 static void
107 cb_cancel_clicked (G_GNUC_UNUSED GtkWidget *ignore,
108 SheetCompare *state)
110 gtk_widget_destroy (GTK_WIDGET (state->dialog));
113 static GtkWidget *
114 create_wb_selector (SheetCompare *state, GtkWidget *sheet_sel)
116 GtkWidget *res = gnm_workbook_sel_new ();
117 gnm_sheet_sel_link (GNM_SHEET_SEL (sheet_sel),
118 GNM_WORKBOOK_SEL (res));
119 return res;
122 static void
123 select_default_sheets (SheetCompare *state)
125 Workbook *wb = wb_control_get_workbook (GNM_WBC (state->wbcg));
126 GList *wb_list = gnm_app_workbook_list ();
128 if (g_list_length (wb_list) > 1) {
129 // Multiple workbooks
131 gnm_workbook_sel_set_workbook
132 (GNM_WORKBOOK_SEL (state->wb_sel_A), wb);
133 gnm_workbook_sel_set_workbook
134 (GNM_WORKBOOK_SEL (state->wb_sel_B),
135 wb == wb_list->data ? wb_list->next->data : wb_list->data);
136 } else if (workbook_sheet_count (wb) > 1) {
137 // One workbook, multiple sheets
138 gnm_sheet_sel_set_sheet (GNM_SHEET_SEL (state->sheet_sel_B),
139 workbook_sheet_by_index (wb, 1));
140 } else {
141 // One workbook, one sheet
145 /* ------------------------------------------------------------------------- */
147 static void
148 setup_section (SheetCompare *state, gboolean *phas, GtkTreeIter *iter,
149 int section)
151 if (!*phas) {
152 gtk_tree_store_insert (state->results, iter, NULL, -1);
153 gtk_tree_store_set (state->results, iter,
154 ITEM_SECTION, section,
155 ITEM_DIRECTION, DIR_NA,
156 -1);
157 *phas = TRUE;
161 static void
162 extract_range (GnmRangeRef const *rr, GnmRange *r, Sheet **psheet)
164 *psheet = rr->a.sheet;
165 r->start.col = rr->a.col;
166 r->start.row = rr->a.row;
167 r->end.col = rr->b.col;
168 r->end.row = rr->b.row;
171 static const char *
172 get_mstyle_name (int e)
174 switch (e) {
175 case MSTYLE_COLOR_BACK: return _("Background color");
176 case MSTYLE_COLOR_PATTERN: return _("Pattern color");
178 case MSTYLE_BORDER_TOP: return _("Top border");
179 case MSTYLE_BORDER_BOTTOM: return _("Bottom border");
180 case MSTYLE_BORDER_LEFT: return _("Left border");
181 case MSTYLE_BORDER_RIGHT: return _("Right border");
182 case MSTYLE_BORDER_REV_DIAGONAL: return _("Reverse diagonal border");
183 case MSTYLE_BORDER_DIAGONAL: return _("Diagonal border");
184 case MSTYLE_PATTERN: return _("Pattern");
186 case MSTYLE_FONT_COLOR: return _("Color");
187 case MSTYLE_FONT_NAME: return _("Font");
188 case MSTYLE_FONT_BOLD: return _("Bold");
189 case MSTYLE_FONT_ITALIC: return _("Italic");
190 case MSTYLE_FONT_UNDERLINE: return _("Underline");
191 case MSTYLE_FONT_STRIKETHROUGH: return _("Strikethrough");
192 case MSTYLE_FONT_SCRIPT: return _("Script");
193 case MSTYLE_FONT_SIZE: return _("Size");
195 case MSTYLE_FORMAT: return _("Format");
197 case MSTYLE_ALIGN_V: return _("Vertical alignment");
198 case MSTYLE_ALIGN_H: return _("Horizontal alignment");
199 case MSTYLE_INDENT: return _("Indentation");
200 case MSTYLE_ROTATION: return _("Rotation");
201 case MSTYLE_TEXT_DIR: return _("Direction");
202 case MSTYLE_WRAP_TEXT: return _("Wrap");
203 case MSTYLE_SHRINK_TO_FIT: return _("Shrink-to-fit");
205 case MSTYLE_CONTENTS_LOCKED: return _("Locked");
206 case MSTYLE_CONTENTS_HIDDEN: return _("Hidden");
208 case MSTYLE_VALIDATION: return _("Validation");
209 case MSTYLE_HLINK: return _("Hyperlink");
210 case MSTYLE_INPUT_MSG: return _("Input message");
211 case MSTYLE_CONDITIONS: return _("Conditional format");
212 default: return "?";
217 static void
218 section_renderer_func (GtkTreeViewColumn *tree_column,
219 GtkCellRenderer *cell,
220 GtkTreeModel *model,
221 GtkTreeIter *iter,
222 gpointer user_data)
224 int section, dir;
225 const char *text = "?";
226 int e;
228 gtk_tree_model_get (model, iter,
229 ITEM_SECTION, &section,
230 ITEM_DIRECTION, &dir,
231 ITEM_MSTYLE_ELEM, &e,
232 -1);
233 switch (dir) {
234 case DIR_NA:
235 switch (section) {
236 case SEC_CELLS: text = _("Cells"); break;
237 case SEC_STYLE: text = _("Formatting"); break;
239 break;
240 case DIR_QUIET:
241 text = (e == -1) ? _("Various") : get_mstyle_name (e);
242 break;
243 case DIR_ADDED: text = _("Added"); break;
244 case DIR_REMOVED: text = _("Removed"); break;
245 case DIR_CHANGED: text = _("Changed"); break;
248 g_object_set (cell, "text", text, NULL);
251 static void
252 location_renderer_func (GtkTreeViewColumn *tree_column,
253 GtkCellRenderer *cell,
254 GtkTreeModel *model,
255 GtkTreeIter *iter,
256 gpointer user_data)
258 GnmRangeRef *loc_old = NULL;
259 GnmRangeRef *loc_new = NULL;
260 GnmRangeRef *loc;
262 gtk_tree_model_get (model, iter,
263 ITEM_OLD_LOC, &loc_new,
264 ITEM_NEW_LOC, &loc_old,
265 -1);
267 loc = loc_old ? loc_old : loc_new;
268 if (loc) {
269 GnmRange r;
270 Sheet *sheet;
271 extract_range (loc, &r, &sheet);
272 g_object_set (cell, "text", range_as_string (&r), NULL);
273 } else
274 g_object_set (cell, "text", "", NULL);
276 g_free (loc_old);
277 g_free (loc_new);
280 static char *
281 do_color (GnmColor const *gcolor)
283 GOColor color = gcolor->go_color;
284 unsigned r, g, b, a;
285 char buf[16];
286 const char *coltxt = NULL;
287 int n;
288 GONamedColor nc;
290 GO_COLOR_TO_RGBA (color, &r, &g, &b, &a);
291 if (a == 0xff)
292 snprintf (buf, sizeof (coltxt), "#%02X%02X%02X", r, g, b);
293 else
294 snprintf (buf, sizeof (coltxt), "#%02X%02X%02X%02X", r, g, b, a);
296 for (n = 0; go_color_palette_query (n, &nc); n++) {
297 if (nc.color == color) {
298 coltxt = nc.name;
299 break;
303 return g_strdup_printf
304 ("%s%s (<span bgcolor=\"%s\"> </span>)",
305 gcolor->is_auto ? "Auto " : "",
306 coltxt ? coltxt : buf,
307 buf);
310 static char *
311 do_bool (gboolean b)
313 return g_strdup (b ? _("Yes") : _("No"));
316 static char *
317 do_int (int i)
319 return g_strdup_printf ("%d", i);
322 static char *
323 do_double (double d)
325 return g_strdup_printf ("%g", d);
328 static char *
329 do_halign (GnmHAlign h)
331 switch (h) {
332 case GNM_HALIGN_GENERAL: return g_strdup (_("General"));
333 case GNM_HALIGN_LEFT: return g_strdup (_("Left"));
334 case GNM_HALIGN_RIGHT: return g_strdup (_("Right"));
335 case GNM_HALIGN_CENTER: return g_strdup (_("Center"));
336 case GNM_HALIGN_FILL: return g_strdup (_("Fill"));
337 case GNM_HALIGN_JUSTIFY: return g_strdup (_("Justify"));
338 case GNM_HALIGN_CENTER_ACROSS_SELECTION: return g_strdup (_("Center across selection"));
339 case GNM_HALIGN_DISTRIBUTED: return g_strdup (_("Distributed"));
340 default: return g_strdup ("?");
344 static char *
345 do_valign (GnmVAlign v)
347 switch (v) {
348 case GNM_VALIGN_TOP: return g_strdup (_("Top"));
349 case GNM_VALIGN_BOTTOM: return g_strdup (_("Bottom"));
350 case GNM_VALIGN_CENTER: return g_strdup (_("Center"));
351 case GNM_VALIGN_JUSTIFY: return g_strdup (_("Justify"));
352 case GNM_VALIGN_DISTRIBUTED: return g_strdup (_("Distributed"));
353 default: return g_strdup ("?");
357 static const char *underlines[] = {
358 N_("None"), N_("Single"), N_("Double"),
359 N_("Single low"), N_("Double low"), NULL
362 static const char *textdirs[] = {
363 N_("Right-to-left"), N_("Auto"), N_("Left-to-rightDouble"), NULL
366 static char *
367 do_enum (int i, const char *const choices[])
369 if (i < 0 || i >= (int)g_strv_length ((gchar **)choices))
370 return g_strdup ("?");
371 return g_strdup (_(choices[i]));
375 static void
376 oldnew_renderer_func (GtkTreeViewColumn *tree_column,
377 GtkCellRenderer *cell,
378 GtkTreeModel *model,
379 GtkTreeIter *iter,
380 gpointer user_data)
382 gboolean qnew = GPOINTER_TO_UINT (user_data);
383 GnmRangeRef *loc = NULL;
384 int section, dir, e;
385 char *text = NULL;
386 gboolean qmarkup = FALSE;
388 gtk_tree_model_get (model, iter,
389 ITEM_SECTION, &section,
390 ITEM_DIRECTION, &dir,
391 (qnew ? ITEM_NEW_LOC : ITEM_OLD_LOC), &loc,
392 ITEM_MSTYLE_ELEM, &e,
393 -1);
394 if (dir == DIR_NA || !loc || !loc->a.sheet)
395 goto done;
397 if (section == SEC_CELLS) {
398 GnmCell const *cell =
399 sheet_cell_get (loc->a.sheet, loc->a.col, loc->a.row);
400 if (!cell)
401 goto error;
402 text = gnm_cell_get_entered_text (cell);
403 } else if (section == SEC_STYLE) {
404 GnmStyle const *style;
405 if (e == -1)
406 goto done;
408 style = sheet_style_get (loc->a.sheet, loc->a.col, loc->a.row);
410 switch (e) {
411 case MSTYLE_COLOR_BACK:
412 text = do_color (gnm_style_get_back_color (style));
413 qmarkup = TRUE;
414 break;
415 case MSTYLE_COLOR_PATTERN:
416 text = do_color (gnm_style_get_pattern_color (style));
417 qmarkup = TRUE;
418 break;
419 case MSTYLE_FONT_COLOR:
420 text = do_color (gnm_style_get_font_color (style));
421 qmarkup = TRUE;
422 break;
423 case MSTYLE_PATTERN:
424 // TODO: Add api to get pattern name from goffice
425 text = do_int (gnm_style_get_pattern (style));
426 break;
428 case MSTYLE_FONT_BOLD:
429 text = do_bool (gnm_style_get_font_bold (style));
430 break;
431 case MSTYLE_FONT_ITALIC:
432 text = do_bool (gnm_style_get_font_italic (style));
433 break;
434 case MSTYLE_FONT_UNDERLINE:
435 text = do_enum (gnm_style_get_font_uline (style),
436 underlines);
437 break;
438 case MSTYLE_FONT_STRIKETHROUGH:
439 text = do_bool (gnm_style_get_font_strike (style));
440 break;
441 case MSTYLE_FONT_SCRIPT:
442 text = do_int (gnm_style_get_font_script (style));
443 break;
444 case MSTYLE_FONT_SIZE:
445 text = do_double (gnm_style_get_font_size (style));
446 break;
447 case MSTYLE_ROTATION:
448 text = do_int (gnm_style_get_rotation (style));
449 break;
450 case MSTYLE_INDENT:
451 text = do_int (gnm_style_get_indent (style));
452 break;
454 case MSTYLE_FORMAT:
455 text = g_strdup (go_format_as_XL (gnm_style_get_format (style)));
456 break;
458 case MSTYLE_TEXT_DIR:
459 text = do_enum (1 + gnm_style_get_text_dir (style),
460 textdirs);
461 break;
462 case MSTYLE_ALIGN_H:
463 text = do_halign (gnm_style_get_align_h (style));
464 break;
465 case MSTYLE_ALIGN_V:
466 text = do_valign (gnm_style_get_align_v (style));
467 break;
468 case MSTYLE_CONTENTS_LOCKED:
469 text = do_bool (gnm_style_get_contents_locked (style));
470 break;
471 case MSTYLE_CONTENTS_HIDDEN:
472 text = do_bool (gnm_style_get_contents_hidden (style));
473 break;
475 default:
476 text = g_strdup (_("Unavailable"));
481 done:
482 g_object_set (cell,
483 (qmarkup ? "markup" : "text"),
484 (text ? text : ""), NULL);
485 g_free (text);
487 g_free (loc);
488 return;
490 error:
491 text = g_strdup ("?");
492 goto done;
495 static void
496 dsc_sheet_start (gpointer user, Sheet const *os, Sheet const *ns)
498 SheetCompare *state = user;
499 state->old_sheet = (Sheet *)os;
500 state->new_sheet = (Sheet *)ns;
503 static void
504 dsc_sheet_end (gpointer user)
506 SheetCompare *state = user;
507 state->old_sheet = NULL;
508 state->new_sheet = NULL;
511 static void
512 dsc_cell_changed (gpointer user, GnmCell const *oc, GnmCell const *nc)
514 SheetCompare *state = user;
515 GtkTreeIter iter;
516 int dir;
518 setup_section (state,
519 &state->has_cell_section,
520 &state->cell_section_iter,
521 SEC_CELLS);
523 dir = (oc ? (nc ? DIR_CHANGED : DIR_REMOVED) : DIR_ADDED);
525 gtk_tree_store_insert (state->results, &iter,
526 &state->cell_section_iter,
527 -1);
528 gtk_tree_store_set (state->results, &iter,
529 ITEM_SECTION, SEC_CELLS,
530 ITEM_DIRECTION, dir,
531 -1);
533 if (oc) {
534 GnmRangeRef loc;
535 gnm_cellref_init (&loc.a, oc->base.sheet,
536 oc->pos.col, oc->pos.row,
537 FALSE);
538 loc.b = loc.a;
539 gtk_tree_store_set (state->results, &iter,
540 ITEM_OLD_LOC, &loc,
541 -1);
544 if (nc) {
545 GnmRangeRef loc;
546 gnm_cellref_init (&loc.a, nc->base.sheet,
547 nc->pos.col, nc->pos.row,
548 FALSE);
549 loc.b = loc.a;
550 gtk_tree_store_set (state->results, &iter,
551 ITEM_NEW_LOC, &loc,
552 -1);
556 static void
557 dsc_style_changed (gpointer user, GnmRange const *r,
558 GnmStyle const *os, GnmStyle const *ns)
560 SheetCompare *state = user;
561 GtkTreeIter iter, piter;
562 GnmRangeRef loc_old, loc_new;
563 unsigned int conflicts;
564 int e, estart;
566 conflicts = gnm_style_find_differences (os, ns, TRUE);
568 setup_section (state,
569 &state->has_style_section,
570 &state->style_section_iter,
571 SEC_STYLE);
573 gnm_cellref_init (&loc_old.a, state->old_sheet,
574 r->start.col, r->start.row,
575 FALSE);
576 gnm_cellref_init (&loc_old.b, state->old_sheet,
577 r->end.col, r->end.row,
578 FALSE);
579 loc_new = loc_old;
580 loc_new.a.sheet = loc_new.b.sheet = state->new_sheet;
582 piter = state->style_section_iter;
583 estart = ((conflicts & (conflicts - 1)) == 0 ? 0 : -1);
584 for (e = estart; e < MSTYLE_ELEMENT_MAX; e++) {
585 gboolean qhead = (e == -1);
586 if (!qhead && (conflicts & (1u << e)) == 0)
587 continue;
589 gtk_tree_store_insert (state->results, &iter, &piter, -1);
590 if (qhead) piter = iter;
592 gtk_tree_store_set (state->results, &iter,
593 ITEM_SECTION, SEC_STYLE,
594 ITEM_DIRECTION, DIR_QUIET,
595 ITEM_OLD_LOC, &loc_old,
596 ITEM_NEW_LOC, &loc_new,
597 ITEM_MSTYLE_ELEM, e,
598 -1);
602 static const GnmDiffActions dsc_actions = {
603 .sheet_start = dsc_sheet_start,
604 .sheet_end = dsc_sheet_end,
605 .cell_changed = dsc_cell_changed,
606 .style_changed = dsc_style_changed,
609 static void
610 cb_compare_clicked (G_GNUC_UNUSED GtkWidget *ignore,
611 SheetCompare *state)
613 GtkTreeView *tv = state->results_view;
614 GtkTreeStore *ts = gtk_tree_store_new
615 (NUM_COLUMNS,
616 G_TYPE_INT, // Enum, really
617 G_TYPE_INT, // Enum, really
618 gnm_rangeref_get_type (),
619 gnm_rangeref_get_type (),
620 G_TYPE_INT); // GnmStyleElement
621 Sheet *sheet_A, *sheet_B;
623 if (gtk_tree_view_get_n_columns (tv) == 0) {
624 GtkTreeViewColumn *tvc;
625 GtkCellRenderer *cr;
627 tvc = gtk_tree_view_column_new ();
628 cr = gtk_cell_renderer_text_new ();
629 gtk_tree_view_column_set_title (tvc, _("Description"));
630 gtk_tree_view_column_set_cell_data_func
631 (tvc, cr, section_renderer_func, NULL, NULL);
632 gtk_tree_view_column_pack_start (tvc, cr, TRUE);
633 gtk_tree_view_append_column (tv, tvc);
635 tvc = gtk_tree_view_column_new ();
636 cr = gtk_cell_renderer_text_new ();
637 gtk_tree_view_column_set_title (tvc, _("Location"));
638 gtk_tree_view_column_set_cell_data_func
639 (tvc, cr, location_renderer_func, NULL, NULL);
640 gtk_tree_view_column_pack_start (tvc, cr, TRUE);
641 gtk_tree_view_append_column (tv, tvc);
643 tvc = gtk_tree_view_column_new ();
644 cr = gtk_cell_renderer_text_new ();
645 gtk_tree_view_column_set_title (tvc, _("Old"));
646 gtk_tree_view_column_set_cell_data_func
647 (tvc, cr, oldnew_renderer_func,
648 GUINT_TO_POINTER (FALSE), NULL);
649 gtk_tree_view_column_pack_start (tvc, cr, TRUE);
650 gtk_tree_view_append_column (tv, tvc);
652 tvc = gtk_tree_view_column_new ();
653 cr = gtk_cell_renderer_text_new ();
654 gtk_tree_view_column_set_title (tvc, _("New"));
655 gtk_tree_view_column_set_cell_data_func
656 (tvc, cr, oldnew_renderer_func,
657 GUINT_TO_POINTER (TRUE), NULL);
658 gtk_tree_view_column_pack_start (tvc, cr, TRUE);
659 gtk_tree_view_append_column (tv, tvc);
662 state->has_cell_section = FALSE;
663 state->has_style_section = FALSE;
665 sheet_A = gnm_sheet_sel_get_sheet (GNM_SHEET_SEL (state->sheet_sel_A));
666 sheet_B = gnm_sheet_sel_get_sheet (GNM_SHEET_SEL (state->sheet_sel_B));
668 if (sheet_A && sheet_B) {
669 state->results = ts;
670 gnm_diff_sheets (&dsc_actions, state, sheet_A, sheet_B);
671 state->results = NULL;
674 gtk_tree_view_set_model (tv, GTK_TREE_MODEL (ts));
675 g_object_unref (ts);
677 gtk_notebook_set_current_page (GTK_NOTEBOOK (state->notebook), 1);
680 /* ------------------------------------------------------------------------- */
682 void
683 dialog_sheet_compare (WBCGtk *wbcg)
685 SheetCompare *state;
686 GtkBuilder *gui;
687 Workbook *wb;
688 PangoLayout *layout;
689 int height, width;
691 g_return_if_fail (wbcg != NULL);
693 wb = wb_control_get_workbook (GNM_WBC (wbcg));
695 gui = gnm_gtk_builder_load ("sheet-compare.ui", NULL, GO_CMD_CONTEXT (wbcg));
696 if (gui == NULL)
697 return;
699 /* Only pop up one copy per workbook */
700 if (gnm_dialog_raise_if_exists (wbcg, SHEET_COMPARE_KEY))
701 return;
703 layout = gtk_widget_create_pango_layout (GTK_WIDGET (wbcg_toplevel (wbcg)), "Mg19");
704 pango_layout_get_pixel_size (layout, &width, &height);
705 g_object_unref (layout);
707 g_object_set_data (G_OBJECT (wb), SHEET_COMPARE_KEY, (gpointer) gui);
708 state = g_new0 (SheetCompare, 1);
709 state->gui = gui;
710 state->wbcg = wbcg;
711 state->dialog = go_gtk_builder_get_widget (gui, "sheet-compare-dialog");
712 state->notebook = go_gtk_builder_get_widget (gui, "notebook");
713 state->cancel_btn = go_gtk_builder_get_widget (gui, "cancel_button");
714 state->compare_btn = go_gtk_builder_get_widget (gui, "compare_button");
715 state->results_window = go_gtk_builder_get_widget (gui, "results_window");
716 state->results_view = GTK_TREE_VIEW (go_gtk_builder_get_widget (gui, "results_treeview"));
718 gtk_widget_set_size_request (state->results_window,
719 width / 4 * 40,
720 height * 10);
722 state->sheet_sel_A = gnm_sheet_sel_new ();
723 state->wb_sel_A = create_wb_selector (state, state->sheet_sel_A);
724 go_gtk_widget_replace (go_gtk_builder_get_widget (gui, "sheet_selector_A"),
725 state->sheet_sel_A);
726 go_gtk_widget_replace (go_gtk_builder_get_widget (gui, "wb_selector_A"),
727 state->wb_sel_A);
729 state->sheet_sel_B = gnm_sheet_sel_new ();
730 state->wb_sel_B = create_wb_selector (state, state->sheet_sel_B);
731 go_gtk_widget_replace (go_gtk_builder_get_widget (gui, "sheet_selector_B"),
732 state->sheet_sel_B);
733 go_gtk_widget_replace (go_gtk_builder_get_widget (gui, "wb_selector_B"),
734 state->wb_sel_B);
736 select_default_sheets (state);
738 #define CONNECT(o,s,c) g_signal_connect(G_OBJECT(o),s,G_CALLBACK(c),state)
739 CONNECT (state->cancel_btn, "clicked", cb_cancel_clicked);
740 CONNECT (state->compare_btn, "clicked", cb_compare_clicked);
741 #undef CONNECT
743 /* a candidate for merging into attach guru */
744 wbc_gtk_attach_guru (state->wbcg, GTK_WIDGET (state->dialog));
745 g_object_set_data_full (G_OBJECT (state->dialog),
746 "state", state,
747 (GDestroyNotify) cb_sheet_compare_destroy);
749 gnm_restore_window_geometry (GTK_WINDOW (state->dialog),
750 SHEET_COMPARE_KEY);
752 go_gtk_nonmodal_dialog (wbcg_toplevel (state->wbcg),
753 GTK_WINDOW (state->dialog));
754 gtk_widget_show_all (GTK_WIDGET (state->dialog));