/* Screem: screem-window.c * * The ScreemWindow widget * * Copyright (C) 2001 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 "screem-window.h" #include "screem-window-private.h" #include "screem-editor.h" #include "screem-preview.h" #include "screem-site.h" #include "screem-site-model.h" #include "screem-site-view.h" #include "screem-tagtree.h" #include "screem-linkview.h" #include "screem-tree-view.h" #include "screem-search.h" #include "screem-site-ui.h" #include "screem-tag-inspector.h" #include "screem-combo-box.h" #include "support.h" #include "pageUI.h" #include "fileops.h" #include "gdl.h" #include "gdl-dock-bar.h" #include "egg-editable-toolbar.h" enum { ARG_0, ARG_APP_ID, ARG_APP, ARG_CTAGSMODEL }; typedef enum _Drop_types { TARGET_URI_LIST, TARGET_URL, TARGET_MOZ } Drop_types; static const GtkTargetEntry drop_types[] = { { "text/uri-list", 0, TARGET_URI_LIST }, { "text/x-moz-url", 0, TARGET_MOZ }, { "_NETSCAPE_URL", 0, TARGET_URL }, { "x-url/http", 0, TARGET_URL }, { "x-url/ftp", 0, TARGET_URL }, }; static const gint num_drop_types = sizeof(drop_types) / sizeof(drop_types [0]); static const gchar *dock_items[] = { "ViewMessages", "Messages", "ViewErrors", "Errors", "ViewShortcut", "Shortcut", "ViewFiles", "Files", "ViewResources", "Resources", "ViewTree", "Structure", "ViewAttributes", "Attributes", "ViewSymbols", "Symbols", }; static const gint dock_n_items = G_N_ELEMENTS( dock_items ); void screem_window_set_document( ScreemWindow *window, ScreemPage *page ); static void screem_window_constructed( ScreemWindow *window ); static void screem_window_real_show_message( ScreemWindow *window, GtkWidget *view, const gchar *message, gboolean force_msgs ); static void screem_window_real_clear_messages( GtkWidget *view ); static gboolean screem_window_clear_status( ScreemWindow *window ); static void screem_window_mdi_change( ScreemMDI *mdi, ScreemPage *page, ScreemPage *previous, ScreemWindow *window ); static void screem_window_mime_change( ScreemPage *page, GParamSpec *spec, gpointer data ); static gboolean screem_window_mark_set( GtkTextBuffer *buffer, const GtkTextIter *it, GtkTextMark *mark, gpointer data ); static gboolean build_attribute_list( ScreemWindow *window ); static void screem_window_toggle_overwrite( ScreemEditor *editor, gboolean overwrite, gpointer data ); static gboolean screem_window_set_mime( ScreemWindow *window ); static void screem_window_mime_switch( GtkWidget *widget, ScreemWindow *window ); static void screem_window_highlight_spelling( ScreemSpell *spell, gint start, gint end, ScreemWindow *window ); static void screem_window_select_context_callback( ScreemTreeView *view, guint start, guint end, gpointer data ); static void screem_window_set_cursor( ScreemTreeView *view, guint start, gpointer data ); static void screem_window_site_action( GtkAction *action, SwitchSiteData *sd ); static void screem_window_drop( GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selectionData, guint info, guint time, ScreemWindow *window ); static void screem_window_layout_changed( GdlDock *dock, ScreemWindow *window ); static void screem_window_search_found( ScreemSearch *search, ScreemPage *page, guint pos, guint length, gpointer data ); static void screem_window_search_notfound( ScreemSearch *search, ScreemPage *page, gpointer data ); static void screem_window_ctags_jumpto( ScreemCtagsView *view, const gchar *pathname, const gchar *pattern, guint line, gpointer data ); static gboolean screem_window_state_event( GtkWindow *window, GdkEventWindowState *event, gpointer data ); static gchar *recent_tooltip_cb( EggRecentItem *item, gpointer data ); static void screem_window_site_name_change( ScreemSite *site, GParamSpec *pspec, ScreemWindow *window ); static void screem_window_message_adj_change( GtkAdjustment *adj ); static void screem_window_ctags_running( ScreemSite *site, ScreemWindow *window ); void screem_window_close( ScreemWindow *window ) { ScreemSite *site; ScreemPage *page; ScreemWindowDetails *details; g_return_if_fail( SCREEM_IS_WINDOW( window ) ); details = window->details; site = screem_window_get_current( window ); details->current = NULL; page = screem_mdi_get_current( details->mdi ); if( page ) { g_signal_handlers_disconnect_matched(G_OBJECT( page ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window ); g_signal_handlers_disconnect_matched(G_OBJECT( page ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, details->tagtree ); g_signal_handlers_disconnect_matched( G_OBJECT( page ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, details->tree_view ); g_signal_handlers_disconnect_matched( G_OBJECT( page ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, details->editor ); g_signal_handlers_disconnect_matched( G_OBJECT( page ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, details->preview ); g_signal_handlers_disconnect_matched( G_OBJECT( page ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, details->link_view ); } screem_mdi_set_current( details->mdi, NULL ); g_signal_handlers_disconnect_matched(G_OBJECT( window->dock ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window ); gtk_widget_destroy( GTK_WIDGET( window ) ); } static void screem_window_create_site_tab( ScreemWindow *window ) { GtkWidget *widget; window->details->site_view = widget = screem_site_view_new(); screem_site_view_set_window( SCREEM_SITE_VIEW( widget ), window ); gtk_widget_show_all( widget ); screem_window_add_dock_item( window, _( "Files" ), GTK_STOCK_HOME, "Files", widget, GTK_POS_RIGHT ); } static void screem_window_constructed( ScreemWindow *window ) { GtkWidget *box; ScreemWindowDetails *details; GtkWidget *button; gboolean offline; GtkWidget *widget; gchar *file; GtkAction *action; GtkWidget *sw; gchar *tmp; GtkTooltips *tip; GtkPositionType postype; GConfClient *client; gint toolbartype; GtkActionGroup *group; GtkWidget *mainbox; GdlDockItem *item; gint i; gboolean show; GtkAdjustment *adj; EggRecentViewUIManager *recentui; details = window->details; gtk_window_set_default_size( GTK_WINDOW( window ), 600, 400 ); gtk_window_set_wmclass( GTK_WINDOW( window ), "Screem", "mainwindow" ); /* content_hbox is the main display area of the window */ window->content_hbox = gtk_vbox_new( FALSE, 0 ); screem_window_init_actions( window ); /* we want a separate action group for current sites */ group = gtk_action_group_new( "OpenSites" ); gtk_action_group_set_translation_domain( group, GETTEXT_PACKAGE ); gtk_ui_manager_insert_action_group( GTK_UI_MANAGER( window->merge ), GTK_ACTION_GROUP( group ), 1 ); window->sites_group = group; group = window->action_group; /* we do this here as we need the GtkUIManager object * to be in existance */ details->mdi = screem_mdi_new( window ); g_signal_connect( G_OBJECT( details->mdi ), "changed", G_CALLBACK( screem_window_mdi_change ), window ); /* create the dock */ mainbox = gtk_hbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX( window->content_hbox ), mainbox, TRUE, TRUE, 0 ); window->dock = gdl_dock_new(); window->layout = G_OBJECT(gdl_dock_layout_new(GDL_DOCK(window->dock))); gtk_box_pack_end( GTK_BOX( mainbox ), window->dock, TRUE, TRUE, 0 ); /* create the status bar */ window->status = gtk_hbox_new( FALSE, 0 ); gtk_widget_show( window->status ); gtk_box_pack_start( GTK_BOX( window->content_hbox ), window->status, FALSE, TRUE, 0 ); /* overwrite mode status bar */ details->overwriteMode = gtk_statusbar_new(); gtk_statusbar_set_has_resize_grip( GTK_STATUSBAR( details->overwriteMode ), TRUE ); gtk_widget_show( details->overwriteMode ); gtk_box_pack_end( GTK_BOX( window->status ), details->overwriteMode, FALSE, FALSE, 0 ); gtk_label_set_width_chars( GTK_LABEL( GTK_STATUSBAR( details->overwriteMode )->label ), 12 ); /* cursor pos status bar */ details->cursorPosition = gtk_statusbar_new(); gtk_statusbar_set_has_resize_grip( GTK_STATUSBAR( details->cursorPosition ), FALSE ); gtk_widget_show( details->cursorPosition ); gtk_label_set_width_chars( GTK_LABEL( GTK_STATUSBAR( details->cursorPosition )->label ), 20 ); gtk_box_pack_end( GTK_BOX( window->status ), details->cursorPosition, FALSE, FALSE, 0 ); details->mime = GTK_WIDGET( screem_combo_box_new() ); details->mimetypes = GTK_TREE_MODEL( screem_support_get_mime_types_store() ); screem_combo_box_set_model( SCREEM_COMBO_BOX( details->mime ), details->mimetypes ); tip = gtk_tooltips_new(); gtk_tooltips_set_tip( tip, GTK_BIN( details->mime )->child, _( "Change type of document" ), "" ); g_object_set_data_full( G_OBJECT( details->mime ), "tipobj", tip, (GDestroyNotify)gtk_object_destroy ); gtk_widget_show( details->mime ); gtk_box_pack_end( GTK_BOX( window->status ), details->mime, FALSE, FALSE, 0 ); g_signal_connect( G_OBJECT( details->mime ), "changed", G_CALLBACK( screem_window_mime_switch ), window ); /* add all views into a box */ postype = screem_get_tab_position(); if( postype == GTK_POS_TOP || postype == GTK_POS_BOTTOM ) { box = gtk_vbox_new( FALSE, 0 ); } else { box = gtk_hbox_new( FALSE, 0 ); } details->box = gtk_hbox_new( FALSE, 0 ); if( postype == GTK_POS_TOP || postype == GTK_POS_LEFT ) { gtk_box_pack_end( GTK_BOX( box ), details->box, TRUE, TRUE, 0 ); } else { gtk_box_pack_start( GTK_BOX( box ), details->box, TRUE, TRUE, 0 ); } /* add our main dock area */ widget = gdl_dock_item_new_with_stock( "Main", _( "Main" ), NULL, GDL_DOCK_ITEM_BEH_LOCKED | GDL_DOCK_ITEM_BEH_NEVER_FLOATING | GDL_DOCK_ITEM_BEH_NO_GRIP ); gtk_container_add( GTK_CONTAINER( widget ), box ); gdl_dock_add_item( GDL_DOCK( window->dock ), GDL_DOCK_ITEM( widget ), GDL_DOCK_CENTER ); gtk_widget_show( widget ); /* add the editor / preview / link view etc */ details->editor = GTK_WIDGET( screem_editor_new( window ) ); g_object_ref( G_OBJECT( details->editor ) ); gtk_object_sink( GTK_OBJECT( details->editor ) ); gtk_widget_show_all( details->editor ); details->current = details->editor; g_signal_connect( G_OBJECT( details->editor ), "overwrite", G_CALLBACK( screem_window_toggle_overwrite ), window ); screem_window_toggle_overwrite( NULL, FALSE, window ); details->preview = GTK_WIDGET( screem_preview_new_with_window( window ) ); g_object_ref( G_OBJECT( details->preview ) ); gtk_object_sink( GTK_OBJECT( details->preview) ); gtk_widget_show_all( details->preview ); details->link_view = GTK_WIDGET( screem_link_view_new( window ) ); g_object_ref( G_OBJECT( details->link_view ) ); gtk_object_sink( GTK_OBJECT( details->link_view) ); gtk_widget_show_all( details->link_view ); details->tree_view = GTK_WIDGET( screem_tree_view_new( window ) ); g_object_ref( G_OBJECT( details->tree_view ) ); gtk_object_sink( GTK_OBJECT( details->tree_view) ); gtk_widget_show_all( details->tree_view ); g_signal_connect( G_OBJECT( details->tree_view ), "select_context", G_CALLBACK( screem_window_select_context_callback ), window ); g_signal_connect( G_OBJECT( details->tree_view ), "set_cursor", G_CALLBACK( screem_window_set_cursor ), window ); gtk_box_pack_start( GTK_BOX( details->box ), details->editor, TRUE, TRUE, 0 ); gtk_box_pack_start( GTK_BOX( details->box ), details->preview, TRUE, TRUE, 0 ); gtk_box_pack_start( GTK_BOX( details->box ), details->link_view, TRUE, TRUE, 0 ); gtk_box_pack_start( GTK_BOX( details->box ), details->tree_view, TRUE, TRUE, 0 ); gtk_widget_hide( details->editor ); gtk_widget_hide( details->preview ); gtk_widget_hide( details->link_view ); gtk_widget_hide( details->tree_view ); /* now create the notebook for the page tabs */ details->notebook = GTK_WIDGET( screem_mdi_get_notebook( details->mdi ) ); gtk_box_pack_start( GTK_BOX( box ), details->notebook, FALSE, FALSE, 0 ); gtk_widget_show( details->notebook ); gtk_widget_show( box ); /* dock stuff */ /* create site tab */ screem_window_create_site_tab( window ); /* create ctags model/tree */ details->ctagsmodel = screem_ctags_model_new(); details->ctagsview = screem_ctags_view_new(); g_signal_connect( G_OBJECT( details->ctagsview ), "jumpto", G_CALLBACK( screem_window_ctags_jumpto ), window ); gtk_tree_view_set_model( GTK_TREE_VIEW( details->ctagsview ), GTK_TREE_MODEL( details->ctagsmodel ) ); sw = gtk_scrolled_window_new( NULL, NULL ); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sw ), GTK_SHADOW_IN ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sw ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); gtk_container_add( GTK_CONTAINER( sw ), GTK_WIDGET( details->ctagsview ) ); gtk_widget_show_all( sw ); screem_window_add_dock_item( window, _( "Symbols" ), GTK_STOCK_PROPERTIES, "Symbols", sw, GTK_POS_RIGHT ); /* add attributes tab */ details->attrtab = (GtkWidget*)screem_tag_inspector_new( window ); g_signal_connect_swapped( G_OBJECT( details->attrtab ), "replace_attribute", G_CALLBACK( screem_view_insert_attribute ), details->editor ); gtk_widget_show_all( details->attrtab ); screem_window_add_dock_item( window, _( "Attributes" ), GTK_STOCK_INDEX, "Attributes", details->attrtab, GTK_POS_RIGHT ); /* create resources tree */ details->tagtree = GTK_WIDGET( screem_tag_tree_new() ); g_object_ref( G_OBJECT( details->tagtree ) ); gtk_object_sink( GTK_OBJECT( details->tagtree ) ); g_object_set( G_OBJECT( details->tagtree ), "window", window, NULL ); gtk_widget_show_all( details->tagtree ); screem_window_add_dock_item( window, _( "Resources" ), "Screem_Resources", "Resources", details->tagtree, GTK_POS_RIGHT ); gtk_widget_show( window->dock ); sw = gtk_scrolled_window_new( NULL, NULL ); adj = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW( sw ) ); g_signal_connect( G_OBJECT( adj ), "changed", G_CALLBACK( screem_window_message_adj_change ), adj ); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sw ), GTK_SHADOW_IN ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sw ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); details->messages = gtk_text_view_new(); gtk_text_view_set_editable( GTK_TEXT_VIEW( details->messages ), FALSE ); gtk_text_view_set_cursor_visible( GTK_TEXT_VIEW( details->messages ), FALSE ); gtk_container_add( GTK_CONTAINER( sw ), details->messages ); gtk_widget_show_all( sw ); screem_window_add_dock_item( window, _( "Messages" ), GTK_STOCK_DIALOG_INFO, "Messages", sw, GTK_POS_BOTTOM ); sw = gtk_scrolled_window_new( NULL, NULL ); adj = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW( sw ) ); g_signal_connect( G_OBJECT( adj ), "changed", G_CALLBACK( screem_window_message_adj_change ), adj ); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sw ), GTK_SHADOW_IN ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sw ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); details->errors = gtk_text_view_new(); gtk_text_view_set_editable( GTK_TEXT_VIEW( details->errors ), FALSE ); gtk_text_view_set_cursor_visible( GTK_TEXT_VIEW( details->errors ), FALSE ); gtk_container_add( GTK_CONTAINER( sw ), details->errors ); gtk_widget_show_all( sw ); screem_window_add_dock_item( window, _( "Errors" ), GTK_STOCK_DIALOG_ERROR, "Errors", sw, GTK_POS_BOTTOM ); gtk_widget_show( details->box ); gtk_widget_show( details->current ); gtk_widget_show( window->content_hbox ); gtk_container_add( GTK_CONTAINER( window ), window->content_hbox ); /* add online status control to status bar */ offline = window->details->offline = window->application->offline; button = gtk_button_new(); tip = gtk_tooltips_new(); gtk_tooltips_set_tip( tip, button, "", "" ); g_object_set_data_full( G_OBJECT( button ), "tipobj", tip, (GDestroyNotify)gtk_object_destroy ); gtk_button_set_relief( GTK_BUTTON( button ), GTK_RELIEF_NONE ); details->online_status = gtk_image_new(); gtk_container_add( GTK_CONTAINER( button ), details->online_status ); gtk_widget_show_all( button ); g_signal_connect_data( G_OBJECT( button ), "clicked", G_CALLBACK( screem_window_toggle_online_status), window, NULL, G_CONNECT_SWAPPED ); gtk_box_pack_start( GTK_BOX( window->status ), button, FALSE, FALSE, 0 ); gtk_widget_set_size_request( button, -1, 16 ); screem_window_toggle_online_status( window, NULL ); #if 0 widget = gdl_dock_bar_new( GDL_DOCK( window->dock ) ); gdl_dock_bar_set_orientation( GDL_DOCK_BAR( widget ), GTK_ORIENTATION_VERTICAL ); gtk_widget_show( widget ); gtk_box_pack_start( GTK_BOX( mainbox ), widget, FALSE, FALSE, 0 ); #endif window->status_text = gtk_statusbar_new(); gtk_box_pack_start( GTK_BOX( window->status ), window->status_text, TRUE, TRUE, 0 ); gtk_statusbar_set_has_resize_grip( GTK_STATUSBAR( window->status_text ), FALSE ); gtk_widget_show( window->status_text ); tmp = screem_get_dot_dir(); file = g_strconcat( tmp, G_DIR_SEPARATOR_S, "layoutv2", NULL ); g_free( tmp ); if( ! uri_exists( file, NULL ) ) { g_free( file ); file = g_strconcat( UIDATADIR, "layout", NULL ); } gdl_dock_layout_load_from_file( GDL_DOCK_LAYOUT(window->layout), file ); gdl_dock_layout_load_layout( GDL_DOCK_LAYOUT( window->layout ), "__default__" ); g_free( file ); /* get visible status of dockitems so we can set the * toggle items in the menu correctly */ for( i = 0; i < dock_n_items; i += 2 ) { action = gtk_action_group_get_action( group, dock_items[ i ] ); item = gdl_dock_get_item_by_name(GDL_DOCK(window->dock), dock_items[ i + 1 ] ); if( action && item ) { show = ( GTK_WIDGET( item )->parent != NULL ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(action), show ); g_object_set_data( G_OBJECT( action ), "item", item ); } } action = gtk_action_group_get_action( group, "ViewMainToolbar"); show = gconf_client_get_bool( window->application->client, "/apps/screem/ui/show_main_toolbar", NULL ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION( action ), show ); action = gtk_action_group_get_action( group, "ViewWizardToolbar"); show = gconf_client_get_bool( window->application->client, "/apps/screem/ui/show_wizard_toolbar", NULL ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION( action ), show ); window->search = screem_search_new(); g_object_set( G_OBJECT( window->search ), "window", window, "editor", window->details->editor, NULL ); g_signal_connect( G_OBJECT( window->search ), "found", G_CALLBACK( screem_window_search_found ), window ); g_signal_connect( G_OBJECT( window->search ), "notfound", G_CALLBACK( screem_window_search_notfound ), window ); gtk_widget_show_all( window->status ); gtk_widget_show( mainbox ); /* only do this here, otherwise we end up with a blank * layout file in some instances */ g_signal_connect( G_OBJECT( window->dock ), "layout_changed", G_CALLBACK( screem_window_layout_changed ), window ); g_signal_connect( G_OBJECT( window ), "window_state_event", G_CALLBACK( screem_window_state_event ), NULL ); screem_window_init_uis( window ); screem_window_mdi_change( details->mdi, NULL, NULL, window ); /* toolbar type */ client = gconf_client_get_default(); toolbartype = gconf_client_get_int( client, "/apps/screem/ui/toolbar_style", NULL ); switch( toolbartype ) { case 1: action = gtk_action_group_get_action( group, "ToolbarIcons" ); break; case 2: action = gtk_action_group_get_action( group, "ToolbarBoth" ); break; case 3: action = gtk_action_group_get_action( group, "ToolbarImportant" ); break; case 4: action = gtk_action_group_get_action( group, "ToolbarText" ); break; default: action = gtk_action_group_get_action( group, "ToolbarDefault" ); break; } gtk_toggle_action_set_active( GTK_TOGGLE_ACTION( action ), TRUE ); g_object_unref( client ); /* add recent pages and sites menu */ details->recent_site_model = egg_recent_model_new( EGG_RECENT_MODEL_SORT_MRU ); details->recent_page_model = egg_recent_model_new( EGG_RECENT_MODEL_SORT_MRU ); egg_recent_model_set_filter_groups( details->recent_site_model, RECENT_SITE_GROUP, NULL ); egg_recent_model_set_filter_groups( details->recent_page_model, RECENT_PAGE_GROUP, NULL ); egg_recent_model_set_limit( details->recent_site_model, 4 ); egg_recent_model_set_limit( details->recent_page_model, 4 ); /* create view for recent sites */ recentui = egg_recent_view_uimanager_new( GTK_UI_MANAGER( window->merge ), "/menubar/Site/RecentSites/", (GCallback)screem_window_recent_site_cb, window ); egg_recent_view_uimanager_set_trailing_sep( recentui, FALSE ); egg_recent_view_uimanager_set_tooltip_func( recentui, (EggUIManagerTooltipFunc)recent_tooltip_cb, "site" ); egg_recent_view_set_model( EGG_RECENT_VIEW( recentui ), details->recent_site_model ); details->recent_site_view = recentui; /* create view for recent pages */ recentui = egg_recent_view_uimanager_new( GTK_UI_MANAGER( window->merge ), "/menubar/File Menu/RecentPages/", (GCallback)screem_window_recent_page_cb, window ); egg_recent_view_uimanager_set_trailing_sep( recentui, FALSE ); egg_recent_view_uimanager_set_tooltip_func( recentui, (EggUIManagerTooltipFunc)recent_tooltip_cb, NULL ); egg_recent_view_set_model( EGG_RECENT_VIEW( recentui ), details->recent_page_model ); details->recent_page_view = recentui; /* We need another 2 for the dropdown on the open toolbar item */ recentui = egg_recent_view_uimanager_new( GTK_UI_MANAGER( window->merge ), "/openpopup/RecentPages", (GCallback)screem_window_recent_page_cb, window ); egg_recent_view_uimanager_set_trailing_sep( recentui, FALSE ); egg_recent_view_uimanager_set_tooltip_func( recentui, (EggUIManagerTooltipFunc)recent_tooltip_cb, NULL ); egg_recent_view_set_model( EGG_RECENT_VIEW( recentui ), details->recent_page_model ); details->recent_page_dropdown_view = recentui; recentui = egg_recent_view_uimanager_new( GTK_UI_MANAGER( window->merge ), "/openpopup/RecentSites/", (GCallback)screem_window_recent_site_cb, window ); egg_recent_view_uimanager_set_trailing_sep( recentui, FALSE ); egg_recent_view_uimanager_set_tooltip_func( recentui, (EggUIManagerTooltipFunc)recent_tooltip_cb, "site" ); egg_recent_view_set_model( EGG_RECENT_VIEW( recentui ), details->recent_site_model ); details->recent_site_dropdown_view = recentui; /* has to be done here */ show = gconf_client_get_bool( window->application->client, "/apps/screem/ui/show_main_toolbar", NULL ); if( show ) { egg_editable_toolbar_show( EGG_EDITABLE_TOOLBAR( window->toolbar ), "Main Toolbar" ); } else { egg_editable_toolbar_hide( EGG_EDITABLE_TOOLBAR( window->toolbar ), "Main Toolbar" ); } } void screem_window_change_view( ScreemWindow *window, GtkWidget *view ) { gboolean activate = FALSE; ScreemWindowDetails *details; ScreemView *current; details = window->details; current = details->current; if( current != view ) { if( view == details->editor ) { details->current = details->editor; } else if( view == details->preview ) { details->current = details->preview; } else if( view == details->link_view ) { details->current = details->link_view; } else if( view == details->tree_view ) { details->current = details->tree_view; } else { g_assert( FALSE ); } gtk_widget_hide( GTK_WIDGET( current ) ); gtk_widget_show( details->current ); screem_window_display_view( window ); } } void screem_window_add_site( ScreemWindow *window, ScreemSite *site ) { const gchar *name; GtkUIManager* merge; const gchar *pathname; SwitchSiteData *sd; gchar *verb_name; gchar *ename; GString *xml; gchar **paths; gint i; guint mergeid; GtkAction *action; name = screem_site_get_name( site ); sd = g_new0( SwitchSiteData, 1 ); sd->site = site; sd->window = window; /* GtkUIManager stuff */ merge = GTK_UI_MANAGER( window->merge ); ename = screem_escape_char( name, ' ' ); verb_name = g_strconcat( "SwitchSite_", ename, NULL ); g_free( ename ); pathname = screem_site_get_pathname( site ); if( ! pathname ) { pathname = _( "Individual Files" ); } ename = screem_escape_underlines( name ); action = gtk_action_new( verb_name, ename, pathname, "Screem_Site" ); g_free( ename ); g_signal_connect( G_OBJECT( action ), "activate", G_CALLBACK( screem_window_site_action ), sd ); gtk_action_group_add_action( GTK_ACTION_GROUP( window->sites_group ), action ); paths = g_strsplit ("menu/Site/SwitchTo", "/", 0); xml = g_string_new (""); for (i=0; paths[i]; ++i) { if (!strcmp("menu",paths[i])) { g_string_append (xml, ""); } else { g_string_append_printf (xml, "", paths[i] ); } } g_string_append_printf (xml, "", verb_name); for ( ; i > 0; -- i ) { if (!strcmp("menu",paths[i-1])) { g_string_append (xml, ""); } else { g_string_append (xml, ""); } } g_string_append (xml, ""); mergeid = gtk_ui_manager_add_ui_from_string (merge, xml->str, xml->len, NULL); g_object_set_data( G_OBJECT( action ), "mergeid", GUINT_TO_POINTER( mergeid ) ); g_object_set_data_full( G_OBJECT( action ), "sitedata", sd, (GDestroyNotify)g_free ); g_string_free( xml, TRUE ); g_free( verb_name ); g_signal_connect( G_OBJECT( site ), "notify::name", G_CALLBACK( screem_window_site_name_change ), window ); } void screem_window_remove_site( ScreemWindow *window, ScreemSite *site ){ GList *actions; GList *tmp; GtkAction *action; guint mergeid; SwitchSiteData *sd; actions = gtk_action_group_list_actions( window->sites_group ); for( tmp = actions; tmp; tmp = tmp->next ) { sd = g_object_get_data( G_OBJECT( tmp->data ), "sitedata" ); if( sd->site == site ) { break; } } /* we must find the site or something really bad has happened */ g_assert( tmp ); action = GTK_ACTION( tmp->data ); g_signal_handlers_disconnect_matched( G_OBJECT( site ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window ); mergeid = GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( action ), "mergeid" ) ); gtk_action_group_remove_action( GTK_ACTION_GROUP( window->sites_group ), action ); gtk_ui_manager_remove_ui( GTK_UI_MANAGER( window->merge ), mergeid ); g_list_free( actions ); } void screem_window_set_current( ScreemWindow *window, ScreemSite *site ) { ScreemWindowDetails *details; GList *docs; GList *tmp; GtkActionGroup *group; GtkAction *action; gboolean enable = ( ! screem_site_get_fake_flag( site ) ); static const gchar* elements[] = { "Save Template", "Close Site", "UploadWizard", "SiteSettings", "SiteStats", "UpdateSite", "ImportSite", "CommitSite", "TaskList", "FixLinks", NULL }; gint i; const gchar *pathname; ScreemPage *page; g_return_if_fail( SCREEM_IS_WINDOW( window ) ); g_return_if_fail( SCREEM_IS_SITE( site ) ); details = window->details; if( site == details->current_site ) { return; } screem_site_view_set_site( SCREEM_SITE_VIEW( window->details->site_view ), site ); if( details->current_site ) { /* store documents list */ docs = screem_mdi_get_document_list( details->mdi ); if( docs ) { docs = g_list_copy( docs ); } screem_site_set_documents( details->current_site, details->name, docs ); screem_mdi_remove_all( details->mdi ); } details->current_site = site; pathname = screem_site_get_pathname( site ); screem_ctags_model_set_pathname( details->ctagsmodel, pathname ); /* enable || disable ui elements */ group = window->action_group; for( i = 0; elements[ i ]; ++ i ) { action = gtk_action_group_get_action( group, elements[ i ] ); if( action ) { gtk_action_set_sensitive( GTK_ACTION( action ), enable ); } } /* now loop through the documents and insert each page */ docs = screem_site_get_documents( site, details->name ); for( tmp = docs; docs; docs = docs->next ) { screem_mdi_add_document( details->mdi, SCREEM_PAGE( docs->data ) ); } page = NULL; if( tmp ) { page = SCREEM_PAGE( tmp->data ); screem_mdi_set_current( details->mdi, page ); } else { screem_window_mdi_change( details->mdi, NULL, NULL, window ); } action = gtk_action_group_get_action( group, "Save Template" ); gtk_action_set_sensitive( action, ( enable &&( page != NULL ) ) ); } ScreemSite *screem_window_get_current( ScreemWindow *window ) { return window->details->current_site; } void screem_window_set_document( ScreemWindow *window, ScreemPage *page ) { const gchar *pathname; const gchar *mime_type; ScreemWindowDetails *details; ScreemSite *site; gboolean loaded; EggRecentItem *item; g_return_if_fail( SCREEM_IS_WINDOW( window ) ); details = window->details; if( ! details->current ) { /* no current view, don't display, probably destroying the window */ return; } loaded = screem_mdi_set_current( details->mdi, page ); site = screem_window_get_current( window ); if( loaded && screem_site_get_fake_flag( site ) ) { pathname = screem_page_get_pathname( page ); if( pathname ) { mime_type = screem_page_get_mime_type( page ); item = egg_recent_item_new_from_uri( pathname ); egg_recent_item_set_mime_type( item, mime_type ); egg_recent_item_add_group( item, RECENT_PAGE_GROUP ); egg_recent_model_add_full( details->recent_page_model, item ); egg_recent_item_unref( item ); } } } ScreemPage* screem_window_get_document( ScreemWindow *window ) { return screem_mdi_get_current( window->details->mdi ); } void screem_window_remove_document( ScreemWindow *window, ScreemPage *page ) { screem_mdi_remove_document( window->details->mdi, page ); } void screem_window_show_message( ScreemWindow *window, const gchar *message, gboolean force_msgs ) { screem_window_real_show_message( window, window->details->messages, message, force_msgs ); } void screem_window_show_error( ScreemWindow *window, const gchar *error, gboolean force_msgs ) { screem_window_real_show_message( window, window->details->errors, error, force_msgs ); } void screem_window_clear_messages( ScreemWindow *window ) { screem_window_real_clear_messages( window->details->messages ); } void screem_window_clear_errors( ScreemWindow *window ) { screem_window_real_clear_messages( window->details->errors ); } void screem_window_print( ScreemWindow *window, gboolean preview ) { ScreemWindowDetails *details; details = window->details; screem_view_print( SCREEM_VIEW( details->current ), preview ); } void screem_window_display_view( ScreemWindow *window ) { ScreemSite *site; ScreemPage *page; ScreemWindowDetails *details; details = window->details; site = screem_window_get_current( window ); page = screem_mdi_get_current( details->mdi ); if( site && details->current ) { g_object_set( G_OBJECT( details->current ), "online", ! window->details->offline, NULL ); screem_view_display( SCREEM_VIEW( details->current ) ); if( details->current != details->tree_view ) { screem_view_display( SCREEM_VIEW( details->tree_view ) ); } } } void screem_window_toggle_online_status( ScreemWindow *window, gpointer data ) { ScreemApplication *application; GConfClient *client; gboolean offline; GtkAction *action; GtkWidget *widget; GtkTooltips *tip; GtkTooltipsData *tip_data; gchar *tiptxt; application = window->application; client = application->client; if( data ) { /* toggle actual setting */ application->offline = ! application->offline; } offline = application->offline; if( window->details->offline != offline ) { gconf_client_set_bool( client, "/apps/screem/general/work_offline", offline, NULL ); window->details->offline = offline; } widget = gtk_widget_get_parent( window->details->online_status ); tip_data = gtk_tooltips_data_get( widget ); tip = tip_data->tooltips; action = gtk_action_group_get_action( GTK_ACTION_GROUP( window->action_group ), "Offline" ); g_object_set( G_OBJECT( action ), "visible", ! offline, NULL ); if( ! offline ) { g_object_get( G_OBJECT( action ), "tooltip", &tiptxt, NULL ); gtk_tooltips_set_tip( tip, widget, tiptxt, "" ); g_free( tiptxt ); } action = gtk_action_group_get_action( GTK_ACTION_GROUP( window->action_group ), "Online" ); g_object_set( G_OBJECT( action ), "visible", offline, NULL ); if( offline ) { g_object_get( G_OBJECT( action ), "tooltip", &tiptxt, NULL ); gtk_tooltips_set_tip( tip, widget, tiptxt, "" ); g_free( tiptxt ); } gtk_image_set_from_stock( GTK_IMAGE( window->details->online_status ), offline ? "Screem_Offline" : "Screem_Online", GTK_ICON_SIZE_BUTTON ); } GList *screem_window_get_documents( ScreemWindow *window ) { g_return_val_if_fail( SCREEM_IS_WINDOW( window ), NULL ); return screem_mdi_get_document_list( window->details->mdi ); } gchar *screem_window_get_selection( ScreemWindow *window ) { ScreemEditor *editor; ScreemPage *page; guint start; guint end; gchar *ret; editor = SCREEM_EDITOR( window->details->editor ); page = screem_window_get_document( window ); if( screem_view_has_selection( SCREEM_VIEW( editor ), &start, &end ) ) { ret = screem_view_get_text( SCREEM_VIEW( editor ), start, end - start ); } else if( page ) { ret = screem_page_get_data( page ); } else { ret = NULL; } return ret; } void screem_window_replace_selection( ScreemWindow *window, const gchar *data ) { ScreemEditor *editor; ScreemPage *page; guint start; guint end; editor = SCREEM_EDITOR( window->details->editor ); page = screem_window_get_document( window ); if( page && ! screem_view_has_selection( SCREEM_VIEW( editor ), &start, &end ) ) { start = 0; end = gtk_text_buffer_get_char_count( GTK_TEXT_BUFFER( page ) ); } screem_view_delete_forward( SCREEM_VIEW( editor ), start, end - start ); screem_view_insert( SCREEM_VIEW( editor ), start, data ); } static void screem_window_dock_item_hidden( GtkWidget *item, ScreemWindow *window ) { gchar *name; gint i; GtkActionGroup *group; GtkAction *action; g_object_get( G_OBJECT( item ), "name", &name, NULL ); group = window->action_group; action = NULL; for( i = 0; i < dock_n_items; i += 2 ) { if( ! strcmp( dock_items[ i + 1 ], name ) ) { action = gtk_action_group_get_action( group, dock_items[ i ] ); break; } } if( action ) { gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(action), FALSE ); } g_free( name ); } static void screem_window_dock_item_locked( GtkWidget *item, GParamSpec *pspec, ScreemWindow *window ) { gchar *name; gint i; GtkActionGroup *group; GtkAction *action; gboolean locked; g_object_get( G_OBJECT( item ), "name", &name, "locked", &locked, NULL ); group = window->action_group; action = NULL; for( i = 0; i < dock_n_items; i += 2 ) { if( ! strcmp( dock_items[ i + 1 ], name ) ) { action = gtk_action_group_get_action( group, dock_items[ i ] ); break; } } if( action ) { gtk_action_set_sensitive( GTK_ACTION( action ), ! locked ); } g_free( name ); } void screem_window_add_dock_item( ScreemWindow *window, const gchar *text, const gchar *stock_id, const gchar *name, GtkWidget *item, GtkPositionType pos ) { GtkWidget *widget; GdlDockPlacement place; switch( pos ) { case GTK_POS_LEFT: place = GDL_DOCK_LEFT; break; case GTK_POS_RIGHT: place = GDL_DOCK_RIGHT; break; case GTK_POS_TOP: place = GDL_DOCK_TOP; break; case GTK_POS_BOTTOM: place = GDL_DOCK_BOTTOM; break; default: g_warning( "Unsupported pos for dock item" ); return; break; } widget = gdl_dock_item_new_with_stock( name, text, stock_id, GDL_DOCK_ITEM_BEH_NORMAL | GDL_DOCK_ITEM_BEH_CANT_ICONIFY ); gtk_container_add( GTK_CONTAINER( widget ), item ); gdl_dock_add_item( GDL_DOCK( window->dock ), GDL_DOCK_ITEM( widget ), place ); gtk_widget_show( widget ); g_signal_connect( G_OBJECT( widget ), "hide", G_CALLBACK( screem_window_dock_item_hidden ), window ); g_signal_connect( G_OBJECT( widget ), "notify::locked", G_CALLBACK( screem_window_dock_item_locked ), window ); } void screem_window_set_title( ScreemWindow *window, ScreemPage *page ) { gchar *tmp; gchar *title; if( page ) { tmp = screem_page_get_title_name( page ); if( screem_page_get_changed( page ) ) { title = g_strdup_printf( "* %s - Screem", tmp ); } else { title = g_strdup_printf( "%s - Screem", tmp ); } g_free( tmp ); } else { title = g_strdup( _( "No Document - Screem" ) ); } gtk_window_set_title( GTK_WINDOW( window ), title ); g_free( title ); } ScreemView *screem_window_get_view( ScreemWindow *window ) { g_return_val_if_fail( SCREEM_IS_WINDOW( window ), NULL ); return window->details->current; } static void screem_window_real_show_message( ScreemWindow *window, GtkWidget *view, const gchar *message, gboolean force_msgs ) { ScreemApplication *application; GtkTextBuffer *buffer; GtkTextIter it; GtkTextIter eit; gint buffersize; g_return_if_fail( GTK_IS_TEXT_VIEW( view ) ); application = SCREEM_APPLICATION( window->application ); buffersize = gconf_client_get_int( application->client, "/apps/screem/messagelines", NULL ); /* put in status bar, or message box */ if( ( ! force_msgs ) && ( ! strchr( message, '\n' ) ) ) { if( window->details->status_timeout ) { g_source_remove( window->details->status_timeout ); gtk_statusbar_pop( GTK_STATUSBAR( window->status_text ), 0 ); } gtk_statusbar_push( GTK_STATUSBAR( window->status_text ), 0, message ); } else { GtkWidget *dockitem; GdlDockObject *parent; /* first parent is the scrolled window */ dockitem = gtk_widget_get_parent( view ); /* second is the GdlDockItem */ dockitem = gtk_widget_get_parent( dockitem ); parent = gdl_dock_object_get_parent_object( GDL_DOCK_OBJECT( dockitem ) ); if( GDL_IS_DOCK_NOTEBOOK( parent ) ) { GtkWidget *notebook; guint pnum; notebook = GDL_DOCK_ITEM( parent )->child; pnum=gtk_notebook_page_num( GTK_NOTEBOOK( notebook ), dockitem ); gtk_notebook_set_current_page( GTK_NOTEBOOK(notebook), pnum ); } buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); /* first trim the buffer if needed*/ gtk_text_buffer_get_end_iter( buffer, &eit ); if( gtk_text_iter_get_line( &eit ) > buffersize ) { gtk_text_buffer_get_iter_at_line( buffer, &it, 0 ); gtk_text_buffer_get_iter_at_line( buffer, &eit, 1 ); gtk_text_buffer_delete( buffer, &it, &eit ); } /* insert the message */ gtk_text_buffer_get_end_iter( buffer, &eit ); gtk_text_buffer_insert( buffer, &eit, message, strlen( message ) ); gtk_text_buffer_get_end_iter( buffer, &eit ); if( ! force_msgs ) { gtk_text_buffer_insert( buffer, &eit, "\n", strlen( "\n" ) ); } } /* gdk_threads_leave(); while( g_main_context_pending(NULL) ) { g_main_context_iteration(NULL,TRUE); } gdk_threads_enter();*/ /* set timeout to clear status bar */ window->details->status_timeout = g_timeout_add( 5000, (GSourceFunc)screem_window_clear_status, window ); } static void screem_window_real_clear_messages( GtkWidget *view ) { GtkTextBuffer *buffer; GtkTextIter it; GtkTextIter eit; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); gtk_text_buffer_get_start_iter( buffer, &it ); gtk_text_buffer_get_end_iter( buffer, &eit ); gtk_text_buffer_delete( buffer, &it, &eit ); buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW( view ) ); } static gboolean screem_window_clear_status( ScreemWindow *window ) { gdk_threads_enter(); gtk_statusbar_pop( GTK_STATUSBAR( window->status_text ), 0 ); window->details->status_timeout = 0; gdk_threads_leave(); return FALSE; } static void screem_window_mdi_change( ScreemMDI *mdi, ScreemPage *page, ScreemPage *previous, ScreemWindow *window ) { ScreemWindowDetails *details; gboolean enable; static const gchar* elements[] = { "Save Document", "Save Document As", "Save Copy", "Save Template", "Close Document", "CloseAll", "Print", "PrintPreview", "Undo", "Redo", "Cut", "Copy", "Paste", "PasteText", "PasteEncoded", "Clear", "SelectAll", "SelectContext", "SelectContent", "Find","FindAgain", "Replace", "Find XPath", "Find XPath Again", "GotoLine", "GotoContextStart", "GotoContextEnd", "GotoParent", "NextAttribute", "PrevAttribute", "Bookmarks", "Auto Indent", "Indent", "UnIndent", "Encode Entities", "URL Encode", "TagLower", "TagUpper", "MarkEditable", "SpellCheck", "Browser0", "Bold", "Italic", "Underline", "Para", "Bullet", "Numbered", "AlignLeft", "AlignCentre", "AlignRight", "Justify", "Font", "Pre", "Subscript", "Superscript", "Table", "TBody", "Tr", "Th", "Td", "Caption", "Summary", "Textarea", "Input", "Fileinput", "Button", "Checkbutton", "Radiobutton", "Optionmenu", "flash object", "applet object", "Basic Structure", "Closing Tag", "Generator", "Author", "Content-Type", "Content-Script-Type", "Content-Style-Type", "MetaRefresh", "InsertDoctype", "InsertFile", "InsertCommand", "CommitPage", "UpdatePage", "TemplateUpdate", NULL }; gint i; GtkActionGroup *group; const gchar *type; const gchar *showtype; GtkTreeIter tit; details = window->details; enable = ( page != NULL ); group = window->action_group; for( i = 0; elements[ i ]; ++ i ) { GtkAction *action; action = gtk_action_group_get_action( group, elements[ i ] ); gtk_action_set_sensitive( GTK_ACTION( action ), enable ); } screem_window_display_view( window ); if( details->tagtree ) { g_object_set( G_OBJECT( details->tagtree ), "page", page, NULL ); } if( details->handle ) { g_source_remove( details->handle ); details->handle = 0; } /* setup status bars for this page */ if( previous ) { g_signal_handlers_disconnect_matched( G_OBJECT( previous ), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window ); if( gtk_tree_model_get_iter_first( details->mimetypes, &tit ) ) { gtk_list_store_remove( GTK_LIST_STORE( details->mimetypes ), &tit ); } } if( details->mime ) { gtk_widget_set_sensitive( details->mime, enable ); gtk_widget_set_sensitive( details->cursorPosition, enable ); gtk_widget_set_sensitive( details->attrtab, enable ); /* gtk_widget_set_sensitive( details->overwriteMode, enable );*/ } if( enable ) { g_signal_connect( G_OBJECT( page ), "mark_set", G_CALLBACK( screem_window_mark_set ), window ); g_signal_connect( G_OBJECT( page ), "notify::mime-type", G_CALLBACK( screem_window_mime_change ), window ); g_signal_connect( G_OBJECT( page ), "notify::pathname", G_CALLBACK( screem_window_mime_change ), window ); type = screem_page_get_mime_type( page ); g_assert( type ); showtype = gnome_vfs_mime_get_description( type ); if( ! showtype ) { showtype = type; } gtk_list_store_prepend( GTK_LIST_STORE( details->mimetypes ), &tit ); gtk_list_store_set( GTK_LIST_STORE( details->mimetypes ), &tit, 0, showtype, 1, type, -1 ); screem_combo_box_set_active_iter( SCREEM_COMBO_BOX( details->mime ), &tit ); } screem_window_set_title( window, page ); } static void screem_window_mime_change( ScreemPage *page, GParamSpec *spec, gpointer data ) { ScreemWindow *window; ScreemWindowDetails *details; const gchar *type; const gchar *showtype; GtkTreeIter tit; const gchar *pathname; window = SCREEM_WINDOW( data ); details = window->details; type = screem_page_get_mime_type( page ); g_assert( type ); showtype = gnome_vfs_mime_get_description( type ); if( ! showtype ) { showtype = type; } if( gtk_tree_model_get_iter_first( details->mimetypes, &tit ) ) { gtk_list_store_set( GTK_LIST_STORE( details->mimetypes ), &tit, 0, showtype, 1, type, -1 ); screem_combo_box_set_active_iter( SCREEM_COMBO_BOX( details->mime ), &tit ); } screem_window_display_view( window ); pathname = screem_page_get_pathname( page ); screem_window_set_title( window, page ); } static gboolean screem_window_real_mark_set( ScreemWindow *window ) { ScreemWindowDetails *details; ScreemPage *page; GtkStatusbar *bar; GtkTextIter it; gint pos; guint row; guint col; gchar *mesg; gint len; details = window->details; details->markset_idle = 0; page = screem_window_get_document( window ); if( page ) { if( window->details->handle ) { g_source_remove( window->details->handle ); } window->details->handle = g_timeout_add( 1500, (GSourceFunc)build_attribute_list, window ); bar = GTK_STATUSBAR( window->details->cursorPosition ); gdk_threads_enter(); pos = screem_view_get_pos( SCREEM_VIEW( details->editor ) ); gtk_text_buffer_get_iter_at_offset( GTK_TEXT_BUFFER( page ), &it, pos ); row = gtk_text_iter_get_line( &it ) + 1; col = gtk_text_iter_get_line_offset( &it ) + 1; gtk_statusbar_pop( bar, 0 ); mesg = g_strdup_printf( _(" Ln %d, Col. %d"), row, col ); len = strlen( mesg ); len = MAX( len, 18 ); gtk_label_set_width_chars( GTK_LABEL( bar->label ), len + 2 ); gtk_statusbar_push( bar, 0, mesg ); gdk_threads_leave(); g_free( mesg ); } return FALSE; } static gboolean screem_window_mark_set( GtkTextBuffer *buffer, const GtkTextIter *it, GtkTextMark *mark, gpointer data ) { ScreemWindow *window; ScreemWindowDetails *details; ScreemPage *page; g_return_val_if_fail( SCREEM_IS_WINDOW( data ), FALSE ); window = SCREEM_WINDOW( data ); details = window->details; page = SCREEM_PAGE( buffer ); if( page ) { if( details->markset_idle ) { g_source_remove( details->markset_idle ); details->markset_idle = 0; } details->markset_idle = g_idle_add( (GSourceFunc)screem_window_real_mark_set, window ); } return TRUE; } static gboolean build_attribute_list( ScreemWindow *window ) { ScreemWindowDetails *details; ScreemEditor *editor; ScreemPage *page; gint pos; gint ppos; details = window->details; editor = SCREEM_EDITOR( details->editor ); details->handle = 0; page = screem_window_get_document( window ); if( ! page ) { return FALSE; } gdk_threads_enter(); pos = screem_view_get_pos( SCREEM_VIEW( editor ) ); ppos = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( editor ), "ppos" ) ); if( screem_tag_inspector_inspect( SCREEM_TAG_INSPECTOR( details->attrtab ), page, pos, ppos ) ) { g_object_set_data( G_OBJECT( editor ), "ppos", GINT_TO_POINTER( pos ) ); } else { g_object_set_data( G_OBJECT( editor ), "ppos", GINT_TO_POINTER( -1 ) ); } gdk_threads_leave(); return FALSE; } static void screem_window_toggle_overwrite( ScreemEditor *editor, gboolean overwrite, gpointer data ) { ScreemWindow *window; ScreemWindowDetails *details; gchar *mesg; gint len; window = SCREEM_WINDOW( data ); details = window->details; gtk_statusbar_pop( GTK_STATUSBAR( details->overwriteMode ), 0 ); if( overwrite ) { mesg = g_strdup( _( " OVR" ) ); } else { mesg = g_strdup( _( " INS" ) ); } len = strlen( mesg ); len = MAX( len, 10 ); gtk_label_set_width_chars( GTK_LABEL( GTK_STATUSBAR( details->overwriteMode )->label ), len + 2 ); gtk_statusbar_push( GTK_STATUSBAR( details->overwriteMode ), 0, mesg ); g_free( mesg ); } static gboolean screem_window_set_mime( ScreemWindow *window ) { ScreemPage *page; gchar *mime_type; gdk_threads_enter(); mime_type = g_object_get_data( G_OBJECT( window ), "mime_type" ); page = screem_window_get_document( window ); screem_page_set_mime_type( page, mime_type ); g_free( mime_type ); gdk_threads_leave(); return FALSE; } static void screem_window_mime_switch( GtkWidget *widget, ScreemWindow *window ) { GtkTreeModel *model; GtkTreeIter it; gchar *mime_type; ScreemPage *page; const gchar *pmime; page = screem_window_get_document( window ); if( ! page ) { return; } model = screem_combo_box_get_model( SCREEM_COMBO_BOX( widget ) ); screem_combo_box_get_active_iter( SCREEM_COMBO_BOX( widget ), &it ); gtk_tree_model_get( model, &it, 1, &mime_type, -1 ); pmime = screem_page_get_mime_type( page ); if( pmime && mime_type && strcmp( pmime, mime_type ) ) { g_object_set_data( G_OBJECT( window ), "mime_type", mime_type ); g_idle_add_full( G_PRIORITY_HIGH_IDLE, (GSourceFunc)screem_window_set_mime, window, NULL ); } else { g_free( mime_type ); } } static void screem_window_highlight_spelling( ScreemSpell *spell, gint start, gint end, ScreemWindow *window ) { ScreemEditor *editor; editor = SCREEM_EDITOR( window->details->editor ); screem_view_select_region( SCREEM_VIEW( editor ), start, end - start ); } static void screem_window_select_context_callback( ScreemTreeView *view, guint start, guint end, gpointer data ) { ScreemWindow *window; ScreemEditor *editor; window = SCREEM_WINDOW( data ); editor = SCREEM_EDITOR( window->details->editor ); screem_view_select_region( SCREEM_VIEW( editor ), start, end - start ); if( GTK_WIDGET( editor ) == window->details->current ) { gtk_widget_grab_focus( GTK_WIDGET( editor ) ); } } static void screem_window_set_cursor( ScreemTreeView *view, guint start, gpointer data ) { ScreemWindow *window; ScreemEditor *editor; window = SCREEM_WINDOW( data ); editor = SCREEM_EDITOR( window->details->editor ); screem_view_set_pos( SCREEM_VIEW( editor ), start ); } static void screem_window_site_action( GtkAction *action, SwitchSiteData *sd ) { screem_window_set_current( sd->window, sd->site ); } static void screem_window_drop( GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selectionData, guint info, guint time, ScreemWindow *window ) { ScreemApplication *app; ScreemSite *dsite; ScreemSite *site; gboolean handled; GList *uris; GList *tmp; gchar *text; handled = FALSE; app = window->application; if( info == TARGET_MOZ ) { glong read; glong written; text = g_utf16_to_utf8( (const gunichar2*)selectionData->data, selectionData->length, &read, &written, NULL ); } else { text = g_strdup( (gchar*)selectionData->data ); } dsite = screem_application_get_default_site( app ); switch( info ) { case TARGET_MOZ: case TARGET_URL: case TARGET_URI_LIST: uris = gnome_vfs_uri_list_parse( text ); for( tmp = uris; tmp; tmp = tmp->next ) { GnomeVFSURI *uri; gchar *url; uri = (GnomeVFSURI*)tmp->data; url = gnome_vfs_uri_to_string( uri, 0 ); if( ( ! window->details->offline ) || gnome_vfs_uri_is_local( uri ) ) { handled = TRUE; if( screem_uri_is_dir( url ) ) { screem_site_open_with_filename( window, app, url ); } else { site = screem_window_get_current( window ); if( ! screem_site_locate_page( site, url ) ) { site = dsite; } screem_page_open_with_filename( site, window, url ); } } gnome_vfs_uri_unref( uri ); } g_list_free( uris ); break; default: /* we don't know about this type, and as such this case should never execute */ screem_window_show_error( SCREEM_WINDOW( window ), _("Error: invalid drop type for window occured\n"), FALSE ); break; } g_free( text ); gtk_drag_finish( context, handled, FALSE, time ); } static void screem_window_layout_changed( GdlDock *dock, ScreemWindow *window ) { gchar *file; gchar *tmp; tmp = screem_get_dot_dir(); file = g_strconcat( tmp, G_DIR_SEPARATOR_S, "layoutv2", NULL ); g_free( tmp ); gdl_dock_layout_save_layout( GDL_DOCK_LAYOUT( window->layout ), "__default__" ); gdl_dock_layout_save_to_file( GDL_DOCK_LAYOUT( window->layout ), file ); g_free( file ); } static void screem_window_search_found( ScreemSearch *search, ScreemPage *page, guint pos, guint length, gpointer data ) { ScreemWindow *window; ScreemEditor *editor; window = SCREEM_WINDOW( data ); editor = SCREEM_EDITOR( window->details->editor ); screem_view_select_region( SCREEM_VIEW( editor ), pos, length ); } static void screem_window_search_notfound( ScreemSearch *search, ScreemPage *page, gpointer data ) { ScreemWindow *window; gchar *tmp; gchar *msg; window = SCREEM_WINDOW( data ); tmp = screem_search_get_find_pattern( search ); msg = g_strdup_printf( _( "No match found for: %s" ), tmp ); g_free( tmp ); /* show in status */ screem_window_show_message( window, msg, FALSE ); /* show in messages as well, then force a newline */ screem_window_show_message( window, msg, TRUE ); screem_window_show_message( window, "\n", TRUE ); g_free( msg ); } static gboolean screem_window_ctags_jumpto_idle( ScreemWindow *window ) { ScreemEditor *editor; ScreemPage *page; gchar *pattern; gchar *text; gchar *found; guint len; guint pos; editor = SCREEM_EDITOR( window->details->editor ); gdk_threads_enter(); page = screem_window_get_document( window ); pattern = g_object_get_data( G_OBJECT( window ), "ctagspattern" ); text = screem_page_get_data( page ); found = find_text( text, pattern, NULL, &len ); if( found ) { pos = found - text; screem_view_select_region( SCREEM_VIEW( editor ), pos, len ); } else { g_print( "FAILED TO FIND: %s\n", pattern ); } g_free( pattern ); g_free( text ); gdk_threads_leave(); return FALSE; } static void screem_window_ctags_jumpto( ScreemCtagsView *view, const gchar *pathname, const gchar *pattern, guint line, gpointer data ) { ScreemWindow *window; ScreemSite *site; ScreemPage *page; ScreemEditor *editor; gchar *tmp; window = SCREEM_WINDOW( data ); site = screem_window_get_current( window ); editor = SCREEM_EDITOR( window->details->editor ); if( screem_page_open_with_filename( site, window, pathname ) ) { page = screem_site_locate_page( site, pathname ); if( ! pattern ) { /* jump to line */ screem_editor_goto_line( editor, line ); } else { tmp = screem_support_escape_regexp( pattern ); g_object_set_data( G_OBJECT( window ), "ctagspattern", tmp ); g_idle_add( (GSourceFunc)screem_window_ctags_jumpto_idle, window ); } } } static gboolean screem_window_state_event( GtkWindow *window, GdkEventWindowState *event, gpointer data ) { ScreemWindow *swindow; ScreemWindowDetails *details; gint x; gint y; gint w; gint h; swindow = SCREEM_WINDOW( window ); details = swindow->details; switch( event->type ) { case GDK_WINDOW_STATE: if( event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED ) { swindow->max = ( event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED ); if( ! swindow->max ) { gtk_window_get_position( window, &x, &y ); gtk_window_get_size( window, &w, &h ); swindow->x = x; swindow->y = y; swindow->w = w; swindow->h = h; } } break; default: break; } return FALSE; } static gchar *recent_tooltip_cb( EggRecentItem *item, gpointer data ) { gchar *url; gchar *tmp; gchar *ret; url = egg_recent_item_get_uri( item ); if( data ) { tmp = _( "Open site: " ); } else { tmp = _( "Open: " ); } ret = g_strdup_printf( "%s %s", tmp, url ); g_free( url ); return ret; } static void screem_window_site_name_change( ScreemSite *site, GParamSpec *pspec, ScreemWindow *window ) { const gchar *name; GtkWidget *tree; GtkTreeViewColumn *column; gchar *ename; screem_window_remove_site( window, site ); screem_window_add_site( window, site ); #if 0 name = screem_site_get_name( site ); ename = screem_escape_underlines( name ); tree = window->details->folders; column = gtk_tree_view_get_column( GTK_TREE_VIEW( tree ), 0 ); gtk_tree_view_column_set_title( column, ename ); g_free( ename ); #endif } static void screem_window_message_adj_change( GtkAdjustment *adj ) { gtk_adjustment_set_value( adj, adj->upper - adj->page_size ); } static void screem_window_ctags_running( ScreemSite *site, ScreemWindow *window ) { const gchar *name; gchar *msg; name = screem_site_get_name( site ); msg = g_strdup_printf( "running ctags on %s", name ); screem_window_show_message( window, msg, FALSE ); g_free( msg ); } /* GObject Stuff */ G_DEFINE_TYPE( ScreemWindow, screem_window, GTK_TYPE_WINDOW ) static void screem_window_finalize( GObject *object ); static void screem_window_set_prop( GObject *object, guint prop_id, const GValue *value, GParamSpec *spec ); static void screem_window_get_prop( GObject *object, guint prop_id, GValue *value, GParamSpec *spec ); static void screem_window_class_init( ScreemWindowClass *klass) { GObjectClass *object_class; GParamSpec *spec; object_class = G_OBJECT_CLASS( klass ); object_class->finalize = screem_window_finalize; object_class->get_property = screem_window_get_prop; object_class->set_property = screem_window_set_prop; spec = g_param_spec_string( "app_id", "Application ID", "The ID", "", G_PARAM_READWRITE ); g_object_class_install_property( object_class, ARG_APP_ID, spec ); spec = g_param_spec_object( "app", "Application", "The Application", G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ); g_object_class_install_property( object_class, ARG_APP, spec ); spec = g_param_spec_object( "ctagsmodel", "ctags model", "The ctags model in use for the current window", G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ); g_object_class_install_property( object_class, ARG_CTAGSMODEL, spec ); } static void screem_window_init( ScreemWindow *window ) { ScreemWindowDetails *details; details = window->details = g_new0( ScreemWindowDetails, 1 ); /* as we only ever open 1 window at the moment we don't need to gen a unique one yet */ details->name = g_strdup( "fixme" ); details->spell = screem_spell_new(); /* hookup the highlight signal so we can scroll the editor to show it */ g_signal_connect( G_OBJECT( details->spell ), "highlight", G_CALLBACK( screem_window_highlight_spelling ), window ); details->cvs = screem_cvs_new( window ); gtk_drag_dest_set( GTK_WIDGET( window ), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, drop_types, num_drop_types, GDK_ACTION_COPY ); g_signal_connect( G_OBJECT( window ), "drag_data_received", G_CALLBACK( screem_window_drop ), window ); } static void screem_window_set_prop( GObject *object, guint prop_id, const GValue *value, GParamSpec *spec ) { const gchar *name; gchar *old_name; GObject *obj; ScreemWindow *window; window = SCREEM_WINDOW( object ); switch( prop_id ) { case ARG_APP_ID: if( ! G_VALUE_HOLDS_STRING( value ) ) return; /* FIXME: set the name */ screem_window_constructed( SCREEM_WINDOW( object ) ); break; case ARG_APP: obj = g_value_get_object( value ); window->application = SCREEM_APPLICATION( obj ); break; } } static void screem_window_get_prop( GObject *object, guint prop_id, GValue *value, GParamSpec *spec ) { ScreemWindow *window; GObject *obj; gchar *name; window = SCREEM_WINDOW( object ); switch( prop_id ) { case ARG_APP_ID: /* FIXME set the name */ g_value_set_string( value, "" ); break; case ARG_APP: obj = G_OBJECT( window->application ); g_value_set_object( value, obj ); break; case ARG_CTAGSMODEL: obj = G_OBJECT( window->details->ctagsmodel ); g_value_set_object( value, obj ); break; } } static void screem_window_finalize( GObject *object ) { ScreemWindow *window; ScreemApplication *app; ScreemWindowDetails *details; GSList *handles; window = SCREEM_WINDOW( object ); app = window->application; details = window->details; g_object_unref( window->search ); if( details->status_timeout ) { g_source_remove( details->status_timeout ); } if( details->name ) { g_free( details->name ); } for( handles = details->browser_notify_handles; handles; handles = handles->next ) { gconf_client_notify_remove( app->client, GPOINTER_TO_INT( handles->data ) ); } g_slist_free( details->browser_notify_handles ); g_object_unref( window->layout ); g_object_unref( details->mdi ); /* remove initial references */ g_object_unref( details->tagtree ); g_object_unref( details->editor ); g_object_unref( details->preview ); g_object_unref( details->link_view ); g_object_unref( details->tree_view ); g_object_unref( details->cvs ); g_object_unref( details->spell ); g_object_unref( details->recent_page_model ); g_object_unref( details->recent_site_model ); g_object_unref( details->ctagsmodel ); g_object_unref( window->action_group ); g_object_unref( window->merge ); g_object_unref( window->toolbar_model ); g_free( details ); G_OBJECT_CLASS( screem_window_parent_class )->finalize( object ); }