Exemple #1
0
/** Destructor for GncCsvParseData.
 * @param parse_data Parse data whose memory will be freed
 */
void gnc_csv_parse_data_free (GncCsvParseData* parse_data)
{
    /* All non-NULL pointers have been initialized and must be freed. */

    if (parse_data->raw_mapping != NULL)
    {
        g_mapped_file_unref (parse_data->raw_mapping);
    }

    if (parse_data->file_str.begin != NULL)
        g_free (parse_data->file_str.begin);

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

    if (parse_data->orig_row_lengths != NULL)
        g_array_free (parse_data->orig_row_lengths, FALSE);

    if (parse_data->options != NULL)
        stf_parse_options_free (parse_data->options);

    if (parse_data->column_types != NULL)
        g_array_free (parse_data->column_types, TRUE);

    if (parse_data->error_lines != NULL)
        g_list_free (parse_data->error_lines);

    if (parse_data->transactions != NULL)
    {
        GList* transactions = parse_data->transactions;
        /* We have to free the GncCsvTransLine's that are at each node in
         * the list before freeing the entire list. */
        do
        {
            g_free (transactions->data);
            transactions = g_list_next (transactions);
        }
        while (transactions != NULL);
        g_list_free (parse_data->transactions);
    }

    g_free (parse_data->chunk);
    g_free (parse_data);
}
Exemple #2
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;
}
void
stf_preview_set_lines (RenderData_t *renderdata,
		       GStringChunk *lines_chunk,
		       GPtrArray *lines)
{
	unsigned int i;
	int colcount = 1;
	GnumericLazyList *ll;
	gboolean hidden;

	g_return_if_fail (renderdata != NULL);

	/* Empty the table.  */
	gtk_tree_view_set_model (renderdata->tree_view, NULL);

	if (renderdata->lines != lines) {
		if (renderdata->lines)
			stf_parse_general_free (renderdata->lines);
		renderdata->lines = lines;
	}

	if (renderdata->lines_chunk != lines_chunk) {
		if (renderdata->lines_chunk)
			g_string_chunk_free (renderdata->lines_chunk);
		renderdata->lines_chunk = lines_chunk;
	}

	if (lines == NULL)
		return;

	for (i = 0; i < lines->len; i++) {
		GPtrArray *line = g_ptr_array_index (lines, i);
		colcount = MAX (colcount, (int)line->len);
	}

	/*
	 * If we are making large changes we need to hide the treeview
	 * because performance otherwise suffers a lot.
	 */
	hidden = gtk_widget_get_visible (GTK_WIDGET (renderdata->tree_view)) &&
		(colcount < renderdata->colcount - 1 ||
		 colcount > renderdata->colcount + 10);
	if (hidden)
		gtk_widget_hide (GTK_WIDGET (renderdata->tree_view));

	while (renderdata->colcount > colcount)
               gtk_tree_view_remove_column
                       (renderdata->tree_view,
                        gtk_tree_view_get_column (renderdata->tree_view,
                                                  --(renderdata->colcount)));

	while (renderdata->colcount < colcount) {
		char *text = g_strdup_printf (_(COLUMN_CAPTION),
					      renderdata->colcount + 1);
		GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
		GtkTreeViewColumn *column =
			gtk_tree_view_column_new_with_attributes
			(text, cell,
			 "text", renderdata->colcount,
			 NULL);
		g_object_set (cell,
			      "single_paragraph_mode", TRUE,
			      NULL);
		gtk_tree_view_append_column (renderdata->tree_view, column);
		g_free (text);
		renderdata->colcount++;
	}

	ll = gnumeric_lazy_list_new (render_get_value, renderdata,
				     MIN (lines->len, LINE_DISPLAY_LIMIT),
				     0);
	gnumeric_lazy_list_add_column (ll, colcount, G_TYPE_STRING);
	gtk_tree_view_set_model (renderdata->tree_view, GTK_TREE_MODEL (ll));
	g_object_unref (ll);

	if (hidden)
		gtk_widget_show (GTK_WIDGET (renderdata->tree_view));
}
Exemple #4
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);
}