Commit 0b2eae22 authored by Andreas J. Guelzow's avatar Andreas J. Guelzow Committed by Andreas J. Guelzow

add src/dialogs/dao-gui-utils.c, src/dialogs/dialog-merge.c,

2002-03-12  Andreas J. Guelzow <aguelzow@taliesin.ca>

	* POTFILES.in : add src/dialogs/dao-gui-utils.c,
	src/dialogs/dialog-merge.c, src/dialogs/merge.glade and
	src/tools/dao.c

2002-03-12  Andreas J. Guelzow <aguelzow@taliesin.ca>

	* workbook-control-gui.c : add Merge to the Edit/Fill menu
	(cb_tools_merge) : new
	* commands.h (cmd_merge_data) : new
	* commands.c : implement the cmd_merge_data command
	(cmd_set_comment_finalize) : simplify

2002-03-12  Andreas J. Guelzow <aguelzow@taliesin.ca>

	* merge.glade : new dialog for the Merge tool
	* dialog-merge.c : newly implemented Merge tool
	* dialogs.h (dialog_merge) : new
	* Makefile.am : add dialog-merge.c and merge.glade
parent 8003739f
2002-03-12 Andreas J. Guelzow <aguelzow@taliesin.ca>
* workbook-control-gui.c : add Merge to the Edit/Fill menu
(cb_tools_merge) : new
* commands.h (cmd_merge_data) : new
* commands.c : implement the cmd_merge_data command
(cmd_set_comment_finalize) : simplify
2002-03-12 Morten Welinder <terra@diku.dk>
* src/sheet.c (sheet_destroy_contents): Plug leak.
......
......@@ -3,6 +3,7 @@ Gnumeric 1.1.2
Andreas:
* Make Single-Factor ANOVA undoable.
* Port search dialog.
* Add merge tool.
Jody:
* Fix XL import of external function names.
......
2002-03-12 Andreas J. Guelzow <aguelzow@taliesin.ca>
* workbook-control-gui.c : add Merge to the Edit/Fill menu
(cb_tools_merge) : new
* commands.h (cmd_merge_data) : new
* commands.c : implement the cmd_merge_data command
(cmd_set_comment_finalize) : simplify
2002-03-12 Morten Welinder <terra@diku.dk>
* src/sheet.c (sheet_destroy_contents): Plug leak.
......
2002-03-12 Andreas J. Guelzow <aguelzow@taliesin.ca>
* workbook-control-gui.c : add Merge to the Edit/Fill menu
(cb_tools_merge) : new
* commands.h (cmd_merge_data) : new
* commands.c : implement the cmd_merge_data command
(cmd_set_comment_finalize) : simplify
2002-03-12 Morten Welinder <terra@diku.dk>
* src/sheet.c (sheet_destroy_contents): Plug leak.
......
2002-03-12 Andreas J. Guelzow <aguelzow@taliesin.ca>
* POTFILES.in : add src/dialogs/dao-gui-utils.c,
src/dialogs/dialog-merge.c, src/dialogs/merge.glade and
src/tools/dao.c
2002-03-12 Duarte Loreto <happyguy_pt@hotmail.com>
* pt.po: Updated Portuguese translation.
......
......@@ -73,6 +73,7 @@ src/dialogs/col-width.glade
src/dialogs/consolidate.glade
src/dialogs/correlation.glade
src/dialogs/covariance.glade
src/dialogs/dao-gui-utils.c
src/dialogs/delete-cells.glade
src/dialogs/descriptive-stats.glade
src/dialogs/dialog-about.c
......@@ -92,6 +93,7 @@ src/dialogs/dialog-goal-seek.c
src/dialogs/dialog-goto-cell.c
src/dialogs/dialog-graph-guru.c
src/dialogs/dialog-insert-cells.c
src/dialogs/dialog-merge.c
src/dialogs/dialog-paste-special.c
src/dialogs/dialog-plugin-manager.c
src/dialogs/dialog-printer-setup.c
......@@ -127,6 +129,7 @@ src/dialogs/hf-config.glade
src/dialogs/histogram.glade
src/dialogs/insert-cells.glade
src/dialogs/mean-tests.glade
src/dialogs/merge.glade
src/dialogs/moving-averages.glade
src/dialogs/names.glade
src/dialogs/plugin-manager.glade
......@@ -206,6 +209,7 @@ src/stf-parse.c
src/stf.c
src/style.c
src/tools/analysis-tools.c
src/tools/dao.c
src/tools/solver/reports.c
src/tools/solver/solver.c
src/validation.c
......
......@@ -4202,14 +4202,13 @@ static void
cmd_set_comment_finalize (GObject *cmd)
{
CmdSetComment *me = CMD_SET_COMMENT (cmd);
if (me->new_text != NULL) {
g_free (me->new_text);
me->new_text = NULL;
}
if (me->old_text != NULL) {
g_free (me->old_text);
me->old_text = NULL;
}
g_free (me->new_text);
me->new_text = NULL;
g_free (me->old_text);
me->old_text = NULL;
gnumeric_command_finalize (cmd);
}
......@@ -4250,7 +4249,6 @@ cmd_set_comment (WorkbookControl *wbc,
return command_push_undo (wbc, obj);
}
/******************************************************************/
/******************************************************************/
#define CMD_ANALYSIS_TOOL_TYPE (cmd_analysis_tool_get_type ())
......@@ -4281,11 +4279,6 @@ cmd_analysis_tool_undo (GnumericCommand *cmd, WorkbookControl *wbc)
switch (me->type) {
case NewSheetOutput:
/*
* Why only pristine? Suppose we undo this (and rebuild the sheet) the sheet pointer will
* have changed therefore we would also need to fix all commands that may refer to that
* sheet pointer...
*/
if (!command_undo_sheet_delete (me->dao->sheet))
return TRUE;
me->dao->sheet = NULL;
......@@ -4401,3 +4394,159 @@ cmd_analysis_tool (WorkbookControl *wbc, Sheet *sheet,
}
/******************************************************************/
#define CMD_MERGE_DATA_TYPE (cmd_merge_data_get_type ())
#define CMD_MERGE_DATA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CMD_MERGE_DATA_TYPE, CmdMergeData))
typedef struct
{
GnumericCommand parent;
Value *merge_zone;
GSList *merge_fields;
GSList *merge_data;
GSList *sheet_list;
WorkbookControl *wbc;
Sheet *sheet;
gint n;
} CmdMergeData;
GNUMERIC_MAKE_COMMAND (CmdMergeData, cmd_merge_data);
static void
cmd_merge_data_delete_sheets (gpointer data, gpointer success)
{
Sheet *sheet = data;
if (!command_undo_sheet_delete (sheet))
*(gboolean *)success = FALSE;
}
static gboolean
cmd_merge_data_undo (GnumericCommand *cmd, WorkbookControl *wbc)
{
CmdMergeData *me = CMD_MERGE_DATA (cmd);
gboolean success = TRUE;
g_slist_foreach (me->sheet_list, cmd_merge_data_delete_sheets, &success);
g_slist_free (me->sheet_list);
me->sheet_list = NULL;
return FALSE;
}
static gboolean
cmd_merge_data_redo (GnumericCommand *cmd, WorkbookControl *wbc)
{
CmdMergeData *me = CMD_MERGE_DATA (cmd);
int i;
CellRegion *merge_content;
Range merge_range;
RangeRef *cell = &me->merge_zone->v_range.cell;
PasteTarget pt;
GSList *this_field = me->merge_fields;
GSList *this_data = me->merge_data;
range_init (&merge_range, cell->a.col, cell->a.row,
cell->b.col, cell->b.row);
merge_content = clipboard_copy_range (cell->a.sheet, &merge_range);
for (i = 0; i < me->n; i++) {
Sheet *new_sheet;
new_sheet = workbook_sheet_add (me->sheet->workbook, NULL, FALSE);
me->sheet_list = g_slist_prepend (me->sheet_list, new_sheet);
clipboard_paste_region (me->wbc, paste_target_init (&pt, new_sheet,
&merge_range, PASTE_ALL_TYPES),
merge_content);
}
me->sheet_list = g_slist_reverse (me->sheet_list);
while (this_field) {
Range target_range;
Range source_range;
Sheet *source_sheet;
GSList *target_sheet;
g_return_val_if_fail (this_data != NULL, TRUE);
cell = &((Value *)this_field->data)->v_range.cell;
range_init (&target_range, cell->a.col, cell->a.row,
cell->a.col, cell->a.row);
cell = &((Value *)this_data->data)->v_range.cell;
range_init (&source_range, cell->a.col, cell->a.row,
cell->a.col, cell->a.row);
source_sheet = cell->a.sheet;
target_sheet = me->sheet_list;
while (target_sheet) {
merge_content = clipboard_copy_range (source_sheet, &source_range);
clipboard_paste_region
(me->wbc, paste_target_init
(&pt, (Sheet *)target_sheet->data,
&target_range, PASTE_AS_VALUES | PASTE_IGNORE_COMMENTS),
merge_content);
target_sheet = target_sheet->next;
source_range.end.row++;
source_range.start.row++;
}
this_field = this_field->next;
this_data = this_data->next;
}
return FALSE;
}
static void
cmd_merge_data_finalize (GObject *cmd)
{
CmdMergeData *me = CMD_MERGE_DATA (cmd);
value_release (me->merge_zone);
me->merge_zone = NULL;
range_list_destroy (me->merge_data);
me->merge_data = NULL;
range_list_destroy (me->merge_fields);
me->merge_fields = NULL;
g_slist_free (me->sheet_list);
me->sheet_list = NULL;
me->n = 0;
gnumeric_command_finalize (cmd);
}
gboolean
cmd_merge_data (WorkbookControl *wbc, Sheet *sheet,
Value *merge_zone, GSList *merge_fields, GSList *merge_data)
{
GObject *obj;
CmdMergeData *me;
RangeRef *cell;
g_return_val_if_fail (IS_SHEET (sheet), TRUE);
g_return_val_if_fail (merge_zone != NULL, TRUE);
g_return_val_if_fail (merge_fields != NULL, TRUE);
g_return_val_if_fail (merge_data != NULL, TRUE);
obj = g_object_new (CMD_MERGE_DATA_TYPE, NULL);
me = CMD_MERGE_DATA (obj);
me->parent.sheet = sheet;
me->sheet = sheet;
me->wbc = wbc;
me->parent.size = 1 + g_slist_length (merge_fields);
me->parent.cmd_descriptor =
g_strdup_printf (_("Merging data into %s"), value_peek_string (merge_zone));
me->merge_zone = merge_zone;
me->merge_fields = merge_fields;
me->merge_data = merge_data;
me->sheet_list = 0;
cell = &((Value *)merge_data->data)->v_range.cell;
me->n = cell->b.row - cell->a.row + 1;
/* Register the command object */
return command_push_undo (wbc, obj);
}
/******************************************************************/
......@@ -97,4 +97,8 @@ gboolean cmd_analysis_tool (WorkbookControl *wbc, Sheet *sheet,
data_analysis_output_t *dao, gpointer specs,
analysis_tool_engine engine);
gboolean cmd_merge_data (WorkbookControl *wbc, Sheet *sheet,
Value *merge_zone, GSList *merge_fields, GSList *merge_data);
#endif /* GNUMERIC_COMMANDS_H */
......@@ -41,6 +41,7 @@ base_files = \
dialog-insert-cells.c \
dialog-define-names.c \
dialog-delete-cells.c \
dialog-merge.c \
dialog-paste-special.c \
dialog-plugin-manager.c \
dialog-printer-setup.c \
......@@ -103,6 +104,7 @@ glade_DATA = \
histogram.glade \
insert-cells.glade \
mean-tests.glade \
merge.glade \
moving-averages.glade \
names.glade \
plugin-manager.glade \
......
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* dialog-merge.c: Dialog to change the order of sheets in the Gnumeric
* spreadsheet
*
* Author:
* Andreas J. Guelzow <aguelzow@taliesin.ca>
*
* Copyright (C) 2002 Andreas J. Guelzow <aguelzow@taliesin.ca>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gnumeric-config.h>
#include <gnumeric.h>
#include "dialogs.h"
#include <gui-util.h>
#include <workbook-control-gui.h>
#include <workbook-edit.h>
#include <workbook-view.h>
#include <workbook.h>
#include <sheet.h>
#include <ranges.h>
#include <value.h>
#include <commands.h>
#include <widgets/gnumeric-expr-entry.h>
#include <libgnome/gnome-i18n.h>
#include <glade/glade.h>
#define MERGE_KEY "merge-dialog"
typedef struct {
WorkbookControlGUI *wbcg;
Sheet *sheet;
GladeXML *gui;
GtkWidget *dialog;
GtkWidget *warning_dialog;
GtkTreeView *list;
GtkListStore *model;
GnumericExprEntry *zone;
GnumericExprEntry *data;
GnumericExprEntry *field;
GtkWidget *add_btn;
GtkWidget *change_btn;
GtkWidget *delete_btn;
GtkWidget *merge_btn;
GtkWidget *cancel_btn;
} MergeState;
enum {
DATA_RANGE,
FIELD_LOCATION,
NUM_COLMNS
};
static void
cb_merge_update_buttons (gpointer ignored, MergeState *state)
{
/* Note: ignored could be NULL or an expr-entry. */
GtkTreeIter iter;
GtkTreeSelection *selection = gtk_tree_view_get_selection (state->list);
gboolean has_selection, has_data, has_work;
has_selection = gtk_tree_selection_get_selected (selection, NULL, &iter);
has_data = gnm_expr_entry_is_cell_ref (state->data, state->sheet, TRUE)
&& gnm_expr_entry_is_cell_ref (state->field, state->sheet, FALSE);
has_work = (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (state->model), NULL) > 0)
&& gnm_expr_entry_is_cell_ref (state->zone, state->sheet, TRUE);
gtk_widget_set_sensitive (state->add_btn, has_data);
gtk_widget_set_sensitive (state->change_btn, has_data && has_selection);
gtk_widget_set_sensitive (state->delete_btn, has_selection);
gtk_widget_set_sensitive (state->merge_btn, has_work);
}
static void
cb_merge_selection_changed (GtkTreeSelection *selection, MergeState *state)
{
GtkTreeIter iter;
gboolean has_selection;
char *data_string = NULL, *field_string = NULL;
has_selection = gtk_tree_selection_get_selected (selection, NULL, &iter);
if (has_selection) {
gtk_tree_model_get (GTK_TREE_MODEL (state->model), &iter,
DATA_RANGE, &data_string,
FIELD_LOCATION, &field_string,
-1);
gnm_expr_entry_load_from_text (state->data, data_string);
gnm_expr_entry_load_from_text (state->field, field_string);
g_free (data_string);
g_free (field_string);
}
cb_merge_update_buttons (NULL, state);
}
static void
merge_store_info_in_list (GtkTreeIter *iter, MergeState *state)
{
char *data_text, *field_text;
GtkTreeSelection *selection;
data_text = gnm_expr_entry_global_range_name (state->data, state->sheet);
field_text = gnm_expr_entry_global_range_name (state->field, state->sheet);
gtk_list_store_set (state->model, iter,
DATA_RANGE, data_text,
FIELD_LOCATION, field_text,
-1);
g_free (data_text);
g_free (field_text);
selection = gtk_tree_view_get_selection (state->list);
gtk_tree_selection_select_iter (selection, iter);
}
static void
cb_merge_add_clicked (GtkWidget *ignore, MergeState *state)
{
GtkTreeIter iter;
GtkTreeIter sel_iter;
GtkTreeSelection *selection = gtk_tree_view_get_selection (state->list);
if (!gtk_tree_selection_get_selected (selection, NULL, &sel_iter))
gtk_list_store_append (state->model, &iter);
else
gtk_list_store_insert_before (state->model, &iter, &sel_iter);
merge_store_info_in_list (&iter, state);
}
static void
cb_merge_change_clicked (GtkWidget *ignore, MergeState *state)
{
GtkTreeIter iter;
GtkTreeSelection *selection = gtk_tree_view_get_selection (state->list);
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
merge_store_info_in_list (&iter, state);
}
static void
cb_merge_delete_clicked (GtkWidget *ignore, MergeState *state)
{
GtkTreeIter iter;
GtkTreeSelection *selection = gtk_tree_view_get_selection (state->list);
if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
gtk_list_store_remove (state->model, &iter);
}
}
static void
cb_merge_cancel_clicked (GtkWidget *ignore, MergeState *state)
{
gtk_widget_destroy (GTK_WIDGET (state->dialog));
}
static void
cb_merge_find_shortest_column (gpointer data, gpointer lp)
{
Value *range = data;
int *length = lp;
int r_length = range->v_range.cell.b.row - range->v_range.cell.a.row + 1;
if (r_length < *length)
*length = r_length;
}
static void
cb_merge_find_longest_column (gpointer data, gpointer lp)
{
Value *range = data;
int *length = lp;
int r_length = range->v_range.cell.b.row - range->v_range.cell.a.row + 1;
if (r_length > *length)
*length = r_length;
}
static void
cb_merge_trim_data (gpointer data, gpointer lp)
{
Value *range = data;
int *length = lp;
int r_length = range->v_range.cell.b.row - range->v_range.cell.a.row + 1;
if (r_length > *length)
range->v_range.cell.b.row = range->v_range.cell.a.row + *length - 1;
range->v_range.cell.b.col = range->v_range.cell.a.col;
}
static void
cb_merge_merge_clicked (GtkWidget *ignore, MergeState *state)
{
GtkTreeIter this_iter;
gint n = 0;
char *data_string = NULL, *field_string = NULL;
GSList *data_list = NULL, *field_list = NULL;
Value *v_zone;
gint field_problems = 0;
gint min_length = SHEET_MAX_ROWS;
gint max_length = 0;
v_zone = gnm_expr_entry_parse_as_value (state->zone, state->sheet);
g_return_if_fail (v_zone != NULL);
while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (state->model),
&this_iter, NULL, n)) {
Value *v_data, *v_field;
gtk_tree_model_get (GTK_TREE_MODEL (state->model), &this_iter,
DATA_RANGE, &data_string,
FIELD_LOCATION, &field_string,
-1);
v_data = global_range_parse (state->sheet, data_string);
v_field = global_range_parse (state->sheet, field_string);
g_free (data_string);
g_free (field_string);
g_return_if_fail (v_data != NULL && v_field != NULL);
if (!global_range_contained (v_field, v_zone)) {
field_problems++;
}
data_list = g_slist_prepend (data_list, v_data);
field_list = g_slist_prepend (field_list, v_field);
n++;
}
if (field_problems > 0) {
char *text;
if (field_problems == 1)
text = g_strdup (_("One field is not part of the merge zone!"));
else
text = g_strdup_printf (_("%i fields are not part of the merge zone!"),
field_problems);
gnumeric_notice_nonmodal ((GtkWindow *) state->dialog,
&(state->warning_dialog),
GTK_MESSAGE_ERROR,
text);
g_free (text);
value_release (v_zone);
range_list_destroy (data_list);
range_list_destroy (field_list);
return;
}
g_slist_foreach (data_list, cb_merge_find_shortest_column, &min_length);
g_slist_foreach (data_list, cb_merge_find_longest_column, &max_length);
if (min_length < max_length) {
char *text = g_strdup_printf (_("The data columns range in length from "
"%i to %i. Shall we trim the lengths to "
"%i and proceed?"), min_length, max_length,
min_length);
if (gnumeric_dialog_question_yes_no (state->wbcg, text, TRUE)) {
g_slist_foreach (data_list, cb_merge_trim_data, &min_length);
g_free (text);
} else {
g_free (text);
value_release (v_zone);
range_list_destroy (data_list);
range_list_destroy (field_list);
return;
}
}
if (!cmd_merge_data (WORKBOOK_CONTROL (state->wbcg), state->sheet,
v_zone, field_list, data_list))
gtk_widget_destroy (state->dialog);
}
static void
cb_merge_destroy (GtkWidget *ignored, MergeState *state)
{
wbcg_edit_detach_guru (state->wbcg);
g_object_unref (G_OBJECT (state->gui));
state->gui = NULL;
g_free (state);
}
void
dialog_merge (WorkbookControlGUI *wbcg)
{
MergeState *state;
GladeXML *gui;
GtkTable *table;
GtkWidget *scrolled;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
g_return_if_fail (wbcg != NULL);
if (gnumeric_dialog_raise_if_exists (wbcg, MERGE_KEY))
return;
gui = gnumeric_glade_xml_new (wbcg, "merge.glade");
if (gui == NULL)
return;
state = g_new0 (MergeState, 1);
state->gui = gui;
state->wbcg = wbcg;
state->sheet = wb_control_cur_sheet (WORKBOOK_CONTROL (state->wbcg));
state->dialog = glade_xml_get_widget (gui, "Merge");
state->warning_dialog = NULL;
state->add_btn = glade_xml_get_widget (gui, "add_button");
state->delete_btn = glade_xml_get_widget (gui, "remove_button");