/* Screem: pageUI.c, * * ScreemPage utility functions for gui stuff * * Copyright (C) 1999 - 2002 David A Knight * * 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 * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 * * For contact information with the author of this source code please see * the AUTHORS file. If there is no AUTHORS file present then check the * about box under the help menu for a contact address */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fileops.h" #include "pageUI.h" #include "support.h" #include "screem-window.h" #include "screem-site.h" #include "screem-site-ui.h" #include "screem-editor.h" #include "screem-preview.h" #include "screem-page.h" #include "screem-search.h" #include "gedit-close-confirmation-dialog.h" gboolean screem_page_open_with_filename( ScreemSite *site, ScreemWindow *window, const gchar *filename ) { GObject *app; ScreemPage *page; gchar *path; const gchar *pathname; GtkAction *action; g_return_val_if_fail( filename != NULL, FALSE ); g_object_get( G_OBJECT( site ), "app", &app, NULL ); path = gnome_vfs_make_uri_from_input( filename ); page = screem_site_locate_page( site, path ); if( screem_site_get_fake_flag( site ) && ! page ) { /* fake site, add to list of pages */ page = screem_page_new( G_OBJECT( app ) ); screem_page_set_pathname( page, path ); if( ! screem_site_add_page( site, page ) ) { /* page is already loaded, FIXME: what now? * this should never occur, as we attempt * to locate the page before we create one */ g_assert( FALSE ); } g_object_unref( page ); } g_free( path ); if( page ) { if( screem_window_get_current( window ) != site ) { screem_window_set_current( window, site ); } screem_window_set_document( window, page ); path = screem_page_template_path( page ); pathname = screem_page_get_pathname( page ); action = gtk_action_group_get_action( window->action_group, "TemplateUpdate" ); if( path && ( ! gnome_vfs_uris_match( pathname, path ) ) && ( screem_compare_file_age( pathname, path ) < 0 ) ) { /* template has changed, no update */ gtk_action_activate( action ); } g_free( path ); } g_object_unref( app ); return ( page != NULL ); } gint screem_page_save_as( ScreemPage *page, ScreemWindow *window, const gchar *dir, ScreemApplication *app ) { gchar *filename; gint status; ScreemSite *site; const gchar *pathname; GSList *filters; GtkFileFilter *filter; static const gchar *filternames[] = { N_( "All Text Files" ), N_( "CSS Files" ), N_( "Javascript Files" ), N_( "Markup Files" ) }; gint i; static const gint num = G_N_ELEMENTS( filternames ); site = NULL; if( window ) { site = screem_window_get_current( window ); } if( site && ! dir ) { pathname = screem_site_get_pathname( site ); } else { pathname = dir; } filters = NULL; for( i = 0; i < num; ++ i ) { filter = screem_get_file_filter( gettext( filternames[ i ] ) ); filters = g_slist_prepend( filters, (gpointer)filter ); } filename = screem_fileselect( _( "Select filename to save as" ), GTK_WINDOW( window ), GTK_FILE_CHOOSER_ACTION_SAVE, pathname, filters, FALSE ); g_slist_free( filters ); /* we didn't select one */ status = SAVE_AS_CANCELLED; if( filename ) { if( ! overwrite( filename ) ) { g_free( filename ); } else { gchar *previous; gboolean hold; previous = (gchar*)screem_page_get_pathname( page ); if( previous ) { previous = g_strdup( previous ); } /* FIXME: if we are overwriting an * already existing file * * 1) scan all windows, closing * filename if it is open * 2) remove filename from site */ screem_page_set_pathname( page, filename ); /* allow save by setting page as changed */ screem_page_set_changed( page, TRUE ); status = SAVE_AS_FAILED; hold = screem_page_save( page, NULL ); /* Hack so anything listening to notify::pathname * will be able to get the mime type correctly * as the file may not have existed before * screem_page_save() was called */ if( hold ) { status = SAVE_AS_OK; screem_page_set_pathname( page, filename ); } /* if we aren't the fake site we now have a file * for which there is no ScreemPage in the site, * we need to add one */ if( previous && ! screem_site_get_fake_flag( site ) && ! screem_site_locate_page( site, previous ) ) { ScreemPage *npage; npage = screem_page_new( G_OBJECT( app ) ); screem_page_set_pathname( npage, previous ); screem_site_add_page( site, npage ); g_object_unref( npage ); } g_free( previous ); } } return status; } gint screem_page_save_confirmation( ScreemPage *page, ScreemWindow *window, gboolean closing ) { GladeXML *xml; GtkWidget *widget; const gchar *label; GString *str; const gchar *temp; gchar *tmp; guint pos; GtkWidget *box; gint button; const gchar *pathname; gchar *basename; const gchar *name; g_assert( closing == FALSE ); if( ! screem_page_is_loaded( page ) ) { return GTK_RESPONSE_NO; } else if( ! screem_page_get_changed( page ) ) { return GTK_RESPONSE_NO; } name = "save_cont"; xml = glade_xml_new( GLADE_PATH"/screem.glade", name, NULL ); widget = glade_xml_get_widget( xml, "text" ); label = gtk_label_get_text( GTK_LABEL( widget ) ); temp = strstr( label, "%s" ); g_assert( temp ); pos = (guint)(temp - label); str = g_string_new( "" ); pos += str->len; g_string_append( str, label ); pathname = screem_page_get_pathname( page ); if( ! pathname ) { pathname = _( "Untitled" ); } basename = g_path_get_basename( pathname ); temp = gnome_vfs_unescape_string_for_display( basename ); g_free( basename ); tmp = g_markup_escape_text( temp, -1 ); g_free( (gchar*)temp ); basename = (gchar*)tmp; g_string_erase( str, pos, 2 ); g_string_insert( str, pos, basename ); g_free( basename ); temp = strstr( str->str, "\n\n" ); g_assert( temp ); pos = (guint)(temp - str->str); g_string_insert( str, pos, "" ); gtk_label_set_markup( GTK_LABEL( widget ), str->str ); g_string_free( str, TRUE ); box = glade_xml_get_widget( xml, name ); gtk_window_set_wmclass( GTK_WINDOW( box ), "Screem", "save_confirm_prompt" ); button = gtk_dialog_run( GTK_DIALOG( box ) ); gtk_widget_destroy( box ); g_object_unref( G_OBJECT( xml ) ); if( button == GTK_RESPONSE_YES ) { screem_page_save( page, NULL ); } else if( button == GTK_RESPONSE_NONE ) { button = GTK_RESPONSE_CANCEL; } return button; } gboolean screem_page_close_page( ScreemPage *page, ScreemWindow *window, gboolean confirm ) { gboolean ret; ScreemApplication *app; /* request save confirmation */ g_object_get( G_OBJECT( window ), "app", &app, NULL ); ret = FALSE; if( ( ! confirm ) || screem_page_save_page_confirmation( page, window, app ) != GTK_RESPONSE_CANCEL ) { screem_page_set_open( page, FALSE ); screem_window_remove_document( window, page ); ret = TRUE; } g_object_unref( G_OBJECT( app ) ); return ret; } gboolean screem_page_save_check( ScreemPage *page ) { const gchar *path; gint button = GTK_RESPONSE_NO; GtkWidget *prompt; GnomeVFSFileInfo *info; GnomeVFSURI *uri; GnomeVFSResult res; path = screem_page_get_pathname( page ); /* Don't save if there is no file associated with this page yet */ if( ! path ) { return FALSE; } uri = gnome_vfs_uri_new( path ); if( uri ) { info = gnome_vfs_file_info_new(); res = gnome_vfs_get_file_info_uri( uri, info, GNOME_VFS_FILE_INFO_FOLLOW_LINKS ); gnome_vfs_uri_unref( uri ); } else { info = NULL; res = GNOME_VFS_ERROR_GENERIC; } if( res != GNOME_VFS_OK && res != GNOME_VFS_ERROR_NOT_FOUND ) { if( info ) { gnome_vfs_file_info_unref( info ); } return FALSE; } /* file exists, check if it has been modified outside of screem */ if( screem_page_get_modified( page ) ) { gchar *temp; temp = gnome_vfs_unescape_string_for_display( path ); prompt = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("%s has changed on disk\nReload instead of saving?"), temp ); g_free( temp ); gtk_window_set_wmclass( GTK_WINDOW( prompt ), "Screem", "revert_prompt" ); button = gtk_dialog_run( GTK_DIALOG( prompt ) ); gtk_widget_destroy( prompt ); if( button == GTK_RESPONSE_YES ) { screem_page_revert( page, NULL ); } } gnome_vfs_file_info_unref( info ); return (button == GTK_RESPONSE_NO); } void external_view( ScreemPage *page ) { const gchar *pathname; gchar *uri; GnomeVFSResult res; pathname = screem_page_get_pathname( page ); g_return_if_fail( pathname != NULL ); if( screem_page_save_confirmation( page, NULL, FALSE ) != GTK_RESPONSE_CANCEL ) { uri = g_strconcat( "file://", pathname, NULL ); res = gnome_vfs_url_show( uri ); /* FIXME: handle errors */ g_free( uri ); } } void screem_page_edit_bookmarks( ScreemWindow *window, ScreemEditor *editor, ScreemPage *page ) { GladeXML *xml; GtkWidget *dialog; gint response; GtkWidget *bookmarkname; GtkWidget *bookmarkline; GtkWidget *jumpto; const gchar *name; gchar *title; gint line; gboolean allowjump; const gchar *pathname; gchar *temp; GtkWidget *treeview; GtkCellRenderer *renderer; GtkTreeViewColumn *col; GtkListStore *store; xml = glade_xml_new( GLADE_PATH"/screem.glade", "bookmarks", NULL ); dialog = glade_xml_get_widget( xml, "bookmarks" ); bookmarkname = glade_xml_get_widget( xml, "bookmarkname" ); screem_gtk_add_history( bookmarkname ); bookmarkname = GTK_BIN( bookmarkname )->child; bookmarkline = glade_xml_get_widget( xml, "bookmarkline" ); line = gtk_text_buffer_get_line_count( GTK_TEXT_BUFFER( page ) ); gtk_spin_button_set_range( GTK_SPIN_BUTTON( bookmarkline ), 1.0, (gdouble)line ); jumpto = glade_xml_get_widget( xml, "jumptobookmark" ); allowjump = ( page == screem_window_get_document( window ) ); gtk_widget_set_sensitive( jumpto, allowjump ); treeview = glade_xml_get_widget( xml, "bookmarkview" ); g_object_set_data( G_OBJECT( treeview ), "page", page ); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new(); gtk_tree_view_column_set_title( col, "Name" ); gtk_tree_view_column_pack_start( col, renderer, TRUE ); gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), col ); gtk_tree_view_column_set_attributes( col, renderer, "text", 0, NULL ); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new(); gtk_tree_view_column_set_title( col, "Line" ); gtk_tree_view_column_pack_start( col, renderer, TRUE ); gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), col ); gtk_tree_view_column_set_attributes( col, renderer, "text", 1, NULL ); store = screem_page_get_bookmark_model( page ); gtk_tree_view_set_model( GTK_TREE_VIEW( treeview ), GTK_TREE_MODEL( store ) ); pathname = screem_page_get_pathname( page ); if( ! pathname ) { pathname = _( "Untitled" ); } temp = gnome_vfs_unescape_string_for_display( pathname ); title = g_strconcat( temp, "- Screem", NULL ); gtk_window_set_title( GTK_WINDOW( dialog ), title ); g_free( temp ); g_free( title ); glade_xml_signal_autoconnect( xml ); while( dialog ) { response = gtk_dialog_run( GTK_DIALOG( dialog ) ); name = gtk_entry_get_text( GTK_ENTRY( bookmarkname ) ); line = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(bookmarkline)); switch( response ) { case 0: /* add */ screem_page_add_bookmark( page, line, name ); break; case 1: /* remove */ screem_page_remove_bookmark( page, name ); break; case 2: /* jump to */ line = screem_page_get_bookmark( page, name ); if( line != -1 ) { screem_editor_goto_line( editor, line ); } break; default: break; } if( response != 0 && response != 1 ) { gtk_widget_destroy( dialog ); dialog = NULL; } } } void screem_page_bookmark_activate( GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data ) { GtkTreeSelection *selection; GtkListStore *model; GtkTreeModel *tmodel; GladeXML *xml; ScreemPage *page; xml = glade_get_widget_tree( GTK_WIDGET( view ) ); selection = gtk_tree_view_get_selection( view ); if( selection ) { GtkTreeIter it; GValue value = {0,}; ScreemPageBookMark *bookmark; GtkWidget *name; GtkWidget *line; page = SCREEM_PAGE( g_object_get_data( G_OBJECT( view ), "page" ) ); model = screem_page_get_bookmark_model( page ); tmodel = GTK_TREE_MODEL( model ); gtk_tree_selection_get_selected( selection, &tmodel, &it ); gtk_tree_model_get_value( GTK_TREE_MODEL( model ), &it, 2, &value ); bookmark = g_value_get_pointer( &value ); name = glade_xml_get_widget( xml, "bookmarkname" ); line = glade_xml_get_widget( xml, "bookmarkline" ); name = GTK_BIN( name )->child; gtk_entry_set_text( GTK_ENTRY( name ), bookmark->name->str ); gtk_spin_button_set_value( GTK_SPIN_BUTTON( line ), (gfloat)bookmark->line_number ); } } gint screem_page_save_page_confirmation( ScreemPage *page, ScreemWindow *window, ScreemApplication *app ) { GSList *tmp; gint ret; ret = GTK_RESPONSE_NO; if( screem_page_is_loaded( page ) && screem_page_get_changed( page ) ) { tmp = g_slist_prepend( NULL, page ); ret = screem_page_save_pages_confirmation( tmp, window, app ); g_slist_free( tmp ); } return ret; } gint screem_page_save_pages_confirmation( GSList *pages, ScreemWindow *window, ScreemApplication *app ) { GtkWindow *gwindow; GtkWidget *confirm; gint ret; gboolean doclose; GSList *saveme; GSList *tmp; ScreemPage *page; const gchar *pathname; g_return_val_if_fail( pages != NULL, GTK_RESPONSE_NO ); gwindow = NULL; if( window ) { gwindow = GTK_WINDOW( window ); } if( ! pages->next ) { confirm = gedit_close_confirmation_dialog_new_single( gwindow, pages->data ); } else { confirm = gedit_close_confirmation_dialog_new( gwindow, pages ); } ret = GTK_RESPONSE_CANCEL; saveme = NULL; if( gedit_close_confirmation_dialog_run( confirm ) ) { ret = GTK_RESPONSE_NO; saveme = gedit_close_confirmation_dialog_get_selected_documents( confirm ); } if( saveme ) { for( tmp = saveme; tmp; tmp = tmp->next ) { page = SCREEM_PAGE( tmp->data ); pathname = screem_page_get_pathname( page ); if( pathname ) { screem_page_save( page, NULL ); } else { screem_page_save_as( page, window, NULL, app ); } } g_slist_free( saveme ); ret = GTK_RESPONSE_YES; } gtk_widget_destroy( confirm ); return ret; }