aboutsummaryrefslogblamecommitdiffstats
path: root/src/popup-commands.c
blob: 1a1d973a59914bc0633d81799ace011f29f7e7b0 (plain) (tree)
1
2
3
                                                                           
  
                                               












                                                                        
                                                                                  
  

   
                   
                           

                              
                          
                                 
                             

                              
                       
                         
                          
                       
                          
 
                       
                    
                   


                            
                          
      
 
    
                                                
                                                 
 
                              
                         
                              
 

                                                      
 

                                                       
 
                                                                  
 

                                                      
                                                        
                                                    
                                                        
                               

 
    
                                             
                                              
 
                              
                         
                              
 

                                                     
 

                                                       
 
                                                                  
 

                                                      
                                                        
                                                    

                                                             
                               

 
    
                                           
                                            
 
                   




















                                                                              
     
                              
                    
                              


                                          
 

                                                       
 


                                                              
 









                                                                                                                   
 

                               
 





                                                                                                        
 

                                                                  

                                              






                                                                                                                             
         
 
                                              


                                 
        
                                                                              

                          
      

 









                                                                          
                                               
                                                
 
                              
                      
                            
                              
 

                                                       
 

                                                       
                                                          
         

                                                                          



                                                          
                                                              
                                       
         


           
















                                                                             

                               
                            
 
                                               
         
                          


                                                                            

                                                                           
                                                                                       

                             
 
                          
                                                 


           
                                     
                                     

                                      

                                        
                              
                             
                              
 


                                                       

                                                                
 







                                                                             
                                                                       





                                                                  
                                                                                 





                                                      
                                                                          
         


    
                                       

                                        
                              
                             
                              

                         

                                                      

                                         
                                                       

                                                                  
                                                                           
                               


    
                                           

                                            
                                                               
                                              


    


                                               
                                                              
                                             

    
                                           

                                            
                                                      
                                                      

 
           
                                                      
                                                 
 

                            
 


                                                                      


    
                                                     

                                                      
                              
                             
                                                      
                              
                               
 


                                                       

                                                                   
 
                                                                             

                                              
                                                                           
                                                                                                           
                                                        
 
                                                               
                                                                             
 

                                                                              
 
                                       
 
                               
                      
                                

                          


    
                                                 

                                                  
                              
                             
                              
 
                                                       

                                                                   
                                                       
                               

 


                                                                  
           

                                           
                                  
 
                         
 
                                                                   
 
                     
         

                                                               

                                                                
         
 
                                                                
         
                            
                                                        
                    
                                                         
         


           
                                                 

                         
                           
                          
                    
 


                                                            
                                        
        
                                         
 

                                                 




                                      
                               
                                    
                                                           

                                    

                                               
                                            
 

                                                       
                      







                                                                      
 
                                                        
                                                             
                                                               
 
                                                

                                                                       
                                       
 
                      
                          

 
    


                                           


                                              




















                                                                                  
      


    
                                        
                                         
 
                              
                            

                              

                         


                                                       

                                                      

                                         

                                                                   
 
                                              
                                     


                                         



                                                    
                                                               
                                      





                                           

                               
                        
 



                                                                 
                    















                                                                                     
      
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 *  Copyright © 2000-2003 Marco Pesenti Gritti
 *
 *  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, 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.
 *
 */

#include "config.h"
#include "popup-commands.h"

#include "ephy-bookmarks-ui.h"
#include "ephy-download.h"
#include "ephy-embed-container.h"
#include "ephy-embed-utils.h"
#include "ephy-file-chooser.h"
#include "ephy-file-helpers.h"
#include "ephy-prefs.h"
#include "ephy-private.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
#include "ephy-web-view.h"

#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <string.h>
#ifdef HAVE_WEBKIT2
#include <webkit2/webkit2.h>
#else
#include <webkit/webkit.h>
#endif

void
popup_cmd_link_in_new_window (GtkAction *action,
                      EphyWindow *window)
{
    EphyEmbedEvent *event;
    EphyEmbed *embed;
    GValue value = { 0, };

    embed = ephy_embed_container_get_active_child 
        (EPHY_EMBED_CONTAINER (window));

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    ephy_embed_event_get_property (event, "link-uri", &value);

    ephy_shell_new_tab (ephy_shell_get_default (),
                NULL, embed,
                g_value_get_string (&value),
                EPHY_NEW_TAB_OPEN_PAGE |
                EPHY_NEW_TAB_IN_NEW_WINDOW);
    g_value_unset (&value);
}

void
popup_cmd_link_in_new_tab (GtkAction *action,
                   EphyWindow *window)
{
    EphyEmbedEvent *event;
    EphyEmbed *embed;
    GValue value = { 0, };

    embed = ephy_embed_container_get_active_child
        (EPHY_EMBED_CONTAINER (window));

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    ephy_embed_event_get_property (event, "link-uri", &value);

    ephy_shell_new_tab (ephy_shell_get_default (),
                window, embed,
                g_value_get_string (&value),
                EPHY_NEW_TAB_OPEN_PAGE |
                EPHY_NEW_TAB_IN_EXISTING_WINDOW |
                EPHY_NEW_TAB_APPEND_AFTER);
    g_value_unset (&value);
}

void
popup_cmd_bookmark_link (GtkAction *action,
             EphyWindow *window)
{
#ifdef HAVE_WEBKIT2
    EphyEmbedEvent *event;
    WebKitHitTestResult *result;
    const char *title;
    const char *location;

    event = ephy_window_get_context_event (window);

    result = ephy_embed_event_get_hit_test_result (event);
    if (!webkit_hit_test_result_context_is_link (result))
    {
        return;
    }

    location = webkit_hit_test_result_get_link_uri (result);
    title = webkit_hit_test_result_get_link_title (result);
    if (!title)
    {
        title = webkit_hit_test_result_get_link_label (result);
    }

    ephy_bookmarks_ui_add_bookmark (GTK_WINDOW (window), location, title);
#else
    EphyEmbedEvent *event;
    char *title;
    char *location = NULL;
    guint context;
    WebKitHitTestResult *result;
    WebKitDOMNode *node, *first_child;

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    result = ephy_embed_event_get_hit_test_result (event);
    g_object_get (result, "context", &context, NULL);
    g_object_get (result, "inner-node", &node, NULL);

    if (context != WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
    {
        node = WEBKIT_DOM_NODE (webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (node)));
        if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node))
            location = webkit_dom_html_anchor_element_get_href (WEBKIT_DOM_HTML_ANCHOR_ELEMENT (node));
    }
    else
    {
        g_object_get (result, "link-uri", &location, NULL);
    }

    if (!node || !location)
        return;

    title = webkit_dom_html_element_get_title (WEBKIT_DOM_HTML_ELEMENT (node));
    
    if (title == NULL || title[0] == '\0')
    {
        title = webkit_dom_html_anchor_element_get_text (WEBKIT_DOM_HTML_ANCHOR_ELEMENT (node));
    }

    /* Sometimes boorkmaklets are presented as images inside a
     * link, try that. */
    if (title == NULL || title[0] == '\0')
    {
        first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (node));
        if (first_child && WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (first_child))
        {
            title = webkit_dom_html_image_element_get_alt (WEBKIT_DOM_HTML_IMAGE_ELEMENT (first_child));
            if (title == NULL || title[0] == '\0')
                title = webkit_dom_html_image_element_get_name (WEBKIT_DOM_HTML_IMAGE_ELEMENT (first_child));
        }
    }

    if (title == NULL || title[0] == '\0')
    {
        title = location;
    }
    
    ephy_bookmarks_ui_add_bookmark (GTK_WINDOW (window), location, title);
    g_free (title);
    g_free (location);
#endif
}

static void
popup_cmd_copy_to_clipboard (EphyWindow *window, const char *text)
{
    gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE),
                text, -1);
    gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
                text, -1);
}

void
popup_cmd_copy_link_address (GtkAction *action,
                 EphyWindow *window)
{
    EphyEmbedEvent *event;
    guint context;
    const char *address;
    GValue value = { 0, };

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    context = ephy_embed_event_get_context (event);

    if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
    {
        ephy_embed_event_get_property (event, "link-uri", &value);
        address = g_value_get_string (&value);

        if (g_str_has_prefix (address, "mailto:"))
            address = address + 7;

        popup_cmd_copy_to_clipboard (window, address);
        g_value_unset (&value);
    }
}

static void
save_property_url_to_destination (EphyWindow *window,
                  const char *location,
                  const char *destination)
{
    EphyDownload *download;

    download = ephy_download_new_for_uri (location, GTK_WINDOW (window));

    if (destination)
        ephy_download_set_destination_uri (download, destination);
    else
        ephy_download_set_auto_destination (download);

    ephy_download_start (download);
}

static void
response_cb (GtkDialog *dialog,
         int response_id,
         char *location)
{
    if (response_id == GTK_RESPONSE_ACCEPT)
    {
        char *uri;
        GtkWindow *window;

        window = gtk_window_get_transient_for (GTK_WINDOW (dialog));

        uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
        save_property_url_to_destination (EPHY_WINDOW (window), location, uri);
        g_free (uri);
    }

    g_free (location);
    gtk_widget_destroy (GTK_WIDGET (dialog));
}

static void
save_property_url (GtkAction *action,
           const char *title,
           EphyWindow *window,
           gboolean ask_dest,
           const char *property)
{
    EphyEmbedEvent *event;
    const char *location;
    GValue value = { 0, };

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    ephy_embed_event_get_property (event, property, &value);
    location = g_value_get_string (&value);

    if (ask_dest)
    {
        EphyFileChooser *dialog;
        char *base;

        base = g_path_get_basename (location);
        dialog = ephy_file_chooser_new (title, GTK_WIDGET (window),
                        GTK_FILE_CHOOSER_ACTION_SAVE,
                        EPHY_FILE_FILTER_NONE);

        gtk_file_chooser_set_do_overwrite_confirmation
                (GTK_FILE_CHOOSER (dialog), TRUE);
        gtk_file_chooser_set_current_name
                (GTK_FILE_CHOOSER (dialog), base);
        g_signal_connect (dialog, "response",
                  G_CALLBACK (response_cb), g_strdup (location));
        gtk_widget_show (GTK_WIDGET (dialog));

        g_free (base);
    }
    else
    {
        save_property_url_to_destination (window, location, NULL);
    }
}

void
popup_cmd_open_link (GtkAction *action,
             EphyWindow *window)
{
    EphyEmbedEvent *event;
    const char *location;
    GValue value = { 0, };
    EphyEmbed *embed;

    embed = ephy_embed_container_get_active_child 
        (EPHY_EMBED_CONTAINER (window));
    g_return_if_fail (embed != NULL);

    event = ephy_window_get_context_event (window);
    ephy_embed_event_get_property (event, "link-uri", &value);
    location = g_value_get_string (&value);
    ephy_web_view_load_url (ephy_embed_get_web_view (embed), location);
    g_value_unset (&value);
}

void
popup_cmd_download_link (GtkAction *action,
             EphyWindow *window)
{
    save_property_url (action, _("Download Link"), window, 
               FALSE, "link-uri");
}

void
popup_cmd_download_link_as (GtkAction *action,
                EphyWindow *window)
{
    save_property_url (action, _("Save Link As"), window, 
               TRUE, "link-uri");
}
void
popup_cmd_save_image_as (GtkAction *action,
             EphyWindow *window)
{
    save_property_url (action, _("Save Image As"),
               window, TRUE, "image-uri");
}

static void
background_download_completed (EphyDownload *download,
                   GtkWidget *window)
{
    const char *uri;
    GSettings *settings;

    uri = ephy_download_get_destination_uri (download);
    settings = ephy_settings_get ("org.gnome.desktop.background");
    g_settings_set_string (settings, "picture-uri", uri);
}

void
popup_cmd_set_image_as_background (GtkAction *action,
                   EphyWindow *window)
{
    EphyEmbedEvent *event;
    const char *location;
    char *dest_uri, *dest, *base, *base_converted;
    GValue value = { 0, };
    EphyDownload *download;

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    ephy_embed_event_get_property (event, "image-uri", &value);
    location = g_value_get_string (&value);

    download = ephy_download_new_for_uri (location, GTK_WINDOW (window));

    base = g_path_get_basename (location);
    base_converted = g_filename_from_utf8 (base, -1, NULL, NULL, NULL);
    dest = g_build_filename (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES), base_converted, NULL);
    dest_uri = g_filename_to_uri (dest, NULL, NULL);

    ephy_download_set_destination_uri (download, dest_uri);
    ephy_download_set_action (download, EPHY_DOWNLOAD_ACTION_DO_NOTHING);

    g_signal_connect (download, "completed",
              G_CALLBACK (background_download_completed), window);

    ephy_download_start (download);

    g_value_unset (&value);
    g_free (base);
    g_free (base_converted);
    g_free (dest);
    g_free (dest_uri);
}

void
popup_cmd_copy_image_location (GtkAction *action,
                   EphyWindow *window)
{
    EphyEmbedEvent *event;
    const char *location;
    GValue value = { 0, };

    event = ephy_window_get_context_event (window);
    ephy_embed_event_get_property (event, "image-uri", &value);
    location = g_value_get_string (&value);
    popup_cmd_copy_to_clipboard (window, location);
    g_value_unset (&value);
}

/* Opens an image URI using its associated handler. Or, if that
 * doesn't work, fallback to open the URI in a new browser window.
 */
static void
image_open_uri (GFile *file,
                const char *remote_address,
        guint32 user_time)
{
    gboolean success;

    success = ephy_file_launch_handler (NULL, file, user_time);

    if (!success)
    {
        ephy_shell_new_tab (ephy_shell_get_default (),
                    NULL, NULL, remote_address,
                    EPHY_NEW_TAB_OPEN_PAGE |
                    EPHY_NEW_TAB_IN_NEW_WINDOW);
    }

    if (strcmp (remote_address, g_file_get_uri (file)) != 0)
    {
        if (success)
            ephy_file_delete_on_exit (file);
        else
            g_file_delete (file, NULL, NULL);
    }
}

static void
save_source_completed_cb (EphyDownload *download)
{
    const char *dest;
    const char *source;
    guint32 user_time;
    GFile *file;

    user_time = ephy_download_get_start_time (download);
    dest = ephy_download_get_destination_uri (download);
    source = ephy_download_get_source_uri (download);
    g_return_if_fail (dest != NULL);
    
    file = g_file_new_for_uri (dest);

    image_open_uri (file, source, user_time);
    g_object_unref (file);
}

static void
save_temp_source (const char *address)
{
    EphyDownload *download;
    const char *static_temp_dir;
    char *base, *tmp_name, *tmp_path, *dest, *dest_uri;

    if (address == NULL) return;

    static_temp_dir = ephy_file_tmp_dir ();
    if (static_temp_dir == NULL) return;

    base = g_path_get_basename (address);
    tmp_name = g_strconcat (base, ".XXXXXX", NULL);
    g_free (base);

    tmp_path = g_build_filename (static_temp_dir, tmp_name, NULL);
    g_free (tmp_name);

    dest = ephy_file_tmp_filename (tmp_path, NULL);
    g_free (tmp_path);

    if (dest == NULL) return;

    dest_uri = g_filename_to_uri (dest, NULL, NULL);
    download = ephy_download_new_for_uri (address, NULL);
    ephy_download_set_destination_uri (download, dest_uri);

    g_signal_connect (download, "completed",
              G_CALLBACK (save_source_completed_cb), NULL);

    ephy_download_start (download);

    g_free (dest);
    g_free (dest_uri);
}

void
popup_replace_spelling (GtkAction *action,
            EphyWindow *window)
{
#ifdef HAVE_WEBKIT2
    /* TODO: Context Menu, Spellchecker */
#else
    EphyEmbed *embed;
    WebKitWebView *view;
    WebKitWebFrame *frame;
    WebKitDOMDOMSelection *selection;
    WebKitDOMDocument *document;
    WebKitDOMDOMWindow *default_view;

    embed = ephy_embed_container_get_active_child 
        (EPHY_EMBED_CONTAINER (window));
    g_return_if_fail (embed != NULL);

    view = WEBKIT_WEB_VIEW (ephy_embed_get_web_view (embed));
    g_return_if_fail (view != NULL);

    document = webkit_web_view_get_dom_document (view);
    default_view = webkit_dom_document_get_default_view (document);
    selection = webkit_dom_dom_window_get_selection (default_view);
    webkit_dom_dom_selection_modify (selection, "move", "backward", "word");
    webkit_dom_dom_selection_modify (selection, "extend", "forward", "word");
    frame = webkit_web_view_get_focused_frame (view);
    webkit_web_frame_replace_selection (frame, gtk_action_get_label (action));
#endif
}

void
popup_cmd_open_image (GtkAction *action,
              EphyWindow *window)
{
    EphyEmbedEvent *event;
    const char *address;
    char *scheme = NULL;
    GValue value = { 0, };
    EphyEmbed *embed;

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    embed = ephy_embed_container_get_active_child 
        (EPHY_EMBED_CONTAINER (window));
    g_return_if_fail (embed != NULL);

    ephy_embed_event_get_property (event, "image-uri", &value);
    address = g_value_get_string (&value);

    scheme = g_uri_parse_scheme (address);
    if (scheme == NULL) goto out;

    if (strcmp (scheme, "file") == 0)
    {
        GFile *file;
        
        file = g_file_new_for_uri (address);
        image_open_uri (file, address,
                gtk_get_current_event_time ());
        g_object_unref (file);
    }
    else
    {
        save_temp_source (address);
    }

 out:
    g_value_unset (&value);
    g_free (scheme);
}

void
popup_cmd_inspect_element (GtkAction *action, EphyWindow *window)
{
#ifndef HAVE_WEBKIT2
    EphyEmbedEvent *event;
    EphyEmbed *embed;
    WebKitWebInspector *inspector;
    guint x, y;

    embed = ephy_embed_container_get_active_child
        (EPHY_EMBED_CONTAINER (window));

    event = ephy_window_get_context_event (window);
    g_return_if_fail (event != NULL);

    inspector = webkit_web_view_get_inspector
        (EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed));

    ephy_embed_event_get_coords (event, &x, &y);
    webkit_web_inspector_inspect_coordinates (inspector, (gdouble)x, (gdouble)y);
#endif
}