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> {
|
@interface AppDelegate: NSResponder<NSApplicationDelegate> {
|
||||||
@private
|
@private
|
||||||
|
NSMutableArray *recentHistory;
|
||||||
id downloadsWindowController;
|
id downloadsWindowController;
|
||||||
id findPanelController;
|
id findPanelController;
|
||||||
id historyWindowController;
|
id historyWindowController;
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#import "HistoryWindowController.h"
|
#import "HistoryWindowController.h"
|
||||||
#import "Website.h"
|
#import "Website.h"
|
||||||
|
|
||||||
|
#define MAX_RECENT_HISTORY 6
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set option defaults for (taken from the cocoa frontend)
|
* 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 {
|
-(void)historyUpdated: (NSNotification*)aNotification {
|
||||||
NSLog(@"history updated...");
|
NSLog(@"history updated... %@", aNotification);
|
||||||
NSArray *history = [Website historicWebsites];
|
id object = [aNotification object];
|
||||||
NSMenu *historyMenu = [[[NSApp menu] itemWithTag: TAG_SUBMENU_HISTORY] submenu];
|
NSMenu *historyMenu = [[[NSApp menu] itemWithTag: TAG_SUBMENU_HISTORY] submenu];
|
||||||
for (NSInteger i = [historyMenu numberOfItems] - 1; i > 0; i--) {
|
|
||||||
[historyMenu removeItemAtIndex: i];
|
if ([object isKindOfClass: [Website class]]) {
|
||||||
}
|
[recentHistory insertObject: object atIndex: 0];
|
||||||
Website *website;
|
NSMenuItem *menuItem = [[[NSMenuItem alloc] initWithTitle: [object name]
|
||||||
NSMenuItem *menuItem;
|
|
||||||
for (NSInteger i = 0; i < [history count] && i < 5; i++) {
|
|
||||||
website = [history objectAtIndex: i];
|
|
||||||
menuItem = [[[NSMenuItem alloc] initWithTitle: [website name]
|
|
||||||
action: @selector(open) keyEquivalent: nil] autorelease];
|
action: @selector(open) keyEquivalent: nil] autorelease];
|
||||||
[menuItem setTarget: website];
|
[menuItem setTarget: object];
|
||||||
[historyMenu addItem: menuItem];
|
[historyMenu insertItem: menuItem atIndex: 1];
|
||||||
|
if ([recentHistory count] > MAX_RECENT_HISTORY) {
|
||||||
|
[recentHistory removeLastObject];
|
||||||
|
[historyMenu removeItemAtIndex: [historyMenu numberOfItems] - 1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[historyMenu update];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)awakeFromNib {
|
-(void)awakeFromNib {
|
||||||
NSLog(@"App awake from nib");
|
NSLog(@"App awake from nib");
|
||||||
|
recentHistory = [[NSMutableArray alloc] init];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||||
selector: @selector(historyUpdated:)
|
selector: @selector(historyUpdated:)
|
||||||
name: WebsiteHistoryUpdatedNotificationName
|
name: WebsiteHistoryUpdatedNotificationName
|
||||||
|
@ -127,7 +129,7 @@ static nserror set_defaults(struct nsoption_s *defaults)
|
||||||
struct nsurl *url;
|
struct nsurl *url;
|
||||||
nserror error;
|
nserror error;
|
||||||
|
|
||||||
error = nsurl_create([[[aWebsite url] absoluteString] cString], &url);
|
error = nsurl_create([[aWebsite url] cString], &url);
|
||||||
if (error == NSERROR_OK) {
|
if (error == NSERROR_OK) {
|
||||||
error = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL);
|
error = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL);
|
||||||
nsurl_unref(url);
|
nsurl_unref(url);
|
||||||
|
|
|
@ -131,7 +131,7 @@
|
||||||
NSString *name = [NSString stringWithCString: title];
|
NSString *name = [NSString stringWithCString: title];
|
||||||
NSString *urlStr = [NSString stringWithCString: nsurl_access(url)];
|
NSString *urlStr = [NSString stringWithCString: nsurl_access(url)];
|
||||||
Website *website = [[Website alloc] initWithName: name
|
Website *website = [[Website alloc] initWithName: name
|
||||||
url: [NSURL URLWithString: urlStr]];
|
url: urlStr];
|
||||||
[website addToHistory];
|
[website addToHistory];
|
||||||
[website release];
|
[website release];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
@interface HistoryWindowController: NSWindowController {
|
@interface HistoryWindowController: NSWindowController {
|
||||||
id outlineView;
|
id outlineView;
|
||||||
BOOL ignoreRefresh;
|
BOOL ignoreRefresh;
|
||||||
NSMutableDictionary *historyItems;
|
NSArray *sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -1,28 +1,63 @@
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
#import "HistoryWindowController.h"
|
#import "HistoryWindowController.h"
|
||||||
#import "Website.h"
|
#import "Website.h"
|
||||||
#import "AppDelegate.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
|
@implementation HistoryWindowController
|
||||||
|
|
||||||
-(id)init {
|
-(id)init {
|
||||||
if (self = [super initWithWindowNibName: @"History"]) {
|
if (self = [super initWithWindowNibName: @"History"]) {
|
||||||
historyItems = [[NSMutableDictionary alloc] init];
|
|
||||||
[historyItems setObject: [Website historicWebsites] forKey: @"recent"];
|
|
||||||
ignoreRefresh = NO;
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)dealloc {
|
-(void)dealloc {
|
||||||
[historyItems release];
|
[sections release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
-(void)updateItems: (NSNotification*)aNotification {
|
-(void)updateItems: (NSNotification*)aNotification {
|
||||||
if (!ignoreRefresh) {
|
if (!ignoreRefresh) {
|
||||||
[historyItems setObject: [Website historicWebsites] forKey: @"recent"];
|
[[sections objectAtIndex: 0] setItems: [NSArray array]];
|
||||||
|
[[sections objectAtIndex: 1] setItems: [NSArray array]];
|
||||||
[outlineView reloadData];
|
[outlineView reloadData];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +82,7 @@
|
||||||
-(void)awakeFromNib {
|
-(void)awakeFromNib {
|
||||||
[[self window] makeKeyAndOrderFront: self];
|
[[self window] makeKeyAndOrderFront: self];
|
||||||
[self registerForHistoryNotifications];
|
[self registerForHistoryNotifications];
|
||||||
[outlineView expandItem: [[historyItems allValues] firstObject] expandChildren: NO];
|
[outlineView expandItem: [sections firstObject] expandChildren: NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL)validateMenuItem: (NSMenuItem*)aMenuItem {
|
-(BOOL)validateMenuItem: (NSMenuItem*)aMenuItem {
|
||||||
|
@ -99,14 +134,14 @@
|
||||||
|
|
||||||
-(id)outlineView: (NSOutlineView*)outlineView child: (NSInteger)index ofItem: (id)item {
|
-(id)outlineView: (NSOutlineView*)outlineView child: (NSInteger)index ofItem: (id)item {
|
||||||
if (item == nil) {
|
if (item == nil) {
|
||||||
return [[historyItems allValues] firstObject];
|
return [sections objectAtIndex: index];
|
||||||
} else {
|
} else {
|
||||||
return [item objectAtIndex: index];
|
return [[item items] objectAtIndex: index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL)outlineView: (NSOutlineView*)outlineView isItemExpandable: (id)item {
|
-(BOOL)outlineView: (NSOutlineView*)outlineView isItemExpandable: (id)item {
|
||||||
if ([item isKindOfClass: [NSArray class]]) {
|
if ([item isKindOfClass: [Section class]]) {
|
||||||
return YES;
|
return YES;
|
||||||
} else {
|
} else {
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -115,20 +150,16 @@
|
||||||
|
|
||||||
-(NSInteger)outlineView: (NSOutlineView*)outlineView numberOfChildrenOfItem: (id)item {
|
-(NSInteger)outlineView: (NSOutlineView*)outlineView numberOfChildrenOfItem: (id)item {
|
||||||
if (item == nil) {
|
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 {
|
-(id)outlineView: (NSOutlineView*)outlineView objectValueForTableColumn: (NSTableColumn*)tableColumn byItem: (id)item {
|
||||||
if ([item isKindOfClass: [NSArray class]]) {
|
return [item name];
|
||||||
return @"Recent History";
|
|
||||||
} else if ([item isKindOfClass: [Website class]]) {
|
|
||||||
return [item name];
|
|
||||||
} else {
|
|
||||||
NSLog(@"clas: %@", [item class]);
|
|
||||||
return @"Error";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL)outlineView: (NSOutlineView*)outlineView shouldSelectItem: (id)item {
|
-(BOOL)outlineView: (NSOutlineView*)outlineView shouldSelectItem: (id)item {
|
||||||
|
|
|
@ -2,21 +2,21 @@
|
||||||
|
|
||||||
#define WebsiteHistoryUpdatedNotificationName @"WebsiteHistoryUpdatedNotification"
|
#define WebsiteHistoryUpdatedNotificationName @"WebsiteHistoryUpdatedNotification"
|
||||||
|
|
||||||
|
struct website_data {
|
||||||
|
int len_name;
|
||||||
|
int len_url;
|
||||||
|
char data[];
|
||||||
|
};
|
||||||
|
|
||||||
@class BookmarkFolder;
|
@class BookmarkFolder;
|
||||||
@interface Website: NSObject {
|
@interface Website: NSObject {
|
||||||
NSString *name;
|
struct website_data *data;
|
||||||
NSURL *url;
|
|
||||||
NSDate *lastVisited;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(id)initWithName: (NSString*)aName url: (NSURL*)aUrl;
|
-(id)initWithName: (NSString*)aName url: (NSString*)aUrl;
|
||||||
-(NSString*)name;
|
-(NSString*)name;
|
||||||
-(NSURL*)url;
|
-(NSString*)url;
|
||||||
|
|
||||||
-(void)open;
|
-(void)open;
|
||||||
|
|
||||||
-(void)addToHistory;
|
-(void)addToHistory;
|
||||||
-(void)removeFromHistory;
|
|
||||||
+(NSArray*)historicWebsites;
|
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -1,36 +1,50 @@
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <stdio.h>
|
||||||
|
#import <string.h>
|
||||||
|
#import <errno.h>
|
||||||
|
|
||||||
#import "Website.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
|
@implementation Website
|
||||||
|
|
||||||
-(id)initWithName: (NSString*)aName url: (NSURL*)aUrl {
|
-(id)initWithName: (NSString*)aName url: (NSString*)aUrl {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
[aName retain];
|
int nlen = [aName length];
|
||||||
[aUrl retain];
|
int urlen = [aUrl length];
|
||||||
name = aName;
|
data = malloc(sizeof (struct website_data) + nlen + urlen);
|
||||||
url = aUrl;
|
data->len_name = nlen;
|
||||||
lastVisited = nil;
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)dealloc {
|
-(void)dealloc {
|
||||||
[name release];
|
free(data);
|
||||||
[url release];
|
|
||||||
[lastVisited release];
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(NSString*)name {
|
-(NSString*)name {
|
||||||
return name;
|
return [NSString stringWithCString: data->data length: data->len_name];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(NSURL*)url {
|
-(NSString*)url {
|
||||||
return url;
|
return [NSString stringWithCString: data->data + data->len_name length:
|
||||||
|
data->len_url];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)open {
|
-(void)open {
|
||||||
|
@ -39,90 +53,26 @@ static NSMutableArray *history;
|
||||||
|
|
||||||
// MARK: - History implementation
|
// 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 {
|
-(void)addToHistory {
|
||||||
[Website initHistoryIfNeeded];
|
static NSString *path = nil;
|
||||||
[lastVisited release];
|
if (path == nil) {
|
||||||
lastVisited = [[NSDate alloc] init];
|
NSCalendarDate *date = [NSCalendarDate calendarDate];
|
||||||
[history insertObject: self atIndex: 0];
|
int month = [date monthOfYear];
|
||||||
NSLog(@"Added %@ , %@ to history!", [self name], [self url]);
|
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:
|
[[NSNotificationCenter defaultCenter] postNotificationName:
|
||||||
WebsiteHistoryUpdatedNotificationName object: self];
|
WebsiteHistoryUpdatedNotificationName object: self];
|
||||||
}
|
}
|
||||||
|
|
||||||
+(NSArray*)historicWebsites {
|
|
||||||
[Website initHistoryIfNeeded];
|
|
||||||
return history;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
Loading…
Reference in New Issue