tweak history impl so as not to require opening and resaving history just to append
This commit is contained in:
parent
8046fb8af2
commit
544ae837d5
|
@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
@interface AppDelegate: NSResponder<NSApplicationDelegate> {
|
||||
@private
|
||||
NSMutableArray *recentHistory;
|
||||
id downloadsWindowController;
|
||||
id findPanelController;
|
||||
id historyWindowController;
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#import "HistoryWindowController.h"
|
||||
#import "Website.h"
|
||||
|
||||
#define MAX_RECENT_HISTORY 6
|
||||
|
||||
/**
|
||||
* Set option defaults for (taken from the cocoa frontend)
|
||||
*
|
||||
|
@ -43,26 +45,26 @@ static nserror set_defaults(struct nsoption_s *defaults)
|
|||
}
|
||||
|
||||
-(void)historyUpdated: (NSNotification*)aNotification {
|
||||
NSLog(@"history updated...");
|
||||
NSArray *history = [Website historicWebsites];
|
||||
NSLog(@"history updated... %@", aNotification);
|
||||
id object = [aNotification object];
|
||||
NSMenu *historyMenu = [[[NSApp menu] itemWithTag: TAG_SUBMENU_HISTORY] submenu];
|
||||
for (NSInteger i = [historyMenu numberOfItems] - 1; i > 0; i--) {
|
||||
[historyMenu removeItemAtIndex: i];
|
||||
}
|
||||
Website *website;
|
||||
NSMenuItem *menuItem;
|
||||
for (NSInteger i = 0; i < [history count] && i < 5; i++) {
|
||||
website = [history objectAtIndex: i];
|
||||
menuItem = [[[NSMenuItem alloc] initWithTitle: [website name]
|
||||
|
||||
if ([object isKindOfClass: [Website class]]) {
|
||||
[recentHistory insertObject: object atIndex: 0];
|
||||
NSMenuItem *menuItem = [[[NSMenuItem alloc] initWithTitle: [object name]
|
||||
action: @selector(open) keyEquivalent: nil] autorelease];
|
||||
[menuItem setTarget: website];
|
||||
[historyMenu addItem: menuItem];
|
||||
[menuItem setTarget: object];
|
||||
[historyMenu insertItem: menuItem atIndex: 1];
|
||||
if ([recentHistory count] > MAX_RECENT_HISTORY) {
|
||||
[recentHistory removeLastObject];
|
||||
[historyMenu removeItemAtIndex: [historyMenu numberOfItems] - 1];
|
||||
}
|
||||
}
|
||||
[historyMenu update];
|
||||
}
|
||||
|
||||
-(void)awakeFromNib {
|
||||
NSLog(@"App awake from nib");
|
||||
recentHistory = [[NSMutableArray alloc] init];
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(historyUpdated:)
|
||||
name: WebsiteHistoryUpdatedNotificationName
|
||||
|
@ -127,7 +129,7 @@ static nserror set_defaults(struct nsoption_s *defaults)
|
|||
struct nsurl *url;
|
||||
nserror error;
|
||||
|
||||
error = nsurl_create([[[aWebsite url] absoluteString] cString], &url);
|
||||
error = nsurl_create([[aWebsite url] cString], &url);
|
||||
if (error == NSERROR_OK) {
|
||||
error = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL);
|
||||
nsurl_unref(url);
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
NSString *name = [NSString stringWithCString: title];
|
||||
NSString *urlStr = [NSString stringWithCString: nsurl_access(url)];
|
||||
Website *website = [[Website alloc] initWithName: name
|
||||
url: [NSURL URLWithString: urlStr]];
|
||||
url: urlStr];
|
||||
[website addToHistory];
|
||||
[website release];
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
@interface HistoryWindowController: NSWindowController {
|
||||
id outlineView;
|
||||
BOOL ignoreRefresh;
|
||||
NSMutableDictionary *historyItems;
|
||||
NSArray *sections;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,28 +1,63 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "HistoryWindowController.h"
|
||||
#import "Website.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "desktop/global_history.h"
|
||||
|
||||
@interface Section: NSObject {
|
||||
NSString *name;
|
||||
NSArray *items;
|
||||
}
|
||||
@end
|
||||
@implementation Section
|
||||
+(id)sectionWithName: (NSString*)aName items: (NSArray*)someItems {
|
||||
Section *section = [[[Section alloc] init] autorelease];
|
||||
section->name = [aName retain];
|
||||
section->items = [someItems retain];
|
||||
return section;
|
||||
}
|
||||
-(NSString*)name {
|
||||
return name;
|
||||
}
|
||||
-(NSArray*)items {
|
||||
return items;
|
||||
}
|
||||
-(void)setItems: (NSArray*)someItems {
|
||||
[items release];
|
||||
items = [someItems retain];
|
||||
}
|
||||
-(void)dealloc {
|
||||
[name release];
|
||||
[items release];
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation HistoryWindowController
|
||||
|
||||
-(id)init {
|
||||
if (self = [super initWithWindowNibName: @"History"]) {
|
||||
historyItems = [[NSMutableDictionary alloc] init];
|
||||
[historyItems setObject: [Website historicWebsites] forKey: @"recent"];
|
||||
ignoreRefresh = NO;
|
||||
sections = [[NSArray arrayWithObjects: [Section sectionWithName: @"Recent"
|
||||
items: [NSArray array]], [Section sectionWithName:
|
||||
@"More than 2 months ago..." items: [NSArray array]], nil]
|
||||
retain];
|
||||
[self updateItems: nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
[historyItems release];
|
||||
[sections release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
-(void)updateItems: (NSNotification*)aNotification {
|
||||
if (!ignoreRefresh) {
|
||||
[historyItems setObject: [Website historicWebsites] forKey: @"recent"];
|
||||
[[sections objectAtIndex: 0] setItems: [NSArray array]];
|
||||
[[sections objectAtIndex: 1] setItems: [NSArray array]];
|
||||
[outlineView reloadData];
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +82,7 @@
|
|||
-(void)awakeFromNib {
|
||||
[[self window] makeKeyAndOrderFront: self];
|
||||
[self registerForHistoryNotifications];
|
||||
[outlineView expandItem: [[historyItems allValues] firstObject] expandChildren: NO];
|
||||
[outlineView expandItem: [sections firstObject] expandChildren: NO];
|
||||
}
|
||||
|
||||
-(BOOL)validateMenuItem: (NSMenuItem*)aMenuItem {
|
||||
|
@ -99,14 +134,14 @@
|
|||
|
||||
-(id)outlineView: (NSOutlineView*)outlineView child: (NSInteger)index ofItem: (id)item {
|
||||
if (item == nil) {
|
||||
return [[historyItems allValues] firstObject];
|
||||
return [sections objectAtIndex: index];
|
||||
} else {
|
||||
return [item objectAtIndex: index];
|
||||
return [[item items] objectAtIndex: index];
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL)outlineView: (NSOutlineView*)outlineView isItemExpandable: (id)item {
|
||||
if ([item isKindOfClass: [NSArray class]]) {
|
||||
if ([item isKindOfClass: [Section class]]) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
|
@ -115,20 +150,16 @@
|
|||
|
||||
-(NSInteger)outlineView: (NSOutlineView*)outlineView numberOfChildrenOfItem: (id)item {
|
||||
if (item == nil) {
|
||||
return 1;
|
||||
return [sections count];
|
||||
} else if ([item isKindOfClass: [Section class]]) {
|
||||
return [[item items] count];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return [item count];
|
||||
}
|
||||
|
||||
-(id)outlineView: (NSOutlineView*)outlineView objectValueForTableColumn: (NSTableColumn*)tableColumn byItem: (id)item {
|
||||
if ([item isKindOfClass: [NSArray class]]) {
|
||||
return @"Recent History";
|
||||
} else if ([item isKindOfClass: [Website class]]) {
|
||||
return [item name];
|
||||
} else {
|
||||
NSLog(@"clas: %@", [item class]);
|
||||
return @"Error";
|
||||
}
|
||||
return [item name];
|
||||
}
|
||||
|
||||
-(BOOL)outlineView: (NSOutlineView*)outlineView shouldSelectItem: (id)item {
|
||||
|
|
|
@ -2,21 +2,21 @@
|
|||
|
||||
#define WebsiteHistoryUpdatedNotificationName @"WebsiteHistoryUpdatedNotification"
|
||||
|
||||
struct website_data {
|
||||
int len_name;
|
||||
int len_url;
|
||||
char data[];
|
||||
};
|
||||
|
||||
@class BookmarkFolder;
|
||||
@interface Website: NSObject {
|
||||
NSString *name;
|
||||
NSURL *url;
|
||||
NSDate *lastVisited;
|
||||
struct website_data *data;
|
||||
}
|
||||
|
||||
-(id)initWithName: (NSString*)aName url: (NSURL*)aUrl;
|
||||
-(id)initWithName: (NSString*)aName url: (NSString*)aUrl;
|
||||
-(NSString*)name;
|
||||
-(NSURL*)url;
|
||||
-(NSString*)url;
|
||||
|
||||
-(void)open;
|
||||
|
||||
-(void)addToHistory;
|
||||
-(void)removeFromHistory;
|
||||
+(NSArray*)historicWebsites;
|
||||
|
||||
@end
|
|
@ -1,36 +1,50 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#import <stdio.h>
|
||||
#import <string.h>
|
||||
#import <errno.h>
|
||||
|
||||
#import "Website.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#define HISTORY_PATH @".cache/NetSurf"
|
||||
#define HISTORY_PATH @"/.cache/NetSurf"
|
||||
|
||||
static NSMutableArray *history;
|
||||
static NSMutableArray *recentHistory;
|
||||
static NSMutableArray *olderHistory;
|
||||
|
||||
@implementation Website
|
||||
|
||||
-(id)initWithName: (NSString*)aName url: (NSURL*)aUrl {
|
||||
-(id)initWithName: (NSString*)aName url: (NSString*)aUrl {
|
||||
if (self = [super init]) {
|
||||
[aName retain];
|
||||
[aUrl retain];
|
||||
name = aName;
|
||||
url = aUrl;
|
||||
lastVisited = nil;
|
||||
int nlen = [aName length];
|
||||
int urlen = [aUrl length];
|
||||
data = malloc(sizeof (struct website_data) + nlen + urlen);
|
||||
data->len_name = nlen;
|
||||
data->len_url = urlen;
|
||||
memcpy(data->data, [aName cString], nlen);
|
||||
memcpy(data->data + nlen, [aUrl cString], urlen);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(id)initWithData: (struct website_data*)someData {
|
||||
if (self = [super init]) {
|
||||
data = someData;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc {
|
||||
[name release];
|
||||
[url release];
|
||||
[lastVisited release];
|
||||
free(data);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(NSString*)name {
|
||||
return name;
|
||||
return [NSString stringWithCString: data->data length: data->len_name];
|
||||
}
|
||||
|
||||
-(NSURL*)url {
|
||||
return url;
|
||||
-(NSString*)url {
|
||||
return [NSString stringWithCString: data->data + data->len_name length:
|
||||
data->len_url];
|
||||
}
|
||||
|
||||
-(void)open {
|
||||
|
@ -39,90 +53,26 @@ static NSMutableArray *history;
|
|||
|
||||
// MARK: - History implementation
|
||||
|
||||
+(id)websiteWithDictionary: (NSDictionary*)dictionary {
|
||||
Website *ret = [[[Website alloc] init] autorelease];
|
||||
if (ret != nil) {
|
||||
ret->name = [dictionary objectForKey: @"name"];
|
||||
[ret->name retain];
|
||||
ret->url = [NSURL URLWithString: [dictionary objectForKey: @"url"]];
|
||||
[ret->url retain];
|
||||
ret->lastVisited = [NSDate dateWithTimeIntervalSince1970: [[dictionary
|
||||
objectForKey: @"date"] doubleValue]];
|
||||
[ret->lastVisited retain];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
-(NSDictionary*)toDictionary {
|
||||
return [NSDictionary dictionaryWithObjectsAndKeys: name, @"name",
|
||||
[url absoluteString], @"url",
|
||||
[NSNumber numberWithDouble: [lastVisited timeIntervalSince1970]], @"date",
|
||||
nil];
|
||||
}
|
||||
|
||||
+(void)saveHistoryToDisk {
|
||||
NSLog(@"Save history to disk");
|
||||
if (history == nil) {
|
||||
return;
|
||||
}
|
||||
NSError *error = nil;
|
||||
NSDictionary *attrs = [NSDictionary dictionary];
|
||||
BOOL ok = [[NSFileManager defaultManager] createDirectoryAtPath: [NSString
|
||||
pathWithComponents: [NSArray arrayWithObjects: NSHomeDirectory(),
|
||||
HISTORY_PATH, nil]] withIntermediateDirectories: YES attributes: attrs
|
||||
error: &error];
|
||||
if (!ok) {
|
||||
NSLog(@"Error creating cache dir!");
|
||||
}
|
||||
NSMutableArray *toSave = [NSMutableArray array];
|
||||
for (NSUInteger i = 0; i < [history count]; i++) {
|
||||
[toSave addObject: [[history objectAtIndex: i] toDictionary]];
|
||||
}
|
||||
ok = [toSave writeToFile: [NSString pathWithComponents: [NSArray
|
||||
arrayWithObjects: NSHomeDirectory(), HISTORY_PATH, @"history", nil]]
|
||||
atomically: YES];
|
||||
if (!ok) {
|
||||
NSLog(@"Failed to save latest history to file");
|
||||
}
|
||||
}
|
||||
|
||||
+(void)initHistoryIfNeeded {
|
||||
if (history == nil) {
|
||||
NSArray *historyDicts = [NSMutableArray arrayWithContentsOfFile:
|
||||
[NSString pathWithComponents: [NSArray arrayWithObjects:
|
||||
NSHomeDirectory(), HISTORY_PATH, @"history", nil]]];
|
||||
history = [[NSMutableArray alloc] init];
|
||||
for (NSUInteger i = 0; i < [historyDicts count]; i++) {
|
||||
[history addObject: [Website websiteWithDictionary: [historyDicts
|
||||
objectAtIndex: i]]];
|
||||
}
|
||||
[[NSNotificationCenter defaultCenter] addObserver: [self class]
|
||||
selector: @selector(saveHistoryToDisk)
|
||||
name: NSApplicationWillTerminateNotification
|
||||
object: nil];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)removeFromHistory {
|
||||
NSLog(@"remove self from history");
|
||||
[history removeObject: self];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:
|
||||
WebsiteHistoryUpdatedNotificationName object: nil];
|
||||
}
|
||||
|
||||
-(void)addToHistory {
|
||||
[Website initHistoryIfNeeded];
|
||||
[lastVisited release];
|
||||
lastVisited = [[NSDate alloc] init];
|
||||
[history insertObject: self atIndex: 0];
|
||||
NSLog(@"Added %@ , %@ to history!", [self name], [self url]);
|
||||
static NSString *path = nil;
|
||||
if (path == nil) {
|
||||
NSCalendarDate *date = [NSCalendarDate calendarDate];
|
||||
int month = [date monthOfYear];
|
||||
int year = [date yearOfCommonEra];
|
||||
path = [[NSString alloc] initWithFormat: @"%@/%@/history_%d_%d",
|
||||
NSHomeDirectory(), HISTORY_PATH, year, month];
|
||||
}
|
||||
NSLog(@"name: %@", [self name]);
|
||||
NSLog(@"url: %@", [self url]);
|
||||
FILE *f = fopen([path cString], "a");
|
||||
if (f != NULL) {
|
||||
int len = sizeof (struct website_data) + data->len_url + data->len_name;
|
||||
fwrite(data, len, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:
|
||||
WebsiteHistoryUpdatedNotificationName object: self];
|
||||
}
|
||||
|
||||
+(NSArray*)historicWebsites {
|
||||
[Website initHistoryIfNeeded];
|
||||
return history;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue