Index: ChangeLog =================================================================== RCS file: /cvs/gnome/gnumeric/ChangeLog,v retrieving revision 1.2435 diff -u -3 -p -r1.2435 ChangeLog --- ChangeLog 26 Sep 2002 21:36:18 -0000 1.2435 +++ ChangeLog 26 Sep 2002 22:11:47 -0000 @@ -1,3 +1,7 @@ +2002-09-27 Lutz Müller + + * src/workbook.[c,h]: New signals: "sheet_added" and "sheet_deleted". + 2002-09-26 Andreas J. Guelzow * src/workbook.c (workbook_sheet_reorder): new Index: src/workbook.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/workbook.c,v retrieving revision 1.563 diff -u -3 -p -r1.563 workbook.c --- src/workbook.c 26 Sep 2002 21:36:19 -0000 1.563 +++ src/workbook.c 26 Sep 2002 22:11:48 -0000 @@ -49,6 +49,8 @@ enum { SUMMARY_CHANGED, FILENAME_CHANGED, SHEET_ORDER_CHANGED, + SHEET_ADDED, + SHEET_DELETED, LAST_SIGNAL }; @@ -370,6 +372,24 @@ workbook_class_init (GObjectClass *objec gnm__VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + signals [SHEET_ADDED] = g_signal_new ("sheet_added", + WORKBOOK_TYPE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (WorkbookClass, sheet_added), + (GSignalAccumulator) NULL, NULL, + gnm__VOID__VOID, + G_TYPE_NONE, + 0, G_TYPE_NONE); + + signals [SHEET_DELETED] = g_signal_new ("sheet_deleted", + WORKBOOK_TYPE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (WorkbookClass, sheet_deleted), + (GSignalAccumulator) NULL, NULL, + gnm__VOID__VOID, + G_TYPE_NONE, + 0, G_TYPE_NONE); } /** @@ -974,6 +994,8 @@ workbook_sheet_add (Workbook *wb, Sheet if (make_dirty) sheet_set_dirty (new_sheet, TRUE); + g_signal_emit (G_OBJECT (wb), signals [SHEET_ADDED], 0); + return new_sheet; } @@ -1033,6 +1055,8 @@ workbook_sheet_delete (Sheet *sheet) /* All is fine, remove the sheet */ workbook_sheet_detach (wb, sheet); + + g_signal_emit (G_OBJECT (wb), signals [SHEET_DELETED], 0); } /** Index: src/workbook.h =================================================================== RCS file: /cvs/gnome/gnumeric/src/workbook.h,v retrieving revision 1.112 diff -u -3 -p -r1.112 workbook.h --- src/workbook.h 26 Sep 2002 21:36:19 -0000 1.112 +++ src/workbook.h 26 Sep 2002 22:11:48 -0000 @@ -52,6 +52,8 @@ typedef struct { void (*summary_changed) (Workbook *wb); void (*filename_changed) (Workbook *wb); void (*sheet_order_changed) (Workbook *wb); + void (*sheet_added) (Workbook *wb); + void (*sheet_deleted) (Workbook *wb); } WorkbookClass; GType workbook_get_type (void); Index: src/dialogs/ChangeLog =================================================================== RCS file: /cvs/gnome/gnumeric/src/dialogs/ChangeLog,v retrieving revision 1.581 diff -u -3 -p -r1.581 ChangeLog --- src/dialogs/ChangeLog 25 Sep 2002 22:37:57 -0000 1.581 +++ src/dialogs/ChangeLog 26 Sep 2002 22:11:50 -0000 @@ -1,3 +1,8 @@ +2002-09-27 Lutz Müller + + * dialog-sheet-order.c: Try to catch up with changes done outside + of the dialog. + 2002-09-26 Lutz Müller * src/dialogs/dialog-sheet-order.c: On ok, we don't care any longer Index: src/dialogs/dialog-sheet-order.c =================================================================== RCS file: /cvs/gnome/gnumeric/src/dialogs/dialog-sheet-order.c,v retrieving revision 1.39 diff -u -3 -p -r1.39 dialog-sheet-order.c --- src/dialogs/dialog-sheet-order.c 25 Sep 2002 22:37:57 -0000 1.39 +++ src/dialogs/dialog-sheet-order.c 26 Sep 2002 22:11:51 -0000 @@ -69,6 +69,8 @@ typedef struct { GSList *old_order; gulong sheet_order_changed_listener; + gulong sheet_added_listener; + gulong sheet_deleted_listener; } SheetManager; enum { @@ -663,6 +665,8 @@ cb_ok_clicked (GtkWidget *ignore, SheetM /* Stop listening to changes in the sheet order. */ g_signal_handler_block (G_OBJECT (wb), state->sheet_order_changed_listener); + g_signal_handler_block (G_OBJECT (wb), state->sheet_added_listener); + g_signal_handler_block (G_OBJECT (wb), state->sheet_deleted_listener); if ((new_order == NULL && changed_names == NULL && color_changed == NULL && protection_changed == NULL) @@ -673,11 +677,16 @@ cb_ok_clicked (GtkWidget *ignore, SheetM protection_changed, new_locks)) { gtk_widget_destroy (GTK_WIDGET (state->dialog)); } else { + /* Restart listening to changes in the sheet order. */ g_signal_handler_unblock (G_OBJECT (wb), state->sheet_order_changed_listener); + g_signal_handler_unblock (G_OBJECT (wb), + state->sheet_added_listener); + g_signal_handler_unblock (G_OBJECT (wb), + state->sheet_deleted_listener); } - + if (deleted_sheets) { g_slist_foreach (deleted_sheets, cb_delete_sheets, NULL); g_slist_free (deleted_sheets); @@ -693,6 +702,10 @@ cb_sheet_order_destroy (GtkWidget *ignor /* Stop to listen to changes in the sheet order. */ g_signal_handler_disconnect (G_OBJECT (wb), state->sheet_order_changed_listener); + g_signal_handler_disconnect (G_OBJECT (wb), + state->sheet_added_listener); + g_signal_handler_disconnect (G_OBJECT (wb), + state->sheet_deleted_listener); wbcg_edit_detach_guru (state->wbcg); g_object_unref (G_OBJECT (state->gui)); @@ -719,32 +732,67 @@ dialog_sheet_order_update_sheet_order (S GdkColor *back, *fore; GtkTreeIter iter; Workbook *wb = wb_control_workbook (WORKBOOK_CONTROL (state->wbcg)); - gint i, j, n_sheets, n_children; + gint i, j, k, n_sheets, n_children, offset = 0; GtkTreeModel *model = GTK_TREE_MODEL (state->model); - Sheet *sheet_wb, *sheet_model; + Sheet *sheet_wb, *sheet_model, *sheet; GtkTreeSelection *sel = gtk_tree_view_get_selection (state->sheet_list); gboolean selected; n_sheets = workbook_sheet_count (wb); n_children = gtk_tree_model_iter_n_children (model, NULL); - g_return_if_fail (n_sheets == n_children); for (i = 0; i < n_sheets; i++) { sheet_wb = workbook_sheet_by_index (wb, i); - for (j = i; j < n_children; j++) { - if (!gtk_tree_model_iter_nth_child (model, &iter, - NULL, j)) - break; + + /* Search this sheet in our list. */ + for (j = i + offset; j < n_children; j++) { + gtk_tree_model_iter_nth_child (model, &iter, NULL, j); gtk_tree_model_get (model, &iter, SHEET_POINTER, &sheet_model, -1); if (sheet_model == sheet_wb) break; } - if (j == i) + if (j == i + offset) { + + /* Perfect. The sheet is where we like it. */ continue; + } + if (j == n_children) { - if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, j)) - break; + /* + * This sheet is not yet in our list. It will + * (hopefully) be added later by cb_sheet_added. + */ + offset--; + continue; + } + + /* It could be that there are some newly added sheets here. */ + for (; i + offset < j; offset++) { + gtk_tree_model_iter_nth_child (model, &iter, NULL, + i + offset); + gtk_tree_model_get (model, &iter, SHEET_POINTER, + &sheet, -1); + for (k = i + 1; k < n_sheets; k++) + if (sheet == workbook_sheet_by_index (wb, k)) + break; + if (k < n_sheets) + break; + } + if (i + offset == j) { + + /* + * There are only new sheets between the 'correct' + * place and the current one. Nothing to do. + */ + continue; + } + + /* + * The sheet is not where it should be. Move it to the + * correct place. + */ + gtk_tree_model_iter_nth_child (model, &iter, NULL, j); selected = gtk_tree_selection_iter_is_selected (sel, &iter); gtk_tree_model_get (model, &iter, SHEET_LOCKED, &is_locked, @@ -757,7 +805,7 @@ dialog_sheet_order_update_sheet_order (S FOREGROUND_COLOUR_POINTER, &fore, -1); gtk_list_store_remove (state->model, &iter); - gtk_list_store_insert (state->model, &iter, i); + gtk_list_store_insert (state->model, &iter, i + offset); gtk_list_store_set (state->model, &iter, SHEET_LOCKED, is_locked, SHEET_LOCK_IMAGE, is_locked ? @@ -794,21 +842,33 @@ cb_sheet_order_changed (Workbook *wb, Sh { GtkTreeIter iter; GtkTreeModel *model = GTK_TREE_MODEL (state->model); - guint i, n = 0; + guint i, n = 0, offset = 0; + guint n_children; Sheet *sheet; + g_message ("sheet_order_changed"); + /* * First question: Has the user already changed the order via * the dialog? If no, we assume that the user wants to see the * sheet order change reflected in the dialog. */ n = g_slist_length (state->old_order); + n_children = gtk_tree_model_iter_n_children (model, NULL); for (i = 0; i < n; i++) { - if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, i)) - break; - gtk_tree_model_get (model, &iter, SHEET_POINTER, &sheet, -1); - if (sheet != g_slist_nth_data (state->old_order, i)) + for (; i + offset < n_children; offset++) { + gtk_tree_model_iter_nth_child (model, &iter, + NULL, i + offset); + gtk_tree_model_get (model, &iter, SHEET_POINTER, + &sheet, -1); + if (sheet == g_slist_nth_data (state->old_order, i)) + break; + } + if (i + offset == n_children) { + + /* The order is different. */ break; + } } if (n == i) { dialog_sheet_order_update_sheet_order (state); @@ -822,11 +882,20 @@ cb_sheet_order_changed (Workbook *wb, Sh */ n = workbook_sheet_count (wb); for (i = 0; i < n; i++) { - if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, i)) - break; - gtk_tree_model_get (model, &iter, SHEET_POINTER, &sheet, -1); - if (sheet != workbook_sheet_by_index (wb, i)) + for (; i + offset < n_children; offset++) { + gtk_tree_model_iter_nth_child (model, &iter, + NULL, i + offset); + gtk_tree_model_get (model, &iter, SHEET_POINTER, + &sheet, -1); + if (sheet == workbook_sheet_by_index (wb, i)) + break; + } + + if (i + offset == n_children) { + + /* The order is different. */ break; + } } if (i == n) { g_slist_free (state->old_order); @@ -847,6 +916,142 @@ cb_sheet_order_changed (Workbook *wb, Sh dialog_sheet_order_update_sheet_order (state); } +static void +cb_sheet_added (Workbook *wb, SheetManager *state) +{ + GtkTreeModel *model = GTK_TREE_MODEL (state->model); + GtkTreeIter iter; + gint n_sheets, n_children, new_index, i; + gint pos_before = 0, pos_after = 0, row; + Sheet *sheet, *new_sheet = NULL; + Sheet *sheet_before = NULL, *sheet_after = NULL; + GdkColor *color = NULL; + GdkColor *text_color = NULL; + + g_message ("sheet_added"); + + n_sheets = workbook_sheet_count (wb); + n_children = gtk_tree_model_iter_n_children (model, NULL); + + /* Identify the new sheet. */ + for (new_index = 0; new_index < n_sheets; new_index++) { + new_sheet = workbook_sheet_by_index (wb, new_index); + for (i = 0; i < n_children; i++) { + gtk_tree_model_iter_nth_child (model, &iter, NULL, i); + gtk_tree_model_get (model, &iter, SHEET_POINTER, + &sheet, -1); + if (sheet == new_sheet) + break; + } + if (i == n_children) + break; + } + g_return_if_fail (new_index < n_sheets); + g_return_if_fail (IS_SHEET (new_sheet)); + + /* + * Check if the sheet before and after are in that order in the + * dialog. + */ + if (new_index > 0) { + sheet = workbook_sheet_by_index (wb, new_index - 1); + + /* Search the position of the sheet before the new sheet. */ + for (pos_before = 0; pos_before < n_children; pos_before++) { + gtk_tree_model_iter_nth_child (model, &iter, NULL, + pos_before); + gtk_tree_model_get (model, &iter, SHEET_POINTER, + &sheet_before, -1); + if (sheet_before == sheet) + break; + } + g_return_if_fail (pos_before < n_children); + } + if (new_index < n_sheets - 1) { + sheet = workbook_sheet_by_index (wb, new_index + 1); + + /* Search the position of the sheet after the new sheet. */ + for (pos_after = 0; pos_after < n_children; pos_after++) { + gtk_tree_model_iter_nth_child (model, &iter, NULL, + pos_after); + gtk_tree_model_get (model, &iter, SHEET_POINTER, + &sheet_after, -1); + if (sheet_after == sheet) + break; + } + g_return_if_fail (pos_after < n_children); + } + + /* + * Determine where to insert the new sheet in our list. Default is + * at the end. + */ + if (sheet_before && sheet_after) { + if ((sheet_before == workbook_sheet_by_index (wb, new_index - 1)) && + (sheet_after == workbook_sheet_by_index (wb, new_index + 1))) + row = pos_before + 1; + } else if (sheet_before) { + if (sheet_before == workbook_sheet_by_index (wb, new_index - 1)) + row = pos_before + 1; + } else if (sheet_after) { + if (sheet_after == workbook_sheet_by_index (wb, new_index + 1)) + row = pos_after; + } else + row = n_children; + + /* Now insert the sheet. */ + g_message ("Sheet (index %i) will be inserted at row %i.", new_index, row); + if (new_sheet->tab_color) + color = &new_sheet->tab_color->color; + if (new_sheet->tab_text_color) + text_color = &new_sheet->tab_text_color->color; + gtk_list_store_insert (state->model, &iter, row); + gtk_list_store_set (state->model, &iter, + SHEET_LOCKED, new_sheet->is_protected, + SHEET_LOCK_IMAGE, new_sheet->is_protected ? + state->image_padlock : state->image_padlock_no, + SHEET_NAME, new_sheet->name_unquoted, + SHEET_NEW_NAME, "", + SHEET_POINTER, new_sheet, + IS_EDITABLE_COLUMN, TRUE, + IS_DELETED, FALSE, + BACKGROUND_COLOUR_POINTER, color, + FOREGROUND_COLOUR_POINTER, text_color, -1); + + cb_selection_changed (NULL, state); +} + +static void +cb_sheet_deleted (Workbook *wb, SheetManager *state) +{ + GtkTreeIter iter; + GtkTreeModel *model = GTK_TREE_MODEL (state->model); + GSList *l; + gint n_sheets, n_children, i, j; + Sheet *sheet = NULL; + + g_message ("sheet_deleted"); + + /* Search the deleted sheet in our list and remove it from there. */ + n_sheets = workbook_sheet_count (wb); + n_children = gtk_tree_model_iter_n_children (model, NULL); + for (i = 0; i < n_children; i++) { + gtk_tree_model_iter_nth_child (model, &iter, NULL, i); + gtk_tree_model_get (model, &iter, SHEET_POINTER, &sheet, -1); + for (j = 0; j < n_sheets; j++) + if (sheet == workbook_sheet_by_index (wb, j)) + break; + if (j == n_sheets) + break; + } + g_return_if_fail (i < n_children); + + gtk_list_store_remove (state->model, &iter); + state->old_order = g_slist_remove (state->old_order, sheet); + + cb_selection_changed (NULL, state); +} + void dialog_sheet_order (WorkbookControlGUI *wbcg) { @@ -890,6 +1095,10 @@ dialog_sheet_order (WorkbookControlGUI * state->sheet_order_changed_listener = g_signal_connect (G_OBJECT (wb), "sheet_order_changed", G_CALLBACK (cb_sheet_order_changed), state); + state->sheet_added_listener = g_signal_connect (G_OBJECT (wb), + "sheet_added", G_CALLBACK (cb_sheet_added), state); + state->sheet_deleted_listener = g_signal_connect (G_OBJECT (wb), + "sheet_deleted", G_CALLBACK (cb_sheet_deleted), state); gtk_button_stock_alignment_set (GTK_BUTTON (state->up_btn), 0., .5, 0., 0.); gtk_button_stock_alignment_set (GTK_BUTTON (state->down_btn), 0., .5, 0., 0.); @@ -961,7 +1170,7 @@ dialog_sheet_order (WorkbookControlGUI * "destroy", G_CALLBACK (cb_sheet_order_destroy), state); gnumeric_non_modal_dialog (state->wbcg, GTK_WINDOW (state->dialog)); - wbcg_edit_attach_guru (state->wbcg, GTK_WIDGET (state->dialog)); +// wbcg_edit_attach_guru (state->wbcg, GTK_WIDGET (state->dialog)); gtk_widget_show_all (GTK_WIDGET (state->dialog)); }