]> git.saurik.com Git - cydia.git/blobdiff - Cydia.mm
Replaced Sources icon.
[cydia.git] / Cydia.mm
index b525d61c073337abc3998727e5e298f428f7187e..a8ef907db817e78a40d130dd5accc814a57a2050 100644 (file)
--- a/Cydia.mm
+++ b/Cydia.mm
@@ -98,7 +98,13 @@ class Status :
     }
 
     virtual void Fail(pkgAcquire::ItemDesc &item) {
-        [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
+        if (
+            item.Owner->Status == pkgAcquire::Item::StatIdle ||
+            item.Owner->Status == pkgAcquire::Item::StatDone
+        )
+            return;
+
+        [delegate_ setError:[NSString stringWithCString:item.Owner->ErrorText.c_str()]];
     }
 
     virtual bool Pulse(pkgAcquire *Owner) {
@@ -278,57 +284,6 @@ inline float interpolate(float begin, float end, float fraction) {
 }
 /* }}} */
 
-/* Reset View {{{ */
-@interface ResetView : UIView {
-    UINavigationBar *navbar_;
-    bool resetting_;
-}
-
-- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
-
-- (void) dealloc;
-- (void) resetView;
-- (void) _resetView;
-- (NSString *) leftTitle;
-- (NSString *) rightTitle;
-@end
-
-@implementation ResetView
-
-- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
-    if ([[navbar_ navigationItems] count] == 1)
-        [self _resetView];
-}
-
-- (void) dealloc {
-    [navbar_ release];
-    [super dealloc];
-}
-
-- (void) resetView {
-    resetting_ = true;
-    if ([[navbar_ navigationItems] count] == 1)
-        [self _resetView];
-    else while ([[navbar_ navigationItems] count] != 1)
-        [navbar_ popNavigationItem];
-    resetting_ = false;
-}
-
-- (void) _resetView {
-    [navbar_ showButtonsWithLeftTitle:[self leftTitle] rightTitle:[self rightTitle]];
-}
-
-- (NSString *) leftTitle {
-    return nil;
-}
-
-- (NSString *) rightTitle {
-    return nil;
-}
-
-@end
-/* }}} */
-
 @class Package;
 
 @interface Database : NSObject {
@@ -365,159 +320,56 @@ inline float interpolate(float begin, float end, float fraction) {
 - (void) setDelegate:(id)delegate;
 @end
 
-/* Package Class {{{ */
-@interface Package : NSObject {
-    pkgCache::PkgIterator iterator_;
-    Database *database_;
-    pkgRecords::Parser *parser_;
-    pkgCache::VerIterator version_;
-    pkgCache::VerFileIterator file_;
+/* Reset View {{{ */
+@interface ResetView : UIView {
+    UINavigationBar *navbar_;
+    bool resetting_;
 }
 
-- (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
-+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
-
-- (NSString *) name;
-- (NSString *) section;
-- (NSString *) latest;
-- (NSString *) installed;
-- (Address *) maintainer;
-- (size_t) size;
-- (NSString *) tagline;
-- (NSString *) description;
-- (NSComparisonResult) compareBySectionAndName:(Package *)package;
+- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
 
-- (void) install;
-- (void) remove;
+- (void) dealloc;
+- (void) resetView;
+- (void) _resetView;
+- (NSString *) leftTitle;
+- (NSString *) rightTitle;
 @end
 
-@implementation Package
-
-- (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
-    if ((self = [super init]) != nil) {
-        iterator_ = iterator;
-        database_ = database;
-
-        version_ = version;
-        file_ = file;
-        parser_ = &[database_ records]->Lookup(file);
-    } return self;
-}
-
-+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
-    for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
-        for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
-            return [[[Package alloc]
-                initWithIterator:iterator 
-                database:database
-                version:version
-                file:file]
-            autorelease];
-    return nil;
-}
-
-- (NSString *) name {
-    return [[NSString stringWithCString:iterator_.Name()] lowercaseString];
-}
-
-- (NSString *) section {
-    return [NSString stringWithCString:iterator_.Section()];
-}
-
-- (NSString *) latest {
-    return [NSString stringWithCString:version_.VerStr()];
-}
-
-- (NSString *) installed {
-    return iterator_.CurrentVer().end() ? nil : [NSString stringWithCString:iterator_.CurrentVer().VerStr()];
-}
-
-- (Address *) maintainer {
-    return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
-}
-
-- (size_t) size {
-    return version_->InstalledSize;
-}
-
-- (NSString *) tagline {
-    return [NSString stringWithCString:parser_->ShortDesc().c_str()];
-}
-
-- (NSString *) description {
-    return [NSString stringWithCString:parser_->LongDesc().c_str()];
-}
-
-- (NSComparisonResult) compareBySectionAndName:(Package *)package {
-    NSComparisonResult result = [[self section] compare:[package section]];
-    if (result != NSOrderedSame)
-        return result;
-    return [[self name] compare:[package name]];
-}
-
-- (void) install {
-    pkgProblemResolver *resolver = [database_ resolver];
-    resolver->Clear(iterator_);
-    resolver->Protect(iterator_);
-    [database_ cache]->MarkInstall(iterator_, false);
-}
-
-- (void) remove {
-    pkgProblemResolver *resolver = [database_ resolver];
-    resolver->Clear(iterator_);
-    resolver->Protect(iterator_);
-    resolver->Remove(iterator_);
-    [database_ cache]->MarkDelete(iterator_, true);
-}
+@implementation ResetView
 
-@end
-/* }}} */
-/* Section Class {{{ */
-@interface Section : NSObject {
-    NSString *name_;
-    size_t row_;
-    NSMutableArray *packages_;
+- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
+    if ([[navbar_ navigationItems] count] == 1)
+        [self _resetView];
 }
 
-- (void) dealloc;
-
-- (Section *) initWithName:(NSString *)name row:(size_t)row;
-- (NSString *) name;
-- (size_t) row;
-- (void) addPackage:(Package *)package;
-@end
-
-@implementation Section
-
 - (void) dealloc {
-    [name_ release];
-    [packages_ release];
+    [navbar_ release];
     [super dealloc];
 }
 
-- (Section *) initWithName:(NSString *)name row:(size_t)row {
-    if ((self = [super init]) != nil) {
-        name_ = [name retain];
-        row_ = row;
-        packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
-    } return self;
+- (void) resetView {
+    resetting_ = true;
+    if ([[navbar_ navigationItems] count] == 1)
+        [self _resetView];
+    else while ([[navbar_ navigationItems] count] != 1)
+        [navbar_ popNavigationItem];
+    resetting_ = false;
 }
 
-- (NSString *) name {
-    return name_;
+- (void) _resetView {
+    [navbar_ showButtonsWithLeftTitle:[self leftTitle] rightTitle:[self rightTitle]];
 }
 
-- (size_t) row {
-    return row_;
+- (NSString *) leftTitle {
+    return nil;
 }
 
-- (void) addPackage:(Package *)package {
-    [packages_ addObject:package];
+- (NSString *) rightTitle {
+    return nil;
 }
 
 @end
 /* }}} */
-
 /* Confirmation View {{{ */
 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
     if ([packages count] == 0)
@@ -646,7 +498,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
         return proposed;
     else {
         _assert(size_t(row) < [fields_ count]);
-        fprintf(stderr, "%f\n", [[[fields_ allValues] objectAtIndex:row] contentSize].height);
         return [[[fields_ allValues] objectAtIndex:row] contentSize].height;
     }
 }
@@ -779,37 +630,191 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 
 @end
 /* }}} */
-/* Package View {{{ */
-@interface PackageView : UIView {
-    UIPreferencesTable *table_;
-    Package *package_;
+
+/* Package Class {{{ */
+@interface Package : NSObject {
+    pkgCache::PkgIterator iterator_;
     Database *database_;
-    NSMutableArray *cells_;
-    id delegate_;
+    pkgRecords::Parser *parser_;
+    pkgCache::VerIterator version_;
+    pkgCache::VerFileIterator file_;
 }
 
-- (void) dealloc;
-
-- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
-- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
-- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
-- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
+- (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
 
-- (BOOL) canSelectRow:(int)row;
-- (void) tableRowSelected:(NSNotification *)notification;
+- (NSString *) name;
+- (NSString *) section;
+- (NSString *) latest;
+- (NSString *) installed;
+- (Address *) maintainer;
+- (size_t) size;
+- (NSString *) tagline;
+- (NSString *) description;
+- (NSComparisonResult) compareBySectionAndName:(Package *)package;
 
-- (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
-- (void) setPackage:(Package *)package;
-- (void) setDelegate:(id)delegate;
+- (void) install;
+- (void) remove;
 @end
 
-@implementation PackageView
+@implementation Package
 
-- (void) dealloc {
-    if (package_ != nil)
-        [package_ release];
-    [table_ release];
-    [database_ release];
+- (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
+    if ((self = [super init]) != nil) {
+        iterator_ = iterator;
+        database_ = database;
+
+        version_ = version;
+        file_ = file;
+        parser_ = &[database_ records]->Lookup(file);
+    } return self;
+}
+
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
+    for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
+        for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
+            return [[[Package alloc]
+                initWithIterator:iterator 
+                database:database
+                version:version
+                file:file]
+            autorelease];
+    return nil;
+}
+
+- (NSString *) name {
+    return [[NSString stringWithCString:iterator_.Name()] lowercaseString];
+}
+
+- (NSString *) section {
+    return [NSString stringWithCString:iterator_.Section()];
+}
+
+- (NSString *) latest {
+    return [NSString stringWithCString:version_.VerStr()];
+}
+
+- (NSString *) installed {
+    return iterator_.CurrentVer().end() ? nil : [NSString stringWithCString:iterator_.CurrentVer().VerStr()];
+}
+
+- (Address *) maintainer {
+    return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
+}
+
+- (size_t) size {
+    return version_->InstalledSize;
+}
+
+- (NSString *) tagline {
+    return [NSString stringWithCString:parser_->ShortDesc().c_str()];
+}
+
+- (NSString *) description {
+    return [NSString stringWithCString:parser_->LongDesc().c_str()];
+}
+
+- (NSComparisonResult) compareBySectionAndName:(Package *)package {
+    NSComparisonResult result = [[self section] compare:[package section]];
+    if (result != NSOrderedSame)
+        return result;
+    return [[self name] compare:[package name]];
+}
+
+- (void) install {
+    pkgProblemResolver *resolver = [database_ resolver];
+    resolver->Clear(iterator_);
+    resolver->Protect(iterator_);
+    [database_ cache]->MarkInstall(iterator_, false);
+}
+
+- (void) remove {
+    pkgProblemResolver *resolver = [database_ resolver];
+    resolver->Clear(iterator_);
+    resolver->Protect(iterator_);
+    resolver->Remove(iterator_);
+    [database_ cache]->MarkDelete(iterator_, true);
+}
+
+@end
+/* }}} */
+/* Section Class {{{ */
+@interface Section : NSObject {
+    NSString *name_;
+    size_t row_;
+    NSMutableArray *packages_;
+}
+
+- (void) dealloc;
+
+- (Section *) initWithName:(NSString *)name row:(size_t)row;
+- (NSString *) name;
+- (size_t) row;
+- (void) addPackage:(Package *)package;
+@end
+
+@implementation Section
+
+- (void) dealloc {
+    [name_ release];
+    [packages_ release];
+    [super dealloc];
+}
+
+- (Section *) initWithName:(NSString *)name row:(size_t)row {
+    if ((self = [super init]) != nil) {
+        name_ = [name retain];
+        row_ = row;
+        packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
+    } return self;
+}
+
+- (NSString *) name {
+    return name_;
+}
+
+- (size_t) row {
+    return row_;
+}
+
+- (void) addPackage:(Package *)package {
+    [packages_ addObject:package];
+}
+
+@end
+/* }}} */
+
+/* Package View {{{ */
+@interface PackageView : UIView {
+    UIPreferencesTable *table_;
+    Package *package_;
+    Database *database_;
+    NSMutableArray *cells_;
+    id delegate_;
+}
+
+- (void) dealloc;
+
+- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
+- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
+- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
+- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
+
+- (BOOL) canSelectRow:(int)row;
+- (void) tableRowSelected:(NSNotification *)notification;
+
+- (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
+- (void) setPackage:(Package *)package;
+- (void) setDelegate:(id)delegate;
+@end
+
+@implementation PackageView
+
+- (void) dealloc {
+    if (package_ != nil)
+        [package_ release];
+    [table_ release];
+    [database_ release];
     [cells_ release];
     [super dealloc];
 }
@@ -836,133 +841,358 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     }
 }
 
-- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
-    UIPreferencesTableCell *cell;
+- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
+    UIPreferencesTableCell *cell;
+
+    switch (group) {
+        case 0: switch (row) {
+            case 0:
+                cell = [cells_ objectAtIndex:0];
+                [cell setTitle:@"Name"];
+                [cell setValue:[package_ name]];
+            break;
+
+            case 1: {
+                cell = [cells_ objectAtIndex:1];
+                [cell setTitle:@"Installed"];
+                NSString *installed([package_ installed]);
+                [cell setValue:(installed == nil ? @"n/a" : installed)];
+            } break;
+
+            case 2:
+                cell = [cells_ objectAtIndex:2];
+                [cell setTitle:@"Latest"];
+                [cell setValue:[package_ latest]];
+            break;
+
+            case 3:
+                cell = [cells_ objectAtIndex:3];
+                [cell setTitle:@"Section"];
+                [cell setValue:[package_ section]];
+            break;
+
+            case 4:
+                cell = [cells_ objectAtIndex:4];
+                [cell setTitle:@"Size"];
+                [cell setValue:SizeString([package_ size])];
+            break;
+
+            case 5:
+                cell = [cells_ objectAtIndex:5];
+                [cell setTitle:@"Maintainer"];
+                [cell setValue:[[package_ maintainer] name]];
+                [cell setShowDisclosure:YES];
+                [cell setShowSelection:YES];
+            break;
+
+            default: _assert(false);
+        } break;
+
+        case 1: switch (row) {
+            case 0:
+                cell = [cells_ objectAtIndex:6];
+                [cell setTitle:nil];
+                [cell setValue:[package_ tagline]];
+            break;
+
+            case 1:
+                cell = [cells_ objectAtIndex:7];
+                [cell setTitle:@"Description"];
+                [cell setValue:[package_ description]];
+            break;
+        } break;
+
+        default: _assert(false);
+    }
+
+    return cell;
+}
+
+- (BOOL) canSelectRow:(int)row {
+    return YES;
+}
+
+- (void) tableRowSelected:(NSNotification *)notification {
+    switch ([table_ selectedRow]) {
+        case 5:
+            [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
+                [[package_ maintainer] email],
+                [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
+            ]]];
+        break;
+    }
+}
+
+- (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
+    if ((self = [super initWithFrame:frame]) != nil) {
+        database_ = [database retain];
+
+        table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
+        [self addSubview:table_];
+
+        [table_ setDataSource:self];
+        [table_ setDelegate:self];
+
+        cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
+
+        for (unsigned i = 0; i != 8; ++i) {
+            UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
+            [cell setShowSelection:NO];
+            [cells_ addObject:cell];
+        }
+    } return self;
+}
+
+- (void) setPackage:(Package *)package {
+    package_ = [package retain];
+    [table_ reloadData];
+}
+
+- (void) setDelegate:(id)delegate {
+    delegate_ = delegate;
+}
+
+@end
+/* }}} */
+/* Package Cell {{{ */
+@protocol PackageCellDelegate
+- (NSString *) versionWithPackage:(Package *)package;
+@end
+
+@interface PackageCell : UITableCell {
+    UITextLabel *name_;
+    UIRightTextLabel *version_;
+    UITextLabel *description_;
+    id delegate_;
+}
+
+- (void) dealloc;
+
+- (PackageCell *) initWithDelegate:(id)delegate;
+- (void) setPackage:(Package *)package;
+
+- (void) _setSelected:(float)fraction;
+- (void) setSelected:(BOOL)selected;
+- (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
+- (void) _setSelectionFadeFraction:(float)fraction;
+
+@end
+
+@implementation PackageCell
+
+- (void) dealloc {
+    [name_ release];
+    [version_ release];
+    [description_ release];
+    [super dealloc];
+}
+
+- (PackageCell *) initWithDelegate:(id)delegate {
+    if ((self = [super init]) != nil) {
+        delegate_ = delegate;
+
+        GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
+        GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
+        GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
+
+        CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+        float clear[] = {0, 0, 0, 0};
+
+        name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
+        [name_ setBackgroundColor:CGColorCreate(space, clear)];
+        [name_ setFont:bold];
+
+        version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
+        [version_ setBackgroundColor:CGColorCreate(space, clear)];
+        [version_ setFont:large];
+
+        description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
+        [description_ setBackgroundColor:CGColorCreate(space, clear)];
+        [description_ setFont:small];
+
+        [self addSubview:name_];
+        [self addSubview:version_];
+        [self addSubview:description_];
+
+        CFRelease(small);
+        CFRelease(large);
+        CFRelease(bold);
+    } return self;
+}
+
+- (void) setPackage:(Package *)package {
+    [name_ setText:[package name]];
+    [version_ setText:[delegate_ versionWithPackage:package]];
+    [description_ setText:[package tagline]];
+}
+
+- (void) _setSelected:(float)fraction {
+    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+
+    float black[] = {
+        interpolate(0.0, 1.0, fraction),
+        interpolate(0.0, 1.0, fraction),
+        interpolate(0.0, 1.0, fraction),
+    1.0};
+
+    float blue[] = {
+        interpolate(0.2, 1.0, fraction),
+        interpolate(0.2, 1.0, fraction),
+        interpolate(1.0, 1.0, fraction),
+    1.0};
+
+    float gray[] = {
+        interpolate(0.4, 1.0, fraction),
+        interpolate(0.4, 1.0, fraction),
+        interpolate(0.4, 1.0, fraction),
+    1.0};
+
+    [name_ setColor:CGColorCreate(space, black)];
+    [version_ setColor:CGColorCreate(space, blue)];
+    [description_ setColor:CGColorCreate(space, gray)];
+}
+
+- (void) setSelected:(BOOL)selected {
+    [self _setSelected:(selected ? 1.0 : 0.0)];
+    [super setSelected:selected];
+}
+
+- (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
+    if (!fade)
+        [self _setSelected:(selected ? 1.0 : 0.0)];
+    [super setSelected:selected withFade:fade];
+}
+
+- (void) _setSelectionFadeFraction:(float)fraction {
+    [self _setSelected:fraction];
+    [super _setSelectionFadeFraction:fraction];
+}
+
+@end
+/* }}} */
+
+/* Source {{{ */
+@interface Source : NSObject {
+    NSString *description_;
+    NSString *label_;
+    NSString *origin_;
+
+    NSString *uri_;
+    NSString *distribution_;
+    NSString *type_;
+
+    BOOL trusted_;
+}
+
+- (void) dealloc;
+
+- (Source *) initWithMetaIndex:(metaIndex *)index;
 
-    switch (group) {
-        case 0: switch (row) {
-            case 0:
-                cell = [cells_ objectAtIndex:0];
-                [cell setTitle:@"Name"];
-                [cell setValue:[package_ name]];
-            break;
+- (BOOL) trusted;
 
-            case 1: {
-                cell = [cells_ objectAtIndex:1];
-                [cell setTitle:@"Installed"];
-                NSString *installed([package_ installed]);
-                [cell setValue:(installed == nil ? @"n/a" : installed)];
-            } break;
+- (NSString *) uri;
+- (NSString *) distribution;
+- (NSString *) type;
 
-            case 2:
-                cell = [cells_ objectAtIndex:2];
-                [cell setTitle:@"Latest"];
-                [cell setValue:[package_ latest]];
-            break;
+- (NSString *) description;
+- (NSString *) label;
+- (NSString *) origin;
+@end
 
-            case 3:
-                cell = [cells_ objectAtIndex:3];
-                [cell setTitle:@"Section"];
-                [cell setValue:[package_ section]];
-            break;
+@implementation Source
 
-            case 4:
-                cell = [cells_ objectAtIndex:4];
-                [cell setTitle:@"Size"];
-                [cell setValue:SizeString([package_ size])];
-            break;
+- (void) dealloc {
+    [uri_ release];
+    [distribution_ release];
+    [type_ release];
 
-            case 5:
-                cell = [cells_ objectAtIndex:5];
-                [cell setTitle:@"Maintainer"];
-                [cell setValue:[[package_ maintainer] name]];
-                [cell setShowDisclosure:YES];
-                [cell setShowSelection:YES];
-            break;
+    if (description_ != nil)
+        [description_ release];
+    if (label_ != nil)
+        [label_ release];
+    if (origin_ != nil)
+        [origin_ release];
 
-            default: _assert(false);
-        } break;
+    [super dealloc];
+}
 
-        case 1: switch (row) {
-            case 0:
-                cell = [cells_ objectAtIndex:6];
-                [cell setTitle:nil];
-                [cell setValue:[package_ tagline]];
-            break;
+- (Source *) initWithMetaIndex:(metaIndex *)index {
+    if ((self = [super init]) != nil) {
+        trusted_ = index->IsTrusted();
 
-            case 1:
-                cell = [cells_ objectAtIndex:7];
-                [cell setTitle:@"Description"];
-                [cell setValue:[package_ description]];
-            break;
-        } break;
+        uri_ = [[NSString stringWithCString:index->GetURI().c_str()] retain];
+        distribution_ = [[NSString stringWithCString:index->GetDist().c_str()] retain];
+        type_ = [[NSString stringWithCString:index->GetType()] retain];
 
-        default: _assert(false);
-    }
+        description_ = nil;
+        label_ = nil;
+        origin_ = nil;
 
-    return cell;
+        debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
+        if (dindex != NULL) {
+            std::ifstream release(dindex->MetaIndexFile("Release").c_str());
+            std::string line;
+            while (std::getline(release, line)) {
+                std::string::size_type colon(line.find(':'));
+                if (colon == std::string::npos)
+                    continue;
+
+                std::string name(line.substr(0, colon));
+                std::string value(line.substr(colon + 1));
+                while (!value.empty() && value[0] == ' ')
+                    value = value.substr(1);
+
+                if (name == "Description")
+                    description_ = [[NSString stringWithCString:value.c_str()] retain];
+                else if (name == "Label")
+                    label_ = [[NSString stringWithCString:value.c_str()] retain];
+                else if (name == "Origin")
+                    origin_ = [[NSString stringWithCString:value.c_str()] retain];
+            }
+        }
+    } return self;
 }
 
-- (BOOL) canSelectRow:(int)row {
-    return YES;
+- (BOOL) trusted {
+    return trusted_;
 }
 
-- (void) tableRowSelected:(NSNotification *)notification {
-    switch ([table_ selectedRow]) {
-        case 5:
-            [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
-                [[package_ maintainer] email],
-                [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
-            ]]];
-        break;
-    }
+- (NSString *) uri {
+    return uri_;
 }
 
-- (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
-    if ((self = [super initWithFrame:frame]) != nil) {
-        database_ = [database retain];
-
-        table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
-        [self addSubview:table_];
-
-        [table_ setDataSource:self];
-        [table_ setDelegate:self];
+- (NSString *) distribution {
+    return distribution_;
+}
 
-        cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
+- (NSString *) type {
+    return type_;
+}
 
-        for (unsigned i = 0; i != 8; ++i) {
-            UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
-            [cell setShowSelection:NO];
-            [cells_ addObject:cell];
-        }
-    } return self;
+- (NSString *) description {
+    return description_;
 }
 
-- (void) setPackage:(Package *)package {
-    package_ = [package retain];
-    [table_ reloadData];
+- (NSString *) label {
+    return label_;
 }
 
-- (void) setDelegate:(id)delegate {
-    delegate_ = delegate;
+- (NSString *) origin {
+    return origin_;
 }
 
 @end
 /* }}} */
-/* Package Cell {{{ */
-@protocol PackageCellDelegate
-- (NSString *) versionWithPackage:(Package *)package;
-@end
-
-@interface PackageCell : UITableCell {
-    UITextLabel *name_;
-    UIRightTextLabel *version_;
+/* Source Cell {{{ */
+@interface SourceCell : UITableCell {
     UITextLabel *description_;
+    UIRightTextLabel *label_;
+    UITextLabel *origin_;
 }
 
 - (void) dealloc;
 
-- (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate;
+- (SourceCell *) initWithSource:(Source *)source;
 
 - (void) _setSelected:(float)fraction;
 - (void) setSelected:(BOOL)selected;
@@ -971,45 +1201,55 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 
 @end
 
-@implementation PackageCell
+@implementation SourceCell
 
 - (void) dealloc {
-    [name_ release];
-    [version_ release];
     [description_ release];
+    [label_ release];
+    [origin_ release];
     [super dealloc];
 }
 
-- (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate {
+- (SourceCell *) initWithSource:(Source *)source {
     if ((self = [super init]) != nil) {
-        GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
-        GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
+        GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 20);
         GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
 
         CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
         float clear[] = {0, 0, 0, 0};
 
-        name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
-        [name_ setText:[package name]];
-        [name_ setBackgroundColor:CGColorCreate(space, clear)];
-        [name_ setFont:bold];
-
-        version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
-        [version_ setText:[delegate versionWithPackage:package]];
-        [version_ setBackgroundColor:CGColorCreate(space, clear)];
-        [version_ setFont:large];
+        NSString *description = [source description];
+        if (description == nil)
+            description = [source uri];
 
-        description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
-        [description_ setText:[package tagline]];
+        description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 270, 25)];
         [description_ setBackgroundColor:CGColorCreate(space, clear)];
-        [description_ setFont:small];
+        [description_ setFont:bold];
+        [description_ setText:description];
+
+        NSString *label = [source label];
+        if (label == nil)
+            label = [source type];
+
+        label_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 32, 90, 25)];
+        [label_ setBackgroundColor:CGColorCreate(space, clear)];
+        [label_ setFont:small];
+        [label_ setText:label];
+
+        NSString *origin = [source origin];
+        if (origin == nil)
+            origin = [source distribution];
+
+        origin_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
+        [origin_ setBackgroundColor:CGColorCreate(space, clear)];
+        [origin_ setFont:small];
+        [origin_ setText:origin];
 
-        [self addSubview:name_];
-        [self addSubview:version_];
         [self addSubview:description_];
+        [self addSubview:label_];
+        [self addSubview:origin_];
 
         CFRelease(small);
-        CFRelease(large);
         CFRelease(bold);
     } return self;
 }
@@ -1035,9 +1275,9 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
         interpolate(0.4, 1.0, fraction),
     1.0};
 
-    [name_ setColor:CGColorCreate(space, black)];
-    [version_ setColor:CGColorCreate(space, blue)];
-    [description_ setColor:CGColorCreate(space, gray)];
+    [description_ setColor:CGColorCreate(space, black)];
+    [label_ setColor:CGColorCreate(space, blue)];
+    [origin_ setColor:CGColorCreate(space, gray)];
 }
 
 - (void) setSelected:(BOOL)selected {
@@ -1064,9 +1304,21 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     Database *database_;
     id delegate_;
     NSMutableArray *sources_;
+    UIAlertSheet *alert_;
 }
 
+- (int) numberOfSectionsInSectionList:(UISectionList *)list;
+- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
+- (int) sectionList:(UISectionList *)list rowForSection:(int)section;
+
+- (int) numberOfRowsInTable:(UITable *)table;
+- (float) table:(UITable *)table heightForRow:(int)row;
+- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col;
+- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
+- (void) tableRowSelected:(NSNotification*)notification;
+
 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
+
 - (void) dealloc;
 - (id) initWithFrame:(CGRect)frame database:(Database *)database;
 - (void) setDelegate:(id)delegate;
@@ -1077,9 +1329,62 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 
 @implementation SourcesView
 
+- (int) numberOfSectionsInSectionList:(UISectionList *)list {
+    return 1;
+}
+
+- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
+    return @"sources";
+}
+
+- (int) sectionList:(UISectionList *)list rowForSection:(int)section {
+    return 0;
+}
+
+- (int) numberOfRowsInTable:(UITable *)table {
+    return [sources_ count];
+}
+
+- (float) table:(UITable *)table heightForRow:(int)row {
+    return 64;
+}
+
+- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
+    return [[[SourceCell alloc] initWithSource:[sources_ objectAtIndex:row]] autorelease];
+}
+
+- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
+    return NO;
+}
+
+- (void) tableRowSelected:(NSNotification*)notification {
+    UITable *table([list_ table]);
+    int row([table selectedRow]);
+    if (row == INT_MAX)
+        return;
+
+    [table selectRow:-1 byExtendingSelection:NO withFade:YES];
+}
+
+- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
+    [alert_ dismiss];
+    [alert_ release];
+    alert_ = nil;
+}
+
 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
     switch (button) {
         case 0:
+            alert_ = [[UIAlertSheet alloc]
+                initWithTitle:@"Unimplemented"
+                buttons:[NSArray arrayWithObjects:@"Okay", nil]
+                defaultButtonIndex:0
+                delegate:self
+                context:self
+            ];
+
+            [alert_ setBodyText:@"This feature will be implemented soon. In the mean time, you may add sources by adding .list files to '/etc/apt/sources.list.d'. If you'd like to be in the default list, please contact the author of Packager."];
+            [alert_ popupAlertAnimated:YES];
         break;
 
         case 1:
@@ -1117,8 +1422,21 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
             0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
         )];
 
+        [self addSubview:list_];
+
         [list_ setDataSource:self];
-        //[list_ setShouldHideHeaderInShortLists:NO];
+        [list_ setShouldHideHeaderInShortLists:NO];
+
+        UITableColumn *column = [[UITableColumn alloc]
+            initWithTitle:@"Name"
+            identifier:@"name"
+            width:frame.size.width
+        ];
+
+        UITable *table = [list_ table];
+        [table setSeparatorStyle:1];
+        [table addTableColumn:column];
+        [table setDelegate:self];
     } return self;
 }
 
@@ -1130,33 +1448,15 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     pkgSourceList list;
     _assert(list.ReadMainList());
 
-    sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
-
-    for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) {
-        metaIndex *index(*source);
-        fprintf(stderr, "\"%s\" \"%s\" \"%s\" \"%s\"\n", index->GetURI().c_str(), index->GetDist().c_str(), index->GetType(), index->IsTrusted() ? "true" : "false");
+    if (sources_ != nil)
+        [sources_ release];
 
-        debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
-        if (dindex == NULL)
-            continue;
-
-        fprintf(stderr, " \"%s\"\n", dindex->MetaIndexFile("Release").c_str());
-
-        std::ifstream release(dindex->MetaIndexFile("Release").c_str());
-        std::string line;
-        while (std::getline(release, line)) {
-            std::string::size_type colon(line.find(':'));
-            if (colon == std::string::npos)
-                continue;
-            std::string name(line.substr(0, colon));
-            std::string value(line.substr(colon + 1));
-            while (!value.empty() && value[0] == ' ')
-                value = value.substr(1);
-            std::cerr << "[" << name << "|" << value << "]" << std::endl;
-        }
-    }
+    sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
+    for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
+        [sources_ addObject:[[[Source alloc] initWithMetaIndex:*source] autorelease]];
 
     [self resetView];
+    [list_ reloadData];
 }
 
 - (NSString *) leftTitle {
@@ -1358,8 +1658,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     }
 
     _assert(pkgDistUpgrade(cache_));
-
-    //InstallPackages(cache_, true);
 }
 
 - (void) setDelegate:(id)delegate {
@@ -1421,7 +1719,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     UITextView *output_;
     UITextLabel *status_;
     id delegate_;
-    UIAlertSheet *alert_;
 }
 
 - (void) dealloc;
@@ -1447,8 +1744,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 
 - (void) addOutput:(NSString *)output;
 - (void) _addOutput:(NSString *)output;
-
-- (void) setStatusFail;
 @end
 
 @protocol ProgressViewDelegate
@@ -1472,7 +1767,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
     if ((self = [super initWithFrame:frame]) != nil) {
         delegate_ = delegate;
-        alert_ = nil;
 
         CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
         float black[] = {0.0, 0.0, 0.0, 1.0};
@@ -1556,9 +1850,7 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 }
 
 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
-    [alert_ dismiss];
-    [alert_ release];
-    alert_ = nil;
+    [sheet dismiss];
 }
 
 - (void) _retachThread {
@@ -1594,9 +1886,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     ];
 }
 
-- (void) setStatusFail {
-}
-
 - (void) setError:(NSString *)error {
     [self
         performSelectorOnMainThread:@selector(_setError:)
@@ -1606,18 +1895,16 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 }
 
 - (void) _setError:(NSString *)error {
-    _assert(alert_ == nil);
-
-    alert_ = [[UIAlertSheet alloc]
+    UIAlertSheet *sheet = [[[UIAlertSheet alloc]
         initWithTitle:@"Package Error"
         buttons:[NSArray arrayWithObjects:@"Okay", nil]
         defaultButtonIndex:0
         delegate:self
         context:self
-    ];
+    ] autorelease];
 
-    [alert_ setBodyText:error];
-    [alert_ popupAlertAnimated:YES];
+    [sheet setBodyText:error];
+    [sheet popupAlertAnimated:YES];
 }
 
 - (void) setTitle:(NSString *)title {
@@ -1689,7 +1976,7 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 
 - (int) numberOfRowsInTable:(UITable *)table;
 - (float) table:(UITable *)table heightForRow:(int)row;
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col;
+- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
 - (void) tableRowSelected:(NSNotification*)notification;
 
@@ -1701,6 +1988,7 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 - (void) deselect;
 - (void) reloadData:(BOOL)reset;
 
+- (NSMutableArray *) packages;
 - (NSString *) title;
 - (void) perform:(Package *)package;
 - (void) addPackage:(Package *)package;
@@ -1729,10 +2017,11 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     return 64;
 }
 
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
-    Package *package = [packages_ objectAtIndex:row];
-    PackageCell *cell = [[[PackageCell alloc] initWithPackage:package delegate:self] autorelease];
-    return cell;
+- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
+    if (reusing == nil)
+        reusing = [[PackageCell alloc] initWithDelegate:self];
+    [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
+    return reusing;
 }
 
 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
@@ -1815,6 +2104,7 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
         [table setSeparatorStyle:1];
         [table addTableColumn:column];
         [table setDelegate:self];
+        [table setReusesTableCells:YES];
 
         pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
     } return self;
@@ -1833,12 +2123,12 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 }
 
 - (void) reloadData:(BOOL)reset {
-    packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
-
-    if (sections_ != nil) {
+    if (sections_ != nil)
         [sections_ release];
-        sections_ = nil;
-    }
+    if (packages_ != nil)
+        [packages_ release];
+
+    packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
 
     for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
         if (Package *package = [Package packageWithIterator:iterator database:database_])
@@ -1869,6 +2159,10 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     }
 }
 
+- (NSMutableArray *) packages {
+    return packages_;
+}
+
 - (NSString *) title {
     return nil;
 }
@@ -1922,6 +2216,8 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 @interface UpgradeView : PackagesView {
 }
 
+- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
+
 - (NSString *) title;
 - (NSString *) leftTitle;
 - (void) addPackage:(Package *)package;
@@ -1931,12 +2227,21 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 
 @implementation UpgradeView
 
+- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
+    if (button != 1)
+        [super navigationBar:navbar buttonClicked:button];
+    else {
+        [database_ upgrade];
+        [delegate_ perform];
+    }
+}
+
 - (NSString *) title {
     return @"Upgrade";
 }
 
 - (NSString *) leftTitle {
-    return @"Upgrade All";
+    return [packages_ count] == 0 ? nil : @"Upgrade All";
 }
 
 - (void) addPackage:(Package *)package {
@@ -1998,7 +2303,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     UITransitionView *transition_;
     UIButtonBar *buttonbar_;
 
-    UIAlertSheet *alert_;
     ConfirmationView *confirm_;
 
     Database *database_;
@@ -2009,6 +2313,7 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     UIScroller *scroller_;
     UIWebView *webview_;
     NSURL *url_;
+    UIProgressIndicator *indicator_;
 
     InstallView *install_;
     UpgradeView *upgrade_;
@@ -2029,8 +2334,7 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
 - (void) buttonBarItemTapped:(id)sender;
 
-- (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
-- (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
+- (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
 
 - (void) applicationDidFinishLaunching:(id)unused;
 @end
@@ -2050,6 +2354,7 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
 
     [webview_ loadRequest:request];
+    [indicator_ startAnimation];
 }
 
 - (void) reloadData:(BOOL)reset {
@@ -2058,6 +2363,17 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     [upgrade_ reloadData:reset];
     [uninstall_ reloadData:reset];
     [sources_ reloadData];
+
+    if (size_t count = [[upgrade_ packages] count]) {
+        NSString *badge([[NSNumber numberWithInt:count] stringValue]);
+        [buttonbar_ setBadgeValue:badge forButton:3];
+        [buttonbar_ setBadgeAnimated:YES forButton:3];
+        [self setApplicationBadge:badge];
+    } else {
+        [buttonbar_ setBadgeValue:nil forButton:3];
+        [buttonbar_ setBadgeAnimated:NO forButton:3];
+        [self removeApplicationBadge];
+    }
 }
 
 - (void) perform {
@@ -2107,17 +2423,15 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
         break;
 
         case 1:
-            _assert(alert_ == nil);
-
-            alert_ = [[UIAlertSheet alloc]
+            UIAlertSheet *sheet = [[[UIAlertSheet alloc]
                 initWithTitle:@"About Cydia Packager"
                 buttons:[NSArray arrayWithObjects:@"Close", nil]
                 defaultButtonIndex:0
                 delegate:self
                 context:self
-            ];
+            ] autorelease];
 
-            [alert_ setBodyText:
+            [sheet setBodyText:
                 @"Copyright (C) 2007\n"
                 "Jay Freeman (saurik)\n"
                 "saurik@saurik.com\n"
@@ -2138,15 +2452,13 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
                 "lounger, rockabilly, tman, Wbiggs"
             ];
 
-            [alert_ presentSheetFromButtonBar:buttonbar_];
+            [sheet presentSheetFromButtonBar:buttonbar_];
         break;
     }
 }
 
 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
-    [alert_ dismiss];
-    [alert_ release];
-    alert_ = nil;
+    [sheet dismiss];
 }
 
 - (void) buttonBarItemTapped:(id)sender {
@@ -2168,19 +2480,15 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     [transition_ transition:0 toView:view];
 }
 
-- (void) view:(UIView *)view didSetFrame:(CGRect)frame {
+- (void) view:(UIView *)view didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
     [scroller_ setContentSize:frame.size];
-}
-
-- (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
-    [scroller_ setContentSize:[webview_ bounds].size];
+    [indicator_ stopAnimation];
 }
 
 - (void) applicationDidFinishLaunching:(id)unused {
     _assert(pkgInitConfig(*_config));
     _assert(pkgInitSystem(*_config, _system));
 
-    alert_ = nil;
     confirm_ = nil;
 
     CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
@@ -2247,6 +2555,11 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     [webview_ setAutoresizes:YES];
     [webview_ setDelegate:self];
 
+    CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
+    indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 15, indsize.width, indsize.height)];
+    [indicator_ setStyle:2];
+    [featured_ addSubview:indicator_];
+
     NSArray *buttonitems = [NSArray arrayWithObjects:
         [NSDictionary dictionaryWithObjectsAndKeys:
             @"buttonBarItemTapped:", kUIButtonBarButtonAction,
@@ -2341,28 +2654,6 @@ void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString
     sources_ = [[SourcesView alloc] initWithFrame:[transition_ bounds] database:database_];
     [sources_ setDelegate:self];
 
-#if 0
-
-    UIAlertSheet *alert = [[UIAlertSheet alloc]
-        initWithTitle:@"Alert Title"
-        buttons:[NSArray arrayWithObjects:@"Yes", nil]
-        defaultButtonIndex:0
-        delegate:self
-        context:self
-    ];
-
-    NSLog(@"%p\n", [alert table]);
-    [[alert table] setDelegate:self];
-    [[alert table] reloadData];
-
-    [alert addTextFieldWithValue:@"Title" label:@"Label"];
-    [alert setShowsOverSpringBoardAlerts:YES];
-    [alert setBodyText:@"This is an alert."];
-    [alert presentSheetFromButtonBar:buttonbar_];
-    //[alert popupAlertAnimated:YES];
-
-#endif
-
     [self reloadData:NO];
     [progress_ resetView];