aboutsummaryrefslogblamecommitdiffstats
path: root/embed/mozilla/FilePicker.cpp
blob: 90b041ef40e49a4dd1dee4d4bfe1fa4a7348c578 (plain) (tree)
1
2
3
  

                                            












                                                                        
                                                                                  
  
        

   
                           
                   
 





                                 
                        
 
                     
                         


                             

                              
                     


                                    
 
                       

                       
 
                               
                                 


                       
 

                                              
                          

                                
 
                                            



                           
                                            
 

                    
                                                                                         


                                                          
 
                                                                          
                                                                                           
 
                                  
 

                                             
                                                                 
 
                                                     
 
 
                         
 
                                                                    


                     
                                                                   

                     
                                                  
                                                                       
                              
                                                     
                                             
                                                              

                                             
                                                              


                                                


                              



                                                                         



                                                                                                   

         



                                                                                        



                                                                                                  


                                                                              



                                              
                                                            
 
                                                   
 
                                                               
 


                                                                                                                    

                                                  
                                                                              
                                                                         


                                                   



                                                                           
                                                                  


                                                   

                                                                               


                                                     



                                                                        
                                                                  


                                                  
                                                                              
                                                                              


                                                  
                                                                              
                                                                              

         


                     
                                                              
 
                                                                                        
 

                                                   
                                          
 
                                                      
 
                          
                                                                      
 


                                                       
 

                                       


                                                 
                                                                              
         
 
                         
                                                                    

                                                       
 
                                                                        
 

                              


                     
                                      
                                                                      
 
                                                   
 
                                              
 
                                        
 

                     
 
                                                                            
 

                                                   
                                               
 
                                             
         
                                        
                                                                            
                                                  
 
                                                                              
 

                                                                     

                                                                  
                                                                          
         
 


                     
                                         
                                                                            
 
                                                 
 
                                        

 
                                                                                  
 
                                                 
 
                                        

 

                                                                
 
                                            
 
                                        

 
                                                               
 
                                                                   
 
                                        

 

                                                                                
 
                                                   
 
                                                 
 
                                                                                     
 
                        
         
                                                                                           
                                                           
                                                         
        
                             
         
 


                     
                                                                               
 

                                                   
                      
                                               
 
                                                                  
 

                                                                        
                                        


                                                                                         
                                                                                                  








                                                                                     



                     

                                                        
 

                                                   

                       
                                     

                                                                              
 
                             
         
                                                                                           
                                                                
                                             
        
                                  

         





                                                            

                                                   
                                        
 

                                       

                                                


                                                                                     



                     





                                                                        
                                      
 

                                        
 

                                                 
 




                                      
                                                  

                         
                                  
 
                                                          
                                                                         
 














                                                                                     
                                               
 

                              
 
          
         




                                                                                      
                                                                                       
         

                                                  
                                                                                   
 
                                               
 
                                                                
         
                                                   
         
            
         
                                                       

         
                          


                     
/*
 *  Copyright © 2001 Philip Langdale
 *  Copyright © 2003, 2004 Christian Persch
 *
 *  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.
 *
 *  $Id$
 */

#include "mozilla-config.h"
#include "config.h"

#include <glib/gconvert.h>
#include <glib/gi18n.h>
#include <gtk/gtkfilefilter.h>
#include <gtk/gtkmessagedialog.h>
#include <gtk/gtkstock.h>

#include <nsStringAPI.h>

#include <nsCOMPtr.h>
#include <nsIDOMWindow.h>
#include <nsIFileURL.h>
#include <nsILocalFile.h>
#include <nsIPromptService.h>
#include <nsIServiceManager.h>
#include <nsIURI.h>
#include <nsNetCID.h>
#include <nsComponentManagerUtils.h>
#include <nsServiceManagerUtils.h>
#include <nsXPCOMCID.h>

#include "ephy-debug.h"
#include "ephy-gui.h"
#include "ephy-prefs.h"

#include "AutoJSContextStack.h"
#include "AutoWindowModalState.h"
#include "EphyUtils.h"

#include "FilePicker.h"

NS_IMPL_ISUPPORTS1(GFilePicker, nsIFilePicker)

GFilePicker::GFilePicker()
: mDialog(nsnull)
, mMode(nsIFilePicker::modeOpen)
{
    LOG ("GFilePicker ctor (%p)", this);
}

GFilePicker::~GFilePicker()
{
    LOG ("GFilePicker dtor (%p)", this);

    if (mDialog)
    {
        g_object_remove_weak_pointer (G_OBJECT (mDialog), (gpointer *) &mDialog);
        gtk_widget_destroy (GTK_WIDGET (mDialog));
    }
}

/* void init (in nsIDOMWindow parent, in AString title, in short mode); */
NS_IMETHODIMP GFilePicker::Init(nsIDOMWindow *parent, const nsAString& title, PRInt16 mode)
{
    LOG ("GFilePicker::Init");

    mParent = do_QueryInterface (parent);

    GtkWidget *gtkparent = EphyUtils::FindGtkParent (parent);

    NS_ENSURE_TRUE (gtkparent, NS_ERROR_FAILURE);


    nsCString cTitle;

    NS_UTF16ToCString (title, NS_CSTRING_ENCODING_UTF8, cTitle);

    mMode = mode;

    GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
    switch (mode)
    {
        case nsIFilePicker::modeGetFolder:
            action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
            break;
        case nsIFilePicker::modeOpenMultiple:
        case nsIFilePicker::modeOpen:
            action = GTK_FILE_CHOOSER_ACTION_OPEN;
            break;
        case nsIFilePicker::modeSave:
            action = GTK_FILE_CHOOSER_ACTION_SAVE;
            break;
        default:
            g_assert_not_reached ();
            break;
    }

    mDialog = ephy_file_chooser_new (cTitle.get(), gtkparent, action,
                     CONF_STATE_UPLOAD_DIR,
                     EPHY_FILE_FILTER_NONE);

    if (parent)
    {
        gtk_window_group_add_window (ephy_gui_ensure_window_group (GTK_WINDOW (gtkparent)),
                         GTK_WINDOW (mDialog));
    }

    if (mode == nsIFilePicker::modeOpenMultiple)
    {
        gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (mDialog), TRUE);
    }
    if (mMode == nsIFilePicker::modeSave)
    {
        gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (mDialog), TRUE);
    }

    g_object_add_weak_pointer (G_OBJECT (mDialog), (gpointer *) &mDialog);

    return NS_OK;
}

/* void appendFilters (in long filterMask); */
NS_IMETHODIMP GFilePicker::AppendFilters(PRInt32 filterMask)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    LOG ("GFilePicker::AppendFilters mask=%d", filterMask);

    // http://lxr.mozilla.org/seamonkey/source/xpfe/components/filepicker/res/locale/en-US/filepicker.properties
    // http://lxr.mozilla.org/seamonkey/source/xpfe/components/filepicker/src/nsFilePicker.js line 131 ff

    if (filterMask & nsIFilePicker::filterAll)
    {
        ephy_file_chooser_add_pattern_filter (mDialog, _("All files"),
                              "*", (char*) NULL);
    }
    if (filterMask & nsIFilePicker::filterHTML)
    {
        ephy_file_chooser_add_mime_filter (mDialog, _("Web pages"),
                           "text/html",
                           "application/xhtml+xml",
                           "text/xml",
                           (char *) NULL);
    }
    if (filterMask & nsIFilePicker::filterText)
    {
        ephy_file_chooser_add_pattern_filter (mDialog, _("Text files"),
                              "*.txt", "*.text", NULL);
    }
    if (filterMask & nsIFilePicker::filterImages)
    {
        ephy_file_chooser_add_mime_filter (mDialog, _("Images"),
                           "image/png",
                           "image/jpeg",
                           "image/gif",
                           (char *) NULL);
    }
    if (filterMask & nsIFilePicker::filterXML)
    {
        ephy_file_chooser_add_pattern_filter (mDialog, _("XML files"),
                              "*.xml", (char *) NULL);
    }
    if (filterMask & nsIFilePicker::filterXUL)
    {
        ephy_file_chooser_add_pattern_filter (mDialog, _("XUL files"),
                              "*.xul", (char *) NULL);
    }

    return NS_OK;
}

/* void appendFilter (in AString title, in AString filter); */

NS_IMETHODIMP GFilePicker::AppendFilter(const nsAString& title, const nsAString& filter)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    LOG ("GFilePicker::AppendFilter");

    if (!filter.Length()) return NS_ERROR_FAILURE;

    nsCString pattern;
    NS_UTF16ToCString (filter, NS_CSTRING_ENCODING_UTF8, pattern);

    char **patterns;
    patterns = g_strsplit (pattern.get(), ";", -1);
    if (!patterns) return NS_ERROR_FAILURE;

    GtkFileFilter *filth;
    filth = gtk_file_filter_new ();

    for (int i = 0; patterns[i] != NULL; i++)
    {
        gtk_file_filter_add_pattern (filth, g_strstrip (patterns[i]));
    }

    nsCString cTitle;
    NS_UTF16ToCString (title, NS_CSTRING_ENCODING_UTF8, cTitle);

    gtk_file_filter_set_name (filth, cTitle.get());

    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (mDialog), filth);

    g_strfreev (patterns);

    return NS_OK;
}

/* attribute AString defaultString; */
NS_IMETHODIMP GFilePicker::GetDefaultString(nsAString& aDefaultString)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    LOG ("GFilePicker::GetDefaultString");

    aDefaultString = mDefaultString;

    return NS_OK;
}

NS_IMETHODIMP GFilePicker::SetDefaultString(const nsAString& aDefaultString)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    mDefaultString.Assign (aDefaultString);

    if (mMode == nsIFilePicker::modeSave)
    {
        nsCString defaultString;
        NS_UTF16ToCString (mDefaultString, NS_CSTRING_ENCODING_UTF8,
                   defaultString);

        LOG ("GFilePicker::SetDefaultString %s", defaultString.get());

        if (!defaultString.Length()) return NS_ERROR_FAILURE;

        /* set_current_name takes UTF-8, not a filename */
        gtk_file_chooser_set_current_name
            (GTK_FILE_CHOOSER (mDialog), defaultString.get());
    }

    return NS_OK;
}

/* attribute AString defaultExtension; */
NS_IMETHODIMP GFilePicker::GetDefaultExtension(nsAString& aDefaultExtension)
{
    LOG ("GFilePicker::GetDefaultExtension");

    return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP GFilePicker::SetDefaultExtension(const nsAString& aDefaultExtension)
{
    LOG ("GFilePicker::SetDefaultExtension");

    return NS_ERROR_NOT_IMPLEMENTED;
}

/* attribute long filterIndex; */
NS_IMETHODIMP GFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
{
    LOG ("GFilePicker::GetFilterIndex");

    return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP GFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
{
    LOG ("GFilePicker::SetFilterIndex index=%d", aFilterIndex);

    return NS_ERROR_NOT_IMPLEMENTED;
}

/* attribute nsILocalFile displayDirectory; */
NS_IMETHODIMP GFilePicker::GetDisplayDirectory(nsILocalFile **aDisplayDirectory)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    LOG ("GFilePicker::GetDisplayDirectory");

    char *dir = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (mDialog));

    if (dir != NULL)
    {
        nsCOMPtr<nsILocalFile> file = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
        file->InitWithNativePath (nsCString (dir));
        NS_IF_ADDREF (*aDisplayDirectory = file);
    
        g_free (dir);
    }

    return NS_OK;
}

NS_IMETHODIMP GFilePicker::SetDisplayDirectory(nsILocalFile *aDisplayDirectory)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    nsCString dir;
    aDisplayDirectory->GetNativePath (dir);

    LOG ("GFilePicker::SetDisplayDirectory to %s", dir.get());

    if (mDefaultString.Length() && mMode != nsIFilePicker::modeSave)
    {
        nsCString defaultString;
        NS_UTF16ToCString (mDefaultString, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
                   defaultString);

        char *filename = g_build_filename (dir.get(), defaultString.get(), (char *) NULL);
        LOG ("Setting filename to %s", filename);
        gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (mDialog), filename);
        g_free (filename);
    }
    else
    {
        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (mDialog),
                             dir.get());
    }

    return NS_OK;
}

/* readonly attribute nsILocalFile file; */
NS_IMETHODIMP GFilePicker::GetFile(nsILocalFile **aFile)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    char *filename;

    LOG ("GFilePicker::GetFile");

    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (mDialog));

    if (filename != NULL)
    {
        nsCOMPtr<nsILocalFile> file = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
        file->InitWithNativePath (nsCString (filename));
        NS_IF_ADDREF (*aFile = file);
    
        g_free (filename);
    }

    return NS_OK;
}

/* readonly attribute nsIFileURL fileURL; */
NS_IMETHODIMP GFilePicker::GetFileURL(nsIFileURL **aFileURL)
{
    NS_ENSURE_TRUE (mDialog, NS_ERROR_FAILURE);

    LOG ("GFilePicker::GetFileURL");

    nsCOMPtr<nsILocalFile> file;
    GetFile (getter_AddRefs(file));
    NS_ENSURE_TRUE (file, NS_ERROR_FAILURE);

    nsCOMPtr<nsIFileURL> fileURL = do_CreateInstance (NS_STANDARDURL_CONTRACTID);
    fileURL->SetFile(file);
    NS_IF_ADDREF(*aFileURL = fileURL);

    return NS_OK;
}

/* readonly attribute nsISimpleEnumerator files; */
NS_IMETHODIMP GFilePicker::GetFiles(nsISimpleEnumerator * *aFiles)
{
    // Not sure if we need to implement it at all, it's used nowhere
    // in mozilla, but I guess a javascript might call it?

    LOG ("GFilePicker::GetFiles");

    return NS_ERROR_NOT_IMPLEMENTED;
}

/* short show (); */
NS_IMETHODIMP GFilePicker::Show(PRInt16 *_retval)
{
    nsresult rv;
    AutoJSContextStack stack;
    rv = stack.Init ();
    if (NS_FAILED (rv)) return rv;

    AutoWindowModalState modelState (mParent);
    mParent = nsnull;

    LOG ("GFilePicker::Show");

    gtk_window_set_modal (GTK_WINDOW (mDialog), TRUE);
    gtk_window_set_destroy_with_parent (GTK_WINDOW (mDialog), FALSE);

    /* If there's just the "ALL" filter, it's no use showing the filters! */
    GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (mDialog));
    if (g_slist_length (filters) == 1)
    {
        GtkFileFilter *filter = GTK_FILE_FILTER (filters->data);
        const char *name = gtk_file_filter_get_name (filter);

        if (!name || strcmp (name, _("All files")) == 0)
        {
            gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (mDialog),
                            filter);
        }
    }
    g_slist_free (filters);

    gtk_widget_show (GTK_WIDGET (mDialog));

    int response;
    char *filename = NULL;

    do
    {
        response = gtk_dialog_run (GTK_DIALOG (mDialog));

        g_free (filename);
        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (mDialog));

        LOG ("GFilePicker::Show response=%d, filename=%s", response, filename);
    }
    while (response == GTK_RESPONSE_ACCEPT &&
           mMode == nsIFilePicker::modeSave &&
           !ephy_gui_check_location_writable (GTK_WIDGET (mDialog), filename));

    gtk_widget_hide (GTK_WIDGET (mDialog));

    if (response == GTK_RESPONSE_ACCEPT && filename != NULL)
    {
        *_retval = nsIFilePicker::returnOK;
    }
    else
    {
        *_retval = nsIFilePicker::returnCancel;
    }

    g_free (filename);

    return NS_OK;
}