diff --git a/src/editor.c b/src/editor.c index b97292bf..62e3c2e0 100644 --- a/src/editor.c +++ b/src/editor.c @@ -227,6 +227,7 @@ void editor_fileinfo_update (GuEditor* ec, const gchar* filename) { struct stat attr; stat(fname, &attr); ec->last_modtime = attr.st_mtime; + ec->last_external_modtime = ec->last_modtime; g_free (fname); g_free (base); @@ -305,6 +306,25 @@ void editor_fileinfo_cleanup (GuEditor* ec) { ec->basename = NULL; } +void editor_modtime_update (GuEditor* ec, gboolean loaded) { + struct stat attr; + stat(ec->filename, &attr); + if (loaded) ec->last_modtime = attr.st_mtime; + ec->last_external_modtime = attr.st_mtime; +} + +gboolean editor_externally_modified (GuEditor* ec, gboolean since_loaded) { + struct stat attr; + stat(ec->filename, &attr); + time_t ref_time; + if (since_loaded) { + ref_time = ec->last_modtime; + } else { + ref_time = ec->last_external_modtime; + } + return difftime (ref_time, attr.st_mtime) != 0.0 && ref_time != 0.0; +} + void editor_sourceview_config (GuEditor* ec) { GtkWrapMode wrapmode = 0; diff --git a/src/editor.h b/src/editor.h index 03a279ad..ef5be28b 100644 --- a/src/editor.h +++ b/src/editor.h @@ -54,6 +54,7 @@ struct _GuEditor { gchar* bibfile; gchar* projfile; time_t last_modtime; + time_t last_external_modtime; /* GUI related members */ GtkSourceView* view; @@ -76,8 +77,10 @@ struct _GuEditor { GuEditor* editor_new (GuMotion* mc); void editor_fileinfo_update (GuEditor* ec, const gchar* filename); -void editor_fileinfo_cleanup (GuEditor* ec); gboolean editor_fileinfo_update_biblio (GuEditor* ec, const gchar* filename); +void editor_fileinfo_cleanup (GuEditor* ec); +void editor_modtime_update (GuEditor* ec, gboolean external); +gboolean editor_externally_modified (GuEditor* ec, gboolean since_loaded); void editor_destroy (GuEditor* ec); void editor_sourceview_config (GuEditor* ec); void editor_activate_spellchecking (GuEditor* ec, gboolean status); diff --git a/src/gui/gui-main.c b/src/gui/gui-main.c index a3d0da28..b7303f40 100644 --- a/src/gui/gui-main.c +++ b/src/gui/gui-main.c @@ -333,6 +333,45 @@ void gui_set_window_title (const gchar* filename, const gchar* text) { g_free (title); } +gboolean on_focus_in_view (GtkWidget* widget, GdkEventFocus* event, GuTabContext* tab) { + slog (L_WARNING, "Focused in '%s' view.\n", tab->editor->filename); + if (editor_externally_modified (tab->editor, FALSE)) { + gui_external_changes_enable (tab); + } + return GDK_EVENT_PROPAGATE; +} + +void on_reload_infobar_response (GtkInfoBar* bar, gint res, gpointer data) { + GuEditor* ec = data; + gboolean reload = res == GTK_RESPONSE_YES; + if (reload) { + tabmanager_set_content (A_LOAD, ec->filename, NULL); + } + editor_modtime_update (ec, reload); + gui_recovery_mode_disable (bar); +} + +// based on gedit's external changes infobar +void gui_external_changes_enable (GuTabContext* tab) { + slog (L_WARNING, "The file '%s' changed on disk.\n", tab->editor->filename); + gchar* action_msg; + if (editor_buffer_changed (tab->editor)) { + action_msg = "Drop changes and reload?"; + } else { + action_msg = "Reload?"; + } + gchar* msg = g_strdup_printf ("The file %s changed on disk. %s", tab->editor->filename, action_msg); + gtk_label_set_text (GTK_LABEL (tab->page->barlabel), msg); + g_free (msg); + + tab->page->infosignal = + g_signal_connect (g_active_tab->page->infobar, "response", + G_CALLBACK (on_reload_infobar_response), (gpointer)tab->editor); + + gtk_widget_set_sensitive (GTK_WIDGET (tab->editor->view), FALSE); + gtk_widget_show (tab->page->infobar); +} + void on_recovery_infobar_response (GtkInfoBar* bar, gint res, gpointer filename) { gchar* prev_workfile = iofunctions_get_swapfile (filename); @@ -348,9 +387,10 @@ void on_recovery_infobar_response (GtkInfoBar* bar, gint res, gpointer filename) void gui_recovery_mode_enable (GuTabContext* tab, const gchar* filename) { gchar* prev_workfile = iofunctions_get_swapfile (filename); - slog (L_WARNING, "Swap file `%s' found.\n", prev_workfile); - gchar* msg = g_strdup_printf (_("Swap file exists for %s, " - "do you want to recover from it?"), filename); + slog (L_WARNING, "Swap file '%s' found.\n", prev_workfile); + gchar* msg = g_strdup_printf ( + _("Swap file exists for %s. " + "Do you want to recover from it?"), filename); gtk_label_set_text (GTK_LABEL (tab->page->barlabel), msg); g_free (msg); @@ -363,6 +403,7 @@ void gui_recovery_mode_enable (GuTabContext* tab, const gchar* filename) { gtk_widget_show (tab->page->infobar); } +// also used for external changes infobar. rename? void gui_recovery_mode_disable (GtkInfoBar *infobar) { gint id = g_active_tab->page->infosignal; g_signal_handler_disconnect (infobar, id); @@ -410,27 +451,17 @@ void gui_save_file (GuTabContext* tab, gboolean saveas) { gchar *text; GtkWidget* focus = NULL; - // check whether the file has been changed by (some) external program - double lastmod; - struct stat attr; - stat(filename, &attr); - lastmod = difftime (tab->editor->last_modtime, attr.st_mtime); - - if (lastmod != 0.0 && tab->editor->last_modtime != 0.0 ) { + if (!new && editor_externally_modified (tab->editor, TRUE)) { // ask the user whether he want to save or reload - ret = utils_save_reload_dialog ( + ret = utils_save_confirmation_dialog ( _("The content of the file has been changed externally. " "Saving will remove any external modifications.")); - if (ret == GTK_RESPONSE_YES) { - tabmanager_set_content (A_LOAD, filename, NULL); - // resets modtime - stat(filename, &attr); - tab->editor->last_modtime = attr.st_mtime; - goto cleanup; - } else if (ret != GTK_RESPONSE_NO) { - // cancel means: do nothing - goto cleanup; - } + // clicking "Cancel" (which returns GTK_RESPONSE_NO) and pressing escape + // (which treturns something else) should both cancel the save. no + // cleanup is required, becaue `pdfname` hasn't had a chance to be + // allocated yet, and `!new` should guarantee that `filename` wasn't + // allocated earlier + if (ret != GTK_RESPONSE_YES) return; } focus = gtk_window_get_focus (gummi_get_gui ()->mainwindow); @@ -447,10 +478,7 @@ void gui_save_file (GuTabContext* tab, gboolean saveas) { if (new) tabmanager_update_tab (filename); gui_set_filename_display (tab, TRUE, TRUE); gtk_widget_grab_focus (GTK_WIDGET (tab->editor->view)); - - // Resets modtime - stat(filename, &attr); - tab->editor->last_modtime = attr.st_mtime; + editor_modtime_update (tab->editor, TRUE); cleanup: if (new) g_free (filename); diff --git a/src/gui/gui-main.h b/src/gui/gui-main.h index 6adec434..9fbe818b 100644 --- a/src/gui/gui-main.h +++ b/src/gui/gui-main.h @@ -123,7 +123,8 @@ void gui_open_file (const gchar* filename); void gui_save_file (GuTabContext* tab, gboolean saveas); void gui_set_hastabs_sensitive (gboolean enable); -void on_tab_notebook_switch_page (GtkNotebook *notebook, GtkWidget* nbpage, int pagenr, void* data); +void on_tab_notebook_switch_page (GtkNotebook *notebook, GtkWidget* nbpage, + int pagenr, void* data); void on_tool_textstyle_bold_activate (GtkWidget* widget, void* user); void on_tool_textstyle_italic_activate (GtkWidget* widget, void* user); void on_tool_textstyle_underline_activate (GtkWidget* widget, void* user); @@ -136,7 +137,6 @@ void on_button_template_open_clicked (GtkWidget* widget, void* user); void on_button_template_close_clicked (GtkWidget* widget, void* user); void on_template_rowitem_edited (GtkWidget* widget, gchar *path, gchar* filenm, void* user); -void gui_recover_from_swapfile (const gchar* filename); void on_menu_autosync_toggled (GtkCheckMenuItem *menu_autosync, void* user); void on_button_biblio_compile_clicked (GtkWidget* widget, void* user); @@ -146,6 +146,11 @@ void on_bibreference_clicked (GtkTreeView* view, GtkTreePath* Path, void on_biblio_filter_changed (GtkWidget* widget, void* user); gboolean on_bibprogressbar_update (void* data); +gboolean on_focus_in_view (GtkWidget* widget, GdkEventFocus* event, GuTabContext* tab); +void on_reload_infobar_response (GtkInfoBar* bar, gint res, gpointer filename); +void gui_external_changes_enable (GuTabContext* tab); +/* void gui_external_changes_disable (GtkInfoBar *infobar); */ // would currently be identical to gui_external_changes_disable + void on_recovery_infobar_response (GtkInfoBar* bar, gint res, gpointer filename); void gui_recovery_mode_enable (GuTabContext* tab, const gchar* filename); void gui_recovery_mode_disable (GtkInfoBar *infobar); diff --git a/src/gui/gui-tabmanager.c b/src/gui/gui-tabmanager.c index 1d8f08f4..d3385294 100644 --- a/src/gui/gui-tabmanager.c +++ b/src/gui/gui-tabmanager.c @@ -71,6 +71,8 @@ int tabmanagergui_create_page (GuTabContext* tc, GuEditor* editor) { gtk_box_pack_start (GTK_BOX (tp->editorbox), tp->infobar, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (tp->editorbox), tp->scrollw, TRUE, TRUE, 0); + g_signal_connect_after (editor->view, "focus-in-event", G_CALLBACK (on_focus_in_view), tc); + pos = gtk_notebook_append_page (GTK_NOTEBOOK (g_tabnotebook), tp->editorbox, GTK_WIDGET (tp->labelbox)); @@ -156,6 +158,7 @@ gint tabmanagergui_replace_page (GuTabContext* tc, GuEditor* newec) { editor_destroy (g_active_editor); gtk_container_add (GTK_CONTAINER (tc->page->scrollw), GTK_WIDGET (newec->view)); + g_signal_connect_after (newec->view, "focus-in-event", G_CALLBACK (on_focus_in_view), tc); gtk_widget_show (GTK_WIDGET(newec->view)); int pos = gtk_notebook_page_num (g_tabnotebook, diff --git a/src/utils.c b/src/utils.c index 4fce9f5a..724e0238 100644 --- a/src/utils.c +++ b/src/utils.c @@ -142,7 +142,7 @@ void slog (gint level, const gchar *fmt, ...) { exit (1); } -gint utils_save_reload_dialog (const gchar* message) { +gint utils_save_confirmation_dialog (const gchar* message) { GtkWidget* dialog; gint ret = 0; @@ -153,7 +153,7 @@ gint utils_save_reload_dialog (const gchar* message) { GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", message); - gtk_dialog_add_buttons(GTK_DIALOG (dialog), "Reload", GTK_RESPONSE_YES, "Save", GTK_RESPONSE_NO, NULL); + gtk_dialog_add_buttons(GTK_DIALOG (dialog), "Cancel", GTK_RESPONSE_NO, "Save Anyway", GTK_RESPONSE_YES, NULL); gtk_window_set_title (GTK_WINDOW (dialog), _("Confirmation")); ret = gtk_dialog_run (GTK_DIALOG (dialog)); diff --git a/src/utils.h b/src/utils.h index 7c2f66bf..88efb42c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -117,7 +117,7 @@ gboolean in_debug_mode(); void slog_set_gui_parent (GtkWindow* p); void slog (gint level, const gchar *fmt, ...); gint utils_yes_no_dialog (const gchar* message); -gint utils_save_reload_dialog (const gchar* message); +gint utils_save_confirmation_dialog (const gchar* message); gboolean utils_path_exists (const gchar* path); gboolean utils_uri_path_exists (const gchar* uri); gboolean utils_set_file_contents (const gchar *filename, const gchar *text, gssize length);