New menu: Edit|Options
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 25 Mar 2017 21:47:27 +0000 (22:47 +0100)
committerJohn Darrington <john@darrington.wattle.id.au>
Mon, 27 Mar 2017 15:55:21 +0000 (17:55 +0200)
Add a new menu to set global options.  Currently it only affects the display
of variables in Dictionary Views.

NEWS
src/ui/gui/automake.mk
src/ui/gui/options-dialog.c [new file with mode: 0644]
src/ui/gui/options-dialog.h [new file with mode: 0644]
src/ui/gui/options.ui [new file with mode: 0644]
src/ui/gui/psppire-conf.c
src/ui/gui/psppire-conf.h
src/ui/gui/psppire-data-window.c
src/ui/gui/psppire-data-window.h
src/ui/gui/psppire-dictview.c
src/ui/gui/psppire-dictview.h

diff --git a/NEWS b/NEWS
index 141723b71f0d8dc8ee7acb6a624f0a546fdc7fce..90505f2e502c9971f9897c319301665ac36e2db2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ Please send PSPP bug reports to bug-gnu-pspp@gnu.org.
 
 Changes from 0.10.2 to 0.10.4:
 
+ * A graphical user interface has a new menu: Edit|Options
+
  * A bug which could cause the HTML driver to go into a tight loop
    has been fixed.
 
index 3f3303fc14de3d99a809a6376dce52f26661edf7..3b752c5c3af6656202dce31e93cc55700d0ccba2 100644 (file)
@@ -27,6 +27,7 @@ UI_FILES = \
        src/ui/gui/means.ui \
        src/ui/gui/missing-val-dialog.ui \
        src/ui/gui/oneway.ui \
+       src/ui/gui/options.ui \
        src/ui/gui/paired-samples.ui \
        src/ui/gui/rank.ui \
        src/ui/gui/runs.ui \
@@ -167,6 +168,8 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/main.c \
        src/ui/gui/missing-val-dialog.c \
        src/ui/gui/missing-val-dialog.h \
+       src/ui/gui/options-dialog.c \
+       src/ui/gui/options-dialog.h \
        src/ui/gui/psppire.c \
        src/ui/gui/psppire.h \
        src/ui/gui/psppire-acr.h \
diff --git a/src/ui/gui/options-dialog.c b/src/ui/gui/options-dialog.c
new file mode 100644 (file)
index 0000000..45f69f5
--- /dev/null
@@ -0,0 +1,149 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "options-dialog.h"
+
+#include "ui/gui/helper.h"
+#include "ui/gui/psppire-conf.h"
+#include "ui/gui/builder-wrapper.h"
+#include "ui/gui/psppire-data-window.h"
+#include "ui/gui/psppire-dialog.h"
+
+#include <gtk/gtk.h>
+
+#include <gettext.h>
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+
+struct options_dialog
+{
+  GtkBuilder *xml;
+  GtkWidget *show_labels;
+  GtkWidget *show_names;
+  PsppireConf *conf;
+
+  GtkWidget *sort_names;
+  GtkWidget *sort_labels;
+  GtkWidget *sort_none;
+};
+
+GType
+pspp_options_var_order_get_type (void)
+{
+  static GType etype = 0;
+  if (G_UNLIKELY(etype == 0)) {
+    static const GEnumValue values[] =
+      {
+       { PSPP_OPTIONS_VAR_ORDER_UNSORTED, "PSPP_OPTIONS_VAR_ORDER_UNSORTED", "unsorted" },
+       { PSPP_OPTIONS_VAR_ORDER_NAME,     "PSPP_OPTIONS_VAR_ORDER_NAME",     "name" },
+       { PSPP_OPTIONS_VAR_ORDER_LABEL,    "PSPP_OPTIONS_VAR_ORDER_LABEL",    "label" },
+       { 0, NULL, NULL }
+      };
+    etype = g_enum_register_static (g_intern_static_string ("PsppOptionsVarOrder"), values);
+  }
+  return etype;
+}
+
+/*
+   Pops up the Options dialog box
+ */
+void
+options_dialog (PsppireDataWindow *de)
+{
+  struct options_dialog fd;
+
+  GtkWidget *dialog ;
+
+  gboolean disp_labels = true;
+
+  fd.xml = builder_new ("options.ui");
+
+  dialog = get_widget_assert (fd.xml, "options-dialog");
+
+  fd.show_labels = get_widget_assert (fd.xml, "radiobutton-labels");
+  fd.show_names  = get_widget_assert (fd.xml, "radiobutton-names");
+
+  fd.sort_labels = get_widget_assert (fd.xml, "radiobutton-sort-by-label");
+  fd.sort_names  = get_widget_assert (fd.xml, "radiobutton-sort-by-name");
+  fd.sort_none   = get_widget_assert (fd.xml, "radiobutton-unsorted");
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
+
+
+  fd.conf = psppire_conf_new ();
+
+  if (psppire_conf_get_boolean (fd.conf,
+                               "VariableLists", "display-labels", &disp_labels))
+    {
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd.show_labels),
+                                   disp_labels);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd.show_names),
+                                   !disp_labels);
+    }
+
+
+  int what = -1;
+  psppire_conf_get_enum (fd.conf, "VariableLists", "sort-order",
+                        PSPP_TYPE_OPTIONS_VAR_ORDER, &what);
+
+  switch (what)
+    {
+    default:
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd.sort_none), true);
+      break;
+    case PSPP_OPTIONS_VAR_ORDER_NAME:
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd.sort_names), true);
+      break;
+    case PSPP_OPTIONS_VAR_ORDER_LABEL:
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd.sort_labels), true);
+      break;
+    }
+
+  const int result = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
+
+  if (result == GTK_RESPONSE_OK)
+    {
+      PsppOptionsVarOrder sort_order = -1;
+      gboolean sl = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd.show_labels));
+
+      psppire_conf_set_boolean (fd.conf,
+                               "VariableLists", "display-labels", sl);
+
+      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd.sort_labels)))
+       {
+         sort_order = PSPP_OPTIONS_VAR_ORDER_LABEL;
+       }
+      else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd.sort_names)))
+       {
+         sort_order = PSPP_OPTIONS_VAR_ORDER_NAME;
+       }
+      else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd.sort_none)))
+       {
+         sort_order = PSPP_OPTIONS_VAR_ORDER_UNSORTED;
+       }
+       
+      psppire_conf_set_enum (fd.conf,
+                            "VariableLists", "sort-order",
+                            PSPP_TYPE_OPTIONS_VAR_ORDER,
+                            sort_order);
+    }
+
+  g_object_unref (fd.xml);
+}
diff --git a/src/ui/gui/options-dialog.h b/src/ui/gui/options-dialog.h
new file mode 100644 (file)
index 0000000..0307b15
--- /dev/null
@@ -0,0 +1,37 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2017  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 <http://www.gnu.org/licenses/>. */
+
+
+#ifndef OPTIONS_DIALOG_H
+#define OPTIONS_DIALOG_H
+
+#include "psppire-data-window.h"
+
+typedef enum
+{
+  PSPP_OPTIONS_VAR_ORDER_UNSORTED,
+  PSPP_OPTIONS_VAR_ORDER_NAME,
+  PSPP_OPTIONS_VAR_ORDER_LABEL,
+} PsppOptionsVarOrder;
+
+GType pspp_options_var_order_get_type (void) G_GNUC_CONST;
+#define PSPP_TYPE_OPTIONS_VAR_ORDER (pspp_options_var_order_get_type ())
+
+
+/* Pops up the Options dialog box */
+void options_dialog (PsppireDataWindow *);
+
+#endif
diff --git a/src/ui/gui/options.ui b/src/ui/gui/options.ui
new file mode 100644 (file)
index 0000000..a3f45d9
--- /dev/null
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+  <requires lib="gtk+" version="3.4.2"/>
+  <requires lib="psppire" version="2053.63976"/>
+  <object class="PsppireDialog" id="options-dialog">
+    <property name="can_focus">False</property>
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="title" translatable="yes">Options Case</property>
+    <property name="modal">True</property>
+    <child>
+      <object class="GtkBox" id="dialog-hbox14">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="margin_left">5</property>
+        <property name="margin_bottom">5</property>
+        <property name="spacing">5</property>
+        <child>
+          <object class="GtkFrame" id="variable-lists-frame">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkButtonBox">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">5</property>
+                    <property name="layout_style">start</property>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton-labels">
+                        <property name="label" translatable="yes">Display _Labels</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton-names</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton-names">
+                        <property name="label" translatable="yes">Display _Names</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="active">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                   <child>
+                      <object class="GtkSeparator">
+                       <property name="visible">True</property>
+                       <property name="can_focus">False</property>
+                      </object>
+                      <packing>
+                       <property name="expand">False</property>
+                       <property name="fill">False</property>
+                       <property name="position">2</property>
+                      </packing>
+                    </child>
+
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton-sort-by-label">
+                        <property name="label" translatable="yes">Sort by L_abel</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton-sort-by-name</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton-sort-by-name">
+                        <property name="label" translatable="yes">Sort by Na_me</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="active">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton-unsorted">
+                        <property name="label" translatable="yes">Do not S_ort</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="active">True</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton-sort-by-name</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">5</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Variable Lists</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+
+
+        <child>
+          <object class="PsppireButtonbox" id="options-buttonbox">
+            <property name="orientation">vertical</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="border_width">5</property>
+            <property name="buttons">PSPPIRE_BUTTON_OK_MASK | PSPPIRE_BUTTON_CANCEL_MASK | PSPPIRE_BUTTON_HELP_MASK</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+       
+      </object>
+    </child>
+    
+  </object>
+</interface>
index 09f6d68a124b5cabaa2c6e5d07fb0aefc1be4c14..ed8077db2d8c52933e3b04455cf92221f3488337 100644 (file)
@@ -248,6 +248,62 @@ psppire_conf_get_string (PsppireConf *conf, const gchar *base,
 
 
 
+
+gboolean
+psppire_conf_get_variant (PsppireConf *conf, const gchar *base,
+                         const gchar *name, GVariant **v)
+{
+  gboolean ok;
+  gchar *b;
+  GError *err = NULL;
+  conf_read (conf);
+  b = g_key_file_get_string (conf->keyfile,
+                            base,
+                            name, &err);
+
+  ok = (err == NULL);
+  if ( err != NULL )
+    g_error_free (err);
+
+  if (ok)
+    {
+      *v = g_variant_parse (NULL, b, NULL, NULL, NULL);
+      g_free (b);
+    }
+
+  return ok;
+}
+
+gboolean
+psppire_conf_get_enum (PsppireConf *conf, const gchar *base,
+                      const gchar *name,
+                      GType t,
+                      int *v)
+{
+  gboolean ok;
+  gchar *b;
+  GError *err = NULL;
+  conf_read (conf);
+  b = g_key_file_get_string (conf->keyfile,
+                            base,
+                            name, &err);
+
+  ok = (err == NULL);
+  if ( err != NULL )
+    g_error_free (err);
+
+  if (ok)
+    {
+      GEnumClass *ec = g_type_class_ref (t);
+      GEnumValue *ev = g_enum_get_value_by_nick (ec, b);
+      *v = ev->value;
+      g_type_class_unref (ec);
+      g_free (b);
+    }
+
+  return ok;
+}
+
 void
 psppire_conf_set_int (PsppireConf *conf,
                      const gchar *base, const gchar *name,
@@ -276,6 +332,34 @@ psppire_conf_set_string (PsppireConf *conf,
   conf_write (conf);
 }
 
+void
+psppire_conf_set_variant (PsppireConf *conf,
+                              const gchar *base, const gchar *name,
+                              GVariant *value)
+{
+  gchar *v = g_variant_print (value, FALSE);
+  g_key_file_set_string (conf->keyfile, base, name, v);
+  conf_write (conf);
+  g_free (v);
+}
+
+void
+psppire_conf_set_enum (PsppireConf *conf,
+                      const gchar *base, const gchar *name,
+                      GType enum_type,
+                      int value)
+{
+  GEnumClass *ec = g_type_class_ref (enum_type);
+  GEnumValue *ev = g_enum_get_value (ec, value);
+  
+  g_key_file_set_string (conf->keyfile, base, name,
+                        ev->value_nick);
+
+  g_type_class_unref (ec);
+  
+  conf_write (conf);
+}
+
 
 
 /*
index 8f944518e08e13bfeb3205e2373d1ca4ee5cf390..5f4b283af5c2cf0f87bc9ccdd0d2d27aa8ff2902 100644 (file)
@@ -85,6 +85,16 @@ gboolean psppire_conf_get_string (PsppireConf *,
 gboolean psppire_conf_get_boolean (PsppireConf *,
                                   const gchar *, const gchar *, gboolean *);
 
+
+gboolean psppire_conf_get_variant (PsppireConf *,
+                                  const gchar *, const gchar *, GVariant **);
+
+
+gboolean psppire_conf_get_enum (PsppireConf *conf, const gchar *base,
+                               const gchar *name,
+                               GType t,
+                               int *v);
+
 void psppire_conf_set_int (PsppireConf *conf,
                           const gchar *base, const gchar *name,
                           gint value);
@@ -97,6 +107,17 @@ void psppire_conf_set_string (PsppireConf *conf,
                               const gchar *base, const gchar *name,
                              const gchar *value);
 
+
+void psppire_conf_set_variant (PsppireConf *conf,
+                              const gchar *base, const gchar *name,
+                              GVariant *value);
+
+
+void psppire_conf_set_enum (PsppireConf *conf,
+                           const gchar *base, const gchar *name,
+                           GType enum_type,
+                           int value);
+
 void psppire_conf_set_window_geometry (PsppireConf *conf,
                                       const gchar *base,
                                       GtkWindow *window);
index fddd3bb3e3b7f8a61f3fbeb62964e2c9803e8287..c9f87d7f6718073174f9c41ae7b2381aad1118a2 100644 (file)
@@ -48,6 +48,7 @@
 #include "gl/xvasprintf.h"
 
 #include "find-dialog.h"
+#include "options-dialog.h"
 #include "psppire-dialog-action-1sks.h"
 #include "psppire-dialog-action-aggregate.h"
 #include "psppire-dialog-action-autorecode.h"
@@ -1357,7 +1358,14 @@ create_edit_menu (PsppireDataWindow *dw)
   
     dw->mi_find = gtk_menu_item_new_with_mnemonic (_("_Find..."));
     g_signal_connect_swapped (dw->mi_find, "activate", G_CALLBACK (find_dialog), dw);
-    gtk_menu_attach (GTK_MENU (menu), dw->mi_find,      0, 1,  i, i + 1); ++i;
+    gtk_menu_attach (GTK_MENU (menu), dw->mi_find,    0, 1,  i, i + 1); ++i;
+  }
+
+  {
+    dw->mi_options = gtk_menu_item_new_with_mnemonic (_("_Options..."));
+    g_signal_connect_swapped (dw->mi_options, "activate",
+                             G_CALLBACK (options_dialog), dw);
+    gtk_menu_attach (GTK_MENU (menu), dw->mi_options, 0, 1,  i, i + 1); ++i;
   }
   
   g_object_set (menuitem, "submenu", menu, NULL);
index fa983fabf1129a2303e75f68b6a93a104264c16a..a632c8d1121f946db80a2b410edc3c7241e78c81 100644 (file)
@@ -88,7 +88,7 @@ struct _PsppireDataWindow
   GtkWidget *mi_insert_case;
   GtkWidget *mi_find;
   GtkWidget *mi_find_separator;
-
+  GtkWidget *mi_options;
 
   GtkWidget *mi_edit_separator ;
   GtkWidget *mi_cut;
index f550f413815b0c4f2528482cf40022d90948d609..37361455f81239556a90d31238604bb9f62da4ea 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2009, 2010, 2011, 2012, 2013  Free Software Foundation
+   Copyright (C) 2009, 2010, 2011, 2012, 2013, 2017  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
@@ -21,6 +21,7 @@
 #include "psppire-dict.h"
 #include "dict-display.h"
 #include "psppire-conf.h"
+#include "options-dialog.h"
 #include <data/format.h>
 #include <libpspp/i18n.h>
 #include "helper.h"
@@ -106,7 +107,6 @@ filter_variables (GtkTreeModel *tmodel, GtkTreeIter *titer, gpointer data)
   return predicate (var);
 }
 
-
 static gint
 unsorted (GtkTreeModel *model,
      GtkTreeIter *a,
@@ -154,6 +154,36 @@ sort_by_label (GtkTreeModel *model,
   return g_strcmp0 (var_get_label (var_a), var_get_label (var_b));
 }
 
+
+static gint
+default_sort (GtkTreeModel *model,
+     GtkTreeIter *a,
+     GtkTreeIter *b,
+     gpointer user_data)
+{
+  int what = -1;
+  psppire_conf_get_enum (psppire_conf_new (), "VariableLists", "sort-order",
+                        PSPP_TYPE_OPTIONS_VAR_ORDER, &what);
+
+  switch (what)
+    {
+    default:
+      return unsorted (model, a, b, user_data);
+      break;
+    case PSPP_OPTIONS_VAR_ORDER_NAME:
+      return sort_by_name (model, a, b, user_data);
+      break;
+    case PSPP_OPTIONS_VAR_ORDER_LABEL:
+      return sort_by_label (model, a, b, user_data);
+      break;
+    }
+
+  g_assert_not_reached ();
+}
+
+
+
+
 static void
 set_model (PsppireDictView *dict_view)
 {
@@ -163,7 +193,7 @@ set_model (PsppireDictView *dict_view)
     return;
 
   dict_view->sorted_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (dict_view->dict));
-  gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (dict_view->sorted_model), unsorted, dict_view, 0);
+  gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (dict_view->sorted_model), default_sort, dict_view, 0);
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dict_view->sorted_model), 
                                        GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
 
@@ -307,7 +337,24 @@ psppire_dict_view_base_finalize (PsppireDictViewClass *class,
 
 }
 
+static gboolean
+use_labels (PsppireDictView *dv)
+{
+  gboolean disp_labels = TRUE;
 
+  if (gtk_check_menu_item_get_inconsistent (GTK_CHECK_MENU_ITEM
+                                           (dv->override_button)))
+    {
+      psppire_conf_get_boolean (psppire_conf_new (),
+                               "VariableLists", "display-labels", &disp_labels);
+    }
+  else
+    {
+      disp_labels = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM
+                                                   (dv->override_button));
+    }
+  return disp_labels;
+}
 
 
 /* A GtkTreeCellDataFunc which renders the name and/or label of the
@@ -329,7 +376,7 @@ var_description_cell_data_func (GtkTreeViewColumn *col,
   gtk_tree_model_get (model,
                      &iter, DICT_TVM_COL_VAR, &var, -1);
 
-  if ( var_has_label (var) && dv->prefer_labels)
+  if (var_has_label (var) && use_labels (dv))
     {
       gchar *text = g_markup_printf_escaped (
                                     "<span stretch=\"condensed\">%s</span>",
@@ -453,7 +500,7 @@ set_tooltip_for_variable (GtkTreeView  *treeview,
 
     get_base_model (tree_model, NULL, &m, NULL);
 
-    if ( PSPPIRE_DICT_VIEW (treeview)->prefer_labels )
+    if ( use_labels (PSPPIRE_DICT_VIEW (treeview)))
       tip = var_get_name (var);
     else
       tip = var_get_label (var);
@@ -481,8 +528,15 @@ toggle_label_preference (GtkCheckMenuItem *checkbox, gpointer data)
 {
   PsppireDictView *dv = PSPPIRE_DICT_VIEW (data);
 
-  dv->prefer_labels = gtk_check_menu_item_get_active (checkbox);
+  gboolean global_setting = TRUE;
+  psppire_conf_get_boolean (psppire_conf_new (),
+                           "VariableLists", "display-labels", &global_setting);
 
+  if (gtk_check_menu_item_get_inconsistent (checkbox))
+    gtk_check_menu_item_set_active (checkbox, !global_setting);
+  
+  gtk_check_menu_item_set_inconsistent (checkbox, FALSE);
+  
   gtk_widget_queue_draw (GTK_WIDGET (dv));
 }
 
@@ -503,6 +557,14 @@ set_sort_criteria (GtkCheckMenuItem *checkbox, PsppireDictView *dv, GtkTreeIterC
   gtk_widget_queue_draw (GTK_WIDGET (dv));
 }
 
+static void
+set_sort_criteria_default (GtkCheckMenuItem *checkbox, gpointer data)
+{
+  PsppireDictView *dv = PSPPIRE_DICT_VIEW (data);
+  set_sort_criteria (checkbox, dv, default_sort);
+}
+
+
 static void
 set_sort_criteria_name (GtkCheckMenuItem *checkbox, gpointer data)
 {
@@ -535,14 +597,9 @@ psppire_dict_view_init (PsppireDictView *dict_view)
 
   GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new ();
 
-  dict_view->prefer_labels = TRUE;
+  dict_view->prefer_labels_override = FALSE;
   dict_view->sorted_model = NULL;
 
-  psppire_conf_get_boolean (psppire_conf_new (),
-                           G_OBJECT_TYPE_NAME (dict_view),
-                           "prefer-labels",
-                           &dict_view->prefer_labels);
-
   gtk_tree_view_column_set_title (col, _("Variable"));
 
   gtk_tree_view_column_pack_start (col, renderer, FALSE);
@@ -577,15 +634,15 @@ psppire_dict_view_init (PsppireDictView *dict_view)
 
   dict_view->menu = gtk_menu_new ();
 
-
   {
     GSList *group = NULL;
     GtkWidget *item =
       gtk_check_menu_item_new_with_label  (_("Prefer variable labels"));
 
-    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
-                                   dict_view->prefer_labels);
-
+    dict_view->override_button = item;
+    gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (item),
+                                         TRUE);
+    
     g_signal_connect (item, "toggled",
                      G_CALLBACK (toggle_label_preference), dict_view);
 
@@ -594,10 +651,15 @@ psppire_dict_view_init (PsppireDictView *dict_view)
     item = gtk_separator_menu_item_new ();
     gtk_menu_shell_append (GTK_MENU_SHELL (dict_view->menu), item);
 
-    item = gtk_radio_menu_item_new_with_label (group, _("Unsorted (dictionary order)"));
+    item = gtk_radio_menu_item_new_with_label (group, _("Default sort order"));
     group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
     gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
     gtk_menu_shell_append (GTK_MENU_SHELL (dict_view->menu), item);
+    g_signal_connect (item, "toggled", G_CALLBACK (set_sort_criteria_default), dict_view);
+
+    item = gtk_radio_menu_item_new_with_label (group, _("Unsorted (dictionary order)"));
+    group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
+    gtk_menu_shell_append (GTK_MENU_SHELL (dict_view->menu), item);
     g_signal_connect (item, "toggled", G_CALLBACK (set_sort_criteria_unsorted), dict_view);
 
     item = gtk_radio_menu_item_new_with_label (group, _("Sort by name"));
index 622ed6135cb9670f7be3c19a594bad12298c4366..9855bb94d70952f7d21507ab7d66ae461add6f79 100644 (file)
@@ -51,7 +51,8 @@ struct _PsppireDictView
   PsppireDict *dict;
   var_predicate_func *predicate;
   GtkWidget *menu;
-  gboolean prefer_labels;
+  gboolean prefer_labels_override;
+  GtkWidget *override_button;
   GtkTreeModel *sorted_model;
 };