/**
 * csv_page_global_change
 * @widget : the widget which emitted the signal
 * @data : mother struct
 *
 * This will update the preview based on the state of
 * the widgets on the csv page
 *
 * returns : nothing
 **/
static void
csv_page_global_change (G_GNUC_UNUSED GtkWidget *widget,
			StfDialogData *pagedata)
{
	StfParseOptions_t *parseoptions = pagedata->parseoptions;
	RenderData_t *renderdata = pagedata->csv.renderdata;
	GSList *sepstr;
	GString *sepc = g_string_new (NULL);
	GStringChunk *lines_chunk;
	GPtrArray *lines;
	StfTrimType_t trim;

	sepstr = NULL;
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_custom))) {
		char *csvcustomtext = gtk_editable_get_chars (GTK_EDITABLE (pagedata->csv.csv_customseparator), 0, -1);

		if (strcmp (csvcustomtext, "") != 0)
			sepstr = g_slist_append (sepstr, csvcustomtext);
		else
			g_free (csvcustomtext);
	}

	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_tab)))
		g_string_append_c (sepc, '\t');
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_colon)))
		g_string_append_c (sepc, ':');
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_comma)))
		g_string_append_c (sepc, ',');
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_space)))
		g_string_append_c (sepc, ' ');
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_semicolon)))
		g_string_append_c (sepc, ';');
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_hyphen)))
		g_string_append_c (sepc, '-');

	stf_parse_options_csv_set_separators (parseoptions,
					      strcmp (sepc->str, "") == 0 ? NULL : sepc->str,
					      sepstr);
	g_string_free (sepc, TRUE);
	go_slist_free_custom (sepstr, g_free);

	stf_parse_options_csv_set_duplicates (parseoptions,
					      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_duplicates)));
	stf_parse_options_csv_set_trim_seps (parseoptions,
					     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (pagedata->csv.csv_trim_seps)));

	lines_chunk = g_string_chunk_new (100 * 1024);

	/* Don't trim on this page.  */
	trim = parseoptions->trim_spaces;
	stf_parse_options_set_trim_spaces (parseoptions, TRIM_TYPE_NEVER);
	lines = stf_parse_general (parseoptions, lines_chunk,
				   pagedata->cur, pagedata->cur_end);
	stf_parse_options_set_trim_spaces (parseoptions, trim);

	stf_preview_set_lines (renderdata, lines_chunk, lines);
}
Example #2
0
/**
 * fixed_page_update_preview
 * @pagedata: mother struct
 *
 * Will simply update the preview
 *
 * returns : nothing
 **/
static void
fixed_page_update_preview (StfDialogData *pagedata)
{
	StfParseOptions_t *parseoptions = pagedata->parseoptions;
	RenderData_t *renderdata = pagedata->fixed.renderdata;
	int i;
	GStringChunk *lines_chunk;
	GPtrArray *lines;
	StfTrimType_t trim;

	lines_chunk = g_string_chunk_new (100 * 1024);

	/* Don't trim on this page.  */
	trim = parseoptions->trim_spaces;
	stf_parse_options_set_trim_spaces (parseoptions, TRIM_TYPE_NEVER);
	lines = stf_parse_general (parseoptions, lines_chunk,
				   pagedata->cur, pagedata->cur_end);
	stf_parse_options_set_trim_spaces (parseoptions, trim);

	stf_preview_set_lines (renderdata, lines_chunk, lines);

	for (i = 0; i < renderdata->colcount; i++) {
		GtkTreeViewColumn *column =
			stf_preview_get_column (renderdata, i);
		GtkCellRenderer *cell =
			stf_preview_get_cell_renderer (renderdata, i);
		GtkWidget *button =
			gtk_tree_view_column_get_button (column);

		gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);

		g_object_set (G_OBJECT (cell),
			      "family", "monospace",
			      NULL);

		g_object_set_data (G_OBJECT (button), "fixed-data", pagedata);
		g_object_set (G_OBJECT (column), "clickable", TRUE, NULL);
		g_signal_connect (button, "button_press_event",
				  G_CALLBACK (cb_col_button_press),
				  GINT_TO_POINTER (i));
		g_signal_connect (button, "key_press_event",
				  G_CALLBACK (cb_col_key_press),
				  GINT_TO_POINTER (i));
	}
}
Example #3
0
/** Parses a file into cells. This requires having an encoding that
 * works (see gnc_csv_convert_encoding). parse_data->options should be
 * set according to how the user wants before calling this
 * function. (Note: this function must be called with guessColTypes as
 * TRUE before it is ever called with it as FALSE.) (Note: if
 * guessColTypes is TRUE, all the column types will be GNC_CSV_NONE
 * right now.)
 * @param parse_data Data that is being parsed
 * @param guessColTypes TRUE to guess what the types of columns are based on the cell contents
 * @param error Will contain an error if there is a failure
 * @return 0 on success, 1 on failure
 */
int gnc_csv_parse (GncCsvParseData* parse_data, gboolean guessColTypes, GError** error)
{
    /* max_cols is the number of columns in the row with the most columns. */
    int i, max_cols = 0;

    if (parse_data->orig_lines != NULL)
    {
        stf_parse_general_free (parse_data->orig_lines);
    }

    /* If everything is fine ... */
    if (parse_data->file_str.begin != NULL)
    {
        /* Do the actual parsing. */
        parse_data->orig_lines = stf_parse_general (parse_data->options, parse_data->chunk,
                                 parse_data->file_str.begin,
                                 parse_data->file_str.end);
    }
    /* If we couldn't get the encoding right, we just want an empty array. */
    else
    {
        parse_data->orig_lines = g_ptr_array_new();
    }

    /* Record the original row lengths of parse_data->orig_lines. */
    if (parse_data->orig_row_lengths != NULL)
        g_array_free (parse_data->orig_row_lengths, FALSE);

    parse_data->orig_row_lengths =
        g_array_sized_new (FALSE, FALSE, sizeof(int), parse_data->orig_lines->len);

    g_array_set_size (parse_data->orig_row_lengths, parse_data->orig_lines->len);
    parse_data->orig_max_row = 0;
    for (i = 0; i < parse_data->orig_lines->len; i++)
    {
        int length = ((GPtrArray*)parse_data->orig_lines->pdata[i])->len;
        parse_data->orig_row_lengths->data[i] = length;
        if (length > parse_data->orig_max_row)
            parse_data->orig_max_row = length;
    }

    /* If it failed, generate an error. */
    if (parse_data->orig_lines == NULL)
    {
        g_set_error (error, 0, 0, "Parsing failed.");
        return 1;
    }

    /* Now that we have data, let's set max_cols. */
    for (i = 0; i < parse_data->orig_lines->len; i++)
    {
        if (max_cols < ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len)
            max_cols = ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len;
    }

    if (guessColTypes)
    {
        /* Free parse_data->column_types if it's already been created. */
        if (parse_data->column_types != NULL)
            g_array_free (parse_data->column_types, TRUE);

        /* Create parse_data->column_types and fill it with guesses based
         * on the contents of each column. */
        parse_data->column_types = g_array_sized_new (FALSE, FALSE, sizeof(int),
                                   max_cols);
        g_array_set_size (parse_data->column_types, max_cols);
        /* TODO Make it actually guess. */
        for (i = 0; i < parse_data->column_types->len; i++)
        {
            parse_data->column_types->data[i] = GNC_CSV_NONE;
        }
    }
    else
    {
        /* If we don't need to guess column types, we will simply set any
         * new columns that are created that didn't exist before to "None"
         * since we don't want gibberish to appear. Note:
         * parse_data->column_types should have already been
         * initialized, so we don't check for it being NULL. */
        int i = parse_data->column_types->len;
        g_array_set_size (parse_data->column_types, max_cols);
        for (; i < parse_data->column_types->len; i++)
        {
            parse_data->column_types->data[i] = GNC_CSV_NONE;
        }
    }

    return 0;
}
/**
 * format_page_update_preview
 * @pagedata: mother struct
 *
 * Will simply utilize the preview rendering functions to update
 * the preview
 *
 * returns : nothing
 **/
static void
format_page_update_preview (StfDialogData *pagedata)
{
	RenderData_t *renderdata = pagedata->format.renderdata;
	unsigned int ui;
	int i;
	int col_import_array_len_old, old_part;
	GStringChunk *lines_chunk;
	char *msg = NULL;

	stf_preview_colformats_clear (renderdata);
	for (ui = 0; ui < pagedata->format.formats->len; ui++) {
		GOFormat *sf = g_ptr_array_index (pagedata->format.formats, ui);
		stf_preview_colformats_add (renderdata, sf);
	}

	lines_chunk = g_string_chunk_new (100 * 1024);
	stf_preview_set_lines (renderdata, lines_chunk,
			       stf_parse_general (pagedata->parseoptions,
						  lines_chunk,
						  pagedata->cur,
						  pagedata->cur_end));

	col_import_array_len_old = pagedata->format.col_import_array_len;
	pagedata->format.col_import_array_len = renderdata->colcount;

	pagedata->format.col_autofit_array =
		g_renew(gboolean, pagedata->format.col_autofit_array,
			pagedata->format.col_import_array_len);
	pagedata->format.col_import_array =
		g_renew(gboolean, pagedata->format.col_import_array,
			pagedata->format.col_import_array_len);
	old_part = (col_import_array_len_old < pagedata->format.col_import_array_len)
		? col_import_array_len_old
		: pagedata->format.col_import_array_len;
	pagedata->format.col_import_count = 0;
	for (i = 0; i < old_part; i++)
		if (pagedata->format.col_import_array[i])
			pagedata->format.col_import_count++;
	for (i = old_part;
	     i < pagedata->format.col_import_array_len; i++) {
		if (pagedata->format.col_import_count < GNM_MAX_COLS) {
			pagedata->format.col_import_array[i] = TRUE;
			pagedata->format.col_import_count++;
		} else {
			pagedata->format.col_import_array[i] = FALSE;
		}
		pagedata->format.col_autofit_array[i] = TRUE;
	}

	format_page_update_column_selection (pagedata);

	if (old_part < renderdata->colcount)
		msg = g_strdup_printf
			(_("A maximum of %d columns can be imported."),
			 GNM_MAX_COLS);

	for (i = old_part; i < renderdata->colcount; i++) {
		GtkTreeViewColumn *column =
			stf_preview_get_column (renderdata, i);
		GtkWidget *button = gtk_tree_view_column_get_button (column);

		if (NULL == g_object_get_data (G_OBJECT (column), "checkbox")) {
			GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
			GtkWidget *check,
				*check_autofit = gtk_check_button_new_with_label (_("Auto fit"));
			char * label_text = g_strdup_printf
				(pagedata->format.col_header, i+1);
			GOFormat const *gf = go_format_general ();
			GtkWidget *format_label = gtk_button_new_with_label
				(go_format_sel_format_classification (gf));
			GtkWidget *format_icon
				= gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_BUTTON);

			check = gtk_check_button_new_with_label (label_text);
			g_free (label_text);
			gtk_button_set_image (GTK_BUTTON (format_label), format_icon);

			g_object_set (G_OBJECT (stf_preview_get_cell_renderer
						(pagedata->format.renderdata, i)),
				      "strikethrough",
				      !pagedata->format.col_import_array[i], NULL);
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(check),
						      pagedata->
						      format.col_import_array[i]);
			label_text = g_strdup_printf
				(_("If this checkbox is selected, "
				   "column %i will be imported into "
				   "Gnumeric."), i+1);
			gtk_widget_set_tooltip_text
				(check,
				 label_text);
			gtk_widget_set_tooltip_text
				(check_autofit,
				 _("If this checkbox is selected, "
				   "the width of the column will be adjusted "
				   "to the longest entry."));
			g_free (label_text);
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(check_autofit),
						      pagedata->
						      format.col_autofit_array[i]);
			g_object_set_data (G_OBJECT (check), "pagedata", pagedata);
			g_object_set_data (G_OBJECT (check_autofit), "pagedata", pagedata);
			g_object_set_data (G_OBJECT (format_label), "pagedata", pagedata);
			gtk_box_pack_start (GTK_BOX(vbox), check, FALSE, FALSE, 0);
			gtk_box_pack_start (GTK_BOX(vbox), format_label, TRUE, TRUE, 0);
			gtk_box_pack_start (GTK_BOX(vbox), check_autofit, TRUE, TRUE, 0);
			gtk_widget_show_all (vbox);

			gtk_tree_view_column_set_widget (column, vbox);
			g_object_set_data (G_OBJECT (column), "pagedata", pagedata);
			g_object_set_data (G_OBJECT (column), "checkbox", check);
			g_object_set_data (G_OBJECT (column), "checkbox-autofit", check_autofit);
			g_object_set_data (G_OBJECT (column), "formatlabel", format_label);
			g_object_set_data (G_OBJECT (button),
					   "pagedata", pagedata);
			g_object_set_data (G_OBJECT (button),
					   "checkbox", check);
			g_object_set_data (G_OBJECT (button),
					   "formatlabel", format_label);
			g_object_set (G_OBJECT (column), "clickable", TRUE, NULL);

			g_signal_connect (G_OBJECT (check),
					  "toggled",
					  G_CALLBACK (cb_col_check_clicked),
					  GINT_TO_POINTER (i));
			g_signal_connect (G_OBJECT (check_autofit),
					  "toggled",
					  G_CALLBACK (cb_col_check_autofit_clicked),
					  GINT_TO_POINTER (i));
			g_signal_connect (G_OBJECT (format_label),
					  "clicked",
					  G_CALLBACK (cb_format_clicked),
					  GINT_TO_POINTER (i));
			g_signal_connect (G_OBJECT (button),
					  "event",
					  G_CALLBACK (cb_col_event),
					  GINT_TO_POINTER (i));
		}
	}
	g_free (msg);
}
Example #5
0
/*
 * stf_read_workbook_auto_csvtab:
 * @fo: file opener
 * @enc: optional encoding
 * @context: command context
 * @book: workbook
 * @input: file to read from+convert
 *
 * Attempt to auto-detect CSV or tab-delimited file
 */
static void
stf_read_workbook_auto_csvtab (G_GNUC_UNUSED GOFileOpener const *fo, gchar const *enc,
			       GOIOContext *context,
			       GoView *view, GsfInput *input)
{
	Sheet *sheet;
	Workbook *book;
	char *name;
	char *data;
	GString *utf8data;
	size_t data_len;
	StfParseOptions_t *po;
	const char *gsfname;
	int cols, rows, i;
	GStringChunk *lines_chunk;
	GPtrArray *lines;
	WorkbookView *wbv = GNM_WORKBOOK_VIEW (view);

	g_return_if_fail (context != NULL);
	g_return_if_fail (wbv != NULL);

	book = wb_view_get_workbook (wbv);

	data = stf_preparse (context, input, &data_len);
	if (!data)
		return;

	enc = go_guess_encoding (data, data_len, enc, &utf8data, NULL);
	g_free (data);

	if (!enc) {
		go_cmd_context_error_import (GO_CMD_CONTEXT (context),
				     _("That file is not in the given encoding."));
		return;
	}

	clear_stray_NULs (context, utf8data);

	/*
	 * Try to get the filename we're reading from.  This is not a
	 * great way.
	 */
	gsfname = gsf_input_name (input);

	{
		const char *ext = gsf_extension_pointer (gsfname);
		gboolean iscsv = ext && strcasecmp (ext, "csv") == 0;
		if (iscsv)
			po = stf_parse_options_guess_csv (utf8data->str);
		else
			po = stf_parse_options_guess (utf8data->str);
	}

	lines_chunk = g_string_chunk_new (100 * 1024);
	lines = stf_parse_general (po, lines_chunk,
				   utf8data->str, utf8data->str + utf8data->len);
	rows = lines->len;
	cols = 0;
	for (i = 0; i < rows; i++) {
		GPtrArray *line = g_ptr_array_index (lines, i);
		cols = MAX (cols, (int)line->len);
	}
	gnm_sheet_suggest_size (&cols, &rows);
	stf_parse_general_free (lines);
	g_string_chunk_free (lines_chunk);

	name = g_path_get_basename (gsfname);
	sheet = sheet_new (book, name, cols, rows);
	g_free (name);
	workbook_sheet_attach (book, sheet);

	if (stf_parse_sheet (po, utf8data->str, NULL, sheet, 0, 0)) {
		gboolean is_csv;
		workbook_recalc_all (book);
		resize_columns (sheet);
		if (po->cols_exceeded || po->rows_exceeded) {
			stf_warning (context,
				     _("Some data did not fit on the "
				       "sheet and was dropped."));
		}
		is_csv = po->sep.chr && po->sep.chr[0] == ',';
		workbook_set_saveinfo
			(book,
			 GO_FILE_FL_WRITE_ONLY,
			 go_file_saver_for_id
			 (is_csv ? "Gnumeric_stf:stf_csv" : "Gnumeric_stf:stf_assistant"));
	} else {
		workbook_sheet_delete (sheet);
		go_cmd_context_error_import (GO_CMD_CONTEXT (context),
			_("Parse error while trying to parse data into sheet"));
	}


	stf_parse_options_free (po);
	g_string_free (utf8data, TRUE);
}