X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Ftext-data-import-dialog.c;h=a82a81a121d5654f435e6fdd8f54516ed9fb5137;hb=c9d55afdda746d7e8b39e5a117c1644debbb0c75;hp=d8df668f197ff91dae430d4557a8aa495c1f07c3;hpb=ebad3a92846289fb77c7e0fb8bb48ac7c02de68c;p=pspp diff --git a/src/ui/gui/text-data-import-dialog.c b/src/ui/gui/text-data-import-dialog.c index d8df668f19..a82a81a121 100644 --- a/src/ui/gui/text-data-import-dialog.c +++ b/src/ui/gui/text-data-import-dialog.c @@ -16,12 +16,16 @@ #include +#include + + + #include "checkbox-treeview.h" #include "descriptives-dialog.h" #include -#include -#include + +#include #include #include #include @@ -50,6 +54,30 @@ #define _(msgid) gettext (msgid) #define N_(msgid) msgid + +#if !GTK_CHECK_VERSION (2, 10, 0) + +void +text_data_import_assistant (GObject *o, gpointer de_) +{ + struct data_editor *de = de_; + + GtkWidget *dialog = + gtk_message_dialog_new (de->parent.window, + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CLOSE, + _("The text import assistant has not been " + "compiled into this build of PSPPIRE, because " + "GTK+ version 2.10.0 or later was not available.")); + + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); +} + +#else + /* TextImportModel, a GtkTreeModel used by the text data import dialog. */ enum @@ -89,6 +117,7 @@ struct assistant GtkWidget *paste_button; GtkWidget *reset_button; int response; + int watch_cursor; GtkCellRenderer *prop_renderer; GtkCellRenderer *fixed_renderer; @@ -222,6 +251,8 @@ static GtkTreeViewColumn *make_data_column (struct import_assistant *, static GtkTreeView *create_data_tree_view (bool input, GtkContainer *parent, struct import_assistant *); static void escape_underscores (const char *in, char *out); +static void push_watch_cursor (struct import_assistant *); +static void pop_watch_cursor (struct import_assistant *); /* Pops up the Text Data Import assistant. */ void @@ -229,34 +260,39 @@ text_data_import_assistant (GObject *o, gpointer de_) { struct data_editor *de = de_; GtkWindow *parent_window = de->parent.window; - struct import_assistant ia = { { 0, } }; + struct import_assistant *ia; - if (!init_file (&ia, parent_window)) - return; + ia = xzalloc (sizeof *ia); + if (!init_file (ia, parent_window)) + { + free (ia); + return; + } - init_assistant (&ia, parent_window); - init_intro_page (&ia); - init_first_line_page (&ia); - init_separators_page (&ia); - init_formats_page (&ia); + init_assistant (ia, parent_window); + init_intro_page (ia); + init_first_line_page (ia); + init_separators_page (ia); + init_formats_page (ia); - gtk_widget_show_all (GTK_WIDGET (ia.asst.assistant)); + gtk_widget_show_all (GTK_WIDGET (ia->asst.assistant)); - ia.asst.main_loop = g_main_loop_new (NULL, false); - g_main_loop_run (ia.asst.main_loop); + ia->asst.main_loop = g_main_loop_new (NULL, false); + g_main_loop_run (ia->asst.main_loop); + g_main_loop_unref (ia->asst.main_loop); - switch (ia.asst.response) + switch (ia->asst.response) { case GTK_RESPONSE_APPLY: { - char *syntax = generate_syntax (&ia); + char *syntax = generate_syntax (ia); execute_syntax (create_syntax_string_source (syntax)); free (syntax); } break; case PSPPIRE_RESPONSE_PASTE: { - char *syntax = generate_syntax (&ia); + char *syntax = generate_syntax (ia); struct syntax_editor *se = (struct syntax_editor *) window_create (WINDOW_SYNTAX, NULL); gtk_text_buffer_insert_at_cursor (se->buffer, syntax, -1); @@ -267,10 +303,11 @@ text_data_import_assistant (GObject *o, gpointer de_) break; } - destroy_formats_page (&ia); - destroy_separators_page (&ia); - destroy_assistant (&ia); - destroy_file (&ia); + destroy_formats_page (ia); + destroy_separators_page (ia); + destroy_assistant (ia); + destroy_file (ia); + free (ia); } /* Emits PSPP syntax to S that applies the dictionary attributes @@ -624,6 +661,7 @@ add_page_to_assistant (struct import_assistant *ia, gtk_assistant_append_page (ia->asst.assistant, content); gtk_assistant_set_page_type (ia->asst.assistant, content, type); gtk_assistant_set_page_title (ia->asst.assistant, content, title_copy); + gtk_assistant_set_page_complete (ia->asst.assistant, content, true); free (title_copy); @@ -647,11 +685,6 @@ on_prepare (GtkAssistant *assistant, GtkWidget *page, gtk_widget_show (ia->asst.paste_button); else gtk_widget_hide (ia->asst.paste_button); - - /* Make the user visit each page in the assistant once. Seems - like a reasonable user interface, plus visiting the final - page is what constructs the dictionary. */ - gtk_assistant_set_page_complete (assistant, page, true); } /* Called when the Cancel button in the assistant is clicked. */ @@ -1276,6 +1309,9 @@ static void revise_fields_preview (struct import_assistant *ia) { GtkWidget *w; + + push_watch_cursor (ia); + w = GTK_WIDGET (ia->separators.fields_tree_view); gtk_widget_destroy (w); get_separators (ia); @@ -1285,6 +1321,8 @@ revise_fields_preview (struct import_assistant *ia) true, GTK_CONTAINER (get_widget_assert (ia->asst.xml, "fields-scroller")), ia); + + pop_watch_cursor (ia); } /* Sets the widgets to match IA's separators substructure. */ @@ -1530,6 +1568,8 @@ prepare_formats_page (struct import_assistant *ia) unsigned long int number = 0; size_t column_idx; + push_watch_cursor (ia); + dict = dict_create (); fg = fmt_guesser_create (); for (column_idx = 0; column_idx < s->column_cnt; column_idx++) @@ -1583,12 +1623,10 @@ prepare_formats_page (struct import_assistant *ia) hold a reference via ia->formats.dict. */ var_store = psppire_var_store_new (psppire_dict); g_object_set (var_store, - "trailing-rows", 1, "format-type", PSPPIRE_VAR_STORE_INPUT_FORMATS, (void *) NULL); var_sheet = PSPPIRE_VAR_SHEET (psppire_var_sheet_new ()); g_object_set (var_sheet, - "row-geometry", var_store, "model", var_store, "may-create-vars", FALSE, (void *) NULL); @@ -1605,6 +1643,8 @@ prepare_formats_page (struct import_assistant *ia) false, GTK_CONTAINER (get_widget_assert (ia->asst.xml, "data-scroller")), ia); + + pop_watch_cursor (ia); } /* Clears the set of user-modified variables from IA's formats @@ -1643,6 +1683,8 @@ on_variable_change (PsppireDict *dict, int dict_idx, GtkTreeView *tv = ia->formats.data_tree_view; gint column_idx = dict_idx + 1; + push_watch_cursor (ia); + /* Remove previous column and replace with new column. */ gtk_tree_view_remove_column (tv, gtk_tree_view_get_column (tv, column_idx)); gtk_tree_view_insert_column (tv, make_data_column (ia, tv, false, dict_idx), @@ -1665,6 +1707,8 @@ on_variable_change (PsppireDict *dict, int dict_idx, var_destroy (p->modified_vars[dict_idx]); p->modified_vars[dict_idx] = var_clone (psppire_dict_get_variable (dict, dict_idx)); + + pop_watch_cursor (ia); } /* Parses the contents of the field at (ROW,COLUMN) according to @@ -1802,6 +1846,19 @@ get_tooltip_location (GtkWidget *widget, gint wx, gint wy, GtkTreeModel *tree_model; bool ok; + /* Check that WIDGET is really visible on the screen before we + do anything else. This is a bug fix for a sticky situation: + when text_data_import_assistant() returns, it frees the data + necessary to compose the tool tip message, but there may be + a tool tip under preparation at that point (even if there is + no visible tool tip) that will call back into us a little + bit later. Perhaps the correct solution to this problem is + to make the data related to the tool tips part of a GObject + that only gets destroyed when all references are released, + but this solution appears to be effective too. */ + if (!GTK_WIDGET_MAPPED (widget)) + return FALSE; + gtk_tree_view_convert_widget_to_bin_window_coords (tree_view, wx, wy, &bx, &by); if (!gtk_tree_view_get_path_at_pos (tree_view, bx, by, @@ -2223,3 +2280,34 @@ text_import_model_iter_to_row (const GtkTreeIter *iter) assert (iter->stamp == TREE_MODEL_STAMP); return GPOINTER_TO_INT (iter->user_data); } + +/* Increments the "watch cursor" level, setting the cursor for + the assistant window to a watch face to indicate to the user + that the ongoing operation may take some time. */ +static void +push_watch_cursor (struct import_assistant *ia) +{ + if (++ia->asst.watch_cursor == 1) + { + GtkWidget *widget = GTK_WIDGET (ia->asst.assistant); + GdkDisplay *display = gtk_widget_get_display (widget); + GdkCursor *cursor = gdk_cursor_new_for_display (display, GDK_WATCH); + gdk_window_set_cursor (widget->window, cursor); + gdk_cursor_unref (cursor); + gdk_display_flush (display); + } +} + +/* Decrements the "watch cursor" level. If the level reaches + zero, the cursor is reset to its default shape. */ +static void +pop_watch_cursor (struct import_assistant *ia) +{ + if (--ia->asst.watch_cursor == 0) + { + GtkWidget *widget = GTK_WIDGET (ia->asst.assistant);; + gdk_window_set_cursor (widget->window, NULL); + } +} + +#endif