-/* psppire-var-store.c
-
- PSPPIRE --- A Graphical User Interface for PSPP
+/* PSPPIRE - a graphical user interface for PSPP.
Copyright (C) 2006 Free Software Foundation
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <string.h>
#include <gtksheet/gsheetmodel.h>
#include "psppire-var-store.h"
-#include "var-sheet.h"
+#include <gtksheet/gsheet-row-iface.h>
#include "helper.h"
#include <data/dictionary.h>
#include "missing-val-dialog.h"
#include <data/value-labels.h>
+#include "var-display.h"
-#define TRAILING_ROWS 40
+enum
+ {
+ PSPPIRE_VAR_STORE_TRAILING_ROWS = 1,
+ PSPPIRE_VAR_STORE_FORMAT_TYPE
+ };
static void psppire_var_store_init (PsppireVarStore *var_store);
static void psppire_var_store_class_init (PsppireVarStoreClass *class);
static void psppire_var_store_sheet_model_init (GSheetModelIface *iface);
static void psppire_var_store_finalize (GObject *object);
-static gchar *psppire_var_store_get_string (const GSheetModel *sheet_model, gint row, gint column);
-static gboolean psppire_var_store_clear (GSheetModel *model, gint row, gint col);
+gchar * missing_values_to_string (const struct variable *pv, GError **err);
+
+
+static gchar *psppire_var_store_get_string (const GSheetModel *sheet_model, glong row, glong column);
+
+static gboolean psppire_var_store_clear (GSheetModel *model, glong row, glong col);
static gboolean psppire_var_store_set_string (GSheetModel *model,
- const gchar *text, gint row, gint column);
+ const gchar *text, glong row, glong column);
-static gint psppire_var_store_get_row_count (const GSheetModel * model);
+static glong psppire_var_store_get_row_count (const GSheetModel * model);
+static glong psppire_var_store_get_column_count (const GSheetModel * model);
static gchar *text_for_column (const struct variable *pv, gint c, GError **err);
static GObjectClass *parent_class = NULL;
+GType
+psppire_var_store_format_type_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0)
+ {
+ static const GEnumValue values[] =
+ {
+ { PSPPIRE_VAR_STORE_INPUT_FORMATS,
+ "PSPPIRE_VAR_STORE_INPUT_FORMATS",
+ "input" },
+ { PSPPIRE_VAR_STORE_OUTPUT_FORMATS,
+ "PSPPIRE_VAR_STORE_OUTPUT_FORMATS",
+ "output" },
+ { 0, NULL, NULL }
+ };
+
+ etype = g_enum_register_static
+ (g_intern_static_string ("PsppireVarStoreFormatType"), values);
+
+ }
+ return etype;
+}
+
GType
psppire_var_store_get_type (void)
{
return var_store_type;
}
+static void
+psppire_var_store_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PsppireVarStore *self = (PsppireVarStore *) object;
+
+ switch (property_id)
+ {
+ case PSPPIRE_VAR_STORE_TRAILING_ROWS:
+ self->trailing_rows = g_value_get_int (value);
+ break;
+
+ case PSPPIRE_VAR_STORE_FORMAT_TYPE:
+ self->format_type = g_value_get_enum (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+psppire_var_store_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PsppireVarStore *self = (PsppireVarStore *) object;
+
+ switch (property_id)
+ {
+ case PSPPIRE_VAR_STORE_TRAILING_ROWS:
+ g_value_set_int (value, self->trailing_rows);
+ break;
+
+ case PSPPIRE_VAR_STORE_FORMAT_TYPE:
+ g_value_set_enum (value, self->format_type);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ break;
+ }
+}
+
+
static void
psppire_var_store_class_init (PsppireVarStoreClass *class)
{
GObjectClass *object_class;
+ GParamSpec *pspec;
parent_class = g_type_class_peek_parent (class);
object_class = (GObjectClass*) class;
object_class->finalize = psppire_var_store_finalize;
+ object_class->set_property = psppire_var_store_set_property;
+ object_class->get_property = psppire_var_store_get_property;
+
+ /* The minimum value for trailing-rows is 1 to prevent the
+ var-store from ever having 0 rows, which breaks invariants
+ in gtksheet. */
+ pspec = g_param_spec_int ("trailing-rows",
+ "Trailing rows",
+ "Number of rows displayed after last variable",
+ 1 /* minimum value */,
+ 100 /* maximum value */,
+ 40 /* default value */,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ PSPPIRE_VAR_STORE_TRAILING_ROWS,
+ pspec);
+
+ pspec = g_param_spec_enum ("format-type",
+ "Variable format type",
+ ("Whether variables have input or output "
+ "formats"),
+ G_TYPE_PSPPIRE_VAR_STORE_FORMAT_TYPE,
+ PSPPIRE_VAR_STORE_OUTPUT_FORMATS,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class,
+ PSPPIRE_VAR_STORE_FORMAT_TYPE,
+ pspec);
}
-
static void
psppire_var_store_init (PsppireVarStore *var_store)
{
gdk_colormap_alloc_color (colormap, &var_store->disabled, FALSE, TRUE);
var_store->dict = 0;
+ var_store->trailing_rows = 40;
+ var_store->format_type = PSPPIRE_VAR_STORE_OUTPUT_FORMATS;
}
static gboolean
-psppire_var_store_item_editable (PsppireVarStore *var_store, gint row, gint column)
+psppire_var_store_item_editable (PsppireVarStore *var_store, glong row, glong column)
{
const struct fmt_spec *write_spec ;
if ( !pv )
return TRUE;
- if ( VAR_STRING == var_get_type (pv) && column == COL_DECIMALS )
+ if ( var_is_alpha (pv) && column == PSPPIRE_VAR_STORE_COL_DECIMALS )
return FALSE;
- write_spec =var_get_write_format (pv);
+ write_spec = var_get_print_format (pv);
switch ( write_spec->type )
{
case FMT_DTIME:
case FMT_WKDAY:
case FMT_MONTH:
- if ( column == COL_DECIMALS || column == COL_WIDTH)
+ if ( column == PSPPIRE_VAR_STORE_COL_DECIMALS || column == PSPPIRE_VAR_STORE_COL_WIDTH)
return FALSE;
break;
default:
struct variable *
-psppire_var_store_get_var (PsppireVarStore *store, gint row)
+psppire_var_store_get_var (PsppireVarStore *store, glong row)
{
return psppire_dict_get_variable (store->dict, row);
}
static gboolean
-psppire_var_store_is_editable (const GSheetModel *model, gint row, gint column)
+psppire_var_store_is_editable (const GSheetModel *model, glong row, glong column)
{
PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
return psppire_var_store_item_editable (store, row, column);
static const GdkColor *
-psppire_var_store_get_foreground (const GSheetModel *model, gint row, gint column)
+psppire_var_store_get_foreground (const GSheetModel *model, glong row, glong column)
{
PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
const PangoFontDescription *
psppire_var_store_get_font_desc (const GSheetModel *model,
- gint row, gint column)
+ glong row, glong column)
{
PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
+
static void
psppire_var_store_sheet_model_init (GSheetModelIface *iface)
{
iface->get_row_count = psppire_var_store_get_row_count;
+ iface->get_column_count = psppire_var_store_get_column_count;
iface->free_strings = TRUE;
iface->get_string = psppire_var_store_get_string;
iface->set_string = psppire_var_store_set_string;
GSheetModel *model = G_SHEET_MODEL (data);
g_sheet_model_range_changed (model,
- n, 0, n, n_COLS);
+ n, 0, n, PSPPIRE_VAR_STORE_n_COLS);
}
static void
-var_delete_callback (GtkWidget *w, gint first, gint n, gpointer data)
+var_delete_callback (GtkWidget *w, gint dict_idx, gint case_idx, gint val_cnt, gpointer data)
{
GSheetModel *model = G_SHEET_MODEL (data);
- g_sheet_model_rows_deleted (model, first, n);
+ g_sheet_model_rows_deleted (model, dict_idx, 1);
}
static void
-var_insert_callback (GtkWidget *w, gint row, gpointer data)
+var_insert_callback (GtkWidget *w, glong row, gpointer data)
{
GSheetModel *model = G_SHEET_MODEL (data);
g_sheet_model_rows_inserted (model, row, 1);
}
+static void
+refresh (PsppireDict *d, gpointer data)
+{
+ PsppireVarStore *vs = data;
+ g_sheet_model_range_changed (G_SHEET_MODEL (vs), -1, -1, -1, -1);
+}
/**
* psppire_var_store_replace_set_dictionary:
g_signal_connect (dict, "variable-changed", G_CALLBACK (var_change_callback),
var_store);
- g_signal_connect (dict, "variables-deleted", G_CALLBACK (var_delete_callback),
+ g_signal_connect (dict, "variable-deleted", G_CALLBACK (var_delete_callback),
var_store);
- g_signal_connect (dict, "variable-inserted", G_CALLBACK (var_insert_callback),
- var_store);
+ g_signal_connect (dict, "variable-inserted",
+ G_CALLBACK (var_insert_callback), var_store);
+ g_signal_connect (dict, "backend-changed", G_CALLBACK (refresh),
+ var_store);
/* The entire model has changed */
g_sheet_model_range_changed (G_SHEET_MODEL (var_store), -1, -1, -1, -1);
}
static gchar *
-psppire_var_store_get_string (const GSheetModel *model, gint row, gint column)
+psppire_var_store_get_string (const GSheetModel *model, glong row, glong column)
{
PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
Returns true if anything was updated, false otherwise.
*/
static gboolean
-psppire_var_store_clear (GSheetModel *model, gint row, gint col)
+psppire_var_store_clear (GSheetModel *model, glong row, glong col)
{
struct variable *pv ;
switch (col)
{
- case COL_LABEL:
+ case PSPPIRE_VAR_STORE_COL_LABEL:
var_set_label (pv, 0);
return TRUE;
break;
*/
static gboolean
psppire_var_store_set_string (GSheetModel *model,
- const gchar *text, gint row, gint col)
+ const gchar *text, glong row, glong col)
{
struct variable *pv ;
switch (col)
{
- case COL_NAME:
+ case PSPPIRE_VAR_STORE_COL_NAME:
return psppire_dict_rename_var (var_store->dict, pv, text);
break;
- case COL_COLUMNS:
+ case PSPPIRE_VAR_STORE_COL_COLUMNS:
if ( ! text) return FALSE;
var_set_display_width (pv, atoi (text));
return TRUE;
break;
- case COL_WIDTH:
+ case PSPPIRE_VAR_STORE_COL_WIDTH:
{
int width = atoi (text);
if ( ! text) return FALSE;
var_set_width (pv, width);
else
{
+ bool for_input
+ = var_store->format_type == PSPPIRE_VAR_STORE_INPUT_FORMATS;
struct fmt_spec fmt ;
fmt = *var_get_write_format (pv);
- if ( width < fmt_min_output_width (fmt.type)
+ if ( width < fmt_min_width (fmt.type, for_input)
||
- width > fmt_max_output_width (fmt.type))
+ width > fmt_max_width (fmt.type, for_input))
return FALSE;
fmt.w = width;
- fmt.d = MIN (fmt_max_output_decimals (fmt.type, width), fmt.d);
+ fmt.d = MIN (fmt_max_decimals (fmt.type, width, for_input), fmt.d);
var_set_both_formats (pv, &fmt);
}
return TRUE;
}
break;
- case COL_DECIMALS:
+ case PSPPIRE_VAR_STORE_COL_DECIMALS:
{
+ bool for_input
+ = var_store->format_type == PSPPIRE_VAR_STORE_INPUT_FORMATS;
int decimals;
struct fmt_spec fmt;
if ( ! text) return FALSE;
decimals = atoi (text);
fmt = *var_get_write_format (pv);
if ( decimals >
- fmt_max_output_decimals (fmt.type,
- fmt.w
- ))
+ fmt_max_decimals (fmt.type,
+ fmt.w,
+ for_input
+ ))
return FALSE;
fmt.d = decimals;
return TRUE;
}
break;
- case COL_LABEL:
+ case PSPPIRE_VAR_STORE_COL_LABEL:
var_set_label (pv, text);
return TRUE;
break;
- case COL_TYPE:
- case COL_VALUES:
- case COL_MISSING:
- case COL_ALIGN:
- case COL_MEASURE:
+ case PSPPIRE_VAR_STORE_COL_TYPE:
+ case PSPPIRE_VAR_STORE_COL_VALUES:
+ case PSPPIRE_VAR_STORE_COL_MISSING:
+ case PSPPIRE_VAR_STORE_COL_ALIGN:
+ case PSPPIRE_VAR_STORE_COL_MEASURE:
/* These can be modified only by their respective dialog boxes */
return FALSE;
break;
}
+const static gchar none[] = N_("None");
+
static gchar *
text_for_column (const struct variable *pv, gint c, GError **err)
{
- static gchar none[] = N_("None");
-
static const gchar *const type_label[] =
{
N_("Numeric"),
switch (c)
{
- case COL_NAME:
+ case PSPPIRE_VAR_STORE_COL_NAME:
return pspp_locale_to_utf8 ( var_get_name (pv), -1, err);
break;
- case COL_TYPE:
+ case PSPPIRE_VAR_STORE_COL_TYPE:
{
switch ( write_spec->type )
{
}
}
break;
- case COL_WIDTH:
+ case PSPPIRE_VAR_STORE_COL_WIDTH:
{
gchar *s;
GString *gstr = g_string_sized_new (10);
return s;
}
break;
- case COL_DECIMALS:
+ case PSPPIRE_VAR_STORE_COL_DECIMALS:
{
gchar *s;
GString *gstr = g_string_sized_new (10);
return s;
}
break;
- case COL_COLUMNS:
+ case PSPPIRE_VAR_STORE_COL_COLUMNS:
{
gchar *s;
GString *gstr = g_string_sized_new (10);
return s;
}
break;
- case COL_LABEL:
+ case PSPPIRE_VAR_STORE_COL_LABEL:
return pspp_locale_to_utf8 (var_get_label (pv), -1, err);
break;
- case COL_MISSING:
+ case PSPPIRE_VAR_STORE_COL_MISSING:
{
- gchar *s;
- const struct missing_values *miss = var_get_missing_values (pv);
- if ( mv_is_empty (miss))
- return g_locale_to_utf8 (gettext (none), -1, 0, 0, err);
- else
- {
- if ( ! mv_has_range (miss))
- {
- GString *gstr = g_string_sized_new (10);
- const int n = mv_n_values (miss);
- gchar *mv[4] = {0,0,0,0};
- gint i;
- for (i = 0 ; i < n; ++i )
- {
- union value v;
- mv_peek_value (miss, &v, i);
- mv[i] = value_to_text (v, *write_spec);
- if ( i > 0 )
- g_string_append (gstr, ", ");
- g_string_append (gstr, mv[i]);
- g_free (mv[i]);
- }
- s = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
- g_string_free (gstr, TRUE);
- }
- else
- {
- GString *gstr = g_string_sized_new (10);
- gchar *l, *h;
- union value low, high;
- mv_peek_range (miss, &low.f, &high.f);
-
- l = value_to_text (low, *write_spec);
- h = value_to_text (high, *write_spec);
-
- g_string_printf (gstr, "%s - %s", l, h);
- g_free (l);
- g_free (h);
-
- if ( mv_has_value (miss))
- {
- gchar *ss = 0;
- union value v;
- mv_peek_value (miss, &v, 0);
-
- ss = value_to_text (v, *write_spec);
-
- g_string_append (gstr, ", ");
- g_string_append (gstr, ss);
- free (ss);
- }
- s = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
- g_string_free (gstr, TRUE);
- }
-
- return s;
- }
+ return missing_values_to_string (pv, err);
}
break;
- case COL_VALUES:
+ case PSPPIRE_VAR_STORE_COL_VALUES:
{
if ( ! var_has_value_labels (pv))
return g_locale_to_utf8 (gettext (none), -1, 0, 0, err);
}
}
break;
- case COL_ALIGN:
+ case PSPPIRE_VAR_STORE_COL_ALIGN:
{
const gint align = var_get_alignment (pv);
return g_locale_to_utf8 (gettext (alignments[align]), -1, 0, 0, err);
}
break;
- case COL_MEASURE:
+ case PSPPIRE_VAR_STORE_COL_MEASURE:
{
- const gint measure = var_get_measure (pv);
-
- g_assert (measure < n_MEASURES);
- return g_locale_to_utf8 (gettext (measures[measure]),
- -1, 0, 0, err);
+ return measure_to_string (pv, err);
}
break;
}
}
-static gint
+static glong
psppire_var_store_get_row_count (const GSheetModel * model)
{
gint rows = 0;
return rows ;
}
+static glong
+psppire_var_store_get_column_count (const GSheetModel * model)
+{
+ return PSPPIRE_VAR_STORE_n_COLS ;
+}
+
+
/* Row related funcs */
-static gint
-geometry_get_row_count (const GSheetRow *geom, gpointer data)
+static glong
+geometry_get_row_count (const GSheetRow *geom)
{
gint rows = 0;
PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
if (vs->dict)
rows = psppire_dict_get_var_cnt (vs->dict);
- return rows + TRAILING_ROWS;
+ return rows + vs->trailing_rows;
}
static gint
-geometry_get_height (const GSheetRow *geom, gint row, gpointer data)
+geometry_get_height (const GSheetRow *geom, glong row)
{
return 25;
}
static gboolean
-geometry_is_sensitive (const GSheetRow *geom, gint row, gpointer data)
+geometry_is_sensitive (const GSheetRow *geom, glong row)
{
PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
static gchar *
-geometry_get_button_label (const GSheetRow *geom, gint unit, gpointer data)
+geometry_get_button_label (const GSheetRow *geom, glong unit)
{
- gchar *label = g_strdup_printf (_("%d"), unit);
+ gchar *label = g_strdup_printf (_("%ld"), unit + 1);
return label;
}
-
static void
psppire_var_store_sheet_row_init (GSheetRowIface *iface)
{
iface->get_button_label = geometry_get_button_label;
}
+
+
+