зеркало из https://github.com/mozilla/snowl.git
612 строки
23 KiB
JavaScript
612 строки
23 KiB
JavaScript
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Snowl.
|
|
*
|
|
* The Initial Developer of the Original Code is Mozilla.
|
|
* Portions created by the Initial Developer are Copyright (C) 2008
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Myk Melez <myk@mozilla.org>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
// modules that come with Firefox
|
|
|
|
// modules that are generic
|
|
Cu.import("resource://snowl/modules/log4moz.js");
|
|
Cu.import("resource://snowl/modules/Observers.js");
|
|
Cu.import("resource://snowl/modules/URI.js");
|
|
|
|
// modules that are Snowl-specific
|
|
Cu.import("resource://snowl/modules/service.js");
|
|
Cu.import("resource://snowl/modules/datastore.js");
|
|
Cu.import("resource://snowl/modules/source.js");
|
|
Cu.import("resource://snowl/modules/feed.js");
|
|
Cu.import("resource://snowl/modules/identity.js");
|
|
Cu.import("resource://snowl/modules/collection.js");
|
|
Cu.import("resource://snowl/modules/opml.js");
|
|
|
|
let CollectionsView = {
|
|
_log: null,
|
|
|
|
get _tree() {
|
|
delete this._tree;
|
|
return this._tree = document.getElementById("sourcesView");
|
|
},
|
|
|
|
get _children() {
|
|
delete this._children;
|
|
return this._children = document.getElementById("sourcesViewChildren");
|
|
},
|
|
|
|
get _searchBox() {
|
|
delete this._searchBox;
|
|
return this._searchBox = document.getElementById("searchBox");
|
|
},
|
|
|
|
get _searchBoxButton() {
|
|
delete this._searchBoxButton;
|
|
return this._searchBoxButton = document.getElementById("searchBoxButton");
|
|
},
|
|
|
|
get itemIds() {
|
|
let intArray = [];
|
|
let strArray = this._tree.getAttribute("itemids").split(",");
|
|
for each (let intg in strArray)
|
|
intArray.push(parseInt(intg));
|
|
delete this._itemIds;
|
|
return this._itemIds = intArray;
|
|
},
|
|
|
|
set itemIds(ids) {
|
|
this._tree.setAttribute("itemids", ids);
|
|
delete this._itemIds;
|
|
return this._itemIds = ids;
|
|
},
|
|
|
|
gMessageViewWindow: null,
|
|
|
|
|
|
//**************************************************************************//
|
|
// Initialization & Destruction
|
|
|
|
init: function() {
|
|
Observers.add("snowl:source:added", this.onSourceAdded, this);
|
|
Observers.add("snowl:message:added", this.onMessageAdded, this);
|
|
Observers.add("snowl:source:removed", this.onSourceRemoved, this);
|
|
// Observers.add("snowl:messages:changed", this.onMessagesComplete, this);
|
|
if (document.getElementById("snowlSidebar")) {
|
|
// Only for sidebar collections tree in list view.
|
|
this._log = Log4Moz.repository.getLogger("Snowl.Sidebar");
|
|
this.gMessageViewWindow = SnowlService.gBrowserWindow;
|
|
}
|
|
else if (document.getElementById("snowlRiver")) {
|
|
// Only for collections tree in river view.
|
|
this._log = Log4Moz.repository.getLogger("Snowl.River");
|
|
this.gMessageViewWindow = window;
|
|
}
|
|
|
|
// Intialize places flat attribute
|
|
if (!this._tree.hasAttribute("flat"))
|
|
this._tree.setAttribute("flat", true);
|
|
|
|
if (!this._searchBox.hasAttribute("collapsed"))
|
|
this._searchBoxButton.setAttribute("checked", true);
|
|
|
|
// Get collections and convert to places tree - one time upgrade
|
|
// XXX move this to datastore.js module
|
|
if (!SnowlPlaces.convertedToPlaces &&
|
|
SnowlPlaces.initializedPlaces &&
|
|
SnowlPlaces.convertedToPlaces != null) {
|
|
// Use null as a lock in case another CollectionsView instantiated.
|
|
SnowlPlaces.convertedToPlaces = null;
|
|
this._getCollections();
|
|
this._buildCollectionTree();
|
|
SnowlPlaces.convertedToPlaces = true;
|
|
}
|
|
|
|
let query = this._tree.getAttribute("flat") == "true" ?
|
|
SnowlPlaces.queryFlat : SnowlPlaces.queryGrouped;
|
|
this._tree.place = query;
|
|
|
|
// Ensure collection tree selection maintained for list view, river handles itself
|
|
if (document.getElementById("snowlSidebar")) {
|
|
this._log.info("init: itemIds = "+this.itemIds);
|
|
this._tree.restoreSelection();
|
|
}
|
|
},
|
|
|
|
unload: function() {
|
|
Observers.remove("snowl:source:added", this.onSourceAdded, this);
|
|
Observers.remove("snowl:message:added", this.onMessageAdded, this);
|
|
Observers.remove("snowl:source:removed", this.onSourceRemoved, this);
|
|
// Observers.remove("snowl:messages:changed", this.onMessagesComplete, this);
|
|
},
|
|
|
|
|
|
//**************************************************************************//
|
|
// Event & Notification Handlers
|
|
|
|
onSourceAdded: function(aPlaceID) {
|
|
this._log.info("onSourceAdded: aPlaceID - "+aPlaceID);
|
|
// Newly subscribed source has been added to places, select the inserted row.
|
|
// The effect of selecting here is that onMessageAdded will trigger a view
|
|
// refresh for each message, so messages pop into the view as added.
|
|
this._tree.currentSelectedIndex = -1;
|
|
setTimeout(function() {
|
|
CollectionsView._tree.restoreSelection([aPlaceID]);
|
|
//CollectionsView._log.info("onSourceAdded: END curIndex - "+CollectionsView._tree.currentIndex);
|
|
}, 30)
|
|
},
|
|
|
|
onMessageAdded: function(message) {
|
|
// If source or author of new message is currently selected in the
|
|
// collections list, refresh view. This observer exists for both list and
|
|
// river and selections may be different.
|
|
//this._log.info("onMessageAdded: COLLECTIONS");
|
|
if (this.isMessageForSelectedCollection(message)) {
|
|
this.gMessageViewWindow.SnowlMessageView.onMessageAdded(message);
|
|
}
|
|
},
|
|
|
|
onMessagesComplete: function(aSourceId) {
|
|
// Finished downloading all messages. Scroll the collection tree intelligently.
|
|
SnowlUtils.scrollPlacement(this._tree, this._tree.currentIndex);
|
|
},
|
|
|
|
onSourceRemoved: function() {
|
|
//this._log.info("onSourceRemoved: curIndex:gMouseEvent - "+
|
|
// this._tree.currentIndex+" : "+SnowlUtils.gMouseEvent);
|
|
SnowlUtils.gRightMouseButtonDown = false;
|
|
// If tree rows removed, attempt to reselect originally selected row.
|
|
setTimeout(function() {
|
|
CollectionsView._tree.restoreSelection();
|
|
if (!CollectionsView._tree.selectedNode) {
|
|
// Original selected row removed, reset and clear.
|
|
CollectionsView._tree.currentIndex = -1;
|
|
CollectionsView._tree.currentSelectedIndex = -1;
|
|
CollectionsView.itemIds = -1;
|
|
CollectionsView.gMessageViewWindow.SnowlMessageView.onCollectionsDeselect();
|
|
}
|
|
}, 30)
|
|
},
|
|
|
|
onSelect: function(aEvent) {
|
|
//this._log.info("onSelect start: curIndex:gMouseEvent - "+
|
|
// this._tree.currentIndex+" : "+SnowlUtils.gMouseEvent);
|
|
// We want to only select onClick (more precisely, mouseup) for mouse events
|
|
// but need onSelect for key events (arrow keys). Since onSelect events do
|
|
// not have info on whether mouse or key, we track it ourselves.
|
|
if (this._tree.currentIndex == -1 || SnowlUtils.gMouseEvent)
|
|
return;
|
|
|
|
this.onClick(aEvent);
|
|
},
|
|
|
|
onClick: function(aEvent) {
|
|
let row = { }, col = { }, obj = { };
|
|
let modKey = aEvent.metaKey || aEvent.ctrlKey || aEvent.shiftKey;
|
|
/*
|
|
this._log.info("onClick start: curIndex:curSelectedIndex = "+
|
|
this._tree.currentIndex+" : "+this._tree.currentSelectedIndex);
|
|
this._log.info("onClick start - gMouseEvent:gRtbutton:modKey = "+
|
|
SnowlUtils.gMouseEvent+" : "+SnowlUtils.gRightMouseButtonDown+" : "+modKey);
|
|
this._log.info("onClick: selectionCount = "+this._tree.view.selection.count);
|
|
this._log.info("onClick: START itemIds - " +this.itemIds.toSource());
|
|
*/
|
|
SnowlUtils.gMouseEvent = false;
|
|
|
|
// Don't run query on right click, or already selected row (unless deselecting).
|
|
if (SnowlUtils.gRightMouseButtonDown || this._tree.currentIndex == -1 ||
|
|
(this._tree.view.selection.count == 1 && !modKey &&
|
|
this._tree.currentIndex == this._tree.currentSelectedIndex))
|
|
return;
|
|
|
|
// If mod key deselected, reset currentIndex
|
|
if (modKey && !this._tree.view.selection.isSelected(this._tree.currentIndex))
|
|
this._tree.currentIndex = -1;
|
|
|
|
// If mod key and multiselection, reset currentSelectedIndex so subsequent
|
|
// non mod key click will select on any previously selected row.
|
|
if (modKey && this._tree.view.selection.count > 1)
|
|
this._tree.currentSelectedIndex = -1;
|
|
else
|
|
this._tree.currentSelectedIndex = this._tree.currentIndex;
|
|
|
|
// Mod key click will deselect a row; for a 0 count notify view to clear.
|
|
if (this._tree.view.selection.count == 0) {
|
|
// this._tree.currentIndex = -1;
|
|
this._tree.currentSelectedIndex = -1;
|
|
this.itemIds = -1;
|
|
this.gMessageViewWindow.SnowlMessageView.onCollectionsDeselect();
|
|
return;
|
|
}
|
|
|
|
// XXX: Bug 477806 - closing container with selected child selects
|
|
// container, does not remember selected child on open. Restoring original
|
|
// selection by traversing the tree for itemID is too expensive here.
|
|
this._tree.boxObject.getCellAt(aEvent.clientX, aEvent.clientY, row, col, obj);
|
|
if (obj.value == "twisty") {
|
|
// this._tree.restoreSelection();
|
|
return;
|
|
}
|
|
|
|
let collection = new SnowlCollection(null,
|
|
name,
|
|
null,
|
|
this.getSelectionConstraints(),
|
|
null);
|
|
this.gMessageViewWindow.SnowlMessageView.setCollection(collection);
|
|
},
|
|
|
|
onCollectionsTreeMouseDown: function(aEvent) {
|
|
SnowlUtils.onTreeMouseDown(aEvent);
|
|
},
|
|
|
|
onTreeContextPopupHidden: function() {
|
|
SnowlUtils.RestoreSelection(this._tree, this.itemIds);
|
|
},
|
|
|
|
onSubscribe: function() {
|
|
SnowlService.gBrowserWindow.Snowl.onSubscribe();
|
|
},
|
|
|
|
onUnsubscribe: function() {
|
|
this.unsubscribe();
|
|
},
|
|
|
|
onRefresh: function() {
|
|
SnowlService.refreshAllSources();
|
|
},
|
|
|
|
onToggleSearchbox: function() {
|
|
if (this._searchBox.hasAttribute("collapsed"))
|
|
this._searchBox.removeAttribute("collapsed");
|
|
else
|
|
this._searchBox.setAttribute("collapsed", true);
|
|
},
|
|
|
|
refreshSource: function() {
|
|
let selectedSources = [];
|
|
|
|
// XXX: Multiselection?
|
|
let selectedSource =
|
|
this._tree.view.nodeForTreeIndex(this._tree.currentSelectedIndex);
|
|
// Create places query object from tree item uri
|
|
let query = new SnowlQuery(selectedSource.uri);
|
|
if (query.queryGroupIDColumn != "sources.id")
|
|
return;
|
|
|
|
selectedSources.push(SnowlService.sourcesByID[query.queryID]);
|
|
SnowlService.refreshAllSources(selectedSources);
|
|
},
|
|
|
|
unsubscribe: function() {
|
|
//this._log.info("unsubscribe: START curIndex:curSelectedIndex = "+
|
|
// this._tree.currentIndex+" : "+this._tree.currentSelectedIndex);
|
|
let selectedSourceNodeID = [];
|
|
let selectedSourceNodesIDs = [];
|
|
|
|
// XXX: Multiselection? since only a source type may be unsubscribed and
|
|
// the tree contains mixed types of items, this needs some thought. Single
|
|
// selection only for now.
|
|
// XXX: fix contextmenu
|
|
|
|
let selectedSource =
|
|
this._tree.view.nodeForTreeIndex(this._tree.currentSelectedIndex);
|
|
// Create places query object from tree item uri
|
|
let query = new SnowlQuery(selectedSource.uri);
|
|
|
|
if (query.queryGroupIDColumn != "sources.id")
|
|
return;
|
|
this._log.info("unsubscribe: source - " + query.queryName + " : " + selectedSource.itemId);
|
|
|
|
selectedSourceNodeID = [selectedSource, query.queryID];
|
|
selectedSourceNodesIDs.push(selectedSourceNodeID);
|
|
|
|
// Delete loop here, if multiple selections..
|
|
for (let i = 0; i < selectedSourceNodesIDs.length; ++i) {
|
|
sourceNode = selectedSourceNodesIDs[i][0];
|
|
sourceID = selectedSourceNodesIDs[i][1];
|
|
SnowlDatastore.dbConnection.beginTransaction();
|
|
try {
|
|
// Delete messages
|
|
// XXX the metadata is a time consuming call, followed by partstext,
|
|
// need to optimize these.
|
|
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM metadata " +
|
|
"WHERE messageID IN " +
|
|
"(SELECT id FROM messages WHERE sourceID = " + sourceID + ")");
|
|
//this._log.info("unsubscribe: Delete messages METADATA DONE");
|
|
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM partsText " +
|
|
"WHERE docid IN " +
|
|
"(SELECT id FROM parts WHERE messageID IN " +
|
|
"(SELECT id FROM messages WHERE sourceID = " + sourceID + "))");
|
|
//this._log.info("unsubscribe: Delete messages PARTSTEXT DONE");
|
|
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM parts " +
|
|
"WHERE messageID IN " +
|
|
"(SELECT id FROM messages WHERE sourceID = " + sourceID + ")");
|
|
//this._log.info("unsubscribe: Delete messages PARTS DONE");
|
|
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM messages " +
|
|
"WHERE sourceID = " + sourceID);
|
|
//this._log.info("unsubscribe: Delete messages DONE");
|
|
// Delete people/identities
|
|
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM people " +
|
|
"WHERE id IN " +
|
|
"(SELECT personId FROM identities WHERE sourceID = " + sourceID + ")");
|
|
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM identities " +
|
|
"WHERE sourceID = " + sourceID);
|
|
//this._log.info("unsubscribe: Delete people/identities DONE");
|
|
// Delete the source
|
|
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM sources " +
|
|
"WHERE id = " + sourceID);
|
|
//this._log.info("unsubscribe: Delete source DONE");
|
|
// Finally, clean up the places tree
|
|
// Authors XXX: a more efficient way would be much better here..
|
|
let anno = SnowlPlaces.SNOWL_COLLECTIONS_GROUPEDFOLDER_ANNO + "Authors";
|
|
let pages = PlacesUtils.annotations.getPagesWithAnnotation(anno, { });
|
|
for (let i = 0; i < pages.length; ++i) {
|
|
let annoVal = PlacesUtils.annotations.getPageAnnotation(pages[i], anno);
|
|
if (annoVal == "snowl:sourceID=" + sourceID) {
|
|
let bookmarkIds = PlacesUtils.bookmarks.getBookmarkIdsForURI(pages[i], {});
|
|
for (let j=0; j < bookmarkIds.length; j++) {
|
|
PlacesUtils.bookmarks.removeItem(bookmarkIds[j]);
|
|
//this._log.info("unsubscribe: Delete Places authors bookmark j:"+j);
|
|
}
|
|
}
|
|
}
|
|
//this._log.info("unsubscribe: Delete Places authors DONE");
|
|
// Source
|
|
PlacesUtils.bookmarks.removeItem(sourceNode.itemId);
|
|
//this._log.info("unsubscribe: Delete Places source DONE");
|
|
|
|
SnowlDatastore.dbConnection.commitTransaction();
|
|
}
|
|
catch(ex) {
|
|
SnowlDatastore.dbConnection.rollbackTransaction();
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
Observers.notify("snowl:source:removed");
|
|
},
|
|
|
|
searchCollections: function(aSearchString) {
|
|
// XXX: applyFilter searches in uri, which is not meaningful, fix this..
|
|
if (!aSearchString)
|
|
this._tree.place = this._tree.place;
|
|
else
|
|
this._tree.applyFilter(aSearchString, [SnowlPlaces.snowlRootID]);
|
|
},
|
|
|
|
isMessageForSelectedCollection: function(aMessageObj) {
|
|
// Determine if source or author of new message is currently selected in the
|
|
// collections list.
|
|
let query, uri, rangeFirst = { }, rangeLast = { }, refreshFlag = false;
|
|
let numRanges = this._tree.view.selection.getRangeCount();
|
|
|
|
for (let i = 0; i < numRanges && !refreshFlag; i++) {
|
|
this._tree.view.selection.getRangeAt(i, rangeFirst, rangeLast);
|
|
for (let index = rangeFirst.value; index <= rangeLast.value; index++) {
|
|
uri = this._tree.view.nodeForTreeIndex(index).uri;
|
|
query = new SnowlQuery(uri);
|
|
if ((query.queryGroupIDColumn == "sources.id" &&
|
|
query.queryID == aMessageObj.sourceID) ||
|
|
(query.queryGroupIDColumn == "authors.id" &&
|
|
query.queryID == aMessageObj.authorID) ||
|
|
// Currently, any place: protocol is a collection that returns all records
|
|
query.queryProtocol == "place:")
|
|
refreshFlag = true;
|
|
}
|
|
}
|
|
|
|
return refreshFlag;
|
|
},
|
|
|
|
getSelectionConstraints: function() {
|
|
// Return contraints object based on selected itemIds in the collections
|
|
// tree and persist the list
|
|
let constraints = [], selectedItemIds = [];
|
|
let itemId, uri, rangeFirst = { }, rangeLast = { }, stop = false;
|
|
let numRanges = this._tree.view.selection.getRangeCount();
|
|
|
|
for (let i = 0; i < numRanges && !stop; i++) {
|
|
this._tree.view.selection.getRangeAt(i, rangeFirst, rangeLast);
|
|
for (let index = rangeFirst.value; index <= rangeLast.value; index++) {
|
|
itemId = this._tree.view.nodeForTreeIndex(index).itemId;
|
|
selectedItemIds.push(itemId);
|
|
uri = this._tree.view.nodeForTreeIndex(index).uri;
|
|
let query = new SnowlQuery(uri);
|
|
if (query.queryProtocol == "place:") {
|
|
// Currently, any place: protocol is a collection that returns all
|
|
// records; for any such selection, break with no constraints. There
|
|
// may be other such 'system' collections but more likely collections
|
|
// will be rows which are user defined snowl: queries. Folders TBD.
|
|
constraints = [];
|
|
stop = true;
|
|
break;
|
|
}
|
|
else {
|
|
// Construct the contraint to be passed to the collection object for
|
|
// the db query.
|
|
let constraint = { };
|
|
constraint.expression = query.queryGroupIDColumn +
|
|
" = :groupValue" + index;
|
|
constraint.parameters = { };
|
|
constraint.parameters["groupValue" + index] = query.queryID;
|
|
constraint.operator = "OR";
|
|
constraints.push(constraint);
|
|
}
|
|
}
|
|
}
|
|
//this._log.info("onClick: constraints = " + constraints.toSource());
|
|
|
|
this.itemIds = selectedItemIds;
|
|
return constraints;
|
|
},
|
|
|
|
//**************************************************************************//
|
|
// Places conversion
|
|
|
|
// Create the source/authors collection from the db to convert to places.
|
|
_collections: null,
|
|
_getCollections: function() {
|
|
this._collections = [];
|
|
|
|
let statement = SnowlDatastore.createStatement(
|
|
"SELECT id, name, iconURL, grouped, groupIDColumn, groupNameColumn, " +
|
|
"groupHomeURLColumn, groupIconURLColumn " +
|
|
"FROM collections ORDER BY orderKey"
|
|
);
|
|
|
|
statement.QueryInterface(Ci.mozIStorageStatementWrapper);
|
|
|
|
try {
|
|
while (statement.step()) {
|
|
this._collections.push(new SnowlCollection(statement.row.id,
|
|
statement.row.name,
|
|
URI.get(statement.row.iconURL),
|
|
null,
|
|
null,
|
|
statement.row.grouped ? true : false,
|
|
statement.row.groupIDColumn,
|
|
statement.row.groupNameColumn,
|
|
statement.row.groupHomeURLColumn,
|
|
statement.row.groupIconURLColumn));
|
|
}
|
|
}
|
|
finally {
|
|
statement.reset();
|
|
}
|
|
},
|
|
|
|
// Convert the list of rows in the tree to places.
|
|
_buildCollectionTree: function() {
|
|
for each (let collection in this._collections) {
|
|
if (collection.grouped) {
|
|
let table, value, sourceID, personID;
|
|
switch (collection.groupIDColumn) {
|
|
case "sources.id":
|
|
table = "sources";
|
|
break;
|
|
case "authors.id":
|
|
table = "people";
|
|
break;
|
|
default:
|
|
table = null;
|
|
break;
|
|
}
|
|
for each (let group in collection.groups) {
|
|
//this._log.info(table+" group.name:group.groupID - " + group.name + " : " + group.groupID);
|
|
if (table == "sources")
|
|
value = group.groupID;
|
|
else if (table == "people") {
|
|
if (!group.groupID)
|
|
// Skip null authors
|
|
continue;
|
|
// Get the sourceID that the author belongs to
|
|
value = SnowlDatastore.selectIdentitiesSourceID(group.groupID);
|
|
}
|
|
placeID = SnowlPlaces.persistPlace(table,
|
|
group.groupID,
|
|
group.name,
|
|
null, //machineURI.spec,
|
|
null, //username,
|
|
group.iconURL,
|
|
value); // aSourceID
|
|
// Store placeID back into messages for db integrity
|
|
SnowlDatastore.dbConnection.executeSimpleSQL(
|
|
"UPDATE " + table +
|
|
" SET placeID = " + placeID +
|
|
" WHERE id = " + group.groupID);
|
|
|
|
this._log.info("Converted to places - " +
|
|
group.name + " : " + group.groupID + " : " + placeID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* A single collection list view tree row.
|
|
*
|
|
* @aNode (nsINavHistoryResultNode) collection row node
|
|
|
|
function lvCollectionNode(aNode) {
|
|
this._node = aNode;
|
|
}
|
|
lvCollectionNode.prototype = {
|
|
get uri() {
|
|
delete this._uri;
|
|
return this._uri = this._node ? _node.uri : null;
|
|
},
|
|
|
|
get itemId() {
|
|
delete this._itemId;
|
|
return this._itemId = this._node ? _node.itemId : null;
|
|
},
|
|
|
|
get viewIndex() {
|
|
delete this.viewIndex;
|
|
return this.viewIndex = this._node ? _node.viewIndex : -1;
|
|
}
|
|
};
|
|
*/
|
|
/**
|
|
* PlacesTreeView overrides here.
|
|
*
|
|
*/
|
|
/*
|
|
PlacesTreeView.prototype._drop = PlacesTreeView.prototype.drop;
|
|
PlacesTreeView.prototype.drop = SnowlTreeViewDrop;
|
|
function SnowlTreeViewDrop(aRow, aOrientation) {
|
|
this._drop(aRow, aOrientation);
|
|
|
|
//CollectionsView._log.info("_drop");
|
|
|
|
// Restore selection
|
|
SnowlUtils.gMouseEvent = false;
|
|
CollectionsView._tree.selectItems(CollectionsView.itemIds);
|
|
};
|
|
*/
|
|
|
|
// Not using this yet..
|
|
//function PlacesController(aView) {
|
|
// this._view = aView;
|
|
//}
|
|
|
|
//PlacesController.prototype = {
|
|
/**
|
|
* The places view.
|
|
*/
|
|
// _view: null
|
|
//};
|
|
|
|
window.addEventListener("load", function() { CollectionsView.init() }, true);
|
|
window.addEventListener("unload", function() { CollectionsView.unload() }, true);
|