зеркало из https://github.com/mozilla/gecko-dev.git
Relanding Bug 675902 - New Downloads view for Places Library. r=mak. Test fix contributed by Mike Conley (r=me). The new view is still disabled.
This commit is contained in:
Родитель
1da79b06c2
Коммит
26944959a9
|
@ -1187,12 +1187,6 @@ function DownloadsViewItemController(aElement) {
|
|||
}
|
||||
|
||||
DownloadsViewItemController.prototype = {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Constants
|
||||
|
||||
get kPrefBdmAlertOnExeOpen() "browser.download.manager.alertOnEXEOpen",
|
||||
get kPrefBdmScanWhenDone() "browser.download.manager.scanWhenDone",
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Command dispatching
|
||||
|
||||
|
@ -1244,87 +1238,17 @@ DownloadsViewItemController.prototype = {
|
|||
commands: {
|
||||
cmd_delete: function DVIC_cmd_delete()
|
||||
{
|
||||
this.dataItem.getDownload(function (aDownload) {
|
||||
if (this.dataItem.inProgress) {
|
||||
aDownload.cancel();
|
||||
this._ensureLocalFileRemoved();
|
||||
}
|
||||
aDownload.remove();
|
||||
}.bind(this));
|
||||
this.dataItem.remove();
|
||||
},
|
||||
|
||||
downloadsCmd_cancel: function DVIC_downloadsCmd_cancel()
|
||||
{
|
||||
if (this.dataItem.inProgress) {
|
||||
this.dataItem.getDownload(function (aDownload) {
|
||||
aDownload.cancel();
|
||||
this._ensureLocalFileRemoved();
|
||||
}.bind(this));
|
||||
}
|
||||
this.dataItem.cancel();
|
||||
},
|
||||
|
||||
downloadsCmd_open: function DVIC_downloadsCmd_open()
|
||||
{
|
||||
// Confirm opening executable files if required.
|
||||
let localFile = this.dataItem.localFile;
|
||||
if (localFile.isExecutable()) {
|
||||
let showAlert = true;
|
||||
try {
|
||||
showAlert = Services.prefs.getBoolPref(this.kPrefBdmAlertOnExeOpen);
|
||||
} catch (ex) { }
|
||||
|
||||
// On Vista and above, we rely on native security prompting for
|
||||
// downloaded content unless it's disabled.
|
||||
if (DownloadsCommon.isWinVistaOrHigher) {
|
||||
try {
|
||||
if (Services.prefs.getBoolPref(this.kPrefBdmScanWhenDone)) {
|
||||
showAlert = false;
|
||||
}
|
||||
} catch (ex) { }
|
||||
}
|
||||
|
||||
if (showAlert) {
|
||||
let name = this.dataItem.target;
|
||||
let message =
|
||||
DownloadsCommon.strings.fileExecutableSecurityWarning(name, name);
|
||||
let title =
|
||||
DownloadsCommon.strings.fileExecutableSecurityWarningTitle;
|
||||
let dontAsk =
|
||||
DownloadsCommon.strings.fileExecutableSecurityWarningDontAsk;
|
||||
|
||||
let checkbox = { value: false };
|
||||
let open = Services.prompt.confirmCheck(window, title, message,
|
||||
dontAsk, checkbox);
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref(this.kPrefBdmAlertOnExeOpen,
|
||||
!checkbox.value);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually open the file.
|
||||
this.dataItem.getDownload(function (aDownload) {
|
||||
try {
|
||||
let launched = false;
|
||||
try {
|
||||
let mimeInfo = aDownload.MIMEInfo;
|
||||
if (mimeInfo.preferredAction == mimeInfo.useHelperApp) {
|
||||
mimeInfo.launchWithFile(localFile);
|
||||
launched = true;
|
||||
}
|
||||
} catch (ex) { }
|
||||
if (!launched) {
|
||||
localFile.launch();
|
||||
}
|
||||
} catch (ex) {
|
||||
// If launch fails, try sending it through the system's external "file:"
|
||||
// URL handler.
|
||||
this._openExternal(localFile);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this.dataItem.openLocalFile();
|
||||
// We explicitly close the panel here to give the user the feedback that
|
||||
// their click has been received, and we're handling the action.
|
||||
// Otherwise, we'd have to wait for the file-type handler to execute
|
||||
|
@ -1335,26 +1259,7 @@ DownloadsViewItemController.prototype = {
|
|||
|
||||
downloadsCmd_show: function DVIC_downloadsCmd_show()
|
||||
{
|
||||
let localFile = this.dataItem.localFile;
|
||||
|
||||
try {
|
||||
// Show the directory containing the file and select the file.
|
||||
localFile.reveal();
|
||||
} catch (ex) {
|
||||
// If reveal fails for some reason (e.g., it's not implemented on unix
|
||||
// or the file doesn't exist), try using the parent if we have it.
|
||||
let parent = localFile.parent.QueryInterface(Ci.nsILocalFile);
|
||||
if (parent) {
|
||||
try {
|
||||
// Open the parent directory to show where the file should be.
|
||||
parent.launch();
|
||||
} catch (ex) {
|
||||
// If launch also fails (probably because it's not implemented), let
|
||||
// the OS handler try to open the parent.
|
||||
this._openExternal(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.dataItem.showLocalFile();
|
||||
|
||||
// We explicitly close the panel here to give the user the feedback that
|
||||
// their click has been received, and we're handling the action.
|
||||
|
@ -1366,20 +1271,12 @@ DownloadsViewItemController.prototype = {
|
|||
|
||||
downloadsCmd_pauseResume: function DVIC_downloadsCmd_pauseResume()
|
||||
{
|
||||
this.dataItem.getDownload(function (aDownload) {
|
||||
if (this.dataItem.paused) {
|
||||
aDownload.resume();
|
||||
} else {
|
||||
aDownload.pause();
|
||||
}
|
||||
}.bind(this));
|
||||
this.dataItem.togglePauseResume();
|
||||
},
|
||||
|
||||
downloadsCmd_retry: function DVIC_downloadsCmd_retry()
|
||||
{
|
||||
this.dataItem.getDownload(function (aDownload) {
|
||||
aDownload.retry();
|
||||
});
|
||||
this.dataItem.retry();
|
||||
},
|
||||
|
||||
downloadsCmd_openReferrer: function DVIC_downloadsCmd_openReferrer()
|
||||
|
@ -1418,31 +1315,6 @@ DownloadsViewItemController.prototype = {
|
|||
// Invoke the command.
|
||||
this.doCommand(defaultCommand);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Support function to open the specified nsIFile.
|
||||
*/
|
||||
_openExternal: function DVIC_openExternal(aFile)
|
||||
{
|
||||
let protocolSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"]
|
||||
.getService(Ci.nsIExternalProtocolService);
|
||||
protocolSvc.loadUrl(makeFileURI(aFile));
|
||||
},
|
||||
|
||||
/**
|
||||
* Support function that deletes the local file for a download. This is
|
||||
* used in cases where the Download Manager service doesn't delete the file
|
||||
* from disk when cancelling. See bug 732924.
|
||||
*/
|
||||
_ensureLocalFileRemoved: function DVIC_ensureLocalFileRemoved()
|
||||
{
|
||||
try {
|
||||
let localFile = this.dataItem.localFile;
|
||||
if (localFile.exists()) {
|
||||
localFile.remove(false);
|
||||
}
|
||||
} catch (ex) { }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@ const nsIDM = Ci.nsIDownloadManager;
|
|||
const kDownloadsStringBundleUrl =
|
||||
"chrome://browser/locale/downloads/downloads.properties";
|
||||
|
||||
const kPrefBdmScanWhenDone = "browser.download.manager.scanWhenDone";
|
||||
const kPrefBdmAlertOnExeOpen = "browser.download.manager.alertOnEXEOpen";
|
||||
|
||||
const kDownloadsStringsRequiringFormatting = {
|
||||
sizeWithUnits: true,
|
||||
shortTimeLeftSeconds: true,
|
||||
|
@ -396,6 +399,117 @@ this.DownloadsCommon = {
|
|||
// never adding to the time left. Ensure that we never fall below one
|
||||
// second left until all downloads are actually finished.
|
||||
return aLastSeconds = Math.max(aSeconds, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens a downloaded file.
|
||||
* If you've a dataItem, you should call dataItem.openLocalFile.
|
||||
* @param aFile
|
||||
* the downloaded file to be opened.
|
||||
* @param aMimeInfo
|
||||
* the mime type info object. May be null.
|
||||
* @param aOwnerWindow
|
||||
* the window with which this action is associated.
|
||||
*/
|
||||
openDownloadedFile: function DC_openDownloadedFile(aFile, aMimeInfo, aOwnerWindow) {
|
||||
if (!(aFile instanceof Ci.nsIFile))
|
||||
throw new Error("aFile must be a nsIFile object");
|
||||
if (aMimeInfo && !(aMimeInfo instanceof Ci.nsIMIMEInfo))
|
||||
throw new Error("Invalid value passed for aMimeInfo");
|
||||
if (!(aOwnerWindow instanceof Ci.nsIDOMWindow))
|
||||
throw new Error("aOwnerWindow must be a dom-window object");
|
||||
|
||||
// Confirm opening executable files if required.
|
||||
if (aFile.isExecutable()) {
|
||||
let showAlert = true;
|
||||
try {
|
||||
showAlert = Services.prefs.getBoolPref(kPrefBdmAlertOnExeOpen);
|
||||
} catch (ex) { }
|
||||
|
||||
// On Vista and above, we rely on native security prompting for
|
||||
// downloaded content unless it's disabled.
|
||||
if (DownloadsCommon.isWinVistaOrHigher) {
|
||||
try {
|
||||
if (Services.prefs.getBoolPref(kPrefBdmScanWhenDone)) {
|
||||
showAlert = false;
|
||||
}
|
||||
} catch (ex) { }
|
||||
}
|
||||
|
||||
if (showAlert) {
|
||||
let name = this.dataItem.target;
|
||||
let message =
|
||||
DownloadsCommon.strings.fileExecutableSecurityWarning(name, name);
|
||||
let title =
|
||||
DownloadsCommon.strings.fileExecutableSecurityWarningTitle;
|
||||
let dontAsk =
|
||||
DownloadsCommon.strings.fileExecutableSecurityWarningDontAsk;
|
||||
|
||||
let checkbox = { value: false };
|
||||
let open = Services.prompt.confirmCheck(aOwnerWindow, title, message,
|
||||
dontAsk, checkbox);
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref(kPrefBdmAlertOnExeOpen,
|
||||
!checkbox.value);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually open the file.
|
||||
try {
|
||||
if (aMimeInfo && aMimeInfo.preferredAction == aMimeInfo.useHelperApp) {
|
||||
aMimeInfo.launchWithFile(aFile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(ex) { }
|
||||
|
||||
// If either we don't have the mime info, or the preferred action failed,
|
||||
// attempt to launch the file directly.
|
||||
try {
|
||||
aFile.launch();
|
||||
}
|
||||
catch(ex) {
|
||||
// If launch fails, try sending it through the system's external "file:"
|
||||
// URL handler.
|
||||
Cc["@mozilla.org/uriloader/external-protocol-service;1"]
|
||||
.getService(Ci.nsIExternalProtocolService)
|
||||
.loadUrl(NetUtil.newURI(aFile));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a donwloaded file in the system file manager.
|
||||
* If you have a dataItem, use dataItem.showLocalFile.
|
||||
*
|
||||
* @param aFile
|
||||
* a downloaded file.
|
||||
*/
|
||||
showDownloadedFile: function DC_showDownloadedFile(aFile) {
|
||||
if (!(aFile instanceof Ci.nsIFile))
|
||||
throw new Error("aFile must be a nsIFile object");
|
||||
try {
|
||||
// Show the directory containing the file and select the file.
|
||||
aFile.reveal();
|
||||
} catch (ex) {
|
||||
// If reveal fails for some reason (e.g., it's not implemented on unix
|
||||
// or the file doesn't exist), try using the parent if we have it.
|
||||
let parent = aFile.parent;
|
||||
if (parent) {
|
||||
try {
|
||||
// Open the parent directory to show where the file should be.
|
||||
parent.launch();
|
||||
} catch (ex) {
|
||||
// If launch also fails (probably because it's not implemented), let
|
||||
// the OS handler try to open the parent.
|
||||
Cc["@mozilla.org/uriloader/external-protocol-service;1"]
|
||||
.getService(Ci.nsIExternalProtocolService)
|
||||
.loadUrl(NetUtil.newURI(parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1212,6 +1326,101 @@ DownloadsDataItem.prototype = {
|
|||
// file, though this may throw an exception if the path is invalid.
|
||||
return new DownloadsLocalFileCtor(aFilename);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the target file for this download.
|
||||
*
|
||||
* @param aOwnerWindow
|
||||
* The window with which the required action is associated.
|
||||
* @throws if the file cannot be opened.
|
||||
*/
|
||||
openLocalFile: function DDI_openLocalFile(aOwnerWindow) {
|
||||
this.getDownload(function(aDownload) {
|
||||
DownloadsCommon.openDownloadedFile(this.localFile,
|
||||
aDownload.MIMEInfo,
|
||||
aOwnerWindow);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the downloaded file in the system file manager.
|
||||
*/
|
||||
showLocalFile: function DDI_showLocalFile() {
|
||||
DownloadsCommon.showDownloadedFile(this.localFile);
|
||||
},
|
||||
|
||||
/**
|
||||
* Resumes the download if paused, pauses it if active.
|
||||
* @throws if the download is not resumable or if has already done.
|
||||
*/
|
||||
togglePauseResume: function DDI_togglePauseResume() {
|
||||
if (!this.inProgress || !this.resumable)
|
||||
throw new Error("The given download cannot be paused or resumed");
|
||||
|
||||
this.getDownload(function(aDownload) {
|
||||
if (this.inProgress) {
|
||||
if (this.paused)
|
||||
aDownload.resume();
|
||||
else
|
||||
aDownload.pause();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Attempts to retry the download.
|
||||
* @throws if we cannot.
|
||||
*/
|
||||
retry: function DDI_retry() {
|
||||
if (!this.canRetry)
|
||||
throw new Error("Cannot rerty this download");
|
||||
|
||||
this.getDownload(function(aDownload) {
|
||||
aDownload.retry();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Support function that deletes the local file for a download. This is
|
||||
* used in cases where the Download Manager service doesn't delete the file
|
||||
* from disk when cancelling. See bug 732924.
|
||||
*/
|
||||
_ensureLocalFileRemoved: function DDI__ensureLocalFileRemoved()
|
||||
{
|
||||
try {
|
||||
let localFile = this.localFile;
|
||||
if (localFile.exists()) {
|
||||
localFile.remove(false);
|
||||
}
|
||||
} catch (ex) { }
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancels the download.
|
||||
* @throws if the download is already done.
|
||||
*/
|
||||
cancel: function() {
|
||||
if (!this.inProgress)
|
||||
throw new Error("Cannot cancel this download");
|
||||
|
||||
this.getDownload(function (aDownload) {
|
||||
aDownload.cancel();
|
||||
this._ensureLocalFileRemoved();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the download.
|
||||
*/
|
||||
remove: function DDI_remove() {
|
||||
this.getDownload(function (aDownload) {
|
||||
if (this.inProgress) {
|
||||
aDownload.cancel();
|
||||
this._ensureLocalFileRemoved();
|
||||
}
|
||||
aDownload.remove();
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ PlacesViewBase.prototype = {
|
|||
_viewElt: null,
|
||||
get viewElt() this._viewElt,
|
||||
|
||||
get associatedElement() this._viewElt,
|
||||
|
||||
get controllers() this._viewElt.controllers,
|
||||
|
||||
// The xul element that represents the root container.
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
richlistitem.download button {
|
||||
/* These buttons should never get focus, as that would "disable"
|
||||
the downloads view controller (it's only used when the richlistbox
|
||||
is focused). */
|
||||
-moz-user-focus: none;
|
||||
}
|
||||
|
||||
/*** Visibility of controls inside download items ***/
|
||||
|
||||
.download-state:-moz-any( [state="6"], /* Blocked (parental) */
|
||||
[state="8"], /* Blocked (dirty) */
|
||||
[state="9"]) /* Blocked (policy) */
|
||||
.downloadTypeIcon:not(.blockedIcon),
|
||||
|
||||
.download-state:not(:-moz-any([state="6"], /* Blocked (parental) */
|
||||
[state="8"], /* Blocked (dirty) */
|
||||
[state="9"]) /* Blocked (policy) */)
|
||||
.downloadTypeIcon.blockedIcon,
|
||||
|
||||
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
|
||||
[state="5"], /* Starting (queued) */
|
||||
[state="0"], /* Downloading */
|
||||
[state="4"], /* Paused */
|
||||
[state="7"]) /* Scanning */)
|
||||
.downloadProgress,
|
||||
|
||||
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
|
||||
[state="5"], /* Starting (queued) */
|
||||
[state="0"], /* Downloading */
|
||||
[state="4"]) /* Paused */)
|
||||
.downloadCancel,
|
||||
|
||||
.download-state:not(:-moz-any([state="2"], /* Failed */
|
||||
[state="3"]) /* Canceled */)
|
||||
.downloadRetry,
|
||||
|
||||
.download-state:not( [state="1"] /* Finished */)
|
||||
.downloadShow
|
||||
{
|
||||
visibility: hidden;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- -->
|
||||
<!-- vim: set ts=2 et sw=2 tw=80: -->
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
|
||||
|
||||
<bindings id="downloadBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="download"
|
||||
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
|
||||
<resources>
|
||||
<stylesheet src="chrome://browser/content/places/download.css"/>
|
||||
</resources>
|
||||
|
||||
<content orient="horizontal" align="center">
|
||||
<xul:image class="downloadTypeIcon"
|
||||
validate="always"
|
||||
xbl:inherits="src=image"/>
|
||||
<xul:image class="downloadTypeIcon blockedIcon"/>
|
||||
<xul:vbox pack="center" flex="1">
|
||||
<xul:description class="downloadTarget"
|
||||
crop="center"
|
||||
xbl:inherits="value=displayName,tooltiptext=displayName"/>
|
||||
<xul:progressmeter anonid="progressmeter"
|
||||
class="downloadProgress"
|
||||
min="0"
|
||||
max="100"
|
||||
xbl:inherits="mode=progressmode,value=progress"/>
|
||||
<xul:description class="downloadDetails"
|
||||
style="width: &downloadDetails.width;"
|
||||
crop="end"
|
||||
xbl:inherits="value=status,tooltiptext=statusTip"/>
|
||||
</xul:vbox>
|
||||
<xul:stack>
|
||||
<xul:button class="downloadButton downloadCancel"
|
||||
command="downloadsCmd_cancel"
|
||||
tooltiptext="&cmd.cancel.label;"/>
|
||||
<xul:button class="downloadButton downloadRetry"
|
||||
command="downloadsCmd_retry"
|
||||
tooltiptext="&cmd.retry.label;"/>
|
||||
<xul:button class="downloadButton downloadShow"
|
||||
command="downloadsCmd_show"
|
||||
tooltiptext="&cmd.show.label;"/>
|
||||
</xul:stack>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -14,3 +14,33 @@ tree[type="places"] {
|
|||
menupopup[placespopup="true"] {
|
||||
-moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-base");
|
||||
}
|
||||
|
||||
richlistitem.download {
|
||||
-moz-binding: url('chrome://browser/content/places/download.xml#download');
|
||||
}
|
||||
|
||||
.download-state:not( [state="0"] /* Downloading */)
|
||||
.downloadPauseMenuItem,
|
||||
.download-state:not( [state="4"] /* Paused */)
|
||||
.downloadResumeMenuItem,
|
||||
.download-state:not(:-moz-any([state="2"], /* Failed */
|
||||
[state="4"]) /* Paused */)
|
||||
.downloadCancelMenuItem,
|
||||
.download-state:not(:-moz-any([state="1"], /* Finished */
|
||||
[state="2"], /* Failed */
|
||||
[state="3"], /* Canceled */
|
||||
[state="6"], /* Blocked (parental) */
|
||||
[state="8"], /* Blocked (dirty) */
|
||||
[state="9"]) /* Blocked (policy) */)
|
||||
.downloadRemoveFromListMenuItem,
|
||||
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
|
||||
[state="5"], /* Starting (queued) */
|
||||
[state="0"], /* Downloading */
|
||||
[state="4"]) /* Paused */)
|
||||
.downloadShowMenuItem,
|
||||
|
||||
.download-state[state="7"] .downloadCommandsSeparator
|
||||
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,13 @@
|
|||
|
||||
Components.utils.import("resource:///modules/MigrationUtils.jsm");
|
||||
|
||||
const DOWNLOADS_QUERY = "place:transition=" +
|
||||
Components.interfaces.nsINavHistoryService.TRANSITION_DOWNLOAD +
|
||||
"&sort=" +
|
||||
Components.interfaces.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
|
||||
|
||||
var PlacesOrganizer = {
|
||||
_places: null,
|
||||
_content: null,
|
||||
|
||||
// IDs of fields from editBookmarkOverlay that should be hidden when infoBox
|
||||
// is minimal. IDs should be kept in sync with the IDs of the elements
|
||||
|
@ -32,8 +36,9 @@ var PlacesOrganizer = {
|
|||
},
|
||||
|
||||
init: function PO_init() {
|
||||
ContentArea.init();
|
||||
|
||||
this._places = document.getElementById("placesList");
|
||||
this._content = document.getElementById("placeContent");
|
||||
this._initFolderTree();
|
||||
|
||||
var leftPaneSelection = "AllBookmarks"; // default to all-bookmarks
|
||||
|
@ -45,12 +50,6 @@ var PlacesOrganizer = {
|
|||
this._backHistory.splice(0, this._backHistory.length);
|
||||
document.getElementById("OrganizerCommand:Back").setAttribute("disabled", true);
|
||||
|
||||
var view = this._content.treeBoxObject.view;
|
||||
if (view.rowCount > 0)
|
||||
view.selection.select(0);
|
||||
|
||||
this._content.focus();
|
||||
|
||||
// Set up the search UI.
|
||||
PlacesSearchBox.init();
|
||||
|
||||
|
@ -84,6 +83,13 @@ var PlacesOrganizer = {
|
|||
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|
||||
gPrivateBrowsingListener.init();
|
||||
#endif
|
||||
|
||||
// Select the first item in the content area view.
|
||||
let view = ContentArea.currentView;
|
||||
let root = view.result ? view.result.root : null;
|
||||
if (root && root.containerOpen && root.childCount >= 0)
|
||||
view.selectNode(root.getChild(0));
|
||||
ContentArea.focus();
|
||||
},
|
||||
|
||||
QueryInterface: function PO_QueryInterface(aIID) {
|
||||
|
@ -139,9 +145,9 @@ var PlacesOrganizer = {
|
|||
|
||||
if (!this._places.hasSelection) {
|
||||
// If no node was found for the given place: uri, just load it directly
|
||||
this._content.place = aLocation;
|
||||
ContentArea.currentPlace = aLocation;
|
||||
}
|
||||
this.onContentTreeSelect();
|
||||
this.updateDetailsPane();
|
||||
|
||||
// update navigation commands
|
||||
if (this._backHistory.length == 0)
|
||||
|
@ -201,8 +207,8 @@ var PlacesOrganizer = {
|
|||
// If either the place of the content tree in the right pane has changed or
|
||||
// the user cleared the search box, update the place, hide the search UI,
|
||||
// and update the back/forward buttons by setting location.
|
||||
if (this._content.place != placeURI || !resetSearchBox) {
|
||||
this._content.place = placeURI;
|
||||
if (ContentArea.currentPlace != placeURI || !resetSearchBox) {
|
||||
ContentArea.currentPlace = placeURI;
|
||||
this.location = node.uri;
|
||||
}
|
||||
|
||||
|
@ -221,8 +227,7 @@ var PlacesOrganizer = {
|
|||
|
||||
PlacesSearchBox.searchFilter.reset();
|
||||
this._setSearchScopeForNode(node);
|
||||
if (this._places.treeBoxObject.focused)
|
||||
this._fillDetailsPane([node]);
|
||||
this.updateDetailsPane();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -247,50 +252,39 @@ var PlacesOrganizer = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Handle clicks on the tree.
|
||||
* Handle clicks on the places list.
|
||||
* Single Left click, right click or modified click do not result in any
|
||||
* special action, since they're related to selection.
|
||||
* @param aEvent
|
||||
* The mouse event.
|
||||
*/
|
||||
onTreeClick: function PO_onTreeClick(aEvent) {
|
||||
onPlacesListClick: function PO_onPlacesListClick(aEvent) {
|
||||
// Only handle clicks on tree children.
|
||||
if (aEvent.target.localName != "treechildren")
|
||||
return;
|
||||
|
||||
var currentView = aEvent.currentTarget;
|
||||
var selectedNode = currentView.selectedNode;
|
||||
if (selectedNode) {
|
||||
var doubleClickOnFlatList = (aEvent.button == 0 && aEvent.detail == 2 &&
|
||||
aEvent.target.parentNode.flatList);
|
||||
var middleClick = (aEvent.button == 1 && aEvent.detail == 1);
|
||||
|
||||
if (PlacesUtils.nodeIsURI(selectedNode) &&
|
||||
(doubleClickOnFlatList || middleClick)) {
|
||||
// Open associated uri in the browser.
|
||||
PlacesOrganizer.openSelectedNode(aEvent);
|
||||
}
|
||||
else if (middleClick &&
|
||||
PlacesUtils.nodeIsContainer(selectedNode)) {
|
||||
let node = this._places.selectedNode;
|
||||
if (node) {
|
||||
let middleClick = aEvent.button == 1 && aEvent.detail == 1;
|
||||
if (middleClick && PlacesUtils.nodeIsContainer(node)) {
|
||||
// The command execution function will take care of seeing if the
|
||||
// selection is a folder or a different container type, and will
|
||||
// load its contents in tabs.
|
||||
PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent, currentView);
|
||||
PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent, this._places);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle focus changes on the trees.
|
||||
* When moving focus between panes we should update the details pane contents.
|
||||
* @param aEvent
|
||||
* The mouse event.
|
||||
* Handle focus changes on the places list and the current content view.
|
||||
*/
|
||||
onTreeFocus: function PO_onTreeFocus(aEvent) {
|
||||
var currentView = aEvent.currentTarget;
|
||||
var selectedNodes = currentView.selectedNode ? [currentView.selectedNode] :
|
||||
this._content.selectedNodes;
|
||||
updateDetailsPane: function PO_updateDetailsPane() {
|
||||
let view = PlacesUIUtils.getViewForNode(document.activeElement);
|
||||
if (view) {
|
||||
let selectedNodes = view.selectedNode ?
|
||||
[view.selectedNode] : view.selectedNodes;
|
||||
this._fillDetailsPane(selectedNodes);
|
||||
}
|
||||
},
|
||||
|
||||
openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer) {
|
||||
|
@ -300,17 +294,12 @@ var PlacesOrganizer = {
|
|||
this._places.selectPlaceURI(aContainer.uri);
|
||||
},
|
||||
|
||||
openSelectedNode: function PO_openSelectedNode(aEvent) {
|
||||
PlacesUIUtils.openNodeWithEvent(this._content.selectedNode, aEvent,
|
||||
this._content);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the options associated with the query currently loaded in the
|
||||
* main places pane.
|
||||
*/
|
||||
getCurrentOptions: function PO_getCurrentOptions() {
|
||||
return PlacesUtils.asQuery(this._content.result.root).queryOptions;
|
||||
return PlacesUtils.asQuery(ContentArea.currentView.result.root).queryOptions;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -318,7 +307,7 @@ var PlacesOrganizer = {
|
|||
* main places pane.
|
||||
*/
|
||||
getCurrentQueries: function PO_getCurrentQueries() {
|
||||
return PlacesUtils.asQuery(this._content.result.root).getQueries();
|
||||
return PlacesUtils.asQuery(ContentArea.currentView.result.root).getQueries();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -564,11 +553,6 @@ var PlacesOrganizer = {
|
|||
canvas.height = height;
|
||||
},
|
||||
|
||||
onContentTreeSelect: function PO_onContentTreeSelect() {
|
||||
if (this._content.treeBoxObject.focused)
|
||||
this._fillDetailsPane(this._content.selectedNodes);
|
||||
},
|
||||
|
||||
_fillDetailsPane: function PO__fillDetailsPane(aNodeList) {
|
||||
var infoBox = document.getElementById("infoBox");
|
||||
var detailsDeck = document.getElementById("detailsDeck");
|
||||
|
@ -671,10 +655,15 @@ var PlacesOrganizer = {
|
|||
else {
|
||||
detailsDeck.selectedIndex = 0;
|
||||
infoBox.hidden = true;
|
||||
var selectItemDesc = document.getElementById("selectItemDescription");
|
||||
var itemsCountLabel = document.getElementById("itemsCountText");
|
||||
var rowCount = this._content.treeBoxObject.view.rowCount;
|
||||
if (rowCount == 0) {
|
||||
let selectItemDesc = document.getElementById("selectItemDescription");
|
||||
let itemsCountLabel = document.getElementById("itemsCountText");
|
||||
let itemsCount = 0;
|
||||
if (ContentArea.currentView.result) {
|
||||
let rootNode = ContentArea.currentView.result.root;
|
||||
if (rootNode.containerOpen)
|
||||
itemsCount = rootNode.childCount;
|
||||
}
|
||||
if (itemsCount == 0) {
|
||||
selectItemDesc.hidden = true;
|
||||
itemsCountLabel.value = PlacesUIUtils.getString("detailsPane.noItems");
|
||||
}
|
||||
|
@ -682,7 +671,7 @@ var PlacesOrganizer = {
|
|||
selectItemDesc.hidden = false;
|
||||
itemsCountLabel.value =
|
||||
PlacesUIUtils.getPluralString("detailsPane.itemsCountLabel",
|
||||
rowCount, [rowCount]);
|
||||
itemsCount, [itemsCount]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -779,14 +768,14 @@ var PlacesSearchBox = {
|
|||
return;
|
||||
}
|
||||
|
||||
var currentOptions = PO.getCurrentOptions();
|
||||
var content = PO._content;
|
||||
let currentView = ContentArea.currentView;
|
||||
let currentOptions = PO.getCurrentOptions();
|
||||
|
||||
// Search according to the current scope, which was set by
|
||||
// PQB_setScope()
|
||||
switch (PlacesSearchBox.filterCollection) {
|
||||
case "bookmarks":
|
||||
content.applyFilter(filterString, this.folders);
|
||||
currentView.applyFilter(filterString, this.folders);
|
||||
break;
|
||||
case "history":
|
||||
if (currentOptions.queryType != Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
|
||||
|
@ -797,13 +786,14 @@ var PlacesSearchBox = {
|
|||
options.resultType = currentOptions.RESULT_TYPE_URI;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||
options.includeHidden = true;
|
||||
content.load([query], options);
|
||||
currentView.load([query], options);
|
||||
}
|
||||
else {
|
||||
content.applyFilter(filterString, null, true);
|
||||
currentView.applyFilter(filterString, null, true);
|
||||
}
|
||||
break;
|
||||
case "downloads": {
|
||||
case "downloads":
|
||||
if (currentView == ContentTree.view) {
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.searchTerms = filterString;
|
||||
query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
|
||||
|
@ -812,16 +802,19 @@ var PlacesSearchBox = {
|
|||
options.resultType = currentOptions.RESULT_TYPE_URI;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||
options.includeHidden = true;
|
||||
content.load([query], options);
|
||||
break;
|
||||
currentView.load([query], options);
|
||||
}
|
||||
else {
|
||||
// The new downloads view doesn't use places for searching downloads.
|
||||
currentView.searchTerm = filterString;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw "Invalid filterCollection on search";
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the details panel
|
||||
PlacesOrganizer.onContentTreeSelect();
|
||||
PlacesOrganizer.updateDetailsPane();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1251,3 +1244,94 @@ let gPrivateBrowsingListener = {
|
|||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
let ContentArea = {
|
||||
init: function CA_init() {
|
||||
this._deck = document.getElementById("placesViewsDeck");
|
||||
this._specialViews = new Map();
|
||||
ContentTree.init();
|
||||
},
|
||||
|
||||
_shouldUseNewDownloadsView: function CA_shouldUseNewDownloadsView() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref("browser.library.useNewDownloadsView");
|
||||
}
|
||||
catch(ex) { }
|
||||
return false;
|
||||
},
|
||||
|
||||
getContentViewForQueryString:
|
||||
function CA_getContentViewForQueryString(aQueryString) {
|
||||
if (this._specialViews.has(aQueryString))
|
||||
return this._specialViews.get(aQueryString);
|
||||
if (aQueryString == DOWNLOADS_QUERY && this._shouldUseNewDownloadsView()) {
|
||||
let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox"), aQueryString);
|
||||
this.setContentViewForQueryString(aQueryString, view);
|
||||
return view;
|
||||
}
|
||||
return ContentTree.view;
|
||||
},
|
||||
|
||||
setContentViewForQueryString:
|
||||
function CA_setContentViewForQueryString(aQueryString, aView) {
|
||||
this._specialViews.set(aQueryString, aView);
|
||||
},
|
||||
|
||||
get currentView() PlacesUIUtils.getViewForNode(this._deck.selectedPanel),
|
||||
set currentView(aView) {
|
||||
if (this.currentView != aView)
|
||||
this._deck.selectedPanel = aView.associatedElement;
|
||||
return aView;
|
||||
},
|
||||
|
||||
get currentPlace() this.currentView.place,
|
||||
set currentPlace(aQueryString) {
|
||||
this.currentView = this.getContentViewForQueryString(aQueryString);
|
||||
this.currentView.place = aQueryString;
|
||||
return aQueryString;
|
||||
},
|
||||
|
||||
focus: function() {
|
||||
this._deck.selectedPanel.focus();
|
||||
}
|
||||
};
|
||||
|
||||
let ContentTree = {
|
||||
init: function CT_init() {
|
||||
this._view = document.getElementById("placeContent");
|
||||
},
|
||||
|
||||
get view() this._view,
|
||||
|
||||
openSelectedNode: function CT_openSelectedNode(aEvent) {
|
||||
let view = this.view;
|
||||
PlacesUIUtils.openNodeWithEvent(view.selectedNode, aEvent, view);
|
||||
},
|
||||
|
||||
onClick: function CT_onClick(aEvent) {
|
||||
// Only handle clicks on tree children.
|
||||
if (aEvent.target.localName != "treechildren")
|
||||
return;
|
||||
|
||||
let node = this.view.selectedNode;
|
||||
if (node) {
|
||||
let doubleClick = aEvent.button == 0 && aEvent.detail == 2;
|
||||
let middleClick = aEvent.button == 1 && aEvent.detail == 1;
|
||||
if (PlacesUtils.nodeIsURI(node) && (doubleClick || middleClick)) {
|
||||
// Open associated uri in the browser.
|
||||
this.openSelectedNode(aEvent);
|
||||
}
|
||||
else if (middleClick && PlacesUtils.nodeIsContainer(node)) {
|
||||
// The command execution function will take care of seeing if the
|
||||
// selection is a folder or a different container type, and will
|
||||
// load its contents in tabs.
|
||||
PlacesUIUtils.openContainerNodeInTabs(node, aEvent, this.view);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onKeyPress: function CT_onKeyPress(aEvent) {
|
||||
if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
|
||||
this.openSelectedNode(aEvent);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<?xml-stylesheet href="chrome://global/skin/"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/places/organizer.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
|
||||
|
||||
<?xul-overlay href="chrome://browser/content/places/editBookmarkOverlay.xul"?>
|
||||
|
||||
|
@ -28,6 +29,8 @@
|
|||
%editMenuOverlayDTD;
|
||||
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
<!ENTITY % downloadsDTD SYSTEM "chrome://browser/locale/downloads/downloads.dtd">
|
||||
%downloadsDTD;
|
||||
]>
|
||||
|
||||
<window id="places"
|
||||
|
@ -42,12 +45,16 @@
|
|||
toggletoolbar="true"
|
||||
persist="width height screenX screenY sizemode">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/places/downloadsView.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/places/places.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/utilityOverlay.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://browser/content/places/editBookmarkOverlay.js"/>
|
||||
<script type="application/javascript"
|
||||
src="chrome://global/content/contentAreaUtils.js"/>
|
||||
|
||||
<stringbundleset id="placesStringSet">
|
||||
<stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
|
||||
|
@ -344,8 +351,8 @@
|
|||
type="places"
|
||||
hidecolumnpicker="true" context="placesContext"
|
||||
onselect="PlacesOrganizer.onPlaceSelected(true);"
|
||||
onclick="PlacesOrganizer.onTreeClick(event);"
|
||||
onfocus="PlacesOrganizer.onTreeFocus(event);"
|
||||
onclick="PlacesOrganizer.onPlacesListClick(event);"
|
||||
onfocus="PlacesOrganizer.updateDetailsPane(event);"
|
||||
seltype="single"
|
||||
persist="width"
|
||||
width="200"
|
||||
|
@ -358,6 +365,9 @@
|
|||
</tree>
|
||||
<splitter collapse="none" persist="state"></splitter>
|
||||
<vbox id="contentView" flex="4">
|
||||
<deck id="placesViewsDeck"
|
||||
selectedIndex="0"
|
||||
flex="1">
|
||||
<tree id="placeContent"
|
||||
class="plain placesTree"
|
||||
context="placesContext"
|
||||
|
@ -366,11 +376,11 @@
|
|||
type="places"
|
||||
flatList="true"
|
||||
enableColumnDrag="true"
|
||||
onkeypress="if (event.keyCode == KeyEvent.DOM_VK_RETURN) PlacesOrganizer.openSelectedNode(event);"
|
||||
onfocus="PlacesOrganizer.updateDetailsPane(event)"
|
||||
onselect="PlacesOrganizer.updateDetailsPane(event)"
|
||||
onkeypress="ContentTree.onKeyPress(event);"
|
||||
onopenflatcontainer="PlacesOrganizer.openFlatContainer(aContainer);"
|
||||
onselect="PlacesOrganizer.onContentTreeSelect();"
|
||||
onfocus="PlacesOrganizer.onTreeFocus(event);"
|
||||
onclick="PlacesOrganizer.onTreeClick(event);">
|
||||
onclick="ContentTree.onClick(event);">
|
||||
<treecols id="placeContentColumns" context="placesColumnsContext">
|
||||
<treecol label="&col.name.label;" id="placesContentTitle" anonid="title" flex="5" primary="true" ordinal="1"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
|
@ -401,6 +411,12 @@
|
|||
</treecols>
|
||||
<treechildren flex="1"/>
|
||||
</tree>
|
||||
<richlistbox flex="1"
|
||||
seltype="multiple"
|
||||
id="downloadsRichListBox" context="downloadsContextMenu"
|
||||
onkeypress="return this._placesView.onKeyPress(event);"
|
||||
oncontextmenu="return this._placesView.onContextMenu(event);"/>
|
||||
</deck>
|
||||
<deck id="detailsDeck" style="height: 11em;">
|
||||
<vbox id="itemsCountBox" align="center">
|
||||
<spacer flex="3"/>
|
||||
|
@ -434,4 +450,61 @@
|
|||
</deck>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
<commandset id="downloadCommands"
|
||||
commandupdater="true"
|
||||
events="focus,select,contextmenu"
|
||||
oncommandupdate="goUpdatePlacesCommands(); goUpdateDownloadCommands();">
|
||||
<command id="downloadsCmd_pauseResume"
|
||||
oncommand="goDoCommand('downloadsCmd_pauseResume')"/>
|
||||
<command id="downloadsCmd_cancel"
|
||||
oncommand="goDoCommand('downloadsCmd_cancel')"/>
|
||||
<command id="downloadsCmd_open"
|
||||
oncommand="goDoCommand('downloadsCmd_open')"/>
|
||||
<command id="downloadsCmd_show"
|
||||
oncommand="goDoCommand('downloadsCmd_show')"/>
|
||||
<command id="downloadsCmd_retry"
|
||||
oncommand="goDoCommand('downloadsCmd_retry')"/>
|
||||
<command id="downloadsCmd_openReferrer"
|
||||
oncommand="goDoCommand('downloadsCmd_openReferrer')"/>
|
||||
</commandset>
|
||||
|
||||
<menupopup id="downloadsContextMenu"
|
||||
class="download-state">
|
||||
<menuitem command="downloadsCmd_pauseResume"
|
||||
class="downloadPauseMenuItem"
|
||||
label="&cmd.pause.label;"
|
||||
accesskey="&cmd.pause.accesskey;"/>
|
||||
<menuitem command="downloadsCmd_pauseResume"
|
||||
class="downloadResumeMenuItem"
|
||||
label="&cmd.resume.label;"
|
||||
accesskey="&cmd.resume.accesskey;"/>
|
||||
<menuitem command="downloadsCmd_cancel"
|
||||
class="downloadCancelMenuItem"
|
||||
label="&cmd.cancel.label;"
|
||||
accesskey="&cmd.cancel.accesskey;"/>
|
||||
<menuitem command="cmd_delete"
|
||||
class="downloadRemoveFromListMenuItem"
|
||||
label="&cmd.removeFromList.label;"
|
||||
accesskey="&cmd.removeFromList.accesskey;"/>
|
||||
<menuitem command="downloadsCmd_show"
|
||||
class="downloadShowMenuItem"
|
||||
#ifdef XP_MACOSX
|
||||
label="&cmd.showMac.label;"
|
||||
accesskey="&cmd.showMac.accesskey;"
|
||||
#else
|
||||
label="&cmd.show.label;"
|
||||
accesskey="&cmd.show.accesskey;"
|
||||
#endif
|
||||
/>
|
||||
|
||||
<menuseparator class="downloadCommandsSeparator"/>
|
||||
|
||||
<menuitem command="downloadsCmd_openReferrer"
|
||||
label="&cmd.goToDownloadPage.label;"
|
||||
accesskey="&cmd.goToDownloadPage.accesskey;"/>
|
||||
<menuitem command="cmd_copy"
|
||||
label="&cmd.copyDownloadLink.label;"
|
||||
accesskey="&cmd.copyDownloadLink.accesskey;"/>
|
||||
</menupopup>
|
||||
</window>
|
||||
|
|
|
@ -56,6 +56,10 @@
|
|||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="associatedElement"
|
||||
readonly="true"
|
||||
onget="return this"/>
|
||||
|
||||
<method name="applyFilter">
|
||||
<parameter name="filterString"/>
|
||||
<parameter name="folderRestrict"/>
|
||||
|
|
|
@ -8,6 +8,9 @@ browser.jar:
|
|||
content/browser/places/bookmarkProperties2.xul (content/bookmarkProperties.xul)
|
||||
* content/browser/places/places.xul (content/places.xul)
|
||||
* content/browser/places/places.js (content/places.js)
|
||||
content/browser/places/downloadsView.js (content/downloadsView.js)
|
||||
content/browser/places/download.xml (content/download.xml)
|
||||
content/browser/places/download.css (content/download.css)
|
||||
content/browser/places/places.css (content/places.css)
|
||||
content/browser/places/organizer.css (content/organizer.css)
|
||||
content/browser/places/bookmarkProperties.xul (content/bookmarkProperties.xul)
|
||||
|
|
|
@ -21,6 +21,7 @@ const MOZURISPEC = "http://mozilla.com/";
|
|||
|
||||
let gLibrary;
|
||||
let PlacesOrganizer;
|
||||
let ContentTree;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
@ -34,6 +35,9 @@ function onLibraryReady() {
|
|||
PlacesOrganizer = gLibrary.PlacesOrganizer;
|
||||
ok(PlacesOrganizer, "Places organizer in scope");
|
||||
|
||||
ContentTree = gLibrary.ContentTree;
|
||||
ok(ContentTree, "ContentTree is in scope");
|
||||
|
||||
tests.makeHistVisit();
|
||||
tests.makeTag();
|
||||
tests.focusTag();
|
||||
|
@ -101,12 +105,12 @@ let tests = {
|
|||
PlacesUtils.asContainer(histContainer);
|
||||
histContainer.containerOpen = true;
|
||||
PlacesOrganizer._places.selectNode(histContainer.getChild(0));
|
||||
let histNode = PlacesOrganizer._content.view.nodeForTreeIndex(0);
|
||||
PlacesOrganizer._content.selectNode(histNode);
|
||||
let histNode = ContentTree.view.view.nodeForTreeIndex(0);
|
||||
ContentTree.view.selectNode(histNode);
|
||||
is(histNode.uri, MOZURISPEC,
|
||||
"historyNode exists: " + histNode.uri);
|
||||
// copy the history node
|
||||
PlacesOrganizer._content.controller.copy();
|
||||
ContentTree.view.controller.copy();
|
||||
},
|
||||
|
||||
historyNode: function (){
|
||||
|
@ -116,7 +120,7 @@ let tests = {
|
|||
PlacesUtils.asContainer(histContainer);
|
||||
histContainer.containerOpen = true;
|
||||
PlacesOrganizer._places.selectNode(histContainer.getChild(0));
|
||||
let histNode = PlacesOrganizer._content.view.nodeForTreeIndex(0);
|
||||
let histNode = ContentTree.view.view.nodeForTreeIndex(0);
|
||||
ok(histNode, "histNode exists: " + histNode.title);
|
||||
// check to see if the history node is tagged!
|
||||
let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(MOZURISPEC));
|
||||
|
@ -133,8 +137,8 @@ let tests = {
|
|||
// is the bookmark visible in the UI?
|
||||
// get the Unsorted Bookmarks node
|
||||
PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks");
|
||||
// now we can see what is in the _content tree
|
||||
let unsortedNode = PlacesOrganizer._content.view.nodeForTreeIndex(1);
|
||||
// now we can see what is in the ContentTree tree
|
||||
let unsortedNode = ContentTree.view.view.nodeForTreeIndex(1);
|
||||
ok(unsortedNode, "unsortedNode is not null: " + unsortedNode.uri);
|
||||
is(unsortedNode.uri, MOZURISPEC, "node uri's are the same");
|
||||
},
|
||||
|
|
|
@ -7,6 +7,7 @@ const TEST_URL = "http://example.com/";
|
|||
let gLibrary;
|
||||
let gItemId;
|
||||
let PlacesOrganizer;
|
||||
let ContentTree;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
@ -15,11 +16,13 @@ function test() {
|
|||
|
||||
function onLibraryReady() {
|
||||
PlacesOrganizer = gLibrary.PlacesOrganizer;
|
||||
ContentTree = gLibrary.ContentTree;
|
||||
|
||||
// Sanity checks.
|
||||
ok(PlacesUtils, "PlacesUtils in scope");
|
||||
ok(PlacesUIUtils, "PlacesUIUtils in scope");
|
||||
ok(PlacesOrganizer, "PlacesOrganizer in scope");
|
||||
ok(ContentTree, "ContentTree is in scope");
|
||||
|
||||
gItemId = PlacesUtils.bookmarks.insertBookmark(
|
||||
PlacesUtils.toolbarFolderId, NetUtil.newURI(TEST_URL),
|
||||
|
@ -41,21 +44,21 @@ function selectBookmarkIn(aLeftPaneQuery) {
|
|||
is(PlacesUtils.bookmarks.getFolderIdForItem(gItemId), rootId,
|
||||
"Bookmark has the right parent");
|
||||
info("Selecting the bookmark in the right pane");
|
||||
PlacesOrganizer._content.selectItems([gItemId]);
|
||||
let bookmarkNode = PlacesOrganizer._content.selectedNode;
|
||||
ContentTree.view.selectItems([gItemId]);
|
||||
let bookmarkNode = ContentTree.view.selectedNode;
|
||||
is(bookmarkNode.uri, TEST_URL, "Found the expected bookmark");
|
||||
}
|
||||
|
||||
function cutSelection() {
|
||||
info("Cutting selection");
|
||||
PlacesOrganizer._content.controller.cut();
|
||||
ContentTree.view.controller.cut();
|
||||
}
|
||||
|
||||
function pasteClipboard(aLeftPaneQuery) {
|
||||
info("Selecting " + aLeftPaneQuery + " in the left pane");
|
||||
PlacesOrganizer.selectLeftPaneQuery(aLeftPaneQuery);
|
||||
info("Pasting clipboard");
|
||||
PlacesOrganizer._content.controller.paste();
|
||||
ContentTree.view.controller.paste();
|
||||
}
|
||||
|
||||
function onClipboardReady() {
|
||||
|
|
|
@ -69,19 +69,20 @@ gTests.push({
|
|||
desc: "Ensure correct selection and functionality in Library",
|
||||
run: function() {
|
||||
let PO = gLibrary.PlacesOrganizer;
|
||||
let ContentTree = gLibrary.ContentTree;
|
||||
// Move selection forth and back.
|
||||
PO.selectLeftPaneQuery("History");
|
||||
PO.selectLeftPaneQuery("UnfiledBookmarks");
|
||||
// Now select the "keepme" folder in the right pane and delete it.
|
||||
PO._content.selectNode(PO._content.result.root.getChild(0));
|
||||
is(PO._content.selectedNode.title, "keepme",
|
||||
ContentTree.view.selectNode(ContentTree.view.result.root.getChild(0));
|
||||
is(ContentTree.view.selectedNode.title, "keepme",
|
||||
"Found folder in content pane");
|
||||
// Test live update.
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
makeURI(TEST_URL),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bm");
|
||||
is(PO._content.result.root.childCount, 2,
|
||||
is(ContentTree.view.result.root.childCount, 2,
|
||||
"Right pane was correctly updated");
|
||||
nextTest();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ gTests.push({
|
|||
desc: "Bug 430148 - Remove or hide the more/less button in details pane...",
|
||||
run: function() {
|
||||
var PO = gLibrary.PlacesOrganizer;
|
||||
let ContentTree = gLibrary.ContentTree;
|
||||
var infoBoxExpanderWrapper = getAndCheckElmtById("infoBoxExpanderWrapper");
|
||||
|
||||
// add a visit to browser history
|
||||
|
@ -57,7 +58,7 @@ gTests.push({
|
|||
checkAddInfoFieldsCollapsed(PO);
|
||||
|
||||
// open history item
|
||||
var view = PO._content.treeBoxObject.view;
|
||||
var view = ContentTree.view.treeBoxObject.view;
|
||||
ok(view.rowCount > 0, "History item exists.");
|
||||
view.selection.select(0);
|
||||
ok(infoBoxExpanderWrapper.hidden,
|
||||
|
@ -94,7 +95,7 @@ gTests.push({
|
|||
checkAddInfoFieldsNotCollapsed(PO);
|
||||
|
||||
// open first bookmark
|
||||
var view = PO._content.treeBoxObject.view;
|
||||
var view = ContentTree.view.treeBoxObject.view;
|
||||
ok(view.rowCount > 0, "Bookmark item exists.");
|
||||
view.selection.select(0);
|
||||
checkInfoBoxSelected(PO);
|
||||
|
|
|
@ -88,7 +88,7 @@ gTests.push({
|
|||
isnot(gLibrary.PlacesOrganizer._places.selectedNode, null,
|
||||
"We correctly have selection in the Library left pane");
|
||||
// Get our bookmark in the right pane.
|
||||
var bookmarkNode = gLibrary.PlacesOrganizer._content.view.nodeForTreeIndex(0);
|
||||
var bookmarkNode = gLibrary.ContentTree.view.view.nodeForTreeIndex(0);
|
||||
is(bookmarkNode.uri, this.URIs[0], "Found bookmark in the right pane");
|
||||
},
|
||||
|
||||
|
@ -130,7 +130,7 @@ gTests.push({
|
|||
isnot(gLibrary.PlacesOrganizer._places.selectedNode, null,
|
||||
"We correctly have selection in the Library left pane");
|
||||
// Get our bookmark in the right pane.
|
||||
var folderNode = gLibrary.PlacesOrganizer._content.view.nodeForTreeIndex(0);
|
||||
var folderNode = gLibrary.ContentTree.view.view.nodeForTreeIndex(0);
|
||||
is(folderNode.title, "Folder", "Found folder in the right pane");
|
||||
},
|
||||
|
||||
|
@ -187,7 +187,7 @@ gTests.push({
|
|||
isnot(gLibrary.PlacesOrganizer._places.selectedNode, null,
|
||||
"We correctly have selection in the Library left pane");
|
||||
// Get our bookmark in the right pane.
|
||||
var folderNode = gLibrary.PlacesOrganizer._content.view.nodeForTreeIndex(0);
|
||||
var folderNode = gLibrary.ContentTree.view.view.nodeForTreeIndex(0);
|
||||
is(folderNode.title, "Query", "Found query in the right pane");
|
||||
},
|
||||
|
||||
|
@ -243,7 +243,7 @@ function runNextTest() {
|
|||
// Middle click on first node in the content tree of the Library.
|
||||
gLibrary.focus();
|
||||
waitForFocus(function() {
|
||||
mouseEventOnCell(gLibrary.PlacesOrganizer._content, 0, 0, { button: 1 });
|
||||
mouseEventOnCell(gLibrary.ContentTree.view, 0, 0, { button: 1 });
|
||||
}, gLibrary);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -202,3 +202,71 @@ treechildren::-moz-tree-image(cutting) {
|
|||
treechildren::-moz-tree-cell-text(cutting) {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
||||
/** Downloads View **/
|
||||
|
||||
richlistitem.download {
|
||||
height: 7em;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
-moz-padding-end: 0;
|
||||
}
|
||||
|
||||
richlistitem.download:first-child {
|
||||
border-top: 1px solid transparent;
|
||||
}
|
||||
|
||||
richlistitem.download:last-child {
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
.downloadTypeIcon {
|
||||
-moz-margin-end: 8px;
|
||||
/* Prevent flickering when changing states. */
|
||||
min-height: 32px;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
.blockedIcon {
|
||||
list-style-image: url("chrome://global/skin/icons/Error.png");
|
||||
}
|
||||
|
||||
.downloadTarget {
|
||||
margin-bottom: 6px;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.downloadDetails {
|
||||
opacity: 0.7;
|
||||
font-size: 95%;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.downloadButton {
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
margin: 3px;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
list-style-image: url("chrome://browser/skin/downloads/buttons.png");
|
||||
}
|
||||
|
||||
.downloadButton > .button-box {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*** Button icons ***/
|
||||
|
||||
.downloadButton.downloadCancel {
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
}
|
||||
|
||||
.downloadButton.downloadShow {
|
||||
-moz-image-region: rect(16px, 16px, 32px, 0px);
|
||||
}
|
||||
|
||||
.downloadButton.downloadRetry {
|
||||
-moz-image-region: rect(32px, 16px, 48px, 0px);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче