Blame SOURCES/0016-session-selector-add-toggle-for-classic-normal-selec.patch

f47161
From 9be62bd711a09cdab0cb7f27faa1504b5afe7c76 Mon Sep 17 00:00:00 2001
b31790
From: Ray Strode <rstrode@redhat.com>
b31790
Date: Tue, 7 Jan 2014 21:02:02 -0500
b31790
Subject: [PATCH 16/19] session-selector: add toggle for classic/normal
b31790
 selection
b31790
b31790
Since we offer both classic mode and regular mode when
b31790
not using the session selector, we should also offer it
b31790
when using the session selector.
b31790
---
f47161
 data/session-selector.ui       |  39 +++++++++++-
f47161
 tools/gnome-session-selector.c | 106 +++++++++++++++++++++++++++++++++
b31790
 2 files changed, 143 insertions(+), 2 deletions(-)
b31790
b31790
diff --git a/data/session-selector.ui b/data/session-selector.ui
b31790
index 4d1e3009..beab73a1 100644
b31790
--- a/data/session-selector.ui
b31790
+++ b/data/session-selector.ui
b31790
@@ -153,71 +153,106 @@
b31790
                                 <property name="fill">False</property>
b31790
                                 <property name="position">2</property>
b31790
                               </packing>
b31790
                             </child>
b31790
                           </object>
b31790
                           <packing>
b31790
                             <property name="expand">False</property>
b31790
                             <property name="fill">True</property>
b31790
                             <property name="position">1</property>
b31790
                           </packing>
b31790
                         </child>
b31790
                       </object>
b31790
                       <packing>
b31790
                         <property name="expand">True</property>
b31790
                         <property name="fill">True</property>
b31790
                         <property name="position">1</property>
b31790
                       </packing>
b31790
                     </child>
b31790
                   </object>
b31790
                   <packing>
b31790
                     <property name="expand">True</property>
b31790
                     <property name="fill">True</property>
b31790
                     <property name="position">1</property>
b31790
                   </packing>
b31790
                 </child>
b31790
                 <child>
b31790
                   <object class="GtkHButtonBox" id="hbuttonbox2">
b31790
                     <property name="visible">True</property>
b31790
                     <property name="can_focus">False</property>
b31790
                     <property name="spacing">6</property>
b31790
-                    <property name="layout_style">end</property>
b31790
+                    <child>
b31790
+                      <object class="GtkBox" id="box1">
b31790
+                        <property name="visible">True</property>
b31790
+                        <property name="can_focus">False</property>
b31790
+                        <property name="spacing">6</property>
b31790
+                        <child>
b31790
+                          <object class="GtkLabel" id="classic-mode-label">
b31790
+                            <property name="visible">True</property>
b31790
+                            <property name="can_focus">False</property>
b31790
+                            <property name="label" translatable="yes">Classic Experience</property>
b31790
+                          </object>
b31790
+                          <packing>
b31790
+                            <property name="expand">False</property>
b31790
+                            <property name="fill">True</property>
b31790
+                            <property name="position">0</property>
b31790
+                          </packing>
b31790
+                        </child>
b31790
+                        <child>
b31790
+                          <object class="GtkSwitch" id="classic-mode-switch">
b31790
+                            <property name="visible">True</property>
b31790
+                            <property name="can_focus">True</property>
b31790
+                          </object>
b31790
+                          <packing>
b31790
+                            <property name="expand">False</property>
b31790
+                            <property name="fill">True</property>
b31790
+                            <property name="position">1</property>
b31790
+                          </packing>
b31790
+                        </child>
b31790
+                      </object>
b31790
+                      <packing>
b31790
+                        <property name="expand">False</property>
b31790
+                        <property name="fill">True</property>
b31790
+                        <property name="position">0</property>
b31790
+                      </packing>
b31790
+                    </child>
b31790
                     <child>
b31790
                       <object class="GtkButton" id="continue-button">
b31790
                         <property name="label" translatable="yes">_Continue</property>
b31790
                         <property name="visible">True</property>
b31790
                         <property name="can_focus">True</property>
b31790
                         <property name="can_default">True</property>
b31790
                         <property name="has_default">True</property>
b31790
                         <property name="receives_default">True</property>
b31790
                         <property name="use_underline">True</property>
b31790
                       </object>
b31790
                       <packing>
b31790
                         <property name="expand">False</property>
b31790
                         <property name="fill">False</property>
b31790
-                        <property name="position">0</property>
b31790
+                        <property name="position">1</property>
b31790
+                        <property name="non_homogeneous">True</property>
b31790
                       </packing>
b31790
                     </child>
b31790
                   </object>
b31790
                   <packing>
b31790
                     <property name="expand">False</property>
b31790
                     <property name="fill">True</property>
b31790
                     <property name="position">2</property>
b31790
                   </packing>
b31790
                 </child>
b31790
               </object>
b31790
             </child>
b31790
           </object>
b31790
         </child>
b31790
       </object>
b31790
     </child>
b31790
   </object>
b31790
   <object class="GtkListStore" id="session-store">
b31790
     <columns>
b31790
       
b31790
       <column type="gchararray"/>
b31790
     </columns>
b31790
   </object>
b31790
   <object class="GtkTreeModelSort" id="sort-model">
b31790
     <property name="model">session-store</property>
b31790
   </object>
b31790
 </interface>
b31790
diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c
b31790
index 53822f6c..a7361a5b 100644
b31790
--- a/tools/gnome-session-selector.c
b31790
+++ b/tools/gnome-session-selector.c
b31790
@@ -16,60 +16,61 @@
b31790
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
b31790
  *
b31790
  * Written by: Matthias Clasen <mclasen@redhat.com>
b31790
  */
b31790
 
b31790
 #include "config.h"
b31790
 
b31790
 #include <fcntl.h>
b31790
 #include <stdlib.h>
b31790
 #include <string.h>
b31790
 #include <sys/types.h>
b31790
 #include <sys/stat.h>
b31790
 #include <unistd.h>
b31790
 
b31790
 #include <glib.h>
b31790
 #include <gtk/gtk.h>
b31790
 #include <gio/gio.h>
b31790
 
b31790
 #include <glib/gi18n.h>
b31790
 #include <glib/gstdio.h>
b31790
 
b31790
 #include <dbus/dbus-glib.h>
b31790
 #include <dbus/dbus-glib-lowlevel.h>
b31790
 
b31790
 #define GSM_SERVICE_DBUS   "org.gnome.SessionManager"
b31790
 #define GSM_PATH_DBUS      "/org/gnome/SessionManager"
b31790
 #define GSM_INTERFACE_DBUS "org.gnome.SessionManager"
b31790
 
b31790
 #define GSM_MANAGER_SCHEMA        "org.gnome.SessionManager"
b31790
 #define KEY_AUTOSAVE_ONE_SHOT     "auto-save-session-one-shot"
b31790
+#define DEFAULT_SESSION_NAME      "gnome"
b31790
 
b31790
 static GtkBuilder *builder;
b31790
 static GtkWidget *session_list;
b31790
 static GtkListStore *store;
b31790
 static GtkTreeModelSort *sort_model;
b31790
 static char *info_text;
b31790
 
b31790
 static void select_session (const char *name);
b31790
 static gboolean make_session_current (const char *name);
b31790
 
b31790
 static char *
b31790
 get_session_path (const char *name)
b31790
 {
b31790
         return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL);
b31790
 }
b31790
 
b31790
 static char *
b31790
 find_new_session_name (void)
b31790
 {
b31790
         char *name;
b31790
         char *path;
b31790
         int i;
b31790
 
b31790
         for (i = 1; i < 20; i++) {
b31790
                 name = g_strdup_printf (_("Session %d"), i);
b31790
                 path = get_session_path (name);
b31790
                 if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
b31790
                         g_free (path);
b31790
                         return name;
b31790
                 }
b31790
@@ -125,104 +126,126 @@ is_valid_session_name (const char *name)
b31790
         gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
b31790
         do {
b31790
                 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &n, -1);
b31790
                 if (strcmp (n, name) == 0) {
b31790
                         char *message;
b31790
                         message = g_strdup_printf (_("A session named “%s” already exists"), name);
b31790
                         warning_text = g_strdup_printf ("%s\n<small>Note: %s</small>", info_text, message);
b31790
                         g_free (message);
b31790
                         g_free (n);
b31790
                         break;
b31790
                 }
b31790
                 g_free (n);
b31790
         } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
b31790
 
b31790
         info_bar = (GtkWidget *) gtk_builder_get_object (builder, "info-bar");
b31790
         label = (GtkWidget*) gtk_builder_get_object (builder, "info-label");
b31790
 
b31790
         if (warning_text != NULL) {
b31790
             gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
b31790
             gtk_label_set_markup (GTK_LABEL (label), warning_text);
b31790
             g_free (warning_text);
b31790
             return FALSE;
b31790
         }
b31790
 
b31790
         gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_OTHER);
b31790
         gtk_label_set_markup (GTK_LABEL (label), info_text);
b31790
 
b31790
         return TRUE;
b31790
 }
b31790
 
b31790
+static char *
b31790
+get_session_type_from_file (const char *name)
b31790
+{
b31790
+        char *file;
b31790
+        char *type;
b31790
+        gboolean loaded;
b31790
+
b31790
+        file = g_build_filename (g_get_user_config_dir (), "gnome-session", name, "type", NULL);
b31790
+        loaded = g_file_get_contents (file, &type, NULL, NULL);
b31790
+        g_free (file);
b31790
+
b31790
+        if (!loaded)
b31790
+                return g_strdup (DEFAULT_SESSION_NAME);
b31790
+
b31790
+        return type;
b31790
+}
b31790
+
b31790
 static void
b31790
 populate_session_list (GtkWidget *session_list)
b31790
 {
b31790
         GtkTreeIter iter;
b31790
         char *path;
b31790
         const char *name;
b31790
         GDir *dir;
b31790
         GError *error;
b31790
         char *saved_session;
b31790
         char *default_session;
b31790
         char *default_name;
b31790
         char last_session[PATH_MAX] = "";
b31790
 
b31790
         saved_session = get_session_path ("saved-session");
b31790
 
b31790
         if (!g_file_test (saved_session, G_FILE_TEST_IS_SYMLINK)) {
b31790
                 default_name = find_new_session_name ();
b31790
                 default_session = get_session_path (default_name);
b31790
                 rename (saved_session, default_session);
b31790
                 if (symlink (default_name, saved_session) < 0)
b31790
                         g_warning ("Failed to convert saved-session to symlink");
b31790
                 g_free (default_name);
b31790
                 g_free (default_session);
b31790
         }
b31790
 
b31790
         path = g_build_filename (g_get_user_config_dir (), "gnome-session", NULL);
b31790
         error = NULL;
b31790
         dir = g_dir_open (path, 0, &error);
b31790
         if (dir == NULL) {
b31790
                 g_warning ("Failed to open %s: %s", path, error->message);
b31790
                 g_error_free (error);
b31790
                 goto out;
b31790
         }
b31790
 
b31790
         default_name = NULL;
b31790
         if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) {
b31790
                 default_name = g_path_get_basename (last_session);
b31790
         }
b31790
 
b31790
         while ((name = g_dir_read_name (dir)) != NULL) {
b31790
+                char *session_type;
b31790
+
b31790
                 if (strcmp (name, "saved-session") == 0)
b31790
                         continue;
b31790
 
b31790
+                session_type = get_session_type_from_file (name);
b31790
+
b31790
                 gtk_list_store_insert_with_values (store, &iter, 100, 0, name, -1);
b31790
+                g_free (session_type);
b31790
 
b31790
                 if (g_strcmp0 (default_name, name) == 0) {
b31790
                         GtkTreeSelection *selection;
b31790
                         GtkTreeIter child_iter;
b31790
 
b31790
                         gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (sort_model), &child_iter, &iter);
b31790
                         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list));
b31790
                         gtk_tree_selection_select_iter (selection, &child_iter);
b31790
                 }
b31790
         }
b31790
 
b31790
         g_free (default_name);
b31790
         g_dir_close (dir);
b31790
 
b31790
  out:
b31790
         g_free (saved_session);
b31790
         g_free (path);
b31790
 }
b31790
 
b31790
 static char *
b31790
 get_last_session (void)
b31790
 {
b31790
         char *saved_session;
b31790
         char last_session[PATH_MAX] = "";
b31790
         char *name = NULL;
b31790
 
b31790
         saved_session = get_session_path ("saved-session");
b31790
 
b31790
         if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) {
b31790
                 name = g_path_get_basename (last_session);
b31790
@@ -260,60 +283,136 @@ remove_session (const char *name)
b31790
         GError *error;
b31790
 
b31790
         path1 = get_session_path ("saved-session");
b31790
         path2 = get_session_path (name);
b31790
 
b31790
         error = NULL;
b31790
         n = g_file_read_link (path1, &error);
b31790
         if (n == NULL) {
b31790
                 g_warning ("Failed to read link: %s", error->message);
b31790
                 g_error_free (error);
b31790
         }
b31790
         else if (strcmp (n, name) == 0) {
b31790
                 unlink (path1);
b31790
         }
b31790
         g_free (n);
b31790
 
b31790
         dir = g_dir_open (path2, 0, NULL);
b31790
         while ((d = g_dir_read_name (dir)) != NULL) {
b31790
                 path = g_build_filename (path2, d, NULL);
b31790
                 unlink (path);
b31790
                 g_free (path);
b31790
         }
b31790
         g_dir_close (dir);
b31790
 
b31790
         remove (path2);
b31790
 
b31790
         g_free (path1);
b31790
         g_free (path2);
b31790
 }
b31790
 
b31790
+static const char *
b31790
+get_session_type_from_switch (void)
b31790
+{
b31790
+        GtkWidget *mode_switch;
b31790
+        gboolean is_classic_mode;
b31790
+
b31790
+        mode_switch = (GtkWidget *)gtk_builder_get_object (builder, "classic-mode-switch");
b31790
+
b31790
+        is_classic_mode = gtk_switch_get_active (GTK_SWITCH (mode_switch));
b31790
+
b31790
+        if (is_classic_mode) {
b31790
+                return "gnome-classic";
b31790
+        } else {
b31790
+                return "gnome";
b31790
+        }
b31790
+}
b31790
+
b31790
+static void
b31790
+set_mode_switch_from_session_type_file (const char *name)
b31790
+{
b31790
+        GtkWidget *mode_switch;
b31790
+        gboolean is_classic_mode = FALSE;
b31790
+        char *type;
b31790
+
b31790
+        mode_switch = (GtkWidget *)gtk_builder_get_object (builder, "classic-mode-switch");
b31790
+
b31790
+        type = get_session_type_from_file (name);
b31790
+        is_classic_mode = strcmp (type, "gnome-classic") == 0;
b31790
+        g_free (type);
b31790
+
b31790
+        gtk_switch_set_active (GTK_SWITCH (mode_switch), is_classic_mode);
b31790
+}
b31790
+
b31790
+static void
b31790
+save_session_type (const char *save_dir,
b31790
+                   const char *type)
b31790
+{
b31790
+        char *file;
b31790
+        GError *error;
b31790
+
b31790
+        file = g_build_filename (save_dir, "type", NULL);
b31790
+
b31790
+        error = NULL;
b31790
+        g_file_set_contents (file, type, strlen (type), &error);
b31790
+        if (error != NULL)
b31790
+                g_warning ("couldn't save session type to %s: %s",
b31790
+                           type, error->message);
b31790
+
b31790
+        g_free (file);
b31790
+}
b31790
+
b31790
+static void
b31790
+save_session_type_from_switch (void)
b31790
+{
b31790
+        char *name, *path;
b31790
+        const char *session_type;
b31790
+
b31790
+        name = get_selected_session ();
b31790
+
b31790
+        if (name == NULL) {
b31790
+                return;
b31790
+        }
b31790
+
b31790
+        path = get_session_path (name);
b31790
+        g_free (name);
b31790
+
b31790
+        session_type = get_session_type_from_switch ();
b31790
+        save_session_type (path, session_type);
b31790
+}
b31790
+
b31790
+static void
b31790
+on_mode_switched (GtkSwitch *mode_switch)
b31790
+{
b31790
+        save_session_type_from_switch ();
b31790
+}
b31790
+
b31790
 static gboolean
b31790
 make_session_current (const char *name)
b31790
 {
b31790
         char *path1;
b31790
         gboolean ret = TRUE;
b31790
 
b31790
         path1 = g_build_filename (g_get_user_config_dir (), "gnome-session", "saved-session", NULL);
b31790
 
b31790
         unlink (path1);
b31790
         if (symlink (name, path1) < 0) {
b31790
                 g_warning ("Failed to make session '%s' current", name);
b31790
                 ret = FALSE;
b31790
         }
b31790
 
b31790
         g_free (path1);
b31790
 
b31790
         return ret;
b31790
 }
b31790
 
b31790
 static void
b31790
 on_remove_session_clicked (GtkButton *button,
b31790
                            gpointer   data)
b31790
 {
b31790
         GtkTreeSelection *selection;
b31790
         GtkTreeModel *model;
b31790
         GtkTreeIter iter;
b31790
         char *name;
b31790
 
b31790
         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list));
b31790
         if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
b31790
@@ -492,60 +591,62 @@ static void
b31790
 create_session_and_begin_rename (void)
b31790
 {
b31790
         gchar *name;
b31790
 
b31790
         name = find_new_session_name ();
b31790
         create_session (name);
b31790
         select_session (name);
b31790
 
b31790
         begin_rename ();
b31790
 }
b31790
 
b31790
 static void
b31790
 on_new_session_clicked (GtkButton *button,
b31790
                         gpointer   data)
b31790
 {
b31790
 	create_session_and_begin_rename ();
b31790
 }
b31790
 
b31790
 static void
b31790
 on_selection_changed (GtkTreeSelection *selection,
b31790
                       gpointer          data)
b31790
 {
b31790
         char *name;
b31790
 
b31790
         name = get_selected_session ();
b31790
 
b31790
         if (name == NULL) {
b31790
                 return;
b31790
         }
b31790
 
b31790
+        set_mode_switch_from_session_type_file (name);
b31790
+
b31790
         g_free (name);
b31790
 }
b31790
 
b31790
 static void
b31790
 update_remove_button (void)
b31790
 {
b31790
         GtkWidget *button;
b31790
 
b31790
         button = (GtkWidget *)gtk_builder_get_object (builder, "remove-session");
b31790
         if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1) {
b31790
                 gtk_widget_set_sensitive (button, TRUE);
b31790
         } else {
b31790
                 gtk_widget_set_sensitive (button, FALSE);
b31790
         }
b31790
 }
b31790
 
b31790
 static void
b31790
 on_row_edited (GtkCellRendererText *cell,
b31790
                const char          *path_string,
b31790
                const char          *new_name,
b31790
                gpointer             data)
b31790
 {
b31790
         GtkTreePath *path;
b31790
         GtkTreeIter  sort_iter, items_iter;
b31790
         char        *old_name;
b31790
         gboolean     was_renamed;
b31790
 
b31790
         path = gtk_tree_path_new_from_string (path_string);
b31790
         gtk_tree_model_get_iter (GTK_TREE_MODEL (sort_model), &sort_iter, path);
b31790
 
b31790
@@ -751,75 +852,80 @@ main (int argc, char *argv[])
b31790
         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
b31790
                                               0, GTK_SORT_ASCENDING);
b31790
         g_signal_connect (store, "row-deleted", G_CALLBACK (on_row_deleted), NULL);
b31790
         g_signal_connect (store, "row-inserted", G_CALLBACK (on_row_inserted), NULL);
b31790
         session_list = (GtkWidget *) gtk_builder_get_object (builder, "session-list");
b31790
 
b31790
         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list));
b31790
         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
b31790
 
b31790
         populate_session_list (session_list);
b31790
 
b31790
         cell = gtk_cell_renderer_text_new ();
b31790
         g_signal_connect (cell, "edited", G_CALLBACK (on_row_edited), NULL);
b31790
 
b31790
         column = gtk_tree_view_column_new_with_attributes ("", cell, "text", 0, NULL);
b31790
         gtk_tree_view_append_column (GTK_TREE_VIEW (session_list), GTK_TREE_VIEW_COLUMN (column));
b31790
 
b31790
         g_signal_connect (session_list, "row-activated", G_CALLBACK (on_row_activated), NULL);
b31790
 
b31790
         g_signal_connect (selection, "changed",
b31790
                           G_CALLBACK (on_selection_changed), NULL);
b31790
 
b31790
         widget = (GtkWidget *) gtk_builder_get_object (builder, "new-session");
b31790
         g_signal_connect (widget, "clicked", G_CALLBACK (on_new_session_clicked), NULL);
b31790
         widget = (GtkWidget *) gtk_builder_get_object (builder, "remove-session");
b31790
         g_signal_connect (widget, "clicked", G_CALLBACK (on_remove_session_clicked), NULL);
b31790
         widget = (GtkWidget *) gtk_builder_get_object (builder, "rename-session");
b31790
         g_signal_connect (widget, "clicked", G_CALLBACK (on_rename_session_clicked), NULL);
b31790
         widget = (GtkWidget *) gtk_builder_get_object (builder, "continue-button");
b31790
         g_signal_connect (widget, "clicked", G_CALLBACK (on_continue_clicked), NULL);
b31790
+        widget = (GtkWidget *) gtk_builder_get_object (builder, "classic-mode-switch");
b31790
+        g_signal_connect (widget, "notify::active", G_CALLBACK (on_mode_switched), NULL);
b31790
 
b31790
         g_signal_connect (window, "map", G_CALLBACK (on_map), NULL);
b31790
         gtk_widget_show (window);
b31790
 
b31790
         if (g_strcmp0 (action, "load") == 0) {
b31790
             info_text = _("Please select a custom session to run");
b31790
         } else if (g_strcmp0 (action, "print") == 0) {
b31790
             info_text = _("Please select a session to use");
b31790
         } else if (g_strcmp0 (action, "save") == 0) {
b31790
             info_text = _("Please select a session to save to");
b31790
         }
b31790
 
b31790
         label = (GtkWidget*) gtk_builder_get_object (builder, "info-label");
b31790
         gtk_label_set_markup (GTK_LABEL (label), info_text);
b31790
 
b31790
         selected_session = get_selected_session ();
b31790
 
b31790
         if (selected_session == NULL) {
b31790
 		create_session_and_begin_rename ();
b31790
 	} else {
b31790
+                set_mode_switch_from_session_type_file (selected_session);
b31790
 		g_free (selected_session);
b31790
         }
b31790
 
b31790
         gtk_main ();
b31790
 
b31790
         selected_session = get_selected_session ();
b31790
 
b31790
         if (g_strcmp0 (action, "load") == 0) {
b31790
                 make_session_current (selected_session);
b31790
+                save_session_type_from_switch ();
b31790
                 auto_save_next_session_if_needed ();
b31790
         } else if (g_strcmp0 (action, "save") == 0) {
b31790
                 char *last_session;
b31790
 
b31790
                 last_session = get_last_session ();
b31790
                 make_session_current (selected_session);
b31790
                 save_session ();
b31790
+                save_session_type_from_switch ();
b31790
                 if (last_session != NULL)
b31790
                     make_session_current (last_session);
b31790
         } else if (g_strcmp0 (action, "print") == 0) {
b31790
                 g_print ("%s\n", selected_session);
b31790
         }
b31790
         g_free (selected_session);
b31790
 
b31790
         return 0;
b31790
 }
b31790
-- 
f47161
2.17.0
b31790