PsppireDelimitedText: Remove g_print statements
[pspp] / src / ui / gui / main.c
index 002d576ac5c1d5bbd1d55283e56a81a2260280e1..157a0dc8f4bd8ed94bfe4268df3bbe6c1fd62055 100644 (file)
@@ -1,10 +1,9 @@
-/*
-   PSPPIRE --- A Graphical User Interface for PSPP
-   Copyright (C) 2004, 2005, 2006  Free Software Foundation
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2004, 2005, 2006, 2010, 2011, 2012, 2013, 2014, 2015, 2016  Free Software Foundation
 
-   This program is free software; you can redistribute it and/or modify
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "ui/gui/psppire.h"
 
 #include <gtk/gtk.h>
-#include "psppire.h"
-#include "progname.h"
 #include <stdlib.h>
-#include <getopt.h>
 
-#include <libpspp/version.h>
-#include <libpspp/copyleft.h>
+#include "language/lexer/include-path.h"
+#include "libpspp/argv-parser.h"
+#include "libpspp/array.h"
+#include "libpspp/assertion.h"
+#include "libpspp/cast.h"
+#include "libpspp/copyleft.h"
+#include "libpspp/str.h"
+#include "libpspp/string-array.h"
+#include "libpspp/version.h"
+#include "ui/source-init-opts.h"
+#include "ui/gui/psppire-syntax-window.h"
+#include "ui/gui/psppire-data-window.h"
+#include "ui/gui/psppire-output-window.h"
 
-static gboolean parse_command_line (int *argc, char ***argv, gchar **filename,
-                                   gboolean *show_splash, GError **err);
+#include "gl/configmake.h"
+#include "gl/progname.h"
+#include "gl/relocatable.h"
+#include "gl/version-etc.h"
+#include "gl/xalloc.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
 
 
-static GtkWidget *
-create_splash_window (void)
+
+static gboolean
+show_version_and_exit ()
 {
-  GtkWidget *splash ;
-  GtkWidget *image;
+  version_etc (stdout, "psppire", PACKAGE_NAME, PACKAGE_VERSION,
+               "Ben Pfaff", "John Darrington", "Jason Stover", NULL_SENTINEL);
 
-  gtk_window_set_auto_startup_notification (FALSE);
+  exit (0);
 
-  splash = gtk_window_new (GTK_WINDOW_POPUP);
+  return TRUE;
+}
 
-  gtk_window_set_position (GTK_WINDOW (splash),
-                          GTK_WIN_POS_CENTER_ALWAYS);
+\f
 
-  image = gtk_image_new_from_file (PKGDATADIR "/splash.png");
+gboolean
+init_prepare (GSource * source, gint * timeout_)
+{
+  return TRUE;
+}
+
+gboolean
+init_check (GSource * source)
+{
+  return TRUE;
+}
 
-  gtk_container_add (GTK_CONTAINER (splash), image);
+gboolean
+init_dispatch (GSource * ss, GSourceFunc callback, gpointer user_data)
+{
+  struct init_source *is = (struct init_source *) ss;
 
-  gtk_widget_show (image);
+  bool finished = initialize (is);
+  is->state++;
 
-  return splash;
+  if (finished)
+    {
+      g_main_loop_quit (is->loop);
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
-static gboolean
-hide_splash_window (gpointer data)
+static GSourceFuncs init_funcs =
+  { init_prepare, init_check, init_dispatch, NULL };
+\f
+
+
+GtkWidget *wsplash = 0;
+gint64 start_time = 0;
+
+
+static GtkWidget *
+create_splash_window (void)
 {
-  GtkWidget *splash = data;
-  gtk_widget_hide (splash);
-  gtk_window_set_auto_startup_notification (TRUE);
-  return FALSE;
+  GtkWidget *sp = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+  const gchar *filename = PKGDATADIR "/splash.png";
+  const char *relocated_filename = relocate (filename);
+  GtkWidget *l = gtk_image_new_from_file (relocated_filename);
+  if (filename != relocated_filename)
+    free (CONST_CAST (char *, relocated_filename));
+
+  gtk_container_add (GTK_CONTAINER (sp), l);
+  gtk_window_set_type_hint (GTK_WINDOW (sp),
+                            GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
+  gtk_window_set_position (GTK_WINDOW (sp), GTK_WIN_POS_CENTER);
+  gtk_window_set_skip_pager_hint (GTK_WINDOW (sp), TRUE);
+  gtk_window_set_skip_taskbar_hint (GTK_WINDOW (sp), TRUE);
+  gtk_window_set_focus_on_map (GTK_WINDOW (sp), FALSE);
+  gtk_window_set_accept_focus (GTK_WINDOW (sp), FALSE);
+
+  GdkGeometry hints;
+  hints.max_height = 100;
+  hints.max_width = 200;
+  gtk_window_set_geometry_hints (GTK_WINDOW (sp),
+                                 NULL, &hints, GDK_HINT_MAX_SIZE);
+
+
+  gtk_window_set_gravity (GTK_WINDOW (sp), GDK_GRAVITY_CENTER);
+
+  gtk_window_set_modal (GTK_WINDOW (sp), TRUE);
+  gtk_window_set_decorated (GTK_WINDOW (sp), FALSE);
+  gtk_window_set_keep_above (GTK_WINDOW (sp), TRUE);
+  gtk_widget_show_all (sp);
+  return sp;
 }
 
 
-static gboolean
-quit_one_loop (gpointer data)
+static gint
+on_local_options (GApplication * application,
+                  GVariantDict * options, gpointer user_data)
 {
-  gtk_main_quit ();
-  return FALSE;
+  {
+    GVariant *b =
+      g_variant_dict_lookup_value (options, "no-unique",
+                                  G_VARIANT_TYPE_BOOLEAN);
+    if (b)
+      {
+       GApplicationFlags flags =  g_application_get_flags (application);
+       flags |= G_APPLICATION_NON_UNIQUE;
+       g_application_set_flags (application, flags);
+       g_variant_unref (b);
+      }
+  }
+  {
+    GVariant *b =
+      g_variant_dict_lookup_value (options, "no-splash",
+                                  G_VARIANT_TYPE_BOOLEAN);
+    if (b)
+      g_variant_unref (b);
+    else
+      start_time = g_get_monotonic_time ();
+  }
+
+
+  return -1;
 }
 
 
-static gboolean
-run_inner_loop (gpointer data)
+static void
+on_startup (GApplication * app, gpointer ud)
 {
-  initialize ();
+  GMainContext *context = g_main_context_new ();
+
+  if (start_time != 0)
+    {
+      wsplash = create_splash_window ();
+      gtk_application_add_window (GTK_APPLICATION (app),
+                                  GTK_WINDOW (wsplash));
+    }
+
+  GMainLoop *loop = g_main_loop_new (context, FALSE);
 
-  g_timeout_add (500, hide_splash_window, data);
+  GSource *ss = g_source_new (&init_funcs, sizeof (struct init_source));
 
-  gtk_main ();
+  ((struct init_source *) ss)->loop = loop;
+  ((struct init_source *) ss)->state = 0;
 
-  de_initialize ();
+  g_source_set_priority (ss, G_PRIORITY_DEFAULT);
 
-  return FALSE;
+  g_source_attach (ss, context);
+  g_main_loop_run (loop);
 }
 
 
+static void
+post_initialise (GApplication * app)
+{
+  register_selection_functions ();
+  psppire_output_window_setup ();
 
-int
-main (int argc, char *argv[])
+  GSimpleAction *quit = g_simple_action_new ("quit", NULL);
+  g_signal_connect_swapped (quit, "activate", G_CALLBACK (psppire_quit), app);
+  g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (quit));
+}
+
+
+#define SPLASH_DURATION 1000
+
+static gboolean
+destroy_splash (gpointer ud)
 {
-  GtkWidget *splash_window;
-  gchar *filename = 0;
-  gboolean show_splash = TRUE;
-  GError *err = 0;
-  gchar *vers;
+  GtkWidget *sp = GTK_WIDGET (ud);
+  gtk_widget_destroy (sp);
+  wsplash = NULL;
+  return G_SOURCE_REMOVE;
+}
 
-  set_program_name (argv[0]);
 
-  if ( ! gtk_parse_args (&argc, &argv) )
+static void
+wait_for_splash (GApplication *app, GtkWindow *x)
+{
+  if (wsplash)
     {
-      perror ("Error parsing arguments");
-      exit (1);
+      gtk_window_set_transient_for (GTK_WINDOW (wsplash), x);
+      gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (wsplash));
+      gtk_window_set_keep_above (GTK_WINDOW (wsplash), TRUE);
+      gtk_window_present (GTK_WINDOW (wsplash));
+
+      /* Remove the splash screen after SPLASH_DURATION milliseconds */
+      gint64 elapsed_time = (g_get_monotonic_time () - start_time) / 1000;
+      if (SPLASH_DURATION - elapsed_time <= 0)
+       destroy_splash (wsplash);
+      else
+       g_timeout_add (SPLASH_DURATION - elapsed_time, destroy_splash, wsplash);
     }
+}
 
-  if ( (vers = gtk_check_version (GTK_MAJOR_VERSION,
-                                GTK_MINOR_VERSION,
-                                GTK_MICRO_VERSION)) )
-    {
-      g_critical (vers);
-    }
 
-  /* Deal with options like --version, --help etc */
-  if ( ! parse_command_line (&argc, &argv, &filename, &show_splash, &err) )
-    {
-      g_clear_error (&err);
-      return 0;
-    }
+static void
+on_activate (GApplication * app, gpointer ud)
+{
+  post_initialise (app);
 
-  gdk_init (&argc, &argv);
+  GtkWindow *x = create_data_window ();
+  gtk_application_add_window (GTK_APPLICATION (app), x);
 
-  splash_window = create_splash_window ();
-  if ( show_splash )
-    gtk_widget_show (splash_window);
+  wait_for_splash (app, x);
+}
 
-  gtk_idle_add (quit_one_loop, 0);
 
-  gtk_quit_add (0, run_inner_loop, splash_window);
-  gtk_main ();
+static void
+on_open (GApplication *app, GFile **files, gint n_files, gchar * hint,
+         gpointer ud)
+{
+  post_initialise (app);
 
+  gchar *file = g_file_get_parse_name (files[0]);
+  GtkWindow *x = psppire_preload_file (file);
+  g_free (file);
 
-  return 0;
+  wait_for_splash (app, x);
 }
 
 
-/* Parses the command line specified by ARGC and ARGV as received by
-   main ().  Returns true if normal execution should proceed,
-   false if the command-line indicates that PSPP should exit. */
-static gboolean
-parse_command_line (int *argc, char ***argv, gchar **filename,
-                   gboolean *show_splash, GError **err)
+/* These are arguments which must be processed BEFORE the X server has been initialised */
+static void
+process_pre_start_arguments (int *argc, char ***argv)
 {
+  GOptionEntry oe[] = {
+    {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
+     show_version_and_exit, N_("Show version information and exit"), 0},
+    {NULL}
+  };
+
+  GOptionContext *oc = g_option_context_new ("");
+  g_option_context_set_help_enabled (oc, FALSE);
+  g_option_context_set_ignore_unknown_options (oc, FALSE);
+  g_option_context_add_main_entries (oc, oe, NULL);
+  g_option_context_parse (oc, argc, argv, NULL);
+}
 
-  static struct option long_options[] =
-    {
-      {"help", no_argument, NULL, 'h'},
-      {"version", no_argument, NULL, 'V'},
-      {"no-splash", no_argument, NULL, 'q'},
-      {0, 0, 0, 0},
-    };
-
-  int c;
-
-  for (;;)
-    {
-      c = getopt_long (*argc, *argv, "hVq", long_options, NULL);
-      if (c == -1)
-       break;
-
-      switch (c)
-       {
-       case 'h':
-         g_print ("Usage: psppire {|--help|--version|--no-splash}\n");
-          return FALSE;
-       case 'V':
-         g_print (version);
-         g_print ("\n");
-         g_print (legal);
-         return FALSE;
-       case 'q':
-         *show_splash = FALSE;
-         break;
-       default:
-         return FALSE;
-       }
-    }
 
-  if ( optind < *argc)
-    {
-      *filename = (*argv)[optind];
-    }
+int
+main (int argc, char *argv[])
+{
+  set_program_name (argv[0]);
 
-  return TRUE;
+  GtkApplication *app =
+    gtk_application_new ("gnu.pspp", G_APPLICATION_HANDLES_OPEN);
+
+  process_pre_start_arguments (&argc, &argv);
+
+  GOptionEntry oe[] = {
+    {"no-splash", 'q', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL,
+      N_("Do not display the splash screen"), 0},
+    {"no-unique", 'n', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL,
+      N_("Do not attempt single instance negotiation"), 0},
+    {NULL}
+  };
+
+  g_application_add_main_option_entries (G_APPLICATION (app), oe);
+
+  g_signal_connect (app, "startup", G_CALLBACK (on_startup), NULL);
+  g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
+  g_signal_connect (app, "handle-local-options",
+                    G_CALLBACK (on_local_options), NULL);
+  g_signal_connect (app, "open", G_CALLBACK (on_open), NULL);
+
+  {
+    GSimpleAction *act_new_syntax = g_simple_action_new ("new-syntax", NULL);
+    g_signal_connect_swapped (act_new_syntax, "activate",
+                              G_CALLBACK (create_syntax_window), NULL);
+    g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_new_syntax));
+  }
+
+  {
+    GSimpleAction *act_new_data = g_simple_action_new ("new-data", NULL);
+    g_signal_connect_swapped (act_new_data, "activate",
+                              G_CALLBACK (create_data_window), NULL);
+    g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_new_data));
+  }
+
+  return g_application_run (G_APPLICATION (app), argc, argv);
 }