]> git.saurik.com Git - cydia.git/commitdiff
Move -init into -loadView -viewDidLoad and friends, as Apple wants. Add -navigationUR...
authorGrant Paul <chpwn@chpwn.com>
Sat, 12 Feb 2011 07:27:43 +0000 (23:27 -0800)
committerGrant Paul <chpwn@chpwn.com>
Sat, 12 Feb 2011 07:27:43 +0000 (23:27 -0800)
1  2 
MobileCydia.mm
UICaboodle/RVPage.h
UICaboodle/RVPage.mm

diff --combined MobileCydia.mm
index 17b17426c0137acf9f92576fad92c4f81553a23a,ccec42b8ab1744cffe5f23dc0ddf165ffaf34f57..bb01abd54eb25d8e79e1ad4638ce3fc0f7adaa03
@@@ -1,5 -1,5 +1,5 @@@
  /* Cydia - iPhone UIKit Front-End for Debian APT
 - * Copyright (C) 2008-2010  Jay Freeman (saurik)
 + * Copyright (C) 2008-2011  Jay Freeman (saurik)
  */
  
  /* Modified BSD License {{{ */
@@@ -402,7 -402,6 +402,7 @@@ static const CFStringCompareFlags LaxCo
  #define ShowInternals (0 && !ForRelease)
  #define IgnoreInstall (0 && !ForRelease)
  #define AlwaysReload (0 && !ForRelease)
 +#define TryIndexedCollation (0 && !ForRelease)
  
  #if !TraceLogging
  #undef _trace
@@@ -1072,7 -1071,7 +1072,7 @@@ static _transient NSMutableDictionary *
  static bool Changed_;
  static time_t now_;
  
 -static bool IsWildcat_;
 +bool IsWildcat_;
  /* }}} */
  
  /* Display Helpers {{{ */
@@@ -1185,6 -1184,7 +1185,6 @@@ bool isSectionVisible(NSString *section
  @protocol CydiaDelegate
  - (void) retainNetworkActivityIndicator;
  - (void) releaseNetworkActivityIndicator;
 -- (void) setPackageController:(CYPackageController *)view;
  - (void) clearPackage:(Package *)package;
  - (void) installPackage:(Package *)package;
  - (void) installPackages:(NSArray *)packages;
@@@ -2735,8 -2735,6 +2735,8 @@@ struct PackageNameOrdering 
      if (range.location != NSNotFound)
          return YES;
  
 +    [self parse];
 +
      range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_];
      if (range.location != NSNotFound)
          return YES;
@@@ -4041,27 -4039,40 +4041,40 @@@ static NSString *Warning_
  
  @implementation CYEmulatedLoadingController
  
- - (CYEmulatedLoadingController *) init {
-     if ((self = [super init])) {
-         [[self view] setBackgroundColor:[UIColor pinStripeColor]];
-         indicator_ = [[CYLoadingIndicator alloc] initWithFrame:[[self view] bounds]];
-         [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-         [[self view] addSubview:indicator_];
-         [indicator_ release];
-         tabbar_ = [[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 49.0f)];
-         [tabbar_ setFrame:CGRectMake(0.0f, [[self view] bounds].size.height - [tabbar_ bounds].size.height, [[self view] bounds].size.width, [tabbar_ bounds].size.height)];
-         [tabbar_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth];
-         [[self view] addSubview:tabbar_];
-         [tabbar_ release];
-         navbar_ = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)];
-         [navbar_ setFrame:CGRectMake(0.0f, 0.0f, [[self view] bounds].size.width, [navbar_ bounds].size.height)];
-         [navbar_ setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth];
-         [[self view] addSubview:navbar_];
-         [navbar_ release];
-     } return self;
+ - (void) dealloc {
+     [self releaseSubviews];
+     [super dealloc];
+ }
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
+     [[self view] setBackgroundColor:[UIColor pinStripeColor]];
+     indicator_ = [[CYLoadingIndicator alloc] initWithFrame:[[self view] bounds]];
+     [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+     [[self view] addSubview:indicator_];
+     tabbar_ = [[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 49.0f)];
+     [tabbar_ setFrame:CGRectMake(0.0f, [[self view] bounds].size.height - [tabbar_ bounds].size.height, [[self view] bounds].size.width, [tabbar_ bounds].size.height)];
+     [tabbar_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth];
+     [[self view] addSubview:tabbar_];
+     navbar_ = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)];
+     [navbar_ setFrame:CGRectMake(0.0f, 0.0f, [[self view] bounds].size.width, [navbar_ bounds].size.height)];
+     [navbar_ setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth];
+     [[self view] addSubview:navbar_];
+ }
+ - (void) releaseSubviews {
+     [indicator_ release];
+     indicator_ = nil;
+     [tabbar_ release];
+     tabbar_ = nil;
+     [navbar_ release];
+     navbar_ = nil;
  }
  
  @end
      [super dealloc];
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[[webview_ request] URL] absoluteString]]];
+ }
  - (void) setHeaders:(NSDictionary *)headers forHost:(NSString *)host {
  }
  
  
      WebDataSource *source([frame dataSource]);
      NSURLResponse *response([source response]);
 +
      NSURL *url([response URL]);
      NSString *scheme([url scheme]);
 -
 -    NSHTTPURLResponse *http;
 -    if (scheme != nil && ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]))
 -        http = (NSHTTPURLResponse *) response;
 -    else
 -        http = nil;
 -
 -    NSDictionary *headers([http allHeaderFields]);
      NSString *host([url host]);
 -    [self setHeaders:headers forHost:host];
 +
 +    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
 +        NSHTTPURLResponse *http((NSHTTPURLResponse *) response);
 +        NSDictionary *headers([http allHeaderFields]);
 +        [self setHeaders:headers forHost:host];
 +    }
  
      if (
          [host isEqualToString:@"cydia.saurik.com"] ||
@@@ -4481,6 -4498,7 +4498,6 @@@ bool DepSubstrate(const pkgCache::VerIt
          //[status_ setFont:font];
  
          output_ = [[UITextView alloc] init];
 -
          [output_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
          //[output_ setTextFont:@"Courier New"];
          [output_ setFont:[[output_ font] fontWithSize:12]];
          10,
          20,
          bounds.size.width - 20,
 -        bounds.size.height - 62
 +        bounds.size.height - 96
      )];
      [close_ setFrame:CGRectMake(
          (bounds.size.width - closewidth) / 2,
  @implementation FileTable
  
  - (void) dealloc {
-     if (package_ != nil)
-         [package_ release];
-     if (name_ != nil)
-         [name_ release];
+     [self releaseSubviews];
+     [package_ release];
+     [name_ release];
      [files_ release];
-     [list_ release];
      [super dealloc];
  }
  
      return cell;
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/files", [package_ id]]];
+ }
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
+     list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]];
+     [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+     [list_ setRowHeight:24.0f];
+     [list_ setDataSource:self];
+     [list_ setDelegate:self];
+     [[self view] addSubview:list_];
+ }
+ - (void) viewDidLoad {
+     [[self navigationItem] setTitle:UCLocalize("INSTALLED_FILES")];
+ }
+ - (void) releaseSubviews {
+     [list_ release];
+     list_ = nil;
+ }
  - (id) initWithDatabase:(Database *)database {
      if ((self = [super init]) != nil) {
          database_ = database;
  
-         [[self navigationItem] setTitle:UCLocalize("INSTALLED_FILES")];
          files_ = [[NSMutableArray arrayWithCapacity:32] retain];
-         list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]];
-         [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-         [list_ setRowHeight:24.0f];
-         [[self view] addSubview:list_];
-         [list_ setDataSource:self];
-         [list_ setDelegate:self];
      } return self;
  }
  
  }
  
  - (void) reloadData {
+     [super reloadData];
      [self setPackage:[database_ packageWithName:name_]];
  }
  
  }
  
  - (void) release {
 -    if ([self retainCount] == 1)
 -        [delegate_ setPackageController:self];
      [super release];
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", [package_ id]]];
+ }
  /* XXX: this is not safe at all... localization of /fail/ */
  - (void) _clickButtonWithName:(NSString *)name {
      if ([name isEqualToString:UCLocalize("CLEAR")])
  }
  #endif
  
++- (void) viewWillAppear:(BOOL)animated {
++    if (![self hasLoaded])
++        [self loadURL:[NSURL URLWithString:CydiaURL(@"ui/package/")]];
++    [super viewWillAppear:animated];
++}
++
  - (id) initWithDatabase:(Database *)database {
      if ((self = [super init]) != nil) {
          database_ = database;
          buttons_ = [[NSMutableArray alloc] initWithCapacity:4];
-         [self loadURL:[NSURL URLWithString:CydiaURL(@"ui/package/")]];
 -        [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"package" ofType:@"html"]]];
      } return self;
  }
  
  }
  
  - (void) reloadData {
++    [super reloadData];
++
      [self setPackage:[database_ packageWithName:name_]];
  }
  
  @end
  /* }}} */
  
 -/* Package Table {{{ */
 -@interface PackageTable : UIView <
 +/* Package List Controller {{{ */
 +@interface PackageListController : CYViewController <
      UITableViewDataSource,
      UITableViewDelegate
  > {
      UITableView *list_;
      NSMutableArray *index_;
      NSMutableDictionary *indices_;
 -    // XXX: this target_ seems to be delegate_. :(
 -    _transient id target_;
 -    SEL action_;
 -    // XXX: why do we even have this delegate_?
 -    _transient id delegate_;
 +    NSString *title_;
  }
  
 -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action;
 -
 +- (id) initWithDatabase:(Database *)database title:(NSString *)title;
  - (void) setDelegate:(id)delegate;
 -
 -- (void) reloadData;
  - (void) resetCursor;
  
 -- (UITableView *) list;
 -
 -- (void) setShouldHideHeaderInShortLists:(BOOL)hide;
 -
 -- (void) deselectWithAnimation:(BOOL)animated;
 -
  @end
  
 -@implementation PackageTable
 +@implementation PackageListController
  
  - (void) dealloc {
      [packages_ release];
      [list_ release];
      [index_ release];
      [indices_ release];
 +    [title_ release];
  
      [super dealloc];
  }
  
 +- (void) deselectWithAnimation:(BOOL)animated {
 +    [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
 +}
 +
 +- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve {
 +    CGRect base = [[self view] bounds];
 +    base.size.height -= bounds.size.height;
 +    base.origin = [list_ frame].origin;
 +
 +    [UIView beginAnimations:nil context:NULL];
 +    [UIView setAnimationBeginsFromCurrentState:YES];
 +    [UIView setAnimationCurve:curve];
 +    [UIView setAnimationDuration:duration];
 +    [list_ setFrame:base];
 +    [UIView commitAnimations];
 +}
 +
 +- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration {
 +    [self resizeForKeyboardBounds:bounds duration:duration curve:UIViewAnimationCurveLinear];
 +}
 +
 +- (void) resizeForKeyboardBounds:(CGRect)bounds {
 +    [self resizeForKeyboardBounds:bounds duration:0];
 +}
 +
 +- (void) keyboardWillShow:(NSNotification *)notification {
 +    CGRect bounds;
 +    CGPoint center;
 +    NSTimeInterval duration;
 +    UIViewAnimationCurve curve;
 +    [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&bounds];
 +    [[[notification userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey] getValue:&center];
 +    [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve];
 +    [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration];
 +
 +    CGRect kbframe = CGRectMake(round(center.x - bounds.size.width / 2.0), round(center.y - bounds.size.height / 2.0), bounds.size.width, bounds.size.height);
 +    UIViewController *base = self;
 +    while ([base parentViewController] != nil)
 +        base = [base parentViewController];
 +    CGRect viewframe = [[base view] convertRect:[list_ frame] fromView:[list_ superview]];
 +    CGRect intersection = CGRectIntersection(viewframe, kbframe);
 +
 +    [self resizeForKeyboardBounds:intersection duration:duration curve:curve];
 +}
 +
 +- (void) keyboardWillHide:(NSNotification *)notification {
 +    NSTimeInterval duration;
 +    UIViewAnimationCurve curve;
 +    [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve];
 +    [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration];
 +
 +    [self resizeForKeyboardBounds:CGRectZero duration:duration curve:curve];
 +}
 +
 +- (void) viewWillAppear:(BOOL)animated {
 +    [super viewWillAppear:animated];
 +
 +    [self resizeForKeyboardBounds:CGRectZero];
 +    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
 +    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
 +}
 +
 +- (void) viewWillDisappear:(BOOL)animated {
 +    [super viewWillDisappear:animated];
 +
 +    [self resizeForKeyboardBounds:CGRectZero];
 +    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
 +    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
 +}
 +
 +- (void) viewDidAppear:(BOOL)animated {
 +    [super viewDidAppear:animated];
 +    [self deselectWithAnimation:animated];
 +}
 +
 +- (void) didSelectPackage:(Package *)package {
 +    CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_] autorelease]);
 +    [view setPackage:package];
 +    [view setDelegate:delegate_];
 +    [[self navigationController] pushViewController:view animated:YES];
 +}
 +
 +#if TryIndexedCollation
  + (BOOL) hasIndexedCollation {
      return NO; // XXX: objc_getClass("UILocalizedIndexedCollation") != nil;
  }
 +#endif
  
  - (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
      NSInteger count([sections_ count]);
      return cell;
  }
  
 -- (void) deselectWithAnimation:(BOOL)animated {
 -    [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
 -}
 -
 -- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
 +- (void) tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)path {
      Package *package([self packageAtIndexPath:path]);
      package = [database_ packageWithName:[package id]];
 -    [target_ performSelector:action_ withObject:package];
 -    return path;
 +    [self didSelectPackage:package];
  }
  
  - (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView {
  }
  
  - (NSInteger) tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
 +#if TryIndexedCollation
      if ([[self class] hasIndexedCollation]) {
          return [[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionForSectionIndexTitleAtIndex:index];
      }
 +#endif
  
      return index;
  }
  
 -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action {
 -    if ((self = [super initWithFrame:frame]) != nil) {
 +- (id) initWithDatabase:(Database *)database title:(NSString *)title {
 +    if ((self = [super init]) != nil) {
          database_ = database;
 +        title_ = [title copy];
 +        [[self navigationItem] setTitle:title_];
  
 -        target_ = target;
 -        action_ = action;
 +#if TryIndexedCollation
 +        if ([[self class] hasIndexedCollation])
 +            index_ = [[[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionIndexTitles] retain]
 +        else
 +#endif
 +            index_ = [[NSMutableArray alloc] initWithCapacity:32];
  
 -        index_ = [[self class] hasIndexedCollation]
 -            ? [[[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionIndexTitles] retain]
 -            : [[NSMutableArray alloc] initWithCapacity:32];
          indices_ = [[NSMutableDictionary alloc] initWithCapacity:32];
  
          packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
          sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
  
 -        list_ = [[UITableView alloc] initWithFrame:[self bounds] style:UITableViewStylePlain];
 +        list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
          [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
          [list_ setRowHeight:73];
 -        [self addSubview:list_];
 +        [[self view] addSubview:list_];
  
          [list_ setDataSource:self];
          [list_ setDelegate:self];
  }
  
  - (void) reloadData {
++    [super reloadData];
++
      era_ = [database_ era];
      NSArray *packages = [database_ packages];
  
  
      Section *section = nil;
  
 +#if TryIndexedCollation
      if ([[self class] hasIndexedCollation]) {
          id collation = [objc_getClass("UILocalizedIndexedCollation") currentCollation];
          NSArray *titles = [collation sectionIndexTitles];
                  [section addToCount];
              }
          _end
 -    } else {
 +    } else
 +#endif
 +    {
          [index_ removeAllObjects];
  
          _profile(PackageTable$reloadData$Section)
      [list_ scrollRectToVisible:CGRectMake(0, 0, 0, 0) animated:NO];
  }
  
 -- (UITableView *) list {
 -    return list_;
 -}
 -
 -- (void) setShouldHideHeaderInShortLists:(BOOL)hide {
 -    //XXX:[list_ setShouldHideHeaderInShortLists:hide];
 -}
 -
  @end
  /* }}} */
 -/* Filtered Package Table {{{ */
 -@interface FilteredPackageTable : PackageTable {
 +/* Filtered Package List Controller {{{ */
 +@interface FilteredPackageListController : PackageListController {
      SEL filter_;
      IMP imp_;
      id object_;
  - (void) setObject:(id)object;
  - (void) setObject:(id)object forFilter:(SEL)filter;
  
 -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action filter:(SEL)filter with:(id)object;
 +- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
  
  @end
  
 -@implementation FilteredPackageTable
 +@implementation FilteredPackageListController
  
  - (void) dealloc {
      if (object_ != nil)
      _end
  }
  
 -- (id) initWithFrame:(CGRect)frame database:(Database *)database target:(id)target action:(SEL)action filter:(SEL)filter with:(id)object {
 -    if ((self = [super initWithFrame:frame database:database target:target action:action]) != nil) {
 +- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
 +    if ((self = [super initWithDatabase:database title:title]) != nil) {
          [self setFilter:filter];
 -        object_ = [object retain];
 +        [self setObject:object];
          [self reloadData];
      } return self;
  }
  
  @end
 -/* }}} */
 -/* Filtered Package Controller {{{ */
 -@interface FilteredPackageController : CYViewController {
 -    _transient Database *database_;
 -    FilteredPackageTable *packages_;
 -    NSString *title_;
 -    SEL filter_;
 -    id object_;
 -}
 -
 -- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
 -
 -@end
 -
 -@implementation FilteredPackageController
 -
 -- (void) dealloc {
 -    [self releaseSubviews];
 -    [title_ release];
 -
 -    [super dealloc];
 -}
 -
 -- (void) viewDidAppear:(BOOL)animated {
 -    [super viewDidAppear:animated];
 -    [packages_ deselectWithAnimation:animated];
 -}
 -
 -- (void) didSelectPackage:(Package *)package {
 -    CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_] autorelease]);
 -    [view setPackage:package];
 -    [view setDelegate:delegate_];
 -    [[self navigationController] pushViewController:view animated:YES];
 -}
 -
 -- (void) loadView {
 -    [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
 -
 -    packages_ = [[FilteredPackageTable alloc]
 -        initWithFrame:[[self view] bounds]
 -        database:database_
 -        target:self
 -        action:@selector(didSelectPackage:)
 -        filter:filter_
 -        with:object_
 -    ];
 -    [packages_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
 -    [[self view] addSubview:packages_];
 -}
 -
 -- (void) viewDidLoad {
 -    [[self navigationItem] setTitle:title_];
 -}
 -
 -- (void) releaseSubviews {
 -    [packages_ release];
 -}
 -
 -- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
 -    if ((self = [super init]) != nil) {
 -        database_ = database;
 -        title_ = [title copy];
 -        filter_ = filter;
 -        object_ = object;
 -    } return self;
 -}
 -
 -- (void) reloadData {
 -    [super reloadData];
 -    [packages_ reloadData];
 -}
 -
 -- (void) setDelegate:(id)delegate {
 -    [super setDelegate:delegate];
 -    [packages_ setDelegate:delegate];
 -}
 -
 -@end
 -
  /* }}} */
  
  /* Home Controller {{{ */
  
  @implementation HomeController
  
--+ (BOOL)shouldHideNavigationBar {
+++ (BOOL) shouldHideNavigationBar {
      return NO;
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:@"cydia://home"];
+ }
  - (void) _setMoreHeaders:(NSMutableURLRequest *)request {
      [super _setMoreHeaders:request];
  
      [alert setCancelButtonIndex:0];
  
      [alert setMessage:
 -        @"Copyright (C) 2008-2010\n"
 +        @"Copyright (C) 2008-2011\n"
          "Jay Freeman (saurik)\n"
          "saurik@saurik.com\n"
          "http://www.saurik.com/"
      [alert show];
  }
  
--- (void) viewWillAppear:(BOOL)animated {
--    [super viewWillAppear:animated];
--
--    if ([[self class] shouldHideNavigationBar])
--        [[self navigationController] setNavigationBarHidden:YES animated:animated];
--}
--
  - (void) viewWillDisappear:(BOOL)animated {
      [super viewWillDisappear:animated];
  
          [[self navigationController] setNavigationBarHidden:NO animated:animated];
  }
  
--- (id) init {
--    if ((self = [super init]) != nil) {
 -        [self loadURL:[NSURL URLWithString:CydiaURL(@"")]];
++- (void) viewWillAppear:(BOOL)animated {
++    if (![self hasLoaded])
 +        [self loadURL:[NSURL URLWithString:CydiaURL(@"ui/home/")]];
  
--        [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
--            initWithTitle:UCLocalize("ABOUT")
--            style:UIBarButtonItemStylePlain
--            target:self
--            action:@selector(aboutButtonClicked)
--        ] autorelease]];
--    } return self;
++    [super viewWillAppear:animated];
++
++    if ([[self class] shouldHideNavigationBar])
++        [[self navigationController] setNavigationBarHidden:YES animated:animated];
++}
++
++- (void) viewDidLoad {
++    [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
++        initWithTitle:UCLocalize("ABOUT")
++        style:UIBarButtonItemStylePlain
++        target:self
++        action:@selector(aboutButtonClicked)
++    ] autorelease]];
  }
  
  @end
  
  @implementation ManageController
  
- - (id) init {
-     if ((self = [super init]) != nil) {
-         [[self navigationItem] setTitle:UCLocalize("MANAGE")];
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:@"cydia://manage"];
+ }
  
 -- (id) init {
 -    if ((self = [super init]) != nil) {
 -        [[self navigationItem] setTitle:UCLocalize("MANAGE")];
++- (void) viewWillAppear:(BOOL)animated {
++    if (![self hasLoaded])
 +        [self loadURL:[NSURL URLWithString:CydiaURL(@"ui/manage/")]];
  
-         [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
-             initWithTitle:UCLocalize("SETTINGS")
-             style:UIBarButtonItemStylePlain
-             target:self
-             action:@selector(settingsButtonClicked)
-         ] autorelease]];
 -        [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]];
++    [super viewWillAppear:animated];
++}
  
-         [self queueStatusDidChange];
-     } return self;
 -        [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
 -            initWithTitle:UCLocalize("SETTINGS")
 -            style:UIBarButtonItemStylePlain
 -            target:self
 -            action:@selector(settingsButtonClicked)
 -        ] autorelease]];
++- (void) viewDidLoad {
++    [[self navigationItem] setTitle:UCLocalize("MANAGE")];
 -        [self queueStatusDidChange];
 -    } return self;
++    [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
++        initWithTitle:UCLocalize("SETTINGS")
++        style:UIBarButtonItemStylePlain
++        target:self
++        action:@selector(settingsButtonClicked)
++    ] autorelease]];
++
++    [self queueStatusDidChange];
  }
  
  - (void) settingsButtonClicked {
  }
  
  - (void) applyLoadingTitle {
--    // No "Loading" title.
++    // Disable "Loading" title.
  }
  
  - (void) applyRightButton {
--    // No right button.
++    // Disable right button.
  }
  #endif
  
  }
  
  - (bool) isLoading {
++    // Never show as loading.
      return false;
  }
  
      id root_;
  }
  
 -- (NSArray *) navigationURLItems;
++- (NSArray *) navigationURLCollection;
  - (void) dropBar:(BOOL)animated;
  - (void) beginUpdate;
  - (void) raiseBar:(BOOL)animated;
  
  @implementation CYTabBarController
  
- - (void) reloadData {
-     size_t count([[self viewControllers] count]);
-     for (size_t i(0); i != count; ++i) {
-         CYNavigationController *page([[self viewControllers] objectAtIndex:(count - i - 1)]);
-         [page reloadData];
 -- (NSArray *) navigationURLItems {
++- (NSArray *) navigationURLCollection {
+     NSMutableArray *items([NSMutableArray array]);
 -    // XXX:Deal with transient view controllers.
++    // XXX: Should this deal with transient view controllers?
+     for (id navigation in [self viewControllers]) {
 -        NSArray *stack = [navigation performSelector:@selector(navigationURLStack)];
++        NSArray *stack = [navigation performSelector:@selector(navigationURLCollection)];
+         if (stack != nil)
+             [items addObject:stack];
      }
  
 -    size_t count([[self viewControllers] count]);
 -    for (size_t i(0); i != count; ++i) {
 -        CYNavigationController *page([[self viewControllers] objectAtIndex:(count - i - 1)]);
 -        [page reloadData];
 -    }
+     return items;
+ }
+ - (void) reloadData {
++    for (CYViewController *controller in [self viewControllers])
++        [controller reloadData];
      [(CYNavigationController *)[self transientViewController] reloadData];
  }
  
++- (void) dealloc {
++    [refreshbar_ release];
++    [[NSNotificationCenter defaultCenter] removeObserver:self];
++
++    [super dealloc];
++}
++
  - (id) initWithDatabase:(Database *)database {
      if ((self = [super init]) != nil) {
          database_ = database;
      }
  }
  
--- (void) dealloc {
--    [refreshbar_ release];
--    [[NSNotificationCenter defaultCenter] removeObserver:self];
--    [super dealloc];
--}
--
  @end
  /* }}} */
  /* Cydia Navigation Controller {{{ */
      _transient id<UINavigationControllerDelegate> delegate_;
  }
  
 -- (NSArray *) navigationURLStack;
++- (NSArray *) navigationURLCollection;
  - (id) initWithDatabase:(Database *)database;
  - (void) reloadData;
  
      [super dealloc];
  }
  
 -- (NSArray *) navigationURLStack {
++- (NSArray *) navigationURLCollection {
+     NSMutableArray *stack([NSMutableArray array]);
+     for (CYViewController *controller in [self viewControllers]) {
+         NSString *url = [[controller navigationURL] absoluteString];
+         if (url != nil)
+             [stack addObject:url];
+     }
+     return stack;
+ }
  - (void) reloadData {
--    size_t count([[self viewControllers] count]);
--    for (size_t i(0); i != count; ++i) {
--        CYViewController *page([[self viewControllers] objectAtIndex:(count - i - 1)]);
--        [page reloadData];
++    for (CYViewController *page in [self viewControllers]) {
++        if ([page hasLoaded])
++            [page reloadData];
      }
  }
  
  /* }}} */
  
  /* Section Controller {{{ */
 -@interface SectionController : FilteredPackageController {
 +@interface SectionController : FilteredPackageListController {
+     NSString *section_;
  }
  
  - (id) initWithDatabase:(Database *)database section:(NSString *)section;
  
  @implementation SectionController
  
+ - (NSURL *) navigationURL {
+     NSString *name = section_;
+     if (name == nil)
+         name = @"all";
+     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://sections/%@", name]];
+ }
  - (id) initWithDatabase:(Database *)database section:(NSString *)name {
      NSString *title;
  
          title = UCLocalize("NO_SECTION");
      }
  
+     section_ = name;
      if ((self = [super initWithDatabase:database title:title filter:@selector(isVisibleInSection:) with:name]) != nil) {
      } return self;
  }
  }
  
  - (id) initWithDatabase:(Database *)database;
- - (void) reloadData;
- - (void) resetView;
  - (void) editButtonClicked;
  
  @end
  @implementation SectionsController
  
  - (void) dealloc {
-     [list_ setDataSource:nil];
-     [list_ setDelegate:nil];
+     [self releaseSubviews];
      [sections_ release];
      [filtered_ release];
-     [list_ release];
      [super dealloc];
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:@"cydia://sections"];
+ }
  - (void) updateNavigationItem {
      [[self navigationItem] setTitle:editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("SECTIONS")];
      if ([sections_ count] == 0) {
      }
  }
  
++- (BOOL) isEditing {
++    return editing_;
++}
++
  - (void) setEditing:(BOOL)editing {
      if ((editing_ = editing))
          [list_ reloadData];
  - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
      static NSString *reuseIdentifier = @"SectionCell";
  
--    SectionCell *cell = (SectionCell *) [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
++    SectionCell *cell = (SectionCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
      if (cell == nil)
          cell = [[[SectionCell alloc] initWithFrame:CGRectZero reuseIdentifier:reuseIdentifier] autorelease];
  
      [[self navigationController] pushViewController:controller animated:YES];
  }
  
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
+     list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]];
+     [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+     [list_ setRowHeight:45.0f];
+     [list_ setDataSource:self];
+     [list_ setDelegate:self];
+     [[self view] addSubview:list_];
+ }
+ - (void) viewDidLoad {
+     [[self navigationItem] setTitle:UCLocalize("SECTIONS")];
+ }
+ - (void) releaseSubviews {
+     [list_ release];
+     list_ = nil;
+ }
  - (id) initWithDatabase:(Database *)database {
      if ((self = [super init]) != nil) {
          database_ = database;
  
-         [[self navigationItem] setTitle:UCLocalize("SECTIONS")];
          sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
          filtered_ = [[NSMutableArray arrayWithCapacity:16] retain];
-         list_ = [[UITableView alloc] initWithFrame:[[self view] bounds]];
-         [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-         [list_ setRowHeight:45.0f];
-         [[self view] addSubview:list_];
-         [list_ setDataSource:self];
-         [list_ setDelegate:self];
-         [self reloadData];
      } return self;
  }
  
  - (void) reloadData {
+     [super reloadData];
      NSArray *packages = [database_ packages];
  
      [sections_ removeAllObjects];
      _trace();
  }
  
- - (void) resetView {
-     if (editing_)
-         [self editButtonClicked];
- }
  - (void)editButtonClicked {
      [self setEditing:!editing_];
  }
  @implementation ChangesController
  
  - (void) dealloc {
-     [list_ setDelegate:nil];
-     [list_ setDataSource:nil];
+     [self releaseSubviews];
      CFRelease(packages_);
      [sections_ release];
-     [list_ release];
      [super dealloc];
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:@"cydia://changes"];
+ }
++- (void) viewWillAppear:(BOOL)animated {
++    // Loads after it appears, so don't load beforehand.
++    loaded_ = YES;
++    [super viewWillAppear:animated];
++}
++
  - (void) viewDidAppear:(BOOL)animated {
      [super viewDidAppear:animated];
      if (!hasSentFirstLoad_) {
          hasSentFirstLoad_ = YES;
          [self performSelector:@selector(reloadData) withObject:nil afterDelay:0.0];
      [delegate_ distUpgrade];
  }
  
- - (NSString *) title { return UCLocalize("CHANGES"); }
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
+     list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
+     [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+     [list_ setRowHeight:73];
+     [list_ setDataSource:self];
+     [list_ setDelegate:self];
+     [[self view] addSubview:list_];
+ }
+ - (void) viewDidLoad {
+     [[self navigationItem] setTitle:UCLocalize("CHANGES")];
+ }
+ - (void) releaseSubviews {
+     [list_ release];
+     list_ = nil;
+ }
  
  - (id) initWithDatabase:(Database *)database {
      if ((self = [super init]) != nil) {
          database_ = database;
-         [[self navigationItem] setTitle:UCLocalize("CHANGES")];
  
 -        // We load after the view is visible, so don't "magically" load beforehand.
 -        loaded_ = YES;
 -
          packages_ = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
          sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
-         list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
-         [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-         [list_ setRowHeight:73];
-         [[self view] addSubview:list_];
-         [list_ setDataSource:self];
-         [list_ setDelegate:self];
      } return self;
  }
  
  @end
  /* }}} */
  /* Search Controller {{{ */
 -@interface SearchController : FilteredPackageController <
 +@interface SearchController : FilteredPackageListController <
      UISearchBarDelegate
  > {
      UISearchBar *search_;
+     BOOL searchloaded_;
  }
  
  - (id) initWithDatabase:(Database *)database;
      [super dealloc];
  }
  
 -    return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://search/%@", [search_ text]]];
+ - (NSURL *) navigationURL {
++    if ([search_ text] == nil || [[search_ text] isEqualToString:@""])
++        return [NSURL URLWithString:@"cydia://search"];
++    else
++        return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://search/%@", [search_ text]]];
+ }
  - (void) setSearchTerm:(NSString *)searchTerm {
      [search_ setText:searchTerm];
+     [self reloadData];
  }
  
  - (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
 -    [packages_ setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)];
 +    [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)];
      [search_ resignFirstResponder];
      [self reloadData];
  }
  
  - (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)text {
 -    [packages_ setObject:[search_ text] forFilter:@selector(isUnfilteredAndSelectedForBy:)];
 +    [self setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)];
      [self reloadData];
  }
  
  - (id) initWithDatabase:(Database *)database {
-     return [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:nil];
+     if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:nil])) {
+         search_ = [[UISearchBar alloc] init];
+     } return self;
  }
  
  - (void)viewDidAppear:(BOOL)animated {
      [super viewDidAppear:animated];
-     if (!search_) {
-         search_ = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)];
+     if (!searchloaded_) {
+         searchloaded_ = YES;
+         [search_ setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)];
          [search_ layoutSubviews];
          [search_ setPlaceholder:UCLocalize("SEARCH_EX")];
  
      }
  }
  
- - (void) _reloadData {
- }
  - (void) reloadData {
-     _profile(SearchController$reloadData)
-         [super reloadData];
-     _end
-     PrintTimes();
 -    [packages_ setObject:[search_ text]];
++    [self setObject:[search_ text]];
+     [super reloadData];
 -    [packages_ resetCursor];
 +    [self resetCursor];
  }
  
  - (void) didSelectPackage:(Package *)package {
  @implementation PackageSettingsController
  
  - (void) dealloc {
+     [self releaseSubviews];
      [name_ release];
-     if (package_ != nil)
-         [package_ release];
-     [table_ release];
-     [subscribedSwitch_ release];
-     [ignoredSwitch_ release];
-     [subscribedCell_ release];
-     [ignoredCell_ release];
+     [package_ release];
  
      [super dealloc];
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/settings", [package_ id]]];
+ }
  - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
      if (package_ == nil)
          return 0;
      return nil;
  }
  
- - (NSString *) title { return UCLocalize("SETTINGS"); }
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
  
- - (id) initWithDatabase:(Database *)database package:(NSString *)package {
-     if ((self = [super init])) {
-         database_ = database;
-         name_ = [package retain];
+     table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped];
+     [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+     [table_ setDataSource:self];
+     [table_ setDelegate:self];
+     [[self view] addSubview:table_];
  
-         [[self navigationItem] setTitle:UCLocalize("SETTINGS")];
+     subscribedSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
+     [subscribedSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
+     [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:UIControlEventValueChanged];
  
-         table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped];
-         [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-         [[self view] addSubview:table_];
+     ignoredSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
+     [ignoredSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
+     [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:UIControlEventValueChanged];
+     // Disable this switch, since it only reflects (not modifies) the ignored state.
+     [ignoredSwitch_ setUserInteractionEnabled:NO];
  
-         subscribedSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
-         [subscribedSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
-         [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:UIControlEventValueChanged];
+     subscribedCell_ = [[UITableViewCell alloc] init];
+     [subscribedCell_ setText:UCLocalize("SHOW_ALL_CHANGES")];
+     [subscribedCell_ setAccessoryView:subscribedSwitch_];
+     [subscribedCell_ setSelectionStyle:UITableViewCellSelectionStyleNone];
  
-         ignoredSwitch_ = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
-         [ignoredSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
-         [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:UIControlEventValueChanged];
-         // Disable this switch, since it only reflects (not modifies) the ignored state.
-         [ignoredSwitch_ setUserInteractionEnabled:NO];
+     ignoredCell_ = [[UITableViewCell alloc] init];
+     [ignoredCell_ setText:UCLocalize("IGNORE_UPGRADES")];
+     [ignoredCell_ setAccessoryView:ignoredSwitch_];
+     [ignoredCell_ setSelectionStyle:UITableViewCellSelectionStyleNone];
+     // FIXME: Ignored state is not saved.
+     [ignoredCell_ setUserInteractionEnabled:NO];
+ }
+ - (void) viewDidLoad {
+     [[self navigationItem] setTitle:UCLocalize("SETTINGS")];
+ }
  
-         subscribedCell_ = [[UITableViewCell alloc] init];
-         [subscribedCell_ setText:UCLocalize("SHOW_ALL_CHANGES")];
-         [subscribedCell_ setAccessoryView:subscribedSwitch_];
-         [subscribedCell_ setSelectionStyle:UITableViewCellSelectionStyleNone];
+ - (void) releaseSubviews {
+     [ignoredCell_ release];
+     ignoredCell_ = nil;
  
-         ignoredCell_ = [[UITableViewCell alloc] init];
-         [ignoredCell_ setText:UCLocalize("IGNORE_UPGRADES")];
-         [ignoredCell_ setAccessoryView:ignoredSwitch_];
-         [ignoredCell_ setSelectionStyle:UITableViewCellSelectionStyleNone];
-         // FIXME: Ignored state is not saved.
-         [ignoredCell_ setUserInteractionEnabled:NO];
+     [subscribedCell_ release];
+     subscribedCell_ = nil;
  
-         [table_ setDataSource:self];
-         [table_ setDelegate:self];
-         [self reloadData];
+     [table_ release];
+     table_ = nil;
+     [ignoredSwitch_ release];
+     ignoredSwitch_ = nil;
+     [subscribedSwitch_ release];
+     subscribedSwitch_ = nil;
+ }
+ - (id) initWithDatabase:(Database *)database package:(NSString *)package {
+     if ((self = [super init])) {
+         database_ = database;
+         name_ = [package retain];
      } return self;
  }
  
  - (void) reloadData {
+     [super reloadData];
      if (package_ != nil)
          [package_ autorelease];
      package_ = [database_ packageWithName:name_];
      [table_ reloadData];
  }
  
--@end
--/* }}} */
--/* Signature Controller {{{ */
--@interface SignatureController : CYBrowserController {
--    _transient Database *database_;
--    NSString *package_;
--}
--
--- (id) initWithDatabase:(Database *)database package:(NSString *)package;
--
--@end
--
--@implementation SignatureController
--
--- (void) dealloc {
--    [package_ release];
--    [super dealloc];
 -}
 -
 -- (NSURL *) navigationURL {
 -    return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/signature", package_]];
--}
--
--- (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
--    // XXX: dude!
--    [super webView:view didClearWindowObject:window forFrame:frame];
--}
--
--- (id) initWithDatabase:(Database *)database package:(NSString *)package {
--    if ((self = [super init]) != nil) {
--        database_ = database;
--        package_ = [package retain];
--        [self reloadData];
--    } return self;
--}
--
--- (void) reloadData {
--    [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"signature" ofType:@"html"]]];
--}
--
  @end
  /* }}} */
  
  /* Installed Controller {{{ */
 -@interface InstalledController : FilteredPackageController {
 +@interface InstalledController : FilteredPackageListController {
      BOOL expert_;
  }
  
      [super dealloc];
  }
  
- - (NSString *) title { return UCLocalize("INSTALLED"); }
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:@"cydia://installed"];
+ }
  
  - (id) initWithDatabase:(Database *)database {
      if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndUnfiltered:) with:[NSNumber numberWithBool:YES]]) != nil) {
  #endif
  }
  
 -- (void) reloadData {
 -    [packages_ reloadData];
 -}
 -
  - (void) updateRoleButton {
      if (Role_ != nil && ![Role_ isEqualToString:@"Developer"])
          [[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc]
  }
  
  - (void) roleButtonClicked {
 -    [packages_ setObject:[NSNumber numberWithBool:expert_]];
 -    [packages_ reloadData];
 +    [self setObject:[NSNumber numberWithBool:expert_]];
 +    [self reloadData];
      expert_ = !expert_;
  
      [self updateRoleButton];
  }
  
 -- (void) setDelegate:(id)delegate {
 -    [super setDelegate:delegate];
 -    [packages_ setDelegate:delegate];
 -}
 -
  @end
  /* }}} */
  
  @end
  /* }}} */
  /* Source Controller {{{ */
 -@interface SourceController : FilteredPackageController {
 +@interface SourceController : FilteredPackageListController {
+     Source *source_;
  }
  
  - (id) initWithDatabase:(Database *)database source:(Source *)source;
  
  @implementation SourceController
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://sources/%@", [source_ name]]];
+ }
  - (id) initWithDatabase:(Database *)database source:(Source *)source {
+     source_ = source;
      if ((self = [super initWithDatabase:database title:[source label] filter:@selector(isVisibleInSource:) with:source]) != nil) {
      } return self;
  }
  }
  
  - (id) initWithDatabase:(Database *)database;
  - (void) updateButtonsForEditingStatus:(BOOL)editing animated:(BOOL)animated;
  
  @end
  }
  
  - (void) dealloc {
-     if (href_ != nil)
-         [href_ release];
-     if (hud_ != nil)
-         [hud_ release];
-     if (error_ != nil)
-         [error_ release];
+     [self releaseSubviews];
+     [href_ release];
+     [hud_ release];
+     [error_ release];
  
      //[self _releaseConnection:installer_];
      [self _releaseConnection:trivial_];
      //[self _releaseConnection:automatic_];
  
      [sources_ release];
-     [list_ release];
      [super dealloc];
  }
  
+ - (NSURL *) navigationURL {
+     return [NSURL URLWithString:@"cydia://sources"];
+ }
  - (void) viewDidAppear:(BOOL)animated {
      [super viewDidAppear:animated];
      [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
      [self _endConnection:connection];
  }
  
- - (NSString *) title { return UCLocalize("SOURCES"); }
  - (NSURLConnection *) _requestHRef:(NSString *)href method:(NSString *)method {
      NSMutableURLRequest *request = [NSMutableURLRequest
          requestWithURL:[NSURL URLWithString:href]
      }
  }
  
- - (id) initWithDatabase:(Database *)database {
-     if ((self = [super init]) != nil) {
-         [[self navigationItem] setTitle:UCLocalize("SOURCES")];
-         [self updateButtonsForEditingStatus:NO animated:NO];
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
  
-         database_ = database;
-         sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
+     list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
+     [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+     [list_ setRowHeight:56];
+     [list_ setDataSource:self];
+     [list_ setDelegate:self];
+     [[self view] addSubview:list_];
+ }
  
-         list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
-         [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-         [list_ setRowHeight:56];
-         [[self view] addSubview:list_];
+ - (void) viewDidLoad {
+     [[self navigationItem] setTitle:UCLocalize("SOURCES")];
+     [self updateButtonsForEditingStatus:NO animated:NO];
+ }
  
-         [list_ setDataSource:self];
-         [list_ setDelegate:self];
+ - (void) releaseSubviews {
+     [list_ release];
+     list_ = nil;
+ }
  
-         [self reloadData];
+ - (id) initWithDatabase:(Database *)database {
+     if ((self = [super init]) != nil) {
+         database_ = database;
+         sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
      } return self;
  }
  
  - (void) reloadData {
+     [super reloadData];
      pkgSourceList list;
      if (!list.ReadMainList())
          return;
  @end
  
  @implementation SettingsController
  - (void) dealloc {
+     [self releaseSubviews];
+     [super dealloc];
+ }
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
+     table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped];
+     [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+     [table_ setDelegate:self];
+     [table_ setDataSource:self];
+     [[self view] addSubview:table_];
+     NSArray *items = [NSArray arrayWithObjects:
+         UCLocalize("USER"),
+         UCLocalize("HACKER"),
+         UCLocalize("DEVELOPER"),
+     nil];
+     segment_ = [[UISegmentedControl alloc] initWithItems:items];
+     container_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44.0f)];
+     [container_ addSubview:segment_];
+ }
+ - (void) viewDidLoad {
+     [[self navigationItem] setTitle:UCLocalize("WHO_ARE_YOU")];
+     int index = -1;
+     if ([Role_ isEqualToString:@"User"]) index = 0;
+     if ([Role_ isEqualToString:@"Hacker"]) index = 1;
+     if ([Role_ isEqualToString:@"Developer"]) index = 2;
+     if (index != -1) {
+         [segment_ setSelectedSegmentIndex:index];
+         [self showDoneButton];
+     }
+     [segment_ addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
+     [self resizeSegmentedControl];
+ }
+ - (void) releaseSubviews {
      [table_ release];
+     table_ = nil;
      [segment_ release];
-     [container_ release];
+     segment_ = nil;
  
-     [super dealloc];
+     [container_ release];
+     container_ = nil;
  }
  
  - (id) initWithDatabase:(Database *)database delegate:(id)delegate {
      if ((self = [super init])) {
          database_ = database;
          roledelegate_ = delegate;
-         [[self navigationItem] setTitle:UCLocalize("WHO_ARE_YOU")];
-         NSArray *items = [NSArray arrayWithObjects:
-             UCLocalize("USER"),
-             UCLocalize("HACKER"),
-             UCLocalize("DEVELOPER"),
-         nil];
-         segment_ = [[UISegmentedControl alloc] initWithItems:items];
-         container_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44.0f)];
-         [container_ addSubview:segment_];
-         int index = -1;
-         if ([Role_ isEqualToString:@"User"]) index = 0;
-         if ([Role_ isEqualToString:@"Hacker"]) index = 1;
-         if ([Role_ isEqualToString:@"Developer"]) index = 2;
-         if (index != -1) {
-             [segment_ setSelectedSegmentIndex:index];
-             [self showDoneButton];
-         }
-         [segment_ addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
-         [self resizeSegmentedControl];
-         table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped];
-         [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-         [table_ setDelegate:self];
-         [table_ setDataSource:self];
-         [[self view] addSubview:table_];
-         [table_ reloadData];
      } return self;
  }
  
      return section == 3 ? container_ : nil;
  }
  
+ - (void) reloadData {
+     [super reloadData];
+     [table_ reloadData];
+ }
  @end
  /* }}} */
  /* Stash Controller {{{ */
  @interface StashController : CYViewController {
-     // XXX: just delete these things
-     _transient UIActivityIndicatorView *spinner_;
-     _transient UILabel *status_;
-     _transient UILabel *caption_;
+     UIActivityIndicatorView *spinner_;
+     UILabel *status_;
+     UILabel *caption_;
  }
  @end
  
  @implementation StashController
- - (id) init {
-     if ((self = [super init])) {
-         [[self view] setBackgroundColor:[UIColor viewFlipsideBackgroundColor]];
  
-         spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
-         CGRect spinrect = [spinner_ frame];
-         spinrect.origin.x = ([[self view] frame].size.width / 2) - (spinrect.size.width / 2);
-         spinrect.origin.y = [[self view] frame].size.height - 80.0f;
-         [spinner_ setFrame:spinrect];
-         [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin];
-         [[self view] addSubview:spinner_];
-         [spinner_ startAnimating];
+ - (void) dealloc {
+     [self releaseSubviews];
  
-         CGRect captrect;
-         captrect.size.width = [[self view] frame].size.width;
-         captrect.size.height = 40.0f;
-         captrect.origin.x = 0;
-         captrect.origin.y = ([[self view] frame].size.height / 2) - (captrect.size.height * 2);
-         caption_ = [[[UILabel alloc] initWithFrame:captrect] autorelease];
-         [caption_ setText:UCLocalize("PREPARING_FILESYSTEM")];
-         [caption_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
-         [caption_ setFont:[UIFont boldSystemFontOfSize:28.0f]];
-         [caption_ setTextColor:[UIColor whiteColor]];
-         [caption_ setBackgroundColor:[UIColor clearColor]];
-         [caption_ setShadowColor:[UIColor blackColor]];
-         [caption_ setTextAlignment:UITextAlignmentCenter];
-         [[self view] addSubview:caption_];
-         CGRect statusrect;
-         statusrect.size.width = [[self view] frame].size.width;
-         statusrect.size.height = 30.0f;
-         statusrect.origin.x = 0;
-         statusrect.origin.y = ([[self view] frame].size.height / 2) - statusrect.size.height;
-         status_ = [[[UILabel alloc] initWithFrame:statusrect] autorelease];
-         [status_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
-         [status_ setText:UCLocalize("EXIT_WHEN_COMPLETE")];
-         [status_ setFont:[UIFont systemFontOfSize:16.0f]];
-         [status_ setTextColor:[UIColor whiteColor]];
-         [status_ setBackgroundColor:[UIColor clearColor]];
-         [status_ setShadowColor:[UIColor blackColor]];
-         [status_ setTextAlignment:UITextAlignmentCenter];
-         [[self view] addSubview:status_];
-     } return self;
+     [super dealloc];
+ }
+ - (void) loadView {
+     [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]];
+     [[self view] setBackgroundColor:[UIColor viewFlipsideBackgroundColor]];
+     spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
+     CGRect spinrect = [spinner_ frame];
+     spinrect.origin.x = ([[self view] frame].size.width / 2) - (spinrect.size.width / 2);
+     spinrect.origin.y = [[self view] frame].size.height - 80.0f;
+     [spinner_ setFrame:spinrect];
+     [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin];
+     [[self view] addSubview:spinner_];
+     [spinner_ startAnimating];
+     CGRect captrect;
+     captrect.size.width = [[self view] frame].size.width;
+     captrect.size.height = 40.0f;
+     captrect.origin.x = 0;
+     captrect.origin.y = ([[self view] frame].size.height / 2) - (captrect.size.height * 2);
+     caption_ = [[[UILabel alloc] initWithFrame:captrect] autorelease];
+     [caption_ setText:UCLocalize("PREPARING_FILESYSTEM")];
+     [caption_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
+     [caption_ setFont:[UIFont boldSystemFontOfSize:28.0f]];
+     [caption_ setTextColor:[UIColor whiteColor]];
+     [caption_ setBackgroundColor:[UIColor clearColor]];
+     [caption_ setShadowColor:[UIColor blackColor]];
+     [caption_ setTextAlignment:UITextAlignmentCenter];
+     [[self view] addSubview:caption_];
+     CGRect statusrect;
+     statusrect.size.width = [[self view] frame].size.width;
+     statusrect.size.height = 30.0f;
+     statusrect.origin.x = 0;
+     statusrect.origin.y = ([[self view] frame].size.height / 2) - statusrect.size.height;
+     status_ = [[[UILabel alloc] initWithFrame:statusrect] autorelease];
+     [status_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
+     [status_ setText:UCLocalize("EXIT_WHEN_COMPLETE")];
+     [status_ setFont:[UIFont systemFontOfSize:16.0f]];
+     [status_ setTextColor:[UIColor whiteColor]];
+     [status_ setBackgroundColor:[UIColor clearColor]];
+     [status_ setShadowColor:[UIColor blackColor]];
+     [status_ setTextAlignment:UITextAlignmentCenter];
+     [[self view] addSubview:status_];
+ }
+ - (void) releaseSubviews {
+     [spinner_ release];
+     spinner_ = nil;
+     [status_ release];
+     status_ = nil;
+     [caption_ release];
+     caption_ = nil;
  }
  
  @end
      if (recently || loaded_ || ManualRefresh) {
          [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO];
  
--        // If we are cancelling due to ManualRefresh or a recent refresh
--        // we need to make sure it knows it's already loaded.
++        // If we are cancelling, we need to make sure it knows it's already loaded.
          loaded_ = true;
          return;
      } else {
      [self complete];
  }
  
- - (void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
-     CYNavigationController *controller = (CYNavigationController *) viewController;
-     if ([[controller viewControllers] count] == 0) {
-         int index = [[tabbar_ viewControllers] indexOfObjectIdenticalTo:controller];
-         CYViewController *root = nil;
-         if (index == 0)
-             root = [[[HomeController alloc] init] autorelease];
-         else if (index == 1)
-             root = [[[SectionsController alloc] initWithDatabase:database_] autorelease];
-         else if (index == 2)
-             root = [[[ChangesController alloc] initWithDatabase:database_] autorelease];
-         if (IsWildcat_) {
-             if (index == 3)
-                 root = [[[InstalledController alloc] initWithDatabase:database_] autorelease];
-             else if (index == 4)
-                 root = [[[SourcesController alloc] initWithDatabase:database_] autorelease];
-             else if (index == 5)
-                 root = [[[SearchController alloc] initWithDatabase:database_] autorelease];
-         } else {
-             if (index == 3)
-                 root = [[[ManageController alloc] init] autorelease];
-             else if (index == 4)
-                 root = [[[SearchController alloc] initWithDatabase:database_] autorelease];
-         }
-         [root setDelegate:self];
-         if (root != nil)
-             [controller setViewControllers:[NSArray arrayWithObject:root]];
-     }
- }
  - (void) showSettings {
      SettingsController *role = [[[SettingsController alloc] initWithDatabase:database_ delegate:self] autorelease];
      CYNavigationController *nav = [[[CYNavigationController alloc] initWithRootViewController:role] autorelease];
          [self setNetworkActivityIndicatorVisible:NO];
  }
  
 -- (void) setPackageController:(CYPackageController *)view {
 -    WebThreadLock();
 -    [view setPackage:nil];
 -    WebThreadUnlock();
 -}
 -
  - (void) cancelAndClear:(bool)clear {
      @synchronized (self) {
          if (clear) {
          controller = [[[CYBrowserController alloc] init] autorelease];
          [(CYBrowserController *)controller loadURL:[NSURL URLWithString:destination]];
      } else if ([components count] == 1) {
+         if ([base isEqualToString:@"storage"]) {
+             controller = [[[CYBrowserController alloc] init] autorelease];
+             [(CYBrowserController *)controller loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]]];
+         }
+         if ([base isEqualToString:@"manage"]) {
+             controller = [[[ManageController alloc] init] autorelease];
+         }
          if ([base isEqualToString:@"sources"]) {
              controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease];
          }
          if ([base isEqualToString:@"package"]) {
              if ([arg2 isEqualToString:@"settings"]) {
                  controller = [[[PackageSettingsController alloc] initWithDatabase:database_ package:arg1] autorelease];
--            } else if ([arg2 isEqualToString:@"signature"]) {
--                controller = [[[SignatureController alloc] initWithDatabase:database_ package:arg1] autorelease];
              } else if ([arg2 isEqualToString:@"files"]) {
                  if (Package *package = [database_ packageWithName:arg1]) {
                      controller = [[[FileTable alloc] initWithDatabase:database_] autorelease];
          [super applicationWillResignActive:application];
  }
  
 -    [Metadata_ setObject:[tabbar_ navigationURLItems] forKey:@"InterfaceState"];
+ - (void) applicationWillTerminate:(UIApplication *)application {
++    Changed_ = true;
++    [Metadata_ setObject:[tabbar_ navigationURLCollection] forKey:@"InterfaceState"];
+     [Metadata_ setObject:[NSDate date] forKey:@"LastClosed"];
+     [Metadata_ setObject:[NSNumber numberWithInt:[tabbar_ selectedIndex]] forKey:@"InterfaceIndex"];
+     [self _saveConfig];
+ }
  - (void) addStashController {
      ++locked_;
      stash_ = [[StashController alloc] init];
@@@ -9014,9 -9210,51 +9157,51 @@@ _trace()
      [self showEmulatedLoadingControllerInView:nil];
      [window_ setUserInteractionEnabled:YES];
  
-     // Show the home page.
-     CYNavigationController *navigation = [[tabbar_ viewControllers] objectAtIndex:0];
-     [navigation setViewControllers:[NSArray arrayWithObject:[self pageForURL:[NSURL URLWithString:@"cydia://home"]]]];
+     int selectedIndex = 0;
+     NSMutableArray *items = nil;
+     bool recently = false;
+     NSDate *closed([Metadata_ objectForKey:@"LastClosed"]);
+     if (closed != nil) {
+         NSTimeInterval interval([closed timeIntervalSinceNow]);
+         // XXX: Is 15 minutes the optimal time here?
+         if (interval <= 0 && interval > -(15*60))
+             recently = true;
+     }
+     if (recently && [Metadata_ objectForKey:@"InterfaceState"]) {
+         items = [[Metadata_ objectForKey:@"InterfaceState"] mutableCopy];
+         selectedIndex = [[Metadata_ objectForKey:@"InterfaceIndex"] intValue];
+     } else {
+         items = [NSMutableArray array];
+         [items addObject:[NSArray arrayWithObject:@"cydia://home"]];
+         [items addObject:[NSArray arrayWithObject:@"cydia://sections"]];
+         [items addObject:[NSArray arrayWithObject:@"cydia://changes"]];
+         if (!IsWildcat_) {
+             [items addObject:[NSArray arrayWithObject:@"cydia://manage"]];
+         } else {
+             [items addObject:[NSArray arrayWithObject:@"cydia://installed"]];
+             [items addObject:[NSArray arrayWithObject:@"cydia://sources"]];
+         }
+         [items addObject:[NSArray arrayWithObject:@"cydia://search"]];
+     }
+     [tabbar_ setSelectedIndex:selectedIndex];
+     for (unsigned int tab = 0; tab < [[tabbar_ viewControllers] count]; tab++) {
+         NSArray *stack = [items objectAtIndex:tab];
+         CYNavigationController *navigation = [[tabbar_ viewControllers] objectAtIndex:tab];
+         NSMutableArray *current = [NSMutableArray array];
+         for (unsigned int nav = 0; nav < [stack count]; nav++) {
+             NSString *addr = [stack objectAtIndex:nav];
+             NSURL *url = [NSURL URLWithString:addr];
+             CYViewController *page = [self pageForURL:url];
+             if (page != nil)
+                 [current addObject:page];
+         }
+         [navigation setViewControllers:current];
+     }
  
      // (Try to) show the startup URL.
      if (starturl_ != nil) {
diff --combined UICaboodle/RVPage.h
index 1f39428a8d5a6ded7d3502036a788653c9ef1392,68ffb39d6cd6669eeb5eff6817aefb8edcc267cf..5d1346e81e856815491bcc0f95713b607e5d1a96
@@@ -2,10 -2,13 +2,31 @@@
  
  #import <UIKit/UIKit.h>
  
++@interface UIViewController (Cydia)
++- (BOOL) hasLoaded;
++@end
++
  @interface CYViewController : UIViewController {
      id delegate_;
+     BOOL loaded_;
  }
- - (void)setDelegate:(id)delegate;
++
++// The default implementation of this method is essentially a no-op,
++// but calling the superclass implementation is *required*.
 +- (void) reloadData;
++// This URL is used to save the state of the view controller. Return
++// nil if you cannot or should not save the URL for this page.
+ - (NSURL *)navigationURL;
++// By default, this delegate is unused. However, it's provided here in case
++// you need some kind of delegate in a subclass.
+ - (void) setDelegate:(id)delegate;
 -- (void) reloadData;
++- (id)delegate;
++// Override this in subclasses if you manage the "has seen first load" state yourself.
++- (BOOL) hasLoaded;
++// This is called when the view managed by the view controller is released.
++// That is not always when the controller itself is released: it also can
++// happen when more memory is needed by the system or whenever the controller
++// just happens not to be visible.
+ - (void) releaseSubviews;
  @end
  
diff --combined UICaboodle/RVPage.mm
index 3e6e69277335f29a04d2e4dd1ea4df265feaba66,d3de6d31bbd7ee725108e63414bfc25a546b6f03..05a1e25b4c16e5da20d94f072bb1d0c97d79481e
@@@ -5,15 -5,40 +5,58 @@@
  
  #import "RVBook.h"
  
 +extern bool IsWildcat_;
 +
++@implementation UIViewController (Cydia)
++
++- (BOOL) hasLoaded {
++    return YES;
++}
++
++@end
++
  @implementation CYViewController
  - (void) setDelegate:(id)delegate {
      delegate_ = delegate;
  }
 -    if (!loaded_)
++- (id) delegate {
++    return delegate_;
++}
++
+ - (void) viewWillAppear:(BOOL)animated {
+     [super viewWillAppear:animated];
++    if (![self hasLoaded])
+         [self reloadData];
+ }
++- (BOOL) hasLoaded {
++    return loaded_;
++}
++
+ - (void) releaseSubviews {
+     // Do nothing.
+ }
+ - (void) setView:(UIView *)view {
+     if (view == nil)
+         [self releaseSubviews];
+     [super setView:view];
+ }
  - (void) reloadData {
+     loaded_ = YES;
+ }
+ - (NSURL *) navigationURL {
+     return nil;
  }
  - (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
 -    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad || orientation == UIInterfaceOrientationPortrait);
 +    return IsWildcat_ || orientation == UIInterfaceOrientationPortrait;
  }
  @end