mirror of https://github.com/Gnucash/gnucash
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
488 lines
11 KiB
488 lines
11 KiB
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
|
|
/*
|
|
* io-context.c : Place holder for an io error context.
|
|
* It is intended to become a place to handle errors
|
|
* as well as storing non-fatal warnings.
|
|
*
|
|
* Authors:
|
|
* Jody Goldberg <jody@gnome.org>
|
|
* Zbigniew Chyla <cyba@gnome.pl>
|
|
*
|
|
* (C) 2000-2002 Jody Goldberg
|
|
*/
|
|
#include <config.h>
|
|
#include "gnumeric.h"
|
|
#include "io-context-priv.h"
|
|
|
|
//#include "sheet.h"
|
|
//#include "workbook.h"
|
|
#include "command-context.h"
|
|
#include "gui-util.h"
|
|
|
|
#include <gsf/gsf-impl-utils.h>
|
|
#include <gtk/gtkmain.h>
|
|
|
|
#define PROGRESS_UPDATE_STEP 0.01
|
|
#define PROGRESS_UPDATE_STEP_END (1.0 / 400)
|
|
#define PROGRESS_UPDATE_PERIOD_SEC 0.20
|
|
|
|
#define IOC_CLASS(ioc) IO_CONTEXT_CLASS(G_OBJECT_GET_CLASS(ioc))
|
|
|
|
static void
|
|
io_context_init (IOContext *ioc)
|
|
{
|
|
ioc->impl = NULL;
|
|
ioc->info = NULL;
|
|
ioc->error_occurred = FALSE;
|
|
ioc->warning_occurred = FALSE;
|
|
|
|
ioc->progress_ranges = NULL;
|
|
ioc->progress_min = 0.0;
|
|
ioc->progress_max = 1.0;
|
|
ioc->last_progress = -1.0;
|
|
ioc->last_time = 0.0;
|
|
ioc->helper.helper_type = GNM_PROGRESS_HELPER_NONE;
|
|
}
|
|
|
|
static void
|
|
ioc_finalize (GObject *obj)
|
|
{
|
|
IOContext *ioc;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (obj));
|
|
|
|
ioc = IO_CONTEXT (obj);
|
|
error_info_free (ioc->info);
|
|
if (ioc->impl) {
|
|
cmd_context_progress_set (ioc->impl, 0.0);
|
|
cmd_context_progress_message_set (ioc->impl, NULL);
|
|
g_object_unref (G_OBJECT (ioc->impl));
|
|
}
|
|
|
|
G_OBJECT_CLASS (g_type_class_peek (G_TYPE_OBJECT))->finalize (obj);
|
|
}
|
|
|
|
static char *
|
|
ioc_get_password (GnmCmdContext *cc, char const *filename)
|
|
{
|
|
IOContext *ioc = (IOContext *)cc;
|
|
return gnm_cmd_context_get_password (ioc->impl, filename);
|
|
}
|
|
|
|
static void
|
|
ioc_set_sensitive (GnmCmdContext *cc, gboolean sensitive)
|
|
{
|
|
(void)cc; (void)sensitive;
|
|
}
|
|
|
|
static void
|
|
ioc_error_error (GnmCmdContext *cc, GError *err)
|
|
{
|
|
gnumeric_io_error_string (IO_CONTEXT (cc), err->message);
|
|
}
|
|
|
|
static void
|
|
ioc_error_error_info (G_GNUC_UNUSED GnmCmdContext *ctxt,
|
|
ErrorInfo *error)
|
|
{
|
|
/* TODO what goes here */
|
|
error_info_print (error);
|
|
}
|
|
|
|
void
|
|
gnumeric_io_error_string (IOContext *context, const gchar *str)
|
|
{
|
|
ErrorInfo *error;
|
|
|
|
g_return_if_fail (context != NULL);
|
|
g_return_if_fail (str != NULL);
|
|
|
|
error = error_info_new_str (str);
|
|
gnumeric_io_error_info_set (context, error);
|
|
}
|
|
|
|
static void
|
|
io_context_gnm_cmd_context_init (GnmCmdContextClass *cc_class)
|
|
{
|
|
cc_class->get_password = ioc_get_password;
|
|
cc_class->set_sensitive = ioc_set_sensitive;
|
|
cc_class->error.error = ioc_error_error;
|
|
cc_class->error.error_info = ioc_error_error_info;
|
|
}
|
|
static void
|
|
io_context_class_init (GObjectClass *klass)
|
|
{
|
|
klass->finalize = ioc_finalize;
|
|
}
|
|
|
|
GSF_CLASS_FULL (IOContext, io_context,
|
|
io_context_class_init, io_context_init,
|
|
G_TYPE_OBJECT, 0,
|
|
GSF_INTERFACE (io_context_gnm_cmd_context_init, GNM_CMD_CONTEXT_TYPE))
|
|
|
|
IOContext *
|
|
gnumeric_io_context_new (GnmCmdContext *cc)
|
|
{
|
|
IOContext *ioc;
|
|
|
|
g_return_val_if_fail (IS_GNM_CMD_CONTEXT (cc), NULL);
|
|
|
|
ioc = g_object_new (TYPE_IO_CONTEXT, NULL);
|
|
/* The cc is optional for subclasses, but mandatory in this class. */
|
|
ioc->impl = cc;
|
|
g_object_ref (G_OBJECT (ioc->impl));
|
|
|
|
return ioc;
|
|
}
|
|
|
|
void
|
|
gnumeric_io_error_unknown (IOContext *context)
|
|
{
|
|
g_return_if_fail (context != NULL);
|
|
|
|
context->error_occurred = TRUE;
|
|
}
|
|
|
|
void
|
|
gnumeric_io_error_info_set (IOContext *context, ErrorInfo *error)
|
|
{
|
|
g_return_if_fail (context != NULL);
|
|
g_return_if_fail (error != NULL);
|
|
|
|
g_return_if_fail (context->info == NULL);
|
|
|
|
context->info = error;
|
|
context->error_occurred = TRUE;
|
|
}
|
|
|
|
void
|
|
gnumeric_io_error_push (IOContext *context, ErrorInfo *error)
|
|
{
|
|
g_return_if_fail (context != NULL);
|
|
g_return_if_fail (error != NULL);
|
|
|
|
error_info_add_details (error, context->info);
|
|
context->info = error;
|
|
}
|
|
|
|
void
|
|
gnumeric_io_error_display (IOContext *context)
|
|
{
|
|
GnmCmdContext *cc;
|
|
|
|
g_return_if_fail (context != NULL);
|
|
|
|
if (context->info != NULL) {
|
|
if (context->impl)
|
|
cc = context->impl;
|
|
else
|
|
cc = GNM_CMD_CONTEXT (context);
|
|
gnm_cmd_context_error_info (cc, context->info);
|
|
}
|
|
}
|
|
|
|
/* TODO: Rename to gnumeric_io_info_clear */
|
|
void
|
|
gnumeric_io_error_clear (IOContext *context)
|
|
{
|
|
g_return_if_fail (context != NULL);
|
|
|
|
context->error_occurred = FALSE;
|
|
context->warning_occurred = FALSE;
|
|
error_info_free (context->info);
|
|
context->info = NULL;
|
|
}
|
|
|
|
gboolean
|
|
gnumeric_io_error_occurred (IOContext *context)
|
|
{
|
|
return context->error_occurred;
|
|
}
|
|
|
|
gboolean
|
|
gnumeric_io_warning_occurred (IOContext *context)
|
|
{
|
|
return context->warning_occurred;
|
|
}
|
|
|
|
void
|
|
io_progress_update (IOContext *ioc, gdouble f)
|
|
{
|
|
gboolean at_end;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
|
|
if (ioc->progress_ranges != NULL) {
|
|
f = f * (ioc->progress_max - ioc->progress_min)
|
|
+ ioc->progress_min;
|
|
}
|
|
|
|
at_end = (f - ioc->last_progress > PROGRESS_UPDATE_STEP_END &&
|
|
f + PROGRESS_UPDATE_STEP > 1);
|
|
if (at_end || f - ioc->last_progress >= PROGRESS_UPDATE_STEP) {
|
|
GTimeVal tv;
|
|
double t;
|
|
|
|
(void) g_get_current_time (&tv);
|
|
t = tv.tv_sec + tv.tv_usec / 1000000.0;
|
|
if (at_end || t - ioc->last_time >= PROGRESS_UPDATE_PERIOD_SEC) {
|
|
GnmCmdContext *cc;
|
|
|
|
if (ioc->impl)
|
|
cc = ioc->impl;
|
|
else
|
|
cc = GNM_CMD_CONTEXT (ioc);
|
|
cmd_context_progress_set (cc, f);
|
|
ioc->last_time = t;
|
|
ioc->last_progress = f;
|
|
}
|
|
}
|
|
|
|
/* FIXME : abstract this into the workbook control */
|
|
while (gtk_events_pending ())
|
|
gtk_main_iteration_do (FALSE);
|
|
}
|
|
|
|
void
|
|
io_progress_message (IOContext *ioc, const gchar *msg)
|
|
{
|
|
GnmCmdContext *cc;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
|
|
if (ioc->impl)
|
|
cc = ioc->impl;
|
|
else
|
|
cc = GNM_CMD_CONTEXT (ioc);
|
|
cmd_context_progress_message_set (cc, msg);
|
|
}
|
|
|
|
void
|
|
io_progress_range_push (IOContext *ioc, gdouble min, gdouble max)
|
|
{
|
|
ProgressRange *r;
|
|
gdouble new_min, new_max;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
|
|
r = g_new (ProgressRange, 1);
|
|
r->min = min;
|
|
r->max = max;
|
|
ioc->progress_ranges = g_list_append (ioc->progress_ranges, r);
|
|
|
|
new_min = min / (ioc->progress_max - ioc->progress_min)
|
|
+ ioc->progress_min;
|
|
new_max = max / (ioc->progress_max - ioc->progress_min)
|
|
+ ioc->progress_min;
|
|
ioc->progress_min = new_min;
|
|
ioc->progress_max = new_max;
|
|
}
|
|
|
|
void
|
|
io_progress_range_pop (IOContext *ioc)
|
|
{
|
|
GList *l;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
g_return_if_fail (ioc->progress_ranges != NULL);
|
|
|
|
l = g_list_last (ioc->progress_ranges);
|
|
ioc->progress_ranges= g_list_remove_link (ioc->progress_ranges, l);
|
|
g_free (l->data);
|
|
g_list_free_1 (l);
|
|
|
|
ioc->progress_min = 0.0;
|
|
ioc->progress_max = 1.0;
|
|
for (l = ioc->progress_ranges; l != NULL; l = l->next) {
|
|
ProgressRange *r = l->data;
|
|
gdouble new_min, new_max;
|
|
|
|
new_min = r->min / (ioc->progress_max - ioc->progress_min)
|
|
+ ioc->progress_min;
|
|
new_max = r->max / (ioc->progress_max - ioc->progress_min)
|
|
+ ioc->progress_min;
|
|
ioc->progress_min = new_min;
|
|
ioc->progress_max = new_max;
|
|
}
|
|
}
|
|
|
|
void
|
|
value_io_progress_set (IOContext *ioc, gint total, gint step)
|
|
{
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
g_return_if_fail (total >= 0);
|
|
|
|
ioc->helper.helper_type = GNM_PROGRESS_HELPER_VALUE;
|
|
ioc->helper.v.value.total = MAX (total, 1);
|
|
ioc->helper.v.value.last = -step;
|
|
ioc->helper.v.value.step = step;
|
|
}
|
|
|
|
void
|
|
value_io_progress_update (IOContext *ioc, gint value)
|
|
{
|
|
gdouble complete;
|
|
gint step, total;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
g_return_if_fail (ioc->helper.helper_type == GNM_PROGRESS_HELPER_VALUE);
|
|
|
|
total = ioc->helper.v.value.total;
|
|
step = ioc->helper.v.value.step;
|
|
|
|
if (value - ioc->helper.v.value.last < step &&
|
|
value + step < total) {
|
|
return;
|
|
}
|
|
ioc->helper.v.value.last = value;
|
|
|
|
complete = (gdouble)value / total;
|
|
io_progress_update (ioc, complete);
|
|
}
|
|
|
|
void
|
|
count_io_progress_set (IOContext *ioc, gint total, gint step)
|
|
{
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
g_return_if_fail (total >= 0);
|
|
|
|
ioc->helper.helper_type = GNM_PROGRESS_HELPER_COUNT;
|
|
ioc->helper.v.count.total = MAX (total, 1);
|
|
ioc->helper.v.count.last = -step;
|
|
ioc->helper.v.count.current = 0;
|
|
ioc->helper.v.count.step = step;
|
|
}
|
|
|
|
void
|
|
count_io_progress_update (IOContext *ioc, gint inc)
|
|
{
|
|
gdouble complete;
|
|
gint current, step, total;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
g_return_if_fail (ioc->helper.helper_type == GNM_PROGRESS_HELPER_COUNT);
|
|
|
|
current = (ioc->helper.v.count.current += inc);
|
|
step = ioc->helper.v.count.step;
|
|
total = ioc->helper.v.count.total;
|
|
|
|
if (current - ioc->helper.v.count.last < step && current + step < total) {
|
|
return;
|
|
}
|
|
ioc->helper.v.count.last = current;
|
|
|
|
complete = (gdouble)current / total;
|
|
io_progress_update (ioc, complete);
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
workbook_io_progress_set (IOContext *ioc, Workbook const *wb, gint step)
|
|
{
|
|
gint n = 0;
|
|
GList *sheets, *l;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
g_return_if_fail (IS_WORKBOOK (wb));
|
|
|
|
sheets = workbook_sheets (wb);
|
|
for (l = sheets; l != NULL; l = l->next) {
|
|
Sheet *sheet = l->data;
|
|
n += g_hash_table_size (sheet->cell_hash);
|
|
}
|
|
g_list_free (sheets);
|
|
|
|
ioc->helper.helper_type = GNM_PROGRESS_HELPER_WORKBOOK;
|
|
ioc->helper.v.workbook.n_elements = MAX (n, 1);
|
|
ioc->helper.v.workbook.last = -step;
|
|
ioc->helper.v.workbook.current = 0;
|
|
ioc->helper.v.workbook.step = step;
|
|
}
|
|
|
|
void
|
|
workbook_io_progress_update (IOContext *ioc, gint inc)
|
|
{
|
|
gdouble complete;
|
|
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
g_return_if_fail (ioc->helper.helper_type == GNM_PROGRESS_HELPER_WORKBOOK);
|
|
|
|
ioc->helper.v.workbook.current += inc;
|
|
if (ioc->helper.v.workbook.current - ioc->helper.v.workbook.last
|
|
< ioc->helper.v.workbook.step) {
|
|
return;
|
|
}
|
|
ioc->helper.v.workbook.last = ioc->helper.v.workbook.current;
|
|
|
|
complete = 1.0 * ioc->helper.v.workbook.current
|
|
/ ioc->helper.v.workbook.n_elements;
|
|
io_progress_update (ioc, complete);
|
|
}
|
|
#endif // 0
|
|
|
|
void
|
|
io_progress_unset (IOContext *ioc)
|
|
{
|
|
g_return_if_fail (IS_IO_CONTEXT (ioc));
|
|
|
|
ioc->helper.helper_type = GNM_PROGRESS_HELPER_NONE;
|
|
}
|
|
|
|
void
|
|
gnm_io_context_set_num_files (IOContext *ioc, guint count)
|
|
{
|
|
IOContextClass *klass = IOC_CLASS(ioc);
|
|
g_return_if_fail (klass != NULL);
|
|
if (klass->set_num_files != NULL)
|
|
klass->set_num_files (ioc, count);
|
|
}
|
|
|
|
void
|
|
gnm_io_context_processing_file (IOContext *ioc, char const *name)
|
|
{
|
|
IOContextClass *klass = IOC_CLASS(ioc);
|
|
g_return_if_fail (klass != NULL);
|
|
if (klass->processing_file != NULL)
|
|
klass->processing_file (ioc, name);
|
|
}
|
|
|
|
void
|
|
gnm_io_warning (G_GNUC_UNUSED IOContext *context,
|
|
char const *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start (args, fmt);
|
|
gnm_io_warning_varargs (context, fmt, args);
|
|
va_end (args);
|
|
}
|
|
|
|
void
|
|
gnm_io_warning_varargs (IOContext *context, char const *fmt, va_list args)
|
|
{
|
|
context->info = error_info_new_vprintf (GNM_WARNING, fmt, args);
|
|
context->warning_occurred = TRUE;
|
|
}
|
|
|
|
void
|
|
gnm_io_warning_unknown_font (IOContext *context,
|
|
G_GNUC_UNUSED char const *font_name)
|
|
{
|
|
g_return_if_fail (IS_IO_CONTEXT (context));
|
|
}
|
|
|
|
void
|
|
gnm_io_warning_unknown_function (IOContext *context,
|
|
G_GNUC_UNUSED char const *funct_name)
|
|
{
|
|
g_return_if_fail (IS_IO_CONTEXT (context));
|
|
}
|
|
|
|
void
|
|
gnm_io_warning_unsupported_feature (IOContext *context, char const *feature)
|
|
{
|
|
g_return_if_fail (IS_IO_CONTEXT (context));
|
|
g_warning ("%s : are not supported yet", feature);
|
|
}
|