From: Ben Pfaff Date: Sun, 2 Dec 2012 03:39:07 +0000 (-0800) Subject: Merge 'master' into 'psppsheet'. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fbuilds%2F20121227032003%2Fpspp;hp=ea17c5b225557fc0760810861451a84dc241d462;p=pspp Merge 'master' into 'psppsheet'. --- diff --git a/NEWS b/NEWS index 5302e26542..e0910fe6e6 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,9 @@ Changes from 0.6.2 to 0.7.9: - SET and SHOW no longer have ENDCMD, NULLINE, PROMPT, CPROMPT, and DPROMPT subcommands. The defaults are now fixed values. + - SHOW now has a JOURNAL subcommand, to show the location of the + journal file. + - VALUE LABELS can now assign value labels to long string variables. diff --git a/configure.ac b/configure.ac index ec5ee2eae2..d681929940 100644 --- a/configure.ac +++ b/configure.ac @@ -324,7 +324,7 @@ AC_SUBST([SIZEOF_SIZE_T]) AC_C_BIGENDIAN -AC_CHECK_FUNCS([__setfpucw fork execl execlp isinf isnan finite getpid feholdexcept fpsetmask popen round]) +AC_CHECK_FUNCS([__setfpucw fork execl isinf isnan finite getpid feholdexcept fpsetmask popen round]) AC_PROG_LN_S diff --git a/doc/invoking.texi b/doc/invoking.texi index f327b1cc5e..24259a5808 100644 --- a/doc/invoking.texi +++ b/doc/invoking.texi @@ -86,8 +86,9 @@ produce multiple output files, presumably in different formats. Use @samp{-} as @var{output-file} to write output to standard output. -If no @option{-o} option is used, then @pspp{} writes output to standard -output in plain text format. +If no @option{-o} option is used, then @pspp{} writes text and CSV +output to standard output and other kinds of output to whose name is +based on the format, e.g.@: @file{pspp.pdf} for PDF output. @item @option{-O @var{option}=@var{value}} Sets an option for the output file configured by a preceding diff --git a/src/data/data-out.c b/src/data/data-out.c index 10ca4ede77..94e72f668b 100644 --- a/src/data/data-out.c +++ b/src/data/data-out.c @@ -864,6 +864,7 @@ rounder_init (struct rounder *r, double number, int max_decimals) r->leading_zeros = strspn (r->string, "0."); r->leading_nines = strspn (r->string, "9."); r->integer_digits = strchr (r->string, '.') - r->string; + assert (r->integer_digits < 64); assert (r->integer_digits >= 0); r->negative = number < 0; } diff --git a/src/data/file-handle-def.h b/src/data/file-handle-def.h index 9a60e72423..53e1bbfb6d 100644 --- a/src/data/file-handle-def.h +++ b/src/data/file-handle-def.h @@ -55,7 +55,7 @@ struct fh_properties enum fh_mode mode; /* File mode. */ size_t record_width; /* Length of fixed-format records. */ size_t tab_width; /* Tab width, 0=do not expand tabs. */ - char *encoding; /* Charset for contents. */ + const char *encoding; /* Charset for contents. */ }; void fh_init (void); diff --git a/src/language/data-io/data-list.c b/src/language/data-io/data-list.c index 17c6032d25..bc295a9aed 100644 --- a/src/language/data-io/data-list.c +++ b/src/language/data-io/data-list.c @@ -429,9 +429,28 @@ parse_free (struct lexer *lexer, struct dictionary *dict, if (lex_match (lexer, T_LPAREN)) { - if (!parse_format_specifier (lexer, &input) - || !fmt_check_input (&input) - || !lex_force_match (lexer, T_RPAREN)) + char type[FMT_TYPE_LEN_MAX + 1]; + + if (!parse_abstract_format_specifier (lexer, type, &input.w, + &input.d)) + return NULL; + if (!fmt_from_name (type, &input.type)) + { + msg (SE, _("Unknown format type `%s'."), type); + return NULL; + } + + /* If no width was included, use the minimum width for the type. + This isn't quite right, because DATETIME by itself seems to become + DATETIME20 (see bug #30690), whereas this will become + DATETIME17. The correct behavior is not documented. */ + if (input.w == 0) + { + input.w = fmt_min_input_width (input.type); + input.d = 0; + } + + if (!fmt_check_input (&input) || !lex_force_match (lexer, T_RPAREN)) return NULL; /* As a special case, N format is treated as F format diff --git a/src/language/data-io/data-parser.c b/src/language/data-io/data-parser.c index 1dc7c93f77..958326e48d 100644 --- a/src/language/data-io/data-parser.c +++ b/src/language/data-io/data-parser.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 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 @@ -455,7 +455,7 @@ cut_field (const struct data_parser *parser, struct dfm_reader *reader, /* Quoted field. */ int quote = ss_get_byte (&p); if (!ss_get_until (&p, quote, field)) - msg (SW, _("Quoted string extends beyond end of line.")); + msg (DW, _("Quoted string extends beyond end of line.")); if (parser->quote_escape && ss_first (p) == quote) { ds_assign_substring (tmp, *field); @@ -464,7 +464,7 @@ cut_field (const struct data_parser *parser, struct dfm_reader *reader, struct substring ss; ds_put_byte (tmp, quote); if (!ss_get_until (&p, quote, &ss)) - msg (SW, _("Quoted string extends beyond end of line.")); + msg (DW, _("Quoted string extends beyond end of line.")); ds_put_substring (tmp, ss); } *field = ds_ss (tmp); @@ -473,10 +473,18 @@ cut_field (const struct data_parser *parser, struct dfm_reader *reader, /* Skip trailing soft separator and a single hard separator if present. */ - ss_ltrim (&p, parser->soft_seps); - if (!ss_is_empty (p) - && ss_find_byte (parser->hard_seps, ss_first (p)) != SIZE_MAX) - ss_advance (&p, 1); + if (!ss_is_empty (p)) + { + size_t n_seps = ss_ltrim (&p, parser->soft_seps); + if (!ss_is_empty (p) + && ss_find_byte (parser->hard_seps, ss_first (p)) != SIZE_MAX) + { + ss_advance (&p, 1); + n_seps++; + } + if (!n_seps) + msg (DW, _("Missing delimiter following quoted string.")); + } } else { @@ -542,7 +550,7 @@ parse_fixed (const struct data_parser *parser, struct dfm_reader *reader, if (dfm_eof (reader)) { - msg (SW, _("Partial case of %d of %d records discarded."), + msg (DW, _("Partial case of %d of %d records discarded."), row - 1, parser->records_per_case); return false; } @@ -599,7 +607,7 @@ parse_delimited_span (const struct data_parser *parser, if (dfm_eof (reader)) { if (f > parser->fields) - msg (SW, _("Partial case discarded. The first variable " + msg (DW, _("Partial case discarded. The first variable " "missing was %s."), f->name); ds_destroy (&tmp); return false; @@ -641,7 +649,7 @@ parse_delimited_no_span (const struct data_parser *parser, if (!cut_field (parser, reader, &first_column, &last_column, &tmp, &s)) { if (f < end - 1 && settings_get_undefined ()) - msg (SW, _("Missing value(s) for all variables from %s onward. " + msg (DW, _("Missing value(s) for all variables from %s onward. " "These will be filled with the system-missing value " "or blanks, as appropriate."), f->name); @@ -661,7 +669,7 @@ parse_delimited_no_span (const struct data_parser *parser, s = dfm_get_record (reader); ss_ltrim (&s, parser->soft_seps); if (!ss_is_empty (s)) - msg (SW, _("Record ends in data not part of any field.")); + msg (DW, _("Record ends in data not part of any field.")); exit: dfm_forward_record (reader); diff --git a/src/language/data-io/inpt-pgm.c b/src/language/data-io/inpt-pgm.c index ccd53be04e..afeb832643 100644 --- a/src/language/data-io/inpt-pgm.c +++ b/src/language/data-io/inpt-pgm.c @@ -112,7 +112,9 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) emit_END_CASE (ds, inp); saw_END_CASE = true; } - else if (cmd_result_is_failure (result) && result != CMD_FAILURE) + else if (cmd_result_is_failure (result) + && result != CMD_FAILURE + && lex_get_error_mode (lexer) != LEX_ERROR_INTERACTIVE) { if (result == CMD_EOF) msg (SE, _("Unexpected end-of-file within INPUT PROGRAM.")); diff --git a/src/language/lexer/format-parser.c b/src/language/lexer/format-parser.c index 45a0b4b1e3..78af09da31 100644 --- a/src/language/lexer/format-parser.c +++ b/src/language/lexer/format-parser.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2010, 2011, 2012 Free Software Foundation, Inc. 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 @@ -117,6 +117,13 @@ parse_format_specifier (struct lexer *lexer, struct fmt_spec *format) return false; } + if (format->w == 0 && !strchr (lex_tokcstr (lexer), '0')) + { + msg (SE, _("Format specifier `%s' lacks required width."), + lex_tokcstr (lexer)); + return false; + } + lex_get (lexer); return true; } diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index 65e92091cd..67f5855939 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -1519,14 +1519,13 @@ static void format_cell_entry (struct tab_table *table, int c, int r, double value, char suffix, bool mark_missing, const struct dictionary *dict) { - const struct fmt_spec f = {FMT_F, 10, 1}; union value v; char suffixes[3]; int suffix_len; char *s; v.f = value; - s = data_out (&v, dict_get_encoding (dict), &f); + s = data_out (&v, dict_get_encoding (dict), settings_get_format ()); suffix_len = 0; if (suffix != 0) diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index 32a979d205..54bc49d946 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-2000, 2009-2012 Free Software Foundation, Inc. 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 @@ -22,6 +22,7 @@ #include "data/casegrouper.h" #include "data/casereader.h" +#include "data/casewriter.h" #include "data/dataset.h" #include "data/dictionary.h" #include "data/transformations.h" @@ -74,6 +75,9 @@ struct dsc_trns size_t var_cnt; /* Number of variables. */ enum dsc_missing_type missing_type; /* Treatment of missing values. */ enum mv_class exclude; /* Classes of missing values to exclude. */ + struct casereader *z_reader; /* Reader for count, mean, stddev. */ + casenumber count; /* Number left in this SPLIT FILE group.*/ + bool ok; }; /* Statistics. Used as bit indexes, so must be 32 or fewer. */ @@ -160,6 +164,9 @@ struct dsc_proc unsigned long show_stats; /* Statistics to display. */ unsigned long calc_stats; /* Statistics to calculate. */ enum moment max_moment; /* Highest moment needed for stats. */ + + /* Z scores. */ + struct casewriter *z_writer; /* Mean and stddev per SPLIT FILE group. */ }; /* Parsing. */ @@ -213,6 +220,7 @@ cmd_descriptives (struct lexer *lexer, struct dataset *ds) dsc->sort_by_stat = DSC_NONE; dsc->sort_ascending = 1; dsc->show_stats = dsc->calc_stats = DEFAULT_STATS; + dsc->z_writer = NULL; /* Parse DESCRIPTIVES. */ while (lex_token (lexer) != T_ENDCMD) @@ -367,6 +375,8 @@ cmd_descriptives (struct lexer *lexer, struct dataset *ds) /* Construct z-score varnames, show translation table. */ if (z_cnt || save_z_scores) { + struct caseproto *proto; + if (save_z_scores) { int gen_cnt = 0; @@ -386,6 +396,13 @@ cmd_descriptives (struct lexer *lexer, struct dataset *ds) } } } + + proto = caseproto_create (); + for (i = 0; i < 1 + 2 * z_cnt; i++) + proto = caseproto_add_width (proto, 0); + dsc->z_writer = autopaging_writer_create (proto); + caseproto_unref (proto); + dump_z_table (dsc); } @@ -475,6 +492,7 @@ free_dsc_proc (struct dsc_proc *dsc) free (dsc_var->z_name); moments_destroy (dsc_var->moments); } + casewriter_destroy (dsc->z_writer); free (dsc->vars); free (dsc); } @@ -601,6 +619,36 @@ descriptives_trns_proc (void *trns_, struct ccase **c, const struct variable **vars; int all_sysmis = 0; + if (t->count <= 0) + { + struct ccase *z_case; + + z_case = casereader_read (t->z_reader); + if (z_case) + { + size_t z_idx = 0; + + t->count = case_num_idx (z_case, z_idx++); + for (z = t->z_scores; z < t->z_scores + t->z_score_cnt; z++) + { + z->mean = case_num_idx (z_case, z_idx++); + z->std_dev = case_num_idx (z_case, z_idx++); + } + case_unref (z_case); + } + else + { + if (t->ok) + { + msg (SE, _("Internal error processing Z scores")); + t->ok = false; + } + for (z = t->z_scores; z < t->z_scores + t->z_score_cnt; z++) + z->mean = z->std_dev = SYSMIS; + } + } + t->count--; + if (t->missing_type == DSC_LISTWISE) { assert(t->vars); @@ -635,11 +683,13 @@ static bool descriptives_trns_free (void *trns_) { struct dsc_trns *t = trns_; + bool ok = t->ok && !casereader_error (t->z_reader); free (t->z_scores); + casereader_destroy (t->z_reader); assert((t->missing_type != DSC_LISTWISE) ^ (t->vars != NULL)); free (t->vars); - return true; + return ok; } /* Sets up a transformation to calculate Z scores. */ @@ -670,6 +720,10 @@ setup_z_trns (struct dsc_proc *dsc, struct dataset *ds) t->var_cnt = 0; t->vars = NULL; } + t->z_reader = casewriter_make_reader (dsc->z_writer); + t->count = 0; + t->ok = true; + dsc->z_writer = NULL; for (cnt = i = 0; i < dsc->var_cnt; i++) { @@ -687,8 +741,6 @@ setup_z_trns (struct dsc_proc *dsc, struct dataset *ds) z = &t->z_scores[cnt++]; z->src_var = dv->v; z->z_var = dst_var; - z->mean = dv->stats[DSC_MEAN]; - z->std_dev = dv->stats[DSC_STDDEV]; } } @@ -707,7 +759,9 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group, struct dataset *ds) { struct casereader *pass1, *pass2; + casenumber count; struct ccase *c; + size_t z_idx; size_t i; c = casereader_peek (group, 0); @@ -739,6 +793,7 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group, dsc->valid = 0.; /* First pass to handle most of the work. */ + count = 0; for (; (c = casereader_read (pass1)) != NULL; case_unref (c)) { double weight = dict_get_case_weight (dataset_dict (ds), c, NULL); @@ -771,6 +826,8 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group, if (x > dv->max) dv->max = x; } + + count++; } if (!casereader_destroy (pass1)) { @@ -806,6 +863,15 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group, } /* Calculate results. */ + if (dsc->z_writer) + { + c = case_create (casewriter_get_proto (dsc->z_writer)); + z_idx = 0; + case_data_rw_idx (c, z_idx++)->f = count; + } + else + c = NULL; + for (i = 0; i < dsc->var_cnt; i++) { struct dsc_var *dv = &dsc->vars[i]; @@ -839,8 +905,17 @@ calc_descriptives (struct dsc_proc *dsc, struct casereader *group, dv->stats[DSC_MAX] = dv->max == -DBL_MAX ? SYSMIS : dv->max; if (dsc->calc_stats & (1ul << DSC_SUM)) dv->stats[DSC_SUM] = W * dv->stats[DSC_MEAN]; + + if (dv->z_name) + { + case_data_rw_idx (c, z_idx++)->f = dv->stats[DSC_MEAN]; + case_data_rw_idx (c, z_idx++)->f = dv->stats[DSC_STDDEV]; + } } + if (c != NULL) + casewriter_write (dsc->z_writer, c); + /* Output results. */ display (dsc); } diff --git a/src/language/stats/npar.c b/src/language/stats/npar.c index af41b10473..737c94e3d2 100644 --- a/src/language/stats/npar.c +++ b/src/language/stats/npar.c @@ -945,7 +945,8 @@ npar_binomial (struct lexer *lexer, struct dataset *ds, { if (lex_match (lexer, T_LPAREN)) { - lex_force_num (lexer); + if (! lex_force_num (lexer)) + return 2; btp->category1 = lex_number (lexer); lex_get (lexer); if ( lex_match (lexer, T_COMMA)) diff --git a/src/language/utilities/set.q b/src/language/utilities/set.q index 243de30063..e6e816a8b7 100644 --- a/src/language/utilities/set.q +++ b/src/language/utilities/set.q @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 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 @@ -708,6 +708,14 @@ show_format (const struct dataset *ds UNUSED) return xstrdup (fmt_to_string (settings_get_format (), str)); } +static char * +show_journal (const struct dataset *ds UNUSED) +{ + return (journal_is_enabled () + ? xasprintf ("\"%s\"", journal_get_file_name ()) + : xstrdup ("disabled")); +} + static char * show_length (const struct dataset *ds UNUSED) { @@ -935,6 +943,7 @@ const struct show_sbc show_table[] = {"ENVIRONMENT", show_system}, {"ERRORS", show_errors}, {"FORMAT", show_format}, + {"JOURNAL", show_journal}, {"LENGTH", show_length}, {"LOCALE", show_locale}, {"MESSAGES", show_messages}, diff --git a/src/libpspp/assertion.h b/src/libpspp/assertion.h index 5b10d638ab..237710813d 100644 --- a/src/libpspp/assertion.h +++ b/src/libpspp/assertion.h @@ -36,3 +36,6 @@ #else #define expensive_assert(EXPR) ((void) 0) #endif + + +#define testing_assert(EXPR) do {if (settings_get_testing_mode ()) assert (EXPR); } while (0); diff --git a/src/math/histogram.c b/src/math/histogram.c index afc40013e0..b00067210f 100644 --- a/src/math/histogram.c +++ b/src/math/histogram.c @@ -21,6 +21,7 @@ #include #include +#include "data/settings.h" #include "libpspp/message.h" #include "libpspp/assertion.h" #include "libpspp/cast.h" @@ -84,6 +85,10 @@ double get_slack (double limit, double half_bin_width, int *n_half_bins) ADJ_MIN and ADJ_MAX are locations of the adjusted values of MIN and MAX (the range will always be equal or slightly larger). Returns the number of bins. + + The "testing_assert" expressions in this function should be algebraically correct. + However, due to floating point rounding they could fail, especially when small numbers + are involved. In normal use, therefore, testing_assert does nothing. */ static int adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, double *adj_max) @@ -97,7 +102,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do double lower_slack = get_slack (min, half_bin_width, &lower_limit); double upper_slack = -get_slack (max, half_bin_width, &upper_limit); - assert (max > min); + testing_assert (max > min); /* If min is negative, then lower_slack may be less than zero. In this case, the lower bound must be extended in the negative direction @@ -108,7 +113,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do lower_limit--; lower_slack += half_bin_width; } - assert (lower_limit * half_bin_width <= min); + testing_assert (lower_limit * half_bin_width <= min); /* However, the upper bound must be extended regardless, because histogram bins span the range [lower, upper). In other words, the upper bound must be @@ -116,7 +121,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do */ upper_limit++;; upper_slack += half_bin_width; - assert (upper_limit * half_bin_width > max); + testing_assert (upper_limit * half_bin_width > max); /* The range must be an EVEN number of half bin_widths */ if ( (upper_limit - lower_limit) % 2) @@ -159,7 +164,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do if (upper_slack > lower_slack) { - assert (upper_slack > half_bin_width); + testing_assert (upper_slack > half_bin_width); /* Adjust the range to the left */ lower_limit --; @@ -169,7 +174,7 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do } else { - assert (lower_slack >= half_bin_width); + testing_assert (lower_slack >= half_bin_width); /* Adjust the range to the right */ lower_limit ++; @@ -197,8 +202,8 @@ adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, do *adj_min = lower_limit * half_bin_width; *adj_max = upper_limit * half_bin_width; - assert (*adj_max > max); - assert (*adj_min <= min); + testing_assert (*adj_max > max); + testing_assert (*adj_min <= min); return (upper_limit - lower_limit) / 2.0; } diff --git a/src/output/ascii.c b/src/output/ascii.c index 1688fd1bf1..9614e6aef8 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 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 @@ -593,9 +593,9 @@ ascii_submit (struct output_driver *driver, } const struct output_driver_factory txt_driver_factory = - { "txt", ascii_create }; + { "txt", "-", ascii_create }; const struct output_driver_factory list_driver_factory = - { "list", ascii_create }; + { "list", "-", ascii_create }; static const struct output_driver_class ascii_driver_class = { diff --git a/src/output/cairo.c b/src/output/cairo.c index 954ae30f54..cd8f0b0e99 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -922,9 +922,12 @@ xr_draw_title (struct xr_driver *xr, const char *title, xr_draw_cell (xr, &cell, bb, bb); } -struct output_driver_factory pdf_driver_factory = { "pdf", xr_pdf_create }; -struct output_driver_factory ps_driver_factory = { "ps", xr_ps_create }; -struct output_driver_factory svg_driver_factory = { "svg", xr_svg_create }; +struct output_driver_factory pdf_driver_factory = + { "pdf", "pspp.pdf", xr_pdf_create }; +struct output_driver_factory ps_driver_factory = + { "ps", "pspp.ps", xr_ps_create }; +struct output_driver_factory svg_driver_factory = + { "svg", "pspp.svg", xr_svg_create }; static const struct output_driver_class cairo_driver_class = { diff --git a/src/output/csv.c b/src/output/csv.c index c8619a9a7d..b57eb7c2d0 100644 --- a/src/output/csv.c +++ b/src/output/csv.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2012 Free Software Foundation, Inc. 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 @@ -255,7 +255,7 @@ csv_submit (struct output_driver *driver, } } -struct output_driver_factory csv_driver_factory = { "csv", csv_create }; +struct output_driver_factory csv_driver_factory = { "csv", "-", csv_create }; static const struct output_driver_class csv_driver_class = { diff --git a/src/output/driver-provider.h b/src/output/driver-provider.h index df31637379..012a304e36 100644 --- a/src/output/driver-provider.h +++ b/src/output/driver-provider.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2012 Free Software Foundation, Inc. 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 @@ -80,6 +80,12 @@ struct output_driver_factory /* The file extension, without the leading dot, e.g. "pdf". */ const char *extension; + /* The default file name, including extension. + + If this is "-", that implies that by default output will be directed to + stdout. */ + const char *default_file_name; + /* Creates a new output driver of this class. NAME and TYPE should be passed directly to output_driver_init. Returns the new output driver if successful, otherwise a null pointer. diff --git a/src/output/driver.c b/src/output/driver.c index acc58cf999..f656845527 100644 --- a/src/output/driver.c +++ b/src/output/driver.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 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 @@ -294,16 +294,23 @@ output_driver_create (struct string_map *options) char *file_name; char *format; + format = string_map_find_and_delete (options, "format"); file_name = string_map_find_and_delete (options, "output-file"); - if (file_name == NULL) - file_name = xstrdup ("-"); - format = string_map_find_and_delete (options, "format"); if (format == NULL) { - const char *extension = strrchr (file_name, '.'); - format = xstrdup (extension != NULL ? extension + 1 : ""); + if (file_name != NULL) + { + const char *extension = strrchr (file_name, '.'); + format = xstrdup (extension != NULL ? extension + 1 : ""); + } + else + format = xstrdup ("txt"); } + f = find_factory (format); + + if (file_name == NULL) + file_name = xstrdup (f->default_file_name); /* XXX should use parse_enum(). */ device_string = string_map_find_and_delete (options, "device"); @@ -320,7 +327,6 @@ output_driver_create (struct string_map *options) device_type = default_device_type (file_name); } - f = find_factory (format); driver = f->create (file_name, device_type, options); if (driver != NULL) { diff --git a/src/output/html.c b/src/output/html.c index 77d4195f30..29a44721d4 100644 --- a/src/output/html.c +++ b/src/output/html.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 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 @@ -477,7 +477,8 @@ html_output_table (struct html_driver *html, struct table_item *item) fputs ("\n\n", html->file); } -struct output_driver_factory html_driver_factory = { "html", html_create }; +struct output_driver_factory html_driver_factory = + { "html", "pspp.html", html_create }; static const struct output_driver_class html_driver_class = { diff --git a/src/output/journal.c b/src/output/journal.c index 66c1b77534..2b58350520 100644 --- a/src/output/journal.c +++ b/src/output/journal.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2010, 2012 Free Software Foundation, Inc. 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 @@ -87,11 +87,11 @@ journal_output (struct journal_driver *j, const char *s) { if (j->file == NULL) { - j->file = fopen (journal_file_name, "a"); + j->file = fopen (journal_get_file_name (), "a"); if (j->file == NULL) { error (0, errno, _("error opening output file `%s'"), - journal_file_name); + journal_get_file_name ()); output_driver_destroy (&j->driver); return; } @@ -144,13 +144,6 @@ journal_enable (void) { if (journal == NULL) { - /* If no journal file name is configured, use the default. */ - if (journal_file_name == NULL) - { - const char *output_path = default_output_path (); - journal_file_name = xasprintf ("%s%s", output_path, "pspp.jnl"); - } - /* Create journal driver. */ journal = xzalloc (sizeof *journal); output_driver_init (&journal->driver, &journal_class, "journal", @@ -171,6 +164,13 @@ journal_disable (void) output_driver_destroy (&journal->driver); } +/* Returns true if journaling is enabled, false otherwise. */ +bool +journal_is_enabled (void) +{ + return journal != NULL; +} + /* Sets the name of the journal file to FILE_NAME. */ void journal_set_file_name (const char *file_name) @@ -179,3 +179,16 @@ journal_set_file_name (const char *file_name) free (journal_file_name); journal_file_name = xstrdup (file_name); } + +/* Returns the name of the journal file. The caller must not modify or free + the returned string. */ +const char * +journal_get_file_name (void) +{ + if (journal_file_name == NULL) + { + const char *output_path = default_output_path (); + journal_file_name = xasprintf ("%s%s", output_path, "pspp.jnl"); + } + return journal_file_name; +} diff --git a/src/output/journal.h b/src/output/journal.h index 5051193a67..377152d5ce 100644 --- a/src/output/journal.h +++ b/src/output/journal.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2012 Free Software Foundation, Inc. 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 @@ -28,6 +28,8 @@ void journal_enable (void); void journal_disable (void); +bool journal_is_enabled (void); void journal_set_file_name (const char *); +const char *journal_get_file_name (void); #endif /* output/journal.h */ diff --git a/src/output/measure.c b/src/output/measure.c index 14cd5dab9f..60894f1cc2 100644 --- a/src/output/measure.c +++ b/src/output/measure.c @@ -18,6 +18,7 @@ #include "output/measure.h" +#include #include #include #if HAVE_LC_PAPER @@ -50,7 +51,7 @@ measure_dimension (const char *dimen) char *tail; /* Number. */ - raw = strtod (dimen, &tail); + raw = c_strtod (dimen, &tail); if (raw < 0.0) goto syntax_error; @@ -150,7 +151,7 @@ parse_paper_size (const char *size, int *h, int *v) char *tail; /* Width. */ - raw_h = strtod (size, &tail); + raw_h = c_strtod (size, &tail); if (raw_h <= 0.0) return false; @@ -158,7 +159,7 @@ parse_paper_size (const char *size, int *h, int *v) tail += strspn (tail, CC_SPACES "x,"); /* Length. */ - raw_v = strtod (tail, &tail); + raw_v = c_strtod (tail, &tail); if (raw_v <= 0.0) return false; diff --git a/src/output/odt.c b/src/output/odt.c index 686e7149c3..a02506c1e9 100644 --- a/src/output/odt.c +++ b/src/output/odt.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 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 @@ -517,7 +517,8 @@ odt_submit (struct output_driver *driver, } } -struct output_driver_factory odt_driver_factory = { "odt", odt_create }; +struct output_driver_factory odt_driver_factory = + { "odt", "pspp.odf", odt_create }; static const struct output_driver_class odt_driver_class = { diff --git a/src/ui/automake.mk b/src/ui/automake.mk index a4eeebf11c..db634cee16 100644 --- a/src/ui/automake.mk +++ b/src/ui/automake.mk @@ -7,7 +7,6 @@ include $(top_srcdir)/src/ui/gui/automake.mk noinst_LTLIBRARIES += src/ui/libuicommon.la src_ui_libuicommon_la_SOURCES = \ - src/ui/debugger.c src/ui/debugger.h \ src/ui/source-init-opts.c src/ui/source-init-opts.h \ src/ui/syntax-gen.c src/ui/syntax-gen.h diff --git a/src/ui/debugger.c b/src/ui/debugger.c deleted file mode 100644 index f3f678461f..0000000000 --- a/src/ui/debugger.c +++ /dev/null @@ -1,72 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2006 Free Software Foundation, Inc. - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "debugger.h" - -#if HAVE_FORK && HAVE_EXECLP -#include -#include -#include -#include -#include -#include - -/* Fork, start gdb and connect to the parent process. - If that happens successfully, then this function does not return, - but exits with EXIT_FAILURE. Otherwise it returns. - */ -void -connect_debugger (void) -{ - char pidstr[20]; - pid_t pid; - - snprintf (pidstr, 20, "%d", getpid ()); - pid = fork (); - if ( pid == -1 ) - { - perror ("Cannot fork"); - return ; - } - if ( pid == 0 ) - { - /* child */ - execlp ("gdb", "gdb", "-p", pidstr, NULL); - perror ("Cannot exec debugger"); - exit (EXIT_FAILURE); - } - else - { - int status; - wait (&status); - if ( EXIT_SUCCESS != WEXITSTATUS (status) ) - return ; - } - - exit (EXIT_FAILURE); -} - -#else /* !(HAVE_FORK && HAVE_EXECLP) */ -/* Don't know how to connect to gdb. - Just return. - */ -void -connect_debugger (void) -{ -} -#endif /* !(HAVE_FORK && HAVE_EXECLP) */ diff --git a/src/ui/debugger.h b/src/ui/debugger.h deleted file mode 100644 index 321e6ca543..0000000000 --- a/src/ui/debugger.h +++ /dev/null @@ -1,26 +0,0 @@ -/* PSPP - a program for statistical analysis. - Copyright (C) 2006 Free Software Foundation, Inc. - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef DEBUGGER_H -#define DEBUGGER_H - - -/* Fork, start gdb and connect to the parent process. - Exit with EXIT_FAILURE. - */ -void connect_debugger (void) ; - -#endif diff --git a/src/ui/gui/aggregate-dialog.c b/src/ui/gui/aggregate-dialog.c index a5c243a8e2..8b54ed584a 100644 --- a/src/ui/gui/aggregate-dialog.c +++ b/src/ui/gui/aggregate-dialog.c @@ -93,15 +93,6 @@ struct aggregate static char * generate_syntax (const struct aggregate *rd); -/* Makes widget W's sensitivity follow the active state of TOGGLE */ -static void -sensitive_if_active (GtkToggleButton *toggle, GtkWidget *w) -{ - gboolean active = gtk_toggle_button_get_active (toggle); - - gtk_widget_set_sensitive (w, active); -} - static void update_arguments (struct aggregate *agg); @@ -577,7 +568,7 @@ aggregate_dialog (PsppireDataWindow *dw) dialog_state_valid, &fd); g_signal_connect (fd.filename_radiobutton, "toggled", - G_CALLBACK (sensitive_if_active), fd.filename_box ); + G_CALLBACK (set_sensitivity_from_toggle), fd.filename_box ); g_signal_connect_swapped (fd.filename_button, "clicked", G_CALLBACK (choose_filename), &fd); diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index ea1f06df8b..8cba97018b 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -163,8 +163,6 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/autorecode-dialog.h \ src/ui/gui/aggregate-dialog.c \ src/ui/gui/aggregate-dialog.h \ - src/ui/gui/binomial-dialog.c \ - src/ui/gui/binomial-dialog.h \ src/ui/gui/builder-wrapper.c \ src/ui/gui/builder-wrapper.h \ src/ui/gui/checkbox-treeview.c \ @@ -177,8 +175,6 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/chi-square-dialog.h \ src/ui/gui/count-dialog.c \ src/ui/gui/count-dialog.h \ - src/ui/gui/crosstabs-dialog.c \ - src/ui/gui/crosstabs-dialog.h \ src/ui/gui/dialog-common.c \ src/ui/gui/dialog-common.h \ src/ui/gui/dict-display.h \ @@ -189,8 +185,6 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/executor.h \ src/ui/gui/find-dialog.c \ src/ui/gui/find-dialog.h \ - src/ui/gui/frequencies-dialog.c \ - src/ui/gui/frequencies-dialog.h \ src/ui/gui/goto-case-dialog.c \ src/ui/gui/goto-case-dialog.h \ src/ui/gui/helper.c \ @@ -225,14 +219,20 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/psppire-dialog.h \ src/ui/gui/psppire-dialog-action.c \ src/ui/gui/psppire-dialog-action.h \ + src/ui/gui/psppire-dialog-action-binomial.c \ + src/ui/gui/psppire-dialog-action-binomial.h \ src/ui/gui/psppire-dialog-action-correlation.c \ src/ui/gui/psppire-dialog-action-correlation.h \ + src/ui/gui/psppire-dialog-action-crosstabs.c \ + src/ui/gui/psppire-dialog-action-crosstabs.h \ src/ui/gui/psppire-dialog-action-descriptives.c \ src/ui/gui/psppire-dialog-action-descriptives.h \ src/ui/gui/psppire-dialog-action-examine.c \ src/ui/gui/psppire-dialog-action-examine.h \ src/ui/gui/psppire-dialog-action-factor.c \ src/ui/gui/psppire-dialog-action-factor.h \ + src/ui/gui/psppire-dialog-action-frequencies.c \ + src/ui/gui/psppire-dialog-action-frequencies.h \ src/ui/gui/psppire-dialog-action-indep-samps.c \ src/ui/gui/psppire-dialog-action-indep-samps.h \ src/ui/gui/psppire-dialog-action-kmeans.c \ diff --git a/src/ui/gui/binomial-dialog.c b/src/ui/gui/binomial-dialog.c deleted file mode 100644 index 90d9118ea6..0000000000 --- a/src/ui/gui/binomial-dialog.c +++ /dev/null @@ -1,195 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2010, 2011, 2012 Free Software Foundation - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "binomial-dialog.h" - -#include "psppire-dialog.h" -#include "psppire-var-view.h" -#include "psppire-acr.h" -#include "dialog-common.h" - -#include "builder-wrapper.h" -#include "executor.h" -#include "helper.h" - -#include - -struct binomial_dialog -{ - PsppireDict *dict; - GtkWidget *var_view; - - GtkWidget *button1; - - GtkWidget *prop_entry; - - GtkWidget *cutpoint_button; - GtkWidget *cutpoint_entry; -}; - -static void -set_sensitivity (GtkToggleButton *button, GtkWidget *w) -{ - gboolean state = gtk_toggle_button_get_active (button); - gtk_widget_set_sensitive (w, state); -} - - -static gboolean -get_proportion (const struct binomial_dialog *bin_d, double *prop) -{ - const gchar *text = gtk_entry_get_text (GTK_ENTRY (bin_d->prop_entry)); - gchar *endptr = NULL; - *prop = g_strtod (text, &endptr); - - if (endptr == text) - return FALSE; - - return TRUE; -} - -static gboolean -dialog_state_valid (gpointer data) -{ - double prop; - struct binomial_dialog *bin_d = data; - - GtkTreeModel *vars = - gtk_tree_view_get_model (GTK_TREE_VIEW (bin_d->var_view)); - - GtkTreeIter notused; - - if ( !gtk_tree_model_get_iter_first (vars, ¬used) ) - return FALSE; - - if ( ! get_proportion (bin_d, &prop)) - return FALSE; - - if (prop < 0 || prop > 1.0) - return FALSE; - - return TRUE; -} - - -static void -refresh (struct binomial_dialog *bin_d) -{ - GtkTreeModel *liststore = - gtk_tree_view_get_model (GTK_TREE_VIEW (bin_d->var_view)); - - gtk_list_store_clear (GTK_LIST_STORE (liststore)); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bin_d->button1), TRUE); - - gtk_entry_set_text (GTK_ENTRY (bin_d->prop_entry), "0.5"); - - gtk_entry_set_text (GTK_ENTRY (bin_d->cutpoint_entry), ""); -} - - - -static char * -generate_syntax (const struct binomial_dialog *scd) -{ - gchar *text; - double prop; - GString *string; - - string = g_string_new ("NPAR TEST\n\t/BINOMIAL"); - - if ( get_proportion (scd, &prop)) - g_string_append_printf (string, "(%g)", prop); - - g_string_append (string, " ="); - - psppire_var_view_append_names (PSPPIRE_VAR_VIEW (scd->var_view), 0, string); - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->cutpoint_button))) - { - const gchar *cutpoint = gtk_entry_get_text (GTK_ENTRY (scd->cutpoint_entry)); - g_string_append_printf (string, "(%s)", cutpoint); - } - - g_string_append (string, ".\n"); - - text = string->str; - - g_string_free (string, FALSE); - - return text; -} - - - -/* Pops up the Chi-Square dialog box */ -void -binomial_dialog (PsppireDataWindow *dw) -{ - gint response; - - struct binomial_dialog bin_d; - - GtkBuilder *xml = builder_new ("binomial.ui"); - - GtkWidget *dialog = get_widget_assert (xml, "binomial-dialog"); - - - - GtkWidget *dict_view = get_widget_assert (xml, "dict-view"); - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (dw)); - - bin_d.var_view = get_widget_assert (xml, "variables-treeview"); - bin_d.button1 = get_widget_assert (xml, "radiobutton3"); - bin_d.prop_entry = get_widget_assert (xml, "proportion-entry"); - - bin_d.cutpoint_entry = get_widget_assert (xml, "cutpoint-entry"); - bin_d.cutpoint_button = get_widget_assert (xml, "radiobutton4"); - - g_object_get (dw->data_editor, "dictionary", &bin_d.dict, NULL); - g_object_set (dict_view, - "model", bin_d.dict, - "predicate", var_is_numeric, - NULL); - - g_signal_connect (bin_d.cutpoint_button, "toggled", G_CALLBACK (set_sensitivity), - bin_d.cutpoint_entry); - - g_signal_connect_swapped (dialog, "refresh", G_CALLBACK (refresh), &bin_d); - - psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), - dialog_state_valid, &bin_d); - - response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); - - - switch (response) - { - case GTK_RESPONSE_OK: - g_free (execute_syntax_string (dw, generate_syntax (&bin_d))); - break; - case PSPPIRE_RESPONSE_PASTE: - g_free (paste_syntax_to_window (generate_syntax (&bin_d))); - break; - default: - break; - } - - g_object_unref (xml); -} diff --git a/src/ui/gui/binomial-dialog.h b/src/ui/gui/binomial-dialog.h deleted file mode 100644 index b50e444cf4..0000000000 --- a/src/ui/gui/binomial-dialog.h +++ /dev/null @@ -1,24 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2010 Free Software Foundation - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef __BINOMIAL_DIALOG_H -#define __BINOMIAL_DIALOG_H - -#include "psppire-data-window.h" - -void binomial_dialog (PsppireDataWindow * data); - -#endif diff --git a/src/ui/gui/chi-square-dialog.c b/src/ui/gui/chi-square-dialog.c index 64a6356ce1..5d4cc4b431 100644 --- a/src/ui/gui/chi-square-dialog.c +++ b/src/ui/gui/chi-square-dialog.c @@ -46,14 +46,6 @@ struct chisquare_dialog GtkListStore *expected_list; }; -static void -set_sensitivity (GtkToggleButton *button, GtkWidget *w) -{ - gboolean state = gtk_toggle_button_get_active (button); - gtk_widget_set_sensitive (w, state); -} - - static gboolean dialog_state_valid (gpointer data) { @@ -198,14 +190,14 @@ chisquare_dialog (PsppireDataWindow *dw) NULL); - g_signal_connect (csd.range_button, "toggled", G_CALLBACK (set_sensitivity), + g_signal_connect (csd.range_button, "toggled", G_CALLBACK (set_sensitivity_from_toggle), range_table); - g_signal_connect (csd.values_button, "toggled", G_CALLBACK (set_sensitivity), + g_signal_connect (csd.values_button, "toggled", G_CALLBACK (set_sensitivity_from_toggle), values_acr); - g_signal_connect (csd.values_button, "toggled", G_CALLBACK (set_sensitivity), + g_signal_connect (csd.values_button, "toggled", G_CALLBACK (set_sensitivity_from_toggle), expected_value_entry); diff --git a/src/ui/gui/crosstabs-dialog.c b/src/ui/gui/crosstabs-dialog.c deleted file mode 100644 index 3cb8218b91..0000000000 --- a/src/ui/gui/crosstabs-dialog.c +++ /dev/null @@ -1,431 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008, 2010, 2011, 2012 Free Software Foundation - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "checkbox-treeview.h" -#include "crosstabs-dialog.h" -#include "psppire-var-view.h" - -#include -#include - -#include -#include -#include -#include "executor.h" -#include -#include -#include "helper.h" - -#include "gettext.h" -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - - -#define CROSSTABS_STATS \ - CS (CHISQ, N_("Chisq")) \ - CS (PHI, N_("Phi")) \ - CS (CC, N_("CC")) \ - CS (LAMBDA, N_("Lambda")) \ - CS (UC, N_("UC")) \ - CS (BTAU, N_("BTau")) \ - CS (CTAU, N_("CTau")) \ - CS (RISK, N_("Risk")) \ - CS (GAMMA, N_("Gamma")) \ - CS (D, N_("D")) \ - CS (KAPPA, N_("Kappa")) \ - CS (ETA, N_("Eta")) \ - CS (CORR, N_("Corr")) \ - CS (STATS_NONE, N_("None")) - -#define CROSSTABS_CELLS \ - CS (COUNT, N_("Count")) \ - CS (ROW, N_("Row")) \ - CS (COLUMN, N_("Column")) \ - CS (TOTAL, N_("Total")) \ - CS (EXPECTED, N_("Expected")) \ - CS (RESIDUAL, N_("Residual")) \ - CS (SRESIDUAL, N_("Std. Residual")) \ - CS (ASRESIDUAL, N_("Adjusted Std. Residual")) \ - CS (CELLS_NONE, N_("None")) - -enum - { -#define CS(NAME, LABEL) CS_##NAME, - CROSSTABS_STATS -#undef CS - N_CROSSTABS_STATS - }; - -enum - { -#define CS(NAME, LABEL) CS_##NAME, - CROSSTABS_CELLS -#undef CS - N_CROSSTABS_CELLS - }; - -enum - { -#define CS(NAME, LABEL) B_CS_##NAME = 1u << CS_##NAME, - CROSSTABS_STATS - CROSSTABS_CELLS -#undef CS - B_CS_STATS_ALL = (1u << N_CROSSTABS_STATS) - 1, - B_CS_CELLS_ALL = (1u << N_CROSSTABS_CELLS) - 1, - B_CS_STATS_DEFAULT = B_CS_CHISQ, - B_CS_CELL_DEFAULT = B_CS_COUNT | B_CS_ROW | B_CS_COLUMN | B_CS_TOTAL, - B_CS_NONE - }; - -static const struct checkbox_entry_item stats[] = - { -#define CS(NAME, LABEL) {#NAME, LABEL}, - CROSSTABS_STATS \ - CS(NONE, N_("None")) -#undef CS - }; - -static const struct checkbox_entry_item cells[] = - { -#define CS(NAME, LABEL) {#NAME, LABEL}, - CROSSTABS_CELLS \ - CS(NONE, N_("None")) -#undef CS - }; - -struct format_options -{ - gboolean avalue; - gboolean pivot; - gboolean table; -}; - -struct crosstabs_dialog -{ - GtkTreeView *row_vars; - GtkTreeView *col_vars; - PsppireDict *dict; - - GtkToggleButton *table_button; - GtkToggleButton *pivot_button; - - GtkWidget *format_dialog; - GtkWidget *cell_dialog; - GtkWidget *stat_dialog; - - GtkToggleButton *avalue; - GtkTreeModel *stat; - GtkTreeModel *cell; - - GtkWidget *stat_view; - GtkWidget *cell_view; - struct format_options current_opts; -}; - -static void -refresh (PsppireDialog *dialog, struct crosstabs_dialog *cd) -{ - GtkTreeModel *liststore = gtk_tree_view_get_model (cd->row_vars); - gtk_list_store_clear (GTK_LIST_STORE (liststore)); - - liststore = gtk_tree_view_get_model (cd->col_vars); - gtk_list_store_clear (GTK_LIST_STORE (liststore)); -} -static void -on_format_clicked (struct crosstabs_dialog *cd) -{ - int ret; - - if (cd->current_opts.avalue) - { - gtk_toggle_button_set_active (cd->avalue, TRUE); - } - if (cd->current_opts.table) - { - gtk_toggle_button_set_active (cd->table_button, TRUE); - } - if (cd->current_opts.pivot) - { - gtk_toggle_button_set_active (cd->pivot_button, TRUE); - } - - ret = psppire_dialog_run (PSPPIRE_DIALOG (cd->format_dialog)); - - if ( ret == PSPPIRE_RESPONSE_CONTINUE ) - { - cd->current_opts.avalue = (gtk_toggle_button_get_active (cd->avalue) == TRUE ) - ? TRUE : FALSE; - cd->current_opts.table = (gtk_toggle_button_get_active (cd->table_button) == TRUE) - ? TRUE : FALSE; - cd->current_opts.pivot = (gtk_toggle_button_get_active (cd->pivot_button) == TRUE) - ? TRUE : FALSE; - } -} - -static void -on_statistics_clicked (struct crosstabs_dialog *cd) -{ - GtkListStore *liststore; - int ret; - - liststore = clone_list_store (GTK_LIST_STORE (cd->stat)); - - ret = psppire_dialog_run (PSPPIRE_DIALOG (cd->stat_dialog)); - - if ( ret == PSPPIRE_RESPONSE_CONTINUE ) - { - g_object_unref (liststore); - } - else - { - g_object_unref (cd->stat); - gtk_tree_view_set_model (GTK_TREE_VIEW (cd->stat_view) , GTK_TREE_MODEL (liststore)); - cd->stat = GTK_TREE_MODEL (liststore); - } -} -static void -on_cell_clicked (struct crosstabs_dialog *cd) -{ - GtkListStore *liststore; - int ret; - - liststore = clone_list_store (GTK_LIST_STORE (cd->cell)); - - ret = psppire_dialog_run (PSPPIRE_DIALOG (cd->cell_dialog)); - - if ( ret == PSPPIRE_RESPONSE_CONTINUE ) - { - g_object_unref (liststore); - } - else - { - g_object_unref (cd->cell); - gtk_tree_view_set_model (GTK_TREE_VIEW (cd->cell_view) , GTK_TREE_MODEL (liststore)); - cd->cell = GTK_TREE_MODEL (liststore); - } -} - -static char * -generate_syntax (const struct crosstabs_dialog *cd) -{ - gint i; - int n; - guint selected; - GtkTreeIter iter; - gboolean ok; - - gchar *text; - GString *string = g_string_new ("CROSSTABS"); - - g_string_append (string, "\n\t/TABLES="); - psppire_var_view_append_names (PSPPIRE_VAR_VIEW (cd->row_vars), 0, string); - g_string_append (string, "\tBY\t"); - psppire_var_view_append_names (PSPPIRE_VAR_VIEW (cd->col_vars), 0, string); - - g_string_append (string, "\n\t/FORMAT="); - - if (cd->current_opts.avalue) - { - g_string_append (string, "AVALUE"); - } - else - { - g_string_append (string, "DVALUE"); - } - g_string_append (string, " "); - if (cd->current_opts.table) - g_string_append (string, "TABLES"); - else - g_string_append (string, "NOTABLES"); - g_string_append (string, " "); - - if (cd->current_opts.pivot) - g_string_append (string, "PIVOT"); - else - g_string_append (string, "NOPIVOT"); - - selected = 0; - for (i = 0, ok = gtk_tree_model_get_iter_first (cd->stat, &iter); ok; - i++, ok = gtk_tree_model_iter_next (cd->stat, &iter)) - { - gboolean toggled; - gtk_tree_model_get (cd->stat, &iter, - CHECKBOX_COLUMN_SELECTED, &toggled, -1); - if (toggled) - selected |= 1u << i; - else - selected &= ~(1u << i); - } - - if (!(selected & (1u << CS_STATS_NONE))) - { - if (selected) - { - g_string_append (string, "\n\t/STATISTICS="); - n = 0; - for (i = 0; i < N_CROSSTABS_STATS; i++) - if (selected & (1u << i)) - { - if (n++) - g_string_append (string, " "); - g_string_append (string, stats[i].name); - } - } - } - - selected = 0; - for (i = 0, ok = gtk_tree_model_get_iter_first (cd->cell, &iter); ok; - i++, ok = gtk_tree_model_iter_next (cd->cell, &iter)) - { - gboolean toggled; - gtk_tree_model_get (cd->cell, &iter, - CHECKBOX_COLUMN_SELECTED, &toggled, -1); - if (toggled) - selected |= 1u << i; - else - selected &= ~(1u << i); - } - - g_string_append (string, "\n\t/CELLS="); - if (selected & (1u << CS_CELLS_NONE)) - g_string_append (string, "NONE"); - else - { - n = 0; - for (i = 0; i < N_CROSSTABS_CELLS; i++) - if (selected & (1u << i)) - { - if (n++) - g_string_append (string, " "); - g_string_append (string, cells[i].name); - } - } - - g_string_append (string, ".\n"); - - text = string->str; - - g_string_free (string, FALSE); - - return text; -} - -/* Dialog is valid iff at least one row and one column variable has - been selected. */ -static gboolean -dialog_state_valid (gpointer data) -{ - struct crosstabs_dialog *cd = data; - - GtkTreeModel *row_vars = gtk_tree_view_get_model (cd->row_vars); - GtkTreeModel *col_vars = gtk_tree_view_get_model (cd->col_vars); - - GtkTreeIter notused; - - return (gtk_tree_model_get_iter_first (row_vars, ¬used) - && gtk_tree_model_get_iter_first (col_vars, ¬used)); -} - -/* Pops up the Crosstabs dialog box */ -void -crosstabs_dialog (PsppireDataWindow *de) -{ - gint response; - struct crosstabs_dialog cd; - - GtkBuilder *xml = builder_new ("crosstabs.ui"); - PsppireDict *dict = NULL; - - - GtkWidget *dialog = get_widget_assert (xml, "crosstabs-dialog"); - GtkWidget *source = get_widget_assert (xml, "dict-treeview"); - GtkWidget *dest_rows = get_widget_assert (xml, "rows"); - GtkWidget *dest_cols = get_widget_assert (xml, "cols"); - GtkWidget *format_button = get_widget_assert (xml, "format-button"); - GtkWidget *stat_button = get_widget_assert (xml, "stats-button"); - GtkWidget *cell_button = get_widget_assert (xml, "cell-button"); - - - cd.stat_view = get_widget_assert (xml, "stats-view"); - cd.cell_view = get_widget_assert (xml, "cell-view"); - - put_checkbox_items_in_treeview (GTK_TREE_VIEW(cd.stat_view), - B_CS_STATS_DEFAULT, - N_CROSSTABS_STATS, - stats - ); - put_checkbox_items_in_treeview (GTK_TREE_VIEW(cd.cell_view), - B_CS_CELL_DEFAULT, - N_CROSSTABS_CELLS, - cells - ); - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de)); - - g_object_get (de->data_editor, "dictionary", &dict, NULL); - g_object_set (source, "model", dict, NULL); - - cd.row_vars = GTK_TREE_VIEW (dest_rows); - cd.col_vars = GTK_TREE_VIEW (dest_cols); - g_object_get (de->data_editor, "dictionary", &cd.dict, NULL); - cd.format_dialog = get_widget_assert (xml, "format-dialog"); - cd.table_button = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "print-tables")); - cd.pivot_button = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "pivot")); - cd.stat_dialog = get_widget_assert (xml, "stat-dialog"); - cd.cell_dialog = get_widget_assert (xml, "cell-dialog"); - - cd.stat = gtk_tree_view_get_model (GTK_TREE_VIEW (cd.stat_view)); - cd.cell = gtk_tree_view_get_model (GTK_TREE_VIEW (cd.cell_view)); - cd.avalue = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "ascending")); - cd.current_opts.avalue = TRUE; - cd.current_opts.table = TRUE; - cd.current_opts.pivot = TRUE; - - gtk_window_set_transient_for (GTK_WINDOW (cd.format_dialog), GTK_WINDOW (de)); - gtk_window_set_transient_for (GTK_WINDOW (cd.cell_dialog), GTK_WINDOW (de)); - gtk_window_set_transient_for (GTK_WINDOW (cd.stat_dialog), GTK_WINDOW (de)); - - g_signal_connect (dialog, "refresh", G_CALLBACK (refresh), &cd); - - psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), - dialog_state_valid, &cd); - - g_signal_connect_swapped (format_button, "clicked", - G_CALLBACK (on_format_clicked), &cd); - g_signal_connect_swapped (stat_button, "clicked", - G_CALLBACK (on_statistics_clicked), &cd); - g_signal_connect_swapped (cell_button, "clicked", - G_CALLBACK (on_cell_clicked), &cd); - - response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); - - - switch (response) - { - case GTK_RESPONSE_OK: - g_free (execute_syntax_string (de, generate_syntax (&cd))); - break; - case PSPPIRE_RESPONSE_PASTE: - g_free (paste_syntax_to_window (generate_syntax (&cd))); - break; - default: - break; - } - - g_object_unref (xml); -} diff --git a/src/ui/gui/crosstabs-dialog.h b/src/ui/gui/crosstabs-dialog.h deleted file mode 100644 index 65e47610d6..0000000000 --- a/src/ui/gui/crosstabs-dialog.h +++ /dev/null @@ -1,24 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008, 2010 Free Software Foundation - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef __CROSSTABS_DIALOG_H -#define __CROSSTABS_DIALOG_H - -#include "psppire-data-window.h" - -void crosstabs_dialog (PsppireDataWindow * data); - -#endif diff --git a/src/ui/gui/data-editor.ui b/src/ui/gui/data-editor.ui index 491b94b1bc..0b1378e842 100644 --- a/src/ui/gui/data-editor.ui +++ b/src/ui/gui/data-editor.ui @@ -266,8 +266,9 @@ - - analyze_frequencies + + uimanager1 + frequencies _Frequencies... @@ -286,8 +287,9 @@ - + crosstabs + uimanager1 _Crosstabs... @@ -397,8 +399,9 @@ - + binomial + uimanager1 _Binomial... @@ -532,7 +535,7 @@ - + diff --git a/src/ui/gui/dialog-common.c b/src/ui/gui/dialog-common.c index c61cb14a64..9e97923e3f 100644 --- a/src/ui/gui/dialog-common.c +++ b/src/ui/gui/dialog-common.c @@ -165,3 +165,30 @@ numeric_only (GtkWidget *source, GtkWidget *dest) return retval; } +/* + A pair of functions intended to be used as callbacks for the "toggled" signal + of a GtkToggleButton widget. They make the sensitivity of W follow the status + of the togglebutton. +*/ +void +set_sensitivity_from_toggle (GtkToggleButton *togglebutton, GtkWidget *w) +{ + gboolean active = gtk_toggle_button_get_active (togglebutton); + + gtk_widget_set_sensitive (w, active); + if (active) + gtk_widget_grab_focus (w); +} + +/* */ +void +set_sensitivity_from_toggle_invert (GtkToggleButton *togglebutton, + GtkWidget *w) +{ + gboolean active = gtk_toggle_button_get_active (togglebutton); + + gtk_widget_set_sensitive (w, !active); +} + + + diff --git a/src/ui/gui/dialog-common.h b/src/ui/gui/dialog-common.h index 328904acfc..d32082477d 100644 --- a/src/ui/gui/dialog-common.h +++ b/src/ui/gui/dialog-common.h @@ -54,5 +54,13 @@ gboolean homogeneous_types (GtkWidget *source, GtkWidget *dest); */ gboolean numeric_only (GtkWidget *source, GtkWidget *dest); +/* + A pair of functions intended to be used as callbacks for the "toggled" signal + of a GtkToggleButton widget. They make the sensitivity of W follow the status + of the togglebutton. +*/ +void set_sensitivity_from_toggle (GtkToggleButton *togglebutton, GtkWidget *w); +void set_sensitivity_from_toggle_invert (GtkToggleButton *togglebutton, GtkWidget *w); + #endif diff --git a/src/ui/gui/frequencies-dialog.c b/src/ui/gui/frequencies-dialog.c deleted file mode 100644 index 32871e0a8b..0000000000 --- a/src/ui/gui/frequencies-dialog.c +++ /dev/null @@ -1,578 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2010, 2011, 2012 Free Software Foundation - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "checkbox-treeview.h" -#include "frequencies-dialog.h" -#include "psppire-var-view.h" - -#include -#include - -#include -#include -#include -#include -#include -#include "executor.h" -#include "helper.h" - -#include "gettext.h" -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - - -#define FREQUENCY_STATS \ - FS (MEAN, N_("Mean")) \ - FS (STDDEV, N_("Standard deviation")) \ - FS (MINIMUM, N_("Minimum")) \ - FS (MAXIMUM, N_("Maximum")) \ - FS (SEMEAN, N_("Standard error of the mean")) \ - FS (VARIANCE, N_("Variance")) \ - FS (SKEWNESS, N_("Skewness")) \ - FS (SESKEW, N_("Standard error of the skewness")) \ - FS (RANGE, N_("Range")) \ - FS (MODE, N_("Mode")) \ - FS (KURTOSIS, N_("Kurtosis")) \ - FS (SEKURT, N_("Standard error of the kurtosis")) \ - FS (MEDIAN, N_("Median")) \ - FS (SUM, N_("Sum")) - -enum - { -#define FS(NAME, LABEL) FS_##NAME, - FREQUENCY_STATS -#undef FS - N_FREQUENCY_STATS - }; - -enum - { -#define FS(NAME, LABEL) B_FS_##NAME = 1u << FS_##NAME, - FREQUENCY_STATS -#undef FS - B_FS_ALL = (1u << N_FREQUENCY_STATS) - 1, - B_FS_DEFAULT = B_FS_MEAN | B_FS_STDDEV | B_FS_MINIMUM | B_FS_MAXIMUM - }; - - -static const struct checkbox_entry_item stats[] = - { -#define FS(NAME, LABEL) {#NAME, LABEL}, - FREQUENCY_STATS -#undef FS - }; - - - -enum frq_order - { - FRQ_AVALUE, - FRQ_DVALUE, - FRQ_ACOUNT, - FRQ_DCOUNT - }; - -enum frq_table - { - FRQ_TABLE, - FRQ_NOTABLE, - FRQ_LIMIT - }; - -struct tables_options -{ - enum frq_order order; - enum frq_table table; - int limit; -}; - -enum frq_scale - { - FRQ_FREQ, - FRQ_PERCENT - }; - -struct charts_options - { - bool use_min; - double min; - bool use_max; - double max; - bool draw_hist; - bool draw_normal; - enum frq_scale scale; - bool draw_pie; - bool pie_include_missing; - }; - -struct frequencies_dialog -{ - /* Main dialog. */ - GtkTreeView *stat_vars; - PsppireDict *dict; - - GtkWidget *tables_button; - GtkWidget *charts_button; - - GtkToggleButton *include_missing; - - GtkTreeModel *stats; - - /* Frequency Tables dialog. */ - GtkWidget *tables_dialog; - struct tables_options tables_opts; - - GtkToggleButton *always; - GtkToggleButton *never; - GtkToggleButton *limit; - GtkSpinButton *limit_spinbutton; - - GtkToggleButton *avalue; - GtkToggleButton *dvalue; - GtkToggleButton *afreq; - GtkToggleButton *dfreq; - - /* Charts dialog. */ - GtkWidget *charts_dialog; - struct charts_options charts_opts; - - GtkToggleButton *freqs; - GtkToggleButton *percents; - - GtkToggleButton *min; - GtkSpinButton *min_spin; - GtkToggleButton *max; - GtkSpinButton *max_spin; - - GtkToggleButton *hist; - GtkToggleButton *normal; - - GtkToggleButton *pie; - GtkToggleButton *pie_include_missing; -}; - -static void -refresh (PsppireDialog *dialog, struct frequencies_dialog *fd) -{ - GtkTreeIter iter; - size_t i; - bool ok; - - GtkTreeModel *liststore = gtk_tree_view_get_model (fd->stat_vars); - gtk_list_store_clear (GTK_LIST_STORE (liststore)); - - for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; - i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) - gtk_list_store_set (GTK_LIST_STORE (fd->stats), &iter, - CHECKBOX_COLUMN_SELECTED, - (B_FS_DEFAULT & (1u << i)) ? true : false, -1); -} - -static char * -generate_syntax (const struct frequencies_dialog *fd) -{ - GtkTreeIter iter; - gboolean ok; - gint i; - guint selected = 0; - - gchar *text; - GString *string = g_string_new ("FREQUENCIES"); - - g_string_append (string, "\n\t/VARIABLES="); - psppire_var_view_append_names (PSPPIRE_VAR_VIEW (fd->stat_vars), 0, string); - - g_string_append (string, "\n\t/FORMAT="); - - switch (fd->tables_opts.order) - { - case FRQ_AVALUE: - g_string_append (string, "AVALUE"); - break; - case FRQ_DVALUE: - g_string_append (string, "DVALUE"); - break; - case FRQ_ACOUNT: - g_string_append (string, "AFREQ"); - break; - case FRQ_DCOUNT: - g_string_append (string, "DFREQ"); - break; - default: - g_assert_not_reached(); - } - - g_string_append (string, " "); - - switch (fd->tables_opts.table) - { - case FRQ_TABLE: - g_string_append (string, "TABLE"); - break; - case FRQ_NOTABLE: - g_string_append (string, "NOTABLE"); - break; - case FRQ_LIMIT: - g_string_append_printf (string, "LIMIT (%d)", fd->tables_opts.limit); - break; - } - - - for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; - i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) - { - gboolean toggled; - gtk_tree_model_get (fd->stats, &iter, - CHECKBOX_COLUMN_SELECTED, &toggled, -1); - if (toggled) - selected |= 1u << i; - } - - if (selected != B_FS_DEFAULT) - { - g_string_append (string, "\n\t/STATISTICS="); - if (selected == B_FS_ALL) - g_string_append (string, "ALL"); - else if (selected == 0) - g_string_append (string, "NONE"); - else - { - int n = 0; - if ((selected & B_FS_DEFAULT) == B_FS_DEFAULT) - { - g_string_append (string, "DEFAULT"); - selected &= ~B_FS_DEFAULT; - n++; - } - for (i = 0; i < N_FREQUENCY_STATS; i++) - if (selected & (1u << i)) - { - if (n++) - g_string_append (string, " "); - g_string_append (string, stats[i].name); - } - } - } - - if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->include_missing))) - g_string_append (string, "\n\t/MISSING=INCLUDE"); - - if (fd->charts_opts.draw_hist) - { - g_string_append (string, "\n\t/HISTOGRAM="); - g_string_append (string, - fd->charts_opts.draw_normal ? "NORMAL" : "NONORMAL"); - - if (fd->charts_opts.scale == FRQ_PERCENT) - g_string_append (string, " PERCENT"); - - if (fd->charts_opts.use_min) - g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts.min); - if (fd->charts_opts.use_max) - g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts.max); - } - - if (fd->charts_opts.draw_pie) - { - g_string_append (string, "\n\t/PIECHART="); - - if (fd->charts_opts.pie_include_missing) - g_string_append (string, " MISSING"); - - if (fd->charts_opts.use_min) - g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts.min); - if (fd->charts_opts.use_max) - g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts.max); - } - - g_string_append (string, ".\n"); - - text = string->str; - - g_string_free (string, FALSE); - - return text; -} - -/* Dialog is valid iff at least one variable has been selected */ -static gboolean -dialog_state_valid (gpointer data) -{ - struct frequencies_dialog *fd = data; - - GtkTreeModel *vars = gtk_tree_view_get_model (fd->stat_vars); - - GtkTreeIter notused; - - return gtk_tree_model_get_iter_first (vars, ¬used); -} - - -static void -on_tables_clicked (struct frequencies_dialog *fd) -{ - int ret; - - switch (fd->tables_opts.order) - { - case FRQ_AVALUE: - gtk_toggle_button_set_active (fd->avalue, TRUE); - break; - case FRQ_DVALUE: - gtk_toggle_button_set_active (fd->dvalue, TRUE); - break; - case FRQ_ACOUNT: - gtk_toggle_button_set_active (fd->afreq, TRUE); - break; - case FRQ_DCOUNT: - gtk_toggle_button_set_active (fd->dfreq, TRUE); - break; - }; - - switch (fd->tables_opts.table) - { - case FRQ_TABLE: - gtk_toggle_button_set_active (fd->always, TRUE); - break; - case FRQ_NOTABLE: - gtk_toggle_button_set_active (fd->never, TRUE); - break; - case FRQ_LIMIT: - gtk_toggle_button_set_active (fd->limit, TRUE); - break; - } - gtk_spin_button_set_value (fd->limit_spinbutton, - fd->tables_opts.limit); - g_signal_emit_by_name (fd->limit, "toggled"); - - ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->tables_dialog)); - - if ( ret == PSPPIRE_RESPONSE_CONTINUE ) - { - if (gtk_toggle_button_get_active (fd->avalue)) - fd->tables_opts.order = FRQ_AVALUE; - else if (gtk_toggle_button_get_active (fd->dvalue)) - fd->tables_opts.order = FRQ_DVALUE; - else if (gtk_toggle_button_get_active (fd->afreq)) - fd->tables_opts.order = FRQ_ACOUNT; - else if (gtk_toggle_button_get_active (fd->dfreq)) - fd->tables_opts.order = FRQ_DCOUNT; - - if (gtk_toggle_button_get_active (fd->always)) - fd->tables_opts.table = FRQ_TABLE; - else if (gtk_toggle_button_get_active (fd->never)) - fd->tables_opts.table = FRQ_NOTABLE; - else - fd->tables_opts.table = FRQ_LIMIT; - - fd->tables_opts.limit = gtk_spin_button_get_value (fd->limit_spinbutton); - } -} - -static void -on_charts_clicked (struct frequencies_dialog *fd) -{ - int ret; - - gtk_toggle_button_set_active (fd->min, fd->charts_opts.use_min); - gtk_spin_button_set_value (fd->min_spin, fd->charts_opts.min); - g_signal_emit_by_name (fd->min, "toggled"); - - gtk_toggle_button_set_active (fd->max, fd->charts_opts.use_max); - gtk_spin_button_set_value (fd->max_spin, fd->charts_opts.max); - g_signal_emit_by_name (fd->max, "toggled"); - - gtk_toggle_button_set_active (fd->hist, fd->charts_opts.draw_hist); - gtk_toggle_button_set_active (fd->normal, fd->charts_opts.draw_normal); - g_signal_emit_by_name (fd->hist, "toggled"); - - switch (fd->charts_opts.scale) - { - case FRQ_FREQ: - gtk_toggle_button_set_active (fd->freqs, TRUE); - break; - case FRQ_DVALUE: - gtk_toggle_button_set_active (fd->percents, TRUE); - break; - }; - - - gtk_toggle_button_set_active (fd->pie, fd->charts_opts.draw_pie); - gtk_toggle_button_set_active (fd->pie_include_missing, - fd->charts_opts.pie_include_missing); - g_signal_emit_by_name (fd->pie, "toggled"); - - ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->charts_dialog)); - - if ( ret == PSPPIRE_RESPONSE_CONTINUE ) - { - fd->charts_opts.use_min = gtk_toggle_button_get_active (fd->min); - fd->charts_opts.min = gtk_spin_button_get_value (fd->min_spin); - - fd->charts_opts.use_max = gtk_toggle_button_get_active (fd->max); - fd->charts_opts.max = gtk_spin_button_get_value (fd->max_spin); - - fd->charts_opts.draw_hist = gtk_toggle_button_get_active (fd->hist); - fd->charts_opts.draw_normal = gtk_toggle_button_get_active (fd->normal); - if (gtk_toggle_button_get_active (fd->freqs)) - fd->charts_opts.scale = FRQ_FREQ; - else if (gtk_toggle_button_get_active (fd->percents)) - fd->charts_opts.scale = FRQ_PERCENT; - - fd->charts_opts.draw_pie = gtk_toggle_button_get_active (fd->pie); - fd->charts_opts.pie_include_missing - = gtk_toggle_button_get_active (fd->pie_include_missing); - } -} - - -/* Makes widget W's sensitivity follow the active state of TOGGLE */ -static void -sensitive_if_active (GtkToggleButton *toggle, GtkWidget *w) -{ - gboolean active = gtk_toggle_button_get_active (toggle); - - gtk_widget_set_sensitive (w, active); -} - -/* Pops up the Frequencies dialog box */ -void -frequencies_dialog (PsppireDataWindow *de) -{ - gint response; - - struct frequencies_dialog fd; - - GtkBuilder *xml = builder_new ("frequencies.ui"); - - GtkWidget *dialog = get_widget_assert (xml, "frequencies-dialog"); - GtkWidget *source = get_widget_assert (xml, "dict-treeview"); - GtkWidget *dest = get_widget_assert (xml, "var-treeview"); - GtkWidget *tables_button = get_widget_assert (xml, "tables-button"); - GtkWidget *charts_button = get_widget_assert (xml, "charts-button"); - GtkWidget *stats_treeview = get_widget_assert (xml, "stats-treeview"); - - put_checkbox_items_in_treeview (GTK_TREE_VIEW(stats_treeview), - B_FS_DEFAULT, - N_FREQUENCY_STATS, - stats - ); - - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de)); - - g_object_get (de->data_editor, "dictionary", &fd.dict, NULL); - g_object_set (source, "model", fd.dict, NULL); - - fd.stat_vars = GTK_TREE_VIEW (dest); - fd.tables_button = get_widget_assert (xml, "tables-button"); - fd.charts_button = get_widget_assert (xml, "charts-button"); - - fd.include_missing = GTK_TOGGLE_BUTTON ( - get_widget_assert (xml, "include_missing")); - - fd.stats = gtk_tree_view_get_model (GTK_TREE_VIEW (stats_treeview)); - - /* Frequency Tables dialog. */ - fd.tables_dialog = get_widget_assert (xml, "tables-dialog"); - fd.tables_opts.order = FRQ_AVALUE; - fd.tables_opts.table = FRQ_TABLE; - fd.tables_opts.limit = 50; - - fd.always = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "always")); - fd.never = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "never")); - fd.limit = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "limit")); - fd.limit_spinbutton = - GTK_SPIN_BUTTON (get_widget_assert (xml, "limit-spin")); - g_signal_connect (fd.limit, "toggled", - G_CALLBACK (sensitive_if_active), fd.limit_spinbutton); - - fd.avalue = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "avalue")); - fd.dvalue = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "dvalue")); - fd.afreq = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "afreq")); - fd.dfreq = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "dfreq")); - - gtk_window_set_transient_for (GTK_WINDOW (fd.tables_dialog), - GTK_WINDOW (de)); - - /* Charts dialog. */ - fd.charts_dialog = get_widget_assert (xml, "charts-dialog"); - fd.charts_opts.use_min = false; - fd.charts_opts.min = 0; - fd.charts_opts.use_max = false; - fd.charts_opts.max = 100; - fd.charts_opts.draw_hist = false; - fd.charts_opts.draw_normal = false; - fd.charts_opts.scale = FRQ_FREQ; - fd.charts_opts.draw_pie = false; - fd.charts_opts.pie_include_missing = false; - - fd.freqs = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "freqs")); - fd.percents = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "percents")); - - fd.min = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "min")); - fd.min_spin = GTK_SPIN_BUTTON (get_widget_assert (xml, "min-spin")); - g_signal_connect (fd.min, "toggled", - G_CALLBACK (sensitive_if_active), fd.min_spin); - fd.max = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "max")); - fd.max_spin = GTK_SPIN_BUTTON (get_widget_assert (xml, "max-spin")); - g_signal_connect (fd.max, "toggled", - G_CALLBACK (sensitive_if_active), fd.max_spin); - - fd.hist = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "hist")); - fd.normal = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "normal")); - g_signal_connect (fd.hist, "toggled", - G_CALLBACK (sensitive_if_active), fd.normal); - - fd.pie = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "pie")); - fd.pie_include_missing = GTK_TOGGLE_BUTTON ( - get_widget_assert (xml, "pie-include-missing")); - g_signal_connect (fd.pie, "toggled", - G_CALLBACK (sensitive_if_active), fd.pie_include_missing); - - gtk_window_set_transient_for (GTK_WINDOW (fd.charts_dialog), - GTK_WINDOW (de)); - - /* Main dialog. */ - g_signal_connect (dialog, "refresh", G_CALLBACK (refresh), &fd); - - psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), - dialog_state_valid, &fd); - - g_signal_connect_swapped (tables_button, "clicked", - G_CALLBACK (on_tables_clicked), &fd); - g_signal_connect_swapped (charts_button, "clicked", - G_CALLBACK (on_charts_clicked), &fd); - - response = psppire_dialog_run (PSPPIRE_DIALOG (dialog)); - - - switch (response) - { - case GTK_RESPONSE_OK: - g_free (execute_syntax_string (de, generate_syntax (&fd))); - break; - case PSPPIRE_RESPONSE_PASTE: - g_free (paste_syntax_to_window (generate_syntax (&fd))); - break; - default: - break; - } - - g_object_unref (xml); -} diff --git a/src/ui/gui/frequencies-dialog.h b/src/ui/gui/frequencies-dialog.h deleted file mode 100644 index 5632ab5e77..0000000000 --- a/src/ui/gui/frequencies-dialog.h +++ /dev/null @@ -1,24 +0,0 @@ -/* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2010 Free Software Foundation - - 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 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef __FREQUENCIES_DIALOG_H -#define __FREQUENCIES_DIALOG_H - -#include "psppire-data-window.h" - -void frequencies_dialog (PsppireDataWindow * data); - -#endif diff --git a/src/ui/gui/psppire-data-window.c b/src/ui/gui/psppire-data-window.c index ad967b3256..73c98b383e 100644 --- a/src/ui/gui/psppire-data-window.c +++ b/src/ui/gui/psppire-data-window.c @@ -26,16 +26,13 @@ #include "libpspp/str.h" #include "ui/gui/aggregate-dialog.h" #include "ui/gui/autorecode-dialog.h" -#include "ui/gui/binomial-dialog.h" #include "ui/gui/builder-wrapper.h" #include "ui/gui/chi-square-dialog.h" #include "ui/gui/comments-dialog.h" #include "ui/gui/compute-dialog.h" #include "ui/gui/count-dialog.h" -#include "ui/gui/crosstabs-dialog.h" #include "ui/gui/entry-dialog.h" #include "ui/gui/executor.h" -#include "ui/gui/frequencies-dialog.h" #include "ui/gui/help-menu.h" #include "ui/gui/helper.h" #include "ui/gui/helper.h" @@ -829,12 +826,24 @@ connect_action (PsppireDataWindow *dw, const char *action_name, GCallback handler) { GtkAction *action = get_action_assert (dw->builder, action_name); - + g_signal_connect_swapped (action, "activate", handler, dw); return action; } +/* Only a data file with at least one variable can be saved. */ +static void +enable_save (PsppireDataWindow *dw) +{ + gboolean enable = psppire_dict_get_var_cnt (dw->dict) > 0; + + gtk_action_set_sensitive (get_action_assert (dw->builder, "file_save"), + enable); + gtk_action_set_sensitive (get_action_assert (dw->builder, "file_save_as"), + enable); +} + /* Initializes as much of a PsppireDataWindow as we can and must before the dataset has been set. @@ -921,6 +930,13 @@ psppire_data_window_finish_init (PsppireDataWindow *de, G_CALLBACK (on_split_change), de); + g_signal_connect_swapped (de->dict, "backend-changed", + G_CALLBACK (enable_save), de); + g_signal_connect_swapped (de->dict, "variable-inserted", + G_CALLBACK (enable_save), de); + g_signal_connect_swapped (de->dict, "variable-deleted", + G_CALLBACK (enable_save), de); + enable_save (de); connect_action (de, "file_new_data", G_CALLBACK (create_data_window)); @@ -954,11 +970,8 @@ psppire_data_window_finish_init (PsppireDataWindow *de, connect_action (de, "transform_count", G_CALLBACK (count_dialog)); connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog)); connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog)); - connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog)); - connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog)); connect_action (de, "univariate", G_CALLBACK (univariate_dialog)); connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog)); - connect_action (de, "binomial", G_CALLBACK (binomial_dialog)); connect_action (de, "runs", G_CALLBACK (runs_dialog)); connect_action (de, "ks-one-sample", G_CALLBACK (ks_one_sample_dialog)); connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog)); diff --git a/src/ui/gui/psppire-dialog-action-binomial.c b/src/ui/gui/psppire-dialog-action-binomial.c new file mode 100644 index 0000000000..97a5f3cfcc --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-binomial.c @@ -0,0 +1,179 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2012 Free Software Foundation + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +#include "psppire-dialog-action-binomial.h" +#include "psppire-value-entry.h" + +#include "dialog-common.h" +#include "helper.h" +#include +#include "psppire-var-view.h" + +#include "psppire-dialog.h" +#include "builder-wrapper.h" +#include "checkbox-treeview.h" +#include "psppire-dict.h" +#include "libpspp/str.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + + +static void +psppire_dialog_action_binomial_class_init (PsppireDialogActionBinomialClass *class); + +G_DEFINE_TYPE (PsppireDialogActionBinomial, psppire_dialog_action_binomial, PSPPIRE_TYPE_DIALOG_ACTION); + + +static gboolean +get_proportion (PsppireDialogActionBinomial *act, double *prop) +{ + const gchar *text = gtk_entry_get_text (GTK_ENTRY (act->prop_entry)); + gchar *endptr = NULL; + *prop = g_strtod (text, &endptr); + + if (endptr == text) + return FALSE; + + return TRUE; +} + +static gboolean +dialog_state_valid (gpointer data) +{ + PsppireDialogActionBinomial *act = PSPPIRE_DIALOG_ACTION_BINOMIAL (data); + double prop; + + GtkTreeModel *vars = + gtk_tree_view_get_model (GTK_TREE_VIEW (act->var_view)); + + GtkTreeIter notused; + + if ( !gtk_tree_model_get_iter_first (vars, ¬used) ) + return FALSE; + + if ( ! get_proportion (act, &prop)) + return FALSE; + + if (prop < 0 || prop > 1.0) + return FALSE; + + return TRUE; +} + +static void +refresh (PsppireDialogAction *da) +{ + PsppireDialogActionBinomial *act = PSPPIRE_DIALOG_ACTION_BINOMIAL (da); + GtkTreeModel *liststore = + gtk_tree_view_get_model (GTK_TREE_VIEW (act->var_view)); + + gtk_list_store_clear (GTK_LIST_STORE (liststore)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (act->button1), TRUE); + + gtk_entry_set_text (GTK_ENTRY (act->prop_entry), "0.5"); + + gtk_entry_set_text (GTK_ENTRY (act->cutpoint_entry), ""); +} + + +static void +psppire_dialog_action_binomial_activate (GtkAction *a) +{ + PsppireDialogActionBinomial *act = PSPPIRE_DIALOG_ACTION_BINOMIAL (a); + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a); + + GtkBuilder *xml = builder_new ("binomial.ui"); + + pda->dialog = get_widget_assert (xml, "binomial-dialog"); + pda->source = get_widget_assert (xml, "dict-view"); + + act->var_view = get_widget_assert (xml, "variables-treeview"); + act->button1 = get_widget_assert (xml, "radiobutton3"); + act->prop_entry = get_widget_assert (xml, "proportion-entry"); + + act->cutpoint_entry = get_widget_assert (xml, "cutpoint-entry"); + act->cutpoint_button = get_widget_assert (xml, "radiobutton4"); + + g_object_unref (xml); + + + g_signal_connect (act->cutpoint_button, "toggled", G_CALLBACK (set_sensitivity_from_toggle), + act->cutpoint_entry); + + psppire_dialog_action_set_refresh (pda, refresh); + + psppire_dialog_action_set_valid_predicate (pda, + dialog_state_valid); + + if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_binomial_parent_class)->activate) + PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_binomial_parent_class)->activate (pda); +} + + + +static char * +generate_syntax (PsppireDialogAction *a) +{ + PsppireDialogActionBinomial *scd = PSPPIRE_DIALOG_ACTION_BINOMIAL (a); + gchar *text = NULL; + + double prop; + GString *string = g_string_new ("NPAR TEST\n\t/BINOMIAL"); + + if ( get_proportion (scd, &prop)) + g_string_append_printf (string, "(%g)", prop); + + g_string_append (string, " ="); + + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (scd->var_view), 0, string); + + if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scd->cutpoint_button))) + { + const gchar *cutpoint = gtk_entry_get_text (GTK_ENTRY (scd->cutpoint_entry)); + g_string_append_printf (string, "(%s)", cutpoint); + } + + g_string_append (string, ".\n"); + + text = string->str; + + g_string_free (string, FALSE); + + return text; +} + +static void +psppire_dialog_action_binomial_class_init (PsppireDialogActionBinomialClass *class) +{ + GtkActionClass *action_class = GTK_ACTION_CLASS (class); + + action_class->activate = psppire_dialog_action_binomial_activate; + + PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax; +} + + +static void +psppire_dialog_action_binomial_init (PsppireDialogActionBinomial *act) +{ +} + diff --git a/src/ui/gui/psppire-dialog-action-binomial.h b/src/ui/gui/psppire-dialog-action-binomial.h new file mode 100644 index 0000000000..0541a402dd --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-binomial.h @@ -0,0 +1,83 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2012 Free Software Foundation + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include +#include + +#include "psppire-dialog-action.h" + +#ifndef __PSPPIRE_DIALOG_ACTION_BINOMIAL_H__ +#define __PSPPIRE_DIALOG_ACTION_BINOMIAL_H__ + +G_BEGIN_DECLS + + +#define PSPPIRE_TYPE_DIALOG_ACTION_BINOMIAL (psppire_dialog_action_binomial_get_type ()) + +#define PSPPIRE_DIALOG_ACTION_BINOMIAL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_BINOMIAL, PsppireDialogActionBinomial)) + +#define PSPPIRE_DIALOG_ACTION_BINOMIAL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + PSPPIRE_TYPE_DIALOG_ACTION_BINOMIAL, \ + PsppireDialogActionBinomialClass)) + + +#define PSPPIRE_IS_DIALOG_ACTION_BINOMIAL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_BINOMIAL)) + +#define PSPPIRE_IS_DIALOG_ACTION_BINOMIAL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_BINOMIAL)) + + +#define PSPPIRE_DIALOG_ACTION_BINOMIAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_BINOMIAL, \ + PsppireDialogActionBinomialClass)) + +typedef struct _PsppireDialogActionBinomial PsppireDialogActionBinomial; +typedef struct _PsppireDialogActionBinomialClass PsppireDialogActionBinomialClass; + + +struct _PsppireDialogActionBinomial +{ + PsppireDialogAction parent; + + /*< private >*/ + gboolean dispose_has_run ; + + + GtkWidget *var_view; + GtkWidget *button1; + GtkWidget *prop_entry; + + GtkWidget *cutpoint_entry; + GtkWidget *cutpoint_button; +}; + + +struct _PsppireDialogActionBinomialClass +{ + PsppireDialogActionClass parent_class; +}; + + +GType psppire_dialog_action_binomial_get_type (void) ; + +G_END_DECLS + +#endif /* __PSPPIRE_DIALOG_ACTION_BINOMIAL_H__ */ diff --git a/src/ui/gui/psppire-dialog-action-crosstabs.c b/src/ui/gui/psppire-dialog-action-crosstabs.c new file mode 100644 index 0000000000..2bc07c6e4c --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-crosstabs.c @@ -0,0 +1,395 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2012 Free Software Foundation + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +#include "psppire-dialog-action-crosstabs.h" +#include "psppire-value-entry.h" + +#include "dialog-common.h" +#include "helper.h" +#include +#include "psppire-var-view.h" + +#include "psppire-dialog.h" +#include "builder-wrapper.h" +#include "checkbox-treeview.h" +#include "psppire-dict.h" +#include "libpspp/str.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + + +static void +psppire_dialog_action_crosstabs_class_init (PsppireDialogActionCrosstabsClass *class); + +G_DEFINE_TYPE (PsppireDialogActionCrosstabs, psppire_dialog_action_crosstabs, PSPPIRE_TYPE_DIALOG_ACTION); + +static gboolean +dialog_state_valid (gpointer data) +{ + PsppireDialogActionCrosstabs *cd = PSPPIRE_DIALOG_ACTION_CROSSTABS (data); + + GtkTreeModel *row_vars = gtk_tree_view_get_model (GTK_TREE_VIEW (cd->dest_rows)); + GtkTreeModel *col_vars = gtk_tree_view_get_model (GTK_TREE_VIEW (cd->dest_cols)); + + GtkTreeIter notused; + + return (gtk_tree_model_get_iter_first (row_vars, ¬used) + && gtk_tree_model_get_iter_first (col_vars, ¬used)); +} + +static void +refresh (PsppireDialogAction *rd_) +{ + PsppireDialogActionCrosstabs *cd = PSPPIRE_DIALOG_ACTION_CROSSTABS (rd_); + + GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (cd->dest_rows)); + gtk_list_store_clear (GTK_LIST_STORE (liststore)); + + liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (cd->dest_cols)); + gtk_list_store_clear (GTK_LIST_STORE (liststore)); +} + +#define CROSSTABS_STATS \ + CS (CHISQ, N_("Chisq")) \ + CS (PHI, N_("Phi")) \ + CS (CC, N_("CC")) \ + CS (LAMBDA, N_("Lambda")) \ + CS (UC, N_("UC")) \ + CS (BTAU, N_("BTau")) \ + CS (CTAU, N_("CTau")) \ + CS (RISK, N_("Risk")) \ + CS (GAMMA, N_("Gamma")) \ + CS (D, N_("D")) \ + CS (KAPPA, N_("Kappa")) \ + CS (ETA, N_("Eta")) \ + CS (CORR, N_("Corr")) \ + CS (STATS_NONE, N_("None")) + + +#define CROSSTABS_CELLS \ + CS (COUNT, N_("Count")) \ + CS (ROW, N_("Row")) \ + CS (COLUMN, N_("Column")) \ + CS (TOTAL, N_("Total")) \ + CS (EXPECTED, N_("Expected")) \ + CS (RESIDUAL, N_("Residual")) \ + CS (SRESIDUAL, N_("Std. Residual")) \ + CS (ASRESIDUAL, N_("Adjusted Std. Residual")) \ + CS (CELLS_NONE, N_("None")) + +enum + { +#define CS(NAME, LABEL) CS_##NAME, + CROSSTABS_STATS +#undef CS + N_CROSSTABS_STATS + }; + +enum + { +#define CS(NAME, LABEL) CS_##NAME, + CROSSTABS_CELLS +#undef CS + N_CROSSTABS_CELLS + }; + +enum + { +#define CS(NAME, LABEL) B_CS_##NAME = 1u << CS_##NAME, + CROSSTABS_STATS + CROSSTABS_CELLS +#undef CS + B_CS_STATS_ALL = (1u << N_CROSSTABS_STATS) - 1, + B_CS_CELLS_ALL = (1u << N_CROSSTABS_CELLS) - 1, + B_CS_STATS_DEFAULT = B_CS_CHISQ, + B_CS_CELL_DEFAULT = B_CS_COUNT | B_CS_ROW | B_CS_COLUMN | B_CS_TOTAL, + B_CS_NONE + }; + +static const struct checkbox_entry_item stats[] = + { +#define CS(NAME, LABEL) {#NAME, LABEL}, + CROSSTABS_STATS \ + CS(NONE, N_("None")) +#undef CS + }; + +static const struct checkbox_entry_item cells[] = + { +#define CS(NAME, LABEL) {#NAME, LABEL}, + CROSSTABS_CELLS \ + CS(NONE, N_("None")) +#undef CS + }; + +static void +on_format_clicked (PsppireDialogActionCrosstabs *cd) +{ + int ret; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cd->avalue_button), cd->format_options_avalue); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cd->table_button), cd->format_options_table); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cd->pivot_button), cd->format_options_pivot); + + ret = psppire_dialog_run (PSPPIRE_DIALOG (cd->format_dialog)); + + if ( ret == PSPPIRE_RESPONSE_CONTINUE ) + { + cd->format_options_avalue = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cd->avalue_button)); + + cd->format_options_table = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cd->table_button)); + + cd->format_options_pivot = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cd->pivot_button)); + } +} + +static void +on_cell_clicked (PsppireDialogActionCrosstabs *cd) +{ + GtkListStore *liststore = clone_list_store (GTK_LIST_STORE (cd->cell)); + + gint ret = psppire_dialog_run (PSPPIRE_DIALOG (cd->cell_dialog)); + + if ( ret == PSPPIRE_RESPONSE_CONTINUE ) + { + g_object_unref (liststore); + } + else + { + gtk_tree_view_set_model (GTK_TREE_VIEW (cd->cell_view) , GTK_TREE_MODEL (liststore)); + cd->cell = GTK_TREE_MODEL (liststore); + } +} + + +static void +on_statistics_clicked (PsppireDialogActionCrosstabs *cd) +{ + GtkListStore *liststore = clone_list_store (GTK_LIST_STORE (cd->stat)); + + gint ret = psppire_dialog_run (PSPPIRE_DIALOG (cd->stat_dialog)); + + if ( ret == PSPPIRE_RESPONSE_CONTINUE ) + { + g_object_unref (liststore); + } + else + { + gtk_tree_view_set_model (GTK_TREE_VIEW (cd->stat_view) , GTK_TREE_MODEL (liststore)); + cd->stat = GTK_TREE_MODEL (liststore); + } +} + + +static void +psppire_dialog_action_crosstabs_activate (GtkAction *a) +{ + PsppireDialogActionCrosstabs *act = PSPPIRE_DIALOG_ACTION_CROSSTABS (a); + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a); + + GtkBuilder *xml = builder_new ("crosstabs.ui"); + + pda->dialog = get_widget_assert (xml, "crosstabs-dialog"); + pda->source = get_widget_assert (xml, "dict-treeview"); + + act->dest_rows = get_widget_assert (xml, "rows"); + act->dest_cols = get_widget_assert (xml, "cols"); + act->format_button = get_widget_assert (xml, "format-button"); + act->stat_button = get_widget_assert (xml, "stats-button"); + act->cell_button = get_widget_assert (xml, "cell-button"); + act->stat_view = get_widget_assert (xml, "stats-view"); + act->cell_view = get_widget_assert (xml, "cell-view"); + act->cell_dialog = get_widget_assert (xml, "cell-dialog"); + act->stat_dialog = get_widget_assert (xml, "stat-dialog"); + act->format_dialog = get_widget_assert (xml, "format-dialog"); + + act->avalue_button = get_widget_assert (xml, "ascending"); + act->table_button = get_widget_assert (xml, "print-tables"); + act->pivot_button = get_widget_assert (xml, "pivot"); + + + g_object_unref (xml); + + act->format_options_avalue = TRUE; + act->format_options_table = TRUE; + act->format_options_pivot = TRUE; + + put_checkbox_items_in_treeview (GTK_TREE_VIEW (act->cell_view), + B_CS_CELL_DEFAULT, + N_CROSSTABS_CELLS, + cells + ); + + act->cell = gtk_tree_view_get_model (GTK_TREE_VIEW (act->cell_view)); + + put_checkbox_items_in_treeview (GTK_TREE_VIEW (act->stat_view), + B_CS_STATS_DEFAULT, + N_CROSSTABS_STATS, + stats + ); + + act->stat = gtk_tree_view_get_model (GTK_TREE_VIEW (act->stat_view)); + + psppire_dialog_action_set_refresh (pda, refresh); + + psppire_dialog_action_set_valid_predicate (pda, + dialog_state_valid); + + g_signal_connect_swapped (act->cell_button, "clicked", + G_CALLBACK (on_cell_clicked), act); + + g_signal_connect_swapped (act->stat_button, "clicked", + G_CALLBACK (on_statistics_clicked), act); + + g_signal_connect_swapped (act->format_button, "clicked", + G_CALLBACK (on_format_clicked), act); + + + if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_crosstabs_parent_class)->activate) + PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_crosstabs_parent_class)->activate (pda); +} + + + +static char * +generate_syntax (PsppireDialogAction *a) +{ + PsppireDialogActionCrosstabs *cd = PSPPIRE_DIALOG_ACTION_CROSSTABS (a); + gchar *text = NULL; + int i, n; + guint selected; + GString *string = g_string_new ("CROSSTABS "); + gboolean ok; + GtkTreeIter iter; + + g_string_append (string, "\n\t/TABLES="); + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (cd->dest_rows), 0, string); + g_string_append (string, "\tBY\t"); + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (cd->dest_cols), 0, string); + + + g_string_append (string, "\n\t/FORMAT="); + + if (cd->format_options_avalue) + g_string_append (string, "AVALUE"); + else + g_string_append (string, "DVALUE"); + g_string_append (string, " "); + + if (cd->format_options_table) + g_string_append (string, "TABLES"); + else + g_string_append (string, "NOTABLES"); + g_string_append (string, " "); + + if (cd->format_options_pivot) + g_string_append (string, "PIVOT"); + else + g_string_append (string, "NOPIVOT"); + + + selected = 0; + for (i = 0, ok = gtk_tree_model_get_iter_first (cd->stat, &iter); ok; + i++, ok = gtk_tree_model_iter_next (cd->stat, &iter)) + { + gboolean toggled; + gtk_tree_model_get (cd->stat, &iter, + CHECKBOX_COLUMN_SELECTED, &toggled, -1); + if (toggled) + selected |= 1u << i; + else + selected &= ~(1u << i); + } + + if (!(selected & (1u << CS_STATS_NONE))) + { + if (selected) + { + g_string_append (string, "\n\t/STATISTICS="); + n = 0; + for (i = 0; i < N_CROSSTABS_STATS; i++) + if (selected & (1u << i)) + { + if (n++) + g_string_append (string, " "); + g_string_append (string, stats[i].name); + } + } + } + + selected = 0; + for (i = 0, ok = gtk_tree_model_get_iter_first (cd->cell, &iter); ok; + i++, ok = gtk_tree_model_iter_next (cd->cell, &iter)) + { + gboolean toggled; + gtk_tree_model_get (cd->cell, &iter, + CHECKBOX_COLUMN_SELECTED, &toggled, -1); + if (toggled) + selected |= 1u << i; + else + selected &= ~(1u << i); + } + + + + g_string_append (string, "\n\t/CELLS="); + if (selected & (1u << CS_CELLS_NONE)) + g_string_append (string, "NONE"); + else + { + n = 0; + for (i = 0; i < N_CROSSTABS_CELLS; i++) + if (selected & (1u << i)) + { + if (n++) + g_string_append (string, " "); + g_string_append (string, cells[i].name); + } + } + + g_string_append (string, ".\n"); + + text = string->str; + + g_string_free (string, FALSE); + + return text; +} + +static void +psppire_dialog_action_crosstabs_class_init (PsppireDialogActionCrosstabsClass *class) +{ + GtkActionClass *action_class = GTK_ACTION_CLASS (class); + + action_class->activate = psppire_dialog_action_crosstabs_activate; + + PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax; +} + + +static void +psppire_dialog_action_crosstabs_init (PsppireDialogActionCrosstabs *act) +{ +} + diff --git a/src/ui/gui/psppire-dialog-action-crosstabs.h b/src/ui/gui/psppire-dialog-action-crosstabs.h new file mode 100644 index 0000000000..ee8169aece --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-crosstabs.h @@ -0,0 +1,102 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2012 Free Software Foundation + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include +#include + +#include "psppire-dialog-action.h" + +#ifndef __PSPPIRE_DIALOG_ACTION_CROSSTABS_H__ +#define __PSPPIRE_DIALOG_ACTION_CROSSTABS_H__ + +G_BEGIN_DECLS + + +#define PSPPIRE_TYPE_DIALOG_ACTION_CROSSTABS (psppire_dialog_action_crosstabs_get_type ()) + +#define PSPPIRE_DIALOG_ACTION_CROSSTABS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_CROSSTABS, PsppireDialogActionCrosstabs)) + +#define PSPPIRE_DIALOG_ACTION_CROSSTABS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + PSPPIRE_TYPE_DIALOG_ACTION_CROSSTABS, \ + PsppireDialogActionCrosstabsClass)) + + +#define PSPPIRE_IS_DIALOG_ACTION_CROSSTABS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_CROSSTABS)) + +#define PSPPIRE_IS_DIALOG_ACTION_CROSSTABS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_CROSSTABS)) + + +#define PSPPIRE_DIALOG_ACTION_CROSSTABS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_CROSSTABS, \ + PsppireDialogActionCrosstabsClass)) + +typedef struct _PsppireDialogActionCrosstabs PsppireDialogActionCrosstabs; +typedef struct _PsppireDialogActionCrosstabsClass PsppireDialogActionCrosstabsClass; + + +struct _PsppireDialogActionCrosstabs +{ + PsppireDialogAction parent; + + /*< private >*/ + gboolean dispose_has_run ; + + GtkWidget *col_vars; + GtkWidget *row_vars; + + GtkWidget *dest_rows; + GtkWidget *dest_cols ; + GtkWidget *format_button ; + GtkWidget *stat_button ; + GtkWidget *cell_button ; + + GtkWidget *stat_view ; + + GtkWidget *cell_view ; + GtkTreeModel *cell ; + GtkWidget *cell_dialog ; + GtkTreeModel *stat; + GtkWidget *stat_dialog ; + + gboolean format_options_avalue; + gboolean format_options_pivot; + gboolean format_options_table; + + GtkWidget *table_button; + GtkWidget *pivot_button; + + GtkWidget *format_dialog; + GtkWidget *avalue_button; +}; + + +struct _PsppireDialogActionCrosstabsClass +{ + PsppireDialogActionClass parent_class; +}; + + +GType psppire_dialog_action_crosstabs_get_type (void) ; + +G_END_DECLS + +#endif /* __PSPPIRE_DIALOG_ACTION_CROSSTABS_H__ */ diff --git a/src/ui/gui/psppire-dialog-action-frequencies.c b/src/ui/gui/psppire-dialog-action-frequencies.c new file mode 100644 index 0000000000..b2ddd196a3 --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-frequencies.c @@ -0,0 +1,486 @@ +/* PSPPIRE - a graphical user interface for PSPP. +Copyright (C) 2012 Free Software Foundation + +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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include + +#include "psppire-dialog-action-frequencies.h" +#include "psppire-value-entry.h" + +#include "dialog-common.h" +#include "helper.h" +#include +#include "psppire-var-view.h" + +#include "psppire-dialog.h" +#include "builder-wrapper.h" +#include "checkbox-treeview.h" +#include "psppire-dict.h" +#include "libpspp/str.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + + +#define FREQUENCY_STATS \ + FS (MEAN, N_("Mean")) \ + FS (STDDEV, N_("Standard deviation")) \ + FS (MINIMUM, N_("Minimum")) \ + FS (MAXIMUM, N_("Maximum")) \ + FS (SEMEAN, N_("Standard error of the mean")) \ + FS (VARIANCE, N_("Variance")) \ + FS (SKEWNESS, N_("Skewness")) \ + FS (SESKEW, N_("Standard error of the skewness")) \ + FS (RANGE, N_("Range")) \ + FS (MODE, N_("Mode")) \ + FS (KURTOSIS, N_("Kurtosis")) \ + FS (SEKURT, N_("Standard error of the kurtosis")) \ + FS (MEDIAN, N_("Median")) \ + FS (SUM, N_("Sum")) + + + +enum +{ +#define FS(NAME, LABEL) FS_##NAME, + FREQUENCY_STATS +#undef FS + N_FREQUENCY_STATS +}; + +enum +{ +#define FS(NAME, LABEL) B_FS_##NAME = 1u << FS_##NAME, + FREQUENCY_STATS +#undef FS + B_FS_ALL = (1u << N_FREQUENCY_STATS) - 1, + B_FS_DEFAULT = B_FS_MEAN | B_FS_STDDEV | B_FS_MINIMUM | B_FS_MAXIMUM +}; + + +static const struct checkbox_entry_item stats[] = { +#define FS(NAME, LABEL) {#NAME, LABEL}, + FREQUENCY_STATS +#undef FS +}; + + +static void +on_tables_clicked (PsppireDialogActionFrequencies * fd) +{ + int ret; + + switch (fd->tables_opts_order) + { + case FRQ_AVALUE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->avalue), TRUE); + break; + case FRQ_DVALUE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->dvalue), TRUE); + break; + case FRQ_ACOUNT: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->afreq), TRUE); + break; + case FRQ_DCOUNT: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->dfreq), TRUE); + break; + }; + + switch (fd->tables_opts_table) + { + case FRQ_TABLE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->always), TRUE); + break; + case FRQ_NOTABLE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->never), TRUE); + break; + case FRQ_LIMIT: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->limit), TRUE); + break; + } + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->limit_spinbutton), + fd->tables_opts_limit); + + g_signal_emit_by_name (fd->limit, "toggled"); + + ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->tables_dialog)); + + if (ret == PSPPIRE_RESPONSE_CONTINUE) + { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->avalue))) + fd->tables_opts_order = FRQ_AVALUE; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->dvalue))) + fd->tables_opts_order = FRQ_DVALUE; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->afreq))) + fd->tables_opts_order = FRQ_ACOUNT; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->dfreq))) + fd->tables_opts_order = FRQ_DCOUNT; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->always))) + fd->tables_opts_table = FRQ_TABLE; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->never))) + fd->tables_opts_table = FRQ_NOTABLE; + else + fd->tables_opts_table = FRQ_LIMIT; + + + fd->tables_opts_limit = + gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->limit_spinbutton)); + } +} + + +static void +on_charts_clicked (PsppireDialogActionFrequencies *fd) +{ + int ret; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->min), fd->charts_opts_use_min); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->min_spin), fd->charts_opts_min); + g_signal_emit_by_name (fd->min, "toggled"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->max), fd->charts_opts_use_max); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->max_spin), fd->charts_opts_max); + g_signal_emit_by_name (fd->max, "toggled"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->hist), fd->charts_opts_draw_hist); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->normal), fd->charts_opts_draw_normal); + g_signal_emit_by_name (fd->hist, "toggled"); + + switch (fd->charts_opts_scale) + { + case FRQ_FREQ: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->freqs), TRUE); + break; + case FRQ_DVALUE: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->percents), TRUE); + break; + }; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->pie), fd->charts_opts_draw_pie); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->pie_include_missing), + fd->charts_opts_pie_include_missing); + + g_signal_emit_by_name (fd->pie, "toggled"); + + ret = psppire_dialog_run (PSPPIRE_DIALOG (fd->charts_dialog)); + + if ( ret == PSPPIRE_RESPONSE_CONTINUE ) + { + fd->charts_opts_use_min = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->min)); + fd->charts_opts_min = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->min_spin)); + + fd->charts_opts_use_max = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->max)); + fd->charts_opts_max = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->max_spin)); + + fd->charts_opts_draw_hist = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->hist)); + fd->charts_opts_draw_normal = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->normal)); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->freqs))) + fd->charts_opts_scale = FRQ_FREQ; + else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->percents))) + fd->charts_opts_scale = FRQ_PERCENT; + + fd->charts_opts_draw_pie = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->pie)); + fd->charts_opts_pie_include_missing + = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->pie_include_missing)); + } +} + + +static void +psppire_dialog_action_frequencies_class_init +(PsppireDialogActionFrequenciesClass * class); + +G_DEFINE_TYPE (PsppireDialogActionFrequencies, + psppire_dialog_action_frequencies, PSPPIRE_TYPE_DIALOG_ACTION); + +static gboolean +dialog_state_valid (gpointer data) +{ + PsppireDialogActionFrequencies *fd = + PSPPIRE_DIALOG_ACTION_FREQUENCIES (data); + + GtkTreeModel *vars = + gtk_tree_view_get_model (GTK_TREE_VIEW (fd->stat_vars)); + + GtkTreeIter notused; + + return gtk_tree_model_get_iter_first (vars, ¬used); +} + +static void +refresh (PsppireDialogAction * fdx) +{ + PsppireDialogActionFrequencies *fd = + PSPPIRE_DIALOG_ACTION_FREQUENCIES (fdx); + + GtkTreeIter iter; + size_t i; + bool ok; + + GtkTreeModel *liststore = + gtk_tree_view_get_model (GTK_TREE_VIEW (fd->stat_vars)); + gtk_list_store_clear (GTK_LIST_STORE (liststore)); + + for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; + i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) + gtk_list_store_set (GTK_LIST_STORE (fd->stats), &iter, + CHECKBOX_COLUMN_SELECTED, + (B_FS_DEFAULT & (1u << i)) ? true : false, -1); +} + + + +static void +psppire_dialog_action_frequencies_activate (GtkAction * a) +{ + PsppireDialogActionFrequencies *act = PSPPIRE_DIALOG_ACTION_FREQUENCIES (a); + PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a); + + GtkBuilder *xml = builder_new ("frequencies.ui"); + + GtkWidget *stats_treeview = get_widget_assert (xml, "stats-treeview"); + GtkWidget *tables_button = get_widget_assert (xml, "tables-button"); + GtkWidget *charts_button = get_widget_assert (xml, "charts-button"); + + pda->dialog = get_widget_assert (xml, "frequencies-dialog"); + pda->source = get_widget_assert (xml, "dict-treeview"); + + act->stat_vars = get_widget_assert (xml, "var-treeview"); + + put_checkbox_items_in_treeview (GTK_TREE_VIEW (stats_treeview), + B_FS_DEFAULT, N_FREQUENCY_STATS, stats); + + act->stats = gtk_tree_view_get_model (GTK_TREE_VIEW (stats_treeview)); + + act->include_missing = get_widget_assert (xml, "include_missing"); + + + act->tables_dialog = get_widget_assert (xml, "tables-dialog"); + act->charts_dialog = get_widget_assert (xml, "charts-dialog"); + act->always = get_widget_assert (xml, "always"); + act->never = get_widget_assert (xml, "never"); + act->limit = get_widget_assert (xml, "limit"); + act->limit_spinbutton = get_widget_assert (xml, "limit-spin"); + + g_signal_connect (act->limit, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), + act->limit_spinbutton); + + act->avalue = get_widget_assert (xml, "avalue"); + act->dvalue = get_widget_assert (xml, "dvalue"); + act->afreq = get_widget_assert (xml, "afreq"); + act->dfreq = get_widget_assert (xml, "dfreq"); + + act->charts_opts_use_min = false; + act->charts_opts_min = 0; + act->charts_opts_use_max = false; + act->charts_opts_max = 100; + act->charts_opts_draw_hist = false; + act->charts_opts_draw_normal = false; + act->charts_opts_scale = FRQ_FREQ; + act->charts_opts_draw_pie = false; + act->charts_opts_pie_include_missing = false; + + act->freqs = get_widget_assert (xml, "freqs"); + act->percents = get_widget_assert (xml, "percents"); + + act->min = get_widget_assert (xml, "min"); + act->min_spin = get_widget_assert (xml, "min-spin"); + g_signal_connect (act->min, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), act->min_spin); + act->max = get_widget_assert (xml, "max"); + act->max_spin = get_widget_assert (xml, "max-spin"); + g_signal_connect (act->max, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), act->max_spin); + + act->hist = get_widget_assert (xml, "hist"); + act->normal = get_widget_assert (xml, "normal"); + g_signal_connect (act->hist, "toggled", + G_CALLBACK (set_sensitivity_from_toggle), act->normal); + + act->pie = (get_widget_assert (xml, "pie")); + act->pie_include_missing = get_widget_assert (xml, "pie-include-missing"); + + + g_object_unref (xml); + + + act->tables_opts_order = FRQ_AVALUE; + act->tables_opts_table = FRQ_TABLE; + act->tables_opts_limit = 50; + + g_signal_connect_swapped (tables_button, "clicked", + G_CALLBACK (on_tables_clicked), act); + + g_signal_connect_swapped (charts_button, "clicked", + G_CALLBACK (on_charts_clicked), act); + + psppire_dialog_action_set_refresh (pda, refresh); + + psppire_dialog_action_set_valid_predicate (pda, dialog_state_valid); + + if (PSPPIRE_DIALOG_ACTION_CLASS + (psppire_dialog_action_frequencies_parent_class)->activate) + PSPPIRE_DIALOG_ACTION_CLASS + (psppire_dialog_action_frequencies_parent_class)->activate (pda); +} + +static char * +generate_syntax (PsppireDialogAction * a) +{ + PsppireDialogActionFrequencies *fd = PSPPIRE_DIALOG_ACTION_FREQUENCIES (a); + gchar *text = NULL; + gint i; + gboolean ok; + GtkTreeIter iter; + guint selected = 0; + + GString *string = g_string_new ("FREQUENCIES"); + + g_string_append (string, "\n\t/VARIABLES="); + psppire_var_view_append_names (PSPPIRE_VAR_VIEW (fd->stat_vars), 0, string); + + g_string_append (string, "\n\t/FORMAT="); + + switch (fd->tables_opts_order) + { + case FRQ_AVALUE: + g_string_append (string, "AVALUE"); + break; + case FRQ_DVALUE: + g_string_append (string, "DVALUE"); + break; + case FRQ_ACOUNT: + g_string_append (string, "AFREQ"); + break; + case FRQ_DCOUNT: + g_string_append (string, "DFREQ"); + break; + default: + g_assert_not_reached (); + } + + g_string_append (string, " "); + + switch (fd->tables_opts_table) + { + case FRQ_TABLE: + g_string_append (string, "TABLE"); + break; + case FRQ_NOTABLE: + g_string_append (string, "NOTABLE"); + break; + case FRQ_LIMIT: + g_string_append_printf (string, "LIMIT (%d)", fd->tables_opts_limit); + break; + } + + + for (i = 0, ok = gtk_tree_model_get_iter_first (fd->stats, &iter); ok; + i++, ok = gtk_tree_model_iter_next (fd->stats, &iter)) + { + gboolean toggled; + gtk_tree_model_get (fd->stats, &iter, + CHECKBOX_COLUMN_SELECTED, &toggled, -1); + if (toggled) + selected |= 1u << i; + } + + if (selected != B_FS_DEFAULT) + { + g_string_append (string, "\n\t/STATISTICS="); + if (selected == B_FS_ALL) + g_string_append (string, "ALL"); + else if (selected == 0) + g_string_append (string, "NONE"); + else + { + int n = 0; + if ((selected & B_FS_DEFAULT) == B_FS_DEFAULT) + { + g_string_append (string, "DEFAULT"); + selected &= ~B_FS_DEFAULT; + n++; + } + for (i = 0; i < N_FREQUENCY_STATS; i++) + if (selected & (1u << i)) + { + if (n++) + g_string_append (string, " "); + g_string_append (string, stats[i].name); + } + } + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->include_missing))) + g_string_append (string, "\n\t/MISSING=INCLUDE"); + + + if (fd->charts_opts_draw_hist) + { + g_string_append (string, "\n\t/HISTOGRAM="); + g_string_append (string, + fd->charts_opts_draw_normal ? "NORMAL" : "NONORMAL"); + + if (fd->charts_opts_scale == FRQ_PERCENT) + g_string_append (string, " PERCENT"); + + if (fd->charts_opts_use_min) + g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts_min); + if (fd->charts_opts_use_max) + g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts_max); + } + + if (fd->charts_opts_draw_pie) + { + g_string_append (string, "\n\t/PIECHART="); + + if (fd->charts_opts_pie_include_missing) + g_string_append (string, " MISSING"); + + if (fd->charts_opts_use_min) + g_string_append_printf (string, " MIN(%.15g)", fd->charts_opts_min); + if (fd->charts_opts_use_max) + g_string_append_printf (string, " MAX(%.15g)", fd->charts_opts_max); + } + + g_string_append (string, ".\n"); + + text = string->str; + + g_string_free (string, FALSE); + + return text; +} + +static void +psppire_dialog_action_frequencies_class_init (PsppireDialogActionFrequenciesClass *class) +{ + GtkActionClass *action_class = GTK_ACTION_CLASS (class); + + action_class->activate = psppire_dialog_action_frequencies_activate; + + PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax; +} + + +static void +psppire_dialog_action_frequencies_init (PsppireDialogActionFrequencies * act) +{ +} diff --git a/src/ui/gui/psppire-dialog-action-frequencies.h b/src/ui/gui/psppire-dialog-action-frequencies.h new file mode 100644 index 0000000000..ea801581ad --- /dev/null +++ b/src/ui/gui/psppire-dialog-action-frequencies.h @@ -0,0 +1,151 @@ +/* PSPPIRE - a graphical user interface for PSPP. + Copyright (C) 2012 Free Software Foundation + + 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 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + +#include +#include + +#include "psppire-dialog-action.h" + +#ifndef __PSPPIRE_DIALOG_ACTION_FREQUENCIES_H__ +#define __PSPPIRE_DIALOG_ACTION_FREQUENCIES_H__ + +G_BEGIN_DECLS + + +#define PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES (psppire_dialog_action_frequencies_get_type ()) + +#define PSPPIRE_DIALOG_ACTION_FREQUENCIES(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES, \ + PsppireDialogActionFrequencies)) + +#define PSPPIRE_DIALOG_ACTION_FREQUENCIES_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES, \ + PsppireDialogActionFrequenciesClass)) + + +#define PSPPIRE_IS_DIALOG_ACTION_FREQUENCIES(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES)) + +#define PSPPIRE_IS_DIALOG_ACTION_FREQUENCIES_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES)) + + +#define PSPPIRE_DIALOG_ACTION_FREQUENCIES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + PSPPIRE_TYPE_DIALOG_ACTION_FREQUENCIES, \ + PsppireDialogActionFrequenciesClass)) + +typedef struct _PsppireDialogActionFrequencies PsppireDialogActionFrequencies; +typedef struct _PsppireDialogActionFrequenciesClass PsppireDialogActionFrequenciesClass; + + +enum frq_scale + { + FRQ_FREQ, + FRQ_PERCENT + }; + +enum frq_order + { + FRQ_AVALUE, + FRQ_DVALUE, + FRQ_ACOUNT, + FRQ_DCOUNT + }; + +enum frq_table + { + FRQ_TABLE, + FRQ_NOTABLE, + FRQ_LIMIT + }; + + +struct _PsppireDialogActionFrequencies +{ + PsppireDialogAction parent; + + /*< private >*/ + gboolean dispose_has_run ; + + GtkWidget *stat_vars; + GtkTreeModel *stats; + + GtkWidget *include_missing; + + enum frq_order tables_opts_order; + enum frq_table tables_opts_table; + gint tables_opts_limit; + + GtkWidget * always; + GtkWidget * never; + GtkWidget * limit; + GtkWidget * limit_spinbutton; + + GtkWidget * avalue; + GtkWidget * dvalue; + GtkWidget * afreq; + GtkWidget * dfreq; + + GtkWidget *tables_dialog; + + /* Charts dialog */ + + GtkWidget *min; + GtkWidget *min_spin; + GtkWidget *max; + GtkWidget *max_spin; + + GtkWidget *hist; + GtkWidget *normal; + + gboolean charts_opts_use_min; + gdouble charts_opts_min; + + gboolean charts_opts_use_max; + gdouble charts_opts_max; + + gboolean charts_opts_draw_hist; + gboolean charts_opts_draw_normal; + + gboolean charts_opts_draw_pie; + gboolean charts_opts_pie_include_missing; + + + enum frq_scale charts_opts_scale; + + GtkWidget *freqs; + GtkWidget *percents; + GtkWidget *pie; + GtkWidget *pie_include_missing; + + GtkWidget *charts_dialog; +}; + + +struct _PsppireDialogActionFrequenciesClass +{ + PsppireDialogActionClass parent_class; +}; + + +GType psppire_dialog_action_frequencies_get_type (void) ; + +G_END_DECLS + +#endif /* __PSPPIRE_DIALOG_ACTION_FREQUENCIES_H__ */ diff --git a/src/ui/gui/psppire-dialog-action-logistic.c b/src/ui/gui/psppire-dialog-action-logistic.c index d93a2f5b0c..0426931e85 100644 --- a/src/ui/gui/psppire-dialog-action-logistic.c +++ b/src/ui/gui/psppire-dialog-action-logistic.c @@ -41,16 +41,6 @@ psppire_dialog_action_logistic_class_init (PsppireDialogActionLogisticClass *cla G_DEFINE_TYPE (PsppireDialogActionLogistic, psppire_dialog_action_logistic, PSPPIRE_TYPE_DIALOG_ACTION); -static void -set_sensitivity_from_toggle (GtkToggleButton *togglebutton, gpointer data) -{ - GtkWidget *w = data; - gboolean active = gtk_toggle_button_get_active (togglebutton); - - gtk_widget_set_sensitive (w, active); -} - - static gboolean dialog_state_valid (gpointer data) { diff --git a/src/ui/gui/psppire-val-chooser.c b/src/ui/gui/psppire-val-chooser.c index 680e147b62..01d694e27e 100644 --- a/src/ui/gui/psppire-val-chooser.c +++ b/src/ui/gui/psppire-val-chooser.c @@ -17,6 +17,7 @@ #include #include +#include "dialog-common.h" #include "psppire-val-chooser.h" #include "libpspp/str.h" @@ -334,14 +335,6 @@ static struct layout range_opt[n_VAL_CHOOSER_BUTTONS]= {N_("_All other values"), NULL, else_set } }; -static void -set_sensitivity_from_toggle (GtkToggleButton *togglebutton, GtkWidget *w) -{ - gboolean active = gtk_toggle_button_get_active (togglebutton); - - gtk_widget_set_sensitive (w, active); -} - static void psppire_val_chooser_init (PsppireValChooser *vr) { diff --git a/src/ui/gui/runs-dialog.c b/src/ui/gui/runs-dialog.c index 7bc05f2422..bfbfc834cb 100644 --- a/src/ui/gui/runs-dialog.c +++ b/src/ui/gui/runs-dialog.c @@ -61,15 +61,6 @@ struct runs static char * generate_syntax (const struct runs *rd); -/* Makes widget W's sensitivity follow the active state of TOGGLE */ -static void -sensitive_if_active (GtkToggleButton *toggle, GtkWidget *w) -{ - gboolean active = gtk_toggle_button_get_active (toggle); - - gtk_widget_set_sensitive (w, active); -} - static void refresh (struct runs *fd) { @@ -151,7 +142,7 @@ runs_dialog (PsppireDataWindow *dw) NULL); g_signal_connect (fd.cb[CB_CUSTOM], "toggled", - G_CALLBACK (sensitive_if_active), fd.entry); + G_CALLBACK (set_sensitivity_from_toggle), fd.entry); psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog), dialog_state_valid, &fd); diff --git a/src/ui/gui/select-cases-dialog.c b/src/ui/gui/select-cases-dialog.c index be0a957f6c..c03906a6a8 100644 --- a/src/ui/gui/select-cases-dialog.c +++ b/src/ui/gui/select-cases-dialog.c @@ -60,27 +60,6 @@ struct select_cases_dialog static gchar * generate_syntax (const struct select_cases_dialog *scd); -static void -set_sensitivity_from_toggle (GtkToggleButton *togglebutton, gpointer data) -{ - GtkWidget *w = data; - gboolean active = gtk_toggle_button_get_active (togglebutton); - - gtk_widget_set_sensitive (w, active); -} - -static void -set_sensitivity_from_toggle_invert (GtkToggleButton *togglebutton, - gpointer data) -{ - GtkWidget *w = data; - gboolean active = gtk_toggle_button_get_active (togglebutton); - - gtk_widget_set_sensitive (w, !active); -} - - - static const gchar label1[]=N_("Approximately %3d%% of all cases."); static const gchar label2[]=N_("Exactly %3d cases from the first %3d cases."); diff --git a/src/ui/gui/widgets.c b/src/ui/gui/widgets.c index 5d8351c441..488656e9e6 100644 --- a/src/ui/gui/widgets.c +++ b/src/ui/gui/widgets.c @@ -15,12 +15,16 @@ #include "psppire-var-view.h" #include "psppire-val-chooser.h" +#include "psppire-dialog-action-binomial.h" #include "psppire-dialog-action-correlation.h" +#include "psppire-dialog-action-crosstabs.h" #include "psppire-dialog-action-descriptives.h" #include "psppire-dialog-action-examine.h" #include "psppire-dialog-action-factor.h" +#include "psppire-dialog-action-frequencies.h" #include "psppire-dialog-action-indep-samps.h" #include "psppire-dialog-action-kmeans.h" +#include "psppire-dialog-action-logistic.h" #include "psppire-dialog-action-means.h" #include "psppire-means-layer.h" #include "psppire-dialog-action-rank.h" @@ -50,10 +54,13 @@ preregister_widgets (void) psppire_var_view_get_type (); psppire_value_entry_get_type (); + psppire_dialog_action_binomial_get_type (); psppire_dialog_action_correlation_get_type (); + psppire_dialog_action_crosstabs_get_type (); psppire_dialog_action_descriptives_get_type (); psppire_dialog_action_examine_get_type (); psppire_dialog_action_factor_get_type (); + psppire_dialog_action_frequencies_get_type (); psppire_dialog_action_logistic_get_type (); psppire_dialog_action_kmeans_get_type (); psppire_dialog_action_means_get_type (); diff --git a/src/ui/terminal/main.c b/src/ui/terminal/main.c index a0ba84d898..3f4139b85d 100644 --- a/src/ui/terminal/main.c +++ b/src/ui/terminal/main.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-2000, 2006-2007, 2009-2012 Free Software Foundation, Inc. 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 @@ -49,7 +49,6 @@ #include "math/random.h" #include "output/driver.h" #include "output/message-item.h" -#include "ui/debugger.h" #include "ui/source-init-opts.h" #include "ui/terminal/terminal-opts.h" #include "ui/terminal/terminal-reader.h" @@ -194,9 +193,6 @@ bug_handler(int sig) recurse. */ signal (sig, SIG_DFL); -#if DEBUGGING - connect_debugger (); -#endif switch (sig) { case SIGABRT: diff --git a/tests/language/data-io/data-list.at b/tests/language/data-io/data-list.at index b0582c6c47..4a59cf795a 100644 --- a/tests/language/data-io/data-list.at +++ b/tests/language/data-io/data-list.at @@ -30,6 +30,7 @@ A,B,C ]) AT_CLEANUP + AT_SETUP([DATA LIST LIST with explicit delimiters]) AT_DATA([data-list.pspp], [dnl data list list ('|','X') /A B C D. @@ -255,3 +256,34 @@ AT_CHECK([cat write.txt], [0], [dnl 1 12 123 1234 12345 . ]) AT_CLEANUP + +AT_SETUP([DATA LIST FREE and LIST report missing delimiters]) +AT_DATA([data-list.sps], [dnl +DATA LIST FREE NOTABLE/s (a10). +LIST. +BEGIN DATA. +'y'z +END DATA. +]) +AT_CHECK([pspp -O format=csv data-list.sps], [0], [dnl +data-list.sps:4: warning: Missing delimiter following quoted string. + +Table: Data List +s +y @&t@ +z @&t@ +]) +AT_CLEANUP + +AT_SETUP([DATA LIST FREE and LIST assume a width if omitted]) +AT_DATA([data-list.sps], [dnl +DATA LIST FREE TABLE/s (a) d (datetime) f (f). +]) +AT_CHECK([pspp -O format=csv data-list.sps], [0], [dnl +Table: Reading free-form data from INLINE. +Variable,Format +s,A1 +d,DATETIME17.0 +f,F1.0 +]) +AT_CLEANUP diff --git a/tests/language/expressions/evaluate.at b/tests/language/expressions/evaluate.at index e56a3a457e..4512458afc 100644 --- a/tests/language/expressions/evaluate.at +++ b/tests/language/expressions/evaluate.at @@ -487,7 +487,7 @@ ANY(string, string[, string]...).]], [[any('a', 'a ', 'b', 'c')], [true]], [[any('b ', 'a', 'b', 'c')], [true]], [[any('c ', 'a', 'b', 'c ')], [true]], - [[any(a, 'b', 'c', 'd')], [error], + [[any(a10, 'b', 'c', 'd')], [error], [error: DEBUG EVALUATE: Function invocation any(format, string, string, string) does not match any known function. Candidates are: ANY(number, number[, number]...) ANY(string, string[, string]...).]], @@ -1740,7 +1740,42 @@ CHECK_EXPR_EVAL([datediff], [[datediff(date.mdy(7,18,2094), date.mdy(11,10,2038), 'quarters')], [222.00]], [[datediff(date.mdy(2,29,1904), date.mdy(2,29,1900), 'quarters')], [15.00]], [[datediff(date.mdy(2,29,1908), date.mdy(2,29,1904), 'quarters')], [16.00]], - [[datediff(date.mdy(2,28,1903), date.mdy(2,29,1900), 'quarters')], [11.00]]) + [[datediff(date.mdy(2,28,1903), date.mdy(2,29,1900), 'quarters')], [11.00]], + +dnl time of day is significant for DATEDIFF + [[datediff(date.mdy(10,15,1910) + 234, date.mdy(10,10,1910) + 123, 'days')], + [5.00]], + [[datediff(date.mdy(10,15,1910) + 123, date.mdy(10,10,1910) + 234, 'days')], + [4.00]], + [[datediff(date.mdy(10,24,1910) + 234, date.mdy(10,10,1910) + 123, 'weeks')], + [2.00]], + [[datediff(date.mdy(10,24,1910) + 123, date.mdy(10,10,1910) + 234, 'weeks')], + [1.00]], + [[datediff(date.mdy(10,10,1910) + 234, date.mdy(5,10,1910) + 123, 'months')], + [5.00]], + [[datediff(date.mdy(10,10,1910) + 123, date.mdy(5,10,1910) + 234, 'months')], + [4.00]], + [[datediff(date.mdy(5,10,1919) + 234, date.mdy(5,10,1910) + 123, 'years')], + [9.00]], + [[datediff(date.mdy(5,10,1919) + 123, date.mdy(5,10,1910) + 234, 'years')], + [8.00]], + + [[datediff(date.mdy(10,10,1910) + 123, date.mdy(10,15,1910) + 234, 'days')], + [-5.00]], + [[datediff(date.mdy(10,10,1910) + 234, date.mdy(10,15,1910) + 123, 'days')], + [-4.00]], + [[datediff(date.mdy(10,10,1910) + 123, date.mdy(10,24,1910) + 234, 'weeks')], + [-2.00]], + [[datediff(date.mdy(10,10,1910) + 234, date.mdy(10,24,1910) + 123, 'weeks')], + [-1.00]], + [[datediff(date.mdy(5,10,1910) + 123, date.mdy(10,10,1910) + 234, 'months')], + [-5.00]], + [[datediff(date.mdy(5,10,1910) + 234, date.mdy(10,10,1910) + 123, 'months')], + [-4.00]], + [[datediff(date.mdy(5,10,1910) + 123, date.mdy(5,10,1919) + 234, 'years')], + [-9.00]], + [[datediff(date.mdy(5,10,1910) + 234, date.mdy(5,10,1919) + 123, 'years')], + [-8.00]]) CHECK_EXPR_EVAL([datesum], dnl DATESUM with non-leap year @@ -1813,7 +1848,13 @@ dnl DATESUM with leap year [[ctime.days(datesum(date.mdy(6,10,1648), 1, 'hours') - date.mdy(6,10,1648))], [0.04]], [[ctime.days(datesum(date.mdy(6,30,1680), 2.5, 'hours') - date.mdy(6,30,1680))], [0.10]], [[ctime.days(datesum(date.mdy(6,19,1768), -4, 'hours') - date.mdy(6,19,1768))], [-0.17]], - [[ctime.days(datesum(date.mdy(8,2,1819), 5, 'hours') - date.mdy(8,2,1819))], [0.21]]) + [[ctime.days(datesum(date.mdy(8,2,1819), 5, 'hours') - date.mdy(8,2,1819))], [0.21]], + +dnl DATESUM preserves time-of-day for units of days and longer. + [[ctime.days(datesum(date.mdy(8,2,1819) + time.hms(1,2,3), 5, 'days') - (date.mdy(8,2,1819) + time.hms(1,2,3)))], [5.00]], + [[ctime.days(datesum(date.mdy(8,2,1819) + time.hms(1,2,3), 5, 'weeks') - (date.mdy(8,2,1819) + time.hms(1,2,3)))], [35.00]], + [[ctime.days(datesum(date.mdy(8,2,1819) + time.hms(1,2,3), 5, 'months') - (date.mdy(8,2,1819) + time.hms(1,2,3)))], [153.00]], + [[ctime.days(datesum(date.mdy(8,2,1819) + time.hms(1,2,3), 5, 'years') - (date.mdy(8,2,1819) + time.hms(1,2,3)))], [1827.00]]) CHECK_EXPR_EVAL([miscellaneous], dnl These test values are from Applied Statistics, Algorithm AS 310. diff --git a/tests/language/lexer/variable-parser.at b/tests/language/lexer/variable-parser.at index f5aed6bdb6..59609f0380 100644 --- a/tests/language/lexer/variable-parser.at +++ b/tests/language/lexer/variable-parser.at @@ -38,13 +38,13 @@ X * Yabbadabbadoo,1,100.0%,0,0.0%,1,100.0% Table: X * Yabbadabbadoo [[count]]. ,Yabbadabbadoo,,,,,,, X,1.00,2.00,3.00,4.00,5.00,6.00,7.00,Total -1.00,.0,.0,.0,.0,.0,.0,.0,.0 -2.00,.0,.0,.0,.0,.0,.0,.0,.0 -3.00,.0,.0,.0,.0,.0,.0,.0,.0 -4.00,.0,.0,.0,.0,1.0,.0,.0,1.0 -5.00,.0,.0,.0,.0,.0,.0,.0,.0 -6.00,.0,.0,.0,.0,.0,.0,.0,.0 -7.00,.0,.0,.0,.0,.0,.0,.0,.0 -Total,.0,.0,.0,.0,1.0,.0,.0,1.0 +1.00,.00,.00,.00,.00,.00,.00,.00,.00 +2.00,.00,.00,.00,.00,.00,.00,.00,.00 +3.00,.00,.00,.00,.00,.00,.00,.00,.00 +4.00,.00,.00,.00,.00,1.00,.00,.00,1.00 +5.00,.00,.00,.00,.00,.00,.00,.00,.00 +6.00,.00,.00,.00,.00,.00,.00,.00,.00 +7.00,.00,.00,.00,.00,.00,.00,.00,.00 +Total,.00,.00,.00,.00,1.00,.00,.00,1.00 ]) AT_CLEANUP diff --git a/tests/language/stats/crosstabs.at b/tests/language/stats/crosstabs.at index 1647e4bd61..4492e9a250 100644 --- a/tests/language/stats/crosstabs.at +++ b/tests/language/stats/crosstabs.at @@ -26,14 +26,14 @@ X * Y,1,100.0%,0,0.0%,1,100.0% Table: X * Y [count]. ,Y,,,,,,, X,1.00,2.00,3.00,4.00,5.00,6.00,7.00,Total -1.00,.0,.0,.0,.0,.0,.0,.0,.0 -2.00,.0,.0,.0,.0,.0,.0,.0,.0 -3.00,.0,.0,.0,.0,.0,.0,.0,.0 -4.00,.0,.0,.0,.0,1.0,.0,.0,1.0 -5.00,.0,.0,.0,.0,.0,.0,.0,.0 -6.00,.0,.0,.0,.0,.0,.0,.0,.0 -7.00,.0,.0,.0,.0,.0,.0,.0,.0 -Total,.0,.0,.0,.0,1.0,.0,.0,1.0 +1.00,.00,.00,.00,.00,.00,.00,.00,.00 +2.00,.00,.00,.00,.00,.00,.00,.00,.00 +3.00,.00,.00,.00,.00,.00,.00,.00,.00 +4.00,.00,.00,.00,.00,1.00,.00,.00,1.00 +5.00,.00,.00,.00,.00,.00,.00,.00,.00 +6.00,.00,.00,.00,.00,.00,.00,.00,.00 +7.00,.00,.00,.00,.00,.00,.00,.00,.00 +Total,.00,.00,.00,.00,1.00,.00,.00,1.00 ]]) AT_CLEANUP @@ -59,9 +59,9 @@ Variable,Format x,F8.0 y,A18 -"crosstabs.sps:4: warning: BEGIN DATA: Missing value(s) for all variables from x onward. These will be filled with the system-missing value or blanks, as appropriate." +"crosstabs.sps:4: warning: Missing value(s) for all variables from x onward. These will be filled with the system-missing value or blanks, as appropriate." -"crosstabs.sps:6: warning: BEGIN DATA: Missing value(s) for all variables from x onward. These will be filled with the system-missing value or blanks, as appropriate." +"crosstabs.sps:6: warning: Missing value(s) for all variables from x onward. These will be filled with the system-missing value or blanks, as appropriate." Table: Summary. ,Cases,,,,, @@ -72,10 +72,10 @@ x * y,4,66.7%,2,33.3%,6,100.0% Table: x * y [count]. ,y,,,, x,one unity ,three lots ,two duality ,zero none ,Total -1.00,1.0,.0,.0,1.0,2.0 -2.00,.0,.0,1.0,.0,1.0 -3.00,.0,1.0,.0,.0,1.0 -Total,1.0,1.0,1.0,1.0,4.0 +1.00,1.00,.00,.00,1.00,2.00 +2.00,.00,.00,1.00,.00,1.00 +3.00,.00,1.00,.00,.00,1.00 +Total,1.00,1.00,1.00,1.00,4.00 ]]) AT_CLEANUP @@ -131,9 +131,9 @@ y * z,9,100.0%,0,0.0%,9,100.0% Table: y * z [count]. ,z,, y,1,2,Total -1,4.0,3.0,7.0 -2,1.0,1.0,2.0 -Total,5.0,4.0,9.0 +1,4.00,3.00,7.00 +2,1.00,1.00,2.00 +Total,5.00,4.00,9.00 ]]) AT_CLEANUP @@ -168,10 +168,10 @@ x * y,4,100.0%,0,0.0%,4,100.0% Table: x * y [count]. ,y,, x,1.00,2.00,Total -2.00,.0,1.0,1.0 -3.00,1.0,.0,1.0 -4.00,1.0,1.0,2.0 -Total,2.0,2.0,4.0 +2.00,.00,1.00,1.00 +3.00,1.00,.00,1.00 +4.00,1.00,1.00,2.00 +Total,2.00,2.00,4.00 Table: Chi-square tests. Statistic,Value,df,Asymp. Sig. (2-tailed) @@ -220,18 +220,18 @@ v1 * v2,6,100.0%,0,0.0%,6,100.0% "Table: v1 * v2 [count, row %, column %, total %]." ,v2,, v1,e ,f ,Total -c ,3.0,1.0,4.0 -,75.0%,25.0%,100.0% -,75.0%,50.0%,66.7% -,50.0%,16.7%,66.7% -d ,1.0,1.0,2.0 -,50.0%,50.0%,100.0% -,25.0%,50.0%,33.3% -,16.7%,16.7%,33.3% -Total,4.0,2.0,6.0 -,66.7%,33.3%,100.0% -,100.0%,100.0%,100.0% -,66.7%,33.3%,100.0% +c ,3.00,1.00,4.00 +,75.00%,25.00%,100.00% +,75.00%,50.00%,66.67% +,50.00%,16.67%,66.67% +d ,1.00,1.00,2.00 +,50.00%,50.00%,100.00% +,25.00%,50.00%,33.33% +,16.67%,16.67%,33.33% +Total,4.00,2.00,6.00 +,66.67%,33.33%,100.00% +,100.00%,100.00%,100.00% +,66.67%,33.33%,100.00% Table: Chi-square tests. Statistic,Value,df,Asymp. Sig. (2-tailed),Exact Sig. (2-tailed),Exact Sig. (1-tailed) @@ -253,18 +253,18 @@ v1 * v2,4,100.0%,0,0.0%,4,100.0% "Table: v1 * v2 [count, row %, column %, total %]." ,v2,, v1,e ,f ,Total -c ,.0,1.0,1.0 -,.0%,100.0%,100.0% -,.0%,33.3%,25.0% -,.0%,25.0%,25.0% -d ,1.0,2.0,3.0 -,33.3%,66.7%,100.0% -,100.0%,66.7%,75.0% -,25.0%,50.0%,75.0% -Total,1.0,3.0,4.0 -,25.0%,75.0%,100.0% -,100.0%,100.0%,100.0% -,25.0%,75.0%,100.0% +c ,.00,1.00,1.00 +,.00%,100.00%,100.00% +,.00%,33.33%,25.00% +,.00%,25.00%,25.00% +d ,1.00,2.00,3.00 +,33.33%,66.67%,100.00% +,100.00%,66.67%,75.00% +,25.00%,50.00%,75.00% +Total,1.00,3.00,4.00 +,25.00%,75.00%,100.00% +,100.00%,100.00%,100.00% +,25.00%,75.00%,100.00% Table: Chi-square tests. Statistic,Value,df,Asymp. Sig. (2-tailed),Exact Sig. (2-tailed),Exact Sig. (1-tailed) @@ -329,17 +329,17 @@ x * y * z,9,100.0%,0,0.0%,9,100.0% Table: x * y * z [count]. z,,y,, ,x,1,2,Total -1,1,1.0,.0,1.0 -,3,1.0,.0,1.0 -,5,.0,1.0,1.0 -,7,1.0,.0,1.0 -,8,1.0,.0,1.0 -Total,,4.0,1.0,5.0 -2,2,.0,1.0,1.0 -,4,1.0,.0,1.0 -,6,1.0,.0,1.0 -,9,1.0,.0,1.0 -Total,,3.0,1.0,4.0 +1,1,1.00,.00,1.00 +,3,1.00,.00,1.00 +,5,.00,1.00,1.00 +,7,1.00,.00,1.00 +,8,1.00,.00,1.00 +Total,,4.00,1.00,5.00 +2,2,.00,1.00,1.00 +,4,1.00,.00,1.00 +,6,1.00,.00,1.00 +,9,1.00,.00,1.00 +Total,,3.00,1.00,4.00 Table: Chi-square tests. z,Statistic,Value,df,Asymp. Sig. (2-tailed) @@ -433,10 +433,10 @@ x * y,6,100.0%,0,0.0%,6,100.0% Table: x * y [count]. ,y,, x,2.00,1.00,Total -4.00,.0,1.0,1.0 -3.00,2.0,1.0,3.0 -2.00,2.0,.0,2.0 -Total,4.0,2.0,6.0 +4.00,.00,1.00,1.00 +3.00,2.00,1.00,3.00 +2.00,2.00,.00,2.00 +Total,4.00,2.00,6.00 ]]) AT_CLEANUP diff --git a/tests/language/stats/descriptives.at b/tests/language/stats/descriptives.at index 9c6be8d38f..9cc7ca0515 100644 --- a/tests/language/stats/descriptives.at +++ b/tests/language/stats/descriptives.at @@ -185,3 +185,94 @@ Variable,N,Mean,Std Dev,Minimum,Maximum abc,6,3.00,.84,2.00,4.00 ]) AT_CLEANUP + +AT_SETUP([DESCRIPTIVES -- Z scores]) +AT_DATA([descriptives.sps], [dnl +DATA LIST LIST NOTABLE /a b. +BEGIN DATA. +1 50 +2 60 +3 70 +END DATA. + +DESCRIPTIVES /VAR=a b /SAVE. +LIST. +]) +AT_CHECK([pspp -O format=csv descriptives.sps], [0], [dnl +Table: Mapping of variables to corresponding Z-scores. +Source,Target +a,Za +b,Zb + +Table: Valid cases = 3; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +a,3,2.00,1.00,1.00,3.00 +b,3,60.00,10.00,50.00,70.00 + +Table: Data List +a,b,Za,Zb +1.00,50.00,-1.00,-1.00 +2.00,60.00,.00,.00 +3.00,70.00,1.00,1.00 +]) +AT_CLEANUP + +AT_SETUP([DESCRIPTIVES -- Z scores with SPLIT FILE]) +AT_DATA([descriptives.sps], [dnl +DATA LIST LIST NOTABLE /group a b. +BEGIN DATA. +1 1 50 +1 2 60 +1 3 70 +2 100 6000 +2 200 7000 +2 400 9000 +2 500 10000 +END DATA. + +SPLIT FILE BY group. +DESCRIPTIVES /VAR=a b /SAVE. +LIST. +]) +AT_CHECK([pspp -O format=csv descriptives.sps], [0], [dnl +Table: Mapping of variables to corresponding Z-scores. +Source,Target +a,Za +b,Zb + +Variable,Value,Label +group,1.00, + +Table: Valid cases = 3; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +a,3,2.00,1.00,1.00,3.00 +b,3,60.00,10.00,50.00,70.00 + +Variable,Value,Label +group,2.00, + +Table: Valid cases = 4; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +a,4,300.00,182.57,100.00,500.00 +b,4,8000.00,1825.74,6000.00,10000.00 + +Variable,Value,Label +group,1.00, + +Table: Data List +group,a,b,Za,Zb +1.00,1.00,50.00,-1.00,-1.00 +1.00,2.00,60.00,.00,.00 +1.00,3.00,70.00,1.00,1.00 + +Variable,Value,Label +group,2.00, + +Table: Data List +group,a,b,Za,Zb +2.00,100.00,6000.00,-1.10,-1.10 +2.00,200.00,7000.00,-.55,-.55 +2.00,400.00,9000.00,.55,.55 +2.00,500.00,10000.00,1.10,1.10 +]) +AT_CLEANUP diff --git a/tests/language/stats/npar.at b/tests/language/stats/npar.at index 38e2e7c4c1..f5eb2a404c 100644 --- a/tests/language/stats/npar.at +++ b/tests/language/stats/npar.at @@ -274,6 +274,28 @@ x,Group1,10.000,10.000,.435,.500,.678 ]) AT_CLEANUP + + +dnl Test for a bug which caused binomial to crash. +AT_SETUP([NPAR TESTS BINOMIAL - crash]) +AT_DATA([nparX.sps], [dnl +data list list /range *. +begin data. +0 +1 +end data. + +* This is invalid syntax +NPAR TEST + /BINOMIAL(0.5) = Range(). + +]) +AT_CHECK([pspp -O format=csv nparX.sps], [1], [ignore]) + +AT_CLEANUP + + + AT_SETUP([NPAR TESTS CHISQUARE]) AT_DATA([npar.sps], [dnl DATA LIST NOTABLE LIST /x * y * w *. diff --git a/tests/language/stats/rank.at b/tests/language/stats/rank.at index 6cb366849b..04d5accce7 100644 --- a/tests/language/stats/rank.at +++ b/tests/language/stats/rank.at @@ -481,19 +481,19 @@ DELETE VAR ran001 TO ran999. LIST. ]) AT_CHECK([pspp -O format=csv rank.sps], [0], [dnl -"rank.sps:3: warning: BEGIN DATA: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." +"rank.sps:3: warning: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." -"rank.sps:4: warning: BEGIN DATA: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." +"rank.sps:4: warning: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." -"rank.sps:5: warning: BEGIN DATA: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." +"rank.sps:5: warning: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." -"rank.sps:6: warning: BEGIN DATA: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." +"rank.sps:6: warning: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." -"rank.sps:7: warning: BEGIN DATA: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." +"rank.sps:7: warning: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." -"rank.sps:8: warning: BEGIN DATA: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." +"rank.sps:8: warning: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." -"rank.sps:9: warning: BEGIN DATA: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." +"rank.sps:9: warning: Missing value(s) for all variables from rx onward. These will be filled with the system-missing value or blanks, as appropriate." Variables Created By RANK diff --git a/tests/output/charts.at b/tests/output/charts.at index 302e05b151..049fc28192 100644 --- a/tests/output/charts.at +++ b/tests/output/charts.at @@ -151,6 +151,7 @@ frequencies pos neg pn ]) -AT_CHECK([pspp -O format=csv histogram.sps], [0], [ignore]) +dnl The --testing-mode flag is important!! +AT_CHECK([pspp --testing-mode -O format=csv histogram.sps], [0], [ignore]) AT_CLEANUP diff --git a/tests/ui/terminal/main.at b/tests/ui/terminal/main.at index 1a22f7a0e8..38a88eca14 100644 --- a/tests/ui/terminal/main.at +++ b/tests/ui/terminal/main.at @@ -34,6 +34,5 @@ include the syntax file that triggered it and a sample of any data file used for input. proximate cause: Segmentation Violation ]) -AT_CHECK([sed -n '/\*\*\*/,$p -/proximate/q' < stderr], [0], [expout]) +AT_CHECK([sed '/proximate/q' < stderr], [0], [expout]) AT_CLEANUP