/* #include Directives {{{ */
+#include <Foundation/NSURL.h>
#include <UIKit/UIKit.h>
#import <GraphicsServices/GraphicsServices.h>
+#include <sstream>
+#include <ext/stdio_filebuf.h>
+
#include <apt-pkg/acquire.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/algorithms.h>
#include <apt-pkg/cachefile.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/debmetaindex.h>
#include <apt-pkg/error.h>
#include <apt-pkg/init.h>
#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/sptr.h>
+
+#include <sys/sysctl.h>
+#include <errno.h>
#include <pcre.h>
#include <string.h>
/* }}} */
/* Extension Keywords {{{ */
-#define _trace() printf("_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
+#define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
#define _assert(test) do \
if (!(test)) { \
- printf("_assert(%s)@%s:%u[%s]\n", #test, __FILE__, __LINE__, __FUNCTION__); \
+ fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
exit(-1); \
} \
while (false)
/* }}} */
+@interface WebView
+- (void) setApplicationNameForUserAgent:(NSString *)applicationName;
+@end
+
+static const int PulseInterval_ = 50000;
+const char *Machine_ = NULL;
+const char *SerialNumber_ = NULL;
+
+@interface NSString (CydiaBypass)
+- (NSString *) stringByAddingPercentEscapes;
+@end
+
+@protocol ProgressDelegate
+- (void) setError:(NSString *)error;
+- (void) setTitle:(NSString *)title;
+- (void) setPercent:(float)percent;
+- (void) addOutput:(NSString *)output;
+@end
+
+NSString *SizeString(double size) {
+ unsigned power = 0;
+ while (size > 1024) {
+ size /= 1024;
+ ++power;
+ }
+
+ static const char *powers_[] = {"B", "kB", "MB", "GB"};
+
+ return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
+}
+
/* Status Delegation {{{ */
class Status :
public pkgAcquireStatus
}
virtual void IMSHit(pkgAcquire::ItemDesc &item) {
- [delegate_ performSelectorOnMainThread:@selector(setStatusIMSHit) withObject:nil waitUntilDone:YES];
}
virtual void Fetch(pkgAcquire::ItemDesc &item) {
- [delegate_ performSelectorOnMainThread:@selector(setStatusFetch) withObject:nil waitUntilDone:YES];
+ [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
}
virtual void Done(pkgAcquire::ItemDesc &item) {
- [delegate_ performSelectorOnMainThread:@selector(setStatusDone) withObject:nil waitUntilDone:YES];
}
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) {
- [delegate_ performSelectorOnMainThread:@selector(setStatusPulse) withObject:nil waitUntilDone:YES];
- return true;
+ bool value = pkgAcquireStatus::Pulse(Owner);
+
+ float percent(
+ double(CurrentBytes + CurrentItems) /
+ double(TotalBytes + TotalItems)
+ );
+
+ [delegate_ setPercent:percent];
+ return value;
}
virtual void Start() {
- [delegate_ performSelectorOnMainThread:@selector(setStatusStart) withObject:nil waitUntilDone:YES];
}
virtual void Stop() {
- [delegate_ performSelectorOnMainThread:@selector(setStatusStop) withObject:nil waitUntilDone:YES];
}
};
/* }}} */
protected:
virtual void Update() {
- printf("Update(): %f (%s)\n", Percent, Op.c_str());
+ [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
+ [delegate_ setPercent:(Percent / 100)];
}
public:
}
virtual void Done() {
- printf("Done()\n");
+ [delegate_ setPercent:1];
}
};
/* }}} */
NSString *email_;
}
+- (void) dealloc;
+
- (NSString *) name;
- (NSString *) email;
@implementation Address
+- (void) dealloc {
+ [name_ release];
+ if (email_ != nil)
+ [email_ release];
+ [super dealloc];
+}
+
- (NSString *) name {
return name_;
}
}
+ (Address *) addressWithString:(NSString *)string {
- return [[[Address alloc] initWithString:string] retain];
+ return [[[Address alloc] initWithString:string] autorelease];
}
- (Address *) initWithString:(NSString *)string {
if ((self = [super init]) != nil) {
const char *error;
int offset;
-
pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
if (code == NULL) {
- printf("%d:%s\n", offset, error);
+ fprintf(stderr, "%d:%s\n", offset, error);
_assert(false);
}
pcre_extra *study = NULL;
int capture;
pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
+ int matches[(capture + 1) * 3];
size_t size = [string length];
const char *data = [string UTF8String];
- int matches[(capture + 1) * 3];
- pcre_exec(code, study, data, size, 0, 0, matches, sizeof(matches) / sizeof(matches[0]));
-
- name_ = [[NSString stringWithCString:(data + matches[2]) length:(matches[3] - matches[2])] retain];
- email_ = [[NSString stringWithCString:(data + matches[4]) length:(matches[5] - matches[4])] retain];
+ if (pcre_exec(code, study, data, size, 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0) {
+ name_ = [[NSString stringWithCString:(data + matches[2]) length:(matches[3] - matches[2])] retain];
+ email_ = [[NSString stringWithCString:(data + matches[4]) length:(matches[5] - matches[4])] retain];
+ } else {
+ name_ = [[NSString stringWithCString:data length:size] retain];
+ email_ = nil;
+ }
} return self;
}
@end
/* }}} */
+/* Linear Algebra {{{ */
+inline float interpolate(float begin, float end, float fraction) {
+ return (end - begin) * fraction + begin;
+}
+/* }}} */
+
+@class Package;
@interface Database : NSObject {
pkgCacheFile cache_;
pkgRecords *records_;
pkgProblemResolver *resolver_;
+ pkgAcquire *fetcher_;
+ FileFd *lock_;
+ SPtr<pkgPackageManager> manager_;
+ id delegate_;
Status status_;
Progress progress_;
+ int statusfd_;
}
+- (void) _readStatus:(NSNumber *)fd;
+- (void) _readOutput:(NSNumber *)fd;
+
+- (Package *) packageWithName:(NSString *)name;
+
- (Database *) init;
- (pkgCacheFile &) cache;
- (pkgRecords *) records;
- (pkgProblemResolver *) resolver;
+- (pkgAcquire &) fetcher;
- (void) reloadData;
+
+- (void) prepare;
+- (void) perform;
- (void) update;
- (void) upgrade;
+
- (void) setDelegate:(id)delegate;
@end
+/* 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
+/* }}} */
+/* Confirmation View {{{ */
+void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
+ if ([packages count] == 0)
+ return;
+
+ CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+ float clear[] = {0, 0, 0, 0};
+ float blue[] = {0, 0, 0.4, 1};
+
+ UITextView *text([[[UITextView alloc] initWithFrame: CGRectMake(110, 3, 200, 60)] autorelease]);
+ [text setEditable:NO];
+ [text setTextSize:16];
+ [text setBackgroundColor:CGColorCreate(space, clear)];
+ [text setTextColor:CGColorCreate(space, blue)];
+ [text setText:([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "])];
+ [text setEnabled:NO];
+
+ CGRect frame([text frame]);
+ CGSize size([text contentSize]);
+ frame.size.height = size.height;
+ [text setFrame:frame];
+
+ [fields setObject:text forKey:key];
+}
+
+@protocol ConfirmationViewDelegate
+- (void) cancel;
+- (void) confirm;
+@end
+
+@interface ConfirmationView : UIView {
+ Database *database_;
+ id delegate_;
+ UITransitionView *transition_;
+ UIView *overlay_;
+ UINavigationBar *navbar_;
+ UIPreferencesTable *table_;
+ NSMutableDictionary *fields_;
+ UIAlertSheet *essential_;
+}
+
+- (void) dealloc;
+- (void) cancel;
+
+- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
+- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
+- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
+
+- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
+- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
+- (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
+- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
+- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
+
+- (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
+
+@end
+
+@implementation ConfirmationView
+
+- (void) dealloc {
+ [transition_ release];
+ [overlay_ release];
+ [navbar_ release];
+ [table_ release];
+ [fields_ release];
+ if (essential_ != nil)
+ [essential_ release];
+ [super dealloc];
+}
+
+- (void) cancel {
+ [transition_ transition:7 toView:nil];
+ [delegate_ cancel];
+}
+
+- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
+ if (from != nil && to == nil)
+ [self removeFromSuperview];
+}
+
+- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
+ switch (button) {
+ case 0:
+ if (essential_ != nil)
+ [essential_ popupAlertAnimated:YES];
+ else
+ [delegate_ confirm];
+ break;
+
+ case 1:
+ [self cancel];
+ break;
+ }
+}
+
+- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
+ [essential_ dismiss];
+ [self cancel];
+}
+
+- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
+ return 2;
+}
+
+- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
+ switch (group) {
+ case 0: return @"Statistics";
+ case 1: return @"Modifications";
+
+ default: _assert(false);
+ }
+}
+
+- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
+ switch (group) {
+ case 0: return 3;
+ case 1: return [fields_ count];
+
+ default: _assert(false);
+ }
+}
+
+- (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
+ if (group != 1 || row == -1)
+ return proposed;
+ else {
+ _assert(size_t(row) < [fields_ count]);
+ return [[[fields_ allValues] objectAtIndex:row] contentSize].height;
+ }
+}
+
+- (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
+ UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
+ [cell setShowSelection:NO];
+
+ switch (group) {
+ case 0: switch (row) {
+ case 0: {
+ [cell setTitle:@"Downloading"];
+ [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
+ } break;
+
+ case 1: {
+ [cell setTitle:@"Resuming At"];
+ [cell setValue:SizeString([database_ fetcher].PartialPresent())];
+ } break;
+
+ case 2: {
+ double size([database_ cache]->UsrSize());
+
+ if (size < 0) {
+ [cell setTitle:@"Disk Freeing"];
+ [cell setValue:SizeString(-size)];
+ } else {
+ [cell setTitle:@"Disk Using"];
+ [cell setValue:SizeString(size)];
+ }
+ } break;
+
+ default: _assert(false);
+ } break;
+
+ case 1:
+ _assert(size_t(row) < [fields_ count]);
+ [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
+ [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
+ break;
+
+ default: _assert(false);
+ }
+
+ return cell;
+}
+
+- (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate {
+ if ((self = [super initWithFrame:[view bounds]]) != nil) {
+ database_ = database;
+ delegate_ = delegate;
+
+ transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
+ [self addSubview:transition_];
+
+ overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
+
+ CGSize navsize = [UINavigationBar defaultSize];
+ CGRect navrect = {{0, 0}, navsize};
+ CGRect bounds = [overlay_ bounds];
+
+ navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
+ [navbar_ setBarStyle:1];
+ [navbar_ setDelegate:self];
+
+ UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
+ [navbar_ pushNavigationItem:navitem];
+ [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
+
+ fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
+
+ NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
+ NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
+ NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
+
+ bool essential(false);
+
+ pkgCacheFile &cache([database_ cache]);
+ for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
+ NSString *name([NSString stringWithCString:iterator.Name()]);
+ if (cache[iterator].NewInstall())
+ [installing addObject:name];
+ else if (cache[iterator].Upgrade())
+ [upgrading addObject:name];
+ else if (cache[iterator].Delete()) {
+ [removing addObject:name];
+ if ((iterator->Flags & pkgCache::Flag::Essential) != 0)
+ essential = true;
+ }
+ }
+
+ if (!essential)
+ essential_ = nil;
+ else {
+ essential_ = [[UIAlertSheet alloc]
+ initWithTitle:@"Unable to Comply"
+ buttons:[NSArray arrayWithObjects:@"Okay", nil]
+ defaultButtonIndex:0
+ delegate:self
+ context:self
+ ];
+
+ [essential_ setBodyText:@"One or more of the packages you are about to remove are marked 'Essential' and cannot be removed by Cydia. Please use apt-get."];
+ }
+
+ AddTextView(fields_, installing, @"Installing");
+ AddTextView(fields_, upgrading, @"Upgrading");
+ AddTextView(fields_, removing, @"Removing");
+
+ table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
+ 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
+ )];
+
+ [table_ setReusesTableCells:YES];
+ [table_ setDataSource:self];
+ [table_ reloadData];
+
+ [overlay_ addSubview:navbar_];
+ [overlay_ addSubview:table_];
+
+ [view addSubview:self];
+
+ [transition_ setDelegate:self];
+
+ UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
+ [transition_ transition:0 toView:blank];
+ [transition_ transition:3 toView:overlay_];
+ } return self;
+}
+
+@end
+/* }}} */
+
/* Package Class {{{ */
@interface Package : NSObject {
pkgCache::PkgIterator iterator_;
Database *database_;
- UITableCell *cell_;
pkgRecords::Parser *parser_;
pkgCache::VerIterator version_;
pkgCache::VerFileIterator file_;
- (NSString *) name;
- (NSString *) section;
-- (BOOL) installed;
-- (NSString *) version;
+- (NSString *) latest;
+- (NSString *) installed;
- (Address *) maintainer;
- (size_t) size;
- (NSString *) tagline;
- (NSString *) description;
-- (UITableCell *) cell;
-- (void) setCell:(UITableCell *)cell;
- (NSComparisonResult) compareBySectionAndName:(Package *)package;
- (void) install;
if ((self = [super init]) != nil) {
iterator_ = iterator;
database_ = database;
- cell_ = nil;
version_ = version;
file_ = file;
+ (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];
+ return [[[Package alloc]
+ initWithIterator:iterator
+ database:database
+ version:version
+ file:file]
+ autorelease];
return nil;
}
- (NSString *) name {
- return [NSString stringWithCString:iterator_.Name()];
+ return [[NSString stringWithCString:iterator_.Name()] lowercaseString];
}
- (NSString *) section {
return [NSString stringWithCString:iterator_.Section()];
}
-- (BOOL) installed {
- return iterator_->CurrentState != pkgCache::State::NotInstalled;
+- (NSString *) latest {
+ return [NSString stringWithCString:version_.VerStr()];
}
-- (NSString *) version {
- return [NSString stringWithCString:version_.VerStr()];
+- (NSString *) installed {
+ return iterator_.CurrentVer().end() ? nil : [NSString stringWithCString:iterator_.CurrentVer().VerStr()];
}
- (Address *) maintainer {
return [NSString stringWithCString:parser_->LongDesc().c_str()];
}
-- (UITableCell *) cell {
- return cell_;
-}
-
-- (void) setCell:(UITableCell *)cell {
- cell_ = cell;
-}
-
- (NSComparisonResult) compareBySectionAndName:(Package *)package {
NSComparisonResult result = [[self section] compare:[package section]];
if (result != NSOrderedSame)
resolver->Clear(iterator_);
resolver->Protect(iterator_);
resolver->Remove(iterator_);
- [database_ cache]->MarkDelete(iterator_, false);
+ [database_ cache]->MarkDelete(iterator_, true);
}
@end
NSMutableArray *packages_;
}
+- (void) dealloc;
+
- (Section *) initWithName:(NSString *)name row:(size_t)row;
- (NSString *) name;
- (size_t) row;
@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];
@end
/* }}} */
-/* Confirmation View {{{ */
-@interface ConfirmationView : UIView {
-}
-
-@end
-
-@implementation ConfirmationView
-@end
-/* }}} */
/* Package View {{{ */
-@interface PackageView : UIPreferencesTable {
+@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;
-- (PackageView *) initWithFrame:(struct CGRect)frame database:(Database *)database;
+- (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];
+}
+
- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
return 2;
}
- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
switch (group) {
- case 0:
- return @"Specifics";
- break;
-
- case 1:
- return @"Description";
- break;
+ case 0: return @"Specifics";
+ case 1: return @"Description";
default: _assert(false);
}
- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
switch (group) {
- case 0:
- return 5;
- break;
-
- case 1:
- return 1;
- break;
+ case 0: return 6;
+ case 1: return 1;
default: _assert(false);
}
[cell setValue:[package_ name]];
break;
- case 1:
+ case 1: {
cell = [cells_ objectAtIndex:1];
- [cell setTitle:@"Version"];
- [cell setValue:[package_ version]];
- break;
+ [cell setTitle:@"Installed"];
+ NSString *installed([package_ installed]);
+ [cell setValue:(installed == nil ? @"n/a" : installed)];
+ } break;
case 2:
cell = [cells_ objectAtIndex:2];
- [cell setTitle:@"Section"];
- [cell setValue:[package_ section]];
+ [cell setTitle:@"Latest"];
+ [cell setValue:[package_ latest]];
break;
- case 3: {
- double size = [package_ size];
- unsigned power = 0;
- while (size > 1024) {
- size /= 1024;
- ++power;
- }
-
+ case 3:
cell = [cells_ objectAtIndex:3];
- [cell setTitle:@"Size"];
- [cell setValue:[NSString stringWithFormat:@"%.1f%c", size, "bkMG"[power]]];
- } break;
+ [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];
case 1: switch (row) {
case 0:
- cell = [cells_ objectAtIndex:5];
- [cell setTitle:@"Tagline"];
+ cell = [cells_ objectAtIndex:6];
+ [cell setTitle:nil];
[cell setValue:[package_ tagline]];
break;
case 1:
- cell = [cells_ objectAtIndex:6];
+ cell = [cells_ objectAtIndex:7];
[cell setTitle:@"Description"];
[cell setValue:[package_ description]];
break;
return cell;
}
-- (PackageView *) initWithFrame:(struct CGRect)frame database:(Database *)database {
+- (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;
- [self setDataSource:self];
+ 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 != 6; ++i) {
- struct CGRect frame = [self frameOfPreferencesCellAtRow:0 inGroup:0];
- UIPreferencesTableCell *cell = [[UIPreferencesTableCell alloc] init];
+ for (unsigned i = 0; i != 8; ++i) {
+ UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
[cell setShowSelection:NO];
[cells_ addObject:cell];
}
}
- (void) setPackage:(Package *)package {
- package_ = package;
- [self reloadData];
+ package_ = [package retain];
+ [table_ reloadData];
+}
+
+- (void) setDelegate:(id)delegate {
+ delegate_ = delegate;
}
@end
/* }}} */
+/* Package Cell {{{ */
+@protocol PackageCellDelegate
+- (NSString *) versionWithPackage:(Package *)package;
+@end
-@implementation Database
+@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;
+
+- (BOOL) trusted;
+
+- (NSString *) uri;
+- (NSString *) distribution;
+- (NSString *) type;
+
+- (NSString *) description;
+- (NSString *) label;
+- (NSString *) origin;
+@end
+
+@implementation Source
+
+- (void) dealloc {
+ [uri_ release];
+ [distribution_ release];
+ [type_ release];
+
+ if (description_ != nil)
+ [description_ release];
+ if (label_ != nil)
+ [label_ release];
+ if (origin_ != nil)
+ [origin_ release];
+
+ [super dealloc];
+}
+
+- (Source *) initWithMetaIndex:(metaIndex *)index {
+ if ((self = [super init]) != nil) {
+ trusted_ = index->IsTrusted();
+
+ uri_ = [[NSString stringWithCString:index->GetURI().c_str()] retain];
+ distribution_ = [[NSString stringWithCString:index->GetDist().c_str()] retain];
+ type_ = [[NSString stringWithCString:index->GetType()] retain];
+
+ description_ = nil;
+ label_ = nil;
+ origin_ = nil;
+
+ 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) trusted {
+ return trusted_;
+}
+
+- (NSString *) uri {
+ return uri_;
+}
+
+- (NSString *) distribution {
+ return distribution_;
+}
+
+- (NSString *) type {
+ return type_;
+}
+
+- (NSString *) description {
+ return description_;
+}
+
+- (NSString *) label {
+ return label_;
+}
+
+- (NSString *) origin {
+ return origin_;
+}
+
+@end
+/* }}} */
+/* Source Cell {{{ */
+@interface SourceCell : UITableCell {
+ UITextLabel *description_;
+ UIRightTextLabel *label_;
+ UITextLabel *origin_;
+}
+
+- (void) dealloc;
+
+- (SourceCell *) initWithSource:(Source *)source;
+
+- (void) _setSelected:(float)fraction;
+- (void) setSelected:(BOOL)selected;
+- (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
+- (void) _setSelectionFadeFraction:(float)fraction;
+
+@end
+
+@implementation SourceCell
+
+- (void) dealloc {
+ [description_ release];
+ [label_ release];
+ [origin_ release];
+ [super dealloc];
+}
+
+- (SourceCell *) initWithSource:(Source *)source {
+ if ((self = [super init]) != nil) {
+ GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 20);
+ GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
+
+ CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+ float clear[] = {0, 0, 0, 0};
+
+ NSString *description = [source description];
+ if (description == nil)
+ description = [source uri];
+
+ description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 270, 25)];
+ [description_ setBackgroundColor:CGColorCreate(space, clear)];
+ [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:description_];
+ [self addSubview:label_];
+ [self addSubview:origin_];
+
+ CFRelease(small);
+ CFRelease(bold);
+ } return self;
+}
+
+- (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};
+
+ [description_ setColor:CGColorCreate(space, black)];
+ [label_ setColor:CGColorCreate(space, blue)];
+ [origin_ 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
+/* }}} */
+/* Sources View {{{ */
+@interface SourcesView : ResetView {
+ UISectionList *list_;
+ 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;
+- (void) reloadData;
+- (NSString *) leftTitle;
+- (NSString *) rightTitle;
+@end
+
+@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:
+ [delegate_ update];
+ break;
+ }
+}
+
+- (void) dealloc {
+ if (sources_ != nil)
+ [sources_ release];
+ [list_ release];
+ [super dealloc];
+}
+
+- (id) initWithFrame:(CGRect)frame database:(Database *)database {
+ if ((self = [super initWithFrame:frame]) != nil) {
+ database_ = database;
+ sources_ = nil;
+
+ CGSize navsize = [UINavigationBar defaultSize];
+ CGRect navrect = {{0, 0}, navsize};
+ CGRect bounds = [self bounds];
+
+ navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
+ [self addSubview:navbar_];
+
+ [navbar_ setBarStyle:1];
+ [navbar_ setDelegate:self];
+
+ UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Sources"] autorelease];
+ [navbar_ pushNavigationItem:navitem];
+
+ list_ = [[UISectionList alloc] initWithFrame:CGRectMake(
+ 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
+ )];
+
+ [self addSubview:list_];
+
+ [list_ setDataSource:self];
+ [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;
+}
+
+- (void) setDelegate:(id)delegate {
+ delegate_ = delegate;
+}
+
+- (void) reloadData {
+ pkgSourceList list;
+ _assert(list.ReadMainList());
+
+ if (sources_ != nil)
+ [sources_ release];
+
+ 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 {
+ return @"Refresh All";
+}
+
+- (NSString *) rightTitle {
+ return @"Edit";
+}
+
+@end
+/* }}} */
+
+@implementation Database
+
+- (void) _readStatus:(NSNumber *)fd {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
+ std::istream is(&ib);
+ std::string line;
+
+ const char *error;
+ int offset;
+ pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
+
+ pcre_extra *study = NULL;
+ int capture;
+ pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
+ int matches[(capture + 1) * 3];
+
+ while (std::getline(is, line)) {
+ const char *data(line.c_str());
+
+ _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
+
+ std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
+ float percent;
+ buffer >> percent;
+ [delegate_ setPercent:(percent / 100)];
+
+ NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
+ std::string type(line.substr(matches[2], matches[3] - matches[2]));
+
+ if (type == "pmerror")
+ [delegate_ setError:string];
+ else if (type == "pmstatus")
+ [delegate_ setTitle:string];
+ else if (type == "pmconffile")
+ ;
+ else _assert(false);
+ }
+
+ [pool release];
+}
+
+- (void) _readOutput:(NSNumber *)fd {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
+ std::istream is(&ib);
+ std::string line;
+
+ while (std::getline(is, line))
+ [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
+
+ [pool release];
+}
+
+- (Package *) packageWithName:(NSString *)name {
+ pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
+ return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
+}
+
+- (Database *) init {
+ if ((self = [super init]) != nil) {
+ records_ = NULL;
+ resolver_ = NULL;
+ fetcher_ = NULL;
+ lock_ = NULL;
+
+ int fds[2];
+
+ _assert(pipe(fds) != -1);
+ statusfd_ = fds[1];
+
+ [NSThread
+ detachNewThreadSelector:@selector(_readStatus:)
+ toTarget:self
+ withObject:[[NSNumber numberWithInt:fds[0]] retain]
+ ];
+
+ _assert(pipe(fds) != -1);
+ _assert(dup2(fds[1], 1) != -1);
+ _assert(close(fds[1]) != -1);
-- (Database *) init {
- if ((self = [super init]) != nil) {
- records_ = NULL;
- resolver_ = NULL;
+ [NSThread
+ detachNewThreadSelector:@selector(_readOutput:)
+ toTarget:self
+ withObject:[[NSNumber numberWithInt:fds[0]] retain]
+ ];
} return self;
}
return resolver_;
}
+- (pkgAcquire &) fetcher {
+ return *fetcher_;
+}
+
- (void) reloadData {
+ _error->Discard();
+ manager_ = NULL;
+ delete lock_;
+ delete fetcher_;
delete resolver_;
delete records_;
cache_.Close();
cache_.Open(progress_, true);
records_ = new pkgRecords(cache_);
resolver_ = new pkgProblemResolver(cache_);
+ fetcher_ = new pkgAcquire(&status_);
+ lock_ = NULL;
}
-- (void) update {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+- (void) prepare {
+ pkgRecords records(cache_);
+
+ lock_ = new FileFd();
+ lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
+ _assert(!_error->PendingError());
+
+ pkgSourceList list;
+ _assert(list.ReadMainList());
+
+ manager_ = (_system->CreatePM(cache_));
+ _assert(manager_->GetArchives(fetcher_, &list, &records));
+ _assert(!_error->PendingError());
+}
+
+- (void) perform {
+ if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
+ return;
+
+ _system->UnLock();
+ pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
+
+ if (result == pkgPackageManager::Failed)
+ return;
+ if (_error->PendingError())
+ return;
+ if (result != pkgPackageManager::Completed)
+ return;
+}
+- (void) update {
pkgSourceList list;
_assert(list.ReadMainList());
pkgAcquire fetcher(&status_);
_assert(list.GetIndexes(&fetcher));
- _assert(fetcher.Run() != pkgAcquire::Failed);
+ _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
bool failed = false;
for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
_assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
_assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
}
-
- [pool release];
}
- (void) upgrade {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
_assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
_assert(pkgApplyStatus(cache_));
}
_assert(pkgDistUpgrade(cache_));
-
- //InstallPackages(cache_, true);
-
- [pool release];
}
- (void) setDelegate:(id)delegate {
+ delegate_ = delegate;
status_.setDelegate(delegate);
progress_.setDelegate(delegate);
}
@end
/* }}} */
-
-@interface ProgressView : UIView {
+/* Progress View {{{ */
+@interface ProgressView : UIView <
+ ProgressDelegate
+> {
UIView *view_;
+ UIView *background_;
UITransitionView *transition_;
- UIView *progress_;
+ UIView *overlay_;
UINavigationBar *navbar_;
+ UIProgressBar *progress_;
+ UITextView *output_;
+ UITextLabel *status_;
+ id delegate_;
}
-- (ProgressView *) initWithFrame:(struct CGRect)frame;
+- (void) dealloc;
+
+- (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
- (void) setContentView:(UIView *)view;
- (void) resetView;
+- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
+
+- (void) _retachThread;
- (void) _detachNewThreadData:(ProgressData *)data;
- (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
-- (void) setStatusIMSHit;
-- (void) setStatusFetch;
-- (void) setStatusDone;
-- (void) setStatusFail;
-- (void) setStatusPulse;
+- (void) setError:(NSString *)error;
+- (void) _setError:(NSString *)error;
+
+- (void) setTitle:(NSString *)title;
+- (void) _setTitle:(NSString *)title;
+
+- (void) setPercent:(float)percent;
+- (void) _setPercent:(NSNumber *)percent;
-- (void) setStatusStart;
-- (void) setStatusStop;
+- (void) addOutput:(NSString *)output;
+- (void) _addOutput:(NSString *)output;
+@end
+
+@protocol ProgressViewDelegate
+- (void) progressViewIsComplete:(ProgressView *)sender;
@end
@implementation ProgressView
-- (ProgressView *) initWithFrame:(struct CGRect)frame {
- if ((self = [super initWithFrame:frame]) != nil) {
- transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
- [self addSubview:transition_];
+- (void) dealloc {
+ [view_ release];
+ [background_ release];
+ [transition_ release];
+ [overlay_ release];
+ [navbar_ release];
+ [progress_ release];
+ [output_ release];
+ [status_ release];
+ [super dealloc];
+}
- progress_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
+- (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
+ if ((self = [super initWithFrame:frame]) != nil) {
+ delegate_ = delegate;
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
float black[] = {0.0, 0.0, 0.0, 1.0};
- [progress_ setBackgroundColor:CGColorCreate(space, black)];
+ float white[] = {1.0, 1.0, 1.0, 1.0};
+ float clear[] = {0.0, 0.0, 0.0, 0.0};
+
+ background_ = [[UIView alloc] initWithFrame:[self bounds]];
+ [background_ setBackgroundColor:CGColorCreate(space, black)];
+ [self addSubview:background_];
+
+ transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
+ [self addSubview:transition_];
+
+ overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
CGSize navsize = [UINavigationBar defaultSize];
CGRect navrect = {{0, 0}, navsize};
navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
- [progress_ addSubview:navbar_];
+ [overlay_ addSubview:navbar_];
[navbar_ setBarStyle:1];
[navbar_ setDelegate:self];
- UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:nil];
+ UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Running..."] autorelease];
[navbar_ pushNavigationItem:navitem];
+
+ CGRect bounds = [overlay_ bounds];
+ CGSize prgsize = [UIProgressBar defaultSize];
+
+ CGRect prgrect = {{
+ (bounds.size.width - prgsize.width) / 2,
+ bounds.size.height - prgsize.height - 20
+ }, prgsize};
+
+ progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
+ [overlay_ addSubview:progress_];
+
+ status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
+ 10,
+ bounds.size.height - prgsize.height - 50,
+ bounds.size.width - 20,
+ 24
+ )];
+
+ [status_ setColor:CGColorCreate(space, white)];
+ [status_ setBackgroundColor:CGColorCreate(space, clear)];
+
+ [status_ setCentersHorizontally:YES];
+ //[status_ setFont:font];
+
+ output_ = [[UITextView alloc] initWithFrame:CGRectMake(
+ 10,
+ navrect.size.height + 20,
+ bounds.size.width - 20,
+ bounds.size.height - navsize.height - 62 - navrect.size.height
+ )];
+
+ //[output_ setTextFont:@"Courier New"];
+ [output_ setTextSize:12];
+
+ [output_ setTextColor:CGColorCreate(space, white)];
+ [output_ setBackgroundColor:CGColorCreate(space, clear)];
+
+ [output_ setMarginTop:0];
+ [output_ setAllowsRubberBanding:YES];
+
+ [overlay_ addSubview:output_];
+ [overlay_ addSubview:status_];
+
+ [progress_ setStyle:0];
} return self;
}
[transition_ transition:6 toView:view_];
}
+- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
+ [sheet dismiss];
+}
+
+- (void) _retachThread {
+ [delegate_ progressViewIsComplete:self];
+ [self resetView];
+}
+
- (void) _detachNewThreadData:(ProgressData *)data {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[[data target] performSelector:[data selector] withObject:[data object]];
- [self performSelectorOnMainThread:@selector(resetView) withObject:nil waitUntilDone:YES];
+ [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
+ [data release];
[pool release];
}
- (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
- [transition_ transition:6 toView:progress_];
+ [status_ setText:nil];
+ [output_ setText:@""];
+ [progress_ setProgress:0];
+
+ [transition_ transition:6 toView:overlay_];
[NSThread
detachNewThreadSelector:@selector(_detachNewThreadData:)
];
}
-- (void) setStatusIMSHit {
- _trace();
+- (void) setError:(NSString *)error {
+ [self
+ performSelectorOnMainThread:@selector(_setError:)
+ withObject:error
+ waitUntilDone:YES
+ ];
}
-- (void) setStatusFetch {
- _trace();
-}
+- (void) _setError:(NSString *)error {
+ UIAlertSheet *sheet = [[[UIAlertSheet alloc]
+ initWithTitle:@"Package Error"
+ buttons:[NSArray arrayWithObjects:@"Okay", nil]
+ defaultButtonIndex:0
+ delegate:self
+ context:self
+ ] autorelease];
-- (void) setStatusDone {
- _trace();
+ [sheet setBodyText:error];
+ [sheet popupAlertAnimated:YES];
}
-- (void) setStatusFail {
- _trace();
+- (void) setTitle:(NSString *)title {
+ [self
+ performSelectorOnMainThread:@selector(_setTitle:)
+ withObject:title
+ waitUntilDone:YES
+ ];
}
-- (void) setStatusPulse {
- _trace();
+- (void) _setTitle:(NSString *)title {
+ [status_ setText:[title stringByAppendingString:@"..."]];
}
-- (void) setStatusStart {
- _trace();
+- (void) setPercent:(float)percent {
+ [self
+ performSelectorOnMainThread:@selector(_setPercent:)
+ withObject:[NSNumber numberWithFloat:percent]
+ waitUntilDone:YES
+ ];
}
-- (void) setStatusStop {
- _trace();
+- (void) _setPercent:(NSNumber *)percent {
+ [progress_ setProgress:[percent floatValue]];
}
-@end
+- (void) addOutput:(NSString *)output {
+ [self
+ performSelectorOnMainThread:@selector(_addOutput:)
+ withObject:output
+ waitUntilDone:YES
+ ];
+}
-@protocol PackagesDelegate
+- (void) _addOutput:(NSString *)output {
+ [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
+ CGSize size = [output_ contentSize];
+ CGRect rect = {{0, size.height}, {size.width, 0}};
+ [output_ scrollRectToVisible:rect animated:YES];
+}
-- (void) viewPackage:(Package *)package;
+@end
+/* }}} */
+@protocol PackagesViewDelegate
+- (void) perform;
+- (void) update;
+- (void) openURL:(NSString *)url;
@end
-@interface Packages : UIView {
- NSString *title_;
+/* PackagesView {{{ */
+@interface PackagesView : ResetView <
+ PackageCellDelegate
+> {
Database *database_;
- bool (*filter_)(Package *package);
NSMutableArray *packages_;
NSMutableArray *sections_;
id delegate_;
UISectionList *list_;
- UINavigationBar *navbar_;
UITransitionView *transition_;
Package *package_;
+ NSString *pkgname_;
PackageView *pkgview_;
- SEL selector_;
}
- (int) numberOfSectionsInSectionList:(UISectionList *)list;
- (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;
- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
-- (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector;
+- (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
- (void) setDelegate:(id)delegate;
-- (void) addPackage:(Package *)package;
+- (void) deselect;
+- (void) reloadData:(BOOL)reset;
+
- (NSMutableArray *) packages;
-- (void) reloadData;
+- (NSString *) title;
+- (void) perform:(Package *)package;
+- (void) addPackage:(Package *)package;
+- (NSString *) versionWithPackage:(Package *)package;
@end
-@implementation Packages
+@implementation PackagesView
- (int) numberOfSectionsInSectionList:(UISectionList *)list {
return [sections_ count];
return 64;
}
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
- Package *package = [packages_ objectAtIndex:row]; {
- UITableCell *cell = [package cell];
- if (cell != nil)
- return cell;
- }
-
-#if 0
- UIImageAndTextTableCell *cell_ = [[UIImageAndTextTableCell alloc] init];
- [package setCell:cell_];
-
- [cell_ setTitle:[package name]];
- return cell_;
-#endif
-
- UITableCell *cell = [[UITableCell alloc] init];
- [package setCell:cell];
-
- GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
- GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
- GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
-
- CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
- float blue[] = {0.2, 0.2, 1.0, 1.0};
- float gray[] = {0.4, 0.4, 0.4, 1.0};
- float clear[] = {0, 0, 0, 0};
-
- UITextLabel *name = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
- [name setText:[package name]];
- [name setBackgroundColor:CGColorCreate(space, clear)];
- [name setFont:bold];
-
- UIRightTextLabel *version = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
- [version setText:[package version]];
- [version setColor:CGColorCreate(space, blue)];
- [version setBackgroundColor:CGColorCreate(space, clear)];
- [version setFont:large];
-
- UITextLabel *description = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
- [description setText:[package tagline]];
- [description setColor:CGColorCreate(space, gray)];
- [description setBackgroundColor:CGColorCreate(space, clear)];
- [description setFont:small];
-
- [cell addSubview:name];
- [cell addSubview:version];
- [cell addSubview:description];
-
- CFRelease(small);
- CFRelease(large);
- CFRelease(bold);
-
- 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 {
return;
package_ = [packages_ objectAtIndex:row];
+ pkgname_ = [[package_ name] retain];
UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
[navbar_ pushNavigationItem:navitem];
- [navbar_ showButtonsWithLeftTitle:nil rightTitle:title_];
+ [navbar_ showButtonsWithLeftTitle:nil rightTitle:[self title]];
[pkgview_ setPackage:package_];
[transition_ transition:1 toView:pkgview_];
-
}
- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
if (button == 0) {
- printf("bef:%ld\n", [database_ cache]->InstCount());
- [package_ performSelector:selector_];
+ [self perform:package_];
pkgProblemResolver *resolver = [database_ resolver];
if (!resolver->Resolve(true))
_error->Discard();
- printf("aft:%ld\n", [database_ cache]->InstCount());
- _assert(false);
+ [delegate_ perform];
}
}
- (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
- [transition_ transition:2 toView:list_];
- [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
- UITable *table = [list_ table];
- [table selectRow:-1 byExtendingSelection:NO withFade:YES];
- //UITableCell *cell = [table cellAtRow:[table selectedRow] column:0];
- //[table selectCell:nil inRow:-1 column:-1 withFade:YES];
- //[table highlightRow:-1];
- //[cell setSelected:NO withFade:YES];
- package_ = nil;
+ [self deselect];
+ [super navigationBar:navbar poppedItem:item];
}
-- (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector {
+- (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
if ((self = [super initWithFrame:frame]) != nil) {
- title_ = title;
- database_ = database;
- filter_ = filter;
- selector_ = selector;
-
- packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
+ database_ = [database retain];
struct CGRect bounds = [self bounds];
CGSize navsize = [UINavigationBar defaultSize];
[navbar_ setBarStyle:1];
[navbar_ setDelegate:self];
- UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:title];
+ UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:[self title]] autorelease];
[navbar_ pushNavigationItem:navitem];
[navitem setBackButtonTitle:@"Packages"];
list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
[list_ setDataSource:self];
+ [list_ setShouldHideHeaderInShortLists:NO];
[transition_ transition:0 toView:list_];
[table setSeparatorStyle:1];
[table addTableColumn:column];
[table setDelegate:self];
+ [table setReusesTableCells:YES];
pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
} return self;
- (void) setDelegate:(id)delegate {
delegate_ = delegate;
+ [pkgview_ setDelegate:delegate];
}
-- (void) addPackage:(Package *)package {
- _assert(sections_ == nil);
- [packages_ addObject:package];
+- (void) deselect {
+ [transition_ transition:(resetting_ ? 0 : 2) toView:list_];
+ UITable *table = [list_ table];
+ [table selectRow:-1 byExtendingSelection:NO withFade:(resetting_ ? NO : YES)];
+ package_ = nil;
}
-- (NSMutableArray *) packages {
- return packages_;
-}
+- (void) reloadData:(BOOL)reset {
+ if (sections_ != nil)
+ [sections_ release];
+ if (packages_ != nil)
+ [packages_ release];
-- (void) reloadData {
- for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator) {
- Package *package = [Package packageWithIterator:iterator database:database_];
- if (package == nil)
- continue;
- if (filter_(package))
+ packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
+
+ for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
+ if (Package *package = [Package packageWithIterator:iterator database:database_])
[self addPackage:package];
- }
[packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
}
[list_ reloadData];
+ if (reset)
+ [self resetView];
+ else if (package_ != nil) {
+ package_ = [database_ packageWithName:pkgname_];
+ [pkgview_ setPackage:package_];
+ }
+}
+
+- (NSMutableArray *) packages {
+ return packages_;
+}
+
+- (NSString *) title {
+ return nil;
+}
+
+- (void) perform:(Package *)package {
+}
+
+- (void) addPackage:(Package *)package {
+ [packages_ addObject:package];
+}
+
+- (NSString *) versionWithPackage:(Package *)package {
+ return nil;
}
@end
+/* }}} */
-bool IsInstalled(Package *package) {
- return [package installed];
+/* InstallView {{{ */
+@interface InstallView : PackagesView {
+}
+
+- (NSString *) title;
+- (void) addPackage:(Package *)package;
+- (void) perform:(Package *)package;
+- (NSString *) versionWithPackage:(Package *)package;
+@end
+
+@implementation InstallView
+
+- (NSString *) title {
+ return @"Install";
+}
+
+- (void) addPackage:(Package *)package {
+ if ([package installed] == nil)
+ [super addPackage:package];
+}
+
+- (void) perform:(Package *)package {
+ [package install];
+}
+
+- (NSString *) versionWithPackage:(Package *)package {
+ return [package latest];
+}
+
+@end
+/* }}} */
+/* UpgradeView {{{ */
+@interface UpgradeView : PackagesView {
+}
+
+- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
+
+- (NSString *) title;
+- (NSString *) leftTitle;
+- (void) addPackage:(Package *)package;
+- (void) perform:(Package *)package;
+- (NSString *) versionWithPackage:(Package *)package;
+@end
+
+@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 [packages_ count] == 0 ? nil : @"Upgrade All";
+}
+
+- (void) addPackage:(Package *)package {
+ NSString *installed = [package installed];
+ if (installed != nil && [[package latest] compare:installed] != NSOrderedSame)
+ [super addPackage:package];
+}
+
+- (void) perform:(Package *)package {
+ [package install];
+}
+
+- (NSString *) versionWithPackage:(Package *)package {
+ return [package latest];
+}
+
+@end
+/* }}} */
+/* UninstallView {{{ */
+@interface UninstallView : PackagesView {
+}
+
+- (NSString *) title;
+- (void) addPackage:(Package *)package;
+- (void) perform:(Package *)package;
+- (NSString *) versionWithPackage:(Package *)package;
+@end
+
+@implementation UninstallView
+
+- (NSString *) title {
+ return @"Uninstall";
+}
+
+- (void) addPackage:(Package *)package {
+ if ([package installed] != nil)
+ [super addPackage:package];
+}
+
+- (void) perform:(Package *)package {
+ [package remove];
}
-bool IsNotInstalled(Package *package) {
- return ![package installed];
+- (NSString *) versionWithPackage:(Package *)package {
+ return [package installed];
}
-@interface Cydia : UIApplication <PackagesDelegate> {
+@end
+/* }}} */
+
+@interface Cydia : UIApplication <
+ ConfirmationViewDelegate,
+ PackagesViewDelegate,
+ ProgressViewDelegate
+> {
UIWindow *window_;
+ UIView *underlay_;
+ UIView *overlay_;
UITransitionView *transition_;
+ UIButtonBar *buttonbar_;
+
+ ConfirmationView *confirm_;
Database *database_;
ProgressView *progress_;
UIScroller *scroller_;
UIWebView *webview_;
NSURL *url_;
+ UIProgressIndicator *indicator_;
- Packages *install_;
- Packages *uninstall_;
+ InstallView *install_;
+ UpgradeView *upgrade_;
+ UninstallView *uninstall_;
+ SourcesView *sources_;
}
- (void) loadNews;
-- (void) reloadData;
+- (void) reloadData:(BOOL)reset;
+- (void) perform;
+- (void) cancel;
+- (void) confirm;
+- (void) update;
+
+- (void) progressViewIsComplete:(ProgressView *)progress;
- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
+- (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) viewPackage:(Package *)package;
+- (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
- (void) applicationDidFinishLaunching:(id)unused;
@end
+#include <objc/objc-class.h>
+
@implementation Cydia
- (void) loadNews {
- [webview_ loadRequest:[NSURLRequest
+ NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:url_
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30.0
- ]];
+ ];
+
+ [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
+ [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
+
+ [webview_ loadRequest:request];
+ [indicator_ startAnimation];
}
-- (void) reloadData {
+- (void) reloadData:(BOOL)reset {
[database_ reloadData];
- [install_ reloadData];
- [uninstall_ reloadData];
+ [install_ reloadData:reset];
+ [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 {
+ [database_ prepare];
+ confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
+}
+
+- (void) cancel {
+ [self reloadData:NO];
+ [confirm_ release];
+ confirm_ = nil;
+}
+
+- (void) confirm {
+ [overlay_ removeFromSuperview];
+
+ [progress_
+ detachNewThreadSelector:@selector(perform)
+ toTarget:database_
+ withObject:nil
+ ];
+}
+
+- (void) update {
+ [progress_
+ detachNewThreadSelector:@selector(update)
+ toTarget:database_
+ withObject:nil
+ ];
+}
+
+- (void) progressViewIsComplete:(ProgressView *)progress {
+ [self reloadData:YES];
+
+ if (confirm_ != nil) {
+ [underlay_ addSubview:overlay_];
+ [confirm_ removeFromSuperview];
+ [confirm_ release];
+ confirm_ = nil;
+ }
}
- (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
break;
case 1:
+ UIAlertSheet *sheet = [[[UIAlertSheet alloc]
+ initWithTitle:@"About Cydia Packager"
+ buttons:[NSArray arrayWithObjects:@"Close", nil]
+ defaultButtonIndex:0
+ delegate:self
+ context:self
+ ] autorelease];
+
+ [sheet setBodyText:
+ @"Copyright (C) 2007\n"
+ "Jay Freeman (saurik)\n"
+ "saurik@saurik.com\n"
+ "http://www.saurik.com/\n"
+ "\n"
+ "The Okori Group\n"
+ "http://www.theokorigroup.com/\n"
+ "\n"
+ "College of Creative Studies,\n"
+ "University of California,\n"
+ "Santa Barbara\n"
+ "http://www.ccs.ucsb.edu/\n"
+ "\n"
+ "Special Thanks:\n"
+ "bad_, BHSPitMonkey, Cobra, core,\n"
+ "Corona, cromas, Darken, dtzWill,\n"
+ "francis, Godores, jerry, Kingstone,\n"
+ "lounger, rockabilly, tman, Wbiggs"
+ ];
+
+ [sheet presentSheetFromButtonBar:buttonbar_];
break;
}
}
+- (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
+ [sheet dismiss];
+}
+
- (void) buttonBarItemTapped:(id)sender {
UIView *view;
switch ([sender tag]) {
case 1: view = featured_; break;
case 2: view = install_; break;
+ case 3: view = upgrade_; break;
case 4: view = uninstall_; break;
+ case 5: view = sources_; break;
default:
_assert(false);
}
+ if ([view respondsToSelector:@selector(resetView)])
+ [(id) view resetView];
[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];
-}
-
-- (void) viewPackage:(Package *)package {
- _assert(false);
+ [indicator_ stopAnimation];
}
- (void) applicationDidFinishLaunching:(id)unused {
_assert(pkgInitConfig(*_config));
_assert(pkgInitSystem(*_config, _system));
+ confirm_ = nil;
+
CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
window_ = [[UIWindow alloc] initWithContentRect:screenrect];
[window_ makeKey: self];
[window_ _setHidden: NO];
- progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds]];
- [database_ setDelegate:progress_];
+ progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
[window_ setContentView:progress_];
- UIView *view = [[UIView alloc] initWithFrame:[progress_ bounds]];
- [progress_ setContentView:view];
+ underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
+ [progress_ setContentView:underlay_];
+
+ overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
+ [underlay_ addSubview:overlay_];
transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
0, 0, screenrect.size.width, screenrect.size.height - 48
)];
- [view addSubview:transition_];
+ [overlay_ addSubview:transition_];
featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
[webview_ setAutoresizes:YES];
[webview_ setDelegate:self];
- url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
- [self loadNews];
+ 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:
nil],
nil];
- UIButtonBar *buttonbar = [[UIButtonBar alloc]
- initInView:view
+ buttonbar_ = [[UIButtonBar alloc]
+ initInView:overlay_
withFrame:CGRectMake(
0, screenrect.size.height - 48,
screenrect.size.width, 48
withItemList:buttonitems
];
- [buttonbar setDelegate:self];
- [buttonbar setBarStyle:1];
- [buttonbar setButtonBarTrackingMode:2];
+ [buttonbar_ setDelegate:self];
+ [buttonbar_ setBarStyle:1];
+ [buttonbar_ setButtonBarTrackingMode:2];
int buttons[5] = {1, 2, 3, 4, 5};
- [buttonbar registerButtonGroup:0 withButtons:buttons withCount:5];
- [buttonbar showButtonGroup:0 withDuration:0];
+ [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
+ [buttonbar_ showButtonGroup:0 withDuration:0];
for (int i = 0; i != 5; ++i)
- [[buttonbar viewWithTag:(i + 1)] setFrame:CGRectMake(
+ [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
i * 64 + 2, 1, 60, 48
)];
- [buttonbar showSelectionForButton:1];
+ [buttonbar_ showSelectionForButton:1];
[transition_ transition:0 toView:featured_];
- [view addSubview:buttonbar];
+ [overlay_ addSubview:buttonbar_];
database_ = [[Database alloc] init];
+ [database_ setDelegate:progress_];
- install_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Install" database:database_ filter:&IsNotInstalled selector:@selector(install)];
+ install_ = [[InstallView alloc] initWithFrame:[transition_ bounds] database:database_];
[install_ setDelegate:self];
- uninstall_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Uninstall" database:database_ filter:&IsInstalled selector:@selector(remove)];
+ upgrade_ = [[UpgradeView alloc] initWithFrame:[transition_ bounds] database:database_];
+ [upgrade_ setDelegate:self];
+
+ uninstall_ = [[UninstallView alloc] initWithFrame:[transition_ bounds] database:database_];
[uninstall_ setDelegate:self];
-#if 0
- UIAlertSheet *alert = [[UIAlertSheet alloc]
- initWithTitle:@"Alert Title"
- buttons:[NSArray arrayWithObjects:@"Yes", nil]
- defaultButtonIndex:0
- delegate:self
- context:self
- ];
+ sources_ = [[SourcesView alloc] initWithFrame:[transition_ bounds] database:database_];
+ [sources_ setDelegate:self];
- NSLog(@"%p\n", [alert table]);
- [[alert table] setDelegate:self];
- [[alert table] reloadData];
+ [self reloadData:NO];
+ [progress_ resetView];
- [alert addTextFieldWithValue:@"Title" label:@"Label"];
- [alert setShowsOverSpringBoardAlerts:YES];
- [alert setBodyText:@"This is an alert."];
- [alert presentSheetFromButtonBar:buttonbar];
- //[alert popupAlertAnimated:YES];
-#endif
+ Package *package([database_ packageWithName:@"cydia"]);
+ NSString *application = package == nil ? @"Cydia" : [NSString stringWithFormat:@"Cydia/%@", [package installed]];
+ WebView *webview = [webview_ webView];
+ [webview setApplicationNameForUserAgent:application];
- [self reloadData];
- [progress_ resetView];
- //[progress_ detachNewThreadSelector:@selector(reloadData) toTarget:self withObject:nil];
+ url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
+ [self loadNews];
}
@end
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ size_t size;
+ sysctlbyname("hw.machine", NULL, &size, NULL, 0);
+ char *machine = new char[size];
+ sysctlbyname("hw.machine", machine, &size, NULL, 0);
+ Machine_ = machine;
+
+ if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
+ if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
+ if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
+ SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
+ CFRelease(serial);
+ }
+
+ IOObjectRelease(service);
+ }
+
UIApplicationMain(argc, argv, [Cydia class]);
[pool release];
}