mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Add support for opening multiple files with the unix filepicker (bug 167152). r=varga, sr=bzbarsky.
This commit is contained in:
parent
9dbb0745e1
commit
5b3486f79b
@ -33,6 +33,7 @@ const nsIFileView = Components.interfaces.nsIFileView;
|
||||
const nsFileView_CONTRACTID = "@mozilla.org/filepicker/fileview;1";
|
||||
const nsITreeView = Components.interfaces.nsITreeView;
|
||||
const nsILocalFile = Components.interfaces.nsILocalFile;
|
||||
const nsIFile = Components.interfaces.nsIFile;
|
||||
const nsLocalFile_CONTRACTID = "@mozilla.org/file/local;1";
|
||||
const nsIPromptService_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1";
|
||||
|
||||
@ -134,6 +135,9 @@ function filepickerLoad() {
|
||||
retvals.buttonStatus = nsIFilePicker.returnCancel;
|
||||
|
||||
var tree = document.getElementById("directoryTree");
|
||||
if (filePickerMode == nsIFilePicker.modeOpenMultiple)
|
||||
tree.removeAttribute("seltype");
|
||||
|
||||
tree.treeBoxObject.view = treeView;
|
||||
|
||||
// Start out with the ok button disabled since nothing will be
|
||||
@ -195,7 +199,7 @@ function showErrorDialog(titleStrName, messageStrName, file)
|
||||
|
||||
function openOnOK()
|
||||
{
|
||||
var dir = treeView.getSelectedFile();
|
||||
var dir = treeView.selectedFiles.queryElementAt(0, nsIFile);
|
||||
if (!dir.isReadable()) {
|
||||
showErrorDialog("errorOpenFileDoesntExistTitle",
|
||||
"errorDirNotReadableMessage",
|
||||
@ -206,7 +210,7 @@ function openOnOK()
|
||||
if (dir)
|
||||
gotoDirectory(dir);
|
||||
|
||||
retvals.file = dir;
|
||||
retvals.fileList = new Array(dir);
|
||||
|
||||
retvals.buttonStatus = nsIFilePicker.returnCancel;
|
||||
|
||||
@ -219,150 +223,150 @@ function openOnOK()
|
||||
function selectOnOK()
|
||||
{
|
||||
var errorTitle, errorMessage, promptService;
|
||||
var ret = nsIFilePicker.returnCancel;
|
||||
var ret = nsIFilePicker.returnOK;
|
||||
|
||||
var isDir = false;
|
||||
var isFile = false;
|
||||
|
||||
var file = processPath(textInput.value);
|
||||
var fileList = processPath(textInput.value);
|
||||
|
||||
if (!file) { // generic error message, should probably never happen
|
||||
if (!fileList) { // generic error message, should probably never happen
|
||||
showErrorDialog("errorPathProblemTitle",
|
||||
"errorPathProblemMessage",
|
||||
textInput.value);
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to normalize - if this fails we will ignore the error
|
||||
// because we will notice the
|
||||
// error later and show a fitting error alert.
|
||||
try{
|
||||
file.normalize();
|
||||
} catch(e) {
|
||||
//promptService.alert(window, "Problem", "normalize failed, continuing");
|
||||
}
|
||||
var curFileIndex;
|
||||
for (curFileIndex = 0; curFileIndex < fileList.length &&
|
||||
ret != nsIFilePicker.returnCancel; ++curFileIndex) {
|
||||
var file = fileList[curFileIndex].QueryInterface(nsIFile);
|
||||
|
||||
var fileExists = file.exists();
|
||||
|
||||
if (!fileExists && (filePickerMode == nsIFilePicker.modeOpen ||
|
||||
filePickerMode == nsIFilePicker.modeOpenMultiple)) {
|
||||
showErrorDialog("errorOpenFileDoesntExistTitle",
|
||||
"errorOpenFileDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fileExists && filePickerMode == nsIFilePicker.modeGetFolder) {
|
||||
showErrorDialog("errorDirDoesntExistTitle",
|
||||
"errorDirDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileExists) {
|
||||
isDir = file.isDirectory();
|
||||
isFile = file.isFile();
|
||||
}
|
||||
|
||||
switch(filePickerMode) {
|
||||
case nsIFilePicker.modeOpen:
|
||||
case nsIFilePicker.modeOpenMultiple:
|
||||
if (isFile) {
|
||||
if (file.isReadable()) {
|
||||
retvals.directory = file.parent.path;
|
||||
ret = nsIFilePicker.returnOK;
|
||||
} else {
|
||||
showErrorDialog("errorOpeningFileTitle",
|
||||
"openWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
// try to normalize - if this fails we will ignore the error
|
||||
// because we will notice the
|
||||
// error later and show a fitting error alert.
|
||||
try{
|
||||
file.normalize();
|
||||
} catch(e) {
|
||||
//promptService.alert(window, "Problem", "normalize failed, continuing");
|
||||
}
|
||||
break;
|
||||
case nsIFilePicker.modeSave:
|
||||
if (isFile) { // can only be true if file.exists()
|
||||
if (!file.isWritable()) {
|
||||
showErrorDialog("errorSavingFileTitle",
|
||||
"saveWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
// we need to pop up a dialog asking if you want to save
|
||||
var confirmTitle = gFilePickerBundle.getString("confirmTitle");
|
||||
var message =
|
||||
gFilePickerBundle.getFormattedString("confirmFileReplacing",
|
||||
[file.path]);
|
||||
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
var rv = promptService.confirm(window, title, message)
|
||||
if (rv) {
|
||||
ret = nsIFilePicker.returnReplace;
|
||||
var fileExists = file.exists();
|
||||
|
||||
if (!fileExists && (filePickerMode == nsIFilePicker.modeOpen ||
|
||||
filePickerMode == nsIFilePicker.modeOpenMultiple)) {
|
||||
showErrorDialog("errorOpenFileDoesntExistTitle",
|
||||
"errorOpenFileDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fileExists && filePickerMode == nsIFilePicker.modeGetFolder) {
|
||||
showErrorDialog("errorDirDoesntExistTitle",
|
||||
"errorDirDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileExists) {
|
||||
isDir = file.isDirectory();
|
||||
isFile = file.isFile();
|
||||
}
|
||||
|
||||
switch(filePickerMode) {
|
||||
case nsIFilePicker.modeOpen:
|
||||
case nsIFilePicker.modeOpenMultiple:
|
||||
if (isFile) {
|
||||
if (file.isReadable()) {
|
||||
retvals.directory = file.parent.path;
|
||||
} else {
|
||||
showErrorDialog("errorOpeningFileTitle",
|
||||
"openWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
break;
|
||||
case nsIFilePicker.modeSave:
|
||||
if (isFile) { // can only be true if file.exists()
|
||||
if (!file.isWritable()) {
|
||||
showErrorDialog("errorSavingFileTitle",
|
||||
"saveWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
// we need to pop up a dialog asking if you want to save
|
||||
var confirmTitle = gFilePickerBundle.getString("confirmTitle");
|
||||
var message =
|
||||
gFilePickerBundle.getFormattedString("confirmFileReplacing",
|
||||
[file.path]);
|
||||
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
var rv = promptService.confirm(window, title, message);
|
||||
if (rv) {
|
||||
ret = nsIFilePicker.returnReplace;
|
||||
retvals.directory = file.parent.path;
|
||||
} else {
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
var parent = file.parent;
|
||||
if (parent.exists() && parent.isDirectory() && parent.isWritable()) {
|
||||
retvals.directory = parent.path;
|
||||
} else {
|
||||
var oldParent = parent;
|
||||
while (!parent.exists()) {
|
||||
oldParent = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
errorTitle =
|
||||
gFilePickerBundle.getFormattedString("errorSavingFileTitle",
|
||||
[file.path]);
|
||||
if (parent.isFile()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentIsFileMessage",
|
||||
[parent.path, file.path]);
|
||||
} else {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentDoesntExistMessage",
|
||||
[oldParent.path, file.path]);
|
||||
}
|
||||
if (!parent.isWritable()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveWithoutPermissionMessage_dir", [parent.path]);
|
||||
}
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
promptService.alert(window, errorTitle, errorMessage);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
var parent = file.parent;
|
||||
if (parent.exists() && parent.isDirectory() && parent.isWritable()) {
|
||||
ret = nsIFilePicker.returnOK;
|
||||
retvals.directory = parent.path;
|
||||
} else {
|
||||
var oldParent = parent;
|
||||
while (!parent.exists()) {
|
||||
oldParent = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
errorTitle =
|
||||
gFilePickerBundle.getFormattedString("errorSavingFileTitle",
|
||||
[file.path]);
|
||||
if (parent.isFile()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentIsFileMessage",
|
||||
[parent.path, file.path]);
|
||||
} else {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentDoesntExistMessage",
|
||||
[oldParent.path, file.path]);
|
||||
}
|
||||
if (!parent.isWritable()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveWithoutPermissionMessage_dir", [parent.path]);
|
||||
}
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
promptService.alert(window, errorTitle, errorMessage);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
break;
|
||||
case nsIFilePicker.modeGetFolder:
|
||||
if (isDir) {
|
||||
retvals.directory = file.parent.path;
|
||||
} else { // if nothing selected, the current directory will be fine
|
||||
retvals.directory = sfile.path;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case nsIFilePicker.modeGetFolder:
|
||||
if (isDir) {
|
||||
retvals.directory = file.parent.path;
|
||||
} else { // if nothing selected, the current directory will be fine
|
||||
retvals.directory = sfile.path;
|
||||
}
|
||||
ret = nsIFilePicker.returnOK;
|
||||
break;
|
||||
}
|
||||
|
||||
retvals.file = file;
|
||||
|
||||
gFilesEnumerator.mFile = file;
|
||||
gFilesEnumerator.mHasMore = true;
|
||||
gFilesEnumerator.mFiles = fileList;
|
||||
|
||||
retvals.files = gFilesEnumerator;
|
||||
retvals.buttonStatus = ret;
|
||||
@ -374,17 +378,18 @@ function selectOnOK()
|
||||
}
|
||||
|
||||
var gFilesEnumerator = {
|
||||
mHasMore: false,
|
||||
mFile: null,
|
||||
mFiles: null,
|
||||
mIndex: 0,
|
||||
|
||||
hasMoreElements: function()
|
||||
{
|
||||
return this.mHasMore;
|
||||
return (this.mIndex < this.mFiles.length);
|
||||
},
|
||||
getNext: function()
|
||||
{
|
||||
this.mHasMore = false;
|
||||
return this.mFile;
|
||||
if (this.mIndex >= this.mFiles.length)
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
return this.mFiles[this.mIndex++];
|
||||
}
|
||||
};
|
||||
|
||||
@ -409,10 +414,11 @@ function onDblClick(e) {
|
||||
}
|
||||
|
||||
function openSelectedFile() {
|
||||
var file = treeView.getSelectedFile();
|
||||
if (!file)
|
||||
var fileList = treeView.selectedFiles;
|
||||
if (fileList.length == 0)
|
||||
return;
|
||||
|
||||
var file = fileList.queryElementAt(0, nsIFile);
|
||||
if (file.isDirectory())
|
||||
gotoDirectory(file);
|
||||
else if (file.isFile())
|
||||
@ -473,8 +479,9 @@ function onKeypress(e) {
|
||||
if (e.keyCode == 8) /* backspace */
|
||||
goUp();
|
||||
else if (e.keyCode == 13) { /* enter */
|
||||
var file = treeView.getSelectedFile();
|
||||
if (file) {
|
||||
var fileList = treeView.selectedFiles;
|
||||
if (fileList.length > 0) {
|
||||
var file = fileList.queryElementAt(0, nsIFile);
|
||||
if (file.isDirectory()) {
|
||||
gotoDirectory(file);
|
||||
e.preventDefault();
|
||||
@ -493,7 +500,7 @@ function doEnabling() {
|
||||
|
||||
function onTreeFocus(event) {
|
||||
// Reset the button label and enabled/disabled state.
|
||||
onFileSelected(treeView.getSelectedFile());
|
||||
onFileSelected(treeView.selectedFiles);
|
||||
}
|
||||
|
||||
function getOKAction(file) {
|
||||
@ -523,24 +530,66 @@ function getOKAction(file) {
|
||||
}
|
||||
|
||||
function onSelect(event) {
|
||||
onFileSelected(treeView.getSelectedFile());
|
||||
onFileSelected(treeView.selectedFiles);
|
||||
}
|
||||
|
||||
function onFileSelected(file) {
|
||||
if (file) {
|
||||
var path = file.leafName;
|
||||
|
||||
if (path) {
|
||||
if ((filePickerMode == nsIFilePicker.modeGetFolder) || !file.isDirectory())
|
||||
textInput.value = path;
|
||||
|
||||
var buttonLabel = getOKAction(file);
|
||||
okButton.setAttribute("label", buttonLabel);
|
||||
okButton.disabled = false;
|
||||
return;
|
||||
function onFileSelected(/* nsIArray */ selectedFileList) {
|
||||
var validFileSelected = false;
|
||||
var invalidSelection = false;
|
||||
var file;
|
||||
var fileCount = selectedFileList.length;
|
||||
|
||||
for (var index = 0; index < fileCount; ++index) {
|
||||
file = selectedFileList.queryElementAt(index, nsIFile);
|
||||
if (file) {
|
||||
var path = file.leafName;
|
||||
|
||||
if (path) {
|
||||
var isDir = file.isDirectory();
|
||||
if ((filePickerMode == nsIFilePicker.modeGetFolder) || !isDir) {
|
||||
if (!validFileSelected)
|
||||
textInput.value = "";
|
||||
addToTextFieldValue(path);
|
||||
}
|
||||
|
||||
if (isDir && fileCount > 1) {
|
||||
// The user has selected multiple items, and one of them is
|
||||
// a directory. This is not a valid state, so we'll disable
|
||||
// the ok button.
|
||||
invalidSelection = true;
|
||||
}
|
||||
|
||||
validFileSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
okButton.disabled = (textInput.value == "");
|
||||
|
||||
if (validFileSelected) {
|
||||
var buttonLabel = getOKAction(file);
|
||||
okButton.setAttribute("label", buttonLabel);
|
||||
okButton.disabled = invalidSelection;
|
||||
} else
|
||||
okButton.disabled = (textInput.value == "");
|
||||
}
|
||||
|
||||
function addToTextFieldValue(path)
|
||||
{
|
||||
var newValue = "";
|
||||
|
||||
if (textInput.value == "")
|
||||
newValue = path.replace(/\"/g, "\\\"");
|
||||
else {
|
||||
// Quote the existing text if needed,
|
||||
// then append the new filename (quoted and escaped)
|
||||
if (textInput.value[0] != '"')
|
||||
newValue = '"' + textInput.value.replace(/\"/g, "\\\"") + '"';
|
||||
else
|
||||
newValue = textInput.value;
|
||||
|
||||
newValue = newValue + ' "' + path.replace(/\"/g, "\\\"") + '"';
|
||||
}
|
||||
|
||||
textInput.value = newValue;
|
||||
}
|
||||
|
||||
function onTextFieldFocus() {
|
||||
@ -624,6 +673,7 @@ function newDir() {
|
||||
return false;
|
||||
}
|
||||
|
||||
file = file[0].QueryInterface(nsIFile);
|
||||
if (file.exists()) {
|
||||
showErrorDialog("errorNewDirDoesExistTitle",
|
||||
"errorNewDirDoesExistMessage",
|
||||
@ -653,7 +703,7 @@ function newDir() {
|
||||
}
|
||||
|
||||
try {
|
||||
file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
file.create(nsIFile.DIRECTORY_TYPE, 0755);
|
||||
} catch (e) {
|
||||
showErrorDialog("errorCreateNewDirTitle",
|
||||
"errorCreateNewDirMessage",
|
||||
@ -699,13 +749,76 @@ function toggleShowHidden(event) {
|
||||
// uses "/" as the directory seperator, "~" as a shortcut
|
||||
// for the home directory (but only when seen at the start
|
||||
// of a path), and ".." to denote the parent directory.
|
||||
// returns the path or false if an error occurred.
|
||||
// returns an array of the files listed,
|
||||
// or false if an error occurred.
|
||||
function processPath(path)
|
||||
{
|
||||
var file;
|
||||
if (path[0] == '~')
|
||||
path = homeDir.path + path.substring(1);
|
||||
var fileArray = new Array();
|
||||
var strLength = path.length;
|
||||
|
||||
if (path[0] == '"' && filePickerMode == nsIFilePicker.modeOpenMultiple &&
|
||||
strLength > 1) {
|
||||
// we have a quoted list of filenames, separated by spaces.
|
||||
// iterate the list and process each file.
|
||||
|
||||
var curFileStart = 1;
|
||||
|
||||
while (1) {
|
||||
var nextQuote;
|
||||
|
||||
// Look for an unescaped quote
|
||||
var quoteSearchStart = curFileStart + 1;
|
||||
do {
|
||||
nextQuote = path.indexOf('"', quoteSearchStart);
|
||||
quoteSearchStart = nextQuote + 1;
|
||||
} while (nextQuote != -1 && path[nextQuote - 1] == '\\');
|
||||
|
||||
if (nextQuote == -1) {
|
||||
// we have a filename with no trailing quote.
|
||||
// just assume that the filename ends at the end of the string.
|
||||
|
||||
if (!processPathEntry(path.substring(curFileStart), fileArray))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!processPathEntry(path.substring(curFileStart, nextQuote), fileArray))
|
||||
return false;
|
||||
|
||||
curFileStart = path.indexOf('"', nextQuote + 1);
|
||||
if (curFileStart == -1) {
|
||||
// no more quotes, but if we're not at the end of the string,
|
||||
// go ahead and process the remaining text.
|
||||
|
||||
if (nextQuote < strLength - 1)
|
||||
if (!processPathEntry(path.substring(nextQuote + 1), fileArray))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
++curFileStart;
|
||||
}
|
||||
} else {
|
||||
// If we didn't start with a quote, assume we just have a single file.
|
||||
if (!processPathEntry(path, fileArray))
|
||||
return false;
|
||||
}
|
||||
|
||||
return fileArray;
|
||||
}
|
||||
|
||||
function processPathEntry(path, fileArray)
|
||||
{
|
||||
var filePath;
|
||||
var file;
|
||||
|
||||
if (path[0] == '~')
|
||||
filePath = homeDir.path + path.substring(1);
|
||||
else
|
||||
filePath = path;
|
||||
|
||||
// Unescape quotes
|
||||
filePath = filePath.replace(/\\\"/g, "\"");
|
||||
|
||||
try{
|
||||
file = sfile.clone().QueryInterface(nsILocalFile);
|
||||
} catch(e) {
|
||||
@ -713,15 +826,15 @@ function processPath(path)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (path[0] == '/') /* an absolute path was entered */
|
||||
file.initWithPath(path);
|
||||
else if ((path.indexOf("/../") > 0) ||
|
||||
(path.substr(-3) == "/..") ||
|
||||
(path.substr(0,3) == "../") ||
|
||||
(path == "..")) {
|
||||
if (filePath[0] == '/') /* an absolute path was entered */
|
||||
file.initWithPath(filePath);
|
||||
else if ((filePath.indexOf("/../") > 0) ||
|
||||
(filePath.substr(-3) == "/..") ||
|
||||
(filePath.substr(0,3) == "../") ||
|
||||
(filePath == "..")) {
|
||||
/* appendRelativePath doesn't allow .. */
|
||||
try{
|
||||
file.initWithPath(file.path + "/" + path);
|
||||
file.initWithPath(file.path + "/" + filePath);
|
||||
} catch (e) {
|
||||
dump("Couldn't init path\n"+e);
|
||||
return false;
|
||||
@ -729,11 +842,13 @@ function processPath(path)
|
||||
}
|
||||
else {
|
||||
try {
|
||||
file.appendRelativePath(path);
|
||||
file.appendRelativePath(filePath);
|
||||
} catch (e) {
|
||||
dump("Couldn't append path\n"+e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return file;
|
||||
|
||||
fileArray[fileArray.length] = file;
|
||||
return true;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIArray;
|
||||
interface nsIFile;
|
||||
|
||||
[scriptable, uuid(60b320d2-1dd2-11b2-bd73-dc3575f78ddd)]
|
||||
@ -56,7 +57,7 @@ interface nsIFileView : nsISupports
|
||||
void setDirectory(in nsIFile directory);
|
||||
void setFilter(in wstring filterString);
|
||||
|
||||
nsIFile getSelectedFile();
|
||||
readonly attribute nsIArray selectedFiles;
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -34,6 +34,7 @@ const nsIFileView = Components.interfaces.nsIFileView;
|
||||
const nsFileView_CONTRACTID = "@mozilla.org/filepicker/fileview;1";
|
||||
const nsITreeView = Components.interfaces.nsITreeView;
|
||||
const nsILocalFile = Components.interfaces.nsILocalFile;
|
||||
const nsIFile = Components.interfaces.nsIFile;
|
||||
const nsLocalFile_CONTRACTID = "@mozilla.org/file/local;1";
|
||||
const nsIPromptService_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1";
|
||||
|
||||
@ -135,6 +136,9 @@ function filepickerLoad() {
|
||||
retvals.buttonStatus = nsIFilePicker.returnCancel;
|
||||
|
||||
var tree = document.getElementById("directoryTree");
|
||||
if (filePickerMode == nsIFilePicker.modeOpenMultiple)
|
||||
tree.removeAttribute("seltype");
|
||||
|
||||
tree.treeBoxObject.view = treeView;
|
||||
|
||||
// Start out with the ok button disabled since nothing will be
|
||||
@ -196,7 +200,7 @@ function showErrorDialog(titleStrName, messageStrName, file)
|
||||
|
||||
function openOnOK()
|
||||
{
|
||||
var dir = treeView.getSelectedFile();
|
||||
var dir = treeView.selectedFiles.queryElementAt(0, nsIFile);
|
||||
if (!dir.isReadable()) {
|
||||
showErrorDialog("errorOpenFileDoesntExistTitle",
|
||||
"errorDirNotReadableMessage",
|
||||
@ -207,7 +211,7 @@ function openOnOK()
|
||||
if (dir)
|
||||
gotoDirectory(dir);
|
||||
|
||||
retvals.file = dir;
|
||||
retvals.fileList = new Array(dir);
|
||||
|
||||
retvals.buttonStatus = nsIFilePicker.returnCancel;
|
||||
|
||||
@ -220,150 +224,150 @@ function openOnOK()
|
||||
function selectOnOK()
|
||||
{
|
||||
var errorTitle, errorMessage, promptService;
|
||||
var ret = nsIFilePicker.returnCancel;
|
||||
var ret = nsIFilePicker.returnOK;
|
||||
|
||||
var isDir = false;
|
||||
var isFile = false;
|
||||
|
||||
var file = processPath(textInput.value);
|
||||
var fileList = processPath(textInput.value);
|
||||
|
||||
if (!file) { // generic error message, should probably never happen
|
||||
if (!fileList) { // generic error message, should probably never happen
|
||||
showErrorDialog("errorPathProblemTitle",
|
||||
"errorPathProblemMessage",
|
||||
textInput.value);
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to normalize - if this fails we will ignore the error
|
||||
// because we will notice the
|
||||
// error later and show a fitting error alert.
|
||||
try{
|
||||
file.normalize();
|
||||
} catch(e) {
|
||||
//promptService.alert(window, "Problem", "normalize failed, continuing");
|
||||
}
|
||||
var curFileIndex;
|
||||
for (curFileIndex = 0; curFileIndex < fileList.length &&
|
||||
ret != nsIFilePicker.returnCancel; ++curFileIndex) {
|
||||
var file = fileList[curFileIndex].QueryInterface(nsIFile);
|
||||
|
||||
var fileExists = file.exists();
|
||||
|
||||
if (!fileExists && (filePickerMode == nsIFilePicker.modeOpen ||
|
||||
filePickerMode == nsIFilePicker.modeOpenMultiple)) {
|
||||
showErrorDialog("errorOpenFileDoesntExistTitle",
|
||||
"errorOpenFileDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fileExists && filePickerMode == nsIFilePicker.modeGetFolder) {
|
||||
showErrorDialog("errorDirDoesntExistTitle",
|
||||
"errorDirDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileExists) {
|
||||
isDir = file.isDirectory();
|
||||
isFile = file.isFile();
|
||||
}
|
||||
|
||||
switch(filePickerMode) {
|
||||
case nsIFilePicker.modeOpen:
|
||||
case nsIFilePicker.modeOpenMultiple:
|
||||
if (isFile) {
|
||||
if (file.isReadable()) {
|
||||
retvals.directory = file.parent.path;
|
||||
ret = nsIFilePicker.returnOK;
|
||||
} else {
|
||||
showErrorDialog("errorOpeningFileTitle",
|
||||
"openWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
// try to normalize - if this fails we will ignore the error
|
||||
// because we will notice the
|
||||
// error later and show a fitting error alert.
|
||||
try{
|
||||
file.normalize();
|
||||
} catch(e) {
|
||||
//promptService.alert(window, "Problem", "normalize failed, continuing");
|
||||
}
|
||||
break;
|
||||
case nsIFilePicker.modeSave:
|
||||
if (isFile) { // can only be true if file.exists()
|
||||
if (!file.isWritable()) {
|
||||
showErrorDialog("errorSavingFileTitle",
|
||||
"saveWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
// we need to pop up a dialog asking if you want to save
|
||||
var confirmTitle = gFilePickerBundle.getString("confirmTitle");
|
||||
var message =
|
||||
gFilePickerBundle.getFormattedString("confirmFileReplacing",
|
||||
[file.path]);
|
||||
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
var rv = promptService.confirm(window, title, message)
|
||||
if (rv) {
|
||||
ret = nsIFilePicker.returnReplace;
|
||||
var fileExists = file.exists();
|
||||
|
||||
if (!fileExists && (filePickerMode == nsIFilePicker.modeOpen ||
|
||||
filePickerMode == nsIFilePicker.modeOpenMultiple)) {
|
||||
showErrorDialog("errorOpenFileDoesntExistTitle",
|
||||
"errorOpenFileDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fileExists && filePickerMode == nsIFilePicker.modeGetFolder) {
|
||||
showErrorDialog("errorDirDoesntExistTitle",
|
||||
"errorDirDoesntExistMessage",
|
||||
file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileExists) {
|
||||
isDir = file.isDirectory();
|
||||
isFile = file.isFile();
|
||||
}
|
||||
|
||||
switch(filePickerMode) {
|
||||
case nsIFilePicker.modeOpen:
|
||||
case nsIFilePicker.modeOpenMultiple:
|
||||
if (isFile) {
|
||||
if (file.isReadable()) {
|
||||
retvals.directory = file.parent.path;
|
||||
} else {
|
||||
showErrorDialog("errorOpeningFileTitle",
|
||||
"openWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
break;
|
||||
case nsIFilePicker.modeSave:
|
||||
if (isFile) { // can only be true if file.exists()
|
||||
if (!file.isWritable()) {
|
||||
showErrorDialog("errorSavingFileTitle",
|
||||
"saveWithoutPermissionMessage_file",
|
||||
file);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
// we need to pop up a dialog asking if you want to save
|
||||
var confirmTitle = gFilePickerBundle.getString("confirmTitle");
|
||||
var message =
|
||||
gFilePickerBundle.getFormattedString("confirmFileReplacing",
|
||||
[file.path]);
|
||||
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
var rv = promptService.confirm(window, title, message);
|
||||
if (rv) {
|
||||
ret = nsIFilePicker.returnReplace;
|
||||
retvals.directory = file.parent.path;
|
||||
} else {
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
var parent = file.parent;
|
||||
if (parent.exists() && parent.isDirectory() && parent.isWritable()) {
|
||||
retvals.directory = parent.path;
|
||||
} else {
|
||||
var oldParent = parent;
|
||||
while (!parent.exists()) {
|
||||
oldParent = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
errorTitle =
|
||||
gFilePickerBundle.getFormattedString("errorSavingFileTitle",
|
||||
[file.path]);
|
||||
if (parent.isFile()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentIsFileMessage",
|
||||
[parent.path, file.path]);
|
||||
} else {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentDoesntExistMessage",
|
||||
[oldParent.path, file.path]);
|
||||
}
|
||||
if (!parent.isWritable()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveWithoutPermissionMessage_dir", [parent.path]);
|
||||
}
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
promptService.alert(window, errorTitle, errorMessage);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
}
|
||||
}
|
||||
} else if (isDir) {
|
||||
if (!sfile.equals(file)) {
|
||||
gotoDirectory(file);
|
||||
}
|
||||
textInput.value = "";
|
||||
doEnabling();
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
} else {
|
||||
var parent = file.parent;
|
||||
if (parent.exists() && parent.isDirectory() && parent.isWritable()) {
|
||||
ret = nsIFilePicker.returnOK;
|
||||
retvals.directory = parent.path;
|
||||
} else {
|
||||
var oldParent = parent;
|
||||
while (!parent.exists()) {
|
||||
oldParent = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
errorTitle =
|
||||
gFilePickerBundle.getFormattedString("errorSavingFileTitle",
|
||||
[file.path]);
|
||||
if (parent.isFile()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentIsFileMessage",
|
||||
[parent.path, file.path]);
|
||||
} else {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveParentDoesntExistMessage",
|
||||
[oldParent.path, file.path]);
|
||||
}
|
||||
if (!parent.isWritable()) {
|
||||
errorMessage =
|
||||
gFilePickerBundle.getFormattedString("saveWithoutPermissionMessage_dir", [parent.path]);
|
||||
}
|
||||
promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
|
||||
promptService.alert(window, errorTitle, errorMessage);
|
||||
ret = nsIFilePicker.returnCancel;
|
||||
break;
|
||||
case nsIFilePicker.modeGetFolder:
|
||||
if (isDir) {
|
||||
retvals.directory = file.parent.path;
|
||||
} else { // if nothing selected, the current directory will be fine
|
||||
retvals.directory = sfile.path;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case nsIFilePicker.modeGetFolder:
|
||||
if (isDir) {
|
||||
retvals.directory = file.parent.path;
|
||||
} else { // if nothing selected, the current directory will be fine
|
||||
retvals.directory = sfile.path;
|
||||
}
|
||||
ret = nsIFilePicker.returnOK;
|
||||
break;
|
||||
}
|
||||
|
||||
retvals.file = file;
|
||||
|
||||
gFilesEnumerator.mFile = file;
|
||||
gFilesEnumerator.mHasMore = true;
|
||||
gFilesEnumerator.mFiles = fileList;
|
||||
|
||||
retvals.files = gFilesEnumerator;
|
||||
retvals.buttonStatus = ret;
|
||||
@ -375,17 +379,18 @@ function selectOnOK()
|
||||
}
|
||||
|
||||
var gFilesEnumerator = {
|
||||
mHasMore: false,
|
||||
mFile: null,
|
||||
mFiles: null,
|
||||
mIndex: 0,
|
||||
|
||||
hasMoreElements: function()
|
||||
{
|
||||
return this.mHasMore;
|
||||
return (this.mIndex < this.mFiles.length);
|
||||
},
|
||||
getNext: function()
|
||||
{
|
||||
this.mHasMore = false;
|
||||
return this.mFile;
|
||||
if (this.mIndex >= this.mFiles.length)
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
return this.mFiles[this.mIndex++];
|
||||
}
|
||||
};
|
||||
|
||||
@ -410,10 +415,11 @@ function onDblClick(e) {
|
||||
}
|
||||
|
||||
function openSelectedFile() {
|
||||
var file = treeView.getSelectedFile();
|
||||
if (!file)
|
||||
var fileList = treeView.selectedFiles;
|
||||
if (fileList.length == 0)
|
||||
return;
|
||||
|
||||
var file = fileList.queryElementAt(0, nsIFile);
|
||||
if (file.isDirectory())
|
||||
gotoDirectory(file);
|
||||
else if (file.isFile())
|
||||
@ -474,8 +480,9 @@ function onKeypress(e) {
|
||||
if (e.keyCode == 8) /* backspace */
|
||||
goUp();
|
||||
else if (e.keyCode == 13) { /* enter */
|
||||
var file = treeView.getSelectedFile();
|
||||
if (file) {
|
||||
var fileList = treeView.selectedFiles;
|
||||
if (fileList.length > 0) {
|
||||
var file = fileList.queryElementAt(0, nsIFile);
|
||||
if (file.isDirectory()) {
|
||||
gotoDirectory(file);
|
||||
e.preventDefault();
|
||||
@ -494,7 +501,7 @@ function doEnabling() {
|
||||
|
||||
function onTreeFocus(event) {
|
||||
// Reset the button label and enabled/disabled state.
|
||||
onFileSelected(treeView.getSelectedFile());
|
||||
onFileSelected(treeView.selectedFiles);
|
||||
}
|
||||
|
||||
function getOKAction(file) {
|
||||
@ -524,24 +531,66 @@ function getOKAction(file) {
|
||||
}
|
||||
|
||||
function onSelect(event) {
|
||||
onFileSelected(treeView.getSelectedFile());
|
||||
onFileSelected(treeView.selectedFiles);
|
||||
}
|
||||
|
||||
function onFileSelected(file) {
|
||||
if (file) {
|
||||
var path = file.leafName;
|
||||
|
||||
if (path) {
|
||||
if ((filePickerMode == nsIFilePicker.modeGetFolder) || !file.isDirectory())
|
||||
textInput.value = path;
|
||||
|
||||
var buttonLabel = getOKAction(file);
|
||||
okButton.setAttribute("label", buttonLabel);
|
||||
okButton.disabled = false;
|
||||
return;
|
||||
function onFileSelected(/* nsIArray */ selectedFileList) {
|
||||
var validFileSelected = false;
|
||||
var invalidSelection = false;
|
||||
var file;
|
||||
var fileCount = selectedFileList.length;
|
||||
|
||||
for (var index = 0; index < fileCount; ++index) {
|
||||
file = selectedFileList.queryElementAt(index, nsIFile);
|
||||
if (file) {
|
||||
var path = file.leafName;
|
||||
|
||||
if (path) {
|
||||
var isDir = file.isDirectory();
|
||||
if ((filePickerMode == nsIFilePicker.modeGetFolder) || !isDir) {
|
||||
if (!validFileSelected)
|
||||
textInput.value = "";
|
||||
addToTextFieldValue(path);
|
||||
}
|
||||
|
||||
if (isDir && fileCount > 1) {
|
||||
// The user has selected multiple items, and one of them is
|
||||
// a directory. This is not a valid state, so we'll disable
|
||||
// the ok button.
|
||||
invalidSelection = true;
|
||||
}
|
||||
|
||||
validFileSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
okButton.disabled = (textInput.value == "");
|
||||
|
||||
if (validFileSelected) {
|
||||
var buttonLabel = getOKAction(file);
|
||||
okButton.setAttribute("label", buttonLabel);
|
||||
okButton.disabled = invalidSelection;
|
||||
} else
|
||||
okButton.disabled = (textInput.value == "");
|
||||
}
|
||||
|
||||
function addToTextFieldValue(path)
|
||||
{
|
||||
var newValue = "";
|
||||
|
||||
if (textInput.value == "")
|
||||
newValue = path.replace(/\"/g, "\\\"");
|
||||
else {
|
||||
// Quote the existing text if needed,
|
||||
// then append the new filename (quoted and escaped)
|
||||
if (textInput.value[0] != '"')
|
||||
newValue = '"' + textInput.value.replace(/\"/g, "\\\"") + '"';
|
||||
else
|
||||
newValue = textInput.value;
|
||||
|
||||
newValue = newValue + ' "' + path.replace(/\"/g, "\\\"") + '"';
|
||||
}
|
||||
|
||||
textInput.value = newValue;
|
||||
}
|
||||
|
||||
function onTextFieldFocus() {
|
||||
@ -625,6 +674,7 @@ function newDir() {
|
||||
return false;
|
||||
}
|
||||
|
||||
file = file[0].QueryInterface(nsIFile);
|
||||
if (file.exists()) {
|
||||
showErrorDialog("errorNewDirDoesExistTitle",
|
||||
"errorNewDirDoesExistMessage",
|
||||
@ -654,7 +704,7 @@ function newDir() {
|
||||
}
|
||||
|
||||
try {
|
||||
file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
file.create(nsIFile.DIRECTORY_TYPE, 0755);
|
||||
} catch (e) {
|
||||
showErrorDialog("errorCreateNewDirTitle",
|
||||
"errorCreateNewDirMessage",
|
||||
@ -700,13 +750,76 @@ function toggleShowHidden(event) {
|
||||
// uses "/" as the directory seperator, "~" as a shortcut
|
||||
// for the home directory (but only when seen at the start
|
||||
// of a path), and ".." to denote the parent directory.
|
||||
// returns the path or false if an error occurred.
|
||||
// returns an array of the files listed,
|
||||
// or false if an error occurred.
|
||||
function processPath(path)
|
||||
{
|
||||
var file;
|
||||
if (path[0] == '~')
|
||||
path = homeDir.path + path.substring(1);
|
||||
var fileArray = new Array();
|
||||
var strLength = path.length;
|
||||
|
||||
if (path[0] == '"' && filePickerMode == nsIFilePicker.modeOpenMultiple &&
|
||||
strLength > 1) {
|
||||
// we have a quoted list of filenames, separated by spaces.
|
||||
// iterate the list and process each file.
|
||||
|
||||
var curFileStart = 1;
|
||||
|
||||
while (1) {
|
||||
var nextQuote;
|
||||
|
||||
// Look for an unescaped quote
|
||||
var quoteSearchStart = curFileStart + 1;
|
||||
do {
|
||||
nextQuote = path.indexOf('"', quoteSearchStart);
|
||||
quoteSearchStart = nextQuote + 1;
|
||||
} while (nextQuote != -1 && path[nextQuote - 1] == '\\');
|
||||
|
||||
if (nextQuote == -1) {
|
||||
// we have a filename with no trailing quote.
|
||||
// just assume that the filename ends at the end of the string.
|
||||
|
||||
if (!processPathEntry(path.substring(curFileStart), fileArray))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!processPathEntry(path.substring(curFileStart, nextQuote), fileArray))
|
||||
return false;
|
||||
|
||||
curFileStart = path.indexOf('"', nextQuote + 1);
|
||||
if (curFileStart == -1) {
|
||||
// no more quotes, but if we're not at the end of the string,
|
||||
// go ahead and process the remaining text.
|
||||
|
||||
if (nextQuote < strLength - 1)
|
||||
if (!processPathEntry(path.substring(nextQuote + 1), fileArray))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
++curFileStart;
|
||||
}
|
||||
} else {
|
||||
// If we didn't start with a quote, assume we just have a single file.
|
||||
if (!processPathEntry(path, fileArray))
|
||||
return false;
|
||||
}
|
||||
|
||||
return fileArray;
|
||||
}
|
||||
|
||||
function processPathEntry(path, fileArray)
|
||||
{
|
||||
var filePath;
|
||||
var file;
|
||||
|
||||
if (path[0] == '~')
|
||||
filePath = homeDir.path + path.substring(1);
|
||||
else
|
||||
filePath = path;
|
||||
|
||||
// Unescape quotes
|
||||
filePath = filePath.replace(/\\\"/g, "\"");
|
||||
|
||||
try{
|
||||
file = sfile.clone().QueryInterface(nsILocalFile);
|
||||
} catch(e) {
|
||||
@ -714,15 +827,15 @@ function processPath(path)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (path[0] == '/') /* an absolute path was entered */
|
||||
file.initWithPath(path);
|
||||
else if ((path.indexOf("/../") > 0) ||
|
||||
(path.substr(-3) == "/..") ||
|
||||
(path.substr(0,3) == "../") ||
|
||||
(path == "..")) {
|
||||
if (filePath[0] == '/') /* an absolute path was entered */
|
||||
file.initWithPath(filePath);
|
||||
else if ((filePath.indexOf("/../") > 0) ||
|
||||
(filePath.substr(-3) == "/..") ||
|
||||
(filePath.substr(0,3) == "../") ||
|
||||
(filePath == "..")) {
|
||||
/* appendRelativePath doesn't allow .. */
|
||||
try{
|
||||
file.initWithPath(file.path + "/" + path);
|
||||
file.initWithPath(file.path + "/" + filePath);
|
||||
} catch (e) {
|
||||
dump("Couldn't init path\n"+e);
|
||||
return false;
|
||||
@ -730,11 +843,13 @@ function processPath(path)
|
||||
}
|
||||
else {
|
||||
try {
|
||||
file.appendRelativePath(path);
|
||||
file.appendRelativePath(filePath);
|
||||
} catch (e) {
|
||||
dump("Couldn't append path\n"+e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return file;
|
||||
|
||||
fileArray[fileArray.length] = file;
|
||||
return true;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ nsFilePicker.prototype = {
|
||||
|
||||
/* readonly attribute nsILocalFile file; */
|
||||
set file(a) { throw "readonly property"; },
|
||||
get file() { return this.mFile; },
|
||||
get file() { return this.mFilesEnumerator.mFiles[0]; },
|
||||
|
||||
/* readonly attribute nsISimpleEnumerator files; */
|
||||
set files(a) { throw "readonly property"; },
|
||||
@ -94,10 +94,10 @@ nsFilePicker.prototype = {
|
||||
/* readonly attribute nsIFileURL fileURL; */
|
||||
set fileURL(a) { throw "readonly property"; },
|
||||
get fileURL() {
|
||||
if (this.mFile) {
|
||||
if (this.mFilesEnumerator) {
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var url = ioService.newFileURI(this.mFile);
|
||||
var url = ioService.newFileURI(this.file);
|
||||
return url;
|
||||
}
|
||||
return null;
|
||||
@ -116,7 +116,6 @@ nsFilePicker.prototype = {
|
||||
get filterIndex() { return this.mFilterIndex; },
|
||||
|
||||
/* members */
|
||||
mFile: undefined,
|
||||
mFilesEnumerator: undefined,
|
||||
mParentWindow: null,
|
||||
|
||||
@ -216,9 +215,7 @@ nsFilePicker.prototype = {
|
||||
"",
|
||||
"chrome,modal,titlebar,resizable=yes,dependent=yes",
|
||||
o);
|
||||
if (parentWin)
|
||||
parentWin.blurSuppression = false;
|
||||
this.mFile = o.retvals.file;
|
||||
|
||||
this.mFilterIndex = o.retvals.filterIndex;
|
||||
this.mFilesEnumerator = o.retvals.files;
|
||||
lastDirectory = o.retvals.directory;
|
||||
|
@ -85,7 +85,7 @@ nsFilePicker.prototype = {
|
||||
|
||||
/* readonly attribute nsILocalFile file; */
|
||||
set file(a) { throw "readonly property"; },
|
||||
get file() { return this.mFile; },
|
||||
get file() { return this.mFilesEnumerator.mFiles[0]; },
|
||||
|
||||
/* readonly attribute nsISimpleEnumerator files; */
|
||||
set files(a) { throw "readonly property"; },
|
||||
@ -94,10 +94,10 @@ nsFilePicker.prototype = {
|
||||
/* readonly attribute nsIFileURL fileURL; */
|
||||
set fileURL(a) { throw "readonly property"; },
|
||||
get fileURL() {
|
||||
if (this.mFile) {
|
||||
if (this.mFilesEnumerator) {
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var url = ioService.newFileURI(this.mFile);
|
||||
var url = ioService.newFileURI(this.file);
|
||||
return url;
|
||||
}
|
||||
return null;
|
||||
@ -116,7 +116,6 @@ nsFilePicker.prototype = {
|
||||
get filterIndex() { return this.mFilterIndex; },
|
||||
|
||||
/* members */
|
||||
mFile: undefined,
|
||||
mFilesEnumerator: undefined,
|
||||
mParentWindow: null,
|
||||
|
||||
@ -216,9 +215,7 @@ nsFilePicker.prototype = {
|
||||
"",
|
||||
"chrome,modal,titlebar,resizable=yes,dependent=yes",
|
||||
o);
|
||||
if (parentWin)
|
||||
parentWin.blurSuppression = false;
|
||||
this.mFile = o.retvals.file;
|
||||
|
||||
this.mFilterIndex = o.retvals.filterIndex;
|
||||
this.mFilesEnumerator = o.retvals.files;
|
||||
lastDirectory = o.retvals.directory;
|
||||
|
@ -52,6 +52,8 @@
|
||||
#include "nsDateTimeFormatCID.h"
|
||||
#include "nsQuickSort.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsArray.h"
|
||||
|
||||
#include "nsWildCard.h"
|
||||
|
||||
@ -340,26 +342,40 @@ nsFileView::SetFilter(const PRUnichar* aFilterString)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFileView::GetSelectedFile(nsIFile** aFile)
|
||||
nsFileView::GetSelectedFiles(nsIArray** aFiles)
|
||||
{
|
||||
*aFile = nsnull;
|
||||
*aFiles = nsnull;
|
||||
|
||||
PRInt32 currentIndex;
|
||||
mSelection->GetCurrentIndex(¤tIndex);
|
||||
PRInt32 numRanges;
|
||||
mSelection->GetRangeCount(&numRanges);
|
||||
|
||||
if (0 <= currentIndex) {
|
||||
PRUint32 dirCount;
|
||||
mDirList->Count(&dirCount);
|
||||
if (currentIndex < (PRInt32) dirCount)
|
||||
mDirList->QueryElementAt(currentIndex, NS_GET_IID(nsIFile),
|
||||
(void**)aFile);
|
||||
else {
|
||||
if (currentIndex < mTotalRows)
|
||||
mFilteredFiles->QueryElementAt(currentIndex - dirCount,
|
||||
NS_GET_IID(nsIFile), (void**)aFile);
|
||||
PRUint32 dirCount;
|
||||
mDirList->Count(&dirCount);
|
||||
|
||||
nsCOMArray<nsIFile> fileArray;
|
||||
|
||||
for (PRInt32 range = 0; range < numRanges; ++range) {
|
||||
PRInt32 rangeBegin, rangeEnd;
|
||||
mSelection->GetRangeAt(range, &rangeBegin, &rangeEnd);
|
||||
|
||||
for (PRInt32 itemIndex = rangeBegin; itemIndex <= rangeEnd; ++itemIndex) {
|
||||
nsCOMPtr<nsIFile> curFile;
|
||||
|
||||
if (itemIndex < (PRInt32) dirCount)
|
||||
curFile = do_QueryElementAt(mDirList, itemIndex);
|
||||
else {
|
||||
if (itemIndex < mTotalRows)
|
||||
curFile = do_QueryElementAt(mFilteredFiles, itemIndex - dirCount);
|
||||
}
|
||||
|
||||
if (curFile)
|
||||
fileArray.AppendObject(curFile);
|
||||
}
|
||||
}
|
||||
|
||||
nsIMutableArray* outArray;
|
||||
NS_NewArray(&outArray, fileArray); // addrefs, return the reference
|
||||
*aFiles = outArray;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user