1 /* #include Directives {{{ */
2 #include <Foundation/NSURL.h>
3 #include <UIKit/UIKit.h>
4 #import <GraphicsServices/GraphicsServices.h>
7 #include <ext/stdio_filebuf.h>
9 #include <apt-pkg/acquire.h>
10 #include <apt-pkg/acquire-item.h>
11 #include <apt-pkg/algorithms.h>
12 #include <apt-pkg/cachefile.h>
13 #include <apt-pkg/configuration.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/init.h>
16 #include <apt-pkg/pkgrecords.h>
17 #include <apt-pkg/sourcelist.h>
18 #include <apt-pkg/sptr.h>
24 /* Extension Keywords {{{ */
25 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
27 #define _assert(test) do \
29 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
35 @interface NSString (CydiaBypass)
36 - (NSString *) stringByAddingPercentEscapes;
39 @protocol ProgressDelegate
40 - (void) setError:(NSString *)error;
41 - (void) setTitle:(NSString *)title;
42 - (void) setPercent:(float)percent;
43 - (void) addOutput:(NSString *)output;
46 /* Status Delegation {{{ */
48 public pkgAcquireStatus
59 void setDelegate(id delegate) {
63 virtual bool MediaChange(std::string media, std::string drive) {
67 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
70 virtual void Fetch(pkgAcquire::ItemDesc &item) {
71 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
74 virtual void Done(pkgAcquire::ItemDesc &item) {
77 virtual void Fail(pkgAcquire::ItemDesc &item) {
78 [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
81 virtual bool Pulse(pkgAcquire *Owner) {
82 bool value = pkgAcquireStatus::Pulse(Owner);
85 double(CurrentBytes + CurrentItems) /
86 double(TotalBytes + TotalItems)
89 [delegate_ setPercent:percent];
93 virtual void Start() {
100 /* Progress Delegation {{{ */
108 virtual void Update() {
109 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
110 [delegate_ setPercent:(Percent / 100)];
119 void setDelegate(id delegate) {
120 delegate_ = delegate;
123 virtual void Done() {
124 [delegate_ setPercent:1];
129 /* External Constants {{{ */
130 extern NSString *kUIButtonBarButtonAction;
131 extern NSString *kUIButtonBarButtonInfo;
132 extern NSString *kUIButtonBarButtonInfoOffset;
133 extern NSString *kUIButtonBarButtonSelectedInfo;
134 extern NSString *kUIButtonBarButtonStyle;
135 extern NSString *kUIButtonBarButtonTag;
136 extern NSString *kUIButtonBarButtonTarget;
137 extern NSString *kUIButtonBarButtonTitle;
138 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
139 extern NSString *kUIButtonBarButtonTitleWidth;
140 extern NSString *kUIButtonBarButtonType;
142 /* Mime Addresses {{{ */
143 @interface Address : NSObject {
151 - (NSString *) email;
153 + (Address *) addressWithString:(NSString *)string;
154 - (Address *) initWithString:(NSString *)string;
157 @implementation Address
165 - (NSString *) name {
169 - (NSString *) email {
173 + (Address *) addressWithString:(NSString *)string {
174 return [[[Address alloc] initWithString:string] autorelease];
177 - (Address *) initWithString:(NSString *)string {
178 if ((self = [super init]) != nil) {
181 pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
184 fprintf(stderr, "%d:%s\n", offset, error);
188 pcre_extra *study = NULL;
190 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
191 int matches[(capture + 1) * 3];
193 size_t size = [string length];
194 const char *data = [string UTF8String];
196 _assert(pcre_exec(code, study, data, size, 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
198 name_ = [[NSString stringWithCString:(data + matches[2]) length:(matches[3] - matches[2])] retain];
199 email_ = [[NSString stringWithCString:(data + matches[4]) length:(matches[5] - matches[4])] retain];
206 /* Right Alignment {{{ */
207 @interface UIRightTextLabel : UITextLabel {
208 float _savedRightEdgeX;
209 BOOL _sizedtofit_flag;
212 - (void) setFrame:(CGRect)frame;
213 - (void) setText:(NSString *)text;
214 - (void) realignText;
217 @implementation UIRightTextLabel
219 - (void) setFrame:(CGRect)frame {
220 [super setFrame:frame];
221 if (_sizedtofit_flag == NO) {
222 _savedRightEdgeX = frame.origin.x;
227 - (void) setText:(NSString *)text {
228 [super setText:text];
232 - (void) realignText {
233 CGRect oldFrame = [self frame];
235 _sizedtofit_flag = YES;
236 [self sizeToFit]; // shrink down size so I can right align it
238 CGRect newFrame = [self frame];
240 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
241 oldFrame.size.width = newFrame.size.width;
242 [super setFrame:oldFrame];
243 _sizedtofit_flag = NO;
248 /* Linear Algebra {{{ */
249 inline float interpolate(float begin, float end, float fraction) {
250 return (end - begin) * fraction + begin;
255 @interface ResetView : UIView {
256 UINavigationBar *navbar_;
264 @implementation ResetView
273 while ([[navbar_ navigationItems] count] != 1)
274 [navbar_ popNavigationItem];
281 @interface Database : NSObject {
283 pkgRecords *records_;
284 pkgProblemResolver *resolver_;
293 - (pkgCacheFile &) cache;
294 - (pkgRecords *) records;
295 - (pkgProblemResolver *) resolver;
302 - (void) setDelegate:(id)delegate;
305 /* Package Class {{{ */
306 @interface Package : NSObject {
307 pkgCache::PkgIterator iterator_;
309 pkgRecords::Parser *parser_;
310 pkgCache::VerIterator version_;
311 pkgCache::VerFileIterator file_;
314 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
315 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
318 - (NSString *) section;
320 - (NSString *) version;
321 - (Address *) maintainer;
323 - (NSString *) tagline;
324 - (NSString *) description;
325 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
331 @implementation Package
333 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
334 if ((self = [super init]) != nil) {
335 iterator_ = iterator;
336 database_ = database;
340 parser_ = &[database_ records]->Lookup(file);
344 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
345 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
346 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
347 return [[[Package alloc]
348 initWithIterator:iterator
356 - (NSString *) name {
357 return [NSString stringWithCString:iterator_.Name()];
360 - (NSString *) section {
361 return [NSString stringWithCString:iterator_.Section()];
365 return iterator_->CurrentState != pkgCache::State::NotInstalled;
368 - (NSString *) version {
369 return [NSString stringWithCString:version_.VerStr()];
372 - (Address *) maintainer {
373 return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
377 return version_->InstalledSize;
380 - (NSString *) tagline {
381 return [NSString stringWithCString:parser_->ShortDesc().c_str()];
384 - (NSString *) description {
385 return [NSString stringWithCString:parser_->LongDesc().c_str()];
388 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
389 NSComparisonResult result = [[self section] compare:[package section]];
390 if (result != NSOrderedSame)
392 return [[self name] compare:[package name]];
396 pkgProblemResolver *resolver = [database_ resolver];
397 resolver->Clear(iterator_);
398 resolver->Protect(iterator_);
399 [database_ cache]->MarkInstall(iterator_, false);
403 pkgProblemResolver *resolver = [database_ resolver];
404 resolver->Clear(iterator_);
405 resolver->Protect(iterator_);
406 resolver->Remove(iterator_);
407 [database_ cache]->MarkDelete(iterator_, true);
412 /* Section Class {{{ */
413 @interface Section : NSObject {
416 NSMutableArray *packages_;
421 - (Section *) initWithName:(NSString *)name row:(size_t)row;
424 - (void) addPackage:(Package *)package;
427 @implementation Section
435 - (Section *) initWithName:(NSString *)name row:(size_t)row {
436 if ((self = [super init]) != nil) {
437 name_ = [name retain];
439 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
443 - (NSString *) name {
451 - (void) addPackage:(Package *)package {
452 [packages_ addObject:package];
458 /* Confirmation View {{{ */
459 @interface ConfirmationView : UIView {
464 @implementation ConfirmationView
467 /* Package View {{{ */
468 @interface PackageView : UIView {
469 UIPreferencesTable *table_;
472 NSMutableArray *cells_;
478 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
479 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
480 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
482 - (BOOL) canSelectRow:(int)row;
483 - (void) tableRowSelected:(NSNotification *)notification;
485 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
486 - (void) setPackage:(Package *)package;
487 - (void) setDelegate:(id)delegate;
490 @implementation PackageView
501 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
505 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
512 return @"Description";
515 default: _assert(false);
519 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
529 default: _assert(false);
533 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
534 UIPreferencesTableCell *cell;
537 case 0: switch (row) {
539 cell = [cells_ objectAtIndex:0];
540 [cell setTitle:@"Name"];
541 [cell setValue:[package_ name]];
545 cell = [cells_ objectAtIndex:1];
546 [cell setTitle:@"Version"];
547 [cell setValue:[package_ version]];
551 cell = [cells_ objectAtIndex:2];
552 [cell setTitle:@"Section"];
553 [cell setValue:[package_ section]];
557 double size = [package_ size];
559 while (size > 1024) {
564 cell = [cells_ objectAtIndex:3];
565 [cell setTitle:@"Size"];
566 [cell setValue:[NSString stringWithFormat:@"%.1f%c", size, "bkMG"[power]]];
570 cell = [cells_ objectAtIndex:4];
571 [cell setTitle:@"Maintainer"];
572 [cell setValue:[[package_ maintainer] name]];
573 [cell setShowDisclosure:YES];
574 [cell setShowSelection:YES];
577 default: _assert(false);
580 case 1: switch (row) {
582 cell = [cells_ objectAtIndex:5];
584 [cell setValue:[package_ tagline]];
588 cell = [cells_ objectAtIndex:6];
589 [cell setTitle:@"Description"];
590 [cell setValue:[package_ description]];
594 default: _assert(false);
600 - (BOOL) canSelectRow:(int)row {
604 - (void) tableRowSelected:(NSNotification *)notification {
605 switch ([table_ selectedRow]) {
607 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
608 [[package_ maintainer] email],
609 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
615 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
616 if ((self = [super initWithFrame:frame]) != nil) {
617 database_ = [database retain];
619 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
620 [self addSubview:table_];
622 [table_ setDataSource:self];
623 [table_ setDelegate:self];
625 cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
627 for (unsigned i = 0; i != 6; ++i) {
628 struct CGRect frame = [table_ frameOfPreferencesCellAtRow:0 inGroup:0];
629 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
630 [cell setShowSelection:NO];
631 [cells_ addObject:cell];
636 - (void) setPackage:(Package *)package {
637 package_ = [package retain];
641 - (void) setDelegate:(id)delegate {
642 delegate_ = delegate;
647 /* Package Cell {{{ */
648 @interface PackageCell : UITableCell {
650 UIRightTextLabel *version_;
651 UITextLabel *description_;
656 - (PackageCell *) initWithPackage:(Package *)package;
658 - (void) _setSelected:(float)fraction;
659 - (void) setSelected:(BOOL)selected;
660 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
661 - (void) _setSelectionFadeFraction:(float)fraction;
665 @implementation PackageCell
670 [description_ release];
674 - (PackageCell *) initWithPackage:(Package *)package {
675 if ((self = [super init]) != nil) {
676 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
677 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
678 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
680 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
681 float clear[] = {0, 0, 0, 0};
683 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
684 [name_ setText:[package name]];
685 [name_ setBackgroundColor:CGColorCreate(space, clear)];
686 [name_ setFont:bold];
688 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
689 [version_ setText:[package version]];
690 [version_ setBackgroundColor:CGColorCreate(space, clear)];
691 [version_ setFont:large];
693 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
694 [description_ setText:[package tagline]];
695 [description_ setBackgroundColor:CGColorCreate(space, clear)];
696 [description_ setFont:small];
698 [self addSubview:name_];
699 [self addSubview:version_];
700 [self addSubview:description_];
708 - (void) _setSelected:(float)fraction {
709 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
712 interpolate(0.0, 1.0, fraction),
713 interpolate(0.0, 1.0, fraction),
714 interpolate(0.0, 1.0, fraction),
718 interpolate(0.2, 1.0, fraction),
719 interpolate(0.2, 1.0, fraction),
720 interpolate(1.0, 1.0, fraction),
724 interpolate(0.4, 1.0, fraction),
725 interpolate(0.4, 1.0, fraction),
726 interpolate(0.4, 1.0, fraction),
729 [name_ setColor:CGColorCreate(space, black)];
730 [version_ setColor:CGColorCreate(space, blue)];
731 [description_ setColor:CGColorCreate(space, gray)];
734 - (void) setSelected:(BOOL)selected {
735 [self _setSelected:(selected ? 1.0 : 0.0)];
736 [super setSelected:selected];
739 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
741 [self _setSelected:(selected ? 1.0 : 0.0)];
742 [super setSelected:selected withFade:fade];
745 - (void) _setSelectionFadeFraction:(float)fraction {
746 [self _setSelected:fraction];
747 [super _setSelectionFadeFraction:fraction];
752 /* Sources View {{{ */
753 @interface SourcesView : ResetView {
754 UISectionList *list_;
757 NSMutableArray *sources_;
760 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
762 - (id) initWithFrame:(CGRect)frame database:(Database *)database;
763 - (void) setDelegate:(id)delegate;
767 @implementation SourcesView
769 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
787 - (id) initWithFrame:(CGRect)frame database:(Database *)database {
788 if ((self = [super initWithFrame:frame]) != nil) {
789 database_ = database;
792 CGSize navsize = [UINavigationBar defaultSize];
793 CGRect navrect = {{0, 0}, navsize};
794 CGRect bounds = [self bounds];
796 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
797 [self addSubview:navbar_];
799 [navbar_ setBarStyle:1];
800 [navbar_ setDelegate:self];
802 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Sources"] autorelease];
803 [navbar_ pushNavigationItem:navitem];
805 [navbar_ showButtonsWithLeftTitle:@"Refresh All" rightTitle:@"Edit"];
807 list_ = [[UISectionList alloc] initWithFrame:CGRectMake(
808 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
811 [list_ setDataSource:self];
815 - (void) setDelegate:(id)delegate {
816 delegate_ = delegate;
819 - (void) reloadData {
821 _assert(list.ReadMainList());
823 sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
825 for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) {
826 fprintf(stderr, "\"%s\" \"%s\" \"%s\"\n", (*source)->GetURI().c_str(), (*source)->GetDist().c_str(), (*source)->GetType());
833 @implementation Database
835 - (void) _readStatus:(NSNumber *)fd {
836 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
838 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
839 std::istream is(&ib);
844 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
846 pcre_extra *study = NULL;
848 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
849 int matches[(capture + 1) * 3];
851 while (std::getline(is, line)) {
852 const char *data(line.c_str());
854 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
856 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
859 [delegate_ setPercent:(percent / 100)];
861 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
862 std::string type(line.substr(matches[2], matches[3] - matches[2]));
864 if (type == "pmerror")
865 [delegate_ setError:string];
866 else if (type == "pmstatus")
867 [delegate_ setTitle:string];
868 else if (type == "pmconffile")
876 - (void) _readOutput:(NSNumber *)fd {
877 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
879 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
880 std::istream is(&ib);
883 while (std::getline(is, line))
884 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
889 - (Database *) init {
890 if ((self = [super init]) != nil) {
896 _assert(pipe(fds) != -1);
900 detachNewThreadSelector:@selector(_readStatus:)
902 withObject:[[NSNumber numberWithInt:fds[0]] retain]
905 _assert(pipe(fds) != -1);
906 _assert(dup2(fds[1], 1) != -1);
907 _assert(close(fds[1]) != -1);
910 detachNewThreadSelector:@selector(_readOutput:)
912 withObject:[[NSNumber numberWithInt:fds[0]] retain]
917 - (pkgCacheFile &) cache {
921 - (pkgRecords *) records {
925 - (pkgProblemResolver *) resolver {
929 - (void) reloadData {
934 cache_.Open(progress_, true);
935 records_ = new pkgRecords(cache_);
936 resolver_ = new pkgProblemResolver(cache_);
940 pkgRecords records(cache_);
943 lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
944 _assert(!_error->PendingError());
946 pkgAcquire fetcher(&status_);
948 _assert(list.ReadMainList());
950 SPtr<pkgPackageManager> manager(_system->CreatePM(cache_));
951 _assert(manager->GetArchives(&fetcher, &list, &records));
952 _assert(!_error->PendingError());
953 _assert(fetcher.Run() != pkgAcquire::Failed);
956 pkgPackageManager::OrderResult result = manager->DoInstall(statusfd_);
958 if (result == pkgPackageManager::Failed)
960 if (_error->PendingError())
962 if (result != pkgPackageManager::Completed)
968 _assert(list.ReadMainList());
971 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
972 _assert(!_error->PendingError());
974 pkgAcquire fetcher(&status_);
975 _assert(list.GetIndexes(&fetcher));
976 _assert(fetcher.Run() != pkgAcquire::Failed);
979 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
980 if ((*item)->Status != pkgAcquire::Item::StatDone) {
985 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
986 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
987 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
992 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
993 _assert(pkgApplyStatus(cache_));
995 if (cache_->BrokenCount() != 0) {
996 _assert(pkgFixBroken(cache_));
997 _assert(cache_->BrokenCount() == 0);
998 _assert(pkgMinimizeUpgrade(cache_));
1001 _assert(pkgDistUpgrade(cache_));
1003 //InstallPackages(cache_, true);
1006 - (void) setDelegate:(id)delegate {
1007 delegate_ = delegate;
1008 status_.setDelegate(delegate);
1009 progress_.setDelegate(delegate);
1014 /* Progress Data {{{ */
1015 @interface ProgressData : NSObject {
1021 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1028 @implementation ProgressData
1030 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1031 if ((self = [super init]) != nil) {
1032 selector_ = selector;
1052 /* Progress View {{{ */
1053 @interface ProgressView : UIView <
1057 UIView *background_;
1058 UITransitionView *transition_;
1060 UINavigationBar *navbar_;
1061 UIProgressBar *progress_;
1062 UITextView *output_;
1063 UITextLabel *status_;
1065 UIAlertSheet *alert_;
1070 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
1071 - (void) setContentView:(UIView *)view;
1074 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1076 - (void) _retachThread;
1077 - (void) _detachNewThreadData:(ProgressData *)data;
1078 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
1080 - (void) setError:(NSString *)error;
1081 - (void) _setError:(NSString *)error;
1083 - (void) setTitle:(NSString *)title;
1084 - (void) _setTitle:(NSString *)title;
1086 - (void) setPercent:(float)percent;
1087 - (void) _setPercent:(NSNumber *)percent;
1089 - (void) addOutput:(NSString *)output;
1090 - (void) _addOutput:(NSString *)output;
1092 - (void) setStatusFail;
1095 @protocol ProgressViewDelegate
1096 - (void) progressViewIsComplete:(ProgressView *)sender;
1099 @implementation ProgressView
1103 [background_ release];
1104 [transition_ release];
1107 [progress_ release];
1113 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
1114 if ((self = [super initWithFrame:frame]) != nil) {
1115 delegate_ = delegate;
1118 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1119 float black[] = {0.0, 0.0, 0.0, 1.0};
1120 float white[] = {1.0, 1.0, 1.0, 1.0};
1121 float clear[] = {0.0, 0.0, 0.0, 0.0};
1123 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1124 [background_ setBackgroundColor:CGColorCreate(space, black)];
1125 [self addSubview:background_];
1127 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1128 [self addSubview:transition_];
1130 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1132 CGSize navsize = [UINavigationBar defaultSize];
1133 CGRect navrect = {{0, 0}, navsize};
1135 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1136 [overlay_ addSubview:navbar_];
1138 [navbar_ setBarStyle:1];
1139 [navbar_ setDelegate:self];
1141 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Running..."] autorelease];
1142 [navbar_ pushNavigationItem:navitem];
1144 CGRect bounds = [overlay_ bounds];
1145 CGSize prgsize = [UIProgressBar defaultSize];
1148 (bounds.size.width - prgsize.width) / 2,
1149 bounds.size.height - prgsize.height - 20
1152 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1153 [overlay_ addSubview:progress_];
1155 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1157 bounds.size.height - prgsize.height - 50,
1158 bounds.size.width - 20,
1162 [status_ setColor:CGColorCreate(space, white)];
1163 [status_ setBackgroundColor:CGColorCreate(space, clear)];
1165 [status_ setCentersHorizontally:YES];
1166 //[status_ setFont:font];
1168 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1170 navrect.size.height + 20,
1171 bounds.size.width - 20,
1172 bounds.size.height - navsize.height - 62 - navrect.size.height
1175 //[output_ setTextFont:@"Courier New"];
1176 [output_ setTextSize:12];
1178 [output_ setTextColor:CGColorCreate(space, white)];
1179 [output_ setBackgroundColor:CGColorCreate(space, clear)];
1181 [output_ setMarginTop:0];
1182 [output_ setAllowsRubberBanding:YES];
1184 [overlay_ addSubview:output_];
1185 [overlay_ addSubview:status_];
1187 [progress_ setStyle:0];
1191 - (void) setContentView:(UIView *)view {
1195 - (void) resetView {
1196 [transition_ transition:6 toView:view_];
1199 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1205 - (void) _retachThread {
1206 [delegate_ progressViewIsComplete:self];
1210 - (void) _detachNewThreadData:(ProgressData *)data {
1211 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1213 [[data target] performSelector:[data selector] withObject:[data object]];
1214 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
1220 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
1221 [status_ setText:nil];
1222 [output_ setText:@""];
1223 [progress_ setProgress:0];
1225 [transition_ transition:6 toView:overlay_];
1228 detachNewThreadSelector:@selector(_detachNewThreadData:)
1230 withObject:[[ProgressData alloc]
1231 initWithSelector:selector
1238 - (void) setStatusFail {
1241 - (void) setError:(NSString *)error {
1243 performSelectorOnMainThread:@selector(_setError:)
1249 - (void) _setError:(NSString *)error {
1250 _assert(alert_ == nil);
1252 alert_ = [[UIAlertSheet alloc]
1253 initWithTitle:@"Package Error"
1254 buttons:[NSArray arrayWithObjects:@"Okay", nil]
1255 defaultButtonIndex:0
1260 [alert_ setBodyText:error];
1261 [alert_ popupAlertAnimated:YES];
1264 - (void) setTitle:(NSString *)title {
1266 performSelectorOnMainThread:@selector(_setTitle:)
1272 - (void) _setTitle:(NSString *)title {
1273 [status_ setText:[title stringByAppendingString:@"..."]];
1276 - (void) setPercent:(float)percent {
1278 performSelectorOnMainThread:@selector(_setPercent:)
1279 withObject:[NSNumber numberWithFloat:percent]
1284 - (void) _setPercent:(NSNumber *)percent {
1285 [progress_ setProgress:[percent floatValue]];
1288 - (void) addOutput:(NSString *)output {
1290 performSelectorOnMainThread:@selector(_addOutput:)
1296 - (void) _addOutput:(NSString *)output {
1297 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
1298 CGSize size = [output_ contentSize];
1299 CGRect rect = {{0, size.height}, {size.width, 0}};
1300 [output_ scrollRectToVisible:rect animated:YES];
1306 @protocol PackagesDelegate
1309 - (void) openURL:(NSString *)url;
1312 @interface Packages : ResetView {
1314 Database *database_;
1315 bool (*filter_)(Package *package);
1316 NSMutableArray *packages_;
1317 NSMutableArray *sections_;
1319 UISectionList *list_;
1320 UITransitionView *transition_;
1322 PackageView *pkgview_;
1326 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
1327 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
1328 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
1330 - (int) numberOfRowsInTable:(UITable *)table;
1331 - (float) table:(UITable *)table heightForRow:(int)row;
1332 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col;
1333 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
1334 - (void) tableRowSelected:(NSNotification*)notification;
1336 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1337 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
1339 - (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector;
1340 - (void) setDelegate:(id)delegate;
1342 - (void) reloadData;
1345 @implementation Packages
1347 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
1348 return [sections_ count];
1351 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
1352 return [[sections_ objectAtIndex:section] name];
1355 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
1356 return [[sections_ objectAtIndex:section] row];
1359 - (int) numberOfRowsInTable:(UITable *)table {
1360 return [packages_ count];
1363 - (float) table:(UITable *)table heightForRow:(int)row {
1367 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
1368 Package *package = [packages_ objectAtIndex:row];
1369 PackageCell *cell = [[[PackageCell alloc] initWithPackage:package] autorelease];
1373 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
1377 - (void) tableRowSelected:(NSNotification*)notification {
1378 int row = [[list_ table] selectedRow];
1382 package_ = [packages_ objectAtIndex:row];
1384 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
1385 [navbar_ pushNavigationItem:navitem];
1387 [navbar_ showButtonsWithLeftTitle:nil rightTitle:title_];
1389 [pkgview_ setPackage:package_];
1390 [transition_ transition:1 toView:pkgview_];
1393 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1395 [package_ performSelector:selector_];
1397 pkgProblemResolver *resolver = [database_ resolver];
1399 resolver->InstallProtect();
1400 if (!resolver->Resolve(true))
1403 [delegate_ perform];
1407 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
1409 [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
1412 - (Packages *) initWithFrame:(struct CGRect)frame title:(NSString *)title database:(Database *)database filter:(bool (*)(Package *))filter selector:(SEL)selector {
1413 if ((self = [super initWithFrame:frame]) != nil) {
1414 title_ = [title retain];
1415 database_ = [database retain];
1417 selector_ = selector;
1419 struct CGRect bounds = [self bounds];
1420 CGSize navsize = [UINavigationBar defaultSize];
1421 CGRect navrect = {{0, 0}, navsize};
1423 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1424 [self addSubview:navbar_];
1426 [navbar_ setBarStyle:1];
1427 [navbar_ setDelegate:self];
1429 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
1430 [navbar_ pushNavigationItem:navitem];
1431 [navitem setBackButtonTitle:@"Packages"];
1433 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1434 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
1437 [self addSubview:transition_];
1439 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
1440 [list_ setDataSource:self];
1442 [transition_ transition:0 toView:list_];
1444 UITableColumn *column = [[UITableColumn alloc]
1445 initWithTitle:@"Name"
1447 width:frame.size.width
1450 UITable *table = [list_ table];
1451 [table setSeparatorStyle:1];
1452 [table addTableColumn:column];
1453 [table setDelegate:self];
1455 pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
1459 - (void) setDelegate:(id)delegate {
1460 delegate_ = delegate;
1461 [pkgview_ setDelegate:delegate];
1465 [transition_ transition:(resetting_ ? 0 : 2) toView:list_];
1466 UITable *table = [list_ table];
1467 [table selectRow:-1 byExtendingSelection:NO withFade:(resetting_ ? NO : YES)];
1471 - (void) reloadData {
1472 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1474 if (sections_ != nil) {
1475 [sections_ release];
1479 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator) {
1480 Package *package = [Package packageWithIterator:iterator database:database_];
1483 if (filter_(package))
1484 [packages_ addObject:package];
1487 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
1488 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
1490 Section *section = nil;
1491 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
1492 Package *package = [packages_ objectAtIndex:offset];
1493 NSString *name = [package section];
1495 if (section == nil || ![[section name] isEqual:name]) {
1496 section = [[Section alloc] initWithName:name row:offset];
1497 [sections_ addObject:section];
1500 [section addPackage:package];
1509 bool IsInstalled(Package *package) {
1510 return [package installed];
1513 bool IsNotInstalled(Package *package) {
1514 return ![package installed];
1517 @interface Cydia : UIApplication <
1519 ProgressViewDelegate
1522 UITransitionView *transition_;
1523 UIButtonBar *buttonbar_;
1524 UIAlertSheet *alert_;
1526 Database *database_;
1527 ProgressView *progress_;
1530 UINavigationBar *navbar_;
1531 UIScroller *scroller_;
1532 UIWebView *webview_;
1536 Packages *uninstall_;
1537 SourcesView *sources_;
1541 - (void) reloadData;
1545 - (void) progressViewIsComplete:(ProgressView *)progress;
1547 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1548 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1549 - (void) buttonBarItemTapped:(id)sender;
1551 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
1552 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
1554 - (void) applicationDidFinishLaunching:(id)unused;
1557 @implementation Cydia
1560 [webview_ loadRequest:[NSURLRequest
1562 cachePolicy:NSURLRequestReloadIgnoringCacheData
1563 timeoutInterval:30.0
1567 - (void) reloadData {
1568 [database_ reloadData];
1569 [install_ reloadData];
1570 [uninstall_ reloadData];
1571 [sources_ reloadData];
1576 detachNewThreadSelector:@selector(perform)
1584 detachNewThreadSelector:@selector(update)
1590 - (void) progressViewIsComplete:(ProgressView *)progress {
1594 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1601 _assert(alert_ == nil);
1603 alert_ = [[UIAlertSheet alloc]
1604 initWithTitle:@"About Cydia Packager"
1605 buttons:[NSArray arrayWithObjects:@"Close", nil]
1606 defaultButtonIndex:0
1611 [alert_ setBodyText:
1612 @"Copyright (C) 2007\n"
1613 "Jay Freeman (saurik)\n"
1614 "saurik@saurik.com\n"
1615 "http://www.saurik.com/\n"
1618 "http://www.theokorigroup.com/\n"
1620 "College of Creative Studies,\n"
1621 "University of California,\n"
1623 "http://www.ccs.ucsb.edu/\n"
1626 "bad_, BHSPitMonkey, Cobra, core,\n"
1627 "Corona, cromas, Darken, dtzWill,\n"
1628 "francis, Godores, jerry, Kingstone,\n"
1629 "lounger, rockabilly, tman, Wbiggs"
1632 [alert_ presentSheetFromButtonBar:buttonbar_];
1637 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1643 - (void) buttonBarItemTapped:(id)sender {
1646 switch ([sender tag]) {
1647 case 1: view = featured_; break;
1648 case 2: view = install_; break;
1649 case 4: view = uninstall_; break;
1650 case 5: view = sources_; break;
1656 if ([view respondsToSelector:@selector(resetView)])
1657 [(id) view resetView];
1658 [transition_ transition:0 toView:view];
1661 - (void) view:(UIView *)view didSetFrame:(CGRect)frame {
1662 [scroller_ setContentSize:frame.size];
1665 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
1666 [scroller_ setContentSize:[webview_ bounds].size];
1669 - (void) applicationDidFinishLaunching:(id)unused {
1670 _assert(pkgInitConfig(*_config));
1671 _assert(pkgInitSystem(*_config, _system));
1673 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
1674 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
1676 [window_ orderFront: self];
1677 [window_ makeKey: self];
1678 [window_ _setHidden: NO];
1680 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
1681 [window_ setContentView:progress_];
1683 UIView *view = [[UIView alloc] initWithFrame:[progress_ bounds]];
1684 [progress_ setContentView:view];
1686 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1687 0, 0, screenrect.size.width, screenrect.size.height - 48
1690 [view addSubview:transition_];
1692 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1694 CGSize navsize = [UINavigationBar defaultSize];
1695 CGRect navrect = {{0, 0}, navsize};
1697 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1698 [featured_ addSubview:navbar_];
1700 [navbar_ setBarStyle:1];
1701 [navbar_ setDelegate:self];
1703 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
1705 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:@"Featured"];
1706 [navbar_ pushNavigationItem:navitem];
1708 struct CGRect subbounds = [featured_ bounds];
1709 subbounds.origin.y += navsize.height;
1710 subbounds.size.height -= navsize.height;
1712 UIImageView *pinstripe = [[UIImageView alloc] initWithFrame:subbounds];
1713 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
1714 [featured_ addSubview:pinstripe];
1716 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
1717 [featured_ addSubview:scroller_];
1719 [scroller_ setScrollingEnabled:YES];
1720 [scroller_ setAdjustForContentSizeChange:YES];
1721 [scroller_ setClipsSubviews:YES];
1722 [scroller_ setAllowsRubberBanding:YES];
1723 [scroller_ setScrollDecelerationFactor:0.99];
1724 [scroller_ setDelegate:self];
1726 webview_ = [[UIWebView alloc] initWithFrame:[scroller_ bounds]];
1727 [scroller_ addSubview:webview_];
1729 [webview_ setTilingEnabled:YES];
1730 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
1731 [webview_ setAutoresizes:YES];
1732 [webview_ setDelegate:self];
1734 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
1737 NSArray *buttonitems = [NSArray arrayWithObjects:
1738 [NSDictionary dictionaryWithObjectsAndKeys:
1739 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1740 @"featured-up.png", kUIButtonBarButtonInfo,
1741 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
1742 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
1743 self, kUIButtonBarButtonTarget,
1744 @"Featured", kUIButtonBarButtonTitle,
1745 @"0", kUIButtonBarButtonType,
1748 [NSDictionary dictionaryWithObjectsAndKeys:
1749 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1750 @"install-up.png", kUIButtonBarButtonInfo,
1751 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
1752 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
1753 self, kUIButtonBarButtonTarget,
1754 @"Install", kUIButtonBarButtonTitle,
1755 @"0", kUIButtonBarButtonType,
1758 [NSDictionary dictionaryWithObjectsAndKeys:
1759 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1760 @"upgrade-up.png", kUIButtonBarButtonInfo,
1761 @"upgrade-dn.png", kUIButtonBarButtonSelectedInfo,
1762 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
1763 self, kUIButtonBarButtonTarget,
1764 @"Upgrade", kUIButtonBarButtonTitle,
1765 @"0", kUIButtonBarButtonType,
1768 [NSDictionary dictionaryWithObjectsAndKeys:
1769 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1770 @"uninstall-up.png", kUIButtonBarButtonInfo,
1771 @"uninstall-dn.png", kUIButtonBarButtonSelectedInfo,
1772 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
1773 self, kUIButtonBarButtonTarget,
1774 @"Uninstall", kUIButtonBarButtonTitle,
1775 @"0", kUIButtonBarButtonType,
1778 [NSDictionary dictionaryWithObjectsAndKeys:
1779 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
1780 @"sources-up.png", kUIButtonBarButtonInfo,
1781 @"sources-dn.png", kUIButtonBarButtonSelectedInfo,
1782 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
1783 self, kUIButtonBarButtonTarget,
1784 @"Sources", kUIButtonBarButtonTitle,
1785 @"0", kUIButtonBarButtonType,
1789 buttonbar_ = [[UIButtonBar alloc]
1791 withFrame:CGRectMake(
1792 0, screenrect.size.height - 48,
1793 screenrect.size.width, 48
1795 withItemList:buttonitems
1798 [buttonbar_ setDelegate:self];
1799 [buttonbar_ setBarStyle:1];
1800 [buttonbar_ setButtonBarTrackingMode:2];
1802 int buttons[5] = {1, 2, 3, 4, 5};
1803 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
1804 [buttonbar_ showButtonGroup:0 withDuration:0];
1806 for (int i = 0; i != 5; ++i)
1807 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
1808 i * 64 + 2, 1, 60, 48
1811 [buttonbar_ showSelectionForButton:1];
1812 [transition_ transition:0 toView:featured_];
1814 [view addSubview:buttonbar_];
1816 database_ = [[Database alloc] init];
1817 [database_ setDelegate:progress_];
1819 install_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Install" database:database_ filter:&IsNotInstalled selector:@selector(install)];
1820 [install_ setDelegate:self];
1822 uninstall_ = [[Packages alloc] initWithFrame:[transition_ bounds] title:@"Uninstall" database:database_ filter:&IsInstalled selector:@selector(remove)];
1823 [uninstall_ setDelegate:self];
1825 sources_ = [[SourcesView alloc] initWithFrame:[transition_ bounds] database:database_];
1826 [sources_ setDelegate:self];
1830 UIAlertSheet *alert = [[UIAlertSheet alloc]
1831 initWithTitle:@"Alert Title"
1832 buttons:[NSArray arrayWithObjects:@"Yes", nil]
1833 defaultButtonIndex:0
1838 NSLog(@"%p\n", [alert table]);
1839 [[alert table] setDelegate:self];
1840 [[alert table] reloadData];
1842 [alert addTextFieldWithValue:@"Title" label:@"Label"];
1843 [alert setShowsOverSpringBoardAlerts:YES];
1844 [alert setBodyText:@"This is an alert."];
1845 [alert presentSheetFromButtonBar:buttonbar_];
1846 //[alert popupAlertAnimated:YES];
1851 [progress_ resetView];
1856 int main(int argc, char *argv[]) {
1857 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1858 UIApplicationMain(argc, argv, [Cydia class]);