Try to fix trunk bustage, sync with RDF API changes.
This commit is contained in:
Родитель
7d6c58b9b3
Коммит
c0e3081817
|
@ -406,7 +406,7 @@
|
|||
isExpandable = YES;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> childProperty;
|
||||
mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty));
|
||||
mRDFService->GetResource(nsDependentCString("http://home.netscape.com/NC-rdf#child"), getter_AddRefs(childProperty));
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> childNodes;
|
||||
mDataSource->GetTargets(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNodes));
|
||||
|
@ -439,7 +439,7 @@
|
|||
- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> propertyResource;
|
||||
mRDFService->GetResource([inPropertyURI UTF8String], getter_AddRefs(propertyResource));
|
||||
mRDFService->GetResource(nsDependentCString([inPropertyURI UTF8String]), getter_AddRefs(propertyResource));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource = dont_AddRef([inItem resource]);
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
// Get the Global History DataSource
|
||||
mRDFService->GetDataSource("rdf:history", &mDataSource);
|
||||
// Get the Date Folder Root
|
||||
mRDFService->GetResource("NC:HistoryByDate", &mRootResource);
|
||||
mRDFService->GetResource(nsDependentCString("NC:HistoryByDate"), &mRootResource);
|
||||
|
||||
[mOutlineView setTarget: self];
|
||||
[mOutlineView setDoubleAction: @selector(openHistoryItem:)];
|
||||
|
|
|
@ -1,468 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ben Goodger <ben@netscape.com> (Original Author)
|
||||
*
|
||||
* 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 NPL, 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 NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "NSString+Utils.h"
|
||||
|
||||
#import "RDFOutlineViewDataSource.h"
|
||||
#import "CHBrowserService.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFLiteral.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIServiceManagerUtils.h"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsString.h"
|
||||
|
||||
|
||||
@interface RDFOutlineViewItem(Private)
|
||||
|
||||
- (unsigned int)cacheVersion;
|
||||
- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version;
|
||||
- (void)setChildren:(NSArray*)childArray;
|
||||
- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren;
|
||||
- (BOOL)cachedChildren;
|
||||
|
||||
- (BOOL)isExpandable;
|
||||
- (int)numChildren;
|
||||
- (id)childAtIndex:(int)index;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation RDFOutlineViewItem
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
mCacheVersion = 0;
|
||||
mExpandable = NO;
|
||||
mNumChildren = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[mChildNodes release];
|
||||
NS_IF_RELEASE(mResource);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (nsIRDFResource*)resource
|
||||
{
|
||||
NS_IF_ADDREF(mResource);
|
||||
return mResource;
|
||||
}
|
||||
|
||||
- (void)setResource:(nsIRDFResource*) aResource
|
||||
{
|
||||
nsIRDFResource* oldResource = mResource;
|
||||
NS_IF_ADDREF(mResource = aResource);
|
||||
NS_IF_RELEASE(oldResource);
|
||||
}
|
||||
|
||||
- (unsigned int)cacheVersion
|
||||
{
|
||||
return mCacheVersion;
|
||||
}
|
||||
|
||||
- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version;
|
||||
{
|
||||
mNumChildren = numChildren;
|
||||
mExpandable = expandable;
|
||||
mCacheVersion = version;
|
||||
}
|
||||
|
||||
- (void)setChildren:(NSArray*)childArray
|
||||
{
|
||||
// childArray can legally be nil here. If it is, we're clearing the cached children
|
||||
NSArray* oldChildren = mChildNodes;
|
||||
mChildNodes = childArray;
|
||||
[mChildNodes retain];
|
||||
[oldChildren release];
|
||||
}
|
||||
|
||||
- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren;
|
||||
{
|
||||
return (mCacheVersion == version) && (needChildren ? (mChildNodes != nil) : 1);
|
||||
}
|
||||
|
||||
- (BOOL)cachedChildren
|
||||
{
|
||||
return (mChildNodes != nil);
|
||||
}
|
||||
|
||||
- (BOOL)isExpandable
|
||||
{
|
||||
return mExpandable;
|
||||
}
|
||||
|
||||
- (int)numChildren
|
||||
{
|
||||
return mNumChildren;
|
||||
}
|
||||
|
||||
- (id)childAtIndex:(int)index
|
||||
{
|
||||
if (mChildNodes)
|
||||
return [mChildNodes objectAtIndex:index];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface RDFOutlineViewDataSource(Private)
|
||||
|
||||
- (void)registerForShutdownNotification;
|
||||
- (void)cleanup;
|
||||
- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RDFOutlineViewDataSource
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
[self registerForShutdownNotification];
|
||||
mCacheVersion = 1;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
[self cleanup];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)cleanup
|
||||
{
|
||||
NS_IF_RELEASE(mContainer);
|
||||
NS_IF_RELEASE(mContainerUtils);
|
||||
NS_IF_RELEASE(mRDFService);
|
||||
|
||||
NS_IF_RELEASE(mDataSource);
|
||||
NS_IF_RELEASE(mRootResource);
|
||||
|
||||
[mDictionary release];
|
||||
mDictionary = nil;
|
||||
}
|
||||
|
||||
- (void)cleanupDataSource
|
||||
{
|
||||
[self cleanup];
|
||||
}
|
||||
|
||||
//
|
||||
// ensureDataSourceLoaded
|
||||
//
|
||||
// defer loading all this rdf junk until it's requested because it's slow
|
||||
//
|
||||
- (void) ensureDataSourceLoaded
|
||||
{
|
||||
if ( !mContainer ) {
|
||||
nsCOMPtr<nsIRDFContainer> ctr = do_CreateInstance("@mozilla.org/rdf/container;1");
|
||||
NS_ADDREF(mContainer = ctr);
|
||||
|
||||
nsCOMPtr<nsIRDFContainerUtils> ctrUtils = do_GetService("@mozilla.org/rdf/container-utils;1");
|
||||
NS_ADDREF(mContainerUtils = ctrUtils);
|
||||
|
||||
nsCOMPtr<nsIRDFService> rdfService = do_GetService("@mozilla.org/rdf/rdf-service;1");
|
||||
NS_ADDREF(mRDFService = rdfService);
|
||||
|
||||
mDictionary = [[NSMutableDictionary alloc] initWithCapacity: 30];
|
||||
|
||||
mDataSource = nsnull;
|
||||
mRootResource = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)registerForShutdownNotification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(shutdown:)
|
||||
name: XPCOMShutDownNotificationName
|
||||
object: nil];
|
||||
}
|
||||
|
||||
- (void)shutdown: (NSNotification*)aNotification
|
||||
{
|
||||
[self cleanupDataSource];
|
||||
}
|
||||
|
||||
- (nsIRDFDataSource*) dataSource
|
||||
{
|
||||
NS_IF_ADDREF(mDataSource);
|
||||
return mDataSource;
|
||||
}
|
||||
|
||||
- (nsIRDFResource*) rootResource
|
||||
{
|
||||
NS_IF_ADDREF(mRootResource);
|
||||
return mRootResource;
|
||||
}
|
||||
|
||||
- (void) setDataSource: (nsIRDFDataSource*) aDataSource
|
||||
{
|
||||
nsIRDFDataSource* oldDataSource = mDataSource;
|
||||
NS_IF_ADDREF(mDataSource = aDataSource);
|
||||
NS_IF_RELEASE(oldDataSource);
|
||||
}
|
||||
|
||||
- (void) setRootResource: (nsIRDFResource*) aResource
|
||||
{
|
||||
nsIRDFResource* oldResource = mRootResource;
|
||||
NS_IF_ADDREF(mRootResource = aResource);
|
||||
NS_IF_RELEASE(oldResource);
|
||||
}
|
||||
|
||||
//
|
||||
// XXX - For now, we'll just say that none of our items are editable, as we aren't using any
|
||||
// RDF datasources that are mutable.
|
||||
//
|
||||
- (BOOL) outlineView: (NSOutlineView*)aOutlineView shouldEditTableColumn: (NSTableColumn*) aTableColumn
|
||||
item: (id) aItem
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) outlineView: (NSOutlineView*)aOutlineView isItemExpandable:(id)aItem
|
||||
{
|
||||
if (!mDataSource)
|
||||
return NO;
|
||||
|
||||
if (!aItem)
|
||||
return YES; // The root is always open
|
||||
|
||||
if (![aItem cacheValid:mCacheVersion needChildren:NO])
|
||||
[self updateItemProperties:aItem enumerateChildren:NO];
|
||||
|
||||
return [aItem isExpandable];
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView*)aOutlineView child:(int)aIndex ofItem:(id)aItem
|
||||
{
|
||||
if (!mDataSource)
|
||||
return nil;
|
||||
|
||||
if (!aItem)
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> rootResource = dont_AddRef([self rootResource]);
|
||||
aItem = [self getWrapperFor:rootResource];
|
||||
}
|
||||
|
||||
if (![aItem cacheValid:mCacheVersion needChildren:YES])
|
||||
[self updateItemProperties:aItem enumerateChildren:YES];
|
||||
|
||||
return [aItem childAtIndex:aIndex];
|
||||
}
|
||||
|
||||
- (int)outlineView:(NSOutlineView*)aOutlineView numberOfChildrenOfItem:(id) aItem;
|
||||
{
|
||||
if (!mDataSource)
|
||||
return 0;
|
||||
|
||||
if (!aItem)
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> rootResource = dont_AddRef([self rootResource]);
|
||||
aItem = [self getWrapperFor:rootResource];
|
||||
}
|
||||
|
||||
if (![aItem cacheValid:mCacheVersion needChildren:YES])
|
||||
[self updateItemProperties:aItem enumerateChildren:YES];
|
||||
|
||||
return [aItem numChildren];
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView*)aOutlineView objectValueForTableColumn:(NSTableColumn*)aTableColumn
|
||||
byItem:(id)aItem
|
||||
{
|
||||
if (!mDataSource || !aItem)
|
||||
return nil;
|
||||
|
||||
// The table column's identifier is the RDF Resource URI of the property being displayed in
|
||||
// that column, e.g. "http://home.netscape.com/NC-rdf#Name"
|
||||
NSString* columnPropertyURI = [aTableColumn identifier];
|
||||
NSString* propString = [self getPropertyString:columnPropertyURI forItem:aItem];
|
||||
|
||||
return [self createCellContents:propString withColumn:columnPropertyURI byItem:aItem];
|
||||
}
|
||||
|
||||
//
|
||||
// createCellContents:withColumn:byItem
|
||||
//
|
||||
// Constructs a NSString from the given string data for this item in the given column.
|
||||
// This should be overridden to do more fancy things, such as add an icon, etc.
|
||||
//
|
||||
- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id)inItem
|
||||
{
|
||||
return inValue;
|
||||
}
|
||||
|
||||
//
|
||||
// outlineView:tooltipForString
|
||||
//
|
||||
// returns the value of the Name property as the tooltip for the given item. Override to do
|
||||
// anything more complicated
|
||||
//
|
||||
- (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem
|
||||
{
|
||||
return [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:inItem];
|
||||
}
|
||||
|
||||
- (void) reloadDataForItem: (id) aItem reloadChildren: (BOOL) aReloadChildren
|
||||
{
|
||||
if (!aItem)
|
||||
[mOutlineView reloadData];
|
||||
else
|
||||
[mOutlineView reloadItem: aItem reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
- (id)getWrapperFor:(nsIRDFResource*) aRDFResource
|
||||
{
|
||||
const char* k;
|
||||
aRDFResource->GetValueConst(&k);
|
||||
NSString* key = [NSString stringWithCString:k];
|
||||
|
||||
// see if we've created a wrapper already, if not, create a new wrapper object
|
||||
// and stash it in our dictionary
|
||||
RDFOutlineViewItem* item = [mDictionary objectForKey:key];
|
||||
if (!item)
|
||||
{
|
||||
item = [[[RDFOutlineViewItem alloc] init] autorelease];
|
||||
[item setResource: aRDFResource];
|
||||
[mDictionary setObject:item forKey:key]; // retains |item|
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
- (void)invalidateCachedItems
|
||||
{
|
||||
mCacheVersion++;
|
||||
}
|
||||
|
||||
- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren
|
||||
{
|
||||
BOOL isExpandable = NO;
|
||||
NSMutableArray* itemChildren = doChildren ? [[[NSMutableArray alloc] initWithCapacity:10] autorelease] : nil;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> itemResource = dont_AddRef([item resource]);
|
||||
|
||||
PRBool isSeq = PR_FALSE;
|
||||
mContainerUtils->IsSeq(mDataSource, itemResource, &isSeq);
|
||||
if (isSeq)
|
||||
isExpandable = YES;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> childProperty;
|
||||
mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty));
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> childNodes;
|
||||
mDataSource->GetTargets(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNodes));
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
childNodes->GetNext(getter_AddRefs(supp));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> childResource = do_QueryInterface(supp);
|
||||
if (childResource)
|
||||
{
|
||||
id childItem = [self getWrapperFor:childResource];
|
||||
if (childItem)
|
||||
{
|
||||
isExpandable = YES;
|
||||
if (!itemChildren) break; // know enough already
|
||||
[itemChildren addObject:childItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// itemChildren will be nil here if we don't care about children, but that's OK.
|
||||
// the setChildren call will clear the cached child list.
|
||||
[item setNumChildren:[itemChildren count] isExpandable:isExpandable cacheVersion:mCacheVersion];
|
||||
[item setChildren:itemChildren];
|
||||
}
|
||||
|
||||
- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> propertyResource;
|
||||
mRDFService->GetResource([inPropertyURI UTF8String], getter_AddRefs(propertyResource));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource = dont_AddRef([inItem resource]);
|
||||
|
||||
nsCOMPtr<nsIRDFNode> valueNode;
|
||||
mDataSource->GetTarget(resource, propertyResource, PR_TRUE, getter_AddRefs(valueNode));
|
||||
if (!valueNode) {
|
||||
#if DEBUG
|
||||
NSLog(@"ValueNode is null in RDF objectValueForTableColumn");
|
||||
#endif
|
||||
return @"";
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> valueLiteral(do_QueryInterface(valueNode));
|
||||
if (!valueLiteral)
|
||||
return @"";
|
||||
|
||||
const PRUnichar* value = NULL;
|
||||
valueLiteral->GetValueConst(&value);
|
||||
if (value)
|
||||
return [NSString stringWithCharacters:value length:nsCRT::strlen(value)];
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
|
||||
@end
|
|
@ -1,460 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* 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 NPL, 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 NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "NSString+Utils.h"
|
||||
#import "NSPasteboard+Utils.h"
|
||||
|
||||
#import "BrowserWindowController.h"
|
||||
#import "HistoryDataSource.h"
|
||||
#import "CHBrowserView.h"
|
||||
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsIBrowserHistory.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
//
|
||||
// class HistoryDataSourceObserver
|
||||
//
|
||||
// An observer, enabled whenver the history panel in the drawer is selected. Tracks
|
||||
// changes to the RDF data source and pokes the history outline view
|
||||
//
|
||||
|
||||
class HistoryDataSourceObserver : public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
HistoryDataSourceObserver(HistoryDataSource* dataSource)
|
||||
: mHistoryDataSource(dataSource)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
virtual ~HistoryDataSourceObserver() { }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*);
|
||||
NS_IMETHOD OnUnassert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*);
|
||||
|
||||
NS_IMETHOD OnMove(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*)
|
||||
{ return NS_OK; }
|
||||
|
||||
NS_IMETHOD OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*, nsIRDFNode*);
|
||||
|
||||
NS_IMETHOD BeginUpdateBatch(nsIRDFDataSource*) { return NS_OK; }
|
||||
NS_IMETHOD EndUpdateBatch(nsIRDFDataSource*) { return NS_OK; }
|
||||
|
||||
private:
|
||||
|
||||
HistoryDataSource* mHistoryDataSource;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(HistoryDataSourceObserver, nsIRDFObserver)
|
||||
|
||||
|
||||
//
|
||||
// OnAssert
|
||||
//
|
||||
// Catches newly added items to the history, for surfing while the drawer is
|
||||
// open.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
HistoryDataSourceObserver::OnAssert(nsIRDFDataSource*, nsIRDFResource*,
|
||||
nsIRDFResource* aProperty, nsIRDFNode*)
|
||||
{
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mHistoryDataSource setNeedsRefresh:YES];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// OnUnassert
|
||||
//
|
||||
// This gets called on redirects, when nsGlobalHistory::RemovePage is called.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
HistoryDataSourceObserver::OnUnassert(nsIRDFDataSource*, nsIRDFResource*,
|
||||
nsIRDFResource* aProperty, nsIRDFNode*)
|
||||
{
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mHistoryDataSource setNeedsRefresh:YES];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// OnChange
|
||||
//
|
||||
// Catches items that are already in history, but need to be moved because you're
|
||||
// visiting them and they change date
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
||||
nsIRDFResource* aProperty, nsIRDFNode*, nsIRDFNode*)
|
||||
{
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mHistoryDataSource setNeedsRefresh:YES];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface HistoryDataSource(Private)
|
||||
|
||||
- (void)cleanupHistory;
|
||||
- (void)removeItemFromHistory:(id)inItem withService:(nsIBrowserHistory*)inHistService;
|
||||
|
||||
@end
|
||||
|
||||
@implementation HistoryDataSource
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self cleanupHistory];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// "non-virtual" cleanup method -- safe to call from dealloc.
|
||||
- (void)cleanupHistory
|
||||
{
|
||||
if (mDataSource && mObserver)
|
||||
{
|
||||
mDataSource->RemoveObserver(mObserver);
|
||||
NS_RELEASE(mObserver); // nulls it
|
||||
}
|
||||
}
|
||||
|
||||
// "virtual" method; called from superclass
|
||||
- (void)cleanupDataSource
|
||||
{
|
||||
[self cleanupHistory];
|
||||
[super cleanupDataSource];
|
||||
}
|
||||
|
||||
//
|
||||
// ensureDataSourceLoaded
|
||||
//
|
||||
// Called when the history panel is selected or brought into view. Inits all
|
||||
// the RDF-fu to make history go. We defer loading everything because it's
|
||||
// sorta slow and we don't want to take the hit when the user creates new windows
|
||||
// or just opens the bookmarks panel.
|
||||
//
|
||||
- (void) ensureDataSourceLoaded
|
||||
{
|
||||
[super ensureDataSourceLoaded];
|
||||
|
||||
NS_ASSERTION(mRDFService, "Uh oh, RDF service not loaded in parent class");
|
||||
|
||||
if ( !mDataSource )
|
||||
{
|
||||
// Get the Global History DataSource
|
||||
mRDFService->GetDataSource("rdf:history", &mDataSource);
|
||||
// Get the Date Folder Root
|
||||
mRDFService->GetResource("NC:HistoryByDate", &mRootResource);
|
||||
|
||||
[mOutlineView setTarget: self];
|
||||
[mOutlineView setDoubleAction: @selector(openHistoryItem:)];
|
||||
[mOutlineView setDeleteAction: @selector(deleteHistoryItems:)];
|
||||
|
||||
mObserver = new HistoryDataSourceObserver(self);
|
||||
if ( mObserver ) {
|
||||
NS_ADDREF(mObserver);
|
||||
mDataSource->AddObserver(mObserver);
|
||||
}
|
||||
[mOutlineView reloadData];
|
||||
}
|
||||
else
|
||||
{
|
||||
// everything is loaded, but we have to refresh our tree otherwise
|
||||
// changes that took place while the drawer was closed won't be noticed
|
||||
[mOutlineView reloadData];
|
||||
}
|
||||
|
||||
NS_ASSERTION(mDataSource, "Uh oh, History RDF Data source not created");
|
||||
}
|
||||
|
||||
- (void)enableObserver
|
||||
{
|
||||
mUpdatesEnabled = YES;
|
||||
}
|
||||
|
||||
-(void)disableObserver
|
||||
{
|
||||
mUpdatesEnabled = NO;
|
||||
}
|
||||
|
||||
- (void)setNeedsRefresh:(BOOL)needsRefresh
|
||||
{
|
||||
mNeedsRefresh = needsRefresh;
|
||||
}
|
||||
|
||||
- (BOOL)needsRefresh
|
||||
{
|
||||
return mNeedsRefresh;
|
||||
}
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
if (mNeedsRefresh)
|
||||
{
|
||||
[self invalidateCachedItems];
|
||||
if (mUpdatesEnabled)
|
||||
{
|
||||
// this can be very slow! See bug 180109.
|
||||
//NSLog(@"history reload started");
|
||||
[self reloadDataForItem:nil reloadChildren:NO];
|
||||
//NSLog(@"history reload done");
|
||||
}
|
||||
mNeedsRefresh = NO;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// createCellContents:withColumn:byItem
|
||||
//
|
||||
// override to create an NSAttributedString instead of just the string with the
|
||||
// given text. We add an icon and adjust the positioning of the text w/in the cell
|
||||
//
|
||||
-(id) createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem
|
||||
{
|
||||
if ([inValue length] == 0)
|
||||
inValue = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem];
|
||||
|
||||
NSMutableAttributedString *cellValue = [[[NSMutableAttributedString alloc] initWithString:inValue] autorelease];
|
||||
|
||||
if ([inColumn isEqualToString:@"http://home.netscape.com/NC-rdf#Name"])
|
||||
{
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
|
||||
// Create an attributed string to hold the empty attachment, then release the components.
|
||||
NSMutableAttributedString *attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment];
|
||||
[textAttachment release];
|
||||
[fileWrapper release];
|
||||
|
||||
//Get the cell of the text attachment.
|
||||
NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:
|
||||
NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
|
||||
|
||||
if ([self outlineView:mOutlineView isItemExpandable:inItem])
|
||||
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]];
|
||||
else
|
||||
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]];
|
||||
|
||||
//Insert the image
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString];
|
||||
|
||||
//Tweak the baseline to vertically center the text.
|
||||
[cellValue addAttribute:NSBaselineOffsetAttributeName
|
||||
value:[NSNumber numberWithFloat:-5.0]
|
||||
range:NSMakeRange(0, 1)];
|
||||
}
|
||||
|
||||
return cellValue;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// filterDragItems:
|
||||
//
|
||||
// Walk the list of items, filtering out any folder. Returns a new list
|
||||
// that has been autoreleased.
|
||||
//
|
||||
- (NSArray*)filterDragItems:(NSArray*)inItems
|
||||
{
|
||||
NSMutableArray* outItems = [[[NSMutableArray alloc] init] autorelease];
|
||||
|
||||
NSEnumerator *enumerator = [inItems objectEnumerator];
|
||||
id obj;
|
||||
while ( (obj = [enumerator nextObject]) ) {
|
||||
if ( ! [mOutlineView isExpandable: obj] ) // if it's not a folder, we can drag it
|
||||
[outItems addObject:obj];
|
||||
}
|
||||
|
||||
return outItems;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
//Need to filter out folders from the list, only allow the urls to be dragged
|
||||
NSArray *toDrag = [self filterDragItems:items];
|
||||
|
||||
int count = [toDrag count];
|
||||
if (count > 0) {
|
||||
if (count == 1) {
|
||||
id item = [toDrag objectAtIndex: 0];
|
||||
|
||||
// if we have just one item, we add some more flavours
|
||||
NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item];
|
||||
NSString* title = [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:item];
|
||||
NSString *cleanedTitle = [title stringByReplacingCharactersInSet:[NSCharacterSet controlCharacterSet] withString:@" "];
|
||||
|
||||
[pboard declareURLPasteboardWithAdditionalTypes:[NSArray array] owner:self];
|
||||
[pboard setDataForURL:url title:cleanedTitle];
|
||||
}
|
||||
else {
|
||||
// not sure what to do here. canceling the drag for now.
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
-(IBAction)openHistoryItem: (id)aSender
|
||||
{
|
||||
int index = [mOutlineView selectedRow];
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
id item = [mOutlineView itemAtRow: index];
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
// expand if collapsed and double click
|
||||
if ([mOutlineView isExpandable: item]) {
|
||||
if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView collapseItem: item];
|
||||
else
|
||||
[mOutlineView expandItem: item];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// get uri
|
||||
NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item];
|
||||
[[mBrowserWindowController getBrowserWrapper] loadURI: url referrer: nil flags: NSLoadFlagsNone activate:YES];
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// deleteHistoryItems:
|
||||
//
|
||||
// Called when user hits backspace with the history view selected. Walks the selection
|
||||
// removing the selected items from the global history in batch-mode, then reloads
|
||||
// the outline.
|
||||
//
|
||||
-(IBAction)deleteHistoryItems: (id)aSender
|
||||
{
|
||||
int index = [mOutlineView selectedRow];
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
// if the user selected a bunch of rows, we want to clear the selection since when
|
||||
// those rows are deleted, the tree will try to keep the same # of rows selected and
|
||||
// it will look really odd. If just 1 row was selected, we keep it around so the user
|
||||
// can keep quickly deleting one row at a time.
|
||||
BOOL clearSelectionWhenDone = [mOutlineView numberOfSelectedRows] > 1;
|
||||
|
||||
nsCOMPtr<nsIBrowserHistory> history = do_GetService("@mozilla.org/browser/global-history;1");
|
||||
if ( history ) {
|
||||
// Even though it looks like relying on row numbers as we delete will get us in trouble
|
||||
// and out of sync, until we actually invalidate the table, the rows keep their prior values.
|
||||
// If children are selected as well as the parent, we'll just end up trying to remove the
|
||||
// host string from history which will silently fail. It's extra work, but harmless.
|
||||
history->StartBatchUpdate();
|
||||
NSEnumerator* rowEnum = [mOutlineView selectedRowEnumerator];
|
||||
for ( NSNumber* currIndex = [rowEnum nextObject]; currIndex; currIndex = [rowEnum nextObject]) {
|
||||
index = [currIndex intValue];
|
||||
RDFOutlineViewItem* item = [mOutlineView itemAtRow: index];
|
||||
if ([mOutlineView isExpandable: item]) {
|
||||
// delete a folder by iterating over each of its children and deleting them. There
|
||||
// should be a better way, but the history api's don't really support them. Expand
|
||||
// the folder before we delete it otherwise we don't get any child nodes to delete.
|
||||
[mOutlineView expandItem:item];
|
||||
NSEnumerator* childEnum = [item->mChildNodes objectEnumerator];
|
||||
RDFOutlineViewItem* currChild = nil;
|
||||
while ( (currChild = [childEnum nextObject]) )
|
||||
[self removeItemFromHistory:currChild withService:history];
|
||||
}
|
||||
else
|
||||
[self removeItemFromHistory:item withService:history];
|
||||
}
|
||||
history->EndBatchUpdate();
|
||||
if ( clearSelectionWhenDone )
|
||||
[mOutlineView deselectAll:self];
|
||||
|
||||
[self invalidateCachedItems];
|
||||
[mOutlineView reloadData]; // necessary or the outline is really horked
|
||||
}
|
||||
}
|
||||
|
||||
-(void)removeItemFromHistory:(id)inItem withService:(nsIBrowserHistory*)inHistService;
|
||||
{
|
||||
NSString* urlString = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem];
|
||||
inHistService->RemovePage([urlString UTF8String]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// outlineView:tooltipForString
|
||||
//
|
||||
// Only show a tooltip if we're not a folder. For urls, use title\nurl as the format.
|
||||
// We can re-use the base-class impl to get the title of the page and then just add on
|
||||
// to that.
|
||||
//
|
||||
- (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem
|
||||
{
|
||||
if ( ! [mOutlineView isExpandable: inItem] ) {
|
||||
// use baseclass to get title of page
|
||||
NSString* pageTitle = [super outlineView:outlineView tooltipStringForItem:inItem];
|
||||
|
||||
// append url
|
||||
NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem];
|
||||
return [NSString stringWithFormat:@"%@\n%@", pageTitle, [url stringByTruncatingTo:80 at:kTruncateAtEnd]];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
Загрузка…
Ссылка в новой задаче