aboutsummaryrefslogtreecommitdiffstats
path: root/embed/mozilla/FilePicker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'embed/mozilla/FilePicker.cpp')
-rw-r--r--embed/mozilla/FilePicker.cpp505
1 files changed, 505 insertions, 0 deletions
diff --git a/embed/mozilla/FilePicker.cpp b/embed/mozilla/FilePicker.cpp
new file mode 100644
index 000000000..baae069ef
--- /dev/null
+++ b/embed/mozilla/FilePicker.cpp
@@ -0,0 +1,505 @@
+/*
+ * 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.
+ */
+
+/* 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.
+ */
+
+#include "ephy-string.h"
+#include "ephy-gui.h"
+#include "eel-gconf-extensions.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 <libgnome/gnome-i18n.h>
+
+#include "nsIFilePicker.h"
+
+#include "nsCRT.h"
+#include "nsCOMPtr.h"
+#include "nsIFactory.h"
+#include "nsISupportsArray.h"
+#include "nsIServiceManager.h"
+#include "nsXPComFactory.h"
+
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#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 "nsReadableUtils.h"
+
+#include <libgnome/gnome-util.h>
+
+#include "FilePicker.h"
+#include "MozillaPrivate.h"
+
+void filePicker_save_content_cb(GtkToggleButton *aButton,
+ GFilePicker *aFilePicker);
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(GFilePicker, nsIFilePicker)
+
+GFilePicker::GFilePicker(PRBool showContentCheck, FileFormat *fileFormats) :
+ mSaveContent(PR_FALSE)
+{
+ NS_INIT_ISUPPORTS();
+ /* member initializers and constructor code */
+
+ mShowContentCheck = showContentCheck;
+ mFileFormats = fileFormats;
+ mFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+ mDisplayDirectory = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+ mDisplayDirectory->InitWithNativePath(nsDependentCString(g_get_home_dir()));
+}
+
+GFilePicker::~GFilePicker()
+{
+ /* destructor code */
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// begin nsIFilePicker impl
+////////////////////////////////////////////////////////////////////////////////
+
+/* void init (in nsIDOMWindowInternal parent, in wstring title, in short mode); */
+NS_IMETHODIMP GFilePicker::Init(nsIDOMWindowInternal *aParent,
+ const PRUnichar *aTitle, PRInt16 aMode)
+{
+ mParent = do_QueryInterface(aParent);
+ mParentWidget = MozillaFindGtkParent(mParent);
+ mTitle = NS_ConvertUCS2toUTF8(aTitle);
+ mMode = aMode;
+
+ return NS_OK;
+}
+
+/* void appendFilters (in long filterMask); */
+NS_IMETHODIMP GFilePicker::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); */
+NS_IMETHODIMP GFilePicker::AppendFilter(const PRUnichar *aTitle,
+ const PRUnichar *aFilter)
+{
+ //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.
+ mFilter = NS_ConvertUCS2toUTF8(aFilter);
+ return NS_OK;
+}
+
+/* attribute long filterIndex; */
+NS_IMETHODIMP GFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP GFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
+{
+ return NS_OK;
+}
+
+/* attribute wstring defaultString; */
+NS_IMETHODIMP GFilePicker::GetDefaultString(PRUnichar * *aDefaultString)
+{
+ *aDefaultString = ToNewUnicode(NS_ConvertUTF8toUCS2(mDefaultString));
+ return NS_OK;
+}
+NS_IMETHODIMP GFilePicker::SetDefaultString(const PRUnichar *aDefaultString)
+{
+ if (aDefaultString)
+ mDefaultString = NS_ConvertUCS2toUTF8(aDefaultString);
+ else
+ mDefaultString = "";
+ return NS_OK;
+}
+
+/* attribute wstring defaultExtension; */
+// Again, due to the crippled file selector, we can't really
+// do anything here.
+NS_IMETHODIMP GFilePicker::GetDefaultExtension(PRUnichar * *aDefaultExtension)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP GFilePicker::SetDefaultExtension(const PRUnichar *aDefaultExtension)
+{
+ return NS_OK;
+}
+
+/* attribute nsILocalFile displayDirectory; */
+NS_IMETHODIMP GFilePicker::GetDisplayDirectory(nsILocalFile * *aDisplayDirectory)
+{
+ NS_IF_ADDREF(*aDisplayDirectory = mDisplayDirectory);
+ return NS_OK;
+}
+NS_IMETHODIMP GFilePicker::SetDisplayDirectory(nsILocalFile * aDisplayDirectory)
+{
+ mDisplayDirectory = aDisplayDirectory;
+ return NS_OK;
+}
+
+/* readonly attribute nsILocalFile file; */
+NS_IMETHODIMP GFilePicker::GetFile(nsILocalFile * *aFile)
+{
+ NS_IF_ADDREF(*aFile = mFile);
+ return NS_OK;
+}
+
+/* readonly attribute nsIFileURL fileURL; */
+NS_IMETHODIMP GFilePicker::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 GFilePicker::GetFiles(nsISimpleEnumerator * *aFiles)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* short show (); */
+NS_IMETHODIMP GFilePicker::Show(PRInt16 *_retval)
+{
+ mFileSelector = gtk_file_selection_new(mTitle.get());
+
+ nsCAutoString cFileName;
+ if(mMode == nsIFilePicker::modeGetFolder)
+ cFileName.Assign("");
+ else
+ cFileName = mDefaultString;
+
+ nsCAutoString cDirName;
+ mDisplayDirectory->GetNativePath(cDirName);
+
+ nsCAutoString cFullPath;
+ cFullPath.Assign(cDirName + NS_LITERAL_CSTRING("/") + cFileName);
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(mFileSelector),
+ cFullPath.get());
+
+ if (!mFilter.IsEmpty())
+ {
+ gtk_file_selection_complete(GTK_FILE_SELECTION(mFileSelector),
+ mFilter.get());
+ }
+
+ if (mParentWidget)
+ gtk_window_set_transient_for(GTK_WINDOW(mFileSelector),
+ GTK_WINDOW(mParentWidget));
+
+ if (mShowContentCheck)
+ {
+ GtkWidget *bbox = gtk_hbutton_box_new ();
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox),
+ GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox), 0);
+ gtk_box_pack_end(GTK_BOX(GTK_FILE_SELECTION(mFileSelector)->action_area),
+ bbox, TRUE, TRUE, 0);
+
+ GtkWidget *saveContent =
+ gtk_check_button_new_with_label(_("Save with content"));
+ g_signal_connect(G_OBJECT(saveContent),
+ "clicked",
+ G_CALLBACK(filePicker_save_content_cb),
+ (gpointer)this);
+
+ gtk_box_pack_start(GTK_BOX(bbox), saveContent,
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all(bbox);
+ }
+
+ if (mFileFormats)
+ {
+ mFormatChooser = gtk_option_menu_new();
+ GtkMenu *options = GTK_MENU(gtk_menu_new());
+
+ FileFormat *current = mFileFormats;
+ while (current->description != NULL)
+ {
+ /* FIXME: the label should include the extensions too */
+ gchar *label = current->description;
+ GtkWidget *item = gtk_menu_item_new_with_label(label);
+ gtk_widget_show(item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(options), item);
+ current++;
+ }
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(mFormatChooser),
+ GTK_WIDGET(options));
+ gtk_widget_show(mFormatChooser);
+ gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION (mFileSelector)->action_area),
+ mFormatChooser,
+ FALSE, TRUE, 0);
+ }
+ else
+ {
+ mFormatChooser = NULL;
+ }
+
+ if (mMode == nsIFilePicker::modeGetFolder)
+ {
+ gtk_widget_set_sensitive(GTK_FILE_SELECTION(mFileSelector)
+ ->file_list, FALSE);
+ }
+
+ gtk_window_set_modal(GTK_WINDOW(mFileSelector), TRUE);
+
+ gint retVal = gtk_dialog_run(GTK_DIALOG(mFileSelector));
+
+ if (retVal == GTK_RESPONSE_OK)
+ {
+ HandleFilePickerResult(_retval);
+ }
+ else
+ {
+ *_retval = returnCancel;
+ }
+
+ gtk_widget_hide(mFileSelector);
+ gtk_widget_destroy(mFileSelector);
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// begin local public methods impl
+////////////////////////////////////////////////////////////////////////////////
+
+NS_METHOD GFilePicker::InitWithGtkWidget (GtkWidget *aParentWidget,
+ const char *aTitle, PRInt16 aMode)
+{
+ mParentWidget = aParentWidget;
+
+ mTitle = nsDependentCString(aTitle);
+
+ mMode = mMode;
+
+ mFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
+
+ return NS_OK;
+}
+
+NS_METHOD GFilePicker::SanityCheck (PRBool *retIsSane)
+{
+ *retIsSane = PR_TRUE;
+
+ PRBool dirExists, fileExists = PR_TRUE;
+
+ if (mDisplayDirectory)
+ {
+ mDisplayDirectory->Exists (&dirExists);
+ }
+ else
+ {
+ dirExists = PR_FALSE;
+ }
+
+ if (mMode == nsIFilePicker::modeOpen)
+ {
+ mFile->Exists (&fileExists);
+ }
+
+ 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(mFileSelector));
+
+ gtk_window_set_modal (GTK_WINDOW(errorDialog), TRUE);
+ gtk_dialog_run (GTK_DIALOG(errorDialog));
+ *retIsSane = PR_FALSE;
+ return NS_OK;
+ }
+
+ PRBool correctType;
+ char *errorText;
+ if (mMode == nsIFilePicker::modeGetFolder)
+ {
+ mDisplayDirectory->IsDirectory (&correctType);
+ errorText = g_strdup (_("A file was selected when a "
+ "folder was expected."));
+ }
+ else
+ {
+ mFile->IsFile (&correctType);
+ 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(mFileSelector));
+
+ gtk_window_set_modal (GTK_WINDOW(errorDialog), TRUE);
+ gtk_dialog_run (GTK_DIALOG(errorDialog));
+ *retIsSane = PR_FALSE;
+ }
+ g_free (errorText);
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// begin local private methods impl
+////////////////////////////////////////////////////////////////////////////////
+
+NS_METHOD GFilePicker::HandleFilePickerResult(PRInt16 *retval)
+{
+ *retval = returnCancel;
+ nsresult rv;
+
+ const char *fileName = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mFileSelector));
+
+ if (!fileName || strlen(fileName) == 0) return NS_ERROR_FAILURE;
+
+ if (mMode == nsIFilePicker::modeSave)
+ {
+ if (!ephy_gui_confirm_overwrite_file (mFileSelector,
+ fileName))
+ {
+ return NS_OK;
+ }
+ }
+
+ const nsACString &cFileName = nsDependentCString(fileName);
+ mFile->InitWithNativePath(cFileName);
+
+ if (mMode == nsIFilePicker::modeGetFolder)
+ {
+ mDisplayDirectory->InitWithNativePath(cFileName);
+ mDefaultString = "";
+ }
+ else
+ {
+ nsCOMPtr<nsIFile> directory;
+ mFile->GetParent(getter_AddRefs(directory));
+ mDisplayDirectory = do_QueryInterface(directory);
+ mFile->GetNativeLeafName(mDefaultString);
+ }
+
+ PRBool passesSanityCheck;
+ rv = SanityCheck(&passesSanityCheck);
+ if (NS_SUCCEEDED(rv) && !passesSanityCheck) return NS_ERROR_FAILURE;
+
+ if (mFormatChooser)
+ {
+ gint i = 0;
+ GtkWidget *menu = gtk_option_menu_get_menu
+ (GTK_OPTION_MENU(mFormatChooser));
+ GList *iterator = GTK_MENU_SHELL(menu)->children;
+ GtkWidget *selected = gtk_menu_get_active (GTK_MENU(menu));
+
+ while (iterator)
+ {
+ if (iterator->data == selected)
+ {
+ mSelectedFileFormat = i;
+ break;
+ }
+ iterator = iterator->next;
+ i++;
+ }
+ }
+
+ *retval = mSaveContent ? returnOKSaveContent : returnOK;
+ return NS_OK;
+}
+
+//------------------------------------------------------------------------------
+
+NS_DEF_FACTORY (GFilePicker, GFilePicker);
+
+/**
+ * NS_NewFilePickerFactory:
+ */
+nsresult NS_NewFilePickerFactory(nsIFactory** aFactory)
+{
+ NS_ENSURE_ARG_POINTER(aFactory);
+ *aFactory = nsnull;
+
+ nsGFilePickerFactory *result = new nsGFilePickerFactory;
+ if (result == NULL)
+ {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(result);
+ *aFactory = result;
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// begin FileSelector callbacks.
+////////////////////////////////////////////////////////////////////////////////
+
+void filePicker_save_content_cb(GtkToggleButton *aButton,
+ GFilePicker *aFilePicker)
+{
+ aFilePicker->mSaveContent = gtk_toggle_button_get_active (aButton) ?
+ PR_TRUE : PR_FALSE;
+}