Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-mozfilepicker.cpp

/*
 *  Copyright (C) 2001 Philip Langdale
 *
 *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 *  2003-10-13 Takuro Ashie <ashie@homa.ne.jp>
 *
 *      Picked from Epiphany and adapt to Kazehakase.
 */

/* Things to be aware of:
 *
 * This filepicker, like the mozilla one, does not make an attempt
 * to verify the validity of the initial directory you pass it.
 * It does check that the user doesn't give it a garbage path
 * during use, but it is the caller's responsibility to give a
 * sensible initial path.
 *
 * At the current moment, we instantiate the filepicker directly
 * in our contenthandler where there is path verification code
 * and else where through our C wrapper, which also does verification.
 * If, at a future date, you need to instantiate filepicker without
 * using the C wrapper, please verify the initial path. See
 * ContentHandler for a way to do this.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <glib/gconvert.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmenu.h>
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkcheckbutton.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtkfilesel.h>
#include <gtk/gtkhbbox.h>
#include <gtk/gtkoptionmenu.h>
#include <gtk/gtkmessagedialog.h>
#include <glib/gi18n.h>

#include "nsIFilePicker.h"

#include "nsCRT.h"
#include "nsCOMPtr.h"
#include "nsISupportsArray.h"
#include "nsIServiceManager.h"

#define MOZILLA_STRICT_API
#include <nsEmbedString.h>
#undef MOZILLA_STRICT_API
#include "nsIPrefService.h"
#include "nsIURI.h"
#include "nsIFileURL.h"
#include "nsIChannel.h"
#include "nsIFileChannel.h"
#include "nsNetCID.h"
#include "nsILocalFile.h"
#include "nsIPromptService.h"

#include "kz-mozfilepicker.h"
#include "kz-mozutils.h"

/* Implementation file */
NS_IMPL_ISUPPORTS1(KzFilePicker, nsIFilePicker)

nsEmbedCString KzFilePicker::mPrevDirectory;

KzFilePicker::KzFilePicker()
{
      NS_INIT_ISUPPORTS();

      /* member initializers and constructor code */
      mFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
      mDisplayDirectory = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
      if (!mPrevDirectory.Length())
      {
            mPrevDirectory = nsEmbedCString(g_get_home_dir());
      }
      mDisplayDirectory->InitWithNativePath(mPrevDirectory);
}

KzFilePicker::~KzFilePicker()
{
      /* destructor code */
}

////////////////////////////////////////////////////////////////////////////////
// begin nsIFilePicker impl
////////////////////////////////////////////////////////////////////////////////

/* void init (in nsIDOMWindowInternal parent, in wstring title, in short mode); */
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
NS_IMETHODIMP KzFilePicker::Init(nsIDOMWindow *aParent,
                         const nsAString &aTitle,
                         PRInt16 aMode)
#else
NS_IMETHODIMP KzFilePicker::Init(nsIDOMWindowInternal *aParent, 
                         const PRUnichar *aTitle, PRInt16 aMode)
#endif
{
      mParent = do_QueryInterface(aParent);
      mParentWidget = GetGtkWindowForDOMWindow(mParent);
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
      NS_UTF16ToCString(aTitle, NS_CSTRING_ENCODING_UTF8, mTitle);
#else
      NS_UTF16ToCString(nsEmbedString(aTitle), NS_CSTRING_ENCODING_UTF8, mTitle);
#endif
      mMode = aMode;
      
      return NS_OK;
}

/* void appendFilters (in long filterMask); */
NS_IMETHODIMP KzFilePicker::AppendFilters(PRInt32 aFilterMask)
{
      //This function cannot be implemented due to the crippled
      //nature of GtkFileSelection, but NS_ERROR_NOT_IMPLEMENTED
      //is interpreted as a terminal error by some callers.
      return NS_OK;
}

/* void appendFilter (in wstring title, in wstring filter); */
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
NS_IMETHODIMP KzFilePicker::AppendFilter(const nsAString &aTitle,
                               const nsAString &aFilter)
#else
NS_IMETHODIMP KzFilePicker::AppendFilter(const PRUnichar *aTitle,
                               const PRUnichar *aFilter)
#endif
{
      //GtkFileSelection is crippled, so we can't provide a short-list
      //of filters to choose from. We provide minimal functionality
      //by using the most recent AppendFilter call as the active filter.
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
      NS_UTF16ToCString(aFilter, NS_CSTRING_ENCODING_UTF8, mFilter);
#else
      NS_UTF16ToCString(nsEmbedString(aFilter), NS_CSTRING_ENCODING_UTF8, mFilter);
#endif
      return NS_OK;
}

/* attribute long filterIndex; */
NS_IMETHODIMP KzFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
{
      return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP KzFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
{
      return NS_OK;
}

/* attribute wstring defaultString; */
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
NS_IMETHODIMP KzFilePicker::GetDefaultString(nsAString &aDefaultString)
#else
NS_IMETHODIMP KzFilePicker::GetDefaultString(PRUnichar * *aDefaultString)
#endif
{
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
      aDefaultString = mDefaultString;
#else
      *aDefaultString = NS_StringCloneData(mDefaultString);
#endif
      return NS_OK;
}
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
NS_IMETHODIMP KzFilePicker::SetDefaultString(const nsAString &aDefaultString)
#else
NS_IMETHODIMP KzFilePicker::SetDefaultString(const PRUnichar *aDefaultString)
#endif
{
      mDefaultString.Assign(aDefaultString);

      return NS_OK;
}

/* attribute wstring defaultExtension; */
// Again, due to the crippled file selector, we can't really
// do anything here.
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
NS_IMETHODIMP KzFilePicker::GetDefaultExtension(nsAString &aDefaultExtension)
#else
NS_IMETHODIMP KzFilePicker::GetDefaultExtension(PRUnichar * *aDefaultExtension)
#endif
{
    return NS_ERROR_NOT_IMPLEMENTED;
}
#ifdef MOZ_NSIFILEPICKER_NSASTRING_
NS_IMETHODIMP KzFilePicker::SetDefaultExtension(const nsAString &aDefaultExtension)
#else
NS_IMETHODIMP KzFilePicker::SetDefaultExtension(const PRUnichar *aDefaultExtension)
#endif
{
    return NS_OK;
}

/* attribute nsILocalFile displayDirectory; */
NS_IMETHODIMP KzFilePicker::GetDisplayDirectory(nsILocalFile * *aDisplayDirectory)
{
      NS_IF_ADDREF(*aDisplayDirectory = mDisplayDirectory);
      return NS_OK;
}
NS_IMETHODIMP KzFilePicker::SetDisplayDirectory(nsILocalFile * aDisplayDirectory)
{
      mDisplayDirectory = aDisplayDirectory;
      return NS_OK;
}

/* readonly attribute nsILocalFile file; */
NS_IMETHODIMP KzFilePicker::GetFile(nsILocalFile * *aFile)
{
      NS_IF_ADDREF(*aFile = mFile);
      return NS_OK;
}

/* readonly attribute nsIFileURL fileURL; */
NS_IMETHODIMP KzFilePicker::GetFileURL(nsIFileURL * *aFileURL)
{
      nsCOMPtr<nsIFileURL> fileURL = 
            do_CreateInstance(NS_STANDARDURL_CONTRACTID);
      fileURL->SetFile(mFile);
      NS_IF_ADDREF(*aFileURL = fileURL);
      return NS_OK;
}

/* readonly attribute nsISimpleEnumerator files; */
NS_IMETHODIMP KzFilePicker::GetFiles(nsISimpleEnumerator * *aFiles)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* short show (); */
NS_IMETHODIMP KzFilePicker::Show(PRInt16 *_retval)
{
      GtkFileChooserAction action;
      GtkFileFilter *filter = NULL;
      const gchar *stock;

      switch (mMode)
      {
       case nsIFilePicker::modeSave:
            action = GTK_FILE_CHOOSER_ACTION_SAVE;
            stock = GTK_STOCK_SAVE;
            break;
       case nsIFilePicker::modeGetFolder:
            action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
            stock = GTK_STOCK_OPEN;
            break;
       case nsIFilePicker::modeOpenMultiple:
            action = GTK_FILE_CHOOSER_ACTION_OPEN;
            stock = GTK_STOCK_OPEN;
            break;
       case nsIFilePicker::modeOpen:
       default:
            action = GTK_FILE_CHOOSER_ACTION_OPEN;
            stock = GTK_STOCK_OPEN;
            break;
      }
                  
      mFileDialog = gtk_file_chooser_dialog_new(mTitle.get(),
                                      NULL,
                                      action,
                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                      stock, GTK_RESPONSE_ACCEPT,
                                      NULL);

      if(mMode == nsIFilePicker::modeSave)
      {
            nsEmbedCString cFileName;
            NS_UTF16ToCString(mDefaultString,
                          NS_CSTRING_ENCODING_UTF8, cFileName);

            gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(mFileDialog),
                                      cFileName.get());
      }

      nsEmbedCString dir;
      
      mDisplayDirectory->GetNativePath (dir);

      gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(mFileDialog),
                                  dir.get());

      if (mFilter.Length())
      {
            filter = gtk_file_filter_new();
            gtk_file_filter_add_pattern(filter, mFilter.get());
      }

      if (mParentWidget)
            gtk_window_set_transient_for(GTK_WINDOW(mFileDialog),
                                   GTK_WINDOW(mParentWidget));

      if (mMode == nsIFilePicker::modeOpenMultiple)
      {
            gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(mFileDialog)
                                         , TRUE);
      }

      gtk_window_set_modal(GTK_WINDOW(mFileDialog), TRUE);

      gint retVal = gtk_dialog_run(GTK_DIALOG(mFileDialog));
      
      HandleFilePickerResult();

      if (retVal != GTK_RESPONSE_ACCEPT)
      {
            *_retval = returnCancel;
      }
      else
      {     
            ValidateFilePickerResult(_retval);
      }

      if (filter)
            g_object_unref(filter);

      gtk_widget_destroy(mFileDialog);

      return NS_OK;
}

////////////////////////////////////////////////////////////////////////////////
// begin local public methods impl
////////////////////////////////////////////////////////////////////////////////

NS_METHOD KzFilePicker::InitWithGtkWidget (GtkWidget *aParentWidget, 
                                 const char *aTitle, PRInt16 aMode)
{
      mParentWidget = aParentWidget;

      mTitle = nsEmbedCString(aTitle);

      mMode = aMode;

      mFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);

      return NS_OK;
}

NS_METHOD KzFilePicker::SanityCheck (PRBool *retIsSane)
{
      *retIsSane = PR_TRUE;
      
      nsresult rv;
      PRBool dirExists, fileExists = PR_TRUE;

      if (mDisplayDirectory)
      {
            rv = mDisplayDirectory->Exists (&dirExists);
            g_return_val_if_fail (NS_SUCCEEDED(rv), rv);
      }
      else
      {
            dirExists = PR_FALSE;
      }

      if (mMode != nsIFilePicker::modeGetFolder)
      {
            rv = mFile->Exists (&fileExists);
            g_return_val_if_fail (NS_SUCCEEDED(rv), rv);
      }

      if (mMode == nsIFilePicker::modeSave && !fileExists)
      {
            return NS_OK;
      }
      
      if (!dirExists || !fileExists)
      {
            GtkWidget *errorDialog = gtk_message_dialog_new (
                        NULL,
                        GTK_DIALOG_MODAL,
                        GTK_MESSAGE_ERROR,
                        GTK_BUTTONS_OK,
                        _("The specified path does not exist."));

            if (mParentWidget)
                  gtk_window_set_transient_for(GTK_WINDOW(errorDialog),
                                         GTK_WINDOW(mFileDialog));

            gtk_window_set_modal (GTK_WINDOW(errorDialog), TRUE);
            gtk_dialog_run (GTK_DIALOG(errorDialog));
            gtk_widget_destroy (errorDialog);
            *retIsSane = PR_FALSE;
            return NS_OK;
      }

      PRBool correctType;
      char *errorText;
      if (mMode == nsIFilePicker::modeGetFolder)
      {
            rv = mDisplayDirectory->IsDirectory (&correctType);
            g_return_val_if_fail (NS_SUCCEEDED(rv), rv);
            errorText = g_strdup (_("A file was selected when a "
                              "folder was expected."));
      }
      else
      {
            rv = mFile->IsFile (&correctType);
            g_return_val_if_fail (NS_SUCCEEDED(rv), rv);
            errorText = g_strdup (_("A folder was selected when a "
                                "file was expected."));
      }
      
      if(!correctType)
      {
            GtkWidget *errorDialog = gtk_message_dialog_new (
                        NULL,
                        GTK_DIALOG_MODAL,
                        GTK_MESSAGE_ERROR,
                        GTK_BUTTONS_OK,
                        errorText);

            if (mParentWidget)
                  gtk_window_set_transient_for(GTK_WINDOW(errorDialog),
                                         GTK_WINDOW(mFileDialog));

            gtk_window_set_modal (GTK_WINDOW(errorDialog), TRUE);
            gtk_dialog_run (GTK_DIALOG(errorDialog));
            gtk_widget_destroy (errorDialog);
            *retIsSane = PR_FALSE;
      }
      g_free (errorText);

      return NS_OK;
}

////////////////////////////////////////////////////////////////////////////////
// begin local private methods impl
////////////////////////////////////////////////////////////////////////////////

NS_METHOD KzFilePicker::HandleFilePickerResult()
{
      char *fileName = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(mFileDialog));

      if (!fileName || strlen(fileName) == 0) return NS_ERROR_FAILURE;

      nsEmbedCString cFileName(fileName);
      mFile->InitWithNativePath(cFileName);

      if (mMode == nsIFilePicker::modeGetFolder)
      {
            mDisplayDirectory->InitWithNativePath(cFileName);
            
            const PRUnichar tmp[] = { '\0' };
            mDefaultString = nsEmbedString(tmp);
      }
      else
      {
            nsCOMPtr<nsIFile> directory;
            mFile->GetParent(getter_AddRefs(directory));
            mDisplayDirectory = do_QueryInterface(directory);
            mDisplayDirectory->GetNativePath(mPrevDirectory);
            mFile->GetLeafName(mDefaultString);
      }

      g_free (fileName);
      
      return NS_OK;
}

NS_METHOD KzFilePicker::ValidateFilePickerResult(PRInt16 *retval)
{
      nsresult rv;

      *retval = returnCancel;

      PRBool passesSanityCheck;
      rv = SanityCheck(&passesSanityCheck);
      if (NS_SUCCEEDED(rv) && !passesSanityCheck) return NS_ERROR_FAILURE;

      if (mMode == nsIFilePicker::modeSave)
      {
#if 0
            const char *fileName = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mFileSelector));
            if (!ephy_gui_confirm_overwrite_file (mFileSelector,
                                            fileName))
            {
                  return NS_OK;
            }
#endif
      }

      *retval = returnOK;

      return NS_OK;
}

Generated by  Doxygen 1.6.0   Back to index