+typedef struct {
+ VikStatusbar *vs;
+ vik_statusbar_type_t vs_type;
+ gchar* message; // Always make a copy of this data
+} statusbar_idle_data;
+
+/**
+ * For the actual statusbar update!
+ */
+static gboolean statusbar_idle_update ( statusbar_idle_data *sid )
+{
+ vik_statusbar_set_message ( sid->vs, sid->vs_type, sid->message );
+ g_free ( sid->message );
+ g_free ( sid );
+ return FALSE;
+}
+
+/**
+ * vik_window_statusbar_update:
+ * @vw: The main window in which the statusbar will be updated.
+ * @message: The string to be displayed. This is copied.
+ * @vs_type: The part of the statusbar to be updated.
+ *
+ * This updates any part of the statusbar with the new string.
+ * It handles calling from the main thread or any background thread
+ * ATM this mostly used from background threads - as from the main thread
+ * one may use the vik_statusbar_set_message() directly.
+ */
+void vik_window_statusbar_update ( VikWindow *vw, const gchar* message, vik_statusbar_type_t vs_type )
+{
+ statusbar_idle_data *sid = g_malloc ( sizeof (statusbar_idle_data) );
+ sid->vs = vw->viking_vs;
+ sid->vs_type = vs_type;
+ sid->message = g_strdup ( message );
+
+ if ( g_thread_self() == vik_window_get_thread ( vw ) ) {
+ g_idle_add ( (GSourceFunc) statusbar_idle_update, sid );
+ }
+ else {
+ // From a background thread
+ gdk_threads_add_idle ( (GSourceFunc) statusbar_idle_update, sid );
+ }
+}
+
+// Actual signal handlers
+static void destroy_window ( GtkWidget *widget,
+ gpointer data )
+{
+ if ( ! --window_count )
+ gtk_main_quit ();
+}
+
+#define VIK_SETTINGS_WIN_SIDEPANEL "window_sidepanel"
+#define VIK_SETTINGS_WIN_STATUSBAR "window_statusbar"
+#define VIK_SETTINGS_WIN_TOOLBAR "window_toolbar"
+// Menubar setting to off is never auto saved in case it's accidentally turned off
+// It's not so obvious so to recover the menu visibility.
+// Thus this value is for setting manually via editting the settings file directly
+#define VIK_SETTINGS_WIN_MENUBAR "window_menubar"
+
+VikWindow *vik_window_new_window ()
+{
+ if ( window_count < MAX_WINDOWS )
+ {
+ VikWindow *vw = window_new ();
+
+ g_signal_connect (G_OBJECT (vw), "destroy",
+ G_CALLBACK (destroy_window), NULL);
+ g_signal_connect (G_OBJECT (vw), "newwindow",
+ G_CALLBACK (vik_window_new_window), NULL);
+ g_signal_connect (G_OBJECT (vw), "openwindow",
+ G_CALLBACK (open_window), NULL);
+
+ gtk_widget_show_all ( GTK_WIDGET(vw) );
+
+ if ( a_vik_get_restore_window_state() ) {
+ // These settings are applied after the show all as these options hide widgets
+ gboolean sidepanel;
+ if ( a_settings_get_boolean ( VIK_SETTINGS_WIN_SIDEPANEL, &sidepanel ) )
+ if ( ! sidepanel ) {
+ gtk_widget_hide ( GTK_WIDGET(vw->viking_vlp) );
+ GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewSidePanel" );
+ gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), FALSE );
+ }
+
+ gboolean statusbar;
+ if ( a_settings_get_boolean ( VIK_SETTINGS_WIN_STATUSBAR, &statusbar ) )
+ if ( ! statusbar ) {
+ gtk_widget_hide ( GTK_WIDGET(vw->viking_vs) );
+ GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewStatusBar" );
+ gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), FALSE );
+ }
+
+ gboolean toolbar;
+ if ( a_settings_get_boolean ( VIK_SETTINGS_WIN_TOOLBAR, &toolbar ) )
+ if ( ! toolbar ) {
+ gtk_widget_hide ( GTK_WIDGET(vw->toolbar) );
+ GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewToolBar" );
+ gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), FALSE );
+ }
+
+ gboolean menubar;
+ if ( a_settings_get_boolean ( VIK_SETTINGS_WIN_MENUBAR, &menubar ) )
+ if ( ! menubar ) {
+ gtk_widget_hide ( gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu" ) );
+ GtkWidget *check_box = gtk_ui_manager_get_widget ( vw->uim, "/ui/MainMenu/View/SetShow/ViewMainMenu" );
+ gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM(check_box), FALSE );
+ }
+ }
+ window_count++;
+
+ return vw;
+ }
+ return NULL;
+}
+
+/**
+ * determine_location_thread:
+ * @vw: The window that will get updated
+ * @threaddata: Data used by our background thread mechanism
+ *
+ * Use the features in vikgoto to determine where we are
+ * Then set up the viewport:
+ * 1. To goto the location
+ * 2. Set an appropriate level zoom for the location type
+ * 3. Some statusbar message feedback
+ */
+static int determine_location_thread ( VikWindow *vw, gpointer threaddata )
+{
+ struct LatLon ll;
+ gchar *name = NULL;
+ gint ans = a_vik_goto_where_am_i ( vw->viking_vvp, &ll, &name );
+
+ int result = a_background_thread_progress ( threaddata, 1.0 );
+ if ( result != 0 ) {
+ vik_window_statusbar_update ( vw, _("Location lookup aborted"), VIK_STATUSBAR_INFO );
+ return -1; /* Abort thread */
+ }
+
+ if ( ans ) {
+ // Zoom out a little
+ gdouble zoom = 16.0;
+
+ if ( ans == 2 ) {
+ // Position found with city precision - so zoom out more
+ zoom = 128.0;
+ }
+ else if ( ans == 3 ) {
+ // Position found via country name search - so zoom wayyyy out
+ zoom = 2048.0;
+ }
+
+ vik_viewport_set_zoom ( vw->viking_vvp, zoom );
+ vik_viewport_set_center_latlon ( vw->viking_vvp, &ll );
+
+ gchar *message = g_strdup_printf ( _("Location found: %s"), name );
+ vik_window_statusbar_update ( vw, message, VIK_STATUSBAR_INFO );
+ g_free ( name );
+ g_free ( message );
+
+ // Signal to redraw from the background
+ vik_layers_panel_emit_update ( vw->viking_vlp );
+ }
+ else
+ vik_window_statusbar_update ( vw, _("Unable to determine location"), VIK_STATUSBAR_INFO );
+
+ return 0;
+}
+
+/**
+ * Steps to be taken once initial loading has completed
+ */
+void vik_window_new_window_finish ( VikWindow *vw )
+{
+ // Don't add a map if we've loaded a Viking file already
+ if ( vw->filename )
+ return;
+
+ if ( a_vik_get_startup_method ( ) == VIK_STARTUP_METHOD_SPECIFIED_FILE ) {
+ vik_window_open_file ( vw, a_vik_get_startup_file(), TRUE );
+ if ( vw->filename )
+ return;
+ }
+
+ // Maybe add a default map layer
+ if ( a_vik_get_add_default_map_layer () ) {
+ VikMapsLayer *vml = VIK_MAPS_LAYER ( vik_layer_create(VIK_LAYER_MAPS, vw->viking_vvp, NULL, FALSE) );
+ vik_layer_rename ( VIK_LAYER(vml), _("Default Map") );
+ vik_aggregate_layer_add_layer ( vik_layers_panel_get_top_layer(vw->viking_vlp), VIK_LAYER(vml), TRUE );
+
+ draw_update ( vw );
+ }
+
+ // If not loaded any file, maybe try the location lookup
+ if ( vw->loaded_type == LOAD_TYPE_READ_FAILURE ) {
+ if ( a_vik_get_startup_method ( ) == VIK_STARTUP_METHOD_AUTO_LOCATION ) {
+
+ vik_statusbar_set_message ( vw->viking_vs, VIK_STATUSBAR_INFO, _("Trying to determine location...") );
+
+ a_background_thread ( GTK_WINDOW(vw),
+ _("Determining location"),
+ (vik_thr_func) determine_location_thread,
+ vw,
+ NULL,
+ NULL,
+ 1 );
+ }
+ }
+}
+
+static void open_window ( VikWindow *vw, GSList *files )
+{
+ gboolean change_fn = (g_slist_length(files) == 1); /* only change fn if one file */
+ GSList *cur_file = files;
+ while ( cur_file ) {
+ // Only open a new window if a viking file
+ gchar *file_name = cur_file->data;
+ if (vw != NULL && vw->filename && check_file_magic_vik ( file_name ) ) {
+ VikWindow *newvw = vik_window_new_window ();
+ if (newvw)
+ vik_window_open_file ( newvw, file_name, TRUE );
+ }
+ else {
+ vik_window_open_file ( vw, file_name, change_fn );
+ }
+ g_free (file_name);
+ cur_file = g_slist_next (cur_file);
+ }
+ g_slist_free (files);
+}
+// End signals
+