зеркало из https://github.com/mozilla/pjs.git
Start using the GTK 2.4 file chooser when available.
r+sr=blizzard
This commit is contained in:
Родитель
4caf9382bb
Коммит
aea7fb58c1
|
@ -65,7 +65,8 @@ interface nsIFilePicker : nsISupports
|
||||||
const long filterApps = 0x40; // Applications (per-platform implementation)
|
const long filterApps = 0x40; // Applications (per-platform implementation)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the file widget.
|
* Initialize the file picker widget. The file picker is not valid until this
|
||||||
|
* method is called.
|
||||||
*
|
*
|
||||||
* @param parent nsIDOMWindow parent. This dialog will be dependent
|
* @param parent nsIDOMWindow parent. This dialog will be dependent
|
||||||
* on this parent. parent must be non-null.
|
* on this parent. parent must be non-null.
|
||||||
|
|
|
@ -79,6 +79,7 @@ CPPSRCS = \
|
||||||
nsGtkMozRemoteHelper.cpp \
|
nsGtkMozRemoteHelper.cpp \
|
||||||
nsClipboard.cpp \
|
nsClipboard.cpp \
|
||||||
nsDragService.cpp \
|
nsDragService.cpp \
|
||||||
|
nsFilePicker.cpp \
|
||||||
nsSound.cpp \
|
nsSound.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,576 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is the Mozilla GTK2 File Chooser.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Christopher Aillon <caillon@redhat.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include <gtk/gtkwindow.h>
|
||||||
|
#include <gtk/gtkdialog.h>
|
||||||
|
#include <gtk/gtkstock.h>
|
||||||
|
|
||||||
|
#include "nsIFileURL.h"
|
||||||
|
#include "nsIURI.h"
|
||||||
|
#include "nsIWidget.h"
|
||||||
|
#include "nsILocalFile.h"
|
||||||
|
#include "nsISupportsArray.h"
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
#include "nsMemory.h"
|
||||||
|
#include "nsEnumeratorUtils.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsReadableUtils.h"
|
||||||
|
|
||||||
|
#include "prmem.h"
|
||||||
|
#include "prlink.h"
|
||||||
|
|
||||||
|
#include "nsFilePicker.h"
|
||||||
|
|
||||||
|
/* from nsFilePicker.js */
|
||||||
|
#define XULFILEPICKER_CID \
|
||||||
|
{ 0x54ae32f8, 0x1dd2, 0x11b2, \
|
||||||
|
{ 0xa2, 0x09, 0xdf, 0x7c, 0x50, 0x53, 0x70, 0xf8} }
|
||||||
|
static NS_DEFINE_CID(kXULFilePickerCID, XULFILEPICKER_CID);
|
||||||
|
|
||||||
|
// XXX total ass. We should really impose a build-time requirement on gtk2.4
|
||||||
|
// and then check at run-time whether the user is actually running gtk2.4.
|
||||||
|
// We should then decide to load the component (or not) from the component mgr.
|
||||||
|
// We don't really have a mechanism to do that, though....
|
||||||
|
|
||||||
|
typedef struct GtkFileChooser;
|
||||||
|
typedef struct GtkFileFilter;
|
||||||
|
|
||||||
|
/* Copied from gtkfilechooser.h */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
|
||||||
|
} GtkFileChooserAction;
|
||||||
|
|
||||||
|
|
||||||
|
typedef gchar* (*_gtk_file_chooser_get_filename_fn)(GtkFileChooser *chooser);
|
||||||
|
typedef GtkWidget* (*_gtk_file_chooser_dialog_new_fn)(const gchar *title,
|
||||||
|
GtkWindow *parent,
|
||||||
|
GtkFileChooserAction action,
|
||||||
|
const gchar *first_button_text,
|
||||||
|
gint first_button_response,
|
||||||
|
const gchar *second_button_text,
|
||||||
|
gint second_button_response,
|
||||||
|
const gchar *third_button_text /* NULL */);
|
||||||
|
typedef void (*_gtk_file_chooser_set_select_multiple_fn)(GtkFileChooser* chooser, gboolean truth);
|
||||||
|
typedef void (*_gtk_file_chooser_set_current_name_fn)(GtkFileChooser* chooser, const gchar* name);
|
||||||
|
typedef void (*_gtk_file_chooser_add_filter_fn)(GtkFileChooser* chooser, GtkFileFilter* filter);
|
||||||
|
typedef GtkFileFilter* (*_gtk_file_filter_new_fn)();
|
||||||
|
typedef void (*_gtk_file_filter_add_pattern_fn)(GtkFileFilter* filter, const gchar* pattern);
|
||||||
|
typedef void (*_gtk_file_filter_set_name_fn)(GtkFileFilter* filter, const gchar* name);
|
||||||
|
|
||||||
|
#define DECL_FUNC_PTR(func) static _##func##_fn _##func
|
||||||
|
|
||||||
|
DECL_FUNC_PTR(gtk_file_chooser_get_filename);
|
||||||
|
DECL_FUNC_PTR(gtk_file_chooser_dialog_new);
|
||||||
|
DECL_FUNC_PTR(gtk_file_chooser_set_select_multiple);
|
||||||
|
DECL_FUNC_PTR(gtk_file_chooser_set_current_name);
|
||||||
|
DECL_FUNC_PTR(gtk_file_chooser_add_filter);
|
||||||
|
DECL_FUNC_PTR(gtk_file_filter_new);
|
||||||
|
DECL_FUNC_PTR(gtk_file_filter_add_pattern);
|
||||||
|
DECL_FUNC_PTR(gtk_file_filter_set_name);
|
||||||
|
|
||||||
|
|
||||||
|
static PRLibrary *
|
||||||
|
LoadVersionedLibrary(const char* libName, const char* libVersion)
|
||||||
|
{
|
||||||
|
char *platformLibName = PR_GetLibraryName(nsnull, libName);
|
||||||
|
nsCAutoString versionLibName(platformLibName);
|
||||||
|
versionLibName.Append(libVersion);
|
||||||
|
PR_FreeLibraryName(platformLibName);
|
||||||
|
return PR_LoadLibrary(versionLibName.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
InitGTK24()
|
||||||
|
{
|
||||||
|
static PRLibrary *libgtk24 = nsnull;
|
||||||
|
|
||||||
|
#define GET_LIBGTK_FUNC(func) \
|
||||||
|
PR_BEGIN_MACRO \
|
||||||
|
_##func = (_##func##_fn) PR_FindFunctionSymbol(libgtk24, #func); \
|
||||||
|
if (!_##func) { \
|
||||||
|
NS_WARNING("Can't load ##func##"); \
|
||||||
|
return NS_ERROR_NOT_AVAILABLE; \
|
||||||
|
} \
|
||||||
|
PR_END_MACRO
|
||||||
|
|
||||||
|
// This is easier
|
||||||
|
PRFuncPtr func = PR_FindFunctionSymbolAndLibrary("gtk_file_chooser_get_filename",
|
||||||
|
&libgtk24);
|
||||||
|
if (libgtk24) {
|
||||||
|
_gtk_file_chooser_get_filename = (_gtk_file_chooser_get_filename_fn)func;
|
||||||
|
} else {
|
||||||
|
// XXX hmm, this seems to fail when gtk 2.4 is already loaded...
|
||||||
|
libgtk24 = LoadVersionedLibrary("gtk-2", ".4");
|
||||||
|
if (!libgtk24) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_chooser_get_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_chooser_dialog_new);
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_chooser_set_select_multiple);
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_chooser_set_current_name);
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_chooser_add_filter);
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_filter_new);
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_filter_add_pattern);
|
||||||
|
GET_LIBGTK_FUNC(gtk_file_filter_set_name);
|
||||||
|
|
||||||
|
// Woot.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok, lib loading crap is done... the real code starts here:
|
||||||
|
|
||||||
|
static GtkFileChooserAction
|
||||||
|
GetGtkFileChooserAction(PRInt16 aMode)
|
||||||
|
{
|
||||||
|
GtkFileChooserAction action;
|
||||||
|
|
||||||
|
switch (aMode) {
|
||||||
|
case nsIFilePicker::modeSave:
|
||||||
|
action = GTK_FILE_CHOOSER_ACTION_SAVE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nsIFilePicker::modeGetFolder:
|
||||||
|
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NS_WARNING("Unknown nsIFilePicker mode");
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
case nsIFilePicker::modeOpen:
|
||||||
|
case nsIFilePicker::modeOpenMultiple:
|
||||||
|
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsString nsFilePicker::mLastUsedUnicodeDirectory;
|
||||||
|
|
||||||
|
//NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF(nsFilePicker)
|
||||||
|
NS_IMPL_RELEASE(nsFilePicker)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsFilePicker)
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->QueryInterface(aIID, aInstancePtr);
|
||||||
|
}
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIFilePicker)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFilePicker)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
nsFilePicker::nsFilePicker()
|
||||||
|
: mMode(nsIFilePicker::modeOpen),
|
||||||
|
mSelectedType(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nsFilePicker::~nsFilePicker()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsFilePicker::ReadValuesFromFileChooser(GtkWidget *file_chooser)
|
||||||
|
{
|
||||||
|
// Grab the filename
|
||||||
|
gchar *filename = _gtk_file_chooser_get_filename ((GtkFileChooser*) (file_chooser));
|
||||||
|
mFile.Assign(filename);
|
||||||
|
g_free(filename);
|
||||||
|
|
||||||
|
// Remember last used directory.
|
||||||
|
nsCOMPtr<nsILocalFile> file;
|
||||||
|
GetFile(getter_AddRefs(file));
|
||||||
|
if (file) {
|
||||||
|
nsCOMPtr<nsIFile> dir;
|
||||||
|
file->GetParent(getter_AddRefs(dir));
|
||||||
|
nsCOMPtr<nsILocalFile> localDir(do_QueryInterface(dir));
|
||||||
|
if (localDir) {
|
||||||
|
mDisplayDirectory = localDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::Init(nsIDOMWindow *aParent, const nsAString &aTitle, PRInt16 aMode)
|
||||||
|
{
|
||||||
|
// The GtkFileChooser API was first exposed in GTK+ 2.4. Make sure we have it,
|
||||||
|
// else fall back to the XUL picker.
|
||||||
|
nsresult rv = InitGTK24();
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("Couldn't load GTK+ 2.4 -- falling back to XUL file chooser.");
|
||||||
|
mXULPicker = do_CreateInstance(kXULFilePickerCID);
|
||||||
|
if (!mXULPicker) {
|
||||||
|
NS_WARNING("Couldn't load XUL file chooser. Running in circles!");
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mXULPicker->Init(aParent, aTitle, aMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIWidget *parent = DOMWindowToWidget(aParent);
|
||||||
|
NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
InitNative(parent, aTitle, aMode);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsFilePicker::InitNative(nsIWidget *aParent,
|
||||||
|
const nsAString& aTitle,
|
||||||
|
PRInt16 aMode)
|
||||||
|
{
|
||||||
|
mParentWidget = aParent;
|
||||||
|
mTitle.Assign(aTitle);
|
||||||
|
mMode = aMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::AppendFilters(PRInt32 aFilterMask)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->AppendFilters(aFilterMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsBaseFilePicker::AppendFilters(aFilterMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->AppendFilter(aTitle, aFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aFilter.Equals(NS_LITERAL_STRING("..apps"))) {
|
||||||
|
// No platform specific thing we can do here, really....
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCAutoString filter, name;
|
||||||
|
CopyUTF16toUTF8(aFilter, filter);
|
||||||
|
CopyUTF16toUTF8(aTitle, name);
|
||||||
|
|
||||||
|
mFilters.AppendCString(filter);
|
||||||
|
mFilterNames.AppendCString(name);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::SetDefaultString(const nsAString& aString)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->SetDefaultString(aString);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDefault = aString;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::GetDefaultString(nsAString& aString)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->GetDefaultString(aString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per API...
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::SetDefaultExtension(const nsAString& aExtension)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->SetDefaultExtension(aExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDefaultExtension = aExtension;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::GetDefaultExtension(nsAString& aExtension)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->GetDefaultExtension(aExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
aExtension = mDefaultExtension;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->GetFilterIndex(aFilterIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
*aFilterIndex = mSelectedType;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->SetFilterIndex(aFilterIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSelectedType = aFilterIndex;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::SetDisplayDirectory(nsILocalFile *aDirectory)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->SetDisplayDirectory(aDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDisplayDirectory = aDirectory;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::GetDisplayDirectory(nsILocalFile **aDirectory)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->GetDisplayDirectory(aDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IF_ADDREF(*aDirectory = mDisplayDirectory);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::GetFile(nsILocalFile **aFile)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->GetFile(aFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ENSURE_ARG_POINTER(aFile);
|
||||||
|
|
||||||
|
*aFile = nsnull;
|
||||||
|
if (mFile.IsEmpty()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsILocalFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
|
||||||
|
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
file->InitWithNativePath(mFile);
|
||||||
|
|
||||||
|
NS_ADDREF(*aFile = file);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::GetFileURL(nsIFileURL **aFileURL)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->GetFileURL(aFileURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsILocalFile> file;
|
||||||
|
GetFile(getter_AddRefs(file));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
NS_NewFileURI(getter_AddRefs(uri), file);
|
||||||
|
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
return CallQueryInterface(uri, aFileURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->GetFiles(aFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ENSURE_ARG_POINTER(aFiles);
|
||||||
|
|
||||||
|
if (mMode == nsIFilePicker::modeOpenMultiple) {
|
||||||
|
return NS_NewArrayEnumerator(aFiles, mFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsFilePicker::Show(PRInt16 *aReturn)
|
||||||
|
{
|
||||||
|
if (mXULPicker) {
|
||||||
|
return mXULPicker->Show(aReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ENSURE_ARG_POINTER(aReturn);
|
||||||
|
|
||||||
|
nsXPIDLCString title;
|
||||||
|
title.Adopt(ToNewUTF8String(mTitle));
|
||||||
|
|
||||||
|
GtkWidget *parent = (GtkWidget*)mParentWidget->GetNativeData(NS_NATIVE_WIDGET);
|
||||||
|
GtkFileChooserAction action = GetGtkFileChooserAction(mMode);
|
||||||
|
const gchar *accept_button = (mMode == GTK_FILE_CHOOSER_ACTION_SAVE)
|
||||||
|
? GTK_STOCK_SAVE : GTK_STOCK_OPEN;
|
||||||
|
|
||||||
|
GtkWidget *file_chooser =
|
||||||
|
_gtk_file_chooser_dialog_new(title, GTK_WINDOW(parent), action,
|
||||||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||||
|
accept_button, GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL);
|
||||||
|
if (mMode == nsIFilePicker::modeOpenMultiple) {
|
||||||
|
_gtk_file_chooser_set_select_multiple ((GtkFileChooser*) (file_chooser), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMode == nsIFilePicker::modeSave) {
|
||||||
|
char *default_filename = ToNewUTF8String(mDefault);
|
||||||
|
_gtk_file_chooser_set_current_name((GtkFileChooser*) (file_chooser),
|
||||||
|
NS_STATIC_CAST(const gchar*, default_filename));
|
||||||
|
nsMemory::Free(default_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt32 count = mFilters.Count();
|
||||||
|
for (PRInt32 i = 0; i < count; ++i) {
|
||||||
|
GtkFileFilter *filter = _gtk_file_filter_new ();
|
||||||
|
|
||||||
|
// This is fun... the GTK file picker does not accept a list of filters
|
||||||
|
// so we need to split out each string, and add it manually.
|
||||||
|
nsCAutoString pattern_list;
|
||||||
|
pattern_list.Assign(*mFilters[i]);
|
||||||
|
nsCString::const_iterator start, end, cur;
|
||||||
|
pattern_list.BeginReading(start);
|
||||||
|
pattern_list.EndReading(end);
|
||||||
|
|
||||||
|
cur = start;
|
||||||
|
while (cur != end) {
|
||||||
|
// Look for our delimiter of '; ' (semi-colon space)
|
||||||
|
if (*cur == ';') {
|
||||||
|
++cur;
|
||||||
|
if (*cur != ' ') {
|
||||||
|
NS_ERROR("The supplied filter is invalid. Go read nsIFilePicker.");
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("The ill eagle filter: %s\n", mFilters[i]->get());
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--cur;
|
||||||
|
const char* pattern = ToNewCString(Substring(start, cur));
|
||||||
|
_gtk_file_filter_add_pattern(filter, pattern);
|
||||||
|
printf("%s\n", pattern);
|
||||||
|
nsMemory::Free((void*)pattern);
|
||||||
|
++cur; ++cur;
|
||||||
|
start = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
++cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally add the last one
|
||||||
|
const char *pattern = ToNewCString(Substring(start, end));
|
||||||
|
_gtk_file_filter_add_pattern(filter, pattern);
|
||||||
|
nsMemory::Free((void*)pattern);
|
||||||
|
|
||||||
|
if (!mFilterNames[i]->IsEmpty()) {
|
||||||
|
// If we have a name for our filter, let's use that.
|
||||||
|
const char *filter_name = mFilterNames[i]->get();
|
||||||
|
_gtk_file_filter_set_name (filter, filter_name);
|
||||||
|
} else {
|
||||||
|
// If we don't have a name, let's just use the filter pattern.
|
||||||
|
const char *filter_pattern = mFilters[i]->get();
|
||||||
|
_gtk_file_filter_set_name (filter, filter_pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
_gtk_file_chooser_add_filter ((GtkFileChooser*) (file_chooser), filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
gint response = gtk_dialog_run (GTK_DIALOG (file_chooser));
|
||||||
|
|
||||||
|
switch (response) {
|
||||||
|
case GTK_RESPONSE_ACCEPT:
|
||||||
|
ReadValuesFromFileChooser(file_chooser);
|
||||||
|
*aReturn = nsIFilePicker::returnOK;
|
||||||
|
if (mMode == modeSave) {
|
||||||
|
nsCOMPtr<nsILocalFile> file;
|
||||||
|
GetFile(getter_AddRefs(file));
|
||||||
|
if (file) {
|
||||||
|
PRBool exists = PR_FALSE;
|
||||||
|
file->Exists(&exists);
|
||||||
|
if (exists) {
|
||||||
|
*aReturn = nsIFilePicker::returnReplace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_RESPONSE_CANCEL:
|
||||||
|
case GTK_RESPONSE_CLOSE:
|
||||||
|
case GTK_RESPONSE_DELETE_EVENT:
|
||||||
|
*aReturn = nsIFilePicker::returnCancel;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NS_WARNING("Unexpected response");
|
||||||
|
*aReturn = nsIFilePicker::returnCancel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_destroy(file_chooser);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is the Mozilla GTK2 File Chooser.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Christopher Aillon <caillon@redhat.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#ifndef nsFilePicker_h__
|
||||||
|
#define nsFilePicker_h__
|
||||||
|
|
||||||
|
#include <gtk/gtkwidget.h>
|
||||||
|
|
||||||
|
#include "nsBaseFilePicker.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
|
||||||
|
class nsIWidget;
|
||||||
|
class nsILocalFile;
|
||||||
|
class nsISupportsArray;
|
||||||
|
|
||||||
|
class nsFilePicker : public nsBaseFilePicker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsFilePicker();
|
||||||
|
virtual ~nsFilePicker();
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
NS_DECL_NSIFILEPICKER
|
||||||
|
|
||||||
|
virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle, PRInt16 aMode);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void ReadValuesFromFileChooser(GtkWidget *file_chooser);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> mParentWidget;
|
||||||
|
nsCOMPtr<nsILocalFile> mDisplayDirectory;
|
||||||
|
nsCOMPtr<nsISupportsArray> mFiles;
|
||||||
|
|
||||||
|
PRInt16 mMode;
|
||||||
|
PRInt16 mSelectedType;
|
||||||
|
nsCString mFile;
|
||||||
|
nsString mTitle;
|
||||||
|
nsString mDefault;
|
||||||
|
nsString mDefaultExtension;
|
||||||
|
|
||||||
|
nsCStringArray mFilters;
|
||||||
|
nsCStringArray mFilterNames;
|
||||||
|
|
||||||
|
/* If we don't have GTK2.4, we need to proxy calls on to a XUL filepicker */
|
||||||
|
nsCOMPtr<nsIFilePicker> mXULPicker;
|
||||||
|
|
||||||
|
static nsString mLastUsedUnicodeDirectory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -48,6 +48,7 @@
|
||||||
#include "nsHTMLFormatConverter.h"
|
#include "nsHTMLFormatConverter.h"
|
||||||
#include "nsClipboard.h"
|
#include "nsClipboard.h"
|
||||||
#include "nsDragService.h"
|
#include "nsDragService.h"
|
||||||
|
#include "nsFilePicker.h"
|
||||||
#include "nsSound.h"
|
#include "nsSound.h"
|
||||||
#include "nsBidiKeyboard.h"
|
#include "nsBidiKeyboard.h"
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsClipboard, Init)
|
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsClipboard, Init)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
|
||||||
|
|
||||||
static const nsModuleComponentInfo components[] =
|
static const nsModuleComponentInfo components[] =
|
||||||
|
@ -82,6 +84,10 @@ static const nsModuleComponentInfo components[] =
|
||||||
NS_LOOKANDFEEL_CID,
|
NS_LOOKANDFEEL_CID,
|
||||||
"@mozilla.org/widget/lookandfeel;1",
|
"@mozilla.org/widget/lookandfeel;1",
|
||||||
nsLookAndFeelConstructor },
|
nsLookAndFeelConstructor },
|
||||||
|
{ "Gtk2 File Picker",
|
||||||
|
NS_FILEPICKER_CID,
|
||||||
|
"@mozilla.org/filepicker;1",
|
||||||
|
nsFilePickerConstructor },
|
||||||
{ "Gtk2 Sound",
|
{ "Gtk2 Sound",
|
||||||
NS_SOUND_CID,
|
NS_SOUND_CID,
|
||||||
"@mozilla.org/sound;1",
|
"@mozilla.org/sound;1",
|
||||||
|
|
|
@ -78,7 +78,7 @@ ifneq (,$(filter beos os2 mac cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
|
||||||
CPPSRCS += nsBaseClipboard.cpp
|
CPPSRCS += nsBaseClipboard.cpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter beos os2 mac cocoa photon windows,$(MOZ_WIDGET_TOOLKIT)))
|
ifneq (,$(filter beos gtk2 os2 mac cocoa photon windows,$(MOZ_WIDGET_TOOLKIT)))
|
||||||
CPPSRCS += nsBaseFilePicker.cpp
|
CPPSRCS += nsBaseFilePicker.cpp
|
||||||
REQUIRES += docshell view intl
|
REQUIRES += docshell view intl
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -73,7 +73,6 @@ nsBaseFilePicker::~nsBaseFilePicker()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX aaaarrrrrrgh! */
|
|
||||||
nsIWidget *nsBaseFilePicker::DOMWindowToWidget(nsIDOMWindow *dw)
|
nsIWidget *nsBaseFilePicker::DOMWindowToWidget(nsIDOMWindow *dw)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(dw);
|
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(dw);
|
||||||
|
|
|
@ -65,8 +65,6 @@ protected:
|
||||||
virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle,
|
virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle,
|
||||||
PRInt16 aMode) = 0;
|
PRInt16 aMode) = 0;
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
nsIWidget *DOMWindowToWidget(nsIDOMWindow *dw);
|
nsIWidget *DOMWindowToWidget(nsIDOMWindow *dw);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче